From 8443a0b923f8f87a71a505edebf6688ff34e3e9e Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 3 Dec 2024 21:14:51 +0800 Subject: [PATCH 001/158] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=AD=97=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/font-default.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/kernel/font-default.c b/src/kernel/font-default.c index 34209fd..897c16b 100644 --- a/src/kernel/font-default.c +++ b/src/kernel/font-default.c @@ -658,17 +658,17 @@ unsigned char font16[] = { // 0x26 & 0b00000000, 0b00000000, - 0b00000000, - 0b00110000, - 0b01001000, - 0b01001000, - 0b01001000, 0b00110000, + 0b01111000, + 0b11001100, + 0b11001100, + 0b11001100, + 0b01111000, 0b00110001, - 0b01001011, - 0b10000110, - 0b10001011, - 0b10010001, + 0b01111011, + 0b11000110, + 0b11001111, + 0b11011001, 0b01110000, 0b00000000, 0b00000000, @@ -727,13 +727,13 @@ unsigned char font16[] = { 0b00000000, 0b00000000, 0b00000000, - 0b00001000, - 0b01001001, - 0b00111011, - 0b00011100, - 0b00101010, - 0b01001001, - 0b00001000, + 0b00011000, + 0b11011011, + 0b01111110, + 0b00111100, + 0b01111110, + 0b11011011, + 0b00011000, 0b00000000, 0b00000000, 0b00000000, From 4300c1d998e60758775ec0a7786f339b1c2c7b5f Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 8 Dec 2024 00:28:43 +0800 Subject: [PATCH 002/158] =?UTF-8?q?=E9=87=8D=E6=9E=84=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8=E9=83=A8=E5=88=86=E6=A1=86=E6=9E=B6=EF=BC=9B?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E4=B8=AD=E6=96=AD=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E5=99=A8=E3=80=81=E5=AE=9A=E6=97=B6=E5=99=A8=E5=92=8C=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E9=A9=B1=E5=8A=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .clang-format | 5 +- .vscode/settings.json | 21 - src/Makefile | 2 +- src/arch/x86/drivers/8259a.c | 189 +++++++-- src/arch/x86/drivers/Makefile | 1 + src/arch/x86/drivers/acpi.c | 290 +++++++------- src/arch/x86/drivers/apic.c | 408 ++++++++++++++++++-- src/arch/x86/drivers/cpufreq.c | 10 +- src/arch/x86/drivers/pit.c | 350 +++++++++++------ src/arch/x86/drivers/sound/sb16.c | 27 +- src/arch/x86/drivers/usb/hci/uhci.c | 12 +- src/arch/x86/drivers/usb/hci/uhci/packet.c | 3 +- src/arch/x86/drivers/usb/hub.c | 11 +- src/arch/x86/drivers/usb/usb.c | 3 +- src/arch/x86/drivers/vesa_display.c | 84 ++++ src/arch/x86/drivers/video.c | 96 +---- src/arch/x86/include/drivers/8259a.h | 6 +- src/arch/x86/include/drivers/apic.h | 64 ++- src/arch/x86/include/drivers/pit.h | 39 +- src/arch/x86/include/drivers/vesa_display.h | 44 +++ src/arch/x86/include/drivers/video.h | 9 - src/arch/x86/include/kernel/feature.h | 71 ++++ src/arch/x86/include/kernel/page.h | 59 +-- src/arch/x86/kernel.lds | 40 +- src/arch/x86/kernel/Makefile | 3 +- src/arch/x86/kernel/descriptor.c | 33 +- src/arch/x86/kernel/feature.c | 91 +++++ src/arch/x86/kernel/page.c | 63 ++- src/arch/x86/kernel/platform.c | 46 ++- src/arch/x86/multiboot2/multiboot2.c | 31 +- src/driver/Makefile | 4 + src/driver/interrupt_dm.c | 179 +++++++++ src/driver/timer_dm.c | 185 +++++++++ src/driver/video.c | 220 +++++++++++ src/driver/video_dm.c | 108 ++++++ src/include/driver/interrupt_dm.h | 37 ++ src/include/driver/timer_dm.h | 62 +++ src/include/driver/video.h | 35 ++ src/include/driver/video_dm.h | 38 ++ src/include/kernel/bus_driver.h | 54 +++ src/include/kernel/console.h | 10 - src/include/kernel/device.h | 75 ++++ src/include/kernel/device_driver.h | 62 +++ src/include/kernel/device_manager.h | 47 +++ src/include/kernel/driver.h | 108 +++++- src/include/kernel/driver_interface.h | 57 +++ src/include/kernel/driver_manager.h | 41 ++ src/include/kernel/memory.h | 67 +++- src/include/kernel/platform.h | 3 +- src/include/kernel/process.h | 13 +- src/include/network/tcp.h | 18 +- src/include/result.h | 18 + src/include/string.h | 48 +-- src/kernel/Makefile | 6 + src/kernel/bus_driver.c | 96 +++++ src/kernel/console.c | 130 ++++--- src/kernel/device.c | 51 +++ src/kernel/device_driver.c | 88 +++++ src/kernel/device_manager.c | 37 ++ src/kernel/driver.c | 113 ++++-- src/kernel/driver_interface.c | 72 ++++ src/kernel/driver_manager.c | 32 ++ src/kernel/main.c | 33 +- src/kernel/memory.c | 39 +- src/kernel/process.c | 56 ++- src/lib/string.c | 32 +- src/network/tcp.c | 218 ++++++----- tools/imagetool | 2 +- 68 files changed, 3623 insertions(+), 982 deletions(-) create mode 100644 src/arch/x86/drivers/vesa_display.c create mode 100644 src/arch/x86/include/drivers/vesa_display.h create mode 100644 src/arch/x86/include/kernel/feature.h create mode 100644 src/arch/x86/kernel/feature.c create mode 100644 src/driver/Makefile create mode 100644 src/driver/interrupt_dm.c create mode 100644 src/driver/timer_dm.c create mode 100644 src/driver/video.c create mode 100644 src/driver/video_dm.c create mode 100644 src/include/driver/interrupt_dm.h create mode 100644 src/include/driver/timer_dm.h create mode 100644 src/include/driver/video.h create mode 100644 src/include/driver/video_dm.h create mode 100644 src/include/kernel/bus_driver.h create mode 100644 src/include/kernel/device.h create mode 100644 src/include/kernel/device_driver.h create mode 100644 src/include/kernel/device_manager.h create mode 100644 src/include/kernel/driver_interface.h create mode 100644 src/include/kernel/driver_manager.h create mode 100644 src/include/result.h create mode 100644 src/kernel/bus_driver.c create mode 100644 src/kernel/device.c create mode 100644 src/kernel/device_driver.c create mode 100644 src/kernel/device_manager.c create mode 100644 src/kernel/driver_interface.c create mode 100644 src/kernel/driver_manager.c diff --git a/.clang-format b/.clang-format index 1856c0b..ef3ee5c 100644 --- a/.clang-format +++ b/.clang-format @@ -3,9 +3,9 @@ Language: Cpp # BasedOnStyle: LLVM AlignAfterOpenBracket: AlwaysBreak AlignArrayOfStructures: Right -AlignConsecutiveAssignments: true +AlignConsecutiveAssignments: AcrossComments AlignConsecutiveBitFields: true -AlignConsecutiveDeclarations: true +AlignConsecutiveDeclarations: AcrossComments AlignConsecutiveMacros: true AlignEscapedNewlines: Left AlignOperands: AlignAfterOperator @@ -97,6 +97,7 @@ PenaltyReturnTypeOnItsOwnLine: 1000 PenaltyIndentedWhitespace: 0 PointerAlignment: Right PPIndentWidth: -1 +QualifierAlignment: Left ReferenceAlignment: Pointer ReflowComments: true SortIncludes: true diff --git a/.vscode/settings.json b/.vscode/settings.json index 8010ab6..0e62506 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -44,27 +44,6 @@ "utility": "c", "cstdlib": "c" }, - "C_Cpp.codeAnalysis.clangTidy.checks.disabled": [ - "clang-diagnostic-int-to-void-pointer-cast", - "clang-diagnostic-int-to-pointer-cast", - "clang-diagnostic-void-pointer-to-int-cast", - "clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling", - "clang-diagnostic-pointer-to-int-cast", - "clang-diagnostic-visibility", - "clang-analyzer-security.insecureAPI.strcpy", - "clang-diagnostic-incompatible-library-redeclaration", - "clang-diagnostic-implicit-function-declaration", - "clang-analyzer-deadcode.DeadStores", - "clang-diagnostic-error" - ], - "C_Cpp.errorSquiggles": "Disabled", - "makefile.launchConfigurations": [ - { - "cwd": "/home/ryan/Desktop/horizon/src", - "binaryPath": "/home/ryan/Desktop/horizon/src/kernel.elf", - "binaryArgs": [] - } - ], "C_Cpp.clang_format_style": "file", "C_Cpp.clang_format_fallbackStyle": "LLVM", "clangd.fallbackFlags": [ diff --git a/src/Makefile b/src/Makefile index 6199ea7..cbbf9c3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,7 +21,7 @@ LD := $(ENV_LD) export AS LD export ARCH_DIR -SRC := $(ARCH_DIR)/ fs/ kernel/ lib/ network/ +SRC := $(ARCH_DIR)/ fs/ driver/ kernel/ lib/ network/ NAME := kernel.elf diff --git a/src/arch/x86/drivers/8259a.c b/src/arch/x86/drivers/8259a.c index 30348c2..287f4fd 100644 --- a/src/arch/x86/drivers/8259a.c +++ b/src/arch/x86/drivers/8259a.c @@ -6,56 +6,173 @@ * @date 2022-07-31 * */ +#include "string.h" #include #include #include #include -void init_8259a(void) -{ - io_out8(PIC0_IMR, 0xff); // 屏蔽主PIC的所有中断 - io_out8(PIC1_IMR, 0xff); // 屏蔽从PIC的所有中断 +// --------new-------- +#include +#include +#include +#include +#include +#include +#include - io_out8(PIC0_ICW1, 0x11); // 级联,边沿触发 - io_out8(PIC0_ICW2, 0x20); // 起始中断向量号位0x20(0x00~0x1f为内部中断) - io_out8(PIC0_ICW3, 1 << 2); // IRQ2用于连接从PIC - io_out8(PIC0_ICW4, 0x01); // 全嵌套模式,非缓冲模式,手动结束中断,x86处理器 +DriverResult pic_init(Device *device); +int pic_redirect_irq(InterruptDevice *device, int irq); +DriverResult pic_enable_irq(InterruptDevice *device, int irq); +DriverResult pic_disable_irq(InterruptDevice *device, int irq); +void pic_eoi(InterruptDevice *device, int irq); - io_out8(PIC1_ICW1, 0x11); // 级联,边沿触发 - io_out8(PIC1_ICW2, 0x28); // 起始中断向量号位0x28 - io_out8(PIC1_ICW3, 0x02); // 连接到主PIC的IRQ2 - io_out8(PIC1_ICW4, 0x01); // 全嵌套模式,非缓冲模式,手动结束中断,x86处理器 +DeviceDriverOps pic_device_driver_ops = { + .register_driver_hook = NULL, + .unregister_driver_hook = NULL, +}; +DeviceOps pic_device_ops = { + .init = pic_init, + .start = NULL, + .stop = NULL, + .destroy = NULL, + .status = NULL, +}; +InterruptDeviceOps pic_interrupt_ops = { + .enable_irq = pic_enable_irq, + .disable_irq = pic_disable_irq, + .eoi = pic_eoi, + .redirect_irq = pic_redirect_irq, +}; - io_out8(PIC0_IMR, 0xfb); // 开启IRQ2(从PIC)中断 - io_out8(PIC1_IMR, 0xff); // 屏蔽从PIC的所有中断 +Driver pic_driver = {.name = STRING_INIT("PIC")}; +DeviceDriver pic_device_driver = { + .name = STRING_INIT("PIC Driver"), + .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, + .priority = DRIVER_PRIORITY_BASIC, + .state = DRIVER_STATE_UNREGISTERED, + .ops = &pic_device_driver_ops, +}; +Device pic_device = { + .name = STRING_INIT("8259a"), - use_apic = 0; + .device_driver = &pic_device_driver, - return; + .ops = &pic_device_ops, + + .private_data_size = 0, +}; +InterruptDevice pic_interrupt_device = { + .interrupt_ops = &pic_interrupt_ops, + .priority = 0, +}; + +void register_pic(void) { + register_device_driver(&pic_driver, &pic_device_driver); + register_interrupt_device( + &pic_device_driver, &pic_device, &pic_interrupt_device); +} + +void mask_8259a(void) { + io_out_byte(PIC0_IMR, 0xff); + io_out_byte(PIC1_IMR, 0xff); +} + +DriverResult pic_init(Device *device) { + io_out_byte(PIC0_IMR, 0xff); // 屏蔽主PIC的所有中断 + io_out_byte(PIC1_IMR, 0xff); // 屏蔽从PIC的所有中断 + + io_out_byte(PIC0_ICW1, 0x11); // 级联,边沿触发 + io_out_byte(PIC0_ICW2, 0x20); // 起始中断向量号位0x20(0x00~0x1f为内部中断) + io_out_byte(PIC0_ICW3, 1 << 2); // IRQ2用于连接从PIC + // 全嵌套模式,非缓冲模式,手动结束中断,x86处理器 + io_out_byte(PIC0_ICW4, 0x01); + + io_out_byte(PIC1_ICW1, 0x11); // 级联,边沿触发 + io_out_byte(PIC1_ICW2, 0x28); // 起始中断向量号位0x28 + io_out_byte(PIC1_ICW3, 0x02); // 连接到主PIC的IRQ2 + // 全嵌套模式,非缓冲模式,手动结束中断,x86处理器 + io_out_byte(PIC1_ICW4, 0x01); + + io_out_byte(PIC0_IMR, 0xfb); // 开启IRQ2(从PIC)中断 + io_out_byte(PIC1_IMR, 0xff); // 屏蔽从PIC的所有中断 + return DRIVER_RESULT_OK; +} + +int pic_redirect_irq(InterruptDevice *device, int irq) { + return irq; } -void mask_8259a(void) -{ - io_out8(PIC0_IMR, 0xff); - io_out8(PIC1_IMR, 0xff); +DriverResult pic_enable_irq(InterruptDevice *device, int irq) { + uint8_t data; + if (irq < 8) { + data = io_in8(PIC0_IMR); + io_out8(PIC0_IMR, BIN_DIS(data, BIT(irq))); + } else { + data = io_in8(PIC1_IMR); + io_out8(PIC1_IMR, BIN_DIS(data, BIT(irq % 8))); + } + return DRIVER_RESULT_OK; } -void pic_enable_irq(int irq) -{ - uint8_t data; - if (irq < 8) { - data = io_in8(PIC0_IMR); - io_out8(PIC0_IMR, data & ~(1 << irq)); - } else { - data = io_in8(PIC1_IMR); - io_out8(PIC1_IMR, data & ~(1 << (irq % 8))); - } +DriverResult pic_disable_irq(InterruptDevice *device, int irq) { + uint8_t data; + if (irq < 8) { + data = io_in8(PIC0_IMR); + io_out8(PIC0_IMR, BIN_EN(data, BIT(irq))); + } else { + data = io_in8(PIC1_IMR); + io_out8(PIC1_IMR, BIN_EN(data, BIT(irq % 8))); + } + return DRIVER_RESULT_OK; } -void pic_eoi(int irq) -{ - if (irq >= 8) { - io_out8(PIC1_OCW1, PIC_EOI); - } - io_out8(PIC0_OCW1, PIC_EOI); +void pic_eoi(InterruptDevice *device, int irq) { + if (irq >= 8) { io_out8(PIC1_OCW1, PIC_EOI); } + io_out8(PIC0_OCW1, PIC_EOI); } + +// --------old-------- + +// void init_8259a(void) { +// io_out8(PIC0_IMR, 0xff); // 屏蔽主PIC的所有中断 +// io_out8(PIC1_IMR, 0xff); // 屏蔽从PIC的所有中断 + +// io_out8(PIC0_ICW1, 0x11); // 级联,边沿触发 +// io_out8(PIC0_ICW2, 0x20); // 起始中断向量号位0x20(0x00~0x1f为内部中断) +// io_out8(PIC0_ICW3, 1 << 2); // IRQ2用于连接从PIC +// io_out8(PIC0_ICW4, 0x01); // 全嵌套模式,非缓冲模式,手动结束中断,x86处理器 + +// io_out8(PIC1_ICW1, 0x11); // 级联,边沿触发 +// io_out8(PIC1_ICW2, 0x28); // 起始中断向量号位0x28 +// io_out8(PIC1_ICW3, 0x02); // 连接到主PIC的IRQ2 +// io_out8(PIC1_ICW4, 0x01); // 全嵌套模式,非缓冲模式,手动结束中断,x86处理器 + +// io_out8(PIC0_IMR, 0xfb); // 开启IRQ2(从PIC)中断 +// io_out8(PIC1_IMR, 0xff); // 屏蔽从PIC的所有中断 + +// use_apic = 0; + +// return; +// } + +// void mask_8259a(void) { +// io_out8(PIC0_IMR, 0xff); +// io_out8(PIC1_IMR, 0xff); +// } + +// void pic_enable_irq(int irq) { +// uint8_t data; +// if (irq < 8) { +// data = io_in8(PIC0_IMR); +// io_out8(PIC0_IMR, data & ~(1 << irq)); +// } else { +// data = io_in8(PIC1_IMR); +// io_out8(PIC1_IMR, data & ~(1 << (irq % 8))); +// } +// } + +// void pic_eoi(int irq) { +// if (irq >= 8) { io_out8(PIC1_OCW1, PIC_EOI); } +// io_out8(PIC0_OCW1, PIC_EOI); +// } diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index 8d0beca..78b02e2 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -13,6 +13,7 @@ SRC += pci.c SRC += pit.c SRC += smbios.c SRC += video.c +SRC += vesa_display.c SRC += network/ SRC += sound/ SRC += usb/ \ No newline at end of file diff --git a/src/arch/x86/drivers/acpi.c b/src/arch/x86/drivers/acpi.c index 4cbd488..fb84372 100644 --- a/src/arch/x86/drivers/acpi.c +++ b/src/arch/x86/drivers/acpi.c @@ -5,6 +5,7 @@ * @version 0.1 * @date 2021-06 */ +#include "kernel/memory.h" #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include struct ACPI_RSDP *RSDP; @@ -22,113 +24,104 @@ struct ACPI_RSDP *RSDP; static status_t acpi_enter(driver_t *drv_obj); static status_t acpi_exit(driver_t *drv_obj); -typedef struct -{ - struct ACPI_RSDT *RSDT; - struct ACPI_FADT *FADT; +typedef struct { + struct ACPI_RSDT *RSDT; + struct ACPI_FADT *FADT; } device_extension_t; driver_func_t acpi_driver = { - .driver_enter = acpi_enter, - .driver_exit = acpi_exit, - .driver_open = NULL, - .driver_close = NULL, - .driver_read = NULL, - .driver_write = NULL, - .driver_devctl = NULL -}; - -char checksum(uint8_t *addr, uint32_t length) -{ - unsigned char sum = 0; - - for (int i = 0; i < length; i++) { - sum += ((char *)addr)[i]; - } - - return sum == 0; + .driver_enter = acpi_enter, + .driver_exit = acpi_exit, + .driver_open = NULL, + .driver_close = NULL, + .driver_read = NULL, + .driver_write = NULL, + .driver_devctl = NULL}; + +char checksum(uint8_t *addr, uint32_t length) { + unsigned char sum = 0; + + for (int i = 0; i < length; i++) { + sum += ((char *)addr)[i]; + } + + return sum == 0; } -uint32_t *acpi_find_rsdp(void) -{ - uint32_t addr; - - for (addr = 0x000e0000; addr < 0x00100000; addr++) { - if (memcmp((void *)addr, "RSD PTR ", 8) == 0) { - if (checksum((uint8_t *)addr, ((struct ACPI_RSDP *)addr)->Length)) { - return (uint32_t *)addr; - } - } - } - return NULL; +uint32_t *acpi_find_rsdp(void) { + uint32_t addr; + + for (addr = 0x000e0000; addr < 0x00100000; addr++) { + if (memcmp((void *)addr, "RSD PTR ", 8) == 0) { + if (checksum((uint8_t *)addr, ((struct ACPI_RSDP *)addr)->Length)) { + return (uint32_t *)addr; + } + } + } + return NULL; } -uint32_t acpi_find_table(device_extension_t *devext, char *Signature) -{ - int i, length = (devext->RSDT->header.Length - sizeof(devext->RSDT->header)) / 4; - struct ACPISDTHeader *header; - for (i = 0; i < length; i++) { - header = remap(devext->RSDT->Entry + i * 4, sizeof(struct ACPISDTHeader)); - if (memcmp(header->Signature, Signature, 4) == 0) { - return (uint32_t)header; - } - } - return 0; +uint32_t acpi_find_table(device_extension_t *devext, char *Signature) { + int i, length = + (devext->RSDT->header.Length - sizeof(devext->RSDT->header)) / 4; + struct ACPISDTHeader *header; + for (i = 0; i < length; i++) { + // TODO: memory result + MEMORY_RESULT_PRINT_CALL( + remap, devext->RSDT->Entry + i * 4, sizeof(struct ACPISDTHeader), + (uint32_t *)&header); + if (memcmp(header->Signature, Signature, 4) == 0) { + return (uint32_t)header; + } + } + return 0; } -static status_t acpi_enter(driver_t *drv_obj) -{ - device_t *devobj; - device_extension_t *devext; - - device_create(drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_MANAGER, &devobj); - if (drv_obj == NULL) { - return FAILED; - } - devext = devobj->device_extension; - if (devext == NULL) { - return FAILED; - } - - RSDP = (struct ACPI_RSDP *)acpi_find_rsdp(); - if (RSDP == NULL) { - return NODEV; - } - unsigned int *ptr = remap(RSDP->RsdtAddress, sizeof(struct ACPI_RSDT)); - if (ptr == NULL) { - return FAILED; - } - devext->RSDT = (struct ACPI_RSDT *)ptr; - // checksum(RSDT, RSDT->header.Length); - if (!checksum((uint8_t *)devext->RSDT, devext->RSDT->header.Length)) - return FAILED; - - devext->FADT = (struct ACPI_FADT *)acpi_find_table(devext, "FACP"); - if (devext->FADT == NULL) { - return FAILED; - } - if (!checksum((uint8_t *)devext->FADT, devext->FADT->h.Length)) - return FAILED; - - if (!(io_in16(devext->FADT->PM1aControlBlock) & 1)) { - if (devext->FADT->SMI_CommandPort && devext->FADT->AcpiEnable) { - io_out8(devext->FADT->SMI_CommandPort, devext->FADT->AcpiEnable); - int i; - for (i = 0; i < 300; i++) { - if (io_in16(devext->FADT->PM1aControlBlock) & 1) - break; - delay(1); - } - if (devext->FADT->PM1bControlBlock) { - for (; i < 300; i++) { - if (io_in16(devext->FADT->PM1bControlBlock) & 1) - break; - delay(1); - } - } - } - } - return SUCCUESS; +static status_t acpi_enter(driver_t *drv_obj) { + device_t *devobj; + device_extension_t *devext; + + device_create( + drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_MANAGER, &devobj); + if (drv_obj == NULL) { return FAILED; } + devext = devobj->device_extension; + if (devext == NULL) { return FAILED; } + + RSDP = (struct ACPI_RSDP *)acpi_find_rsdp(); + if (RSDP == NULL) { return NODEV; } + uint32_t *ptr; + MEMORY_RESULT_PRINT_CALL( + remap, RSDP->RsdtAddress, sizeof(struct ACPI_RSDT), (uint32_t *)&ptr); + if (ptr == NULL) { return FAILED; } + devext->RSDT = (struct ACPI_RSDT *)ptr; + // checksum(RSDT, RSDT->header.Length); + if (!checksum((uint8_t *)devext->RSDT, devext->RSDT->header.Length)) + return FAILED; + + devext->FADT = (struct ACPI_FADT *)acpi_find_table(devext, "FACP"); + if (devext->FADT == NULL) { return FAILED; } + if (!checksum((uint8_t *)devext->FADT, devext->FADT->h.Length)) + return FAILED; + + if (!(io_in16(devext->FADT->PM1aControlBlock) & 1)) { + if (devext->FADT->SMI_CommandPort && devext->FADT->AcpiEnable) { + io_out8(devext->FADT->SMI_CommandPort, devext->FADT->AcpiEnable); + int i; + for (i = 0; i < 300; i++) { + if (io_in16(devext->FADT->PM1aControlBlock) & 1) break; + // TODO: Delay + // delay(1); + } + if (devext->FADT->PM1bControlBlock) { + for (; i < 300; i++) { + if (io_in16(devext->FADT->PM1bControlBlock) & 1) break; + // TODO: Delay + // delay(1); + } + } + } + } + return SUCCUESS; } /* @@ -137,8 +130,9 @@ static status_t acpi_enter(driver_t *drv_obj) * NameOP | \(可选) | _ | S | 5 | _ * 08 | 5A | 5F | 53 | 35 | 5F * ----------------------------------- - * PackageOP | PkgLength | NumElements | prefix Num | prefix Num | prefix Num | prefix Num - * 12 | 0A | 04 | 0A 05 | 0A 05 | 0A 05 | 0A 05 + * PackageOP | PkgLength | NumElements | prefix Num | prefix Num | prefix Num | + * prefix Num 12 | 0A | 04 | 0A 05 | 0A 05 | 0A + * 05 | 0A 05 * ----------------------------------- * PkgLength: bit6~7为长度的字节数-1;bit4~5保留;bit0~3为长度的低4位 * prefix: 0A Byte @@ -151,59 +145,59 @@ static status_t acpi_enter(driver_t *drv_obj) /* void acpi_shutdown(device_extension_t *devext) { - int i; - uint16_t SLP_TYPa, SLP_TYPb; - struct ACPISDTHeader *header = (struct ACPISDTHeader *)acpi_find_table(devext, "DSDT"); - - char *S5Addr = (char *)header; - int dsdtLength = (header->Length - sizeof(struct ACPISDTHeader))/4; - - for(i = 0; i < dsdtLength; i++) - { - if (memcmp(S5Addr, "_S5_", 4) == 0) break; - S5Addr++; - } - if (i < dsdtLength) - { - if ( ( *(S5Addr-1) == 0x08 || ( *(S5Addr-2) == 0x08 && *(S5Addr-1) == '\\') ) && *(S5Addr+4) == 0x12 ) - { - S5Addr+=5; - S5Addr+=((*S5Addr&0xc0)>>6)+2; - - if (*S5Addr == 0x0a) S5Addr++; - SLP_TYPa = *(S5Addr)<<10; - S5Addr++; - - if (*S5Addr == 0x0a) S5Addr++; - SLP_TYPb = *(S5Addr)<<10; - S5Addr++; - } - // 关于PM1x_CNT_BLK的描述见 ACPI Specification Ver6.3 4.8.3.2.1 - io_out16(devext->FADT->PM1aControlBlock, SLP_TYPa | 1<<13); - if (devext->FADT->PM1bControlBlock != 0) - { - io_out16(devext->FADT->PM1bControlBlock, SLP_TYPb | 1<<13); - } - } + int i; + uint16_t SLP_TYPa, SLP_TYPb; + struct ACPISDTHeader *header = (struct ACPISDTHeader +*)acpi_find_table(devext, "DSDT"); + + char *S5Addr = (char *)header; + int dsdtLength = (header->Length - sizeof(struct ACPISDTHeader))/4; + + for(i = 0; i < dsdtLength; i++) + { + if (memcmp(S5Addr, "_S5_", 4) == 0) break; + S5Addr++; + } + if (i < dsdtLength) + { + if ( ( *(S5Addr-1) == 0x08 || ( *(S5Addr-2) == 0x08 && *(S5Addr-1) == +'\\') ) && *(S5Addr+4) == 0x12 ) + { + S5Addr+=5; + S5Addr+=((*S5Addr&0xc0)>>6)+2; + + if (*S5Addr == 0x0a) S5Addr++; + SLP_TYPa = *(S5Addr)<<10; + S5Addr++; + + if (*S5Addr == 0x0a) S5Addr++; + SLP_TYPb = *(S5Addr)<<10; + S5Addr++; + } + // 关于PM1x_CNT_BLK的描述见 ACPI Specification Ver6.3 4.8.3.2.1 + io_out16(devext->FADT->PM1aControlBlock, SLP_TYPa | 1<<13); + if (devext->FADT->PM1bControlBlock != 0) + { + io_out16(devext->FADT->PM1bControlBlock, SLP_TYPb | 1<<13); + } + } } */ -static status_t acpi_exit(driver_t *drv_obj) -{ - device_t *devobj, *next; - // device_extension_t *ext; - list_for_each_owner_safe (devobj, next, &drv_obj->device_list, list) { - device_delete(devobj); - } - string_del(&drv_obj->name); - return SUCCUESS; +static status_t acpi_exit(driver_t *drv_obj) { + device_t *devobj, *next; + // device_extension_t *ext; + list_for_each_owner_safe (devobj, next, &drv_obj->device_list, list) { + device_delete(devobj); + } + string_del(&drv_obj->name); + return SUCCUESS; } -static __init void acpi_driver_entry(void) -{ - if (driver_create(acpi_driver, DRV_NAME) < 0) { - printk(COLOR_RED "[driver] %s driver create failed!\n", __func__); - } +static __init void acpi_driver_entry(void) { + if (driver_create(acpi_driver, DRV_NAME) < 0) { + printk(COLOR_RED "[driver] %s driver create failed!\n", __func__); + } } driver_initcall(acpi_driver_entry); diff --git a/src/arch/x86/drivers/apic.c b/src/arch/x86/drivers/apic.c index 341fcb2..9c56485 100644 --- a/src/arch/x86/drivers/apic.c +++ b/src/arch/x86/drivers/apic.c @@ -5,6 +5,8 @@ * @version 0.1 Alpha * @date 2021-06 */ +#include +#include #include #include #include @@ -12,66 +14,399 @@ #include #include #include +#include +#include +#include #include #include #include #include +#include +#include +#include void apic_timer_handler(void); -uint32_t *lapic; -char use_apic; +char use_apic; volatile struct ioapic { uint32_t reg; uint32_t pad[3]; uint32_t data; -} *ioapic; - -// 检查是否支持x2APIC -int check_apic_support(void) { - uint32_t a, b, c, d; - get_cpuid(1, 0, &a, &b, &c, &d); - printk("CPUID 01H: eax:%x ebx:%x ecx:%x edx:%x\n", a, b, c, d); - if (!(d & (1 << 9))) { - printk(COLOR_RED "No Support APIC!\n"); - return -1; - } - return 0; +}; + +// --------new--------- +#include +#include +#include +#include +DriverResult apic_init(Device *device); +DriverResult apic_start(Device *device); +DriverResult apic_stop(Device *device); +DriverResult apic_driver_init(struct DeviceDriver *driver); +int apic_redirect_irq(InterruptDevice *device, int irq); +DriverResult apic_enable_irq(InterruptDevice *device, int irq); +DriverResult apic_disable_irq(InterruptDevice *device, int irq); +DriverResult apic_timer_init(Device *device); +DriverResult apic_timer_start(Device *device); +DriverResult apic_timer_stop(Device *device); +void apic_eoi(InterruptDevice *device, int irq); +TimerResult apic_timer_set_frequency( + TimerDevice *timer_device, uint32_t frequency); +void apic_timer_irq_handler(Device *device); + +typedef struct ApicInfo { + enum { + APIC_TYPE_XAPIC, + APIC_TYPE_X2APIC, + } apic_type; + uint32_t apic_base; + uint32_t apic_base_high; // 仅在使用x2APIC有用 + uint32_t apic_id; + uint32_t apic_id_high; // 仅在使用x2APIC有用 + uint8_t version; + uint8_t max_lvt_entry; + uint32_t *lapic_mmio; + struct ioapic *ioapic; +} ApicInfo; +ApicInfo apic_info; + +uint32_t lapic_write(int index, int value) { + apic_info.lapic_mmio[index / 4] = value; + return apic_info.lapic_mmio[APIC_ID / 4]; +} + +uint32_t lapic_read(int index) { + return apic_info.lapic_mmio[index / 4]; } +DeviceDriverOps apic_device_driver_ops = { + .register_driver_hook = NULL, + .unregister_driver_hook = NULL, +}; +DeviceOps apic_device_ops = { + .init = apic_init, + .start = apic_start, + .stop = apic_stop, + .destroy = NULL, + .status = NULL, +}; +InterruptDeviceOps apic_interrupt_ops = { + .enable_irq = apic_enable_irq, + .disable_irq = apic_disable_irq, + .eoi = apic_eoi, + .redirect_irq = apic_redirect_irq, +}; + +DeviceDriverOps apic_timer_device_driver_ops = { + .register_driver_hook = NULL, + .unregister_driver_hook = NULL, +}; +DeviceOps apic_timer_device_ops = { + .init = apic_timer_init, + .start = apic_timer_start, + .stop = apic_timer_stop, + .destroy = NULL, + .status = NULL, +}; +TimerOps apic_timer_ops = { + .set_frequency = apic_timer_set_frequency, +}; + +Driver apic_driver = {.name = STRING_INIT("APIC")}; + +DeviceDriver apic_device_driver = { + .name = STRING_INIT("APIC"), + .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, + .priority = DRIVER_PRIORITY_BASIC, + .state = DRIVER_STATE_UNREGISTERED, + .ops = &apic_device_driver_ops, +}; +Device apic_device = { + .name = STRING_INIT("APIC"), + .device_driver = &apic_device_driver, + .ops = &apic_device_ops, + .private_data_size = 0, +}; +InterruptDevice apic_interrupt_device = { + .interrupt_ops = &apic_interrupt_ops, + .priority = 1, +}; + +DeviceDriver apic_timer_device_driver = { + .name = STRING_INIT("APIC Timer"), + .type = DEVICE_TYPE_TIMER, + .priority = DRIVER_PRIORITY_BASIC, + .state = DRIVER_STATE_UNREGISTERED, + .ops = &apic_timer_device_driver_ops, +}; +DeviceIrq apic_timer_irq = { + .device = &apic_timer_device, + .irq = PIC_PIT_IRQ, + .handler = apic_timer_irq_handler, +}; +Device apic_timer_device = { + .name = STRING_INIT("APIC Timer"), + .device_driver = &apic_timer_device_driver, + .ops = &apic_timer_device_ops, + .irq = &apic_timer_irq, + .private_data_size = 0, +}; +TimerDevice apic_timer_timer_device = { + .current_frequency = 0, + .min_frequency = 0, + .max_frequency = 0, + .source_frequency = 0, + .priority = 2, + .timer_ops = &apic_timer_ops, +}; + uint32_t io_apic_read(uint32_t reg) { - ioapic->reg = reg; - return ioapic->data; + apic_info.ioapic->reg = reg; + return apic_info.ioapic->data; } void io_apic_write(uint32_t reg, uint32_t data) { - ioapic->reg = reg; - ioapic->data = data; + apic_info.ioapic->reg = reg; + apic_info.ioapic->data = data; } -void lapic_write(int index, int value) { - lapic[index / 4] = value; - lapic[APIC_ID / 4]; +DriverResult register_apic(void) { + register_device_driver(&apic_driver, &apic_device_driver); + register_device_driver(&apic_driver, &apic_timer_device_driver); + register_interrupt_device( + &apic_device_driver, &apic_device, &apic_interrupt_device); + register_timer_device( + &apic_device_driver, &apic_timer_device, &apic_timer_timer_device); + return DRIVER_RESULT_OK; } -uint32_t lapic_read(int index) { - return lapic[index / 4]; +DriverResult apic_driver_init(struct DeviceDriver *driver) { + if (cpu_check_feature(CPUID_FEAT_X2APIC)) { + apic_info.apic_type = APIC_TYPE_X2APIC; + // 还未实现x2apic支持,这里只是简单的初始化 + uint32_t low, high; + read_msr(APIC_BASE_MSR, &low, &high); + + apic_info.apic_base = 0xfee00000; + apic_info.apic_base_high = low >> 12; + + DRV_RESULT_PRINT_CALL( + driver_remap_memory, &apic_driver, apic_info.apic_base, 0x3ff, + (uint32_t *)&apic_info.lapic_mmio); + DRV_RESULT_PRINT_CALL( + driver_remap_memory, &apic_driver, 0xfec00000, 0xfff00, + (uint32_t *)apic_info.ioapic); + + read_msr(X2APIC_ID_MSR, &apic_info.apic_id, &apic_info.apic_id_high); + apic_info.version = (lapic_read(APIC_Ver) & 0xff) | + ((lapic_read(APIC_Ver) >> 16) & 0xff); + } else if (cpu_check_feature(CPUID_FEAT_APIC)) { + apic_info.apic_type = APIC_TYPE_XAPIC; + apic_info.apic_base = 0xfee00000; + + DRV_RESULT_PRINT_CALL( + driver_remap_memory, &apic_driver, apic_info.apic_base, 0x3ff, + (uint32_t *)&apic_info.lapic_mmio); + DRV_RESULT_PRINT_CALL( + driver_remap_memory, &apic_driver, 0xfec00000, 0xfff00, + (uint32_t *)&apic_info.ioapic); + + apic_info.apic_id = lapic_read(APIC_ID) >> 24; + apic_info.version = (lapic_read(APIC_Ver) & 0xff); + apic_info.max_lvt_entry = (lapic_read(APIC_Ver) >> 16) & 0xff; + } else { + return DRIVER_RESULT_DEVICE_NOT_EXIST; + } + return DRIVER_RESULT_OK; } -void init_apic(void) { - if (check_apic_support()) { - init_8259a(); - return; +void enable_apic_with_msr(void) { + // TODO: 完善xAPIC和x2APIC支持 + uint32_t low, high; + read_msr(APIC_BASE_MSR, &low, &high); + write_msr(APIC_BASE_MSR, BIN_EN(low, BIT(APIC_GLOBAL_ENABLE_BIT)), high); +} + +void disable_apic_with_msr(void) { + // TODO: 完善xAPIC和x2APIC支持 + uint32_t low, high; + read_msr(APIC_BASE_MSR, &low, &high); + write_msr(APIC_BASE_MSR, BIN_DIS(low, BIT(APIC_GLOBAL_ENABLE_BIT)), high); +} + +void enable_apic_with_sivr(void) { + uint32_t data = lapic_read(APIC_SIVR); + lapic_write(APIC_SIVR, BIN_EN(data, BIT(APIC_SOFTWARE_ENABLE_BIT))); +} + +void disable_apic_with_sivr(void) { + uint32_t data = lapic_read(APIC_SIVR); + lapic_write(APIC_SIVR, BIN_DIS(data, BIT(APIC_SOFTWARE_ENABLE_BIT))); +} + +void enable_apic(void) { + if (apic_info.apic_type == APIC_TYPE_X2APIC) { + enable_apic_with_msr(); + } else if (apic_info.apic_type == APIC_TYPE_XAPIC) { + enable_apic_with_sivr(); + } +} + +void disable_apic(void) { + if (apic_info.apic_type == APIC_TYPE_X2APIC) { + disable_apic_with_msr(); + } else if (apic_info.apic_type == APIC_TYPE_XAPIC) { + disable_apic_with_sivr(); } +} + +DriverResult apic_init(Device *device) { + apic_driver_init(&apic_device_driver); + + lapic_write(APIC_LVT_LINT0, BIT(16)); + lapic_write(APIC_LVT_LINT1, BIT(16)); + lapic_write(APIC_LVT_ERROR, 0xfe); + lapic_write(APIC_ESR, 0); + lapic_write(APIC_ESR, 0); + lapic_write(APIC_EOI, 0); + + lapic_write(APIC_ICR_HIGH, 0); + lapic_write( + APIC_ICR_LOW, APIC_ICR_DELIVERY_MODE_INIT | + APIC_ICR_TRIGGER_MODE_LEVEL | + APIC_ICR_DEST_SHORTHAND_ALL_INCLUDING_SELF); + const int timeout = 100000; + int i; + for (i = 0; + i < timeout && lapic_read(APIC_ICR_LOW) & APIC_ICR_STAT_SEND_PENDING; + i++) + ; + + if (i == timeout) { + print_error("APIC init timeout\n"); + return DRIVER_RESULT_TIMEOUT; + } + + lapic_write(APIC_TPR, 0); + + for (int i = 0; i < apic_info.max_lvt_entry; i++) { + apic_disable_irq(device->driver_manager_extension, 0x20 + i); + } + return DRIVER_RESULT_OK; +} + +DriverResult apic_timer_calibrate(Device *device) { + const int ms = 10; + Timer timer; + timer_init(&timer); + + uint32_t data = lapic_read(APIC_LVT_TIMER); + lapic_write(APIC_LVT_TIMER, BIN_DIS(data, BIT(16))); + + lapic_write(APIC_TIMER_ICT, 0xffffffff); + + enable_interrupt(); + delay_ms(&timer, ms); + disable_interrupt(); + + lapic_write(APIC_LVT_TIMER, BIN_EN(data, BIT(16))); + + uint32_t apic_timer_count = lapic_read(APIC_TIMER_CCT); + uint32_t freq = (0xffffffff - apic_timer_count) * (1000 / ms); + apic_timer_timer_device.source_frequency = freq; + apic_timer_timer_device.min_frequency = DIV_ROUND_UP(freq, 0xffffffff); + apic_timer_timer_device.max_frequency = freq; + return DRIVER_RESULT_OK; +} + +DriverResult apic_timer_init(Device *device) { + lapic_write(APIC_TIMER_DCR, APIC_TIMER_DCR_DIVIDE_BY_1); + lapic_write( + APIC_LVT_TIMER, + APIC_LVT_TIMER_MODE_PERIODIC | (0x20 + LAPIC_TIMER_IRQ)); + apic_timer_calibrate(device); + return DRIVER_RESULT_OK; +} + +DriverResult apic_start(Device *device) { + /*打了个洞,不过都有APIC了至少得有PIC吧,问题不大 + 所有文档都指明了要先关闭8259A,那就关吧*/ mask_8259a(); + + enable_apic(); + return DRIVER_RESULT_OK; +} + +DriverResult apic_timer_start(Device *device) { + uint32_t data = lapic_read(APIC_LVT_TIMER); + lapic_write(APIC_LVT_TIMER, BIN_DIS(data, BIT(16))); + return DRIVER_RESULT_OK; +} + +DriverResult apic_stop(Device *device) { + disable_apic(); + return DRIVER_RESULT_OK; +} + +DriverResult apic_timer_stop(Device *device) { + uint32_t data = lapic_read(APIC_LVT_TIMER); + lapic_write(APIC_LVT_TIMER, BIN_EN(data, BIT(16))); + return DRIVER_RESULT_OK; +} + +int apic_redirect_irq(InterruptDevice *device, int irq) { + if (irq == PIC_PIT_IRQ) { + irq = APIC_PIT_IRQ; + } else if (irq == 2) { + irq = 0; + } + return irq; +} + +DriverResult apic_enable_irq(InterruptDevice *device, int irq) { + io_apic_write(IOAPIC_TBL + irq * 2, BIN_DIS(0x20 + irq, BIT(16))); + io_apic_write(IOAPIC_TBL + irq * 2 + 1, 0); + return DRIVER_RESULT_OK; +} + +DriverResult apic_disable_irq(InterruptDevice *device, int irq) { + io_apic_write(IOAPIC_TBL + irq * 2, BIN_EN(0x20 + irq, BIT(16))); + io_apic_write(IOAPIC_TBL + irq * 2 + 1, 0); + return DRIVER_RESULT_OK; +} + +void apic_eoi(InterruptDevice *device, int irq) { + lapic_write(APIC_EOI, 0); +} + +TimerResult apic_timer_set_frequency( + TimerDevice *timer_device, uint32_t frequency) { + uint32_t divisor = apic_timer_timer_device.source_frequency / frequency; + lapic_write(APIC_TIMER_ICT, divisor); + return TIMER_RESULT_OK; +} + +void apic_timer_irq_handler(Device *device) { + timer_irq_handler(device); +} + +// --------old--------- +// TODO: 删除旧代码 + +void init_apic(void) { + // if (check_apic_support()) { + // init_8259a(); + // return; + // } + // mask_8259a(); use_apic = 1; // cpu_RDMSR(IA32_APIC_BASE, &l, &h); // printk("APIC Base:%#08x%08x\n", h, l); // cpu_WRMSR(IA32_APIC_BASE, l | (1<<10) | (1<<11), h); // //APIC全局使能,启用APIC - lapic = remap(0xfee00000, 0x3ff); - ioapic = remap(0xfec00000, 0xfff00); + // apic_info.lapic_mmio = remap(0xfee00000, 0x3ff); + // apic_info.ioapic = remap(0xfec00000, 0xfff00); io_cli(); lapic_write(APIC_SIVR, 1 << 8); // 设定Loacl APIC定时器 @@ -104,7 +439,7 @@ void init_apic(void) { // 屏蔽LVT // lapic_write(APIC_LVT_CMCI, 1<<16); // lapic_write(APIC_LVT_THMR, 1<<16); - if (((lapic[APIC_Ver / 4] >> 16) & 0xff) >= 4) { + if (((apic_info.lapic_mmio[APIC_Ver / 4] >> 16) & 0xff) >= 4) { lapic_write(APIC_LVT_PMCR, 1 << 16); } lapic_write(APIC_LVT_LINT0, 1 << 16); @@ -116,7 +451,7 @@ void init_apic(void) { lapic_write(APIC_ICR_HIGH, 0); lapic_write(APIC_ICR_LOW, (1 << 19) | (1 << 15) | (1 << 10) | (1 << 8)); - while (lapic[APIC_ICR_LOW / 4] & (1 << 12)) + while (apic_info.lapic_mmio[APIC_ICR_LOW / 4] & (1 << 12)) ; lapic_write(APIC_TPR, 0); @@ -128,7 +463,7 @@ void init_apic(void) { } put_irq_handler(LAPIC_TIMER_IRQ, (irq_handler_t)apic_timer_handler); - apic_enable_irq(LAPIC_TIMER_IRQ); + // apic_enable_irq(LAPIC_TIMER_IRQ); } void apic_timer_handler(void) { @@ -141,12 +476,3 @@ void apic_timer_handler(void) { cur_thread->ticks--; } } - -void apic_enable_irq(int irq) { - io_apic_write(IOAPIC_TBL + irq * 2, 0x20 + irq); - io_apic_write(IOAPIC_TBL + irq * 2 + 1, 0); -} - -void apic_eoi(void) { - lapic_write(APIC_EOI, 0); -} \ No newline at end of file diff --git a/src/arch/x86/drivers/cpufreq.c b/src/arch/x86/drivers/cpufreq.c index 0236ad8..d9213f9 100644 --- a/src/arch/x86/drivers/cpufreq.c +++ b/src/arch/x86/drivers/cpufreq.c @@ -20,21 +20,21 @@ unsigned int cpu_get_freq(void) { struct fifo fifo; char fifo_buf[4]; fifo_init(&fifo, 4, (int *)fifo_buf); - timer = timer_alloc(); - timer_init(timer, &fifo, 128); + // timer = timer_alloc(); + // timer_init(timer, &fifo, 128); - timer_settime(timer, 100); + // timer_settime(timer, 100); while (fifo_status(&fifo) == 0) io_hlt(); fifo_get(&fifo); - timer_settime(timer, 100); + // timer_settime(timer, 100); __asm__ __volatile__("rdtsc \n\t" : "=A"(tsc)); while (fifo_status(&fifo) == 0) ; fifo_get(&fifo); __asm__ __volatile__("rdtsc \n\t" : "=A"(tsc2)); - timer_free(timer); + // timer_free(timer); return (tsc2 - tsc) / 1000 / 1000; } \ No newline at end of file diff --git a/src/arch/x86/drivers/pit.c b/src/arch/x86/drivers/pit.c index 780aeb4..cb1046a 100644 --- a/src/arch/x86/drivers/pit.c +++ b/src/arch/x86/drivers/pit.c @@ -1,154 +1,250 @@ /** * @file pit.c * @author Ryan Wang (ryan1202@foxmail.com) - * @brief - * @version 1.0 + * @brief PIT(Programmable Interval Timer)驱动 * @date 2022-07-31 */ +#include #include #include #include #include #include +#include +#include #include #include +#include -struct timerctl timerctl; - -void init_timer(void) { - int i; - io_out8(PIT_CTRL, 0x34); - io_out8(PIT_CNT0, 0x9c); - io_out8(PIT_CNT0, 0x2e); - - timerctl.count = 0; - timerctl.next = 0xffffffff; // 没有定时器 - timerctl.using = 0; - for (i = 0; i <= MAX_TIMER; i++) { - timerctl.timers0[i].flags = TIMER_FREE; // 释放所有计时器 - } - - if (use_apic) { - put_irq_handler(APIC_PIT_IRQ, timer_handler); - irq_enable(APIC_PIT_IRQ); - } else { - put_irq_handler(PIC_PIT_IRQ, timer_handler); - irq_enable(PIC_PIT_IRQ); - } - return; + +// ---------new--------- +#include +#include +#include +#include +#include + +#define PIT_MAX_FREQUENCY 1193180 + +DriverResult pit_init(Device *device); +TimerResult pit_set_frequency(TimerDevice *timer_device, uint32_t frequency); +DriverResult pit_start(Device *device); +DriverResult pit_stop(Device *device); +void pit_irq_handler(Device *device); + +DeviceDriverOps pit_driver_ops = { + .register_driver_hook = NULL, + .unregister_driver_hook = NULL, +}; +DeviceOps pit_device_ops = { + .init = pit_init, + .destroy = NULL, + .start = pit_start, + .stop = pit_stop, + .status = NULL, +}; +TimerOps pit_timer_ops = { + .set_frequency = pit_set_frequency, +}; +DeviceIrq pit_irq = { + .device = &pit_device, + .irq = PIC_PIT_IRQ, + .handler = pit_irq_handler, +}; + +Driver pit_driver; +DeviceDriver pit_device_driver = { + .name = STRING_INIT("PIT"), + .type = DEVICE_TYPE_TIMER, + .priority = DRIVER_PRIORITY_BASIC, + .state = DRIVER_STATE_UNREGISTERED, + .ops = &pit_driver_ops, +}; +Device pit_device = { + .device_driver = &pit_device_driver, + .ops = &pit_device_ops, + .irq = &pit_irq, + .private_data_size = 0, +}; +TimerDevice pit_timer_device = { + .current_frequency = 0, + .min_frequency = PIT_MAX_FREQUENCY / (uint16_t)-1, + .max_frequency = PIT_MAX_FREQUENCY / 1, + .source_frequency = PIT_MAX_FREQUENCY, + .priority = 1, + + .timer_ops = &pit_timer_ops, +}; + +void register_pit() { + register_device_driver(&pit_driver, &pit_device_driver); + register_timer_device(&pit_device_driver, &pit_device, &pit_timer_device); } -void timer_handler(int irq) { - int i; - struct timer *timer; - timerctl.count++; - if (use_apic) { - struct task_s *cur_thread = get_current_thread(); - cur_thread->elapsed_ticks++; - - if (cur_thread->ticks == 0) { - schedule(); - } else { - cur_thread->ticks--; - } - } - if (timerctl.next > timerctl.count) { return; } - timer = timerctl.timers[0]; - for (i = 0; i < timerctl.using; i++) { - if (timer->timeout > timerctl.count) { break; } - timer->flags = TIMER_UNUSED; - fifo_put(timer->fifo, timer->data); - timer = timer->next; - } - timerctl.using -= i; - timerctl.timers[0] = timer; - if (timerctl.using > 0) { - timerctl.next = timerctl.timers[0]->timeout; - } else { - timerctl.next = 0xffffffff; - } - return; +DriverResult pit_init(Device *device) { + io_out_byte(PIT_CTRL, 0x34); + register_device_irq(pit_device.irq); + return DRIVER_RESULT_OK; } -struct timer *timer_alloc(void) { - int i; - for (i = 0; i < MAX_TIMER; i++) { - if (timerctl.timers0[i].flags == 0) { - timerctl.timers0[i].flags = TIMER_UNUSED; - return &timerctl.timers0[i]; - } - } - return 0; +TimerResult pit_set_frequency(TimerDevice *timer_device, uint32_t frequency) { + uint32_t divisor = PIT_MAX_FREQUENCY / frequency; + io_out_byte(PIT_CNT0, (uint8_t)(divisor & 0xff)); + io_out_byte(PIT_CNT0, (uint8_t)((divisor >> 8) & 0xff)); + return TIMER_RESULT_OK; } -void timer_free(struct timer *timer) { - if (timer->flags == TIMER_USING) { timerctl.using --; } - timer->flags = TIMER_FREE; - return; +DriverResult pit_start(Device *device) { + DRV_RESULT_DELIVER_CALL(interrupt_enable_irq, device->irq->irq); + return DRIVER_RESULT_OK; } -void timer_init(struct timer *timer, struct fifo *fifo, int data) { - timer->fifo = fifo; - timer->data = data; - return; +DriverResult pit_stop(Device *device) { + DRV_RESULT_DELIVER_CALL(interrupt_disable_irq, device->irq->irq); + return DRIVER_RESULT_OK; } -void timer_settime(struct timer *timer, unsigned int timeout) { - int e; - struct timer *t, *s; - timer->timeout = timeout + timerctl.count; - timer->flags = TIMER_USING; - e = io_load_eflags(); - io_cli(); - timerctl.using ++; - if (timerctl.using == 1) { - timerctl.timers[0] = timer; - timer->next = 0; - timerctl.next = timer->timeout; - io_store_eflags(e); - return; - } - t = timerctl.timers[0]; - if (timer->timeout <= t->timeout) { - timerctl.timers[0] = timer; - timer->next = t; - timerctl.next = timer->timeout; - io_store_eflags(e); - return; - } - for (;;) { - s = t; - t = t->next; - if (t == 0) { break; } - if (timer->timeout <= t->timeout) { - s->next = timer; - timer->next = t; - io_store_eflags(e); - return; - } - } - s->next = timer; - timer->next = 0; - io_store_eflags(e); - return; +void pit_irq_handler(Device *device) { + timer_irq_handler(device); } -/** - * @brief 等待 - * - * @param time 时间(单位:10毫秒) - */ -void delay(int time) { - struct timer *timer; - struct fifo fifo; - char buf[1]; - timer = timer_alloc(); - fifo_init(&fifo, 1, (int *)buf); - timer_init(timer, &fifo, 0); - timer_settime(timer, time); - while (!fifo_status(&fifo)) - ; - fifo_get(&fifo); - timer_free(timer); +// ---------old--------- +// struct timerctl timerctl; + +// void init_timer(void) { +// int i; +// io_out8(PIT_CTRL, 0x34); +// io_out8(PIT_CNT0, 0x9c); +// io_out8(PIT_CNT0, 0x2e); + +// timerctl.count = 0; +// timerctl.next = 0xffffffff; // 没有定时器 +// timerctl.using = 0; +// for (i = 0; i <= MAX_TIMER; i++) { +// timerctl.timers0[i].flags = TIMER_FREE; // 释放所有计时器 +// } + +// if (use_apic) { +// put_irq_handler(APIC_PIT_IRQ, timer_handler); +// irq_enable(APIC_PIT_IRQ); +// } else { +// put_irq_handler(PIC_PIT_IRQ, timer_handler); +// irq_enable(PIC_PIT_IRQ); +// } +// return; +// } + +void timer_handler(int irq) { + // int i; + // struct timer *timer; + // timerctl.count++; + // if (use_apic) { + // struct task_s *cur_thread = get_current_thread(); + // cur_thread->elapsed_ticks++; + + // if (cur_thread->ticks == 0) { + // schedule(); + // } else { + // cur_thread->ticks--; + // } + // } + // if (timerctl.next > timerctl.count) { return; } + // timer = timerctl.timers[0]; + // for (i = 0; i < timerctl.using; i++) { + // if (timer->timeout > timerctl.count) { break; } + // timer->flags = TIMER_UNUSED; + // fifo_put(timer->fifo, timer->data); + // timer = timer->next; + // } + // timerctl.using -= i; + // timerctl.timers[0] = timer; + // if (timerctl.using > 0) { + // timerctl.next = timerctl.timers[0]->timeout; + // } else { + // timerctl.next = 0xffffffff; + // } return; } + +// struct timer *timer_alloc(void) { +// int i; +// for (i = 0; i < MAX_TIMER; i++) { +// if (timerctl.timers0[i].flags == 0) { +// timerctl.timers0[i].flags = TIMER_UNUSED; +// return &timerctl.timers0[i]; +// } +// } +// return 0; +// } + +// void timer_free(struct timer *timer) { +// if (timer->flags == TIMER_USING) { timerctl.using --; } +// timer->flags = TIMER_FREE; +// return; +// } + +// void timer_init(struct timer *timer, struct fifo *fifo, int data) { +// timer->fifo = fifo; +// timer->data = data; +// return; +// } + +// void timer_settime(struct timer *timer, unsigned int timeout) { +// int e; +// struct timer *t, *s; +// timer->timeout = timeout + timerctl.count; +// timer->flags = TIMER_USING; +// e = io_load_eflags(); +// io_cli(); +// timerctl.using ++; +// if (timerctl.using == 1) { +// timerctl.timers[0] = timer; +// timer->next = 0; +// timerctl.next = timer->timeout; +// io_store_eflags(e); +// return; +// } +// t = timerctl.timers[0]; +// if (timer->timeout <= t->timeout) { +// timerctl.timers[0] = timer; +// timer->next = t; +// timerctl.next = timer->timeout; +// io_store_eflags(e); +// return; +// } +// for (;;) { +// s = t; +// t = t->next; +// if (t == 0) { break; } +// if (timer->timeout <= t->timeout) { +// s->next = timer; +// timer->next = t; +// io_store_eflags(e); +// return; +// } +// } +// s->next = timer; +// timer->next = 0; +// io_store_eflags(e); +// return; +// } + +// /** +// * @brief 等待 +// * +// * @param time 时间(单位:10毫秒) +// */ +// void delay(int time) { +// struct timer *timer; +// struct fifo fifo; +// char buf[1]; +// timer = timer_alloc(); +// fifo_init(&fifo, 1, (int *)buf); +// timer_init(timer, &fifo, 0); +// timer_settime(timer, time); +// while (!fifo_status(&fifo)) +// ; +// fifo_get(&fifo); +// timer_free(timer); +// return; +// } diff --git a/src/arch/x86/drivers/sound/sb16.c b/src/arch/x86/drivers/sound/sb16.c index ffc58a3..a04bcb5 100644 --- a/src/arch/x86/drivers/sound/sb16.c +++ b/src/arch/x86/drivers/sound/sb16.c @@ -45,7 +45,7 @@ static status_t sb16_enter(driver_t *drv_obj); static status_t sb16_exit(driver_t *drv_obj); status_t sb16_open(device_t *device); status_t sb16_close(device_t *device); -status_t sb16_write(device_t *dev, uint8_t *buf, uint32_t offset, size_t size); +status_t sb16_write(device_t *dev, uint8_t *buf, uint32_t offset, size_t size); #define DRV_NAME "Sound Blaster 16 Driver" #define DEV_NAME "sb16" @@ -53,13 +53,14 @@ status_t sb16_write(device_t *dev, uint8_t *buf, uint32_t offset, size_t size); #define DMA_MAX 4 uint32_t data_len[DMA_MAX]; -driver_func_t sb16_driver = {.driver_enter = sb16_enter, - .driver_exit = sb16_exit, - .driver_open = sb16_open, - .driver_close = sb16_close, - .driver_read = NULL, - .driver_write = sb16_write, - .driver_devctl = NULL}; +driver_func_t sb16_driver = { + .driver_enter = sb16_enter, + .driver_exit = sb16_exit, + .driver_open = sb16_open, + .driver_close = sb16_close, + .driver_read = NULL, + .driver_write = sb16_write, + .driver_devctl = NULL}; typedef struct { int major_ver, minor_ver; @@ -92,7 +93,8 @@ static status_t sb16_enter(driver_t *drv_obj) { device_t *devobj; device_extension_t *devext; - device_create(drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_SOUND, &devobj); + device_create( + drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_SOUND, &devobj); if (devobj == NULL) { device_delete(devobj); return FAILED; @@ -158,7 +160,8 @@ void sb16_set_sample_rate(uint16_t samplerate) { status_t dsp_reset(void) { io_out8(SB16_DSP_RESET, 1); - delay(1); + // TODO: Delay + // delay(1); io_out8(SB16_DSP_RESET, 0); int data = dsp_read(); @@ -182,7 +185,9 @@ void sb16_request(device_extension_t *devext) { int length = data_len[devext->index_r]; if (devext->index_r == devext->index_w) { return; } - sb16_dma_config(0x05, (uint32_t)(0x800000 + devext->index_r * 0x10000), data_len[devext->index_r]); + sb16_dma_config( + 0x05, (uint32_t)(0x800000 + devext->index_r * 0x10000), + data_len[devext->index_r]); uint16_t sample_count = length / sizeof(int16_t) / 2 - 1; dsp_write(0xb0); diff --git a/src/arch/x86/drivers/usb/hci/uhci.c b/src/arch/x86/drivers/usb/hci/uhci.c index cf598df..a220808 100644 --- a/src/arch/x86/drivers/usb/hci/uhci.c +++ b/src/arch/x86/drivers/usb/hci/uhci.c @@ -68,7 +68,8 @@ void uhci_reset(uhci_t *devext) { // io_out16(devext->io_base+UHCI_REG_USBINTR, 0); //禁用UHCI的所有中断 io_out16(devext->io_base + UHCI_REG_CMD, UHCI_CMD_GLBRESET); - delay(50 / 10); // 至少50ms + // TODO: Delay + // delay(50 / 10); // 至少50ms io_out16(devext->io_base + UHCI_REG_CMD, 0); devext->port_cnt = @@ -137,20 +138,23 @@ void uhci_port_reset(uhci_t *devext, int port) { uint32_t io_port = devext->io_base + UHCI_PORTSC1 + port * 2; io_out16(io_port, UHCI_PORT_SC_RESET); - delay(50 / 10); + // TODO: Delay + // delay(50 / 10); uint32_t value = io_in16(io_port); io_out16(io_port, BIN_DIS(value, UHCI_PORT_SC_RESET)); do { value = io_in16(io_port); } while (BIN_IS_EN(value, UHCI_PORT_SC_RESET)); - delay(10 / 10); + // TODO: Delay + // delay(10 / 10); // 使能 io_out16( io_port, UHCI_PORT_SC_CONN_CHG | UHCI_PORT_SC_EN_CHG | UHCI_PORT_SC_ENABLE); io_in16(io_port); - delay(10 / 10); + // TODO: Delay + // delay(10 / 10); } void uhci_port_init(usb_hcd_t *hcd, int port) { diff --git a/src/arch/x86/drivers/usb/hci/uhci/packet.c b/src/arch/x86/drivers/usb/hci/uhci/packet.c index b07eb23..96d084b 100644 --- a/src/arch/x86/drivers/usb/hci/uhci/packet.c +++ b/src/arch/x86/drivers/usb/hci/uhci/packet.c @@ -74,7 +74,8 @@ int uhci_wait_transfer(uhci_qh_t *qh) { while (timeout > 0) { if (td->active == 0) { return 1; } - delay(10 / 10); + // TODO: Delay + // delay(10 / 10); timeout--; } printk("[UHCI]td %#08x(phy %#08x) timeout.", td, td->td_addr_phy); diff --git a/src/arch/x86/drivers/usb/hub.c b/src/arch/x86/drivers/usb/hub.c index 2439f75..1ccce43 100644 --- a/src/arch/x86/drivers/usb/hub.c +++ b/src/arch/x86/drivers/usb/hub.c @@ -11,7 +11,8 @@ void usb_init_hub(usb_hcd_t *hcd, usb_device_t *device) { usb_endpoint_t ep = usb_default_ep; hcd->device_count++; usb_set_address(hcd, device, &ep, hcd->device_count); - delay(2); + // TODO: Delay + // delay(2); device->address = hcd->device_count; struct usb_hub_descriptor *desc = usb_get_hub_descriptor(hcd, device, &ep); usb_show_hub_descriptor(desc); @@ -22,9 +23,10 @@ void usb_init_hub(usb_hcd_t *hcd, usb_device_t *device) { for (i = 1; i <= desc->bNbrPorts; i++) { usb_set_port_feature(hcd, device, &ep, i, HUB_FEAT_PORT_POWER); - delay(50 / 10); + // TODO: Delay + // delay(50 / 10); usb_set_port_feature(hcd, device, &ep, i, HUB_FEAT_PORT_RESET); - delay(200 / 10); + // delay(200 / 10); status = usb_get_port_status(hcd, device, &ep, i); if (BIN_IS_EN(status, USB_PORT_STAT_CONNECTION)) { @@ -33,7 +35,8 @@ void usb_init_hub(usb_hcd_t *hcd, usb_device_t *device) { : USB_SPEED_FULL), 0); usb_init_device(hcd, dev); - delay(100 / 10); + // TODO: Delay + // delay(100 / 10); } } } \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/usb.c b/src/arch/x86/drivers/usb/usb.c index 8a83180..35cea00 100644 --- a/src/arch/x86/drivers/usb/usb.c +++ b/src/arch/x86/drivers/usb/usb.c @@ -65,7 +65,8 @@ int usb_init_device(usb_hcd_t *hcd, usb_device_t *device) { usb_show_device_descriptor(hcd, device, &ep, desc); hcd->device_count++; usb_set_address(hcd, device, &ep, hcd->device_count); - delay(2); + // TODO: Delay + // delay(2); device->address = hcd->device_count; usb_get_config_descriptor(hcd, device, &ep); diff --git a/src/arch/x86/drivers/vesa_display.c b/src/arch/x86/drivers/vesa_display.c new file mode 100644 index 0000000..ca0457f --- /dev/null +++ b/src/arch/x86/drivers/vesa_display.c @@ -0,0 +1,84 @@ +#include "drivers/video.h" +#include +#include +#include +#include +#include +#include +#include +#include + +struct VesaDisplayInfo vesa_display_info; + +DriverResult vesa_display_device_init(Device *device); +DriverResult vesa_display_device_start(Device *device); + +DeviceDriverOps vesa_display_driver_ops = { + .register_driver_hook = NULL, + .unregister_driver_hook = NULL, +}; +DeviceOps vesa_display_device_ops = { + .init = vesa_display_device_init, + .start = vesa_display_device_start, + .stop = NULL, + .destroy = NULL, + .status = NULL, +}; + +Driver vesa_display_driver = { + .name = STRING_INIT("vesa display driver"), +}; +DeviceDriver vesa_display_device_driver = { + .name = STRING_INIT("vesa display device driver"), + .type = DEVICE_TYPE_VIDEO, + .priority = DRIVER_PRIORITY_BASIC, + .state = DRIVER_STATE_UNREGISTERED, + .ops = &vesa_display_driver_ops, +}; +Device vesa_display_device = { + .name = STRING_INIT("vesa display"), + .device_driver = &vesa_display_device_driver, + .ops = &vesa_display_device_ops, + .private_data_size = 0, +}; +VideoDevice vesa_display_video_device = { + .device = &vesa_display_device, +}; + +void register_vesa_display(void) { + register_device_driver(&vesa_display_driver, &vesa_display_device_driver); + register_video_device( + &vesa_display_device_driver, &vesa_display_device, + &vesa_display_video_device); +} + +#define SEG_ADDR2LINEAR_ADDR(addr) \ + ((unsigned int *)(((unsigned int)(addr) >> 12) & 0xffff0) + \ + ((unsigned int)(addr) & 0xffff)) + +DriverResult vesa_display_device_init(Device *device) { + vesa_display_info.vbe_mode_info->OemStringPtr = + SEG_ADDR2LINEAR_ADDR(vesa_display_info.vbe_mode_info->OemStringPtr); + vesa_display_info.vbe_mode_info->VideoModePtr = + SEG_ADDR2LINEAR_ADDR(vesa_display_info.vbe_mode_info->VideoModePtr); + vesa_display_info.vbe_mode_info->OemVendorNamePtr = + SEG_ADDR2LINEAR_ADDR(vesa_display_info.vbe_mode_info->OemVendorNamePtr); + vesa_display_info.vbe_mode_info->OemProduceRevPtr = + SEG_ADDR2LINEAR_ADDR(vesa_display_info.vbe_mode_info->OemProduceRevPtr); + vesa_display_info.vbe_mode_info->OemProductNamePtr = SEG_ADDR2LINEAR_ADDR( + vesa_display_info.vbe_mode_info->OemProductNamePtr); + return DRIVER_RESULT_OK; +} + +DriverResult vesa_display_device_start(Device *device) { + vesa_display_info.vram = (uint8_t *)VRAM_VIR_ADDR; + VideoDevice *video_device = device->driver_manager_extension; + video_device->mode_info.width = vesa_display_info.width; + video_device->mode_info.height = vesa_display_info.height; + video_device->mode_info.bits_per_pixel = vesa_display_info.BitsPerPixel; + video_device->mode_info.bytes_per_pixel = + vesa_display_info.BitsPerPixel / 8; + video_device->framebuffer_address = vesa_display_info.vram; + + return DRIVER_RESULT_OK; +} diff --git a/src/arch/x86/drivers/video.c b/src/arch/x86/drivers/video.c index 70324da..e199d0c 100644 --- a/src/arch/x86/drivers/video.c +++ b/src/arch/x86/drivers/video.c @@ -33,7 +33,7 @@ void init_video() { video_info.vram = (uint8_t *)VRAM_VIR_ADDR; printk( - "Display mode: %d*%d %dbit\n", video_info.width, video_info.height, + "Display mode: %d*%d %dbit \n", video_info.width, video_info.height, video_info.BitsPerPixel); video_info.vbe_mode_info->OemStringPtr = @@ -125,98 +125,4 @@ void show_vbeinfo() { printk("OEM VendorName:%s\n", video_info.vbe_mode_info->OemVendorNamePtr); printk("OEM ProductName:%s\n", video_info.vbe_mode_info->OemProductNamePtr); printk("OEM ProduceRev:%s\n", video_info.vbe_mode_info->OemProduceRevPtr); -} - -/** - * @brief 写像素 - * - * @param x x坐标 - * @param y y坐标 - * @param color 颜色 - */ -void write_pixel(int x, int y, unsigned int color) { - unsigned char r, g, b; - r = (unsigned char)(color >> 16); - g = (unsigned char)(color >> 8); - b = (unsigned char)color; - unsigned char *vram = - (unsigned char *)(video_info.vram + (y * video_info.width + x) * - (video_info.BitsPerPixel / 8)); - if (video_info.BitsPerPixel == 32) { - vram[0] = color & 0xff; - vram[1] = (color >> 8) & 0xff; - vram[2] = (color >> 16) & 0xff; - } else if (video_info.BitsPerPixel == 24) { - vram[0] = color & 0xff; - vram[1] = (color >> 8) & 0xff; - vram[2] = (color >> 16) & 0xff; - } else if (video_info.BitsPerPixel == 16) { - vram[0] = ((g * 63 / 255) & 0x7) << 5 | (b * 31 / 255); - vram[1] = (r * 31 / 255) << 3 | ((g * 63 / 255) & 0x38) >> 3; - } else if (video_info.BitsPerPixel == 8) { - vram[0] = (r / 51) + (g / 51) * 6 + (b / 51) * 36; - } -} - -/** - * @brief 画矩形 - * - * @param x x坐标 - * @param y y坐标 - * @param width 宽度 - * @param height 高度 - * @param color 颜色 - */ -void draw_rect(int x, int y, int width, int height, int color) { - /*wide-video wide*/ - int x0, y0; - for (y0 = 0; y0 < height; y0++) { - for (x0 = 0; x0 < width; x0++) { - write_pixel(x + x0, y + y0, color); - } - } -} - -/** - * @brief 打印字符 - * - * @param x x坐标 - * @param y y坐标 - * @param ascii 字符数据(16*8点阵字体) - * @param color 颜色 - */ -void print_word(int x, int y, unsigned char *ascii, unsigned int color) { - int i; - char d; - for (i = 0; i < 16; i++) { - // vram = (unsigned char *)(video_info.vram + ((y+i)*video_info.width + - // x)*(video_info.BitsPerPixel/8)); - d = ascii[i]; - if (d & 0x80) { write_pixel(x + 0, y + i, color); } - if (d & 0x40) { write_pixel(x + 1, y + i, color); } - if (d & 0x20) { write_pixel(x + 2, y + i, color); } - if (d & 0x10) { write_pixel(x + 3, y + i, color); } - if (d & 0x08) { write_pixel(x + 4, y + i, color); } - if (d & 0x04) { write_pixel(x + 5, y + i, color); } - if (d & 0x02) { write_pixel(x + 6, y + i, color); } - if (d & 0x01) { write_pixel(x + 7, y + i, color); } - } -} - -/** - * @brief 打印字符串 - * - * @param x x坐标 - * @param y y坐标 - * @param color 颜色 - * @param font 字体 - * @param string 字符串 - */ -void print_string( - int x, int y, unsigned int color, unsigned char *font, char *string) { - while (*string != 0) { - print_word(x, y, font + (*string) * 16, color); - string++; - x += 9; - } } \ No newline at end of file diff --git a/src/arch/x86/include/drivers/8259a.h b/src/arch/x86/include/drivers/8259a.h index 02531de..d2f9a59 100644 --- a/src/arch/x86/include/drivers/8259a.h +++ b/src/arch/x86/include/drivers/8259a.h @@ -16,9 +16,9 @@ #define PIC_EOI 0x20 +extern struct Device pic_device; + void mask_8259a(void); -void init_8259a(void); -void pic_enable_irq(int irq); -void pic_eoi(int irq); +void register_pic(void); #endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/apic.h b/src/arch/x86/include/drivers/apic.h index 4f8e308..d4bed97 100644 --- a/src/arch/x86/include/drivers/apic.h +++ b/src/arch/x86/include/drivers/apic.h @@ -1,7 +1,9 @@ #ifndef APIC_H #define APIC_H -#define APIC_ID 0x20 +#include "kernel/driver.h" + +#define APIC_ID 0x20 #define APIC_Ver 0x30 #define APIC_TPR 0x80 #define APIC_APR 0x90 @@ -19,7 +21,7 @@ #define APIC_INT_DISABLE 0x00010000 -#define APIC_ESR 0x280 +#define APIC_ESR 0x280 #define APIC_LVT_CMCI 0x2f0 #define APIC_ICR_LOW 0x300 #define APIC_ICR_HIGH 0x310 @@ -34,12 +36,62 @@ #define APIC_TIMER_CCT 0x390 #define APIC_TIMER_DCR 0x3E0 +#define APIC_BASE_MSR 0x1b +#define X2APIC_ID_MSR 0x802 + +// Interrupt Command Register +#define APIC_ICR_DELIVERY_MODE_FIXED (0b000 << 8) +#define APIC_ICR_DELIVERY_MODE_LOW_PRIO (0b001 << 8) +#define APIC_ICR_DELIVERY_MODE_SMI (0b010 << 8) +#define APIC_ICR_DELIVERY_MODE_NMI (0b100 << 8) +#define APIC_ICR_DELIVERY_MODE_INIT (0b101 << 8) +#define APIC_ICR_DELIVERY_MODE_STARTUP (0b110 << 8) + +#define APIC_ICR_DEST_MODE_BIT 11 +#define APIC_ICR_DEST_MODE_PHYSICAL (0 << APIC_ICR_DEST_MODE_BIT) +#define APIC_ICR_DEST_MODE_LOGICAL (1 << APIC_ICR_DEST_MODE_BIT) + +#define APIC_ICR_STAT_BIT 12 +#define APIC_ICR_STAT_IDLE (0 << APIC_ICR_STAT_BIT) +#define APIC_ICR_STAT_SEND_PENDING (1 << APIC_ICR_STAT_BIT) + +#define APIC_ICR_LEVEL_BIT 14 +#define APIC_ICR_LEVEL_DEASSERT (0 << APIC_ICR_LEVEL_BIT) +#define APIC_ICR_LEVEL_ASSERT (1 << APIC_ICR_LEVEL_BIT) + +#define APIC_ICR_TRIGGER_MODE_BIT 15 +#define APIC_ICR_TRIGGER_MODE_EDGE (0 << APIC_ICR_TRIGGER_MODE_BIT) +#define APIC_ICR_TRIGGER_MODE_LEVEL (1 << APIC_ICR_TRIGGER_MODE_BIT) + +#define APIC_ICR_DEST_SHORTHAND_NO_SHORTHAND (0b00 << 18) +#define APIC_ICR_DEST_SHORTHAND_SELF (0b01 << 18) +#define APIC_ICR_DEST_SHORTHAND_ALL_INCLUDING_SELF (0b10 << 18) +#define APIC_ICR_DEST_SHORTHAND_ALL_EXCLUDING_SELF (0b11 << 18) + +// Divide Configuration Register +#define APIC_TIMER_DCR_DIVIDE_BY_2 0b0000 +#define APIC_TIMER_DCR_DIVIDE_BY_4 0b0001 +#define APIC_TIMER_DCR_DIVIDE_BY_8 0b0010 +#define APIC_TIMER_DCR_DIVIDE_BY_16 0b0011 +#define APIC_TIMER_DCR_DIVIDE_BY_32 0b1000 +#define APIC_TIMER_DCR_DIVIDE_BY_64 0b1001 +#define APIC_TIMER_DCR_DIVIDE_BY_128 0b1010 +#define APIC_TIMER_DCR_DIVIDE_BY_1 0b1011 + +// Timer LVT +#define APIC_LVT_TIMER_MODE_ONESHOT (0b00 << 17) +#define APIC_LVT_TIMER_MODE_PERIODIC (0b001 << 17) +#define APIC_LVT_TIMER_MODE_TSC_DEADLINE (0b010 << 17) + +// MSR +#define APIC_GLOBAL_ENABLE_BIT 11 +// SVIR +#define APIC_SOFTWARE_ENABLE_BIT 8 + #define LAPIC_TIMER_IRQ 0 -void init_apic(void); -void apic_enable_irq(int irq); -void apic_eoi(void); +extern struct Device apic_timer_device; -extern char use_apic; +DriverResult register_apic(void); #endif diff --git a/src/arch/x86/include/drivers/pit.h b/src/arch/x86/include/drivers/pit.h index cab64d7..b199335 100644 --- a/src/arch/x86/include/drivers/pit.h +++ b/src/arch/x86/include/drivers/pit.h @@ -4,36 +4,39 @@ #define PIT_CTRL 0x43 #define PIT_CNT0 0x40 -#define PIC_PIT_IRQ 0 // 使用PIC时PIT的IRQ为1 +#define PIC_PIT_IRQ 0 // 使用PIC时PIT的IRQ为1 #define APIC_PIT_IRQ 2 // 使用APIC时PIT的IRQ为2 #define MAX_TIMER 2048 -#define TIMER_FREE 0 +#define TIMER_FREE 0 #define TIMER_UNUSED 1 -#define TIMER_USING 2 +#define TIMER_USING 2 struct timer { - struct timer *next; - unsigned int timeout, flags; - struct fifo *fifo; - int data; + struct timer *next; + unsigned int timeout, flags; + struct fifo *fifo; + int data; }; struct timerctl { - unsigned int count, next, using; - struct timer *timers[MAX_TIMER]; - struct timer timers0[MAX_TIMER]; + unsigned int count, next, using; + struct timer *timers[MAX_TIMER]; + struct timer timers0[MAX_TIMER]; }; -extern struct timerctl timerctl; +// extern struct timerctl timerctl; -void init_timer(void); -void timer_handler(int irq); -struct timer *timer_alloc(void); -void timer_free(struct timer *timer); -void timer_init(struct timer *timer, struct fifo *fifo, int data); -void timer_settime(struct timer *timer, unsigned int timeout); -void delay(int time); +// void init_timer(void); +// void timer_handler(int irq); +// struct timer *timer_alloc(void); +// void timer_free(struct timer *timer); +// void timer_init(struct timer *timer, struct fifo *fifo, int data); +// void timer_settime(struct timer *timer, unsigned int timeout); +// void delay(int time); + +void register_pit(); +extern struct Device pit_device; #endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/vesa_display.h b/src/arch/x86/include/drivers/vesa_display.h new file mode 100644 index 0000000..0b12c3b --- /dev/null +++ b/src/arch/x86/include/drivers/vesa_display.h @@ -0,0 +1,44 @@ +#ifndef _VESA_DISPLAY_H +#define _VESA_DISPLAY_H + +struct VbeModeInfoBlock { + unsigned char VbeSignature[4]; + unsigned short VbeVersion; + unsigned int *OemStringPtr; + unsigned int Capabilities; + unsigned int *VideoModePtr; + unsigned short TotalMemory; + unsigned short OemSoftwareRev; + unsigned int *OemVendorNamePtr; + unsigned int *OemProductNamePtr; + unsigned int *OemProduceRevPtr; + unsigned char Reserved[222]; + unsigned char OemData; +} __attribute__((packed)); + +struct VbeControlInfoBlock { + unsigned char VbeSignature[4]; + unsigned short VbeVersion; + unsigned int OemStringPtr; + unsigned char Capabilities[4]; + unsigned int VideoModePtr; + unsigned short TotalMemory; + unsigned short OemSoftwareRev; + unsigned int OemVendorNamePtr; + unsigned int OemProductNamePtr; + unsigned int OemProduceRevPtr; + unsigned char OemData[256]; +}; + +struct VesaDisplayInfo { + unsigned short width, height; + unsigned short BitsPerPixel; + unsigned char *vram; + struct VbeModeInfoBlock *vbe_mode_info; + struct VbeControlInfoBlock *vbe_conrtol_info; +}; + +extern struct Device vesa_display_device; +void register_vesa_display(void); + +#endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/video.h b/src/arch/x86/include/drivers/video.h index 6ebb33f..963c3b9 100644 --- a/src/arch/x86/include/drivers/video.h +++ b/src/arch/x86/include/drivers/video.h @@ -50,18 +50,9 @@ struct VideoInfo { extern struct VideoInfo video_info; -// 写像素 -void write_pixel(int x, int y, unsigned int color); // 获取显示模式信息 void init_video(void); // 输出VBE信息 void show_vbeinfo(void); -// 输出字符 -void print_word(int x, int y, unsigned char *ascii, unsigned int color); -// 输出字符串 -void print_string( - int x, int y, unsigned int color, unsigned char *font, char *string); - -void draw_rect(int x, int y, int width, int height, int color); #endif \ No newline at end of file diff --git a/src/arch/x86/include/kernel/feature.h b/src/arch/x86/include/kernel/feature.h new file mode 100644 index 0000000..6fabf23 --- /dev/null +++ b/src/arch/x86/include/kernel/feature.h @@ -0,0 +1,71 @@ +#ifndef _FEATURE_H +#define _FEATURE_H + +enum x86_cpu_features { + CPUID_FEAT_SSE3 = 0, + CPUID_FEAT_PCLMUL = 1, + CPUID_FEAT_DTES64 = 2, + CPUID_FEAT_MONITOR = 3, + CPUID_FEAT_DS_CPL = 4, + CPUID_FEAT_VMX = 5, + CPUID_FEAT_SMX = 6, + CPUID_FEAT_EST = 7, + CPUID_FEAT_TM2 = 8, + CPUID_FEAT_SSSE3 = 9, + CPUID_FEAT_CID = 10, + CPUID_FEAT_FMA = 12, + CPUID_FEAT_CX16 = 13, + CPUID_FEAT_XTPR = 14, + CPUID_FEAT_PDCM = 15, + CPUID_FEAT_PCID = 17, + CPUID_FEAT_DCA = 18, + CPUID_FEAT_SSE4_1 = 19, + CPUID_FEAT_SSE4_2 = 20, + CPUID_FEAT_X2APIC = 21, + CPUID_FEAT_MOVBE = 22, + CPUID_FEAT_POPCNT = 23, + CPUID_FEAT_TSC_DEADLINE = 24, + CPUID_FEAT_AES = 25, + CPUID_FEAT_XSAVE = 26, + CPUID_FEAT_OSXSAVE = 27, + CPUID_FEAT_AVX = 28, + CPUID_FEAT_F16C = 29, + CPUID_FEAT_RDRAND = 30, + CPUID_FEAT_HYPERVISOR = 31, + + CPUID_FEAT_FPU = 32 + 0, + CPUID_FEAT_VME = 32 + 1, + CPUID_FEAT_DE = 32 + 2, + CPUID_FEAT_PSE = 32 + 3, + CPUID_FEAT_TSC = 32 + 4, + CPUID_FEAT_MSR = 32 + 5, + CPUID_FEAT_PAE = 32 + 6, + CPUID_FEAT_MCE = 32 + 7, + CPUID_FEAT_CX8 = 32 + 8, + CPUID_FEAT_APIC = 32 + 9, + CPUID_FEAT_SEP = 32 + 11, + CPUID_FEAT_MTRR = 32 + 12, + CPUID_FEAT_PGE = 32 + 13, + CPUID_FEAT_MCA = 32 + 14, + CPUID_FEAT_CMOV = 32 + 15, + CPUID_FEAT_PAT = 32 + 16, + CPUID_FEAT_PSE36 = 32 + 17, + CPUID_FEAT_PSN = 32 + 18, + CPUID_FEAT_CLFLUSH = 32 + 19, + CPUID_FEAT_DS = 32 + 21, + CPUID_FEAT_ACPI = 32 + 22, + CPUID_FEAT_MMX = 32 + 23, + CPUID_FEAT_FXSR = 32 + 24, + CPUID_FEAT_SSE = 32 + 25, + CPUID_FEAT_SSE2 = 32 + 26, + CPUID_FEAT_SS = 32 + 27, + CPUID_FEAT_HTT = 32 + 28, + CPUID_FEAT_TM = 32 + 29, + CPUID_FEAT_PBE = 32 + 31 +}; + +void read_features(void); +int cpu_check_feature(enum x86_cpu_features feature); +void print_features(); + +#endif \ No newline at end of file diff --git a/src/arch/x86/include/kernel/page.h b/src/arch/x86/include/kernel/page.h index 6561928..9dc4445 100644 --- a/src/arch/x86/include/kernel/page.h +++ b/src/arch/x86/include/kernel/page.h @@ -6,47 +6,48 @@ #define PDT_PHY_ADDR 0x201000 // 页目录表物理地址 -#define TBL_PHY_ADDR 0x202000 +#define TBL_PHY_ADDR 0x202000 #define VRAM_PT_PHY_ADDR 0x203000 #define DMA_PT_PHY_ADDR1 0x204000 #define DMA_PT_PHY_ADDR2 0x205000 #define PAGE_SIZE 1024 * 4 // 页大小 -#define SIGN_P 0x01 // 存在 +#define SIGN_P 0x01 // 存在 #define SIGN_RW 0x02 // 读写 -#define SIGN_US 0x04 // 普通/超级用户 +#define SIGN_US 0x04 // 普通/超级用户 #define SIGN_USER 0x04 // 用户内存 #define SIGN_SYS 0x00 // 系统内存 -#define SIGN_PWT 0x08 // 页级写穿 -#define SIGN_PCD 0x10 // 页级高速缓存 -#define SIGN_A 0x20 // 访问 -#define SIGN_D 0x40 // 脏页 -#define SIGN_PAT 0x80 // 页表属性 -#define SIGN_G 0x100 // 全局 +#define SIGN_PWT 0x08 // 页级写穿 +#define SIGN_PCD 0x10 // 页级高速缓存 +#define SIGN_A 0x20 // 访问 +#define SIGN_D 0x40 // 脏页 +#define SIGN_PAT 0x80 // 页表属性 +#define SIGN_G 0x100 // 全局 #define SIGN_AVL 0x200 // 软件可用 -void setup_page(void); -uint32_t *pte_ptr(uint32_t vaddr); -uint32_t *pde_ptr(uint32_t vaddr); -uint32_t vir2phy(uint32_t vaddr); -void *remap(uint32_t paddr, size_t size); -void unmap(uint32_t vaddr, size_t size); -int alloc_vir_page(void); -int free_vir_page(int vir_addr); -void *kernel_alloc_pages(int pages); -void kernel_free_page(int vaddr, int pages); -void fill_vir_page_table(uint32_t vaddr, uint8_t sign); -void clean_vir_page_table(uint32_t vaddr); -uint32_t alloc_mem_page(void); -uint32_t free_mem_page(int address); -void *thread_get_page(struct task_s *thread, uint32_t vaddr); -uint32_t thread_alloc_vir_page(struct task_s *thread); -uint32_t thread_free_vir_page(struct task_s *thread, uint32_t addr); -void *thread_alloc_page(struct task_s *thread, int pages); -void thread_free_page(struct task_s *thread, uint32_t vaddr, int pages); -int thread_use_page(struct task_s *thread, uint32_t vaddr, uint32_t addr, int pages); +void setup_page(void); +uint32_t *pte_ptr(uint32_t vaddr); +uint32_t *pde_ptr(uint32_t vaddr); +uint32_t vir2phy(uint32_t vaddr); +MemoryResult remap(uint32_t in_paddr, size_t in_size, uint32_t *out_vaddr); +void unmap(uint32_t vaddr, size_t size); +int alloc_vir_page(void); +int free_vir_page(int vir_addr); +void *kernel_alloc_pages(int pages); +void kernel_free_page(int vaddr, int pages); +void fill_vir_page_table(uint32_t vaddr, uint8_t sign); +void clean_vir_page_table(uint32_t vaddr); +uint32_t alloc_mem_page(void); +uint32_t free_mem_page(int address); +void *thread_get_page(struct task_s *thread, uint32_t vaddr); +uint32_t thread_alloc_vir_page(struct task_s *thread); +uint32_t thread_free_vir_page(struct task_s *thread, uint32_t addr); +void *thread_alloc_page(struct task_s *thread, int pages); +void thread_free_page(struct task_s *thread, uint32_t vaddr, int pages); +MemoryResult thread_use_page( + struct task_s *thread, uint32_t vaddr, uint32_t addr, int pages); #endif \ No newline at end of file diff --git a/src/arch/x86/kernel.lds b/src/arch/x86/kernel.lds index 31c36f8..d6b5cc5 100644 --- a/src/arch/x86/kernel.lds +++ b/src/arch/x86/kernel.lds @@ -1,6 +1,6 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) -ENTRY(_start) +ENTRY(_start) /* start is at boot/xxx/xxx.S */ PHDRS { @@ -17,11 +17,12 @@ SECTIONS { . = 0x00100000; /* code segment */ - .text ALIGN(4) : { + .text : { + . = ALIGN(4); /* 4 bytes align */ *(.text) *(.init.text) *(.exit.text) - } :text + } : text .initcall ALIGN(8) : { @@ -29,7 +30,7 @@ SECTIONS { KEEP(*(.initcall_0.text)) KEEP(*(.initcall_1.text)) PROVIDE(__initcall_end = .); - } :text + } : text .exitcall ALIGN(8) : { @@ -37,34 +38,17 @@ SECTIONS { KEEP(*(.exitcall_0.text)) KEEP(*(.exitcall_1.text)) PROVIDE(__exitcall_end = .); - } :text + } : text /* data segment */ - .data ALIGN(4) : { + .data : { + . = ALIGN(4); /* 4 bytes align */ *(.data) - } :data + } : data /* bss segement */ - .bss ALIGN(4) : { + .bss : { + . = ALIGN(4); /* 4 bytes align */ *(.bss) - } :data - - . = ALIGN(4); - _end_of_file = .; /* 标记文件结尾 */ - - . = ALIGN(4); - /DISCARD/ : { - *(.note*) - *(.comment) - } - .debug_aranges 0 (NOLOAD) : { *(.debug_aranges) } - .debug_info 0 (NOLOAD) : { *(.debug_info) } - .debug_abbrev 0 (NOLOAD) : { *(.debug_abbrev) } - .debug_line 0 (NOLOAD) : { *(.debug_line) } - .debug_str 0 (NOLOAD) : { *(.debug_str) } - .debug_addr 0 (NOLOAD) : { *(.debug_addr) } - .debug_line_str 0 (NOLOAD) : { *(.debug_line_str) } - .debug_rnglists 0 (NOLOAD) : { *(.debug_rnglists) } - .debug_str_offsets 0 (NOLOAD) : { *(.debug_str_offsets) } - .debug_loclists 0 (NOLOAD) : { *(.debug_loclists) } + } : data } \ No newline at end of file diff --git a/src/arch/x86/kernel/Makefile b/src/arch/x86/kernel/Makefile index d3bf441..fd4bc87 100644 --- a/src/arch/x86/kernel/Makefile +++ b/src/arch/x86/kernel/Makefile @@ -2,4 +2,5 @@ SRC += start.asm SRC += func.asm SRC += descriptor.c SRC += page.c -SRC += platform.c \ No newline at end of file +SRC += platform.c +SRC += feature.c \ No newline at end of file diff --git a/src/arch/x86/kernel/descriptor.c b/src/arch/x86/kernel/descriptor.c index 30a0594..5fed4e6 100644 --- a/src/arch/x86/kernel/descriptor.c +++ b/src/arch/x86/kernel/descriptor.c @@ -5,6 +5,7 @@ * @version 1.2 * @date 2022-07-31 */ +#include "driver/interrupt_dm.h" #include #include #include @@ -337,27 +338,29 @@ void exception_handler( } void do_irq(int irq) { - if (use_apic) { - apic_eoi(); - } else { - pic_eoi(irq); - } + // if (use_apic) { + // apic_eoi(); + // } else { + // pic_eoi(irq); + // } device_irq_handler(irq); irq_table[irq](irq); } void default_irq_handler(int irq) { - if (use_apic) { - apic_eoi(); - } else { - pic_eoi(irq); - } + // if (use_apic) { + // apic_eoi(); + // } else { + // pic_eoi(irq); + // } + interrupt_eoi(irq); } void irq_enable(int irq) { - if (use_apic) { - apic_enable_irq(irq); - } else { - pic_enable_irq(irq); - } + // if (use_apic) { + // apic_enable_irq(irq); + // } else { + // pic_enable_irq(irq); + // } + interrupt_enable_irq(irq); } diff --git a/src/arch/x86/kernel/feature.c b/src/arch/x86/kernel/feature.c new file mode 100644 index 0000000..993c854 --- /dev/null +++ b/src/arch/x86/kernel/feature.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include + +char vendor_id[13] = {0}; +char model_name[49] = {0}; +static uint32_t max_basic_func_num; +static uint8_t cpu_family, cpu_model, cpu_stepping_id; +static uint8_t processor_type, brand_index; +static uint8_t default_apic_id, max_logical_processor_per_package; +static uint16_t cache_line_size; +static uint32_t feature_flags[2]; + +const char feature_names[64][16] = { + "SSE3", "PCLMUL", "DTES64", "MONITOR", "DS-CPL", + "VMX", "SMX", "EST", "TM2", "SSSE3", + "CID", "", "FMA", "CX16", "XTPR", + "PDCM", "", "PCID", "DCA", "SSE4.1", + "SSE4.2", "x2APIC", "MOVBE", "POPCNT", "TSC-DEADLINE", + "AES", "XSAVE", "OSXSAVE", "AVX", "F16C", + "RDRAND", "HYPERVISOR", + + "FPU", "VME", "DE", "PSE", "TSC", + "MSR", "PAE", "MCE", "CX8", "APIC", + "", "SEP", "MTRR", "PGE", "MCA", + "CMOV", "PAT", "PSE36", "PSN", "CLFLUSH", + "", "DS", "ACPI", "MMX", "FXSR", + "SSE", "SSE2", "SS", "HTT", "TM", + "", "PBE", +}; + +void read_features(void) { + uint32_t a, b, c, d; + get_cpuid( + 0, 0, &max_basic_func_num, (uint32_t *)&vendor_id[0], + (uint32_t *)&vendor_id[8], (uint32_t *)&vendor_id[4]); + get_cpuid(1, 0, &a, &b, &c, &d); + cpu_family = (a >> 8) & 0x0f + (a >> 20) & 0xff; + cpu_model = ((a >> 4) & 0x0f) | (((a >> 16) & 0x0f) << 4); + cpu_stepping_id = a & 0x0f; + processor_type = (a >> 12) & 0x03; + + default_apic_id = b >> 24; + max_logical_processor_per_package = (b >> 16) & 0xff; + cache_line_size = ((b >> 8) & 0xff) * 8; + brand_index = b & 0xff; + + feature_flags[0] = c; + feature_flags[1] = d; + + get_cpuid( + 0x80000002, 0, (uint32_t *)&model_name[0], (uint32_t *)&model_name[4], + (uint32_t *)&model_name[8], (uint32_t *)&model_name[12]); + get_cpuid( + 0x80000003, 0, (uint32_t *)&model_name[16], (uint32_t *)&model_name[20], + (uint32_t *)&model_name[24], (uint32_t *)&model_name[28]); + get_cpuid( + 0x80000003, 0, (uint32_t *)&model_name[32], (uint32_t *)&model_name[36], + (uint32_t *)&model_name[40], (uint32_t *)&model_name[44]); +} + +int cpu_check_feature(enum x86_cpu_features feature) { + if (feature >= 32) { + return !!(feature_flags[1] & BIT(feature % 32)); + } else { + return !!(feature_flags[0] & BIT(feature)); + } +} + +void print_features() { + printk("CPU Infomations:\n"); + printk("Vendor: %s,", vendor_id); + printk("Model: %s\n", model_name); + printk("Family: %d,", cpu_family); + printk("Model: %d,", cpu_model); + printk("Stepping ID: %d\n", cpu_stepping_id); + printk("Processor Type: %d,", processor_type); + printk("Default APIC ID: %d\n", default_apic_id); + printk( + "Max Logical Processor Per Package: %d\n", + max_logical_processor_per_package); + printk("Cache Line Size: %dBytes\n", cache_line_size); + printk("Brand Index: %d\n", brand_index); + printk("Features: "); + for (int i = 0; i < 64; i++) { + if (cpu_check_feature(i)) { printk("%s, ", feature_names[i]); } + } + printk("\n"); +} diff --git a/src/arch/x86/kernel/page.c b/src/arch/x86/kernel/page.c index fc9f057..27091a0 100644 --- a/src/arch/x86/kernel/page.c +++ b/src/arch/x86/kernel/page.c @@ -5,7 +5,7 @@ * @version 1.2 * @date 2022-07-15 */ -#include +#include #include #include #include @@ -15,6 +15,9 @@ #include #include + +extern struct VesaDisplayInfo vesa_display_info; + void setup_page(void) { uint32_t *pdt = (uint32_t *)PDT_PHY_ADDR; memset((void *)PDT_PHY_ADDR, 0, PAGE_SIZE); // 清空数据 @@ -51,9 +54,9 @@ void setup_page(void) { } // VRAM - uint32_t vram_addr = (uint32_t)video_info.vram; - uint32_t size = - video_info.width * video_info.height * (video_info.BitsPerPixel / 8); + uint32_t vram_addr = (uint32_t)vesa_display_info.vram; + uint32_t size = vesa_display_info.width * vesa_display_info.height * + (vesa_display_info.BitsPerPixel / 8); for (i = 1; i <= DIV_ROUND_UP(size, PAGE_SIZE * 1024); i++) { pdt[i] = ((VRAM_PT_PHY_ADDR + (i - 1) * PAGE_SIZE) | SIGN_RW | SIGN_SYS | @@ -178,40 +181,27 @@ int __unmap(uint32_t vaddr, size_t size) { * * @param paddr 物理地址 * @param size 大小 - * @return void* 虚拟地址 + * @param uint32_t* 虚拟地址 */ -void *remap(uint32_t paddr, size_t size) { - - if (!paddr || !size) { return NULL; } - uint32_t i, j, *pdt, *pt; - for (i = 0; i < 1024; i++) { - pdt = (uint32_t *)0xfffff000; - if (pdt[i]) { - for (j = 0; j < 1024; j++) { - pt = (uint32_t *)(0xffc00000 + i * 0x1000); - if (pt[j] == ((paddr + size - 1) & 0x003ff000)) { - return (void *)(i * 0x40000 + j * 0x1000 + - (paddr & 0x0fff)); - } - } - } - } +MemoryResult remap(uint32_t in_paddr, size_t in_size, uint32_t *out_vaddr) { - uint32_t vaddr = alloc_vaddr(size); - if (vaddr == 0) { - printk("alloc virtual addr for IO remap failed!\n"); - return NULL; - } + if (!in_paddr || !in_size) { return MEMORY_RESULT_INVALID_INPUT; } + uint32_t vaddr; + MEMORY_RESULT_DELIVER_CALL(alloc_vaddr, in_size, &vaddr); + int old_status = io_load_eflags(); io_cli(); + __remap(in_paddr, vaddr, in_size); + io_store_eflags(old_status); - __remap(paddr, vaddr, size); + __remap(in_paddr, vaddr, in_size); io_sti(); uint32_t ret = vaddr & 0xfffff000; - ret |= (paddr & 0x0fff); - return (void *)ret; + ret |= (in_paddr & 0x0fff); + *out_vaddr = ret; + return MEMORY_RESULT_OK; } /** @@ -524,15 +514,15 @@ void thread_free_page(struct task_s *thread, uint32_t vaddr, int pages) { * @param addr 内存的物理地址 * @param pages 载入内存的大小(单位:页) * - * @return 成功则返回0,失败则返回NULL + * @return MemoryResult */ -int thread_use_page( +MemoryResult thread_use_page( struct task_s *thread, uint32_t vaddr, uint32_t addr, int pages) { int i = 0; int idx = (vaddr - USER_VIR_MEM_BASE_ADDR) / PAGE_SIZE; while (i < pages) { - if (thread->vir_page_mmap.bits[idx / 8] & (1 << (idx % 8))) { - return -1; + if (mmap_get(&thread->vir_page_mmap, idx)) { + return MEMORY_RESULT_MEMORY_IS_USED; } mmap_set(&thread->vir_page_mmap, idx, 1); @@ -547,16 +537,19 @@ int thread_use_page( *pde = pt | SIGN_P | SIGN_RW | SIGN_USER; // 填写页目录项为页表的地址 } - pt = (uint32_t)remap(pt & 0xfffff000, PAGE_SIZE); + + MEMORY_RESULT_DELIVER_CALL(remap, pt & 0xfffff000, PAGE_SIZE, &pt); + pte = (uint32_t *)(pt + ((vaddr & 0x003ff000) >> 12) * 4); if (((*pte) & 0x00000001) != 0x00000001) { // 不存在页表项 *pte = addr | SIGN_P | SIGN_RW | SIGN_USER; // 填写页表项为页的地址 addr += PAGE_SIZE; } + unmap(pt, PAGE_SIZE); idx++; i++; } - return 0; + return MEMORY_RESULT_OK; } diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index ff6bf69..7e95f7d 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -1,14 +1,50 @@ +#include +#include #include #include +#include #include +#include #include #include +#include +#include +#include +#include -void platform_init() { +BusDriverOps platform_ops = { + .register_device_hook = NULL, + .unregister_device_hook = NULL, +}; + +Driver platform_driver; +BusDriver platform_bus = { + .driver_type = DRIVER_TYPE_BUS_DRIVER, + .bus_type = BUS_TYPE_PLATFORM, + .name = STRING_INIT("platform"), + .state = DRIVER_STATE_UNREGISTERED, + .private_data_size = 0, +}; + +void init_platform() { init_descriptor(); - init_video(); - init_console(); + // init_video(); + // init_console(); init_memory(); - init_apic(); - init_timer(); + + register_bus_driver(&platform_driver, &platform_bus); + read_features(); + register_vesa_display(); + register_pic(); + register_apic(); + register_pit(); +} + +void platform_init_and_start_devices() { + init_and_start(&vesa_display_device); + init_console(); + print_features(); + interrupt_dm_start(); // 启动由interrupt_dm选择的中断控制器 + DRV_RESULT_PRINT_CALL(init_and_start, &pit_device); + DRV_RESULT_PRINT_CALL(init_and_start, &apic_timer_device); } \ No newline at end of file diff --git a/src/arch/x86/multiboot2/multiboot2.c b/src/arch/x86/multiboot2/multiboot2.c index 9ab1ec6..a5868c8 100644 --- a/src/arch/x86/multiboot2/multiboot2.c +++ b/src/arch/x86/multiboot2/multiboot2.c @@ -1,21 +1,15 @@ #include "multiboot2.h" -#include +#include #include #include #include #include #include +extern struct VesaDisplayInfo vesa_display_info; + void multiboot2_loader(uint32_t eax, uint32_t ebx) { if (eax != 0x36d76289) { - // 尝试输出 - video_info.vram = (uint8_t *)0xe0000000; - video_info.width = 1024; - video_info.height = 768; - video_info.BitsPerPixel = 32; - print_string( - 0, 0, 0xffffff, font16, - "Not booted by a multiboot2-compliant bootloader."); while (true) ; } @@ -30,19 +24,19 @@ void multiboot2_loader(uint32_t eax, uint32_t ebx) { uint32_t size = *(p + 1); switch (type) { case MBIT_FRAMEBUFER_INFO: { - struct framebuffer_tag *fb = (struct framebuffer_tag *)p; - video_info.vram = (uint8_t *)fb->framebuffer_addr[0]; - video_info.width = fb->framebuffer_width; - video_info.height = fb->framebuffer_height; - video_info.BitsPerPixel = fb->framebuffer_bpp; + struct framebuffer_tag *fb = (struct framebuffer_tag *)p; + vesa_display_info.vram = (uint8_t *)fb->framebuffer_addr[0]; + vesa_display_info.width = fb->framebuffer_width; + vesa_display_info.height = fb->framebuffer_height; + vesa_display_info.BitsPerPixel = fb->framebuffer_bpp; break; } case MBIT_VBE_INFO: { struct vbe_info_tag *vbe = (struct vbe_info_tag *)p; - video_info.vbe_mode_info = - (struct vbe_mode_info_block *)vbe->vbe_mode_info; - video_info.vbe_conrtol_info = - (struct vbe_control_info_block *)vbe->vbe_control_info; + vesa_display_info.vbe_mode_info = + (struct VbeModeInfoBlock *)vbe->vbe_mode_info; + vesa_display_info.vbe_conrtol_info = + (struct VbeControlInfoBlock *)vbe->vbe_control_info; break; } case MBIT_MEM_MAP: { @@ -70,5 +64,4 @@ void multiboot2_loader(uint32_t eax, uint32_t ebx) { size >>= 2; p += size; } - print_string(0, 0, 0xc0c0c0, font16, "Starting up by multiboot2 success!"); } \ No newline at end of file diff --git a/src/driver/Makefile b/src/driver/Makefile new file mode 100644 index 0000000..e2fce8e --- /dev/null +++ b/src/driver/Makefile @@ -0,0 +1,4 @@ +SRC += timer_dm.c +SRC += interrupt_dm.c +SRC += video_dm.c +SRC += video.c \ No newline at end of file diff --git a/src/driver/interrupt_dm.c b/src/driver/interrupt_dm.c new file mode 100644 index 0000000..b06fba0 --- /dev/null +++ b/src/driver/interrupt_dm.c @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DriverResult interrupt_start(DeviceManager *manager, Device *device); + +DeviceManagerOps interrupt_dm_ops = { + .dm_load_hook = NULL, + .dm_unload_hook = NULL, +}; + +typedef struct InterruptDeviceManager { + InterruptDevice *current_device; +} InterruptDeviceManager; + +InterruptDeviceManager interrupt_dm_ext; + +struct DeviceManager interrupt_device_manager = { + .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, + + .ops = &interrupt_dm_ops, + + .private_data = &interrupt_dm_ext, +}; + +/** + * @brief 检查是否提供了必要的接口 + */ +DriverResult check_intterupt_ops(InterruptDevice *interrupt_device) { + if (!interrupt_device->interrupt_ops) { + print_error( + "%s has no operations\n", interrupt_device->device->name.text); + return DRIVER_RESULT_DEVICE_DRIVER_HAVE_NO_OPS; + } + if (!interrupt_device->interrupt_ops->disable_irq) { + print_error( + "%s has no disable_irq operation\n", + interrupt_device->device->name.text); + return DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS; + } + if (!interrupt_device->interrupt_ops->enable_irq) { + print_error( + "%s has no enable_irq operation\n", + interrupt_device->device->name.text); + return DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS; + } + if (!interrupt_device->interrupt_ops->eoi) { + print_error( + "%s has no eoi operation\n", interrupt_device->device->name.text); + return DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS; + } + if (!interrupt_device->interrupt_ops->redirect_irq) { + print_error( + "%s has no redirect_irq operation\n", + interrupt_device->device->name.text); + return DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS; + } + return DRIVER_RESULT_OK; +} + +DriverResult register_interrupt_device( + DeviceDriver *device_driver, Device *device, + InterruptDevice *interrupt_device) { + interrupt_device->device = device; + DRV_RESULT_DELIVER_CALL(check_intterupt_ops, interrupt_device); + + DRV_RESULT_DELIVER_CALL(register_device, device_driver, device); + list_add_tail(&device->dm_list, &interrupt_device_manager.device_driver_lh); + + InterruptDeviceManager *manager = interrupt_device_manager.private_data; + if (manager->current_device) { + if (interrupt_device->priority > manager->current_device->priority) { + if (manager->current_device->device->state == DEVICE_STATE_ACTIVE) { + DEV_OPS_CALL( + manager->current_device->device, stop, + manager->current_device->device); + } + manager->current_device = interrupt_device; + } + } else { + manager->current_device = interrupt_device; + } + + return DRIVER_RESULT_OK; +} + +DriverResult unregister_interrupt_device( + DeviceDriver *device_driver, Device *device, + InterruptDevice *interrupt_device) { + + InterruptDeviceManager *manager = interrupt_device_manager.private_data; + Device *cur; + + DEV_OPS_CALL(device, stop, device); + // 如果是正在使用的设备 + if (manager->current_device == interrupt_device) { + // 寻找替代的设备 + InterruptDevice *new_interrupt_device; + list_for_each_owner ( + cur, &interrupt_device_manager.device_driver_lh, device_list) { + if (cur != device) { + if (new_interrupt_device == NULL) { + new_interrupt_device = cur->driver_manager_extension; + } else { + InterruptDevice *cur_interrupt_device = + (InterruptDevice *)cur->driver_manager_extension; + if (cur_interrupt_device->priority > + new_interrupt_device->priority) { + new_interrupt_device = cur_interrupt_device; + } + } + } + } + if (new_interrupt_device != NULL) { + Device *new_device = new_interrupt_device->device; + DeviceDriver *new_device_driver = new_device->device_driver; + DRV_RESULT_DELIVER_CALL( + register_interrupt_device, new_device_driver, new_device, + new_interrupt_device); + // 恢复运行状态 + if (device->state == DEVICE_STATE_ACTIVE) { + DEV_OPS_CALL(new_device, init, new_device); + DEV_OPS_CALL(new_device, start, new_device); + } else if (device->state == DEVICE_STATE_READY) { + DEV_OPS_CALL(new_device, init, new_device); + } + manager->current_device = new_interrupt_device; + } + } + DEV_OPS_CALL(device, destroy, device); + + DRV_RESULT_DELIVER_CALL(unregister_device, device_driver, device); + list_del(&device->dm_list); + + return DRIVER_RESULT_OK; +} + +DriverResult interrupt_dm_start() { + if (interrupt_dm_ext.current_device) { + Device *device = interrupt_dm_ext.current_device->device; + DRV_RESULT_DELIVER_CALL(init_device, device); + DEV_OPS_CALL(device, start, device); + } + return DRIVER_RESULT_OK; +} + +uint32_t interrupt_redirect_irq(int irq) { + InterruptDeviceManager *manager = interrupt_device_manager.private_data; + InterruptDevice *interrupt_device = manager->current_device; + return interrupt_device->interrupt_ops->redirect_irq(interrupt_device, irq); +} + +DriverResult interrupt_enable_irq(int irq) { + InterruptDeviceManager *manager = interrupt_device_manager.private_data; + InterruptDevice *interrupt_device = manager->current_device; + DRV_RESULT_DELIVER_CALL( + interrupt_device->interrupt_ops->enable_irq, interrupt_device, irq); + return DRIVER_RESULT_OK; +} + +DriverResult interrupt_disable_irq(int irq) { + InterruptDeviceManager *manager = interrupt_device_manager.private_data; + InterruptDevice *interrupt_device = manager->current_device; + DRV_RESULT_DELIVER_CALL( + interrupt_device->interrupt_ops->disable_irq, interrupt_device, irq); + return DRIVER_RESULT_OK; +} + +void interrupt_eoi(int irq) { + InterruptDeviceManager *manager = interrupt_device_manager.private_data; + InterruptDevice *interrupt_device = manager->current_device; + interrupt_device->interrupt_ops->eoi(interrupt_device, irq); +} diff --git a/src/driver/timer_dm.c b/src/driver/timer_dm.c new file mode 100644 index 0000000..e1b398c --- /dev/null +++ b/src/driver/timer_dm.c @@ -0,0 +1,185 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const int default_frequencies[] = {100, 250, 1000}; + +DriverResult timer_dm_load(DeviceManager *manager); +DriverResult timer_dm_unload(DeviceManager *manager); +DriverResult timer_device_init(DeviceManager *manager, Device *device); + +DeviceManagerOps timer_dm_ops = { + .dm_load_hook = timer_dm_load, + .dm_unload_hook = timer_dm_unload, + + .init_device_hook = timer_device_init, + .start_device_hook = NULL, + .stop_device_hook = NULL, + .destroy_device_hook = NULL, +}; + +typedef struct TimerDeviceManager { + Device *scheduler_timer; +} TimerDeviceManager; + +TimerDeviceManager timer_dm_ext; + +struct DeviceManager timer_device_manager = { + .type = DEVICE_TYPE_TIMER, + + .ops = &timer_dm_ops, + + .private_data = &timer_dm_ext, +}; + +DriverResult timer_dm_load(DeviceManager *manager) { + TimerDeviceManager *timer_manager = manager->private_data; + timer_manager->scheduler_timer = NULL; + + return DRIVER_RESULT_OK; +} + +DriverResult timer_dm_unload(DeviceManager *manager) { + TimerDeviceManager *timer_manager = manager->private_data; + timer_manager->scheduler_timer = NULL; + + return DRIVER_RESULT_OK; +} + +DriverResult timer_device_init(DeviceManager *manager, Device *device) { + TimerDevice *timer_device = (TimerDevice *)device->driver_manager_extension; + + const int count = + sizeof(default_frequencies) / sizeof(typeof(default_frequencies[0])); + int freq; + int error = 0xfffffff; + int i; + for (i = 0; i < count; i++) { + if (timer_device->source_frequency % default_frequencies[i] < error) { + error = timer_device->source_frequency % default_frequencies[i]; + freq = default_frequencies[i]; + } + } + DRV_RESULT_DELIVER_CALL(timer_set_frequency, device, freq); + + TimerDeviceManager *timer_manager = manager->private_data; + if (timer_manager->scheduler_timer == NULL) { + timer_manager->scheduler_timer = device; + } else { + TimerDevice *scheduler_timer_device = + (TimerDevice *) + timer_manager->scheduler_timer->driver_manager_extension; + if (scheduler_timer_device->priority < timer_device->priority) { + timer_manager->scheduler_timer = device; + } + } + return DRIVER_RESULT_OK; +} + +DriverResult timer_set_frequency(Device *device, uint32_t frequency) { + TimerDevice *timer_device = (TimerDevice *)device->driver_manager_extension; + + TimerResult result = + timer_device->timer_ops->set_frequency(timer_device, frequency); + + timer_device->current_frequency = frequency; + timer_device->counter = 0; + if (result != TIMER_RESULT_OK) { return DRIVER_RESULT_OTHER_ERROR; } + return DRIVER_RESULT_OK; +} + +void timer_irq_handler(Device *device) { + TimerDevice *timer_device = (TimerDevice *)device->driver_manager_extension; + timer_device->counter++; + + Timer *cur, *next; + list_for_each_owner_safe (cur, next, &timer_device->timer_list_lh, list) { + if (cur->timeout > timer_device->counter) { break; } + list_del(&cur->list); + cur->timeout = 0; + } +} + +DriverResult register_timer_device( + DeviceDriver *device_driver, Device *device, TimerDevice *timer_device) { + + device->driver_manager_extension = timer_device; + timer_device->device = device; + DRV_RESULT_DELIVER_CALL(register_device, device_driver, device); + list_init(&timer_device->timer_list_lh); + list_add_tail(&device->dm_list, &timer_device_manager.device_driver_lh); + + return DRIVER_RESULT_OK; +} + +DriverResult unregister_timer_device( + DeviceDriver *device_driver, Device *device, TimerDevice *timer_device) { + Timer *timer, *next; + list_for_each_owner_safe (timer, next, &timer_device->timer_list_lh, list) { + timer->timer_device = NULL; + timer->timeout = 0; + list_del(&timer->list); + } + + DRV_RESULT_DELIVER_CALL(unregister_device, device_driver, device); + list_del(&device->device_list); + return DRIVER_RESULT_OK; +} + +DriverResult timer_init(Timer *timer) { + timer->timer_device = + timer_dm_ext.scheduler_timer->driver_manager_extension; + timer->timeout = 0; + return DRIVER_RESULT_OK; +} + +DriverResult timer_set_timeout(Timer *timer, uint32_t count) { + if (timer->timer_device == NULL) return DRIVER_RESULT_DEVICE_NOT_EXIST; + timer->timeout = timer->timer_device->counter + count; + + // 在插入时排序 + if (!list_empty(&timer->timer_device->timer_list_lh)) { + Timer *last_timer = + list_last_owner(&timer->timer_device->timer_list_lh, Timer, list); + while (last_timer->timeout > timer->timeout) { + last_timer = list_prev_onwer(last_timer, list); + } + list_add_after(&timer->list, &last_timer->list); + } else { + list_add_tail(&timer->list, &timer->timer_device->timer_list_lh); + } + return DRIVER_RESULT_OK; +} + +uint32_t timer_count_ms(Timer *timer, uint32_t ms) { + uint32_t freq = timer->timer_device->current_frequency; + if (freq < 1000) { + return DIV_ROUND_UP(ms * freq, 1000); + } else { + return DIV_ROUND_UP(ms, (freq / 1000)); + } +} + +void delay_ms(Timer *timer, uint32_t ms) { + uint32_t count = timer_count_ms(timer, ms); + timer_set_timeout(timer, count); + + while (timer->timeout != 0) + ; +} + +void delay_ms_async(Timer *timer, uint32_t ms) { + uint32_t count = timer_count_ms(timer, ms); + timer_set_timeout(timer, count); + // 设置完立即返回 +} + +bool timer_is_timeout(Timer *timer) { + return timer->timeout == 0; +} diff --git a/src/driver/video.c b/src/driver/video.c new file mode 100644 index 0000000..fe8102f --- /dev/null +++ b/src/driver/video.c @@ -0,0 +1,220 @@ +#include "driver/video.h" +#include +#include + +extern struct VideoDeviceManager video_dm_ext; +void write_pixel_rgbto8(uint8_t *vram, uint8_t r, uint8_t g, uint8_t b) { + *vram = (r * 6 / 256) + (g * 6 / 256) * 6 + (b * 6 / 256) * 36; +} + +void write_pixel_rgbto16(uint8_t *vram, uint8_t r, uint8_t g, uint8_t b) { + *((uint16_t *)vram) = + (r * 32 / 256) << 11 | ((g * 64 / 256)) << 5 | (b * 32 / 256); +} + +void write_pixel_rgbto24(uint8_t *vram, uint8_t r, uint8_t g, uint8_t b) { + vram[0] = b; + vram[1] = g; + vram[2] = r; +} + +void write_pixel_rgbto32(uint8_t *vram, uint8_t r, uint8_t g, uint8_t b) { + vram[0] = b; + vram[1] = g; + vram[2] = r; + vram[3] = 0; +} + +void write_pixel_raw_8(uint8_t *vram, uint32_t color) { + *vram = color; +} +void write_pixel_raw_16(uint8_t *vram, uint32_t color) { + *((uint16_t *)vram) = color; +} +void write_pixel_raw_24(uint8_t *vram, uint32_t color) { + vram[0] = color & 0xff; + vram[1] = (color >> 8) & 0xff; + vram[2] = (color >> 16) & 0xff; +} +void write_pixel_raw_32(uint8_t *vram, uint32_t color) { + *((uint32_t *)vram) = color; +} + +FramebufferOps fb_ops_8 = { + .write_pixel_raw = write_pixel_raw_8, + .write_pixel_rgb = write_pixel_rgbto8, +}; +FramebufferOps fb_ops_16 = { + .write_pixel_raw = write_pixel_raw_16, + .write_pixel_rgb = write_pixel_rgbto16, +}; +FramebufferOps fb_ops_24 = { + .write_pixel_raw = write_pixel_raw_24, + .write_pixel_rgb = write_pixel_rgbto24, +}; +FramebufferOps fb_ops_32 = { + .write_pixel_raw = write_pixel_raw_32, + .write_pixel_rgb = write_pixel_rgbto32, +}; + +/** + * @brief 写像素 + * + * @param x x坐标 + * @param y y坐标 + * @param color 颜色 + */ +void inline write_pixel( + VideoDevice *video_device, int x, int y, uint32_t color) { + uint8_t *vram = video_device->framebuffer_address; + vram += (y * video_device->mode_info.width + x) * + (video_device->mode_info.bits_per_pixel / 8); + video_device->framebuffer_ops->write_pixel_raw(vram, color); +} + +/** + * @brief 写像素 + * + * @param x x坐标 + * @param y y坐标 + * @param r 红色 + * @param g 绿色 + * @param b 蓝色 + */ +void inline write_pixel_rgb( + VideoDevice *video_device, int x, int y, uint8_t r, uint8_t g, uint8_t b) { + uint8_t *vram = video_device->framebuffer_address; + vram += (y * video_device->mode_info.width + x) * + (video_device->mode_info.bits_per_pixel / 8); + video_device->framebuffer_ops->write_pixel_rgb(vram, r, g, b); +} + +/** + * @brief 画矩形 + * + * @param video_device 显示设备 + * @param x x坐标 + * @param y y坐标 + * @param width 宽度 + * @param height 高度 + * @param color 颜色 + */ +void draw_rect( + VideoDevice *video_device, int x, int y, int width, int height, int color) { + int bpp = video_device->mode_info.bytes_per_pixel; + int x0, y0; + uint8_t *vram = video_device->framebuffer_address + + (y * video_device->mode_info.width + x) * bpp; + int delta = (video_device->mode_info.width - width) * bpp; + for (y0 = 0; y0 < height; y0++) { + for (x0 = 0; x0 < width; x0++) { + video_device->framebuffer_ops->write_pixel_raw(vram, color); + vram += bpp; + } + vram += delta; + } +} + +/** + * @brief 画矩形 + * + * @param x x坐标 + * @param y y坐标 + * @param width 宽度 + * @param height 高度 + * @param r 红色 + * @param g 绿色 + * @param b 蓝色 + */ +void draw_rect_rgb( + VideoDevice *video_device, int x, int y, int width, int height, uint8_t r, + uint8_t g, uint8_t b) { + int bpp = video_device->mode_info.bytes_per_pixel; + int x0, y0; + uint8_t *vram = video_device->framebuffer_address + + (y * video_device->mode_info.width + x) * bpp; + int delta = (video_device->mode_info.width - width) * bpp; + for (y0 = y; y0 < y + height; y0++) { + for (x0 = 0; x0 < width; x0++) { + video_device->framebuffer_ops->write_pixel_rgb(vram, r, g, b); + vram += bpp; + } + vram += delta; + } +} + +/** + * @brief 打印字符 + * + * @param x x坐标 + * @param y y坐标 + * @param ascii 字符数据(16*8点阵字体) + * @param color 颜色 + */ +void print_word( + FramebufferOps *ops, VideoModeInfo *mode_info, uint8_t *vram, + uint8_t *ascii, int color) { + int i; + char d; + uint8_t bpp = mode_info->bytes_per_pixel; + int delta = (mode_info->width - 8) * bpp; + for (i = 0; i < 16; i++) { + d = ascii[i]; + if (d & 0x80) { ops->write_pixel_raw(vram, color); } + vram += bpp; + if (d & 0x40) { ops->write_pixel_raw(vram, color); } + vram += bpp; + if (d & 0x20) { ops->write_pixel_raw(vram, color); } + vram += bpp; + if (d & 0x10) { ops->write_pixel_raw(vram, color); } + vram += bpp; + if (d & 0x08) { ops->write_pixel_raw(vram, color); } + vram += bpp; + if (d & 0x04) { ops->write_pixel_raw(vram, color); } + vram += bpp; + if (d & 0x02) { ops->write_pixel_raw(vram, color); } + vram += bpp; + if (d & 0x01) { ops->write_pixel_raw(vram, color); } + vram += bpp; + vram += delta; + } +} + +/** + * @brief 打印字符 + * + * @param x x坐标 + * @param y y坐标 + * @param ascii 字符数据(16*8点阵字体) + * @param r 红色 + * @param g 绿色 + * @param b 蓝色 + */ +void print_word_rgb( + FramebufferOps *ops, VideoModeInfo *mode_info, uint8_t *vram, char *ascii, + uint8_t r, uint8_t g, uint8_t b) { + int i; + char d; + uint8_t bpp = mode_info->bytes_per_pixel; + int delta = (mode_info->width - 8) * bpp; + for (i = 0; i < 16; i++) { + d = ascii[i]; + if (d & 0x80) { ops->write_pixel_rgb(vram, r, g, b); } + vram += bpp; + if (d & 0x40) { ops->write_pixel_rgb(vram, r, g, b); } + vram += bpp; + if (d & 0x20) { ops->write_pixel_rgb(vram, r, g, b); } + vram += bpp; + if (d & 0x10) { ops->write_pixel_rgb(vram, r, g, b); } + vram += bpp; + if (d & 0x08) { ops->write_pixel_rgb(vram, r, g, b); } + vram += bpp; + if (d & 0x04) { ops->write_pixel_rgb(vram, r, g, b); } + vram += bpp; + if (d & 0x02) { ops->write_pixel_rgb(vram, r, g, b); } + vram += bpp; + if (d & 0x01) { ops->write_pixel_rgb(vram, r, g, b); } + vram += bpp; + vram += delta; + } +} diff --git a/src/driver/video_dm.c b/src/driver/video_dm.c new file mode 100644 index 0000000..f8590ea --- /dev/null +++ b/src/driver/video_dm.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include +#include + +DriverResult video_device_start(DeviceManager *manager, Device *device); + +DeviceManagerOps video_dm_ops = { + .dm_load_hook = NULL, + .dm_unload_hook = NULL, + + .init_device_hook = NULL, + .start_device_hook = video_device_start, + .stop_device_hook = NULL, + .destroy_device_hook = NULL, +}; + +VideoDeviceManager video_dm_ext; + +struct DeviceManager video_device_manager = { + .type = DEVICE_TYPE_VIDEO, + + .ops = &video_dm_ops, + + .private_data = &video_dm_ext, +}; + +DriverResult video_dm_load(DeviceManager *manager) { + VideoDeviceManager *video_manager = manager->private_data; + video_manager->main_display_device = NULL; + + return DRIVER_RESULT_OK; +} + +DriverResult video_dm_unload(DeviceManager *manager) { + VideoDeviceManager *video_manager = manager->private_data; + video_manager->main_display_device = NULL; + + return DRIVER_RESULT_OK; +} + +DriverResult register_video_device( + DeviceDriver *device_driver, Device *device, VideoDevice *video_device) { + device->driver_manager_extension = video_device; + if (device->driver_manager_extension == NULL) { + return DRIVER_RESULT_OUT_OF_MEMORY; + } + video_device->device = device; + + DRV_RESULT_DELIVER_CALL(register_device, device_driver, device); + list_init(&video_device->video_list_lh); + list_add_tail(&device->dm_list, &video_device_manager.device_driver_lh); + + return DRIVER_RESULT_OK; +} + +DriverResult unregister_video_devce( + DeviceDriver *device_driver, Device *device, VideoDevice *video_device) { + list_del(&video_device->video_list_lh); + return DRIVER_RESULT_OK; +} + +DriverResult video_device_start(DeviceManager *manager, Device *device) { + VideoDevice *video_device = (VideoDevice *)device->driver_manager_extension; + + if (video_dm_ext.main_display_device == NULL) { + video_dm_ext.main_display_device = device; + } + if (video_device->framebuffer_address == NULL) { + return DRIVER_RESULT_OTHER_ERROR; + } + if (video_device->mode_info.bits_per_pixel == 8) { + video_device->framebuffer_ops = &fb_ops_8; + } else if (video_device->mode_info.bits_per_pixel == 16) { + video_device->framebuffer_ops = &fb_ops_16; + } else if (video_device->mode_info.bits_per_pixel == 24) { + video_device->framebuffer_ops = &fb_ops_24; + } else if (video_device->mode_info.bits_per_pixel == 32) { + video_device->framebuffer_ops = &fb_ops_32; + } else { + return DRIVER_RESULT_UNSUPPORT_DEVICE; + } + + return DRIVER_RESULT_OK; +} + +DriverResult video_get_video_device(int in_index, VideoDevice **out_device) { + Device *device; + if (in_index == 0) { + *out_device = + video_dm_ext.main_display_device->driver_manager_extension; + return DRIVER_RESULT_OK; + } + int i = 0; + list_for_each_owner ( + device, &video_device_manager.device_driver_lh, dm_list) { + if (device == video_dm_ext.main_display_device) { continue; } + if (i == in_index) { + *out_device = device->driver_manager_extension; + return DRIVER_RESULT_OK; + } + i++; + } + return DRIVER_RESULT_DEVICE_NOT_EXIST; +} diff --git a/src/include/driver/interrupt_dm.h b/src/include/driver/interrupt_dm.h new file mode 100644 index 0000000..29312f9 --- /dev/null +++ b/src/include/driver/interrupt_dm.h @@ -0,0 +1,37 @@ +#ifndef _INTERRUPT_DM_H +#define _INTERRUPT_DM_H + +#include "kernel/device.h" +#include "kernel/device_driver.h" +#include "kernel/device_manager.h" +#include "kernel/driver.h" +#include + +struct InterruptDevice; + +typedef struct InterruptDeviceOps { + int (*redirect_irq)(struct InterruptDevice *device, int irq); + DriverResult (*enable_irq)(struct InterruptDevice *device, int irq); + DriverResult (*disable_irq)(struct InterruptDevice *device, int irq); + void (*eoi)(struct InterruptDevice *device, int irq); +} InterruptDeviceOps; + +typedef struct InterruptDevice { + Device *device; + InterruptDeviceOps *interrupt_ops; + uint8_t priority; +} InterruptDevice; + +DriverResult register_interrupt_device( + DeviceDriver *device_driver, Device *device, + InterruptDevice *interrupt_device); + +extern struct DeviceManager interrupt_device_manager; + +DriverResult interrupt_dm_start(); +uint32_t interrupt_redirect_irq(int irq); +DriverResult interrupt_enable_irq(int irq); +DriverResult interrupt_disable_irq(int irq); +void interrupt_eoi(int irq); + +#endif \ No newline at end of file diff --git a/src/include/driver/timer_dm.h b/src/include/driver/timer_dm.h new file mode 100644 index 0000000..16becbd --- /dev/null +++ b/src/include/driver/timer_dm.h @@ -0,0 +1,62 @@ +#ifndef _TIMER_DM_H +#define _TIMER_DM_H + +#include "kernel/device.h" +#include "kernel/device_driver.h" +#include "result.h" +#include "stdint.h" + +typedef enum TimerResult { + TIMER_RESULT_OK = 0, + TIMER_RESULT_FREQ_TOO_LARGE, + TIMER_RESULT_FREQ_TOO_SMALL, + TIMER_RESULT_OTHER_ERROR, +} TimerResult; + +#define TIMER_RESULT_DELIVER_CALL(func, ...) \ + RESULT_DELIVER_CALL(TimerResult, TIMER_RESULT_OK, func, {}, __VA_ARGS__) + +struct TimerDevice; + +typedef struct TimerOps { + TimerResult (*set_frequency)( + struct TimerDevice *timer_device, uint32_t frequency); + TimerResult (*one_shot)( + struct TimerDevice *timer_device, + uint32_t frequency); // 单次中断,可用于校准其他定时器 +} TimerOps; + +typedef struct TimerDevice { + list_t timer_list_lh; + + Device *device; + uint32_t current_frequency; + uint32_t min_frequency; + uint32_t max_frequency; + uint32_t source_frequency; + uint32_t priority; + + uint32_t counter; + + TimerOps *timer_ops; +} TimerDevice; + +typedef struct Timer { + list_t list; + + TimerDevice *timer_device; + uint32_t timeout; +} Timer; + +extern struct DeviceManager timer_device_manager; + +DriverResult register_timer_device( + DeviceDriver *device_driver, Device *device, TimerDevice *timer_device); +DriverResult timer_init(Timer *timer); +void timer_irq_handler(Device *device); +DriverResult timer_set_frequency(Device *device, uint32_t frequency); +void delay_ms(Timer *timer, uint32_t ms); +void delay_ms_async(Timer *timer, uint32_t ms); +bool timer_is_timeout(Timer *timer); + +#endif \ No newline at end of file diff --git a/src/include/driver/video.h b/src/include/driver/video.h new file mode 100644 index 0000000..7b5de28 --- /dev/null +++ b/src/include/driver/video.h @@ -0,0 +1,35 @@ +#ifndef _DRIVER_VIDEO_H +#define _DRIVER_VIDEO_H +// TODO: video.h改名 +#include "stdint.h" + +typedef struct FramebufferOps { + void (*write_pixel_raw)(uint8_t *vram, uint32_t color); + void (*write_pixel_rgb)(uint8_t *vram, uint8_t r, uint8_t g, uint8_t b); +} FramebufferOps; + +struct VideoDevice; +struct VideoModeInfo; +void inline write_pixel( + struct VideoDevice *video_device, int x, int y, uint32_t color); +void inline write_pixel_rgb( + struct VideoDevice *video_device, int x, int y, uint8_t r, uint8_t g, + uint8_t b); +void draw_rect( + struct VideoDevice *video_device, int x, int y, int width, int height, + int color); +void draw_rect_rgb( + struct VideoDevice *video_device, int x, int y, int width, int height, + uint8_t r, uint8_t g, uint8_t b); +void print_word( + FramebufferOps *ops, struct VideoModeInfo *mode_info, uint8_t *vram, + uint8_t *ascii, int color); +void print_word_rgb( + FramebufferOps *ops, struct VideoModeInfo *mode_info, uint8_t *vram, + char *ascii, uint8_t r, uint8_t g, uint8_t b); + +extern FramebufferOps fb_ops_8; +extern FramebufferOps fb_ops_16; +extern FramebufferOps fb_ops_24; +extern FramebufferOps fb_ops_32; +#endif \ No newline at end of file diff --git a/src/include/driver/video_dm.h b/src/include/driver/video_dm.h new file mode 100644 index 0000000..e6d801b --- /dev/null +++ b/src/include/driver/video_dm.h @@ -0,0 +1,38 @@ +#ifndef _VIDEO_DM_H +#define _VIDEO_DM_H + +#include "driver/video.h" +#include "kernel/device.h" +#include "kernel/device_driver.h" +#include "kernel/list.h" +#include "stdint.h" + +typedef struct VideoModeInfo { + uint16_t width; + uint16_t height; + uint8_t bits_per_pixel; + uint8_t bytes_per_pixel; +} VideoModeInfo; + +typedef struct VideoDevice { + list_t video_list_lh; + + Device *device; + VideoModeInfo mode_info; + uint8_t *framebuffer_address; + + FramebufferOps *framebuffer_ops; +} VideoDevice; + +typedef struct VideoDeviceManager { + Device *main_display_device; +} VideoDeviceManager; + +extern struct DeviceManager video_device_manager; + +DriverResult register_video_device( + DeviceDriver *device_driver, Device *device, VideoDevice *video_device); +DriverResult unregister_video_devce( + DeviceDriver *device_driver, Device *device, VideoDevice *video_device); +DriverResult video_get_video_device(int in_index, VideoDevice **out_device); +#endif \ No newline at end of file diff --git a/src/include/kernel/bus_driver.h b/src/include/kernel/bus_driver.h new file mode 100644 index 0000000..ba86f63 --- /dev/null +++ b/src/include/kernel/bus_driver.h @@ -0,0 +1,54 @@ +#ifndef _BUS_DRIVER_H +#define _BUS_DRIVER_H + +#include "kernel/device_driver.h" +#include "kernel/driver.h" +#include "kernel/driver_manager.h" + +#define BUS_OPS_CALL(bus, func, ...) \ + { \ + if ((bus)->ops->func != NULL) { \ + DRV_RESULT_DELIVER_CALL((bus)->ops->func, __VA_ARGS__) \ + } \ + } + +struct BusDriver; + +typedef enum BusType { + BUS_TYPE_PLATFORM, + BUS_TYPE_PCI, + BUS_TYPE_ISA, + BUS_TYPE_USB, + BUS_TYPE_MAX, +} BusType; + +typedef struct BusDriverOps { + DriverResult (*register_device_hook)(struct DeviceDriver *device_driver); + DriverResult (*unregister_device_hook)(struct DeviceDriver *device_driver); +} BusDriverOps; + +typedef struct BusDriver { + // 继承SubDriver特征 + SubDriver driver; + + list_t dm_list; + list_t device_lh; + string_t name; + DriverType driver_type; + BusType bus_type; + DriverState state; + + BusDriverOps *ops; + + void *private_data; + uint32_t private_data_size; +} BusDriver; + +extern struct DriverManager bus_driver_manager; + +DriverResult register_bus_driver(Driver *driver, BusDriver *bus_driver); +DriverResult unregister_bus_driver(Driver *driver, BusType type); +DriverResult bus_register_device(DeviceDriver *device_driver); +DriverResult bus_unregister_device(DeviceDriver *device_driver); + +#endif \ No newline at end of file diff --git a/src/include/kernel/console.h b/src/include/kernel/console.h index d852f2a..7966eb8 100644 --- a/src/include/kernel/console.h +++ b/src/include/kernel/console.h @@ -22,16 +22,6 @@ #define COLOR_LYELLOW "" #define COLOR_BWHITE "" -struct console { - unsigned char *vram; - unsigned char *font; - int start_x, start_y; - int cur_x, cur_y; - int width, height; - int color; - int flag; -}; - void init_console(void); void console_start(void); void console_set_cursor(int x, int y); diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h new file mode 100644 index 0000000..5fe71d9 --- /dev/null +++ b/src/include/kernel/device.h @@ -0,0 +1,75 @@ +#ifndef _DEVICE_H +#define _DEVICE_H + +#include "kernel/driver.h" +#include "kernel/driver_interface.h" +#include "kernel/list.h" +#include "stdint.h" +#include "string.h" + +// 调用后自动传递错误 +#define DEV_OPS_CALL(dm, func, ...) \ + { \ + if ((dm)->ops->func != NULL) { \ + DRV_RESULT_DELIVER_CALL((dm)->ops->func, __VA_ARGS__) \ + } \ + } + +typedef enum { + DEVICE_TYPE_UNKNOWN = 0, + DEVICE_TYPE_INTERRUPT_CONTROLLER, + DEVICE_TYPE_TIMER, + DEVICE_TYPE_VIDEO, + DEVICE_TYPE_STORAGE, + DEVICE_TYPE_MOUSE, + DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_SOUND, + DEVICE_TYPE_BUS_CONTROLLER, + DEVICE_TYPE_ETHERNET, + DEVICE_TYPE_MAX, +} DeviceType; + +struct Device; + +typedef struct DeviceOps { + DriverResult (*init)(struct Device *dev); // 初始化设备 + DriverResult (*start)(struct Device *dev); // 启动设备 + DriverResult (*stop)(struct Device *dev); // 停止设备 + DriverResult (*destroy)(struct Device *dev); // 销毁设备 + DriverResult (*status)(struct Device *dev); // 查询设备状态 +} DeviceOps; + +typedef enum { + DEVICE_STATE_UNREGISTERED, // 设备未注册 + DEVICE_STATE_REGISTERED, // 设备已注册 + DEVICE_STATE_READY, // 设备准备就绪 + DEVICE_STATE_ACTIVE, // 设备正在运行 + DEVICE_STATE_ERROR, // 设备错误 +} DeviceState; + +struct DeviceDriver; + +typedef struct Device { + list_t device_list; + list_t dm_list; + string_t name; + DeviceState state; + struct DeviceDriver *device_driver; + + DeviceIrq *irq; + + DeviceOps *ops; + + void *private_data; + uint32_t private_data_size; + void *driver_manager_extension; // 设备管理器所需的扩展信息 +} Device; + +DriverResult register_device( + struct DeviceDriver *device_driver, Device *device); +DriverResult unregister_device( + struct DeviceDriver *device_driver, Device *device); +DriverResult init_device(Device *device); +DriverResult init_and_start(Device *device); + +#endif \ No newline at end of file diff --git a/src/include/kernel/device_driver.h b/src/include/kernel/device_driver.h new file mode 100644 index 0000000..b75aa8a --- /dev/null +++ b/src/include/kernel/device_driver.h @@ -0,0 +1,62 @@ +#ifndef _DEVICE_DRIVER_H +#define _DEVICE_DRIVER_H + +#include "kernel/device.h" +#include "kernel/driver.h" +#include "kernel/list.h" +#include "stdint.h" +#include "string.h" + +// 调用后自动传递错误 +#define DRV_OPS_CALL(dm, func, ...) \ + { \ + if ((dm)->ops->func != NULL) { \ + DRV_RESULT_DELIVER_CALL((dm)->ops->func, __VA_ARGS__) \ + } \ + } + +typedef enum { + DRIVER_PRIORITY_BASIC, // 基础驱动 + DRIVER_PRIORITY_GENERAL, // 通用驱动 + DRIVER_PRIORITY_OPTIMIZED, // 优化驱动 + DRIVER_PRIORITY_EXCLUSIVE, // 专属驱动 +} DriverPriority; + +struct DeviceDriver; + +typedef struct DeviceDriverOps { + DriverResult (*register_driver_hook)(struct DeviceDriver *driver); + DriverResult (*unregister_driver_hook)(struct DeviceDriver *driver); +} DeviceDriverOps; + +typedef enum { + DRIVER_STATE_UNREGISTERED, // 驱动未注册 + DRIVER_STATE_REGISTERED, // 驱动已注册 + DRIVER_STATE_ACTIVE, // 驱动正在运行 +} DriverState; + +typedef struct DeviceDriver { + // 继承SubDriver特征 + SubDriver driver; + + list_t bus_list; + list_t device_lh; + string_t name; + DeviceType type; + DriverPriority priority; + DriverState state; + + DeviceDriverOps *ops; + + void *private_data; + uint32_t private_data_size; +} DeviceDriver; + +extern struct DriverManager device_driver_manager; + +DriverResult register_device_driver( + Driver *driver, DeviceDriver *device_driver); +DriverResult unregister_device_driver( + Driver *driver, DeviceDriver *device_driver); + +#endif \ No newline at end of file diff --git a/src/include/kernel/device_manager.h b/src/include/kernel/device_manager.h new file mode 100644 index 0000000..df4f975 --- /dev/null +++ b/src/include/kernel/device_manager.h @@ -0,0 +1,47 @@ +#ifndef _DEVICE_MANAGER_H +#define _DEVICE_MANAGER_H + +#include "kernel/device.h" +#include "kernel/driver.h" +#include "kernel/list.h" + +#define DEVM_OPS_CALL(dm, func, ...) \ + { \ + if ((dm)->ops->func != NULL) { \ + DRV_RESULT_DELIVER_CALL((dm)->ops->func, __VA_ARGS__) \ + } \ + } + +struct DeviceManager; + +typedef struct DeviceMangerOps { + DriverResult (*dm_load_hook)(struct DeviceManager *manager); + DriverResult (*dm_unload_hook)(struct DeviceManager *manager); + + DriverResult (*init_device_hook)( + struct DeviceManager *manager, Device *device); + DriverResult (*start_device_hook)( + struct DeviceManager *manager, Device *device); + DriverResult (*stop_device_hook)( + struct DeviceManager *manager, Device *device); + DriverResult (*destroy_device_hook)( + struct DeviceManager *manager, Device *device); +} DeviceManagerOps; + +typedef struct DeviceManager { + list_t dm_list; + list_t device_driver_lh; + + DeviceType type; + + DeviceManagerOps *ops; + + void *private_data; +} DeviceManager; + +extern DeviceManager *device_managers[DEVICE_TYPE_MAX]; + +DriverResult register_device_manager(DeviceManager *manager); +DriverResult unregister_device_manager(DeviceManager *manager); + +#endif \ No newline at end of file diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index 44cfadb..f7f9d46 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -1,6 +1,7 @@ #ifndef _DRIVER_H #define _DRIVER_H +#include #define DRIVER_MAX_NAME_LEN 64 #define DEVICE_MAX_NAME_LEN 64 @@ -43,24 +44,31 @@ typedef struct { status_t (*driver_exit)(struct _driver_s *drv); status_t (*driver_open)(struct _device_s *dev); status_t (*driver_close)(struct _device_s *dev); - status_t (*driver_read)(struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); - status_t (*driver_write)(struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); - status_t (*driver_devctl)(struct _device_s *dev, uint32_t func_num, uint32_t value); + status_t (*driver_read)( + struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); + status_t (*driver_write)( + struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); + status_t (*driver_devctl)( + struct _device_s *dev, uint32_t func_num, uint32_t value); } driver_func_t; #define DEV_READ(device, buf, offset, size) \ - device->drv_obj->function.driver_read(device, (uint8_t *)buf, (uint32_t)offset, (size_t)size) + device->drv_obj->function.driver_read( \ + device, (uint8_t *)buf, (uint32_t)offset, (size_t)size) #define DEV_WRITE(device, buf, offset, size) \ - device->drv_obj->function.driver_write(device, (uint8_t *)buf, (uint32_t)offset, (size_t)size) -#define DEV_CTL(device, func, value) \ - device->drv_obj->function.driver_devctl(device, (uint32_t)func, (uint32_t)value) + device->drv_obj->function.driver_write( \ + device, (uint8_t *)buf, (uint32_t)offset, (size_t)size) +#define DEV_CTL(device, func, value) \ + device->drv_obj->function.driver_devctl( \ + device, (uint32_t)func, (uint32_t)value) typedef struct _device_manager_s { string_t name; list_t dev_listhead; void *private_data; - void (*dm_register)(struct _device_manager_s *dm, struct _device_s *dev, char *name); + void (*dm_register)( + struct _device_manager_s *dm, struct _device_s *dev, char *name); void (*dm_unregister)(struct _device_manager_s *dm, struct _device_s *dev); void (*drv_inited)(struct _device_manager_s *dm); @@ -89,16 +97,78 @@ void init_dm(void); void dm_start(void); struct index_node *dev_open(char *path); int dev_close(struct index_node *inode); -int dev_read(struct index_node *inode, uint8_t *buffer, uint32_t length); -int dev_write(struct index_node *inode, uint8_t *buffer, uint32_t length); -int dev_ioctl(struct index_node *inode, uint32_t cmd, uint32_t arg); -status_t driver_create(driver_func_t func, char *driver_name); -status_t device_create(driver_t *driver, unsigned long device_extension_size, char *name, dev_type_t type, - device_t **device); -void device_delete(device_t *device); -void device_register_irq(device_t *devobj, int irq, driver_irq_handler_t handler); -void device_unregister_irq(device_t *devobj, int irq); -void device_irq_handler(int irq); -void driver_inited(); +int dev_read(struct index_node *inode, uint8_t *buffer, uint32_t length); +int dev_write(struct index_node *inode, uint8_t *buffer, uint32_t length); +int dev_ioctl(struct index_node *inode, uint32_t cmd, uint32_t arg); +status_t driver_create(driver_func_t func, char *driver_name); +status_t device_create( + driver_t *driver, unsigned long device_extension_size, char *name, + dev_type_t type, device_t **device); +void device_delete(device_t *device); +void device_register_irq( + device_t *devobj, int irq, driver_irq_handler_t handler); +void device_unregister_irq(device_t *devobj, int irq); +void driver_inited(); + +// --------new-------- + +#include "result.h" + +typedef enum { + DRIVER_TYPE_DEVICE_DRIVER = 0, + DRIVER_TYPE_BUS_DRIVER, + DRIVER_TYPE_MAX, +} DriverType; + +extern list_t startup_dm_lh; + +// 实体的驱动,管理着一个驱动下的所有类型的抽象驱动 +typedef struct Driver { + string_t name; + list_t sub_driver_lh; + list_t remapped_memory_lh; +} Driver; + +typedef struct SubDriver { + list_t list; + list_t sub_driver_list; + Driver *driver; + DriverType type; +} SubDriver; + +typedef enum DriverResult { + DRIVER_RESULT_OK, + DRIVER_RESULT_TIMEOUT, + DRIVER_RESULT_BUS_DRIVER_ALREADY_EXIST, + DRIVER_RESULT_BUS_DRIVER_NOT_EXIST, + DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST, + DRIVER_RESULT_DEVICE_MANAGER_NOT_EXIST, + DRIVER_RESULT_DEVICE_NOT_EXIST, + DRIVER_RESULT_DEVICE_DRIVER_HAVE_NO_OPS, + DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS, + DRIVER_RESULT_INVALID_IRQ_NUMBER, + DRIVER_RESULT_OUT_OF_MEMORY, + DRIVER_RESULT_NULL_POINTER, + DRIVER_RESULT_UNSUPPORT_DEVICE, + DRIVER_RESULT_OTHER_ERROR, +} DriverResult; + +DriverResult register_sub_driver(Driver *driver, SubDriver *sub_driver); +DriverResult unregister_sub_driver(Driver *driver, SubDriver *sub_driver); +void print_driver_result( + DriverResult result, char *file, int line, char *func_with_args); + +#define DRV_PRINT_RESULT(result, func, ...) \ + print_driver_result(result, __FILE__, __LINE__, #func "(" #__VA_ARGS__ ")"); +#define DRV_RESULT_DELIVER_CALL(func, ...) \ + RESULT_DELIVER_CALL( \ + DriverResult, DRIVER_RESULT_OK, func, \ + { DRV_PRINT_RESULT(result, func, ...); }, __VA_ARGS__) + +#define DRV_RESULT_PRINT_CALL(func, ...) \ + { \ + DriverResult result = func(__VA_ARGS__); \ + DRV_PRINT_RESULT(result, func, __VA_ARGS__); \ + } #endif \ No newline at end of file diff --git a/src/include/kernel/driver_interface.h b/src/include/kernel/driver_interface.h new file mode 100644 index 0000000..144857e --- /dev/null +++ b/src/include/kernel/driver_interface.h @@ -0,0 +1,57 @@ +#ifndef _DRIVER_INTERFACE_H +#define _DRIVER_INTERFACE_H + +#ifdef ARCH_X86 + +#define io_out_byte(port, data) io_out8(port, data) +#define io_out_word(port, data) io_out16(port, data) +#define io_out_dword(port, data) io_out32(port, data) + +#define io_in_byte(port, data) io_in8(port, data) +#define io_in_word(port, data) io_in16(port, data) +#define io_in_dword(port, data) io_in32(port, data) + +#define read_msr(msr, l, h) cpu_RDMSR(msr, l, h) +#define write_msr(msr, l, h) cpu_WRMSR(msr, l, h) + +#define enable_interrupt() io_sti() +#define disable_interrupt() io_cli() + +#else +#error Driver: Unsupport Architecture +#endif + +#include +#define print_error(str, ...) \ + printk(COLOR_RED __FILE__ " Line %d: " str, __LINE__, ##__VA_ARGS__) +#define print_device_info(device, str, ...) \ + printk("[%s]" str, device->name.text, __VA_ARGS__) +#define print_driver_info(driver, str, ...) \ + printk("[%s]" str, driver.name.text, __VA_ARGS__) + +#include "kernel/list.h" +struct Device; +typedef void (*DeviceIrqHandler)(struct Device *device); +typedef struct DeviceIrq { + list_t list; + int irq; + struct Device *device; + DeviceIrqHandler handler; +} DeviceIrq; + +#include "kernel/driver.h" +#include "stdint.h" +typedef struct DriverRemappedMemory { + list_t list; + uint32_t start; + uint32_t size; +} DriverRemappedMemory; + +enum DriverResult register_device_irq(DeviceIrq *dev_irq); +enum DriverResult unregister_device_irq(DeviceIrq *dev_irq); +void device_irq_handler(int irq); +DriverResult driver_remap_memory( + Driver *in_driver, uint32_t in_physical_address, uint32_t in_size, + uint32_t *out_virtual_address); + +#endif \ No newline at end of file diff --git a/src/include/kernel/driver_manager.h b/src/include/kernel/driver_manager.h new file mode 100644 index 0000000..07e8fa2 --- /dev/null +++ b/src/include/kernel/driver_manager.h @@ -0,0 +1,41 @@ +#ifndef _DRIVER_MANAGER_H +#define _DRIVER_MANAGER_H + +#include "kernel/device_driver.h" +#include "kernel/driver.h" +#include "kernel/list.h" +#include "result.h" + +// 调用后自动传递错误 +#define DM_OPS_CALL(dm, func, ...) \ + { \ + if ((dm)->ops->func != NULL) { \ + DRV_RESULT_DELIVER_CALL((dm)->ops->func, __VA_ARGS__) \ + } \ + } + +struct DriverManager; + +typedef struct DriverManagerOps { + DriverResult (*dm_load_hook)(struct DriverManager *driver_manager); + DriverResult (*register_device_driver_hook)( + struct DriverManager *driver_manager, struct DeviceDriver *driver); + DriverResult (*unregister_device_driver_hook)( + struct DriverManager *driver_manager, struct DeviceDriver *driver); + DriverResult (*dm_unload_hook)(struct DriverManager *driver_manager); +} DriverManagerOps; + +typedef struct DriverManager { + list_t dm_lh; + DriverType type; + DriverManagerOps *ops; + + void *private_data; +} DriverManager; + +extern DriverManager *driver_managers[DRIVER_TYPE_MAX]; + +DriverResult register_driver_manager(DriverManager *driver_manager); +DriverResult unregister_driver_manager(DriverManager *driver_manager); + +#endif \ No newline at end of file diff --git a/src/include/kernel/memory.h b/src/include/kernel/memory.h index 876b693..73caa71 100644 --- a/src/include/kernel/memory.h +++ b/src/include/kernel/memory.h @@ -1,50 +1,77 @@ #ifndef _MEMORY_H #define _MEMORY_H +#include "result.h" #include #include #define PHY_MEM_BASE_ADDR 0x1000000 -#define PHY_MEM_MMAP 0x210000 +#define PHY_MEM_MMAP 0x210000 #define PHY_MEM_MMAP_SIZE 0x20000 #define VIR_MEM_BASE_ADDR 0x1000000 -#define VIR_MEM_MMAP 0x230000 +#define VIR_MEM_MMAP 0x230000 #define VIR_MEM_MMAP_SIZE 0x10000 #define KERN_VIR_MEM_BASE_ADDR 0x00000000 #define USER_VIR_MEM_BASE_ADDR 0x80000000 -#define MEMORY_BLOCKS 0x1000 -#define MEMORY_BLOCK_FREE 0 // 内存信息块空闲 -#define MEMORY_BLOCK_USING 1 // 内存信息块使用中 +#define MEMORY_BLOCKS 0x1000 +#define MEMORY_BLOCK_FREE 0 // 内存信息块空闲 +#define MEMORY_BLOCK_USING 1 // 内存信息块使用中 #define MEMORY_BLOCK_MODE_SMALL 0 // 小块内存描述1024一下的内存块 -#define MEMORY_BLOCK_MODE_BIG 1 // 大块内存描述4kb为单位的内存块 +#define MEMORY_BLOCK_MODE_BIG 1 // 大块内存描述4kb为单位的内存块 extern struct mmap phy_page_mmap; extern struct mmap vir_page_mmap; +typedef enum MemoryResult { + MEMORY_RESULT_OK, + MEMORY_RESULT_INVALID_INPUT, + MEMORY_RESULT_OUT_OF_MEMORY, + MEMORY_RESULT_MEMORY_IS_USED, +} MemoryResult; + struct mmap { - int len; - unsigned char *bits; + int len; + unsigned char *bits; }; struct memory_block { - unsigned int address; - int size; - int flags; - int mode; + unsigned int address; + int size; + int flags; + int mode; }; struct memory_manage { - struct memory_block free_blocks[MEMORY_BLOCKS]; + struct memory_block free_blocks[MEMORY_BLOCKS]; }; -void init_memory(void); -int get_memory_size(void); -int mmap_search(struct mmap *btmp, unsigned int cnt); -void mmap_set(struct mmap *btmp, unsigned int bit_index, int value); -unsigned long alloc_vaddr(size_t size); -void *kmalloc(uint32_t size); -int kfree(void *address); +void init_memory(void); +int get_memory_size(void); +int mmap_search(struct mmap *btmp, unsigned int cnt); +void mmap_set(struct mmap *btmp, unsigned int bit_index, int value); +int mmap_get(struct mmap *btmp, uint32_t bit_index); +MemoryResult alloc_vaddr(size_t in_size, uint32_t *out_vaddr); +void *kmalloc(uint32_t size); +int kfree(void *address); + +void print_memory_result( + MemoryResult result, char *file, int line, char *func_with_args); + +#define MEM_PRINT_RESULT(result, func, ...) \ + print_memory_result(result, __FILE__, __LINE__, #func "(" #__VA_ARGS__ ")"); +#define MEMORY_RESULT_DELIVER_CALL(func, ...) \ + RESULT_DELIVER_CALL( \ + MemoryResult, MEMORY_RESULT_OK, func, \ + { MEM_PRINT_RESULT(result, func, __VA_ARGS__); }, __VA_ARGS__) +#define MEMORY_RESULT_PRINT_CALL(func, ...) \ + ({ \ + MemoryResult result = func(__VA_ARGS__); \ + if (result != MEMORY_RESULT_OK) { \ + MEM_PRINT_RESULT(result, func, __VA_ARGS__); \ + } \ + result; \ + }) #endif \ No newline at end of file diff --git a/src/include/kernel/platform.h b/src/include/kernel/platform.h index 9d936d3..481b073 100644 --- a/src/include/kernel/platform.h +++ b/src/include/kernel/platform.h @@ -1,5 +1,6 @@ #ifndef _PLATFORM_H -void platform_init(); +void init_platform(); +void platform_init_and_start_devices(); #endif \ No newline at end of file diff --git a/src/include/kernel/process.h b/src/include/kernel/process.h index 2bdb7a3..836ed08 100644 --- a/src/include/kernel/process.h +++ b/src/include/kernel/process.h @@ -7,11 +7,12 @@ #define USER_STACK3_ADDR 0xffbff000 #define USER_START_ADDR 0X80000000 -void start_process(void *filename); -void process_excute(void *filename, struct program_struct *prog); -void page_dir_activate(struct task_s *thread); -void process_activate(struct task_s *thread); -int process_load_segment(struct task_s *thread, struct index_node *inode, unsigned long offset, - unsigned long filesz, unsigned long memsz, unsigned long vaddr); +void start_process(void *filename); +void process_excute(void *filename, struct program_struct *prog); +void page_dir_activate(struct task_s *thread); +void process_activate(struct task_s *thread); +MemoryResult process_load_segment( + struct task_s *thread, struct index_node *inode, unsigned long offset, + unsigned long filesz, unsigned long memsz, unsigned long vaddr); #endif \ No newline at end of file diff --git a/src/include/network/tcp.h b/src/include/network/tcp.h index d98b2c2..6e424af 100644 --- a/src/include/network/tcp.h +++ b/src/include/network/tcp.h @@ -1,7 +1,7 @@ #ifndef TCP_H #define TCP_H -#include "../stdint.h" +#include "driver/timer_dm.h" #include "kernel/list.h" #include "network.h" #include @@ -76,11 +76,9 @@ typedef struct { uint32_t sended; // 已发送的数据大小 } swin; - tcp_status_t status; - uint32_t wait_ms, seq, ack; - struct timer *timer; - struct fifo fifo; - int fifo_buf[2]; + tcp_status_t status; + uint32_t wait_ms, seq, ack; + Timer timer; } tcp_conn_t; #define PROTOCOL_TCP 0x06 @@ -88,8 +86,10 @@ void tcp_create(netc_t *netc); int tcp_bind(netc_t *netc, uint16_t src_port); int tcp_ipv4_connect(netc_t *netc, uint8_t *ip, uint16_t dst_port); void tcp_ipv4_close(netc_t *netc); -void tcp_recv(uint8_t *buf, uint16_t offset, uint16_t length, uint8_t *ip, uint8_t ip_len); -int tcp_write(netc_t *netc, uint8_t *buf, uint32_t length); -int tcp_read(netc_t *netc, uint8_t *buf, uint32_t length); +void tcp_recv( + uint8_t *buf, uint16_t offset, uint16_t length, uint8_t *ip, + uint8_t ip_len); +int tcp_write(netc_t *netc, uint8_t *buf, uint32_t length); +int tcp_read(netc_t *netc, uint8_t *buf, uint32_t length); #endif \ No newline at end of file diff --git a/src/include/result.h b/src/include/result.h new file mode 100644 index 0000000..c0bb9eb --- /dev/null +++ b/src/include/result.h @@ -0,0 +1,18 @@ +#ifndef _RESULT_H +#define _RESULT_H + +#define RESULT_DELIVER_CALL(result_type, result_ok, func, add_ops, ...) \ + { \ + result_type result = func(__VA_ARGS__); \ + if (result != result_ok) { \ + add_ops; \ + return result; \ + } \ + } + +#define RESULT_CASE_PRINT(result) \ + case result: \ + printk(#result); \ + break; + +#endif \ No newline at end of file diff --git a/src/include/string.h b/src/include/string.h index 6d6ea9b..8488086 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -10,48 +10,52 @@ #include "stddef.h" #include "stdint.h" -#include "types.h" #define STRING_MAX_LEN 256 +#define STRING_INIT(str) \ + { \ + .text = str "\0", .length = sizeof(str) + 1, \ + .max_length = sizeof(str) + 1 \ + } typedef struct _string { - unsigned int length; - unsigned int max_length; - char *text; + unsigned int length; + unsigned int max_length; + char *text; } string_t; void string_init(string_t *string); -int string_new(string_t *string, char *text, unsigned int max_len); +int string_new(string_t *string, char *text, unsigned int max_len); void string_del(string_t *string); -int string_cpy(string_t *dest, string_t *src); +int string_cpy(string_t *dest, string_t *src); char *itoa(char **ps, int val, int base); -int atoi(const char *src); +int atoi(const char *src); char *itoa16_align(char *str, int num); void *memset(void *src, uint8_t value, uint32_t size); void memcpy(void *dst_, const void *src_, uint32_t size); -int memcmp(const void *s1, const void *s2, int n); +int memcmp(const void *s1, const void *s2, int n); void *memset16(void *src, uint16_t value, uint32_t size); void *memset32(void *src, uint32_t value, uint32_t size); void *memmove(void *dst, const void *src, uint32_t count); #define bzero(str, n) memset(str, 0, n) -char *strcpy(char *dst_, const char *src_); -uint32_t strlen(const char *str); -int8_t strcmp(const char *a, const char *b); -char *strchr(const char *s, int c); -char *strrchr(char *str, int c); -char *strcat(char *strDest, const char *strSrc); -int strncmp(const char *s1, const char *s2, int n); -int strpos(char *str, char ch); -char *strncpy(char *dst_, char *src_, int n); -char *strncat(char *dst, const char *src, int n); -int strmet(const char *src, char *buf, char ch); -char *strstr(const char *haystack, const char *needle); -size_t strspn(const char *s, const char *accept); +char *strcpy(char *dst_, const char *src_); +uint32_t strlen(const char *str); +int8_t strcmp(const char *a, const char *b); +char *strchr(const char *s, int c); +char *strrchr(char *str, int c); +char *strcat(char *strDest, const char *strSrc); +int strncmp(const char *s1, const char *s2, int n); +int strpos(char *str, char ch); +char *strncpy(char *dst_, char *src_, int n); +char *strncat(char *dst, const char *src, int n); +int strmet(const char *src, char *buf, char ch); +char *strstr(const char *haystack, const char *needle); +size_t strspn(const char *s, const char *accept); const char *strpbrk(const char *str1, const char *str2); -int strcoll(const char *str1, const char *str2); +int strcoll(const char *str1, const char *str2); #endif /*_LIB_STDINT_H*/ diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 3889902..6c2b58f 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -7,6 +7,12 @@ SRC += sync.c SRC += thread.c SRC += initcall.c SRC += driver.c +SRC += bus_driver.c +SRC += device_driver.c +SRC += device_manager.c +SRC += driver_manager.c +SRC += driver_interface.c +SRC += device.c SRC += process.c SRC += syscall.c SRC += app.c diff --git a/src/kernel/bus_driver.c b/src/kernel/bus_driver.c new file mode 100644 index 0000000..d145e9e --- /dev/null +++ b/src/kernel/bus_driver.c @@ -0,0 +1,96 @@ +#include "kernel/device_driver.h" +#include "kernel/list.h" +#include +#include +#include +#include + +BusDriver *bus_drivers[BUS_TYPE_MAX]; + +DriverResult bus_driver_manager_load(DriverManager *driver_manager); +DriverResult bus_driver_manager_unload(DriverManager *driver_manager); +DriverResult driver_load(BusDriver *driver); +DriverResult driver_unload(BusDriver *driver); + +DriverManagerOps bus_driver_ops = { + .dm_load_hook = bus_driver_manager_load, + .dm_unload_hook = bus_driver_manager_unload, + .register_device_driver_hook = NULL, + .unregister_device_driver_hook = NULL, +}; + +typedef struct BusDriverManagerExt { + DeviceDriver *bus_controller_device; +} BusDriverMangerExt; + +BusDriverMangerExt bus_driver_manager_ext; + +struct DriverManager bus_driver_manager = { + .type = DRIVER_TYPE_DEVICE_DRIVER, + + .ops = &bus_driver_ops, + + .private_data = &bus_driver_manager_ext, +}; + +DriverResult bus_driver_manager_load(DriverManager *driver_manager) { + + return DRIVER_RESULT_OK; +} + +DriverResult bus_driver_manager_unload(DriverManager *driver_manager) { + + return DRIVER_RESULT_OK; +} + +DriverResult register_bus_driver(Driver *driver, BusDriver *bus_driver) { + + DriverManager *manager = driver_managers[DRIVER_TYPE_BUS_DRIVER]; + if (manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; + + BusDriver *_bus_driver = bus_drivers[bus_driver->driver_type]; + if (_bus_driver != NULL) return DRIVER_RESULT_BUS_DRIVER_ALREADY_EXIST; + + bus_driver->private_data = kmalloc(bus_driver->private_data_size); + bus_driver->state = DRIVER_STATE_REGISTERED; + + DRV_RESULT_DELIVER_CALL(register_sub_driver, driver, &bus_driver->driver); + + return DRIVER_RESULT_OK; +} + +DriverResult unregister_bus_driver(Driver *driver, BusType type) { + + DriverManager *manager = driver_managers[DRIVER_TYPE_BUS_DRIVER]; + if (manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; + + BusDriver *bus_driver = bus_drivers[type]; + if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + + DRV_RESULT_DELIVER_CALL(unregister_sub_driver, driver, &bus_driver->driver); + + bus_driver->state = DRIVER_STATE_UNREGISTERED; + if (bus_driver->private_data != NULL) kfree(bus_driver->private_data); + + return DRIVER_RESULT_OK; +} + +DriverResult bus_register_device(DeviceDriver *device_driver) { + BusDriver *bus_driver = bus_drivers[device_driver->type]; + if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + + list_add_tail(&device_driver->bus_list, &bus_driver->device_lh); + BUS_OPS_CALL(bus_driver, register_device_hook, device_driver); + + return DRIVER_RESULT_OK; +} + +DriverResult bus_unregister_device(DeviceDriver *device_driver) { + BusDriver *bus_driver = bus_drivers[device_driver->type]; + if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + + BUS_OPS_CALL(bus_driver, unregister_device_hook, device_driver); + list_del(&device_driver->bus_list); + + return DRIVER_RESULT_OK; +} diff --git a/src/kernel/console.c b/src/kernel/console.c index 8463c18..1654645 100644 --- a/src/kernel/console.c +++ b/src/kernel/console.c @@ -5,14 +5,29 @@ * @version 0.3 * @date 2022-07-15 */ -#include +#include "driver/video_dm.h" +#include #include #include #include #include #include +#include #include +struct console { + struct VideoDevice *video_device; + + uint8_t *vram; + uint8_t *cur_vram; + uint8_t *font; + int start_x, start_y; + int cur_x, cur_y; + int width, height; + int color; + int flag; +}; + int command_length = 0; char command[CMD_MAX_LENGTH]; struct console console; @@ -22,14 +37,17 @@ struct console console; * */ void init_console(void) { - console.vram = video_info.vram; - console.font = font16; - console.cur_x = 0; - console.cur_y = 0; - console.width = video_info.width / 10; - console.height = video_info.height / 16; - console.color = 0xc0c0c0; - console.flag = CMD_FLAG_OUTPUT; + video_get_video_device(0, &console.video_device); + + console.vram = console.video_device->framebuffer_address; + console.cur_vram = console.vram; + console.font = font16; + console.cur_x = 0; + console.cur_y = 0; + console.width = console.video_device->mode_info.width / 10; + console.height = console.video_device->mode_info.height / 16; + console.color = 0xc0c0c0; + console.flag = CMD_FLAG_OUTPUT; } /** @@ -87,6 +105,24 @@ void console_input(char c) } */ +void scroll_screen(void) { + int i, j; + int screen_width = console.video_device->mode_info.width; + int screen_height = console.video_device->mode_info.height; + int bpp = console.video_device->mode_info.bytes_per_pixel; + + uint32_t *dst = (uint32_t *)console.vram; + uint32_t *src = (uint32_t *)(console.vram + 16 * screen_width * bpp); + for (j = 0; j < console.height; j++) { + for (i = 0; i < screen_width * bpp * 16 / 4; i++) { + *dst = *src; + dst += 4; + src += 4; + } + } + draw_rect(console.video_device, 0, screen_height - 16, screen_width, 16, 0); +} + /** * @brief 打印一个字符 * @@ -94,36 +130,21 @@ void console_input(char c) * @param color 颜色 */ void print_char(unsigned char c, unsigned int color) { - int i, j, k; - uint32_t _color = color; if (c > 127) { c = '?'; } + int bpp = console.video_device->mode_info.bytes_per_pixel; print_word( - console.cur_x * 10 + 1, console.cur_y * 16, console.font + c * 16, - _color); + console.video_device->framebuffer_ops, &console.video_device->mode_info, + console.cur_vram + 1 * bpp, console.font + c * 16, color); console.cur_x++; + console.cur_vram += 10 * bpp; if (console.cur_x >= console.width) { - console.cur_x = 0; + int screen_width = console.video_device->mode_info.width; + console.cur_x = 0; console.cur_y++; + console.cur_vram = + console.vram + console.cur_y * 16 * screen_width * bpp; } - if (console.cur_y >= console.height) { - console.cur_y = console.height - 1; - console.cur_x = 0; - int height = console.height * 16; - int width = console.width * 10; - int byte_per_pixel = video_info.BitsPerPixel / 8; - for (i = 16; i < height; i++) { - for (j = 0; j < width; j++) { - for (k = 0; k < byte_per_pixel; k++) { - console.vram - [((i - 16) * video_info.width + j) * byte_per_pixel + - k] = - console.vram - [(i * video_info.width + j) * byte_per_pixel + k]; - } - } - } - draw_rect(0, console.height * 16 - 16, console.width * 10, 16, 0); - } + if (console.cur_y >= console.height) { scroll_screen(); } } /** @@ -141,8 +162,10 @@ int printk(const char *fmt, ...) { i = vsprintf(buf, fmt, arg); va_end(); - char *p = buf, c; - int len = i; + char *p = buf, c; + int len = i; + int bpp = console.video_device->mode_info.bytes_per_pixel; + int screen_width = console.video_device->mode_info.width; while (len) { c = *p++; if (c == '<' && len == i) { @@ -210,37 +233,48 @@ int printk(const char *fmt, ...) { case '\n': console.cur_y++; console.cur_x = 0; - if (console.cur_y >= console.height) { - print_char('\n', color); - if (console.cur_y < 0) { console.cur_y = 0; } - if (console.flag == CMD_FLAG_INPUT) { - console.start_y = console.cur_y; - } - } + console.cur_vram = + console.vram + console.cur_y * 16 * screen_width * bpp; break; case '\b': if (console.flag == CMD_FLAG_INPUT) { if (console.cur_x != console.start_x && console.cur_y != console.start_y) { console.cur_x--; + console.cur_vram -= 10 * bpp; draw_rect( - console.cur_x * 10, console.cur_y * 16, 10, 16, 0); + console.video_device, console.cur_x * 10 + 1, + console.cur_y * 16, 8, 16, 0); } } break; case '\t': - if ((console.cur_x % 4) == 0) { console.cur_x += 4; } - while (console.cur_x % 4) { - console.cur_x++; - } + console.cur_x += 4 - console.cur_x & 3; break; case '\r': break; default: - draw_rect(console.cur_x * 10, console.cur_y * 16, 10, 16, 0); + draw_rect( + console.video_device, console.cur_x * 10, console.cur_y * 16, + 10, 16, 0); print_char(c, color); break; } + if (console.cur_x > console.width) { + console.cur_x = 0; + console.cur_y++; + console.cur_vram = + console.vram + console.cur_y * 16 * screen_width * bpp; + } + if (console.cur_y >= console.height) { + print_char('\n', color); + if (console.cur_y < 0) { console.cur_y = 0; } + if (console.flag == CMD_FLAG_INPUT) { + console.start_y = console.cur_y; + } + console.cur_vram = + console.vram + console.cur_y * 16 * screen_width * bpp; + } len--; } diff --git a/src/kernel/device.c b/src/kernel/device.c new file mode 100644 index 0000000..57747af --- /dev/null +++ b/src/kernel/device.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#include + +DriverResult register_device(DeviceDriver *device_driver, Device *device) { + device->state = DEVICE_STATE_REGISTERED; + list_add_tail(&device->device_list, &device_driver->device_lh); + bus_register_device(device_driver); + return DRIVER_RESULT_OK; +} + +DriverResult unregister_device(DeviceDriver *device_driver, Device *device) { + device->state = DEVICE_STATE_REGISTERED; + bus_unregister_device(device_driver); + list_del(&device->device_list); + return DRIVER_RESULT_OK; +} + +DriverResult init_device(Device *device) { + DeviceManager *manager = device_managers[device->device_driver->type]; + if (device->ops->init != NULL) { + DriverResult result = device->ops->init(device); + if (result != DRIVER_RESULT_OK) { + if (result != DRIVER_RESULT_DEVICE_NOT_EXIST) { + DRV_PRINT_RESULT(result, device->ops->init, device); + return result; + } else { + return DRIVER_RESULT_OK; + } + } + } + DEVM_OPS_CALL(manager, init_device_hook, manager, device); + return DRIVER_RESULT_OK; +} + +DriverResult start_device(Device *device) { + DeviceManager *manager = device_managers[device->device_driver->type]; + DEV_OPS_CALL(device, start, device); + DEVM_OPS_CALL(manager, start_device_hook, manager, device); + return DRIVER_RESULT_OK; +} + +DriverResult init_and_start(Device *device) { + DRV_RESULT_DELIVER_CALL(init_device, device); + DRV_RESULT_DELIVER_CALL(start_device, device); + return DRIVER_RESULT_OK; +} diff --git a/src/kernel/device_driver.c b/src/kernel/device_driver.c new file mode 100644 index 0000000..e9ebc4c --- /dev/null +++ b/src/kernel/device_driver.c @@ -0,0 +1,88 @@ +#include "kernel/device.h" +#include +#include +#include +#include +#include + +DriverResult device_driver_manager_load(DriverManager *driver_manager); +DriverResult device_driver_manager_unload(DriverManager *driver_manager); +DriverResult driver_load(DeviceDriver *driver); +DriverResult driver_unload(DeviceDriver *driver); + +DriverManagerOps device_driver_ops = { + .dm_load_hook = device_driver_manager_load, + .dm_unload_hook = device_driver_manager_unload, + .register_device_driver_hook = NULL, + .unregister_device_driver_hook = NULL, +}; + +typedef struct DeviceDriverManagerExt { + +} DeviceDriverMangerExt; + +DeviceDriverMangerExt device_driver_manager_ext; + +struct DriverManager device_driver_manager = { + .type = DRIVER_TYPE_DEVICE_DRIVER, + + .ops = &device_driver_ops, + + .private_data = &device_driver_manager_ext, +}; + +DriverResult device_driver_manager_load(DriverManager *driver_manager) { + for (int i = 0; i < DEVICE_TYPE_MAX; i++) { + DeviceManager *device_manager = device_managers[i]; + if (device_manager != NULL) { + DEVM_OPS_CALL(device_manager, dm_load_hook, device_manager); + } + } + + return DRIVER_RESULT_OK; +} + +DriverResult device_driver_manager_unload(DriverManager *driver_manager) { + for (int i = 0; i < DEVICE_TYPE_MAX; i++) { + DeviceManager *device_manager = device_managers[i]; + if (device_manager != NULL) { + DEVM_OPS_CALL(device_manager, dm_unload_hook, device_manager); + } + } + + return DRIVER_RESULT_OK; +} + +DriverResult register_device_driver( + Driver *driver, DeviceDriver *device_driver) { + + DriverManager *manager = driver_managers[DRIVER_TYPE_DEVICE_DRIVER]; + if (manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; + + device_driver->private_data = kmalloc(device_driver->private_data_size); + device_driver->state = DRIVER_STATE_REGISTERED; + + DM_OPS_CALL(manager, register_device_driver_hook, manager, device_driver); + + DRV_RESULT_DELIVER_CALL( + register_sub_driver, driver, &device_driver->driver); + + return DRIVER_RESULT_OK; +} + +DriverResult unregister_device_driver( + Driver *driver, DeviceDriver *device_driver) { + + DriverManager *manager = driver_managers[device_driver->type]; + if (manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; + + DRV_RESULT_DELIVER_CALL( + unregister_sub_driver, driver, &device_driver->driver); + + DM_OPS_CALL(manager, unregister_device_driver_hook, manager, device_driver); + + device_driver->state = DRIVER_STATE_UNREGISTERED; + if (device_driver->private_data != NULL) kfree(device_driver->private_data); + + return DRIVER_RESULT_OK; +} diff --git a/src/kernel/device_manager.c b/src/kernel/device_manager.c new file mode 100644 index 0000000..2ef37c2 --- /dev/null +++ b/src/kernel/device_manager.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include + +DeviceManager *device_managers[DEVICE_TYPE_MAX]; + +DriverResult register_device_manager(DeviceManager *manager) { + DeviceManager *old_manager = device_managers[manager->type]; + if (old_manager != NULL) { + DRV_RESULT_DELIVER_CALL(unregister_device_manager, old_manager); + } + + device_managers[manager->type] = manager; + list_add_tail(&manager->dm_list, &startup_dm_lh); + + DEVM_OPS_CALL(manager, dm_load_hook, manager); + return DRIVER_RESULT_OK; +} + +DriverResult unregister_device_manager(DeviceManager *manager) { + // 关闭所有设备 + Device *cur; + list_for_each_owner (cur, &manager->device_driver_lh, device_list) { + if (cur->state != DEVICE_STATE_UNREGISTERED) { + DEV_OPS_CALL(cur, destroy, cur); + } + } + DEVM_OPS_CALL(manager, dm_unload_hook, manager); + // 从链表中删除 + list_del(&manager->dm_list); + + device_managers[manager->type] = NULL; + return DRIVER_RESULT_OK; +} diff --git a/src/kernel/driver.c b/src/kernel/driver.c index 76075aa..c1a6b14 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -11,24 +11,24 @@ #include #include #include +#include #include #include -#include #include #include LIST_HEAD(driver_list_head); -list_t irq_handler_lists[16] = { - LIST_HEAD_INIT(irq_handler_lists[0]), LIST_HEAD_INIT(irq_handler_lists[1]), - LIST_HEAD_INIT(irq_handler_lists[2]), LIST_HEAD_INIT(irq_handler_lists[3]), - LIST_HEAD_INIT(irq_handler_lists[4]), LIST_HEAD_INIT(irq_handler_lists[5]), - LIST_HEAD_INIT(irq_handler_lists[6]), LIST_HEAD_INIT(irq_handler_lists[7]), - LIST_HEAD_INIT(irq_handler_lists[8]), LIST_HEAD_INIT(irq_handler_lists[9]), - LIST_HEAD_INIT(irq_handler_lists[10]), LIST_HEAD_INIT(irq_handler_lists[11]), - LIST_HEAD_INIT(irq_handler_lists[12]), LIST_HEAD_INIT(irq_handler_lists[13]), - LIST_HEAD_INIT(irq_handler_lists[14]), LIST_HEAD_INIT(irq_handler_lists[15]), -}; +// list_t device_irq_lists[16] = { +// LIST_HEAD_INIT(device_irq_lists[0]), LIST_HEAD_INIT(device_irq_lists[1]), +// LIST_HEAD_INIT(device_irq_lists[2]), LIST_HEAD_INIT(device_irq_lists[3]), +// LIST_HEAD_INIT(device_irq_lists[4]), LIST_HEAD_INIT(device_irq_lists[5]), +// LIST_HEAD_INIT(device_irq_lists[6]), LIST_HEAD_INIT(device_irq_lists[7]), +// LIST_HEAD_INIT(device_irq_lists[8]), LIST_HEAD_INIT(device_irq_lists[9]), +// LIST_HEAD_INIT(device_irq_lists[10]), LIST_HEAD_INIT(device_irq_lists[11]), +// LIST_HEAD_INIT(device_irq_lists[12]), LIST_HEAD_INIT(device_irq_lists[13]), +// LIST_HEAD_INIT(device_irq_lists[14]), LIST_HEAD_INIT(device_irq_lists[15]), +// }; struct index_node *dev; @@ -41,6 +41,50 @@ struct file_operations device_fops = { .seek = fs_seek, }; +// --------new-------- +#include +#include +#include + +LIST_HEAD(startup_dm_lh); + +void print_driver_result( + DriverResult result, char *file, int line, char *func_with_args) { + if (result == DRIVER_RESULT_OK) return; + printk("[At file %s line%d: %s]", file, line, func_with_args); + switch (result) { + RESULT_CASE_PRINT(DRIVER_RESULT_OK) + RESULT_CASE_PRINT(DRIVER_RESULT_TIMEOUT) + RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_DRIVER_HAVE_NO_OPS) + RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS) + RESULT_CASE_PRINT(DRIVER_RESULT_INVALID_IRQ_NUMBER) + RESULT_CASE_PRINT(DRIVER_RESULT_OUT_OF_MEMORY) + RESULT_CASE_PRINT(DRIVER_RESULT_BUS_DRIVER_ALREADY_EXIST) + RESULT_CASE_PRINT(DRIVER_RESULT_BUS_DRIVER_NOT_EXIST) + RESULT_CASE_PRINT(DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST) + RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_MANAGER_NOT_EXIST) + RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_NOT_EXIST) + RESULT_CASE_PRINT(DRIVER_RESULT_NULL_POINTER) + RESULT_CASE_PRINT(DRIVER_RESULT_UNSUPPORT_DEVICE) + RESULT_CASE_PRINT(DRIVER_RESULT_OTHER_ERROR) + } +} + +DriverResult register_sub_driver(Driver *driver, SubDriver *sub_driver) { + sub_driver->driver = driver; + + list_add(&sub_driver->sub_driver_list, &driver->sub_driver_lh); + + return DRIVER_RESULT_OK; +} + +DriverResult unregister_sub_driver(Driver *driver, SubDriver *sub_driver) { + list_del(&sub_driver->sub_driver_list); + + return DRIVER_RESULT_OK; +} + +// --------old--------- struct index_node *dev_open(char *path) { struct index_node *inode = vfs_open(path); if (inode == NULL) return NULL; @@ -53,17 +97,18 @@ int dev_close(struct index_node *inode) { } int dev_read(struct index_node *inode, uint8_t *buffer, uint32_t length) { - return inode->device->drv_obj->function.driver_read(inode->device, (uint8_t *)buffer, inode->fp->offset, - length); + return inode->device->drv_obj->function.driver_read( + inode->device, (uint8_t *)buffer, inode->fp->offset, length); } int dev_write(struct index_node *inode, uint8_t *buffer, uint32_t length) { - return inode->device->drv_obj->function.driver_write(inode->device, (uint8_t *)buffer, inode->fp->offset, - length); + return inode->device->drv_obj->function.driver_write( + inode->device, (uint8_t *)buffer, inode->fp->offset, length); } int dev_ioctl(struct index_node *inode, uint32_t cmd, uint32_t arg) { - return inode->device->drv_obj->function.driver_devctl(inode->device, cmd, arg); + return inode->device->drv_obj->function.driver_devctl( + inode->device, cmd, arg); } void init_dm(void) { @@ -94,14 +139,15 @@ status_t driver_create(driver_func_t func, char *driver_name) { } void driver_inited() { - driver_t *cur, *next; - list_for_each_owner_safe (cur, next, &driver_list_head, list) { + driver_t *cur; + list_for_each_owner (cur, &driver_list_head, list) { if (cur->dm != NULL) { cur->dm->drv_inited(cur->dm); } } } -status_t device_create(driver_t *driver, unsigned long device_extension_size, char *name, dev_type_t type, - device_t **device) { +status_t device_create( + driver_t *driver, unsigned long device_extension_size, char *name, + dev_type_t type, device_t **device) { device_t *devobj = kmalloc(sizeof(device_t) + device_extension_size); devobj->type = type; spinlock_init(&devobj->lock); @@ -143,31 +189,24 @@ void device_delete(device_t *device) { kfree(device); } -void device_register_irq(device_t *devobj, int irq, driver_irq_handler_t handler) { +void device_register_irq( + device_t *devobj, int irq, driver_irq_handler_t handler) { if (irq > 16) return; - if (list_empty(&irq_handler_lists[irq])) irq_enable(irq); + // if (list_empty(&device_irq_lists[irq])) irq_enable(irq); dev_irq_t *dev_irq = kmalloc(sizeof(dev_irq_t)); dev_irq->devobj = devobj; dev_irq->handler = handler; - list_add_tail(&dev_irq->list, &irq_handler_lists[irq]); + // list_add_tail(&dev_irq->list, &device_irq_lists[irq]); } void device_unregister_irq(device_t *devobj, int irq) { if (irq > 16) return; - if (list_empty(&irq_handler_lists[irq])) return; + // if (list_empty(&device_irq_lists[irq])) return; dev_irq_t *dev_irq, *next; - list_for_each_owner_safe (dev_irq, next, &irq_handler_lists[irq], list) { - if (dev_irq->devobj == devobj) { - list_del(&dev_irq->list); - kfree(dev_irq); - } - } -} - -void device_irq_handler(int irq) { - dev_irq_t *cur, *next; - if (list_empty(&irq_handler_lists[irq])) return; - list_for_each_owner_safe (cur, next, &irq_handler_lists[irq], list) { - cur->handler(cur->devobj, irq); + // list_for_each_owner_safe (dev_irq, next, &device_irq_lists[irq], list) { + if (dev_irq->devobj == devobj) { + list_del(&dev_irq->list); + kfree(dev_irq); } + // } } diff --git a/src/kernel/driver_interface.c b/src/kernel/driver_interface.c new file mode 100644 index 0000000..ed47242 --- /dev/null +++ b/src/kernel/driver_interface.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +list_t device_irq_lists[16] = { + LIST_HEAD_INIT(device_irq_lists[0]), LIST_HEAD_INIT(device_irq_lists[1]), + LIST_HEAD_INIT(device_irq_lists[2]), LIST_HEAD_INIT(device_irq_lists[3]), + LIST_HEAD_INIT(device_irq_lists[4]), LIST_HEAD_INIT(device_irq_lists[5]), + LIST_HEAD_INIT(device_irq_lists[6]), LIST_HEAD_INIT(device_irq_lists[7]), + LIST_HEAD_INIT(device_irq_lists[8]), LIST_HEAD_INIT(device_irq_lists[9]), + LIST_HEAD_INIT(device_irq_lists[10]), LIST_HEAD_INIT(device_irq_lists[11]), + LIST_HEAD_INIT(device_irq_lists[12]), LIST_HEAD_INIT(device_irq_lists[13]), + LIST_HEAD_INIT(device_irq_lists[14]), LIST_HEAD_INIT(device_irq_lists[15]), +}; + +DriverResult register_device_irq(DeviceIrq *dev_irq) { + if (dev_irq->irq > 16) { + print_error("invalid irq number:%d\n", dev_irq->irq); + return DRIVER_RESULT_INVALID_IRQ_NUMBER; + } + dev_irq->irq = interrupt_redirect_irq(dev_irq->irq); + list_add_tail(&dev_irq->list, &device_irq_lists[dev_irq->irq]); + return DRIVER_RESULT_OK; +} + +DriverResult unregister_device_irq(DeviceIrq *dev_irq) { + list_del(&dev_irq->list); + return DRIVER_RESULT_OK; +} + +void device_irq_handler(int irq) { + DeviceIrq *cur; + if (list_empty(&device_irq_lists[irq])) return; + list_for_each_owner (cur, &device_irq_lists[irq], list) { + cur->handler(cur->device); + } +} + +DriverResult driver_remap_memory( + Driver *in_driver, uint32_t in_physical_address, uint32_t in_size, + uint32_t *out_virtual_address) { + uint32_t start = in_physical_address & 0xfffff000; + uint32_t end = (in_physical_address + in_size + 0xfff) & 0xfffff000; + uint32_t tmp; + uint32_t virtual_address = 0; + for (uint32_t i = start; i < end; i += 0x1000) { + MemoryResult result = MEMORY_RESULT_PRINT_CALL(remap, i, 0x3ff, &tmp); + if (result != MEMORY_RESULT_OK) { + for (int j = start; j < i; j++) { + // 释放之前映射的内存 + unmap(j, 0x3ff); + } + printk( + "Driver Interface: remap memory:0x%08x(size: %d) failed\n", + in_physical_address, in_size); + return DRIVER_RESULT_OTHER_ERROR; + } + if (virtual_address == 0) { virtual_address = tmp; } + } + DriverRemappedMemory *remapped_memory = + kmalloc(sizeof(DriverRemappedMemory)); + remapped_memory->size = in_size; + remapped_memory->start = virtual_address; + list_add_tail(&remapped_memory->list, &in_driver->remapped_memory_lh); + *out_virtual_address = virtual_address; + return DRIVER_RESULT_OK; +} diff --git a/src/kernel/driver_manager.c b/src/kernel/driver_manager.c new file mode 100644 index 0000000..d0548a4 --- /dev/null +++ b/src/kernel/driver_manager.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include + +DriverManager *driver_managers[DRIVER_TYPE_MAX]; + +DriverResult register_driver_manager(DriverManager *driver_manager) { + + DriverManager *old_manager = driver_managers[driver_manager->type]; + if (old_manager != NULL) { + DRV_RESULT_DELIVER_CALL(unregister_driver_manager, old_manager); + } + + list_init(&driver_manager->dm_lh); + driver_managers[driver_manager->type] = driver_manager; + + DM_OPS_CALL(driver_manager, dm_load_hook, driver_manager); + return DRIVER_RESULT_OK; +} + +DriverResult unregister_driver_manager(DriverManager *driver_manager) { + DriverManager *old_manager = driver_managers[driver_manager->type]; + + if (old_manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; + DM_OPS_CALL(old_manager, dm_unload_hook, old_manager); + + driver_managers[driver_manager->type] = NULL; + + return DRIVER_RESULT_OK; +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 45861c9..5493b35 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -4,12 +4,19 @@ * @brief 内核主程序 * @date 2020-03 */ +#include "driver/video_dm.h" +#include +#include #include #include #include #include +#include #include +#include +#include #include +#include #include #include #include @@ -25,25 +32,31 @@ #include #include #include -#include -#include void idle(void *arg); struct task_s *task_idle; int main() { - platform_init(); + register_driver_manager(&device_driver_manager); + register_driver_manager(&bus_driver_manager); + register_device_manager(&interrupt_device_manager); + register_device_manager(&timer_device_manager); + register_device_manager(&video_device_manager); + + init_platform(); + platform_init_and_start_devices(); + init_task(); task_idle = thread_start("Idle", 1, idle, 0); - init_pci(); - io_sti(); + // init_pci(); + // io_sti(); printk("Memory Size:%dM\n", get_memory_size()); - init_vfs(); - do_initcalls(); - init_fs(); + // init_vfs(); + // do_initcalls(); + // init_fs(); - thread_start( - "NetworkRxPacketProcess", THREAD_DEFAULT_PRIO, net_process_pack, NULL); + // thread_start( + // "NetworkRxPacketProcess", THREAD_DEFAULT_PRIO, net_process_pack, NULL); // int ret = dhcp_main(default_net_dev); // while (ret == -4) { diff --git a/src/kernel/memory.c b/src/kernel/memory.c index 5e12c7d..c78bffc 100644 --- a/src/kernel/memory.c +++ b/src/kernel/memory.c @@ -109,24 +109,31 @@ void mmap_set(struct mmap *btmp, unsigned int bit_index, int value) { } } -unsigned long alloc_vaddr(size_t size) { - size = ((size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)); - if (!size) return 0; +int mmap_get(struct mmap *btmp, uint32_t bit_index) { + uint32_t byte_idx = bit_index / 8; + uint32_t bit_odd = bit_index % 8; + return (btmp->bits[byte_idx] & (1 << bit_odd)) != 0; +} + +MemoryResult alloc_vaddr(size_t in_size, uint32_t *out_vaddr) { + in_size = ((in_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)); + if (!in_size) return MEMORY_RESULT_INVALID_INPUT; - int pages = size / PAGE_SIZE; + uint32_t pages = in_size / PAGE_SIZE; /* 扫描获取请求的页数 */ int idx = mmap_search(&vir_page_mmap, pages); - if (idx == -1) return 0; + if (idx == -1) return MEMORY_RESULT_OUT_OF_MEMORY; int i; - /* 把已经扫描到的位置1,表明已经分配了 */ + /* 把已经扫描到的位设置为1,表明已经分配了 */ for (i = 0; i < pages; i++) { mmap_set(&vir_page_mmap, idx + i, 1); } /* 返还转换好的虚拟地址 */ - return KERN_VIR_MEM_BASE_ADDR + VIR_MEM_BASE_ADDR + idx * PAGE_SIZE; + *out_vaddr = KERN_VIR_MEM_BASE_ADDR + VIR_MEM_BASE_ADDR + idx * PAGE_SIZE; + return MEMORY_RESULT_OK; } // 默认对齐32字节 @@ -137,6 +144,7 @@ void *kmalloc(uint32_t size) { uint32_t break_cnt; // 要打碎成几块 void *new_address; + if (size == 0) { return NULL; } // 大于1024字节就用页 if (size >= 2048) { int pages = DIV_ROUND_UP(size, PAGE_SIZE); // 一共占多少个页 @@ -197,11 +205,11 @@ void *kmalloc(uint32_t size) { memory_manage->free_blocks[i].address = (uint32_t)new_address; new_address += break_size; // 设置size - memory_manage->free_blocks[i].size = break_size; + memory_manage->free_blocks[i].size = break_size; // 设置为可以分配 memory_manage->free_blocks[i].flags = MEMORY_BLOCK_FREE; // 设置为小块模式 - memory_manage->free_blocks[i].mode = MEMORY_BLOCK_MODE_SMALL; + memory_manage->free_blocks[i].mode = MEMORY_BLOCK_MODE_SMALL; break_cnt--; if (break_cnt <= 0) { break; } } @@ -253,3 +261,16 @@ int kfree(void *address) { return -1; // 失败 } + +void print_memory_result( + MemoryResult result, char *file, int line, char *func_with_args) { + + if (result == MEMORY_RESULT_OK) return; + printk("[At file %s line%d: %s]", file, line, func_with_args); + switch (result) { + RESULT_CASE_PRINT(MEMORY_RESULT_OK) + RESULT_CASE_PRINT(MEMORY_RESULT_INVALID_INPUT) + RESULT_CASE_PRINT(MEMORY_RESULT_OUT_OF_MEMORY) + RESULT_CASE_PRINT(MEMORY_RESULT_MEMORY_IS_USED) + } +} diff --git a/src/kernel/process.c b/src/kernel/process.c index 45bcf42..4da255a 100644 --- a/src/kernel/process.c +++ b/src/kernel/process.c @@ -7,6 +7,7 @@ */ #include #include +#include #include #include #include @@ -29,16 +30,18 @@ void start_process(void *entry) { struct task_s *cur = get_current_thread(); cur->kstack += sizeof(struct thread_stack); struct intr_stack *proc_stack = (struct intr_stack *)cur->kstack; - proc_stack->edi = proc_stack->esi = proc_stack->ebp = proc_stack->esp_dummy = 0; + proc_stack->edi = proc_stack->esi = proc_stack->ebp = + proc_stack->esp_dummy = 0; proc_stack->ebx = proc_stack->edx = proc_stack->ecx = proc_stack->eax = 0; proc_stack->gs = 0; proc_stack->ds = proc_stack->es = proc_stack->fs = SELECTOR_U_DATA; proc_stack->eip = function; proc_stack->cs = SELECTOR_U_CODE; - proc_stack->eflags = (1 << 1) | (1 << 9) | (0 << 12); - proc_stack->esp = - (void *)((uint32_t)thread_get_page(get_current_thread(), USER_STACK3_ADDR) + PAGE_SIZE - 4); - proc_stack->ss = SELECTOR_U_STACK; + proc_stack->eflags = (1 << 1) | (1 << 9) | (0 << 12); + proc_stack->esp = (void *)((uint32_t)thread_get_page( + get_current_thread(), USER_STACK3_ADDR) + + PAGE_SIZE - 4); + proc_stack->ss = SELECTOR_U_STACK; thread_intr_exit(proc_stack); } @@ -50,7 +53,9 @@ void start_process(void *entry) { void page_dir_activate(struct task_s *thread) { uint32_t pagedir_phy_addr = PDT_PHY_ADDR; - if (thread->pgdir != NULL) { pagedir_phy_addr = vir2phy((uint32_t)thread->pgdir); } + if (thread->pgdir != NULL) { + pagedir_phy_addr = vir2phy((uint32_t)thread->pgdir); + } write_cr3((uint32_t *)pagedir_phy_addr); } @@ -74,9 +79,10 @@ uint32_t *create_page_dir(void) { uint32_t *page_dir_vaddr = kernel_alloc_pages(1); if (page_dir_vaddr == NULL) { return NULL; } // 复制第0~511个与创建第1023个页目录表项 - memcpy((void *)(page_dir_vaddr + 0 * 4), (void *)(0xfffff000 + 0 * 4), 2048); + memcpy( + (void *)(page_dir_vaddr + 0 * 4), (void *)(0xfffff000 + 0 * 4), 2048); uint32_t new_page_dir_phy_addr = vir2phy((uint32_t)page_dir_vaddr); - page_dir_vaddr[1023] = new_page_dir_phy_addr | SIGN_USER | SIGN_RW | SIGN_P; + page_dir_vaddr[1023] = new_page_dir_phy_addr | SIGN_USER | SIGN_RW | SIGN_P; return page_dir_vaddr; } @@ -86,9 +92,11 @@ uint32_t *create_page_dir(void) { * @param user_prog 用户进程 */ void create_user_vaddr_mmap(struct task_s *user_prog) { - uint32_t pg_cnt = DIV_ROUND_UP((0xffcfffff - USER_START_ADDR) / PAGE_SIZE / 8, PAGE_SIZE); + uint32_t pg_cnt = + DIV_ROUND_UP((0xffcfffff - USER_START_ADDR) / PAGE_SIZE / 8, PAGE_SIZE); user_prog->vir_page_mmap.bits = kernel_alloc_pages(pg_cnt); - user_prog->vir_page_mmap.len = (0xffcfffff - USER_START_ADDR) / PAGE_SIZE / 8; + user_prog->vir_page_mmap.len = + (0xffcfffff - USER_START_ADDR) / PAGE_SIZE / 8; memset(user_prog->vir_page_mmap.bits, 0, user_prog->vir_page_mmap.len); } @@ -100,14 +108,19 @@ void create_user_vaddr_mmap(struct task_s *user_prog) { */ void process_excute(void *entry, struct program_struct *prog) { struct task_s *thread = kernel_alloc_pages(1); - struct prog_segment *p, *next; + struct prog_segment *p; init_thread(thread, prog->name.text, THREAD_DEFAULT_PRIO); create_user_vaddr_mmap(thread); thread_create(thread, start_process, entry); thread->pgdir = create_page_dir(); init_thread_memory_manage(thread); - list_for_each_owner_safe (p, next, &prog->seg_head, list) { - process_load_segment(thread, prog->inode, p->offset, p->filesz, p->memsz, p->vaddr); + list_for_each_owner (p, &prog->seg_head, list) { + MemoryResult result = process_load_segment( + thread, prog->inode, p->offset, p->filesz, p->memsz, p->vaddr); + if (result != MEMORY_RESULT_OK) { + printk("Load segment failed\n"); + return; + } } // 将该任务加入任务队列 @@ -128,16 +141,21 @@ void process_excute(void *entry, struct program_struct *prog) { * @param vaddr 段的虚拟地址 * @return int 成功为0,失败为-1 */ -int process_load_segment(struct task_s *thread, struct index_node *inode, unsigned long offset, - unsigned long filesz, unsigned long memsz, unsigned long vaddr) { +MemoryResult process_load_segment( + struct task_s *thread, struct index_node *inode, unsigned long offset, + unsigned long filesz, unsigned long memsz, unsigned long vaddr) { unsigned long size0 = PAGE_SIZE - (vaddr & 0xfff); unsigned long page_num = 1; if (memsz > size0) { page_num += DIV_ROUND_UP(memsz - size0, PAGE_SIZE); } + uint32_t *addr = kernel_alloc_pages(page_num); - int ret = thread_use_page(thread, vaddr, vir2phy((uint32_t)addr), page_num); - if (ret == -1) { return -1; } + MEMORY_RESULT_DELIVER_CALL( + thread_use_page, thread, vaddr, vir2phy((uint32_t)addr), page_num); + inode->f_ops.seek(inode, offset, 0); inode->f_ops.read(inode, (uint8_t *)(addr + (vaddr & 0xfff)), filesz); - if (memsz > filesz) { memset((void *)(addr + (vaddr & 0xfff) + filesz), 0, memsz - filesz); } - return 0; + if (memsz > filesz) { + memset((void *)(addr + (vaddr & 0xfff) + filesz), 0, memsz - filesz); + } + return MEMORY_RESULT_OK; } \ No newline at end of file diff --git a/src/lib/string.c b/src/lib/string.c index 3ab0033..62fbe89 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -7,6 +7,7 @@ #include #include +#include /** * @brief 初始化字符串 @@ -140,7 +141,7 @@ void *memset32(void *src, uint32_t value, uint32_t size) { void memcpy(void *dst_, const void *src_, uint32_t size) { - uint8_t *dst = dst_; + uint8_t *dst = dst_; const uint8_t *src = src_; while (size-- > 0) { *dst = *src; @@ -295,20 +296,20 @@ char *itoa16_align(char *str, int num) { char *p = str; char ch; int i; - //为0 + // 为0 if (num == 0) { *p++ = '0'; } else { // 4位4位的分解出来 - for (i = 28; i >= 0; i -= 4) { //从最高得4位开始 - ch = (num >> i) & 0xF; //取得4位 - ch += '0'; //大于0就+'0'变成ASICA的数字 - if (ch > '9') { //大于9就加上7变成ASICA的字母 + for (i = 28; i >= 0; i -= 4) { // 从最高得4位开始 + ch = (num >> i) & 0xF; // 取得4位 + ch += '0'; // 大于0就+'0'变成ASICA的数字 + if (ch > '9') { // 大于9就加上7变成ASICA的字母 ch += 7; } - *p++ = ch; //指针地址上记录下来。 + *p++ = ch; // 指针地址上记录下来。 } } - *p = 0; //最后在指针地址后加个0用于字符串结束 + *p = 0; // 最后在指针地址后加个0用于字符串结束 return str; } @@ -338,19 +339,22 @@ int strmet(const char *src, char *buf, char ch) { char *strstr(const char *haystack, const char *needle) { char *thaystack = (char *)haystack; char *tneedle = (char *)needle; - int i = 0; // thaystack 主串的元素下标位置,从下标0开始找,可以通过变量进行设置,从其他下标开始找! - int j = 0; // tneedle 子串的元素下标位置 + int i = + 0; // thaystack + // 主串的元素下标位置,从下标0开始找,可以通过变量进行设置,从其他下标开始找! + int j = 0; // tneedle 子串的元素下标位置 while (i <= strlen(thaystack) - 1 && j <= strlen(tneedle) - 1) { - //字符相等,则继续匹配下一个字符 + // 字符相等,则继续匹配下一个字符 if (thaystack[i] == tneedle[j]) { i++; j++; - } else { //在匹配过程中发现有一个字符和子串中的不等,马上回退到 下一个要匹配的位置 + } else { // 在匹配过程中发现有一个字符和子串中的不等,马上回退到 + // 下一个要匹配的位置 i = i - j + 1; j = 0; } } - //循环完了后j的值等于strlen(tneedle) 子串中的字符已经在主串中都连续匹配到了 + // 循环完了后j的值等于strlen(tneedle) 子串中的字符已经在主串中都连续匹配到了 if (j == strlen(tneedle)) { return thaystack + i - strlen(tneedle); } return NULL; @@ -380,7 +384,7 @@ const char *strpbrk(const char *str1, const char *str2) { const char *temp2 = str2; while (*temp1 != '\0') { - temp2 = str2; //将str2 指针从新指向在字符串的首地址 + temp2 = str2; // 将str2 指针从新指向在字符串的首地址 while (*temp2 != '\0') { if (*temp2 == *temp1) return temp1; else temp2++; diff --git a/src/network/tcp.c b/src/network/tcp.c index 301448e..4f5b309 100644 --- a/src/network/tcp.c +++ b/src/network/tcp.c @@ -1,3 +1,4 @@ +#include "driver/timer_dm.h" #include "kernel/list.h" #include "kernel/memory.h" #include "network/netpack.h" @@ -19,7 +20,8 @@ LIST_HEAD(tcp_lh); const int rmem_defualt_size = 32768; const int wmem_defualt_size = 16384; -uint16_t tcp_checksum(netc_t *netc, uint8_t dst_ip[4], uint8_t *buf, uint32_t length) { +uint16_t tcp_checksum( + netc_t *netc, uint8_t dst_ip[4], uint8_t *buf, uint32_t length) { int i; uint8_t src_ip[4]; uint32_t chksum = 0; @@ -48,22 +50,19 @@ int tcp_send_for_status_change(netc_t *netc, uint8_t *buf, int length) { netc_ip_send(netc, conn->dst_ip, 0, PROTOCOL_TCP, buf, length); conn->wait_ms = 600; - conn->timer = timer_alloc(); - timer_init(conn->timer, &conn->fifo, 0); - fifo_init(&conn->fifo, 2, conn->fifo_buf); - timer_settime(conn->timer, conn->wait_ms / 10); + timer_init(&conn->timer); + delay_ms_async(&conn->timer, conn->wait_ms); while (conn->status == status) { - if (fifo_status(&conn->fifo)) { - while (fifo_status(&conn->fifo)) - fifo_get(&conn->fifo); + if (!timer_is_timeout(&conn->timer)) { + while (!timer_is_timeout(&conn->timer)) + ; conn->wait_ms *= 2; if (conn->wait_ms >= 120000) { return -1; } netc_ip_send(netc, conn->dst_ip, 0, PROTOCOL_TCP, buf, length); - timer_settime(conn->timer, conn->wait_ms / 10); + delay_ms_async(&conn->timer, conn->wait_ms); } } - timer_free(conn->timer); - if (fifo_status(&conn->fifo)) fifo_get(&conn->fifo); + timer_init(&conn->timer); return 0; } @@ -74,40 +73,42 @@ int tcp_send(netc_t *netc, uint8_t *buf, int length) { memcpy(header, conn->header_buf, sizeof(tcp_header_t)); - header->seq = HOST2BE_DWORD(conn->seq); - header->ack = HOST2BE_DWORD(conn->ack); - header->flags = TCP_FLAG_PSH | TCP_FLAG_ACK; - header->ack = HOST2BE_DWORD(conn->ack); - header->window = HOST2BE_WORD(conn->rwin.size - conn->rwin.acked - conn->rwin.recved); + header->seq = HOST2BE_DWORD(conn->seq); + header->ack = HOST2BE_DWORD(conn->ack); + header->flags = TCP_FLAG_PSH | TCP_FLAG_ACK; + header->ack = HOST2BE_DWORD(conn->ack); + header->window = + HOST2BE_WORD(conn->rwin.size - conn->rwin.acked - conn->rwin.recved); header->urgent_pointer = 0; memcpy(sendbuf + sizeof(tcp_header_t), buf, length); header->checksum = 0; - header->checksum = HOST2BE_WORD(tcp_checksum(netc, conn->dst_ip, sendbuf, sizeof(tcp_header_t) + length)); + header->checksum = HOST2BE_WORD(tcp_checksum( + netc, conn->dst_ip, sendbuf, sizeof(tcp_header_t) + length)); conn->swin.unacked += length; conn->swin.sended -= length; - netc_ip_send(netc, conn->dst_ip, 0, PROTOCOL_TCP, sendbuf, sizeof(tcp_header_t) + length); + netc_ip_send( + netc, conn->dst_ip, 0, PROTOCOL_TCP, sendbuf, + sizeof(tcp_header_t) + length); conn->wait_ms = 600; - conn->timer = timer_alloc(); - timer_init(conn->timer, &conn->fifo, 0); - fifo_init(&conn->fifo, 2, conn->fifo_buf); - timer_settime(conn->timer, conn->wait_ms / 10); + timer_init(&conn->timer); + delay_ms_async(&conn->timer, conn->wait_ms); while (conn->swin.unacked) { - if (fifo_status(&conn->fifo)) { - while (fifo_status(&conn->fifo)) - fifo_get(&conn->fifo); + if (!timer_is_timeout(&conn->timer)) { + while (!timer_is_timeout(&conn->timer)) + ; conn->wait_ms *= 2; if (conn->wait_ms >= 120000) { return -1; } - netc_ip_send(netc, conn->dst_ip, 0, PROTOCOL_TCP, sendbuf, sizeof(tcp_header_t) + length); - timer_settime(conn->timer, conn->wait_ms / 10); + netc_ip_send( + netc, conn->dst_ip, 0, PROTOCOL_TCP, sendbuf, + sizeof(tcp_header_t) + length); + delay_ms_async(&conn->timer, conn->wait_ms); } } kfree(sendbuf); - timer_free(conn->timer); - if (fifo_status(&conn->fifo)) fifo_get(&conn->fifo); return 0; } @@ -117,27 +118,24 @@ int wait_for_status_change(netc_t *netc) { int i = 0; conn->wait_ms = 1000; - conn->timer = timer_alloc(); - timer_init(conn->timer, &conn->fifo, 0); - fifo_init(&conn->fifo, 2, conn->fifo_buf); - timer_settime(conn->timer, conn->wait_ms / 10); + timer_init(&conn->timer); + delay_ms_async(&conn->timer, conn->wait_ms); while (conn->status == status) { - if (fifo_status(&conn->fifo)) { - while (fifo_status(&conn->fifo)) - fifo_get(&conn->fifo); + if (!timer_is_timeout(&conn->timer)) { + while (!timer_is_timeout(&conn->timer)) + ; i++; if (i > 10) return -1; } } - timer_free(conn->timer); - if (fifo_status(&conn->fifo)) fifo_get(&conn->fifo); return 0; } void tcp_analyse_option(netc_t *netc, uint8_t *buf) { - int i = 0; - tcp_conn_t *conn = (tcp_conn_t *)netc->app_private; - uint8_t option_size = (((tcp_header_t *)buf)->offset >> 4) * 4 - sizeof(tcp_header_t); + int i = 0; + tcp_conn_t *conn = (tcp_conn_t *)netc->app_private; + uint8_t option_size = + (((tcp_header_t *)buf)->offset >> 4) * 4 - sizeof(tcp_header_t); buf += sizeof(tcp_header_t); while (i < option_size) { @@ -147,7 +145,8 @@ void tcp_analyse_option(netc_t *netc, uint8_t *buf) { case TCP_OPTION_NOP: break; case TCP_OPTION_MSS: - conn->mss = MIN(conn->mss, BE2HOST_WORD(*(uint16_t *)(buf + i + 2))); + conn->mss = + MIN(conn->mss, BE2HOST_WORD(*(uint16_t *)(buf + i + 2))); break; default: break; @@ -229,11 +228,13 @@ int tcp_ipv4_connect(netc_t *netc, uint8_t *ip, uint16_t dst_port) { header->checksum = 0; // 设置TCP Option最大分片大小(Maximum segment size) - conn->header_buf[sizeof(tcp_header_t) + 0] = TCP_OPTION_MSS; - conn->header_buf[sizeof(tcp_header_t) + 1] = 4; // 该Option长度为4字节 - *(uint16_t *)(conn->header_buf + sizeof(tcp_header_t) + 2) = HOST2BE_WORD(1460); + conn->header_buf[sizeof(tcp_header_t) + 0] = TCP_OPTION_MSS; + conn->header_buf[sizeof(tcp_header_t) + 1] = 4; // 该Option长度为4字节 + *(uint16_t *)(conn->header_buf + sizeof(tcp_header_t) + 2) = + HOST2BE_WORD(1460); - header->checksum = HOST2BE_WORD(tcp_checksum(netc, conn->dst_ip, conn->header_buf, tcp_length)); + header->checksum = HOST2BE_WORD( + tcp_checksum(netc, conn->dst_ip, conn->header_buf, tcp_length)); conn->status = TCP_STAT_SYN_SENT; @@ -243,7 +244,8 @@ int tcp_ipv4_connect(netc_t *netc, uint8_t *ip, uint16_t dst_port) { header->offset = (tcp_length / 4) << 4; if (conn->status == TCP_STAT_CLOSED) { kfree(conn->rwin.mem); - timer_free(conn->timer); + // Timer + // timer_free(conn->timer); kfree(conn); return -1; } @@ -257,8 +259,10 @@ int tcp_ipv4_connect(netc_t *netc, uint8_t *ip, uint16_t dst_port) { header->ack = HOST2BE_DWORD(conn->ack); header->flags = TCP_FLAG_ACK; header->checksum = 0; - header->checksum = HOST2BE_WORD(tcp_checksum(netc, conn->dst_ip, conn->header_buf, tcp_length)); - netc_ip_send(netc, conn->dst_ip, 0, PROTOCOL_TCP, conn->header_buf, tcp_length); + header->checksum = HOST2BE_WORD( + tcp_checksum(netc, conn->dst_ip, conn->header_buf, tcp_length)); + netc_ip_send( + netc, conn->dst_ip, 0, PROTOCOL_TCP, conn->header_buf, tcp_length); return 0; } @@ -284,7 +288,8 @@ int tcp_listen(netc_t *netc) { header->window = HOST2BE_WORD(rmem_defualt_size); header->urgent_pointer = 0; header->checksum = 0; - header->checksum = HOST2BE_WORD(tcp_checksum(netc, conn->dst_ip, conn->header_buf, tcp_length)); + header->checksum = HOST2BE_WORD( + tcp_checksum(netc, conn->dst_ip, conn->header_buf, tcp_length)); conn->seq += 1; tcp_send_for_status_change(netc, conn->header_buf, tcp_length); @@ -297,13 +302,15 @@ void tcp_ipv4_close(netc_t *netc) { tcp_conn_t *conn = (tcp_conn_t *)netc->app_private; header = (tcp_header_t *)conn->header_buf; - header->seq = HOST2BE_DWORD(conn->seq); - header->ack = HOST2BE_DWORD(conn->ack); - header->flags = TCP_FLAG_FIN | TCP_FLAG_ACK; - header->window = HOST2BE_WORD(conn->rwin.size - conn->rwin.recved - conn->rwin.acked); + header->seq = HOST2BE_DWORD(conn->seq); + header->ack = HOST2BE_DWORD(conn->ack); + header->flags = TCP_FLAG_FIN | TCP_FLAG_ACK; + header->window = + HOST2BE_WORD(conn->rwin.size - conn->rwin.recved - conn->rwin.acked); header->urgent_pointer = 0; header->checksum = 0; - header->checksum = HOST2BE_WORD(tcp_checksum(netc, conn->dst_ip, conn->header_buf, sizeof(tcp_header_t))); + header->checksum = HOST2BE_WORD(tcp_checksum( + netc, conn->dst_ip, conn->header_buf, sizeof(tcp_header_t))); conn->status = TCP_STAT_FIN_WAIT1; conn->seq += 1; @@ -317,25 +324,28 @@ void tcp_ipv4_close(netc_t *netc) { header->ack = HOST2BE_DWORD(conn->ack); header->flags = TCP_FLAG_ACK; header->checksum = 0; - header->checksum = - HOST2BE_WORD(tcp_checksum(netc, conn->dst_ip, conn->header_buf, sizeof(tcp_header_t))); + header->checksum = HOST2BE_WORD(tcp_checksum( + netc, conn->dst_ip, conn->header_buf, sizeof(tcp_header_t))); - netc_ip_send(netc, conn->dst_ip, 0, PROTOCOL_TCP, conn->header_buf, sizeof(tcp_header_t)); + netc_ip_send( + netc, conn->dst_ip, 0, PROTOCOL_TCP, conn->header_buf, + sizeof(tcp_header_t)); conn->wait_ms = 2 * TCP_MSL_MS; - timer_settime(conn->timer, conn->wait_ms / 10); - while (!fifo_status(&conn->fifo)) + + delay_ms_async(&conn->timer, conn->wait_ms); + while (!timer_is_timeout(&conn->timer)) ; - fifo_get(&conn->fifo); } end: kfree(conn->rwin.mem); - timer_free(conn->timer); kfree(conn); return; } -void tcp_recv(uint8_t *buf, uint16_t offset, uint16_t length, uint8_t *ip, uint8_t ip_len) { +void tcp_recv( + uint8_t *buf, uint16_t offset, uint16_t length, uint8_t *ip, + uint8_t ip_len) { netc_t *netc; tcp_header_t *tcp_head = (tcp_header_t *)(buf + offset); uint16_t chksum = tcp_head->checksum; @@ -350,7 +360,8 @@ void tcp_recv(uint8_t *buf, uint16_t offset, uint16_t length, uint8_t *ip, uint8 spin_lock(&tcp_lock); list_for_each_owner_safe (cur, next, &tcp_lh, list) { if (cur->src_port == dst_port) { - if ((cur->dst_port == src_port && memcmp(cur->dst_ip, ip, ip_len) == 0) || + if ((cur->dst_port == src_port && + memcmp(cur->dst_ip, ip, ip_len) == 0) || cur->status == TCP_STAT_LISTEN) { conn = cur; flag = 0; @@ -364,7 +375,10 @@ void tcp_recv(uint8_t *buf, uint16_t offset, uint16_t length, uint8_t *ip, uint8 netc = conn->netc; tcp_head->checksum = 0; - if (chksum != HOST2BE_WORD(tcp_checksum(netc, netc->dst_laddr, buf + offset, length))) { return; } + if (chksum != HOST2BE_WORD(tcp_checksum( + netc, netc->dst_laddr, buf + offset, length))) { + return; + } if (tcp_head->flags & TCP_FLAG_RST) { conn->status = TCP_STAT_CLOSED; } header = (tcp_header_t *)conn->header_buf; @@ -385,8 +399,9 @@ void tcp_recv(uint8_t *buf, uint16_t offset, uint16_t length, uint8_t *ip, uint8 break; case TCP_STAT_SYN_SENT: if (tcp_head->flags & TCP_FLAG_SYN) { - conn->swin.size = MIN(wmem_defualt_size, BE2HOST_WORD(tcp_head->window)); - conn->ack = r_seq; + conn->swin.size = + MIN(wmem_defualt_size, BE2HOST_WORD(tcp_head->window)); + conn->ack = r_seq; } if (tcp_head->flags & TCP_FLAG_ACK) { if (conn->seq == r_ack) { conn->status = TCP_STAT_ESTABLISHED; } @@ -406,13 +421,18 @@ void tcp_recv(uint8_t *buf, uint16_t offset, uint16_t length, uint8_t *ip, uint8 // printk("TCP seq=%04X, ack=%04X\n", r_seq, r_ack); if (len > 0) { if (conn->rwin.recved + len < conn->rwin.size) { - memcpy(conn->rwin.mem + conn->rwin.head + conn->rwin.acked + conn->rwin.recved, - buf + offset + head_len, len); + memcpy( + conn->rwin.mem + conn->rwin.head + conn->rwin.acked + + conn->rwin.recved, + buf + offset + head_len, len); } else { int tmp = conn->rwin.size - conn->rwin.recved; - memcpy(conn->rwin.mem + conn->rwin.head + conn->rwin.acked + conn->rwin.recved, - buf + offset + head_len, tmp); - memcpy(conn->rwin.mem, buf + offset + head_len + tmp, len - tmp); + memcpy( + conn->rwin.mem + conn->rwin.head + conn->rwin.acked + + conn->rwin.recved, + buf + offset + head_len, tmp); + memcpy( + conn->rwin.mem, buf + offset + head_len + tmp, len - tmp); } conn->rwin.recved += len; } @@ -427,37 +447,46 @@ void tcp_recv(uint8_t *buf, uint16_t offset, uint16_t length, uint8_t *ip, uint8 conn->swin.head = (conn->swin.head + tmp) % conn->swin.size; conn->swin.tail = (conn->swin.tail + tmp) % conn->swin.size; } - if ((add > 0 && list_empty(&net_rx_tcp_lh)) || tcp_head->flags & TCP_FLAG_PSH) { - header->seq = HOST2BE_DWORD(conn->seq); - header->ack = HOST2BE_DWORD(conn->ack + add); - header->flags = TCP_FLAG_ACK; - header->window = HOST2BE_WORD(conn->rwin.size - conn->rwin.recved); + if ((add > 0 && list_empty(&net_rx_tcp_lh)) || + tcp_head->flags & TCP_FLAG_PSH) { + header->seq = HOST2BE_DWORD(conn->seq); + header->ack = HOST2BE_DWORD(conn->ack + add); + header->flags = TCP_FLAG_ACK; + header->window = + HOST2BE_WORD(conn->rwin.size - conn->rwin.recved); header->urgent_pointer = 0; header->checksum = 0; - header->checksum = - HOST2BE_WORD(tcp_checksum(netc, conn->dst_ip, conn->header_buf, sizeof(tcp_header_t))); - conn->swin.head = (conn->swin.head + conn->rwin.unacked + add) % conn->swin.size; - conn->swin.tail = (conn->swin.tail + conn->rwin.unacked + add) % conn->swin.size; + header->checksum = HOST2BE_WORD(tcp_checksum( + netc, conn->dst_ip, conn->header_buf, + sizeof(tcp_header_t))); + conn->swin.head = (conn->swin.head + conn->rwin.unacked + add) % + conn->swin.size; + conn->swin.tail = (conn->swin.tail + conn->rwin.unacked + add) % + conn->swin.size; // 发送ACK包表示确认收到 conn->rwin.acked += conn->rwin.unacked + add; conn->rwin.recved -= conn->rwin.unacked + add; conn->rwin.unacked = 0; - netc_ip_send(netc, conn->dst_ip, 0, PROTOCOL_TCP, conn->header_buf, sizeof(tcp_header_t)); + netc_ip_send( + netc, conn->dst_ip, 0, PROTOCOL_TCP, conn->header_buf, + sizeof(tcp_header_t)); } else { conn->rwin.unacked += add; } } if (tcp_head->flags & TCP_FLAG_FIN) { - header->seq = HOST2BE_DWORD(conn->seq); - header->ack = HOST2BE_DWORD(conn->ack + len); - header->flags = TCP_FLAG_ACK; - header->window = HOST2BE_WORD(conn->rwin.size - conn->rwin.recved); + header->seq = HOST2BE_DWORD(conn->seq); + header->ack = HOST2BE_DWORD(conn->ack + len); + header->flags = TCP_FLAG_ACK; + header->window = HOST2BE_WORD(conn->rwin.size - conn->rwin.recved); header->urgent_pointer = 0; header->checksum = 0; header->flags |= TCP_FLAG_FIN; - header->checksum = - HOST2BE_WORD(tcp_checksum(netc, conn->dst_ip, conn->header_buf, sizeof(tcp_header_t))); - netc_ip_send(netc, conn->dst_ip, 0, PROTOCOL_TCP, conn->header_buf, sizeof(tcp_header_t)); + header->checksum = HOST2BE_WORD(tcp_checksum( + netc, conn->dst_ip, conn->header_buf, sizeof(tcp_header_t))); + netc_ip_send( + netc, conn->dst_ip, 0, PROTOCOL_TCP, conn->header_buf, + sizeof(tcp_header_t)); if (conn->swin.unacked == 0) { conn->status = TCP_STAT_LAST_ACK; } else { @@ -471,12 +500,16 @@ void tcp_recv(uint8_t *buf, uint16_t offset, uint16_t length, uint8_t *ip, uint8 conn->status = TCP_STAT_FIN_WAIT2; kfree(conn->swin.mem); conn->ack = r_seq; - if (tcp_head->flags & TCP_FLAG_FIN) { conn->status = TCP_STAT_TIME_WAIT; } + if (tcp_head->flags & TCP_FLAG_FIN) { + conn->status = TCP_STAT_TIME_WAIT; + } } } break; case TCP_STAT_FIN_WAIT2: - if (tcp_head->flags & TCP_FLAG_FIN) { conn->status = TCP_STAT_TIME_WAIT; } + if (tcp_head->flags & TCP_FLAG_FIN) { + conn->status = TCP_STAT_TIME_WAIT; + } if (len == 0) { len = 1; } break; case TCP_STAT_LAST_ACK: @@ -519,7 +552,8 @@ int tcp_read(netc_t *netc, uint8_t *buf, uint32_t length) { int i = 0; while (conn->rwin.acked == 0) { i++; - delay(1); + // TODO: Delay + // delay(1); if (i == 1000) { break; } } diff --git a/tools/imagetool b/tools/imagetool index eeb6ba6..e413271 160000 --- a/tools/imagetool +++ b/tools/imagetool @@ -1 +1 @@ -Subproject commit eeb6ba602d5272ecfefe0c2a1d2fad55a8a0d61a +Subproject commit e41327101e70d4ce1ea4f49a123a7845b92a61eb From 0f9b5bc88a18a18073d054f8c4c9fcddf296f348 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 8 Dec 2024 00:56:51 +0800 Subject: [PATCH 003/158] update --- install_grub.py | 10 +++++----- src/arch/x86/kernel/platform.c | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/install_grub.py b/install_grub.py index 1657d18..a438b5c 100644 --- a/install_grub.py +++ b/install_grub.py @@ -15,7 +15,6 @@ grub_cfg_path = 'grub.cfg' prefix_path = "/boot/grub/" grub_mkimage_path = "grub-mkimage" -grub_dir_path = "/usr/lib/grub/" default_mods =\ "minicmd normal gzio gcry_crc verifiers terminal \ priority_queue gettext extcmd datetime crypto bufio boot \ @@ -45,7 +44,7 @@ def create_grub_directory(disk_image_path, disk_dir, grub_cfg_path): run_command(f"{imagetool_path} {disk_image_path} mkdir /p0/boot/grub/", hide=True) run_command(f"{imagetool_path} {disk_image_path} copy {grub_cfg_path} /p0/boot/grub/grub.cfg") -def install_grub(disk_image_path, platform, fs, mods): +def install_grub(disk_image_path, grub_dir_path, platform, fs, mods): # 检查 hd0.img 是否存在 flag = True if os.path.isfile(disk_image_path): @@ -96,11 +95,12 @@ def install_grub(disk_image_path, platform, fs, mods): if __name__ == "__main__": parser = argparse.ArgumentParser(description="安装GRUB到磁盘镜像") parser.add_argument("--image", help="磁盘映像路径", default=hd_img_path) - parser.add_argument("--platform", help="目标平台") - parser.add_argument("--fs", help="文件系统") + parser.add_argument("--platform", help="目标平台", required=True) + parser.add_argument("--fs", help="文件系统", required=True) parser.add_argument("--mods", help="要额外附加的模块", default=default_mods) args = parser.parse_args() + grub_dir_path = "/usr/lib/grub/" if os.name == 'nt': print("检测到为Windows,请输入grub路径:") path = input() @@ -109,4 +109,4 @@ def install_grub(disk_image_path, platform, fs, mods): grub_dir_path = path grub_mkimage_path = path + grub_mkimage_path - install_grub(args.image, args.platform, args.fs, args.mods) + install_grub(args.image, grub_dir_path, args.platform, args.fs, args.mods) diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index 7e95f7d..1c99daa 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -28,12 +28,11 @@ BusDriver platform_bus = { void init_platform() { init_descriptor(); - // init_video(); - // init_console(); init_memory(); register_bus_driver(&platform_driver, &platform_bus); read_features(); + register_vesa_display(); register_pic(); register_apic(); From 0b498003e6bfdb84d0c8469d66286c371555b843 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 10 Dec 2024 00:29:54 +0800 Subject: [PATCH 004/158] =?UTF-8?q?[WIP]=E5=BB=BA=E7=AB=8B=E6=80=BB?= =?UTF-8?q?=E7=BA=BF=E9=A9=B1=E5=8A=A8=E6=A1=86=E6=9E=B6=EF=BC=9B=E9=87=8D?= =?UTF-8?q?=E5=86=99=E9=83=A8=E5=88=86pci=E6=80=BB=E7=BA=BF=E5=8F=8A?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E5=99=A8=E9=A9=B1=E5=8A=A8=EF=BC=9B=E4=BF=AE?= =?UTF-8?q?=E6=94=B9wait=5Fqueue=EF=BC=9B=E6=96=B0=E5=A2=9E=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8=E4=BE=9D=E8=B5=96=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/8259a.c | 3 + src/arch/x86/drivers/Makefile | 3 +- src/arch/x86/drivers/apic.c | 13 +- src/arch/x86/drivers/ide.c | 173 ++++++---- src/arch/x86/drivers/network/rtl8139.c | 98 +++--- src/arch/x86/drivers/pci.c | 435 ++++++++++++++++--------- src/arch/x86/drivers/pit.c | 4 +- src/arch/x86/drivers/usb/hci/uhci.c | 8 +- src/arch/x86/drivers/vesa_display.c | 3 + src/arch/x86/include/drivers/pci.h | 117 +++++-- src/arch/x86/kernel/descriptor.c | 2 +- src/arch/x86/kernel/page.c | 8 +- src/arch/x86/kernel/platform.c | 20 +- src/driver/Makefile | 3 +- src/driver/bus_dm.c | 39 +++ src/driver/interrupt_dm.c | 4 +- src/driver/timer_dm.c | 3 +- src/driver/video_dm.c | 3 +- src/include/driver/bus_dm.h | 21 ++ src/include/kernel/bus_driver.h | 27 +- src/include/kernel/device.h | 3 +- src/include/kernel/device_driver.h | 2 + src/include/kernel/driver.h | 9 +- src/include/kernel/driver_dependency.h | 27 ++ src/include/kernel/driver_interface.h | 6 +- src/include/kernel/platform.h | 2 + src/kernel/Makefile | 1 + src/kernel/bus_driver.c | 68 +++- src/kernel/device.c | 5 +- src/kernel/device_driver.c | 2 + src/kernel/device_manager.c | 1 - src/kernel/driver.c | 16 +- src/kernel/driver_dependency.c | 43 +++ src/kernel/driver_interface.c | 36 +- src/kernel/initcall.c | 2 +- src/kernel/main.c | 2 +- src/kernel/wait_queue.c | 36 +- 37 files changed, 891 insertions(+), 357 deletions(-) create mode 100644 src/driver/bus_dm.c create mode 100644 src/include/driver/bus_dm.h create mode 100644 src/include/kernel/driver_dependency.h create mode 100644 src/kernel/driver_dependency.c diff --git a/src/arch/x86/drivers/8259a.c b/src/arch/x86/drivers/8259a.c index 287f4fd..4691c56 100644 --- a/src/arch/x86/drivers/8259a.c +++ b/src/arch/x86/drivers/8259a.c @@ -19,6 +19,7 @@ #include #include #include +#include #include DriverResult pic_init(Device *device); @@ -49,6 +50,7 @@ Driver pic_driver = {.name = STRING_INIT("PIC")}; DeviceDriver pic_device_driver = { .name = STRING_INIT("PIC Driver"), .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, + .bus = &platform_bus, .priority = DRIVER_PRIORITY_BASIC, .state = DRIVER_STATE_UNREGISTERED, .ops = &pic_device_driver_ops, @@ -68,6 +70,7 @@ InterruptDevice pic_interrupt_device = { }; void register_pic(void) { + register_driver(&pic_driver); register_device_driver(&pic_driver, &pic_device_driver); register_interrupt_device( &pic_device_driver, &pic_device, &pic_interrupt_device); diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index 78b02e2..6b8a832 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -4,15 +4,14 @@ SRC += acpi.c SRC += apic.c SRC += cpufreq.c SRC += disk.c +SRC += pci.c SRC += dma.c SRC += ide.c SRC += keyboard.c SRC += mouse.c SRC += msr.c -SRC += pci.c SRC += pit.c SRC += smbios.c -SRC += video.c SRC += vesa_display.c SRC += network/ SRC += sound/ diff --git a/src/arch/x86/drivers/apic.c b/src/arch/x86/drivers/apic.c index 9c56485..05599df 100644 --- a/src/arch/x86/drivers/apic.c +++ b/src/arch/x86/drivers/apic.c @@ -40,6 +40,8 @@ volatile struct ioapic { #include #include #include +#include + DriverResult apic_init(Device *device); DriverResult apic_start(Device *device); DriverResult apic_stop(Device *device); @@ -117,6 +119,7 @@ Driver apic_driver = {.name = STRING_INIT("APIC")}; DeviceDriver apic_device_driver = { .name = STRING_INIT("APIC"), + .bus = &platform_bus, .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, .priority = DRIVER_PRIORITY_BASIC, .state = DRIVER_STATE_UNREGISTERED, @@ -135,6 +138,7 @@ InterruptDevice apic_interrupt_device = { DeviceDriver apic_timer_device_driver = { .name = STRING_INIT("APIC Timer"), + .bus = &platform_bus, .type = DEVICE_TYPE_TIMER, .priority = DRIVER_PRIORITY_BASIC, .state = DRIVER_STATE_UNREGISTERED, @@ -172,6 +176,7 @@ void io_apic_write(uint32_t reg, uint32_t data) { } DriverResult register_apic(void) { + register_driver(&apic_driver); register_device_driver(&apic_driver, &apic_device_driver); register_device_driver(&apic_driver, &apic_timer_device_driver); register_interrupt_device( @@ -191,12 +196,14 @@ DriverResult apic_driver_init(struct DeviceDriver *driver) { apic_info.apic_base = 0xfee00000; apic_info.apic_base_high = low >> 12; + uint32_t tmp; DRV_RESULT_PRINT_CALL( driver_remap_memory, &apic_driver, apic_info.apic_base, 0x3ff, - (uint32_t *)&apic_info.lapic_mmio); + &tmp); + apic_info.lapic_mmio = (uint32_t *)tmp; DRV_RESULT_PRINT_CALL( - driver_remap_memory, &apic_driver, 0xfec00000, 0xfff00, - (uint32_t *)apic_info.ioapic); + driver_remap_memory, &apic_driver, 0xfec00000, 0xfff00, &tmp); + apic_info.ioapic = (struct ioapic *)tmp; read_msr(X2APIC_ID_MSR, &apic_info.apic_id, &apic_info.apic_id_high); apic_info.version = (lapic_read(APIC_Ver) & 0xff) | diff --git a/src/arch/x86/drivers/ide.c b/src/arch/x86/drivers/ide.c index 9f0babd..a22acdb 100644 --- a/src/arch/x86/drivers/ide.c +++ b/src/arch/x86/drivers/ide.c @@ -253,23 +253,30 @@ typedef struct _device_extension_s { static status_t ide_enter(driver_t *drv_obj); static status_t ide_exit(driver_t *drv_obj); -status_t ide_read(struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); -status_t ide_write(struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); -void ide0_handler(device_t *devobj, int irq); -void ide1_handler(device_t *devobj, int irq); -void ide_reset_driver(struct ide_channel *channel); -void ide_select_device(device_extension_t *devext, char mode, unsigned char head); -int ide_pulling(struct ide_channel *channel, unsigned int advanced_check); -int ide_wait(device_extension_t *devext); -void ide_select_addressing_mode(device_extension_t *devext, unsigned int lba, unsigned char *mode, - unsigned char *head, unsigned char *data); -void ide_select_sector(device_extension_t *devext, unsigned char mode, unsigned char *lba, - unsigned int count); -void ide_select_cmd(unsigned char rw, unsigned char mode, unsigned char *cmd); -int AtaTypeTransfer(device_extension_t *devext, unsigned char rw, unsigned int lba, unsigned int count, - void *buf); -int PioDataTransfer(device_extension_t *devext, unsigned char rw, unsigned char mode, unsigned char *buf, - unsigned short count); +status_t ide_read( + struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); +status_t ide_write( + struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); +void ide0_handler(device_t *devobj, int irq); +void ide1_handler(device_t *devobj, int irq); +void ide_reset_driver(struct ide_channel *channel); +void ide_select_device( + device_extension_t *devext, char mode, unsigned char head); +int ide_pulling(struct ide_channel *channel, unsigned int advanced_check); +int ide_wait(device_extension_t *devext); +void ide_select_addressing_mode( + device_extension_t *devext, unsigned int lba, unsigned char *mode, + unsigned char *head, unsigned char *data); +void ide_select_sector( + device_extension_t *devext, unsigned char mode, unsigned char *lba, + unsigned int count); +void ide_select_cmd(unsigned char rw, unsigned char mode, unsigned char *cmd); +int AtaTypeTransfer( + device_extension_t *devext, unsigned char rw, unsigned int lba, + unsigned int count, void *buf); +int PioDataTransfer( + device_extension_t *devext, unsigned char rw, unsigned char mode, + unsigned char *buf, unsigned short count); uint8_t disk_count; struct ide_channel channels[2]; @@ -290,7 +297,8 @@ driver_func_t ide_driver = { #define DRV_NAME "General HardDisk Driver(IDE)" #define DEV_NAME "hd" -int ide_read_identity_info(device_extension_t *devext, struct ide_channel *channel) { +int ide_read_identity_info( + device_extension_t *devext, struct ide_channel *channel) { devext->info = kmalloc(sizeof(struct ide_identify_info)); if (devext->info == NULL) { printk("kmalloc for ide device info falied!\n"); @@ -300,7 +308,8 @@ int ide_read_identity_info(device_extension_t *devext, struct ide_channel *chann ide_reset_driver(devext->channel); ide_select_device(devext, 0, 0); - // while (!(io_in8(ATA_REG_STATUS(channel)) & ATA_STATUS_READY)) __asm__("nop\n\t"); + // while (!(io_in8(ATA_REG_STATUS(channel)) & ATA_STATUS_READY)) + // __asm__("nop\n\t"); IDE_SEND_CMD(channel, ATA_CMD_IDENTIFY); // 获取硬盘识别信息 ide_wait(devext); @@ -314,7 +323,9 @@ int ide_read_identity_info(device_extension_t *devext, struct ide_channel *chann return -1; } printk("\n"); - port_insw(ATA_REG_DATA(devext->channel), (unsigned int)devext->info, sizeof(struct ide_identify_info)); + port_insw( + ATA_REG_DATA(devext->channel), (unsigned int)devext->info, + sizeof(struct ide_identify_info)); return 0; } @@ -324,26 +335,26 @@ static status_t ide_enter(driver_t *drv_obj) { device_t *devobj; device_extension_t *devext; - struct pci_device *device = pci_get_device_ByClass(IDE_CLASSCODE, IDE_SUBCLASS); - if (device == NULL) { return NODEV; } - - // 使用兼容模式(如支持) - if (device->prog_if & 0x01) { - if (device->prog_if & 0x02) { - pci_write8(device->bus, device->dev, device->function, PCI_REG_PROGIF, device->prog_if | 0x01); - device->prog_if = pci_read8(device->bus, device->dev, device->function, PCI_REG_PROGIF); - } else { - return UNSUPPORT; - } - } - if (device->prog_if & 0x04) { - if (device->prog_if & 0x08) { - pci_write8(device->bus, device->dev, device->function, PCI_REG_PROGIF, device->prog_if | 0x04); - device->prog_if = pci_read8(device->bus, device->dev, device->function, PCI_REG_PROGIF); - } else { - return UNSUPPORT; - } - } + // struct pci_device *device = pci_get_device_ByClass(IDE_CLASSCODE, + // IDE_SUBCLASS); if (device == NULL) { return NODEV; } + + // // 使用兼容模式(如支持) + // if (device->prog_if & 0x01) { + // if (device->prog_if & 0x02) { + // pci_write8(device->bus, device->dev, device->function, + // PCI_REG_PROGIF, device->prog_if | 0x01); device->prog_if = + // pci_read8(device->bus, device->dev, device->function, PCI_REG_PROGIF); } + // else { return UNSUPPORT; + // } + // } + // if (device->prog_if & 0x04) { + // if (device->prog_if & 0x08) { + // pci_write8(device->bus, device->dev, device->function, + // PCI_REG_PROGIF, device->prog_if | 0x04); device->prog_if = + // pci_read8(device->bus, device->dev, device->function, PCI_REG_PROGIF); } + // else { return UNSUPPORT; + // } + // } #ifdef IDE_DMA_MODE if (!(device->prog_if & 0x80)) // 是否支持DMA { @@ -358,11 +369,12 @@ static status_t ide_enter(driver_t *drv_obj) { channels[1].channel_num = 1; channels[1].irq_num = IDE1_IRQ; channels[0].selected_drive = channels[1].selected_drive = 0; - channels[0].bmr = device->bar[4].base_addr; - channels[1].bmr = channels[0].bmr; + // channels[0].bmr = + // device->bar[4].base_addr; channels[1].bmr + // = channels[0].bmr; - pci_enable_bus_mastering(device); - pci_enable_io_space(device); + // pci_enable_bus_mastering(device); + // pci_enable_io_space(device); while (i < IDE_MAX_CHANNEL_NUM) { channel = &channels[i]; @@ -370,7 +382,9 @@ static status_t ide_enter(driver_t *drv_obj) { while (j < IDE_MAX_DEV_PER_CNL) { char devname[3] = {0}; sprintf(devname, "%s%d", DEV_NAME, i * 2 + j); - device_create(drv_obj, sizeof(device_extension_t), devname, DEV_STORAGE, &devobj); + device_create( + drv_obj, sizeof(device_extension_t), devname, DEV_STORAGE, + &devobj); devext = devobj->device_extension; if (devext == NULL) { device_delete(devobj); @@ -384,7 +398,7 @@ static status_t ide_enter(driver_t *drv_obj) { device_register_irq(devobj, IDE1_IRQ, ide1_handler); } - devext->device = device; + // devext->device = device; devext->channel = channel; devext->drive_num = j; devext->type = IDE_ATA; @@ -400,17 +414,21 @@ static status_t ide_enter(driver_t *drv_obj) { wait_queue_init(devext->wqm); devext->PRD = kmalloc(sizeof(struct physicalRegionDescriptor) * 64); - io_out32(IDE_BM_REG_PRDT_ADDR(channel), vir2phy((uint32_t)devext->PRD)); + io_out32( + IDE_BM_REG_PRDT_ADDR(channel), vir2phy((uint32_t)devext->PRD)); io_out8(IDE_BM_REG_STATUS(channel), 1 << (j + 5)); - devext->command_sets = (int)((devext->info->cmd_set1 << 16) + devext->info->cmd_set0); + devext->command_sets = + (int)((devext->info->cmd_set1 << 16) + devext->info->cmd_set0); if (devext->command_sets & (1 << 26)) { - devext->size = ((unsigned int)devext->info->lba48sectors[1] << 16) + - (unsigned int)devext->info->lba48sectors[0]; + devext->size = + ((unsigned int)devext->info->lba48sectors[1] << 16) + + (unsigned int)devext->info->lba48sectors[0]; } else { - devext->size = ((unsigned int)devext->info->lba28sectors[1] << 16) + - (unsigned int)devext->info->lba28sectors[0]; + devext->size = + ((unsigned int)devext->info->lba28sectors[1] << 16) + + (unsigned int)devext->info->lba28sectors[0]; } devext->size /= 2; @@ -439,10 +457,13 @@ static status_t ide_exit(driver_t *drv_obj) { return SUCCUESS; } -status_t ide_read(struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size) { +status_t ide_read( + struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size) { device_extension_t *devext = dev->device_extension; wait_queue_add(devext->wqm, 0); - if (devext->wqm->list_head.next->next != &devext->wqm->list_head) { thread_block(TASK_BLOCKED); } + if (devext->wqm->list_head.next->next != &devext->wqm->list_head) { + thread_block(TASK_BLOCKED); + } int length = DIV_ROUND_UP(size, SECTOR_SIZE); char *tmp_buffer = kmalloc(length * SECTOR_SIZE); AtaTypeTransfer(devext, IDE_READ, offset, length, tmp_buffer); @@ -452,10 +473,13 @@ status_t ide_read(struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t s return SUCCUESS; } -status_t ide_write(struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size) { +status_t ide_write( + struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size) { device_extension_t *devext = dev->device_extension; wait_queue_add(devext->wqm, 0); - if (devext->wqm->list_head.next->next != &devext->wqm->list_head) { thread_block(TASK_BLOCKED); } + if (devext->wqm->list_head.next->next != &devext->wqm->list_head) { + thread_block(TASK_BLOCKED); + } int length = DIV_ROUND_UP(size, SECTOR_SIZE); uint8_t *tmp_buffer; if (size % SECTOR_SIZE == 0) { @@ -493,8 +517,11 @@ void ide_reset_driver(struct ide_channel *channel) { io_out8(ATA_REG_CTL(channel), ctrl); } -void ide_select_device(device_extension_t *devext, char mode, unsigned char head) { - io_out8(ATA_REG_DEVICE(devext->channel), (0xa0 | 0x40 | devext->drive_num << 4 | head)); +void ide_select_device( + device_extension_t *devext, char mode, unsigned char head) { + io_out8( + ATA_REG_DEVICE(devext->channel), + (0xa0 | 0x40 | devext->drive_num << 4 | head)); devext->channel->selected_drive = devext->drive_num; } @@ -527,8 +554,9 @@ int ide_wait(device_extension_t *devext) { return 0; } -void ide_select_addressing_mode(device_extension_t *devext, unsigned int lba, unsigned char *mode, - unsigned char *head, unsigned char *data) { +void ide_select_addressing_mode( + device_extension_t *devext, unsigned int lba, unsigned char *mode, + unsigned char *head, unsigned char *data) { unsigned short cyl; unsigned char sector; if (lba >= 0x10000000 && devext->capabilities & 0x200) { @@ -563,8 +591,9 @@ void ide_select_addressing_mode(device_extension_t *devext, unsigned int lba, un } } -void ide_select_sector(device_extension_t *devext, unsigned char mode, unsigned char *lba, - unsigned int count) { +void ide_select_sector( + device_extension_t *devext, unsigned char mode, unsigned char *lba, + unsigned int count) { struct ide_channel *channel = devext->channel; /* 如果是LBA48就要写入24高端字节 */ @@ -609,8 +638,9 @@ void ide_select_cmd(unsigned char rw, unsigned char mode, unsigned char *cmd) { #endif } -int PioDataTransfer(device_extension_t *devext, unsigned char rw, unsigned char mode, unsigned char *buf, - unsigned short count) { +int PioDataTransfer( + device_extension_t *devext, unsigned char rw, unsigned char mode, + unsigned char *buf, unsigned short count) { short i; unsigned char error; if (rw == IDE_READ) { @@ -638,14 +668,17 @@ int PioDataTransfer(device_extension_t *devext, unsigned char rw, unsigned char // printk("write success! "); } /* 刷新写缓冲区 */ - io_out8(ATA_REG_CMD(devext->channel), mode > 1 ? ATA_CMD_CACHE_FLUSH_EXT : ATA_CMD_CACHE_FLUSH); + io_out8( + ATA_REG_CMD(devext->channel), + mode > 1 ? ATA_CMD_CACHE_FLUSH_EXT : ATA_CMD_CACHE_FLUSH); ide_pulling(devext->channel, 0); } return 0; } -int AtaTypeTransfer(device_extension_t *devext, unsigned char rw, unsigned int lba, unsigned int count, - void *buf) { +int AtaTypeTransfer( + device_extension_t *devext, unsigned char rw, unsigned int lba, + unsigned int count, void *buf) { unsigned char mode; /* 0: CHS, 1:LBA28, 2: LBA48 */ unsigned char dma; /* 0: No DMA, 1: DMA */ @@ -696,7 +729,7 @@ int AtaTypeTransfer(device_extension_t *devext, unsigned char rw, unsigned int l uint32_t status = io_in8(IDE_BM_REG_STATUS(channel)); io_out8(IDE_BM_REG_STATUS(channel), status | 0x06); #else - dma = 0; + dma = 0; #endif /* 选择寻址模式 */ @@ -738,7 +771,9 @@ int AtaTypeTransfer(device_extension_t *devext, unsigned char rw, unsigned int l io_out8(IDE_BM_REG_CMD(channel), tmp & 0xfe); } else { /* PIO模式数据传输 */ - if ((err = PioDataTransfer(devext, rw, mode, _buf, todo))) { return err; } + if ((err = PioDataTransfer(devext, rw, mode, _buf, todo))) { + return err; + } _buf += todo * SECTOR_SIZE; done += todo; } diff --git a/src/arch/x86/drivers/network/rtl8139.c b/src/arch/x86/drivers/network/rtl8139.c index ebc6b9a..dfa8193 100644 --- a/src/arch/x86/drivers/network/rtl8139.c +++ b/src/arch/x86/drivers/network/rtl8139.c @@ -29,9 +29,10 @@ #define CHIP_HAS_LWAKE 0x01 -#define IMR_ALL \ - RTL8139_IMR_SERR | RTL8139_IMR_TimeOut | RTL8139_IMR_LenChg | RTL8139_IMR_FOVW | RTL8139_IMR_TER | \ - RTL8139_IMR_TOK | RTL8139_IMR_RER | RTL8139_IMR_ROK +#define IMR_ALL \ + RTL8139_IMR_SERR | RTL8139_IMR_TimeOut | RTL8139_IMR_LenChg | \ + RTL8139_IMR_FOVW | RTL8139_IMR_TER | RTL8139_IMR_TOK | \ + RTL8139_IMR_RER | RTL8139_IMR_ROK #define RXFTH_NONE RTL8139_RCR_RXFTH(0x07) #define RBLEN_64K 0x03 @@ -48,9 +49,12 @@ static status_t rtl8139_enter(driver_t *drv_obj); static status_t rtl8139_exit(driver_t *drv_obj); static status_t rtl8139_open(struct _device_s *dev); static status_t rtl8139_close(struct _device_s *dev); -static status_t rtl8139_write(struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); -static status_t rtl8139_read(struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); -static status_t rtl8139_ioctl(struct _device_s *dev, uint32_t func_num, uint32_t value); +static status_t rtl8139_write( + struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); +static status_t rtl8139_read( + struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); +static status_t rtl8139_ioctl( + struct _device_s *dev, uint32_t func_num, uint32_t value); driver_func_t rtl8139_driver = { .driver_enter = rtl8139_enter, @@ -114,11 +118,14 @@ void rtl8139_handler(device_t *devobj, int irq) { int i; // printk("[RTL8139]Status:%#0x\t", status); - io_out16(devext->io_base + RTL8139_ISR, - status & ~(RTL8139_ISR_FOVW | RTL8139_ISR_RXOVW | RTL8139_ISR_ROK | RTL8139_ISR_TER)); + io_out16( + devext->io_base + RTL8139_ISR, + status & ~(RTL8139_ISR_FOVW | RTL8139_ISR_RXOVW | RTL8139_ISR_ROK | + RTL8139_ISR_TER)); if (status & RTL8139_ISR_TOK) { - // if (!wait_queue_empty(devext->wqm)) { wait_queue_wakeup_all(devext->wqm); } - // printk("idx_w:%d idx_done:%d+1\n", devext->tx_idx_w, devext->tx_idx_done); + // if (!wait_queue_empty(devext->wqm)) { + // wait_queue_wakeup_all(devext->wqm); } printk("idx_w:%d + // idx_done:%d+1\n", devext->tx_idx_w, devext->tx_idx_done); devext->tx_idx_done = (devext->tx_idx_done + 1) % TX_DESC_NR; io_out16(devext->io_base + RTL8139_ISR, RTL8139_ISR_TOK); } @@ -130,10 +137,13 @@ void rtl8139_handler(device_t *devobj, int irq) { rx_status = LE2HOST_DWORD(*(uint32_t *)(devext->rx_buffer + i)); length = (rx_status >> 16) - 4; i += 4; - if (length >= sizeof(eth_frame_t) && (rx_status & RTL8139_RX_STAT_ROK)) { + if (length >= sizeof(eth_frame_t) && + (rx_status & RTL8139_RX_STAT_ROK)) { uint8_t *buffer = kmalloc(length); if (i + length >= RTL8139_RECV_BUF_SIZE) { - memcpy(buffer, devext->rx_buffer + i, RTL8139_RECV_BUF_SIZE - i); + memcpy( + buffer, devext->rx_buffer + i, + RTL8139_RECV_BUF_SIZE - i); i = RTL8139_RECV_BUF_SIZE - i; memcpy(buffer + i, devext->rx_buffer + i, length - i); } else { @@ -141,11 +151,12 @@ void rtl8139_handler(device_t *devobj, int irq) { } net_rx_raw_pack(ETH_FRAME, buffer, length); } else { - printk("[RTL8139]RX Error: status %04x,size %04x, cur %04x\n", rx_status, length + 4, - devext->rx_offset); + printk( + "[RTL8139]RX Error: status %04x,size %04x, cur %04x\n", + rx_status, length + 4, devext->rx_offset); } - devext->rx_offset = - (devext->rx_offset + length + 8 + 3) & ~3; // +8:4字节CRC和4字节包头;+3:4字节对齐用 + devext->rx_offset = (devext->rx_offset + length + 8 + 3) & + ~3; // +8:4字节CRC和4字节包头;+3:4字节对齐用 devext->rx_offset %= RTL8139_RECV_BUF_SIZE; io_out16(devext->io_base + RTL8139_CAPR, devext->rx_offset - 0x10); io_out16(devext->io_base + RTL8139_ISR, RTL8139_ISR_ROK); @@ -161,19 +172,21 @@ static status_t rtl8139_enter(driver_t *drv_obj) { device_extension_t *devext; int i; - device_create(drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_ETH_NET, &devobj); + device_create( + drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_ETH_NET, &devobj); devext = devobj->device_extension; - devext->device = pci_get_device_ById(RTL8139_VENDOR_ID, RTL8139_DEVICE_ID); + // devext->device = pci_get_device_ById(RTL8139_VENDOR_ID, + // RTL8139_DEVICE_ID); if (devext->device == NULL) { printk(COLOR_YELLOW "\n[RTL8139]Cannot find device!\n"); device_delete(devobj); return NODEV; } - pci_enable_bus_mastering(devext->device); - devext->io_base = pci_device_get_io_addr(devext->device); - devext->irq = devext->device->irqline; + // pci_enable_bus_mastering(devext->device); + // devext->io_base = pci_device_get_io_addr(devext->device); + devext->irq = devext->device->irqline; // 初始化RTL8139 io_out8(devext->io_base + RTL8139_CONFIG1, 0x00); // 通电 @@ -200,8 +213,10 @@ static status_t rtl8139_enter(driver_t *drv_obj) { for (i = 0; i < 6; i++) { devext->mac_addr[i] = io_in8(devext->io_base + RTL8139_IDRN(i)); } - printk("[RTL8139]MAC Address:%02x:%02x:%02x:%02x:%02x:%02x\n", devext->mac_addr[0], devext->mac_addr[1], - devext->mac_addr[2], devext->mac_addr[3], devext->mac_addr[4], devext->mac_addr[5]); + printk( + "[RTL8139]MAC Address:%02x:%02x:%02x:%02x:%02x:%02x\n", + devext->mac_addr[0], devext->mac_addr[1], devext->mac_addr[2], + devext->mac_addr[3], devext->mac_addr[4], devext->mac_addr[5]); io_out8(devext->io_base + RTL8139_9346CR, 0xc0); // Unlock @@ -223,10 +238,14 @@ static status_t rtl8139_enter(driver_t *drv_obj) { io_out16(devext->io_base + RTL8139_BMCR, 0x3100); io_out8(devext->io_base + RTL8139_MSR, 0x40); - io_out32(devext->io_base + RTL8139_RCR, RXFTH_NONE | RBLEN | RTL8139_RCR_MXDMA(0x07) | RTL8139_RCR_AER | - RTL8139_RCR_AR | RTL8139_RCR_WRAP | RTL8139_RCR_AB | - RTL8139_RCR_AM | RTL8139_RCR_APM | RTL8139_RCR_AAP); - io_out32(devext->io_base + RTL8139_TCR, RTL8139_TCR_MXDMA(0x07) | RTL8139_TCR_TXRR(2)); + io_out32( + devext->io_base + RTL8139_RCR, + RXFTH_NONE | RBLEN | RTL8139_RCR_MXDMA(0x07) | RTL8139_RCR_AER | + RTL8139_RCR_AR | RTL8139_RCR_WRAP | RTL8139_RCR_AB | + RTL8139_RCR_AM | RTL8139_RCR_APM | RTL8139_RCR_AAP); + io_out32( + devext->io_base + RTL8139_TCR, + RTL8139_TCR_MXDMA(0x07) | RTL8139_TCR_TXRR(2)); io_out32(devext->io_base + RTL8139_MARN(0), 0xffffffff); io_out32(devext->io_base + RTL8139_MARN(4), 0xffffffff); @@ -240,7 +259,9 @@ static status_t rtl8139_enter(driver_t *drv_obj) { wait_queue_init(devext->wqm); wait_queue_init(devext->rqm); - io_out8(devext->io_base + RTL8139_CR, RTL8139_CR_RE | RTL8139_CR_TE); // 允许接收和发送 + io_out8( + devext->io_base + RTL8139_CR, + RTL8139_CR_RE | RTL8139_CR_TE); // 允许接收和发送 for (i = 0; i < TX_DESC_NR; i++) { io_out32(devext->io_base + RTL8139_TSADN(i), devext->tx_buffer_phy[i]); io_in32(devext->io_base + RTL8139_TSADN(i)); @@ -263,29 +284,31 @@ static status_t rtl8139_open(struct _device_s *dev) { return SUCCUESS; } -static status_t rtl8139_read(struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size) { +static status_t rtl8139_read( + struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size) { device_extension_t *devext = dev->device_extension; wait_queue_t *rq; struct read_request_s *rreq; - // rq = wait_queue_add(devext->rqm, sizeof(struct read_request_s)); - // rreq = (struct read_request_s *)rq->private_data; - // rreq->buffer = buf; - // rreq->length = size; + // rq = wait_queue_add(devext->rqm, sizeof(struct + // read_request_s)); rreq = (struct read_request_s + // *)rq->private_data; rreq->buffer = buf; rreq->length = size; // thread_block(TASK_BLOCKED); return SUCCUESS; } -static status_t rtl8139_write(struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size) { +static status_t rtl8139_write( + struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size) { device_extension_t *devext = dev->device_extension; wait_queue_t *wq; uint32_t idx; if (size > ETH_MAX_FRAME_SIZE) { return FAILED; } - // printk(" idx_w:%d idx_done:%d\n", devext->tx_idx_w, devext->tx_idx_done); - // while ((io_in32(devext->io_base + RTL8139_TSDN(devext->tx_idx_w)) & RTL8139_TSR_OWN)) + // printk(" idx_w:%d idx_done:%d\n", devext->tx_idx_w, + // devext->tx_idx_done); while ((io_in32(devext->io_base + + // RTL8139_TSDN(devext->tx_idx_w)) & RTL8139_TSR_OWN)) // ; while ((devext->tx_idx_w + 1) % TX_DESC_NR == devext->tx_idx_done) {} idx = devext->tx_idx_w; @@ -297,7 +320,8 @@ static status_t rtl8139_write(struct _device_s *dev, uint8_t *buf, uint32_t offs return SUCCUESS; } -static status_t rtl8139_ioctl(struct _device_s *dev, uint32_t func_num, uint32_t value) { +static status_t rtl8139_ioctl( + struct _device_s *dev, uint32_t func_num, uint32_t value) { int i; device_extension_t *devext = dev->device_extension; diff --git a/src/arch/x86/drivers/pci.c b/src/arch/x86/drivers/pci.c index a27f557..61186e6 100644 --- a/src/arch/x86/drivers/pci.c +++ b/src/arch/x86/drivers/pci.c @@ -5,29 +5,36 @@ * @version 0.1 * @date 2020-07 */ +#include "kernel/wait_queue.h" +#include #include #include +#include +#include +#include #include +#include +#include #include -struct pci_device pci_devices[PCI_MAX_DEVICE]; - -void init_pci() { - int i, j, k; - - printk("device id\tvendor id\theader " - "type\tclasscode\tsubclass\tprogif\trevision id\n"); - for (i = 0; i < PCI_MAX_DEVICE; i++) { - pci_devices[i].status = PCI_DEVICE_STATUS_INVALID; - } - for (i = 0; i < PCI_MAX_BUS; i++) { - for (j = 0; j < PCI_MAX_DEV; j++) { - for (k = 0; k < PCI_MAX_FUNC; k++) { - pci_scan_device(i, j, k); - } - } - } -} +// struct pci_device pci_devices[PCI_MAX_DEVICE]; + +// void init_pci() { +// int i, j, k; + +// printk("device id\tvendor id\theader " +// "type\tclasscode\tsubclass\tprogif\trevision id\n"); +// for (i = 0; i < PCI_MAX_DEVICE; i++) { +// pci_devices[i].status = PCI_DEVICE_STATUS_INVALID; +// } +// for (i = 0; i < PCI_MAX_BUS; i++) { +// for (j = 0; j < PCI_MAX_DEV; j++) { +// for (k = 0; k < PCI_MAX_FUNC; k++) { +// pci_scan_device(i, j, k); +// } +// } +// } +// } PCI_READ(8, uint8_t) PCI_READ(16, uint16_t) @@ -42,89 +49,44 @@ PCI_WRITE_DEVICE(8, uint8_t) PCI_WRITE_DEVICE(16, uint16_t) PCI_WRITE_DEVICE(32, uint32_t) -void pci_scan_device(uint8_t bus, uint8_t device, uint8_t function) { - uint32_t value = pci_read32(bus, device, function, 0); - uint16_t vendorID = value & 0xffff; - uint16_t deviceID = value >> 16; - if (vendorID == 0xffff) { return; } - value = pci_read32(bus, device, function, 0x0c); - uint8_t header_type = value >> 16; - value = pci_read32(bus, device, function, 8); - uint32_t classcode = value >> 8; - uint8_t revisionID = value & 0xff; - - struct pci_device *dev = pci_alloc_device(); - if (dev == NULL) { return; } - pci_device_init( - dev, bus, device, function, vendorID, deviceID, classcode, revisionID, - header_type); - - if (header_type == 0x00) { - int bar; - for (bar = 0; bar < PCI_MAX_BAR; bar++) { - value = pci_read32(bus, device, function, PCI_BAR(bar)); - pci_write32(bus, device, function, PCI_BAR(bar), 0xffffffff); - uint32_t len = pci_read32(bus, device, function, PCI_BAR(bar)); - pci_write32(bus, device, function, PCI_BAR(bar), value); - - if (len != 0 && len != 0xffffffff) { - pci_bar_init(&dev->bar[bar], value, len); - } - } - } - - value = pci_read32(bus, device, function, 0x3c) & 0xffff; - if ((value & 0xff) > 0 && (value & 0xff) < 32) { - dev->irqline = value & 0xff; - dev->irqpin = value >> 8; - } - - printk( - "%#06x\t\t%#06x\t\t%#04x\t\t%#04x\t\t%#04x\t\t%#04x\t%#04x\n", deviceID, - vendorID, header_type & (uint8_t)(~0x80), dev->classcode, dev->subclass, - dev->prog_if, revisionID); -} - -struct pci_device *pci_get_device_ById(uint16_t vendorID, uint16_t deviceID) { - int i; - struct pci_device *device; - - for (i = 0; i < PCI_MAX_DEVICE; i++) { - device = &pci_devices[i]; - if (device->vendorID == vendorID && device->deviceID == deviceID) { - return device; - } - } - return NULL; -} - -struct pci_device *pci_get_device_ByClassFull( - uint8_t classcode, uint8_t subclass, uint8_t progif) { - int i; - struct pci_device *device; - - for (i = 0; i < PCI_MAX_DEVICE; i++) { - device = &pci_devices[i]; - if (device->classcode == classcode && device->subclass == subclass && - device->prog_if == progif) { - return device; - } - } - return NULL; -} - -struct pci_device *pci_get_device_ByClass(uint8_t classcode, uint8_t subclass) { - int i; - struct pci_device *device; - - for (i = 0; i < PCI_MAX_DEVICE; i++) { - device = &pci_devices[i]; - if (device->classcode == classcode && device->subclass == subclass) { - return device; - } - } - return NULL; -} +// struct pci_device *pci_get_device_ById(uint16_t vendorID, uint16_t deviceID) +// { int i; struct pci_device *device; + +// for (i = 0; i < PCI_MAX_DEVICE; i++) { +// device = &pci_devices[i]; +// if (device->vendorID == vendorID && device->deviceID == deviceID) { +// return device; +// } +// } +// return NULL; +// } + +// struct pci_device *pci_get_device_ByClassFull( +// uint8_t classcode, uint8_t subclass, uint8_t progif) { +// int i; +// struct pci_device *device; + +// for (i = 0; i < PCI_MAX_DEVICE; i++) { +// device = &pci_devices[i]; +// if (device->classcode == classcode && device->subclass == subclass && +// device->prog_if == progif) { +// return device; +// } +// } +// return NULL; +// } + +// struct pci_device *pci_get_device_ByClass(uint8_t classcode, uint8_t +// subclass) { int i; struct pci_device *device; + +// for (i = 0; i < PCI_MAX_DEVICE; i++) { +// device = &pci_devices[i]; +// if (device->classcode == classcode && device->subclass == subclass) { +// return device; +// } +// } +// return NULL; +// } void pci_enable_bus_mastering(struct pci_device *device) { uint32_t value = @@ -147,17 +109,169 @@ void pci_enable_mem_space(struct pci_device *device) { pci_write32(device->bus, device->dev, device->function, 0x04, value); } -uint32_t pci_get_device_connected(void) { - int i; - struct pci_device *device; +void get_pci_device_info( + PciDevice *dev, uint8_t bus, uint8_t device, uint8_t func, + uint16_t vendorID, uint16_t deviceID, uint32_t classcode, + uint8_t revisionID, uint8_t multifunction) { + int i; + + dev->bus_num = bus; + dev->dev_num = device; + dev->function_num = func; + dev->vendorID = vendorID; + dev->deviceID = deviceID; + dev->classcode = classcode >> 16; + dev->subclass = (classcode & 0xff00) >> 8; + dev->prog_if = classcode & 0xff; + dev->revisionID = revisionID; + dev->multifunction = multifunction; + for (i = 0; i < PCI_MAX_BAR; i++) { - device = &pci_devices[i]; - if (device->status != PCI_DEVICE_STATUS_USING) { break; } + dev->bar[i].type = PCI_BAR_TYPE_INVALID; } - return i; + dev->irqline = -1; +} + +uint32_t pci_device_get_mem_addr(struct pci_device *dev) { + int i; + + for (i = 0; i < PCI_MAX_BAR; i++) { + if (dev->bar[i].type == PCI_BAR_TYPE_MEM) { + return dev->bar[i].base_addr; + } + } + return -1; } -struct pci_device *pci_alloc_device(void) { +uint32_t pci_device_get_io_addr(struct pci_device *dev) { + int i; + + for (i = 0; i < PCI_MAX_BAR; i++) { + if (dev->bar[i].type == PCI_BAR_TYPE_IO) { + return dev->bar[i].base_addr; + } + } + return -1; +} + +// --------new-------- +#include +#include +#include +#include +#include + +PciDevice pci_devices[PCI_MAX_DEVICE]; + +DriverResult pci_device_init(Device *device); + +DeviceDriverOps pci_driver_ops = { + .register_driver_hook = NULL, + .unregister_driver_hook = NULL, +}; +DeviceOps pci_device_ops = { + .init = pci_device_init, + .start = NULL, + .stop = NULL, + .destroy = NULL, + .status = NULL, +}; +BusDriverOps pci_bus_driver_ops = { + .register_bus_hook = NULL, + .unregister_bus_hook = NULL, +}; +BusOps pci_bus_ops = { + .register_device_hook = NULL, + .unregister_device_hook = NULL, +}; +BusControllerDeviceOps pci_controller_ops = { + .probe = NULL, +}; + +DriverDependency pci_dependencies[] = { + { + .in_type = DRIVER_DEPENDENCY_TYPE_BUS, + .dependency_in_bus = {BUS_TYPE_PLATFORM, 0}, + .out_bus = NULL, + }, +}; +Driver pci_driver = { + .name = STRING_INIT("pci driver"), + .dependency_count = sizeof(pci_dependencies) / sizeof(DriverDependency), + .dependencies = pci_dependencies, +}; +DeviceDriver pci_device_driver = { + .name = STRING_INIT("pci device driver"), + .bus = NULL, + .type = DEVICE_TYPE_BUS_CONTROLLER, + .state = DRIVER_STATE_UNREGISTERED, + .private_data_size = 0, + .ops = &pci_driver_ops, +}; +Device pci_device = { + .name = STRING_INIT("pci controller"), + .state = DEVICE_STATE_UNREGISTERED, + .private_data_size = 0, + .ops = &pci_device_ops, +}; +BusDriver pci_bus_driver = { + .name = STRING_INIT("pci"), + .driver_type = DRIVER_TYPE_BUS_DRIVER, + .bus_type = BUS_TYPE_PCI, + .state = DRIVER_STATE_UNREGISTERED, + .private_data_size = 0, + .ops = &pci_bus_driver_ops, +}; +BusControllerDevice pci_bus_controller_device = { + .device = &pci_device, + .bus_driver = &pci_bus_driver, + .bus_controller_ops = &pci_controller_ops, +}; + +DriverResult pci_device_init(Device *device) { + int i; + for (i = 0; i < PCI_MAX_DEVICE; i++) { + pci_devices[i].status = PCI_DEVICE_STATUS_INVALID; + } + wait_queue_wakeup_all(&bus_wqm[BUS_TYPE_PCI]); + return DRIVER_RESULT_OK; +} + +DriverResult pci_probe(Device *device) { + int i, j, k; + bool flag; + // printk("device id\tvendor id\theader " + // "type\tclasscode\tsubclass\tprogif\trevision id\n"); + for (i = 0; i < PCI_MAX_BUS; i++) { + Bus *bus = kmalloc(sizeof(Bus)); + bus->ops = &pci_bus_ops; + flag = false; + for (j = 0; j < PCI_MAX_DEV; j++) { + for (k = 0; k < PCI_MAX_FUNC; k++) { + DriverResult result = pci_scan_device(bus, i, j, k); + if (result == DRIVER_RESULT_DEVICE_NOT_EXIST) { + continue; + } else if (result == DRIVER_RESULT_OK) { + flag = true; + } else if (result == DRIVER_RESULT_NULL_POINTER) { + print_error( + "pci_probe: pci device(%d:%d:%d) alloc failed!\n", i, j, + k); + } + } + } + if (flag) { + // 如果该总线下有设备则注册总线 + register_bus(&pci_bus_driver, &pci_device, bus); + } else { + // 如果没有设备则释放内存 + kfree(bus); + } + } + return DRIVER_RESULT_OK; +} + +PciDevice *pci_alloc_device(void) { int i; for (i = 0; i < PCI_MAX_DEVICE; i++) { @@ -169,7 +283,17 @@ struct pci_device *pci_alloc_device(void) { return NULL; } -int pci_free_device(struct pci_device *dev) { +uint32_t pci_get_device_connected(void) { + int i; + PciDevice *device; + for (i = 0; i < PCI_MAX_BAR; i++) { + device = &pci_devices[i]; + if (device->status != PCI_DEVICE_STATUS_USING) { break; } + } + return i; +} + +int pci_free_device(PciDevice *dev) { int i; for (i = 0; i < PCI_MAX_DEVICE; i++) { @@ -181,30 +305,7 @@ int pci_free_device(struct pci_device *dev) { return -1; } -void pci_device_init( - struct pci_device *dev, uint8_t bus, uint8_t device, uint8_t func, - uint16_t vendorID, uint16_t deviceID, uint32_t classcode, - uint8_t revisionID, uint8_t multifunction) { - int i; - - dev->bus = bus; - dev->dev = device; - dev->function = func; - dev->vendorID = vendorID; - dev->deviceID = deviceID; - dev->classcode = classcode >> 16; - dev->subclass = (classcode & 0xff00) >> 8; - dev->prog_if = classcode & 0xff; - dev->revisionID = revisionID; - dev->multifunction = multifunction; - - for (i = 0; i < PCI_MAX_BAR; i++) { - dev->bar[i].type = PCI_BAR_TYPE_INVALID; - } - dev->irqline = -1; -} - -void pci_bar_init(struct pci_device_bar *bar, uint32_t addr, uint32_t len) { +void get_pci_bar_info(PciDeviceBar *bar, uint32_t addr, uint32_t len) { if (addr == 0xffffffff) { addr = 0; } if (addr & 1) // I/O内存 { @@ -218,24 +319,62 @@ void pci_bar_init(struct pci_device_bar *bar, uint32_t addr, uint32_t len) { } } -uint32_t pci_device_get_mem_addr(struct pci_device *dev) { - int i; +DriverResult pci_scan_device( + Bus *bus, uint8_t bus_num, uint8_t device_num, uint8_t function_num) { + uint32_t value = pci_read32(bus_num, device_num, function_num, 0); + uint16_t vendorID = value & 0xffff; + uint16_t deviceID = value >> 16; + if (vendorID == 0xffff) { return DRIVER_RESULT_DEVICE_NOT_EXIST; } + value = pci_read32(bus_num, device_num, function_num, 0x0c); + uint8_t header_type = value >> 16; + value = pci_read32(bus_num, device_num, function_num, 8); + uint32_t classcode = value >> 8; + uint8_t revisionID = value & 0xff; - for (i = 0; i < PCI_MAX_BAR; i++) { - if (dev->bar[i].type == PCI_BAR_TYPE_MEM) { - return dev->bar[i].base_addr; - } - } - return -1; -} + PciDevice *pci_device = pci_alloc_device(); + if (pci_device == NULL) { return DRIVER_RESULT_NULL_POINTER; } + pci_device->device = NULL; + get_pci_device_info( + pci_device, bus_num, device_num, function_num, vendorID, deviceID, + classcode, revisionID, header_type); -uint32_t pci_device_get_io_addr(struct pci_device *dev) { - int i; + if (header_type == 0x00) { + int bar; + for (bar = 0; bar < PCI_MAX_BAR; bar++) { + value = pci_read32(bus_num, device_num, function_num, PCI_BAR(bar)); + pci_write32( + bus_num, device_num, function_num, PCI_BAR(bar), 0xffffffff); + uint32_t len = + pci_read32(bus_num, device_num, function_num, PCI_BAR(bar)); + pci_write32(bus_num, device_num, function_num, PCI_BAR(bar), value); - for (i = 0; i < PCI_MAX_BAR; i++) { - if (dev->bar[i].type == PCI_BAR_TYPE_IO) { - return dev->bar[i].base_addr; + if (len != 0 && len != 0xffffffff) { + get_pci_bar_info(&pci_device->bar[bar], value, len); + } } } - return -1; + + value = pci_read32(bus_num, device_num, function_num, 0x3c) & 0xffff; + if ((value & 0xff) > 0 && (value & 0xff) < 32) { + pci_device->irqline = value & 0xff; + pci_device->irqpin = value >> 8; + } + + // printk( + // "%#06x\t\t%#06x\t\t%#04x\t\t%#04x\t\t%#04x\t\t%#04x\t%#04x\n", deviceID, + // vendorID, header_type & (uint8_t)(~0x80), dev->classcode, dev->subclass, + // dev->prog_if, revisionID); + return DRIVER_RESULT_OK; } + +static __init void pci_driver_entry(void) { + register_driver(&pci_driver); + pci_device_driver.bus = pci_dependencies[0].out_bus; + register_device_driver(&pci_driver, &pci_device_driver); + register_bus_driver(&pci_driver, &pci_bus_driver); + register_bus_controller_device( + &pci_device_driver, &pci_bus_driver, &pci_device, + &pci_bus_controller_device); +} + +driver_initcall(pci_driver_entry); diff --git a/src/arch/x86/drivers/pit.c b/src/arch/x86/drivers/pit.c index cb1046a..6cf5d97 100644 --- a/src/arch/x86/drivers/pit.c +++ b/src/arch/x86/drivers/pit.c @@ -16,11 +16,11 @@ #include #include - // ---------new--------- #include #include #include +#include #include #include @@ -55,6 +55,7 @@ DeviceIrq pit_irq = { Driver pit_driver; DeviceDriver pit_device_driver = { .name = STRING_INIT("PIT"), + .bus = &platform_bus, .type = DEVICE_TYPE_TIMER, .priority = DRIVER_PRIORITY_BASIC, .state = DRIVER_STATE_UNREGISTERED, @@ -77,6 +78,7 @@ TimerDevice pit_timer_device = { }; void register_pit() { + register_driver(&pit_driver); register_device_driver(&pit_driver, &pit_device_driver); register_timer_device(&pit_device_driver, &pit_device, &pit_timer_device); } diff --git a/src/arch/x86/drivers/usb/hci/uhci.c b/src/arch/x86/drivers/usb/hci/uhci.c index a220808..55fb6a9 100644 --- a/src/arch/x86/drivers/usb/hci/uhci.c +++ b/src/arch/x86/drivers/usb/hci/uhci.c @@ -91,8 +91,8 @@ static status_t uhci_enter(driver_t *drv_obj) { device_create(drv_obj, sizeof(uhci_t), DEV_NAME, DEV_USB, &devobj); devext = devobj->device_extension; - devext->device = - pci_get_device_ByClassFull(UHCI_CLASSID, UHCI_SUBCLASSID, UHCI_PROGIF); + // devext->device = + // pci_get_device_ByClassFull(UHCI_CLASSID, UHCI_SUBCLASSID, UHCI_PROGIF); if (devext->device == NULL) { printk(COLOR_YELLOW "\n[UHCI]Cannot find UHCI controller!\n"); device_delete(devobj); @@ -102,8 +102,8 @@ static status_t uhci_enter(driver_t *drv_obj) { devext->io_base = devext->device->bar[4].base_addr & 0xfffffff0; - pci_enable_bus_mastering(devext->device); - pci_enable_io_space(devext->device); + // pci_enable_bus_mastering(devext->device); + // pci_enable_io_space(devext->device); uhci_reset(devext); uint16_t intr = io_in16(devext->io_base + UHCI_REG_USBINTR); diff --git a/src/arch/x86/drivers/vesa_display.c b/src/arch/x86/drivers/vesa_display.c index ca0457f..37df353 100644 --- a/src/arch/x86/drivers/vesa_display.c +++ b/src/arch/x86/drivers/vesa_display.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,7 @@ Driver vesa_display_driver = { }; DeviceDriver vesa_display_device_driver = { .name = STRING_INIT("vesa display device driver"), + .bus = &platform_bus, .type = DEVICE_TYPE_VIDEO, .priority = DRIVER_PRIORITY_BASIC, .state = DRIVER_STATE_UNREGISTERED, @@ -46,6 +48,7 @@ VideoDevice vesa_display_video_device = { }; void register_vesa_display(void) { + register_driver(&vesa_display_driver); register_device_driver(&vesa_display_driver, &vesa_display_device_driver); register_video_device( &vesa_display_device_driver, &vesa_display_device, diff --git a/src/arch/x86/include/drivers/pci.h b/src/arch/x86/include/drivers/pci.h index 5119e4c..e789b98 100644 --- a/src/arch/x86/include/drivers/pci.h +++ b/src/arch/x86/include/drivers/pci.h @@ -30,31 +30,36 @@ #define PCI_MAX_FUNC 8 #define PCI_MAX_DEVICE 256 -#define PCI_SEL_REG(bus, device, function, offset) \ - { \ - uint32_t addr_reg; \ - addr_reg = (1 << 31) | (bus << 16) | (device << 11) | (func << 8) | (offset & 0xfc); \ - io_out32(PCI_CONFIG_ADDR, addr_reg); \ +#define PCI_SEL_REG(bus, device, function, offset) \ + { \ + uint32_t addr_reg; \ + addr_reg = (1 << 31) | (bus << 16) | (device << 11) | (func << 8) | \ + (offset & 0xfc); \ + io_out32(PCI_CONFIG_ADDR, addr_reg); \ } -#define PCI_READ(size, type) \ - type pci_read##size(uint8_t bus, uint8_t device, uint8_t func, uint8_t offset) { \ - PCI_SEL_REG(bus, device, func, offset); \ - return io_in##size(PCI_CONFIG_DATA); \ +#define PCI_READ(size, type) \ + type pci_read##size( \ + uint8_t bus, uint8_t device, uint8_t func, uint8_t offset) { \ + PCI_SEL_REG(bus, device, func, offset); \ + return io_in##size(PCI_CONFIG_DATA); \ } -#define PCI_WRITE(size, type) \ - void pci_write##size(uint8_t bus, uint8_t device, uint8_t func, uint8_t offset, type value) { \ - PCI_SEL_REG(bus, device, func, offset); \ - io_out##size(PCI_CONFIG_DATA, value); \ +#define PCI_WRITE(size, type) \ + void pci_write##size( \ + uint8_t bus, uint8_t device, uint8_t func, uint8_t offset, \ + type value) { \ + PCI_SEL_REG(bus, device, func, offset); \ + io_out##size(PCI_CONFIG_DATA, value); \ } #define PCI_READ_DEVICE(size, type) \ type pci_device_read##size(struct pci_device *dev, uint8_t offset) { \ return pci_read##size(dev->bus, dev->dev, dev->function, offset); \ } -#define PCI_WRITE_DEVICE(size, type) \ - void pci_device_write##size(struct pci_device *dev, uint8_t offset, type value) { \ - pci_write##size(dev->bus, dev->dev, dev->function, offset, value); \ +#define PCI_WRITE_DEVICE(size, type) \ + void pci_device_write##size( \ + struct pci_device *dev, uint8_t offset, type value) { \ + pci_write##size(dev->bus, dev->dev, dev->function, offset, value); \ } struct pci_device_bar { @@ -92,32 +97,78 @@ struct pci_device { uint8_t pci_read8(uint8_t bus, uint8_t device, uint8_t func, uint8_t offset); uint16_t pci_read16(uint8_t bus, uint8_t device, uint8_t func, uint8_t offset); uint32_t pci_read32(uint8_t bus, uint8_t device, uint8_t func, uint8_t offset); -void pci_write8(uint8_t bus, uint8_t device, uint8_t func, uint8_t offset, uint8_t value); -void pci_write16(uint8_t bus, uint8_t device, uint8_t func, uint8_t offset, uint16_t value); -void pci_write32(uint8_t bus, uint8_t device, uint8_t func, uint8_t offset, uint32_t value); +void pci_write8( + uint8_t bus, uint8_t device, uint8_t func, uint8_t offset, uint8_t value); +void pci_write16( + uint8_t bus, uint8_t device, uint8_t func, uint8_t offset, uint16_t value); +void pci_write32( + uint8_t bus, uint8_t device, uint8_t func, uint8_t offset, uint32_t value); uint8_t pci_device_read8(struct pci_device *dev, uint8_t offset); uint16_t pci_device_read16(struct pci_device *dev, uint8_t offset); uint32_t pci_device_read32(struct pci_device *dev, uint8_t offset); -void pci_device_write8(struct pci_device *dev, uint8_t offset, uint8_t value); -void pci_device_write16(struct pci_device *dev, uint8_t offset, uint16_t value); -void pci_device_write32(struct pci_device *dev, uint8_t offset, uint32_t value); +void pci_device_write8(struct pci_device *dev, uint8_t offset, uint8_t value); +void pci_device_write16(struct pci_device *dev, uint8_t offset, uint16_t value); +void pci_device_write32(struct pci_device *dev, uint8_t offset, uint32_t value); void init_pci(); -void pci_scan_device(uint8_t bus, uint8_t device, uint8_t function); +// void pci_scan_device(uint8_t bus, uint8_t device, uint8_t function); struct pci_device *pci_get_device_ById(uint16_t vendorID, uint16_t deviceID); struct pci_device *pci_get_device_ByClass(uint8_t classcode, uint8_t subclass); -struct pci_device *pci_get_device_ByClassFull(uint8_t classcode, uint8_t subclass, uint8_t progif); -void pci_enable_bus_mastering(struct pci_device *device); -void pci_enable_io_space(struct pci_device *device); -void pci_enable_mem_space(struct pci_device *device); -uint32_t pci_get_device_connected(void); -struct pci_device *pci_alloc_device(void); -int pci_free_device(struct pci_device *dev); -void pci_device_init(struct pci_device *dev, uint8_t bus, uint8_t device, uint8_t func, uint16_t vendorID, - uint16_t deviceID, uint32_t classcode, uint8_t revisionID, uint8_t multifunction); -void pci_bar_init(struct pci_device_bar *bar, uint32_t addr, uint32_t len); +struct pci_device *pci_get_device_ByClassFull( + uint8_t classcode, uint8_t subclass, uint8_t progif); +void pci_enable_bus_mastering(struct pci_device *device); +void pci_enable_io_space(struct pci_device *device); +void pci_enable_mem_space(struct pci_device *device); +uint32_t pci_get_device_connected(void); +// struct pci_device *pci_alloc_device(void); +// int pci_free_device(struct pci_device *dev); +// void get_pci_device_info( +// struct pci_device *dev, uint8_t bus, uint8_t device, uint8_t func, +// uint16_t vendorID, uint16_t deviceID, uint32_t classcode, +// uint8_t revisionID, uint8_t multifunction); uint32_t pci_device_get_mem_addr(struct pci_device *dev); uint32_t pci_device_get_io_addr(struct pci_device *dev); +#include "kernel/bus_driver.h" +#include "kernel/driver.h" + +typedef struct PciDeviceBar { + uint32_t type; + uint32_t base_addr; + uint32_t length; +} PciDeviceBar; +typedef struct PciDevice { + Bus *bus; + Device *device; + + char status; + + uint8_t bus_num; + uint8_t dev_num; + uint8_t function_num; + + uint16_t vendorID; + uint16_t deviceID; + uint8_t classcode; + uint8_t subclass; + uint8_t prog_if; + uint8_t revisionID; + uint8_t multifunction; + uint8_t irqline; + uint8_t irqpin; + + PciDeviceBar bar[PCI_MAX_BAR]; +} PciDevice; + +PciDevice *pci_alloc_device(void); +int pci_free_device(PciDevice *dev); +void get_pci_device_info( + PciDevice *dev, uint8_t bus, uint8_t device, uint8_t func, + uint16_t vendorID, uint16_t deviceID, uint32_t classcode, + uint8_t revisionID, uint8_t multifunction); +void get_pci_bar_info(PciDeviceBar *bar, uint32_t addr, uint32_t len); +DriverResult pci_scan_device( + Bus *bus, uint8_t bus_num, uint8_t device_num, uint8_t function_num); + #endif \ No newline at end of file diff --git a/src/arch/x86/kernel/descriptor.c b/src/arch/x86/kernel/descriptor.c index 5fed4e6..17ff033 100644 --- a/src/arch/x86/kernel/descriptor.c +++ b/src/arch/x86/kernel/descriptor.c @@ -5,7 +5,7 @@ * @version 1.2 * @date 2022-07-31 */ -#include "driver/interrupt_dm.h" +#include #include #include #include diff --git a/src/arch/x86/kernel/page.c b/src/arch/x86/kernel/page.c index 27091a0..9e0cd5d 100644 --- a/src/arch/x86/kernel/page.c +++ b/src/arch/x86/kernel/page.c @@ -15,7 +15,6 @@ #include #include - extern struct VesaDisplayInfo vesa_display_info; void setup_page(void) { @@ -187,6 +186,11 @@ MemoryResult remap(uint32_t in_paddr, size_t in_size, uint32_t *out_vaddr) { if (!in_paddr || !in_size) { return MEMORY_RESULT_INVALID_INPUT; } + if (in_paddr + in_size < 0x400000) { + // 低4MB内存默认已经映射,直接返回 + return in_paddr; + } + uint32_t vaddr; MEMORY_RESULT_DELIVER_CALL(alloc_vaddr, in_size, &vaddr); int old_status = io_load_eflags(); @@ -194,8 +198,6 @@ MemoryResult remap(uint32_t in_paddr, size_t in_size, uint32_t *out_vaddr) { __remap(in_paddr, vaddr, in_size); io_store_eflags(old_status); - __remap(in_paddr, vaddr, in_size); - io_sti(); uint32_t ret = vaddr & 0xfffff000; diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index 1c99daa..9990988 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -1,3 +1,4 @@ +#include "kernel/list.h" #include #include #include @@ -13,24 +14,37 @@ #include BusDriverOps platform_ops = { + .register_bus_hook = NULL, + .unregister_bus_hook = NULL, +}; +BusOps platform_bus_ops = { .register_device_hook = NULL, .unregister_device_hook = NULL, }; -Driver platform_driver; -BusDriver platform_bus = { +Driver platform_driver; +Bus platform_bus = { + .controller_device = NULL, + .ops = &platform_bus_ops, +}; +BusDriver platform_bus_driver = { .driver_type = DRIVER_TYPE_BUS_DRIVER, .bus_type = BUS_TYPE_PLATFORM, .name = STRING_INIT("platform"), .state = DRIVER_STATE_UNREGISTERED, .private_data_size = 0, + .ops = &platform_ops, }; void init_platform() { init_descriptor(); init_memory(); - register_bus_driver(&platform_driver, &platform_bus); + // 因为platform_bus是虚拟的,所以不需要注册device + register_bus_driver(&platform_driver, &platform_bus_driver); + list_init(&platform_bus_driver.bus_lh); + list_add_tail(&platform_bus.bus_list, &platform_bus_driver.bus_lh); + read_features(); register_vesa_display(); diff --git a/src/driver/Makefile b/src/driver/Makefile index e2fce8e..99c1fb1 100644 --- a/src/driver/Makefile +++ b/src/driver/Makefile @@ -1,4 +1,5 @@ SRC += timer_dm.c SRC += interrupt_dm.c SRC += video_dm.c -SRC += video.c \ No newline at end of file +SRC += video.c +SRC += bus_dm.c \ No newline at end of file diff --git a/src/driver/bus_dm.c b/src/driver/bus_dm.c new file mode 100644 index 0000000..c145a7d --- /dev/null +++ b/src/driver/bus_dm.c @@ -0,0 +1,39 @@ +#include "kernel/bus_driver.h" +#include +#include +#include +#include +#include + +DriverResult bus_controller_start(DeviceManager *manager, Device *device); + +DeviceManagerOps bus_controller_dm_ops = { + .dm_load_hook = NULL, + .dm_unload_hook = NULL, +}; + +typedef struct BusControllerDeviceManager { +} BusControllerDeviceManager; + +BusControllerDeviceManager bus_controller_dm_ext; + +struct DeviceManager bus_controller_device_manager = { + .type = DEVICE_TYPE_BUS_CONTROLLER, + + .ops = &bus_controller_dm_ops, + + .private_data = &bus_controller_dm_ext, +}; + +DriverResult register_bus_controller_device( + DeviceDriver *device_driver, BusDriver *bus_driver, Device *device, + BusControllerDevice *bus_controller_device) { + + device->device_driver = device_driver; + bus_controller_device->device = device; + bus_controller_device->bus_driver = bus_driver; + + DRV_RESULT_DELIVER_CALL( + register_device, device_driver, device_driver->bus, device); + return DRIVER_RESULT_OK; +} diff --git a/src/driver/interrupt_dm.c b/src/driver/interrupt_dm.c index b06fba0..2246bbe 100644 --- a/src/driver/interrupt_dm.c +++ b/src/driver/interrupt_dm.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -70,7 +71,8 @@ DriverResult register_interrupt_device( interrupt_device->device = device; DRV_RESULT_DELIVER_CALL(check_intterupt_ops, interrupt_device); - DRV_RESULT_DELIVER_CALL(register_device, device_driver, device); + DRV_RESULT_DELIVER_CALL( + register_device, device_driver, device_driver->bus, device); list_add_tail(&device->dm_list, &interrupt_device_manager.device_driver_lh); InterruptDeviceManager *manager = interrupt_device_manager.private_data; diff --git a/src/driver/timer_dm.c b/src/driver/timer_dm.c index e1b398c..71110a7 100644 --- a/src/driver/timer_dm.c +++ b/src/driver/timer_dm.c @@ -111,7 +111,8 @@ DriverResult register_timer_device( device->driver_manager_extension = timer_device; timer_device->device = device; - DRV_RESULT_DELIVER_CALL(register_device, device_driver, device); + DRV_RESULT_DELIVER_CALL( + register_device, device_driver, device_driver->bus, device); list_init(&timer_device->timer_list_lh); list_add_tail(&device->dm_list, &timer_device_manager.device_driver_lh); diff --git a/src/driver/video_dm.c b/src/driver/video_dm.c index f8590ea..20fec07 100644 --- a/src/driver/video_dm.c +++ b/src/driver/video_dm.c @@ -50,7 +50,8 @@ DriverResult register_video_device( } video_device->device = device; - DRV_RESULT_DELIVER_CALL(register_device, device_driver, device); + DRV_RESULT_DELIVER_CALL( + register_device, device_driver, device_driver->bus, device); list_init(&video_device->video_list_lh); list_add_tail(&device->dm_list, &video_device_manager.device_driver_lh); diff --git a/src/include/driver/bus_dm.h b/src/include/driver/bus_dm.h new file mode 100644 index 0000000..3261e60 --- /dev/null +++ b/src/include/driver/bus_dm.h @@ -0,0 +1,21 @@ +#ifndef _BUS_DM_H +#define _BUS_DM_H + +#include "kernel/bus_driver.h" +#include "kernel/device.h" + +typedef struct BusControllerDeviceOps { + void (*probe)(Device *device); +} BusControllerDeviceOps; + +typedef struct BusControllerDevice { + Device *device; + BusDriver *bus_driver; + BusControllerDeviceOps *bus_controller_ops; +} BusControllerDevice; + +DriverResult register_bus_controller_device( + DeviceDriver *device_driver, BusDriver *bus_driver, Device *device, + BusControllerDevice *bus_controller_device); + +#endif \ No newline at end of file diff --git a/src/include/kernel/bus_driver.h b/src/include/kernel/bus_driver.h index ba86f63..cbf4f87 100644 --- a/src/include/kernel/bus_driver.h +++ b/src/include/kernel/bus_driver.h @@ -4,6 +4,8 @@ #include "kernel/device_driver.h" #include "kernel/driver.h" #include "kernel/driver_manager.h" +#include "kernel/list.h" +#include "kernel/wait_queue.h" #define BUS_OPS_CALL(bus, func, ...) \ { \ @@ -22,17 +24,23 @@ typedef enum BusType { BUS_TYPE_MAX, } BusType; +struct Bus; typedef struct BusDriverOps { + DriverResult (*register_bus_hook)(struct Bus *bus); + DriverResult (*unregister_bus_hook)(struct Bus *bus); +} BusDriverOps; + +typedef struct BusOps { DriverResult (*register_device_hook)(struct DeviceDriver *device_driver); DriverResult (*unregister_device_hook)(struct DeviceDriver *device_driver); -} BusDriverOps; +} BusOps; typedef struct BusDriver { // 继承SubDriver特征 SubDriver driver; list_t dm_list; - list_t device_lh; + list_t bus_lh; string_t name; DriverType driver_type; BusType bus_type; @@ -44,11 +52,24 @@ typedef struct BusDriver { uint32_t private_data_size; } BusDriver; +typedef struct Bus { + list_t device_lh; + list_t bus_list; + BusDriver *bus_driver; + Device *controller_device; + BusOps *ops; +} Bus; + +extern struct BusDriver *bus_drivers[BUS_TYPE_MAX]; +extern wait_queue_manager_t bus_wqm[BUS_TYPE_MAX]; extern struct DriverManager bus_driver_manager; DriverResult register_bus_driver(Driver *driver, BusDriver *bus_driver); DriverResult unregister_bus_driver(Driver *driver, BusType type); -DriverResult bus_register_device(DeviceDriver *device_driver); +DriverResult register_bus( + BusDriver *bus_driver, Device *bus_controller_device, Bus *bus); +DriverResult unregister_bus(Bus *bus); +DriverResult bus_register_device(DeviceDriver *device_driver, Bus *bus); DriverResult bus_unregister_device(DeviceDriver *device_driver); #endif \ No newline at end of file diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index 5fe71d9..00e534d 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -65,8 +65,9 @@ typedef struct Device { void *driver_manager_extension; // 设备管理器所需的扩展信息 } Device; +struct Bus; DriverResult register_device( - struct DeviceDriver *device_driver, Device *device); + struct DeviceDriver *device_driver, struct Bus *bus, Device *device); DriverResult unregister_device( struct DeviceDriver *device_driver, Device *device); DriverResult init_device(Device *device); diff --git a/src/include/kernel/device_driver.h b/src/include/kernel/device_driver.h index b75aa8a..caeca97 100644 --- a/src/include/kernel/device_driver.h +++ b/src/include/kernel/device_driver.h @@ -35,12 +35,14 @@ typedef enum { DRIVER_STATE_ACTIVE, // 驱动正在运行 } DriverState; +struct Bus; typedef struct DeviceDriver { // 继承SubDriver特征 SubDriver driver; list_t bus_list; list_t device_lh; + struct Bus *bus; string_t name; DeviceType type; DriverPriority priority; diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index f7f9d46..b63f245 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -1,7 +1,7 @@ #ifndef _DRIVER_H #define _DRIVER_H -#include +#include "stdint.h" #define DRIVER_MAX_NAME_LEN 64 #define DEVICE_MAX_NAME_LEN 64 @@ -125,10 +125,15 @@ extern list_t startup_dm_lh; // 实体的驱动,管理着一个驱动下的所有类型的抽象驱动 typedef struct Driver { string_t name; + list_t driver_list; list_t sub_driver_lh; list_t remapped_memory_lh; + + int dependency_count; + struct DriverDenpendency *dependencies; } Driver; +struct DriverDenpendency; typedef struct SubDriver { list_t list; list_t sub_driver_list; @@ -153,6 +158,8 @@ typedef enum DriverResult { DRIVER_RESULT_OTHER_ERROR, } DriverResult; +DriverResult register_driver(Driver *driver); +DriverResult unregister_driver(Driver *driver); DriverResult register_sub_driver(Driver *driver, SubDriver *sub_driver); DriverResult unregister_sub_driver(Driver *driver, SubDriver *sub_driver); void print_driver_result( diff --git a/src/include/kernel/driver_dependency.h b/src/include/kernel/driver_dependency.h new file mode 100644 index 0000000..e378f2e --- /dev/null +++ b/src/include/kernel/driver_dependency.h @@ -0,0 +1,27 @@ +#ifndef _DRIVER_DEPENDENCY_H +#define _DRIVER_DEPENDENCY_H + +#include "kernel/bus_driver.h" +#include "kernel/device_manager.h" + +typedef struct DriverDenpendency { + enum { + DRIVER_DEPENDENCY_TYPE_BUS, // 依赖某种总线 + DRIVER_DEPENDENCY_TYPE_DEVICE, // 依赖某种设备类型 + } in_type; + union { + struct { + BusType type; + int bus_num; + } dependency_in_bus; + DeviceType in_device_type; + }; + union { + Bus *out_bus; + DeviceManager *device_manager; + }; +} DriverDependency; + +DriverResult check_dependency(Driver *driver); + +#endif \ No newline at end of file diff --git a/src/include/kernel/driver_interface.h b/src/include/kernel/driver_interface.h index 144857e..7ff2340 100644 --- a/src/include/kernel/driver_interface.h +++ b/src/include/kernel/driver_interface.h @@ -17,6 +17,9 @@ #define enable_interrupt() io_sti() #define disable_interrupt() io_cli() +#define load_interrupt_status() io_load_eflags(); +#define store_interrupt_status(status) io_store_eflags(status); + #else #error Driver: Unsupport Architecture #endif @@ -43,7 +46,8 @@ typedef struct DeviceIrq { #include "stdint.h" typedef struct DriverRemappedMemory { list_t list; - uint32_t start; + uint32_t vir_start; + uint32_t phy_start; uint32_t size; } DriverRemappedMemory; diff --git a/src/include/kernel/platform.h b/src/include/kernel/platform.h index 481b073..db27a4d 100644 --- a/src/include/kernel/platform.h +++ b/src/include/kernel/platform.h @@ -1,5 +1,7 @@ #ifndef _PLATFORM_H +extern struct Bus platform_bus; + void init_platform(); void platform_init_and_start_devices(); diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 6c2b58f..1a97c5a 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -12,6 +12,7 @@ SRC += device_driver.c SRC += device_manager.c SRC += driver_manager.c SRC += driver_interface.c +SRC += driver_dependency.c SRC += device.c SRC += process.c SRC += syscall.c diff --git a/src/kernel/bus_driver.c b/src/kernel/bus_driver.c index d145e9e..245df72 100644 --- a/src/kernel/bus_driver.c +++ b/src/kernel/bus_driver.c @@ -1,11 +1,13 @@ -#include "kernel/device_driver.h" -#include "kernel/list.h" #include +#include #include #include +#include #include +#include -BusDriver *bus_drivers[BUS_TYPE_MAX]; +BusDriver *bus_drivers[BUS_TYPE_MAX]; +wait_queue_manager_t bus_wqm[BUS_TYPE_MAX]; DriverResult bus_driver_manager_load(DriverManager *driver_manager); DriverResult bus_driver_manager_unload(DriverManager *driver_manager); @@ -20,13 +22,12 @@ DriverManagerOps bus_driver_ops = { }; typedef struct BusDriverManagerExt { - DeviceDriver *bus_controller_device; } BusDriverMangerExt; BusDriverMangerExt bus_driver_manager_ext; struct DriverManager bus_driver_manager = { - .type = DRIVER_TYPE_DEVICE_DRIVER, + .type = DRIVER_TYPE_BUS_DRIVER, .ops = &bus_driver_ops, @@ -34,7 +35,9 @@ struct DriverManager bus_driver_manager = { }; DriverResult bus_driver_manager_load(DriverManager *driver_manager) { - + for (int i = 0; i < BUS_TYPE_MAX; i++) { + wait_queue_init(&bus_wqm[i]); + } return DRIVER_RESULT_OK; } @@ -56,6 +59,8 @@ DriverResult register_bus_driver(Driver *driver, BusDriver *bus_driver) { DRV_RESULT_DELIVER_CALL(register_sub_driver, driver, &bus_driver->driver); + bus_drivers[bus_driver->bus_type] = bus_driver; + return DRIVER_RESULT_OK; } @@ -67,6 +72,13 @@ DriverResult unregister_bus_driver(Driver *driver, BusType type) { BusDriver *bus_driver = bus_drivers[type]; if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + bus_drivers[bus_driver->driver_type] = NULL; + + Bus *cur, *next; + list_for_each_owner_safe (cur, next, &bus_driver->bus_lh, bus_list) { + unregister_bus(cur); + } + DRV_RESULT_DELIVER_CALL(unregister_sub_driver, driver, &bus_driver->driver); bus_driver->state = DRIVER_STATE_UNREGISTERED; @@ -75,22 +87,54 @@ DriverResult unregister_bus_driver(Driver *driver, BusType type) { return DRIVER_RESULT_OK; } -DriverResult bus_register_device(DeviceDriver *device_driver) { - BusDriver *bus_driver = bus_drivers[device_driver->type]; +DriverResult register_bus( + BusDriver *bus_driver, Device *bus_controller_device, Bus *bus) { if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; - list_add_tail(&device_driver->bus_list, &bus_driver->device_lh); - BUS_OPS_CALL(bus_driver, register_device_hook, device_driver); + bus->bus_driver = bus_driver; + bus->controller_device = bus_controller_device; + list_init(&bus->device_lh); + list_add_tail(&bus->bus_list, &bus_driver->bus_lh); + BUS_OPS_CALL(bus_driver, register_bus_hook, bus); return DRIVER_RESULT_OK; } -DriverResult bus_unregister_device(DeviceDriver *device_driver) { +DriverResult unregister_bus(Bus *bus) { + BusDriver *bus_driver = bus->bus_driver; + if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + + // 取消注册bus下的所有device_driver + DeviceDriver *cur, *next; + list_for_each_owner_safe (cur, next, &bus->device_lh, bus_list) { + bus_unregister_device(cur); + } + + BUS_OPS_CALL(bus_driver, unregister_bus_hook, bus); + list_del(&bus->bus_list); + bus->bus_driver = NULL; + + return DRIVER_RESULT_OK; +} + +DriverResult bus_register_device(DeviceDriver *device_driver, Bus *bus) { BusDriver *bus_driver = bus_drivers[device_driver->type]; if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; - BUS_OPS_CALL(bus_driver, unregister_device_hook, device_driver); + device_driver->bus = bus; + list_add_tail(&device_driver->bus_list, &bus->device_lh); + BUS_OPS_CALL(bus, register_device_hook, device_driver); + + return DRIVER_RESULT_OK; +} + +DriverResult bus_unregister_device(DeviceDriver *device_driver) { + Bus *bus = device_driver->bus; + if (bus == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + + BUS_OPS_CALL(bus, unregister_device_hook, device_driver); list_del(&device_driver->bus_list); + device_driver->bus = NULL; return DRIVER_RESULT_OK; } diff --git a/src/kernel/device.c b/src/kernel/device.c index 57747af..5ae3a68 100644 --- a/src/kernel/device.c +++ b/src/kernel/device.c @@ -6,10 +6,11 @@ #include #include -DriverResult register_device(DeviceDriver *device_driver, Device *device) { +DriverResult register_device( + DeviceDriver *device_driver, Bus *bus, Device *device) { device->state = DEVICE_STATE_REGISTERED; list_add_tail(&device->device_list, &device_driver->device_lh); - bus_register_device(device_driver); + bus_register_device(device_driver, bus); return DRIVER_RESULT_OK; } diff --git a/src/kernel/device_driver.c b/src/kernel/device_driver.c index e9ebc4c..e4d4350 100644 --- a/src/kernel/device_driver.c +++ b/src/kernel/device_driver.c @@ -1,4 +1,5 @@ #include "kernel/device.h" +#include "kernel/list.h" #include #include #include @@ -59,6 +60,7 @@ DriverResult register_device_driver( DriverManager *manager = driver_managers[DRIVER_TYPE_DEVICE_DRIVER]; if (manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; + list_init(&device_driver->device_lh); device_driver->private_data = kmalloc(device_driver->private_data_size); device_driver->state = DRIVER_STATE_REGISTERED; diff --git a/src/kernel/device_manager.c b/src/kernel/device_manager.c index 2ef37c2..71e4604 100644 --- a/src/kernel/device_manager.c +++ b/src/kernel/device_manager.c @@ -14,7 +14,6 @@ DriverResult register_device_manager(DeviceManager *manager) { } device_managers[manager->type] = manager; - list_add_tail(&manager->dm_list, &startup_dm_lh); DEVM_OPS_CALL(manager, dm_load_hook, manager); return DRIVER_RESULT_OK; diff --git a/src/kernel/driver.c b/src/kernel/driver.c index c1a6b14..5a5136d 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -5,6 +5,7 @@ * @version 0.3 * @date 2022-07-20 */ +#include "kernel/driver_dependency.h" #include #include #include @@ -46,7 +47,7 @@ struct file_operations device_fops = { #include #include -LIST_HEAD(startup_dm_lh); +LIST_HEAD(driver_lh); void print_driver_result( DriverResult result, char *file, int line, char *func_with_args) { @@ -70,6 +71,19 @@ void print_driver_result( } } +DriverResult register_driver(Driver *driver) { + list_init(&driver->sub_driver_lh); + list_init(&driver->remapped_memory_lh); + list_add_tail(&driver->driver_list, &driver_lh); + check_dependency(driver); + return DRIVER_RESULT_OK; +} + +DriverResult unregister_driver(Driver *driver) { + list_del(&driver->driver_list); + return DRIVER_RESULT_OK; +} + DriverResult register_sub_driver(Driver *driver, SubDriver *sub_driver) { sub_driver->driver = driver; diff --git a/src/kernel/driver_dependency.c b/src/kernel/driver_dependency.c new file mode 100644 index 0000000..c049b36 --- /dev/null +++ b/src/kernel/driver_dependency.c @@ -0,0 +1,43 @@ +#include "kernel/list.h" +#include "kernel/thread.h" +#include "kernel/wait_queue.h" +#include +#include +#include +#include + +DriverResult check_dependency(Driver *driver) { + int count = driver->dependency_count; + DriverDependency *deps = driver->dependencies; + + for (int i = 0; i < count; i++) { + if (deps[i].in_type == DRIVER_DEPENDENCY_TYPE_BUS) { + if (deps[i].dependency_in_bus.type > BUS_TYPE_MAX) { + return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + } + + Bus *bus; + BusDriver *bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; + if (bus_driver == NULL) { // 总线驱动还没初始化 + wait_queue_add(&bus_wqm[deps[i].dependency_in_bus.type], 0); + thread_block(TASK_BLOCKED); + bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; + } + + int j = 0; + list_for_each_owner (bus, &bus_driver->bus_lh, bus_list) { + if (j == deps[i].dependency_in_bus.bus_num) { + deps[i].out_bus = bus; + break; + } + j++; + } + } else if (deps[i].in_type == DRIVER_DEPENDENCY_TYPE_DEVICE) { + if (deps[i].in_device_type > DEVICE_TYPE_MAX) { + return DRIVER_RESULT_DEVICE_MANAGER_NOT_EXIST; + } + // TODO: device依赖 + } + } + return DRIVER_RESULT_OK; +} \ No newline at end of file diff --git a/src/kernel/driver_interface.c b/src/kernel/driver_interface.c index ed47242..d9990eb 100644 --- a/src/kernel/driver_interface.c +++ b/src/kernel/driver_interface.c @@ -44,28 +44,36 @@ void device_irq_handler(int irq) { DriverResult driver_remap_memory( Driver *in_driver, uint32_t in_physical_address, uint32_t in_size, uint32_t *out_virtual_address) { + // 地址对齐页大小 uint32_t start = in_physical_address & 0xfffff000; uint32_t end = (in_physical_address + in_size + 0xfff) & 0xfffff000; uint32_t tmp; uint32_t virtual_address = 0; - for (uint32_t i = start; i < end; i += 0x1000) { - MemoryResult result = MEMORY_RESULT_PRINT_CALL(remap, i, 0x3ff, &tmp); - if (result != MEMORY_RESULT_OK) { - for (int j = start; j < i; j++) { - // 释放之前映射的内存 - unmap(j, 0x3ff); - } - printk( - "Driver Interface: remap memory:0x%08x(size: %d) failed\n", - in_physical_address, in_size); - return DRIVER_RESULT_OTHER_ERROR; + + // 调用前先检查是否已经被映射 + DriverRemappedMemory *cur; + list_for_each_owner (cur, &in_driver->remapped_memory_lh, list) { + if (cur->phy_start < start && cur->phy_start + cur->size > end) { + virtual_address = cur->vir_start; + return DRIVER_RESULT_OK; } - if (virtual_address == 0) { virtual_address = tmp; } } + + MemoryResult result = + MEMORY_RESULT_PRINT_CALL(remap, start, end - start, &tmp); + if (result != MEMORY_RESULT_OK) { + printk( + "Driver Interface: remap memory:0x%08x(size: %d) failed\n", + in_physical_address, in_size); + return DRIVER_RESULT_OTHER_ERROR; + } + if (virtual_address == 0) { virtual_address = tmp; } + DriverRemappedMemory *remapped_memory = kmalloc(sizeof(DriverRemappedMemory)); - remapped_memory->size = in_size; - remapped_memory->start = virtual_address; + remapped_memory->size = end - start; + remapped_memory->vir_start = virtual_address; + remapped_memory->phy_start = start; list_add_tail(&remapped_memory->list, &in_driver->remapped_memory_lh); *out_virtual_address = virtual_address; return DRIVER_RESULT_OK; diff --git a/src/kernel/initcall.c b/src/kernel/initcall.c index 925b82e..2bc83b3 100644 --- a/src/kernel/initcall.c +++ b/src/kernel/initcall.c @@ -20,7 +20,7 @@ void do_initcalls(void) { for (; func < &(*__initcall_end); func++) { (*func)(); } - driver_inited(); + // driver_inited(); } void do_exitcalls(void) { diff --git a/src/kernel/main.c b/src/kernel/main.c index 5493b35..574c6ac 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -52,7 +52,7 @@ int main() { // io_sti(); printk("Memory Size:%dM\n", get_memory_size()); // init_vfs(); - // do_initcalls(); + do_initcalls(); // init_fs(); // thread_start( diff --git a/src/kernel/wait_queue.c b/src/kernel/wait_queue.c index 12cfde5..9079b17 100644 --- a/src/kernel/wait_queue.c +++ b/src/kernel/wait_queue.c @@ -6,8 +6,9 @@ * @date 2022-07-20 */ -#include "kernel/list.h" +#include #include +#include #include #include @@ -17,7 +18,8 @@ * @return wait_queue_manager_t* 等待队列的管理结构 */ wait_queue_manager_t *create_wait_queue(void) { - wait_queue_manager_t *wqm = (wait_queue_manager_t *)kmalloc(sizeof(wait_queue_manager_t)); + wait_queue_manager_t *wqm = + (wait_queue_manager_t *)kmalloc(sizeof(wait_queue_manager_t)); return wqm; } @@ -54,11 +56,14 @@ bool wait_queue_empty(wait_queue_manager_t *wqm) { wait_queue_t *wait_queue_add(wait_queue_manager_t *wqm, uint32_t size) { wait_queue_t *wq = (wait_queue_t *)kmalloc(sizeof(wait_queue_t)); wq->thread = get_current_thread(); - int old_status = io_load_eflags(); + int old_status = load_interrupt_status(); + disable_interrupt(); spin_lock(&wqm->lock); + list_add_tail(&wq->list, &wqm->list_head); + spin_unlock(&wqm->lock); - io_store_eflags(old_status); + store_interrupt_status(old_status); if (size != 0) { wq->private_data = kmalloc(size); } else { @@ -85,18 +90,23 @@ wait_queue_t *wait_queue_first(wait_queue_manager_t *wqm) { */ void wait_queue_wakeup(wait_queue_manager_t *wqm) { if (list_empty(&wqm->list_head)) { return; } - wait_queue_t *wq = list_first_owner(&wqm->list_head, wait_queue_t, list); + wait_queue_t *wq = list_first_owner(&wqm->list_head, wait_queue_t, list); struct task_s *thread = wq->thread; - int old_status = io_load_eflags(); + int old_status = load_interrupt_status(); + disable_interrupt(); spin_lock(&wqm->lock); + list_del(&wq->list); if (wq->private_data != NULL) { kfree(wq->private_data); } kfree(wq); - if (thread->status == TASK_BLOCKED || thread->status == TASK_WAITING || thread->status == TASK_HANGING) { + + if (thread->status == TASK_BLOCKED || thread->status == TASK_WAITING || + thread->status == TASK_HANGING) { thread_unblock(thread); } + spin_unlock(&wqm->lock); - io_store_eflags(old_status); + store_interrupt_status(old_status); return; } @@ -107,9 +117,12 @@ void wait_queue_wakeup(wait_queue_manager_t *wqm) { */ void wait_queue_wakeup_all(wait_queue_manager_t *wqm) { if (list_empty(&wqm->list_head)) { return; } - wait_queue_t *cur, *next; + wait_queue_t *cur, *next; struct task_s *thread; - int old_status = io_load_eflags(); + + int old_status = load_interrupt_status(); + disable_interrupt(); + spin_lock(&wqm->lock); list_for_each_owner_safe (cur, next, &wqm->list_head, list) { thread = cur->thread; @@ -121,7 +134,8 @@ void wait_queue_wakeup_all(wait_queue_manager_t *wqm) { thread_unblock(thread); } } + spin_unlock(&wqm->lock); - io_store_eflags(old_status); + store_interrupt_status(old_status); return; } From 386ea8b652c5421601d88644019c505544b2c94a Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 13 Dec 2024 21:22:53 +0800 Subject: [PATCH 005/158] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E5=99=A8=E9=A2=91=E7=8E=87=E6=AF=94=E8=BE=83=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=EF=BC=9B=E6=96=B0=E5=A2=9E=E7=BB=93=E6=9D=9F=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .clang-format | 2 +- src/arch/x86/include/kernel/thread.h | 121 ++++++++++++++------------- src/driver/timer_dm.c | 34 +++++++- src/kernel/thread.c | 55 +++++++++--- 4 files changed, 138 insertions(+), 74 deletions(-) diff --git a/.clang-format b/.clang-format index ef3ee5c..58a164c 100644 --- a/.clang-format +++ b/.clang-format @@ -92,7 +92,7 @@ PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 1000000 +PenaltyExcessCharacter: 1000 PenaltyReturnTypeOnItsOwnLine: 1000 PenaltyIndentedWhitespace: 0 PointerAlignment: Right diff --git a/src/arch/x86/include/kernel/thread.h b/src/arch/x86/include/kernel/thread.h index 233d60c..5f9f7af 100644 --- a/src/arch/x86/include/kernel/thread.h +++ b/src/arch/x86/include/kernel/thread.h @@ -8,79 +8,84 @@ typedef void thread_func(void *); typedef enum { - TASK_RUNNING, - TASK_READY, - TASK_BLOCKED, - TASK_WAITING, - TASK_HANGING, - TASK_DIED + TASK_RUNNING, + TASK_READY, + TASK_BLOCKED, + TASK_WAITING, + TASK_HANGING, + TASK_DIED } task_status_t; struct intr_stack { - uint32_t vec_no; - uint32_t edi; - uint32_t esi; - uint32_t ebp; - uint32_t esp_dummy; - uint32_t ebx; - uint32_t edx; - uint32_t ecx; - uint32_t eax; - uint32_t gs; - uint32_t fs; - uint32_t es; - uint32_t ds; - - uint32_t err_code; - void (*eip)(void); - uint32_t cs; - uint32_t eflags; - void *esp; - uint32_t ss; + uint32_t vec_no; + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp_dummy; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint32_t gs; + uint32_t fs; + uint32_t es; + uint32_t ds; + + uint32_t err_code; + void (*eip)(void); + uint32_t cs; + uint32_t eflags; + void *esp; + uint32_t ss; }; struct thread_stack { - uint32_t ebp; - uint32_t ebx; - uint32_t edi; - uint32_t esi; + uint32_t ebp; + uint32_t ebx; + uint32_t edi; + uint32_t esi; - void (*eip)(thread_func *func, void *func_arg); + void (*eip)(thread_func *func, void *func_arg); - void(*unused_retaddr); - thread_func *function; - void *func_arg; + void(*unused_retaddr); + thread_func *function; + void *func_arg; }; struct task_s { - uint32_t *kstack; - - uint32_t pid; - char name[32]; - task_status_t status; - uint8_t priority; - uint8_t ticks; - uint32_t elapsed_ticks; - uint32_t *pgdir; - uint32_t stack_magic; - - struct mmap vir_page_mmap; - struct memory_manage *memory_manage; - - list_t general_tag; - list_t all_list_tag; + uint32_t *kstack; + + uint32_t pid; + char name[32]; + task_status_t status; + uint8_t priority; + uint8_t ticks; + uint32_t elapsed_ticks; + uint32_t *pgdir; + uint32_t stack_magic; + + struct mmap vir_page_mmap; + struct memory_manage *memory_manage; + + list_t general_tag; + list_t all_list_tag; }; #define THREAD_DEFAULT_PRIO 100 +extern list_t thread_all; + struct task_s *get_current_thread(); -void init_thread(struct task_s *pthread, char *name, int priority); -void thread_create(struct task_s *pthread, thread_func *function, void *func_arg); -struct task_s *thread_start(char *name, int priority, thread_func function, void *func_arg); -void thread_block(task_status_t status); -void thread_unblock(struct task_s *pthread); -void init_task(void); -void schedule(void); -void init_thread_memory_manage(struct task_s *thread); +void init_thread(struct task_s *pthread, char *name, int priority); +void thread_create( + struct task_s *pthread, thread_func *function, void *func_arg); +struct task_s *thread_start( + char *name, int priority, thread_func function, void *func_arg); +void thread_exit(void); +void thread_block(task_status_t status); +void thread_unblock(struct task_s *pthread); +void init_task(void); +void schedule(void); +void init_thread_memory_manage(struct task_s *thread); #endif \ No newline at end of file diff --git a/src/driver/timer_dm.c b/src/driver/timer_dm.c index 71110a7..4419a9a 100644 --- a/src/driver/timer_dm.c +++ b/src/driver/timer_dm.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -58,12 +59,14 @@ DriverResult timer_device_init(DeviceManager *manager, Device *device) { const int count = sizeof(default_frequencies) / sizeof(typeof(default_frequencies[0])); int freq; - int error = 0xfffffff; + int min_error = 0xfffffff; // 误差 int i; for (i = 0; i < count; i++) { - if (timer_device->source_frequency % default_frequencies[i] < error) { - error = timer_device->source_frequency % default_frequencies[i]; - freq = default_frequencies[i]; + int error = timer_device->source_frequency % default_frequencies[i]; + if (error < min_error || + (error == min_error && default_frequencies[i] > freq)) { + min_error = timer_device->source_frequency % default_frequencies[i]; + freq = default_frequencies[i]; } } DRV_RESULT_DELIVER_CALL(timer_set_frequency, device, freq); @@ -82,6 +85,15 @@ DriverResult timer_device_init(DeviceManager *manager, Device *device) { return DRIVER_RESULT_OK; } +int timer_get_schedule_tick(int priority) { + if (priority <= 0) { return 0; } + TimerDevice *timer_device = + (TimerDevice *)timer_device_manager.private_data; + int ticks = priority * timer_device->current_frequency / 1000; + if (ticks == 0) { ticks = 1; } // 如果小于粒度,至少1个tick + return ticks; +} + DriverResult timer_set_frequency(Device *device, uint32_t frequency) { TimerDevice *timer_device = (TimerDevice *)device->driver_manager_extension; @@ -104,6 +116,20 @@ void timer_irq_handler(Device *device) { list_del(&cur->list); cur->timeout = 0; } + + if (!list_empty(&thread_all)) { + // 已启用多任务 + if (device == timer_dm_ext.scheduler_timer) { + struct task_s *cur_thread = get_current_thread(); + cur_thread->elapsed_ticks++; + + if (cur_thread->ticks == 0) { + schedule(); + } else { + cur_thread->ticks--; + } + } + } } DriverResult register_timer_device( diff --git a/src/kernel/thread.c b/src/kernel/thread.c index 29cce70..9965a96 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -6,8 +6,10 @@ * @date 2021-02 * */ +#include #include #include +#include #include #include #include @@ -18,9 +20,9 @@ struct task_s *main_thread; list_t thread_ready; -list_t thread_all; -struct lock pid_lock; -uint32_t new_pid = 0; +LIST_HEAD(thread_all); +struct lock pid_lock; +uint32_t new_pid = 0; extern struct task_s *task_idle; @@ -56,6 +58,7 @@ struct task_s *get_current_thread() { static void kernel_thread(thread_func *function, void *func_arg) { io_sti(); function(func_arg); + thread_exit(); } /** @@ -65,7 +68,8 @@ static void kernel_thread(thread_func *function, void *func_arg) { * @param function 线程入口函数 * @param func_arg 参数 */ -void thread_create(struct task_s *pthread, thread_func *function, void *func_arg) { +void thread_create( + struct task_s *pthread, thread_func *function, void *func_arg) { pthread->pid = alloc_pid(); pthread->kstack -= sizeof(struct intr_stack); pthread->kstack -= sizeof(struct thread_stack); @@ -73,7 +77,8 @@ void thread_create(struct task_s *pthread, thread_func *function, void *func_arg kthread_stack->eip = kernel_thread; kthread_stack->function = function; kthread_stack->func_arg = func_arg; - kthread_stack->ebp = kthread_stack->ebx = kthread_stack->esi = kthread_stack->edi = 0; + kthread_stack->ebp = kthread_stack->ebx = kthread_stack->esi = + kthread_stack->edi = 0; } /** @@ -84,7 +89,7 @@ void thread_create(struct task_s *pthread, thread_func *function, void *func_arg * @param priority 优先级 */ void init_thread(struct task_s *pthread, char *name, int priority) { - memset(pthread, 0, sizeof(sizeof(struct task_s))); + memset(pthread, 0, sizeof(struct task_s)); strcpy(pthread->name, name); if (pthread == main_thread) { pthread->status = TASK_RUNNING; @@ -93,7 +98,7 @@ void init_thread(struct task_s *pthread, char *name, int priority) { } pthread->priority = priority; pthread->kstack = (uint32_t *)((uint32_t)pthread + PAGE_SIZE); - pthread->ticks = priority; + pthread->ticks = timer_get_schedule_tick(priority); pthread->elapsed_ticks = 0; pthread->pgdir = NULL; pthread->stack_magic = 0x10000000; @@ -108,7 +113,8 @@ void init_thread(struct task_s *pthread, char *name, int priority) { * @param func_arg 参数 * @return struct task_s* 创建好的线程 */ -struct task_s *thread_start(char *name, int priority, thread_func function, void *func_arg) { +struct task_s *thread_start( + char *name, int priority, thread_func function, void *func_arg) { struct task_s *thread = kernel_alloc_pages(1); init_thread(thread, name, priority); @@ -138,6 +144,31 @@ struct task_s *thread_start(char *name, int priority, thread_func function, void return thread; } +void thread_exit(void) { + struct task_s *cur = get_current_thread(); + cur->status = TASK_DIED; + + list_del(&cur->general_tag); + list_del(&cur->all_list_tag); + + kfree(cur); + + struct task_s *next; + next = list_first_owner(&thread_ready, struct task_s, general_tag); + + if (list_length(&thread_ready) > 1) { + list_del(thread_ready.next); + next->status = TASK_RUNNING; + + process_activate(next); + + switch_to((int *)cur, (int *)next); + } else { + process_activate(task_idle); + switch_to((int *)cur, (int *)task_idle); + } +} + /** * @brief 阻塞当前线程 * @@ -148,7 +179,8 @@ struct task_s *thread_start(char *name, int priority, thread_func function, void */ void thread_block(task_status_t status) { int old_status = io_load_eflags(); - if ((status != TASK_BLOCKED) && (status != TASK_WAITING) && (status != TASK_HANGING)) { + if ((status != TASK_BLOCKED) && (status != TASK_WAITING) && + (status != TASK_HANGING)) { printk("error"); while (1) ; @@ -166,7 +198,8 @@ void thread_block(task_status_t status) { */ void thread_unblock(struct task_s *pthread) { int old_status = io_load_eflags(); - if ((pthread->status != TASK_BLOCKED) && (pthread->status != TASK_WAITING) && + if ((pthread->status != TASK_BLOCKED) && + (pthread->status != TASK_WAITING) && (pthread->status != TASK_HANGING)) { printk("error"); while (1) @@ -191,6 +224,7 @@ void thread_unblock(struct task_s *pthread) { static void make_main_thread(void) { main_thread = get_current_thread(); init_thread(main_thread, "System", 10); + main_thread->pid = alloc_pid(); if (list_find(&main_thread->all_list_tag, &thread_all)) { printk("thread main:start error!\n"); @@ -206,7 +240,6 @@ static void make_main_thread(void) { */ void init_task(void) { list_init(&thread_ready); - list_init(&thread_all); lock_init(&pid_lock); make_main_thread(); } From b8a45969c11d74201dcd4934a7c8db0bf8e9846c Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 13 Dec 2024 21:26:58 +0800 Subject: [PATCH 006/158] =?UTF-8?q?[WIP]=E6=9B=B4=E6=96=B0PCI=E6=80=BB?= =?UTF-8?q?=E7=BA=BF=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/8259a.c | 1 + src/arch/x86/drivers/apic.c | 93 ++++---- src/arch/x86/drivers/pci.c | 345 +++++++++++++++++++++++----- src/arch/x86/drivers/pit.c | 1 + src/arch/x86/drivers/vesa_display.c | 1 + src/arch/x86/include/drivers/apic.h | 2 +- src/arch/x86/include/drivers/pci.h | 116 +++++++++- src/arch/x86/kernel/descriptor.c | 1 + src/arch/x86/kernel/func.asm | 8 +- src/arch/x86/kernel/platform.c | 4 +- src/include/driver/timer_dm.h | 1 + src/include/kernel/bus_driver.h | 26 ++- src/include/kernel/device_driver.h | 8 +- src/include/kernel/driver.h | 68 ++++-- src/kernel/bus_driver.c | 20 +- src/kernel/device.c | 1 + src/kernel/device_driver.c | 13 +- src/kernel/driver.c | 116 ++++++++-- src/kernel/driver_dependency.c | 12 +- src/kernel/initcall.c | 3 +- src/kernel/main.c | 11 +- 21 files changed, 662 insertions(+), 189 deletions(-) diff --git a/src/arch/x86/drivers/8259a.c b/src/arch/x86/drivers/8259a.c index 4691c56..e75214f 100644 --- a/src/arch/x86/drivers/8259a.c +++ b/src/arch/x86/drivers/8259a.c @@ -71,6 +71,7 @@ InterruptDevice pic_interrupt_device = { void register_pic(void) { register_driver(&pic_driver); + driver_init(&pic_driver); register_device_driver(&pic_driver, &pic_device_driver); register_interrupt_device( &pic_device_driver, &pic_device, &pic_interrupt_device); diff --git a/src/arch/x86/drivers/apic.c b/src/arch/x86/drivers/apic.c index 05599df..aa4d332 100644 --- a/src/arch/x86/drivers/apic.c +++ b/src/arch/x86/drivers/apic.c @@ -146,7 +146,7 @@ DeviceDriver apic_timer_device_driver = { }; DeviceIrq apic_timer_irq = { .device = &apic_timer_device, - .irq = PIC_PIT_IRQ, + .irq = 2, .handler = apic_timer_irq_handler, }; Device apic_timer_device = { @@ -175,53 +175,66 @@ void io_apic_write(uint32_t reg, uint32_t data) { apic_info.ioapic->data = data; } -DriverResult register_apic(void) { +void register_apic(void) { register_driver(&apic_driver); + driver_init(&apic_driver); register_device_driver(&apic_driver, &apic_device_driver); register_device_driver(&apic_driver, &apic_timer_device_driver); register_interrupt_device( &apic_device_driver, &apic_device, &apic_interrupt_device); register_timer_device( &apic_device_driver, &apic_timer_device, &apic_timer_timer_device); - return DRIVER_RESULT_OK; +} + +void x2apic_init(struct DeviceDriver *driver) { + apic_info.apic_type = APIC_TYPE_X2APIC; + // 还未实现x2apic支持,这里只是简单的初始化 + uint32_t low, high; + read_msr(APIC_BASE_MSR, &low, &high); + + apic_info.apic_base = 0xfee00000; + apic_info.apic_base_high = low >> 12; + + uint32_t tmp; + DRV_RESULT_PRINT_CALL( + driver_remap_memory, &apic_driver, apic_info.apic_base, 0x3ff, &tmp); + apic_info.lapic_mmio = (uint32_t *)tmp; + DRV_RESULT_PRINT_CALL( + driver_remap_memory, &apic_driver, 0xfec00000, 0xfff00, &tmp); + apic_info.ioapic = (struct ioapic *)tmp; + + read_msr(X2APIC_ID_MSR, &apic_info.apic_id, &apic_info.apic_id_high); + apic_info.version = + (lapic_read(APIC_Ver) & 0xff) | ((lapic_read(APIC_Ver) >> 16) & 0xff); +} + +void xapic_init(struct DeviceDriver *driver) { + apic_info.apic_type = APIC_TYPE_XAPIC; + apic_info.apic_base = 0xfee00000; + + DRV_RESULT_PRINT_CALL( + driver_remap_memory, &apic_driver, apic_info.apic_base, 0x3ff, + (uint32_t *)&apic_info.lapic_mmio); + DRV_RESULT_PRINT_CALL( + driver_remap_memory, &apic_driver, 0xfec00000, 0xfff00, + (uint32_t *)&apic_info.ioapic); + + apic_info.apic_id = lapic_read(APIC_ID) >> 24; + apic_info.version = (lapic_read(APIC_Ver) & 0xff); + apic_info.max_lvt_entry = (lapic_read(APIC_Ver) >> 16) & 0xff; } DriverResult apic_driver_init(struct DeviceDriver *driver) { + /** + * 所有文档都说要先屏蔽8259a的中断,直到我无数次触发#DF才知道为什么... + * 防止apic完成初始化前触发中断无法正确处理导致异常 + */ if (cpu_check_feature(CPUID_FEAT_X2APIC)) { - apic_info.apic_type = APIC_TYPE_X2APIC; - // 还未实现x2apic支持,这里只是简单的初始化 - uint32_t low, high; - read_msr(APIC_BASE_MSR, &low, &high); - - apic_info.apic_base = 0xfee00000; - apic_info.apic_base_high = low >> 12; - - uint32_t tmp; - DRV_RESULT_PRINT_CALL( - driver_remap_memory, &apic_driver, apic_info.apic_base, 0x3ff, - &tmp); - apic_info.lapic_mmio = (uint32_t *)tmp; - DRV_RESULT_PRINT_CALL( - driver_remap_memory, &apic_driver, 0xfec00000, 0xfff00, &tmp); - apic_info.ioapic = (struct ioapic *)tmp; - - read_msr(X2APIC_ID_MSR, &apic_info.apic_id, &apic_info.apic_id_high); - apic_info.version = (lapic_read(APIC_Ver) & 0xff) | - ((lapic_read(APIC_Ver) >> 16) & 0xff); + mask_8259a(); + x2apic_init(driver); } else if (cpu_check_feature(CPUID_FEAT_APIC)) { - apic_info.apic_type = APIC_TYPE_XAPIC; - apic_info.apic_base = 0xfee00000; - - DRV_RESULT_PRINT_CALL( - driver_remap_memory, &apic_driver, apic_info.apic_base, 0x3ff, - (uint32_t *)&apic_info.lapic_mmio); - DRV_RESULT_PRINT_CALL( - driver_remap_memory, &apic_driver, 0xfec00000, 0xfff00, - (uint32_t *)&apic_info.ioapic); - - apic_info.apic_id = lapic_read(APIC_ID) >> 24; - apic_info.version = (lapic_read(APIC_Ver) & 0xff); - apic_info.max_lvt_entry = (lapic_read(APIC_Ver) >> 16) & 0xff; + mask_8259a(); + xapic_init(driver); } else { return DRIVER_RESULT_DEVICE_NOT_EXIST; } @@ -320,7 +333,7 @@ DriverResult apic_timer_calibrate(Device *device) { lapic_write(APIC_LVT_TIMER, BIN_EN(data, BIT(16))); uint32_t apic_timer_count = lapic_read(APIC_TIMER_CCT); - uint32_t freq = (0xffffffff - apic_timer_count) * (1000 / ms); + uint32_t freq = (0xffffffff - apic_timer_count) / ms * 1000; apic_timer_timer_device.source_frequency = freq; apic_timer_timer_device.min_frequency = DIV_ROUND_UP(freq, 0xffffffff); apic_timer_timer_device.max_frequency = freq; @@ -337,15 +350,13 @@ DriverResult apic_timer_init(Device *device) { } DriverResult apic_start(Device *device) { - /*打了个洞,不过都有APIC了至少得有PIC吧,问题不大 - 所有文档都指明了要先关闭8259A,那就关吧*/ - mask_8259a(); - enable_apic(); return DRIVER_RESULT_OK; } DriverResult apic_timer_start(Device *device) { + register_device_irq(apic_timer_device.irq); + interrupt_enable_irq(apic_timer_device.irq->irq); uint32_t data = lapic_read(APIC_LVT_TIMER); lapic_write(APIC_LVT_TIMER, BIN_DIS(data, BIT(16))); return DRIVER_RESULT_OK; diff --git a/src/arch/x86/drivers/pci.c b/src/arch/x86/drivers/pci.c index 61186e6..5e09aaf 100644 --- a/src/arch/x86/drivers/pci.c +++ b/src/arch/x86/drivers/pci.c @@ -5,7 +5,6 @@ * @version 0.1 * @date 2020-07 */ -#include "kernel/wait_queue.h" #include #include #include @@ -14,6 +13,7 @@ #include #include #include +#include #include #include @@ -109,25 +109,30 @@ void pci_enable_mem_space(struct pci_device *device) { pci_write32(device->bus, device->dev, device->function, 0x04, value); } -void get_pci_device_info( +void fill_pci_device_info( PciDevice *dev, uint8_t bus, uint8_t device, uint8_t func, uint16_t vendorID, uint16_t deviceID, uint32_t classcode, - uint8_t revisionID, uint8_t multifunction) { + uint8_t revisionID, uint8_t multifunction, uint8_t header_type, + uint8_t bist, uint8_t latency_timer, uint8_t cache_line_size) { int i; - dev->bus_num = bus; - dev->dev_num = device; - dev->function_num = func; - dev->vendorID = vendorID; - dev->deviceID = deviceID; - dev->classcode = classcode >> 16; - dev->subclass = (classcode & 0xff00) >> 8; - dev->prog_if = classcode & 0xff; - dev->revisionID = revisionID; - dev->multifunction = multifunction; + dev->bus_num = bus; + dev->dev_num = device; + dev->function_num = func; + dev->vendor_id = vendorID; + dev->device_id = deviceID; + dev->classcode = classcode >> 16; + dev->subclass = (classcode & 0xff00) >> 8; + dev->prog_if = classcode & 0xff; + dev->revisionID = revisionID; + dev->multifunction = multifunction; + dev->header_type = header_type; + dev->bist = bist; + dev->latency_timer = latency_timer; + dev->cache_line_size = cache_line_size; for (i = 0; i < PCI_MAX_BAR; i++) { - dev->bar[i].type = PCI_BAR_TYPE_INVALID; + dev->common.bar[i].type = PCI_BAR_TYPE_INVALID; } dev->irqline = -1; } @@ -160,10 +165,14 @@ uint32_t pci_device_get_io_addr(struct pci_device *dev) { #include #include #include +#include PciDevice pci_devices[PCI_MAX_DEVICE]; +DriverResult pci_driver_init(Driver *driver); DriverResult pci_device_init(Device *device); +DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus); +DriverResult pci_init_bus(BusDriver *bus_driver); DeviceDriverOps pci_driver_ops = { .register_driver_hook = NULL, @@ -179,10 +188,12 @@ DeviceOps pci_device_ops = { BusDriverOps pci_bus_driver_ops = { .register_bus_hook = NULL, .unregister_bus_hook = NULL, + .init = pci_init_bus, }; BusOps pci_bus_ops = { .register_device_hook = NULL, .unregister_device_hook = NULL, + .scan_bus = pci_scan_bus, }; BusControllerDeviceOps pci_controller_ops = { .probe = NULL, @@ -199,6 +210,7 @@ Driver pci_driver = { .name = STRING_INIT("pci driver"), .dependency_count = sizeof(pci_dependencies) / sizeof(DriverDependency), .dependencies = pci_dependencies, + .init = pci_driver_init, }; DeviceDriver pci_device_driver = { .name = STRING_INIT("pci device driver"), @@ -233,44 +245,83 @@ DriverResult pci_device_init(Device *device) { for (i = 0; i < PCI_MAX_DEVICE; i++) { pci_devices[i].status = PCI_DEVICE_STATUS_INVALID; } - wait_queue_wakeup_all(&bus_wqm[BUS_TYPE_PCI]); return DRIVER_RESULT_OK; } -DriverResult pci_probe(Device *device) { - int i, j, k; - bool flag; - // printk("device id\tvendor id\theader " - // "type\tclasscode\tsubclass\tprogif\trevision id\n"); - for (i = 0; i < PCI_MAX_BUS; i++) { - Bus *bus = kmalloc(sizeof(Bus)); - bus->ops = &pci_bus_ops; - flag = false; - for (j = 0; j < PCI_MAX_DEV; j++) { - for (k = 0; k < PCI_MAX_FUNC; k++) { - DriverResult result = pci_scan_device(bus, i, j, k); - if (result == DRIVER_RESULT_DEVICE_NOT_EXIST) { - continue; - } else if (result == DRIVER_RESULT_OK) { - flag = true; - } else if (result == DRIVER_RESULT_NULL_POINTER) { - print_error( - "pci_probe: pci device(%d:%d:%d) alloc failed!\n", i, j, - k); - } - } +DriverResult pci_probe(BusDriver *bus_driver) { + PciDriver *pci_driver; + for (int i = 0; i < PCI_MAX_DEVICE; i++) { + if (pci_devices[i].status == PCI_DEVICE_STATUS_USING && + pci_devices[i].pci_driver != NULL) { + pci_driver = pci_devices[i].pci_driver; + pci_driver->ops->probe(pci_driver, &pci_devices[i]); } - if (flag) { - // 如果该总线下有设备则注册总线 - register_bus(&pci_bus_driver, &pci_device, bus); - } else { - // 如果没有设备则释放内存 - kfree(bus); + } + return DRIVER_RESULT_OK; +} + +DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus) { + int i, j; + PciDevice *pci_device; + for (i = 0; i < PCI_MAX_DEV; i++) { + for (j = 0; j < PCI_MAX_FUNC; j++) { + DriverResult result = + pci_scan_device(bus, bus->bus_num, i, j, &pci_device); + if (result == DRIVER_RESULT_DEVICE_NOT_EXIST) { + continue; + } else if (result == DRIVER_RESULT_NULL_POINTER) { + print_error( + "pci_probe_bus: pci device(%d:%d:%d) alloc failed!\n", + bus->bus_num, i, j); + continue; + } else if (result == DRIVER_RESULT_UNSUPPORT_DEVICE) { + print_error( + "pci_probe_bus: pci device(%d:%d:%d) unsupport! Header " + "Type:%d\n", + bus->bus_num, i, j, pci_device->header_type); + continue; + } + + bus_driver->device_count++; + if (!pci_device->multifunction) { + // 没有多个功能就枚举下一个设备 + break; + } + + if (pci_device->header_type == 1) { // 为PCI-to-PCI桥 + bus_driver->bus_count = + MAX(bus_driver->bus_count, + pci_device->pci2pci_bridge.subordinate_bus_number); + + Bus *new_bus = kmalloc(sizeof(Bus)); + new_bus->ops = &pci_bus_ops; + new_bus->primary_bus = bus; + new_bus->bus_num = + pci_device->pci2pci_bridge.secondary_bus_number; + new_bus->subordinate_bus_num = + pci_device->pci2pci_bridge.subordinate_bus_number; + + register_bus(bus_driver, bus->controller_device, new_bus); + } } } return DRIVER_RESULT_OK; } +DriverResult pci_init_bus(BusDriver *bus_driver) { + pci_bus_driver.bus_count = 1; // 默认只有一个主总线 + + Bus *bus = kmalloc(sizeof(Bus)); + bus->ops = &pci_bus_ops; + bus->bus_num = 0; + bus->subordinate_bus_num = 0; + bus->primary_bus = NULL; + register_bus(&pci_bus_driver, &pci_device, bus); + // printk("device id\tvendor id\theader " + // "type\tclasscode\tsubclass\tprogif\trevision id\n"); + return DRIVER_RESULT_OK; +} + PciDevice *pci_alloc_device(void) { int i; @@ -320,23 +371,32 @@ void get_pci_bar_info(PciDeviceBar *bar, uint32_t addr, uint32_t len) { } DriverResult pci_scan_device( - Bus *bus, uint8_t bus_num, uint8_t device_num, uint8_t function_num) { + Bus *bus, uint8_t bus_num, uint8_t device_num, uint8_t function_num, + PciDevice **out_pci_device) { uint32_t value = pci_read32(bus_num, device_num, function_num, 0); uint16_t vendorID = value & 0xffff; uint16_t deviceID = value >> 16; if (vendorID == 0xffff) { return DRIVER_RESULT_DEVICE_NOT_EXIST; } - value = pci_read32(bus_num, device_num, function_num, 0x0c); - uint8_t header_type = value >> 16; + + value = pci_read32(bus_num, device_num, function_num, 0x0c); + uint8_t bist = value >> 24; + uint8_t multifunction = (value >> 23) & 0x01; + uint8_t header_type = (value >> 16) & 0x7f; + uint8_t latency_timer = value >> 8; + uint8_t cache_line_size = value & 0xff; + value = pci_read32(bus_num, device_num, function_num, 8); uint32_t classcode = value >> 8; uint8_t revisionID = value & 0xff; PciDevice *pci_device = pci_alloc_device(); if (pci_device == NULL) { return DRIVER_RESULT_NULL_POINTER; } + *out_pci_device = pci_device; pci_device->device = NULL; - get_pci_device_info( + fill_pci_device_info( pci_device, bus_num, device_num, function_num, vendorID, deviceID, - classcode, revisionID, header_type); + classcode, revisionID, multifunction, header_type, bist, latency_timer, + cache_line_size); if (header_type == 0x00) { int bar; @@ -349,32 +409,191 @@ DriverResult pci_scan_device( pci_write32(bus_num, device_num, function_num, PCI_BAR(bar), value); if (len != 0 && len != 0xffffffff) { - get_pci_bar_info(&pci_device->bar[bar], value, len); + get_pci_bar_info(&pci_device->common.bar[bar], value, len); + } + } + + value = pci_read32(bus_num, device_num, function_num, 0x28); + pci_device->common.cardbus_cis_pointer = value; + + value = pci_read32(bus_num, device_num, function_num, 0x2c); + pci_device->common.subsystem_id = value >> 16; + pci_device->common.subsystem_vendor_id = value & 0xffff; + + value = pci_read32(bus_num, device_num, function_num, 0x30); + pci_device->common.expension_rom_base_address = value; + + value = pci_read32(bus_num, device_num, function_num, 0x34); + pci_device->common.capabilities_pointer = value & 0xff; + + value = pci_read32(bus_num, device_num, function_num, 0x3c); + pci_device->common.max_latency = value >> 24; + pci_device->common.min_grant = value >> 16; + } else if (header_type == 0x01) { + int bar; + for (bar = 0; bar < 2; bar++) { + value = pci_read32(bus_num, device_num, function_num, PCI_BAR(bar)); + pci_write32( + bus_num, device_num, function_num, PCI_BAR(bar), 0xffffffff); + uint32_t len = + pci_read32(bus_num, device_num, function_num, PCI_BAR(bar)); + pci_write32(bus_num, device_num, function_num, PCI_BAR(bar), value); + + if (len != 0 && len != 0xffffffff) { + get_pci_bar_info(&pci_device->common.bar[bar], value, len); } } - } - value = pci_read32(bus_num, device_num, function_num, 0x3c) & 0xffff; - if ((value & 0xff) > 0 && (value & 0xff) < 32) { - pci_device->irqline = value & 0xff; - pci_device->irqpin = value >> 8; + value = pci_read32(bus_num, device_num, function_num, 0x18); + pci_device->pci2pci_bridge.secondary_latency_timer = value >> 24; + pci_device->pci2pci_bridge.subordinate_bus_number = value >> 16; + pci_device->pci2pci_bridge.secondary_bus_number = value >> 8; + pci_device->pci2pci_bridge.primary_bus_number = value & 0xff; + + value = pci_read32(bus_num, device_num, function_num, 0x1c); + pci_device->pci2pci_bridge.secondary_status = value >> 16; + pci_device->pci2pci_bridge.io_limit = value >> 8; + pci_device->pci2pci_bridge.io_base = value & 0xff; + + value = pci_read32(bus_num, device_num, function_num, 0x20); + pci_device->pci2pci_bridge.memory_limit = value >> 16; + pci_device->pci2pci_bridge.memory_base = value & 0xffff; + + value = pci_read32(bus_num, device_num, function_num, 0x24); + pci_device->pci2pci_bridge.prefetchable_memory_limit = value >> 16; + pci_device->pci2pci_bridge.prefetchable_memory_base = value & 0xffff; + + value = pci_read32(bus_num, device_num, function_num, 0x28); + pci_device->pci2pci_bridge.prefetchable_base_upper = value; + value = pci_read32(bus_num, device_num, function_num, 0x2c); + pci_device->pci2pci_bridge.prefetchable_limit_upper = value; + + value = pci_read32(bus_num, device_num, function_num, 0x30); + pci_device->pci2pci_bridge.io_limit_upper = value >> 16; + pci_device->pci2pci_bridge.io_base_upper = value & 0xffff; + + value = pci_read32(bus_num, device_num, function_num, 0x34); + pci_device->pci2pci_bridge.capabilities_pointer = value & 0xff; + + value = pci_read32(bus_num, device_num, function_num, 0x38); + pci_device->pci2pci_bridge.expension_rom_base_address = value; + + value = pci_read32(bus_num, device_num, function_num, 0x3c); + pci_device->pci2pci_bridge.bridge_control = value >> 16; + } else if (header_type == 0x02) { + value = pci_read32(bus_num, device_num, function_num, 0x10); + pci_device->pci2cardbus_bridge.cardbus_socket_base_address = value; + + value = pci_read32(bus_num, device_num, function_num, 0x14); + pci_device->pci2cardbus_bridge.secondary_status = value >> 16; + pci_device->pci2cardbus_bridge.capabilities_offset = value & 0xff; + + value = pci_read32(bus_num, device_num, function_num, 0x18); + pci_device->pci2cardbus_bridge.cardbus_latency_timer = value >> 24; + pci_device->pci2cardbus_bridge.subordiante_bus_number = value >> 16; + pci_device->pci2cardbus_bridge.cardbus_bus_number = value >> 8; + pci_device->pci2cardbus_bridge.pci_bus_number = value & 0xff; + + value = pci_read32(bus_num, device_num, function_num, 0x1c); + pci_device->pci2cardbus_bridge.memory_base0 = value; + value = pci_read32(bus_num, device_num, function_num, 0x20); + pci_device->pci2cardbus_bridge.memory_limit0 = value; + + value = pci_read32(bus_num, device_num, function_num, 0x24); + pci_device->pci2cardbus_bridge.memory_base1 = value; + value = pci_read32(bus_num, device_num, function_num, 0x28); + pci_device->pci2cardbus_bridge.memory_limit1 = value; + + value = pci_read32(bus_num, device_num, function_num, 0x2c); + pci_device->pci2cardbus_bridge.io_base0 = value; + value = pci_read32(bus_num, device_num, function_num, 0x30); + pci_device->pci2cardbus_bridge.io_limit0 = value; + + value = pci_read32(bus_num, device_num, function_num, 0x34); + pci_device->pci2cardbus_bridge.io_base1 = value; + value = pci_read32(bus_num, device_num, function_num, 0x38); + pci_device->pci2cardbus_bridge.io_limit1 = value; + + value = pci_read32(bus_num, device_num, function_num, 0x40); + pci_device->pci2cardbus_bridge.subsystem_vendor_id = value >> 16; + pci_device->pci2cardbus_bridge.subsystem_device_id = value & 0xffff; + + value = pci_read32(bus_num, device_num, function_num, 0x44); + pci_device->pci2cardbus_bridge.legacy_base_address = value; + + value = pci_read32(bus_num, device_num, function_num, 0x3c); + pci_device->pci2cardbus_bridge.bridge_control = value >> 16; + } else { + print_error("unsupport PCI Header Type: %d\n", header_type); + return DRIVER_RESULT_UNSUPPORT_DEVICE; } + pci_device->irqline = value & 0xff; + pci_device->irqpin = value >> 8; // printk( - // "%#06x\t\t%#06x\t\t%#04x\t\t%#04x\t\t%#04x\t\t%#04x\t%#04x\n", deviceID, - // vendorID, header_type & (uint8_t)(~0x80), dev->classcode, dev->subclass, - // dev->prog_if, revisionID); + // "%#06x\t\t%#06x\t\t%#04x\t\t%#04x\t\t%#04x\t\t%#04x\t%#04x\n", + // deviceID, vendorID, header_type & (uint8_t)(~0x80), dev->classcode, + // dev->subclass, dev->prog_if, revisionID); return DRIVER_RESULT_OK; } -static __init void pci_driver_entry(void) { - register_driver(&pci_driver); +DriverResult pci_set_driver(PciDriver *pci_driver, PciDevice *pci_device) { + if (pci_device->pci_driver == NULL) { + pci_device->pci_driver = pci_driver; + } else { + return DRIVER_RESULT_DEVICE_DRIVER_CONFLICT; + } + return DRIVER_RESULT_OK; +} + +DriverResult pci_match(PciDriver *pci_driver, PciDevice *pci_device) { + if (pci_driver->find_type == FIND_BY_VENDORID_DEVICEID) { + if (pci_device->vendor_id == pci_driver->vendor_device.vendorID && + pci_device->device_id == pci_driver->vendor_device.deviceID) { + pci_device->pci_driver = pci_driver; + DRV_RESULT_DELIVER_CALL(pci_set_driver, pci_driver, pci_device); + } + } else if (pci_driver->find_type == FIND_BY_CLASSCODE_SUBCLASS) { + if (pci_device->classcode == pci_driver->class_subclass.classcode && + pci_device->subclass == pci_driver->class_subclass.subclass) { + pci_device->pci_driver = pci_driver; + DRV_RESULT_DELIVER_CALL(pci_set_driver, pci_driver, pci_device); + } + } else if (pci_driver->find_type == FIND_BY_CLASSCODE_SUBCLASS_PROGIF) { + if (pci_device->classcode == + pci_driver->class_subclass_progif.classcode && + pci_device->subclass == + pci_driver->class_subclass_progif.subclass && + pci_device->prog_if == pci_driver->class_subclass_progif.progif) { + pci_device->pci_driver = pci_driver; + DRV_RESULT_DELIVER_CALL(pci_set_driver, pci_driver, pci_device); + } + } + return DRIVER_RESULT_OK; +} + +DriverResult pci_register_driver(Driver *driver, PciDriver *pci_driver) { + int i; + for (i = 0; i < PCI_MAX_DEVICE; i++) { + pci_match(pci_driver, &pci_devices[i]); + } + + return DRIVER_RESULT_OK; +} + +DriverResult pci_driver_init(Driver *driver) { + check_dependency(&pci_driver); pci_device_driver.bus = pci_dependencies[0].out_bus; + DRV_RESULT_DELIVER_CALL( + register_bus_controller_device, &pci_device_driver, &pci_bus_driver, + &pci_device, &pci_bus_controller_device); + return DRIVER_RESULT_OK; +} + +static __init void pci_initcall(void) { + register_driver(&pci_driver); register_device_driver(&pci_driver, &pci_device_driver); register_bus_driver(&pci_driver, &pci_bus_driver); - register_bus_controller_device( - &pci_device_driver, &pci_bus_driver, &pci_device, - &pci_bus_controller_device); } -driver_initcall(pci_driver_entry); +driver_initcall(pci_initcall); diff --git a/src/arch/x86/drivers/pit.c b/src/arch/x86/drivers/pit.c index 6cf5d97..d064ac7 100644 --- a/src/arch/x86/drivers/pit.c +++ b/src/arch/x86/drivers/pit.c @@ -79,6 +79,7 @@ TimerDevice pit_timer_device = { void register_pit() { register_driver(&pit_driver); + driver_init(&pit_driver); register_device_driver(&pit_driver, &pit_device_driver); register_timer_device(&pit_device_driver, &pit_device, &pit_timer_device); } diff --git a/src/arch/x86/drivers/vesa_display.c b/src/arch/x86/drivers/vesa_display.c index 37df353..1bc95c3 100644 --- a/src/arch/x86/drivers/vesa_display.c +++ b/src/arch/x86/drivers/vesa_display.c @@ -49,6 +49,7 @@ VideoDevice vesa_display_video_device = { void register_vesa_display(void) { register_driver(&vesa_display_driver); + driver_init(&vesa_display_driver); register_device_driver(&vesa_display_driver, &vesa_display_device_driver); register_video_device( &vesa_display_device_driver, &vesa_display_device, diff --git a/src/arch/x86/include/drivers/apic.h b/src/arch/x86/include/drivers/apic.h index d4bed97..99cbaf3 100644 --- a/src/arch/x86/include/drivers/apic.h +++ b/src/arch/x86/include/drivers/apic.h @@ -92,6 +92,6 @@ extern struct Device apic_timer_device; -DriverResult register_apic(void); +void register_apic(void); #endif diff --git a/src/arch/x86/include/drivers/pci.h b/src/arch/x86/include/drivers/pci.h index e789b98..d29af17 100644 --- a/src/arch/x86/include/drivers/pci.h +++ b/src/arch/x86/include/drivers/pci.h @@ -138,37 +138,141 @@ typedef struct PciDeviceBar { uint32_t base_addr; uint32_t length; } PciDeviceBar; + typedef struct PciDevice { Bus *bus; Device *device; + struct PciDriver *pci_driver; + char status; uint8_t bus_num; uint8_t dev_num; uint8_t function_num; - uint16_t vendorID; - uint16_t deviceID; + uint16_t vendor_id; + uint16_t device_id; uint8_t classcode; uint8_t subclass; uint8_t prog_if; uint8_t revisionID; + uint8_t bist; uint8_t multifunction; + uint8_t header_type; + uint8_t latency_timer; + uint8_t cache_line_size; uint8_t irqline; uint8_t irqpin; - PciDeviceBar bar[PCI_MAX_BAR]; + union { + struct { + PciDeviceBar bar[PCI_MAX_BAR]; + + uint32_t cardbus_cis_pointer; + uint16_t subsystem_id; + uint16_t subsystem_vendor_id; + uint32_t expension_rom_base_address; + uint8_t capabilities_pointer; + uint8_t max_latency; + uint8_t min_grant; + } common; + struct { + PciDeviceBar bar[2]; + + uint8_t secondary_latency_timer; + uint8_t secondary_bus_number; + uint8_t subordinate_bus_number; + uint8_t primary_bus_number; + uint16_t secondary_status; + + uint16_t io_base_upper; + uint16_t io_base; + uint16_t io_limit_upper; + uint16_t io_limit; + + uint16_t memory_limit; + uint16_t memory_base; + + uint32_t prefetchable_limit_upper; + uint16_t prefetchable_memory_limit; + uint32_t prefetchable_base_upper; + uint16_t prefetchable_memory_base; + + uint8_t capabilities_pointer; + uint32_t expension_rom_base_address; + uint16_t bridge_control; + } pci2pci_bridge; + struct { + uint32_t cardbus_socket_base_address; + uint16 secondary_status; + uint8_t capabilities_offset; + uint8_t cardbus_latency_timer; + uint8_t subordiante_bus_number; + uint8_t cardbus_bus_number; + uint8_t pci_bus_number; + uint32_t memory_base0; + uint32_t memory_limit0; + uint32_t memory_base1; + uint32_t memory_limit1; + uint32_t io_base0; + uint32_t io_limit0; + uint32_t io_base1; + uint32_t io_limit1; + uint16_t bridge_control; + uint16_t subsystem_vendor_id; + uint16_t subsystem_device_id; + uint32_t legacy_base_address; + } pci2cardbus_bridge; + }; } PciDevice; +typedef struct PciDriverOps { + + DriverResult (*probe)( + struct PciDriver *pci_driver, struct PciDevice *pci_device); +} PciDeviceOps; + +typedef struct PciDriver { + Driver *driver; + DeviceDriver *device_driver; + + enum { + FIND_BY_CLASSCODE_SUBCLASS, + FIND_BY_CLASSCODE_SUBCLASS_PROGIF, + FIND_BY_VENDORID_DEVICEID, + } find_type; + + union { + struct { + uint16_t vendorID; + uint16_t deviceID; + } vendor_device; + struct { + uint8_t classcode; + uint8_t subclass; + } class_subclass; + struct { + uint8_t classcode; + uint8_t subclass; + uint8_t progif; + } class_subclass_progif; + }; + PciDevice *pci_device; + + PciDeviceOps *ops; +} PciDriver; + PciDevice *pci_alloc_device(void); int pci_free_device(PciDevice *dev); -void get_pci_device_info( +void fill_pci_device_info( PciDevice *dev, uint8_t bus, uint8_t device, uint8_t func, uint16_t vendorID, uint16_t deviceID, uint32_t classcode, - uint8_t revisionID, uint8_t multifunction); + uint8_t revisionID, uint8_t multifunction, uint8_t header_type, + uint8_t bist, uint8_t latency_timer, uint8_t cache_line_size); void get_pci_bar_info(PciDeviceBar *bar, uint32_t addr, uint32_t len); DriverResult pci_scan_device( - Bus *bus, uint8_t bus_num, uint8_t device_num, uint8_t function_num); + Bus *bus, uint8_t bus_num, uint8_t device_num, uint8_t function_num, + PciDevice **out_pci_device); #endif \ No newline at end of file diff --git a/src/arch/x86/kernel/descriptor.c b/src/arch/x86/kernel/descriptor.c index 17ff033..922a778 100644 --- a/src/arch/x86/kernel/descriptor.c +++ b/src/arch/x86/kernel/descriptor.c @@ -343,6 +343,7 @@ void do_irq(int irq) { // } else { // pic_eoi(irq); // } + interrupt_eoi(irq); device_irq_handler(irq); irq_table[irq](irq); } diff --git a/src/arch/x86/kernel/func.asm b/src/arch/x86/kernel/func.asm index a8c3c71..f2afebc 100644 --- a/src/arch/x86/kernel/func.asm +++ b/src/arch/x86/kernel/func.asm @@ -85,15 +85,15 @@ EXCEPTION_ENTRY 8,ERROR_CODE EXCEPTION_ENTRY 9,NO_ERROR_CODE EXCEPTION_ENTRY 10,ERROR_CODE EXCEPTION_ENTRY 11,ERROR_CODE -EXCEPTION_ENTRY 12,NO_ERROR_CODE +EXCEPTION_ENTRY 12,ERROR_CODE EXCEPTION_ENTRY 13,ERROR_CODE EXCEPTION_ENTRY 14,ERROR_CODE EXCEPTION_ENTRY 15,NO_ERROR_CODE -EXCEPTION_ENTRY 16,ERROR_CODE +EXCEPTION_ENTRY 16,NO_ERROR_CODE EXCEPTION_ENTRY 17,ERROR_CODE EXCEPTION_ENTRY 18,NO_ERROR_CODE -EXCEPTION_ENTRY 19,ERROR_CODE -EXCEPTION_ENTRY 20,ERROR_CODE +EXCEPTION_ENTRY 19,NO_ERROR_CODE +EXCEPTION_ENTRY 20,NO_ERROR_CODE EXCEPTION_ENTRY 21,NO_ERROR_CODE EXCEPTION_ENTRY 22,NO_ERROR_CODE EXCEPTION_ENTRY 23,ERROR_CODE diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index 9990988..a9ef020 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -1,4 +1,3 @@ -#include "kernel/list.h" #include #include #include @@ -12,6 +11,7 @@ #include #include #include +#include BusDriverOps platform_ops = { .register_bus_hook = NULL, @@ -60,4 +60,6 @@ void platform_init_and_start_devices() { interrupt_dm_start(); // 启动由interrupt_dm选择的中断控制器 DRV_RESULT_PRINT_CALL(init_and_start, &pit_device); DRV_RESULT_PRINT_CALL(init_and_start, &apic_timer_device); + + platform_bus_driver.subdriver.state = SUBDRIVER_STATE_READY; } \ No newline at end of file diff --git a/src/include/driver/timer_dm.h b/src/include/driver/timer_dm.h index 16becbd..f5b92a0 100644 --- a/src/include/driver/timer_dm.h +++ b/src/include/driver/timer_dm.h @@ -54,6 +54,7 @@ DriverResult register_timer_device( DeviceDriver *device_driver, Device *device, TimerDevice *timer_device); DriverResult timer_init(Timer *timer); void timer_irq_handler(Device *device); +int timer_get_schedule_tick(int priority); DriverResult timer_set_frequency(Device *device, uint32_t frequency); void delay_ms(Timer *timer, uint32_t ms); void delay_ms_async(Timer *timer, uint32_t ms); diff --git a/src/include/kernel/bus_driver.h b/src/include/kernel/bus_driver.h index cbf4f87..2a08f06 100644 --- a/src/include/kernel/bus_driver.h +++ b/src/include/kernel/bus_driver.h @@ -6,6 +6,7 @@ #include "kernel/driver_manager.h" #include "kernel/list.h" #include "kernel/wait_queue.h" +#include #define BUS_OPS_CALL(bus, func, ...) \ { \ @@ -28,16 +29,20 @@ struct Bus; typedef struct BusDriverOps { DriverResult (*register_bus_hook)(struct Bus *bus); DriverResult (*unregister_bus_hook)(struct Bus *bus); + + DriverResult (*init)(struct BusDriver *bus_driver); } BusDriverOps; typedef struct BusOps { DriverResult (*register_device_hook)(struct DeviceDriver *device_driver); DriverResult (*unregister_device_hook)(struct DeviceDriver *device_driver); + + DriverResult (*scan_bus)(struct BusDriver *bus_driver, struct Bus *bus); } BusOps; typedef struct BusDriver { // 继承SubDriver特征 - SubDriver driver; + SubDriver subdriver; list_t dm_list; list_t bus_lh; @@ -46,6 +51,9 @@ typedef struct BusDriver { BusType bus_type; DriverState state; + uint32_t bus_count; + uint32_t device_count; + BusDriverOps *ops; void *private_data; @@ -53,15 +61,19 @@ typedef struct BusDriver { } BusDriver; typedef struct Bus { - list_t device_lh; - list_t bus_list; - BusDriver *bus_driver; - Device *controller_device; - BusOps *ops; + list_t device_lh; + list_t bus_list; + BusDriver *bus_driver; + Device *controller_device; + struct Bus *primary_bus; + + uint32_t bus_num; + uint32_t subordinate_bus_num; + + BusOps *ops; } Bus; extern struct BusDriver *bus_drivers[BUS_TYPE_MAX]; -extern wait_queue_manager_t bus_wqm[BUS_TYPE_MAX]; extern struct DriverManager bus_driver_manager; DriverResult register_bus_driver(Driver *driver, BusDriver *bus_driver); diff --git a/src/include/kernel/device_driver.h b/src/include/kernel/device_driver.h index caeca97..3015797 100644 --- a/src/include/kernel/device_driver.h +++ b/src/include/kernel/device_driver.h @@ -29,16 +29,10 @@ typedef struct DeviceDriverOps { DriverResult (*unregister_driver_hook)(struct DeviceDriver *driver); } DeviceDriverOps; -typedef enum { - DRIVER_STATE_UNREGISTERED, // 驱动未注册 - DRIVER_STATE_REGISTERED, // 驱动已注册 - DRIVER_STATE_ACTIVE, // 驱动正在运行 -} DriverState; - struct Bus; typedef struct DeviceDriver { // 继承SubDriver特征 - SubDriver driver; + SubDriver subdriver; list_t bus_list; list_t device_lh; diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index b63f245..ec67ce7 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -1,6 +1,7 @@ #ifndef _DRIVER_H #define _DRIVER_H +#include "kernel/wait_queue.h" #include "stdint.h" #define DRIVER_MAX_NAME_LEN 64 #define DEVICE_MAX_NAME_LEN 64 @@ -114,13 +115,41 @@ void driver_inited(); #include "result.h" +typedef enum DriverResult { + DRIVER_RESULT_OK, + DRIVER_RESULT_TIMEOUT, + DRIVER_RESULT_BUS_DRIVER_ALREADY_EXIST, + DRIVER_RESULT_BUS_DRIVER_NOT_EXIST, + DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST, + DRIVER_RESULT_DEVICE_MANAGER_NOT_EXIST, + DRIVER_RESULT_DEVICE_NOT_EXIST, + DRIVER_RESULT_DEVICE_DRIVER_CONFLICT, + DRIVER_RESULT_DEVICE_DRIVER_HAVE_NO_OPS, + DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS, + DRIVER_RESULT_INVALID_IRQ_NUMBER, + DRIVER_RESULT_OUT_OF_MEMORY, + DRIVER_RESULT_NULL_POINTER, + DRIVER_RESULT_UNSUPPORT_DEVICE, + DRIVER_RESULT_OTHER_ERROR, +} DriverResult; + typedef enum { DRIVER_TYPE_DEVICE_DRIVER = 0, DRIVER_TYPE_BUS_DRIVER, DRIVER_TYPE_MAX, } DriverType; -extern list_t startup_dm_lh; +typedef enum { + DRIVER_STATE_UNREGISTERED, // 驱动未注册 + DRIVER_STATE_UNINITED, // 驱动未初始化 + DRIVER_STATE_ACTIVE, // 驱动正在运行 +} DriverState; + +typedef enum { + SUBDRIVER_STATE_UNREGISTERED, // 子驱动未注册 + SUBDRIVER_STATE_UNREADY, // 子驱动未准备好 + SUBDRIVER_STATE_READY, // 子驱动准备好 +} SubDriverState; // 实体的驱动,管理着一个驱动下的所有类型的抽象驱动 typedef struct Driver { @@ -129,39 +158,34 @@ typedef struct Driver { list_t sub_driver_lh; list_t remapped_memory_lh; + DriverState state; + int dependency_count; struct DriverDenpendency *dependencies; + + DriverResult (*init)(struct Driver *driver); } Driver; struct DriverDenpendency; typedef struct SubDriver { - list_t list; - list_t sub_driver_list; - Driver *driver; - DriverType type; + list_t list; + list_t sub_driver_list; + Driver *driver; + DriverType type; + SubDriverState state; + + wait_queue_manager_t wqm; } SubDriver; -typedef enum DriverResult { - DRIVER_RESULT_OK, - DRIVER_RESULT_TIMEOUT, - DRIVER_RESULT_BUS_DRIVER_ALREADY_EXIST, - DRIVER_RESULT_BUS_DRIVER_NOT_EXIST, - DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST, - DRIVER_RESULT_DEVICE_MANAGER_NOT_EXIST, - DRIVER_RESULT_DEVICE_NOT_EXIST, - DRIVER_RESULT_DEVICE_DRIVER_HAVE_NO_OPS, - DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS, - DRIVER_RESULT_INVALID_IRQ_NUMBER, - DRIVER_RESULT_OUT_OF_MEMORY, - DRIVER_RESULT_NULL_POINTER, - DRIVER_RESULT_UNSUPPORT_DEVICE, - DRIVER_RESULT_OTHER_ERROR, -} DriverResult; +extern list_t startup_dm_lh; DriverResult register_driver(Driver *driver); DriverResult unregister_driver(Driver *driver); -DriverResult register_sub_driver(Driver *driver, SubDriver *sub_driver); +DriverResult register_sub_driver( + Driver *driver, SubDriver *sub_driver, DriverType type); DriverResult unregister_sub_driver(Driver *driver, SubDriver *sub_driver); +DriverResult driver_init(Driver *driver); +DriverResult driver_start_all(void); void print_driver_result( DriverResult result, char *file, int line, char *func_with_args); diff --git a/src/kernel/bus_driver.c b/src/kernel/bus_driver.c index 245df72..9320c9f 100644 --- a/src/kernel/bus_driver.c +++ b/src/kernel/bus_driver.c @@ -5,6 +5,7 @@ #include #include #include +#include BusDriver *bus_drivers[BUS_TYPE_MAX]; wait_queue_manager_t bus_wqm[BUS_TYPE_MAX]; @@ -55,9 +56,12 @@ DriverResult register_bus_driver(Driver *driver, BusDriver *bus_driver) { if (_bus_driver != NULL) return DRIVER_RESULT_BUS_DRIVER_ALREADY_EXIST; bus_driver->private_data = kmalloc(bus_driver->private_data_size); - bus_driver->state = DRIVER_STATE_REGISTERED; + bus_driver->state = DRIVER_STATE_UNINITED; + list_init(&bus_driver->bus_lh); - DRV_RESULT_DELIVER_CALL(register_sub_driver, driver, &bus_driver->driver); + DRV_RESULT_DELIVER_CALL( + register_sub_driver, driver, &bus_driver->subdriver, + DRIVER_TYPE_BUS_DRIVER); bus_drivers[bus_driver->bus_type] = bus_driver; @@ -79,7 +83,8 @@ DriverResult unregister_bus_driver(Driver *driver, BusType type) { unregister_bus(cur); } - DRV_RESULT_DELIVER_CALL(unregister_sub_driver, driver, &bus_driver->driver); + DRV_RESULT_DELIVER_CALL( + unregister_sub_driver, driver, &bus_driver->subdriver); bus_driver->state = DRIVER_STATE_UNREGISTERED; if (bus_driver->private_data != NULL) kfree(bus_driver->private_data); @@ -91,6 +96,15 @@ DriverResult register_bus( BusDriver *bus_driver, Device *bus_controller_device, Bus *bus) { if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + Bus *primary_bus = bus->primary_bus; + Bus *tmp_bus = bus; + while (primary_bus != NULL) { + primary_bus->subordinate_bus_num = + MAX(primary_bus->subordinate_bus_num, tmp_bus->subordinate_bus_num); + tmp_bus = primary_bus; + primary_bus = primary_bus->primary_bus; + } + bus->bus_driver = bus_driver; bus->controller_device = bus_controller_device; list_init(&bus->device_lh); diff --git a/src/kernel/device.c b/src/kernel/device.c index 5ae3a68..4f474c1 100644 --- a/src/kernel/device.c +++ b/src/kernel/device.c @@ -42,6 +42,7 @@ DriverResult start_device(Device *device) { DeviceManager *manager = device_managers[device->device_driver->type]; DEV_OPS_CALL(device, start, device); DEVM_OPS_CALL(manager, start_device_hook, manager, device); + device->device_driver->subdriver.state = SUBDRIVER_STATE_READY; return DRIVER_RESULT_OK; } diff --git a/src/kernel/device_driver.c b/src/kernel/device_driver.c index e4d4350..979d8de 100644 --- a/src/kernel/device_driver.c +++ b/src/kernel/device_driver.c @@ -1,9 +1,9 @@ -#include "kernel/device.h" -#include "kernel/list.h" +#include #include #include #include #include +#include #include DriverResult device_driver_manager_load(DriverManager *driver_manager); @@ -62,12 +62,15 @@ DriverResult register_device_driver( list_init(&device_driver->device_lh); device_driver->private_data = kmalloc(device_driver->private_data_size); - device_driver->state = DRIVER_STATE_REGISTERED; + device_driver->state = DRIVER_STATE_UNINITED; DM_OPS_CALL(manager, register_device_driver_hook, manager, device_driver); DRV_RESULT_DELIVER_CALL( - register_sub_driver, driver, &device_driver->driver); + register_sub_driver, driver, &device_driver->subdriver, + DRIVER_TYPE_DEVICE_DRIVER); + + device_driver->state = DRIVER_STATE_ACTIVE; return DRIVER_RESULT_OK; } @@ -79,7 +82,7 @@ DriverResult unregister_device_driver( if (manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; DRV_RESULT_DELIVER_CALL( - unregister_sub_driver, driver, &device_driver->driver); + unregister_sub_driver, driver, &device_driver->subdriver); DM_OPS_CALL(manager, unregister_device_driver_hook, manager, device_driver); diff --git a/src/kernel/driver.c b/src/kernel/driver.c index 5a5136d..7d527f0 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -5,13 +5,14 @@ * @version 0.3 * @date 2022-07-20 */ -#include "kernel/driver_dependency.h" -#include #include #include +#include #include #include #include +#include +#include #include #include #include @@ -56,6 +57,7 @@ void print_driver_result( switch (result) { RESULT_CASE_PRINT(DRIVER_RESULT_OK) RESULT_CASE_PRINT(DRIVER_RESULT_TIMEOUT) + RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_DRIVER_CONFLICT) RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_DRIVER_HAVE_NO_OPS) RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS) RESULT_CASE_PRINT(DRIVER_RESULT_INVALID_IRQ_NUMBER) @@ -72,10 +74,11 @@ void print_driver_result( } DriverResult register_driver(Driver *driver) { + + driver->state = DRIVER_STATE_UNINITED; list_init(&driver->sub_driver_lh); list_init(&driver->remapped_memory_lh); list_add_tail(&driver->driver_list, &driver_lh); - check_dependency(driver); return DRIVER_RESULT_OK; } @@ -84,8 +87,11 @@ DriverResult unregister_driver(Driver *driver) { return DRIVER_RESULT_OK; } -DriverResult register_sub_driver(Driver *driver, SubDriver *sub_driver) { +DriverResult register_sub_driver( + Driver *driver, SubDriver *sub_driver, DriverType type) { sub_driver->driver = driver; + sub_driver->state = SUBDRIVER_STATE_UNREADY; + sub_driver->type = type; list_add(&sub_driver->sub_driver_list, &driver->sub_driver_lh); @@ -98,6 +104,78 @@ DriverResult unregister_sub_driver(Driver *driver, SubDriver *sub_driver) { return DRIVER_RESULT_OK; } +DriverResult driver_init(Driver *driver) { + DriverResult result; + if (driver->init != NULL) { + result = driver->init(driver); + if (result != DRIVER_RESULT_OK) { + driver->state = DRIVER_STATE_UNREGISTERED; + unregister_driver(driver); + print_error( + "driver_init: driver %s init failed!\n", driver->name.text); + return result; + } + } + driver->state = DRIVER_STATE_ACTIVE; + return DRIVER_RESULT_OK; +} + +void sub_driver_start_thread(void *arg) { + SubDriver *sub_driver = arg; + if (sub_driver->type == DRIVER_TYPE_DEVICE_DRIVER) { + DeviceDriver *device_driver = + container_of(sub_driver, DeviceDriver, subdriver); + Device *device; + list_for_each_owner (device, &device_driver->device_lh, device_list) { + if (device->ops->init != NULL) { device->ops->init(device); } + if (device->ops->start != NULL) { device->ops->start(device); } + } + device_driver->subdriver.state = SUBDRIVER_STATE_READY; + } else if (sub_driver->type == DRIVER_TYPE_BUS_DRIVER) { + BusDriver *bus_driver = container_of(sub_driver, BusDriver, subdriver); + if (bus_driver->ops->init != NULL) { + bus_driver->ops->init(bus_driver); + } + + Bus *bus; + list_for_each_owner (bus, &bus_driver->bus_lh, bus_list) { + // 先等待Bus Controller Device就绪 + while (bus->controller_device->device_driver->subdriver.state != + SUBDRIVER_STATE_READY) { + schedule(); + } + if (bus->ops->scan_bus != NULL) { + bus->ops->scan_bus(bus_driver, bus); + } + } + } +} + +void driver_start_thread(void *arg) { + Driver *driver = arg; + check_dependency(driver); + driver_init(driver); + + SubDriver *sub_driver; + list_for_each_owner (sub_driver, &driver->sub_driver_lh, sub_driver_list) { + thread_start( + "sub_driver_start_thread", THREAD_DEFAULT_PRIO, + sub_driver_start_thread, sub_driver); + } +} + +DriverResult driver_start_all(void) { + Driver *driver; + list_for_each_owner (driver, &driver_lh, driver_list) { + if (driver->state == DRIVER_STATE_UNINITED) { + thread_start( + "driver_start_thread", THREAD_DEFAULT_PRIO, driver_start_thread, + driver); + } + } + return DRIVER_RESULT_OK; +} + // --------old--------- struct index_node *dev_open(char *path) { struct index_node *inode = vfs_open(path); @@ -133,21 +211,21 @@ status_t driver_create(driver_func_t func, char *driver_name) { driver_t *drv_obj; int status; - drv_obj = kmalloc(sizeof(driver_t)); - if (drv_obj == NULL) { return FAILED; } - if (func.driver_enter == NULL) { return FAILED; } - list_init(&drv_obj->device_list); - list_init(&drv_obj->list); - drv_obj->function = func; - status = drv_obj->function.driver_enter(drv_obj); - if (status == NODEV) { - printk("[driver manager]Cannot found device:%s\n", driver_name); - } else if (status != SUCCUESS) { - return FAILED; - } - string_init(&drv_obj->name); - string_new(&drv_obj->name, driver_name, DRIVER_MAX_NAME_LEN); - list_add_tail(&drv_obj->list, &driver_list_head); + // drv_obj = kmalloc(sizeof(driver_t)); + // if (drv_obj == NULL) { return FAILED; } + // if (func.driver_enter == NULL) { return FAILED; } + // list_init(&drv_obj->device_list); + // list_init(&drv_obj->list); + // drv_obj->function = func; + // status = drv_obj->function.driver_enter(drv_obj); + // if (status == NODEV) { + // printk("[driver manager]Cannot found device:%s\n", driver_name); + // } else if (status != SUCCUESS) { + // return FAILED; + // } + // string_init(&drv_obj->name); + // string_new(&drv_obj->name, driver_name, DRIVER_MAX_NAME_LEN); + // list_add_tail(&drv_obj->list, &driver_list_head); return SUCCUESS; } diff --git a/src/kernel/driver_dependency.c b/src/kernel/driver_dependency.c index c049b36..1d0a8f2 100644 --- a/src/kernel/driver_dependency.c +++ b/src/kernel/driver_dependency.c @@ -1,10 +1,10 @@ -#include "kernel/list.h" -#include "kernel/thread.h" -#include "kernel/wait_queue.h" #include #include #include #include +#include +#include +#include DriverResult check_dependency(Driver *driver) { int count = driver->dependency_count; @@ -18,8 +18,10 @@ DriverResult check_dependency(Driver *driver) { Bus *bus; BusDriver *bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; - if (bus_driver == NULL) { // 总线驱动还没初始化 - wait_queue_add(&bus_wqm[deps[i].dependency_in_bus.type], 0); + if (bus_driver == NULL || + bus_driver->subdriver.state != SUBDRIVER_STATE_READY) { + // 总线驱动还没准备好则等待 + wait_queue_add(&bus_driver->subdriver.wqm, 0); thread_block(TASK_BLOCKED); bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; } diff --git a/src/kernel/initcall.c b/src/kernel/initcall.c index 2bc83b3..69b6b9e 100644 --- a/src/kernel/initcall.c +++ b/src/kernel/initcall.c @@ -8,6 +8,7 @@ */ #include #include +#include extern initcall_t __initcall_start[]; extern initcall_t __initcall_end[]; @@ -15,12 +16,10 @@ extern exitcall_t __exitcall_start[]; extern exitcall_t __exitcall_end[]; void do_initcalls(void) { - init_dm(); initcall_t *func = &(*__initcall_start); for (; func < &(*__initcall_end); func++) { (*func)(); } - // driver_inited(); } void do_exitcalls(void) { diff --git a/src/kernel/main.c b/src/kernel/main.c index 574c6ac..3449f4a 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -4,9 +4,9 @@ * @brief 内核主程序 * @date 2020-03 */ -#include "driver/video_dm.h" #include #include +#include #include #include #include @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,7 @@ #include #include #include +#include void idle(void *arg); struct task_s *task_idle; @@ -49,10 +51,11 @@ int main() { init_task(); task_idle = thread_start("Idle", 1, idle, 0); // init_pci(); - // io_sti(); + io_sti(); printk("Memory Size:%dM\n", get_memory_size()); // init_vfs(); do_initcalls(); + driver_start_all(); // init_fs(); // thread_start( @@ -102,8 +105,10 @@ int main() { } } +extern uint32_t lapic_read(int index); + void idle(void *arg) { for (;;) { - io_hlt(); + enable_interrupt(); } } From 8617a24d244937646fca12c43256b53944987306 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 13 Dec 2024 22:01:00 +0800 Subject: [PATCH 007/158] update --- src/arch/x86/drivers/8042.c | 29 ++++++++++----- src/arch/x86/drivers/8259a.c | 2 +- src/arch/x86/drivers/acpi.c | 2 +- src/arch/x86/drivers/usb/func.c | 2 +- src/arch/x86/drivers/usb/hci/uhci/skeleton.c | 2 +- src/arch/x86/drivers/usb/hub.c | 3 +- src/arch/x86/drivers/vesa_display.c | 2 +- src/driver/bus_dm.c | 2 +- src/driver/video.c | 2 +- src/kernel/console.c | 3 +- src/network/ipv4.c | 29 +++++++++------ src/network/network.c | 38 +++++++++++++------- src/network/tcp.c | 8 ++--- 13 files changed, 79 insertions(+), 45 deletions(-) diff --git a/src/arch/x86/drivers/8042.c b/src/arch/x86/drivers/8042.c index 56490dc..f5e3a82 100644 --- a/src/arch/x86/drivers/8042.c +++ b/src/arch/x86/drivers/8042.c @@ -5,13 +5,14 @@ * @version 0.1 * @date 2021-06 */ -#include "kernel/driver.h" #include #include +#include #include #include #include + static status_t i8042_enter(driver_t *drv_obj); static status_t i8042_exit(driver_t *drv_obj); @@ -42,7 +43,8 @@ int i8042_get_status(uint8_t type) { void i8042_wait_ctr_send_ready(void) { for (;;) { - if ((io_in8(I8042_PORT_STAT) & I8042_STAT_INBUF) == 0) { // 输入缓存区为空 + if ((io_in8(I8042_PORT_STAT) & I8042_STAT_INBUF) == + 0) { // 输入缓存区为空 return; } } @@ -65,7 +67,8 @@ static status_t i8042_enter(driver_t *drv_obj) { device_t *devobj; device_extension_t *devext; - device_create(drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_MANAGER, &devobj); + device_create( + drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_MANAGER, &devobj); devext = devobj->device_extension; // 1.禁用设备 @@ -74,7 +77,9 @@ static status_t i8042_enter(driver_t *drv_obj) { // 2.配置控制器 i8042_send_cmd(I8042_CMD_WRITE); - i8042_write_data(I8042_CFG_TRANS1 | I8042_CFG_SYS_FLAG | I8042_CFG_INT2 | I8042_CFG_INT1); + i8042_write_data( + I8042_CFG_TRANS1 | I8042_CFG_SYS_FLAG | I8042_CFG_INT2 | + I8042_CFG_INT1); // 3.控制器自检 i8042_send_cmd(I8042_CMD_TEST_CTL); @@ -123,7 +128,9 @@ static status_t i8042_enter(driver_t *drv_obj) { i8042_write_data(I8042_CMD_RESET_DEV); for (i = 0; i < 2; i++) { - if (i8042_read_data() == 0xfc) { printk("[i8042]PS/2 Port1 Device reset failed!\n"); } + if (i8042_read_data() == 0xfc) { + printk("[i8042]PS/2 Port1 Device reset failed!\n"); + } } if (i8042_get_status(I8042_STAT_OUTBUF)) { devext->p1_dev_type = i8042_read_data(); @@ -146,7 +153,9 @@ static status_t i8042_enter(driver_t *drv_obj) { i8042_write_data(I8042_CMD_RESET_DEV); for (i = 0; i < 2; i++) { - if (i8042_read_data() == 0xfc) { printk("[i8042]PS/2 Port1 Device reset failed!\n"); } + if (i8042_read_data() == 0xfc) { + printk("[i8042]PS/2 Port1 Device reset failed!\n"); + } } if (i8042_get_status(I8042_STAT_OUTBUF)) { devext->p2_dev_type = i8042_read_data(); @@ -154,9 +163,13 @@ static status_t i8042_enter(driver_t *drv_obj) { printk("[i8042]Found PS/2 device 2.Type: Mouse\n"); i8042_send_cmd(I8042_CMD_SEND_TO_P2); i8042_write_data(0xf4); - if (i8042_read_data() != 0xfa) { printk("[i8042]PS/2 Port2 Device: mouse enable failed!\n"); } + if (i8042_read_data() != 0xfa) { + printk("[i8042]PS/2 Port2 Device: mouse enable failed!\n"); + } } else { - printk("[i8042]Found PS/2 device 2.Type: %#0X\n", devext->p2_dev_type); + printk( + "[i8042]Found PS/2 device 2.Type: %#0X\n", + devext->p2_dev_type); } } else { // AT键盘没有设备类型的响应 devext->p2_dev_type = 0xff; diff --git a/src/arch/x86/drivers/8259a.c b/src/arch/x86/drivers/8259a.c index e75214f..1fc4e35 100644 --- a/src/arch/x86/drivers/8259a.c +++ b/src/arch/x86/drivers/8259a.c @@ -6,7 +6,6 @@ * @date 2022-07-31 * */ -#include "string.h" #include #include #include @@ -21,6 +20,7 @@ #include #include #include +#include DriverResult pic_init(Device *device); int pic_redirect_irq(InterruptDevice *device, int irq); diff --git a/src/arch/x86/drivers/acpi.c b/src/arch/x86/drivers/acpi.c index fb84372..de3769e 100644 --- a/src/arch/x86/drivers/acpi.c +++ b/src/arch/x86/drivers/acpi.c @@ -5,13 +5,13 @@ * @version 0.1 * @date 2021-06 */ -#include "kernel/memory.h" #include #include #include #include #include #include +#include #include #include #include diff --git a/src/arch/x86/drivers/usb/func.c b/src/arch/x86/drivers/usb/func.c index 9cacad5..d665e85 100644 --- a/src/arch/x86/drivers/usb/func.c +++ b/src/arch/x86/drivers/usb/func.c @@ -1,7 +1,7 @@ -#include "kernel/list.h" #include #include #include +#include #include #include diff --git a/src/arch/x86/drivers/usb/hci/uhci/skeleton.c b/src/arch/x86/drivers/usb/hci/uhci/skeleton.c index 0933721..0de1700 100644 --- a/src/arch/x86/drivers/usb/hci/uhci/skeleton.c +++ b/src/arch/x86/drivers/usb/hci/uhci/skeleton.c @@ -1,7 +1,7 @@ -#include "stdint.h" #include #include #include +#include void uhci_skel_init(uhci_t *devext) { int i; diff --git a/src/arch/x86/drivers/usb/hub.c b/src/arch/x86/drivers/usb/hub.c index 1ccce43..318b2a4 100644 --- a/src/arch/x86/drivers/usb/hub.c +++ b/src/arch/x86/drivers/usb/hub.c @@ -1,5 +1,4 @@ -#include "bits.h" -#include "drivers/usb/uhci.h" +#include #include #include #include diff --git a/src/arch/x86/drivers/vesa_display.c b/src/arch/x86/drivers/vesa_display.c index 1bc95c3..99486d3 100644 --- a/src/arch/x86/drivers/vesa_display.c +++ b/src/arch/x86/drivers/vesa_display.c @@ -1,6 +1,6 @@ -#include "drivers/video.h" #include #include +#include #include #include #include diff --git a/src/driver/bus_dm.c b/src/driver/bus_dm.c index c145a7d..6e08a6d 100644 --- a/src/driver/bus_dm.c +++ b/src/driver/bus_dm.c @@ -1,5 +1,5 @@ -#include "kernel/bus_driver.h" #include +#include #include #include #include diff --git a/src/driver/video.c b/src/driver/video.c index fe8102f..18d8897 100644 --- a/src/driver/video.c +++ b/src/driver/video.c @@ -1,4 +1,4 @@ -#include "driver/video.h" +#include #include #include diff --git a/src/kernel/console.c b/src/kernel/console.c index 1654645..31f2a1b 100644 --- a/src/kernel/console.c +++ b/src/kernel/console.c @@ -5,8 +5,8 @@ * @version 0.3 * @date 2022-07-15 */ -#include "driver/video_dm.h" #include +#include #include #include #include @@ -15,6 +15,7 @@ #include #include + struct console { struct VideoDevice *video_device; diff --git a/src/network/ipv4.c b/src/network/ipv4.c index d193aed..77e3964 100644 --- a/src/network/ipv4.c +++ b/src/network/ipv4.c @@ -1,4 +1,3 @@ -#include "network/netpack.h" #include #include #include @@ -6,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -26,8 +26,9 @@ void ipv4_init(net_device_t *netdev) { data->mtu -= 20; // 去掉ip头的长度 } -void ipv4_send_pack(netc_t *netc, uint8_t *dst_ip, uint8_t flags, uint8_t id, uint8_t ttl, uint8_t protocol, - uint8_t offset, uint8_t *data, uint16_t datalen) { +void ipv4_send_pack( + netc_t *netc, uint8_t *dst_ip, uint8_t flags, uint8_t id, uint8_t ttl, + uint8_t protocol, uint8_t offset, uint8_t *data, uint16_t datalen) { int i; uint32_t chksum = 0; ipv4_header_t *header; @@ -53,15 +54,17 @@ void ipv4_send_pack(netc_t *netc, uint8_t *dst_ip, uint8_t flags, uint8_t id, ui for (i = 0; i < 20 / sizeof(uint16_t); i++) { chksum += BE2HOST_WORD(buf[i]); } - header->HeaderChecksum = HOST2BE_WORD(~(uint16_t)((chksum & 0xffff) + (chksum >> 16))); + header->HeaderChecksum = + HOST2BE_WORD(~(uint16_t)((chksum & 0xffff) + (chksum >> 16))); net_dev->net_write(netc, (uint8_t *)buf, datalen + 20); kfree(buf); } -int ipv4_send(netc_t *netc, uint8_t *dst_ip, uint8_t DF, uint8_t ttl, uint8_t protocol, uint8_t *data, - uint32_t datalen) { +int ipv4_send( + netc_t *netc, uint8_t *dst_ip, uint8_t DF, uint8_t ttl, uint8_t protocol, + uint8_t *data, uint32_t datalen) { uint32_t i, id; uint32_t len; net_device_t *net_dev = netc->net_dev; @@ -78,14 +81,18 @@ int ipv4_send(netc_t *netc, uint8_t *dst_ip, uint8_t DF, uint8_t ttl, uint8_t pr while (len > ipv4->mtu) { if (DF) { return -1; } // 不允许分片则直接退出 - ipv4_send_pack(netc, dst_ip, 1, id, ttl, protocol, i * ipv4->mtu, data, ipv4->mtu); + ipv4_send_pack( + netc, dst_ip, 1, id, ttl, protocol, i * ipv4->mtu, data, ipv4->mtu); i++; } - ipv4_send_pack(netc, dst_ip, 0, id, ttl, protocol, i * ipv4->mtu, data, datalen % ipv4->mtu); + ipv4_send_pack( + netc, dst_ip, 0, id, ttl, protocol, i * ipv4->mtu, data, + datalen % ipv4->mtu); return 0; } -void ipv4_read(net_rx_pack_t *pack, uint8_t *buf, uint16_t offset, uint16_t length) { +void ipv4_read( + net_rx_pack_t *pack, uint8_t *buf, uint16_t offset, uint16_t length) { ipv4_header_t *header = (ipv4_header_t *)(buf + offset); header->HeaderChecksum = BE2HOST_WORD(header->HeaderChecksum); @@ -95,7 +102,9 @@ void ipv4_read(net_rx_pack_t *pack, uint8_t *buf, uint16_t offset, uint16_t leng switch (header->Protocol) { case PROTOCOL_TCP: - net_raw2tcp_pack(pack, 4, header->SourceAddress, offset + 20, header->TotalLength - 20); + net_raw2tcp_pack( + pack, 4, header->SourceAddress, offset + 20, + header->TotalLength - 20); break; case PROTOCOL_UDP: net_raw2udp_pack(pack, offset + 20, header->TotalLength - 20); diff --git a/src/network/network.c b/src/network/network.c index 074802e..b6f03c8 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -1,19 +1,18 @@ -#include "kernel/spinlock.h" -#include "network/tcp.h" -#include "network/udp.h" -#include "stdint.h" #include #include #include #include #include #include +#include #include #include #include #include #include #include +#include +#include LIST_HEAD(net_rx_raw_pack_lh); LIST_HEAD(net_rx_tcp_lh); @@ -30,7 +29,8 @@ void init_network(void) { list_init(ð_dm.dev_listhead); } -netc_t *netc_create(net_device_t *net_dev, uint16_t protocol, uint16_t app_protocol) { +netc_t *netc_create( + net_device_t *net_dev, uint16_t protocol, uint16_t app_protocol) { netc_t *netc = kmalloc(sizeof(netc_t)); spinlock_init(&netc->spin_lock); @@ -54,9 +54,13 @@ int netc_delete(netc_t *netc) { return 0; } -void netc_set_dest(netc_t *netc, uint8_t dst_mac[6], uint8_t *dst_laddr, uint8_t dst_laddr_len) { +void netc_set_dest( + netc_t *netc, uint8_t dst_mac[6], uint8_t *dst_laddr, + uint8_t dst_laddr_len) { memcpy(netc->dst_mac, dst_mac, 6); - if (dst_laddr != NULL) { memcpy(netc->dst_laddr, dst_laddr, dst_laddr_len); } + if (dst_laddr != NULL) { + memcpy(netc->dst_laddr, dst_laddr, dst_laddr_len); + } } int netc_read(netc_t *netc, uint8_t *buf, uint32_t size) { @@ -82,8 +86,12 @@ void netc_drop_all(netc_t *netc) { netc->recv_len = 0; } -void netc_ip_send(netc_t *netc, uint8_t *ip, uint8_t DF, uint8_t proto, uint8_t *buf, uint32_t size) { - if (netc->protocol == ETH_TYPE_IPV4) { ipv4_send(netc, ip, DF, default_ttl, proto, buf, size); } +void netc_ip_send( + netc_t *netc, uint8_t *ip, uint8_t DF, uint8_t proto, uint8_t *buf, + uint32_t size) { + if (netc->protocol == ETH_TYPE_IPV4) { + ipv4_send(netc, ip, DF, default_ttl, proto, buf, size); + } } int netc_get_mtu(netc_t *netc) { @@ -100,7 +108,8 @@ void net_process_pack(void *arg) { net_rx_pack_t *pack_cur, *next; while (1) { if (!list_empty(&net_rx_raw_pack_lh)) { - list_for_each_owner_safe (pack_cur, next, &net_rx_raw_pack_lh, list) { + list_for_each_owner_safe ( + pack_cur, next, &net_rx_raw_pack_lh, list) { list_del(&pack_cur->list); switch (pack_cur->type) { case ETH_FRAME: @@ -112,8 +121,9 @@ void net_process_pack(void *arg) { } list_for_each_owner_safe (pack_cur, next, &net_rx_tcp_lh, list) { list_del(&pack_cur->list); - tcp_recv(pack_cur->data, pack_cur->proto_start, pack_cur->data_len, pack_cur->src_ip_addr, - pack_cur->src_ip_len); + tcp_recv( + pack_cur->data, pack_cur->proto_start, pack_cur->data_len, + pack_cur->src_ip_addr, pack_cur->src_ip_len); } // kfree(pack_cur->data); kfree(pack_cur); @@ -132,7 +142,9 @@ void net_rx_raw_pack(enum frame_type type, uint8_t *buf, uint32_t length) { list_add_tail(&pack->list, &net_rx_raw_pack_lh); } -void net_raw2tcp_pack(net_rx_pack_t *pack, uint8_t ip_len, uint8_t *ip_addr, uint32_t start, uint32_t len) { +void net_raw2tcp_pack( + net_rx_pack_t *pack, uint8_t ip_len, uint8_t *ip_addr, uint32_t start, + uint32_t len) { pack->proto_start = start; pack->src_ip_len = ip_len; pack->src_ip_addr = ip_addr; diff --git a/src/network/tcp.c b/src/network/tcp.c index 4f5b309..2419e89 100644 --- a/src/network/tcp.c +++ b/src/network/tcp.c @@ -1,12 +1,12 @@ -#include "driver/timer_dm.h" -#include "kernel/list.h" -#include "kernel/memory.h" -#include "network/netpack.h" #include +#include #include #include +#include +#include #include #include +#include #include #include #include From 2588342b7f053fb6ca86ce250dc85a47086bdcbf Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 13 Dec 2024 23:44:33 +0800 Subject: [PATCH 008/158] =?UTF-8?q?[WIP]=E6=96=B0=E5=A2=9E=E7=AD=89?= =?UTF-8?q?=E5=BE=85=E7=BA=BF=E7=A8=8B=E9=80=80=E5=87=BA=E6=9C=BA=E5=88=B6?= =?UTF-8?q?=EF=BC=9B=E6=94=B9=E4=B8=BA=E7=AD=89=E5=BE=85=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E5=AE=8C=E6=88=90=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E6=89=A7=E8=A1=8C=EF=BC=9B=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?tab=E8=BE=93=E5=87=BA=E5=BC=82=E5=B8=B8=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/Makefile | 12 +- src/arch/x86/drivers/pci.c | 263 ++++++++++++-------------- src/arch/x86/include/drivers/pci.h | 100 +++------- src/arch/x86/include/kernel/thread.h | 3 + src/include/kernel/driver_interface.h | 4 +- src/kernel/console.c | 8 +- src/kernel/driver.c | 21 +- src/kernel/thread.c | 8 + 8 files changed, 196 insertions(+), 223 deletions(-) diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index 6b8a832..9cd84c0 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -6,13 +6,13 @@ SRC += cpufreq.c SRC += disk.c SRC += pci.c SRC += dma.c -SRC += ide.c -SRC += keyboard.c -SRC += mouse.c +#SRC += ide.c +#SRC += keyboard.c +#SRC += mouse.c SRC += msr.c SRC += pit.c SRC += smbios.c SRC += vesa_display.c -SRC += network/ -SRC += sound/ -SRC += usb/ \ No newline at end of file +#SRC += network/ +#SRC += sound/ +#SRC += usb/ \ No newline at end of file diff --git a/src/arch/x86/drivers/pci.c b/src/arch/x86/drivers/pci.c index 5e09aaf..f31b64e 100644 --- a/src/arch/x86/drivers/pci.c +++ b/src/arch/x86/drivers/pci.c @@ -36,130 +36,6 @@ // } // } -PCI_READ(8, uint8_t) -PCI_READ(16, uint16_t) -PCI_READ(32, uint32_t) -PCI_WRITE(8, uint8_t) -PCI_WRITE(16, uint16_t) -PCI_WRITE(32, uint32_t) -PCI_READ_DEVICE(8, uint8_t) -PCI_READ_DEVICE(16, uint16_t) -PCI_READ_DEVICE(32, uint32_t) -PCI_WRITE_DEVICE(8, uint8_t) -PCI_WRITE_DEVICE(16, uint16_t) -PCI_WRITE_DEVICE(32, uint32_t) - -// struct pci_device *pci_get_device_ById(uint16_t vendorID, uint16_t deviceID) -// { int i; struct pci_device *device; - -// for (i = 0; i < PCI_MAX_DEVICE; i++) { -// device = &pci_devices[i]; -// if (device->vendorID == vendorID && device->deviceID == deviceID) { -// return device; -// } -// } -// return NULL; -// } - -// struct pci_device *pci_get_device_ByClassFull( -// uint8_t classcode, uint8_t subclass, uint8_t progif) { -// int i; -// struct pci_device *device; - -// for (i = 0; i < PCI_MAX_DEVICE; i++) { -// device = &pci_devices[i]; -// if (device->classcode == classcode && device->subclass == subclass && -// device->prog_if == progif) { -// return device; -// } -// } -// return NULL; -// } - -// struct pci_device *pci_get_device_ByClass(uint8_t classcode, uint8_t -// subclass) { int i; struct pci_device *device; - -// for (i = 0; i < PCI_MAX_DEVICE; i++) { -// device = &pci_devices[i]; -// if (device->classcode == classcode && device->subclass == subclass) { -// return device; -// } -// } -// return NULL; -// } - -void pci_enable_bus_mastering(struct pci_device *device) { - uint32_t value = - pci_read32(device->bus, device->dev, device->function, 0x04); - value |= 4; - pci_write32(device->bus, device->dev, device->function, 0x04, value); -} - -void pci_enable_io_space(struct pci_device *device) { - uint32_t value = - pci_read32(device->bus, device->dev, device->function, 0x04); - value |= 1; - pci_write32(device->bus, device->dev, device->function, 0x04, value); -} - -void pci_enable_mem_space(struct pci_device *device) { - uint32_t value = - pci_read32(device->bus, device->dev, device->function, 0x04); - value |= 2; - pci_write32(device->bus, device->dev, device->function, 0x04, value); -} - -void fill_pci_device_info( - PciDevice *dev, uint8_t bus, uint8_t device, uint8_t func, - uint16_t vendorID, uint16_t deviceID, uint32_t classcode, - uint8_t revisionID, uint8_t multifunction, uint8_t header_type, - uint8_t bist, uint8_t latency_timer, uint8_t cache_line_size) { - int i; - - dev->bus_num = bus; - dev->dev_num = device; - dev->function_num = func; - dev->vendor_id = vendorID; - dev->device_id = deviceID; - dev->classcode = classcode >> 16; - dev->subclass = (classcode & 0xff00) >> 8; - dev->prog_if = classcode & 0xff; - dev->revisionID = revisionID; - dev->multifunction = multifunction; - dev->header_type = header_type; - dev->bist = bist; - dev->latency_timer = latency_timer; - dev->cache_line_size = cache_line_size; - - for (i = 0; i < PCI_MAX_BAR; i++) { - dev->common.bar[i].type = PCI_BAR_TYPE_INVALID; - } - dev->irqline = -1; -} - -uint32_t pci_device_get_mem_addr(struct pci_device *dev) { - int i; - - for (i = 0; i < PCI_MAX_BAR; i++) { - if (dev->bar[i].type == PCI_BAR_TYPE_MEM) { - return dev->bar[i].base_addr; - } - } - return -1; -} - -uint32_t pci_device_get_io_addr(struct pci_device *dev) { - int i; - - for (i = 0; i < PCI_MAX_BAR; i++) { - if (dev->bar[i].type == PCI_BAR_TYPE_IO) { - return dev->bar[i].base_addr; - } - } - return -1; -} - -// --------new-------- #include #include #include @@ -240,29 +116,114 @@ BusControllerDevice pci_bus_controller_device = { .bus_controller_ops = &pci_controller_ops, }; -DriverResult pci_device_init(Device *device) { +DEF_PCI_RW(8) +DEF_PCI_RW(16) +DEF_PCI_RW(32) +DEF_PCI_RW_DEVICE(8) +DEF_PCI_RW_DEVICE(16) +DEF_PCI_RW_DEVICE(32) + +void fill_pci_device_info( + PciDevice *dev, uint8_t bus, uint8_t device, uint8_t func, + uint16_t vendorID, uint16_t deviceID, uint32_t classcode, + uint8_t revisionID, uint8_t multifunction, uint8_t header_type, + uint8_t bist, uint8_t latency_timer, uint8_t cache_line_size) { int i; - for (i = 0; i < PCI_MAX_DEVICE; i++) { - pci_devices[i].status = PCI_DEVICE_STATUS_INVALID; + + dev->bus_num = bus; + dev->dev_num = device; + dev->function_num = func; + dev->vendor_id = vendorID; + dev->device_id = deviceID; + dev->classcode = classcode >> 16; + dev->subclass = (classcode & 0xff00) >> 8; + dev->prog_if = classcode & 0xff; + dev->revision_id = revisionID; + dev->multifunction = multifunction; + dev->header_type = header_type; + dev->bist = bist; + dev->latency_timer = latency_timer; + dev->cache_line_size = cache_line_size; + + for (i = 0; i < PCI_MAX_BAR; i++) { + dev->common.bar[i].type = PCI_BAR_TYPE_INVALID; } - return DRIVER_RESULT_OK; + dev->irqline = -1; +} +void pci_enable_bus_mastering(PciDevice *pci_device) { + uint32_t value = pci_read32( + pci_device->bus_num, pci_device->dev_num, pci_device->function_num, + 0x04); + value |= 4; + pci_write32( + pci_device->bus_num, pci_device->dev_num, pci_device->function_num, + 0x04, value); } -DriverResult pci_probe(BusDriver *bus_driver) { - PciDriver *pci_driver; - for (int i = 0; i < PCI_MAX_DEVICE; i++) { - if (pci_devices[i].status == PCI_DEVICE_STATUS_USING && - pci_devices[i].pci_driver != NULL) { - pci_driver = pci_devices[i].pci_driver; - pci_driver->ops->probe(pci_driver, &pci_devices[i]); +void pci_enable_io_space(PciDevice *pci_device) { + uint32_t value = pci_read32( + pci_device->bus_num, pci_device->dev_num, pci_device->function_num, + 0x04); + value |= 1; + pci_write32( + pci_device->bus_num, pci_device->dev_num, pci_device->function_num, + 0x04, value); +} + +void pci_enable_mem_space(PciDevice *pci_device) { + uint32_t value = pci_read32( + pci_device->bus_num, pci_device->dev_num, pci_device->function_num, + 0x04); + value |= 2; + pci_write32( + pci_device->bus_num, pci_device->dev_num, pci_device->function_num, + 0x04, value); +} + +uint32_t pci_device_get_mem_addr(PciDevice *pci_device) { + int i; + + if (pci_device->header_type == 0x0) { + for (i = 0; i < PCI_MAX_BAR; i++) { + if (pci_device->common.bar[i].type == PCI_BAR_TYPE_MEM) { + return pci_device->common.bar[i].base_addr; + } + } + } else if (pci_device->header_type == 0x1) { + for (i = 0; i < 2; i++) { + if (pci_device->pci2pci_bridge.bar[i].type == PCI_BAR_TYPE_MEM) { + return pci_device->pci2pci_bridge.bar[i].base_addr; + } } } - return DRIVER_RESULT_OK; + return -1; +} + +uint32_t pci_device_get_io_addr(PciDevice *pci_device) { + int i; + + if (pci_device->header_type == 0x0) { + for (i = 0; i < PCI_MAX_BAR; i++) { + if (pci_device->common.bar[i].type == PCI_BAR_TYPE_IO) { + return pci_device->common.bar[i].base_addr; + } + } + } else if (pci_device->header_type == 0x1) { + for (i = 0; i < 2; i++) { + if (pci_device->pci2pci_bridge.bar[i].type == PCI_BAR_TYPE_IO) { + return pci_device->pci2pci_bridge.bar[i].base_addr; + } + } + } + return -1; } DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus) { int i, j; PciDevice *pci_device; + print_driver_info( + pci_driver, "device id\tvendor id\theader " + "type\tclasscode\tsubclass\tprogif\trevision id\n"); for (i = 0; i < PCI_MAX_DEV; i++) { for (j = 0; j < PCI_MAX_FUNC; j++) { DriverResult result = @@ -283,6 +244,13 @@ DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus) { } bus_driver->device_count++; + print_driver_info( + pci_driver, + "%#06x\t\t%#06x\t\t%#04x\t\t%#04x\t\t%#04x\t\t%#04x\t%#04x\n", + pci_device->device_id, pci_device->vendor_id, + pci_device->header_type, pci_device->classcode, + pci_device->subclass, pci_device->prog_if, + pci_device->revision_id); if (!pci_device->multifunction) { // 没有多个功能就枚举下一个设备 break; @@ -530,10 +498,6 @@ DriverResult pci_scan_device( pci_device->irqline = value & 0xff; pci_device->irqpin = value >> 8; - // printk( - // "%#06x\t\t%#06x\t\t%#04x\t\t%#04x\t\t%#04x\t\t%#04x\t%#04x\n", - // deviceID, vendorID, header_type & (uint8_t)(~0x80), dev->classcode, - // dev->subclass, dev->prog_if, revisionID); return DRIVER_RESULT_OK; } @@ -580,6 +544,25 @@ DriverResult pci_register_driver(Driver *driver, PciDriver *pci_driver) { return DRIVER_RESULT_OK; } +DriverResult pci_device_init(Device *device) { + int i; + for (i = 0; i < PCI_MAX_DEVICE; i++) { + pci_devices[i].status = PCI_DEVICE_STATUS_INVALID; + } + return DRIVER_RESULT_OK; +} + +DriverResult pci_probe(BusDriver *bus_driver) { + PciDriver *pci_driver; + for (int i = 0; i < PCI_MAX_DEVICE; i++) { + if (pci_devices[i].status == PCI_DEVICE_STATUS_USING && + pci_devices[i].pci_driver != NULL) { + pci_driver = pci_devices[i].pci_driver; + pci_driver->ops->probe(pci_driver, &pci_devices[i]); + } + } + return DRIVER_RESULT_OK; +} DriverResult pci_driver_init(Driver *driver) { check_dependency(&pci_driver); diff --git a/src/arch/x86/include/drivers/pci.h b/src/arch/x86/include/drivers/pci.h index d29af17..32e3633 100644 --- a/src/arch/x86/include/drivers/pci.h +++ b/src/arch/x86/include/drivers/pci.h @@ -1,7 +1,8 @@ #ifndef _PCI_H #define _PCI_H -#include +#include "kernel/driver_interface.h" +#include "stdint.h" #define PCI_CONFIG_ADDR 0xcf8 #define PCI_CONFIG_DATA 0xcfc @@ -35,65 +36,40 @@ uint32_t addr_reg; \ addr_reg = (1 << 31) | (bus << 16) | (device << 11) | (func << 8) | \ (offset & 0xfc); \ - io_out32(PCI_CONFIG_ADDR, addr_reg); \ + io_out_dword(PCI_CONFIG_ADDR, addr_reg); \ } -#define PCI_READ(size, type) \ - type pci_read##size( \ +#define DEF_PCI_RW(size) \ + uint##size##_t pci_read##size( \ uint8_t bus, uint8_t device, uint8_t func, uint8_t offset) { \ PCI_SEL_REG(bus, device, func, offset); \ return io_in##size(PCI_CONFIG_DATA); \ - } -#define PCI_WRITE(size, type) \ - void pci_write##size( \ - uint8_t bus, uint8_t device, uint8_t func, uint8_t offset, \ - type value) { \ - PCI_SEL_REG(bus, device, func, offset); \ - io_out##size(PCI_CONFIG_DATA, value); \ + } \ + void pci_write##size( \ + uint8_t bus, uint8_t device, uint8_t func, uint8_t offset, \ + uint##size##_t value) { \ + PCI_SEL_REG(bus, device, func, offset); \ + io_out##size(PCI_CONFIG_DATA, value); \ } -#define PCI_READ_DEVICE(size, type) \ - type pci_device_read##size(struct pci_device *dev, uint8_t offset) { \ - return pci_read##size(dev->bus, dev->dev, dev->function, offset); \ - } -#define PCI_WRITE_DEVICE(size, type) \ - void pci_device_write##size( \ - struct pci_device *dev, uint8_t offset, type value) { \ - pci_write##size(dev->bus, dev->dev, dev->function, offset, value); \ +#define DEF_PCI_RW_DEVICE(size) \ + uint##size##_t pci_device_read##size(PciDevice *device, uint8_t offset) { \ + return pci_read##size( \ + device->bus_num, device->dev_num, device->function_num, offset); \ + } \ + void pci_device_write##size( \ + PciDevice *device, uint8_t offset, uint##size##_t value) { \ + pci_write##size( \ + device->bus_num, device->dev_num, device->function_num, offset, \ + value); \ } -struct pci_device_bar { - uint32_t type; - uint32_t base_addr; - uint32_t length; -}; - #define PCI_DEVICE_STATUS_INVALID 0 #define PCI_DEVICE_STATUS_USING 1 #define PCI_BAR_TYPE_INVALID 0 #define PCI_BAR_TYPE_MEM 1 #define PCI_BAR_TYPE_IO 2 -struct pci_device { - char status; - - uint8_t bus; - uint8_t dev; - uint8_t function; - - uint16_t vendorID; - uint16_t deviceID; - uint8_t classcode; - uint8_t subclass; - uint8_t prog_if; - uint8_t revisionID; - uint8_t multifunction; - uint8_t irqline; - uint8_t irqpin; - - struct pci_device_bar bar[PCI_MAX_BAR]; -}; - uint8_t pci_read8(uint8_t bus, uint8_t device, uint8_t func, uint8_t offset); uint16_t pci_read16(uint8_t bus, uint8_t device, uint8_t func, uint8_t offset); uint32_t pci_read32(uint8_t bus, uint8_t device, uint8_t func, uint8_t offset); @@ -104,31 +80,9 @@ void pci_write16( void pci_write32( uint8_t bus, uint8_t device, uint8_t func, uint8_t offset, uint32_t value); -uint8_t pci_device_read8(struct pci_device *dev, uint8_t offset); -uint16_t pci_device_read16(struct pci_device *dev, uint8_t offset); -uint32_t pci_device_read32(struct pci_device *dev, uint8_t offset); -void pci_device_write8(struct pci_device *dev, uint8_t offset, uint8_t value); -void pci_device_write16(struct pci_device *dev, uint8_t offset, uint16_t value); -void pci_device_write32(struct pci_device *dev, uint8_t offset, uint32_t value); - -void init_pci(); -// void pci_scan_device(uint8_t bus, uint8_t device, uint8_t function); -struct pci_device *pci_get_device_ById(uint16_t vendorID, uint16_t deviceID); -struct pci_device *pci_get_device_ByClass(uint8_t classcode, uint8_t subclass); -struct pci_device *pci_get_device_ByClassFull( - uint8_t classcode, uint8_t subclass, uint8_t progif); -void pci_enable_bus_mastering(struct pci_device *device); -void pci_enable_io_space(struct pci_device *device); -void pci_enable_mem_space(struct pci_device *device); +void init_pci(); + uint32_t pci_get_device_connected(void); -// struct pci_device *pci_alloc_device(void); -// int pci_free_device(struct pci_device *dev); -// void get_pci_device_info( -// struct pci_device *dev, uint8_t bus, uint8_t device, uint8_t func, -// uint16_t vendorID, uint16_t deviceID, uint32_t classcode, -// uint8_t revisionID, uint8_t multifunction); -uint32_t pci_device_get_mem_addr(struct pci_device *dev); -uint32_t pci_device_get_io_addr(struct pci_device *dev); #include "kernel/bus_driver.h" #include "kernel/driver.h" @@ -156,7 +110,7 @@ typedef struct PciDevice { uint8_t classcode; uint8_t subclass; uint8_t prog_if; - uint8_t revisionID; + uint8_t revision_id; uint8_t bist; uint8_t multifunction; uint8_t header_type; @@ -275,4 +229,10 @@ DriverResult pci_scan_device( Bus *bus, uint8_t bus_num, uint8_t device_num, uint8_t function_num, PciDevice **out_pci_device); +uint32_t pci_device_get_mem_addr(PciDevice *pci_device); +void pci_enable_mem_space(PciDevice *pci_device); +void pci_enable_io_space(PciDevice *pci_device); +void pci_enable_bus_mastering(PciDevice *pci_device); +uint32_t pci_device_get_io_addr(PciDevice *pci_device); + #endif \ No newline at end of file diff --git a/src/arch/x86/include/kernel/thread.h b/src/arch/x86/include/kernel/thread.h index 5f9f7af..b36e0e3 100644 --- a/src/arch/x86/include/kernel/thread.h +++ b/src/arch/x86/include/kernel/thread.h @@ -64,6 +64,8 @@ struct task_s { uint32_t *pgdir; uint32_t stack_magic; + uint8_t *end_flag; + struct mmap vir_page_mmap; struct memory_manage *memory_manage; @@ -87,5 +89,6 @@ void thread_unblock(struct task_s *pthread); void init_task(void); void schedule(void); void init_thread_memory_manage(struct task_s *thread); +void thread_set_end_flag(struct task_s *pthread, uint8_t *flag); #endif \ No newline at end of file diff --git a/src/include/kernel/driver_interface.h b/src/include/kernel/driver_interface.h index 7ff2340..065702c 100644 --- a/src/include/kernel/driver_interface.h +++ b/src/include/kernel/driver_interface.h @@ -28,9 +28,9 @@ #define print_error(str, ...) \ printk(COLOR_RED __FILE__ " Line %d: " str, __LINE__, ##__VA_ARGS__) #define print_device_info(device, str, ...) \ - printk("[%s]" str, device->name.text, __VA_ARGS__) + printk("[%s]" str, device->name.text, ##__VA_ARGS__) #define print_driver_info(driver, str, ...) \ - printk("[%s]" str, driver.name.text, __VA_ARGS__) + printk("[%s]" str, driver.name.text, ##__VA_ARGS__) #include "kernel/list.h" struct Device; diff --git a/src/kernel/console.c b/src/kernel/console.c index 31f2a1b..140ce3e 100644 --- a/src/kernel/console.c +++ b/src/kernel/console.c @@ -15,7 +15,6 @@ #include #include - struct console { struct VideoDevice *video_device; @@ -249,9 +248,12 @@ int printk(const char *fmt, ...) { } } break; - case '\t': - console.cur_x += 4 - console.cur_x & 3; + case '\t': { + int tab = 4 - console.cur_x % 4; + console.cur_x += tab; + console.cur_vram += tab * 10 * bpp; break; + } case '\r': break; default: diff --git a/src/kernel/driver.c b/src/kernel/driver.c index 7d527f0..0e5d82d 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -5,6 +5,7 @@ * @version 0.3 * @date 2022-07-20 */ +#include "kernel/spinlock.h" #include #include #include @@ -19,6 +20,7 @@ #include #include +#include LIST_HEAD(driver_list_head); // list_t device_irq_lists[16] = { @@ -156,23 +158,38 @@ void driver_start_thread(void *arg) { check_dependency(driver); driver_init(driver); + uint8_t end_flag = 0; + SubDriver *sub_driver; list_for_each_owner (sub_driver, &driver->sub_driver_lh, sub_driver_list) { - thread_start( + + struct task_s *task = thread_start( "sub_driver_start_thread", THREAD_DEFAULT_PRIO, sub_driver_start_thread, sub_driver); + thread_set_end_flag(task, &end_flag); + } + + while (end_flag > 0) { + schedule(); } } DriverResult driver_start_all(void) { + uint8_t end_flag = 0; Driver *driver; list_for_each_owner (driver, &driver_lh, driver_list) { if (driver->state == DRIVER_STATE_UNINITED) { - thread_start( + + struct task_s *task = thread_start( "driver_start_thread", THREAD_DEFAULT_PRIO, driver_start_thread, driver); + thread_set_end_flag(task, &end_flag); } } + + while (end_flag > 0) { + schedule(); + } return DRIVER_RESULT_OK; } diff --git a/src/kernel/thread.c b/src/kernel/thread.c index 9965a96..abde771 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -16,6 +16,7 @@ #include #include #include +#include #include struct task_s *main_thread; @@ -148,6 +149,8 @@ void thread_exit(void) { struct task_s *cur = get_current_thread(); cur->status = TASK_DIED; + (*cur->end_flag)--; + list_del(&cur->general_tag); list_del(&cur->all_list_tag); @@ -169,6 +172,11 @@ void thread_exit(void) { } } +void thread_set_end_flag(struct task_s *pthread, uint8_t *flag) { + (*flag)++; + pthread->end_flag = flag; +} + /** * @brief 阻塞当前线程 * From 627020634473ae89caf2e8564aa7078a4e1defeb Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 3 Jan 2025 23:42:52 +0800 Subject: [PATCH 009/158] =?UTF-8?q?[WIP]=E5=88=9D=E6=AD=A5=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0IDE=E9=A9=B1=E5=8A=A8=E5=8F=8A=E5=AD=98=E5=82=A8?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E7=AE=A1=E7=90=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/stdint.h | 46 +++--- src/arch/x86/drivers/Makefile | 3 +- src/arch/x86/drivers/apic.c | 4 +- src/arch/x86/drivers/ide.c | 12 +- src/arch/x86/drivers/pci.c | 187 +++++++++++++++++-------- src/arch/x86/drivers/vesa_display.c | 2 +- src/arch/x86/include/drivers/pci.h | 52 ++++--- src/arch/x86/include/kernel/func.h | 54 ++++++- src/driver/Makefile | 6 +- src/driver/interrupt_dm.c | 18 +-- src/driver/storage_dm.c | 104 ++++++++++++++ src/driver/storage_io_queue.c | 42 ++++++ src/driver/timer.c | 66 +++++++++ src/driver/timer_dm.c | 76 ++-------- src/driver/video_dm.c | 15 +- src/include/bits.h | 4 +- src/include/driver/storage_dm.h | 48 +++++++ src/include/driver/storage_io_queue.h | 26 ++++ src/include/driver/timer_dm.h | 6 + src/include/driver/transfer.h | 49 +++++++ src/include/kernel/bus_driver.h | 1 + src/include/kernel/device.h | 21 ++- src/include/kernel/device_manager.h | 2 +- src/include/kernel/driver.h | 5 +- src/include/kernel/driver_dependency.h | 2 +- src/include/kernel/driver_interface.h | 18 ++- src/include/kernel/periodic_task.h | 17 +++ src/include/types.h | 2 + src/kernel/Makefile | 2 + src/kernel/console.c | 9 +- src/kernel/device.c | 39 ++++++ src/kernel/device_manager.c | 3 +- src/kernel/driver.c | 9 +- src/kernel/driver_interface.c | 2 +- src/kernel/main.c | 12 +- src/kernel/memory.c | 1 + src/kernel/objects.c | 0 src/kernel/periodic_task.c | 25 ++++ src/lib/string.c | 1 + 39 files changed, 773 insertions(+), 218 deletions(-) create mode 100644 src/driver/storage_dm.c create mode 100644 src/driver/storage_io_queue.c create mode 100644 src/driver/timer.c create mode 100644 src/include/driver/storage_dm.h create mode 100644 src/include/driver/storage_io_queue.h create mode 100644 src/include/driver/transfer.h create mode 100644 src/include/kernel/periodic_task.h create mode 100644 src/kernel/objects.c create mode 100644 src/kernel/periodic_task.c diff --git a/include/stdint.h b/include/stdint.h index b04578a..a4151b9 100644 --- a/include/stdint.h +++ b/include/stdint.h @@ -1,25 +1,35 @@ #ifndef _STDINT_H #define _STDINT_H -typedef unsigned int uint32_t; -typedef int int32_t; -typedef unsigned short uint16_t; -typedef short int16_t; -typedef unsigned char uint8_t; -typedef char int8_t; +// 依赖编译器的内置类型__UINT64_TYPE__,__INT64_TYPE__和__SIZE_TYPE__ -typedef unsigned int u32; -typedef int i32; -typedef unsigned short u16; -typedef short i16; -typedef unsigned char u8; -typedef char i8; +typedef __UINT64_TYPE__ uint64_t; +typedef __INT64_TYPE__ int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; -typedef unsigned int uint32; -typedef int int32; -typedef unsigned short uint16; -typedef short int16; -typedef unsigned char uint8; -typedef char int8; +typedef __UINT64_TYPE__ u64; +typedef __INT64_TYPE__ i64; +typedef unsigned int u32; +typedef int i32; +typedef unsigned short u16; +typedef short i16; +typedef unsigned char u8; +typedef char i8; + +typedef __UINT64_TYPE__ uint64; +typedef __INT64_TYPE__ int64; +typedef unsigned int uint32; +typedef int int32; +typedef unsigned short uint16; +typedef short int16; +typedef unsigned char uint8; +typedef char int8; + +typedef __SIZE_TYPE__ size_t; #endif diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index 9cd84c0..cabdcaa 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -15,4 +15,5 @@ SRC += smbios.c SRC += vesa_display.c #SRC += network/ #SRC += sound/ -#SRC += usb/ \ No newline at end of file +#SRC += usb/ +SRC += disk/ \ No newline at end of file diff --git a/src/arch/x86/drivers/apic.c b/src/arch/x86/drivers/apic.c index aa4d332..e824045 100644 --- a/src/arch/x86/drivers/apic.c +++ b/src/arch/x86/drivers/apic.c @@ -304,14 +304,14 @@ DriverResult apic_init(Device *device) { ; if (i == timeout) { - print_error("APIC init timeout\n"); + print_error_with_position("APIC init timeout\n"); return DRIVER_RESULT_TIMEOUT; } lapic_write(APIC_TPR, 0); for (int i = 0; i < apic_info.max_lvt_entry; i++) { - apic_disable_irq(device->driver_manager_extension, 0x20 + i); + apic_disable_irq(device->device_manager_extension, 0x20 + i); } return DRIVER_RESULT_OK; } diff --git a/src/arch/x86/drivers/ide.c b/src/arch/x86/drivers/ide.c index a22acdb..1e146c7 100644 --- a/src/arch/x86/drivers/ide.c +++ b/src/arch/x86/drivers/ide.c @@ -323,7 +323,7 @@ int ide_read_identity_info( return -1; } printk("\n"); - port_insw( + io_stream_in16( ATA_REG_DATA(devext->channel), (unsigned int)devext->info, sizeof(struct ide_identify_info)); return 0; @@ -343,7 +343,7 @@ static status_t ide_enter(driver_t *drv_obj) { // if (device->prog_if & 0x02) { // pci_write8(device->bus, device->dev, device->function, // PCI_REG_PROGIF, device->prog_if | 0x01); device->prog_if = - // pci_read8(device->bus, device->dev, device->function, PCI_REG_PROGIF); } + // pci_read8(device->bus, device->dev, device->function, PCI_REG_PROGIF); } // else { return UNSUPPORT; // } // } @@ -351,7 +351,7 @@ static status_t ide_enter(driver_t *drv_obj) { // if (device->prog_if & 0x08) { // pci_write8(device->bus, device->dev, device->function, // PCI_REG_PROGIF, device->prog_if | 0x04); device->prog_if = - // pci_read8(device->bus, device->dev, device->function, PCI_REG_PROGIF); } + // pci_read8(device->bus, device->dev, device->function, PCI_REG_PROGIF); } // else { return UNSUPPORT; // } // } @@ -651,7 +651,8 @@ int PioDataTransfer( ide_reset_driver(devext->channel); return error; } - port_insw(ATA_REG_DATA(devext->channel), (unsigned int)buf, 256); + io_stream_in16( + ATA_REG_DATA(devext->channel), (unsigned int)buf, 256); buf += SECTOR_SIZE; } } else { @@ -663,7 +664,8 @@ int PioDataTransfer( return error; } /* 把数据写入端口,完成1个扇区后会产生一次中断 */ - port_outsw(ATA_REG_DATA(devext->channel), (unsigned int)buf, 256); + io_stream_out16( + ATA_REG_DATA(devext->channel), (unsigned int)buf, 256); buf += SECTOR_SIZE; // printk("write success! "); } diff --git a/src/arch/x86/drivers/pci.c b/src/arch/x86/drivers/pci.c index f31b64e..000f382 100644 --- a/src/arch/x86/drivers/pci.c +++ b/src/arch/x86/drivers/pci.c @@ -5,43 +5,26 @@ * @version 0.1 * @date 2020-07 */ +#include "kernel/list.h" #include #include +#include #include #include #include +#include +#include +#include #include #include +#include #include +#include #include #include #include -// struct pci_device pci_devices[PCI_MAX_DEVICE]; - -// void init_pci() { -// int i, j, k; - -// printk("device id\tvendor id\theader " -// "type\tclasscode\tsubclass\tprogif\trevision id\n"); -// for (i = 0; i < PCI_MAX_DEVICE; i++) { -// pci_devices[i].status = PCI_DEVICE_STATUS_INVALID; -// } -// for (i = 0; i < PCI_MAX_BUS; i++) { -// for (j = 0; j < PCI_MAX_DEV; j++) { -// for (k = 0; k < PCI_MAX_FUNC; k++) { -// pci_scan_device(i, j, k); -// } -// } -// } -// } - -#include -#include -#include -#include -#include -#include +LIST_HEAD(pci_driver_lh); PciDevice pci_devices[PCI_MAX_DEVICE]; @@ -49,6 +32,7 @@ DriverResult pci_driver_init(Driver *driver); DriverResult pci_device_init(Device *device); DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus); DriverResult pci_init_bus(BusDriver *bus_driver); +DriverResult pci_probe(BusDriver *bus_driver, Bus *bus); DeviceDriverOps pci_driver_ops = { .register_driver_hook = NULL, @@ -70,6 +54,7 @@ BusOps pci_bus_ops = { .register_device_hook = NULL, .unregister_device_hook = NULL, .scan_bus = pci_scan_bus, + .probe_device = pci_probe, }; BusControllerDeviceOps pci_controller_ops = { .probe = NULL, @@ -231,12 +216,12 @@ DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus) { if (result == DRIVER_RESULT_DEVICE_NOT_EXIST) { continue; } else if (result == DRIVER_RESULT_NULL_POINTER) { - print_error( + print_error_with_position( "pci_probe_bus: pci device(%d:%d:%d) alloc failed!\n", bus->bus_num, i, j); continue; } else if (result == DRIVER_RESULT_UNSUPPORT_DEVICE) { - print_error( + print_error_with_position( "pci_probe_bus: pci device(%d:%d:%d) unsupport! Header " "Type:%d\n", bus->bus_num, i, j, pci_device->header_type); @@ -244,6 +229,7 @@ DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus) { } bus_driver->device_count++; + pci_device->status = PCI_DEVICE_STATUS_UNUSED; print_driver_info( pci_driver, "%#06x\t\t%#06x\t\t%#04x\t\t%#04x\t\t%#04x\t\t%#04x\t%#04x\n", @@ -492,58 +478,133 @@ DriverResult pci_scan_device( value = pci_read32(bus_num, device_num, function_num, 0x3c); pci_device->pci2cardbus_bridge.bridge_control = value >> 16; } else { - print_error("unsupport PCI Header Type: %d\n", header_type); + print_error_with_position( + "unsupport PCI Header Type: %d\n", header_type); return DRIVER_RESULT_UNSUPPORT_DEVICE; } pci_device->irqline = value & 0xff; pci_device->irqpin = value >> 8; + PciDriver *pci_driver; + list_for_each_owner (pci_driver, &pci_driver_lh, pci_driver_list) { + if (pci_driver->pci_device != NULL) { continue; } + if (pci_driver->find_type == FIND_BY_VENDORID_DEVICEID) { + if (pci_driver->vendor_device.vendor_id == vendorID && + pci_driver->vendor_device.device_id == deviceID) { + pci_device->pci_driver = pci_driver; + pci_driver->pci_device = pci_device; + break; + } + } else if (pci_driver->find_type == FIND_BY_CLASSCODE_SUBCLASS) { + if (pci_driver->class_subclass.classcode == classcode && + pci_driver->class_subclass.subclass == pci_device->subclass) { + pci_device->pci_driver = pci_driver; + pci_driver->pci_device = pci_device; + break; + } + } else if (pci_driver->find_type == FIND_BY_CLASSCODE_SUBCLASS_PROGIF) { + if (pci_driver->class_subclass_progif.classcode == classcode && + pci_driver->class_subclass_progif.subclass == + pci_device->subclass && + pci_driver->class_subclass_progif.progif == + pci_device->prog_if) { + pci_device->pci_driver = pci_driver; + pci_driver->pci_device = pci_device; + break; + } + } + } + return DRIVER_RESULT_OK; } -DriverResult pci_set_driver(PciDriver *pci_driver, PciDevice *pci_device) { - if (pci_device->pci_driver == NULL) { - pci_device->pci_driver = pci_driver; - } else { - return DRIVER_RESULT_DEVICE_DRIVER_CONFLICT; +bool pci_match_driver(PciDriver *pci_driver, PciDriver *new_pci_driver) { + if (new_pci_driver->find_type == FIND_BY_VENDORID_DEVICEID) { + if (new_pci_driver->vendor_device.vendor_id == + pci_driver->vendor_device.vendor_id && + new_pci_driver->vendor_device.device_id == + pci_driver->vendor_device.device_id) { + return true; + } + } else if (new_pci_driver->find_type == FIND_BY_CLASSCODE_SUBCLASS) { + if (new_pci_driver->class_subclass.classcode == + pci_driver->class_subclass.classcode && + new_pci_driver->class_subclass.subclass == + pci_driver->class_subclass.subclass) { + return true; + } + } else if (new_pci_driver->find_type == FIND_BY_CLASSCODE_SUBCLASS_PROGIF) { + if (new_pci_driver->class_subclass_progif.classcode == + pci_driver->class_subclass_progif.classcode && + new_pci_driver->class_subclass_progif.subclass == + pci_driver->class_subclass_progif.subclass && + new_pci_driver->class_subclass_progif.progif == + pci_driver->class_subclass_progif.progif) { + return true; + } } - return DRIVER_RESULT_OK; + return false; } -DriverResult pci_match(PciDriver *pci_driver, PciDevice *pci_device) { +bool pci_match_device(PciDriver *pci_driver, PciDevice *pci_device) { if (pci_driver->find_type == FIND_BY_VENDORID_DEVICEID) { - if (pci_device->vendor_id == pci_driver->vendor_device.vendorID && - pci_device->device_id == pci_driver->vendor_device.deviceID) { - pci_device->pci_driver = pci_driver; - DRV_RESULT_DELIVER_CALL(pci_set_driver, pci_driver, pci_device); + if (pci_driver->vendor_device.vendor_id == pci_device->vendor_id && + pci_driver->vendor_device.device_id == pci_device->device_id) { + return true; } } else if (pci_driver->find_type == FIND_BY_CLASSCODE_SUBCLASS) { - if (pci_device->classcode == pci_driver->class_subclass.classcode && - pci_device->subclass == pci_driver->class_subclass.subclass) { - pci_device->pci_driver = pci_driver; - DRV_RESULT_DELIVER_CALL(pci_set_driver, pci_driver, pci_device); + if (pci_driver->class_subclass.classcode == pci_device->classcode && + pci_driver->class_subclass.subclass == pci_device->subclass) { + return true; } } else if (pci_driver->find_type == FIND_BY_CLASSCODE_SUBCLASS_PROGIF) { - if (pci_device->classcode == - pci_driver->class_subclass_progif.classcode && - pci_device->subclass == - pci_driver->class_subclass_progif.subclass && - pci_device->prog_if == pci_driver->class_subclass_progif.progif) { - pci_device->pci_driver = pci_driver; - DRV_RESULT_DELIVER_CALL(pci_set_driver, pci_driver, pci_device); + if (pci_driver->class_subclass_progif.classcode == + pci_device->classcode && + pci_driver->class_subclass_progif.subclass == + pci_device->subclass && + pci_driver->class_subclass_progif.progif == pci_device->prog_if) { + return true; } } - return DRIVER_RESULT_OK; + return false; } -DriverResult pci_register_driver(Driver *driver, PciDriver *pci_driver) { - int i; - for (i = 0; i < PCI_MAX_DEVICE; i++) { - pci_match(pci_driver, &pci_devices[i]); +DriverResult pci_register_driver(Driver *driver, PciDriver *new_pci_driver) { + PciDriver *old_pci_driver; + list_for_each_owner (old_pci_driver, &pci_driver_lh, pci_driver_list) { + if (new_pci_driver->find_type == old_pci_driver->find_type) { + if (pci_match_driver(old_pci_driver, new_pci_driver)) { + return DRIVER_RESULT_DEVICE_DRIVER_CONFLICT; + } + break; + } else if ( + new_pci_driver->find_type == FIND_BY_CLASSCODE_SUBCLASS_PROGIF && + old_pci_driver->find_type == FIND_BY_CLASSCODE_SUBCLASS) { + if (new_pci_driver->class_subclass_progif.classcode == + old_pci_driver->class_subclass_progif.classcode && + new_pci_driver->class_subclass_progif.subclass == + old_pci_driver->class_subclass_progif.subclass && + new_pci_driver->class_subclass_progif.progif == + old_pci_driver->class_subclass_progif.progif) { + list_del(&old_pci_driver->pci_driver_list); + break; + } + } else if ( + new_pci_driver->find_type == FIND_BY_CLASSCODE_SUBCLASS && + old_pci_driver->find_type == FIND_BY_CLASSCODE_SUBCLASS_PROGIF) { + if (new_pci_driver->class_subclass.classcode == + old_pci_driver->class_subclass.classcode && + new_pci_driver->class_subclass.subclass == + old_pci_driver->class_subclass.subclass) { + return DRIVER_RESULT_DEVICE_DRIVER_CONFLICT; + } + } } + list_add_tail(&new_pci_driver->pci_driver_list, &pci_driver_lh); return DRIVER_RESULT_OK; } + DriverResult pci_device_init(Device *device) { int i; for (i = 0; i < PCI_MAX_DEVICE; i++) { @@ -552,13 +613,19 @@ DriverResult pci_device_init(Device *device) { return DRIVER_RESULT_OK; } -DriverResult pci_probe(BusDriver *bus_driver) { +DriverResult pci_probe(BusDriver *bus_driver, Bus *bus) { PciDriver *pci_driver; for (int i = 0; i < PCI_MAX_DEVICE; i++) { - if (pci_devices[i].status == PCI_DEVICE_STATUS_USING && - pci_devices[i].pci_driver != NULL) { - pci_driver = pci_devices[i].pci_driver; - pci_driver->ops->probe(pci_driver, &pci_devices[i]); + if (pci_devices[i].status == PCI_DEVICE_STATUS_UNUSED) { + list_for_each_owner (pci_driver, &pci_driver_lh, pci_driver_list) { + if (pci_match_device(pci_driver, &pci_devices[i])) { + pci_devices[i].status = PCI_DEVICE_STATUS_USING; + pci_devices[i].pci_driver = pci_driver; + pci_devices[i].bus = bus; + pci_driver->pci_device = &pci_devices[i]; + pci_driver->ops->probe(&pci_devices[i]); + } + } } } return DRIVER_RESULT_OK; diff --git a/src/arch/x86/drivers/vesa_display.c b/src/arch/x86/drivers/vesa_display.c index 99486d3..1045009 100644 --- a/src/arch/x86/drivers/vesa_display.c +++ b/src/arch/x86/drivers/vesa_display.c @@ -76,7 +76,7 @@ DriverResult vesa_display_device_init(Device *device) { DriverResult vesa_display_device_start(Device *device) { vesa_display_info.vram = (uint8_t *)VRAM_VIR_ADDR; - VideoDevice *video_device = device->driver_manager_extension; + VideoDevice *video_device = device->device_manager_extension; video_device->mode_info.width = vesa_display_info.width; video_device->mode_info.height = vesa_display_info.height; video_device->mode_info.bits_per_pixel = vesa_display_info.BitsPerPixel; diff --git a/src/arch/x86/include/drivers/pci.h b/src/arch/x86/include/drivers/pci.h index 32e3633..ceff410 100644 --- a/src/arch/x86/include/drivers/pci.h +++ b/src/arch/x86/include/drivers/pci.h @@ -65,7 +65,8 @@ } #define PCI_DEVICE_STATUS_INVALID 0 -#define PCI_DEVICE_STATUS_USING 1 +#define PCI_DEVICE_STATUS_UNUSED 1 +#define PCI_DEVICE_STATUS_USING 2 #define PCI_BAR_TYPE_INVALID 0 #define PCI_BAR_TYPE_MEM 1 #define PCI_BAR_TYPE_IO 2 @@ -183,11 +184,12 @@ typedef struct PciDevice { typedef struct PciDriverOps { - DriverResult (*probe)( - struct PciDriver *pci_driver, struct PciDevice *pci_device); -} PciDeviceOps; + DriverResult (*probe)(struct PciDevice *pci_device); +} PciDriverOps; typedef struct PciDriver { + list_t pci_driver_list; + Driver *driver; DeviceDriver *device_driver; @@ -199,8 +201,8 @@ typedef struct PciDriver { union { struct { - uint16_t vendorID; - uint16_t deviceID; + uint16_t vendor_id; + uint16_t device_id; } vendor_device; struct { uint8_t classcode; @@ -214,25 +216,37 @@ typedef struct PciDriver { }; PciDevice *pci_device; - PciDeviceOps *ops; + PciDriverOps *ops; } PciDriver; -PciDevice *pci_alloc_device(void); -int pci_free_device(PciDevice *dev); -void fill_pci_device_info( - PciDevice *dev, uint8_t bus, uint8_t device, uint8_t func, - uint16_t vendorID, uint16_t deviceID, uint32_t classcode, - uint8_t revisionID, uint8_t multifunction, uint8_t header_type, - uint8_t bist, uint8_t latency_timer, uint8_t cache_line_size); +extern list_t pci_driver_lh; +extern Driver pci_driver; + +DriverResult pci_set_driver(PciDriver *pci_driver, PciDevice *pci_device); +PciDevice *pci_alloc_device(void); +int pci_free_device(PciDevice *dev); +void fill_pci_device_info( + PciDevice *dev, uint8_t bus, uint8_t device, uint8_t func, + uint16_t vendorID, uint16_t deviceID, uint32_t classcode, + uint8_t revisionID, uint8_t multifunction, uint8_t header_type, + uint8_t bist, uint8_t latency_timer, uint8_t cache_line_size); void get_pci_bar_info(PciDeviceBar *bar, uint32_t addr, uint32_t len); DriverResult pci_scan_device( Bus *bus, uint8_t bus_num, uint8_t device_num, uint8_t function_num, PciDevice **out_pci_device); -uint32_t pci_device_get_mem_addr(PciDevice *pci_device); -void pci_enable_mem_space(PciDevice *pci_device); -void pci_enable_io_space(PciDevice *pci_device); -void pci_enable_bus_mastering(PciDevice *pci_device); -uint32_t pci_device_get_io_addr(PciDevice *pci_device); +uint8_t pci_device_read8(PciDevice *device, uint8_t offset); +uint16_t pci_device_read16(PciDevice *device, uint8_t offset); +uint32_t pci_device_read32(PciDevice *device, uint8_t offset); +void pci_device_write8(PciDevice *device, uint8_t offset, uint8_t value); +void pci_device_write16(PciDevice *device, uint8_t offset, uint16_t value); +void pci_device_write32(PciDevice *device, uint8_t offset, uint32_t value); + +DriverResult pci_register_driver(Driver *driver, PciDriver *new_pci_driver); +uint32_t pci_device_get_mem_addr(PciDevice *pci_device); +void pci_enable_mem_space(PciDevice *pci_device); +void pci_enable_io_space(PciDevice *pci_device); +void pci_enable_bus_mastering(PciDevice *pci_device); +uint32_t pci_device_get_io_addr(PciDevice *pci_device); #endif \ No newline at end of file diff --git a/src/arch/x86/include/kernel/func.h b/src/arch/x86/include/kernel/func.h index a7e7c35..927e36d 100644 --- a/src/arch/x86/include/kernel/func.h +++ b/src/arch/x86/include/kernel/func.h @@ -26,16 +26,39 @@ void io_sti(void); void io_hlt(void); void io_stihlt(void); -static inline void get_cpuid(unsigned int Mop, unsigned int Sop, unsigned int *a, unsigned int *b, - unsigned int *c, unsigned int *d) { - __asm__ __volatile__("cpuid \n\t" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "0"(Mop), "2"(Sop)); +static inline void get_cpuid( + unsigned int Mop, unsigned int Sop, unsigned int *a, unsigned int *b, + unsigned int *c, unsigned int *d) { + __asm__ __volatile__("cpuid \n\t" + : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) + : "0"(Mop), "2"(Sop)); } static inline void ltr(unsigned short sel) { __asm__ __volatile__("ltr %0" ::"r"(sel)); } +static inline void io_stream_in8( + unsigned int port, unsigned int buffer, unsigned int nr) { + __asm__ __volatile__("cld;\n\t \ + rep;\n\t \ + insb;\n\t \ + mfence;" ::"d"(port), + "D"(buffer), "c"(nr) + : "memory"); +} + +static inline void io_stream_out8( + unsigned int port, unsigned int buffer, unsigned int nr) { + __asm__ __volatile__("cld;\n\t \ + rep;\n\t \ + outsb;\n\t \ + mfence;\n\t" ::"d"(port), + "S"(buffer), "c"(nr) + : "memory"); +} -static inline void port_insw(unsigned int port, unsigned int buffer, unsigned int nr) { +static inline void io_stream_in16( + unsigned int port, unsigned int buffer, unsigned int nr) { __asm__ __volatile__("cld;\n\t \ rep;\n\t \ insw;\n\t \ @@ -44,7 +67,8 @@ static inline void port_insw(unsigned int port, unsigned int buffer, unsigned in : "memory"); } -static inline void port_outsw(unsigned int port, unsigned int buffer, unsigned int nr) { +static inline void io_stream_out16( + unsigned int port, unsigned int buffer, unsigned int nr) { __asm__ __volatile__("cld;\n\t \ rep;\n\t \ outsw;\n\t \ @@ -53,6 +77,26 @@ static inline void port_outsw(unsigned int port, unsigned int buffer, unsigned i : "memory"); } +static inline void io_stream_in32( + unsigned int port, unsigned int buffer, unsigned int nr) { + __asm__ __volatile__("cld;\n\t \ + rep;\n\t \ + insl;\n\t \ + mfence;\n\t" ::"d"(port), + "S"(buffer), "c"(nr) + : "memory"); +} + +static inline void io_stream_out32( + unsigned int port, unsigned int buffer, unsigned int nr) { + __asm__ __volatile__("cld;\n\t \ + rep;\n\t \ + outsl;\n\t \ + mfence;\n\t" ::"d"(port), + "S"(buffer), "c"(nr) + : "memory"); +} + static inline unsigned int bsr(unsigned int x) { unsigned int index; __asm__ __volatile__("bsrl %1, %0" : "=r"(index) : "r"(x)); diff --git a/src/driver/Makefile b/src/driver/Makefile index 99c1fb1..cca45aa 100644 --- a/src/driver/Makefile +++ b/src/driver/Makefile @@ -2,4 +2,8 @@ SRC += timer_dm.c SRC += interrupt_dm.c SRC += video_dm.c SRC += video.c -SRC += bus_dm.c \ No newline at end of file +SRC += bus_dm.c +SRC += storage_dm.c +SRC += transfer.c +SRC += storage_io_queue.c +SRC += timer.c \ No newline at end of file diff --git a/src/driver/interrupt_dm.c b/src/driver/interrupt_dm.c index 2246bbe..eb24143 100644 --- a/src/driver/interrupt_dm.c +++ b/src/driver/interrupt_dm.c @@ -35,29 +35,29 @@ struct DeviceManager interrupt_device_manager = { */ DriverResult check_intterupt_ops(InterruptDevice *interrupt_device) { if (!interrupt_device->interrupt_ops) { - print_error( + print_error_with_position( "%s has no operations\n", interrupt_device->device->name.text); return DRIVER_RESULT_DEVICE_DRIVER_HAVE_NO_OPS; } if (!interrupt_device->interrupt_ops->disable_irq) { - print_error( + print_error_with_position( "%s has no disable_irq operation\n", interrupt_device->device->name.text); return DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS; } if (!interrupt_device->interrupt_ops->enable_irq) { - print_error( + print_error_with_position( "%s has no enable_irq operation\n", interrupt_device->device->name.text); return DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS; } if (!interrupt_device->interrupt_ops->eoi) { - print_error( + print_error_with_position( "%s has no eoi operation\n", interrupt_device->device->name.text); return DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS; } if (!interrupt_device->interrupt_ops->redirect_irq) { - print_error( + print_error_with_position( "%s has no redirect_irq operation\n", interrupt_device->device->name.text); return DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS; @@ -73,7 +73,7 @@ DriverResult register_interrupt_device( DRV_RESULT_DELIVER_CALL( register_device, device_driver, device_driver->bus, device); - list_add_tail(&device->dm_list, &interrupt_device_manager.device_driver_lh); + list_add_tail(&device->dm_list, &interrupt_device_manager.device_lh); InterruptDeviceManager *manager = interrupt_device_manager.private_data; if (manager->current_device) { @@ -105,13 +105,13 @@ DriverResult unregister_interrupt_device( // 寻找替代的设备 InterruptDevice *new_interrupt_device; list_for_each_owner ( - cur, &interrupt_device_manager.device_driver_lh, device_list) { + cur, &interrupt_device_manager.device_lh, device_list) { if (cur != device) { if (new_interrupt_device == NULL) { - new_interrupt_device = cur->driver_manager_extension; + new_interrupt_device = cur->device_manager_extension; } else { InterruptDevice *cur_interrupt_device = - (InterruptDevice *)cur->driver_manager_extension; + (InterruptDevice *)cur->device_manager_extension; if (cur_interrupt_device->priority > new_interrupt_device->priority) { new_interrupt_device = cur_interrupt_device; diff --git a/src/driver/storage_dm.c b/src/driver/storage_dm.c new file mode 100644 index 0000000..7329ff3 --- /dev/null +++ b/src/driver/storage_dm.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void storage_periodic_task(void *arg); + +DriverResult storage_device_block_read( + Device *device, uint8_t *buf, offset_t offset, size_t size); +DriverResult storage_device_block_write( + Device *device, uint8_t *buf, offset_t offset, size_t size); + +DeviceManagerOps storage_dm_ops = { + .dm_load_hook = NULL, + .dm_unload_hook = NULL, +}; + +typedef struct StorageDeviceManager { +} StorageDeviceManager; + +StorageDeviceManager storage_dm_ext; + +struct DeviceManager storage_device_manager = { + .type = DEVICE_TYPE_STORAGE, + + .ops = &storage_dm_ops, + + .private_data = &storage_dm_ext, +}; + +DriverResult register_storage_device( + DeviceDriver *device_driver, Device *device, + StorageDevice *storage_device) { + storage_device->device = device; + + if (device->transfer->type_in == TRANSFER_TYPE_BLOCK) { + device->transfer->in.block = storage_device_block_read; + } + if (device->transfer->type_out == TRANSFER_TYPE_BLOCK) { + device->transfer->out.block = storage_device_block_write; + } + device->device_manager_extension = storage_device; + list_init(&storage_device->io_queue_lh); + + DRV_RESULT_DELIVER_CALL( + register_device, device_driver, device_driver->bus, device); + list_add_tail(&device->dm_list, &storage_device_manager.device_lh); + + storage_device->periodic_task.func = storage_periodic_task; + storage_device->periodic_task.arg = storage_device; + periodic_task_add(&storage_device->periodic_task); + + return DRIVER_RESULT_OK; +} + +DriverResult unregister_storage_device( + DeviceDriver *device_driver, Device *device, + StorageDevice *storage_device) { + + DRV_RESULT_DELIVER_CALL(unregister_device, device_driver, device); + list_del(&device->device_list); + return DRIVER_RESULT_OK; +} + +DriverResult storage_device_block_read( + Device *device, uint8_t *buf, offset_t offset, size_t size) { + + StorageRequest *request = kmalloc(sizeof(StorageRequest)); + request->rw = false; + request->buf = buf; + request->offset = offset % 512; + request->position = offset / 512; + request->count = DIV_ROUND_UP(offset + size, 512) - request->position; + + storage_add_request(device->device_manager_extension, request); + + return DRIVER_RESULT_OK; +} + +DriverResult storage_device_block_write( + Device *device, uint8_t *buf, offset_t offset, size_t size) { + + StorageRequest *request = kmalloc(sizeof(StorageRequest)); + request->rw = true; + request->buf = buf; + request->offset = offset % 512; + request->position = offset / 512; + request->count = DIV_ROUND_UP(offset + size, 512) - request->position; + + storage_add_request(device->device_manager_extension, request); + + return DRIVER_RESULT_OK; +} diff --git a/src/driver/storage_io_queue.c b/src/driver/storage_io_queue.c new file mode 100644 index 0000000..c99e2cc --- /dev/null +++ b/src/driver/storage_io_queue.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +void storage_add_request( + StorageDevice *storage_device, StorageRequest *request) { + StorageRequest *req; + request->storage_device = storage_device; + list_for_each_owner (req, &storage_device->io_queue_lh, list) { + if (req->position > request->position) { + list_add_before(&request->list, &req->list); + return; + } + } + list_add_tail(&request->list, &storage_device->io_queue_lh); +} + +void storage_periodic_task(void *arg) { + StorageDevice *storage_device = (StorageDevice *)arg; + + if (!storage_device->ops->is_busy(storage_device) && + !list_empty(&storage_device->io_queue_lh)) { + StorageRequest *request = list_first_owner( + &storage_device->io_queue_lh, StorageRequest, list); + storage_submit_request(request); + } +} + +void storage_finish_request(StorageRequest *storage_request) { + storage_request->is_finished = true; +} + +void storage_submit_request(StorageRequest *request) { + StorageDevice *storage_device = request->storage_device; + if (request->rw) { + storage_device->ops->submit_write_request(storage_device, request); + } else { + storage_device->ops->submit_read_request(storage_device, request); + } + list_del(&request->list); +} \ No newline at end of file diff --git a/src/driver/timer.c b/src/driver/timer.c new file mode 100644 index 0000000..f493e50 --- /dev/null +++ b/src/driver/timer.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +extern TimerDeviceManager timer_dm_ext; + +DriverResult timer_init(Timer *timer) { + timer->timer_device = + timer_dm_ext.scheduler_timer->device_manager_extension; + timer->timeout = 0; + return DRIVER_RESULT_OK; +} + +DriverResult timer_set_timeout(Timer *timer, uint32_t count) { + if (timer->timer_device == NULL) return DRIVER_RESULT_DEVICE_NOT_EXIST; + timer->timeout = timer->timer_device->counter + count; + + // 在插入时排序 + if (!list_empty(&timer->timer_device->timer_list_lh)) { + Timer *last_timer = + list_last_owner(&timer->timer_device->timer_list_lh, Timer, list); + while (last_timer->timeout > timer->timeout) { + last_timer = list_prev_onwer(last_timer, list); + } + list_add_after(&timer->list, &last_timer->list); + } else { + list_add_tail(&timer->list, &timer->timer_device->timer_list_lh); + } + return DRIVER_RESULT_OK; +} + +uint32_t timer_count_ms(Timer *timer, uint32_t ms) { + uint32_t freq = timer->timer_device->current_frequency; + if (freq < 1000) { + return DIV_ROUND_UP(ms * freq, 1000); + } else { + return DIV_ROUND_UP(ms, (freq / 1000)); + } +} + +void delay_ms(Timer *timer, uint32_t ms) { + uint32_t count = timer_count_ms(timer, ms); + timer->period = 0; + timer_set_timeout(timer, count); + + while (timer->timeout != 0) + ; +} + +void delay_ms_async(Timer *timer, uint32_t ms) { + uint32_t count = timer_count_ms(timer, ms); + timer->period = 0; + timer_set_timeout(timer, count); + // 设置完立即返回 +} + +void set_periodic_ms(Timer *timer, uint32_t ms) { + uint32_t count = timer_count_ms(timer, ms); + timer->period = count; + timer_set_timeout(timer, count); +} + +bool timer_is_timeout(Timer *timer) { + return timer->timeout == 0; +} diff --git a/src/driver/timer_dm.c b/src/driver/timer_dm.c index 4419a9a..afbb15f 100644 --- a/src/driver/timer_dm.c +++ b/src/driver/timer_dm.c @@ -4,8 +4,6 @@ #include #include #include -#include -#include #include #include @@ -25,10 +23,6 @@ DeviceManagerOps timer_dm_ops = { .destroy_device_hook = NULL, }; -typedef struct TimerDeviceManager { - Device *scheduler_timer; -} TimerDeviceManager; - TimerDeviceManager timer_dm_ext; struct DeviceManager timer_device_manager = { @@ -54,7 +48,7 @@ DriverResult timer_dm_unload(DeviceManager *manager) { } DriverResult timer_device_init(DeviceManager *manager, Device *device) { - TimerDevice *timer_device = (TimerDevice *)device->driver_manager_extension; + TimerDevice *timer_device = (TimerDevice *)device->device_manager_extension; const int count = sizeof(default_frequencies) / sizeof(typeof(default_frequencies[0])); @@ -77,7 +71,7 @@ DriverResult timer_device_init(DeviceManager *manager, Device *device) { } else { TimerDevice *scheduler_timer_device = (TimerDevice *) - timer_manager->scheduler_timer->driver_manager_extension; + timer_manager->scheduler_timer->device_manager_extension; if (scheduler_timer_device->priority < timer_device->priority) { timer_manager->scheduler_timer = device; } @@ -95,7 +89,7 @@ int timer_get_schedule_tick(int priority) { } DriverResult timer_set_frequency(Device *device, uint32_t frequency) { - TimerDevice *timer_device = (TimerDevice *)device->driver_manager_extension; + TimerDevice *timer_device = (TimerDevice *)device->device_manager_extension; TimerResult result = timer_device->timer_ops->set_frequency(timer_device, frequency); @@ -107,14 +101,18 @@ DriverResult timer_set_frequency(Device *device, uint32_t frequency) { } void timer_irq_handler(Device *device) { - TimerDevice *timer_device = (TimerDevice *)device->driver_manager_extension; + TimerDevice *timer_device = (TimerDevice *)device->device_manager_extension; timer_device->counter++; Timer *cur, *next; list_for_each_owner_safe (cur, next, &timer_device->timer_list_lh, list) { if (cur->timeout > timer_device->counter) { break; } list_del(&cur->list); - cur->timeout = 0; + if (cur->period) { + timer_set_timeout(cur, cur->period); + } else { + cur->timeout = 0; + } } if (!list_empty(&thread_all)) { @@ -135,12 +133,12 @@ void timer_irq_handler(Device *device) { DriverResult register_timer_device( DeviceDriver *device_driver, Device *device, TimerDevice *timer_device) { - device->driver_manager_extension = timer_device; + device->device_manager_extension = timer_device; timer_device->device = device; DRV_RESULT_DELIVER_CALL( register_device, device_driver, device_driver->bus, device); list_init(&timer_device->timer_list_lh); - list_add_tail(&device->dm_list, &timer_device_manager.device_driver_lh); + list_add_tail(&device->dm_list, &timer_device_manager.device_lh); return DRIVER_RESULT_OK; } @@ -158,55 +156,3 @@ DriverResult unregister_timer_device( list_del(&device->device_list); return DRIVER_RESULT_OK; } - -DriverResult timer_init(Timer *timer) { - timer->timer_device = - timer_dm_ext.scheduler_timer->driver_manager_extension; - timer->timeout = 0; - return DRIVER_RESULT_OK; -} - -DriverResult timer_set_timeout(Timer *timer, uint32_t count) { - if (timer->timer_device == NULL) return DRIVER_RESULT_DEVICE_NOT_EXIST; - timer->timeout = timer->timer_device->counter + count; - - // 在插入时排序 - if (!list_empty(&timer->timer_device->timer_list_lh)) { - Timer *last_timer = - list_last_owner(&timer->timer_device->timer_list_lh, Timer, list); - while (last_timer->timeout > timer->timeout) { - last_timer = list_prev_onwer(last_timer, list); - } - list_add_after(&timer->list, &last_timer->list); - } else { - list_add_tail(&timer->list, &timer->timer_device->timer_list_lh); - } - return DRIVER_RESULT_OK; -} - -uint32_t timer_count_ms(Timer *timer, uint32_t ms) { - uint32_t freq = timer->timer_device->current_frequency; - if (freq < 1000) { - return DIV_ROUND_UP(ms * freq, 1000); - } else { - return DIV_ROUND_UP(ms, (freq / 1000)); - } -} - -void delay_ms(Timer *timer, uint32_t ms) { - uint32_t count = timer_count_ms(timer, ms); - timer_set_timeout(timer, count); - - while (timer->timeout != 0) - ; -} - -void delay_ms_async(Timer *timer, uint32_t ms) { - uint32_t count = timer_count_ms(timer, ms); - timer_set_timeout(timer, count); - // 设置完立即返回 -} - -bool timer_is_timeout(Timer *timer) { - return timer->timeout == 0; -} diff --git a/src/driver/video_dm.c b/src/driver/video_dm.c index 20fec07..6a6d729 100644 --- a/src/driver/video_dm.c +++ b/src/driver/video_dm.c @@ -44,8 +44,8 @@ DriverResult video_dm_unload(DeviceManager *manager) { DriverResult register_video_device( DeviceDriver *device_driver, Device *device, VideoDevice *video_device) { - device->driver_manager_extension = video_device; - if (device->driver_manager_extension == NULL) { + device->device_manager_extension = video_device; + if (device->device_manager_extension == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } video_device->device = device; @@ -53,7 +53,7 @@ DriverResult register_video_device( DRV_RESULT_DELIVER_CALL( register_device, device_driver, device_driver->bus, device); list_init(&video_device->video_list_lh); - list_add_tail(&device->dm_list, &video_device_manager.device_driver_lh); + list_add_tail(&device->dm_list, &video_device_manager.device_lh); return DRIVER_RESULT_OK; } @@ -65,7 +65,7 @@ DriverResult unregister_video_devce( } DriverResult video_device_start(DeviceManager *manager, Device *device) { - VideoDevice *video_device = (VideoDevice *)device->driver_manager_extension; + VideoDevice *video_device = (VideoDevice *)device->device_manager_extension; if (video_dm_ext.main_display_device == NULL) { video_dm_ext.main_display_device = device; @@ -92,15 +92,14 @@ DriverResult video_get_video_device(int in_index, VideoDevice **out_device) { Device *device; if (in_index == 0) { *out_device = - video_dm_ext.main_display_device->driver_manager_extension; + video_dm_ext.main_display_device->device_manager_extension; return DRIVER_RESULT_OK; } int i = 0; - list_for_each_owner ( - device, &video_device_manager.device_driver_lh, dm_list) { + list_for_each_owner (device, &video_device_manager.device_lh, dm_list) { if (device == video_dm_ext.main_display_device) { continue; } if (i == in_index) { - *out_device = device->driver_manager_extension; + *out_device = device->device_manager_extension; return DRIVER_RESULT_OK; } i++; diff --git a/src/include/bits.h b/src/include/bits.h index 296d689..0889bc3 100644 --- a/src/include/bits.h +++ b/src/include/bits.h @@ -29,8 +29,8 @@ #define BIN_EN(n, x) ((n) | x) #define BIN_DIS(n, x) ((n) & ~x) -#define BIN_IS_DIS(n, x) (!BIN_EN(n, x)) -#define BIN_IS_EN(n, x) (!BIN_IS_DIS(n, x)) +#define BIN_IS_DIS(n, x) (!((n) & (x))) +#define BIN_IS_EN(n, x) ((!BIN_IS_DIS(n, x))) #endif diff --git a/src/include/driver/storage_dm.h b/src/include/driver/storage_dm.h new file mode 100644 index 0000000..b491e6d --- /dev/null +++ b/src/include/driver/storage_dm.h @@ -0,0 +1,48 @@ +#ifndef _STORAGE_DM_H +#define _STORAGE_DM_H + +#include "kernel/device_driver.h" +#include "kernel/device_manager.h" +#include "kernel/driver.h" +#include "kernel/periodic_task.h" + +typedef enum StorageDeviceType { + STORAGE_DEVICE_TYPE_UNKNOWN, + STORAGE_DEVICE_TYPE_ATA, + STORAGE_DEVICE_TYPE_SCSI, +} StorageDeviceType; + +struct StorageDevice; +struct StorageRequest; +typedef struct StorageDeviceOps { + DriverResult (*submit_read_request)( + struct StorageDevice *storage_device, struct StorageRequest *request); + DriverResult (*submit_write_request)( + struct StorageDevice *storage_device, struct StorageRequest *request); + bool (*is_busy)(struct StorageDevice *storage_device); +} StorageDeviceOps; + +typedef struct StorageDevice { + Device *device; + StorageDeviceType type; + StorageDeviceOps *ops; + + PeriodicTask periodic_task; + list_t io_queue_lh; +} StorageDevice; + +typedef struct StorageDeviceDriver { + string_t name; + list_t driver_list; + list_t device_list; + StorageDeviceOps *ops; +} StorageDeviceDriver; + +extern DeviceManager storage_device_manager; + +DriverResult register_storage_device( + DeviceDriver *device_driver, Device *device, StorageDevice *storage_device); +DriverResult unregister_storage_device( + DeviceDriver *device_driver, Device *device, StorageDevice *storage_device); + +#endif \ No newline at end of file diff --git a/src/include/driver/storage_io_queue.h b/src/include/driver/storage_io_queue.h new file mode 100644 index 0000000..52030ae --- /dev/null +++ b/src/include/driver/storage_io_queue.h @@ -0,0 +1,26 @@ +#ifndef _STORAGE_IO_QUEUE_H +#define _STORAGE_IO_QUEUE_H + +#include "driver/storage_dm.h" +#include "kernel/list.h" +#include "stdint.h" +#include "types.h" + +typedef struct StorageRequest { + StorageDevice *storage_device; + + list_t list; + bool rw; + uint8_t *buf; + uint32_t offset; + uint64_t position; + uint32_t count; + bool is_finished; +} StorageRequest; + +void storage_add_request( + StorageDevice *storage_device, StorageRequest *request); +void storage_submit_request(StorageRequest *request); +void storage_finish_request(StorageRequest *storage_request); + +#endif \ No newline at end of file diff --git a/src/include/driver/timer_dm.h b/src/include/driver/timer_dm.h index f5b92a0..8cdd0d7 100644 --- a/src/include/driver/timer_dm.h +++ b/src/include/driver/timer_dm.h @@ -46,8 +46,13 @@ typedef struct Timer { TimerDevice *timer_device; uint32_t timeout; + uint32_t period; } Timer; +typedef struct TimerDeviceManager { + Device *scheduler_timer; +} TimerDeviceManager; + extern struct DeviceManager timer_device_manager; DriverResult register_timer_device( @@ -59,5 +64,6 @@ DriverResult timer_set_frequency(Device *device, uint32_t frequency); void delay_ms(Timer *timer, uint32_t ms); void delay_ms_async(Timer *timer, uint32_t ms); bool timer_is_timeout(Timer *timer); +DriverResult timer_set_timeout(Timer *timer, uint32_t count); #endif \ No newline at end of file diff --git a/src/include/driver/transfer.h b/src/include/driver/transfer.h new file mode 100644 index 0000000..697dcd3 --- /dev/null +++ b/src/include/driver/transfer.h @@ -0,0 +1,49 @@ +#ifndef _TRANSFER_H +#define _TRANSFER_H + +#include "kernel/driver.h" +#include "stdint.h" +#include "types.h" + +struct Device; +typedef DriverResult (*BlockTransferIn)( + struct Device *device, uint8_t *buf, offset_t offset, size_t size); +typedef DriverResult (*BlockTransferOut)( + struct Device *device, uint8_t *buf, offset_t offset, size_t size); + +typedef DriverResult (*StreamTransferIn)( + struct Device *device, uint8_t *buf, size_t size); +typedef DriverResult (*StreamTransferOut)( + struct Device *device, uint8_t *buf, size_t size); + +typedef void (*InterruptTransferCallbackSingle)( + struct Device *device, void *private_data, size_t data); +typedef void (*InterruptTransferCallbackMultiple)( + struct Device *device, void *private_data, void *data, size_t size); +typedef DriverResult (*InterruptTransferIn)( + struct Device *device, InterruptTransferCallbackSingle callback_single, + InterruptTransferCallbackMultiple callback_multiple); + +typedef enum TransferType { + TRANSFER_TYPE_NONE, + TRANSFER_TYPE_BLOCK, + TRANSFER_TYPE_STREAM, + TRANSFER_TYPE_INTERRUPT, +} TransferType; + +typedef struct Transfer { + TransferType type_in; + union { + BlockTransferIn block; + StreamTransferIn stream; + InterruptTransferIn interrupt; + } in; + + TransferType type_out; + union { + BlockTransferOut block; + StreamTransferOut stream; + } out; +} Transfer; + +#endif \ No newline at end of file diff --git a/src/include/kernel/bus_driver.h b/src/include/kernel/bus_driver.h index 2a08f06..706dbac 100644 --- a/src/include/kernel/bus_driver.h +++ b/src/include/kernel/bus_driver.h @@ -38,6 +38,7 @@ typedef struct BusOps { DriverResult (*unregister_device_hook)(struct DeviceDriver *device_driver); DriverResult (*scan_bus)(struct BusDriver *bus_driver, struct Bus *bus); + DriverResult (*probe_device)(struct BusDriver *bus_driver, struct Bus *bus); } BusOps; typedef struct BusDriver { diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index 00e534d..2a0d02c 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -1,12 +1,16 @@ #ifndef _DEVICE_H #define _DEVICE_H +#include "driver/transfer.h" #include "kernel/driver.h" #include "kernel/driver_interface.h" #include "kernel/list.h" #include "stdint.h" #include "string.h" +#include "types.h" +#define device_print_error(device, str, ...) \ + print_error(device->name.text, str, ##__VA_ARGS__) // 调用后自动传递错误 #define DEV_OPS_CALL(dm, func, ...) \ { \ @@ -49,6 +53,13 @@ typedef enum { struct DeviceDriver; +typedef struct ChildDevice { + bool is_using; + uint32_t id; + struct Device *parent; + void *private_data; +} ChildDevice; + typedef struct Device { list_t device_list; list_t dm_list; @@ -57,12 +68,16 @@ typedef struct Device { struct DeviceDriver *device_driver; DeviceIrq *irq; - + Transfer *transfer; DeviceOps *ops; + uint32_t max_child_device; + ChildDevice *child_devices; + void **child_private_data; + void *private_data; uint32_t private_data_size; - void *driver_manager_extension; // 设备管理器所需的扩展信息 + void *device_manager_extension; // 设备管理器所需的扩展信息 } Device; struct Bus; @@ -70,6 +85,8 @@ DriverResult register_device( struct DeviceDriver *device_driver, struct Bus *bus, Device *device); DriverResult unregister_device( struct DeviceDriver *device_driver, Device *device); +DriverResult unregister_child_device(ChildDevice *child_device); +DriverResult register_child_device(Device *device, int private_data_size); DriverResult init_device(Device *device); DriverResult init_and_start(Device *device); diff --git a/src/include/kernel/device_manager.h b/src/include/kernel/device_manager.h index df4f975..69172ab 100644 --- a/src/include/kernel/device_manager.h +++ b/src/include/kernel/device_manager.h @@ -30,7 +30,7 @@ typedef struct DeviceMangerOps { typedef struct DeviceManager { list_t dm_list; - list_t device_driver_lh; + list_t device_lh; DeviceType type; diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index ec67ce7..7beaf76 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -126,6 +126,7 @@ typedef enum DriverResult { DRIVER_RESULT_DEVICE_DRIVER_CONFLICT, DRIVER_RESULT_DEVICE_DRIVER_HAVE_NO_OPS, DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS, + DRIVER_RESULT_NO_VALID_CHILD_DEVICE, DRIVER_RESULT_INVALID_IRQ_NUMBER, DRIVER_RESULT_OUT_OF_MEMORY, DRIVER_RESULT_NULL_POINTER, @@ -160,8 +161,8 @@ typedef struct Driver { DriverState state; - int dependency_count; - struct DriverDenpendency *dependencies; + int dependency_count; + struct DriverDependency *dependencies; DriverResult (*init)(struct Driver *driver); } Driver; diff --git a/src/include/kernel/driver_dependency.h b/src/include/kernel/driver_dependency.h index e378f2e..ced28f9 100644 --- a/src/include/kernel/driver_dependency.h +++ b/src/include/kernel/driver_dependency.h @@ -4,7 +4,7 @@ #include "kernel/bus_driver.h" #include "kernel/device_manager.h" -typedef struct DriverDenpendency { +typedef struct DriverDependency { enum { DRIVER_DEPENDENCY_TYPE_BUS, // 依赖某种总线 DRIVER_DEPENDENCY_TYPE_DEVICE, // 依赖某种设备类型 diff --git a/src/include/kernel/driver_interface.h b/src/include/kernel/driver_interface.h index 065702c..b7dca7b 100644 --- a/src/include/kernel/driver_interface.h +++ b/src/include/kernel/driver_interface.h @@ -3,13 +3,21 @@ #ifdef ARCH_X86 +#include "kernel/func.h" + +#define io_in_byte(port) io_in8(port) +#define io_in_word(port) io_in16(port) +#define io_in_dword(port) io_in32(port) #define io_out_byte(port, data) io_out8(port, data) #define io_out_word(port, data) io_out16(port, data) #define io_out_dword(port, data) io_out32(port, data) -#define io_in_byte(port, data) io_in8(port, data) -#define io_in_word(port, data) io_in16(port, data) -#define io_in_dword(port, data) io_in32(port, data) +#define io_stream_in_byte(port, buffer, nr) io_stream_in8(port, buffer, nr) +#define io_stream_in_word(port, buffer, nr) io_stream_in16(port, buffer, nr) +#define io_stream_in_dword(port, buffer, nr) io_stream_in32(port, buffer, nr) +#define io_stream_out_byte(port, buffer, nr) io_stream_out8(port, buffer, nr) +#define io_stream_out_word(port, buffer, nr) io_stream_out16(port, buffer, nr) +#define io_stream_out_dword(port, buffer, nr) io_stream_out32(port, buffer, nr) #define read_msr(msr, l, h) cpu_RDMSR(msr, l, h) #define write_msr(msr, l, h) cpu_WRMSR(msr, l, h) @@ -25,8 +33,10 @@ #endif #include -#define print_error(str, ...) \ +#define print_error_with_position(str, ...) \ printk(COLOR_RED __FILE__ " Line %d: " str, __LINE__, ##__VA_ARGS__) +#define print_error(source, str, ...) \ + printk(COLOR_RED "[%s]" str, source, ##__VA_ARGS__) #define print_device_info(device, str, ...) \ printk("[%s]" str, device->name.text, ##__VA_ARGS__) #define print_driver_info(driver, str, ...) \ diff --git a/src/include/kernel/periodic_task.h b/src/include/kernel/periodic_task.h new file mode 100644 index 0000000..bba5155 --- /dev/null +++ b/src/include/kernel/periodic_task.h @@ -0,0 +1,17 @@ +#ifndef _PERIODIC_TASK_H +#define _PERIODIC_TASK_H + +#include "kernel/list.h" + +typedef struct PeriodicTask { + list_t period_task_list; + + void (*func)(void *arg); + void *arg; +} PeriodicTask; + +void periodic_task(void *arg); +void periodic_task_add(PeriodicTask *periodic_task); +void periodic_task_del(PeriodicTask *periodic_task); + +#endif \ No newline at end of file diff --git a/src/include/types.h b/src/include/types.h index 63c9a94..b973a10 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -9,4 +9,6 @@ #define true 1 #define false 0 +#define offset_t uint64_t + #endif /*_TYPES_H_*/ \ No newline at end of file diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 1a97c5a..a2b6b42 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -19,6 +19,8 @@ SRC += syscall.c SRC += app.c SRC += elf.c SRC += wait_queue.c +SRC += periodic_task.c +SRC += objects.c #INCLUDE_PATH = ../include/ ../$(ARCH)/include/ diff --git a/src/kernel/console.c b/src/kernel/console.c index 140ce3e..300a5eb 100644 --- a/src/kernel/console.c +++ b/src/kernel/console.c @@ -113,11 +113,11 @@ void scroll_screen(void) { uint32_t *dst = (uint32_t *)console.vram; uint32_t *src = (uint32_t *)(console.vram + 16 * screen_width * bpp); - for (j = 0; j < console.height; j++) { + for (j = 0; j < console.height - 1; j++) { for (i = 0; i < screen_width * bpp * 16 / 4; i++) { *dst = *src; - dst += 4; - src += 4; + dst += 1; + src += 1; } } draw_rect(console.video_device, 0, screen_height - 16, screen_width, 16, 0); @@ -272,6 +272,9 @@ int printk(const char *fmt, ...) { if (console.cur_y >= console.height) { print_char('\n', color); if (console.cur_y < 0) { console.cur_y = 0; } + if (console.cur_y > console.height - 1) { + console.cur_y = console.height - 1; + } if (console.flag == CMD_FLAG_INPUT) { console.start_y = console.cur_y; } diff --git a/src/kernel/device.c b/src/kernel/device.c index 4f474c1..64c5e95 100644 --- a/src/kernel/device.c +++ b/src/kernel/device.c @@ -4,12 +4,29 @@ #include #include #include +#include #include DriverResult register_device( DeviceDriver *device_driver, Bus *bus, Device *device) { + device->state = DEVICE_STATE_REGISTERED; + + device->child_devices = + kmalloc(device->max_child_device * sizeof(ChildDevice)); + device->child_private_data = + kmalloc(device->max_child_device * sizeof(void *)); + for (int i = 0; i < device->max_child_device; i++) { + device->child_devices[i].id = i; + device->child_devices[i].is_using = false; + device->child_devices[i].parent = device; + } + + if (device->private_data_size != 0) { + device->private_data = kmalloc(device->private_data_size); + } list_add_tail(&device->device_list, &device_driver->device_lh); + bus_register_device(device_driver, bus); return DRIVER_RESULT_OK; } @@ -21,6 +38,28 @@ DriverResult unregister_device(DeviceDriver *device_driver, Device *device) { return DRIVER_RESULT_OK; } +DriverResult register_child_device(Device *device, int private_data_size) { + ChildDevice *new = NULL; + for (int i = 0; i < device->max_child_device; i++) { + new = &device->child_devices[i]; + if (!new->is_using) { break; } + } + if (new == NULL) { return DRIVER_RESULT_NO_VALID_CHILD_DEVICE; } + + new->is_using = true; + new->private_data = kmalloc(private_data_size); + device->child_private_data[new->id] = new->private_data; + return DRIVER_RESULT_OK; +} + +DriverResult unregister_child_device(ChildDevice *child_device) { + Device *device = child_device->parent; + child_device->is_using = false; + kfree(child_device->private_data); + device->child_private_data[child_device->id] = NULL; + return DRIVER_RESULT_OK; +} + DriverResult init_device(Device *device) { DeviceManager *manager = device_managers[device->device_driver->type]; if (device->ops->init != NULL) { diff --git a/src/kernel/device_manager.c b/src/kernel/device_manager.c index 71e4604..55174ae 100644 --- a/src/kernel/device_manager.c +++ b/src/kernel/device_manager.c @@ -13,6 +13,7 @@ DriverResult register_device_manager(DeviceManager *manager) { DRV_RESULT_DELIVER_CALL(unregister_device_manager, old_manager); } + list_init(&manager->device_lh); device_managers[manager->type] = manager; DEVM_OPS_CALL(manager, dm_load_hook, manager); @@ -22,7 +23,7 @@ DriverResult register_device_manager(DeviceManager *manager) { DriverResult unregister_device_manager(DeviceManager *manager) { // 关闭所有设备 Device *cur; - list_for_each_owner (cur, &manager->device_driver_lh, device_list) { + list_for_each_owner (cur, &manager->device_lh, device_list) { if (cur->state != DEVICE_STATE_UNREGISTERED) { DEV_OPS_CALL(cur, destroy, cur); } diff --git a/src/kernel/driver.c b/src/kernel/driver.c index 0e5d82d..e4b3239 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -6,6 +6,7 @@ * @date 2022-07-20 */ #include "kernel/spinlock.h" +#include "kernel/wait_queue.h" #include #include #include @@ -62,6 +63,7 @@ void print_driver_result( RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_DRIVER_CONFLICT) RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_DRIVER_HAVE_NO_OPS) RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS) + RESULT_CASE_PRINT(DRIVER_RESULT_NO_VALID_CHILD_DEVICE) RESULT_CASE_PRINT(DRIVER_RESULT_INVALID_IRQ_NUMBER) RESULT_CASE_PRINT(DRIVER_RESULT_OUT_OF_MEMORY) RESULT_CASE_PRINT(DRIVER_RESULT_BUS_DRIVER_ALREADY_EXIST) @@ -95,6 +97,7 @@ DriverResult register_sub_driver( sub_driver->state = SUBDRIVER_STATE_UNREADY; sub_driver->type = type; + wait_queue_init(&sub_driver->wqm); list_add(&sub_driver->sub_driver_list, &driver->sub_driver_lh); return DRIVER_RESULT_OK; @@ -113,7 +116,7 @@ DriverResult driver_init(Driver *driver) { if (result != DRIVER_RESULT_OK) { driver->state = DRIVER_STATE_UNREGISTERED; unregister_driver(driver); - print_error( + print_error_with_position( "driver_init: driver %s init failed!\n", driver->name.text); return result; } @@ -146,9 +149,13 @@ void sub_driver_start_thread(void *arg) { SUBDRIVER_STATE_READY) { schedule(); } + wait_queue_wakeup_all(&bus_driver->subdriver.wqm); if (bus->ops->scan_bus != NULL) { bus->ops->scan_bus(bus_driver, bus); } + if (bus->ops->probe_device != NULL) { + bus->ops->probe_device(bus_driver, bus); + } } } } diff --git a/src/kernel/driver_interface.c b/src/kernel/driver_interface.c index d9990eb..31860c0 100644 --- a/src/kernel/driver_interface.c +++ b/src/kernel/driver_interface.c @@ -20,7 +20,7 @@ list_t device_irq_lists[16] = { DriverResult register_device_irq(DeviceIrq *dev_irq) { if (dev_irq->irq > 16) { - print_error("invalid irq number:%d\n", dev_irq->irq); + print_error_with_position("invalid irq number:%d\n", dev_irq->irq); return DRIVER_RESULT_INVALID_IRQ_NUMBER; } dev_irq->irq = interrupt_redirect_irq(dev_irq->irq); diff --git a/src/kernel/main.c b/src/kernel/main.c index 3449f4a..07bf08b 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -5,9 +5,9 @@ * @date 2020-03 */ #include +#include #include #include -#include #include #include #include @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -33,7 +33,6 @@ #include #include #include -#include void idle(void *arg); struct task_s *task_idle; @@ -44,6 +43,7 @@ int main() { register_device_manager(&interrupt_device_manager); register_device_manager(&timer_device_manager); register_device_manager(&video_device_manager); + register_device_manager(&storage_device_manager); init_platform(); platform_init_and_start_devices(); @@ -56,6 +56,8 @@ int main() { // init_vfs(); do_initcalls(); driver_start_all(); + thread_start( + "Kernel Periodic Tasks", THREAD_DEFAULT_PRIO, periodic_task, NULL); // init_fs(); // thread_start( @@ -105,10 +107,8 @@ int main() { } } -extern uint32_t lapic_read(int index); - void idle(void *arg) { for (;;) { - enable_interrupt(); + schedule(); } } diff --git a/src/kernel/memory.c b/src/kernel/memory.c index c78bffc..0bbc7fd 100644 --- a/src/kernel/memory.c +++ b/src/kernel/memory.c @@ -232,6 +232,7 @@ void *kmalloc(uint32_t size) { } int kfree(void *address) { + if (address == NULL) { return 0; } int i; uint32_t addr = (uint32_t)address; for (i = 0; i < MEMORY_BLOCKS; i++) { diff --git a/src/kernel/objects.c b/src/kernel/objects.c new file mode 100644 index 0000000..e69de29 diff --git a/src/kernel/periodic_task.c b/src/kernel/periodic_task.c new file mode 100644 index 0000000..2f9e652 --- /dev/null +++ b/src/kernel/periodic_task.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +LIST_HEAD(periodic_task_lh); + +void periodic_task(void *arg) { + PeriodicTask *periodic_task; + while (true) { + list_for_each_owner ( + periodic_task, &periodic_task_lh, period_task_list) { + periodic_task->func(periodic_task->arg); + } + schedule(); + } +} + +void periodic_task_add(PeriodicTask *periodic_task) { + list_add_tail(&periodic_task->period_task_list, &periodic_task_lh); +} + +void periodic_task_del(PeriodicTask *periodic_task) { + list_del(&periodic_task->period_task_list); +} \ No newline at end of file diff --git a/src/lib/string.c b/src/lib/string.c index 62fbe89..872e945 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -30,6 +30,7 @@ void string_init(string_t *string) { */ int string_new(string_t *string, char *text, unsigned int max_len) { if (string == NULL || text == NULL || max_len < 1) { return -1; } + max_len += 1; string->text = kmalloc(max_len); if (string->text == NULL) { return -1; } From 91183751dfff16abb47e603c588edcf6b3cfa445 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 5 Jan 2025 00:25:48 +0800 Subject: [PATCH 010/158] =?UTF-8?q?ide=E9=A9=B1=E5=8A=A8=E6=96=B0=E5=A2=9E?= =?UTF-8?q?DMA=E4=BC=A0=E8=BE=93=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/disk/Makefile | 1 + src/arch/x86/drivers/disk/ata/Makefile | 3 + src/arch/x86/drivers/disk/ata/ata.c | 0 src/arch/x86/drivers/disk/ata/ata_driver.c | 38 ++ src/arch/x86/drivers/disk/ata/ide.c | 405 ++++++++++++++++++ .../x86/drivers/disk/ata/ide_controller.c | 219 ++++++++++ src/arch/x86/drivers/disk/ata/include/ata.h | 12 + .../x86/drivers/disk/ata/include/ata_cmd.h | 99 +++++ .../x86/drivers/disk/ata/include/ata_driver.h | 262 +++++++++++ src/arch/x86/drivers/disk/ata/include/ide.h | 47 ++ .../drivers/disk/ata/include/ide_controller.h | 65 +++ src/include/driver/storage_io_queue.h | 1 + 12 files changed, 1152 insertions(+) create mode 100644 src/arch/x86/drivers/disk/Makefile create mode 100644 src/arch/x86/drivers/disk/ata/Makefile create mode 100644 src/arch/x86/drivers/disk/ata/ata.c create mode 100644 src/arch/x86/drivers/disk/ata/ata_driver.c create mode 100644 src/arch/x86/drivers/disk/ata/ide.c create mode 100644 src/arch/x86/drivers/disk/ata/ide_controller.c create mode 100644 src/arch/x86/drivers/disk/ata/include/ata.h create mode 100644 src/arch/x86/drivers/disk/ata/include/ata_cmd.h create mode 100644 src/arch/x86/drivers/disk/ata/include/ata_driver.h create mode 100644 src/arch/x86/drivers/disk/ata/include/ide.h create mode 100644 src/arch/x86/drivers/disk/ata/include/ide_controller.h diff --git a/src/arch/x86/drivers/disk/Makefile b/src/arch/x86/drivers/disk/Makefile new file mode 100644 index 0000000..144fe69 --- /dev/null +++ b/src/arch/x86/drivers/disk/Makefile @@ -0,0 +1 @@ +SRC += ata/ \ No newline at end of file diff --git a/src/arch/x86/drivers/disk/ata/Makefile b/src/arch/x86/drivers/disk/ata/Makefile new file mode 100644 index 0000000..e238cb7 --- /dev/null +++ b/src/arch/x86/drivers/disk/ata/Makefile @@ -0,0 +1,3 @@ +SRC += ata_driver.c +SRC += ide.c +SRC += ide_controller.c \ No newline at end of file diff --git a/src/arch/x86/drivers/disk/ata/ata.c b/src/arch/x86/drivers/disk/ata/ata.c new file mode 100644 index 0000000..e69de29 diff --git a/src/arch/x86/drivers/disk/ata/ata_driver.c b/src/arch/x86/drivers/disk/ata/ata_driver.c new file mode 100644 index 0000000..0283b21 --- /dev/null +++ b/src/arch/x86/drivers/disk/ata/ata_driver.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/ata_driver.h" +#include "include/ide.h" +#include "include/ide_controller.h" + +DriverDependency ata_dependencies[] = { + { + .in_type = DRIVER_DEPENDENCY_TYPE_BUS, + .dependency_in_bus = {BUS_TYPE_PCI, 0}, + .out_bus = NULL, + }, +}; + +Driver ata_driver = { + .name = STRING_INIT("ATA Driver"), + .dependency_count = sizeof(ata_dependencies) / sizeof(DriverDependency), + .dependencies = ata_dependencies, +}; + +static __init void ata_driver_initcall(void) { + register_driver(&ata_driver); + register_device_driver(&ata_driver, &ide_controller_device_driver); + register_device_driver(&ata_driver, &ide_device_driver); + pci_register_driver(&ata_driver, &ide_pci_driver); +} + +driver_initcall(ata_driver_initcall); \ No newline at end of file diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c new file mode 100644 index 0000000..dbde929 --- /dev/null +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -0,0 +1,405 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/ata.h" +#include "include/ata_cmd.h" +#include "include/ata_driver.h" +#include "include/ide.h" +#include "include/ide_controller.h" + +DriverResult ide_device_init(Device *device); + +DriverResult ide_device_read_sectors( + StorageDevice *storage_device, StorageRequest *request); +DriverResult ide_device_write_sectors( + StorageDevice *storage_device, StorageRequest *request); +bool ide_device_is_busy(StorageDevice *storage_device); + +StorageDeviceOps ide_storage_device_ops = { + .submit_read_request = ide_device_read_sectors, + .submit_write_request = ide_device_write_sectors, + .is_busy = ide_device_is_busy, +}; +DeviceDriverOps ide_device_driver_ops = { + .register_driver_hook = NULL, + .unregister_driver_hook = NULL, +}; +DeviceOps ide_device_ops = { + .init = ide_device_init, + .start = NULL, + .stop = NULL, + .destroy = NULL, + .status = NULL, +}; + +DeviceDriver ide_device_driver = { + .name = STRING_INIT("IDE Driver"), + .type = DEVICE_TYPE_STORAGE, + .priority = DRIVER_PRIORITY_BASIC, + .state = DRIVER_STATE_UNREGISTERED, + .ops = &ide_device_driver_ops, +}; +Transfer ide_transfer = { + .type_in = TRANSFER_TYPE_BLOCK, + .type_out = TRANSFER_TYPE_BLOCK, +}; + +void ide_channel0_handler(Device *device) { + IdeChannel *ide_channel = device->child_private_data[0]; + + int status = io_in_byte(ide_channel->io_base + ATA_REG_ALTSTATUS); + if (BIN_IS_EN(status, ATA_STATUS_ERR)) { + print_error("IDE", "IDE device error!"); + } + + IdeDevice *ide_device = + ide_channel->ide_devices[ide_channel->selected_device]; + StorageRequest *request = ide_device->current_request; + ide_device->current_request = NULL; + if (ide_device->mode == TRANSFER_MODE_DMA) { + uint8_t data = io_in_byte(ide_channel->bmide + IDE_REG_BM_STATUS); + io_out_byte( + ide_channel->bmide + IDE_REG_BM_STATUS, + BIN_EN(data, IDE_BMSTATUS_INT | IDE_BMSTATUS_ERROR)); + + data = io_in_byte(ide_channel->bmide + IDE_REG_BM_COMMAND); + io_out_byte( + ide_channel->bmide + IDE_REG_BM_COMMAND, + BIN_DIS(data, IDE_BMCMD_START_STOP_BM)); + + if (request->rw == 0 && request->dma_buf != request->buf) { + memcpy(request->buf, request->dma_buf, request->count * 512); + } + kfree(request->dma_buf); + } + storage_finish_request(request); +} +void ide_channel1_handler(Device *device) { +} + +void ide_sync(IdeChannel *channel) { + // 保证先前的命令执行,而不是在缓存中 + io_in_byte(channel->io_base + ATA_REG_ALTSTATUS); +} + +void ide_pause(IdeChannel *channel) { + ide_sync(channel); + delay_ms(&channel->timer, 1); +} + +void ide_device_probe(IdeChannel *channel) { + int i, status, err = 0; + AtaDeviceType type = ATA_DEVICE_TYPE_ATA; + + timer_init(&channel->timer); + channel->device_count = 0; + // ide_reset_drive(channel); + for (i = 0; i < 2; i++) { + // 1.选择设备 + ide_select_device(channel, i); + ide_pause(channel); + + // 2.发送IDENTIFY命令 + io_out_byte( + channel->io_base + ATA_REG_COMMAND, ATA_CMD_IDENTIFY_DEVICE); + + // 3.检查设备状态 + if (io_in_byte(channel->io_base + ATA_REG_STATUS) == 0) { + continue; // 设备不存在 + } + while (true) { + status = io_in_byte(channel->io_base + ATA_REG_STATUS); + if (BIN_IS_EN(status, ATA_STATUS_ERR)) { + err = 1; + break; + } + if (BIN_IS_DIS(status, ATA_STATUS_BUSY) && + BIN_IS_EN(status, ATA_STATUS_DRQ)) { + break; + } + } + + // 4.检查设备类型 + if (err != 0) { + uint8_t cl = io_in_byte(channel->io_base + ATA_REG_LBA1); + uint8_t ch = io_in_byte(channel->io_base + ATA_REG_LBA2); + + if (cl == ~ch && (cl == 0x14 || cl == 0x69)) { + type = ATA_DEVICE_TYPE_ATAPI; + io_out_byte( + channel->io_base + ATA_REG_COMMAND, + ATA_CMD_IDENTIFY_PACKET_DEVICE); + ide_wait(channel); + } else { + continue; + } + } + + // 5.读取设备信息 + AtaIdentifyInfo *identify = kmalloc(512); + io_stream_in_word( + channel->io_base + ATA_REG_DATA, (uint32_t)identify, + sizeof(AtaIdentifyInfo) / 2); + + // 6.注册设备 + Device *device = kmalloc(sizeof(Device)); + device->ops = &ide_device_ops; + device->state = DEVICE_STATE_UNREGISTERED; + device->device_driver = &ide_device_driver; + device->private_data_size = sizeof(IdeDevice); + device->transfer = &ide_transfer; + string_new(&device->name, "IDE HardDisk", 13); + + StorageDevice *storage_device = kmalloc(sizeof(StorageDevice)); + storage_device->type = STORAGE_DEVICE_TYPE_ATA; + storage_device->ops = &ide_storage_device_ops; + + register_storage_device(&ide_device_driver, device, storage_device); + + IdeDevice *ide_device = device->private_data; + ide_device->device = device; + ide_device->channel = channel; + ide_device->type = type; + ide_device->info = identify; + ide_device->device_num = i; + ide_device->current_request = NULL; + + channel->ide_devices[i] = ide_device; + init_and_start(device); + + channel->device_count++; + } + if (channel->device_count) { + uint8_t data = io_in_byte(channel->io_base + ATA_REG_CONTROL); + io_out_byte( + channel->io_base + ATA_REG_CONTROL, + BIN_DIS(data, ATA_CONTROL_NIEN)); + channel->prdt = kmalloc(sizeof(PhysicalRegionDescriptorTable)); + interrupt_enable_irq(channel->irq->irq); + } +} + +DriverResult ide_device_init(Device *device) { + IdeDevice *ide_device = device->private_data; + AtaIdentifyInfo *identify = ide_device->info; + + if (identify->capabilities.dma_supported) { + ide_device->mode = TRANSFER_MODE_DMA; + ide_device->cmdset[ATA_CMDSET_READ] = ATA_CMD_READ_DMA_EXT; + ide_device->cmdset[ATA_CMDSET_WRITE] = ATA_CMD_WRITE_DMA_EXT; + ide_device->cmdset[ATA_CMDSET_READ] = ATA_CMD_READ_DMA; + ide_device->cmdset[ATA_CMDSET_WRITE] = ATA_CMD_WRITE_DMA; + } else if (identify->pio_modes_supported) { + ide_device->mode = TRANSFER_MODE_PIO; + ide_device->cmdset[ATA_CMDSET_READ_EXT] = ATA_CMD_READ_PIO_EXT; + ide_device->cmdset[ATA_CMDSET_WRITE_EXT] = ATA_CMD_WRITE_PIO_EXT; + ide_device->cmdset[ATA_CMDSET_READ] = ATA_CMD_READ_PIO; + ide_device->cmdset[ATA_CMDSET_WRITE] = ATA_CMD_WRITE_PIO; + } else { + return DRIVER_RESULT_UNSUPPORT_DEVICE; + } + + return DRIVER_RESULT_OK; +} + +void ide_set_sector_lba28(IdeChannel *channel, uint32_t lba0, uint8_t count) { + io_out_byte(channel->io_base + ATA_REG_SECCOUNT0, count); + io_out_byte(channel->io_base + ATA_REG_LBA0, lba0 & 0xff); + io_out_byte(channel->io_base + ATA_REG_LBA1, (lba0 >> 8) & 0xff); + io_out_byte(channel->io_base + ATA_REG_LBA2, (lba0 >> 16) & 0xff); +} + +void ide_set_sector_lba48( + IdeChannel *channel, uint32_t lba0, uint32_t lba1, uint16_t count) { + io_out_byte(channel->io_base + ATA_REG_SECCOUNT1, count >> 8); + io_out_byte(channel->io_base + ATA_REG_LBA3, lba1 & 0xff); + io_out_byte(channel->io_base + ATA_REG_LBA4, (lba1 >> 8) & 0xff); + io_out_byte(channel->io_base + ATA_REG_LBA5, (lba1 >> 16) & 0xff); + + io_out_byte(channel->io_base + ATA_REG_SECCOUNT0, count); + io_out_byte(channel->io_base + ATA_REG_LBA0, lba0 & 0xff); + io_out_byte(channel->io_base + ATA_REG_LBA1, (lba0 >> 8) & 0xff); + io_out_byte(channel->io_base + ATA_REG_LBA2, (lba0 >> 16) & 0xff); +} + +/** + * 通过PIO方式接收数据 + */ +void ide_device_recv_pio(IdeDevice *device, uint32_t *buf, uint32_t count) { + IdeChannel *channel = device->channel; + + ide_wait(channel); + io_stream_in_word( + channel->io_base + ATA_REG_DATA, (uint32_t)buf, + count << 8 /* count * 512 / 2 */); +} + +/** + * 通过PIO方式发送数据 + */ +void ide_device_send_pio(IdeDevice *device, uint32_t *buf, uint32_t count) { + IdeChannel *channel = device->channel; + + ide_wait(channel); + io_stream_out_word( + channel->io_base + ATA_REG_DATA, (uint32_t)buf, + count << 8 /* count * 512 / 2 */); +} + +/** + * 配置DMA + */ +void ide_device_set_dma(IdeDevice *device, StorageRequest *request) { + IdeChannel *channel = device->channel; + + PhysicalRegionDescriptorTable *prdt = channel->prdt; + + uint8_t *buffer; + buffer = (uint32_t)request->buf & 3 + ? kmalloc(request->count * 512) // 未对齐则另外分配 + : request->buf; // 传入的缓冲区已对齐则直接使用 + request->dma_buf = buffer; + prdt->base_addr = vir2phy((uint32_t)buffer); + prdt->count = request->count * 512; + prdt->sign = BIT(15); + + io_out_dword(channel->bmide + IDE_REG_BM_PRDT, vir2phy((uint32_t)prdt)); + + uint8_t data = io_in_byte(channel->bmide + IDE_REG_BM_STATUS); + io_out_byte( + channel->bmide + IDE_REG_BM_STATUS, + BIN_EN(data, IDE_BMSTATUS_INT | IDE_BMSTATUS_ERROR)); + + io_in_byte(channel->bmide + IDE_REG_BM_COMMAND); + data = (request->rw == 0) ? BIN_EN(data, IDE_BMCMD_READ_WRITE) + : BIN_DIS(data, IDE_BMCMD_READ_WRITE); + io_out_byte(channel->bmide + IDE_REG_BM_COMMAND, data); +} + +/** + * 从设备读取扇区,调用方保证buf与count的合法性 + * + * lba0 & lba1: lba地址,最大支持48位 + * + * count: 扇区数,最大为65535 + */ +DriverResult ide_device_read_sectors( + StorageDevice *storage_device, StorageRequest *request) { + IdeDevice *ide_device = storage_device->device->private_data; + IdeChannel *channel = ide_device->channel; + + bool flag = false; + + // 因为没有实现对28位地址的处理,所以超过24位都使用48位地址 + if ((request->position < 0x1000000) || request->count < 0x100) { + flag = true; + } + + if (ide_device->mode == TRANSFER_MODE_DMA) { + ide_device_set_dma(ide_device, request); + } + + ide_select_device(channel, ide_device->device_num); + ide_wait(channel); + + uint8_t cmd; + if (flag) { + ide_set_sector_lba28(channel, request->position, request->count); + cmd = ide_device->cmdset[ATA_CMDSET_READ]; + } else { + ide_set_sector_lba48( + channel, request->position & 0xffffff, request->position >> 24, + request->count); + cmd = ide_device->cmdset[ATA_CMDSET_READ_EXT]; + } + + ide_wait(channel); + io_out_byte(channel->io_base + ATA_REG_COMMAND, cmd); + + ide_device->current_request = request; + if (ide_device->mode == TRANSFER_MODE_PIO) { + ide_device_recv_pio( + ide_device, (uint32_t *)request->buf, request->count); + } else { + uint8_t data = io_in_byte(channel->bmide + IDE_REG_BM_COMMAND); + io_out_byte( + channel->bmide + IDE_REG_BM_COMMAND, + BIN_EN(data, IDE_BMCMD_START_STOP_BM)); + } + return DRIVER_RESULT_OK; +} + +/** + * 向设备写入扇区,调用方保证buf与count的合法性 + * + * lba0 & lba1: lba地址,最大支持48位 + * + * count: 扇区数,最大为65535 + */ +DriverResult ide_device_write_sectors( + StorageDevice *storage_device, StorageRequest *request) { + IdeDevice *ide_device = storage_device->device->private_data; + IdeChannel *channel = ide_device->channel; + + bool flag = false; + + // 因为没有实现对28位地址的处理,所以超过24位都使用48位地址 + if ((request->position < 0x1000000) || request->count < 0x100) { + flag = true; + } + + if (ide_device->mode == TRANSFER_MODE_DMA) { + ide_device_set_dma(ide_device, request); + if (request->dma_buf != request->buf) { + memcpy(request->dma_buf, request->buf, request->count * 512); + } + } + + ide_select_device(channel, ide_device->device_num); + ide_wait(channel); + + uint8_t cmd; + if (flag) { + ide_set_sector_lba28(channel, request->position, request->count); + cmd = ide_device->cmdset[ATA_CMDSET_WRITE]; + } else { + ide_set_sector_lba48( + channel, request->position & 0xffffff, request->position >> 24, + request->count); + cmd = ide_device->cmdset[ATA_CMDSET_WRITE_EXT]; + } + + ide_wait(channel); + io_out_byte(channel->io_base + ATA_REG_COMMAND, cmd); + + if (ide_device->mode == TRANSFER_MODE_PIO) { + ide_device_send_pio( + ide_device, (uint32_t *)request->buf, request->count); + } else { + uint8_t data = io_in_byte(channel->bmide + IDE_REG_BM_COMMAND); + io_out_byte( + channel->bmide + IDE_REG_BM_COMMAND, + BIN_EN(data, IDE_BMCMD_START_STOP_BM)); + } + return DRIVER_RESULT_OK; +} + +bool ide_device_is_busy(StorageDevice *storage_device) { + Device *device = storage_device->device; + IdeDevice *ide_device = device->private_data; + + return ide_device->current_request != NULL; +} diff --git a/src/arch/x86/drivers/disk/ata/ide_controller.c b/src/arch/x86/drivers/disk/ata/ide_controller.c new file mode 100644 index 0000000..c715043 --- /dev/null +++ b/src/arch/x86/drivers/disk/ata/ide_controller.c @@ -0,0 +1,219 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/ata_driver.h" +#include "include/ide.h" +#include "include/ide_controller.h" + +DriverResult ide_controller_probe(PciDevice *pci_device); +DriverResult ide_controller_init(Device *device); + +DeviceDriverOps ide_controller_device_driver_ops = { + .register_driver_hook = NULL, + .unregister_driver_hook = NULL, +}; +DeviceDriver ide_controller_device_driver = { + .name = STRING_INIT("IDE Controller Device Driver"), + .type = DEVICE_TYPE_BUS_CONTROLLER, + .priority = DRIVER_PRIORITY_BASIC, + .state = DRIVER_STATE_UNREGISTERED, + .ops = &ide_controller_device_driver_ops, +}; + +DeviceOps ide_controller_device_ops = { + .init = ide_controller_init, + .start = NULL, + .stop = NULL, + .destroy = NULL, + .status = NULL, +}; + +PciDriverOps ide_pci_driver_ops = { + .probe = ide_controller_probe, +}; +PciDriver ide_pci_driver = { + .find_type = FIND_BY_CLASSCODE_SUBCLASS, + .class_subclass = {IDE_CONTROLLER_CLASSCODE, IDE_CONTROLLER_SUBCLASS}, + .device_driver = &ide_controller_device_driver, + .driver = &ata_driver, + .ops = &ide_pci_driver_ops, +}; + +void ide_detect_channel_mode( + IdeChannel *channel, PciDevice *pci_device, int i) { + int bit = 1 << (i * 2); + if (pci_device->prog_if & bit) { + if (pci_device->prog_if & (bit << 1)) { + channel->channel_num = i; + channel->mode = IDE_NATIVE_MODE; + pci_device->prog_if |= bit; + pci_device_write8(pci_device, PCI_REG_PROGIF, pci_device->prog_if); + } else { + channel->channel_num = i; + channel->mode = IDE_COMPATITY_MODE; + } + } +} + +DriverResult ide_controller_probe(PciDevice *pci_device) { + Device *device = kmalloc(sizeof(Device)); + string_new(&device->name, "IDE Controller", 15); + device->state = DEVICE_STATE_UNREGISTERED; + device->ops = &ide_controller_device_ops; + device->device_driver = &ide_controller_device_driver; + device->private_data_size = sizeof(IdeControllerInfo); + device->max_child_device = 2; + register_device(&ide_controller_device_driver, pci_device->bus, device); + + IdeControllerInfo *info = device->private_data; + info->pci_device = pci_device; + info->dma_support = pci_device->prog_if >> 7; + info->bus_master_base = pci_device->common.bar[4].base_addr; + + return DRIVER_RESULT_OK; +} + +void ide_controller_setup_legacy_mode(IdeChannel *channel) { + channel->io_base = + (channel->channel_num ? ATA_SECONDARY_PORT : ATA_PRIMARY_PORT); + channel->control_base = + (channel->channel_num ? ATA_SECONDARY_CONTROL_PORT + : ATA_PRIMARY_CONTROL_PORT); + channel->irq->irq = (channel->channel_num ? IDE_IRQ1 : IDE_IRQ0); +} + +void ide_controller_setup_pci_mode(PciDevice *pci_device, IdeChannel *channel) { + channel->io_base = + pci_device->common.bar[channel->channel_num * 2].base_addr; + channel->control_base = + pci_device->common.bar[channel->channel_num * 2 + 1].base_addr; + channel->irq->irq = pci_device->irqline; +} + +DriverResult ide_controller_init(Device *device) { + IdeControllerInfo *info = device->private_data; + + for (int i = 0; i < 2; i++) { + register_child_device(device, sizeof(IdeChannel)); + + IdeChannel *channel = device->child_private_data[i]; + + channel->channel_num = i; + // 检查是否支持PCI Native模式 + ide_detect_channel_mode(channel, info->pci_device, i); + + DeviceIrq *irq = kmalloc(sizeof(DeviceIrq)); + irq->device = device; + irq->handler = + (channel->channel_num == 0 ? ide_channel0_handler + : ide_channel1_handler); + channel->irq = irq; + + if (channel->mode == IDE_COMPATITY_MODE) { + ide_controller_setup_legacy_mode(channel); + } else { + ide_controller_setup_pci_mode(info->pci_device, channel); + } + + if (BIN_IS_EN(info->pci_device->prog_if, BIT(7))) { + channel->bmide = info->pci_device->common.bar[4].base_addr; + channel->bmide += (channel->channel_num ? 8 : 0); + pci_enable_bus_mastering(info->pci_device); + } + + // 禁用并注册IRQ + io_out_byte(channel->io_base + ATA_REG_CONTROL, ATA_CONTROL_NIEN); + register_device_irq(irq); + + ide_device_probe(channel); + } + + return DRIVER_RESULT_OK; +} + +void ide_print_error(IdeChannel *channel, char *source) { + int status = io_in_byte(channel->io_base + ATA_REG_STATUS); + if (status & ATA_STATUS_DF) { + print_error(source, "Device Fault!\n"); + } else if (status & ATA_STATUS_ERR) { + int err = io_in_byte(channel->io_base + ATA_REG_ERROR); + if (err & ATA_ERROR_AMNF) { + print_error(source, "No Address Mark Found\n"); + } + if (err & ATA_ERROR_TK0NF) { + print_error(source, "No Media or Media Mark Found\n"); + } + if (err & ATA_ERROR_ABRT) { print_error(source, "Command Aborted\n"); } + if (err & ATA_ERROR_MCR) { + print_error(source, "No Media or Media Error\n"); + } + if (err & ATA_ERROR_IDNF) { + print_error(source, "ID mark not Found\n"); + } + if (err & ATA_ERROR_MC) { + print_error(source, "No Media or Media Error\n"); + } + if (err & ATA_ERROR_UNC) { + print_error(source, "Uncorrectable Data Error\n"); + } + if (err & ATA_ERROR_BBK) { print_error(source, "Bad Sectors\n"); } + } else if (status & ATA_STATUS_DRQ) { + print_error(source, "Reads Nothing\n"); + } +} + +void ide_reset_drive(IdeChannel *channel) { + uint8_t data = io_in_byte(channel->io_base + ATA_REG_CONTROL); + io_out_byte(channel->io_base + ATA_REG_CONTROL, BIN_EN(data, BIT(2))); + + // 等待重置 + int i; + for (i = 0; i < 50; i++) { + io_in_byte(channel->io_base + ATA_REG_STATUS); + } + io_out_byte(channel->io_base + ATA_REG_CONTROL, data); + channel->selected_device = 0; +} + +void ide_select_device(IdeChannel *channel, int device_num) { + io_out_byte( + channel->io_base + ATA_REG_HDDEV_SEL, + device_num << 4 | BIT(6) | BIT(5) | BIT(7)); + channel->selected_device = device_num; +} + +int ide_wait(IdeChannel *channel) { + int status; + do { + status = io_in_byte(channel->io_base + ATA_REG_STATUS); + } while (BIN_IS_EN(status, ATA_STATUS_BUSY)); + return 0; +} + +void ide_polling(IdeChannel *channel) { + + // 等待400ns + for (int i = 0; i < 4; i++) { + io_in_byte(channel->io_base + ATA_REG_ALTSTATUS); // 读一次需要100ns + } + + int status; + do { + status = io_in_byte(channel->io_base + ATA_REG_STATUS); + } while (BIN_IS_EN(status, ATA_STATUS_BUSY)); + + if (BIN_IS_EN(status, ATA_STATUS_ERR)) { + print_error_with_position("in ide_select_device(): IDE Error!\n"); + } +} diff --git a/src/arch/x86/drivers/disk/ata/include/ata.h b/src/arch/x86/drivers/disk/ata/include/ata.h new file mode 100644 index 0000000..5121958 --- /dev/null +++ b/src/arch/x86/drivers/disk/ata/include/ata.h @@ -0,0 +1,12 @@ +#ifndef _ATA_H +#define _ATA_H + +typedef enum AtaCmdIndex { + ATA_CMDSET_READ, + ATA_CMDSET_READ_EXT, + ATA_CMDSET_WRITE, + ATA_CMDSET_WRITE_EXT, + ATA_CMDSET_MAX, +} AtaCmdIndex; + +#endif \ No newline at end of file diff --git a/src/arch/x86/drivers/disk/ata/include/ata_cmd.h b/src/arch/x86/drivers/disk/ata/include/ata_cmd.h new file mode 100644 index 0000000..306c736 --- /dev/null +++ b/src/arch/x86/drivers/disk/ata/include/ata_cmd.h @@ -0,0 +1,99 @@ +#ifndef _ATA_CMD_H +#define _ATA_CMD_H + +#define ATA_CMD_CFA_ERASE_SECTORS 0xc0 +#define ATA_CMD_CFA_REQUEST_EXTENDED_ERROR 0x03 +#define ATA_CMD_CFA_TRANSLATE_SECTOR 0x87 +#define ATA_CMD_CFA_WRITE_MULTIPLE_WITHOUT_ERASE 0xcd +#define ATA_CMD_CFA_WRITE_SECTORS_WITHOUT_ERASE 0x38 + +#define ATA_CMD_CHECK_MEDIA_CARD_TYPE 0xd1 +#define ATA_CMD_CHECK_POWER_MODE 0xe5 + +#define ATA_CMD_CONFIG_STREAM 0x51 +#define ATA_CMD_CONFIG_FREEZE_LOCK 0xb1 +#define ATA_CMD_CONFIG_IDENTIFY 0xb1 +#define ATA_CMD_CONFIG_RESTORE 0xb1 +#define ATA_CMD_CONFIG_SET 0xb1 + +#define ATA_CMD_DEVICE_RESET 0x08 +#define ATA_CMD_DOWNLOAD_MICROCODE 0x92 +#define ATA_CMD_EXEC_DEVICE_DIAGNOSTIC 0x90 + +#define ATA_CMD_FLUSH_CACHE 0xe7 +#define ATA_CMD_FLUSH_CACHE_EXT 0xea + +#define ATA_CMD_GET_MEDIA_STATUS 0xda +#define ATA_CMD_MEDIA_EJECT 0xed +#define ATA_CMD_MEDIA_LOCK 0xde +#define ATA_CMD_MEDIA_UNLOCK 0xdf +#define ATA_CMD_STANDBY_IMMEDIATE 0xe0 +#define ATA_CMD_IDLE_IMMEDIATE 0xe1 +#define ATA_CMD_STANDBY 0xe2 +#define ATA_CMD_IDLE 0xe3 + +#define ATA_CMD_NOP 0x00 +#define ATA_CMD_SLEEP 0xe6 +#define ATA_CMD_IDENTIFY_DEVICE 0xec +#define ATA_CMD_IDENTIFY_PACKET_DEVICE 0xa1 +#define ATA_CMD_SET_FEATURES 0xef +#define ATA_CMD_PACKET 0xa0 +#define ATA_CMD_SERVICE 0xa2 + +#define ATA_CMD_READ_BUFFER 0xe4 +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xc8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_READ_DMA_QUEUED 0xc7 +#define ATA_CMD_READ_DMA_QUEUED_EXT 0x26 +#define ATA_CMD_READ_STREAM_DMA_EXT 0x2a +#define ATA_CMD_READ_STREAM_EXT 0x2b +#define ATA_CMD_READ_VERIFY_SECTORS 0x40 +#define ATA_CMD_READ_VERIFY_SECTORS_EXT 0x42 + +#define ATA_CMD_WRITE_BUFFER 0xe8 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xca +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_WRITE_DMA_QUEUED 0xcc +#define ATA_CMD_WRITE_DMA_QUEUED_EXT 0x36 +#define ATA_CMD_WRITE_DMA_MAX_ADDR_EXT 0x37 +#define ATA_CMD_WRITE_STREAM_DMA_EXT 0x3a +#define ATA_CMD_WRITE_STREAM_EXT 0x3b + +#define ATA_CMD_READ_NATIVE_MAX_ADDR 0xf8 +#define ATA_CMD_READ_NATIVE_MAX_ADDR_EXT 0x27 +#define ATA_CMD_SET_MAX_ADDR 0xf9 + +#define ATA_CMD_READ_LOG_EXT 0x2f +#define ATA_CMD_WRITE_LOG_EXT 0x3f + +#define ATA_CMD_WRITE_DMA_FUA_EXT 0x3d +#define ATA_CMD_WRITE_DMA_QUEUED_FUA_EXT 0x3e +#define ATA_CMD_WRITE_FUA 0xce + +#define ATA_CMD_SET_MULTIPLE_MODE 0xc6 +#define ATA_CMD_READ_MULTIPLE 0xc4 +#define ATA_CMD_READ_MULTIPLE_EXT 0x29 +#define ATA_CMD_WRITE_MULTIPLE 0xc5 +#define ATA_CMD_WRITE_MULTIPLE_EXT 0x39 + +#define ATA_CMD_SECURITY_SET_PASSWORD 0xf1 +#define ATA_CMD_SECURITY_UNLOCK 0xf2 +#define ATA_CMD_SECURITY_ERASE_PREPARE 0xf3 +#define ATA_CMD_SECURITY_ERASE_UNIT 0xf4 +#define ATA_CMD_SECURITY_FREEZE_LOCK 0xf5 +#define ATA_CMD_SECURITY_DISABLE_PASSWORD 0xf6 + +#define ATA_CMD_SMART_DISABLE_OPERATIONS 0xb0 +#define ATA_CMD_SMART_EN_DIS_AUTOSAVE 0xb0 +#define ATA_CMD_SMART_ENABLE_OPERATIONS 0xb0 +#define ATA_CMD_SMART_EXECUTE_OFFLINE_IMMEDIATE 0xb0 +#define ATA_CMD_SMART_READ_DATA 0xb0 +#define ATA_CMD_SMART_READ_LOG 0xb0 +#define ATA_CMD_SMART_RETURN_STATUS 0xb0 +#define ATA_CMD_SMART_WRITE_LOG 0xb0 + +#endif \ No newline at end of file diff --git a/src/arch/x86/drivers/disk/ata/include/ata_driver.h b/src/arch/x86/drivers/disk/ata/include/ata_driver.h new file mode 100644 index 0000000..cb20364 --- /dev/null +++ b/src/arch/x86/drivers/disk/ata/include/ata_driver.h @@ -0,0 +1,262 @@ +#ifndef _ATA_DRIVER_H +#define _ATA_DRIVER_H + +#include "bits.h" +#include + +#define ATA_PRIMARY_PORT 0x1f0 +#define ATA_SECONDARY_PORT 0x170 + +#define ATA_PRIMARY_CONTROL_PORT 0x3f6 +#define ATA_SECONDARY_CONTROL_PORT 0x376 + +typedef enum AtaDeviceType { + ATA_DEVICE_TYPE_ATA, + ATA_DEVICE_TYPE_ATAPI, +} AtaDeviceType; + +#define ATA_STATUS_BUSY 0x80 // 驱动器忙 +#define ATA_STATUS_READY 0x40 // 驱动器就绪 +#define ATA_STATUS_DF 0x20 // 驱动器写故障 +#define ATA_STATUS_SEEK 0x10 // 驱动器查找完成 +#define ATA_STATUS_DRQ 0x08 // 请求数据 +#define ATA_STATUS_CORR 0x04 // Correct data +#define ATA_STATUS_INDEX 0x02 // 索引 +#define ATA_STATUS_ERR 0x01 // 错误 + +#define ATA_ERROR_BBK 0x80 // 错误块 +#define ATA_ERROR_UNC 0x40 // 无法矫正的数据 +#define ATA_ERROR_MC 0x20 // 媒体更改 +#define ATA_ERROR_IDNF 0x10 // 找不到ID标记 +#define ATA_ERROR_MCR 0x08 // 媒体更改请求 +#define ATA_ERROR_ABRT 0x04 // 命令终止 +#define ATA_ERROR_TK0NF 0x02 // 找不到磁道0 +#define ATA_ERROR_AMNF 0x01 // 没有地址标记 + +#define ATA_CONTROL_NIEN BIT(1) // 禁止中断 +#define ATA_CONTROL_SRST BIT(2) // 软复位 +#define ATA_CONTROL_HOB BIT(7) // 高字节优先(大端字节序) + +#define ATA_REG_DATA 0x00 +#define ATA_REG_ERROR 0x01 +#define ATA_REG_FEATURES 0x01 +#define ATA_REG_SECCOUNT0 0x02 +#define ATA_REG_LBA0 0x03 +#define ATA_REG_LBA1 0x04 +#define ATA_REG_LBA2 0x05 +#define ATA_REG_HDDEV_SEL 0x06 +#define ATA_REG_COMMAND 0x07 +#define ATA_REG_STATUS 0x07 + +#define ATA_REG_SECCOUNT1 0x02 +#define ATA_REG_LBA3 0x03 +#define ATA_REG_LBA4 0x04 +#define ATA_REG_LBA5 0x05 + +#define ATA_REG_CONTROL 0x02 +#define ATA_REG_ALTSTATUS 0x02 +#define ATA_REG_DEVADDRESS 0x03 + +#define ATA_PRIMARY 0x00 +#define ATA_SECONDARY 0x01 + +#define ATA_MASTER 0x00 +#define ATA_SLAVE 0x01 + +typedef struct AtaIdentifyInfo { + struct { + uint8_t reserved1 : 1; + uint8_t retired1 : 1; + uint8_t response_incomplete : 1; + uint8_t retired2 : 3; + uint8_t obsolete : 1; + uint8_t removable : 1; + uint8_t retired3 : 7; + uint8_t device_type : 1; + } general_config; + uint16_t obsolete1; + uint16_t specific_config; + uint16_t obsolete2; + uint32_t retired1; + uint16_t obsolete3; + uint32_t reserved1; + uint16_t retired2; + uint8_t serial_number[20]; + uint32_t retired3; + uint16_t obsolete4; + uint8_t firmware_revision[8]; + uint8_t model_number[40]; + uint8_t max_block_transfer; + uint8_t reserved2; + uint16_t reserved3; + struct { + uint8_t retired; + uint8_t dma_supported : 1; + uint8_t lba_supported : 1; + uint8_t ioready_disabled : 1; + uint8_t ioready_supported : 1; + uint8_t reserved1 : 1; + uint8_t standby_timer_supported : 1; + uint8_t reserved2 : 2; + } capabilities; + uint16_t reserved4; + uint32_t obsolete5; + uint16_t translation_field_valid : 3; + uint16_t reserved5 : 13; + uint16_t obsolete6[5]; + uint8_t current_block; + uint8_t multiple_sector_valid : 1; + uint8_t reserved6 : 7; + uint32_t total_sectors; + uint16_t obsolete7; + struct { + uint8_t dma_modes_supported : 3; + uint8_t reserved1 : 5; + uint8_t dma_modes_select : 3; + uint8_t reserved2 : 5; + } multiword_dma; + uint8_t pio_modes_supported; + uint8_t reserved7; + uint16_t min_multiword_dma_cycle_time; + uint16_t recommended_multiword_dma_cycle_time; + uint16_t min_pio_cycle_time; + uint16_t min_pio_cycle_time_ioready; + uint32_t reserved8; + uint16_t reserved9[4]; + uint16_t max_queue_depth : 5; + uint16_t reserved10 : 11; + uint16_t reserved_for_sata[4]; + uint16_t major_version; + uint16_t minor_version; + struct { + uint8_t smart_supported : 1; + uint8_t security_supported : 1; + uint8_t removable_media : 1; + uint8_t power_management_supported : 1; + uint8_t reserved1 : 1; + uint8_t write_cache_supported : 1; + uint8_t look_ahead_supported : 1; + uint8_t release_interrupt_supported : 1; + uint8_t service_interrupt_supported : 1; + uint8_t device_reset_supported : 1; + uint8_t host_protected_area_supported : 1; + uint8_t obsolete1 : 1; + uint8_t write_buffer_command_supported : 1; + uint8_t read_buffer_command_supported : 1; + uint8_t nop_command_supported : 1; + uint8_t obsolete : 1; + uint8_t download_microcode_supported : 1; + uint8_t rw_dma_queued_supported : 1; + uint8_t cfa_supported : 1; + uint8_t advanced_power_management : 1; + uint8_t removable_media_status_notification_supported : 1; + uint8_t powerup_in_standby_supported : 1; + uint8_t set_features_required_to_spinup_after_powerup : 1; + uint8_t obsolete2 : 1; + uint8_t set_max_security_supported : 1; + uint8_t auto_acoustic_management_supported : 1; + uint8_t addressing_48bit_supported : 1; + uint8_t device_config_overlay_supported : 1; + uint8_t mandatory_flush_cache_supported : 1; + uint8_t flush_cache_ext_supported : 1; + uint8_t reserved2 : 2; + uint8_t smart_error_log_supported : 1; + uint8_t smart_self_test_supported : 1; + uint8_t media_serial_number_supported : 1; + uint8_t media_card_pass_through_supported : 1; + uint8_t streaming_feature_supported : 1; + uint8_t general_purpose_logging_supported : 1; + uint8_t write_fua_ext_supported : 1; + uint8_t write_queued_fua_ext_supported : 1; + uint8_t name_64bit_supported : 1; + uint8_t urg_gor_read_stream_dma_supported : 1; + uint8_t urg_for_write_stream_dma_supported : 1; + uint8_t reserved3 : 2; + uint8_t idle_immediate_supported : 1; + uint8_t reserved4 : 2; + uint8_t smart_enabled : 1; + uint8_t security_mode_enabled : 1; + uint8_t removablemedia_enabled : 1; + uint8_t power_management_enabled : 1; + uint8_t reserved5 : 1; + uint8_t write_cache_enabled : 1; + uint8_t look_ahead_enabled : 1; + uint8_t release_interrupt_enabled : 1; + uint8_t service_interrupt_enabled : 1; + uint8_t device_reset_enabled : 1; + uint8_t host_protected_area_enabled : 1; + uint8_t obsolete3 : 1; + uint8_t write_buffer_command_enabled : 1; + uint8_t read_buffer_command_enabled : 1; + uint8_t nop_command_enabled : 1; + uint8_t obsolete4 : 1; + uint8_t download_microcode_enabled : 1; + uint8_t rw_dma_queued_enabled : 1; + uint8_t cfa_enabled : 1; + uint8_t advanced_power_management_enabled : 1; + uint8_t removable_media_status_notification_enabled : 1; + uint8_t powerup_in_standby_enabled : 1; + uint8_t set_features_required_to_spinup_after_powerup_enabled : 1; + uint8_t obsolete5 : 1; + uint8_t set_max_security_enabled : 1; + uint8_t auto_acoustic_management_enabled : 1; + uint8_t addressing_48bit_enabled : 1; + uint8_t device_config_overlay_enabled : 1; + uint8_t mandatory_flush_cache_enabled : 1; + uint8_t flush_cache_ext_enabled : 1; + uint8_t reserved6 : 2; + uint8_t smart_error_log_enabled : 1; + uint8_t smart_self_test_enabled : 1; + uint8_t media_serial_number_enabled : 1; + uint8_t media_card_pass_through_enabled : 1; + uint8_t streaming_feature_enabled : 1; + uint8_t general_purpose_logging_enabled : 1; + uint8_t write_fua_ext_enabled : 1; + uint8_t write_queued_fua_ext_enabled : 1; + uint8_t reserved7 : 2; + uint8_t idle_immediate_enabled : 1; + uint8_t reserved8 : 2; + } command_set_feature_support; + uint8_t udma_mode_support; + uint8_t udma_mode_select; + uint16_t time_required_for_security_erase; + uint16_t time_required_for_enhanced_security_erase; + uint16_t current_advanced_power_management_value; + uint16_t master_password_revision_code; + uint16_t hardware_reset_result; + uint8_t current_AAM_value; + uint8_t recommended_AAM_value; + uint16_t stream_min_request_size; + uint16_t streaming_transfer_time_DMA; + uint16_t streaming_access_latency_DMA_PIO; + uint16_t streaming_performance_granularity[2]; + uint16_t max_lba48_addressable_sectors[4]; + uint16_t streaming_transfer_time_PIO; + uint16_t reserved11; + uint16_t physical_logical_sector_size : 4; + uint16_t reserved12 : 8; + uint16_t device_logical_sector_is_longer_than_256 : 1; + uint16_t device_has_multiple_logical_sectors : 1; + uint16_t reserved13 : 2; + uint16_t inter_seek_delay; + uint32_t unique_id1; + uint16_t unique_id2 : 4; + uint32_t ieee_oui : 24; + uint16_t naa : 4; + uint16_t world_wide_name[4]; + uint16_t reserved14; + uint16_t words_per_logical_sector[2]; + uint16_t reserved15[8]; + uint16_t removable_media_status; + uint16_t security_status; + uint16_t vendor_specific[31]; + uint16_t CFA_power_mode; + uint16_t reserved16[15]; + uint8_t current_media_serial_number[60]; + uint16_t reserved17[49]; + uint16_t integrity_word; +} __attribute__((packed)) AtaIdentifyInfo; + +extern struct Driver ata_driver; + +#endif \ No newline at end of file diff --git a/src/arch/x86/drivers/disk/ata/include/ide.h b/src/arch/x86/drivers/disk/ata/include/ide.h new file mode 100644 index 0000000..1576099 --- /dev/null +++ b/src/arch/x86/drivers/disk/ata/include/ide.h @@ -0,0 +1,47 @@ +#ifndef _ATA_IDE_H +#define _ATA_IDE_H + +#include "ata.h" +#include "ata_driver.h" +#include "driver/storage_io_queue.h" +#include "ide_controller.h" +#include "kernel/device.h" +#include "stdint.h" + +#define IDE_IRQ0 14 +#define IDE_IRQ1 15 + +typedef struct IdeOps { + void (*set_sector)( + struct Device *device, uint32_t lba0, uint32_t lba1, uint32_t count); +} IdeOps; + +typedef struct IdeDevice { + Device *device; + IdeChannel *channel; + AtaIdentifyInfo *info; + AtaDeviceType type; + uint8_t device_num; + enum { + TRANSFER_MODE_PIO, + TRANSFER_MODE_DMA, + } mode; + + StorageRequest *current_request; + + AtaCmdIndex cmdset[ATA_CMDSET_MAX]; +} IdeDevice; + +typedef struct PhysicalRegionDescriptorTable { + uint32_t base_addr; + uint16_t count; + uint16_t sign; +} __attribute__((packed)) PhysicalRegionDescriptorTable; + +extern struct DeviceDriver ide_device_driver; + +void ide_channel0_handler(struct Device *device); +void ide_channel1_handler(struct Device *device); +void ide_device_probe(IdeChannel *channel); + +#endif \ No newline at end of file diff --git a/src/arch/x86/drivers/disk/ata/include/ide_controller.h b/src/arch/x86/drivers/disk/ata/include/ide_controller.h new file mode 100644 index 0000000..94c028a --- /dev/null +++ b/src/arch/x86/drivers/disk/ata/include/ide_controller.h @@ -0,0 +1,65 @@ +#ifndef _ATA_IDE_CONTROLL_H +#define _ATA_IDE_CONTROLL_H + +#include "bits.h" +#include "driver/timer_dm.h" +#include "drivers/pci.h" +#include "kernel/driver_interface.h" +#include "stdint.h" + +#define IDE_CONTROLLER_CLASSCODE 0x01 +#define IDE_CONTROLLER_SUBCLASS 0x01 + +#define IDE_REG_BM_COMMAND 0x00 +#define IDE_REG_BM_STATUS 0x02 +#define IDE_REG_BM_PRDT 0x04 + +#define IDE_BMCMD_START_STOP_BM BIT(0) +#define IDE_BMCMD_READ_WRITE BIT(3) + +#define IDE_BMSTATUS_ACTIVE BIT(0) +#define IDE_BMSTATUS_ERROR BIT(1) +#define IDE_BMSTATUS_INT BIT(2) +#define IDE_BMSTATUS_DMA0_CAP BIT(5) +#define IDE_BMSTATUS_DMA1_CAP BIT(6) + +extern struct BusDriverOps ide_bus_driver_ops; +extern struct BusDriver ide_bus_driver; + +extern struct PciDriver ide_pci_driver; + +typedef struct IdeChannelInfo { + enum { + IDE_COMPATITY_MODE, + IDE_NATIVE_MODE, + } mode; + DeviceIrq *irq; + uint16_t io_base; + uint16_t control_base; + uint16_t bmide; + uint8_t channel_num; + uint8_t device_count; + + Timer timer; + + int selected_device; + struct IdeDevice *ide_devices[2]; + struct PhysicalRegionDescriptorTable *prdt; +} IdeChannel; + +typedef struct IdeControllerInfo { + uint8_t dma_support; + + PciDevice *pci_device; + uint32_t bus_master_base; +} IdeControllerInfo; + +extern struct DeviceDriver ide_controller_device_driver; +extern struct BusControllerDeviceOps ide_bus_controller_device_ops; + +int ide_wait(IdeChannel *channel); +void ide_print_error(IdeChannel *channel, char *source); +void ide_reset_drive(IdeChannel *channel); +void ide_select_device(IdeChannel *channel, int device_num); + +#endif \ No newline at end of file diff --git a/src/include/driver/storage_io_queue.h b/src/include/driver/storage_io_queue.h index 52030ae..ed420a8 100644 --- a/src/include/driver/storage_io_queue.h +++ b/src/include/driver/storage_io_queue.h @@ -12,6 +12,7 @@ typedef struct StorageRequest { list_t list; bool rw; uint8_t *buf; + uint8_t *dma_buf; uint32_t offset; uint64_t position; uint32_t count; From 0dce10f79c8f85e177bee446c7304d8833813a60 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 5 Jan 2025 23:05:20 +0800 Subject: [PATCH 011/158] =?UTF-8?q?=E6=94=B9=E8=BF=9BIDE=E4=B8=AD=E6=96=AD?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/disk/ata/ide.c | 29 ++++++++++++------- .../x86/drivers/disk/ata/ide_controller.c | 24 +++++++-------- .../drivers/disk/ata/include/ide_controller.h | 2 +- src/driver/storage_io_queue.c | 1 - 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index dbde929..950c0eb 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -57,27 +57,25 @@ Transfer ide_transfer = { .type_out = TRANSFER_TYPE_BLOCK, }; -void ide_channel0_handler(Device *device) { - IdeChannel *ide_channel = device->child_private_data[0]; - - int status = io_in_byte(ide_channel->io_base + ATA_REG_ALTSTATUS); +void ide_handle_interrupt(IdeChannel *channel) { + int status = io_in_byte(channel->io_base + ATA_REG_ALTSTATUS); if (BIN_IS_EN(status, ATA_STATUS_ERR)) { print_error("IDE", "IDE device error!"); + ide_print_error(channel); } - IdeDevice *ide_device = - ide_channel->ide_devices[ide_channel->selected_device]; - StorageRequest *request = ide_device->current_request; + IdeDevice *ide_device = channel->ide_devices[channel->selected_device]; + StorageRequest *request = ide_device->current_request; ide_device->current_request = NULL; if (ide_device->mode == TRANSFER_MODE_DMA) { - uint8_t data = io_in_byte(ide_channel->bmide + IDE_REG_BM_STATUS); + uint8_t data = io_in_byte(channel->bmide + IDE_REG_BM_STATUS); io_out_byte( - ide_channel->bmide + IDE_REG_BM_STATUS, + channel->bmide + IDE_REG_BM_STATUS, BIN_EN(data, IDE_BMSTATUS_INT | IDE_BMSTATUS_ERROR)); - data = io_in_byte(ide_channel->bmide + IDE_REG_BM_COMMAND); + data = io_in_byte(channel->bmide + IDE_REG_BM_COMMAND); io_out_byte( - ide_channel->bmide + IDE_REG_BM_COMMAND, + channel->bmide + IDE_REG_BM_COMMAND, BIN_DIS(data, IDE_BMCMD_START_STOP_BM)); if (request->rw == 0 && request->dma_buf != request->buf) { @@ -87,7 +85,16 @@ void ide_channel0_handler(Device *device) { } storage_finish_request(request); } + +void ide_channel0_handler(Device *device) { + IdeChannel *ide_channel = device->child_private_data[0]; + + ide_handle_interrupt(ide_channel); +} void ide_channel1_handler(Device *device) { + IdeChannel *ide_channel = device->child_private_data[1]; + + ide_handle_interrupt(ide_channel); } void ide_sync(IdeChannel *channel) { diff --git a/src/arch/x86/drivers/disk/ata/ide_controller.c b/src/arch/x86/drivers/disk/ata/ide_controller.c index c715043..365386c 100644 --- a/src/arch/x86/drivers/disk/ata/ide_controller.c +++ b/src/arch/x86/drivers/disk/ata/ide_controller.c @@ -142,34 +142,32 @@ DriverResult ide_controller_init(Device *device) { return DRIVER_RESULT_OK; } -void ide_print_error(IdeChannel *channel, char *source) { +void ide_print_error(IdeChannel *channel) { int status = io_in_byte(channel->io_base + ATA_REG_STATUS); if (status & ATA_STATUS_DF) { - print_error(source, "Device Fault!\n"); + print_error("IDE", "Device Fault!\n"); } else if (status & ATA_STATUS_ERR) { int err = io_in_byte(channel->io_base + ATA_REG_ERROR); if (err & ATA_ERROR_AMNF) { - print_error(source, "No Address Mark Found\n"); + print_error("IDE", "No Address Mark Found\n"); } if (err & ATA_ERROR_TK0NF) { - print_error(source, "No Media or Media Mark Found\n"); + print_error("IDE", "No Media or Media Mark Found\n"); } - if (err & ATA_ERROR_ABRT) { print_error(source, "Command Aborted\n"); } + if (err & ATA_ERROR_ABRT) { print_error("IDE", "Command Aborted\n"); } if (err & ATA_ERROR_MCR) { - print_error(source, "No Media or Media Error\n"); - } - if (err & ATA_ERROR_IDNF) { - print_error(source, "ID mark not Found\n"); + print_error("IDE", "No Media or Media Error\n"); } + if (err & ATA_ERROR_IDNF) { print_error("IDE", "ID mark not Found\n"); } if (err & ATA_ERROR_MC) { - print_error(source, "No Media or Media Error\n"); + print_error("IDE", "No Media or Media Error\n"); } if (err & ATA_ERROR_UNC) { - print_error(source, "Uncorrectable Data Error\n"); + print_error("IDE", "Uncorrectable Data Error\n"); } - if (err & ATA_ERROR_BBK) { print_error(source, "Bad Sectors\n"); } + if (err & ATA_ERROR_BBK) { print_error("IDE", "Bad Sectors\n"); } } else if (status & ATA_STATUS_DRQ) { - print_error(source, "Reads Nothing\n"); + print_error("IDE", "Reads Nothing\n"); } } diff --git a/src/arch/x86/drivers/disk/ata/include/ide_controller.h b/src/arch/x86/drivers/disk/ata/include/ide_controller.h index 94c028a..86e594e 100644 --- a/src/arch/x86/drivers/disk/ata/include/ide_controller.h +++ b/src/arch/x86/drivers/disk/ata/include/ide_controller.h @@ -58,7 +58,7 @@ extern struct DeviceDriver ide_controller_device_driver; extern struct BusControllerDeviceOps ide_bus_controller_device_ops; int ide_wait(IdeChannel *channel); -void ide_print_error(IdeChannel *channel, char *source); +void ide_print_error(IdeChannel *channel); void ide_reset_drive(IdeChannel *channel); void ide_select_device(IdeChannel *channel, int device_num); diff --git a/src/driver/storage_io_queue.c b/src/driver/storage_io_queue.c index c99e2cc..fa8d29d 100644 --- a/src/driver/storage_io_queue.c +++ b/src/driver/storage_io_queue.c @@ -1,7 +1,6 @@ #include #include #include -#include void storage_add_request( StorageDevice *storage_device, StorageRequest *request) { From 2cc46a6785ca0d4f90f9173ca48f3462c5a61156 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 11 Jan 2025 20:27:09 +0800 Subject: [PATCH 012/158] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AD=98=E5=82=A8?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=88=86=E7=B1=BB=EF=BC=9B=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E8=AE=BE=E5=A4=87=E8=AF=B7=E6=B1=82=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=90=88=E5=B9=B6=E5=8A=9F=E8=83=BD=EF=BC=9B=E5=88=A0?= =?UTF-8?q?=E9=99=A4apic=E9=A9=B1=E5=8A=A8=E6=97=A7=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/apic.c | 86 ----------------------------- src/arch/x86/drivers/disk/ata/ide.c | 2 +- src/driver/storage_io_queue.c | 13 +++++ src/include/driver/storage_dm.h | 3 +- 4 files changed, 15 insertions(+), 89 deletions(-) diff --git a/src/arch/x86/drivers/apic.c b/src/arch/x86/drivers/apic.c index e824045..64527b3 100644 --- a/src/arch/x86/drivers/apic.c +++ b/src/arch/x86/drivers/apic.c @@ -408,89 +408,3 @@ TimerResult apic_timer_set_frequency( void apic_timer_irq_handler(Device *device) { timer_irq_handler(device); } - -// --------old--------- -// TODO: 删除旧代码 - -void init_apic(void) { - // if (check_apic_support()) { - // init_8259a(); - // return; - // } - // mask_8259a(); - use_apic = 1; - // cpu_RDMSR(IA32_APIC_BASE, &l, &h); - // printk("APIC Base:%#08x%08x\n", h, l); - // cpu_WRMSR(IA32_APIC_BASE, l | (1<<10) | (1<<11), h); - // //APIC全局使能,启用APIC - // apic_info.lapic_mmio = remap(0xfee00000, 0x3ff); - // apic_info.ioapic = remap(0xfec00000, 0xfff00); - io_cli(); - lapic_write(APIC_SIVR, 1 << 8); - // 设定Loacl APIC定时器 - lapic_write(APIC_TIMER_DCR, 0x0b); // divide by 16 - lapic_write( - APIC_LVT_TIMER, (1 << 17) | (0x20 + LAPIC_TIMER_IRQ)); // 周期性计时 - int a, b, c, d; - get_cpuid( - 0x15, 0x00, (unsigned int *)&a, (unsigned int *)&b, (unsigned int *)&c, - (unsigned int *)&d); - - lapic_write(APIC_TIMER_ICT, 100000); - - // 获取APICID - /* - * xAPIC Mode(Address:FEE0 0020H) - * P6 family and Pentium processors: 24~27bit - * Pentium 4 processors, Xeon processors, and later processors: 24~31bit - * - * x2APIC Mode(MSR Address: 802H):0~31bit - */ - int apicid = lapic_read(APIC_ID); - printk("APICID:%#x \n", apicid); - // 获取APIC版本 - /* - * 16~23位 Max LVT Entry - * 0~7位 Version - */ - printk("APIC Ver:%04x \n", lapic_read(APIC_Ver)); - // 屏蔽LVT - // lapic_write(APIC_LVT_CMCI, 1<<16); - // lapic_write(APIC_LVT_THMR, 1<<16); - if (((apic_info.lapic_mmio[APIC_Ver / 4] >> 16) & 0xff) >= 4) { - lapic_write(APIC_LVT_PMCR, 1 << 16); - } - lapic_write(APIC_LVT_LINT0, 1 << 16); - lapic_write(APIC_LVT_LINT1, 1 << 16); - lapic_write(APIC_LVT_ERROR, 0xfe); - lapic_write(APIC_ESR, 0); - lapic_write(APIC_ESR, 0); - lapic_write(APIC_EOI, 0); - - lapic_write(APIC_ICR_HIGH, 0); - lapic_write(APIC_ICR_LOW, (1 << 19) | (1 << 15) | (1 << 10) | (1 << 8)); - while (apic_info.lapic_mmio[APIC_ICR_LOW / 4] & (1 << 12)) - ; - - lapic_write(APIC_TPR, 0); - - int i, count = (io_apic_read(IOAPIC_VER) >> 16) & 0xff; - for (i = 0; i <= count; i++) { - io_apic_write(IOAPIC_TBL + i * 2, APIC_INT_DISABLE | (0x20 + i)); - io_apic_write(IOAPIC_TBL + i * 2 + 1, 0); - } - - put_irq_handler(LAPIC_TIMER_IRQ, (irq_handler_t)apic_timer_handler); - // apic_enable_irq(LAPIC_TIMER_IRQ); -} - -void apic_timer_handler(void) { - struct task_s *cur_thread = get_current_thread(); - cur_thread->elapsed_ticks++; - - if (cur_thread->ticks == 0) { - schedule(); - } else { - cur_thread->ticks--; - } -} diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index 950c0eb..b5918e6 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -171,7 +171,7 @@ void ide_device_probe(IdeChannel *channel) { string_new(&device->name, "IDE HardDisk", 13); StorageDevice *storage_device = kmalloc(sizeof(StorageDevice)); - storage_device->type = STORAGE_DEVICE_TYPE_ATA; + storage_device->type = STORAGE_DEVICE_TYPE_HARDDISK; storage_device->ops = &ide_storage_device_ops; register_storage_device(&ide_device_driver, device, storage_device); diff --git a/src/driver/storage_io_queue.c b/src/driver/storage_io_queue.c index fa8d29d..0e70613 100644 --- a/src/driver/storage_io_queue.c +++ b/src/driver/storage_io_queue.c @@ -2,11 +2,24 @@ #include #include +bool storage_try_merge_request( + StorageRequest *new_request, StorageRequest *request) { + if (new_request->rw == request->rw) { + if (new_request->position + new_request->count >= request->position && + new_request->position <= request->position + request->count) { + new_request->count += request->count; + return true; + } + } + return false; +} + void storage_add_request( StorageDevice *storage_device, StorageRequest *request) { StorageRequest *req; request->storage_device = storage_device; list_for_each_owner (req, &storage_device->io_queue_lh, list) { + if (storage_try_merge_request(request, req)) { return; } if (req->position > request->position) { list_add_before(&request->list, &req->list); return; diff --git a/src/include/driver/storage_dm.h b/src/include/driver/storage_dm.h index b491e6d..1d18727 100644 --- a/src/include/driver/storage_dm.h +++ b/src/include/driver/storage_dm.h @@ -8,8 +8,7 @@ typedef enum StorageDeviceType { STORAGE_DEVICE_TYPE_UNKNOWN, - STORAGE_DEVICE_TYPE_ATA, - STORAGE_DEVICE_TYPE_SCSI, + STORAGE_DEVICE_TYPE_HARDDISK, } StorageDeviceType; struct StorageDevice; From 37bb64f127b9aad88d3bbc2ce0b41da1ac910a64 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 11 Jan 2025 20:27:36 +0800 Subject: [PATCH 013/158] update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9730bfb..f98f72a 100644 --- a/.gitignore +++ b/.gitignore @@ -54,7 +54,7 @@ dkms.conf compile_commands.json # Others -disk/ +/disk/ tools/bin/ tools/imagetool/target/ core From 31c74f2c84088f6ec569a6659a5a6011dd9847e3 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 12 Jan 2025 23:31:24 +0800 Subject: [PATCH 014/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=90=88=E5=B9=B6?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E8=AE=BE=E5=A4=87=E8=AF=BB=E5=86=99=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/acpi.c | 10 +-- src/arch/x86/drivers/disk/ata/ide.c | 27 ++++---- src/driver/storage_dm.c | 29 +++++---- src/driver/storage_io_queue.c | 90 ++++++++++++++++++++++++++- src/include/driver/storage_dm.h | 3 + src/include/driver/storage_io_queue.h | 10 ++- src/include/driver/transfer.h | 5 +- 7 files changed, 136 insertions(+), 38 deletions(-) diff --git a/src/arch/x86/drivers/acpi.c b/src/arch/x86/drivers/acpi.c index de3769e..f47d6db 100644 --- a/src/arch/x86/drivers/acpi.c +++ b/src/arch/x86/drivers/acpi.c @@ -5,6 +5,7 @@ * @version 0.1 * @date 2021-06 */ +#include #include #include #include @@ -80,6 +81,9 @@ uint32_t acpi_find_table(device_extension_t *devext, char *Signature) { static status_t acpi_enter(driver_t *drv_obj) { device_t *devobj; device_extension_t *devext; + Timer timer; + + timer_init(&timer); device_create( drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_MANAGER, &devobj); @@ -109,14 +113,12 @@ static status_t acpi_enter(driver_t *drv_obj) { int i; for (i = 0; i < 300; i++) { if (io_in16(devext->FADT->PM1aControlBlock) & 1) break; - // TODO: Delay - // delay(1); + delay_ms(&timer, 1); } if (devext->FADT->PM1bControlBlock) { for (; i < 300; i++) { if (io_in16(devext->FADT->PM1bControlBlock) & 1) break; - // TODO: Delay - // delay(1); + delay_ms(&timer, 1); } } } diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index b5918e6..a4545fa 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -78,10 +78,8 @@ void ide_handle_interrupt(IdeChannel *channel) { channel->bmide + IDE_REG_BM_COMMAND, BIN_DIS(data, IDE_BMCMD_START_STOP_BM)); - if (request->rw == 0 && request->dma_buf != request->buf) { - memcpy(request->buf, request->dma_buf, request->count * 512); - } - kfree(request->dma_buf); + if (request->rw == 0) { storage_solve_read_request(request); } + kfree(request->real_buf); } storage_finish_request(request); } @@ -173,6 +171,7 @@ void ide_device_probe(IdeChannel *channel) { StorageDevice *storage_device = kmalloc(sizeof(StorageDevice)); storage_device->type = STORAGE_DEVICE_TYPE_HARDDISK; storage_device->ops = &ide_storage_device_ops; + storage_device->block_size = 512; register_storage_device(&ide_device_driver, device, storage_device); @@ -275,13 +274,13 @@ void ide_device_set_dma(IdeDevice *device, StorageRequest *request) { PhysicalRegionDescriptorTable *prdt = channel->prdt; uint8_t *buffer; - buffer = (uint32_t)request->buf & 3 - ? kmalloc(request->count * 512) // 未对齐则另外分配 - : request->buf; // 传入的缓冲区已对齐则直接使用 - request->dma_buf = buffer; - prdt->base_addr = vir2phy((uint32_t)buffer); - prdt->count = request->count * 512; - prdt->sign = BIT(15); + buffer = (uint32_t)request->buf & 3 + ? kmalloc(request->count * 512) // 未对齐则另外分配 + : request->buf; // 传入的缓冲区已对齐则直接使用 + request->real_buf = buffer; + prdt->base_addr = vir2phy((uint32_t)buffer); + prdt->count = request->count * 512; + prdt->sign = BIT(15); io_out_dword(channel->bmide + IDE_REG_BM_PRDT, vir2phy((uint32_t)prdt)); @@ -318,6 +317,8 @@ DriverResult ide_device_read_sectors( if (ide_device->mode == TRANSFER_MODE_DMA) { ide_device_set_dma(ide_device, request); } + request->real_buf = + (request->real_buf == NULL) ? request->buf : request->real_buf; ide_select_device(channel, ide_device->device_num); ide_wait(channel); @@ -370,9 +371,7 @@ DriverResult ide_device_write_sectors( if (ide_device->mode == TRANSFER_MODE_DMA) { ide_device_set_dma(ide_device, request); - if (request->dma_buf != request->buf) { - memcpy(request->dma_buf, request->buf, request->count * 512); - } + storage_solve_write_request(request); } ide_select_device(channel, ide_device->device_num); diff --git a/src/driver/storage_dm.c b/src/driver/storage_dm.c index 7329ff3..72eb372 100644 --- a/src/driver/storage_dm.c +++ b/src/driver/storage_dm.c @@ -12,14 +12,15 @@ #include #include #include +#include #include extern void storage_periodic_task(void *arg); DriverResult storage_device_block_read( - Device *device, uint8_t *buf, offset_t offset, size_t size); + Device *device, uint8_t *buf, uint32_t position, size_t count); DriverResult storage_device_block_write( - Device *device, uint8_t *buf, offset_t offset, size_t size); + Device *device, uint8_t *buf, uint32_t position, size_t count); DeviceManagerOps storage_dm_ops = { .dm_load_hook = NULL, @@ -74,31 +75,35 @@ DriverResult unregister_storage_device( } DriverResult storage_device_block_read( - Device *device, uint8_t *buf, offset_t offset, size_t size) { + Device *device, uint8_t *buf, uint32_t position, size_t count) { + StorageDevice *storage_device = device->device_manager_extension; StorageRequest *request = kmalloc(sizeof(StorageRequest)); request->rw = false; request->buf = buf; - request->offset = offset % 512; - request->position = offset / 512; - request->count = DIV_ROUND_UP(offset + size, 512) - request->position; + request->position = position; + request->count = + DIV_ROUND_UP(position + count, storage_device->block_size) - + request->position; - storage_add_request(device->device_manager_extension, request); + storage_add_request(storage_device, request); return DRIVER_RESULT_OK; } DriverResult storage_device_block_write( - Device *device, uint8_t *buf, offset_t offset, size_t size) { + Device *device, uint8_t *buf, uint32_t position, size_t count) { + StorageDevice *storage_device = device->device_manager_extension; StorageRequest *request = kmalloc(sizeof(StorageRequest)); request->rw = true; request->buf = buf; - request->offset = offset % 512; - request->position = offset / 512; - request->count = DIV_ROUND_UP(offset + size, 512) - request->position; + request->position = position; + request->count = + DIV_ROUND_UP(position + count, storage_device->block_size) - + request->position; - storage_add_request(device->device_manager_extension, request); + storage_add_request(storage_device, request); return DRIVER_RESULT_OK; } diff --git a/src/driver/storage_io_queue.c b/src/driver/storage_io_queue.c index 0e70613..e87e5f2 100644 --- a/src/driver/storage_io_queue.c +++ b/src/driver/storage_io_queue.c @@ -1,13 +1,49 @@ +#include "types.h" #include #include #include +#include +#include +#include +#include bool storage_try_merge_request( StorageRequest *new_request, StorageRequest *request) { if (new_request->rw == request->rw) { if (new_request->position + new_request->count >= request->position && new_request->position <= request->position + request->count) { - new_request->count += request->count; + if (request->next_merged_request != NULL) { + // 如果是被合并过的请求,就继续合并 + StorageRequest *last_request = request->next_merged_request; + while (last_request) { + last_request = last_request->next_merged_request; + } + + request->position = + MIN(request->position, new_request->position); + request->count = MAX(new_request->position + new_request->count, + request->position + request->count) - + request->position; + + last_request->next_merged_request = new_request; + } else { + // 如果未合并过,就新申请一个请求替换掉 + StorageRequest *req = kmalloc(sizeof(StorageRequest)); + req->buf = NULL; // 缓冲区先不申请,等到真正提交时再申请 + req->position = MIN(new_request->position, request->position); + req->count = MAX(new_request->position + new_request->count, + request->position + request->count) - + req->position; + req->rw = new_request->rw; + req->is_finished = 0; + req->storage_device = new_request->storage_device; + + req->next_merged_request = request; + request->next_merged_request = new_request; + + list_add_before(&req->list, &request->list); + list_del(&request->list); + } return true; } } @@ -18,6 +54,7 @@ void storage_add_request( StorageDevice *storage_device, StorageRequest *request) { StorageRequest *req; request->storage_device = storage_device; + request->is_finished = 0; list_for_each_owner (req, &storage_device->io_queue_lh, list) { if (storage_try_merge_request(request, req)) { return; } if (req->position > request->position) { @@ -41,14 +78,63 @@ void storage_periodic_task(void *arg) { void storage_finish_request(StorageRequest *storage_request) { storage_request->is_finished = true; + StorageRequest *req = storage_request->next_merged_request; + if (req) { + while (req) { + req->is_finished = true; + req = req->next_merged_request; + } + } } void storage_submit_request(StorageRequest *request) { StorageDevice *storage_device = request->storage_device; + if (request->buf == NULL && request->next_merged_request != NULL) { + request->buf = kmalloc(request->count * storage_device->block_size); + } if (request->rw) { storage_device->ops->submit_write_request(storage_device, request); } else { storage_device->ops->submit_read_request(storage_device, request); } list_del(&request->list); -} \ No newline at end of file +} + +void storage_solve_read_request(StorageRequest *request) { + StorageRequest *req = request->next_merged_request; + if (req) { + uint32_t start = request->position; + while (req) { + uint32_t offset = + (req->position - start) * request->storage_device->block_size; + memcpy( + req->buf, request->real_buf + offset, + req->count * req->storage_device->block_size); + req = req->next_merged_request; + } + } else if (request->buf != request->real_buf) { + memcpy( + request->buf, request->real_buf, + request->count * request->storage_device->block_size); + } +} + +void storage_solve_write_request(StorageRequest *request) { + StorageRequest *req = request->next_merged_request; + if (req) { + uint32_t start = request->position; + while (req) { + uint32_t offset = + (req->position - start) * request->storage_device->block_size; + // 写入需要分先后,由于合并请求时已经按顺序排列了,直接覆盖就好 + memcpy( + request->real_buf + offset, req->buf, + req->count * req->storage_device->block_size); + req = req->next_merged_request; + } + } else if (request->buf != request->real_buf) { + memcpy( + request->real_buf, request->buf, + request->count * request->storage_device->block_size); + } +} diff --git a/src/include/driver/storage_dm.h b/src/include/driver/storage_dm.h index 1d18727..6b65929 100644 --- a/src/include/driver/storage_dm.h +++ b/src/include/driver/storage_dm.h @@ -5,6 +5,7 @@ #include "kernel/device_manager.h" #include "kernel/driver.h" #include "kernel/periodic_task.h" +#include typedef enum StorageDeviceType { STORAGE_DEVICE_TYPE_UNKNOWN, @@ -26,6 +27,8 @@ typedef struct StorageDevice { StorageDeviceType type; StorageDeviceOps *ops; + uint32_t block_size; + PeriodicTask periodic_task; list_t io_queue_lh; } StorageDevice; diff --git a/src/include/driver/storage_io_queue.h b/src/include/driver/storage_io_queue.h index ed420a8..b3870e1 100644 --- a/src/include/driver/storage_io_queue.h +++ b/src/include/driver/storage_io_queue.h @@ -11,12 +11,13 @@ typedef struct StorageRequest { list_t list; bool rw; - uint8_t *buf; - uint8_t *dma_buf; - uint32_t offset; + uint8_t *buf; // 调用方传入的缓冲区 + uint8_t *real_buf; // 实际读写时使用的缓冲区 uint64_t position; uint32_t count; bool is_finished; + + struct StorageRequest *next_merged_request; } StorageRequest; void storage_add_request( @@ -24,4 +25,7 @@ void storage_add_request( void storage_submit_request(StorageRequest *request); void storage_finish_request(StorageRequest *storage_request); +void storage_solve_read_request(StorageRequest *request); +void storage_solve_write_request(StorageRequest *request); + #endif \ No newline at end of file diff --git a/src/include/driver/transfer.h b/src/include/driver/transfer.h index 697dcd3..9059299 100644 --- a/src/include/driver/transfer.h +++ b/src/include/driver/transfer.h @@ -3,13 +3,12 @@ #include "kernel/driver.h" #include "stdint.h" -#include "types.h" struct Device; typedef DriverResult (*BlockTransferIn)( - struct Device *device, uint8_t *buf, offset_t offset, size_t size); + struct Device *device, uint8_t *buf, uint32_t position, size_t count); typedef DriverResult (*BlockTransferOut)( - struct Device *device, uint8_t *buf, offset_t offset, size_t size); + struct Device *device, uint8_t *buf, uint32_t position, size_t count); typedef DriverResult (*StreamTransferIn)( struct Device *device, uint8_t *buf, size_t size); From dc1a773a8316ed441de70b0f252f98951c1f3a50 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 13 Jan 2025 22:47:58 +0800 Subject: [PATCH 015/158] =?UTF-8?q?=E4=BC=98=E5=8C=96IDE=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E6=B5=81=E7=A8=8B=EF=BC=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E4=BB=8E=E6=A8=A1=E6=9D=BF=E5=88=86=E9=85=8D=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/disk/ata/ide.c | 29 ++++++++++++++++----------- src/include/kernel/driver_interface.h | 7 +++++++ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index a4545fa..158e615 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -57,6 +57,20 @@ Transfer ide_transfer = { .type_out = TRANSFER_TYPE_BLOCK, }; +Device ide_device_template = { + .name = STRING_INIT("IDE Harddisk"), + .transfer = &ide_transfer, + .state = DEVICE_STATE_UNREGISTERED, + .device_driver = &ide_device_driver, + .ops = &ide_device_ops, + .private_data_size = sizeof(IdeDevice), +}; +StorageDevice storage_device_template = { + .block_size = 512, + .type = STORAGE_DEVICE_TYPE_HARDDISK, + .ops = &ide_storage_device_ops, +}; + void ide_handle_interrupt(IdeChannel *channel) { int status = io_in_byte(channel->io_base + ATA_REG_ALTSTATUS); if (BIN_IS_EN(status, ATA_STATUS_ERR)) { @@ -160,18 +174,9 @@ void ide_device_probe(IdeChannel *channel) { sizeof(AtaIdentifyInfo) / 2); // 6.注册设备 - Device *device = kmalloc(sizeof(Device)); - device->ops = &ide_device_ops; - device->state = DEVICE_STATE_UNREGISTERED; - device->device_driver = &ide_device_driver; - device->private_data_size = sizeof(IdeDevice); - device->transfer = &ide_transfer; - string_new(&device->name, "IDE HardDisk", 13); - - StorageDevice *storage_device = kmalloc(sizeof(StorageDevice)); - storage_device->type = STORAGE_DEVICE_TYPE_HARDDISK; - storage_device->ops = &ide_storage_device_ops; - storage_device->block_size = 512; + Device *device = kmalloc_from_template(ide_device_template); + StorageDevice *storage_device = + kmalloc_from_template(storage_device_template); register_storage_device(&ide_device_driver, device, storage_device); diff --git a/src/include/kernel/driver_interface.h b/src/include/kernel/driver_interface.h index b7dca7b..8828ebe 100644 --- a/src/include/kernel/driver_interface.h +++ b/src/include/kernel/driver_interface.h @@ -68,4 +68,11 @@ DriverResult driver_remap_memory( Driver *in_driver, uint32_t in_physical_address, uint32_t in_size, uint32_t *out_virtual_address); +#define kmalloc_from_template(template) \ + ({ \ + void *data = kmalloc(sizeof(template)); \ + memcpy(data, &template, sizeof(template)); \ + data; \ + }) + #endif \ No newline at end of file From 6e0936ecd929983b2c5c8e2031b9ed7988f13bb6 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 26 Jan 2025 22:20:53 +0800 Subject: [PATCH 016/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AF=B9=E8=B1=A1?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=EF=BC=9B=E6=96=B0=E5=A2=9E=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E6=95=B0=E7=BB=84=E6=94=AF=E6=8C=81=EF=BC=9B=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=86=85=E7=BD=AE=E8=AE=BE=E5=A4=87=E9=A9=B1=E5=8A=A8=E7=BB=93?= =?UTF-8?q?=E6=9E=84=EF=BC=9B=E6=96=B0=E5=A2=9E=E7=94=9F=E6=88=90=E5=B8=A6?= =?UTF-8?q?=E6=95=B0=E5=AD=97=E5=90=8E=E7=BC=80=E5=AD=97=E7=AC=A6=E4=B8=B2?= =?UTF-8?q?=E5=87=BD=E6=95=B0=EF=BC=9B=E6=96=B0=E5=A2=9E=E5=90=91=E4=B8=8A?= =?UTF-8?q?=E5=8F=96=E6=95=B4=E5=88=B02=E7=9A=84=E6=AC=A1=E5=B9=82?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Makefile | 2 +- src/arch/x86/drivers/8259a.c | 7 +- src/arch/x86/drivers/apic.c | 18 ++- src/arch/x86/drivers/disk/ata/ata_driver.c | 2 +- .../x86/drivers/disk/ata/ide_controller.c | 19 ++-- src/arch/x86/drivers/pci.c | 9 +- src/arch/x86/drivers/pit.c | 8 +- src/arch/x86/drivers/vesa_display.c | 12 +- src/arch/x86/kernel/platform.c | 9 +- src/driver/bus_dm.c | 3 +- src/driver/interrupt_dm.c | 2 - src/driver/storage_dm.c | 6 +- src/driver/timer_dm.c | 3 +- src/driver/transfer.c | 1 + src/driver/video_dm.c | 8 +- src/include/driver/bus_dm.h | 2 + src/include/driver/video_dm.h | 1 + src/include/dyn_array.h | 50 +++++++++ src/include/kernel/device.h | 3 +- src/include/kernel/driver.h | 7 +- src/include/kernel/driver_interface.h | 2 +- src/include/kernel/platform.h | 5 +- src/include/math.h | 9 +- src/include/objects/object.h | 69 ++++++++++++ src/include/objects/types.h | 9 ++ src/include/stdint.h | 46 +++++--- src/include/string.h | 2 + src/kernel/Makefile | 1 - src/kernel/device.c | 20 +++- src/kernel/driver.c | 28 ++--- src/kernel/main.c | 49 +++++++- src/kernel/objects.c | 0 src/lib/Makefile | 3 +- src/lib/dyn_array.c | 65 +++++++++++ src/lib/math.c | 32 +++--- src/lib/string.c | 30 +++++ src/objects/Makefile | 2 + src/objects/objects.c | 105 ++++++++++++++++++ src/objects/types.c | 44 ++++++++ 39 files changed, 584 insertions(+), 109 deletions(-) create mode 100644 src/driver/transfer.c create mode 100644 src/include/dyn_array.h create mode 100644 src/include/objects/object.h create mode 100644 src/include/objects/types.h delete mode 100644 src/kernel/objects.c create mode 100644 src/lib/dyn_array.c create mode 100644 src/objects/Makefile create mode 100644 src/objects/objects.c create mode 100644 src/objects/types.c diff --git a/src/Makefile b/src/Makefile index cbbf9c3..e84c0fd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,7 +21,7 @@ LD := $(ENV_LD) export AS LD export ARCH_DIR -SRC := $(ARCH_DIR)/ fs/ driver/ kernel/ lib/ network/ +SRC := $(ARCH_DIR)/ fs/ driver/ kernel/ lib/ network/ objects/ NAME := kernel.elf diff --git a/src/arch/x86/drivers/8259a.c b/src/arch/x86/drivers/8259a.c index 1fc4e35..09bce3c 100644 --- a/src/arch/x86/drivers/8259a.c +++ b/src/arch/x86/drivers/8259a.c @@ -28,6 +28,8 @@ DriverResult pic_enable_irq(InterruptDevice *device, int irq); DriverResult pic_disable_irq(InterruptDevice *device, int irq); void pic_eoi(InterruptDevice *device, int irq); +extern Driver core_driver; + DeviceDriverOps pic_device_driver_ops = { .register_driver_hook = NULL, .unregister_driver_hook = NULL, @@ -46,7 +48,6 @@ InterruptDeviceOps pic_interrupt_ops = { .redirect_irq = pic_redirect_irq, }; -Driver pic_driver = {.name = STRING_INIT("PIC")}; DeviceDriver pic_device_driver = { .name = STRING_INIT("PIC Driver"), .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, @@ -70,9 +71,7 @@ InterruptDevice pic_interrupt_device = { }; void register_pic(void) { - register_driver(&pic_driver); - driver_init(&pic_driver); - register_device_driver(&pic_driver, &pic_device_driver); + register_device_driver(&core_driver, &pic_device_driver); register_interrupt_device( &pic_device_driver, &pic_device, &pic_interrupt_device); } diff --git a/src/arch/x86/drivers/apic.c b/src/arch/x86/drivers/apic.c index 64527b3..658ce9b 100644 --- a/src/arch/x86/drivers/apic.c +++ b/src/arch/x86/drivers/apic.c @@ -57,6 +57,8 @@ TimerResult apic_timer_set_frequency( TimerDevice *timer_device, uint32_t frequency); void apic_timer_irq_handler(Device *device); +extern Driver core_driver; + typedef struct ApicInfo { enum { APIC_TYPE_XAPIC, @@ -115,8 +117,6 @@ TimerOps apic_timer_ops = { .set_frequency = apic_timer_set_frequency, }; -Driver apic_driver = {.name = STRING_INIT("APIC")}; - DeviceDriver apic_device_driver = { .name = STRING_INIT("APIC"), .bus = &platform_bus, @@ -176,10 +176,8 @@ void io_apic_write(uint32_t reg, uint32_t data) { } void register_apic(void) { - register_driver(&apic_driver); - driver_init(&apic_driver); - register_device_driver(&apic_driver, &apic_device_driver); - register_device_driver(&apic_driver, &apic_timer_device_driver); + register_device_driver(&core_driver, &apic_device_driver); + register_device_driver(&core_driver, &apic_timer_device_driver); register_interrupt_device( &apic_device_driver, &apic_device, &apic_interrupt_device); register_timer_device( @@ -197,10 +195,10 @@ void x2apic_init(struct DeviceDriver *driver) { uint32_t tmp; DRV_RESULT_PRINT_CALL( - driver_remap_memory, &apic_driver, apic_info.apic_base, 0x3ff, &tmp); + driver_remap_memory, &core_driver, apic_info.apic_base, 0x3ff, &tmp); apic_info.lapic_mmio = (uint32_t *)tmp; DRV_RESULT_PRINT_CALL( - driver_remap_memory, &apic_driver, 0xfec00000, 0xfff00, &tmp); + driver_remap_memory, &core_driver, 0xfec00000, 0xfff00, &tmp); apic_info.ioapic = (struct ioapic *)tmp; read_msr(X2APIC_ID_MSR, &apic_info.apic_id, &apic_info.apic_id_high); @@ -213,10 +211,10 @@ void xapic_init(struct DeviceDriver *driver) { apic_info.apic_base = 0xfee00000; DRV_RESULT_PRINT_CALL( - driver_remap_memory, &apic_driver, apic_info.apic_base, 0x3ff, + driver_remap_memory, &core_driver, apic_info.apic_base, 0x3ff, (uint32_t *)&apic_info.lapic_mmio); DRV_RESULT_PRINT_CALL( - driver_remap_memory, &apic_driver, 0xfec00000, 0xfff00, + driver_remap_memory, &core_driver, 0xfec00000, 0xfff00, (uint32_t *)&apic_info.ioapic); apic_info.apic_id = lapic_read(APIC_ID) >> 24; diff --git a/src/arch/x86/drivers/disk/ata/ata_driver.c b/src/arch/x86/drivers/disk/ata/ata_driver.c index 0283b21..a70fa96 100644 --- a/src/arch/x86/drivers/disk/ata/ata_driver.c +++ b/src/arch/x86/drivers/disk/ata/ata_driver.c @@ -23,7 +23,7 @@ DriverDependency ata_dependencies[] = { }; Driver ata_driver = { - .name = STRING_INIT("ATA Driver"), + .short_name = STRING_INIT("AtaDriver"), .dependency_count = sizeof(ata_dependencies) / sizeof(DriverDependency), .dependencies = ata_dependencies, }; diff --git a/src/arch/x86/drivers/disk/ata/ide_controller.c b/src/arch/x86/drivers/disk/ata/ide_controller.c index 365386c..9f6f635 100644 --- a/src/arch/x86/drivers/disk/ata/ide_controller.c +++ b/src/arch/x86/drivers/disk/ata/ide_controller.c @@ -38,6 +38,14 @@ DeviceOps ide_controller_device_ops = { .destroy = NULL, .status = NULL, }; +Device ide_controller_device_templete = { + .name = STRING_INIT("IDE Controller"), + .state = DEVICE_STATE_UNREGISTERED, + .device_driver = &ide_controller_device_driver, + .ops = &ide_controller_device_ops, + .max_child_device = 2, + .private_data_size = sizeof(IdeControllerInfo), +}; PciDriverOps ide_pci_driver_ops = { .probe = ide_controller_probe, @@ -67,14 +75,9 @@ void ide_detect_channel_mode( } DriverResult ide_controller_probe(PciDevice *pci_device) { - Device *device = kmalloc(sizeof(Device)); - string_new(&device->name, "IDE Controller", 15); - device->state = DEVICE_STATE_UNREGISTERED; - device->ops = &ide_controller_device_ops; - device->device_driver = &ide_controller_device_driver; - device->private_data_size = sizeof(IdeControllerInfo); - device->max_child_device = 2; - register_device(&ide_controller_device_driver, pci_device->bus, device); + Device *device = kmalloc_from_template(ide_controller_device_templete); + register_device( + &ide_controller_device_driver, NULL, pci_device->bus, device); IdeControllerInfo *info = device->private_data; info->pci_device = pci_device; diff --git a/src/arch/x86/drivers/pci.c b/src/arch/x86/drivers/pci.c index 000f382..979e2e6 100644 --- a/src/arch/x86/drivers/pci.c +++ b/src/arch/x86/drivers/pci.c @@ -68,13 +68,13 @@ DriverDependency pci_dependencies[] = { }, }; Driver pci_driver = { - .name = STRING_INIT("pci driver"), + .short_name = STRING_INIT("PciDriver"), .dependency_count = sizeof(pci_dependencies) / sizeof(DriverDependency), .dependencies = pci_dependencies, .init = pci_driver_init, }; DeviceDriver pci_device_driver = { - .name = STRING_INIT("pci device driver"), + .name = STRING_INIT("PCI Device Driver"), .bus = NULL, .type = DEVICE_TYPE_BUS_CONTROLLER, .state = DRIVER_STATE_UNREGISTERED, @@ -82,13 +82,13 @@ DeviceDriver pci_device_driver = { .ops = &pci_driver_ops, }; Device pci_device = { - .name = STRING_INIT("pci controller"), + .name = STRING_INIT("PCI Controller"), .state = DEVICE_STATE_UNREGISTERED, .private_data_size = 0, .ops = &pci_device_ops, }; BusDriver pci_bus_driver = { - .name = STRING_INIT("pci"), + .name = STRING_INIT("PCI"), .driver_type = DRIVER_TYPE_BUS_DRIVER, .bus_type = BUS_TYPE_PCI, .state = DRIVER_STATE_UNREGISTERED, @@ -96,6 +96,7 @@ BusDriver pci_bus_driver = { .ops = &pci_bus_driver_ops, }; BusControllerDevice pci_bus_controller_device = { + .short_name = STRING_INIT("PCI"), .device = &pci_device, .bus_driver = &pci_bus_driver, .bus_controller_ops = &pci_controller_ops, diff --git a/src/arch/x86/drivers/pit.c b/src/arch/x86/drivers/pit.c index d064ac7..80396f4 100644 --- a/src/arch/x86/drivers/pit.c +++ b/src/arch/x86/drivers/pit.c @@ -32,6 +32,8 @@ DriverResult pit_start(Device *device); DriverResult pit_stop(Device *device); void pit_irq_handler(Device *device); +extern Driver core_driver; + DeviceDriverOps pit_driver_ops = { .register_driver_hook = NULL, .unregister_driver_hook = NULL, @@ -52,7 +54,6 @@ DeviceIrq pit_irq = { .handler = pit_irq_handler, }; -Driver pit_driver; DeviceDriver pit_device_driver = { .name = STRING_INIT("PIT"), .bus = &platform_bus, @@ -62,6 +63,7 @@ DeviceDriver pit_device_driver = { .ops = &pit_driver_ops, }; Device pit_device = { + .name = STRING_INIT("PIT"), .device_driver = &pit_device_driver, .ops = &pit_device_ops, .irq = &pit_irq, @@ -78,9 +80,7 @@ TimerDevice pit_timer_device = { }; void register_pit() { - register_driver(&pit_driver); - driver_init(&pit_driver); - register_device_driver(&pit_driver, &pit_device_driver); + register_device_driver(&core_driver, &pit_device_driver); register_timer_device(&pit_device_driver, &pit_device, &pit_timer_device); } diff --git a/src/arch/x86/drivers/vesa_display.c b/src/arch/x86/drivers/vesa_display.c index 1045009..f0de739 100644 --- a/src/arch/x86/drivers/vesa_display.c +++ b/src/arch/x86/drivers/vesa_display.c @@ -9,6 +9,7 @@ #include #include +extern Driver core_driver; struct VesaDisplayInfo vesa_display_info; DriverResult vesa_display_device_init(Device *device); @@ -26,11 +27,8 @@ DeviceOps vesa_display_device_ops = { .status = NULL, }; -Driver vesa_display_driver = { - .name = STRING_INIT("vesa display driver"), -}; DeviceDriver vesa_display_device_driver = { - .name = STRING_INIT("vesa display device driver"), + .name = STRING_INIT("VESA Display Device Driver"), .bus = &platform_bus, .type = DEVICE_TYPE_VIDEO, .priority = DRIVER_PRIORITY_BASIC, @@ -38,7 +36,7 @@ DeviceDriver vesa_display_device_driver = { .ops = &vesa_display_driver_ops, }; Device vesa_display_device = { - .name = STRING_INIT("vesa display"), + .name = STRING_INIT("Vesa Display"), .device_driver = &vesa_display_device_driver, .ops = &vesa_display_device_ops, .private_data_size = 0, @@ -48,9 +46,7 @@ VideoDevice vesa_display_video_device = { }; void register_vesa_display(void) { - register_driver(&vesa_display_driver); - driver_init(&vesa_display_driver); - register_device_driver(&vesa_display_driver, &vesa_display_device_driver); + register_device_driver(&core_driver, &vesa_display_device_driver); register_video_device( &vesa_display_device_driver, &vesa_display_device, &vesa_display_video_device); diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index a9ef020..4d766d9 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -36,10 +36,13 @@ BusDriver platform_bus_driver = { .ops = &platform_ops, }; -void init_platform() { +// 完成一些平台必要的准备工作 +void platform_early_init() { + // 初始化段描述符和中断描述符 init_descriptor(); - init_memory(); +} +void platform_init() { // 因为platform_bus是虚拟的,所以不需要注册device register_bus_driver(&platform_driver, &platform_bus_driver); list_init(&platform_bus_driver.bus_lh); @@ -53,7 +56,7 @@ void init_platform() { register_pit(); } -void platform_init_and_start_devices() { +void platform_start_devices() { init_and_start(&vesa_display_device); init_console(); print_features(); diff --git a/src/driver/bus_dm.c b/src/driver/bus_dm.c index 6e08a6d..e75c5bc 100644 --- a/src/driver/bus_dm.c +++ b/src/driver/bus_dm.c @@ -34,6 +34,7 @@ DriverResult register_bus_controller_device( bus_controller_device->bus_driver = bus_driver; DRV_RESULT_DELIVER_CALL( - register_device, device_driver, device_driver->bus, device); + register_device, device_driver, &bus_controller_device->short_name, + device_driver->bus, device); return DRIVER_RESULT_OK; } diff --git a/src/driver/interrupt_dm.c b/src/driver/interrupt_dm.c index eb24143..0f7baf8 100644 --- a/src/driver/interrupt_dm.c +++ b/src/driver/interrupt_dm.c @@ -71,8 +71,6 @@ DriverResult register_interrupt_device( interrupt_device->device = device; DRV_RESULT_DELIVER_CALL(check_intterupt_ops, interrupt_device); - DRV_RESULT_DELIVER_CALL( - register_device, device_driver, device_driver->bus, device); list_add_tail(&device->dm_list, &interrupt_device_manager.device_lh); InterruptDeviceManager *manager = interrupt_device_manager.private_data; diff --git a/src/driver/storage_dm.c b/src/driver/storage_dm.c index 72eb372..cd0b8b0 100644 --- a/src/driver/storage_dm.c +++ b/src/driver/storage_dm.c @@ -1,3 +1,4 @@ +#include "string.h" #include #include #include @@ -28,6 +29,7 @@ DeviceManagerOps storage_dm_ops = { }; typedef struct StorageDeviceManager { + uint8_t device_count; } StorageDeviceManager; StorageDeviceManager storage_dm_ext; @@ -54,8 +56,10 @@ DriverResult register_storage_device( device->device_manager_extension = storage_device; list_init(&storage_device->io_queue_lh); + string_t name; + string_new_with_number(&name, "Storage", 7, storage_dm_ext.device_count++); DRV_RESULT_DELIVER_CALL( - register_device, device_driver, device_driver->bus, device); + register_device, device_driver, &name, device_driver->bus, device); list_add_tail(&device->dm_list, &storage_device_manager.device_lh); storage_device->periodic_task.func = storage_periodic_task; diff --git a/src/driver/timer_dm.c b/src/driver/timer_dm.c index afbb15f..03f4add 100644 --- a/src/driver/timer_dm.c +++ b/src/driver/timer_dm.c @@ -135,8 +135,7 @@ DriverResult register_timer_device( device->device_manager_extension = timer_device; timer_device->device = device; - DRV_RESULT_DELIVER_CALL( - register_device, device_driver, device_driver->bus, device); + list_init(&timer_device->timer_list_lh); list_add_tail(&device->dm_list, &timer_device_manager.device_lh); diff --git a/src/driver/transfer.c b/src/driver/transfer.c new file mode 100644 index 0000000..5ccbe00 --- /dev/null +++ b/src/driver/transfer.c @@ -0,0 +1 @@ +#include diff --git a/src/driver/video_dm.c b/src/driver/video_dm.c index 6a6d729..cac2897 100644 --- a/src/driver/video_dm.c +++ b/src/driver/video_dm.c @@ -5,6 +5,7 @@ #include #include #include +#include DriverResult video_device_start(DeviceManager *manager, Device *device); @@ -50,8 +51,13 @@ DriverResult register_video_device( } video_device->device = device; + string_t name; + string_new_with_number( + &name, "Video", 5, video_dm_ext.video_device_count++); + DRV_RESULT_DELIVER_CALL( - register_device, device_driver, device_driver->bus, device); + register_device, device_driver, &name, device_driver->bus, device); + list_init(&video_device->video_list_lh); list_add_tail(&device->dm_list, &video_device_manager.device_lh); diff --git a/src/include/driver/bus_dm.h b/src/include/driver/bus_dm.h index 3261e60..441f1d1 100644 --- a/src/include/driver/bus_dm.h +++ b/src/include/driver/bus_dm.h @@ -3,12 +3,14 @@ #include "kernel/bus_driver.h" #include "kernel/device.h" +#include "string.h" typedef struct BusControllerDeviceOps { void (*probe)(Device *device); } BusControllerDeviceOps; typedef struct BusControllerDevice { + string_t short_name; Device *device; BusDriver *bus_driver; BusControllerDeviceOps *bus_controller_ops; diff --git a/src/include/driver/video_dm.h b/src/include/driver/video_dm.h index e6d801b..2e2cc73 100644 --- a/src/include/driver/video_dm.h +++ b/src/include/driver/video_dm.h @@ -26,6 +26,7 @@ typedef struct VideoDevice { typedef struct VideoDeviceManager { Device *main_display_device; + uint8_t video_device_count; } VideoDeviceManager; extern struct DeviceManager video_device_manager; diff --git a/src/include/dyn_array.h b/src/include/dyn_array.h new file mode 100644 index 0000000..00ef258 --- /dev/null +++ b/src/include/dyn_array.h @@ -0,0 +1,50 @@ +#ifndef _DYN_ARRAY_H +#define _DYN_ARRAY_H + +#include "stdint.h" + +typedef struct DynArray { + struct DynArrayBlock *first_block; + struct DynArrayBlock *last_block; + + size_t size; + size_t capacity; + size_t block_size; + size_t element_size; +} DynArray; + +struct DynArrayBlock { + struct DynArrayBlock *next; + void *data; +}; + +DynArray *dyn_array_new(size_t element_size, size_t block_size); +struct DynArrayBlock *dyn_array_find_block(DynArray *dyn_array, size_t idx); +void *dyn_array_new_item_addr(DynArray *dyn_array); + +#define dyn_array_get(arr, type, idx) \ + (type)({ \ + int block_index = (idx) / (arr)->block_size; \ + int block_offset = (idx) % (arr)->block_size; \ + \ + struct DynArrayBlock *block = dyn_array_find_block(arr, block_index); \ + ((type *)block->data)[block_offset]; \ + }) + +#define dyn_array_set(arr, type, idx, value) \ + { \ + int block_index = (idx) / (arr)->block_size; \ + int block_offset = (idx) % (arr)->block_size; \ + \ + struct DynArrayBlock *block = dyn_array_find_block(arr, block_index); \ + ((type *)block->data)[block_offset] = value; \ + } + +#define dyn_array_append(arr, type, value) \ + { \ + type *addr = dyn_array_new_item_addr(arr); \ + *addr = value; \ + (arr)->size++; \ + } + +#endif \ No newline at end of file diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index 2a0d02c..c87d254 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -82,7 +82,8 @@ typedef struct Device { struct Bus; DriverResult register_device( - struct DeviceDriver *device_driver, struct Bus *bus, Device *device); + struct DeviceDriver *device_driver, string_t *name, struct Bus *bus, + Device *device); DriverResult unregister_device( struct DeviceDriver *device_driver, Device *device); DriverResult unregister_child_device(ChildDevice *child_device); diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index 7beaf76..5a2fc32 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -152,9 +152,9 @@ typedef enum { SUBDRIVER_STATE_READY, // 子驱动准备好 } SubDriverState; -// 实体的驱动,管理着一个驱动下的所有类型的抽象驱动 +// 描述驱动程序的结构,管理着一个驱动下的所有类型的抽象驱动 typedef struct Driver { - string_t name; + string_t short_name; list_t driver_list; list_t sub_driver_lh; list_t remapped_memory_lh; @@ -187,9 +187,12 @@ DriverResult register_sub_driver( DriverResult unregister_sub_driver(Driver *driver, SubDriver *sub_driver); DriverResult driver_init(Driver *driver); DriverResult driver_start_all(void); +void add_driver_objects(void); void print_driver_result( DriverResult result, char *file, int line, char *func_with_args); +extern struct Object driver_object; + #define DRV_PRINT_RESULT(result, func, ...) \ print_driver_result(result, __FILE__, __LINE__, #func "(" #__VA_ARGS__ ")"); #define DRV_RESULT_DELIVER_CALL(func, ...) \ diff --git a/src/include/kernel/driver_interface.h b/src/include/kernel/driver_interface.h index 8828ebe..b844286 100644 --- a/src/include/kernel/driver_interface.h +++ b/src/include/kernel/driver_interface.h @@ -40,7 +40,7 @@ #define print_device_info(device, str, ...) \ printk("[%s]" str, device->name.text, ##__VA_ARGS__) #define print_driver_info(driver, str, ...) \ - printk("[%s]" str, driver.name.text, ##__VA_ARGS__) + printk("[%s]" str, driver.short_name.text, ##__VA_ARGS__) #include "kernel/list.h" struct Device; diff --git a/src/include/kernel/platform.h b/src/include/kernel/platform.h index db27a4d..1d5e956 100644 --- a/src/include/kernel/platform.h +++ b/src/include/kernel/platform.h @@ -2,7 +2,8 @@ extern struct Bus platform_bus; -void init_platform(); -void platform_init_and_start_devices(); +void platform_early_init(); +void platform_init(); +void platform_start_devices(); #endif \ No newline at end of file diff --git a/src/include/math.h b/src/include/math.h index 93e73dc..2a86a84 100644 --- a/src/include/math.h +++ b/src/include/math.h @@ -8,9 +8,10 @@ #define DIV_ROUND_UP(X, STEP) ((X + STEP - 1) / (STEP)) -int min(int a, int b); -int max(int a, int b); -int abs(int n); -int pow(int x, int y); +int min(int a, int b); +int max(int a, int b); +int abs(int n); +int pow(int x, int y); +unsigned int find_next_pow_of_2(unsigned int n); #endif diff --git a/src/include/objects/object.h b/src/include/objects/object.h new file mode 100644 index 0000000..841376c --- /dev/null +++ b/src/include/objects/object.h @@ -0,0 +1,69 @@ +#ifndef _OBJECT_H +#define _OBJECT_H + +#include "dyn_array.h" +#include "result.h" +#include "stdint.h" +#include "string.h" + +typedef enum ObjectResult { + OBJECT_OK, + OBJECT_ERROR_MEMORY, + OBJECT_ERROR_INVALID_OPERATION, +} ObjectResult; + +#define OBJECT_DIR_SIZE_SMALL 8 +#define OBJECT_DIR_SIZE_MEDIUM 16 +#define OBJECT_DIR_SIZE_LARGE 32 + +typedef enum ObjectType { + OBJECT_TYPE_TYPE, // 表示该对象用于表示一种对象类型 + OBJECT_TYPE_DIRECTORY, // 表示该对象是一个目录 + OBJECT_TYPE_DRIVER, // 表示该对象是一个驱动程序 + OBJECT_TYPE_DEVICE, // 表示该对象是一个设备 + OBJECT_TYPE_FILE, // 表示该对象是一个文件 + OBJECT_TYPE_VALUE, // 表示该对象是一个值 + OBJECT_TYPE_BUILTIN_MAX, // 表示对象系统内建类型数量的最大值 +} ObjectType; + +typedef struct Object { + string_t name; + ObjectType type; + + struct Object *parent; + union { + uint32_t type; + struct { + DynArray *children; + } directory; + struct Driver *driver; + struct Device *device; + struct { + } file; + struct { + enum { + VALUE_TYPE_STRING, + VALUE_TYPE_INTEGER, + } type; + union { + string_t string; + size_t integer; + }; + } value; + } value; +} Object; + +extern Object root_object; +extern Object driver_object; +extern Object device_object; + +ObjectResult init_object_tree(); +ObjectResult add_object(Object *parent, Object *child); +ObjectResult init_object_directory(Object *object, size_t block_size); +Object *create_object(Object *parent, string_t *name, ObjectType type); +void show_object_tree(); + +#define append_object(parent, child) \ + dyn_array_append((parent)->value.directory.children, Object *, (child)); + +#endif \ No newline at end of file diff --git a/src/include/objects/types.h b/src/include/objects/types.h new file mode 100644 index 0000000..e9f8737 --- /dev/null +++ b/src/include/objects/types.h @@ -0,0 +1,9 @@ +#ifndef _OBJECT_TYPES_H +#define _OBJECT_TYPES_H + +#include "object.h" + +ObjectResult init_builtin_types(); +Object *create_object_type(string_t *name); + +#endif \ No newline at end of file diff --git a/src/include/stdint.h b/src/include/stdint.h index cccf373..a4151b9 100644 --- a/src/include/stdint.h +++ b/src/include/stdint.h @@ -1,25 +1,35 @@ #ifndef _STDINT_H #define _STDINT_H -typedef unsigned int uint32_t; -typedef int int32_t; -typedef unsigned short uint16_t; -typedef short int16_t; -typedef unsigned char uint8_t; -typedef char int8_t; +// 依赖编译器的内置类型__UINT64_TYPE__,__INT64_TYPE__和__SIZE_TYPE__ -typedef unsigned int u32; -typedef int i32; -typedef unsigned short u16; -typedef short i16; -typedef unsigned char u8; -typedef char i8; +typedef __UINT64_TYPE__ uint64_t; +typedef __INT64_TYPE__ int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; -typedef unsigned int uint32; -typedef int int32; -typedef unsigned short uint16; -typedef short int16; -typedef unsigned char uint8; -typedef char int8; +typedef __UINT64_TYPE__ u64; +typedef __INT64_TYPE__ i64; +typedef unsigned int u32; +typedef int i32; +typedef unsigned short u16; +typedef short i16; +typedef unsigned char u8; +typedef char i8; + +typedef __UINT64_TYPE__ uint64; +typedef __INT64_TYPE__ int64; +typedef unsigned int uint32; +typedef int int32; +typedef unsigned short uint16; +typedef short int16; +typedef unsigned char uint8; +typedef char int8; + +typedef __SIZE_TYPE__ size_t; #endif diff --git a/src/include/string.h b/src/include/string.h index 8488086..d341cdf 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -26,6 +26,8 @@ typedef struct _string { void string_init(string_t *string); int string_new(string_t *string, char *text, unsigned int max_len); +int string_new_with_number( + string_t *string, char *text, int text_len, int number); void string_del(string_t *string); int string_cpy(string_t *dest, string_t *src); diff --git a/src/kernel/Makefile b/src/kernel/Makefile index a2b6b42..e4151dd 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -20,7 +20,6 @@ SRC += app.c SRC += elf.c SRC += wait_queue.c SRC += periodic_task.c -SRC += objects.c #INCLUDE_PATH = ../include/ ../$(ARCH)/include/ diff --git a/src/kernel/device.c b/src/kernel/device.c index 64c5e95..7782754 100644 --- a/src/kernel/device.c +++ b/src/kernel/device.c @@ -5,10 +5,21 @@ #include #include #include +#include #include +#include +/** + * @brief 注册设备 + * + * @param device_driver + * @param name 无空格的设备名,如未提供则不会被添加到对象树中 + * @param bus + * @param device + * @return DriverResult + */ DriverResult register_device( - DeviceDriver *device_driver, Bus *bus, Device *device) { + DeviceDriver *device_driver, string_t *name, Bus *bus, Device *device) { device->state = DEVICE_STATE_REGISTERED; @@ -28,6 +39,13 @@ DriverResult register_device( list_add_tail(&device->device_list, &device_driver->device_lh); bus_register_device(device_driver, bus); + + if (name != NULL && name->text != NULL && name->length != 0) { + Object *object = + create_object(&device_object, name, OBJECT_TYPE_DEVICE); + object->value.device = device; + } + return DRIVER_RESULT_OK; } diff --git a/src/kernel/driver.c b/src/kernel/driver.c index e4b3239..8f59d93 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -5,8 +5,6 @@ * @version 0.3 * @date 2022-07-20 */ -#include "kernel/spinlock.h" -#include "kernel/wait_queue.h" #include #include #include @@ -17,23 +15,16 @@ #include #include #include +#include #include +#include #include #include +#include #include LIST_HEAD(driver_list_head); -// list_t device_irq_lists[16] = { -// LIST_HEAD_INIT(device_irq_lists[0]), LIST_HEAD_INIT(device_irq_lists[1]), -// LIST_HEAD_INIT(device_irq_lists[2]), LIST_HEAD_INIT(device_irq_lists[3]), -// LIST_HEAD_INIT(device_irq_lists[4]), LIST_HEAD_INIT(device_irq_lists[5]), -// LIST_HEAD_INIT(device_irq_lists[6]), LIST_HEAD_INIT(device_irq_lists[7]), -// LIST_HEAD_INIT(device_irq_lists[8]), LIST_HEAD_INIT(device_irq_lists[9]), -// LIST_HEAD_INIT(device_irq_lists[10]), LIST_HEAD_INIT(device_irq_lists[11]), -// LIST_HEAD_INIT(device_irq_lists[12]), LIST_HEAD_INIT(device_irq_lists[13]), -// LIST_HEAD_INIT(device_irq_lists[14]), LIST_HEAD_INIT(device_irq_lists[15]), -// }; struct index_node *dev; @@ -53,6 +44,12 @@ struct file_operations device_fops = { LIST_HEAD(driver_lh); +Driver core_driver = { + .short_name = STRING_INIT("CoreDriver"), + .init = NULL, + .state = DRIVER_STATE_UNINITED, +}; + void print_driver_result( DriverResult result, char *file, int line, char *func_with_args) { if (result == DRIVER_RESULT_OK) return; @@ -83,6 +80,10 @@ DriverResult register_driver(Driver *driver) { list_init(&driver->sub_driver_lh); list_init(&driver->remapped_memory_lh); list_add_tail(&driver->driver_list, &driver_lh); + + Object *object = + create_object(&driver_object, &driver->short_name, OBJECT_TYPE_DRIVER); + object->value.driver = driver; return DRIVER_RESULT_OK; } @@ -117,7 +118,8 @@ DriverResult driver_init(Driver *driver) { driver->state = DRIVER_STATE_UNREGISTERED; unregister_driver(driver); print_error_with_position( - "driver_init: driver %s init failed!\n", driver->name.text); + "driver_init: driver %s init failed!\n", + driver->short_name.text); return result; } } diff --git a/src/kernel/main.c b/src/kernel/main.c index 07bf08b..6a569a5 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -4,6 +4,9 @@ * @brief 内核主程序 * @date 2020-03 */ +#include "driver/storage_io_queue.h" +#include "kernel/list.h" +#include "objects/object.h" #include #include #include @@ -33,11 +36,16 @@ #include #include #include +#include +#include void idle(void *arg); struct task_s *task_idle; +extern Driver core_driver; int main() { + platform_early_init(); + register_driver_manager(&device_driver_manager); register_driver_manager(&bus_driver_manager); register_device_manager(&interrupt_device_manager); @@ -45,8 +53,14 @@ int main() { register_device_manager(&video_device_manager); register_device_manager(&storage_device_manager); - init_platform(); - platform_init_and_start_devices(); + init_memory(); + init_object_tree(); + + register_driver(&core_driver); + driver_init(&core_driver); + + platform_init(); + platform_start_devices(); init_task(); task_idle = thread_start("Idle", 1, idle, 0); @@ -58,6 +72,37 @@ int main() { driver_start_all(); thread_start( "Kernel Periodic Tasks", THREAD_DEFAULT_PRIO, periodic_task, NULL); + + // uint8_t buf1[512], buf2[512]; + // Device *device = + // list_first_owner(&storage_device_manager.device_lh, Device, dm_list); + // StorageRequest request1 = { + // .storage_device = device->device_manager_extension, + // .rw = 0, + // .buf = buf1, + // .position = 0, + // .count = 1, + // .is_finished = 0, + // }; + // StorageRequest request2 = { + // .storage_device = device->device_manager_extension, + // .rw = 0, + // .buf = buf2, + // .position = 1, + // .count = 1, + // .is_finished = 0, + // }; + // storage_add_request(device->device_manager_extension, &request1); + // storage_add_request(device->device_manager_extension, &request2); + // while (!(request1.is_finished && request2.is_finished)) { + // schedule(); + // } + // print_hex(buf1, 512); + // print_hex(buf2, 512); + + show_object_tree(); + + // storage_add_request(device->device_manager_extension, &request); // init_fs(); // thread_start( diff --git a/src/kernel/objects.c b/src/kernel/objects.c deleted file mode 100644 index e69de29..0000000 diff --git a/src/lib/Makefile b/src/lib/Makefile index b3615d4..c1f8a1d 100644 --- a/src/lib/Makefile +++ b/src/lib/Makefile @@ -2,4 +2,5 @@ SRC += ctype.c SRC += math.c SRC += string.c SRC += vsprintf.c -SRC += rand.c \ No newline at end of file +SRC += rand.c +SRC += dyn_array.c \ No newline at end of file diff --git a/src/lib/dyn_array.c b/src/lib/dyn_array.c new file mode 100644 index 0000000..f665099 --- /dev/null +++ b/src/lib/dyn_array.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +DynArray *dyn_array_new(size_t element_size, size_t block_size) { + DynArray *array = kmalloc(sizeof(DynArray)); + if (array == NULL) { return NULL; } + + array->size = 0; + array->capacity = block_size; + array->block_size = block_size; + array->element_size = find_next_pow_of_2(element_size); + + array->first_block = kmalloc(sizeof(struct DynArrayBlock)); + array->first_block->next = NULL; + array->first_block->data = kmalloc(block_size * array->element_size); + array->last_block = array->first_block; + + return array; +} + +void dyn_array_extend_block(DynArray *dyn_array) { + struct DynArrayBlock *block = dyn_array->first_block; + while (block->next != NULL) { + block = block->next; + } + + struct DynArrayBlock *new_block = kmalloc(sizeof(struct DynArrayBlock)); + + block->next = new_block; + new_block->next = NULL; + new_block->data = kmalloc(dyn_array->block_size * dyn_array->element_size); + + dyn_array->capacity += dyn_array->block_size * dyn_array->element_size; + + dyn_array->last_block = new_block; +} + +struct DynArrayBlock *dyn_array_find_block(DynArray *dyn_array, size_t idx) { + struct DynArrayBlock *block = dyn_array->first_block; + + for (int i = 0; i < idx; i++) { + if (block->next == NULL) { dyn_array_extend_block(dyn_array); } + block = block->next; + } + + return block; +} + +/** + * @brief 找到新的元素的地址 + * + */ +void *dyn_array_new_item_addr(DynArray *dyn_array) { + struct DynArrayBlock *block = dyn_array->last_block; + if (dyn_array->size % dyn_array->block_size == 0 && dyn_array->size != 0) { + dyn_array_extend_block(dyn_array); + block = dyn_array->last_block; + } + + return block->data + + (dyn_array->size % dyn_array->block_size) * dyn_array->element_size; +} \ No newline at end of file diff --git a/src/lib/math.c b/src/lib/math.c index 35b5967..6af79dd 100644 --- a/src/lib/math.c +++ b/src/lib/math.c @@ -1,26 +1,32 @@ #include -int max(int a, int b) -{ - return a>b ? a : b; +int max(int a, int b) { + return a > b ? a : b; } -int min(int a, int b) -{ - return a=0 ? n : -n; +int abs(int n) { + return n >= 0 ? n : -n; } -int pow(int x, int y) -{ +int pow(int x, int y) { int i, ans = x; - for(i = 0; i < y; i++) - { + for (i = 0; i < y; i++) { ans *= x; } return ans; +} + +unsigned int find_next_pow_of_2(unsigned int n) { + n--; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n++; + return n; } \ No newline at end of file diff --git a/src/lib/string.c b/src/lib/string.c index 872e945..1bd3e2b 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -44,6 +44,36 @@ int string_new(string_t *string, char *text, unsigned int max_len) { return 0; } +/** + * @brief 新建带数字后缀的字符串 + * + * @param string + * @param text 文本 + * @param text_len 文本长度 + * @param number 数字 + * @return int + */ +int string_new_with_number( + string_t *string, char *text, int text_len, int number) { + + // 计算数字长度 + int len = 0; + int x = number; + do { + len++; + x /= 10; + } while (x > 0); + + string_new(string, text, text_len + len); + x = number; + for (int i = text_len + len - 1; i >= text_len; i--) { + string->text[i] = '0' + x % 10; + x /= 10; + } + + return 0; +} + /** * @brief 删除字符串 * diff --git a/src/objects/Makefile b/src/objects/Makefile new file mode 100644 index 0000000..9acfe72 --- /dev/null +++ b/src/objects/Makefile @@ -0,0 +1,2 @@ +SRC += objects.c +SRC += types.c \ No newline at end of file diff --git a/src/objects/objects.c b/src/objects/objects.c new file mode 100644 index 0000000..1745a38 --- /dev/null +++ b/src/objects/objects.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +Object root_object = { + .name = STRING_INIT(""), // 根对象的名字不会起到任何作用,所以设为空 + .type = OBJECT_TYPE_DIRECTORY, +}; +Object driver_object = { + .name = STRING_INIT("Driver"), + .type = OBJECT_TYPE_DIRECTORY, +}; +Object device_object = { + .name = STRING_INIT("Device"), + .type = OBJECT_TYPE_DIRECTORY, +}; + +/** + * @brief 初始化对象目录的children结构 + * + * @param object + * @param block_size + * @return ObjectResult + */ +ObjectResult init_object_directory(Object *object, size_t block_size) { + DynArray *children = dyn_array_new(sizeof(Object *), block_size); + if (children == NULL) { return OBJECT_ERROR_MEMORY; } + + object->value.directory.children = children; + return OBJECT_OK; +} + +/** + * @brief 初始化对象树 + * + * @return ObjectResult + */ +ObjectResult init_object_tree() { + init_object_directory(&root_object, OBJECT_DIR_SIZE_SMALL); + init_object_directory(&driver_object, OBJECT_DIR_SIZE_LARGE); + init_object_directory(&device_object, OBJECT_DIR_SIZE_LARGE); + add_object(&root_object, &driver_object); + add_object(&root_object, &device_object); + + init_builtin_types(); + return OBJECT_OK; +} + +ObjectResult add_object(Object *parent, Object *child) { + if (parent->type != OBJECT_TYPE_DIRECTORY) { + return OBJECT_ERROR_INVALID_OPERATION; + } + + append_object(parent, child); + + return OBJECT_OK; +} + +Object *create_object(Object *parent, string_t *name, ObjectType type) { + Object *object = kmalloc(sizeof(Object)); + if (object == NULL) { return NULL; } + + object->name = *name; + object->type = type; + object->parent = parent; + + add_object(parent, object); + + return object; +} + +Object *create_object_directory(Object *parent, string_t *name) { + Object *object = create_object(parent, name, OBJECT_TYPE_DIRECTORY); + if (object == NULL) { return NULL; } + + init_object_directory(object, OBJECT_DIR_SIZE_SMALL); + + return object; +} + +void print_object_directory(Object *object, int level) { + for (int i = 0; i < object->value.directory.children->size; i++) { + Object *child = + dyn_array_get(object->value.directory.children, Object *, i); + for (int j = 0; j < level; j++) { + printk("|\t"); + } + printk("|-%s\n", child->name.text); + if (child->type == OBJECT_TYPE_DIRECTORY) { + print_object_directory(child, level + 1); + } + } +} + +void show_object_tree() { + Object *object = &root_object; + printk("root\n_\n"); + print_object_directory(object, 0); +} \ No newline at end of file diff --git a/src/objects/types.c b/src/objects/types.c new file mode 100644 index 0000000..e6ac28e --- /dev/null +++ b/src/objects/types.c @@ -0,0 +1,44 @@ +#include +#include +#include + +#define DEFINE_OBJECT_TYPE(type_name) \ + { \ + .name = STRING_INIT(#type_name), .type = OBJECT_TYPE_TYPE, \ + .value.type = OBJECT_TYPE_##type_name \ + } + +Object object_builtin_types[OBJECT_TYPE_BUILTIN_MAX] = { + DEFINE_OBJECT_TYPE(TYPE), DEFINE_OBJECT_TYPE(DIRECTORY), + DEFINE_OBJECT_TYPE(DRIVER), DEFINE_OBJECT_TYPE(DEVICE), + DEFINE_OBJECT_TYPE(FILE), DEFINE_OBJECT_TYPE(VALUE), +}; + +Object object_type_directory = { + .name = STRING_INIT("ObjectType"), + .type = OBJECT_TYPE_DIRECTORY, +}; + +ObjectResult init_builtin_types() { + DynArray *children = dyn_array_new(sizeof(Object *), OBJECT_DIR_SIZE_SMALL); + init_object_directory(&object_type_directory, OBJECT_DIR_SIZE_LARGE); + add_object(&root_object, &object_type_directory); + + object_type_directory.value.directory.children = children; + for (int i = 0; i < OBJECT_TYPE_BUILTIN_MAX; i++) { + add_object(&object_type_directory, &object_builtin_types[i]); + } + + return OBJECT_OK; +} + +Object *create_object_type(string_t *name) { + Object *object = + create_object(&object_type_directory, name, OBJECT_TYPE_TYPE); + if (object == NULL) { return NULL; } + + object->value.type = + object_type_directory.value.directory.children->size - 1; + + return object; +} \ No newline at end of file From 1050283b422ccbd492dd8abe5130622d75101b1d Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 11 Feb 2025 01:56:17 +0800 Subject: [PATCH 017/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=AC=A6=E5=8F=B7?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/disk/ata/ide.c | 4 ++- src/arch/x86/drivers/pci.c | 3 ++ src/arch/x86/kernel/platform.c | 18 ++++++++---- src/driver/bus_dm.c | 2 +- src/driver/storage_dm.c | 2 +- src/include/kernel/bus_driver.h | 17 +++++++---- src/include/kernel/device.h | 9 +++++- src/include/kernel/device_driver.h | 3 ++ src/include/objects/object.h | 4 +++ src/kernel/bus_driver.c | 44 +++++++++++++++++++++-------- src/kernel/device.c | 8 +++--- src/lib/string.c | 5 +++- src/objects/objects.c | 22 ++++++++++++++- src/objects/types.c | 7 +++-- 14 files changed, 113 insertions(+), 35 deletions(-) diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index 158e615..6547214 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -174,7 +175,8 @@ void ide_device_probe(IdeChannel *channel) { sizeof(AtaIdentifyInfo) / 2); // 6.注册设备 - Device *device = kmalloc_from_template(ide_device_template); + Device *device = kmalloc_from_template(ide_device_template); + device->bus = &platform_bus; // TODO: BUS StorageDevice *storage_device = kmalloc_from_template(storage_device_template); diff --git a/src/arch/x86/drivers/pci.c b/src/arch/x86/drivers/pci.c index 979e2e6..d09f4f6 100644 --- a/src/arch/x86/drivers/pci.c +++ b/src/arch/x86/drivers/pci.c @@ -19,11 +19,13 @@ #include #include #include +#include #include #include #include #include + LIST_HEAD(pci_driver_lh); PciDevice pci_devices[PCI_MAX_DEVICE]; @@ -84,6 +86,7 @@ DeviceDriver pci_device_driver = { Device pci_device = { .name = STRING_INIT("PCI Controller"), .state = DEVICE_STATE_UNREGISTERED, + .bus = &platform_bus, .private_data_size = 0, .ops = &pci_device_ops, }; diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index 4d766d9..9b99a9c 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -1,3 +1,7 @@ +#include "driver/bus_dm.h" +#include "kernel/memory.h" +#include "objects/object.h" +#include "string.h" #include #include #include @@ -22,19 +26,20 @@ BusOps platform_bus_ops = { .unregister_device_hook = NULL, }; -Driver platform_driver; -Bus platform_bus = { - .controller_device = NULL, - .ops = &platform_bus_ops, -}; +Driver platform_driver; BusDriver platform_bus_driver = { .driver_type = DRIVER_TYPE_BUS_DRIVER, .bus_type = BUS_TYPE_PLATFORM, - .name = STRING_INIT("platform"), + .name = STRING_INIT("Platform"), .state = DRIVER_STATE_UNREGISTERED, .private_data_size = 0, .ops = &platform_ops, }; +Bus platform_bus = { + .controller_device = NULL, + .bus_driver = &platform_bus_driver, + .ops = &platform_bus_ops, +}; // 完成一些平台必要的准备工作 void platform_early_init() { @@ -45,6 +50,7 @@ void platform_early_init() { void platform_init() { // 因为platform_bus是虚拟的,所以不需要注册device register_bus_driver(&platform_driver, &platform_bus_driver); + platform_bus.object = platform_bus_driver.object; list_init(&platform_bus_driver.bus_lh); list_add_tail(&platform_bus.bus_list, &platform_bus_driver.bus_lh); diff --git a/src/driver/bus_dm.c b/src/driver/bus_dm.c index e75c5bc..3ac8b2d 100644 --- a/src/driver/bus_dm.c +++ b/src/driver/bus_dm.c @@ -35,6 +35,6 @@ DriverResult register_bus_controller_device( DRV_RESULT_DELIVER_CALL( register_device, device_driver, &bus_controller_device->short_name, - device_driver->bus, device); + device->bus, device); return DRIVER_RESULT_OK; } diff --git a/src/driver/storage_dm.c b/src/driver/storage_dm.c index cd0b8b0..0b7c6c6 100644 --- a/src/driver/storage_dm.c +++ b/src/driver/storage_dm.c @@ -59,7 +59,7 @@ DriverResult register_storage_device( string_t name; string_new_with_number(&name, "Storage", 7, storage_dm_ext.device_count++); DRV_RESULT_DELIVER_CALL( - register_device, device_driver, &name, device_driver->bus, device); + register_device, device_driver, &name, device->bus, device); list_add_tail(&device->dm_list, &storage_device_manager.device_lh); storage_device->periodic_task.func = storage_periodic_task; diff --git a/src/include/kernel/bus_driver.h b/src/include/kernel/bus_driver.h index 706dbac..d166a03 100644 --- a/src/include/kernel/bus_driver.h +++ b/src/include/kernel/bus_driver.h @@ -5,7 +5,8 @@ #include "kernel/driver.h" #include "kernel/driver_manager.h" #include "kernel/list.h" -#include "kernel/wait_queue.h" +#include "objects/object.h" +#include "string.h" #include #define BUS_OPS_CALL(bus, func, ...) \ @@ -34,8 +35,8 @@ typedef struct BusDriverOps { } BusDriverOps; typedef struct BusOps { - DriverResult (*register_device_hook)(struct DeviceDriver *device_driver); - DriverResult (*unregister_device_hook)(struct DeviceDriver *device_driver); + DriverResult (*register_device_hook)(struct Device *device); + DriverResult (*unregister_device_hook)(struct Device *device); DriverResult (*scan_bus)(struct BusDriver *bus_driver, struct Bus *bus); DriverResult (*probe_device)(struct BusDriver *bus_driver, struct Bus *bus); @@ -52,6 +53,8 @@ typedef struct BusDriver { BusType bus_type; DriverState state; + Object *object; + uint32_t bus_count; uint32_t device_count; @@ -68,6 +71,10 @@ typedef struct Bus { Device *controller_device; struct Bus *primary_bus; + string_t name; + Object *object; + + uint32_t last_device_num; uint32_t bus_num; uint32_t subordinate_bus_num; @@ -82,7 +89,7 @@ DriverResult unregister_bus_driver(Driver *driver, BusType type); DriverResult register_bus( BusDriver *bus_driver, Device *bus_controller_device, Bus *bus); DriverResult unregister_bus(Bus *bus); -DriverResult bus_register_device(DeviceDriver *device_driver, Bus *bus); -DriverResult bus_unregister_device(DeviceDriver *device_driver); +DriverResult bus_register_device(Device *device, Bus *bus); +DriverResult bus_unregister_device(Device *device); #endif \ No newline at end of file diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index c87d254..db6d1ba 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -5,6 +5,7 @@ #include "kernel/driver.h" #include "kernel/driver_interface.h" #include "kernel/list.h" +#include "objects/object.h" #include "stdint.h" #include "string.h" #include "types.h" @@ -60,13 +61,20 @@ typedef struct ChildDevice { void *private_data; } ChildDevice; +struct Bus; + typedef struct Device { + list_t bus_list; list_t device_list; list_t dm_list; string_t name; DeviceState state; struct DeviceDriver *device_driver; + struct Bus *bus; + + Object *object; + DeviceIrq *irq; Transfer *transfer; DeviceOps *ops; @@ -80,7 +88,6 @@ typedef struct Device { void *device_manager_extension; // 设备管理器所需的扩展信息 } Device; -struct Bus; DriverResult register_device( struct DeviceDriver *device_driver, string_t *name, struct Bus *bus, Device *device); diff --git a/src/include/kernel/device_driver.h b/src/include/kernel/device_driver.h index 3015797..86e2340 100644 --- a/src/include/kernel/device_driver.h +++ b/src/include/kernel/device_driver.h @@ -4,6 +4,7 @@ #include "kernel/device.h" #include "kernel/driver.h" #include "kernel/list.h" +#include "objects/object.h" #include "stdint.h" #include "string.h" @@ -42,6 +43,8 @@ typedef struct DeviceDriver { DriverPriority priority; DriverState state; + Object *object; + DeviceDriverOps *ops; void *private_data; diff --git a/src/include/objects/object.h b/src/include/objects/object.h index 841376c..41c0d6a 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -23,6 +23,7 @@ typedef enum ObjectType { OBJECT_TYPE_DEVICE, // 表示该对象是一个设备 OBJECT_TYPE_FILE, // 表示该对象是一个文件 OBJECT_TYPE_VALUE, // 表示该对象是一个值 + OBJECT_TYPE_SYM_LINK, // 表示该对象是一个符号链接 OBJECT_TYPE_BUILTIN_MAX, // 表示对象系统内建类型数量的最大值 } ObjectType; @@ -50,10 +51,12 @@ typedef struct Object { size_t integer; }; } value; + struct Object *sym_link; } value; } Object; extern Object root_object; +extern Object bus_object; extern Object driver_object; extern Object device_object; @@ -61,6 +64,7 @@ ObjectResult init_object_tree(); ObjectResult add_object(Object *parent, Object *child); ObjectResult init_object_directory(Object *object, size_t block_size); Object *create_object(Object *parent, string_t *name, ObjectType type); +Object *create_object_directory(Object *parent, string_t *name); void show_object_tree(); #define append_object(parent, child) \ diff --git a/src/kernel/bus_driver.c b/src/kernel/bus_driver.c index 9320c9f..d829d5d 100644 --- a/src/kernel/bus_driver.c +++ b/src/kernel/bus_driver.c @@ -1,3 +1,7 @@ +#include "kernel/driver_interface.h" +#include "objects/object.h" +#include "objects/types.h" +#include "string.h" #include #include #include @@ -65,6 +69,9 @@ DriverResult register_bus_driver(Driver *driver, BusDriver *bus_driver) { bus_drivers[bus_driver->bus_type] = bus_driver; + bus_driver->object = + create_object_directory(&bus_object, &bus_driver->name); + return DRIVER_RESULT_OK; } @@ -76,6 +83,8 @@ DriverResult unregister_bus_driver(Driver *driver, BusType type) { BusDriver *bus_driver = bus_drivers[type]; if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + // TODO: delete_object(&bus_driver->object); + bus_drivers[bus_driver->driver_type] = NULL; Bus *cur, *next; @@ -105,10 +114,14 @@ DriverResult register_bus( primary_bus = primary_bus->primary_bus; } + string_new_with_number(&bus->name, "", 0, bus->bus_num); bus->bus_driver = bus_driver; bus->controller_device = bus_controller_device; list_init(&bus->device_lh); list_add_tail(&bus->bus_list, &bus_driver->bus_lh); + + bus->object = create_object_directory(bus_driver->object, &bus->name); + BUS_OPS_CALL(bus_driver, register_bus_hook, bus); return DRIVER_RESULT_OK; @@ -118,8 +131,10 @@ DriverResult unregister_bus(Bus *bus) { BusDriver *bus_driver = bus->bus_driver; if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + // TODO: delete_object(&bus->object); + // 取消注册bus下的所有device_driver - DeviceDriver *cur, *next; + Device *cur, *next; list_for_each_owner_safe (cur, next, &bus->device_lh, bus_list) { bus_unregister_device(cur); } @@ -131,24 +146,31 @@ DriverResult unregister_bus(Bus *bus) { return DRIVER_RESULT_OK; } -DriverResult bus_register_device(DeviceDriver *device_driver, Bus *bus) { - BusDriver *bus_driver = bus_drivers[device_driver->type]; +DriverResult bus_register_device(Device *device, Bus *bus) { + BusDriver *bus_driver = bus->bus_driver; if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; - device_driver->bus = bus; - list_add_tail(&device_driver->bus_list, &bus->device_lh); - BUS_OPS_CALL(bus, register_device_hook, device_driver); + device->bus = bus; + list_add_tail(&device->bus_list, &bus->device_lh); + BUS_OPS_CALL(bus, register_device_hook, device); + + string_t *name = kmalloc(sizeof(string_t)); + string_new_with_number(name, "", 0, bus->last_device_num++); + device->object = create_object(bus->object, name, OBJECT_TYPE_DEVICE); + device->object->value.device = device; return DRIVER_RESULT_OK; } -DriverResult bus_unregister_device(DeviceDriver *device_driver) { - Bus *bus = device_driver->bus; +DriverResult bus_unregister_device(Device *device) { + Bus *bus = device->bus; if (bus == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; - BUS_OPS_CALL(bus, unregister_device_hook, device_driver); - list_del(&device_driver->bus_list); - device_driver->bus = NULL; + BUS_OPS_CALL(bus, unregister_device_hook, device); + list_del(&device->bus_list); + device->bus = NULL; + + // TODO: delete_object(&device_driver->object); return DRIVER_RESULT_OK; } diff --git a/src/kernel/device.c b/src/kernel/device.c index 7782754..240f55c 100644 --- a/src/kernel/device.c +++ b/src/kernel/device.c @@ -38,12 +38,12 @@ DriverResult register_device( } list_add_tail(&device->device_list, &device_driver->device_lh); - bus_register_device(device_driver, bus); + bus_register_device(device, bus); if (name != NULL && name->text != NULL && name->length != 0) { Object *object = - create_object(&device_object, name, OBJECT_TYPE_DEVICE); - object->value.device = device; + create_object(&device_object, name, OBJECT_TYPE_SYM_LINK); + object->value.sym_link = device->object; } return DRIVER_RESULT_OK; @@ -51,7 +51,7 @@ DriverResult register_device( DriverResult unregister_device(DeviceDriver *device_driver, Device *device) { device->state = DEVICE_STATE_REGISTERED; - bus_unregister_device(device_driver); + bus_unregister_device(device); list_del(&device->device_list); return DRIVER_RESULT_OK; } diff --git a/src/lib/string.c b/src/lib/string.c index 1bd3e2b..9373a66 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -64,7 +64,10 @@ int string_new_with_number( x /= 10; } while (x > 0); - string_new(string, text, text_len + len); + int ret = string_new(string, text, text_len + len); + if (ret != 0) { return ret; } + string->length = text_len + len; + x = number; for (int i = text_len + len - 1; i >= text_len; i--) { string->text[i] = '0' + x % 10; diff --git a/src/objects/objects.c b/src/objects/objects.c index 1745a38..a11425c 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -10,6 +10,11 @@ Object root_object = { .name = STRING_INIT(""), // 根对象的名字不会起到任何作用,所以设为空 + .type = OBJECT_TYPE_DIRECTORY, + .parent = NULL, +}; +Object bus_object = { + .name = STRING_INIT("Bus"), .type = OBJECT_TYPE_DIRECTORY, }; Object driver_object = { @@ -43,9 +48,11 @@ ObjectResult init_object_directory(Object *object, size_t block_size) { */ ObjectResult init_object_tree() { init_object_directory(&root_object, OBJECT_DIR_SIZE_SMALL); + init_object_directory(&bus_object, OBJECT_DIR_SIZE_SMALL); init_object_directory(&driver_object, OBJECT_DIR_SIZE_LARGE); init_object_directory(&device_object, OBJECT_DIR_SIZE_LARGE); add_object(&root_object, &driver_object); + add_object(&root_object, &bus_object); add_object(&root_object, &device_object); init_builtin_types(); @@ -57,6 +64,7 @@ ObjectResult add_object(Object *parent, Object *child) { return OBJECT_ERROR_INVALID_OPERATION; } + child->parent = parent; append_object(parent, child); return OBJECT_OK; @@ -84,6 +92,13 @@ Object *create_object_directory(Object *parent, string_t *name) { return object; } +void print_symbol_link(Object *object) { + if (object != NULL && object != &root_object) { + print_symbol_link(object->parent); + printk("\\%s", object->name.text); + } +} + void print_object_directory(Object *object, int level) { for (int i = 0; i < object->value.directory.children->size; i++) { Object *child = @@ -91,7 +106,12 @@ void print_object_directory(Object *object, int level) { for (int j = 0; j < level; j++) { printk("|\t"); } - printk("|-%s\n", child->name.text); + printk("|-%s", child->name.text); + if (child->type == OBJECT_TYPE_SYM_LINK) { + printk("\t->\t"); + print_symbol_link(child->value.sym_link); + } + printk("\n"); if (child->type == OBJECT_TYPE_DIRECTORY) { print_object_directory(child, level + 1); } diff --git a/src/objects/types.c b/src/objects/types.c index e6ac28e..c1a8a97 100644 --- a/src/objects/types.c +++ b/src/objects/types.c @@ -9,9 +9,10 @@ } Object object_builtin_types[OBJECT_TYPE_BUILTIN_MAX] = { - DEFINE_OBJECT_TYPE(TYPE), DEFINE_OBJECT_TYPE(DIRECTORY), - DEFINE_OBJECT_TYPE(DRIVER), DEFINE_OBJECT_TYPE(DEVICE), - DEFINE_OBJECT_TYPE(FILE), DEFINE_OBJECT_TYPE(VALUE), + DEFINE_OBJECT_TYPE(TYPE), DEFINE_OBJECT_TYPE(DIRECTORY), + DEFINE_OBJECT_TYPE(DRIVER), DEFINE_OBJECT_TYPE(DEVICE), + DEFINE_OBJECT_TYPE(FILE), DEFINE_OBJECT_TYPE(VALUE), + DEFINE_OBJECT_TYPE(SYM_LINK), }; Object object_type_directory = { From d39b61dff6dabeb1a7b6757c0b578e8546e09190 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 11 Feb 2025 22:47:47 +0800 Subject: [PATCH 018/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E4=B8=BAdyn=5Farr?= =?UTF-8?q?ay=E5=AE=9E=E7=8E=B0foreach=EF=BC=9B=20=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?=E9=80=9A=E8=BF=87ascii=E5=AD=97=E7=AC=A6=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=AF=B9=E8=B1=A1=E5=8A=9F=E8=83=BD=EF=BC=9B?= =?UTF-8?q?=20=E5=88=A0=E9=99=A4=20=E9=83=A8=E5=88=86=E6=97=A7=E7=9A=84?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/Makefile | 1 - src/arch/x86/drivers/ide.c | 793 ---------------------------------- src/arch/x86/drivers/video.c | 128 ------ src/include/dyn_array.h | 17 + src/include/objects/object.h | 7 +- src/include/string.h | 7 +- src/kernel/main.c | 12 +- src/lib/dyn_array.c | 26 ++ src/lib/string.c | 5 +- src/objects/objects.c | 54 +++ 10 files changed, 115 insertions(+), 935 deletions(-) delete mode 100644 src/arch/x86/drivers/ide.c delete mode 100644 src/arch/x86/drivers/video.c diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index cabdcaa..845f6a1 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -6,7 +6,6 @@ SRC += cpufreq.c SRC += disk.c SRC += pci.c SRC += dma.c -#SRC += ide.c #SRC += keyboard.c #SRC += mouse.c SRC += msr.c diff --git a/src/arch/x86/drivers/ide.c b/src/arch/x86/drivers/ide.c deleted file mode 100644 index 1e146c7..0000000 --- a/src/arch/x86/drivers/ide.c +++ /dev/null @@ -1,793 +0,0 @@ -/** - * @file ide.c - * @author Ryan Wang (ryan1202@foxmail.com) - * @brief IDE驱动 - * @version 1.2 - * @date 2023-01-23 - */ - -// #define IDE_DMA_MODE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ATA_PRIMARY_PORT 0x1f0 -#define ATA_SECONDARY_PORT 0x170 - -#define ATA_STATUS_BUSY 0x80 // 驱动器忙 -#define ATA_STATUS_READY 0x40 // 驱动器就绪 -#define ATA_STATUS_DF 0x20 // 驱动器写故障 -#define ATA_STATUS_SEEK 0x10 // 驱动器查找完成 -#define ATA_STATUS_DRQ 0x08 // 请求数据 -#define ATA_STATUS_CORR 0x04 // Correct data -#define ATA_STATUS_INDEX 0x02 // 索引 -#define ATA_STATUS_ERR 0x01 // 错误 - -#define ATA_ERROR_BBK 0x80 // 错误块 -#define ATA_ERROR_UNC 0x40 // 无法矫正的数据 -#define ATA_ERROR_MC 0x20 // 媒体更改 -#define ATA_ERROR_IDNF 0x10 // 找不到ID标记 -#define ATA_ERROR_MCR 0x08 // 媒体更改请求 -#define ATA_ERROR_ABRT 0x04 // 命令终止 -#define ATA_ERROR_TK0NF 0x02 // 找不到磁道0 -#define ATA_ERROR_AMNF 0x01 // 没有地址标记 - -#define ATA_CMD_RESTORE 0x10 -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xc8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xca -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xe7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xea -#define ATA_CMD_PACKET 0xa0 -#define ATA_CMD_IDENTIFY_PACKET 0xa1 -#define ATA_CMD_IDENTIFY 0xec -#define ATAPI_CMD_READ 0xA8 -#define ATAPI_CMD_EJECT 0x1B - -#define IDE_ATA 0x00 -#define IDE_ATAPI 0x01 - -#define ATA_PRIMARY 0x00 -#define ATA_SECONDARY 0x01 - -#define IDE_READ 0x01 -#define IDE_WRITE 0x02 - -#define ATA_MASTER 0x00 -#define ATA_SLAVE 0x01 - -#define ATA_REG_DATA(channel) (channel->base + 0) -#define ATA_REG_FEATURE(channel) (channel->base + 1) -#define ATA_REG_ERROR(channel) (channel->base + 1) -#define ATA_REG_SECTOR_CNT(channel) (channel->base + 2) -#define ATA_REG_SECTOR_LOW(channel) (channel->base + 3) -#define ATA_REG_SECTOR_MID(channel) (channel->base + 4) -#define ATA_REG_SECTOR_HIGH(channel) (channel->base + 5) -#define ATA_REG_DEVICE(channel) (channel->base + 6) -#define ATA_REG_STATUS(channel) (channel->base + 7) -#define ATA_REG_CMD(channel) (channel->base + 7) -#define ATA_REG_ALT_STATUS(channel) (channel->base + 0x206) -#define ATA_REG_CTL(channel) (channel->base + 0x206) - -// UDMA寄存器(Bus Master IDE Register) - -#define IDE_BM_REG_CMD(channel) (channel->channel_num * 8 + 0) -#define IDE_BM_REG_SPEC0(channel) (channel->channel_num * 8 + 1) -#define IDE_BM_REG_STATUS(channel) (channel->channel_num * 8 + 2) -#define IDE_BM_REG_SPEC1(channel) (channel->channel_num * 8 + 3) -#define IDE_BM_REG_PRDT_ADDR(channel) (channel->channel_num * 8 + 4) - -// Bus Master IDE Command Register - -#define IDE_BMCR_START 0x01 -#define IDE_BMCR_RW 0x08 - -// Bus Master IDE Status Register - -#define IDE_BMSR_ACTIVE 0x01 -#define IDE_BMSR_ERROR 0x02 -#define IDE_BMSR_INTERRUPT 0x04 -#define IDE_BMSR_DMA0_CAPABLE 0x20 -#define IDE_BMSR_DMA1_CAPABLE 0x40 -#define IDE_BMSR_SIMPLEX_ONLY 0x80 - -#define IDE_DISK_CNT 0x475 // BIOS数据区中此处保存了磁盘数 -#define IDE_MAX_CHANNEL_NUM 2 -#define IDE_MAX_DEV_PER_CNL 2 - -#define SECTOR_SIZE 512 - -#define IDE0_IRQ 14 -#define IDE1_IRQ 15 - -#define IDE_SEND_CMD(channel, cmd) io_out8(ATA_REG_CMD(channel), cmd) - -struct physicalRegionDescriptor { - uint32_t base_addr; - uint16_t count; - uint16_t EOT; -}; - -struct ide_identify_info { - unsigned short general_config; - unsigned short obsolete0; - unsigned short specific_config; - unsigned short obsolete1; - unsigned short retired0[2]; - unsigned short obsolete2; - unsigned short compact_flash[2]; - unsigned short retired1; - unsigned short serial_number[10]; - unsigned short retired2[2]; - unsigned short obsolete3; - unsigned short firmware_version[4]; - unsigned short model_number[20]; - unsigned short max_logical_transferred_per_DRQ; - unsigned short trusted_computing_feature_set_options; - unsigned short capabilities0; - unsigned short capabilities1; - unsigned short obsolete4[2]; - unsigned short report_88_70to_64_valid; - unsigned short obsolete5[5]; - unsigned short mul_sesc_setting_valid; - unsigned short lba28sectors[2]; - unsigned short obsolete6; - unsigned short multword_DMA_select; - unsigned short PIO_mode_supported; - unsigned short min_mulword_DMA_cycle_time_per_word; - unsigned short manufacture_recommend_multiword_DMA_cycle_time; - unsigned short min_PIO_cycle_time_flow_control; - unsigned short min_PIO_cycle_time_IORDY_flow_control; - unsigned short reserved1[2]; - unsigned short reserved2[4]; - unsigned short queue_depth; - unsigned short SATA_capabilities; - unsigned short reserved3; - unsigned short SATA_features_supported; - unsigned short SATA_features_enabled; - unsigned short major_version; - unsigned short minor_version; - unsigned short cmd_set0; - unsigned short cmd_set1; - unsigned short cmd_feature_sets_supported2; - unsigned short cmd_feature_sets_supported3; - unsigned short cmd_feature_sets_supported4; - unsigned short cmd_feature_sets_supported5; - unsigned short ultra_DMA_modes; - unsigned short time_required_erase_cmd; - unsigned short time_required_enhanced_cmd; - unsigned short current_AAM_level_value; - unsigned short master_password_identifier; - unsigned short hardware_reset_result; - unsigned short current_AAM_value; - unsigned short stream_min_request_size; - unsigned short streaming_transger_time_DMA; - unsigned short streamimg_access_latency_DMA_PIO; - unsigned short streaming_performance_granularity[2]; - unsigned short lba48sectors[4]; - unsigned short streaming_transfer_time_PIO; - unsigned short reserved4; - unsigned short physical_logical_sector_size; - unsigned short inter_seek_delay; - unsigned short world_wide_name[4]; - unsigned short reserved5[4]; - unsigned short reserved6; - unsigned short words_per_logical_sector[2]; - unsigned short cmd_feature_supported; - unsigned short cmd_feature_supported_enabled; - unsigned short reserved7[6]; - unsigned short obsolete7; - unsigned short security_status; - unsigned short vendor_specific[31]; - unsigned short CFA_power_mode; - unsigned short reserved8[7]; - unsigned short dev_from_factor; - unsigned short reserved9[7]; - unsigned short current_media_serial_number[30]; - unsigned short SCT_cmd_transport; - unsigned short reserved10[2]; - unsigned short alignment_logical_blocks_within_a_physical_block; - unsigned short write_read_verify_sector_count_mode_3[2]; - unsigned short write_read_verify_sector_count_mode_2[2]; - unsigned short NV_cache_capabilities; - unsigned short NV_cache_size[2]; - unsigned short nominal_media_rotation_rate; - unsigned short reserved11; - unsigned short NV_cache_options; - unsigned short write_read_verify_feature_set_current_mode; - unsigned short reserved12; - unsigned short transport_major_version_number; - unsigned short transport_minor_version_number; - unsigned short reserved13[10]; - unsigned short min_blocks_per_cmd; - unsigned short max_blocks_per_cmd; - unsigned short reserved14[19]; - unsigned short integrity_word; -} __attribute__((packed)); - -struct ide_channel { - uint8_t channel_num; - unsigned short base; - char irq_num; - struct _device_extension_s *device; - char selected_drive; - uint32_t bmr; -}; - -typedef struct _device_extension_s { - char flag; - char drive_num; - char type; - struct pci_device *device; - struct ide_channel *channel; - struct ide_identify_info *info; - int int_flag; - unsigned short capabilities; - unsigned short signature; - unsigned int command_sets; - unsigned int size; - wait_queue_manager_t *wqm; - struct physicalRegionDescriptor *PRD; - int index_r, index_w; -} device_extension_t; - -static status_t ide_enter(driver_t *drv_obj); -static status_t ide_exit(driver_t *drv_obj); -status_t ide_read( - struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); -status_t ide_write( - struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); -void ide0_handler(device_t *devobj, int irq); -void ide1_handler(device_t *devobj, int irq); -void ide_reset_driver(struct ide_channel *channel); -void ide_select_device( - device_extension_t *devext, char mode, unsigned char head); -int ide_pulling(struct ide_channel *channel, unsigned int advanced_check); -int ide_wait(device_extension_t *devext); -void ide_select_addressing_mode( - device_extension_t *devext, unsigned int lba, unsigned char *mode, - unsigned char *head, unsigned char *data); -void ide_select_sector( - device_extension_t *devext, unsigned char mode, unsigned char *lba, - unsigned int count); -void ide_select_cmd(unsigned char rw, unsigned char mode, unsigned char *cmd); -int AtaTypeTransfer( - device_extension_t *devext, unsigned char rw, unsigned int lba, - unsigned int count, void *buf); -int PioDataTransfer( - device_extension_t *devext, unsigned char rw, unsigned char mode, - unsigned char *buf, unsigned short count); - -uint8_t disk_count; -struct ide_channel channels[2]; - -driver_func_t ide_driver = { - .driver_enter = ide_enter, - .driver_exit = ide_exit, - .driver_open = NULL, - .driver_close = NULL, - .driver_read = ide_read, - .driver_write = ide_write, - .driver_devctl = NULL, -}; - -#define IDE_CLASSCODE 0x01 -#define IDE_SUBCLASS 0x01 - -#define DRV_NAME "General HardDisk Driver(IDE)" -#define DEV_NAME "hd" - -int ide_read_identity_info( - device_extension_t *devext, struct ide_channel *channel) { - devext->info = kmalloc(sizeof(struct ide_identify_info)); - if (devext->info == NULL) { - printk("kmalloc for ide device info falied!\n"); - return -1; - } - - ide_reset_driver(devext->channel); - ide_select_device(devext, 0, 0); - - // while (!(io_in8(ATA_REG_STATUS(channel)) & ATA_STATUS_READY)) - // __asm__("nop\n\t"); - IDE_SEND_CMD(channel, ATA_CMD_IDENTIFY); // 获取硬盘识别信息 - - ide_wait(devext); - uint32_t status = io_in8(ATA_REG_STATUS(channel)); - printk("[IDE]Channel%d: Status %#02X ", channel->channel_num, status); - status = io_in8(IDE_BM_REG_STATUS(channel)); - printk("%#02X ", status); - char err = ide_pulling(channel, 1); - if (err) { - printk("error! %d\n", err); - return -1; - } - printk("\n"); - io_stream_in16( - ATA_REG_DATA(devext->channel), (unsigned int)devext->info, - sizeof(struct ide_identify_info)); - return 0; -} - -static status_t ide_enter(driver_t *drv_obj) { - struct ide_channel *channel; - int i = 0, j = 0; - device_t *devobj; - device_extension_t *devext; - - // struct pci_device *device = pci_get_device_ByClass(IDE_CLASSCODE, - // IDE_SUBCLASS); if (device == NULL) { return NODEV; } - - // // 使用兼容模式(如支持) - // if (device->prog_if & 0x01) { - // if (device->prog_if & 0x02) { - // pci_write8(device->bus, device->dev, device->function, - // PCI_REG_PROGIF, device->prog_if | 0x01); device->prog_if = - // pci_read8(device->bus, device->dev, device->function, PCI_REG_PROGIF); } - // else { return UNSUPPORT; - // } - // } - // if (device->prog_if & 0x04) { - // if (device->prog_if & 0x08) { - // pci_write8(device->bus, device->dev, device->function, - // PCI_REG_PROGIF, device->prog_if | 0x04); device->prog_if = - // pci_read8(device->bus, device->dev, device->function, PCI_REG_PROGIF); } - // else { return UNSUPPORT; - // } - // } -#ifdef IDE_DMA_MODE - if (!(device->prog_if & 0x80)) // 是否支持DMA - { - return UNSUPPORT; - } -#endif - - channels[0].base = ATA_PRIMARY_PORT; - channels[0].channel_num = 0; - channels[0].irq_num = IDE0_IRQ; - channels[1].base = ATA_SECONDARY_PORT; - channels[1].channel_num = 1; - channels[1].irq_num = IDE1_IRQ; - channels[0].selected_drive = channels[1].selected_drive = 0; - // channels[0].bmr = - // device->bar[4].base_addr; channels[1].bmr - // = channels[0].bmr; - - // pci_enable_bus_mastering(device); - // pci_enable_io_space(device); - - while (i < IDE_MAX_CHANNEL_NUM) { - channel = &channels[i]; - - while (j < IDE_MAX_DEV_PER_CNL) { - char devname[3] = {0}; - sprintf(devname, "%s%d", DEV_NAME, i * 2 + j); - device_create( - drv_obj, sizeof(device_extension_t), devname, DEV_STORAGE, - &devobj); - devext = devobj->device_extension; - if (devext == NULL) { - device_delete(devobj); - goto next; - } - channel->device = devext; - - if (i == 0) { - device_register_irq(devobj, IDE0_IRQ, ide0_handler); - } else if (i == 1) { - device_register_irq(devobj, IDE1_IRQ, ide1_handler); - } - - // devext->device = device; - devext->channel = channel; - devext->drive_num = j; - devext->type = IDE_ATA; - devext->int_flag = 0; - - int ret = ide_read_identity_info(devext, channel); - if (ret != 0) { - device_delete(devobj); - goto next; - } - - devext->wqm = create_wait_queue(); - wait_queue_init(devext->wqm); - - devext->PRD = kmalloc(sizeof(struct physicalRegionDescriptor) * 64); - io_out32( - IDE_BM_REG_PRDT_ADDR(channel), vir2phy((uint32_t)devext->PRD)); - io_out8(IDE_BM_REG_STATUS(channel), 1 << (j + 5)); - - devext->command_sets = - (int)((devext->info->cmd_set1 << 16) + devext->info->cmd_set0); - - if (devext->command_sets & (1 << 26)) { - devext->size = - ((unsigned int)devext->info->lba48sectors[1] << 16) + - (unsigned int)devext->info->lba48sectors[0]; - } else { - devext->size = - ((unsigned int)devext->info->lba28sectors[1] << 16) + - (unsigned int)devext->info->lba28sectors[0]; - } - devext->size /= 2; - - devext->capabilities = devext->info->capabilities0; - devext->signature = devext->info->general_config; - devext->flag = 1; - next: - j++; - } - j = 0; - i++; - } - return SUCCUESS; -} - -static status_t ide_exit(driver_t *drv_obj) { - device_t *devobj, *next; - device_extension_t *devext; - // device_extension_t *ext; - list_for_each_owner_safe (devobj, next, &drv_obj->device_list, list) { - devext = devobj->device_extension; - kfree(devext->info); - device_delete(devobj); - } - string_del(&drv_obj->name); - return SUCCUESS; -} - -status_t ide_read( - struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size) { - device_extension_t *devext = dev->device_extension; - wait_queue_add(devext->wqm, 0); - if (devext->wqm->list_head.next->next != &devext->wqm->list_head) { - thread_block(TASK_BLOCKED); - } - int length = DIV_ROUND_UP(size, SECTOR_SIZE); - char *tmp_buffer = kmalloc(length * SECTOR_SIZE); - AtaTypeTransfer(devext, IDE_READ, offset, length, tmp_buffer); - memcpy(buf, tmp_buffer, size); - kfree(tmp_buffer); - wait_queue_wakeup(devext->wqm); - return SUCCUESS; -} - -status_t ide_write( - struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size) { - device_extension_t *devext = dev->device_extension; - wait_queue_add(devext->wqm, 0); - if (devext->wqm->list_head.next->next != &devext->wqm->list_head) { - thread_block(TASK_BLOCKED); - } - int length = DIV_ROUND_UP(size, SECTOR_SIZE); - uint8_t *tmp_buffer; - if (size % SECTOR_SIZE == 0) { - tmp_buffer = (uint8_t *)kmalloc(length * SECTOR_SIZE); - AtaTypeTransfer(devext, IDE_READ, offset + length - 1, 1, tmp_buffer); - memcpy(tmp_buffer, buf, size); - } else { - tmp_buffer = buf; - AtaTypeTransfer(devext, IDE_READ, offset, length, tmp_buffer); - } - AtaTypeTransfer(devext, IDE_WRITE, offset, length, tmp_buffer); - wait_queue_wakeup(devext->wqm); - return SUCCUESS; -} - -void ide_write_sector(device_extension_t *devext, uint32_t lba, char *buf) { - AtaTypeTransfer(devext, IDE_WRITE, lba, 1, buf); -} - -void ide0_handler(device_t *devobj, int irq) { -} - -void ide1_handler(device_t *devobj, int irq) { -} - -void ide_reset_driver(struct ide_channel *channel) { - char ctrl = io_in8(ATA_REG_CTL(channel)); - io_out8(ATA_REG_CTL(channel), ctrl | (1 << 2)); - - // 等待重置 - int i; - for (i = 0; i < 50; i++) { - io_in8(ATA_REG_ALT_STATUS(channel)); - } - io_out8(ATA_REG_CTL(channel), ctrl); -} - -void ide_select_device( - device_extension_t *devext, char mode, unsigned char head) { - io_out8( - ATA_REG_DEVICE(devext->channel), - (0xa0 | 0x40 | devext->drive_num << 4 | head)); - devext->channel->selected_drive = devext->drive_num; -} - -int ide_pulling(struct ide_channel *channel, unsigned int advanced_check) { - int i; - for (i = 0; i < 4; i++) { - io_in8(ATA_REG_ALT_STATUS(channel)); - } - i = 10000; - while ((io_in8(ATA_REG_STATUS(channel)) & ATA_STATUS_BUSY) && i--) - ; - - if (advanced_check) { - unsigned char state = io_in8(ATA_REG_STATUS(channel)); - - if (state & ATA_STATUS_ERR) { return 2; } - - if (state & ATA_STATUS_DF) { return 1; } - - if ((state & ATA_STATUS_DRQ) == 0) { return 3; } - } - - return 0; -} - -int ide_wait(device_extension_t *devext) { - struct ide_channel *channel = devext->channel; - while (io_in8(ATA_REG_STATUS(channel)) & ATA_STATUS_BUSY) - ; - return 0; -} - -void ide_select_addressing_mode( - device_extension_t *devext, unsigned int lba, unsigned char *mode, - unsigned char *head, unsigned char *data) { - unsigned short cyl; - unsigned char sector; - if (lba >= 0x10000000 && devext->capabilities & 0x200) { - *mode = 2; - data[0] = lba & 0xff; - data[1] = (lba >> 8) & 0xff; - data[2] = (lba >> 16) & 0xff; - data[3] = (lba >> 24) & 0xff; - data[4] = 0; - data[5] = 0; - *head = 0; - } else if (devext->capabilities & 0x200) { - *mode = 1; - data[0] = lba & 0xff; - data[1] = (lba >> 8) & 0xff; - data[2] = (lba >> 16) & 0xff; - data[3] = 0; - data[4] = 0; - data[5] = 0; - *head = (lba >> 24) & 0x0f; - } else { - *mode = 0; - sector = (lba % 63) + 1; - cyl = (lba + 1 - sector) / (16 * 63); - data[0] = sector; - data[1] = (cyl >> 0) & 0xFF; - data[2] = (cyl >> 8) & 0xFF; - data[3] = 0; - data[4] = 0; - data[5] = 0; - *head = (lba + 1 - sector) % (16 * 63) / (63); - } -} - -void ide_select_sector( - device_extension_t *devext, unsigned char mode, unsigned char *lba, - unsigned int count) { - struct ide_channel *channel = devext->channel; - - /* 如果是LBA48就要写入24高端字节 */ - if (mode == 2) { - io_out8(ATA_REG_FEATURE(channel), 0); // PIO mode. - - /* 写入要读写的扇区数*/ - io_out8(ATA_REG_SECTOR_CNT(channel), 0); - - /* 写入lba地址24~47位(即扇区号) */ - io_out8(ATA_REG_SECTOR_LOW(channel), lba[3]); - io_out8(ATA_REG_SECTOR_MID(channel), lba[4]); - io_out8(ATA_REG_SECTOR_HIGH(channel), lba[5]); - } - - io_out8(ATA_REG_FEATURE(channel), 0); // PIO mode. - - /* 写入要读写的扇区数*/ - io_out8(ATA_REG_SECTOR_CNT(channel), count); - - /* 写入lba地址0~23位(即扇区号) */ - io_out8(ATA_REG_SECTOR_LOW(channel), lba[0]); - io_out8(ATA_REG_SECTOR_MID(channel), lba[1]); - io_out8(ATA_REG_SECTOR_HIGH(channel), lba[2]); -} - -void ide_select_cmd(unsigned char rw, unsigned char mode, unsigned char *cmd) { -#ifdef IDE_DMA_MODE - if (mode == 0 && rw == IDE_READ) *cmd = ATA_CMD_READ_DMA; - if (mode == 1 && rw == IDE_READ) *cmd = ATA_CMD_READ_DMA; - if (mode == 2 && rw == IDE_READ) *cmd = ATA_CMD_READ_DMA_EXT; - if (mode == 0 && rw == IDE_WRITE) *cmd = ATA_CMD_WRITE_DMA; - if (mode == 1 && rw == IDE_WRITE) *cmd = ATA_CMD_WRITE_DMA; - if (mode == 2 && rw == IDE_WRITE) *cmd = ATA_CMD_WRITE_DMA_EXT; -#else - if (mode == 0 && rw == IDE_READ) *cmd = ATA_CMD_READ_PIO; - if (mode == 1 && rw == IDE_READ) *cmd = ATA_CMD_READ_PIO; - if (mode == 2 && rw == IDE_READ) *cmd = ATA_CMD_READ_PIO_EXT; - if (mode == 0 && rw == IDE_WRITE) *cmd = ATA_CMD_WRITE_PIO; - if (mode == 1 && rw == IDE_WRITE) *cmd = ATA_CMD_WRITE_PIO; - if (mode == 2 && rw == IDE_WRITE) *cmd = ATA_CMD_WRITE_PIO_EXT; -#endif -} - -int PioDataTransfer( - device_extension_t *devext, unsigned char rw, unsigned char mode, - unsigned char *buf, unsigned short count) { - short i; - unsigned char error; - if (rw == IDE_READ) { - for (i = 0; i < count; i++) { - /* 醒来后开始执行下面代码*/ - if ((error = ide_wait(devext))) { // 若失败 - /* 重置磁盘驱动并返回 */ - ide_reset_driver(devext->channel); - return error; - } - io_stream_in16( - ATA_REG_DATA(devext->channel), (unsigned int)buf, 256); - buf += SECTOR_SIZE; - } - } else { - for (i = 0; i < count; i++) { - /* 等待硬盘控制器请求数据 */ - if ((error = ide_wait(devext))) { // 若失败 - /* 重置磁盘驱动并返回 */ - ide_reset_driver(devext->channel); - return error; - } - /* 把数据写入端口,完成1个扇区后会产生一次中断 */ - io_stream_out16( - ATA_REG_DATA(devext->channel), (unsigned int)buf, 256); - buf += SECTOR_SIZE; - // printk("write success! "); - } - /* 刷新写缓冲区 */ - io_out8( - ATA_REG_CMD(devext->channel), - mode > 1 ? ATA_CMD_CACHE_FLUSH_EXT : ATA_CMD_CACHE_FLUSH); - ide_pulling(devext->channel, 0); - } - return 0; -} - -int AtaTypeTransfer( - device_extension_t *devext, unsigned char rw, unsigned int lba, - unsigned int count, void *buf) { - - unsigned char mode; /* 0: CHS, 1:LBA28, 2: LBA48 */ - unsigned char dma; /* 0: No DMA, 1: DMA */ - unsigned char cmd; - unsigned char *_buf = (unsigned char *)buf; - - unsigned char lbaIO[6]; /* 由于最大是48位,所以这里数组的长度为6 */ - - struct ide_channel *channel = devext->channel; - - unsigned char head, err; - - /* 要去操作的扇区数 */ - unsigned int todo; - /* 已经完成的扇区数 */ - unsigned int done = 0; - - while (done < count) { - /* 获取要去操作的扇区数 - 由于一次最大只能操作256个扇区,这里用256作为分界 - */ - if ((done + 256) <= count) { - todo = 256; - } else { - todo = count - done; - } - - /* 选择传输模式(PIO或DMA) */ -#ifdef IDE_DMA_MODE - int size; - dma = 1; // 默认使用DMA模式 - i = 0; - while (i < 64 && todo > 0) { - size = (todo * SECTOR_SIZE) % 65536; - devext->PRD[i].base_addr = vir2phy((uint32_t)_buf); - devext->PRD[i].count = size; - _buf += size; - todo -= size / SECTOR_SIZE; - done += size / SECTOR_SIZE; - i++; - } - io_out8(IDE_BM_REG_CMD(channel), 0); // 停止传输 - if (rw == IDE_READ) { - io_out8(IDE_BM_REG_CMD(channel), 0x08); // 读取模式 - } else { - io_out8(IDE_BM_REG_CMD(channel), 0x00); // 写入模式 - } - uint32_t status = io_in8(IDE_BM_REG_STATUS(channel)); - io_out8(IDE_BM_REG_STATUS(channel), status | 0x06); -#else - dma = 0; -#endif - - /* 选择寻址模式 */ - // (I) Select one from LBA28, LBA48 or CHS; - ide_select_addressing_mode(devext, lba + done, &mode, &head, lbaIO); - - /* 等待驱动不繁忙 */ - // (III) Wait if the drive is busy; - while (io_in8(ATA_REG_STATUS(channel)) & ATA_STATUS_BUSY) - ; - /* 从控制器中选择设备 */ - ide_select_device(devext, mode, head); - - /* 填写参数,扇区和扇区数 */ - ide_select_sector(devext, mode, lbaIO, count); - - /* 等待磁盘控制器处于准备状态 */ - while (!(io_in8(ATA_REG_STATUS(channel)) & ATA_STATUS_READY)) - ; - - /* 选择并发送命令 */ - ide_select_cmd(rw, mode, &cmd); - - /* 等待磁盘控制器处于准备状态 */ - while (!(io_in8(ATA_REG_STATUS(channel)) & ATA_STATUS_READY)) - ; - - /* 发送命令 */ - IDE_SEND_CMD(channel, cmd); - - /* 根据不同的模式传输数据 */ - if (dma) { /* DMA模式 */ - int tmp = io_in8(IDE_BM_REG_CMD(channel)); - io_out8(IDE_BM_REG_CMD(channel), tmp | 0x01); - while (!(io_in8(IDE_BM_REG_STATUS(channel)) & 0x04)) - ; - io_out8(IDE_BM_REG_STATUS(channel), 0x04); - tmp = io_in8(IDE_BM_REG_STATUS(channel)); - io_out8(IDE_BM_REG_CMD(channel), tmp & 0xfe); - } else { - /* PIO模式数据传输 */ - if ((err = PioDataTransfer(devext, rw, mode, _buf, todo))) { - return err; - } - _buf += todo * SECTOR_SIZE; - done += todo; - } - } - - return 0; -} - -static __init void ide_driver_entry(void) { - if (driver_create(ide_driver, DRV_NAME) < 0) { - printk(COLOR_RED "[driver] %s driver create failed!\n", __func__); - } -} - -driver_initcall(ide_driver_entry); diff --git a/src/arch/x86/drivers/video.c b/src/arch/x86/drivers/video.c deleted file mode 100644 index e199d0c..0000000 --- a/src/arch/x86/drivers/video.c +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @file video.c - * @author Ryan Wang (ryan1202@foxmail.com) - * @brief - * @version 0.6 - * @date 2020-10 - */ -#include -#include -#include -#include -#include - -struct VideoInfo video_info; - -/** - * VIDEO_INFO_ADDR处存着loader保存的显示模式信息 - * VIDEO_INFO_ADDR+0 X分辨率 - * VIDEO_INFO_ADDR+2 Y分辨率 - * VIDEO_INFO_ADDR+4 颜色位数 - * VIDEO_INFO_ADDR+6 显存物理地址 - * VIDEO_INFO_ADDR+10 显示模式的INFO_BLOCK - * - * 2024.11.25: VIDEO_INFO_ADDR已废弃,直接在平台初始化阶段赋值video_info - */ - -#define SEG_ADDR2LINEAR_ADDR(addr) \ - ((unsigned int *)(((unsigned int)(addr) >> 12) & 0xffff0) + \ - ((unsigned int)(addr) & 0xffff)) - -void init_video() { - // 因为VRAM地址在启用分页后发生了变化,所以要重新设置 - video_info.vram = (uint8_t *)VRAM_VIR_ADDR; - - printk( - "Display mode: %d*%d %dbit \n", video_info.width, video_info.height, - video_info.BitsPerPixel); - - video_info.vbe_mode_info->OemStringPtr = - SEG_ADDR2LINEAR_ADDR(video_info.vbe_mode_info->OemStringPtr); - video_info.vbe_mode_info->VideoModePtr = - SEG_ADDR2LINEAR_ADDR(video_info.vbe_mode_info->VideoModePtr); - video_info.vbe_mode_info->OemVendorNamePtr = - SEG_ADDR2LINEAR_ADDR(video_info.vbe_mode_info->OemVendorNamePtr); - video_info.vbe_mode_info->OemProduceRevPtr = - SEG_ADDR2LINEAR_ADDR(video_info.vbe_mode_info->OemProduceRevPtr); - video_info.vbe_mode_info->OemProductNamePtr = - SEG_ADDR2LINEAR_ADDR(video_info.vbe_mode_info->OemProductNamePtr); - - // 如果是256色模式则设置调色板 - if (video_info.BitsPerPixel == 8) { - unsigned char table[216 * 3], *p; - int i, j, k, eflags; - for (i = 0; i < 6; i++) { - for (j = 0; j < 6; j++) { - for (k = 0; k < 6; k++) { - table[(k + j * 6 + i * 36) * 3 + 0] = k * 51; - table[(k + j * 6 + i * 36) * 3 + 1] = j * 51; - table[(k + j * 6 + i * 36) * 3 + 2] = i * 51; - } - } - } - eflags = io_load_eflags(); - io_cli(); - io_out8(0x3c8, 0); - p = table; - for (i = 0; i < 216; i++) { - io_out8(0x3c9, p[0] / 4); - io_out8(0x3c9, p[1] / 4); - io_out8(0x3c9, p[2] / 4); - p += 3; - } - io_store_eflags(eflags); - } -} - -/** - * @brief 显示VBE相关信息 - * - */ -void show_vbeinfo() { - int i; - - printk("VBE Version:%x\n", video_info.vbe_mode_info->VbeVersion); - printk("OEMString:%s\n", video_info.vbe_mode_info->OemStringPtr); - - printk("VBE Capabilities:\n"); - printk( - " %s\n", - (video_info.vbe_mode_info->Capabilities & 0x01 - ? "DAC width is switchable to 8 bits per primary color" - : "DAC is fixed width, with 6 bits per primary color")); - printk( - " %s\n", (video_info.vbe_mode_info->Capabilities & 0x02 - ? "Controller is not VGA compatible" - : "Controller is VGA compatible")); - printk( - " %s\n", - (video_info.vbe_mode_info->Capabilities & 0x04 - ? "When programming large blocks of information to the RAMDAC" - : "Normal RAMDAC operation")); - printk( - " %s\n", - (video_info.vbe_mode_info->Capabilities & 0x08 - ? "Hardware stereoscopic signaling supported by controller" - : "No hardware stereoscopic signaling support")); - printk( - " %s\n", (video_info.vbe_mode_info->Capabilities & 0x10 - ? "Stereo signaling supported via VESA EVC" - : "Stereo signaling supported via external VESA " - "stereo connector")); - - printk("VideoMode:\n"); - for (i = 0; - ((unsigned short *)video_info.vbe_mode_info->VideoModePtr)[i] >= 0x100; - i++) { - printk( - "%x ", - ((unsigned short *)video_info.vbe_mode_info->VideoModePtr)[i]); - } - printk("\n"); - - printk("VBE totalMemory:%dKB\n", video_info.vbe_mode_info->TotalMemory); - printk("OEM SoftwareRev:%#x\n", video_info.vbe_mode_info->OemSoftwareRev); - printk("OEM VendorName:%s\n", video_info.vbe_mode_info->OemVendorNamePtr); - printk("OEM ProductName:%s\n", video_info.vbe_mode_info->OemProductNamePtr); - printk("OEM ProduceRev:%s\n", video_info.vbe_mode_info->OemProduceRevPtr); -} \ No newline at end of file diff --git a/src/include/dyn_array.h b/src/include/dyn_array.h index 00ef258..caa071b 100644 --- a/src/include/dyn_array.h +++ b/src/include/dyn_array.h @@ -2,6 +2,7 @@ #define _DYN_ARRAY_H #include "stdint.h" +#include "types.h" typedef struct DynArray { struct DynArrayBlock *first_block; @@ -22,6 +23,13 @@ DynArray *dyn_array_new(size_t element_size, size_t block_size); struct DynArrayBlock *dyn_array_find_block(DynArray *dyn_array, size_t idx); void *dyn_array_new_item_addr(DynArray *dyn_array); +void *dyn_array_next_ptr( + DynArray *dyn_array, struct DynArrayBlock **block, int *block_index, + int *block_offset); +bool dyn_array_is_end( + DynArray *dyn_array, struct DynArrayBlock *block, int block_index, + int block_offset); + #define dyn_array_get(arr, type, idx) \ (type)({ \ int block_index = (idx) / (arr)->block_size; \ @@ -47,4 +55,13 @@ void *dyn_array_new_item_addr(DynArray *dyn_array); (arr)->size++; \ } +#define dyn_array_foreach(arr, type, var) \ + struct DynArrayBlock *_block = (arr)->first_block; \ + int _block_index = 0; \ + int _block_offset = 1; \ + for (var = *((type *)_block->data); \ + !dyn_array_is_end(arr, _block, _block_index, _block_offset); \ + var = *((type *)dyn_array_next_ptr( \ + arr, &_block, &_block_index, &_block_offset))) + #endif \ No newline at end of file diff --git a/src/include/objects/object.h b/src/include/objects/object.h index 41c0d6a..ec29655 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -2,7 +2,6 @@ #define _OBJECT_H #include "dyn_array.h" -#include "result.h" #include "stdint.h" #include "string.h" @@ -10,6 +9,8 @@ typedef enum ObjectResult { OBJECT_OK, OBJECT_ERROR_MEMORY, OBJECT_ERROR_INVALID_OPERATION, + OBJECT_ERROR_CANNOT_FIND, + OBJECT_ERROR_ILLEGAL_ARGUMENT, } ObjectResult; #define OBJECT_DIR_SIZE_SMALL 8 @@ -63,6 +64,10 @@ extern Object device_object; ObjectResult init_object_tree(); ObjectResult add_object(Object *parent, Object *child); ObjectResult init_object_directory(Object *object, size_t block_size); +ObjectResult open_oringinal_object_by_ascii_path( + char *path, Object **out_object); +// 通过ASCII路径打开对象,对于符号链接会自动解析 +ObjectResult open_object_by_ascii_path(char *path, Object **object); Object *create_object(Object *parent, string_t *name, ObjectType type); Object *create_object_directory(Object *parent, string_t *name); void show_object_tree(); diff --git a/src/include/string.h b/src/include/string.h index d341cdf..63bcac1 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -12,11 +12,8 @@ #include "stdint.h" #define STRING_MAX_LEN 256 -#define STRING_INIT(str) \ - { \ - .text = str "\0", .length = sizeof(str) + 1, \ - .max_length = sizeof(str) + 1 \ - } +#define STRING_INIT(str) \ + { .text = str "\0", .length = sizeof(str), .max_length = sizeof(str) } typedef struct _string { unsigned int length; diff --git a/src/kernel/main.c b/src/kernel/main.c index 6a569a5..52b5aca 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -64,7 +64,6 @@ int main() { init_task(); task_idle = thread_start("Idle", 1, idle, 0); - // init_pci(); io_sti(); printk("Memory Size:%dM\n", get_memory_size()); // init_vfs(); @@ -73,9 +72,12 @@ int main() { thread_start( "Kernel Periodic Tasks", THREAD_DEFAULT_PRIO, periodic_task, NULL); - // uint8_t buf1[512], buf2[512]; - // Device *device = - // list_first_owner(&storage_device_manager.device_lh, Device, dm_list); + // Object *object; + // ObjectResult result = + // open_object_by_ascii_path("\\Device\\Storage0", &object); + // if (result != OBJECT_OK) { printk("Open Storage0 Error!\n"); } + // uint8_t buf1[512], buf2[512]; + // Device *device = object->value.device; // StorageRequest request1 = { // .storage_device = device->device_manager_extension, // .rw = 0, @@ -100,7 +102,7 @@ int main() { // print_hex(buf1, 512); // print_hex(buf2, 512); - show_object_tree(); + // show_object_tree(); // storage_add_request(device->device_manager_extension, &request); // init_fs(); diff --git a/src/lib/dyn_array.c b/src/lib/dyn_array.c index f665099..02defb3 100644 --- a/src/lib/dyn_array.c +++ b/src/lib/dyn_array.c @@ -62,4 +62,30 @@ void *dyn_array_new_item_addr(DynArray *dyn_array) { return block->data + (dyn_array->size % dyn_array->block_size) * dyn_array->element_size; +} + +// 以下两个函数都是为foreach服务的 + +void *dyn_array_next_ptr( + DynArray *dyn_array, struct DynArrayBlock **block, int *block_index, + int *block_offset) { + + struct DynArrayBlock *current_block = *block; + int offset = *block_offset; + + if (offset + 1 < dyn_array->block_size) { + (*block_offset)++; + } else { + (*block_index)++; + *block_offset = 0; + *block = (*block)->next; + } + return (void *)current_block->data + offset * dyn_array->element_size; +} + +bool dyn_array_is_end( + DynArray *dyn_array, struct DynArrayBlock *block, int block_index, + int block_offset) { + return block == NULL && + block_offset == dyn_array->size % dyn_array->block_size; } \ No newline at end of file diff --git a/src/lib/string.c b/src/lib/string.c index 9373a66..5b55a24 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -64,9 +64,10 @@ int string_new_with_number( x /= 10; } while (x > 0); - int ret = string_new(string, text, text_len + len); + int ret = string_new(string, text, text_len + len + 1); if (ret != 0) { return ret; } - string->length = text_len + len; + string->length = text_len + len + 1; + string->text[string->length - 1] = '\0'; x = number; for (int i = text_len + len - 1; i >= text_len; i--) { diff --git a/src/objects/objects.c b/src/objects/objects.c index a11425c..d509d38 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -59,6 +59,60 @@ ObjectResult init_object_tree() { return OBJECT_OK; } +ObjectResult find_object_by_name( + Object *parent, Object **out_child, string_t *name) { + Object *child; + dyn_array_foreach(parent->value.directory.children, Object *, child) { + if (child->name.length == name->length && + strncmp(child->name.text, name->text, name->length) == 0) { + *out_child = child; + return OBJECT_OK; + } + } + return OBJECT_ERROR_CANNOT_FIND; +} + +ObjectResult open_oringinal_object_by_ascii_path( + char *path, Object **out_object) { + // 必须从根对象开始 + if (path[0] != '\\') { return OBJECT_ERROR_ILLEGAL_ARGUMENT; } + path++; + + char ascii_name[256]; + string_t name = {0, 0, ascii_name}; + Object *object = &root_object; + while (*path) { + int i = 0; + while (*path != '\0' && *path != '\\') { + ascii_name[i] = *path; + path++; + i++; + } + if (*path == '\\') { path++; } + ascii_name[i] = '\0'; + name.length = i + 1; + name.max_length = i + 1; + + Object *child; + ObjectResult result = find_object_by_name(object, &child, &name); + if (result != OBJECT_OK) { return result; } + + object = child; + } + *out_object = object; + return OBJECT_OK; +} + +ObjectResult open_object_by_ascii_path(char *path, Object **object) { + ObjectResult result = open_oringinal_object_by_ascii_path(path, object); + if (result == OBJECT_OK) { + while ((*object)->type == OBJECT_TYPE_SYM_LINK) { + *object = (*object)->value.sym_link; + } + } + return result; +} + ObjectResult add_object(Object *parent, Object *child) { if (parent->type != OBJECT_TYPE_DIRECTORY) { return OBJECT_ERROR_INVALID_OPERATION; From 372d733313dea38ae1766df70385d4326c65268b Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 12 Feb 2025 23:15:43 +0800 Subject: [PATCH 019/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E7=9A=84=E6=95=B0=E6=8D=AE=E4=BC=A0=E8=BE=93=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/disk/ata/ide.c | 7 +-- src/driver/Makefile | 2 +- src/driver/storage_dm.c | 17 +++--- src/driver/storage_io.c | 50 ++++++++++++++++++ src/driver/storage_io_queue.c | 2 +- src/driver/transfer.c | 1 - src/include/driver/storage_io.h | 13 +++++ src/include/driver/transfer.h | 48 ----------------- src/include/kernel/device.h | 3 +- src/include/objects/object.h | 3 ++ src/include/objects/transfer.h | 80 +++++++++++++++++++++++++++++ src/kernel/main.c | 35 ++++--------- 12 files changed, 169 insertions(+), 92 deletions(-) create mode 100644 src/driver/storage_io.c delete mode 100644 src/driver/transfer.c create mode 100644 src/include/driver/storage_io.h delete mode 100644 src/include/driver/transfer.h create mode 100644 src/include/objects/transfer.h diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index 6547214..fe683b9 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -11,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -53,14 +53,9 @@ DeviceDriver ide_device_driver = { .state = DRIVER_STATE_UNREGISTERED, .ops = &ide_device_driver_ops, }; -Transfer ide_transfer = { - .type_in = TRANSFER_TYPE_BLOCK, - .type_out = TRANSFER_TYPE_BLOCK, -}; Device ide_device_template = { .name = STRING_INIT("IDE Harddisk"), - .transfer = &ide_transfer, .state = DEVICE_STATE_UNREGISTERED, .device_driver = &ide_device_driver, .ops = &ide_device_ops, diff --git a/src/driver/Makefile b/src/driver/Makefile index cca45aa..7896bb9 100644 --- a/src/driver/Makefile +++ b/src/driver/Makefile @@ -4,6 +4,6 @@ SRC += video_dm.c SRC += video.c SRC += bus_dm.c SRC += storage_dm.c -SRC += transfer.c SRC += storage_io_queue.c +SRC += storage_io.c SRC += timer.c \ No newline at end of file diff --git a/src/driver/storage_dm.c b/src/driver/storage_dm.c index 0b7c6c6..acca6e1 100644 --- a/src/driver/storage_dm.c +++ b/src/driver/storage_dm.c @@ -1,7 +1,6 @@ -#include "string.h" #include +#include #include -#include #include #include #include @@ -11,9 +10,12 @@ #include #include #include +#include +#include #include #include #include +#include #include extern void storage_periodic_task(void *arg); @@ -47,12 +49,6 @@ DriverResult register_storage_device( StorageDevice *storage_device) { storage_device->device = device; - if (device->transfer->type_in == TRANSFER_TYPE_BLOCK) { - device->transfer->in.block = storage_device_block_read; - } - if (device->transfer->type_out == TRANSFER_TYPE_BLOCK) { - device->transfer->out.block = storage_device_block_write; - } device->device_manager_extension = storage_device; list_init(&storage_device->io_queue_lh); @@ -62,6 +58,11 @@ DriverResult register_storage_device( register_device, device_driver, &name, device->bus, device); list_add_tail(&device->dm_list, &storage_device_manager.device_lh); + device->object->in.block = storage_transfer; + device->object->in.is_transfer_done = storage_is_transfer_done; + device->object->out.block = storage_transfer; + device->object->out.is_transfer_done = storage_is_transfer_done; + storage_device->periodic_task.func = storage_periodic_task; storage_device->periodic_task.arg = storage_device; periodic_task_add(&storage_device->periodic_task); diff --git a/src/driver/storage_io.c b/src/driver/storage_io.c new file mode 100644 index 0000000..05cdffa --- /dev/null +++ b/src/driver/storage_io.c @@ -0,0 +1,50 @@ +/** + * 默认的存储设备IO实现 + */ +#include "kernel/device.h" +#include +#include +#include +#include +#include +#include + +TransferResult storage_transfer( + Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count, void **handle) { + Device *device = object->value.device; + StorageRequest *request = kmalloc(sizeof(StorageRequest)); + + request->storage_device = device->device_manager_extension; + request->rw = (direction == TRANSFER_IN) ? 0 : 1; + request->buf = buf; + request->position = position; + request->count = count; + request->is_finished = 0; + + *handle = (void *)request; + + storage_add_request(device->device_manager_extension, request); + return TRANSFER_OK; +} + +TransferResult storage_is_transfer_done( + Object *object, void **handle, bool *done) { + if (object->type != OBJECT_TYPE_DEVICE) { + return TRANSFER_ERROR_INVALID_PARAMETER; + } + Device *device = object->value.device; + + if (device->device_driver->type != DEVICE_TYPE_STORAGE) { + return TRANSFER_ERROR_INVALID_PARAMETER; + } + StorageDevice *storage_device = device->device_manager_extension; + + StorageRequest *req = *handle; + if (req->storage_device != storage_device || done == NULL) { + return TRANSFER_ERROR_INVALID_PARAMETER; + } + *done = req->is_finished; + + return TRANSFER_OK; +} \ No newline at end of file diff --git a/src/driver/storage_io_queue.c b/src/driver/storage_io_queue.c index e87e5f2..12eefc3 100644 --- a/src/driver/storage_io_queue.c +++ b/src/driver/storage_io_queue.c @@ -1,4 +1,3 @@ -#include "types.h" #include #include #include @@ -6,6 +5,7 @@ #include #include #include +#include bool storage_try_merge_request( StorageRequest *new_request, StorageRequest *request) { diff --git a/src/driver/transfer.c b/src/driver/transfer.c deleted file mode 100644 index 5ccbe00..0000000 --- a/src/driver/transfer.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/src/include/driver/storage_io.h b/src/include/driver/storage_io.h new file mode 100644 index 0000000..555b5af --- /dev/null +++ b/src/include/driver/storage_io.h @@ -0,0 +1,13 @@ +#ifndef _STORAGE_IO_H +#define _STORAGE_IO_H + +#include +#include + +TransferResult storage_transfer( + Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count, void **handle); +TransferResult storage_is_transfer_done( + Object *object, void **handle, bool *done); + +#endif \ No newline at end of file diff --git a/src/include/driver/transfer.h b/src/include/driver/transfer.h deleted file mode 100644 index 9059299..0000000 --- a/src/include/driver/transfer.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef _TRANSFER_H -#define _TRANSFER_H - -#include "kernel/driver.h" -#include "stdint.h" - -struct Device; -typedef DriverResult (*BlockTransferIn)( - struct Device *device, uint8_t *buf, uint32_t position, size_t count); -typedef DriverResult (*BlockTransferOut)( - struct Device *device, uint8_t *buf, uint32_t position, size_t count); - -typedef DriverResult (*StreamTransferIn)( - struct Device *device, uint8_t *buf, size_t size); -typedef DriverResult (*StreamTransferOut)( - struct Device *device, uint8_t *buf, size_t size); - -typedef void (*InterruptTransferCallbackSingle)( - struct Device *device, void *private_data, size_t data); -typedef void (*InterruptTransferCallbackMultiple)( - struct Device *device, void *private_data, void *data, size_t size); -typedef DriverResult (*InterruptTransferIn)( - struct Device *device, InterruptTransferCallbackSingle callback_single, - InterruptTransferCallbackMultiple callback_multiple); - -typedef enum TransferType { - TRANSFER_TYPE_NONE, - TRANSFER_TYPE_BLOCK, - TRANSFER_TYPE_STREAM, - TRANSFER_TYPE_INTERRUPT, -} TransferType; - -typedef struct Transfer { - TransferType type_in; - union { - BlockTransferIn block; - StreamTransferIn stream; - InterruptTransferIn interrupt; - } in; - - TransferType type_out; - union { - BlockTransferOut block; - StreamTransferOut stream; - } out; -} Transfer; - -#endif \ No newline at end of file diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index db6d1ba..2a04c87 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -1,11 +1,11 @@ #ifndef _DEVICE_H #define _DEVICE_H -#include "driver/transfer.h" #include "kernel/driver.h" #include "kernel/driver_interface.h" #include "kernel/list.h" #include "objects/object.h" +#include "objects/transfer.h" #include "stdint.h" #include "string.h" #include "types.h" @@ -76,7 +76,6 @@ typedef struct Device { Object *object; DeviceIrq *irq; - Transfer *transfer; DeviceOps *ops; uint32_t max_child_device; diff --git a/src/include/objects/object.h b/src/include/objects/object.h index ec29655..8cd3b66 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -2,6 +2,7 @@ #define _OBJECT_H #include "dyn_array.h" +#include "objects/transfer.h" #include "stdint.h" #include "string.h" @@ -33,6 +34,8 @@ typedef struct Object { ObjectType type; struct Object *parent; + TransferIn in; + TransferOut out; union { uint32_t type; struct { diff --git a/src/include/objects/transfer.h b/src/include/objects/transfer.h new file mode 100644 index 0000000..0bd7616 --- /dev/null +++ b/src/include/objects/transfer.h @@ -0,0 +1,80 @@ +#ifndef _TRANSFER_H +#define _TRANSFER_H + +#include "result.h" +#include "stdint.h" +#include + +typedef enum { + TRANSFER_OK, + TRANSFER_ERROR_NOT_IMPLEMENTED, + TRANSFER_ERROR_NOT_SUPPORTED, + TRANSFER_ERROR_INVALID_PARAMETER, + TRANSFER_ERROR_NO_MEMORY, + TRANSFER_ERROR_OTHER, +} TransferResult; + +typedef enum { + TRANSFER_IN, + TRANSFER_OUT, +} TransferDirection; + +struct Object; +typedef TransferResult (*BlockTransfer)( + struct Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count, void **handle); + +typedef TransferResult (*StreamTransfer)( + struct Object *object, TransferDirection direction, uint8_t *buf, + size_t size, void **handle); + +typedef void (*InterruptTransferCallbackSingle)( + struct Object *object, void *private_data, size_t data); +typedef void (*InterruptTransferCallbackMultiple)( + struct Object *object, void *private_data, void *data, size_t size); +typedef TransferResult (*InterruptTransfer)( + struct Object *object, InterruptTransferCallbackSingle callback_single, + InterruptTransferCallbackMultiple callback_multiple); + +typedef TransferResult (*IsTransferDone)( + struct Object *object, void **handle, bool *done); + +typedef enum TransferType { + TRANSFER_TYPE_NONE, + TRANSFER_TYPE_BLOCK, + TRANSFER_TYPE_STREAM, + TRANSFER_TYPE_INTERRUPT, +} TransferType; + +typedef struct TransferIn { + TransferType type; + IsTransferDone is_transfer_done; + union { + BlockTransfer block; + StreamTransfer stream; + InterruptTransfer interrupt; + }; +} TransferIn; + +typedef struct TransferOut { + TransferType type; + IsTransferDone is_transfer_done; + union { + BlockTransfer block; + StreamTransfer stream; + }; +} TransferOut; + +#define TRANSFER_IN_BLOCK(object) ((object)->in.block) +#define TRANSFER_IN_STREAM(object) ((object)->in.stream) +#define TRANSFER_IN_INTTERRUPT(object) ((object)->in.interrupt) + +#define TRANSFER_IN_IS_DONE(object) ((object)->in.is_transfer_done) + +#define TRANSFER_OUT_BLOCK(object) ((object)->in.block) +#define TRANSFER_OUT_STREAM(object) ((object)->in.stream) +#define TRANSFER_OUT_INTTERRUPT(object) ((object)->in.interrupt) + +#define TRANSFER_OUT_IS_DONE(object) ((object)->in.is_transfer_done) + +#endif \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index 52b5aca..a725004 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -7,6 +7,7 @@ #include "driver/storage_io_queue.h" #include "kernel/list.h" #include "objects/object.h" +#include "objects/transfer.h" #include #include #include @@ -72,35 +73,19 @@ int main() { thread_start( "Kernel Periodic Tasks", THREAD_DEFAULT_PRIO, periodic_task, NULL); + // void *handle = NULL; // Object *object; // ObjectResult result = // open_object_by_ascii_path("\\Device\\Storage0", &object); // if (result != OBJECT_OK) { printk("Open Storage0 Error!\n"); } - // uint8_t buf1[512], buf2[512]; - // Device *device = object->value.device; - // StorageRequest request1 = { - // .storage_device = device->device_manager_extension, - // .rw = 0, - // .buf = buf1, - // .position = 0, - // .count = 1, - // .is_finished = 0, - // }; - // StorageRequest request2 = { - // .storage_device = device->device_manager_extension, - // .rw = 0, - // .buf = buf2, - // .position = 1, - // .count = 1, - // .is_finished = 0, - // }; - // storage_add_request(device->device_manager_extension, &request1); - // storage_add_request(device->device_manager_extension, &request2); - // while (!(request1.is_finished && request2.is_finished)) { - // schedule(); - // } - // print_hex(buf1, 512); - // print_hex(buf2, 512); + // uint8_t buf[512]; + // TRANSFER_IN_BLOCK(object)(object, TRANSFER_IN, buf, 0, 1, &handle); + + // bool is_done; + // do { + // TRANSFER_IN_IS_DONE(object)(object, &handle, &is_done); + // } while (!is_done); + // print_hex(buf, 512); // show_object_tree(); From faa3b519e7a854755c029d710858868ec6ca8bd7 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 13 Feb 2025 20:41:45 +0800 Subject: [PATCH 020/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20Partition=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E7=B1=BB=E5=9E=8B=20=E6=96=B0=E5=A2=9E=20mbr=E5=88=86?= =?UTF-8?q?=E5=8C=BA=E8=AF=86=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/disk/ata/ide.c | 24 +++--- .../x86/drivers/disk/ata/ide_controller.c | 5 +- src/arch/x86/drivers/disk/ata/include/ide.h | 2 +- src/driver/Makefile | 4 +- src/driver/bus_dm.c | 2 +- src/driver/storage/Makefile | 4 + src/driver/storage/disk/Makefile | 2 + src/driver/storage/disk/disk.c | 14 ++++ src/driver/storage/disk/mbr.c | 39 ++++++++++ src/driver/{ => storage}/storage_dm.c | 73 ++++++++----------- src/driver/{ => storage}/storage_io.c | 6 +- src/driver/{ => storage}/storage_io_queue.c | 4 +- src/driver/video_dm.c | 2 +- src/include/driver/storage/disk/disk.h | 21 ++++++ src/include/driver/storage/disk/mbr.h | 20 +++++ src/include/driver/{ => storage}/storage_dm.h | 5 ++ src/include/driver/{ => storage}/storage_io.h | 0 .../driver/{ => storage}/storage_io_queue.h | 2 +- src/include/kernel/device.h | 2 +- src/include/objects/object.h | 9 ++- src/include/objects/types.h | 2 +- src/kernel/bus_driver.c | 9 +-- src/kernel/device.c | 4 +- src/kernel/driver.c | 2 +- src/kernel/main.c | 15 ++-- src/kernel/thread.c | 6 +- src/objects/objects.c | 6 +- src/objects/types.c | 4 +- 28 files changed, 193 insertions(+), 95 deletions(-) create mode 100644 src/driver/storage/Makefile create mode 100644 src/driver/storage/disk/Makefile create mode 100644 src/driver/storage/disk/disk.c create mode 100644 src/driver/storage/disk/mbr.c rename src/driver/{ => storage}/storage_dm.c (58%) rename src/driver/{ => storage}/storage_io.c (91%) rename src/driver/{ => storage}/storage_io_queue.c (98%) create mode 100644 src/include/driver/storage/disk/disk.h create mode 100644 src/include/driver/storage/disk/mbr.h rename src/include/driver/{ => storage}/storage_dm.h (94%) rename src/include/driver/{ => storage}/storage_io.h (100%) rename src/include/driver/{ => storage}/storage_io_queue.h (95%) diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index fe683b9..51096af 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -1,7 +1,7 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -89,7 +89,7 @@ void ide_handle_interrupt(IdeChannel *channel) { BIN_DIS(data, IDE_BMCMD_START_STOP_BM)); if (request->rw == 0) { storage_solve_read_request(request); } - kfree(request->real_buf); + if (request->buf != request->real_buf) { kfree(request->real_buf); } } storage_finish_request(request); } @@ -121,7 +121,8 @@ void ide_device_probe(IdeChannel *channel) { timer_init(&channel->timer); channel->device_count = 0; - // ide_reset_drive(channel); + + Device *device[2] = {NULL, NULL}; for (i = 0; i < 2; i++) { // 1.选择设备 ide_select_device(channel, i); @@ -170,15 +171,15 @@ void ide_device_probe(IdeChannel *channel) { sizeof(AtaIdentifyInfo) / 2); // 6.注册设备 - Device *device = kmalloc_from_template(ide_device_template); - device->bus = &platform_bus; // TODO: BUS + device[i] = kmalloc_from_template(ide_device_template); + device[i]->bus = &platform_bus; // TODO: BUS StorageDevice *storage_device = kmalloc_from_template(storage_device_template); - register_storage_device(&ide_device_driver, device, storage_device); + register_storage_device(&ide_device_driver, device[i], storage_device); - IdeDevice *ide_device = device->private_data; - ide_device->device = device; + IdeDevice *ide_device = device[i]->private_data; + ide_device->device = device[i]; ide_device->channel = channel; ide_device->type = type; ide_device->info = identify; @@ -186,7 +187,6 @@ void ide_device_probe(IdeChannel *channel) { ide_device->current_request = NULL; channel->ide_devices[i] = ide_device; - init_and_start(device); channel->device_count++; } @@ -197,6 +197,10 @@ void ide_device_probe(IdeChannel *channel) { BIN_DIS(data, ATA_CONTROL_NIEN)); channel->prdt = kmalloc(sizeof(PhysicalRegionDescriptorTable)); interrupt_enable_irq(channel->irq->irq); + + for (i = 0; i < 2; i++) { + if (device[i] != NULL) { init_and_start(device[i]); } + } } } diff --git a/src/arch/x86/drivers/disk/ata/ide_controller.c b/src/arch/x86/drivers/disk/ata/ide_controller.c index 9f6f635..dea745c 100644 --- a/src/arch/x86/drivers/disk/ata/ide_controller.c +++ b/src/arch/x86/drivers/disk/ata/ide_controller.c @@ -75,9 +75,10 @@ void ide_detect_channel_mode( } DriverResult ide_controller_probe(PciDevice *pci_device) { - Device *device = kmalloc_from_template(ide_controller_device_templete); + Device *device = kmalloc_from_template(ide_controller_device_templete); + string_t name = STRING_INIT(""); register_device( - &ide_controller_device_driver, NULL, pci_device->bus, device); + &ide_controller_device_driver, name, pci_device->bus, device); IdeControllerInfo *info = device->private_data; info->pci_device = pci_device; diff --git a/src/arch/x86/drivers/disk/ata/include/ide.h b/src/arch/x86/drivers/disk/ata/include/ide.h index 1576099..a7941c7 100644 --- a/src/arch/x86/drivers/disk/ata/include/ide.h +++ b/src/arch/x86/drivers/disk/ata/include/ide.h @@ -3,7 +3,7 @@ #include "ata.h" #include "ata_driver.h" -#include "driver/storage_io_queue.h" +#include "driver/storage/storage_io_queue.h" #include "ide_controller.h" #include "kernel/device.h" #include "stdint.h" diff --git a/src/driver/Makefile b/src/driver/Makefile index 7896bb9..2899264 100644 --- a/src/driver/Makefile +++ b/src/driver/Makefile @@ -1,9 +1,7 @@ +SRC += storage/ SRC += timer_dm.c SRC += interrupt_dm.c SRC += video_dm.c SRC += video.c SRC += bus_dm.c -SRC += storage_dm.c -SRC += storage_io_queue.c -SRC += storage_io.c SRC += timer.c \ No newline at end of file diff --git a/src/driver/bus_dm.c b/src/driver/bus_dm.c index 3ac8b2d..5855eeb 100644 --- a/src/driver/bus_dm.c +++ b/src/driver/bus_dm.c @@ -34,7 +34,7 @@ DriverResult register_bus_controller_device( bus_controller_device->bus_driver = bus_driver; DRV_RESULT_DELIVER_CALL( - register_device, device_driver, &bus_controller_device->short_name, + register_device, device_driver, bus_controller_device->short_name, device->bus, device); return DRIVER_RESULT_OK; } diff --git a/src/driver/storage/Makefile b/src/driver/storage/Makefile new file mode 100644 index 0000000..3334b47 --- /dev/null +++ b/src/driver/storage/Makefile @@ -0,0 +1,4 @@ +SRC += disk/ +SRC += storage_dm.c +SRC += storage_io_queue.c +SRC += storage_io.c \ No newline at end of file diff --git a/src/driver/storage/disk/Makefile b/src/driver/storage/disk/Makefile new file mode 100644 index 0000000..36e641e --- /dev/null +++ b/src/driver/storage/disk/Makefile @@ -0,0 +1,2 @@ +SRC += mbr.c +SRC += disk.c \ No newline at end of file diff --git a/src/driver/storage/disk/disk.c b/src/driver/storage/disk/disk.c new file mode 100644 index 0000000..0f0b788 --- /dev/null +++ b/src/driver/storage/disk/disk.c @@ -0,0 +1,14 @@ +#include "driver/storage/storage_io.h" +#include +#include +#include + +TransferResult disk_transfer( + Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count, void **handle) { + Partition *partition = object->value.partition; + + return TRANSFER_IN_BLOCK(partition->storage_object)( + partition->storage_object, direction, buf, + position + partition->start_lba, count, handle); +} \ No newline at end of file diff --git a/src/driver/storage/disk/mbr.c b/src/driver/storage/disk/mbr.c new file mode 100644 index 0000000..e2eb6ab --- /dev/null +++ b/src/driver/storage/disk/mbr.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include + +#define MBR_PARTITION_ENTRY_SIZE 16 +#define MBR_PARTITION_TABLE_OFFSET 446 +#define MBR_PARTITION_COUNT 4 + +bool disk_is_mbr(StorageDevice *storage_device) { + return storage_device->superblock[510] == 0x55 && + storage_device->superblock[511] == 0xAA; +} + +void parse_mbr_partition_table(StorageDevice *storage_device) { + int partition_count = 0; + MBRPartitionEntry *partition_table = + (MBRPartitionEntry *)&storage_device + ->superblock[MBR_PARTITION_TABLE_OFFSET]; + + for (int i = 0; i < MBR_PARTITION_COUNT; i++) { + if (partition_table[i].system_id != 0) { + string_t name; + string_new_with_number(&name, "Partition", 9, partition_count); + Object *object = create_object( + storage_device->object, name, OBJECT_TYPE_PARTITION); + + Partition *partition = kmalloc(sizeof(Partition)); + partition->type = PARTITION_TYPE_MBR; + partition->start_lba = partition_table[i].starting_lba; + partition->size_lba = partition_table[i].size_in_lba; + partition->mbr = &partition_table[i]; + object->value.partition = partition; + partition_count++; + } + } +} \ No newline at end of file diff --git a/src/driver/storage_dm.c b/src/driver/storage/storage_dm.c similarity index 58% rename from src/driver/storage_dm.c rename to src/driver/storage/storage_dm.c index acca6e1..d898432 100644 --- a/src/driver/storage_dm.c +++ b/src/driver/storage/storage_dm.c @@ -1,6 +1,7 @@ -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -8,8 +9,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -18,16 +19,14 @@ #include #include -extern void storage_periodic_task(void *arg); - -DriverResult storage_device_block_read( - Device *device, uint8_t *buf, uint32_t position, size_t count); -DriverResult storage_device_block_write( - Device *device, uint8_t *buf, uint32_t position, size_t count); +extern void storage_periodic_task(void *arg); +DriverResult start_storage_device(DeviceManager *manager, Device *device); DeviceManagerOps storage_dm_ops = { - .dm_load_hook = NULL, - .dm_unload_hook = NULL, + .dm_load_hook = NULL, + .dm_unload_hook = NULL, + .start_device_hook = start_storage_device, + .stop_device_hook = NULL, }; typedef struct StorageDeviceManager { @@ -55,7 +54,7 @@ DriverResult register_storage_device( string_t name; string_new_with_number(&name, "Storage", 7, storage_dm_ext.device_count++); DRV_RESULT_DELIVER_CALL( - register_device, device_driver, &name, device->bus, device); + register_device, device_driver, name, device->bus, device); list_add_tail(&device->dm_list, &storage_device_manager.device_lh); device->object->in.block = storage_transfer; @@ -67,6 +66,8 @@ DriverResult register_storage_device( storage_device->periodic_task.arg = storage_device; periodic_task_add(&storage_device->periodic_task); + storage_device->object = create_object_directory(&device_object, name); + return DRIVER_RESULT_OK; } @@ -79,36 +80,22 @@ DriverResult unregister_storage_device( return DRIVER_RESULT_OK; } -DriverResult storage_device_block_read( - Device *device, uint8_t *buf, uint32_t position, size_t count) { - StorageDevice *storage_device = device->device_manager_extension; - - StorageRequest *request = kmalloc(sizeof(StorageRequest)); - request->rw = false; - request->buf = buf; - request->position = position; - request->count = - DIV_ROUND_UP(position + count, storage_device->block_size) - - request->position; - - storage_add_request(storage_device, request); - - return DRIVER_RESULT_OK; -} - -DriverResult storage_device_block_write( - Device *device, uint8_t *buf, uint32_t position, size_t count) { +DriverResult start_storage_device(DeviceManager *manager, Device *device) { StorageDevice *storage_device = device->device_manager_extension; - - StorageRequest *request = kmalloc(sizeof(StorageRequest)); - request->rw = true; - request->buf = buf; - request->position = position; - request->count = - DIV_ROUND_UP(position + count, storage_device->block_size) - - request->position; - - storage_add_request(storage_device, request); - + void *handle; + storage_device->superblock = kmalloc(2 * 512); + storage_transfer( + device->object, TRANSFER_IN, storage_device->superblock, 0, 2, &handle); + + bool is_done; + do { + storage_is_transfer_done(device->object, &handle, &is_done); + } while (!is_done); + + if (storage_device->type == STORAGE_DEVICE_TYPE_HARDDISK) { + if (disk_is_mbr(storage_device)) { + parse_mbr_partition_table(storage_device); + } + } return DRIVER_RESULT_OK; } diff --git a/src/driver/storage_io.c b/src/driver/storage/storage_io.c similarity index 91% rename from src/driver/storage_io.c rename to src/driver/storage/storage_io.c index 05cdffa..1a1efe4 100644 --- a/src/driver/storage_io.c +++ b/src/driver/storage/storage_io.c @@ -2,9 +2,9 @@ * 默认的存储设备IO实现 */ #include "kernel/device.h" -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/src/driver/storage_io_queue.c b/src/driver/storage/storage_io_queue.c similarity index 98% rename from src/driver/storage_io_queue.c rename to src/driver/storage/storage_io_queue.c index 12eefc3..2680ce6 100644 --- a/src/driver/storage_io_queue.c +++ b/src/driver/storage/storage_io_queue.c @@ -1,5 +1,5 @@ -#include -#include +#include +#include #include #include #include diff --git a/src/driver/video_dm.c b/src/driver/video_dm.c index cac2897..b5b7b2d 100644 --- a/src/driver/video_dm.c +++ b/src/driver/video_dm.c @@ -56,7 +56,7 @@ DriverResult register_video_device( &name, "Video", 5, video_dm_ext.video_device_count++); DRV_RESULT_DELIVER_CALL( - register_device, device_driver, &name, device_driver->bus, device); + register_device, device_driver, name, device_driver->bus, device); list_init(&video_device->video_list_lh); list_add_tail(&device->dm_list, &video_device_manager.device_lh); diff --git a/src/include/driver/storage/disk/disk.h b/src/include/driver/storage/disk/disk.h new file mode 100644 index 0000000..167ca9a --- /dev/null +++ b/src/include/driver/storage/disk/disk.h @@ -0,0 +1,21 @@ +#ifndef _DISK_H +#define _DISK_H + +#include "stdint.h" +#include + +typedef struct Partition { + enum { + PARTITION_TYPE_MBR, + PARTITION_TYPE_GPT, + } type; + union { + MBRPartitionEntry *mbr; + }; + size_t start_lba; + size_t size_lba; + + Object *storage_object; +} Partition; + +#endif \ No newline at end of file diff --git a/src/include/driver/storage/disk/mbr.h b/src/include/driver/storage/disk/mbr.h new file mode 100644 index 0000000..09914a8 --- /dev/null +++ b/src/include/driver/storage/disk/mbr.h @@ -0,0 +1,20 @@ +#ifndef _DISK_MBR_H +#define _DISK_MBR_H + +#include + +typedef struct { + uint8_t boot_indicator; + uint8_t starting_head; + uint16_t starting_sector_cylinder; + uint8_t system_id; + uint8_t ending_head; + uint16_t ending_sector_cylinder; + uint32_t starting_lba; + uint32_t size_in_lba; +} __attribute__((packed)) MBRPartitionEntry; + +bool disk_is_mbr(StorageDevice *storage_device); +void parse_mbr_partition_table(StorageDevice *storage_device); + +#endif \ No newline at end of file diff --git a/src/include/driver/storage_dm.h b/src/include/driver/storage/storage_dm.h similarity index 94% rename from src/include/driver/storage_dm.h rename to src/include/driver/storage/storage_dm.h index 6b65929..5a4eb50 100644 --- a/src/include/driver/storage_dm.h +++ b/src/include/driver/storage/storage_dm.h @@ -31,6 +31,11 @@ typedef struct StorageDevice { PeriodicTask periodic_task; list_t io_queue_lh; + + uint8_t *superblock; + + // 存储设备的分区目录对象 + Object *object; } StorageDevice; typedef struct StorageDeviceDriver { diff --git a/src/include/driver/storage_io.h b/src/include/driver/storage/storage_io.h similarity index 100% rename from src/include/driver/storage_io.h rename to src/include/driver/storage/storage_io.h diff --git a/src/include/driver/storage_io_queue.h b/src/include/driver/storage/storage_io_queue.h similarity index 95% rename from src/include/driver/storage_io_queue.h rename to src/include/driver/storage/storage_io_queue.h index b3870e1..ebd3d8a 100644 --- a/src/include/driver/storage_io_queue.h +++ b/src/include/driver/storage/storage_io_queue.h @@ -1,7 +1,7 @@ #ifndef _STORAGE_IO_QUEUE_H #define _STORAGE_IO_QUEUE_H -#include "driver/storage_dm.h" +#include "driver/storage/storage_dm.h" #include "kernel/list.h" #include "stdint.h" #include "types.h" diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index 2a04c87..de04d21 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -88,7 +88,7 @@ typedef struct Device { } Device; DriverResult register_device( - struct DeviceDriver *device_driver, string_t *name, struct Bus *bus, + struct DeviceDriver *device_driver, string_t name, struct Bus *bus, Device *device); DriverResult unregister_device( struct DeviceDriver *device_driver, Device *device); diff --git a/src/include/objects/object.h b/src/include/objects/object.h index 8cd3b66..57af036 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -26,9 +26,11 @@ typedef enum ObjectType { OBJECT_TYPE_FILE, // 表示该对象是一个文件 OBJECT_TYPE_VALUE, // 表示该对象是一个值 OBJECT_TYPE_SYM_LINK, // 表示该对象是一个符号链接 + OBJECT_TYPE_PARTITION, // 表示该对象是一个分区 OBJECT_TYPE_BUILTIN_MAX, // 表示对象系统内建类型数量的最大值 } ObjectType; +struct Partition; typedef struct Object { string_t name; ObjectType type; @@ -55,7 +57,8 @@ typedef struct Object { size_t integer; }; } value; - struct Object *sym_link; + struct Object *sym_link; + struct Partition *partition; } value; } Object; @@ -71,8 +74,8 @@ ObjectResult open_oringinal_object_by_ascii_path( char *path, Object **out_object); // 通过ASCII路径打开对象,对于符号链接会自动解析 ObjectResult open_object_by_ascii_path(char *path, Object **object); -Object *create_object(Object *parent, string_t *name, ObjectType type); -Object *create_object_directory(Object *parent, string_t *name); +Object *create_object(Object *parent, string_t name, ObjectType type); +Object *create_object_directory(Object *parent, string_t name); void show_object_tree(); #define append_object(parent, child) \ diff --git a/src/include/objects/types.h b/src/include/objects/types.h index e9f8737..1b6e633 100644 --- a/src/include/objects/types.h +++ b/src/include/objects/types.h @@ -4,6 +4,6 @@ #include "object.h" ObjectResult init_builtin_types(); -Object *create_object_type(string_t *name); +Object *create_object_type(string_t name); #endif \ No newline at end of file diff --git a/src/kernel/bus_driver.c b/src/kernel/bus_driver.c index d829d5d..9c62b7b 100644 --- a/src/kernel/bus_driver.c +++ b/src/kernel/bus_driver.c @@ -69,8 +69,7 @@ DriverResult register_bus_driver(Driver *driver, BusDriver *bus_driver) { bus_drivers[bus_driver->bus_type] = bus_driver; - bus_driver->object = - create_object_directory(&bus_object, &bus_driver->name); + bus_driver->object = create_object_directory(&bus_object, bus_driver->name); return DRIVER_RESULT_OK; } @@ -120,7 +119,7 @@ DriverResult register_bus( list_init(&bus->device_lh); list_add_tail(&bus->bus_list, &bus_driver->bus_lh); - bus->object = create_object_directory(bus_driver->object, &bus->name); + bus->object = create_object_directory(bus_driver->object, bus->name); BUS_OPS_CALL(bus_driver, register_bus_hook, bus); @@ -154,8 +153,8 @@ DriverResult bus_register_device(Device *device, Bus *bus) { list_add_tail(&device->bus_list, &bus->device_lh); BUS_OPS_CALL(bus, register_device_hook, device); - string_t *name = kmalloc(sizeof(string_t)); - string_new_with_number(name, "", 0, bus->last_device_num++); + string_t name; + string_new_with_number(&name, "", 0, bus->last_device_num++); device->object = create_object(bus->object, name, OBJECT_TYPE_DEVICE); device->object->value.device = device; diff --git a/src/kernel/device.c b/src/kernel/device.c index 240f55c..f9de7ee 100644 --- a/src/kernel/device.c +++ b/src/kernel/device.c @@ -19,7 +19,7 @@ * @return DriverResult */ DriverResult register_device( - DeviceDriver *device_driver, string_t *name, Bus *bus, Device *device) { + DeviceDriver *device_driver, string_t name, Bus *bus, Device *device) { device->state = DEVICE_STATE_REGISTERED; @@ -40,7 +40,7 @@ DriverResult register_device( bus_register_device(device, bus); - if (name != NULL && name->text != NULL && name->length != 0) { + if (name.text != NULL && name.length != 0) { Object *object = create_object(&device_object, name, OBJECT_TYPE_SYM_LINK); object->value.sym_link = device->object; diff --git a/src/kernel/driver.c b/src/kernel/driver.c index 8f59d93..deb3b70 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -82,7 +82,7 @@ DriverResult register_driver(Driver *driver) { list_add_tail(&driver->driver_list, &driver_lh); Object *object = - create_object(&driver_object, &driver->short_name, OBJECT_TYPE_DRIVER); + create_object(&driver_object, driver->short_name, OBJECT_TYPE_DRIVER); object->value.driver = driver; return DRIVER_RESULT_OK; } diff --git a/src/kernel/main.c b/src/kernel/main.c index a725004..920c449 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -4,12 +4,9 @@ * @brief 内核主程序 * @date 2020-03 */ -#include "driver/storage_io_queue.h" -#include "kernel/list.h" -#include "objects/object.h" -#include "objects/transfer.h" #include -#include +#include +#include #include #include #include @@ -24,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +36,7 @@ #include #include #include +#include #include void idle(void *arg); @@ -67,11 +66,11 @@ int main() { task_idle = thread_start("Idle", 1, idle, 0); io_sti(); printk("Memory Size:%dM\n", get_memory_size()); + thread_start( + "Kernel Periodic Tasks", THREAD_DEFAULT_PRIO, periodic_task, NULL); // init_vfs(); do_initcalls(); driver_start_all(); - thread_start( - "Kernel Periodic Tasks", THREAD_DEFAULT_PRIO, periodic_task, NULL); // void *handle = NULL; // Object *object; @@ -87,7 +86,7 @@ int main() { // } while (!is_done); // print_hex(buf, 512); - // show_object_tree(); + show_object_tree(); // storage_add_request(device->device_manager_extension, &request); // init_fs(); diff --git a/src/kernel/thread.c b/src/kernel/thread.c index abde771..ca54141 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -257,10 +257,11 @@ void init_task(void) { * */ void schedule(void) { + io_cli(); struct task_s *cur = get_current_thread(); if (cur->status == TASK_RUNNING) { if (list_find(&cur->general_tag, &thread_ready)) { - printk("error!\n"); + printk("Error:Current thread is in thread_ready list!\n"); while (1) ; } @@ -270,7 +271,8 @@ void schedule(void) { } struct task_s *next; next = list_first_owner(&thread_ready, struct task_s, general_tag); - if (list_length(&thread_ready) > 1) { + io_sti(); + if (next != cur) { list_del(thread_ready.next); next->status = TASK_RUNNING; diff --git a/src/objects/objects.c b/src/objects/objects.c index d509d38..3df3459 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -124,11 +124,11 @@ ObjectResult add_object(Object *parent, Object *child) { return OBJECT_OK; } -Object *create_object(Object *parent, string_t *name, ObjectType type) { +Object *create_object(Object *parent, string_t name, ObjectType type) { Object *object = kmalloc(sizeof(Object)); if (object == NULL) { return NULL; } - object->name = *name; + object->name = name; object->type = type; object->parent = parent; @@ -137,7 +137,7 @@ Object *create_object(Object *parent, string_t *name, ObjectType type) { return object; } -Object *create_object_directory(Object *parent, string_t *name) { +Object *create_object_directory(Object *parent, string_t name) { Object *object = create_object(parent, name, OBJECT_TYPE_DIRECTORY); if (object == NULL) { return NULL; } diff --git a/src/objects/types.c b/src/objects/types.c index c1a8a97..461b91a 100644 --- a/src/objects/types.c +++ b/src/objects/types.c @@ -12,7 +12,7 @@ Object object_builtin_types[OBJECT_TYPE_BUILTIN_MAX] = { DEFINE_OBJECT_TYPE(TYPE), DEFINE_OBJECT_TYPE(DIRECTORY), DEFINE_OBJECT_TYPE(DRIVER), DEFINE_OBJECT_TYPE(DEVICE), DEFINE_OBJECT_TYPE(FILE), DEFINE_OBJECT_TYPE(VALUE), - DEFINE_OBJECT_TYPE(SYM_LINK), + DEFINE_OBJECT_TYPE(SYM_LINK), DEFINE_OBJECT_TYPE(PARTITION), }; Object object_type_directory = { @@ -33,7 +33,7 @@ ObjectResult init_builtin_types() { return OBJECT_OK; } -Object *create_object_type(string_t *name) { +Object *create_object_type(string_t name) { Object *object = create_object(&object_type_directory, name, OBJECT_TYPE_TYPE); if (object == NULL) { return NULL; } From fb4ace80dd590965e201327229f9604eed3088a7 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 13 Feb 2025 22:46:20 +0800 Subject: [PATCH 021/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E9=80=9A=E8=BF=87?= =?UTF-8?q?=E5=88=86=E5=8C=BA=E5=AF=B9=E8=B1=A1=E8=AF=BB=E5=86=99=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/storage/disk/disk.c | 32 +++++++++++++++++++++++--- src/driver/storage/disk/mbr.c | 25 +++++++++++++------- src/include/driver/storage/disk/disk.h | 11 +++++++++ src/include/driver/storage/disk/mbr.h | 14 +++++------ src/include/kernel/device.h | 1 - src/kernel/main.c | 4 ++-- src/objects/objects.c | 18 +++++++++++---- 7 files changed, 78 insertions(+), 27 deletions(-) diff --git a/src/driver/storage/disk/disk.c b/src/driver/storage/disk/disk.c index 0f0b788..2f142e2 100644 --- a/src/driver/storage/disk/disk.c +++ b/src/driver/storage/disk/disk.c @@ -1,9 +1,9 @@ -#include "driver/storage/storage_io.h" #include #include +#include #include -TransferResult disk_transfer( +TransferResult disk_transfer_in( Object *object, TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, void **handle) { Partition *partition = object->value.partition; @@ -11,4 +11,30 @@ TransferResult disk_transfer( return TRANSFER_IN_BLOCK(partition->storage_object)( partition->storage_object, direction, buf, position + partition->start_lba, count, handle); -} \ No newline at end of file +} + +TransferResult disk_transfer_out( + Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count, void **handle) { + Partition *partition = object->value.partition; + + return TRANSFER_OUT_BLOCK(partition->storage_object)( + partition->storage_object, direction, buf, + position + partition->start_lba, count, handle); +} + +TransferResult disk_is_transfer_in_done( + Object *object, void **handle, bool *is_done) { + Partition *partition = object->value.partition; + + return TRANSFER_IN_IS_DONE(partition->storage_object)( + partition->storage_object, handle, is_done); +} + +TransferResult disk_is_transfer_out_done( + Object *object, void **handle, bool *is_done) { + Partition *partition = object->value.partition; + + return TRANSFER_OUT_IS_DONE(partition->storage_object)( + partition->storage_object, handle, is_done); +} diff --git a/src/driver/storage/disk/mbr.c b/src/driver/storage/disk/mbr.c index e2eb6ab..287bec5 100644 --- a/src/driver/storage/disk/mbr.c +++ b/src/driver/storage/disk/mbr.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #define MBR_PARTITION_ENTRY_SIZE 16 @@ -21,18 +21,27 @@ void parse_mbr_partition_table(StorageDevice *storage_device) { ->superblock[MBR_PARTITION_TABLE_OFFSET]; for (int i = 0; i < MBR_PARTITION_COUNT; i++) { - if (partition_table[i].system_id != 0) { + if (partition_table[i].sign != 0) { string_t name; string_new_with_number(&name, "Partition", 9, partition_count); Object *object = create_object( storage_device->object, name, OBJECT_TYPE_PARTITION); - Partition *partition = kmalloc(sizeof(Partition)); - partition->type = PARTITION_TYPE_MBR; - partition->start_lba = partition_table[i].starting_lba; - partition->size_lba = partition_table[i].size_in_lba; - partition->mbr = &partition_table[i]; - object->value.partition = partition; + Partition *partition = kmalloc(sizeof(Partition)); + partition->storage_object = storage_device->device->object; + partition->type = PARTITION_TYPE_MBR; + partition->start_lba = partition_table[i].start_lba; + partition->size_lba = partition_table[i].size; + partition->mbr = &partition_table[i]; + object->value.partition = partition; + + object->in.type = TRANSFER_TYPE_BLOCK; + object->in.block = disk_transfer_in; + object->in.is_transfer_done = disk_is_transfer_in_done; + object->out.type = TRANSFER_TYPE_BLOCK; + object->out.block = disk_transfer_out; + object->out.is_transfer_done = disk_is_transfer_out_done; + partition_count++; } } diff --git a/src/include/driver/storage/disk/disk.h b/src/include/driver/storage/disk/disk.h index 167ca9a..f1371eb 100644 --- a/src/include/driver/storage/disk/disk.h +++ b/src/include/driver/storage/disk/disk.h @@ -18,4 +18,15 @@ typedef struct Partition { Object *storage_object; } Partition; +TransferResult disk_transfer_in( + Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count, void **handle); +TransferResult disk_transfer_out( + Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count, void **handle); +TransferResult disk_is_transfer_in_done( + Object *object, void **handle, bool *is_done); +TransferResult disk_is_transfer_out_done( + Object *object, void **handle, bool *is_done); + #endif \ No newline at end of file diff --git a/src/include/driver/storage/disk/mbr.h b/src/include/driver/storage/disk/mbr.h index 09914a8..00fe5a8 100644 --- a/src/include/driver/storage/disk/mbr.h +++ b/src/include/driver/storage/disk/mbr.h @@ -4,14 +4,12 @@ #include typedef struct { - uint8_t boot_indicator; - uint8_t starting_head; - uint16_t starting_sector_cylinder; - uint8_t system_id; - uint8_t ending_head; - uint16_t ending_sector_cylinder; - uint32_t starting_lba; - uint32_t size_in_lba; + uint8_t sign; + uint8_t start_chs[3]; + uint8_t fs_type; + uint8_t end_chs[3]; + uint32_t start_lba; + uint32_t size; } __attribute__((packed)) MBRPartitionEntry; bool disk_is_mbr(StorageDevice *storage_device); diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index de04d21..16d429e 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -5,7 +5,6 @@ #include "kernel/driver_interface.h" #include "kernel/list.h" #include "objects/object.h" -#include "objects/transfer.h" #include "stdint.h" #include "string.h" #include "types.h" diff --git a/src/kernel/main.c b/src/kernel/main.c index 920c449..f7e5b3a 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -75,7 +75,7 @@ int main() { // void *handle = NULL; // Object *object; // ObjectResult result = - // open_object_by_ascii_path("\\Device\\Storage0", &object); + // open_object_by_ascii_path("\\Device\\Storage0\\Partition0", &object); // if (result != OBJECT_OK) { printk("Open Storage0 Error!\n"); } // uint8_t buf[512]; // TRANSFER_IN_BLOCK(object)(object, TRANSFER_IN, buf, 0, 1, &handle); @@ -86,7 +86,7 @@ int main() { // } while (!is_done); // print_hex(buf, 512); - show_object_tree(); + // show_object_tree(); // storage_add_request(device->device_manager_extension, &request); // init_fs(); diff --git a/src/objects/objects.c b/src/objects/objects.c index 3df3459..30fd997 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -60,13 +60,16 @@ ObjectResult init_object_tree() { } ObjectResult find_object_by_name( - Object *parent, Object **out_child, string_t *name) { + Object *parent, Object **out_child, string_t *name, bool is_directory) { Object *child; dyn_array_foreach(parent->value.directory.children, Object *, child) { if (child->name.length == name->length && strncmp(child->name.text, name->text, name->length) == 0) { - *out_child = child; - return OBJECT_OK; + if ((child->type == OBJECT_TYPE_DIRECTORY && is_directory) || + (child->type != OBJECT_TYPE_DIRECTORY && !is_directory)) { + *out_child = child; + return OBJECT_OK; + } } } return OBJECT_ERROR_CANNOT_FIND; @@ -88,13 +91,18 @@ ObjectResult open_oringinal_object_by_ascii_path( path++; i++; } - if (*path == '\\') { path++; } + bool is_directory = false; + if (*path == '\\') { + is_directory = true; + path++; + } ascii_name[i] = '\0'; name.length = i + 1; name.max_length = i + 1; Object *child; - ObjectResult result = find_object_by_name(object, &child, &name); + ObjectResult result = + find_object_by_name(object, &child, &name, is_directory); if (result != OBJECT_OK) { return result; } object = child; From 8077c833d31a2051896640297c1c6a0befb20b23 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 25 Feb 2025 23:40:49 +0800 Subject: [PATCH 022/158] =?UTF-8?q?=E7=AE=80=E5=8C=96wait=5Fqueue=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/kernel/wait_queue.h | 21 ++++----- src/kernel/wait_queue.c | 83 ++++++++++++--------------------- 2 files changed, 39 insertions(+), 65 deletions(-) diff --git a/src/include/kernel/wait_queue.h b/src/include/kernel/wait_queue.h index dcd950c..99a978d 100644 --- a/src/include/kernel/wait_queue.h +++ b/src/include/kernel/wait_queue.h @@ -9,20 +9,15 @@ typedef struct { spinlock_t lock; list_t list_head; -} wait_queue_manager_t; +} WaitQueue; -typedef struct { - struct task_s *thread; - void *private_data; - list_t list; -} wait_queue_t; +typedef struct task_s WaitQueueItem; -wait_queue_manager_t *create_wait_queue(void); -void wait_queue_init(wait_queue_manager_t *wqm); -bool wait_queue_empty(wait_queue_manager_t *wqm); -wait_queue_t *wait_queue_add(wait_queue_manager_t *wqm, uint32_t size); -wait_queue_t *wait_queue_first(wait_queue_manager_t *wqm); -void wait_queue_wakeup(wait_queue_manager_t *wqm); -void wait_queue_wakeup_all(wait_queue_manager_t *wqm); +void wait_queue_init(WaitQueue *wq); +bool wait_queue_empty(WaitQueue *wq); +void wait_queue_add(WaitQueue *wq); +WaitQueueItem *wait_queue_first(WaitQueue *wq); +void wait_queue_wakeup(WaitQueue *wq); +void wait_queue_wakeup_all(WaitQueue *wq); #endif \ No newline at end of file diff --git a/src/kernel/wait_queue.c b/src/kernel/wait_queue.c index 9079b17..8d7f341 100644 --- a/src/kernel/wait_queue.c +++ b/src/kernel/wait_queue.c @@ -6,81 +6,64 @@ * @date 2022-07-20 */ +#include "kernel/thread.h" #include #include #include #include #include -/** - * @brief 创建一个等待队列 - * - * @return wait_queue_manager_t* 等待队列的管理结构 - */ -wait_queue_manager_t *create_wait_queue(void) { - wait_queue_manager_t *wqm = - (wait_queue_manager_t *)kmalloc(sizeof(wait_queue_manager_t)); - return wqm; -} - /** * @brief 初始化等待队列 * - * @param wqm 等待队列管理结构 + * @param wq 等待队列管理结构 */ -void wait_queue_init(wait_queue_manager_t *wqm) { - spinlock_init(&wqm->lock); - list_init(&wqm->list_head); +void wait_queue_init(WaitQueue *wq) { + spinlock_init(&wq->lock); + list_init(&wq->list_head); return; } /** * @brief 检查等待队列是否为空 * - * @param wqm 等待队列管理结构 + * @param wq 等待队列管理结构 * @return true * @return false */ -bool wait_queue_empty(wait_queue_manager_t *wqm) { - return list_empty(&wqm->list_head); +bool wait_queue_empty(WaitQueue *wq) { + return list_empty(&wq->list_head); } /** * @brief 添加当前任务到等待队列 * - * @param wqm 等待队列管理结构 - * @param size private_data的大小 + * @param wq 等待队列管理结构 * - * @return wait_queue_t * + * @return */ -wait_queue_t *wait_queue_add(wait_queue_manager_t *wqm, uint32_t size) { - wait_queue_t *wq = (wait_queue_t *)kmalloc(sizeof(wait_queue_t)); - wq->thread = get_current_thread(); - int old_status = load_interrupt_status(); +void wait_queue_add(WaitQueue *wq) { + struct task_s *task = get_current_thread(); + int old_status = load_interrupt_status(); disable_interrupt(); - spin_lock(&wqm->lock); + spin_lock(&wq->lock); - list_add_tail(&wq->list, &wqm->list_head); + // 把当前线程的list tag直接挂到等待队列的list上 + list_add_tail(&task->general_tag, &wq->list_head); - spin_unlock(&wqm->lock); + spin_unlock(&wq->lock); store_interrupt_status(old_status); - if (size != 0) { - wq->private_data = kmalloc(size); - } else { - wq->private_data = NULL; - } - return wq; } /** * @brief 获取等待队列中的第一个任务 * - * @param wqm 等待队列管理结构 - * @return wait_queue_t* + * @param wq 等待队列管理结构 + * @return */ -wait_queue_t *wait_queue_first(wait_queue_manager_t *wqm) { +WaitQueueItem *wait_queue_first(WaitQueue *wqm) { if (list_empty(&wqm->list_head)) { return NULL; } - return list_first_owner(&wqm->list_head, wait_queue_t, list); + return list_first_owner(&wqm->list_head, WaitQueueItem, general_tag); } /** @@ -88,17 +71,15 @@ wait_queue_t *wait_queue_first(wait_queue_manager_t *wqm) { * * @param wqm 等待队列管理结构 */ -void wait_queue_wakeup(wait_queue_manager_t *wqm) { +void wait_queue_wakeup(WaitQueue *wqm) { if (list_empty(&wqm->list_head)) { return; } - wait_queue_t *wq = list_first_owner(&wqm->list_head, wait_queue_t, list); - struct task_s *thread = wq->thread; - int old_status = load_interrupt_status(); + struct task_s *thread = + list_first_owner(&wqm->list_head, struct task_s, general_tag); + int old_status = load_interrupt_status(); disable_interrupt(); spin_lock(&wqm->lock); - list_del(&wq->list); - if (wq->private_data != NULL) { kfree(wq->private_data); } - kfree(wq); + list_del(&thread->general_tag); if (thread->status == TASK_BLOCKED || thread->status == TASK_WAITING || thread->status == TASK_HANGING) { @@ -115,20 +96,18 @@ void wait_queue_wakeup(wait_queue_manager_t *wqm) { * * @param wqm 等待队列管理结构 */ -void wait_queue_wakeup_all(wait_queue_manager_t *wqm) { +void wait_queue_wakeup_all(WaitQueue *wqm) { if (list_empty(&wqm->list_head)) { return; } - wait_queue_t *cur, *next; + WaitQueueItem *cur, *next; struct task_s *thread; int old_status = load_interrupt_status(); disable_interrupt(); spin_lock(&wqm->lock); - list_for_each_owner_safe (cur, next, &wqm->list_head, list) { - thread = cur->thread; - list_del(&cur->list); - if (cur->private_data != NULL) { kfree(cur->private_data); } - kfree(cur); + list_for_each_owner_safe (cur, next, &wqm->list_head, general_tag) { + thread = cur; + list_del(&cur->general_tag); if (thread->status == TASK_BLOCKED || thread->status == TASK_WAITING || thread->status == TASK_HANGING) { thread_unblock(thread); From 2a5db56fdb2892ab6d5a4ac6ea3669606300a2ff Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 26 Feb 2025 00:08:19 +0800 Subject: [PATCH 023/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E4=BA=92=E6=96=A5?= =?UTF-8?q?=E9=94=81=E3=80=81=E8=AF=BB=E5=86=99=E9=94=81=E3=80=81=E6=9D=A1?= =?UTF-8?q?=E4=BB=B6=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/kernel/condvar.h | 33 ++++++++++++++++++ src/include/kernel/mutex.h | 22 ++++++++++++ src/include/kernel/rwlock.h | 65 +++++++++++++++++++++++++++++++++++ src/include/kernel/spinlock.h | 4 +-- 4 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 src/include/kernel/condvar.h create mode 100644 src/include/kernel/mutex.h create mode 100644 src/include/kernel/rwlock.h diff --git a/src/include/kernel/condvar.h b/src/include/kernel/condvar.h new file mode 100644 index 0000000..2fe52f5 --- /dev/null +++ b/src/include/kernel/condvar.h @@ -0,0 +1,33 @@ +#ifndef _CONDVAR_H +#define _CONDVAR_H + +#include "kernel/spinlock.h" +#include "kernel/thread.h" +#include "kernel/wait_queue.h" + +typedef struct { + WaitQueue wait_queue; +} condvar_t; + +void condvar_init(condvar_t *cv) { + wait_queue_init(&cv->wait_queue); +} + +void condvar_wait(condvar_t *cv, spinlock_t *mutex) { + wait_queue_add(&cv->wait_queue); + spin_unlock(mutex); + + thread_block(TASK_BLOCKED); + + spin_lock(mutex); +} + +void condvar_signal(condvar_t *cv) { + wait_queue_wakeup(&cv->wait_queue); +} + +void condvar_broadcast(condvar_t *cv) { + wait_queue_wakeup_all(&cv->wait_queue); +} + +#endif diff --git a/src/include/kernel/mutex.h b/src/include/kernel/mutex.h new file mode 100644 index 0000000..8aac346 --- /dev/null +++ b/src/include/kernel/mutex.h @@ -0,0 +1,22 @@ +#ifndef _MUTEX_H +#define _MUTEX_H + +#include "kernel/thread.h" + +typedef volatile int mutex_t; + +void mutex_init(mutex_t *lock) { + *lock = 0; +} + +void mutex_lock(mutex_t *lock) { + while (__sync_lock_test_and_set(lock, 1)) { + schedule(); + } +} + +void mutex_unlock(mutex_t *lock) { + __sync_lock_release(lock); +} + +#endif \ No newline at end of file diff --git a/src/include/kernel/rwlock.h b/src/include/kernel/rwlock.h new file mode 100644 index 0000000..c679765 --- /dev/null +++ b/src/include/kernel/rwlock.h @@ -0,0 +1,65 @@ +#ifndef _RWLOCK_H +#define _RWLOCK_H + +#include "kernel/condvar.h" +#include "kernel/spinlock.h" + +typedef struct { + spinlock_t status_lock; // 保护读写锁内部状态 + condvar_t read_lock; + condvar_t write_lock; + int read_count; + int write_count; + int write_waiting; +} rwlock_t; + +void rwlock_init(rwlock_t *lock) { + spinlock_init(&lock->status_lock); + condvar_init(&lock->read_lock); + condvar_init(&lock->write_lock); + lock->read_count = 0; + lock->write_count = 0; + lock->write_waiting = 0; +} + +void rwlock_read_lock(rwlock_t *lock) { + spin_lock(&lock->status_lock); + while (lock->write_count > 0 || lock->write_waiting > 0) { + condvar_wait(&lock->read_lock, &lock->status_lock); + } + lock->read_count++; + spin_unlock(&lock->status_lock); +} + +void rwlock_read_unlock(rwlock_t *lock) { + spin_lock(&lock->status_lock); + lock->read_count--; + if (lock->read_count == 0 && lock->write_waiting > 0) { + condvar_signal(&lock->write_lock); + } + spin_unlock(&lock->status_lock); +} + +void rwlock_write_lock(rwlock_t *lock) { + spin_lock(&lock->status_lock); + lock->write_waiting++; + while (lock->read_count > 0 || lock->write_count > 0) { + condvar_wait(&lock->write_lock, &lock->status_lock); + } + lock->write_waiting--; + lock->write_count++; + spin_unlock(&lock->status_lock); +} + +void rwlock_write_unlock(rwlock_t *lock) { + spin_lock(&lock->status_lock); + lock->write_count--; + if (lock->write_count > 0) { + condvar_signal(&lock->write_lock); + } else { + condvar_broadcast(&lock->read_lock); + } + spin_unlock(&lock->status_lock); +} + +#endif \ No newline at end of file diff --git a/src/include/kernel/spinlock.h b/src/include/kernel/spinlock.h index 38b3495..684ef69 100644 --- a/src/include/kernel/spinlock.h +++ b/src/include/kernel/spinlock.h @@ -1,7 +1,7 @@ #ifndef _SPINLOCK_H #define _SPINLOCK_H -typedef int spinlock_t; +typedef volatile int spinlock_t; #define SPINLOCK(lock) spinlock_t lock = 0; @@ -20,7 +20,7 @@ static inline void spin_lock(spinlock_t *lock) { } } -static inline void spin_unlock(spinlock_t __volatile__ *lock) { +static inline void spin_unlock(volatile spinlock_t *lock) { __asm__ __volatile__("" ::: "memory"); *lock = 0; } From e03d8d18cafea89a7a9e7069d9ed69e0a5a7f0bf Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 28 Feb 2025 23:05:28 +0800 Subject: [PATCH 024/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20Object=E5=BC=95?= =?UTF-8?q?=E7=94=A8=E8=AE=A1=E6=95=B0=E4=B8=8Eobject=5Fclose=EF=BC=9B=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20dyn=5Farray=5Fremove?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/dyn_array.h | 7 +++-- src/include/objects/object.h | 13 +++++++++ src/lib/dyn_array.c | 54 +++++++++++++++++++++++++++++++++--- src/objects/objects.c | 19 +++++++++++-- 4 files changed, 84 insertions(+), 9 deletions(-) diff --git a/src/include/dyn_array.h b/src/include/dyn_array.h index caa071b..a3dbde6 100644 --- a/src/include/dyn_array.h +++ b/src/include/dyn_array.h @@ -14,14 +14,17 @@ typedef struct DynArray { size_t element_size; } DynArray; -struct DynArrayBlock { +typedef struct DynArrayBlock { struct DynArrayBlock *next; void *data; -}; + int left_space; +} DynArrayBlock; DynArray *dyn_array_new(size_t element_size, size_t block_size); +void dyn_array_delete(DynArray *dyn_array); struct DynArrayBlock *dyn_array_find_block(DynArray *dyn_array, size_t idx); void *dyn_array_new_item_addr(DynArray *dyn_array); +void dyn_array_remove(DynArray *dyn_array, void *item); void *dyn_array_next_ptr( DynArray *dyn_array, struct DynArrayBlock **block, int *block_index, diff --git a/src/include/objects/object.h b/src/include/objects/object.h index 57af036..457ede3 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -27,6 +27,7 @@ typedef enum ObjectType { OBJECT_TYPE_VALUE, // 表示该对象是一个值 OBJECT_TYPE_SYM_LINK, // 表示该对象是一个符号链接 OBJECT_TYPE_PARTITION, // 表示该对象是一个分区 + OBJECT_TYPE_VOLUME, // 表示该对象是一个卷 OBJECT_TYPE_BUILTIN_MAX, // 表示对象系统内建类型数量的最大值 } ObjectType; @@ -38,14 +39,22 @@ typedef struct Object { struct Object *parent; TransferIn in; TransferOut out; + + uint32_t reference; + union { uint32_t type; struct { + void *data; DynArray *children; } directory; struct Driver *driver; struct Device *device; struct { + void *data; + size_t size; + size_t offset; + void *buffer; } file; struct { enum { @@ -59,7 +68,10 @@ typedef struct Object { } value; struct Object *sym_link; struct Partition *partition; + struct Volume *volume; } value; + + void (*release_data)(struct Object *object); } Object; extern Object root_object; @@ -76,6 +88,7 @@ ObjectResult open_oringinal_object_by_ascii_path( ObjectResult open_object_by_ascii_path(char *path, Object **object); Object *create_object(Object *parent, string_t name, ObjectType type); Object *create_object_directory(Object *parent, string_t name); +void object_close(Object *object); void show_object_tree(); #define append_object(parent, child) \ diff --git a/src/lib/dyn_array.c b/src/lib/dyn_array.c index 02defb3..07a3397 100644 --- a/src/lib/dyn_array.c +++ b/src/lib/dyn_array.c @@ -2,6 +2,7 @@ #include #include #include +#include #include DynArray *dyn_array_new(size_t element_size, size_t block_size) { @@ -13,14 +14,26 @@ DynArray *dyn_array_new(size_t element_size, size_t block_size) { array->block_size = block_size; array->element_size = find_next_pow_of_2(element_size); - array->first_block = kmalloc(sizeof(struct DynArrayBlock)); - array->first_block->next = NULL; - array->first_block->data = kmalloc(block_size * array->element_size); - array->last_block = array->first_block; + array->first_block = kmalloc(sizeof(struct DynArrayBlock)); + array->first_block->next = NULL; + array->first_block->data = kmalloc(block_size * array->element_size); + array->first_block->left_space = array->block_size; + array->last_block = array->first_block; return array; } +void dyn_array_delete(DynArray *dyn_array) { + struct DynArrayBlock *block = dyn_array->first_block; + while (block != NULL) { + struct DynArrayBlock *next = block->next; + kfree(block->data); + kfree(block); + block = next; + } + kfree(dyn_array); +} + void dyn_array_extend_block(DynArray *dyn_array) { struct DynArrayBlock *block = dyn_array->first_block; while (block->next != NULL) { @@ -32,6 +45,7 @@ void dyn_array_extend_block(DynArray *dyn_array) { block->next = new_block; new_block->next = NULL; new_block->data = kmalloc(dyn_array->block_size * dyn_array->element_size); + new_block->left_space = dyn_array->block_size; dyn_array->capacity += dyn_array->block_size * dyn_array->element_size; @@ -83,6 +97,38 @@ void *dyn_array_next_ptr( return (void *)current_block->data + offset * dyn_array->element_size; } +void dyn_array_remove(DynArray *dyn_array, void *item) { + struct DynArrayBlock *block = dyn_array->first_block; + struct DynArrayBlock *last_block = NULL; + + while (block != NULL) { + for (int i = 0; i < dyn_array->block_size; i++) { + if (block->data + i * dyn_array->element_size == item) { + memset( + block->data + i * dyn_array->element_size, 0, + dyn_array->element_size); + + dyn_array->size--; + block->left_space--; + if (block->left_space == 0 && block != dyn_array->first_block) { + if (last_block != NULL) { + last_block->next = block->next; + } else { + dyn_array->first_block = block->next; + } + if (dyn_array->last_block == block) { + dyn_array->last_block = last_block; + } + kfree(block); + } + return; + } + } + last_block = block; + block = block->next; + } +} + bool dyn_array_is_end( DynArray *dyn_array, struct DynArrayBlock *block, int block_index, int block_offset) { diff --git a/src/objects/objects.c b/src/objects/objects.c index 30fd997..5b6c94e 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -107,6 +107,7 @@ ObjectResult open_oringinal_object_by_ascii_path( object = child; } + object->reference++; *out_object = object; return OBJECT_OK; } @@ -136,15 +137,27 @@ Object *create_object(Object *parent, string_t name, ObjectType type) { Object *object = kmalloc(sizeof(Object)); if (object == NULL) { return NULL; } - object->name = name; - object->type = type; - object->parent = parent; + object->name = name; + object->type = type; + object->parent = parent; + object->reference = 0; add_object(parent, object); return object; } +void object_close(Object *object) { + object->reference--; + if (object->reference != 0) return; + if (object->release_data != NULL) { object->release_data(object); } + if (object->type == OBJECT_TYPE_DIRECTORY) { + dyn_array_delete(object->value.directory.children); + } + dyn_array_remove(object->parent->value.directory.children, object); + kfree(object); +} + Object *create_object_directory(Object *parent, string_t name) { Object *object = create_object(parent, name, OBJECT_TYPE_DIRECTORY); if (object == NULL) { return NULL; } From fe5e303cc76d7696646dcc5e0795738c6e8db87f Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 4 Mar 2025 00:05:23 +0800 Subject: [PATCH 025/158] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E5=86=99=E5=85=A5?= =?UTF-8?q?IDE=E6=97=B6=E6=B2=A1=E6=9C=89=E5=86=99=E5=85=A5current=5Freque?= =?UTF-8?q?st=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/disk/ata/ide.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index 51096af..d1037e7 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -397,6 +397,7 @@ DriverResult ide_device_write_sectors( ide_wait(channel); io_out_byte(channel->io_base + ATA_REG_COMMAND, cmd); + ide_device->current_request = request; if (ide_device->mode == TRANSFER_MODE_PIO) { ide_device_send_pio( ide_device, (uint32_t *)request->buf, request->count); From 28cd05680c5f4974ed43aad054a1d0afca348e60 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 4 Mar 2025 00:09:00 +0800 Subject: [PATCH 026/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=EF=BC=9B=20=E4=BF=AE=E6=94=B9=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/Makefile | 1 + src/arch/x86/drivers/apic.c | 2 +- src/arch/x86/drivers/cmos.c | 94 +++++++++++++++++++++++++ src/arch/x86/drivers/vesa_display.c | 2 +- src/arch/x86/include/drivers/cmos.h | 52 +++++--------- src/arch/x86/kernel/platform.c | 3 + src/driver/Makefile | 3 +- src/driver/bus_dm.c | 4 +- src/driver/interrupt_dm.c | 27 ++++--- src/driver/time_dm.c | 52 ++++++++++++++ src/driver/timer.c | 5 +- src/driver/timer_dm.c | 26 ++++--- src/driver/video_dm.c | 23 +++--- src/include/driver/interrupt_dm.h | 2 +- src/include/driver/storage/storage_dm.h | 8 ++- src/include/driver/time_dm.h | 53 ++++++++++++++ src/include/driver/timer_dm.h | 2 +- src/include/driver/video_dm.h | 2 +- src/include/kernel/device.h | 5 +- src/include/kernel/device_manager.h | 4 +- src/include/objects/transfer.h | 24 ++++--- src/kernel/device_driver.c | 4 +- src/kernel/device_manager.c | 4 +- src/kernel/driver.c | 32 ++++----- src/kernel/driver_dependency.c | 2 +- 25 files changed, 317 insertions(+), 119 deletions(-) create mode 100644 src/arch/x86/drivers/cmos.c create mode 100644 src/driver/time_dm.c create mode 100644 src/include/driver/time_dm.h diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index 845f6a1..50a6d32 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -12,6 +12,7 @@ SRC += msr.c SRC += pit.c SRC += smbios.c SRC += vesa_display.c +SRC += cmos.c #SRC += network/ #SRC += sound/ #SRC += usb/ diff --git a/src/arch/x86/drivers/apic.c b/src/arch/x86/drivers/apic.c index 658ce9b..f4a097d 100644 --- a/src/arch/x86/drivers/apic.c +++ b/src/arch/x86/drivers/apic.c @@ -309,7 +309,7 @@ DriverResult apic_init(Device *device) { lapic_write(APIC_TPR, 0); for (int i = 0; i < apic_info.max_lvt_entry; i++) { - apic_disable_irq(device->device_manager_extension, 0x20 + i); + apic_disable_irq(device->dm_ext, 0x20 + i); } return DRIVER_RESULT_OK; } diff --git a/src/arch/x86/drivers/cmos.c b/src/arch/x86/drivers/cmos.c new file mode 100644 index 0000000..28caadb --- /dev/null +++ b/src/arch/x86/drivers/cmos.c @@ -0,0 +1,94 @@ +#include "kernel/driver.h" +#include +#include +#include +#include +#include + +extern Driver core_driver; + +DriverResult rtc_get_time(TimeDevice *time_device, TimeType type, Time *time); + +DeviceDriverOps rtc_device_driver_ops = { + +}; +DeviceOps rtc_device_ops = { + .init = NULL, + .start = NULL, + .stop = NULL, + .destroy = NULL, + .status = NULL, +}; +TimeDeviceOps rtc_time_device_ops = { + .get_time = rtc_get_time, + .set_time = NULL, +}; + +DeviceDriver rtc_device_driver = { + .name = STRING_INIT("RTC"), + .bus = &platform_bus, + .type = DEVICE_TYPE_TIME, + .priority = DRIVER_PRIORITY_BASIC, + .ops = &rtc_device_driver_ops, + .private_data_size = 0, +}; +Device rtc_device = { + .name = STRING_INIT("RTC"), + .device_driver = &rtc_device_driver, + .ops = &rtc_device_ops, + .private_data_size = 0, +}; +TimeDevice rtc_time_device = { + .device = &rtc_device, + .type = TIME_TYPE_LOCAL, + .ops = &rtc_time_device_ops}; + +void register_cmos(void) { + register_device_driver(&core_driver, &rtc_device_driver); + register_time_device(&rtc_device_driver, &rtc_device, &rtc_time_device); +} + +int rtc_guess_year(int year) { + return 2000 + year; +} + +bool rtc_is_updating(void) { + return (CMOS_READ(CMOS_STATUS_A) & 0x80); +} + +bool rtc_is_bcd(void) { + return !(CMOS_READ(CMOS_STATUS_B) & 0x04); +} + +DriverResult rtc_get_time(TimeDevice *time_device, TimeType type, Time *time) { + while (rtc_is_updating()) + ; + int second = CMOS_READ(CMOS_SECONDS); + int minute = CMOS_READ(CMOS_MINUTES); + int hour = CMOS_READ(CMOS_HOURS); + int day = CMOS_READ(CMOS_DAY_OF_MONTH); + int month = CMOS_READ(CMOS_MONTH); + int year = CMOS_READ(CMOS_YEAR); + + if (rtc_is_bcd()) { + second = BCD2BIN(second); + minute = BCD2BIN(minute); + hour = BCD2BIN(hour); + day = BCD2BIN(day); + month = BCD2BIN(month); + year = BCD2BIN(year); + } + + time->time.year = rtc_guess_year(year); + time->time.month = month; + time->time.day = day; + time->time.hour = hour; + time->time.minute = minute; + time->time.second = second; + + return DRIVER_RESULT_OK; +} + +DriverResult rtc_set_time(Device *device, TimeType type, Time *time) { + return DRIVER_RESULT_OK; +} diff --git a/src/arch/x86/drivers/vesa_display.c b/src/arch/x86/drivers/vesa_display.c index f0de739..1044095 100644 --- a/src/arch/x86/drivers/vesa_display.c +++ b/src/arch/x86/drivers/vesa_display.c @@ -72,7 +72,7 @@ DriverResult vesa_display_device_init(Device *device) { DriverResult vesa_display_device_start(Device *device) { vesa_display_info.vram = (uint8_t *)VRAM_VIR_ADDR; - VideoDevice *video_device = device->device_manager_extension; + VideoDevice *video_device = device->dm_ext; video_device->mode_info.width = vesa_display_info.width; video_device->mode_info.height = vesa_display_info.height; video_device->mode_info.bits_per_pixel = vesa_display_info.BitsPerPixel; diff --git a/src/arch/x86/include/drivers/cmos.h b/src/arch/x86/include/drivers/cmos.h index 6cffc5e..e6d8b1a 100644 --- a/src/arch/x86/include/drivers/cmos.h +++ b/src/arch/x86/include/drivers/cmos.h @@ -7,44 +7,30 @@ #define CMOS_DATA 0x71 // CMOS寄存器 -#define CMOS_SECONDS 0x00 -#define CMOS_MINUTES 0x02 -#define CMOS_HOURS 0x04 -#define CMOS_WEEKDAY 0x06 +#define CMOS_SECONDS 0x00 +#define CMOS_MINUTES 0x02 +#define CMOS_HOURS 0x04 +#define CMOS_WEEKDAY 0x06 #define CMOS_DAY_OF_MONTH 0x07 -#define CMOS_MONTH 0x08 -#define CMOS_YEAR 0x09 -#define CMOS_STATUS_A 0x0a -#define CMOS_STATUS_B 0x0b +#define CMOS_MONTH 0x08 +#define CMOS_YEAR 0x09 +#define CMOS_STATUS_A 0x0a +#define CMOS_STATUS_B 0x0b #define CMOS_FLOPPY_TYPE 0x10 -#define CMOS_EQP 0x14 -#define CMOS_CENTURY 0x32 +#define CMOS_EQP 0x14 +#define CMOS_CENTURY 0x32 -#define CMOS_READ(reg) ({ \ - io_out8(CMOS_REGS, reg); \ - io_in8(CMOS_DATA); \ -}) +#define CMOS_READ(reg) \ + ({ \ + io_out8(CMOS_REGS, reg); \ + io_in8(CMOS_DATA); \ + }) #define BCD2BIN(bcd) ((bcd >> 4) * 10 + (bcd & 0x0f)) +#define BIN2BCD(bin) (((bin / 10) << 4) + (bin % 10)) -struct time { - int year, month, day; - int hour, minute, second; -}; - -static inline void cmos_get_time(struct time *time) -{ - io_cli(); - do { - time->year = CMOS_READ(CMOS_YEAR) + CMOS_READ(CMOS_CENTURY) * 0x100; - time->month = CMOS_READ(CMOS_MONTH); - time->day = CMOS_READ(CMOS_DAY_OF_MONTH); - time->hour = CMOS_READ(CMOS_HOURS); - time->minute = CMOS_READ(CMOS_MINUTES); - time->second = CMOS_READ(CMOS_SECONDS); - } while (time->second != CMOS_READ(CMOS_SECONDS)); - io_out8(CMOS_REGS, 0x00); - io_sti(); -} +extern struct Device rtc_device; + +void register_cmos(void); #endif \ No newline at end of file diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index 9b99a9c..d472cd5 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,7 @@ void platform_init() { register_pic(); register_apic(); register_pit(); + register_cmos(); } void platform_start_devices() { @@ -69,6 +71,7 @@ void platform_start_devices() { interrupt_dm_start(); // 启动由interrupt_dm选择的中断控制器 DRV_RESULT_PRINT_CALL(init_and_start, &pit_device); DRV_RESULT_PRINT_CALL(init_and_start, &apic_timer_device); + DRV_RESULT_PRINT_CALL(init_and_start, &rtc_device); platform_bus_driver.subdriver.state = SUBDRIVER_STATE_READY; } \ No newline at end of file diff --git a/src/driver/Makefile b/src/driver/Makefile index 2899264..b43abe9 100644 --- a/src/driver/Makefile +++ b/src/driver/Makefile @@ -4,4 +4,5 @@ SRC += interrupt_dm.c SRC += video_dm.c SRC += video.c SRC += bus_dm.c -SRC += timer.c \ No newline at end of file +SRC += timer.c +SRC += time_dm.c \ No newline at end of file diff --git a/src/driver/bus_dm.c b/src/driver/bus_dm.c index 5855eeb..638dcca 100644 --- a/src/driver/bus_dm.c +++ b/src/driver/bus_dm.c @@ -8,8 +8,8 @@ DriverResult bus_controller_start(DeviceManager *manager, Device *device); DeviceManagerOps bus_controller_dm_ops = { - .dm_load_hook = NULL, - .dm_unload_hook = NULL, + .dm_load = NULL, + .dm_unload = NULL, }; typedef struct BusControllerDeviceManager { diff --git a/src/driver/interrupt_dm.c b/src/driver/interrupt_dm.c index 0f7baf8..8a4b6a3 100644 --- a/src/driver/interrupt_dm.c +++ b/src/driver/interrupt_dm.c @@ -12,8 +12,8 @@ DriverResult interrupt_start(DeviceManager *manager, Device *device); DeviceManagerOps interrupt_dm_ops = { - .dm_load_hook = NULL, - .dm_unload_hook = NULL, + .dm_load = NULL, + .dm_unload = NULL, }; typedef struct InterruptDeviceManager { @@ -22,7 +22,7 @@ typedef struct InterruptDeviceManager { InterruptDeviceManager interrupt_dm_ext; -struct DeviceManager interrupt_device_manager = { +struct DeviceManager interrupt_dm = { .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, .ops = &interrupt_dm_ops, @@ -71,9 +71,9 @@ DriverResult register_interrupt_device( interrupt_device->device = device; DRV_RESULT_DELIVER_CALL(check_intterupt_ops, interrupt_device); - list_add_tail(&device->dm_list, &interrupt_device_manager.device_lh); + list_add_tail(&device->dm_list, &interrupt_dm.device_lh); - InterruptDeviceManager *manager = interrupt_device_manager.private_data; + InterruptDeviceManager *manager = interrupt_dm.private_data; if (manager->current_device) { if (interrupt_device->priority > manager->current_device->priority) { if (manager->current_device->device->state == DEVICE_STATE_ACTIVE) { @@ -94,7 +94,7 @@ DriverResult unregister_interrupt_device( DeviceDriver *device_driver, Device *device, InterruptDevice *interrupt_device) { - InterruptDeviceManager *manager = interrupt_device_manager.private_data; + InterruptDeviceManager *manager = interrupt_dm.private_data; Device *cur; DEV_OPS_CALL(device, stop, device); @@ -102,14 +102,13 @@ DriverResult unregister_interrupt_device( if (manager->current_device == interrupt_device) { // 寻找替代的设备 InterruptDevice *new_interrupt_device; - list_for_each_owner ( - cur, &interrupt_device_manager.device_lh, device_list) { + list_for_each_owner (cur, &interrupt_dm.device_lh, device_list) { if (cur != device) { if (new_interrupt_device == NULL) { - new_interrupt_device = cur->device_manager_extension; + new_interrupt_device = cur->dm_ext; } else { InterruptDevice *cur_interrupt_device = - (InterruptDevice *)cur->device_manager_extension; + (InterruptDevice *)cur->dm_ext; if (cur_interrupt_device->priority > new_interrupt_device->priority) { new_interrupt_device = cur_interrupt_device; @@ -151,13 +150,13 @@ DriverResult interrupt_dm_start() { } uint32_t interrupt_redirect_irq(int irq) { - InterruptDeviceManager *manager = interrupt_device_manager.private_data; + InterruptDeviceManager *manager = interrupt_dm.private_data; InterruptDevice *interrupt_device = manager->current_device; return interrupt_device->interrupt_ops->redirect_irq(interrupt_device, irq); } DriverResult interrupt_enable_irq(int irq) { - InterruptDeviceManager *manager = interrupt_device_manager.private_data; + InterruptDeviceManager *manager = interrupt_dm.private_data; InterruptDevice *interrupt_device = manager->current_device; DRV_RESULT_DELIVER_CALL( interrupt_device->interrupt_ops->enable_irq, interrupt_device, irq); @@ -165,7 +164,7 @@ DriverResult interrupt_enable_irq(int irq) { } DriverResult interrupt_disable_irq(int irq) { - InterruptDeviceManager *manager = interrupt_device_manager.private_data; + InterruptDeviceManager *manager = interrupt_dm.private_data; InterruptDevice *interrupt_device = manager->current_device; DRV_RESULT_DELIVER_CALL( interrupt_device->interrupt_ops->disable_irq, interrupt_device, irq); @@ -173,7 +172,7 @@ DriverResult interrupt_disable_irq(int irq) { } void interrupt_eoi(int irq) { - InterruptDeviceManager *manager = interrupt_device_manager.private_data; + InterruptDeviceManager *manager = interrupt_dm.private_data; InterruptDevice *interrupt_device = manager->current_device; interrupt_device->interrupt_ops->eoi(interrupt_device, irq); } diff --git a/src/driver/time_dm.c b/src/driver/time_dm.c new file mode 100644 index 0000000..1126d68 --- /dev/null +++ b/src/driver/time_dm.c @@ -0,0 +1,52 @@ +#include "kernel/list.h" +#include +#include +#include +#include +#include + +DriverResult timer_dm_load(DeviceManager *manager); +DriverResult timer_dm_unload(DeviceManager *manager); + +DeviceManagerOps time_dm_ops = { + .dm_load = timer_dm_load, + .dm_unload = timer_dm_unload, +}; + +TimeDeviceManager time_dm_ext; +DeviceManager time_dm = { + .type = DEVICE_TYPE_TIME, + .ops = &time_dm_ops, + .private_data = &time_dm_ext, +}; + +DriverResult time_dm_load(DeviceManager *manager) { + manager->private_data = kmalloc(sizeof(TimeDeviceManager)); + return DRIVER_RESULT_OK; +} + +DriverResult time_dm_unload(DeviceManager *manager) { + kfree(manager->private_data); + return DRIVER_RESULT_OK; +} + +DriverResult register_time_device( + DeviceDriver *driver, Device *device, TimeDevice *time_device) { + device->dm_ext = time_device; + time_device->device = device; + + list_add_tail(&device->dm_list, &time_dm.device_lh); + + if (time_dm_ext.time_devices[time_device->type] == NULL) { + time_dm_ext.time_devices[time_device->type] = time_device; + } + return DRIVER_RESULT_OK; +} + +DriverResult get_current_time(TimeType type, Time *time) { + TimeDevice *time_device = time_dm_ext.time_devices[type]; + if (time_device != NULL) { + return time_device->ops->get_time(time_device, type, time); + } + return DRIVER_RESULT_UNSUPPORT_DEVICE; +} diff --git a/src/driver/timer.c b/src/driver/timer.c index f493e50..e5bc16f 100644 --- a/src/driver/timer.c +++ b/src/driver/timer.c @@ -6,9 +6,8 @@ extern TimerDeviceManager timer_dm_ext; DriverResult timer_init(Timer *timer) { - timer->timer_device = - timer_dm_ext.scheduler_timer->device_manager_extension; - timer->timeout = 0; + timer->timer_device = timer_dm_ext.scheduler_timer->dm_ext; + timer->timeout = 0; return DRIVER_RESULT_OK; } diff --git a/src/driver/timer_dm.c b/src/driver/timer_dm.c index 03f4add..d8d2b93 100644 --- a/src/driver/timer_dm.c +++ b/src/driver/timer_dm.c @@ -14,8 +14,8 @@ DriverResult timer_dm_unload(DeviceManager *manager); DriverResult timer_device_init(DeviceManager *manager, Device *device); DeviceManagerOps timer_dm_ops = { - .dm_load_hook = timer_dm_load, - .dm_unload_hook = timer_dm_unload, + .dm_load = timer_dm_load, + .dm_unload = timer_dm_unload, .init_device_hook = timer_device_init, .start_device_hook = NULL, @@ -25,7 +25,7 @@ DeviceManagerOps timer_dm_ops = { TimerDeviceManager timer_dm_ext; -struct DeviceManager timer_device_manager = { +struct DeviceManager timer_dm = { .type = DEVICE_TYPE_TIMER, .ops = &timer_dm_ops, @@ -48,7 +48,7 @@ DriverResult timer_dm_unload(DeviceManager *manager) { } DriverResult timer_device_init(DeviceManager *manager, Device *device) { - TimerDevice *timer_device = (TimerDevice *)device->device_manager_extension; + TimerDevice *timer_device = (TimerDevice *)device->dm_ext; const int count = sizeof(default_frequencies) / sizeof(typeof(default_frequencies[0])); @@ -70,8 +70,7 @@ DriverResult timer_device_init(DeviceManager *manager, Device *device) { timer_manager->scheduler_timer = device; } else { TimerDevice *scheduler_timer_device = - (TimerDevice *) - timer_manager->scheduler_timer->device_manager_extension; + (TimerDevice *)timer_manager->scheduler_timer->dm_ext; if (scheduler_timer_device->priority < timer_device->priority) { timer_manager->scheduler_timer = device; } @@ -81,15 +80,14 @@ DriverResult timer_device_init(DeviceManager *manager, Device *device) { int timer_get_schedule_tick(int priority) { if (priority <= 0) { return 0; } - TimerDevice *timer_device = - (TimerDevice *)timer_device_manager.private_data; - int ticks = priority * timer_device->current_frequency / 1000; + TimerDevice *timer_device = (TimerDevice *)timer_dm.private_data; + int ticks = priority * timer_device->current_frequency / 1000; if (ticks == 0) { ticks = 1; } // 如果小于粒度,至少1个tick return ticks; } DriverResult timer_set_frequency(Device *device, uint32_t frequency) { - TimerDevice *timer_device = (TimerDevice *)device->device_manager_extension; + TimerDevice *timer_device = (TimerDevice *)device->dm_ext; TimerResult result = timer_device->timer_ops->set_frequency(timer_device, frequency); @@ -101,7 +99,7 @@ DriverResult timer_set_frequency(Device *device, uint32_t frequency) { } void timer_irq_handler(Device *device) { - TimerDevice *timer_device = (TimerDevice *)device->device_manager_extension; + TimerDevice *timer_device = (TimerDevice *)device->dm_ext; timer_device->counter++; Timer *cur, *next; @@ -133,11 +131,11 @@ void timer_irq_handler(Device *device) { DriverResult register_timer_device( DeviceDriver *device_driver, Device *device, TimerDevice *timer_device) { - device->device_manager_extension = timer_device; - timer_device->device = device; + device->dm_ext = timer_device; + timer_device->device = device; list_init(&timer_device->timer_list_lh); - list_add_tail(&device->dm_list, &timer_device_manager.device_lh); + list_add_tail(&device->dm_list, &timer_dm.device_lh); return DRIVER_RESULT_OK; } diff --git a/src/driver/video_dm.c b/src/driver/video_dm.c index b5b7b2d..fcb77e8 100644 --- a/src/driver/video_dm.c +++ b/src/driver/video_dm.c @@ -10,8 +10,8 @@ DriverResult video_device_start(DeviceManager *manager, Device *device); DeviceManagerOps video_dm_ops = { - .dm_load_hook = NULL, - .dm_unload_hook = NULL, + .dm_load = NULL, + .dm_unload = NULL, .init_device_hook = NULL, .start_device_hook = video_device_start, @@ -21,7 +21,7 @@ DeviceManagerOps video_dm_ops = { VideoDeviceManager video_dm_ext; -struct DeviceManager video_device_manager = { +struct DeviceManager video_dm = { .type = DEVICE_TYPE_VIDEO, .ops = &video_dm_ops, @@ -45,10 +45,8 @@ DriverResult video_dm_unload(DeviceManager *manager) { DriverResult register_video_device( DeviceDriver *device_driver, Device *device, VideoDevice *video_device) { - device->device_manager_extension = video_device; - if (device->device_manager_extension == NULL) { - return DRIVER_RESULT_OUT_OF_MEMORY; - } + device->dm_ext = video_device; + if (device->dm_ext == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } video_device->device = device; string_t name; @@ -59,7 +57,7 @@ DriverResult register_video_device( register_device, device_driver, name, device_driver->bus, device); list_init(&video_device->video_list_lh); - list_add_tail(&device->dm_list, &video_device_manager.device_lh); + list_add_tail(&device->dm_list, &video_dm.device_lh); return DRIVER_RESULT_OK; } @@ -71,7 +69,7 @@ DriverResult unregister_video_devce( } DriverResult video_device_start(DeviceManager *manager, Device *device) { - VideoDevice *video_device = (VideoDevice *)device->device_manager_extension; + VideoDevice *video_device = (VideoDevice *)device->dm_ext; if (video_dm_ext.main_display_device == NULL) { video_dm_ext.main_display_device = device; @@ -97,15 +95,14 @@ DriverResult video_device_start(DeviceManager *manager, Device *device) { DriverResult video_get_video_device(int in_index, VideoDevice **out_device) { Device *device; if (in_index == 0) { - *out_device = - video_dm_ext.main_display_device->device_manager_extension; + *out_device = video_dm_ext.main_display_device->dm_ext; return DRIVER_RESULT_OK; } int i = 0; - list_for_each_owner (device, &video_device_manager.device_lh, dm_list) { + list_for_each_owner (device, &video_dm.device_lh, dm_list) { if (device == video_dm_ext.main_display_device) { continue; } if (i == in_index) { - *out_device = device->device_manager_extension; + *out_device = device->dm_ext; return DRIVER_RESULT_OK; } i++; diff --git a/src/include/driver/interrupt_dm.h b/src/include/driver/interrupt_dm.h index 29312f9..a6a8279 100644 --- a/src/include/driver/interrupt_dm.h +++ b/src/include/driver/interrupt_dm.h @@ -26,7 +26,7 @@ DriverResult register_interrupt_device( DeviceDriver *device_driver, Device *device, InterruptDevice *interrupt_device); -extern struct DeviceManager interrupt_device_manager; +extern struct DeviceManager interrupt_dm; DriverResult interrupt_dm_start(); uint32_t interrupt_redirect_irq(int irq); diff --git a/src/include/driver/storage/storage_dm.h b/src/include/driver/storage/storage_dm.h index 5a4eb50..34da1fd 100644 --- a/src/include/driver/storage/storage_dm.h +++ b/src/include/driver/storage/storage_dm.h @@ -4,7 +4,9 @@ #include "kernel/device_driver.h" #include "kernel/device_manager.h" #include "kernel/driver.h" +#include "kernel/list.h" #include "kernel/periodic_task.h" +#include "string.h" #include typedef enum StorageDeviceType { @@ -27,6 +29,8 @@ typedef struct StorageDevice { StorageDeviceType type; StorageDeviceOps *ops; + string_t name; + uint32_t block_size; PeriodicTask periodic_task; @@ -34,6 +38,8 @@ typedef struct StorageDevice { uint8_t *superblock; + list_t block_cache_lh; + // 存储设备的分区目录对象 Object *object; } StorageDevice; @@ -45,7 +51,7 @@ typedef struct StorageDeviceDriver { StorageDeviceOps *ops; } StorageDeviceDriver; -extern DeviceManager storage_device_manager; +extern DeviceManager storage_dm; DriverResult register_storage_device( DeviceDriver *device_driver, Device *device, StorageDevice *storage_device); diff --git a/src/include/driver/time_dm.h b/src/include/driver/time_dm.h new file mode 100644 index 0000000..e72152c --- /dev/null +++ b/src/include/driver/time_dm.h @@ -0,0 +1,53 @@ +#ifndef _TIME_DM_H +#define _TIME_DM_H + +#include "kernel/device_driver.h" +#include "kernel/device_manager.h" + +typedef enum TimeType { + TIME_TYPE_UNIX_TIMESTAMP, // Unix时间戳 + TIME_TYPE_UTC, // UTC时间 + TIME_TYPE_LOCAL, // 本地时间 + TIME_TYPE_MAX, +} TimeType; + +typedef struct TimeUTC { + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; +} TimeFull; + +typedef union Time { + uint32_t timestamp; + TimeFull time; +} Time; + +struct TimeDevice; +typedef struct TimeDeviceOps { + DriverResult (*get_time)( + struct TimeDevice *device, TimeType type, Time *time); + DriverResult (*set_time)( + struct TimeDevice *device, TimeType type, Time *time); +} TimeDeviceOps; + +typedef struct TimeDevice { + Device *device; + TimeType type; + TimeDeviceOps *ops; +} TimeDevice; + +typedef struct TimeDeviceManager { + TimeDevice *time_devices[TIME_TYPE_MAX]; +} TimeDeviceManager; + +extern DeviceManager time_dm; + +DriverResult register_time_device( + DeviceDriver *driver, Device *device, TimeDevice *time_device); + +DriverResult get_current_time(TimeType type, Time *time); + +#endif \ No newline at end of file diff --git a/src/include/driver/timer_dm.h b/src/include/driver/timer_dm.h index 8cdd0d7..caac4bb 100644 --- a/src/include/driver/timer_dm.h +++ b/src/include/driver/timer_dm.h @@ -53,7 +53,7 @@ typedef struct TimerDeviceManager { Device *scheduler_timer; } TimerDeviceManager; -extern struct DeviceManager timer_device_manager; +extern struct DeviceManager timer_dm; DriverResult register_timer_device( DeviceDriver *device_driver, Device *device, TimerDevice *timer_device); diff --git a/src/include/driver/video_dm.h b/src/include/driver/video_dm.h index 2e2cc73..b44dbfa 100644 --- a/src/include/driver/video_dm.h +++ b/src/include/driver/video_dm.h @@ -29,7 +29,7 @@ typedef struct VideoDeviceManager { uint8_t video_device_count; } VideoDeviceManager; -extern struct DeviceManager video_device_manager; +extern struct DeviceManager video_dm; DriverResult register_video_device( DeviceDriver *device_driver, Device *device, VideoDevice *video_device); diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index 16d429e..32541a0 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -22,7 +22,7 @@ typedef enum { DEVICE_TYPE_UNKNOWN = 0, DEVICE_TYPE_INTERRUPT_CONTROLLER, - DEVICE_TYPE_TIMER, + DEVICE_TYPE_TIMER, // 定时器设备 DEVICE_TYPE_VIDEO, DEVICE_TYPE_STORAGE, DEVICE_TYPE_MOUSE, @@ -30,6 +30,7 @@ typedef enum { DEVICE_TYPE_SOUND, DEVICE_TYPE_BUS_CONTROLLER, DEVICE_TYPE_ETHERNET, + DEVICE_TYPE_TIME, // 时间设备(如:Unix时间戳/UTC时间) DEVICE_TYPE_MAX, } DeviceType; @@ -83,7 +84,7 @@ typedef struct Device { void *private_data; uint32_t private_data_size; - void *device_manager_extension; // 设备管理器所需的扩展信息 + void *dm_ext; // 设备管理器所需的扩展信息 } Device; DriverResult register_device( diff --git a/src/include/kernel/device_manager.h b/src/include/kernel/device_manager.h index 69172ab..489ebf9 100644 --- a/src/include/kernel/device_manager.h +++ b/src/include/kernel/device_manager.h @@ -15,8 +15,8 @@ struct DeviceManager; typedef struct DeviceMangerOps { - DriverResult (*dm_load_hook)(struct DeviceManager *manager); - DriverResult (*dm_unload_hook)(struct DeviceManager *manager); + DriverResult (*dm_load)(struct DeviceManager *manager); + DriverResult (*dm_unload)(struct DeviceManager *manager); DriverResult (*init_device_hook)( struct DeviceManager *manager, Device *device); diff --git a/src/include/objects/transfer.h b/src/include/objects/transfer.h index 0bd7616..80f662c 100644 --- a/src/include/objects/transfer.h +++ b/src/include/objects/transfer.h @@ -65,16 +65,24 @@ typedef struct TransferOut { }; } TransferOut; -#define TRANSFER_IN_BLOCK(object) ((object)->in.block) -#define TRANSFER_IN_STREAM(object) ((object)->in.stream) -#define TRANSFER_IN_INTTERRUPT(object) ((object)->in.interrupt) +#define TRANSFER_IN_BLOCK(object, ...) \ + ((object)->in.block(object, TRANSFER_IN, __VA_ARGS__)) +#define TRANSFER_IN_STREAM(object, ...) \ + ((object)->in.stream(object, TRANSFER_IN, __VA_ARGS__)) +#define TRANSFER_IN_INTTERRUPT(object, ...) \ + ((object)->in.interrupt(object, __VA_ARGS__)) -#define TRANSFER_IN_IS_DONE(object) ((object)->in.is_transfer_done) +#define TRANSFER_IN_IS_DONE(object, ...) \ + ((object)->in.is_transfer_done(object, __VA_ARGS__)) -#define TRANSFER_OUT_BLOCK(object) ((object)->in.block) -#define TRANSFER_OUT_STREAM(object) ((object)->in.stream) -#define TRANSFER_OUT_INTTERRUPT(object) ((object)->in.interrupt) +#define TRANSFER_OUT_BLOCK(object, ...) \ + ((object)->in.block(object, TRANSFER_OUT, __VA_ARGS__)) +#define TRANSFER_OUT_STREAM(object, ...) \ + ((object)->in.stream(object, TRANSFER_OUT, __VA_ARGS__)) +#define TRANSFER_OUT_INTTERRUPT(object, ...) \ + ((object)->in.interrupt(object, __VA_ARGS__)) -#define TRANSFER_OUT_IS_DONE(object) ((object)->in.is_transfer_done) +#define TRANSFER_OUT_IS_DONE(object, ...) \ + ((object)->in.is_transfer_done(object, __VA_ARGS__)) #endif \ No newline at end of file diff --git a/src/kernel/device_driver.c b/src/kernel/device_driver.c index 979d8de..23f3246 100644 --- a/src/kernel/device_driver.c +++ b/src/kernel/device_driver.c @@ -36,7 +36,7 @@ DriverResult device_driver_manager_load(DriverManager *driver_manager) { for (int i = 0; i < DEVICE_TYPE_MAX; i++) { DeviceManager *device_manager = device_managers[i]; if (device_manager != NULL) { - DEVM_OPS_CALL(device_manager, dm_load_hook, device_manager); + DEVM_OPS_CALL(device_manager, dm_load, device_manager); } } @@ -47,7 +47,7 @@ DriverResult device_driver_manager_unload(DriverManager *driver_manager) { for (int i = 0; i < DEVICE_TYPE_MAX; i++) { DeviceManager *device_manager = device_managers[i]; if (device_manager != NULL) { - DEVM_OPS_CALL(device_manager, dm_unload_hook, device_manager); + DEVM_OPS_CALL(device_manager, dm_unload, device_manager); } } diff --git a/src/kernel/device_manager.c b/src/kernel/device_manager.c index 55174ae..600c98f 100644 --- a/src/kernel/device_manager.c +++ b/src/kernel/device_manager.c @@ -16,7 +16,7 @@ DriverResult register_device_manager(DeviceManager *manager) { list_init(&manager->device_lh); device_managers[manager->type] = manager; - DEVM_OPS_CALL(manager, dm_load_hook, manager); + DEVM_OPS_CALL(manager, dm_load, manager); return DRIVER_RESULT_OK; } @@ -28,7 +28,7 @@ DriverResult unregister_device_manager(DeviceManager *manager) { DEV_OPS_CALL(cur, destroy, cur); } } - DEVM_OPS_CALL(manager, dm_unload_hook, manager); + DEVM_OPS_CALL(manager, dm_unload, manager); // 从链表中删除 list_del(&manager->dm_list); diff --git a/src/kernel/driver.c b/src/kernel/driver.c index deb3b70..17daee2 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -28,14 +28,14 @@ LIST_HEAD(driver_list_head); struct index_node *dev; -struct file_operations device_fops = { - .open = dev_open, - .close = dev_close, - .read = dev_read, - .write = dev_write, - .ioctl = dev_ioctl, - .seek = fs_seek, -}; +// struct file_operations device_fops = { +// .open = dev_open, +// .close = dev_close, +// .read = dev_read, +// .write = dev_write, +// .ioctl = dev_ioctl, +// .seek = fs_seek, +// }; // --------new-------- #include @@ -98,7 +98,7 @@ DriverResult register_sub_driver( sub_driver->state = SUBDRIVER_STATE_UNREADY; sub_driver->type = type; - wait_queue_init(&sub_driver->wqm); + wait_queue_init(&sub_driver->wq); list_add(&sub_driver->sub_driver_list, &driver->sub_driver_lh); return DRIVER_RESULT_OK; @@ -151,7 +151,7 @@ void sub_driver_start_thread(void *arg) { SUBDRIVER_STATE_READY) { schedule(); } - wait_queue_wakeup_all(&bus_driver->subdriver.wqm); + wait_queue_wakeup_all(&bus_driver->subdriver.wq); if (bus->ops->scan_bus != NULL) { bus->ops->scan_bus(bus_driver, bus); } @@ -204,10 +204,10 @@ DriverResult driver_start_all(void) { // --------old--------- struct index_node *dev_open(char *path) { - struct index_node *inode = vfs_open(path); - if (inode == NULL) return NULL; - else inode->device->drv_obj->function.driver_open(inode->device); - return inode; + // struct index_node *inode = vfs_open(path); + // if (inode == NULL) return NULL; + // else inode->device->drv_obj->function.driver_open(inode->device); + // return inode; } int dev_close(struct index_node *inode) { @@ -289,9 +289,9 @@ status_t device_create( eth_dm.dm_register(ð_dm, devobj, name); driver->dm = ð_dm; } else { - devobj->inode = vfs_create(name, ATTR_DEV, dev); + // devobj->inode = vfs_create(name, ATTR_DEV, dev); devobj->inode->device = devobj; - devobj->inode->f_ops = device_fops; + // devobj->inode->f_ops = device_fops; devobj->inode->fp = kmalloc(sizeof(struct file)); } diff --git a/src/kernel/driver_dependency.c b/src/kernel/driver_dependency.c index 1d0a8f2..d871345 100644 --- a/src/kernel/driver_dependency.c +++ b/src/kernel/driver_dependency.c @@ -21,7 +21,7 @@ DriverResult check_dependency(Driver *driver) { if (bus_driver == NULL || bus_driver->subdriver.state != SUBDRIVER_STATE_READY) { // 总线驱动还没准备好则等待 - wait_queue_add(&bus_driver->subdriver.wqm, 0); + wait_queue_add(&bus_driver->subdriver.wq); thread_block(TASK_BLOCKED); bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; } From 1546a4e8b132ea49408b5adf92b7aa2a9fc81f2f Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 7 Mar 2025 00:36:43 +0800 Subject: [PATCH 027/158] =?UTF-8?q?[WIP]=E9=87=8D=E6=9E=84=20FAT32?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8=E7=A8=8B=E5=BA=8F=EF=BC=9B=20[WIP]=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20=E5=88=86=E5=8C=BA=E8=AF=86=E5=88=AB=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=9B=20=E6=96=B0=E5=A2=9E=20=E5=AF=B9=E8=B1=A1?= =?UTF-8?q?=E6=8C=82=E8=BD=BD=E5=8A=9F=E8=83=BD=EF=BC=9B=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20=E5=9D=97=E7=BC=93=E5=AD=98=EF=BC=9B=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=20=E5=AF=B9=E8=B1=A1=E7=B3=BB=E7=BB=9F=E9=87=87?= =?UTF-8?q?=E7=94=A8=E9=93=BE=E8=A1=A8=E5=AD=98=E5=82=A8=E5=AD=90=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=EF=BC=9B=20=E6=96=B0=E5=A2=9E=20=E5=AF=B9=E8=B1=A1?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=BB=9F=E4=B8=80=E7=9A=84=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=EF=BC=9B=20=E6=96=B0=E5=A2=9E=20=E6=9D=A1?= =?UTF-8?q?=E4=BB=B6=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/stddef.h | 5 +- src/driver/storage/Makefile | 3 +- src/driver/storage/disk/disk.c | 38 +- src/driver/storage/disk/mbr.c | 9 +- src/driver/storage/storage_dm.c | 31 +- src/driver/storage/storage_io.c | 37 +- src/driver/storage/storage_io_queue.c | 28 +- src/driver/storage/volume.c | 43 ++ src/fs/Makefile | 6 +- src/fs/fat/Makefile | 6 + src/fs/fat/cluster.c | 247 +++++++ src/fs/fat/dir.c | 131 ++++ src/fs/fat/entry.c | 298 ++++++++ src/fs/fat/fat.c | 305 ++++++++ src/fs/fat/include/cluster.h | 48 ++ src/fs/fat/include/dir.h | 82 +++ src/fs/fat/include/entry.h | 25 + src/fs/fat/include/fat.h | 99 +++ src/fs/fat/include/name.h | 40 ++ src/fs/fat/include/time.h | 8 + src/fs/fat/name.c | 433 ++++++++++++ src/fs/fat32.c | 843 ----------------------- src/fs/fs.c | 206 ++---- src/include/driver/storage/disk/disk.h | 31 +- src/include/driver/storage/disk/mbr.h | 10 +- src/include/driver/storage/disk/volume.h | 8 + src/include/driver/storage/storage_dm.h | 10 +- src/include/driver/storage/storage_io.h | 5 +- src/include/fs/fat32.h | 126 ---- src/include/fs/fs.h | 132 ++-- src/include/kernel/block_cache.h | 48 ++ src/include/kernel/condvar.h | 25 +- src/include/kernel/device.h | 8 +- src/include/kernel/device_driver.h | 4 +- src/include/kernel/driver.h | 2 +- src/include/kernel/rwlock.h | 54 +- src/include/multiple_return.h | 7 + src/include/network/arp.h | 2 +- src/include/objects/mount.h | 8 + src/include/objects/object.h | 23 +- src/include/objects/ops.h | 18 + src/include/objects/transfer.h | 23 +- src/include/string.h | 3 + src/include/types.h | 3 + src/kernel/Makefile | 3 + src/kernel/app.c | 44 +- src/kernel/block_cache.c | 127 ++++ src/kernel/bus_driver.c | 4 +- src/kernel/condvar.c | 22 + src/kernel/main.c | 29 +- src/kernel/rwlock.c | 63 ++ src/kernel/syscall.c | 56 +- src/lib/string.c | 29 + src/network/arp.c | 6 +- src/objects/Makefile | 4 +- src/objects/mount.c | 14 + src/objects/objects.c | 102 ++- src/objects/ops.c | 70 ++ src/objects/types.c | 10 +- 59 files changed, 2641 insertions(+), 1463 deletions(-) create mode 100644 src/driver/storage/volume.c create mode 100644 src/fs/fat/Makefile create mode 100644 src/fs/fat/cluster.c create mode 100644 src/fs/fat/dir.c create mode 100644 src/fs/fat/entry.c create mode 100644 src/fs/fat/fat.c create mode 100644 src/fs/fat/include/cluster.h create mode 100644 src/fs/fat/include/dir.h create mode 100644 src/fs/fat/include/entry.h create mode 100644 src/fs/fat/include/fat.h create mode 100644 src/fs/fat/include/name.h create mode 100644 src/fs/fat/include/time.h create mode 100644 src/fs/fat/name.c delete mode 100644 src/fs/fat32.c create mode 100644 src/include/driver/storage/disk/volume.h delete mode 100644 src/include/fs/fat32.h create mode 100644 src/include/kernel/block_cache.h create mode 100644 src/include/multiple_return.h create mode 100644 src/include/objects/mount.h create mode 100644 src/include/objects/ops.h create mode 100644 src/kernel/block_cache.c create mode 100644 src/kernel/condvar.c create mode 100644 src/kernel/rwlock.c create mode 100644 src/objects/mount.c create mode 100644 src/objects/ops.c diff --git a/include/stddef.h b/include/stddef.h index 6171f2a..d3b5cb5 100644 --- a/include/stddef.h +++ b/include/stddef.h @@ -13,8 +13,6 @@ */ /* 32位操作系统 */ -typedef unsigned int size_t; -typedef int ssize_t; typedef unsigned int ino_t; @@ -26,14 +24,13 @@ typedef unsigned int dma_addr_t; /* 64位操作系统 */ /* typedef unsigned long flags_t; -typedef unsigned long size_t; typedef unsigned long register_t; typedef unsigned long address_t; */ typedef unsigned char *buf8_t; // 字节类型的缓冲区 typedef unsigned short *buf16_t; // 字类型的缓冲区 -typedef unsigned int *buf32_t; // 双字类型的缓冲区 +typedef unsigned int *buf32_t; // 双字类型的缓冲区 /* *这里是define类型的 diff --git a/src/driver/storage/Makefile b/src/driver/storage/Makefile index 3334b47..c889628 100644 --- a/src/driver/storage/Makefile +++ b/src/driver/storage/Makefile @@ -1,4 +1,5 @@ SRC += disk/ SRC += storage_dm.c SRC += storage_io_queue.c -SRC += storage_io.c \ No newline at end of file +SRC += storage_io.c +SRC += volume.c \ No newline at end of file diff --git a/src/driver/storage/disk/disk.c b/src/driver/storage/disk/disk.c index 2f142e2..e0f3824 100644 --- a/src/driver/storage/disk/disk.c +++ b/src/driver/storage/disk/disk.c @@ -3,38 +3,54 @@ #include #include +TransferResult disk_transfer_in_async( + Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count, void **handle) { + Partition *partition = object->value.partition; + + return TRANSFER_IN_BLOCK_ASYNC( + partition->storage_object, buf, position + partition->start_lba, count, + handle); +} + TransferResult disk_transfer_in( + Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count) { + Partition *partition = object->value.partition; + + return TRANSFER_IN_BLOCK( + partition->storage_object, buf, position + partition->start_lba, count); +} + +TransferResult disk_transfer_out_async( Object *object, TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, void **handle) { Partition *partition = object->value.partition; - return TRANSFER_IN_BLOCK(partition->storage_object)( - partition->storage_object, direction, buf, - position + partition->start_lba, count, handle); + return TRANSFER_OUT_BLOCK_ASYNC( + partition->storage_object, buf, position + partition->start_lba, count, + handle); } TransferResult disk_transfer_out( Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count, void **handle) { + uint32_t position, size_t count) { Partition *partition = object->value.partition; - return TRANSFER_OUT_BLOCK(partition->storage_object)( - partition->storage_object, direction, buf, - position + partition->start_lba, count, handle); + return TRANSFER_OUT_BLOCK( + partition->storage_object, buf, position + partition->start_lba, count); } TransferResult disk_is_transfer_in_done( Object *object, void **handle, bool *is_done) { Partition *partition = object->value.partition; - return TRANSFER_IN_IS_DONE(partition->storage_object)( - partition->storage_object, handle, is_done); + return TRANSFER_IN_IS_DONE(partition->storage_object, handle, is_done); } TransferResult disk_is_transfer_out_done( Object *object, void **handle, bool *is_done) { Partition *partition = object->value.partition; - return TRANSFER_OUT_IS_DONE(partition->storage_object)( - partition->storage_object, handle, is_done); + return TRANSFER_OUT_IS_DONE(partition->storage_object, handle, is_done); } diff --git a/src/driver/storage/disk/mbr.c b/src/driver/storage/disk/mbr.c index 287bec5..1729b5e 100644 --- a/src/driver/storage/disk/mbr.c +++ b/src/driver/storage/disk/mbr.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -21,7 +22,7 @@ void parse_mbr_partition_table(StorageDevice *storage_device) { ->superblock[MBR_PARTITION_TABLE_OFFSET]; for (int i = 0; i < MBR_PARTITION_COUNT; i++) { - if (partition_table[i].sign != 0) { + if (partition_table[i].fs_type != 0) { string_t name; string_new_with_number(&name, "Partition", 9, partition_count); Object *object = create_object( @@ -33,15 +34,21 @@ void parse_mbr_partition_table(StorageDevice *storage_device) { partition->start_lba = partition_table[i].start_lba; partition->size_lba = partition_table[i].size; partition->mbr = &partition_table[i]; + partition->index = partition_count; + partition->object = object; object->value.partition = partition; object->in.type = TRANSFER_TYPE_BLOCK; object->in.block = disk_transfer_in; + object->in.block_async = disk_transfer_in_async; object->in.is_transfer_done = disk_is_transfer_in_done; object->out.type = TRANSFER_TYPE_BLOCK; object->out.block = disk_transfer_out; + object->out.block_async = disk_transfer_out_async; object->out.is_transfer_done = disk_is_transfer_out_done; + probe_volume(partition); + partition_count++; } } diff --git a/src/driver/storage/storage_dm.c b/src/driver/storage/storage_dm.c index d898432..98f4e13 100644 --- a/src/driver/storage/storage_dm.c +++ b/src/driver/storage/storage_dm.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -23,8 +24,8 @@ extern void storage_periodic_task(void *arg); DriverResult start_storage_device(DeviceManager *manager, Device *device); DeviceManagerOps storage_dm_ops = { - .dm_load_hook = NULL, - .dm_unload_hook = NULL, + .dm_load = NULL, + .dm_unload = NULL, .start_device_hook = start_storage_device, .stop_device_hook = NULL, }; @@ -35,7 +36,7 @@ typedef struct StorageDeviceManager { StorageDeviceManager storage_dm_ext; -struct DeviceManager storage_device_manager = { +struct DeviceManager storage_dm = { .type = DEVICE_TYPE_STORAGE, .ops = &storage_dm_ops, @@ -48,22 +49,27 @@ DriverResult register_storage_device( StorageDevice *storage_device) { storage_device->device = device; - device->device_manager_extension = storage_device; + device->dm_ext = storage_device; list_init(&storage_device->io_queue_lh); string_t name; string_new_with_number(&name, "Storage", 7, storage_dm_ext.device_count++); DRV_RESULT_DELIVER_CALL( register_device, device_driver, name, device->bus, device); - list_add_tail(&device->dm_list, &storage_device_manager.device_lh); + list_add_tail(&device->dm_list, &storage_dm.device_lh); + device->object->in.type = TRANSFER_TYPE_BLOCK; device->object->in.block = storage_transfer; + device->object->in.block_async = storage_transfer_async; device->object->in.is_transfer_done = storage_is_transfer_done; + device->object->out.type = TRANSFER_TYPE_BLOCK; device->object->out.block = storage_transfer; + device->object->out.block_async = storage_transfer_async; device->object->out.is_transfer_done = storage_is_transfer_done; storage_device->periodic_task.func = storage_periodic_task; storage_device->periodic_task.arg = storage_device; + storage_device->name = name; periodic_task_add(&storage_device->periodic_task); storage_device->object = create_object_directory(&device_object, name); @@ -81,21 +87,20 @@ DriverResult unregister_storage_device( } DriverResult start_storage_device(DeviceManager *manager, Device *device) { - StorageDevice *storage_device = device->device_manager_extension; - void *handle; + StorageDevice *storage_device = device->dm_ext; + storage_device->superblock = kmalloc(2 * 512); storage_transfer( - device->object, TRANSFER_IN, storage_device->superblock, 0, 2, &handle); - - bool is_done; - do { - storage_is_transfer_done(device->object, &handle, &is_done); - } while (!is_done); + device->object, TRANSFER_IN, storage_device->superblock, 0, 2); if (storage_device->type == STORAGE_DEVICE_TYPE_HARDDISK) { if (disk_is_mbr(storage_device)) { parse_mbr_partition_table(storage_device); } + list_init(&storage_device->block_cache_lh); + } else { + storage_device->block_cache_lh.next = NULL; + storage_device->block_cache_lh.prev = NULL; } return DRIVER_RESULT_OK; } diff --git a/src/driver/storage/storage_io.c b/src/driver/storage/storage_io.c index 1a1efe4..2b57706 100644 --- a/src/driver/storage/storage_io.c +++ b/src/driver/storage/storage_io.c @@ -2,20 +2,25 @@ * 默认的存储设备IO实现 */ #include "kernel/device.h" +#include "kernel/thread.h" #include #include #include +#include #include #include #include -TransferResult storage_transfer( +TransferResult storage_transfer_async( Object *object, TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, void **handle) { + while (object->type == OBJECT_TYPE_SYM_LINK) { + object = object->value.sym_link; + } Device *device = object->value.device; StorageRequest *request = kmalloc(sizeof(StorageRequest)); - request->storage_device = device->device_manager_extension; + request->storage_device = device->dm_ext; request->rw = (direction == TRANSFER_IN) ? 0 : 1; request->buf = buf; request->position = position; @@ -24,7 +29,31 @@ TransferResult storage_transfer( *handle = (void *)request; - storage_add_request(device->device_manager_extension, request); + storage_add_request(device->dm_ext, request); + return TRANSFER_OK; +} + +TransferResult storage_transfer( + Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count) { + while (object->type == OBJECT_TYPE_SYM_LINK) { + object = object->value.sym_link; + } + Device *device = object->value.device; + StorageRequest *request = kmalloc(sizeof(StorageRequest)); + + request->storage_device = device->dm_ext; + request->rw = (direction == TRANSFER_IN) ? 0 : 1; + request->buf = buf; + request->position = position; + request->count = count; + request->is_finished = 0; + + storage_add_request(device->dm_ext, request); + + while (!request->is_finished) { + schedule(); + } return TRANSFER_OK; } @@ -38,7 +67,7 @@ TransferResult storage_is_transfer_done( if (device->device_driver->type != DEVICE_TYPE_STORAGE) { return TRANSFER_ERROR_INVALID_PARAMETER; } - StorageDevice *storage_device = device->device_manager_extension; + StorageDevice *storage_device = device->dm_ext; StorageRequest *req = *handle; if (req->storage_device != storage_device || done == NULL) { diff --git a/src/driver/storage/storage_io_queue.c b/src/driver/storage/storage_io_queue.c index 2680ce6..dd5745f 100644 --- a/src/driver/storage/storage_io_queue.c +++ b/src/driver/storage/storage_io_queue.c @@ -1,3 +1,5 @@ +#include "kernel/block_cache.h" +#include "kernel/rwlock.h" #include #include #include @@ -55,6 +57,10 @@ void storage_add_request( StorageRequest *req; request->storage_device = storage_device; request->is_finished = 0; + if (list_empty(&storage_device->io_queue_lh)) { + storage_submit_request(request); + return; + } list_for_each_owner (req, &storage_device->io_queue_lh, list) { if (storage_try_merge_request(request, req)) { return; } if (req->position > request->position) { @@ -68,11 +74,23 @@ void storage_add_request( void storage_periodic_task(void *arg) { StorageDevice *storage_device = (StorageDevice *)arg; - if (!storage_device->ops->is_busy(storage_device) && - !list_empty(&storage_device->io_queue_lh)) { - StorageRequest *request = list_first_owner( - &storage_device->io_queue_lh, StorageRequest, list); - storage_submit_request(request); + if (!storage_device->ops->is_busy(storage_device)) { + if (!list_empty(&storage_device->io_queue_lh)) { + StorageRequest *request = list_first_owner( + &storage_device->io_queue_lh, StorageRequest, list); + storage_submit_request(request); + } else if ( + storage_device->block_cache_lh.next != NULL && + !list_empty(&storage_device->block_cache_lh)) { + BlockCacheEntry *entry = list_first_owner( + &storage_device->block_cache_lh, BlockCacheEntry, list); + rwlock_read_lock(&entry->lock); + entry->cache->write( + entry, entry->cache->size, entry->cache->private_data); + list_del(&entry->list); + entry->dirty = false; + rwlock_read_unlock(&entry->lock); + } } } diff --git a/src/driver/storage/volume.c b/src/driver/storage/volume.c new file mode 100644 index 0000000..250b10d --- /dev/null +++ b/src/driver/storage/volume.c @@ -0,0 +1,43 @@ +#include "objects/object.h" +#include "string.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void probe_volume(Partition *partition) { + Object *object = partition->storage_object; + StorageDevice *storage_device = + partition->storage_object->value.device->dm_ext; + string_t prefix = storage_device->name; + partition->superblock = kmalloc(2 * SECTOR_SIZE); + + storage_transfer( + object, TRANSFER_IN, partition->superblock, partition->start_lba, 2); + + if (partition->type == PARTITION_TYPE_MBR) { + FileSystem *fs; + list_for_each_owner (fs, &fs_list_head, list) { + if (fs->ops->fs_check(partition) == FS_OK) { + FileSystemInfo *fs_info = kmalloc(sizeof(FileSystemInfo)); + fs_info->partition = partition; + fs_info->ops = fs->ops; + string_t name; + string_new_with_string_number( + &name, prefix.text, prefix.length - 1, "Volume", 6, + partition->index); + Object *root_object = + create_object_directory(&volumes_object, name); + partition->object->fs_info = fs_info; + + object_mount(partition->object, root_object); + break; + } + } + } +} \ No newline at end of file diff --git a/src/fs/Makefile b/src/fs/Makefile index 50c90e4..5d0ed13 100644 --- a/src/fs/Makefile +++ b/src/fs/Makefile @@ -1,3 +1,5 @@ -SRC += fat32.c +# SRC += fat32.c SRC += fs.c -SRC += vfs.c \ No newline at end of file +# SRC += vfs.c + +SRC += fat/ \ No newline at end of file diff --git a/src/fs/fat/Makefile b/src/fs/fat/Makefile new file mode 100644 index 0000000..b4b090f --- /dev/null +++ b/src/fs/fat/Makefile @@ -0,0 +1,6 @@ +SRC += fat.c +SRC += cluster.c +SRC += dir.c +SRC += name.c +SRC += entry.c +SRC += time.c \ No newline at end of file diff --git a/src/fs/fat/cluster.c b/src/fs/fat/cluster.c new file mode 100644 index 0000000..f7a7dbf --- /dev/null +++ b/src/fs/fat/cluster.c @@ -0,0 +1,247 @@ +#include "include/cluster.h" +#include "const.h" +#include "include/dir.h" +#include "include/fat.h" +#include "multiple_return.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +inline uint32_t cluster2sector(FatInfo *fat_info, uint32_t cluster) { + return fat_info->data_start + (cluster - 2) * fat_info->bpb->BPB_SecPerClus; +} + +FsResult fat_table_read( + BlockCacheEntry *entry, size_t cache_size, void *private_data) { + FatInfo *fat_info = private_data; + Partition *partition = fat_info->partition; + + int count = cache_size / SECTOR_SIZE; + + TRANSFER_IN_BLOCK( + partition->storage_object, entry->data, + fat_info->fat_start + entry->position, count); + return FS_OK; +} + +FsResult fat_table_write( + BlockCacheEntry *entry, size_t cache_size, void *private_data) { + FatInfo *fat_info = private_data; + Partition *partition = fat_info->partition; + + int count = cache_size / SECTOR_SIZE; + + for (int i = 0; i < fat_info->bpb->BPB_NumFATs; i++) { + TRANSFER_OUT_BLOCK( + partition->storage_object, entry->data, + fat_info->fat_start + entry->position, count); + } + + return FS_OK; +} + +uint32_t get_next_cluster(FatInfo *fat_info, uint32_t cluster) { + uint32_t index = cluster / fat_info->num_count; + uint32_t offset = cluster % fat_info->num_count; + + BlockCacheEntry *entry = block_cache_read(fat_info->fat_table_cache, index); + if (entry == NULL) return 0xffffffff; + uint32_t data = 0xffffffff; + if (fat_info->type == FAT_TYPE_FAT32) { + data = ((uint32_t *)entry->data)[offset]; + } else if (fat_info->type == FAT_TYPE_FAT16) { + data = ((uint16_t *)entry->data)[offset]; + } + block_cache_read_done(entry); + + return data; +} + +void set_cluster(FatInfo *fat_info, uint32_t cluster, uint32_t data) { + uint32_t index = cluster / fat_info->num_count; + uint32_t offset = cluster % fat_info->num_count; + + BlockCacheEntry *entry = + block_cache_write(fat_info->fat_table_cache, index); + + if (fat_info->type == FAT_TYPE_FAT32) { + ((uint32_t *)entry->data)[offset] = data; + } else if (fat_info->type == FAT_TYPE_FAT16) { + ((uint16_t *)entry->data)[offset] = data & 0xffff; + } + + block_cache_write_done(fat_info->storage_device, entry); +} + +FsResult alloc_cluster( + FatInfo *fat_info, uint32_t last_cluster, bool is_first_cluster, + uint32_t *out_cluster) { + + // 1.先找到一个空闲的簇 + uint32_t index = fat_info->last_cluster / fat_info->num_count; + uint32_t offset = fat_info->last_cluster % fat_info->num_count; + + int i; + bool finded; + while (index < fat_info->fat_sectors && !finded) { + BlockCacheEntry *entry = + block_cache_read(fat_info->fat_table_cache, index); + for (i = offset; i < fat_info->num_count; i++) { + if (((uint32_t *)entry->data)[i] == 0) { + finded = true; + break; + } + } + block_cache_read_done(entry); + + index++; + offset = 0; + } + fat_info->last_cluster = index * fat_info->num_count + i; + if (finded) { + set_cluster(fat_info, index * fat_info->num_count + i, 0x0fffffff); + *out_cluster = index * fat_info->num_count + i; + } else { + return FS_ERROR_NO_SPARE_SPACE; + } + + if (!is_first_cluster) { + // 2.将上一个簇的FAT表项指向新分配的簇 + set_cluster(fat_info, last_cluster, *out_cluster); + } + + return FS_OK; +} + +FsResult free_cluster( + FatInfo *fat_info, uint32_t cluster, uint32_t *out_cluster) { + uint32_t index = cluster / fat_info->num_count; + uint32_t offset = cluster % fat_info->num_count; + + BlockCacheEntry *entry; + + if (out_cluster != NULL) { + entry = block_cache_read(fat_info->fat_table_cache, index); + if (fat_info->type == FAT_TYPE_FAT32) { + *out_cluster = ((uint32_t *)entry->data)[offset]; + } else if (fat_info->type == FAT_TYPE_FAT16) { + *out_cluster = ((uint16_t *)entry->data)[offset]; + } + block_cache_read_done(entry); + } + + set_cluster(fat_info, cluster, 0); + + return FS_OK; +} + +inline bool is_eof(FatInfo *fat_info, uint32_t cluster) { + if (fat_info->type == FAT_TYPE_FAT32) { + return cluster >= 0x0FFFFFF8; + } else if (fat_info->type == FAT_TYPE_FAT16) { + return cluster >= 0xFFF8; + } else if (fat_info->type == FAT_TYPE_FAT12) { + return cluster >= 0x0FF8; + } + return false; +} + +FsResult get_cluster_segment(FatInfo *fat_info, FatDirEntry *entry) { + DynArray *arr = entry->cluster_list; + ClusterSegment segment; + + uint32_t cluster; + if (arr->size == 0) { + cluster = entry->short_dir.first_cluster_low; + if (fat_info->type == FAT_TYPE_FAT32) { + cluster |= entry->short_dir.first_cluster_high << 16; + } + } else { + cluster = + ((ClusterSegment)dyn_array_get(arr, ClusterSegment, arr->size - 1)) + .end; + if (is_eof(fat_info, cluster)) { return FS_ERROR_END_OF_FILE; } + cluster = get_next_cluster(fat_info, cluster); + } + segment.start = cluster; + while (!is_eof(fat_info, cluster)) { + uint32_t tmp = get_next_cluster(fat_info, cluster); + if (tmp != cluster + 1) { + segment.end = cluster; + dyn_array_append(arr, ClusterSegment, segment); + if (tmp < 2) return FS_ERROR_ILLEGAL_DATA; + else return FS_OK; + } + cluster = tmp; + } + + segment.start = segment.end = 0x0fffffff; + dyn_array_append(arr, ClusterSegment, segment); + + return FS_OK; +} + +FsResult fat_cluster_list_get( + FatInfo *fat_info, FatDirEntry *entry, uint32_t index, + CurrentCluster *cur_cluster) { + DynArray *arr = entry->cluster_list; + + int counter = index; + + ClusterSegment clus_seg; + dyn_array_foreach(arr, ClusterSegment, clus_seg) { + int length = clus_seg.end - clus_seg.start + 1; + if (counter < length) { + cur_cluster->cluster = clus_seg.start + counter; + cur_cluster->block = _block; + return FS_OK; + } + counter -= length; + } + + return FS_OK; +} + +FsResult fat_cluster_list_get_next( + FatInfo *fat_info, FatDirEntry *entry, CurrentCluster *cur_cluster) { + ClusterSegment *seg = cur_cluster->block->data; + if (cur_cluster->cluster < seg->end) { + cur_cluster->cluster++; + } else { + if (cur_cluster->block->next != NULL) { + get_next: + cur_cluster->block = cur_cluster->block->next; + seg = cur_cluster->block->data; + cur_cluster->cluster = seg->start; + } else { + FsResult result = get_cluster_segment(fat_info, entry); + if (result != FS_OK) return result; + goto get_next; + } + } + return FS_OK; +} + +FsResult get_last_cluster( + FatInfo *fat_info, FatDirEntry *entry, DEF_MRET(uint32_t, last_cluster)) { + DynArray *arr = entry->cluster_list; + ClusterSegment seg, tmp; + + tmp = dyn_array_get(arr, ClusterSegment, arr->size - 1); + if (!is_eof(fat_info, tmp.end)) { + while (!is_eof(fat_info, tmp.end)) { + seg = tmp; + FS_RESULT_PASS(get_cluster_segment(fat_info, entry)); + tmp = dyn_array_get(arr, ClusterSegment, arr->size - 1); + } + } + MRET(last_cluster) = seg.end; + return FS_OK; +} diff --git a/src/fs/fat/dir.c b/src/fs/fat/dir.c new file mode 100644 index 0000000..c439de7 --- /dev/null +++ b/src/fs/fat/dir.c @@ -0,0 +1,131 @@ +#include "include/dir.h" +#include "include/cluster.h" +#include "include/entry.h" +#include "include/fat.h" +#include "include/name.h" +#include +#include +#include +#include +#include +#include + +typedef struct FatCurrentEntry { + FatDirEntry *entry; + CurrentCluster cur_cluster; + int number; +} FatCurrentEntry; + +static inline void fat_first_entry( + FatInfo *fat_info, FatCurrentEntry *entry, int number) { + entry->number = number; + int index = number / fat_info->entry_per_cluster; + fat_cluster_list_get(fat_info, entry->entry, index, &entry->cur_cluster); +} + +static inline FsResult fat_next_entry( + FatInfo *fat_info, FatCurrentEntry *entry) { + entry->number++; + if (entry->number == fat_info->entry_per_cluster) { + return fat_cluster_list_get_next( + fat_info, entry->entry, &entry->cur_cluster); + } + return FS_OK; +} + +static inline void fat_read_current_entry( + FatInfo *fat_info, FatCurrentEntry *entry, uint8_t *buf) { + fat_entry_read( + fat_info, entry->entry, entry->cur_cluster.cluster, entry->number, buf); +} + +// 扫描目录项 +// mode = 0 : 匹配目录项 +// mode = 1 : 扫描所有目录项 +FsResult fat32_read_dir_entry( + FatCurrentEntry *cur_entry, string_t *name, uint8_t *buf, + uint16_t *utf16_name, uint16_t **_utf16_name, int *utf16_length, + uint32_t *longname_cluster, int *longname_number) { + ShortDir *short_dir = (ShortDir *)buf; + if (short_dir->name.base[0] == 0x00) return FS_ERROR_CANNOT_FIND; + if (buf[0] == 0xe5 || buf[0] == 0x05) return FS_ERROR_NOT_MATCH; + + LongDir *long_dir = (LongDir *)buf; + if (long_dir->attr == ATTR_LONG_NAME) { + if (long_dir->order & 0x40) { + int count = long_dir->order & 0x3f; + *longname_cluster = cur_entry->cur_cluster.cluster; + *longname_number = cur_entry->number; + *_utf16_name = utf16_name + (count - 1) * 13; + *utf16_length = 0; + } + *utf16_length += read_long_name(long_dir, *_utf16_name); + *_utf16_name -= 13; + } else if (*utf16_length > 0) { + fat_utf16_to_utf8(utf16_name, *utf16_length + 1, name); + } else { + if (short_dir->name.base[0] == '.') return FS_ERROR_NOT_MATCH; + *name = read_short_name(short_dir); + } + + return FS_OK; +} + +FsResult search_dir( + FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, + bool is_directory, FatDirEntry **out_entry, int mode) { + FatCurrentEntry cur_entry; + cur_entry.entry = parent_entry; + + FatDirEntry *tmp_entry; + + uint8_t buf[0x20]; + + ShortDir *short_dir; + uint16_t *utf16_name = kmalloc(256 * sizeof(uint16_t)), *_utf16_name; + int utf16_length = 0; + + uint32_t longname_cluster; + int longname_number; + + FsResult result; + FsResult _result = FS_OK; + + string_t _name; + + fat_first_entry(fat_info, &cur_entry, 0); + for (; _result == FS_OK; _result = fat_next_entry(fat_info, &cur_entry)) { + fat_read_current_entry(fat_info, &cur_entry, buf); + result = fat32_read_dir_entry( + &cur_entry, &_name, buf, utf16_name, &_utf16_name, &utf16_length, + &longname_cluster, &longname_number); + + if (result == FS_ERROR_NOT_MATCH) continue; + else if (result == FS_ERROR_CANNOT_FIND) break; + + short_dir = (ShortDir *)buf; + if (utf16_length == 0) { + // 为短文件名 + longname_cluster = 0; + longname_number = 0; + } + if (short_dir->attr != ATTR_LONG_NAME) { + tmp_entry = generate_dir_entry( + fat_info, parent_entry, (ShortDir *)buf, _name, is_directory, + cur_entry.cur_cluster.cluster, cur_entry.number, 0, 0); + } + + if (is_directory && (short_dir->attr & ATTR_DIRECTORY) == 0) continue; + if (!is_directory && (short_dir->attr & ATTR_DIRECTORY) != 0) continue; + + if (mode == 0 && strncmp(_name.text, name.text, _name.length) == 0) { + *out_entry = tmp_entry; + + parent_entry->new_entry_number = cur_entry.number + 1; + result = FS_OK; + break; + } + } + kfree(utf16_name); + return result; +} diff --git a/src/fs/fat/entry.c b/src/fs/fat/entry.c new file mode 100644 index 0000000..71219fd --- /dev/null +++ b/src/fs/fat/entry.c @@ -0,0 +1,298 @@ +#include "include/entry.h" +#include "include/cluster.h" +#include "include/dir.h" +#include "include/fat.h" +#include "include/name.h" +#include "include/time.h" +#include "kernel/list.h" +#include "kernel/memory.h" +#include "multiple_return.h" +#include "objects/object.h" +#include +#include +#include +#include +#include +#include +#include + +PRIVATE FsResult +entry_read(BlockCacheEntry *entry, size_t cache_size, void *private_data) { + FatInfo *fat_info = private_data; + Partition *partition = fat_info->partition; + + int count = DIV_ROUND_UP(cache_size, fat_info->bpb->BPB_BytesPerSec); + uint32_t sector = cluster2sector(fat_info, entry->position); + + TRANSFER_IN_BLOCK(partition->storage_object, entry->data, sector, count); + return FS_OK; +} + +PRIVATE FsResult +entry_write(BlockCacheEntry *entry, size_t cache_size, void *private_data) { + FatInfo *fat_info = private_data; + Partition *partition = fat_info->partition; + + int count = DIV_ROUND_UP(cache_size, fat_info->bpb->BPB_BytesPerSec); + uint32_t sector = cluster2sector(fat_info, entry->position); + + for (int i = 0; i < fat_info->bpb->BPB_NumFATs; i++) { + TRANSFER_OUT_BLOCK( + partition->storage_object, entry->data, sector, count); + } + + return FS_OK; +} + +PUBLIC void entry_cache_init( + FatInfo *fat_info, FatDirEntry *entry, size_t cache_size) { + + entry->cache = + block_cache_create(cache_size, 1, entry_read, entry_write, fat_info); + BlockCacheEntry *cache_entry = block_cache_read(entry->cache, 0); + block_cache_read_done(cache_entry); +} + +PUBLIC FsResult fat_entry_read( + FatInfo *fat_info, FatDirEntry *parent_entry, int cluster, int number, + uint8_t *entry) { + BlockCacheEntry *cache_entry = + block_cache_read(parent_entry->cache, cluster); + memcpy( + entry, cache_entry->data + number * sizeof(ShortDir), sizeof(ShortDir)); + block_cache_read_done(cache_entry); + return FS_OK; +} + +PUBLIC FsResult fat_entry_write( + FatInfo *fat_info, FatDirEntry *parent_entry, int cluster, int number, + uint8_t *entry) { + BlockCacheEntry *cache_entry = + block_cache_write(parent_entry->cache, cluster); + memcpy( + cache_entry->data + number * sizeof(ShortDir), entry, sizeof(ShortDir)); + block_cache_write_done(fat_info->storage_device, cache_entry); + return FS_OK; +} + +PRIVATE FsResult fat_dir_get_new_entry( + FatInfo *fat_info, FatDirEntry *entry, DEF_MRET(uint32_t, last_cluster), + DEF_MRET(int, last_number)) { + + int number = entry->new_entry_number; + uint32_t cluster; + uint8_t buf[32]; + FS_RESULT_PASS(get_last_cluster(fat_info, entry, &cluster)); + do { + FS_RESULT_PASS(fat_entry_read(fat_info, entry, cluster, number, buf)); + number++; + } while (buf[0] != 0 && number <= fat_info->entry_per_cluster); + number -= 1; + if (number == fat_info->entry_per_cluster && buf[0] != 0) { + FS_RESULT_PASS(alloc_cluster(fat_info, cluster, false, &cluster)); + number = 0; + } + MRET(last_cluster) = cluster; + MRET(last_number) = number; + return FS_OK; +} + +PRIVATE int fat_increase_new_entry_number( + FatInfo *fat_info, FatDirEntry *entry, uint32_t *cluster) { + entry->new_entry_number++; + if (entry->new_entry_number == fat_info->entry_per_cluster) { + FS_RESULT_PASS(alloc_cluster(fat_info, *cluster, false, cluster)); + entry->new_entry_number = 0; + } + return entry->new_entry_number; +} + +PRIVATE FsResult fat_longname_entry_write( + FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, + uint8_t checksum, uint32_t *cluster, int *number) { + LongDir long_dir; + int len8, len16; + int longdir_count; + + uint16_t *utf16_name = kmalloc(name.length); + fat_utf8_to_utf16((uint8_t *)name.text, utf16_name, &len8, &len16); + longdir_count = DIV_ROUND_UP(len16, 13); + + long_dir.attr = ATTR_LONG_NAME; + long_dir.checksum = checksum; + long_dir.first_cluster = 0; + long_dir.type = 0; + for (int i = 0; i < longdir_count; i++, number++) { + long_dir.order = longdir_count - i; + if (i == 0) { + int len = len16 % 13; + for (int j = 0; j < 5; j++) { + if (j < len) long_dir.name1[j] = utf16_name[j]; + else long_dir.name1[j] = 0xffff; + } + for (int j = 0; j < 6; j++) { + if (j < len) long_dir.name2[j] = utf16_name[j + 5]; + else long_dir.name2[j] = 0xffff; + } + for (int j = 0; j < 3; j++) { + if (j < len) long_dir.name3[j] = utf16_name[j + 11]; + else long_dir.name3[j] = 0xffff; + } + } else { + memcpy(long_dir.name1, utf16_name, 5 * sizeof(uint16_t)); + memcpy(long_dir.name2, utf16_name + 5, 6 * sizeof(uint16_t)); + memcpy(long_dir.name3, utf16_name + 11, 2 * sizeof(uint16_t)); + } + if (i == longdir_count - 1) long_dir.order |= 0x40; + FS_RESULT_PASS(fat_entry_write( + fat_info, parent_entry, *cluster, *number, (uint8_t *)&long_dir)); + utf16_name += 13; + + *number = + fat_increase_new_entry_number(fat_info, parent_entry, cluster); + } + return FS_OK; +} + +PUBLIC FatDirEntry *generate_dir_entry( + FatInfo *fat_info, FatDirEntry *parent_entry, ShortDir *short_dir, + string_t name, bool is_directory, uint32_t cluster, uint32_t number, + uint32_t longname_cluster, uint32_t longname_number) { + FatDirEntry *entry = kmalloc(sizeof(FatDirEntry)); + string_cpy(&entry->name, &name); + memcpy(&entry->short_dir, short_dir, sizeof(ShortDir)); + + entry->cluster_list = dyn_array_new(sizeof(ClusterSegment), 8); + get_cluster_segment(fat_info, entry); + + Object *object; + if (entry->short_dir.attr & ATTR_DIRECTORY) { + FsResult result = fs_obj_create_dir( + parent_entry->object, fat_info->fs_info, entry->name, &object); + if (result != FS_OK) { return NULL; } + object->value.directory.data = entry; + entry_cache_init(fat_info, entry, fat_info->bytes_per_cluster); + } else { + FsResult result = fs_obj_create_file( + parent_entry->object, fat_info->fs_info, entry->name, &object); + if (result != FS_OK) { return NULL; } + object->value.file.data = entry; + object->value.file.offset = 0; + object->value.file.size = entry->short_dir.file_size; + } + entry->object = object; + + return entry; +} + +PUBLIC FsResult fat_create_entry( + FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, + bool is_directory, FatDirEntry **out_entry) { + + Time time; + DriverResult result = get_current_time(TIME_TYPE_LOCAL, &time); + if (result != DRIVER_RESULT_OK) { return FS_ERROR_OTHER; } + TimeFull full_time = time.time; + uint16_t cur_time = + FAT_TIME(full_time.hour, full_time.minute, full_time.second); + uint16_t cur_date = + FAT_DATE(full_time.year, full_time.month, full_time.day); + + uint32_t first_cluster; + FS_RESULT_PASS(alloc_cluster(fat_info, 0, true, &first_cluster)); + + NameType type = + check_name(fat_info->type, (uint8_t *)name.text, name.length); + ShortName short_name; + if (fat_info->type != FAT_TYPE_FAT32 && type == LONG_NAME) { + return FS_ERROR_INVALID_PATH_OR_NAME; + } + FS_RESULT_PASS(long_name2short_name( + fat_info, parent_entry, name, is_directory, &short_name)); + + int caps = check_name_caps((uint8_t *)name.text, 11); + int ntres = 0; + if ((caps & 0x03) == 0x01) ntres |= FAT32_BASE_L; + if ((caps & 0x0c) == 0x04) ntres |= FAT32_BASE_L; + + ShortDir short_dir; + short_dir.name = short_name; + short_dir.attr = ATTR_ARCHIVE; + short_dir.nt_res = ntres; + short_dir.crt_time_tenth = (full_time.second % 2) * 100; + short_dir.crt_time = cur_time; + short_dir.crt_date = cur_date; + short_dir.last_access_date = cur_date; + short_dir.first_cluster_high = first_cluster >> 16; + short_dir.write_time = cur_time; + short_dir.write_date = cur_date; + short_dir.first_cluster_low = first_cluster & 0xffff; + short_dir.file_size = 0; + if (is_directory) { short_dir.attr |= ATTR_DIRECTORY; } + + int checksum = fat_checksum(&short_dir.name); + + uint32_t cluster; + int number; + fat_dir_get_new_entry(fat_info, parent_entry, &cluster, &number); + if (fat_info->type == FAT_TYPE_FAT32 && type == LONG_NAME) { + FS_RESULT_PASS(fat_longname_entry_write( + fat_info, parent_entry, name, checksum, &cluster, &number)); + } + FS_RESULT_PASS(fat_entry_write( + fat_info, parent_entry, cluster, number, (uint8_t *)&short_dir)); + + FatDirEntry *entry; + entry = generate_dir_entry( + fat_info, parent_entry, &short_dir, name, is_directory, cluster, number, + 0, 0); + + if (is_directory) { + static ShortName dot = {". ", " "}; + short_dir.name = dot; + short_dir.attr = ATTR_DIRECTORY; + FS_RESULT_PASS(fat_entry_write( + fat_info, entry, first_cluster, 0, (uint8_t *)&short_dir)); + + short_dir.name.base[1] = '.'; + short_dir.first_cluster_low = parent_entry->short_dir.first_cluster_low; + short_dir.first_cluster_high = + parent_entry->short_dir.first_cluster_high; + FS_RESULT_PASS(fat_entry_write( + fat_info, entry, first_cluster, 1, (uint8_t *)&short_dir)); + entry->new_entry_number = 1; + } + return FS_OK; +} + +PUBLIC FsResult +fat_delete_entry(FatInfo *fat_info, FatDirEntry *entry, string_t name) { + uint32_t cluster = entry->shortname_cluster; + uint32_t num = entry->shortname_number; + + uint8_t buf[32]; + FS_RESULT_PASS(fat_entry_read(fat_info, entry, cluster, num, buf)); + buf[0] = 0xe5; + FS_RESULT_PASS(fat_entry_write(fat_info, entry, cluster, num, buf)); + + if (fat_info->type == FAT_TYPE_FAT32 && entry->longname_cluster != 0) { + uint32_t cluster = entry->longname_cluster; + int number = entry->longname_number; + + while (cluster <= entry->shortname_cluster && + number <= entry->shortname_number) { + FS_RESULT_PASS( + fat_entry_read(fat_info, entry, cluster, number, buf)); + buf[0] = 0xe5; + FS_RESULT_PASS( + fat_entry_write(fat_info, entry, cluster, number, buf)); + number++; + if (number == fat_info->entry_per_cluster) { + cluster = get_next_cluster(fat_info, cluster); + num = 0; + } + } + } + + return FS_OK; +} diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c new file mode 100644 index 0000000..80c4aae --- /dev/null +++ b/src/fs/fat/fat.c @@ -0,0 +1,305 @@ +#include "include/fat.h" +#include "include/cluster.h" +#include "include/dir.h" +#include "include/entry.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +FsResult fat_check(Partition *partition); +FsResult fat_mount(FileSystemInfo *fs_info, Object *root_object); +FsResult fat_open( + FileSystemInfo *fs_info, void *parent, string_t name, Object **object); +FsResult fat_close(Object *object); +FsResult fat_seek(Object *object, size_t offset); +FsResult fat_read(Object *file, void *buf, size_t size); +FsResult fat_write(Object *file, void *buf, size_t size); + +FsResult fat_opendir( + FileSystemInfo *fs_info, void *parent, string_t name, Object **object); +FsResult fat_closedir(Object *object); +FsResult fat_create_file(Object *directory, string_t name, Object **object); +FsResult fat_delete_file(Object *directory, string_t name); +FsResult fat_mkdir(Object *directory, string_t name, Object **object); +FsResult fat_rmdir(Object *directory, string_t name); + +FileSystemOps fat_ops = { + .fs_check = fat_check, + .fs_mount = fat_mount, +}; + +FsFileOps fat_file_ops = { + .fs_open = fat_open, + .fs_close = fat_close, + .fs_seek = fat_seek, + .fs_read = fat_read, + .fs_write = fat_write, +}; + +FsDirectoryOps fat_dir_ops = { + .fs_opendir = fat_opendir, + .fs_closedir = fat_closedir, + .fs_create_file = fat_create_file, + .fs_delete_file = fat_delete_file, +}; + +FileSystem fat_fs = { + .name = STRING_INIT("FAT"), + .ops = &fat_ops, +}; + +FatType fat_type_determine(FatInfo *fat_info); + +FsResult fat_check(Partition *partition) { + if (partition->type == PARTITION_TYPE_MBR) { + if (partition->mbr->fs_type == 0x0b || + partition->mbr->fs_type == 0x0c) { + return FS_OK; + } + } + return FS_ERROR_UNSUPPORT; +} + +FsResult fat_mount(FileSystemInfo *fs_info, Object *root_object) { + FatBpb *bpb = (FatBpb *)fs_info->partition->superblock; + FatFsInfo *fat_fs_info = + (FatFsInfo *)(fs_info->partition->superblock + SECTOR_SIZE); + FatInfo *fat_info = kmalloc(sizeof(FatInfo)); + fat_info->fs_info = fs_info; + fs_info->private_data = fat_info; + + fat_info->partition = fs_info->partition; + + fat_info->bpb = bpb; + fat_info->fat_fs_info = fat_fs_info; + + int root_dir_sectors = + ((bpb->BPB_RootEntCnt * 32) + (bpb->BPB_BytesPerSec - 1)) / + bpb->BPB_BytesPerSec; + + fat_info->fat_sectors = + (bpb->BPB_FATSz16 != 0) ? (bpb->BPB_FATSz16) : (bpb->fat32.BPB_FATSz32); + + fat_info->total_sectors = + (bpb->BPB_TotSec16 != 0) ? (bpb->BPB_TotSec16) : (bpb->BPB_TotSec32); + + fat_info->data_sectors = + fat_info->total_sectors - + (bpb->BPB_RevdSecCnt + (bpb->BPB_NumFATs * fat_info->fat_sectors) + + root_dir_sectors); + + fat_info->type = fat_type_determine(fat_info); + + fat_info->fat_start = fs_info->partition->start_lba + bpb->BPB_RevdSecCnt; + fat_info->data_start = + fat_info->fat_start + (bpb->BPB_NumFATs * fat_info->fat_sectors); + fat_info->sector_per_cluster = bpb->BPB_SecPerClus; + fat_info->bytes_per_cluster = + fat_info->sector_per_cluster * bpb->BPB_BytesPerSec; + fat_info->entry_per_cluster = fat_info->bytes_per_cluster / 32; + + int cache_size = fat_info->bytes_per_cluster; + + if (fat_info->type == FAT_TYPE_FAT32) { + fat_info->num_count = cache_size / 4; + } else if (fat_info->type == FAT_TYPE_FAT16) { + fat_info->num_count = cache_size / 2; + } + + fat_info->fat_table_cache = block_cache_create( + fat_info->bytes_per_cluster, 4, fat_table_read, fat_table_write, + fat_info); + + const string_t root_name = STRING_INIT(""); + const ShortDir root_short_dir = { + {" ", " "}, + ATTR_DIRECTORY, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 + }; + const FatDirEntry root_entry = { + root_name, root_short_dir, 0, 0, 0, 0, {0}, NULL, NULL, + }; + fat_info->root_entry = root_entry; + fat_info->root_entry.object = root_object; + root_object->value.directory.data = &fat_info->root_entry; + fat_info->root_entry.cluster_list = + dyn_array_new(sizeof(ClusterSegment), 8); + entry_cache_init( + fat_info, &fat_info->root_entry, fat_info->bytes_per_cluster); + get_cluster_segment(fat_info, &fat_info->root_entry); + + root_object->fs_info->private_data = fat_info; + root_object->fs_info->file_ops = fat_file_ops; + root_object->fs_info->dir_ops = fat_dir_ops; + fat_info->storage_device = + fs_info->partition->storage_object->value.device->dm_ext; + + return FS_OK; +} + +FatType fat_type_determine(FatInfo *fat_info) { + + int count_of_cluster = + fat_info->data_sectors / fat_info->bpb->BPB_SecPerClus; + + if (count_of_cluster < 4085) { + return FAT_TYPE_FAT12; + } else if (count_of_cluster < 65525) { + return FAT_TYPE_FAT16; + } else { + return FAT_TYPE_FAT32; + } +} + +FsResult fat_open( + FileSystemInfo *fs_info, void *parent, string_t name, Object **object) { + FatInfo *fat_info = fs_info->private_data; + FatDirEntry *entry; + + FsResult result = search_dir(fat_info, parent, name, false, &entry, 0); + *object = entry->object; + return result; +} + +FsResult fat_opendir( + FileSystemInfo *fs_info, void *parent, string_t name, Object **object) { + FatInfo *fat_info = fs_info->private_data; + FatDirEntry *entry; + + FsResult result = search_dir(fat_info, parent, name, true, &entry, 0); + *object = entry->object; + return result; +} + +FsResult fat_close(Object *object) { + FatDirEntry *entry = object->value.file.data; + if (entry->cache != NULL) block_cache_destroy(entry->cache); + dyn_array_delete(entry->cluster_list); + string_del(&entry->name); + kfree(entry); + return FS_OK; +} + +FsResult fat_closedir(Object *object) { + return fat_close(object); +} + +FsResult fat_seek(Object *object, size_t offset) { + object->value.file.offset = offset; + return FS_OK; +} + +FsResult fat_transfer( + BlockTransfer transfer, TransferDirection direction, + IsTransferDone is_transfer_done, FatInfo *fat_info, Object *storage_object, + Object *file, void *buf, size_t size) { + FatDirEntry *entry = file->value.file.data; + + uint32_t cluster_index = + file->value.file.offset / fat_info->bytes_per_cluster; + + CurrentCluster cur_cluster; + fat_cluster_list_get(fat_info, entry, cluster_index, &cur_cluster); + + uint32_t offset = file->value.file.offset; + uint32_t readed = 0; + + void *handle; + while (size > 0) { + uint32_t read_size = fat_info->bytes_per_cluster - offset; + if (read_size > size) { read_size = size; } + + uint32_t sector = cluster2sector(fat_info, cur_cluster.cluster); + + transfer( + storage_object, direction, buf + readed, sector, + fat_info->sector_per_cluster); + + readed += read_size; + size -= read_size; + offset += read_size; + + if (offset == fat_info->bytes_per_cluster) { + offset = 0; + fat_cluster_list_get_next(fat_info, entry, &cur_cluster); + } + } + bool done; + do { + TRANSFER_IN_IS_DONE(storage_object, &handle, &done); + } while (!done); + file->value.file.offset = offset; + + return FS_OK; +} + +FsResult fat_read(Object *file, void *buf, size_t size) { + FatInfo *fat_info = file->fs_info->private_data; + Object *storage_object = fat_info->partition->storage_object; + return fat_transfer( + storage_object->in.block, TRANSFER_IN, + storage_object->in.is_transfer_done, fat_info, storage_object, file, + buf, size); +} + +FsResult fat_write(Object *file, void *buf, size_t size) { + FatInfo *fat_info = file->fs_info->private_data; + Object *storage_object = fat_info->partition->storage_object; + return fat_transfer( + storage_object->out.block, TRANSFER_OUT, + storage_object->out.is_transfer_done, fat_info, storage_object, file, + buf, size); +} + +FsResult fat_create_file(Object *directory, string_t name, Object **object) { + FatInfo *fat_info = (FatInfo *)directory->fs_info; + FatDirEntry *entry, *parent = directory->value.directory.data; + + FsResult result = search_dir(fat_info, parent, name, false, &entry, 0); + if (result == FS_OK) { return FS_ERROR_ALREADY_EXISTS; } + + fat_create_entry(fat_info, parent, name, false, &entry); + + *object = entry->object; + return FS_OK; +} + +FsResult fat_delete_file(Object *directory, string_t name) { + FatInfo *fat_info = (FatInfo *)directory->fs_info; + FatDirEntry *entry, *parent = directory->value.directory.data; + + FsResult result = search_dir(fat_info, parent, name, false, &entry, 0); + if (result != FS_OK) { return result; } + + fat_delete_entry(fat_info, entry, name); + return FS_OK; +} + +FsResult fat_mkdir(Object *directory, string_t name, Object **object) { + FatInfo *fat_info = (FatInfo *)directory->fs_info; + FatDirEntry *entry, *parent = directory->value.directory.data; + + FsResult result = search_dir(fat_info, parent, name, true, &entry, 0); + if (result == FS_OK) { return FS_ERROR_ALREADY_EXISTS; } + + fat_create_entry(fat_info, parent, name, true, &entry); + + *object = entry->object; + return FS_OK; +} + +void fat_initcall() { + register_fs(&fat_fs); +} + +fs_initcall(fat_initcall); diff --git a/src/fs/fat/include/cluster.h b/src/fs/fat/include/cluster.h new file mode 100644 index 0000000..90c8a78 --- /dev/null +++ b/src/fs/fat/include/cluster.h @@ -0,0 +1,48 @@ +#ifndef _FAT_CLUSTER_H +#define _FAT_CLUSTER_H + +#include "dir.h" +#include "dyn_array.h" +#include "fat.h" +#include "fs/fs.h" +#include +#include + +// 保存一个连续的簇链 +typedef struct ClusterSegment { + uint32_t start; + uint32_t end; +} ClusterSegment; + +typedef struct CurrentCluster { + uint32_t cluster; + DynArrayBlock *block; +} CurrentCluster; + +uint32_t cluster2sector(FatInfo *fat_info, uint32_t cluster); + +FsResult fat_table_read( + BlockCacheEntry *entry, size_t cache_size, void *private_data); +FsResult fat_table_write( + BlockCacheEntry *entry, size_t cache_size, void *private_data); + +uint32_t get_next_cluster(FatInfo *fat_info, uint32_t clus); +void set_cluster(FatInfo *fat_info, uint32_t cluster, uint32_t data); +FsResult alloc_cluster( + FatInfo *fat_info, uint32_t last_cluster, bool is_first_cluster, + uint32_t *out_clus); +FsResult free_cluster(FatInfo *fat_info, uint32_t cluster, uint32_t *out_clus); +bool is_eof(FatInfo *fat_info, uint32_t clus); +FsResult get_cluster_segment(FatInfo *fat_info, FatDirEntry *entry); + +FsResult fat_cluster_list_get( + FatInfo *fat_info, FatDirEntry *entry, uint32_t index, + CurrentCluster *cur_cluster); +FsResult fat_cluster_list_get_next( + FatInfo *fat_info, FatDirEntry *entry, CurrentCluster *cur_cluster); +inline bool fat_cluster_list_is_last( + FatInfo *fat_info, FatDirEntry *entry, CurrentCluster *cur_cluster); +FsResult get_last_cluster( + FatInfo *fat_info, FatDirEntry *entry, DEF_MRET(uint32_t, last_cluster)); + +#endif \ No newline at end of file diff --git a/src/fs/fat/include/dir.h b/src/fs/fat/include/dir.h new file mode 100644 index 0000000..79c279f --- /dev/null +++ b/src/fs/fat/include/dir.h @@ -0,0 +1,82 @@ +#ifndef _FAT_DIR_H +#define _FAT_DIR_H + +#include "dyn_array.h" +#include "fs/fs.h" +#include "kernel/block_cache.h" +#include "name.h" +#include "objects/object.h" +#include "stdint.h" +#include "string.h" +#include + +#define ATTR_READ_ONLY 0x01 +#define ATTR_HIDDEN 0x02 +#define ATTR_SYSTEM 0x04 +#define ATTR_VOLUME_ID 0x08 +#define ATTR_DIRECTORY 0x10 +#define ATTR_ARCHIVE 0x20 +#define ATTR_LONG_NAME 0x0f + +#define FAT32_BASE_L 0x08 +#define FAT32_EXT_L 0x10 + +typedef struct ShortDir { + ShortName name; + uint8_t attr; + uint8_t nt_res; + uint8_t crt_time_tenth; + uint16_t crt_time; + uint16_t crt_date; + uint16_t last_access_date; + uint16_t first_cluster_high; + uint16_t write_time; + uint16_t write_date; + uint16_t first_cluster_low; + uint32_t file_size; +} __attribute__((packed)) ShortDir; + +typedef struct LongDir { + uint8_t order; + uint16_t name1[5]; + uint8_t attr; + uint8_t type; + uint8_t checksum; + uint16_t name2[6]; + uint16_t first_cluster; + uint16_t name3[2]; +} __attribute__((packed)) LongDir; + +typedef struct FatDirEntry { + string_t name; + ShortDir short_dir; + + // 短目录项所在的簇号 + uint32_t shortname_cluster; + // 短目录项所在的簇内的序号 + uint8_t shortname_number; + + // 长目录项所在的簇号 + uint32_t longname_cluster; + // 长目录项所在的簇内的序号 + uint8_t longname_number; + + union { + // 文件夹已知的最后一个子目录项的序号 + int new_entry_number; + }; + + DynArray *cluster_list; + BlockCache *cache; + + Object *object; +} FatDirEntry; + +struct FatInfo; +FsResult search_dir( + struct FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, + bool match_directory, FatDirEntry **out_entry, int mode); +void entry_cache_init( + struct FatInfo *fat_info, FatDirEntry *entry, size_t cache_size); + +#endif \ No newline at end of file diff --git a/src/fs/fat/include/entry.h b/src/fs/fat/include/entry.h new file mode 100644 index 0000000..dd48643 --- /dev/null +++ b/src/fs/fat/include/entry.h @@ -0,0 +1,25 @@ +#ifndef _FAT_ENTRY_H +#define _FAT_ENTRY_H + +#include "dir.h" +#include "fs/fs.h" + +struct FatInfo; +struct FatDirEntry; +FsResult fat_entry_read( + struct FatInfo *fat_info, struct FatDirEntry *parent_entry, int cluster, + int number, uint8_t *entry); +FsResult fat_entry_write( + struct FatInfo *fat_info, struct FatDirEntry *parent_entry, int cluster, + int number, uint8_t *entry); +FatDirEntry *generate_dir_entry( + struct FatInfo *fat_info, FatDirEntry *parent_entry, ShortDir *short_dir, + string_t name, bool is_directory, uint32_t cluster, uint32_t number, + uint32_t longname_cluster, uint32_t longname_number); +FsResult fat_create_entry( + struct FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, + bool is_directory, FatDirEntry **out_entry); +FsResult fat_delete_entry( + struct FatInfo *fat_info, FatDirEntry *entry, string_t name); + +#endif \ No newline at end of file diff --git a/src/fs/fat/include/fat.h b/src/fs/fat/include/fat.h new file mode 100644 index 0000000..fd87542 --- /dev/null +++ b/src/fs/fat/include/fat.h @@ -0,0 +1,99 @@ +#ifndef _FAT_H +#define _FAT_H + +#include "dir.h" +#include "driver/storage/disk/disk.h" +#include "driver/storage/storage_dm.h" +#include "kernel/block_cache.h" +#include "objects/object.h" +#include + +#define FAT_CACHE_SIZE 2 + +typedef enum FatType { + FAT_TYPE_FAT12, + FAT_TYPE_FAT16, + FAT_TYPE_FAT32, + FAT_TYPE_EXFAT +} FatType; + +typedef struct FatBpb { + uint8_t BS_jmpBoot[3]; + char BS_OEMName[8]; + uint16_t BPB_BytesPerSec; + uint8_t BPB_SecPerClus; + uint16_t BPB_RevdSecCnt; + uint8_t BPB_NumFATs; + uint16_t BPB_RootEntCnt; + uint16_t BPB_TotSec16; + uint8_t BPB_Media; + uint16_t BPB_FATSz16; + uint16_t BPB_SecPerTrk; + uint16_t BPB_NumHeads; + uint32_t BPB_HiddSec; + uint32_t BPB_TotSec32; + union { + struct { + uint8_t BS_DrvNum; + uint8_t BS_Reserved1; + uint8_t BS_BootSig; + uint32_t BS_VolID; + char BS_VolLab[11]; + char BS_FilSysType[8]; + } __attribute__((packed)) fat12_16; + struct { + uint32_t BPB_FATSz32; + uint16_t BPB_ExtFlags; + uint16_t BPB_FSVer; + uint32_t BPB_RootClus; + uint16_t BPB_FSInfo; + uint16_t BPB_BkBootSec; + uint8_t BPB_Reserved[12]; + uint8_t BS_DrvNum; + uint8_t BS_Reserved1; + uint8_t BS_BootSig; + uint32_t BS_VolID; + char BS_VolLab[11]; + char BS_FilSysType[8]; + } __attribute__((packed)) fat32; + }; +} __attribute__((packed)) FatBpb; + +typedef struct FatFsInfo { + uint32_t FSI_LeadSig; + uint8_t FSI_Reserved1[480]; + uint32_t FSI_StrucSig; + uint32_t FSI_Free_Count; + uint32_t FSI_Nxt_Free; + uint8_t FSI_Reserved2[12]; + uint32_t FSI_TrailSig; +} __attribute__((packed)) FatFsInfo; + +typedef struct FatInfo { + Partition *partition; + FileSystemInfo *fs_info; + FatType type; + + StorageDevice *storage_device; + + FatBpb *bpb; + FatFsInfo *fat_fs_info; + + uint32_t fat_start; + uint32_t data_start; + int fat_sectors; + int data_sectors; + int total_sectors; + int bytes_per_cluster; + int sector_per_cluster; + int entry_per_cluster; + int num_count; + + BlockCache *fat_table_cache; + + uint32_t last_cluster; + + FatDirEntry root_entry; +} FatInfo; + +#endif \ No newline at end of file diff --git a/src/fs/fat/include/name.h b/src/fs/fat/include/name.h new file mode 100644 index 0000000..277ff70 --- /dev/null +++ b/src/fs/fat/include/name.h @@ -0,0 +1,40 @@ +#ifndef _FAT_NAME_H +#define _FAT_NAME_H + +#include "fs/fs.h" +#include "multiple_return.h" + +typedef struct ShortName { + char base[8]; + char ext[3]; +} __attribute__((packed)) ShortName; + +typedef enum NameType { + SHORT_NAME, + LONG_NAME, + INVALID_NAME_TYPE, +} NameType; + +enum FatType; +struct FatInfo; +struct FatDirEntry; +struct ShortDir; +struct LongDir; +int check_name_caps(uint8_t *name, int len); +bool is_available_short_name_char(uint8_t c); +NameType check_name(enum FatType type, uint8_t *text, int len); +FsResult short_name_new(string_t name, ShortName *short_name); +uint8_t fat_checksum(ShortName *short_name); +int read_long_name(struct LongDir *long_dir, uint16_t *utf16_name); +string_t read_short_name(struct ShortDir *short_dir); +FsResult long_name2short_name( + struct FatInfo *fat_info, struct FatDirEntry *parent, string_t long_name, + bool is_directory, ShortName *short_name); + +void fat_utf16_to_utf8(uint16_t *utf16, int utf16_length, string_t *utf8); +void fat_utf8_to_utf16( + uint8_t *utf8, uint16_t *utf16, DEF_MRET(int, utf8_length), + DEF_MRET(int, utf16_length)); +int fat_utf16_count_utf8_length(uint16_t *utf16, int utf16_length); + +#endif \ No newline at end of file diff --git a/src/fs/fat/include/time.h b/src/fs/fat/include/time.h new file mode 100644 index 0000000..a565b3f --- /dev/null +++ b/src/fs/fat/include/time.h @@ -0,0 +1,8 @@ +#ifndef _FAT_TIME_H +#define _FAT_TIME_H + +#define FAT_DATE(year, month, day) (((year - 1980) << 9) | (month << 5) | day) +#define FAT_TIME(hour, minute, second) \ + ((hour << 11) | (minute << 5) | (second >> 1)) + +#endif \ No newline at end of file diff --git a/src/fs/fat/name.c b/src/fs/fat/name.c new file mode 100644 index 0000000..12a2fa8 --- /dev/null +++ b/src/fs/fat/name.c @@ -0,0 +1,433 @@ +#include "include/name.h" +#include "include/dir.h" +#include "include/fat.h" +#include "math.h" +#include "multiple_return.h" +#include +#include +#include + +/** + * @brief 确认文件名与扩展名的大小写状况 + * + * @param name 文件名 + * @param len 文件名长度 + */ +int check_name_caps(uint8_t *name, int len) { + int ret = 0; + int flag = 0; + for (int i = 0; i < len; i++) { + if (name[i] == '.') { + flag = 2; + continue; + } + if ('a' <= name[i] && name[i] <= 'z') { + ret |= 1 << flag; + } else if ('A' <= name[i] && name[i] <= 'Z') { + ret |= 2 << flag; + } + } + return ret; +} + +bool is_available_short_name_char(uint8_t c) { + // 非ASCII字符 + if (c >= 0x80) { return false; } + // '^', '_', '`', a-z, '{' + if ('^' <= c && c <= '{') { return true; } + // '@', A-Z + if ('@' <= c && c <= 'Z') { return true; } + // 0-9 + if ('0' <= c && c <= '9') { return true; } + // ' ', '!', '#', $', '%', '&', '\'' ,'(', ')' + if (' ' <= c && c <= ')' && c != '\"') { return true; } + // '-', '}', '~' + if (c == '-' || c == '}' || c == '~') { return true; } + return false; +} + +bool is_available_long_name_char(uint8_t c) { + // '@', A-Z, '[', ']', + if ('@' <= c && c <= ']') { return true; } + // '^', '_', '`', a-z, '{' + if ('^' <= c && c <= '{') { return true; } + // 0-9 + if ('0' <= c && c <= '9') { return true; } + // '+', ',', '-', '.' + if ('+' <= c && c <= '.') { return true; } + // ' ', '!', '#', '$', '%', '&', '\'', '(', ')' + if (' ' <= c && c <= ')' && c != '\"') { return true; } + // ';', '}', '~' + if (c == ';' || c == '}' || c == '~') { return true; } + return false; +} + +/** + * @brief 确认文件名是否能直接作为短文件名 + * + * @param name 文件名 + */ +bool check_short_name(uint8_t *text, int len, int dot) { + // 如果文件名和扩展名的长度超过了8.3 + if (dot > 8 || dot < len - 3) return false; + + // 如果存在大小写混合 + int caps = check_name_caps(text, len); + if ((caps & 0x03) || (caps & 0x0c) == 0x0c) return false; + + for (int i = 0; i < len; i++) { + if (i == dot) continue; + if (!is_available_short_name_char(text[i])) return false; + } + return true; +} + +bool check_long_name(uint8_t *text, int len) { + for (int i = 0; i < len; i++) { + if (text[i] == 0) break; + if (text[i] >= 0x80) { + // 跳过UTF-8字符 + if ((text[i] & 0xe0) == 0xc0) i++; + if ((text[i] & 0xf0) == 0xe0) i += 2; + if ((text[i] & 0xf8) == 0xf0) i += 3; + } else if (!is_available_long_name_char(text[i])) return false; + } + return true; +} + +NameType check_name(FatType type, uint8_t *text, int len) { + int dot = 0; + while (text[dot] != '.' && dot < len) { + dot++; + } + if (!check_short_name(text, len, dot)) { + if (type == FAT_TYPE_FAT32 && check_long_name(text, len)) { + return LONG_NAME; + } + return INVALID_NAME_TYPE; + } + return SHORT_NAME; +} + +FsResult short_name_new(string_t name, ShortName *short_name) { + int len = name.length; + uint8_t *text = (uint8_t *)name.text; + + int dot = len - 1; + while (text[dot] != '.' && dot >= 0) { + dot--; + } + + if (!check_short_name(text, len, dot)) { + return FS_ERROR_INVALID_PATH_OR_NAME; + } + + for (int i = 0; i < 8; i++) { + if (i < dot) { + if ('a' <= text[i] && text[i] <= 'z') { + short_name->base[i] = text[i] - 32; + } else { + short_name->base[i] = text[i]; + } + } else { + short_name->base[i] = ' '; + } + } + for (int i = 0; i < 3; i++) { + if (i < len - dot) { + char c = text[dot + 1 + i]; + if ('a' <= c && c <= 'z') { + short_name->ext[i] = c - 32; + } else { + short_name->ext[i] = c; + } + } else { + short_name->ext[i] = ' '; + } + } + + return FS_OK; +} + +uint8_t fat_checksum(ShortName *short_name) { + uint8_t *name = (uint8_t *)short_name; + + uint8_t sum = 0; + for (int i = 11; i != 0; i--) { + sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + *name++; + } + return sum; +} + +int read_long_name(LongDir *long_dir, uint16_t *utf16_name) { + int x; + int pos = 0; + for (x = 0; x < 5; x++) { + if (long_dir->name1[x] == 0xffff || long_dir->name1[x] == 0x00) break; + else utf16_name[pos++] = long_dir->name1[x]; + } + for (x = 0; x < 6; x++) { + if (long_dir->name2[x] == 0xffff || long_dir->name2[x] == 0x00) break; + else utf16_name[pos++] = long_dir->name2[x]; + } + for (x = 0; x < 2; x++) { + if (long_dir->name3[x] == 0xffff || long_dir->name3[x] == 0x00) break; + else utf16_name[pos++] = long_dir->name3[x]; + } + return pos++; +} + +string_t read_short_name(ShortDir *short_dir) { + int j = 0; + int x; + string_t name; + name.text = kmalloc(13); + name.max_length = 13; + + for (x = 0; x < 8; x++) { + char c = short_dir->name.base[x]; + if (c != ' ') { + if ('A' <= c && c <= 'Z') { + name.text[j++] = + (short_dir->nt_res & FAT32_BASE_L) ? c + 32 : c; + } else { + name.text[j++] = c; + } + } + } + if (short_dir->name.ext[0] == ' ' && short_dir->name.ext[1] == ' ' && + short_dir->name.ext[2] == ' ') { + name.length = j; + return name; + } + name.text[j++] = '.'; + for (x = 0; x < 3; x++) { + char c = short_dir->name.ext[x]; + if (c == ' ') { + if ('A' <= c && c <= 'Z') { + name.text[j++] = (short_dir->nt_res & FAT32_EXT_L) ? c + 32 : c; + } else { + name.text[j++] = c; + } + } + } + return name; +} + +FsResult long_name2short_name( + FatInfo *fat_info, FatDirEntry *parent, string_t long_name, + bool is_directory, ShortName *short_name) { + if (short_name == NULL) { return FS_ERROR_OUT_OF_MEMORY; } + + int len = long_name.length; + uint8_t *text = (uint8_t *)long_name.text; + bool flag = true; + + int dot = len - 1; + while (text[dot] != '.' && dot >= 0) { + dot--; + } + int base_name_len = 0; + int ext_name_len = 0; + char tmp_name[12] = " "; + + int i, j; + for (i = 0, j = 0; i < 8; i++) { + if (i < dot) { + if (is_available_short_name_char(text[i])) { + if ('a' <= text[i] && text[i] <= 'z') { + short_name->base[j] = text[i] - 32; + } else { + short_name->base[j] = text[i]; + } + } else if (text[i] >= 0x80) { // 跳过UTF-8字符 + flag = false; + short_name->base[j] = '_'; + } else { + continue; + } + tmp_name[j] = short_name->base[j]; + base_name_len++; + } else { + short_name->base[j] = ' '; + } + j++; + } + + tmp_name[j] = '.'; + int k = j + 1; + + for (i = 0, j = 0; i < 3; i++) { + if (i < dot) { + uint8_t c = text[dot + 1 + i]; + if (is_available_short_name_char(c)) { + if ('a' <= c && c <= 'z') { + short_name->ext[j] = c - 32; + } else { + short_name->ext[j] = c; + } + } else if (c >= 0x80) { + flag = false; + short_name->ext[j] = '_'; + } else { + continue; + } + } else { + short_name->ext[j] = ' '; + } + tmp_name[k + j] = short_name->ext[j]; + j++; + ext_name_len++; + } + + string_t name; + name.text = tmp_name; + name.length = base_name_len + ext_name_len + 1; + name.max_length = name.length; + + if (!flag && check_short_name((uint8_t *)short_name, 11, dot)) { + // 完全满足短文件名条件,检查是否重名 + return search_dir(fat_info, parent, name, is_directory, NULL, 0); + } else { + for (int n = 1; n < 999999; n++) { + // 统计位数 + int x = n; + int i = MIN(base_name_len, 7); + while (x != 0 && i > 1) { + char c = (x % 10) + '0'; + short_name->base[i] = c; + x /= 10; + i--; + } + short_name->base[i] = '~'; + + // 检查是否重名 + FsResult result = + search_dir(fat_info, parent, name, is_directory, NULL, 0); + if (result == FS_ERROR_CANNOT_FIND) { + // 找不到说明可用 + return FS_OK; + } + // 找得到说明重名,继续循环 + } + } + + return FS_ERROR_INVALID_PATH_OR_NAME; +} + +uint32_t fat_utf16_to_unicode(uint16_t **utf16) { + uint16_t *buf = *utf16; + uint32_t unicode = buf[0]; + if (((buf[0] & 0xfc00) == 0xdc00) && ((buf[1] & 0xfc00) == 0xd800)) { + unicode = (buf[1] & 0x03ff) << 16; + unicode |= buf[0] & 0x03ff; + (*utf16)++; + } + (*utf16)++; + return unicode; +} + +uint32_t fat_utf8_to_unicode(uint8_t **utf8) { + uint32_t unicode = 0; + uint8_t *buf = *utf8; + if (buf[0] < 0x80) { + unicode = buf[0]; + (*utf8)++; + } else if (buf[0] < 0xe0) { + unicode = (buf[0] & 0x1f) << 6; + unicode |= buf[1] & 0x3f; + (*utf8) += 2; + } else if (buf[0] < 0xf0) { + unicode = (buf[0] & 0x0f) << 12; + unicode |= (buf[1] & 0x3f) << 6; + unicode |= buf[2] & 0x3f; + (*utf8) += 3; + } else { + unicode = (buf[0] & 0x07) << 18; + unicode |= (buf[1] & 0x3f) << 12; + unicode |= (buf[2] & 0x3f) << 6; + unicode |= buf[3] & 0x3f; + (*utf8) += 4; + } + return unicode; +} + +void fat_unicode_to_utf16(uint32_t unicode, uint16_t **utf16) { + uint16_t *buf = *utf16; + if (unicode < 0x10000) { + buf[0] = unicode; + } else { + buf[0] = 0xd800 | ((unicode >> 10) & 0x03ff); + buf[1] = 0xdc00 | (unicode & 0x03ff); + (*utf16)++; + } + (*utf16)++; +} + +int fat_utf16_count_utf8_length(uint16_t *utf16, int utf16_length) { + int utf8_length = 0; + uint16_t *p = utf16; + for (int i = 0; i < utf16_length; i++) { + uint32_t unicode = fat_utf16_to_unicode(&p); + + if (unicode < 0x80) { + utf8_length += 1; + } else if (unicode < 0x800) { + utf8_length += 2; + } else if (unicode < 0x10000) { + utf8_length += 3; + } else { + utf8_length += 4; + } + } + return utf8_length; +} + +void fat_utf16_to_utf8(uint16_t *utf16, int utf16_length, string_t *utf8) { + int utf8_length = fat_utf16_count_utf8_length(utf16, utf16_length); + utf8->text = kmalloc(utf8_length + 1); + utf8->length = utf8_length; + utf8->max_length = utf8_length + 1; + + uint16_t *p = utf16; + uint8_t *q = (uint8_t *)utf8->text; + for (int i = 0; i < utf16_length; i++) { + uint32_t unicode = fat_utf16_to_unicode(&p); + + if (unicode < 0x80) { + q[0] = unicode; + q++; + } else if (unicode < 0x800) { + q[0] = 0xc0 | (unicode >> 6); + q[1] = 0x80 | (unicode & 0x3f); + q += 2; + } else if (unicode < 0x10000) { + q[0] = 0xe0 | (unicode >> 12); + q[1] = 0x80 | ((unicode >> 6) & 0x3f); + q[2] = 0x80 | (unicode & 0x3f); + q += 3; + } else { + q[0] = 0xf0 | (unicode >> 18); + q[1] = 0x80 | ((unicode >> 12) & 0x3f); + q[2] = 0x80 | ((unicode >> 6) & 0x3f); + q[3] = 0x80 | (unicode & 0x3f); + q += 4; + } + } + return; +} + +void fat_utf8_to_utf16( + uint8_t *utf8, uint16_t *utf16, DEF_MRET(int, utf8_length), + DEF_MRET(int, utf16_length)) { + uint32_t unicode; + uint8_t *p = utf8; + uint16_t *q = utf16; + while (*p != '\0' || *(p + 1) != '\0') { + unicode = fat_utf8_to_unicode(&p); + fat_unicode_to_utf16(unicode, &q); + } + MRET(utf8_length) = p - utf8; + MRET(utf16_length) = q - utf16; + return; +} diff --git a/src/fs/fat32.c b/src/fs/fat32.c deleted file mode 100644 index fcca895..0000000 --- a/src/fs/fat32.c +++ /dev/null @@ -1,843 +0,0 @@ -/** - * @file fat32.c - * @author Ryan Wang (ryan1202@foxmail.com) - * @brief FAT32文件系统 - * @version 1.1 - * @date 2023-01-23 - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -// struct FAT_clus_list *clus_list; - -fs_operations_t fat32_fs_ops = { - .fs_check = fat32_check, - .fs_read_superblock = fat32_readsuperblock, - .fs_open = FAT32_open, - .fs_opendir = FAT32_find_dir, - .fs_close = FAT32_close, - .fs_read = FAT32_read, - .fs_write = FAT32_write, - .fs_create = FAT32_create_file, - .fs_delete = FAT32_delete_file, -}; - -status_t fat32_check(struct partition_table *pt) { - if (pt->fs_type == 0x0b || pt->fs_type == 0x0c) { return SUCCUESS; } - return FAILED; -} - -status_t fat32_readsuperblock(partition_t *partition, char *data) { - struct FAT32_dir sdir; - struct pt_fat32 *fat32 = kmalloc(sizeof(struct pt_fat32)); - struct index_node *dev = partition->device->inode; - memcpy(fat32, data, SECTOR_SIZE); - dev->f_ops.seek(dev, partition->start_lba + 1, 0); - dev->f_ops.read(dev, (uint8_t *)&fat32->FSInfo, SECTOR_SIZE); - - if (fat32->FSInfo.FSI_LeadSig == 0x41615252) { - partition->root->device = partition->device; - struct directory *dir = kmalloc(sizeof(struct directory)); - fat32->fat_buffer = kmalloc(SECTOR_SIZE); - - dir->start = 2; // 根目录在2号簇 - dir->inode = partition->root; - fat32->fat_start = partition->start_lba + fat32->BPB_RevdSecCnt; - fat32->data_start = fat32->fat_start + fat32->BPB_NumFATs * fat32->BPB_FATSz32; - fat32->buffer_pos = 0; - partition->private_data = fat32; - partition->root->dir = dir; - - dev->f_ops.seek(dev, fat32->data_start, 0); - dev->f_ops.read(dev, (uint8_t *)&sdir, sizeof(struct FAT32_dir)); - if (sdir.DIR_Attr == FAT32_ATTR_VOLUME_ID) { - string_del(&partition->name); - int cnt = 0; - while (sdir.DIR_Name[cnt] != ' ' && cnt < 11) - cnt++; - string_new(&partition->name, (char *)sdir.DIR_Name, cnt); - } - - return SUCCUESS; - } - kfree(fat32); - return FAILED; -} - -int FAT32_read(struct index_node *inode, uint8_t *buffer, uint32_t length) { - struct file *fp = inode->fp; - struct index_node *dev = inode->part->device->inode; - struct pt_fat32 *fat32 = fs_FAT32(inode->part->private_data); - int cnt, off = 0, tmp; - int pos; - const uint32_t clus_size = SECTOR_SIZE * fat32->BPB_SecPerClus; - const uint8_t *buf = kmalloc(clus_size); - - cnt = fp->offset / (clus_size); - pos = fp->index_table[cnt]; - dev->f_ops.seek(dev, - (fp->offset / SECTOR_SIZE) % fat32->BPB_SecPerClus + fat32->data_start + - (pos - 2) * fat32->BPB_SecPerClus, - 0); - if (fp->offset % (clus_size)) { - tmp = clus_size - fp->offset % (clus_size); - dev->f_ops.read(dev, (uint8_t *)buf, SECTOR_SIZE); - memcpy(buffer, buf + fp->offset % (clus_size), tmp); - off += tmp; - cnt++; - } - while (length - off > clus_size) { - pos = fp->index_table[cnt++]; - dev->f_ops.seek(dev, fat32->data_start + (pos - 2) * fat32->BPB_SecPerClus, 0); - dev->f_ops.read(dev, buffer + off, MIN(clus_size, length - off)); - off += clus_size; - } - tmp = fp->offset; - fp->offset += length; - if (fp->offset >= fp->size) { fp->offset = fp->size; } - return fp->offset - tmp; -} - -int FAT32_write(struct index_node *inode, uint8_t *buffer, uint32_t length) { - int i; - int pos; - struct file *fp = inode->fp; - struct pt_fat32 *fat32 = inode->part->private_data; - const uint8_t *buf = kmalloc(SECTOR_SIZE * fat32->BPB_SecPerClus); - struct FAT32_dir *sdir; - struct index_node *dev = inode->device->inode; - - int cnt = DIV_ROUND_UP(fp->offset, (SECTOR_SIZE * fat32->BPB_SecPerClus)); - int off = fp->offset % SECTOR_SIZE; - int off2 = cnt % fat32->BPB_SecPerClus; - - if (cnt > inode->fp->size / SECTOR_SIZE / fat32->BPB_SecPerClus) { - cnt = inode->fp->size / SECTOR_SIZE / fat32->BPB_SecPerClus; - } - pos = inode->fp->index_table[cnt]; - - dev->f_ops.seek(dev, off2 + (fat32->data_start + (pos - 2) * fat32->BPB_SecPerClus), 0); - dev->f_ops.write(dev, (uint8_t *)buf, MIN(SECTOR_SIZE - off, off + length)); - if (fp->offset % SECTOR_SIZE + length <= SECTOR_SIZE) goto done; - else { length -= SECTOR_SIZE - off; } - - i = 0; - while (length > 0) { - if (i % 2 == 0 && i != 0) { pos = fat_next(inode, pos, 1, 1); } - dev->f_ops.seek(dev, (i % 2 + (pos - 2) * fat32->BPB_SecPerClus + fat32->data_start), 0); - } - -done: - pos = fat_next(inode, fp->dir_start, fp->dir_offset / (SECTOR_SIZE * fat32->BPB_SecPerClus), 0); - dev->f_ops.seek(dev, fat32->data_start + (pos - 2) * fat32->BPB_SecPerClus + fp->dir_offset / SECTOR_SIZE, - 0); - dev->f_ops.read(dev, (uint8_t *)buf, SECTOR_SIZE); - sdir = (struct FAT32_dir *)(buf + fp->dir_offset % SECTOR_SIZE); - - inode->last_access_date.year = inode->write_date.year = BCD2BIN(CMOS_READ(CMOS_YEAR)); - inode->last_access_date.month = inode->write_date.month = BCD2BIN(CMOS_READ(CMOS_MONTH)); - inode->last_access_date.day = inode->write_date.day = BCD2BIN(CMOS_READ(CMOS_DAY_OF_MONTH)); - inode->write_time.hour = BCD2BIN(CMOS_READ(CMOS_HOURS)); - inode->write_time.minute = BCD2BIN(CMOS_READ(CMOS_MINUTES)); - inode->write_time.second = BCD2BIN(CMOS_READ(CMOS_SECONDS)); - sdir->DIR_LastAccDate = sdir->DIR_WrtDate = - (inode->write_date.year + 20) << 9 | inode->write_date.month << 5 | inode->write_date.day; - sdir->DIR_WrtTime = - inode->write_time.hour << 11 | inode->write_time.minute << 5 | inode->write_time.second; - dev->f_ops.seek(dev, fat32->data_start + (pos - 2) * fat32->BPB_SecPerClus + fp->dir_offset / SECTOR_SIZE, - 0); - dev->f_ops.write(dev, (uint8_t *)buf, SECTOR_SIZE); - - fp->offset += length; - return length; -} - -struct index_node *FAT32_create_file(partition_t *part, struct index_node *parent, char *name, int len) { - struct index_node *dev = part->device->inode; - char buf[SECTOR_SIZE], filename_short[11]; - unsigned int pos, i = 0, j, len2, name_count = 1, count = 1, name_len; - unsigned char checksum; - struct directory *dir = parent->dir; - struct pt_fat32 *fat32 = part->private_data; - struct FAT32_long_dir *ldir; - struct FAT32_dir *sdir; - struct index_node *inode = vfs_create(name, ATTR_FILE, parent); - struct file *file = kmalloc(sizeof(struct file)); - uint32_t offset; - int flag; - - file->inode = inode; - file->dir_start = parent->dir->start; - file->cur_pos = 0; - file->start = 0; - inode->fp = file; - inode->device = parent->device; - inode->part = part; - inode->f_ops = parent->f_ops; - pos = dir->start; - do { - // 如果到了下一个扇区,重新读取 - if (i % SECTOR_SIZE == 0) { - offset = fat32->data_start + (pos - 2) * fat32->BPB_SecPerClus + i / SECTOR_SIZE; - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)buf, SECTOR_SIZE); - } - - /** - * 统计短目录项重名个数(只在目录项是长文件名时使用) - * 如有重名,则短目录名以以下格式命名: SAMEFI~N.TXT (假设原名为samefilename.txt) - * 如果当前数字不够,则将'~'前移 - */ - if (buf[i % SECTOR_SIZE + 11] != FAT32_ATTR_LONG_NAME) { - flag = 1; - for (j = 0; j < 8 && buf[i % SECTOR_SIZE + j] != '~'; j++) { - if (buf[i % SECTOR_SIZE + j] != name[j]) { - flag = 0; - break; - } - } - if (flag) { name_count++; } - } - i += 0x20; - - if (i / SECTOR_SIZE / fat32->BPB_SecPerClus) pos = fat_next(inode, pos, 1, 1); - } while (buf[i]); - - flag = 0; - pos = ((pos - 2) * fat32->BPB_SecPerClus) * SECTOR_SIZE + i; - int len_without_ext; - int len_ext; - - for (i = 0; i < len && name[i] != '.'; i++) - if (islower(name[i])) flag |= 0x1; // 文件名含小写 - else if (isupper(name[i])) flag |= 0x2; // 文件名含大写 - - len_without_ext = i; - len_ext = len - len_without_ext - 1; - - if (i >= len) len_ext++; // 无扩展名文件 - for (; i < len; i++) - if (islower(name[i])) flag |= 0x4; // 扩展名含小写 - else if (isupper(name[i])) flag |= 0x8; // 扩展名含大写 - - // 文件名和扩展名混杂大小写或长度过长则作为长目录项 - if (len > 11 || len_ext > 3 || len_without_ext > 8 || (flag & 0x03) == 0x03 || (flag & 0x0c) == 0x0c) { - len2 = DIV_ROUND_UP(len, 13); - int tmp = name_count / 10; - while (tmp) { - count++; - tmp /= 10; - } - name_len = min(6, 8 - count - 1); - tmp = 10000000; - for (i = 0; i < 8; i++) { - if (i < name_len) filename_short[i] = toupper(name[i] ? name[i] : ' '); - else if (i == name_len) filename_short[i] = '~'; - else if (i - name_len < count) filename_short[i] = (name_count / tmp % 10 + '0'); - else filename_short[i] = ' '; - tmp /= 10; - } - for (; i < 11; i++) { - if (i - 8 < len_ext) filename_short[i] = name[len - len_ext + i - 8]; - else filename_short[i] = ' '; - } - FAT32_checksum(filename_short, checksum); - for (i = 0; i < len2; i++) { - int k; - if ((pos + i * 0x20) % SECTOR_SIZE == 0) { - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.write(dev, (uint8_t *)buf, SECTOR_SIZE); - offset = fat32->data_start + (pos + i * 0x20) / SECTOR_SIZE; - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)buf, SECTOR_SIZE); - } - ldir = (struct FAT32_long_dir *)(buf + (pos + i * 0x20) % SECTOR_SIZE); - ldir->LDIR_Ord = len2 - i; - if (i == 0) ldir->LDIR_Ord |= 0x40; - int f = 0; - for (j = 0; (j % 13) < 5; j++) { - if (j < len - (len2 - i - 1) * 13) { - ldir->LDIR_Name1[j] = name[j]; - f = 1; - } else { - if (f) ldir->LDIR_Name1[j] = 0xffff; - else { - f = 0; - ldir->LDIR_Name1[j] = 0; - } - } - } - ldir->LDIR_Attr = FAT32_ATTR_LONG_NAME; - ldir->LDIR_Type = 0; - ldir->LDIR_Chksum = checksum; - for (; (j % 13) < 11; j++) { - if (j < len - (len2 - i - 1) * 13) { - ldir->LDIR_Name2[j - 5] = name[j]; - f = 1; - } else { - if (f) ldir->LDIR_Name2[j - 5] = 0xffff; - else { - f = 0; - ldir->LDIR_Name2[j - 5] = 0; - } - } - } - ldir->LDIR_FstClusLO = 0; - for (k = (j % 13); k < 13; k++) { - if (k < len - (len2 - i - 1) * 13) { - ldir->LDIR_Name3[k - 11] = name[j]; - f = 1; - } else { - if (f) ldir->LDIR_Name3[k - 11] = 0xffff; - else { - f = 0; - ldir->LDIR_Name3[k - 11] = 0; - } - } - } - } - pos += i * 0x20; - if (pos % SECTOR_SIZE == 0) { - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.write(dev, (uint8_t *)buf, SECTOR_SIZE); - offset = fat32->data_start + pos / SECTOR_SIZE; - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)buf, SECTOR_SIZE); - } - for (i = 0; i < 11; i++) { - buf[pos % SECTOR_SIZE + i] = filename_short[i]; - } - sdir = (struct FAT32_dir *)(buf + pos % SECTOR_SIZE); - sdir->DIR_Attr = FAT32_ATTR_ARCHIVE; - - int year = BCD2BIN(CMOS_READ(CMOS_YEAR)) + 20; - int month = BCD2BIN(CMOS_READ(CMOS_MONTH)); - int day = BCD2BIN(CMOS_READ(CMOS_DAY_OF_MONTH)); - sdir->DIR_LastAccDate = sdir->DIR_CrtDate = sdir->DIR_WrtDate = year << 9 | month << 5 | day; - int hour = BCD2BIN(CMOS_READ(CMOS_HOURS)); - int minute = BCD2BIN(CMOS_READ(CMOS_MINUTES)); - int second = BCD2BIN(CMOS_READ(CMOS_SECONDS)); - sdir->DIR_CrtTime = sdir->DIR_WrtTime = hour << 11 | minute << 5 | second >> 1; - sdir->DIR_CrtTimeTenth = second * 10; - - int file_clus = fat32_alloc_clus(part, 0, 1); - sdir->DIR_FstClusHI = file_clus >> 16; - sdir->DIR_FstClusLO = file_clus & 0xffff; - sdir->DIR_FileSize = 0; - } else { - for (i = 0, j = 0; i < 8 && name[i] != '.' && j < len; i++, j++) - buf[pos % SECTOR_SIZE + i] = toupper(name[j]); - for (; i < 8; i++) - buf[pos % SECTOR_SIZE + i] = ' '; - for (j++; i < 11; i++, j++) { - if (j < len) buf[pos % SECTOR_SIZE + i] = toupper(name[j]); - else buf[pos % SECTOR_SIZE + i] = ' '; - } - - sdir = (struct FAT32_dir *)(buf + pos % SECTOR_SIZE); - sdir->DIR_Attr = FAT32_ATTR_ARCHIVE; - - sdir->DIR_NTRes = 0; - if (flag & 0x01) sdir->DIR_NTRes |= FAT32_BASE_L; - if (flag & 0x04) sdir->DIR_NTRes |= FAT32_EXT_L; - - int year = BCD2BIN(CMOS_READ(CMOS_YEAR)) + 20; - int month = BCD2BIN(CMOS_READ(CMOS_MONTH)); - int day = BCD2BIN(CMOS_READ(CMOS_DAY_OF_MONTH)); - sdir->DIR_LastAccDate = sdir->DIR_CrtDate = sdir->DIR_WrtDate = year << 9 | month << 5 | day; - int hour = BCD2BIN(CMOS_READ(CMOS_HOURS)); - int minute = BCD2BIN(CMOS_READ(CMOS_MINUTES)); - int second = BCD2BIN(CMOS_READ(CMOS_SECONDS)); - sdir->DIR_CrtTime = sdir->DIR_WrtTime = hour << 11 | minute << 5 | second >> 1; - sdir->DIR_CrtTimeTenth = second * 10; - - int file_clus = fat32_alloc_clus(part, 0, 1); - sdir->DIR_FstClusHI = file_clus >> 16; - sdir->DIR_FstClusLO = file_clus & 0xffff; - sdir->DIR_FileSize = 0; - } - construct_idxtbl(inode); - file->dir_offset = (pos % (SECTOR_SIZE * fat32->BPB_SecPerClus)); - file->start = sdir->DIR_FstClusHI << 16 | sdir->DIR_FstClusLO; - sdir = kmalloc(sizeof(struct FAT32_dir)); - memcpy(sdir, buf + pos % SECTOR_SIZE, sizeof(struct FAT32_dir)); - file->private_data = sdir; - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.write(dev, (uint8_t *)buf, SECTOR_SIZE); - return inode; -} - -void FAT32_delete_file(partition_t *part, struct index_node *inode) { - char buf[SECTOR_SIZE]; - unsigned int pos, i; - struct file *file = inode->fp; - struct pt_fat32 *fat32 = part->private_data; - struct index_node *dev = inode->device->inode; - uint32_t offset; - bool f = true; - offset = fat32->data_start + (inode->fp->dir_start - 2) * fat32->BPB_SecPerClus + - inode->fp->dir_offset / SECTOR_SIZE; - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)buf, SECTOR_SIZE); - pos = inode->fp->dir_offset; - do { - if (pos % SECTOR_SIZE == 0 && pos >= SECTOR_SIZE) { - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.write(dev, (uint8_t *)buf, SECTOR_SIZE); - offset -= 1; - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)buf, SECTOR_SIZE); - } - buf[pos % SECTOR_SIZE] = 0xe5; - pos -= 0x20; - } while (buf[pos % SECTOR_SIZE + 11] & FAT32_ATTR_LONG_NAME); - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.write(dev, (uint8_t *)buf, SECTOR_SIZE); - pos = file->start; // 释放文件在文件分配表中对应的簇 - while (f) { - i = find_member_in_fat(part, pos); - if (i >= 0x0fffffff) f = 0; - fat32_free_clus(part, 0, pos); - pos = i; - } -} - -void FAT32_close(struct index_node *inode) { - struct file *file; - file = inode->fp; - kfree(file->private_data); - return; -} - -struct index_node *FAT32_open(struct _partition_s *part, struct index_node *parent, char *filename) { - int i, j, x; - struct FAT32_long_dir *ldir; - struct FAT32_dir *sdir; - struct directory *dir = parent->dir; - struct file *file = kmalloc(sizeof(struct file)); - struct index_node *inode = vfs_create(filename, ATTR_FILE, parent); - struct index_node *dev = part->device->inode; - struct pt_fat32 *fat32 = part->private_data; - uint32_t offset; - uint8_t flag = 0, f = 1; - unsigned int cc; - uint8_t buf[fat32->BPB_SecPerClus * SECTOR_SIZE]; - file->inode = inode; - inode->fp = file; - inode->part = parent->part; - inode->f_ops = parent->f_ops; - inode->device = parent->device; - int len = strlen(filename); - cc = dir->start; - - while (f) { - if (find_member_in_fat(part, cc) >= 0x0fffffff) f = 0; - offset = fat32->data_start + (cc - 2) * fat32->BPB_SecPerClus; - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)buf, fat32->BPB_SecPerClus * SECTOR_SIZE); - for (i = 0x00; i < SECTOR_SIZE * fat32->BPB_SecPerClus; i += 0x20) { - if (buf[i + 11] == FAT32_ATTR_LONG_NAME) continue; - if (buf[i] == 0xe5 || buf[i] == 0x00 || buf[i] == 0x05) continue; - ldir = (struct FAT32_long_dir *)(buf + i) - 1; - sdir = (struct FAT32_dir *)(buf + i); - j = 0; - - // 如果是长目录项 - while (ldir->LDIR_Attr == FAT32_ATTR_LONG_NAME && ldir->LDIR_Ord != 0xe5) { - for (x = 0; x < 5; x++) { - if (j > len && ldir->LDIR_Name1[x] == 0xffff) continue; - else if (j > len || ldir->LDIR_Name1[x] != (unsigned short)(filename[j++])) goto cmp_fail; - } - for (x = 0; x < 6; x++) { - if (j > len && ldir->LDIR_Name2[x] == 0xffff) continue; - else if (j > len || ldir->LDIR_Name2[x] != (unsigned short)(filename[j++])) goto cmp_fail; - } - for (x = 0; x < 2; x++) { - if (j > len && ldir->LDIR_Name3[x] == 0xffff) continue; - else if (j > len || ldir->LDIR_Name3[x] != (unsigned short)(filename[j++])) goto cmp_fail; - } - - if (j >= len) { - flag = 1; - goto cmp_success; - } - - ldir--; - } - - // 如果是短目录项 - j = 0; - if (sdir->DIR_Attr & FAT32_ATTR_DIRECTORY) continue; - for (x = 0; x < 8; x++) { - if (sdir->DIR_Name[x] == ' ') { - if (!(sdir->DIR_Attr & FAT32_ATTR_DIRECTORY)) { - if (filename[j] == '.' || filename[j] == 0) continue; - else if (sdir->DIR_Name[x] == filename[j]) { - j++; - continue; - } else goto cmp_fail; - } else goto cmp_fail; - } else if ((sdir->DIR_Name[x] >= 'A' && sdir->DIR_Name[x] <= 'Z') || - (sdir->DIR_Name[x] >= 'a' && sdir->DIR_Name[x] <= 'z')) { - if (sdir->DIR_NTRes & FAT32_BASE_L) { - if (j < len && sdir->DIR_Name[x] + 32 == filename[j]) { - j++; - continue; - } else goto cmp_fail; - } else { - if (j < len && sdir->DIR_Name[x] == filename[j]) { - j++; - continue; - } else goto cmp_fail; - } - } else if (sdir->DIR_Name[x] >= '0' && sdir->DIR_Name[x] <= '9') { - if (j < len && sdir->DIR_Name[x] == filename[j]) { - j++; - continue; - } else goto cmp_fail; - } else { - j++; - } - } - j++; - for (x = 0; x < 3; x++) { - if ((sdir->DIR_Ext[x] >= 'A' && sdir->DIR_Ext[x] <= 'Z') || - (sdir->DIR_Ext[x] >= 'a' && sdir->DIR_Ext[x] <= 'z')) { - if (sdir->DIR_NTRes & FAT32_BASE_L) { - if (j < len && sdir->DIR_Ext[x] + 32 == filename[j]) { - j++; - continue; - } else goto cmp_fail; - } else { - if (j < len && sdir->DIR_Ext[x] == filename[j]) { - j++; - continue; - } else goto cmp_fail; - } - } else if (sdir->DIR_Ext[x] >= '0' && sdir->DIR_Ext[x] <= '9') { - if (j < len && sdir->DIR_Ext[x] == filename[j]) { - j++; - continue; - } else goto cmp_fail; - } else if (sdir->DIR_Ext[x] == ' ') { - if (sdir->DIR_Ext[x] == filename[j]) { - if (sdir->DIR_Ext[x] == filename[j]) { - j++; - continue; - } else goto cmp_fail; - } - } else { - goto cmp_fail; - } - } - flag = 1; - goto cmp_success; - cmp_fail:; - } - cc = find_member_in_fat(part, cc); - }; -cmp_success: - if (flag) { - string_init(&inode->name); - string_new(&inode->name, filename, len); - file->dir_start = cc; - file->dir_offset = i; - file->start = file->cur_pos = (sdir->DIR_FstClusHI << 16 | sdir->DIR_FstClusLO) & 0x0fffffff; - file->private_data = kmalloc(sizeof(struct FAT32_dir)); - file->size = sdir->DIR_FileSize; - memcpy(file->private_data, sdir, sizeof(struct FAT32_dir)); - - inode->create_date.year = (sdir->DIR_CrtDate >> 9) - 20; - inode->create_date.month = (sdir->DIR_CrtDate >> 5) & 0x0f; - inode->create_date.day = sdir->DIR_CrtDate & 0x1f; - inode->write_date.year = (sdir->DIR_WrtDate >> 9) - 20; - inode->write_date.month = (sdir->DIR_WrtDate >> 5) & 0x0f; - inode->write_date.day = sdir->DIR_WrtDate & 0x1f; - inode->last_access_date.year = (sdir->DIR_LastAccDate >> 9) - 20; - inode->last_access_date.month = (sdir->DIR_LastAccDate >> 5) & 0x0f; - inode->last_access_date.day = sdir->DIR_LastAccDate & 0x1f; - inode->create_time.hour = sdir->DIR_CrtTime >> 11; - inode->create_time.minute = (sdir->DIR_CrtTime >> 5) & 0x3f; - inode->create_time.second = sdir->DIR_CrtTime & 0x1f; - inode->write_time.hour = sdir->DIR_WrtTime >> 11; - inode->write_time.minute = (sdir->DIR_WrtTime >> 5) & 0x3f; - inode->write_time.second = sdir->DIR_WrtTime & 0x1f; - - construct_idxtbl(inode); - return inode; - } else { - vfs_close(inode); - kfree(file); - return NULL; - } -} - -struct index_node *FAT32_find_dir(struct _partition_s *part, struct index_node *parent, char *name) { - unsigned int i, j, cc, x; - bool flag, f; - uint8_t *buf = kmalloc(((struct pt_fat32 *)part->private_data)->BPB_SecPerClus * SECTOR_SIZE); - struct directory *dir = kmalloc(sizeof(struct directory)); - struct pt_fat32 *fat32 = part->private_data; - struct index_node *dev = part->device->inode; - struct FAT32_long_dir *ldir; - struct FAT32_dir *sdir; - int len = strlen(name); - uint32_t offset; - dir->inode = kmalloc(sizeof(struct index_node)); - dir->inode->attribute = ATTR_DIR; - dir->inode->parent = parent; - dir->inode->f_ops = parent->f_ops; - dir->inode->device = part->device; - dir->inode->part = part; - list_init(&dir->inode->childs); - list_add_tail(&dir->inode->list, &parent->childs); - string_init(&dir->inode->name); - string_new(&dir->inode->name, name, len); - flag = 0; - f = 1; - cc = parent->dir->start; - while (f) { - if (find_member_in_fat(part, cc) >= 0x0fffffff) f = 0; - offset = fat32->data_start + (cc - 2) * fat32->BPB_SecPerClus; - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)buf, fat32->BPB_SecPerClus * SECTOR_SIZE); - for (i = 0x00; i < SECTOR_SIZE * fat32->BPB_SecPerClus; i += 0x20) { - if (buf[i + 11] == FAT32_ATTR_LONG_NAME) continue; - if (buf[i] == 0xe5 || buf[i] == 0x00 || buf[i] == 0x05) continue; - ldir = (struct FAT32_long_dir *)(buf + i) - 1; - j = 0; - - // 如果是长目录项 - while (ldir->LDIR_Attr == FAT32_ATTR_LONG_NAME && ldir->LDIR_Ord != 0xe5) { - for (x = 0; x < 5; x++) { - if (j > len && ldir->LDIR_Name1[x] == 0xffff) continue; - else if (j > len || ldir->LDIR_Name1[x] != (unsigned short)(name[j++])) goto cmp_fail; - } - for (x = 0; x < 6; x++) { - if (j > len && ldir->LDIR_Name2[x] == 0xffff) continue; - else if (j > len || ldir->LDIR_Name2[x] != (unsigned short)(name[j++])) goto cmp_fail; - } - for (x = 0; x < 2; x++) { - if (j > len && ldir->LDIR_Name3[x] == 0xffff) continue; - else if (j > len || ldir->LDIR_Name3[x] != (unsigned short)(name[j++])) goto cmp_fail; - } - - if (j >= len) { - flag = true; - goto cmp_success; - } - - ldir--; - } - - // 如果是短目录项 - j = 0; - sdir = (struct FAT32_dir *)(buf + i); - for (x = 0; x < 11; x++) { - if (sdir->DIR_Name[x] == ' ') { - if (sdir->DIR_Attr & FAT32_ATTR_DIRECTORY) { - if (sdir->DIR_Name[x] == name[j]) { - j++; - continue; - } else { - goto cmp_fail; - } - } - } else if ((sdir->DIR_Name[x] >= 'A' && sdir->DIR_Name[x] <= 'Z') || - (sdir->DIR_Name[x] >= 'a' && sdir->DIR_Name[x] <= 'z')) { - if (sdir->DIR_NTRes & FAT32_BASE_L) { - if (j < len && sdir->DIR_Name[x] + 32 == name[j]) { - j++; - continue; - } else { - goto cmp_fail; - } - } else { - if (j < len && sdir->DIR_Name[x] == name[j]) { - j++; - continue; - } else { - goto cmp_fail; - } - } - - } else if (j < len && sdir->DIR_Name[x] == name[j]) { - j++; - continue; - } else if (sdir->DIR_Name[x] >= '0' && sdir->DIR_Name[x] <= '9') { - goto cmp_fail; - } else { - goto cmp_fail; - } - } - flag = true; - goto cmp_success; - cmp_fail:; - } - cc = find_member_in_fat(part, cc); - }; -cmp_success: - if (flag) { - sdir = (struct FAT32_dir *)(buf + i); - dir->dir_start = cc; - dir->dir_offset = i; - dir->start = (sdir->DIR_FstClusHI << 16 | sdir->DIR_FstClusLO); - dir->inode->dir = dir; - - dir->inode->create_date.year = (sdir->DIR_CrtDate >> 9) - 20; - dir->inode->create_date.month = (sdir->DIR_CrtDate >> 5) & 0x0f; - dir->inode->create_date.day = sdir->DIR_CrtDate & 0x1f; - dir->inode->write_date.year = (sdir->DIR_WrtDate >> 9) - 20; - dir->inode->write_date.month = (sdir->DIR_WrtDate >> 5) & 0x0f; - dir->inode->write_date.day = sdir->DIR_WrtDate & 0x1f; - dir->inode->last_access_date.year = (sdir->DIR_LastAccDate >> 9) - 20; - dir->inode->last_access_date.month = (sdir->DIR_LastAccDate >> 5) & 0x0f; - dir->inode->last_access_date.day = sdir->DIR_LastAccDate & 0x1f; - dir->inode->create_time.hour = sdir->DIR_CrtTime >> 11; - dir->inode->create_time.minute = (sdir->DIR_CrtTime >> 5) & 0x3f; - dir->inode->create_time.second = sdir->DIR_CrtTime & 0x1f; - dir->inode->write_time.hour = sdir->DIR_WrtTime >> 11; - dir->inode->write_time.minute = (sdir->DIR_WrtTime >> 5) & 0x3f; - dir->inode->write_time.second = sdir->DIR_WrtTime & 0x1f; - kfree(buf); - return dir->inode; - } else { - vfs_close(dir->inode); - kfree(dir); - kfree(buf); - return NULL; - } -} - -void construct_idxtbl(struct index_node *inode) { - int i; - - struct pt_fat32 *fat32 = inode->part->private_data; - int cnt = inode->fp->size / SECTOR_SIZE / fat32->BPB_SecPerClus; - inode->fp->index_table = kmalloc(cnt * sizeof(uint32_t)); - - inode->fp->index_table[0] = inode->fp->start; - for (i = 1; i < cnt; i++) { - inode->fp->index_table[i] = find_member_in_fat(inode->part, inode->fp->index_table[i - 1]); - } -} - -int fat32_alloc_clus(partition_t *part, int last_clus, int first) { - int i, j; - struct pt_fat32 *fat32 = part->private_data; - uint32_t offset = fat32->fat_start; - struct index_node *dev = part->device->inode; - - i = 3; - if (DIV_ROUND_UP(i, 128) != fat32->buffer_pos) { - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)fat32->fat_buffer, SECTOR_SIZE); - } - while (fat32->fat_buffer[i % 128]) { - if (i % 128 == 0) { - offset = fat32->fat_start + (i / 128); - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)fat32->fat_buffer, SECTOR_SIZE); - } - i++; - } - for (j = 0; j < fat32->BPB_NumFATs; j++) { - offset = fat32->fat_start + j * fat32->BPB_FATSz32 + (i / 128); - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)fat32->fat_buffer, SECTOR_SIZE); - fat32->fat_buffer[i % 128] = 0x0fffffff; - dev->f_ops.write(dev, (uint8_t *)fat32->fat_buffer, SECTOR_SIZE); - if (!first) { - offset = fat32->fat_start + j * fat32->BPB_FATSz32 + (last_clus / 128); - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)fat32->fat_buffer, SECTOR_SIZE); - fat32->fat_buffer[last_clus % 128] = i; - dev->f_ops.write(dev, (uint8_t *)fat32->fat_buffer, SECTOR_SIZE); - } - } - return i; -} - -int fat32_free_clus(partition_t *part, int last_clus, int clus) { - int buf1[128], buf2[128]; - int j; - struct pt_fat32 *fat32 = part->private_data; - uint32_t offset; - if (last_clus < 3 && clus < 3) return -1; - for (j = 0; j < fat32->BPB_NumFATs; j++) { - if (last_clus > 2 && clus > 2) { - offset = fat32->fat_start + j * fat32->BPB_FATSz32 + last_clus / 128; - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)buf1, SECTOR_SIZE); - if (clus / 128 != last_clus / 128) { - offset = fat32->fat_start + j * fat32->BPB_FATSz32 + clus / 128; - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)buf2, SECTOR_SIZE); - buf1[last_clus % 128] = buf2[clus % 128]; - buf2[clus % 128] = 0x00; - dev->f_ops.write(dev, (uint8_t *)buf2, SECTOR_SIZE); - } else { - buf1[last_clus % 128] = buf1[clus % 128]; - buf1[clus % 128] = 0x00; - } - offset = fat32->fat_start + j * fat32->BPB_FATSz32 + last_clus / 128; - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.write(dev, (uint8_t *)buf1, SECTOR_SIZE); - } else if (clus > 2) { - offset = fat32->fat_start + j * fat32->BPB_FATSz32 + clus / 128; - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)buf1, SECTOR_SIZE); - buf1[clus % 128] = 0x00; - dev->f_ops.write(dev, (uint8_t *)buf1, SECTOR_SIZE); - } - } - return 0; -} - -unsigned int find_member_in_fat(struct _partition_s *part, int i) { - struct index_node *dev = part->device->inode; - unsigned int next_clus; - struct pt_fat32 *fat32 = part->private_data; - uint32_t offset = part->start_lba + fat32->BPB_RevdSecCnt + (i / 128); - if (DIV_ROUND_UP(i, 128) != fat32->buffer_pos) { - dev->f_ops.seek(dev, offset, 0); - dev->f_ops.read(dev, (uint8_t *)fat32->fat_buffer, SECTOR_SIZE); - } - next_clus = fat32->fat_buffer[i % 128]; - return next_clus; -} - -uint32_t fat_next(struct index_node *inode, uint32_t clus, int next, int alloc) { - uint32_t i, tmp, c = clus; - partition_t *part = inode->part; - - if (inode->fp->cur_pos - inode->fp->start < clus) { c = c - (inode->fp->cur_pos - inode->fp->start); } - - for (i = 0; i < next; i++) { - tmp = find_member_in_fat(part, c); - if (tmp < 0x0ffffff8) c = tmp; - else { - if (alloc) { c = fat32_alloc_clus(part, c, 0); } - break; - } - } - - inode->fp->cur_pos = c; - return c; -} - -static __init void fat32_fs_entry(void) { - fs_register("FAT32", &fat32_fs_ops); -} - -fs_initcall(fat32_fs_entry); diff --git a/src/fs/fs.c b/src/fs/fs.c index 3815f01..913a6e5 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c @@ -1,185 +1,63 @@ +#include "fat/include/fat.h" +#include "objects/transfer.h" +#include "stdint.h" #include #include #include #include -#include +#include +#include -LIST_HEAD(part_list_head); LIST_HEAD(fs_list_head); -struct file_operations fs_fops = { - .open = fs_open, .close = fs_close, .read = NULL, .write = NULL, .seek = fs_seek, .ioctl = NULL}; - -struct file *fds[FD_MAX_NR]; -int fd_num; +void register_fs(FileSystem *fs) { + list_add_tail(&fs->list, &fs_list_head); +} -void init_fs(void) { - int i; - struct index_node *inode, *next, *part_inode; - struct partition_table *pt; - for (i = 0; i < FD_MAX_NR; i++) { - fds[i] = NULL; - } - char *buffer = kmalloc(SECTOR_SIZE); - list_for_each_owner_safe (inode, next, &dev->childs, list) { - if (inode->device->type == DEV_STORAGE) { - fs_t *fs, *fs_next; - inode->f_ops.seek(inode, 0, 0); - inode->f_ops.read(inode, (uint8_t *)buffer, SECTOR_SIZE); - for (i = 0; i < 4; i++) { - pt = (struct partition_table *)(buffer + 0x1be + i * sizeof(struct partition_table)); - if (pt->sign != 0x80 && pt->sign != 0x00) continue; - list_for_each_owner_safe (fs, fs_next, &fs_list_head, list) { - if (fs->fs_ops->fs_check(pt) == FAILED) continue; - char *path = kmalloc(inode->name.length + 3); - path[0] = '/'; - strcpy(path + 1, inode->name.text); - path[inode->name.length + 1] = 'p'; - path[inode->name.length + 2] = i + '1'; - part_inode = vfs_mkdir(path); - part_inode->f_ops = fs_fops; - part_inode->f_ops.read = fs->fs_ops->fs_read; - part_inode->f_ops.write = fs->fs_ops->fs_write; - part_inode->part = kmalloc(sizeof(partition_t)); - part_inode->part->fs = fs; - part_inode->part->root = part_inode; - part_inode->part->device = inode->device; - part_inode->part->start_lba = pt->start_lba; - list_add_tail(&part_inode->part->list, &part_list_head); - char *superblock = kmalloc(SECTOR_SIZE); - inode->f_ops.seek(inode, pt->start_lba, 0); - inode->f_ops.read(inode, (uint8_t *)superblock, SECTOR_SIZE); - fs->fs_ops->fs_read_superblock(part_inode->part, superblock); - } - } - } - } +void unregister_fs(FileSystem *fs) { + list_del(&fs->list); } -int fs_register(char *name, fs_operations_t *fs_ops) { - fs_t *fs = kmalloc(sizeof(fs_t)); - string_init(&fs->name); - string_new(&fs->name, name, strlen(name)); - fs->fs_ops = fs_ops; - list_add_tail(&fs->list, &fs_list_head); - return 0; +// 为文件系统实现对象树的接口 +TransferResult fs_obj_read( + struct Object *object, TransferDirection direction, uint8_t *buf, + size_t size) { + FsResult result = object->fs_info->file_ops.fs_read(object, buf, size); + if (result == FS_OK) return TRANSFER_OK; + else return TRANSFER_ERROR_OTHER; } -int alloc_fd(void) { - if (fd_num >= FD_MAX_NR - 1) { - int i; - for (i = 0; i < FD_MAX_NR; i++) { - if (fds[i] == NULL) { - fds[i] = (struct file *)-1; - return i; - } - } - return -1; - } - fd_num++; - return fd_num - 1; +TransferResult fs_obj_write( + struct Object *object, TransferDirection direction, uint8_t *buf, + size_t size) { + FsResult result = object->fs_info->file_ops.fs_write(object, buf, size); + if (result == FS_OK) return TRANSFER_OK; + else return TRANSFER_ERROR_OTHER; } -struct index_node *fs_opendir(char *path) { - struct index_node *inode, *parent, *next; - partition_t *part, *pnext; - uint8_t f; - int l = strlen(path); - char *name = kmalloc(l), *p; - strcpy(name, path); - p = name; - if (p[0] == '/' && p[1] == 0) return root; - int cnt = l; - while (p[cnt] != '/') - cnt--; - p[cnt] = 0; - if ((inode = vfs_opendir(p)) != NULL) return inode; +FsResult fs_obj_create_file( + Object *parent, FileSystemInfo *info, string_t name, Object **object) { + *object = create_object(parent, name, OBJECT_TYPE_FILE); + Object *out = *object; + if (out == NULL) return FS_ERROR_OTHER; - int length = 0; - if (*p != '/') return NULL; // 绝对路径以"/"开始 - else if (p[1] == '\0') { return root; } - p++; - while (p[length] != '/' && p[length] != '\0') - length++; - p[length] = 0; - f = 1; - list_for_each_owner_safe (part, pnext, &part_list_head, list) { - if (strncmp(p, part->root->name.text, length) == 0) { - f = 0; - inode = part->root; - break; - } - } - if (f) return NULL; - while (*p != '\0') { - f = 1; - p += length + 1; - parent = inode; - length = 0; - while (p[length] != '/' && p[length] != '\0') - length++; - p[length] = 0; - // inode = vfs_find(inode, p); - list_for_each_owner_safe (inode, next, &parent->childs, list) { - if (strncmp(p, inode->name.text, length - 1) == 0 && inode->attribute == ATTR_DIR) { - f = 0; - break; - } - } - if (f) inode = parent->part->fs->fs_ops->fs_opendir(parent->part, parent, p); - if (inode == NULL) return NULL; - if (p + length >= name + cnt && inode->attribute == ATTR_DIR) { - string_init(&inode->name); - string_new(&inode->name, p, strlen(p)); - return inode; - } - } - return NULL; -} + out->in.type = TRANSFER_TYPE_STREAM; + out->in.stream = fs_obj_read; + out->out.type = TRANSFER_TYPE_STREAM; + out->out.stream = fs_obj_write; -struct index_node *fs_open(char *path) { - struct index_node *inode, *parent, *next; - inode = vfs_open(path); - if (inode == NULL) { - int cnt = strlen(path) - 1; - while (path[cnt] != '/') - cnt--; - parent = fs_opendir(path); - path[cnt] = 0; - path += cnt + 1; - list_for_each_owner_safe (inode, next, &parent->childs, list) { - if (strncmp(path, inode->name.text, strlen(path) - 1) == 0 && inode->attribute != ATTR_DIR) { - return inode; - } - } - inode = parent->part->fs->fs_ops->fs_open(parent->part, parent, path); - } - return inode; -} + out->fs_info = info; -int fs_close(struct index_node *inode) { - inode->part->fs->fs_ops->fs_close(inode); - kfree(inode->fp); - string_del(&inode->name); - return 0; + return FS_OK; } -int fs_seek(struct index_node *inode, unsigned int offset, unsigned int origin) { - inode->fp->offset = origin + offset; - return 0; -} +FsResult fs_obj_create_dir( + Object *parent, FileSystemInfo *info, string_t name, Object **object) { + *object = create_object_directory(parent, name); + Object *out = *object; + if (out == NULL) return FS_ERROR_OTHER; -int fs_create(struct index_node *parent, char *name) { - struct index_node *inode = vfs_create(name, ATTR_FILE, parent); - inode->fp = parent->fp; - inode->part = parent->part; - inode->f_ops = parent->f_ops; - inode->part->fs->fs_ops->fs_create(inode->part, parent, name, strlen(name)); - return 0; -} + out->fs_info = info; -int fs_delete(struct index_node *inode) { - inode->part->fs->fs_ops->fs_delete(inode->part, inode); - fs_close(inode); - return 0; -} \ No newline at end of file + return FS_OK; +} diff --git a/src/include/driver/storage/disk/disk.h b/src/include/driver/storage/disk/disk.h index f1371eb..6e7299d 100644 --- a/src/include/driver/storage/disk/disk.h +++ b/src/include/driver/storage/disk/disk.h @@ -1,32 +1,45 @@ #ifndef _DISK_H #define _DISK_H +#include "objects/transfer.h" #include "stdint.h" -#include +#include +struct Object; +struct MBRPartitionEntry; typedef struct Partition { enum { PARTITION_TYPE_MBR, PARTITION_TYPE_GPT, } type; union { - MBRPartitionEntry *mbr; + struct MBRPartitionEntry *mbr; }; - size_t start_lba; - size_t size_lba; + size_t start_lba; + size_t size_lba; + uint8_t index; - Object *storage_object; + uint8_t *superblock; + + struct Object *object; + struct Object *storage_object; } Partition; TransferResult disk_transfer_in( - Object *object, TransferDirection direction, uint8_t *buf, + struct Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count); +TransferResult disk_transfer_in_async( + struct Object *object, TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, void **handle); TransferResult disk_transfer_out( - Object *object, TransferDirection direction, uint8_t *buf, + struct Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count); +TransferResult disk_transfer_out_async( + struct Object *object, TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, void **handle); TransferResult disk_is_transfer_in_done( - Object *object, void **handle, bool *is_done); + struct Object *object, void **handle, bool *is_done); TransferResult disk_is_transfer_out_done( - Object *object, void **handle, bool *is_done); + struct Object *object, void **handle, bool *is_done); #endif \ No newline at end of file diff --git a/src/include/driver/storage/disk/mbr.h b/src/include/driver/storage/disk/mbr.h index 00fe5a8..a944906 100644 --- a/src/include/driver/storage/disk/mbr.h +++ b/src/include/driver/storage/disk/mbr.h @@ -1,9 +1,10 @@ #ifndef _DISK_MBR_H #define _DISK_MBR_H -#include +#include +#include -typedef struct { +typedef struct MBRPartitionEntry { uint8_t sign; uint8_t start_chs[3]; uint8_t fs_type; @@ -12,7 +13,8 @@ typedef struct { uint32_t size; } __attribute__((packed)) MBRPartitionEntry; -bool disk_is_mbr(StorageDevice *storage_device); -void parse_mbr_partition_table(StorageDevice *storage_device); +struct StorageDevice; +bool disk_is_mbr(struct StorageDevice *storage_device); +void parse_mbr_partition_table(struct StorageDevice *storage_device); #endif \ No newline at end of file diff --git a/src/include/driver/storage/disk/volume.h b/src/include/driver/storage/disk/volume.h new file mode 100644 index 0000000..e8088db --- /dev/null +++ b/src/include/driver/storage/disk/volume.h @@ -0,0 +1,8 @@ +#ifndef _VOLUME_H +#define _VOLUME_H + +#include "driver/storage/disk/disk.h" + +void probe_volume(Partition *partition); + +#endif \ No newline at end of file diff --git a/src/include/driver/storage/storage_dm.h b/src/include/driver/storage/storage_dm.h index 34da1fd..67e0c0d 100644 --- a/src/include/driver/storage/storage_dm.h +++ b/src/include/driver/storage/storage_dm.h @@ -1,7 +1,6 @@ #ifndef _STORAGE_DM_H #define _STORAGE_DM_H -#include "kernel/device_driver.h" #include "kernel/device_manager.h" #include "kernel/driver.h" #include "kernel/list.h" @@ -24,6 +23,7 @@ typedef struct StorageDeviceOps { bool (*is_busy)(struct StorageDevice *storage_device); } StorageDeviceOps; +struct Object; typedef struct StorageDevice { Device *device; StorageDeviceType type; @@ -41,7 +41,7 @@ typedef struct StorageDevice { list_t block_cache_lh; // 存储设备的分区目录对象 - Object *object; + struct Object *object; } StorageDevice; typedef struct StorageDeviceDriver { @@ -54,8 +54,10 @@ typedef struct StorageDeviceDriver { extern DeviceManager storage_dm; DriverResult register_storage_device( - DeviceDriver *device_driver, Device *device, StorageDevice *storage_device); + struct DeviceDriver *device_driver, Device *device, + StorageDevice *storage_device); DriverResult unregister_storage_device( - DeviceDriver *device_driver, Device *device, StorageDevice *storage_device); + struct DeviceDriver *device_driver, Device *device, + StorageDevice *storage_device); #endif \ No newline at end of file diff --git a/src/include/driver/storage/storage_io.h b/src/include/driver/storage/storage_io.h index 555b5af..c2b2226 100644 --- a/src/include/driver/storage/storage_io.h +++ b/src/include/driver/storage/storage_io.h @@ -4,9 +4,12 @@ #include #include -TransferResult storage_transfer( +TransferResult storage_transfer_async( Object *object, TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, void **handle); +TransferResult storage_transfer( + Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count); TransferResult storage_is_transfer_done( Object *object, void **handle, bool *done); diff --git a/src/include/fs/fat32.h b/src/include/fs/fat32.h deleted file mode 100644 index a21b4b9..0000000 --- a/src/include/fs/fat32.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef FAT32_H -#define FAT32_H - -#include -#include -#include - -#define isFAT32(data) strncmp(((struct pt_fat32 *)data)->BS_FilSysType, "FAT32", 5) == 0 -#define fs_FAT32(fs) ((struct pt_fat32 *)(fs)) -#define FAT32_checksum(string, checksum) \ - { \ - int i; \ - for (i = 0; i < 11; i++) { \ - checksum = ((checksum & 1) ? 0x80 : 0) * (checksum >> 1) * string[i]; \ - } \ - } - -#define FAT32_ATTR_READ_ONLY 0x01 -#define FAT32_ATTR_HIDDEN 0x02 -#define FAT32_ATTR_SYSTEM 0x04 -#define FAT32_ATTR_VOLUME_ID 0x08 -#define FAT32_ATTR_DIRECTORY 0x10 -#define FAT32_ATTR_ARCHIVE 0x20 -#define FAT32_ATTR_LONG_NAME 0x0f - -#define FAT32_BASE_L 0x08 -#define FAT32_EXT_L 0x10 - -struct FS_Info { - unsigned int FSI_LeadSig; - unsigned char FSI_Reserved1[480]; - unsigned int FSI_StrucSig; - unsigned int FSI_Free_Count; - unsigned int FSI_Nxt_Free; - unsigned char FSI_Reserved2[12]; - unsigned int FSI_TrailSig; -} __attribute__((packed)); - -struct pt_fat32 { - unsigned char BS_jmpBoot[3]; - unsigned char BS_OEMName[8]; - unsigned short BPB_BytesPerSec; - unsigned char BPB_SecPerClus; - unsigned short BPB_RevdSecCnt; - unsigned char BPB_NumFATs; - unsigned short BPB_RootEntCnt; - unsigned short BPB_TotSec16; - unsigned char BPB_Media; - unsigned short BPB_FATSz16; - unsigned short BPB_SecPerTrk; - unsigned short BPB_NumHeads; - unsigned int BPB_HiddSec; - unsigned int BPB_TotSec32; - unsigned int BPB_FATSz32; - unsigned short BPB_ExtFlags; - unsigned short BPB_FSVer; - unsigned int BPB_RootClus; - unsigned short BPB_FSInfo; - unsigned short BPB_BkBootSec; - unsigned char BPB_Reserved[12]; - unsigned char BS_DrvNum; - unsigned char BS_Reserved1; - unsigned char BS_BootSig; - unsigned int BS_VolID; - unsigned char BS_VolLab[11]; - unsigned char BS_FilSysType[8]; - unsigned char BootCode[420]; - unsigned short Signature; - - struct FS_Info FSInfo; - - unsigned int fat_start; - unsigned int *fat_buffer, buffer_pos; - unsigned int data_start; - -} __attribute__((packed)); - -struct FAT_clus_list { - struct FAT_clus_list *prev; - unsigned int next_clus; - struct FAT_clus_list *next; -}; - -struct FAT32_dir { - unsigned char DIR_Name[8]; - unsigned char DIR_Ext[3]; - unsigned char DIR_Attr; - unsigned char DIR_NTRes; - unsigned char DIR_CrtTimeTenth; - unsigned short DIR_CrtTime; - unsigned short DIR_CrtDate; - unsigned short DIR_LastAccDate; - unsigned short DIR_FstClusHI; - unsigned short DIR_WrtTime; - unsigned short DIR_WrtDate; - unsigned short DIR_FstClusLO; - unsigned int DIR_FileSize; -} __attribute__((packed)); - -struct FAT32_long_dir { - unsigned char LDIR_Ord; - unsigned short LDIR_Name1[5]; - unsigned char LDIR_Attr; - unsigned char LDIR_Type; - unsigned char LDIR_Chksum; - unsigned short LDIR_Name2[6]; - unsigned short LDIR_FstClusLO; - unsigned short LDIR_Name3[2]; -} __attribute__((packed)); - -status_t fat32_check(struct partition_table *pt); -status_t fat32_readsuperblock(partition_t *partition, char *data); -struct index_node *FAT32_open(struct _partition_s *part, struct index_node *parent, char *filename); -void FAT32_close(struct index_node *inode); -int FAT32_read(struct index_node *inode, uint8_t *buffer, uint32_t length); -int FAT32_write(struct index_node *inode, uint8_t *buffer, uint32_t length); -struct index_node *FAT32_create_file(partition_t *part, struct index_node *parent, char *name, int len); -void FAT32_delete_file(partition_t *part, struct index_node *inode); -struct index_node *FAT32_find_dir(struct _partition_s *part, struct index_node *parent, char *name); -void construct_idxtbl(struct index_node *inode); -int fat32_alloc_clus(partition_t *part, int last_clus, int first); -int fat32_free_clus(partition_t *part, int last_clus, int clus); -unsigned int find_member_in_fat(struct _partition_s *part, int i); -uint32_t fat_next(struct index_node *inode, uint32_t clus, int next, int alloc); - -#endif \ No newline at end of file diff --git a/src/include/fs/fs.h b/src/include/fs/fs.h index b83bcea..e98841b 100644 --- a/src/include/fs/fs.h +++ b/src/include/fs/fs.h @@ -1,62 +1,84 @@ #ifndef _FS_H #define _FS_H +#include "string.h" #include #include -#include - -#define FD_MAX_NR 128 - -struct partition_table { - uint8_t sign; - uint8_t start_chs[3]; - uint8_t fs_type; - uint8_t end_chs[3]; - uint32_t start_lba; - uint32_t size; -}; - -typedef struct { - status_t (*fs_check)(struct partition_table *pt); - status_t (*fs_read_superblock)(struct _partition_s *partition, char *data); - struct index_node *(*fs_open)(struct _partition_s *part, struct index_node *parent, char *filename); - struct index_node *(*fs_opendir)(struct _partition_s *part, struct index_node *parent, char *name); - void (*fs_close)(struct index_node *inode); - int (*fs_read)(struct index_node *inode, uint8_t *buffer, uint32_t length); - int (*fs_write)(struct index_node *inode, uint8_t *buffer, uint32_t length); - struct index_node *(*fs_create)(struct _partition_s *part, struct index_node *parent, char *name, - int len); - void (*fs_delete)(struct _partition_s *part, struct index_node *inode); -} fs_operations_t; - -typedef struct { - list_t list; - string_t name; - fs_operations_t *fs_ops; -} fs_t; - -typedef struct _partition_s { - list_t list; - string_t name; - device_t *device; - fs_t *fs; - struct index_node *root; - int start_lba; - void *private_data; -} partition_t; - -extern struct file *fds[FD_MAX_NR]; -extern int fd_num; - -void init_fs(void); -int alloc_fd(void); -struct index_node *fs_open(char *path); -int fs_close(struct index_node *inode); -int fs_read(struct index_node *inode, uint8_t *buffer, uint32_t length); -int fs_write(struct index_node *inode, uint8_t *buffer, uint32_t length); -int fs_seek(struct index_node *inode, unsigned int offset, unsigned int origin); -int fs_create(struct index_node *parent, char *name); -int fs_delete(struct index_node *inode); -int fs_register(char *name, fs_operations_t *fs_ops); +#include +#include + +typedef enum FsResult { + FS_OK, + FS_ERROR_UNSUPPORT, + FS_ERROR_INVALID_PATH_OR_NAME, + FS_ERROR_OUT_OF_MEMORY, + FS_ERROR_NO_SPARE_SPACE, + FS_ERROR_CANNOT_FIND, + FS_ERROR_ALREADY_EXISTS, + FS_ERROR_END_OF_FILE, + FS_ERROR_ILLEGAL_DATA, + FS_ERROR_NOT_MATCH, + FS_ERROR_OTHER, +} FsResult; + +#define FS_RESULT_PASS(call) \ + { \ + FsResult result = call; \ + if (result != FS_OK) { return result; } \ + } + +struct Partition; +struct FileSystemInfo; +typedef struct FileSystemOps { + FsResult (*fs_check)(struct Partition *partition); + FsResult (*fs_mount)( + struct FileSystemInfo *fs_info, struct Object *root_object); +} FileSystemOps; + +struct Volume; +typedef struct FsFileOps { + FsResult (*fs_open)( + struct FileSystemInfo *fs_info, void *parent, string_t name, + struct Object **object); + FsResult (*fs_close)(struct Object *object); + FsResult (*fs_seek)(struct Object *object, size_t offset); + FsResult (*fs_read)(struct Object *file, void *buf, size_t size); + FsResult (*fs_write)(struct Object *file, void *buf, size_t size); +} FsFileOps; + +typedef struct FsDirectoryOps { + FsResult (*fs_opendir)( + struct FileSystemInfo *fs_info, void *parent, string_t name, + struct Object **object); + FsResult (*fs_closedir)(struct Object *object); + FsResult (*fs_create_file)( + struct Object *directory, string_t name, struct Object **object); + FsResult (*fs_delete_file)(struct Object *directory, string_t name); +} FsDirectoryOps; + +typedef struct FileSystem { + list_t list; + string_t name; + + FileSystemOps *ops; +} FileSystem; + +typedef struct FileSystemInfo { + struct Partition *partition; + void *private_data; + FileSystemOps *ops; + FsFileOps file_ops; + FsDirectoryOps dir_ops; +} FileSystemInfo; + +extern list_t fs_list_head; + +void register_fs(FileSystem *fs); +void unregister_fs(FileSystem *fs); + +FsResult fs_obj_create_file( + Object *parent, FileSystemInfo *info, string_t name, Object **object); +FsResult fs_obj_create_dir( + Object *parent, FileSystemInfo *info, string_t name, Object **object); #endif \ No newline at end of file diff --git a/src/include/kernel/block_cache.h b/src/include/kernel/block_cache.h new file mode 100644 index 0000000..b5c2c32 --- /dev/null +++ b/src/include/kernel/block_cache.h @@ -0,0 +1,48 @@ +#ifndef _BLOCK_CACHE_H +#define _BLOCK_CACHE_H + +#include "driver/storage/storage_dm.h" +#include "fs/fs.h" +#include "kernel/list.h" +#include "kernel/rwlock.h" +#include "stddef.h" + +typedef struct BlockCacheEntry { + struct BlockCache *cache; + list_t list; + size_t position; + void *data; + bool dirty; + rwlock_t lock; + list_t lru_node; +} BlockCacheEntry; + +typedef FsResult (*BlockCacheRealTransfer)( + BlockCacheEntry *cache_entry, size_t cache_size, void *private_data); + +typedef struct BlockCache { + int count; + int size; + list_t lru_lh; // 全局LRU链表头,头部为最近使用 + BlockCacheEntry *entries; + + void *private_data; + + BlockCacheRealTransfer read; + BlockCacheRealTransfer write; +} BlockCache; + +// 创建和销毁LRU缓存 +BlockCache *block_cache_create( + int size, int count, BlockCacheRealTransfer read, + BlockCacheRealTransfer write, void *private_data); +void block_cache_destroy(BlockCache *cache); + +BlockCacheEntry *block_cache_read(BlockCache *cache, size_t position); +BlockCacheEntry *block_cache_write(BlockCache *cache, size_t position); + +void block_cache_read_done(BlockCacheEntry *entry); +void block_cache_write_done( + StorageDevice *storage_device, BlockCacheEntry *entry); + +#endif diff --git a/src/include/kernel/condvar.h b/src/include/kernel/condvar.h index 2fe52f5..94917c6 100644 --- a/src/include/kernel/condvar.h +++ b/src/include/kernel/condvar.h @@ -2,32 +2,15 @@ #define _CONDVAR_H #include "kernel/spinlock.h" -#include "kernel/thread.h" #include "kernel/wait_queue.h" typedef struct { WaitQueue wait_queue; } condvar_t; -void condvar_init(condvar_t *cv) { - wait_queue_init(&cv->wait_queue); -} - -void condvar_wait(condvar_t *cv, spinlock_t *mutex) { - wait_queue_add(&cv->wait_queue); - spin_unlock(mutex); - - thread_block(TASK_BLOCKED); - - spin_lock(mutex); -} - -void condvar_signal(condvar_t *cv) { - wait_queue_wakeup(&cv->wait_queue); -} - -void condvar_broadcast(condvar_t *cv) { - wait_queue_wakeup_all(&cv->wait_queue); -} +void condvar_init(condvar_t *cv); +void condvar_wait(condvar_t *cv, spinlock_t *mutex); +void condvar_signal(condvar_t *cv); +void condvar_broadcast(condvar_t *cv); #endif diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index 32541a0..e250b76 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -4,7 +4,6 @@ #include "kernel/driver.h" #include "kernel/driver_interface.h" #include "kernel/list.h" -#include "objects/object.h" #include "stdint.h" #include "string.h" #include "types.h" @@ -52,8 +51,6 @@ typedef enum { DEVICE_STATE_ERROR, // 设备错误 } DeviceState; -struct DeviceDriver; - typedef struct ChildDevice { bool is_using; uint32_t id; @@ -62,7 +59,8 @@ typedef struct ChildDevice { } ChildDevice; struct Bus; - +struct Object; +struct DeviceDriver; typedef struct Device { list_t bus_list; list_t device_list; @@ -73,7 +71,7 @@ typedef struct Device { struct Bus *bus; - Object *object; + struct Object *object; DeviceIrq *irq; DeviceOps *ops; diff --git a/src/include/kernel/device_driver.h b/src/include/kernel/device_driver.h index 86e2340..2ca3935 100644 --- a/src/include/kernel/device_driver.h +++ b/src/include/kernel/device_driver.h @@ -4,7 +4,6 @@ #include "kernel/device.h" #include "kernel/driver.h" #include "kernel/list.h" -#include "objects/object.h" #include "stdint.h" #include "string.h" @@ -31,6 +30,7 @@ typedef struct DeviceDriverOps { } DeviceDriverOps; struct Bus; +struct Object; typedef struct DeviceDriver { // 继承SubDriver特征 SubDriver subdriver; @@ -43,7 +43,7 @@ typedef struct DeviceDriver { DriverPriority priority; DriverState state; - Object *object; + struct Object *object; DeviceDriverOps *ops; diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index 5a2fc32..ebaad19 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -175,7 +175,7 @@ typedef struct SubDriver { DriverType type; SubDriverState state; - wait_queue_manager_t wqm; + WaitQueue wq; } SubDriver; extern list_t startup_dm_lh; diff --git a/src/include/kernel/rwlock.h b/src/include/kernel/rwlock.h index c679765..d2ef179 100644 --- a/src/include/kernel/rwlock.h +++ b/src/include/kernel/rwlock.h @@ -13,53 +13,11 @@ typedef struct { int write_waiting; } rwlock_t; -void rwlock_init(rwlock_t *lock) { - spinlock_init(&lock->status_lock); - condvar_init(&lock->read_lock); - condvar_init(&lock->write_lock); - lock->read_count = 0; - lock->write_count = 0; - lock->write_waiting = 0; -} - -void rwlock_read_lock(rwlock_t *lock) { - spin_lock(&lock->status_lock); - while (lock->write_count > 0 || lock->write_waiting > 0) { - condvar_wait(&lock->read_lock, &lock->status_lock); - } - lock->read_count++; - spin_unlock(&lock->status_lock); -} - -void rwlock_read_unlock(rwlock_t *lock) { - spin_lock(&lock->status_lock); - lock->read_count--; - if (lock->read_count == 0 && lock->write_waiting > 0) { - condvar_signal(&lock->write_lock); - } - spin_unlock(&lock->status_lock); -} - -void rwlock_write_lock(rwlock_t *lock) { - spin_lock(&lock->status_lock); - lock->write_waiting++; - while (lock->read_count > 0 || lock->write_count > 0) { - condvar_wait(&lock->write_lock, &lock->status_lock); - } - lock->write_waiting--; - lock->write_count++; - spin_unlock(&lock->status_lock); -} - -void rwlock_write_unlock(rwlock_t *lock) { - spin_lock(&lock->status_lock); - lock->write_count--; - if (lock->write_count > 0) { - condvar_signal(&lock->write_lock); - } else { - condvar_broadcast(&lock->read_lock); - } - spin_unlock(&lock->status_lock); -} +void rwlock_init(rwlock_t *lock); +void rwlock_read_lock(rwlock_t *lock); +void rwlock_read_unlock(rwlock_t *lock); +bool rwlock_write_try_lock(rwlock_t *lock); +void rwlock_write_lock(rwlock_t *lock); +void rwlock_write_unlock(rwlock_t *lock); #endif \ No newline at end of file diff --git a/src/include/multiple_return.h b/src/include/multiple_return.h new file mode 100644 index 0000000..ed68dee --- /dev/null +++ b/src/include/multiple_return.h @@ -0,0 +1,7 @@ +#ifndef _MULTIPLE_RETURN_H_ +#define _MULTIPLE_RETURN_H_ + +#define DEF_MRET(type, name) type *out_##name +#define MRET(name) (*out_##name) + +#endif \ No newline at end of file diff --git a/src/include/network/arp.h b/src/include/network/arp.h index 965bbef..ef23393 100644 --- a/src/include/network/arp.h +++ b/src/include/network/arp.h @@ -28,7 +28,7 @@ typedef struct { uint8_t mac[6]; list_t list; - wait_queue_manager_t wqm; + WaitQueue wq; } arp_cache_t; uint8_t *ip2mac(netc_t *netc, uint8_t *ip); diff --git a/src/include/objects/mount.h b/src/include/objects/mount.h new file mode 100644 index 0000000..16e0277 --- /dev/null +++ b/src/include/objects/mount.h @@ -0,0 +1,8 @@ +#ifndef _MOUNT_H +#define _MOUNT_H + +#include "objects/object.h" + +ObjectResult object_mount(Object *origin, Object *dest); + +#endif \ No newline at end of file diff --git a/src/include/objects/object.h b/src/include/objects/object.h index 457ede3..f9db6d3 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -2,6 +2,7 @@ #define _OBJECT_H #include "dyn_array.h" +#include "kernel/list.h" #include "objects/transfer.h" #include "stdint.h" #include "string.h" @@ -12,6 +13,7 @@ typedef enum ObjectResult { OBJECT_ERROR_INVALID_OPERATION, OBJECT_ERROR_CANNOT_FIND, OBJECT_ERROR_ILLEGAL_ARGUMENT, + OBJECT_ERROR_OTHER, } ObjectResult; #define OBJECT_DIR_SIZE_SMALL 8 @@ -33,6 +35,8 @@ typedef enum ObjectType { struct Partition; typedef struct Object { + list_t list; + string_t name; ObjectType type; @@ -40,13 +44,18 @@ typedef struct Object { TransferIn in; TransferOut out; + bool fixed; uint32_t reference; + bool is_mounted; + struct Object *origin; + struct FileSystemInfo *fs_info; + union { uint32_t type; struct { - void *data; - DynArray *children; + void *data; + list_t children; } directory; struct Driver *driver; struct Device *device; @@ -68,7 +77,6 @@ typedef struct Object { } value; struct Object *sym_link; struct Partition *partition; - struct Volume *volume; } value; void (*release_data)(struct Object *object); @@ -78,14 +86,13 @@ extern Object root_object; extern Object bus_object; extern Object driver_object; extern Object device_object; +extern Object volumes_object; ObjectResult init_object_tree(); ObjectResult add_object(Object *parent, Object *child); -ObjectResult init_object_directory(Object *object, size_t block_size); -ObjectResult open_oringinal_object_by_ascii_path( - char *path, Object **out_object); -// 通过ASCII路径打开对象,对于符号链接会自动解析 -ObjectResult open_object_by_ascii_path(char *path, Object **object); +// 通过路径打开对象,对于符号链接会自动解析 +ObjectResult open_oringinal_object_by_path(char *path, Object **out_object); +ObjectResult open_object_by_path(char *path, Object **object); Object *create_object(Object *parent, string_t name, ObjectType type); Object *create_object_directory(Object *parent, string_t name); void object_close(Object *object); diff --git a/src/include/objects/ops.h b/src/include/objects/ops.h new file mode 100644 index 0000000..eb4f664 --- /dev/null +++ b/src/include/objects/ops.h @@ -0,0 +1,18 @@ +#ifndef _OBJECT_OPS_H +#define _OBJECT_OPS_H + +#include "object.h" +#include + +#define OBJ_READ_STREAM(object) (object)->in.stream +#define OBJ_WRITE_STREAM(object) (object)->out.stream +#define OBJ_READ_BLOCK(object) (object)->in.block +#define OBJ_WRITE_BLOCK(object) (object)->out.block +#define OBJ_READ_INTERRUPT(object) (object)->in.interrupt +#define OBJ_WRITE_INTERRUPT(object) (object)->out.interrupt + +ObjectResult obj_open(Object *parent, DEF_MRET(Object *, child), string_t name); +ObjectResult obj_opendir( + Object *parent, DEF_MRET(Object *, child), string_t name); + +#endif \ No newline at end of file diff --git a/src/include/objects/transfer.h b/src/include/objects/transfer.h index 80f662c..2d34b21 100644 --- a/src/include/objects/transfer.h +++ b/src/include/objects/transfer.h @@ -1,7 +1,6 @@ #ifndef _TRANSFER_H #define _TRANSFER_H -#include "result.h" #include "stdint.h" #include @@ -21,10 +20,16 @@ typedef enum { struct Object; typedef TransferResult (*BlockTransfer)( + struct Object *object, TransferDirection direction, uint8_t *buf, + uint32_t position, size_t count); +typedef TransferResult (*BlockTransferAsync)( struct Object *object, TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, void **handle); typedef TransferResult (*StreamTransfer)( + struct Object *object, TransferDirection direction, uint8_t *buf, + size_t size); +typedef TransferResult (*StreamTransferAsync)( struct Object *object, TransferDirection direction, uint8_t *buf, size_t size, void **handle); @@ -54,6 +59,10 @@ typedef struct TransferIn { StreamTransfer stream; InterruptTransfer interrupt; }; + union { + BlockTransferAsync block_async; + StreamTransferAsync stream_async; + }; } TransferIn; typedef struct TransferOut { @@ -63,12 +72,20 @@ typedef struct TransferOut { BlockTransfer block; StreamTransfer stream; }; + union { + BlockTransferAsync block_async; + StreamTransferAsync stream_async; + }; } TransferOut; #define TRANSFER_IN_BLOCK(object, ...) \ ((object)->in.block(object, TRANSFER_IN, __VA_ARGS__)) +#define TRANSFER_IN_BLOCK_ASYNC(object, ...) \ + ((object)->in.block_async(object, TRANSFER_IN, __VA_ARGS__)) #define TRANSFER_IN_STREAM(object, ...) \ ((object)->in.stream(object, TRANSFER_IN, __VA_ARGS__)) +#define TRANSFER_IN_STREAM_ASYNC(object, ...) \ + ((object)->in.stream_async(object, TRANSFER_IN, __VA_ARGS__)) #define TRANSFER_IN_INTTERRUPT(object, ...) \ ((object)->in.interrupt(object, __VA_ARGS__)) @@ -77,8 +94,12 @@ typedef struct TransferOut { #define TRANSFER_OUT_BLOCK(object, ...) \ ((object)->in.block(object, TRANSFER_OUT, __VA_ARGS__)) +#define TRANSFER_OUT_BLOCK_ASYNC(object, ...) \ + ((object)->in.block_async(object, TRANSFER_OUT, __VA_ARGS__)) #define TRANSFER_OUT_STREAM(object, ...) \ ((object)->in.stream(object, TRANSFER_OUT, __VA_ARGS__)) +#define TRANSFER_OUT_STREAM_ASYNC(object, ...) \ + ((object)->in.stream_async(object, TRANSFER_OUT, __VA_ARGS__)) #define TRANSFER_OUT_INTTERRUPT(object, ...) \ ((object)->in.interrupt(object, __VA_ARGS__)) diff --git a/src/include/string.h b/src/include/string.h index 63bcac1..6077c55 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -25,6 +25,9 @@ void string_init(string_t *string); int string_new(string_t *string, char *text, unsigned int max_len); int string_new_with_number( string_t *string, char *text, int text_len, int number); +int string_new_with_string_number( + string_t *string, char *text, int text_len, char *append_text, + int append_text_len, int number); void string_del(string_t *string); int string_cpy(string_t *dest, string_t *src); diff --git a/src/include/types.h b/src/include/types.h index b973a10..c362eef 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -11,4 +11,7 @@ #define offset_t uint64_t +#define PRIVATE static +#define PUBLIC + #endif /*_TYPES_H_*/ \ No newline at end of file diff --git a/src/kernel/Makefile b/src/kernel/Makefile index e4151dd..97c4cf4 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -20,6 +20,9 @@ SRC += app.c SRC += elf.c SRC += wait_queue.c SRC += periodic_task.c +SRC += block_cache.c +SRC += rwlock.c +SRC += condvar.c #INCLUDE_PATH = ../include/ ../$(ARCH)/include/ diff --git a/src/kernel/app.c b/src/kernel/app.c index eb42a32..1725473 100644 --- a/src/kernel/app.c +++ b/src/kernel/app.c @@ -18,28 +18,26 @@ * * @param path 应用程序的路径 */ -void run_app(char *path) -{ - struct program_struct *prog = kmalloc(sizeof(struct program_struct)); - prog->inode = fs_open(path); - if (prog->inode == NULL) { - printk("Cannot find file %s!", path); - } - string_init(&prog->name); - string_init(&prog->filename); - string_init(&prog->path); - string_cpy(&prog->filename, &prog->inode->name); - string_new(&prog->path, path, 255); +void run_app(char *path) { + struct program_struct *prog = kmalloc(sizeof(struct program_struct)); + // prog->inode = fs_open(path); + if (prog->inode == NULL) { printk("Cannot find file %s!", path); } + string_init(&prog->name); + string_init(&prog->filename); + string_init(&prog->path); + string_cpy(&prog->filename, &prog->inode->name); + string_new(&prog->path, path, 255); - char sign[4]; - prog->inode->f_ops.read(prog->inode, (uint8_t *)sign, 4); - if (strncmp(sign, "\177ELF", 4) == 0) { - string_cpy(&prog->name, &prog->filename); - list_init(&prog->seg_head); - unsigned int *entry = elf_load(prog); - process_excute(entry, prog); - } else { - printk("Unsupport Executable File or Command %s!", prog->inode->name.text); - } - fs_close(prog->inode); + char sign[4]; + prog->inode->f_ops.read(prog->inode, (uint8_t *)sign, 4); + if (strncmp(sign, "\177ELF", 4) == 0) { + string_cpy(&prog->name, &prog->filename); + list_init(&prog->seg_head); + unsigned int *entry = elf_load(prog); + process_excute(entry, prog); + } else { + printk( + "Unsupport Executable File or Command %s!", prog->inode->name.text); + } + // fs_close(prog->inode); } \ No newline at end of file diff --git a/src/kernel/block_cache.c b/src/kernel/block_cache.c new file mode 100644 index 0000000..fb5520a --- /dev/null +++ b/src/kernel/block_cache.c @@ -0,0 +1,127 @@ +#include "kernel/block_cache.h" +#include "driver/storage/storage_dm.h" +#include "kernel/rwlock.h" +#include "stddef.h" +#include +#include + +// 将节点移到LRU链表头部 +static void move_to_list_head(BlockCache *cache, BlockCacheEntry *entry) { + list_del(&entry->lru_node); + list_add(&entry->lru_node, &cache->lru_lh); +} + +static BlockCacheEntry *get_free_entry(BlockCache *cache) { + BlockCacheEntry *entry; + list_for_each_owner_reverse (entry, &cache->lru_lh, lru_node) { + if (rwlock_write_try_lock(&entry->lock)) { + if (entry->dirty) { + cache->write(entry, cache->size, cache->private_data); + entry->dirty = false; + list_del(&entry->list); + } + return entry; + } + } + return NULL; +} + +BlockCache *block_cache_create( + int size, int count, BlockCacheRealTransfer read, + BlockCacheRealTransfer write, void *private_data) { + BlockCache *cache = kmalloc(sizeof(BlockCache)); + if (!cache) return NULL; + cache->count = count; + cache->size = size; + cache->entries = kmalloc(sizeof(BlockCacheEntry) * count); + if (!cache->entries) { + kfree(cache); + return NULL; + } + + cache->read = read; + cache->write = write; + cache->private_data = private_data; + + list_init(&cache->lru_lh); + for (int i = 0; i < count; i++) { + BlockCacheEntry *entry = &cache->entries[i]; + rwlock_init(&entry->lock); + entry->list.prev = NULL; + entry->list.next = NULL; + entry->cache = cache; + entry->position = -1; + entry->data = kmalloc(cache->size); + list_add_tail(&entry->lru_node, &cache->lru_lh); + } + return cache; +} + +void block_cache_destroy(BlockCache *cache) { + // 释放所有缓存项 + BlockCacheEntry *entry; + list_t *pos, *next; + list_for_each_safe(pos, next, &cache->lru_lh) { + entry = (BlockCacheEntry *)((char *)pos - + offsetof(BlockCacheEntry, lru_node)); + if (entry->dirty) { + cache->write(entry, cache->size, cache->private_data); + list_del(&entry->list); + } + list_del(&entry->lru_node); + kfree(entry->data); + kfree(entry); + } + kfree(cache); +} + +static BlockCacheEntry *find_entry(BlockCache *cache, size_t position) { + BlockCacheEntry *entry; + list_for_each_owner (entry, &cache->lru_lh, lru_node) { + if (entry->position == position) return entry; + } + return NULL; +} + +BlockCacheEntry *block_cache_read(BlockCache *cache, size_t position) { + BlockCacheEntry *entry = find_entry(cache, position); + if (entry == NULL) { + // 未命中,调用read回调函数 + entry = get_free_entry(cache); + if (entry == NULL) return NULL; + entry->position = position; + cache->read(entry, cache->size, cache->private_data); + move_to_list_head(cache, entry); + rwlock_write_unlock(&entry->lock); + } + rwlock_read_lock(&entry->lock); + return entry; +} + +BlockCacheEntry *block_cache_write(BlockCache *cache, size_t position) { + BlockCacheEntry *entry = find_entry(cache, position); + if (entry == NULL) { + // 未命中,调用read回调函数 + entry = get_free_entry(cache); + if (entry == NULL) return NULL; + entry->position = position; + move_to_list_head(cache, entry); + } else { + rwlock_write_lock(&entry->lock); + } + entry->dirty = true; + return entry; +} + +void block_cache_read_done(BlockCacheEntry *entry) { + rwlock_read_unlock(&entry->lock); +} + +void block_cache_write_done( + StorageDevice *storage_device, BlockCacheEntry *entry) { + if (storage_device->block_cache_lh.next != NULL && + entry->list.prev == NULL) { + list_add_tail(&entry->list, &storage_device->block_cache_lh); + } + rwlock_write_unlock(&entry->lock); +} diff --git a/src/kernel/bus_driver.c b/src/kernel/bus_driver.c index 9c62b7b..e8188fe 100644 --- a/src/kernel/bus_driver.c +++ b/src/kernel/bus_driver.c @@ -11,8 +11,8 @@ #include #include -BusDriver *bus_drivers[BUS_TYPE_MAX]; -wait_queue_manager_t bus_wqm[BUS_TYPE_MAX]; +BusDriver *bus_drivers[BUS_TYPE_MAX]; +WaitQueue bus_wqm[BUS_TYPE_MAX]; DriverResult bus_driver_manager_load(DriverManager *driver_manager); DriverResult bus_driver_manager_unload(DriverManager *driver_manager); diff --git a/src/kernel/condvar.c b/src/kernel/condvar.c new file mode 100644 index 0000000..600b0d5 --- /dev/null +++ b/src/kernel/condvar.c @@ -0,0 +1,22 @@ +#include + +void condvar_init(condvar_t *cv) { + wait_queue_init(&cv->wait_queue); +} + +void condvar_wait(condvar_t *cv, spinlock_t *mutex) { + wait_queue_add(&cv->wait_queue); + spin_unlock(mutex); + + thread_block(TASK_BLOCKED); + + spin_lock(mutex); +} + +void condvar_signal(condvar_t *cv) { + wait_queue_wakeup(&cv->wait_queue); +} + +void condvar_broadcast(condvar_t *cv) { + wait_queue_wakeup_all(&cv->wait_queue); +} \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index f7e5b3a..0b870d6 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -4,9 +4,12 @@ * @brief 内核主程序 * @date 2020-03 */ +#include "string.h" #include +#include #include #include +#include #include #include #include @@ -36,6 +39,7 @@ #include #include #include +#include #include #include @@ -48,10 +52,11 @@ int main() { register_driver_manager(&device_driver_manager); register_driver_manager(&bus_driver_manager); - register_device_manager(&interrupt_device_manager); - register_device_manager(&timer_device_manager); - register_device_manager(&video_device_manager); - register_device_manager(&storage_device_manager); + register_device_manager(&interrupt_dm); + register_device_manager(&timer_dm); + register_device_manager(&time_dm); + register_device_manager(&video_dm); + register_device_manager(&storage_dm); init_memory(); init_object_tree(); @@ -72,6 +77,17 @@ int main() { do_initcalls(); driver_start_all(); + uint8_t buf[512]; + Object *object; + ObjectResult result = open_object_by_path( + "\\Volumes\\Storage0Volume0\\boot\\grub\\grub.cfg", &object); + if (result != OBJECT_OK) { printk("Open File Error!\n"); } + OBJ_READ_STREAM(object)(object, TRANSFER_IN, buf, 512); + // const string_t name = STRING_INIT("一个长文件名.txt"); + // volume->fs->ops->fs_open(volume, "/一个长文件名.txt", &parent); + // volume->fs->ops->fs_create_file(volume, parent, name, &file_object); + // volume->fs->ops->fs_close(object); + // void *handle = NULL; // Object *object; // ObjectResult result = @@ -84,13 +100,10 @@ int main() { // do { // TRANSFER_IN_IS_DONE(object)(object, &handle, &is_done); // } while (!is_done); - // print_hex(buf, 512); + print_hex(buf, 512); // show_object_tree(); - // storage_add_request(device->device_manager_extension, &request); - // init_fs(); - // thread_start( // "NetworkRxPacketProcess", THREAD_DEFAULT_PRIO, net_process_pack, NULL); diff --git a/src/kernel/rwlock.c b/src/kernel/rwlock.c new file mode 100644 index 0000000..5c6ce6d --- /dev/null +++ b/src/kernel/rwlock.c @@ -0,0 +1,63 @@ +#include "types.h" +#include + +void rwlock_init(rwlock_t *lock) { + spinlock_init(&lock->status_lock); + condvar_init(&lock->read_lock); + condvar_init(&lock->write_lock); + lock->read_count = 0; + lock->write_count = 0; + lock->write_waiting = 0; +} + +void rwlock_read_lock(rwlock_t *lock) { + spin_lock(&lock->status_lock); + while (lock->write_count > 0 || lock->write_waiting > 0) { + condvar_wait(&lock->read_lock, &lock->status_lock); + } + lock->read_count++; + spin_unlock(&lock->status_lock); +} + +void rwlock_read_unlock(rwlock_t *lock) { + spin_lock(&lock->status_lock); + lock->read_count--; + if (lock->read_count == 0 && lock->write_waiting > 0) { + condvar_signal(&lock->write_lock); + } + spin_unlock(&lock->status_lock); +} + +bool rwlock_write_try_lock(rwlock_t *lock) { + spin_lock(&lock->status_lock); + if (lock->read_count == 0 && lock->write_count == 0) { + lock->write_count++; + spin_unlock(&lock->status_lock); + return true; + } else { + spin_unlock(&lock->status_lock); + return false; + } +} + +void rwlock_write_lock(rwlock_t *lock) { + spin_lock(&lock->status_lock); + lock->write_waiting++; + while (lock->read_count > 0 || lock->write_count > 0) { + condvar_wait(&lock->write_lock, &lock->status_lock); + } + lock->write_waiting--; + lock->write_count++; + spin_unlock(&lock->status_lock); +} + +void rwlock_write_unlock(rwlock_t *lock) { + spin_lock(&lock->status_lock); + lock->write_count--; + if (lock->write_count > 0) { + condvar_signal(&lock->write_lock); + } else { + condvar_broadcast(&lock->read_lock); + } + spin_unlock(&lock->status_lock); +} diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 8f97918..fbd7d47 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -12,25 +12,30 @@ #include #include -int sys_getpid(void); -int sys_putchar(char c); -int sys_puts(char *str); -int sys_open(char *pathname, int flags); -int sys_close(int fd); -ssize_t sys_read(int fd, void *buf, size_t count); -ssize_t sys_write(int fd, void *buf, size_t count); +int sys_getpid(void); +int sys_putchar(char c); +int sys_puts(char *str); +int sys_open(char *pathname, int flags); +int sys_close(int fd); +size_t sys_read(int fd, void *buf, size_t count); +size_t sys_write(int fd, void *buf, size_t count); typedef void *syscall_t; syscall_t syscall_table[][2] = { - {sys_getpid, (void *)0}, // 此处存的是数字,只是做了类型转换 - {sys_putchar, (void *)1}, {sys_puts, (void *)1}, {sys_open, (void *)2}, - {sys_close, (void *)1}, {sys_read, (void *)3}, {sys_write, (void *)3}, + { sys_getpid, (void *)0}, // 此处存的是数字,只是做了类型转换 + {sys_putchar, (void *)1}, + { sys_puts, (void *)1}, + { sys_open, (void *)2}, + { sys_close, (void *)1}, + { sys_read, (void *)3}, + { sys_write, (void *)3}, }; typedef unsigned long (*syscall0_func_t)(void); typedef unsigned long (*syscall1_func_t)(unsigned long); typedef unsigned long (*syscall2_func_t)(unsigned long, unsigned long); -typedef unsigned long (*syscall3_func_t)(unsigned long, unsigned long, unsigned long); +typedef unsigned long (*syscall3_func_t)( + unsigned long, unsigned long, unsigned long); int sys_getpid(void) { return get_current_thread()->pid; @@ -46,29 +51,30 @@ int sys_puts(char *str) { } int sys_open(char *pathname, int flags) { - struct index_node *inode = fs_open(pathname); - int fd = alloc_fd(); - fds[fd] = inode->fp; - return fd; + // struct index_node *inode = fs_open(pathname); + // int fd = alloc_fd(); + // fds[fd] = inode->fp; + // return fd; } int sys_close(int fd) { - int ret = fds[fd]->inode->f_ops.close(fds[fd]->inode); - fds[fd] = NULL; - return ret; + // int ret = fds[fd]->inode->f_ops.close(fds[fd]->inode); + // fds[fd] = NULL; + // return ret; } -ssize_t sys_read(int fd, void *buf, size_t count) { - struct file *file = fds[fd]; - return file->inode->f_ops.read(file->inode, buf, count); +size_t sys_read(int fd, void *buf, size_t count) { + // struct file *file = fds[fd]; + // return file->inode->f_ops.read(file->inode, buf, count); } -ssize_t sys_write(int fd, void *buf, size_t count) { - struct file *file = fds[fd]; - return file->inode->f_ops.write(file->inode, buf, count); +size_t sys_write(int fd, void *buf, size_t count) { + // struct file *file = fds[fd]; + // return file->inode->f_ops.write(file->inode, buf, count); } -uint32_t do_syscall(uint32_t func, uint32_t arg1, uint32_t arg2, uint32_t arg3) { +uint32_t do_syscall( + uint32_t func, uint32_t arg1, uint32_t arg2, uint32_t arg3) { uint32_t ret = 0; if (syscall_table[func]) { switch ((uint32_t)syscall_table[func][1]) { diff --git a/src/lib/string.c b/src/lib/string.c index 5b55a24..512cd66 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -78,6 +78,35 @@ int string_new_with_number( return 0; } +int string_new_with_string_number( + string_t *string, char *text, int text_len, char *append_text, + int append_text_len, int number) { + + // 计算数字长度 + int len = 0; + int x = number; + do { + len++; + x /= 10; + } while (x > 0); + + int ret = string_new(string, text, text_len + append_text_len + len + 1); + if (ret != 0) { return ret; } + string->length = text_len + append_text_len + len + 1; + string->text[string->length - 1] = '\0'; + + strncpy(string->text + text_len, append_text, append_text_len); + + x = number; + for (int i = text_len + append_text_len + len - 1; + i >= text_len + append_text_len; i--) { + string->text[i] = '0' + x % 10; + x /= 10; + } + + return 0; +} + /** * @brief 删除字符串 * diff --git a/src/network/arp.c b/src/network/arp.c index 94a1a4c..48e167d 100644 --- a/src/network/arp.c +++ b/src/network/arp.c @@ -15,7 +15,7 @@ uint8_t *ip2mac(netc_t *netc, uint8_t *ip) { if (cur->mac[0] != 0) { return cur->mac; } else { - wait_queue_add(&cur->wqm, 0); + wait_queue_add(&cur->wq); thread_block(TASK_BLOCKED); } } @@ -23,7 +23,7 @@ uint8_t *ip2mac(netc_t *netc, uint8_t *ip) { cache = kmalloc(sizeof(arp_cache_t)); memcpy(cache->ip, ip, 4); - wait_queue_init(&cache->wqm); + wait_queue_init(&cache->wq); list_add_tail(&cache->list, &arp_cache_lh); send_arp(netc, ip, ARP_REQUEST); while (cache->mac[0] == 0) {} @@ -61,7 +61,7 @@ void arp_read(uint8_t *buf, uint16_t offset, uint16_t length) { if (memcmp(cur->ip, arp->src_ip, 4) == 0) { if (cur->mac[0] == 0) { memcpy(cur->mac, arp->src_hw_addr, 6); - wait_queue_wakeup_all(&cur->wqm); + wait_queue_wakeup_all(&cur->wq); } else { memcpy(cur->mac, arp->src_hw_addr, 6); } diff --git a/src/objects/Makefile b/src/objects/Makefile index 9acfe72..f11f562 100644 --- a/src/objects/Makefile +++ b/src/objects/Makefile @@ -1,2 +1,4 @@ SRC += objects.c -SRC += types.c \ No newline at end of file +SRC += types.c +SRC += mount.c +SRC += ops.c \ No newline at end of file diff --git a/src/objects/mount.c b/src/objects/mount.c new file mode 100644 index 0000000..24b6993 --- /dev/null +++ b/src/objects/mount.c @@ -0,0 +1,14 @@ +#include +#include +#include + +ObjectResult object_mount(Object *origin, Object *dest) { + if (dest->is_mounted) { return OBJECT_ERROR_INVALID_OPERATION; } + dest->is_mounted = true; + dest->origin = origin; + + dest->fs_info = origin->fs_info; + + origin->fs_info->ops->fs_mount(origin->fs_info, dest); + return OBJECT_OK; +} \ No newline at end of file diff --git a/src/objects/objects.c b/src/objects/objects.c index 5b6c94e..577513e 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -1,3 +1,5 @@ +#include "kernel/list.h" +#include "objects/ops.h" #include #include #include @@ -12,33 +14,31 @@ Object root_object = { .name = STRING_INIT(""), // 根对象的名字不会起到任何作用,所以设为空 .type = OBJECT_TYPE_DIRECTORY, .parent = NULL, + .fixed = true, }; Object bus_object = { - .name = STRING_INIT("Bus"), - .type = OBJECT_TYPE_DIRECTORY, + .name = STRING_INIT("Bus"), + .type = OBJECT_TYPE_DIRECTORY, + .fixed = true, }; Object driver_object = { - .name = STRING_INIT("Driver"), - .type = OBJECT_TYPE_DIRECTORY, + .name = STRING_INIT("Driver"), + .type = OBJECT_TYPE_DIRECTORY, + .fixed = true, }; Object device_object = { - .name = STRING_INIT("Device"), - .type = OBJECT_TYPE_DIRECTORY, + .name = STRING_INIT("Device"), + .type = OBJECT_TYPE_DIRECTORY, + .fixed = true, +}; +Object volumes_object = { + .name = STRING_INIT("Volumes"), + .type = OBJECT_TYPE_DIRECTORY, + .fixed = true, }; -/** - * @brief 初始化对象目录的children结构 - * - * @param object - * @param block_size - * @return ObjectResult - */ -ObjectResult init_object_directory(Object *object, size_t block_size) { - DynArray *children = dyn_array_new(sizeof(Object *), block_size); - if (children == NULL) { return OBJECT_ERROR_MEMORY; } - - object->value.directory.children = children; - return OBJECT_OK; +static inline void init_object_directory(Object *object) { + list_init(&object->value.directory.children); } /** @@ -47,36 +47,21 @@ ObjectResult init_object_directory(Object *object, size_t block_size) { * @return ObjectResult */ ObjectResult init_object_tree() { - init_object_directory(&root_object, OBJECT_DIR_SIZE_SMALL); - init_object_directory(&bus_object, OBJECT_DIR_SIZE_SMALL); - init_object_directory(&driver_object, OBJECT_DIR_SIZE_LARGE); - init_object_directory(&device_object, OBJECT_DIR_SIZE_LARGE); + init_object_directory(&root_object); + init_object_directory(&bus_object); + init_object_directory(&driver_object); + init_object_directory(&device_object); + init_object_directory(&volumes_object); add_object(&root_object, &driver_object); add_object(&root_object, &bus_object); add_object(&root_object, &device_object); + add_object(&root_object, &volumes_object); init_builtin_types(); return OBJECT_OK; } -ObjectResult find_object_by_name( - Object *parent, Object **out_child, string_t *name, bool is_directory) { - Object *child; - dyn_array_foreach(parent->value.directory.children, Object *, child) { - if (child->name.length == name->length && - strncmp(child->name.text, name->text, name->length) == 0) { - if ((child->type == OBJECT_TYPE_DIRECTORY && is_directory) || - (child->type != OBJECT_TYPE_DIRECTORY && !is_directory)) { - *out_child = child; - return OBJECT_OK; - } - } - } - return OBJECT_ERROR_CANNOT_FIND; -} - -ObjectResult open_oringinal_object_by_ascii_path( - char *path, Object **out_object) { +ObjectResult open_oringinal_object_by_path(char *path, Object **out_object) { // 必须从根对象开始 if (path[0] != '\\') { return OBJECT_ERROR_ILLEGAL_ARGUMENT; } path++; @@ -101,8 +86,9 @@ ObjectResult open_oringinal_object_by_ascii_path( name.max_length = i + 1; Object *child; - ObjectResult result = - find_object_by_name(object, &child, &name, is_directory); + ObjectResult result; + if (!is_directory) result = obj_open(object, &child, name); + else result = obj_opendir(object, &child, name); if (result != OBJECT_OK) { return result; } object = child; @@ -112,8 +98,8 @@ ObjectResult open_oringinal_object_by_ascii_path( return OBJECT_OK; } -ObjectResult open_object_by_ascii_path(char *path, Object **object) { - ObjectResult result = open_oringinal_object_by_ascii_path(path, object); +ObjectResult open_object_by_path(char *path, Object **object) { + ObjectResult result = open_oringinal_object_by_path(path, object); if (result == OBJECT_OK) { while ((*object)->type == OBJECT_TYPE_SYM_LINK) { *object = (*object)->value.sym_link; @@ -128,7 +114,7 @@ ObjectResult add_object(Object *parent, Object *child) { } child->parent = parent; - append_object(parent, child); + list_add_tail(&child->list, &parent->value.directory.children); return OBJECT_OK; } @@ -142,27 +128,20 @@ Object *create_object(Object *parent, string_t name, ObjectType type) { object->parent = parent; object->reference = 0; - add_object(parent, object); + ObjectResult result = add_object(parent, object); + if (result != OBJECT_OK) { + kfree(object); + return NULL; + } return object; } -void object_close(Object *object) { - object->reference--; - if (object->reference != 0) return; - if (object->release_data != NULL) { object->release_data(object); } - if (object->type == OBJECT_TYPE_DIRECTORY) { - dyn_array_delete(object->value.directory.children); - } - dyn_array_remove(object->parent->value.directory.children, object); - kfree(object); -} - Object *create_object_directory(Object *parent, string_t name) { Object *object = create_object(parent, name, OBJECT_TYPE_DIRECTORY); if (object == NULL) { return NULL; } - init_object_directory(object, OBJECT_DIR_SIZE_SMALL); + init_object_directory(object); return object; } @@ -175,9 +154,8 @@ void print_symbol_link(Object *object) { } void print_object_directory(Object *object, int level) { - for (int i = 0; i < object->value.directory.children->size; i++) { - Object *child = - dyn_array_get(object->value.directory.children, Object *, i); + Object *child; + list_for_each_owner (child, &object->value.directory.children, list) { for (int j = 0; j < level; j++) { printk("|\t"); } diff --git a/src/objects/ops.c b/src/objects/ops.c new file mode 100644 index 0000000..efbfa78 --- /dev/null +++ b/src/objects/ops.c @@ -0,0 +1,70 @@ +#include "kernel/list.h" +#include "kernel/memory.h" +#include "objects/transfer.h" +#include +#include +#include +#include + +ObjectResult obj_open( + Object *parent, DEF_MRET(Object *, child), string_t name) { + Object *child; + list_for_each_owner (child, &parent->value.directory.children, list) { + if (child->name.length == name.length && + strncmp(child->name.text, name.text, name.length) == 0) { + MRET(child) = child; + child->reference++; + return OBJECT_OK; + } + } + // 如果缓存中找不到,则调用文件系统接口读取 + if (parent->fs_info != NULL) { + FsResult result = parent->fs_info->file_ops.fs_open( + parent->fs_info, parent->value.directory.data, name, &MRET(child)); + child->reference++; + if (result == FS_OK) return OBJECT_OK; + } + return OBJECT_ERROR_CANNOT_FIND; +} + +ObjectResult obj_opendir( + Object *parent, DEF_MRET(Object *, child), string_t name) { + Object *child; + list_for_each_owner (child, &parent->value.directory.children, list) { + if (child->name.length == name.length && + strncmp(child->name.text, name.text, name.length) == 0) { + if (child->type == OBJECT_TYPE_DIRECTORY) { + MRET(child) = child; + child->reference++; + return OBJECT_OK; + } + } + } + // 如果缓存中找不到,则调用文件系统接口读取 + if (parent->fs_info != NULL) { + FsResult result = parent->fs_info->dir_ops.fs_opendir( + parent->fs_info, parent->value.directory.data, name, &MRET(child)); + child->reference++; + if (result == FS_OK) return OBJECT_OK; + } + return OBJECT_ERROR_CANNOT_FIND; +} + +ObjectResult obj_close(Object *object) { + object->reference--; + if (object->reference > 0) return OBJECT_OK; + if (!object->is_mounted && !object->fixed) { + if (object->release_data != NULL) object->release_data(object); + if (object->fs_info != NULL) { + if (object->type == OBJECT_TYPE_FILE) { + object->fs_info->file_ops.fs_close(object); + } else if (object->type == OBJECT_TYPE_DIRECTORY) { + object->fs_info->dir_ops.fs_closedir(object); + } + } + list_del(&object->list); + obj_close(object->parent); + kfree(object); + } + return OBJECT_OK; +} diff --git a/src/objects/types.c b/src/objects/types.c index 461b91a..44d4352 100644 --- a/src/objects/types.c +++ b/src/objects/types.c @@ -1,7 +1,10 @@ +#include "kernel/list.h" #include #include #include +static int type_number = OBJECT_TYPE_BUILTIN_MAX; + #define DEFINE_OBJECT_TYPE(type_name) \ { \ .name = STRING_INIT(#type_name), .type = OBJECT_TYPE_TYPE, \ @@ -21,11 +24,9 @@ Object object_type_directory = { }; ObjectResult init_builtin_types() { - DynArray *children = dyn_array_new(sizeof(Object *), OBJECT_DIR_SIZE_SMALL); - init_object_directory(&object_type_directory, OBJECT_DIR_SIZE_LARGE); + list_init(&object_type_directory.value.directory.children); add_object(&root_object, &object_type_directory); - object_type_directory.value.directory.children = children; for (int i = 0; i < OBJECT_TYPE_BUILTIN_MAX; i++) { add_object(&object_type_directory, &object_builtin_types[i]); } @@ -38,8 +39,7 @@ Object *create_object_type(string_t name) { create_object(&object_type_directory, name, OBJECT_TYPE_TYPE); if (object == NULL) { return NULL; } - object->value.type = - object_type_directory.value.directory.children->size - 1; + object->value.type = type_number - 1; return object; } \ No newline at end of file From 7b562f4d5777848085a861c1616fcd4ab1680840 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 7 Mar 2025 17:46:51 +0800 Subject: [PATCH 028/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=8A=9F=E8=83=BD=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fs/fat/dir.c | 3 +- src/fs/fat/entry.c | 21 +++++++------ src/fs/fat/fat.c | 11 ++++--- src/fs/fat/include/entry.h | 3 +- src/include/config.h | 2 -- src/include/objects/object.h | 7 +++++ src/include/objects/ops.h | 1 + src/kernel/main.c | 25 +++++++-------- src/objects/objects.c | 1 - src/objects/ops.c | 59 +++++++++++++++++++++++++----------- 10 files changed, 83 insertions(+), 50 deletions(-) diff --git a/src/fs/fat/dir.c b/src/fs/fat/dir.c index c439de7..9e349fd 100644 --- a/src/fs/fat/dir.c +++ b/src/fs/fat/dir.c @@ -112,7 +112,8 @@ FsResult search_dir( if (short_dir->attr != ATTR_LONG_NAME) { tmp_entry = generate_dir_entry( fat_info, parent_entry, (ShortDir *)buf, _name, is_directory, - cur_entry.cur_cluster.cluster, cur_entry.number, 0, 0); + cur_entry.cur_cluster.cluster, cur_entry.number, + longname_cluster, longname_number); } if (is_directory && (short_dir->attr & ATTR_DIRECTORY) == 0) continue; diff --git a/src/fs/fat/entry.c b/src/fs/fat/entry.c index 71219fd..37d9c24 100644 --- a/src/fs/fat/entry.c +++ b/src/fs/fat/entry.c @@ -4,7 +4,6 @@ #include "include/fat.h" #include "include/name.h" #include "include/time.h" -#include "kernel/list.h" #include "kernel/memory.h" #include "multiple_return.h" #include "objects/object.h" @@ -180,7 +179,11 @@ PUBLIC FatDirEntry *generate_dir_entry( object->value.file.offset = 0; object->value.file.size = entry->short_dir.file_size; } - entry->object = object; + entry->longname_cluster = longname_cluster; + entry->longname_number = longname_number; + entry->shortname_cluster = cluster; + entry->shortname_number = number; + entry->object = object; return entry; } @@ -265,27 +268,27 @@ PUBLIC FsResult fat_create_entry( return FS_OK; } -PUBLIC FsResult -fat_delete_entry(FatInfo *fat_info, FatDirEntry *entry, string_t name) { +PUBLIC FsResult fat_delete_entry( + FatInfo *fat_info, FatDirEntry *parent, FatDirEntry *entry, string_t name) { uint32_t cluster = entry->shortname_cluster; uint32_t num = entry->shortname_number; uint8_t buf[32]; - FS_RESULT_PASS(fat_entry_read(fat_info, entry, cluster, num, buf)); + FS_RESULT_PASS(fat_entry_read(fat_info, parent, cluster, num, buf)); buf[0] = 0xe5; - FS_RESULT_PASS(fat_entry_write(fat_info, entry, cluster, num, buf)); + FS_RESULT_PASS(fat_entry_write(fat_info, parent, cluster, num, buf)); if (fat_info->type == FAT_TYPE_FAT32 && entry->longname_cluster != 0) { uint32_t cluster = entry->longname_cluster; int number = entry->longname_number; while (cluster <= entry->shortname_cluster && - number <= entry->shortname_number) { + number < entry->shortname_number) { FS_RESULT_PASS( - fat_entry_read(fat_info, entry, cluster, number, buf)); + fat_entry_read(fat_info, parent, cluster, number, buf)); buf[0] = 0xe5; FS_RESULT_PASS( - fat_entry_write(fat_info, entry, cluster, number, buf)); + fat_entry_write(fat_info, parent, cluster, number, buf)); number++; if (number == fat_info->entry_per_cluster) { cluster = get_next_cluster(fat_info, cluster); diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c index 80c4aae..be0b979 100644 --- a/src/fs/fat/fat.c +++ b/src/fs/fat/fat.c @@ -129,7 +129,8 @@ FsResult fat_mount(FileSystemInfo *fs_info, Object *root_object) { const FatDirEntry root_entry = { root_name, root_short_dir, 0, 0, 0, 0, {0}, NULL, NULL, }; - fat_info->root_entry = root_entry; + fat_info->root_entry = root_entry; + fat_info->root_entry.object = root_object; root_object->value.directory.data = &fat_info->root_entry; fat_info->root_entry.cluster_list = @@ -262,7 +263,7 @@ FsResult fat_write(Object *file, void *buf, size_t size) { } FsResult fat_create_file(Object *directory, string_t name, Object **object) { - FatInfo *fat_info = (FatInfo *)directory->fs_info; + FatInfo *fat_info = directory->fs_info->private_data; FatDirEntry *entry, *parent = directory->value.directory.data; FsResult result = search_dir(fat_info, parent, name, false, &entry, 0); @@ -275,18 +276,18 @@ FsResult fat_create_file(Object *directory, string_t name, Object **object) { } FsResult fat_delete_file(Object *directory, string_t name) { - FatInfo *fat_info = (FatInfo *)directory->fs_info; + FatInfo *fat_info = directory->fs_info->private_data; FatDirEntry *entry, *parent = directory->value.directory.data; FsResult result = search_dir(fat_info, parent, name, false, &entry, 0); if (result != FS_OK) { return result; } - fat_delete_entry(fat_info, entry, name); + fat_delete_entry(fat_info, parent, entry, name); return FS_OK; } FsResult fat_mkdir(Object *directory, string_t name, Object **object) { - FatInfo *fat_info = (FatInfo *)directory->fs_info; + FatInfo *fat_info = directory->fs_info->private_data; FatDirEntry *entry, *parent = directory->value.directory.data; FsResult result = search_dir(fat_info, parent, name, true, &entry, 0); diff --git a/src/fs/fat/include/entry.h b/src/fs/fat/include/entry.h index dd48643..2ff49ef 100644 --- a/src/fs/fat/include/entry.h +++ b/src/fs/fat/include/entry.h @@ -20,6 +20,7 @@ FsResult fat_create_entry( struct FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, bool is_directory, FatDirEntry **out_entry); FsResult fat_delete_entry( - struct FatInfo *fat_info, FatDirEntry *entry, string_t name); + struct FatInfo *fat_info, FatDirEntry *parent, FatDirEntry *entry, + string_t name); #endif \ No newline at end of file diff --git a/src/include/config.h b/src/include/config.h index 930d7cc..15aad96 100644 --- a/src/include/config.h +++ b/src/include/config.h @@ -1,6 +1,4 @@ #ifndef _CONFIG_H #define _CONFIG_H -#define ARCH_X86 - #endif \ No newline at end of file diff --git a/src/include/objects/object.h b/src/include/objects/object.h index f9db6d3..b9427c2 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -13,9 +13,16 @@ typedef enum ObjectResult { OBJECT_ERROR_INVALID_OPERATION, OBJECT_ERROR_CANNOT_FIND, OBJECT_ERROR_ILLEGAL_ARGUMENT, + OBJECT_ERROR_OCCUPIED, OBJECT_ERROR_OTHER, } ObjectResult; +#define OBJ_PASS(call) \ + { \ + ObjectResult result = call; \ + if (result != OBJECT_OK) { return result; } \ + } + #define OBJECT_DIR_SIZE_SMALL 8 #define OBJECT_DIR_SIZE_MEDIUM 16 #define OBJECT_DIR_SIZE_LARGE 32 diff --git a/src/include/objects/ops.h b/src/include/objects/ops.h index eb4f664..e390930 100644 --- a/src/include/objects/ops.h +++ b/src/include/objects/ops.h @@ -14,5 +14,6 @@ ObjectResult obj_open(Object *parent, DEF_MRET(Object *, child), string_t name); ObjectResult obj_opendir( Object *parent, DEF_MRET(Object *, child), string_t name); +ObjectResult obj_delete_file(Object *parent, string_t name); #endif \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index 0b870d6..26719bf 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -77,30 +77,27 @@ int main() { do_initcalls(); driver_start_all(); - uint8_t buf[512]; - Object *object; - ObjectResult result = open_object_by_path( - "\\Volumes\\Storage0Volume0\\boot\\grub\\grub.cfg", &object); - if (result != OBJECT_OK) { printk("Open File Error!\n"); } - OBJ_READ_STREAM(object)(object, TRANSFER_IN, buf, 512); + // uint8_t buf[512]; + // Object *object; + // ObjectResult result = + // open_object_by_path("\\Volumes\\Storage0Volume0\\", &object); + // if (result != OBJECT_OK) { printk("Open File Error!\n"); } // const string_t name = STRING_INIT("一个长文件名.txt"); - // volume->fs->ops->fs_open(volume, "/一个长文件名.txt", &parent); - // volume->fs->ops->fs_create_file(volume, parent, name, &file_object); - // volume->fs->ops->fs_close(object); + // obj_delete_file(object, name); // void *handle = NULL; // Object *object; // ObjectResult result = - // open_object_by_ascii_path("\\Device\\Storage0\\Partition0", &object); - // if (result != OBJECT_OK) { printk("Open Storage0 Error!\n"); } - // uint8_t buf[512]; - // TRANSFER_IN_BLOCK(object)(object, TRANSFER_IN, buf, 0, 1, &handle); + // open_object_by_ascii_path("\\Device\\Storage0\\Partition0", + // &object); if (result != OBJECT_OK) { printk("Open Storage0 + // Error!\n"); } uint8_t buf[512]; TRANSFER_IN_BLOCK(object)(object, + // TRANSFER_IN, buf, 0, 1, &handle); // bool is_done; // do { // TRANSFER_IN_IS_DONE(object)(object, &handle, &is_done); // } while (!is_done); - print_hex(buf, 512); + // print_hex(buf, 512); // show_object_tree(); diff --git a/src/objects/objects.c b/src/objects/objects.c index 577513e..e3f2d15 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -93,7 +93,6 @@ ObjectResult open_oringinal_object_by_path(char *path, Object **out_object) { object = child; } - object->reference++; *out_object = object; return OBJECT_OK; } diff --git a/src/objects/ops.c b/src/objects/ops.c index efbfa78..ff7a9e9 100644 --- a/src/objects/ops.c +++ b/src/objects/ops.c @@ -6,19 +6,32 @@ #include #include -ObjectResult obj_open( - Object *parent, DEF_MRET(Object *, child), string_t name) { +ObjectResult obj_search( + Object *parent, DEF_MRET(Object *, child), string_t name, ObjectType type) { Object *child; list_for_each_owner (child, &parent->value.directory.children, list) { if (child->name.length == name.length && strncmp(child->name.text, name.text, name.length) == 0) { - MRET(child) = child; - child->reference++; - return OBJECT_OK; + if (child->type == type) { + MRET(child) = child; + return OBJECT_OK; + } } } + return OBJECT_ERROR_CANNOT_FIND; +} + +ObjectResult obj_open( + Object *parent, DEF_MRET(Object *, child), string_t name) { + Object *child; + ObjectResult result = obj_search(parent, &child, name, OBJECT_TYPE_FILE); + if (result == OBJECT_OK) { + MRET(child) = child; + child->reference++; + return OBJECT_OK; + } // 如果缓存中找不到,则调用文件系统接口读取 - if (parent->fs_info != NULL) { + else if (parent->fs_info != NULL) { FsResult result = parent->fs_info->file_ops.fs_open( parent->fs_info, parent->value.directory.data, name, &MRET(child)); child->reference++; @@ -29,19 +42,16 @@ ObjectResult obj_open( ObjectResult obj_opendir( Object *parent, DEF_MRET(Object *, child), string_t name) { - Object *child; - list_for_each_owner (child, &parent->value.directory.children, list) { - if (child->name.length == name.length && - strncmp(child->name.text, name.text, name.length) == 0) { - if (child->type == OBJECT_TYPE_DIRECTORY) { - MRET(child) = child; - child->reference++; - return OBJECT_OK; - } - } + Object *child; + ObjectResult result = + obj_search(parent, &child, name, OBJECT_TYPE_DIRECTORY); + if (result == OBJECT_OK) { + MRET(child) = child; + child->reference++; + return OBJECT_OK; } // 如果缓存中找不到,则调用文件系统接口读取 - if (parent->fs_info != NULL) { + else if (parent->fs_info != NULL) { FsResult result = parent->fs_info->dir_ops.fs_opendir( parent->fs_info, parent->value.directory.data, name, &MRET(child)); child->reference++; @@ -68,3 +78,18 @@ ObjectResult obj_close(Object *object) { } return OBJECT_OK; } + +ObjectResult obj_delete_file(Object *parent, string_t name) { + Object *child; + ObjectResult result = obj_search(parent, &child, name, OBJECT_TYPE_FILE); + if (result == OBJECT_OK) { + if (child->reference > 0) return OBJECT_ERROR_OCCUPIED; + result = obj_close(child); + } + if (parent->fs_info != NULL) { + FsResult result = parent->fs_info->dir_ops.fs_delete_file(parent, name); + if (result != FS_OK) return OBJECT_ERROR_OTHER; + } + + return OBJECT_OK; +} From 08157efe532c838bc814a0f8189c94cf5027f5eb Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 7 Mar 2025 21:34:45 +0800 Subject: [PATCH 029/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E5=AF=B9=E8=B1=A1?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E7=BB=9F=E4=B8=80=E7=9A=84=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E3=80=81=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=EF=BC=88=E5=A4=B9?= =?UTF-8?q?=EF=BC=89=E6=8E=A5=E5=8F=A3=EF=BC=9B=20=E4=BF=AE=E5=A4=8D=20FAT?= =?UTF-8?q?32=E7=B0=87=E5=88=86=E9=85=8Dbug=EF=BC=9B=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20FAT32=E8=8E=B7=E5=8F=96=E4=B8=8B=E4=B8=80=E7=B0=87=E7=9A=84?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E9=94=99=E8=AF=AF=EF=BC=9B=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20FAT32=E5=AF=B9=E4=BA=8E=E9=95=BF=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=A4=B9=E5=90=8D=E7=9A=84=E8=BD=AC=E6=8D=A2=E9=94=99=E8=AF=AF?= =?UTF-8?q?=20=E6=96=B0=E5=A2=9E=20FAT32=E5=88=9B=E5=BB=BA=E3=80=81?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=E5=A4=B9=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=9B=20=E4=BF=AE=E5=A4=8D=20dyn=5Farray=E7=9A=84=E9=83=A8?= =?UTF-8?q?=E5=88=86bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fs/fat/cluster.c | 30 ++++++++++------ src/fs/fat/dir.c | 30 ++++++++++++++-- src/fs/fat/entry.c | 15 ++++---- src/fs/fat/fat.c | 37 +++++++++++++------ src/fs/fat/include/cluster.h | 1 + src/fs/fat/include/dir.h | 1 + src/fs/fat/name.c | 63 ++++++++++++++------------------ src/include/dyn_array.h | 2 +- src/include/fs/fs.h | 8 +++-- src/include/objects/object.h | 3 ++ src/include/objects/ops.h | 4 +++ src/kernel/main.c | 12 +++---- src/lib/dyn_array.c | 6 ++-- src/objects/ops.c | 69 +++++++++++++++++++++++++++++------- 14 files changed, 193 insertions(+), 88 deletions(-) diff --git a/src/fs/fat/cluster.c b/src/fs/fat/cluster.c index f7a7dbf..5e05198 100644 --- a/src/fs/fat/cluster.c +++ b/src/fs/fat/cluster.c @@ -89,7 +89,7 @@ FsResult alloc_cluster( uint32_t offset = fat_info->last_cluster % fat_info->num_count; int i; - bool finded; + bool finded = false; while (index < fat_info->fat_sectors && !finded) { BlockCacheEntry *entry = block_cache_read(fat_info->fat_table_cache, index); @@ -200,6 +200,7 @@ FsResult fat_cluster_list_get( int length = clus_seg.end - clus_seg.start + 1; if (counter < length) { cur_cluster->cluster = clus_seg.start + counter; + cur_cluster->offset = _block_offset; cur_cluster->block = _block; return FS_OK; } @@ -211,20 +212,29 @@ FsResult fat_cluster_list_get( FsResult fat_cluster_list_get_next( FatInfo *fat_info, FatDirEntry *entry, CurrentCluster *cur_cluster) { - ClusterSegment *seg = cur_cluster->block->data; + FsResult result; + ClusterSegment *seg = + &((ClusterSegment *)cur_cluster->block->data)[cur_cluster->offset]; if (cur_cluster->cluster < seg->end) { cur_cluster->cluster++; } else { - if (cur_cluster->block->next != NULL) { - get_next: - cur_cluster->block = cur_cluster->block->next; - seg = cur_cluster->block->data; - cur_cluster->cluster = seg->start; - } else { - FsResult result = get_cluster_segment(fat_info, entry); + cur_cluster->offset++; + if (cur_cluster->offset >= entry->cluster_list->block_size) { + cur_cluster->offset = 0; + if (cur_cluster->block->next == NULL) { + result = get_cluster_segment(fat_info, entry); + if (result != FS_OK) return result; + } + cur_cluster->block = cur_cluster->block->next; + } + seg = + &((ClusterSegment *)cur_cluster->block->data)[cur_cluster->offset]; + if (cur_cluster->offset >= (entry->cluster_list->block_size - + cur_cluster->block->left_space)) { + result = get_cluster_segment(fat_info, entry); if (result != FS_OK) return result; - goto get_next; } + cur_cluster->cluster = seg->start; } return FS_OK; } diff --git a/src/fs/fat/dir.c b/src/fs/fat/dir.c index 9e349fd..2bd9cac 100644 --- a/src/fs/fat/dir.c +++ b/src/fs/fat/dir.c @@ -3,6 +3,7 @@ #include "include/entry.h" #include "include/fat.h" #include "include/name.h" +#include "types.h" #include #include #include @@ -27,8 +28,11 @@ static inline FsResult fat_next_entry( FatInfo *fat_info, FatCurrentEntry *entry) { entry->number++; if (entry->number == fat_info->entry_per_cluster) { - return fat_cluster_list_get_next( - fat_info, entry->entry, &entry->cur_cluster); + entry->number = 0; + FS_RESULT_PASS(fat_cluster_list_get_next( + fat_info, entry->entry, &entry->cur_cluster)); + if (entry->cur_cluster.cluster >= 0x0fffffff) + return FS_ERROR_END_OF_FILE; } return FS_OK; } @@ -130,3 +134,25 @@ FsResult search_dir( kfree(utf16_name); return result; } + +bool fat_dir_is_empty(FatInfo *fat_info, FatDirEntry *parent_entry) { + FatCurrentEntry cur_entry; + cur_entry.entry = parent_entry; + + uint8_t buf[0x20]; + ShortDir *short_dir = (ShortDir *)buf; + + FsResult _result = FS_OK; + + fat_first_entry(fat_info, &cur_entry, 0); + for (; _result == FS_OK; _result = fat_next_entry(fat_info, &cur_entry)) { + fat_read_current_entry(fat_info, &cur_entry, buf); + + if (buf[0] == 0xe5 || buf[0] == 0x05) continue; + if (short_dir->attr == ATTR_LONG_NAME) continue; + if (buf[0] == '.') continue; + + if (buf[0] != 0) return false; + } + return true; +} diff --git a/src/fs/fat/entry.c b/src/fs/fat/entry.c index 37d9c24..e9fbcfd 100644 --- a/src/fs/fat/entry.c +++ b/src/fs/fat/entry.c @@ -91,8 +91,9 @@ PRIVATE FsResult fat_dir_get_new_entry( FS_RESULT_PASS(alloc_cluster(fat_info, cluster, false, &cluster)); number = 0; } - MRET(last_cluster) = cluster; - MRET(last_number) = number; + entry->new_entry_number = number; + MRET(last_cluster) = cluster; + MRET(last_number) = number; return FS_OK; } @@ -121,7 +122,7 @@ PRIVATE FsResult fat_longname_entry_write( long_dir.checksum = checksum; long_dir.first_cluster = 0; long_dir.type = 0; - for (int i = 0; i < longdir_count; i++, number++) { + for (int i = 0; i < longdir_count; i++) { long_dir.order = longdir_count - i; if (i == 0) { int len = len16 % 13; @@ -235,10 +236,12 @@ PUBLIC FsResult fat_create_entry( int checksum = fat_checksum(&short_dir.name); - uint32_t cluster; - int number; + uint32_t cluster, longname_cluster = 0; + int number, longname_number = 0; fat_dir_get_new_entry(fat_info, parent_entry, &cluster, &number); if (fat_info->type == FAT_TYPE_FAT32 && type == LONG_NAME) { + longname_cluster = cluster; + longname_number = number; FS_RESULT_PASS(fat_longname_entry_write( fat_info, parent_entry, name, checksum, &cluster, &number)); } @@ -248,7 +251,7 @@ PUBLIC FsResult fat_create_entry( FatDirEntry *entry; entry = generate_dir_entry( fat_info, parent_entry, &short_dir, name, is_directory, cluster, number, - 0, 0); + longname_cluster, longname_number); if (is_directory) { static ShortName dot = {". ", " "}; diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c index be0b979..f94d197 100644 --- a/src/fs/fat/fat.c +++ b/src/fs/fat/fat.c @@ -31,8 +31,8 @@ FsResult fat_opendir( FsResult fat_closedir(Object *object); FsResult fat_create_file(Object *directory, string_t name, Object **object); FsResult fat_delete_file(Object *directory, string_t name); -FsResult fat_mkdir(Object *directory, string_t name, Object **object); -FsResult fat_rmdir(Object *directory, string_t name); +FsResult fat_mkdir(Object *parent_obj, string_t name, Object **object); +FsResult fat_rmdir(Object *parent_obj, string_t name); FileSystemOps fat_ops = { .fs_check = fat_check, @@ -52,6 +52,8 @@ FsDirectoryOps fat_dir_ops = { .fs_closedir = fat_closedir, .fs_create_file = fat_create_file, .fs_delete_file = fat_delete_file, + .fs_mkdir = fat_mkdir, + .fs_rmdir = fat_rmdir, }; FileSystem fat_fs = { @@ -262,9 +264,9 @@ FsResult fat_write(Object *file, void *buf, size_t size) { buf, size); } -FsResult fat_create_file(Object *directory, string_t name, Object **object) { - FatInfo *fat_info = directory->fs_info->private_data; - FatDirEntry *entry, *parent = directory->value.directory.data; +FsResult fat_create_file(Object *parent_obj, string_t name, Object **object) { + FatInfo *fat_info = parent_obj->fs_info->private_data; + FatDirEntry *entry, *parent = parent_obj->value.directory.data; FsResult result = search_dir(fat_info, parent, name, false, &entry, 0); if (result == FS_OK) { return FS_ERROR_ALREADY_EXISTS; } @@ -275,9 +277,9 @@ FsResult fat_create_file(Object *directory, string_t name, Object **object) { return FS_OK; } -FsResult fat_delete_file(Object *directory, string_t name) { - FatInfo *fat_info = directory->fs_info->private_data; - FatDirEntry *entry, *parent = directory->value.directory.data; +FsResult fat_delete_file(Object *parent_obj, string_t name) { + FatInfo *fat_info = parent_obj->fs_info->private_data; + FatDirEntry *entry, *parent = parent_obj->value.directory.data; FsResult result = search_dir(fat_info, parent, name, false, &entry, 0); if (result != FS_OK) { return result; } @@ -286,9 +288,9 @@ FsResult fat_delete_file(Object *directory, string_t name) { return FS_OK; } -FsResult fat_mkdir(Object *directory, string_t name, Object **object) { - FatInfo *fat_info = directory->fs_info->private_data; - FatDirEntry *entry, *parent = directory->value.directory.data; +FsResult fat_mkdir(Object *parent_obj, string_t name, Object **object) { + FatInfo *fat_info = parent_obj->fs_info->private_data; + FatDirEntry *entry, *parent = parent_obj->value.directory.data; FsResult result = search_dir(fat_info, parent, name, true, &entry, 0); if (result == FS_OK) { return FS_ERROR_ALREADY_EXISTS; } @@ -299,6 +301,19 @@ FsResult fat_mkdir(Object *directory, string_t name, Object **object) { return FS_OK; } +FsResult fat_rmdir(Object *parent_obj, string_t name) { + FatInfo *fat_info = parent_obj->fs_info->private_data; + FatDirEntry *entry, *parent = parent_obj->value.directory.data; + + FsResult result = search_dir(fat_info, parent, name, true, &entry, 0); + if (result != FS_OK) { return result; } + + if (!fat_dir_is_empty(fat_info, entry)) return FS_ERROR_NOT_EMPTY; + + fat_delete_entry(fat_info, parent, entry, name); + return FS_OK; +} + void fat_initcall() { register_fs(&fat_fs); } diff --git a/src/fs/fat/include/cluster.h b/src/fs/fat/include/cluster.h index 90c8a78..b3f9d88 100644 --- a/src/fs/fat/include/cluster.h +++ b/src/fs/fat/include/cluster.h @@ -16,6 +16,7 @@ typedef struct ClusterSegment { typedef struct CurrentCluster { uint32_t cluster; + int offset; DynArrayBlock *block; } CurrentCluster; diff --git a/src/fs/fat/include/dir.h b/src/fs/fat/include/dir.h index 79c279f..b0f56f7 100644 --- a/src/fs/fat/include/dir.h +++ b/src/fs/fat/include/dir.h @@ -78,5 +78,6 @@ FsResult search_dir( bool match_directory, FatDirEntry **out_entry, int mode); void entry_cache_init( struct FatInfo *fat_info, FatDirEntry *entry, size_t cache_size); +bool fat_dir_is_empty(struct FatInfo *fat_info, FatDirEntry *parent_entry); #endif \ No newline at end of file diff --git a/src/fs/fat/name.c b/src/fs/fat/name.c index 12a2fa8..ceb578b 100644 --- a/src/fs/fat/name.c +++ b/src/fs/fat/name.c @@ -217,15 +217,17 @@ string_t read_short_name(ShortDir *short_dir) { FsResult long_name2short_name( FatInfo *fat_info, FatDirEntry *parent, string_t long_name, bool is_directory, ShortName *short_name) { - if (short_name == NULL) { return FS_ERROR_OUT_OF_MEMORY; } int len = long_name.length; uint8_t *text = (uint8_t *)long_name.text; bool flag = true; - int dot = len - 1; - while (text[dot] != '.' && dot >= 0) { + int dot = len; + if (!is_directory) { dot--; + while (text[dot] != '.' && dot >= 0) { + dot--; + } } int base_name_len = 0; int ext_name_len = 0; @@ -235,49 +237,38 @@ FsResult long_name2short_name( for (i = 0, j = 0; i < 8; i++) { if (i < dot) { if (is_available_short_name_char(text[i])) { - if ('a' <= text[i] && text[i] <= 'z') { + if ('a' <= text[i] && text[i] <= 'z') short_name->base[j] = text[i] - 32; - } else { - short_name->base[j] = text[i]; - } + else short_name->base[j] = text[i]; } else if (text[i] >= 0x80) { // 跳过UTF-8字符 flag = false; short_name->base[j] = '_'; - } else { - continue; - } + } else continue; tmp_name[j] = short_name->base[j]; base_name_len++; - } else { - short_name->base[j] = ' '; - } + } else short_name->base[j] = ' '; j++; } - tmp_name[j] = '.'; - int k = j + 1; - - for (i = 0, j = 0; i < 3; i++) { - if (i < dot) { - uint8_t c = text[dot + 1 + i]; - if (is_available_short_name_char(c)) { - if ('a' <= c && c <= 'z') { - short_name->ext[j] = c - 32; - } else { - short_name->ext[j] = c; - } - } else if (c >= 0x80) { - flag = false; - short_name->ext[j] = '_'; - } else { - continue; - } - } else { - short_name->ext[j] = ' '; + if (!is_directory) { + tmp_name[j] = '.'; + int k = j + 1; + + for (i = 0, j = 0; i < 3; i++) { + if (i < dot) { + uint8_t c = text[dot + 1 + i]; + if (is_available_short_name_char(c)) { + if ('a' <= c && c <= 'z') short_name->ext[j] = c - 32; + else short_name->ext[j] = c; + } else if (c >= 0x80) { + flag = false; + short_name->ext[j] = '_'; + } else continue; + } else short_name->ext[j] = ' '; + tmp_name[k + j] = short_name->ext[j]; + j++; + ext_name_len++; } - tmp_name[k + j] = short_name->ext[j]; - j++; - ext_name_len++; } string_t name; diff --git a/src/include/dyn_array.h b/src/include/dyn_array.h index a3dbde6..3c6ea86 100644 --- a/src/include/dyn_array.h +++ b/src/include/dyn_array.h @@ -61,7 +61,7 @@ bool dyn_array_is_end( #define dyn_array_foreach(arr, type, var) \ struct DynArrayBlock *_block = (arr)->first_block; \ int _block_index = 0; \ - int _block_offset = 1; \ + int _block_offset = 0; \ for (var = *((type *)_block->data); \ !dyn_array_is_end(arr, _block, _block_index, _block_offset); \ var = *((type *)dyn_array_next_ptr( \ diff --git a/src/include/fs/fs.h b/src/include/fs/fs.h index e98841b..f88f53f 100644 --- a/src/include/fs/fs.h +++ b/src/include/fs/fs.h @@ -15,6 +15,7 @@ typedef enum FsResult { FS_ERROR_NO_SPARE_SPACE, FS_ERROR_CANNOT_FIND, FS_ERROR_ALREADY_EXISTS, + FS_ERROR_NOT_EMPTY, FS_ERROR_END_OF_FILE, FS_ERROR_ILLEGAL_DATA, FS_ERROR_NOT_MATCH, @@ -52,8 +53,11 @@ typedef struct FsDirectoryOps { struct Object **object); FsResult (*fs_closedir)(struct Object *object); FsResult (*fs_create_file)( - struct Object *directory, string_t name, struct Object **object); - FsResult (*fs_delete_file)(struct Object *directory, string_t name); + struct Object *parent_obj, string_t name, struct Object **object); + FsResult (*fs_delete_file)(struct Object *parent_obj, string_t name); + FsResult (*fs_mkdir)( + struct Object *parent_obj, string_t name, struct Object **object); + FsResult (*fs_rmdir)(struct Object *parent_obj, string_t name); } FsDirectoryOps; typedef struct FileSystem { diff --git a/src/include/objects/object.h b/src/include/objects/object.h index b9427c2..76841a0 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -14,6 +14,9 @@ typedef enum ObjectResult { OBJECT_ERROR_CANNOT_FIND, OBJECT_ERROR_ILLEGAL_ARGUMENT, OBJECT_ERROR_OCCUPIED, + OBJECT_ERROR_ALREADY_EXISTS, + OBJECT_ERROR_FIXED, + OBJECT_ERROR_NOT_EMPTY, OBJECT_ERROR_OTHER, } ObjectResult; diff --git a/src/include/objects/ops.h b/src/include/objects/ops.h index e390930..9d5472d 100644 --- a/src/include/objects/ops.h +++ b/src/include/objects/ops.h @@ -14,6 +14,10 @@ ObjectResult obj_open(Object *parent, DEF_MRET(Object *, child), string_t name); ObjectResult obj_opendir( Object *parent, DEF_MRET(Object *, child), string_t name); +ObjectResult obj_close(Object *object); +ObjectResult obj_create_file(Object *parent, string_t name); ObjectResult obj_delete_file(Object *parent, string_t name); +ObjectResult obj_mkdir(Object *parent, string_t name); +ObjectResult obj_rmdir(Object *parent, string_t name); #endif \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index 26719bf..beb66ef 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -78,12 +78,12 @@ int main() { driver_start_all(); // uint8_t buf[512]; - // Object *object; - // ObjectResult result = - // open_object_by_path("\\Volumes\\Storage0Volume0\\", &object); - // if (result != OBJECT_OK) { printk("Open File Error!\n"); } - // const string_t name = STRING_INIT("一个长文件名.txt"); - // obj_delete_file(object, name); + Object *object; + ObjectResult result = + open_object_by_path("\\Volumes\\Storage0Volume0\\", &object); + if (result != OBJECT_OK) { printk("Open File Error!\n"); } + const string_t name = STRING_INIT("A folder"); + obj_rmdir(object, name); // void *handle = NULL; // Object *object; diff --git a/src/lib/dyn_array.c b/src/lib/dyn_array.c index 07a3397..5afc7c4 100644 --- a/src/lib/dyn_array.c +++ b/src/lib/dyn_array.c @@ -69,10 +69,11 @@ struct DynArrayBlock *dyn_array_find_block(DynArray *dyn_array, size_t idx) { */ void *dyn_array_new_item_addr(DynArray *dyn_array) { struct DynArrayBlock *block = dyn_array->last_block; - if (dyn_array->size % dyn_array->block_size == 0 && dyn_array->size != 0) { + if (block->left_space == 0 && dyn_array->size != 0) { dyn_array_extend_block(dyn_array); block = dyn_array->last_block; } + block->left_space--; return block->data + (dyn_array->size % dyn_array->block_size) * dyn_array->element_size; @@ -94,7 +95,8 @@ void *dyn_array_next_ptr( *block_offset = 0; *block = (*block)->next; } - return (void *)current_block->data + offset * dyn_array->element_size; + return (void *)current_block->data + + (*block_index) * dyn_array->element_size; } void dyn_array_remove(DynArray *dyn_array, void *item) { diff --git a/src/objects/ops.c b/src/objects/ops.c index ff7a9e9..feceb0c 100644 --- a/src/objects/ops.c +++ b/src/objects/ops.c @@ -1,18 +1,21 @@ #include "kernel/list.h" #include "kernel/memory.h" #include "objects/transfer.h" +#include "string.h" #include #include #include #include ObjectResult obj_search( - Object *parent, DEF_MRET(Object *, child), string_t name, ObjectType type) { + Object *parent, DEF_MRET(Object *, child), string_t name, + bool is_directory) { Object *child; list_for_each_owner (child, &parent->value.directory.children, list) { if (child->name.length == name.length && strncmp(child->name.text, name.text, name.length) == 0) { - if (child->type == type) { + if ((is_directory && child->type == OBJECT_TYPE_DIRECTORY) || + (!is_directory && child->type != OBJECT_TYPE_DIRECTORY)) { MRET(child) = child; return OBJECT_OK; } @@ -24,7 +27,7 @@ ObjectResult obj_search( ObjectResult obj_open( Object *parent, DEF_MRET(Object *, child), string_t name) { Object *child; - ObjectResult result = obj_search(parent, &child, name, OBJECT_TYPE_FILE); + ObjectResult result = obj_search(parent, &child, name, false); if (result == OBJECT_OK) { MRET(child) = child; child->reference++; @@ -43,8 +46,7 @@ ObjectResult obj_open( ObjectResult obj_opendir( Object *parent, DEF_MRET(Object *, child), string_t name) { Object *child; - ObjectResult result = - obj_search(parent, &child, name, OBJECT_TYPE_DIRECTORY); + ObjectResult result = obj_search(parent, &child, name, true); if (result == OBJECT_OK) { MRET(child) = child; child->reference++; @@ -63,14 +65,13 @@ ObjectResult obj_opendir( ObjectResult obj_close(Object *object) { object->reference--; if (object->reference > 0) return OBJECT_OK; + if (object->fs_info == NULL) return OBJECT_OK; if (!object->is_mounted && !object->fixed) { if (object->release_data != NULL) object->release_data(object); - if (object->fs_info != NULL) { - if (object->type == OBJECT_TYPE_FILE) { - object->fs_info->file_ops.fs_close(object); - } else if (object->type == OBJECT_TYPE_DIRECTORY) { - object->fs_info->dir_ops.fs_closedir(object); - } + if (object->type == OBJECT_TYPE_FILE) { + object->fs_info->file_ops.fs_close(object); + } else if (object->type == OBJECT_TYPE_DIRECTORY) { + object->fs_info->dir_ops.fs_closedir(object); } list_del(&object->list); obj_close(object->parent); @@ -79,11 +80,24 @@ ObjectResult obj_close(Object *object) { return OBJECT_OK; } +ObjectResult obj_create_file(Object *parent, string_t name) { + Object *child; + ObjectResult result = obj_search(parent, &child, name, false); + if (result == OBJECT_OK) return OBJECT_ERROR_ALREADY_EXISTS; + if (parent->fs_info != NULL) { + FsResult result = + parent->fs_info->dir_ops.fs_create_file(parent, name, &child); + if (result != FS_OK) return OBJECT_ERROR_OTHER; + } + return OBJECT_OK; +} + ObjectResult obj_delete_file(Object *parent, string_t name) { Object *child; - ObjectResult result = obj_search(parent, &child, name, OBJECT_TYPE_FILE); + ObjectResult result = obj_search(parent, &child, name, false); if (result == OBJECT_OK) { if (child->reference > 0) return OBJECT_ERROR_OCCUPIED; + if (child->fixed) return OBJECT_ERROR_FIXED; result = obj_close(child); } if (parent->fs_info != NULL) { @@ -93,3 +107,34 @@ ObjectResult obj_delete_file(Object *parent, string_t name) { return OBJECT_OK; } + +ObjectResult obj_mkdir(Object *parent, string_t name) { + Object *child; + ObjectResult result = obj_search(parent, &child, name, true); + if (result == OBJECT_OK) return OBJECT_ERROR_ALREADY_EXISTS; + if (parent->fs_info != NULL) { + FsResult result = + parent->fs_info->dir_ops.fs_mkdir(parent, name, &child); + if (result != FS_OK) return OBJECT_ERROR_OTHER; + } + return OBJECT_OK; +} + +ObjectResult obj_rmdir(Object *parent, string_t name) { + Object *child; + ObjectResult result = obj_search(parent, &child, name, true); + if (parent->fs_info != NULL) { + FsResult result = parent->fs_info->dir_ops.fs_rmdir(parent, name); + if (result != FS_OK) return OBJECT_ERROR_OTHER; + } else { + if (result != OBJECT_OK) return OBJECT_ERROR_CANNOT_FIND; + if (child->fixed) return OBJECT_ERROR_FIXED; + if (!child->is_mounted) return OBJECT_ERROR_OCCUPIED; + if (child->reference > 0) return OBJECT_ERROR_OCCUPIED; + if (!list_empty(&child->value.directory.children)) + return OBJECT_ERROR_NOT_EMPTY; + list_del(&child->list); + kfree(child); + } + return result; +} From 350c1d624a66a0f41280c7c3d583252299628878 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 8 Mar 2025 18:20:24 +0800 Subject: [PATCH 030/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E8=AF=BB=E5=8F=96=E5=92=8C=E8=AE=BE=E7=BD=AE=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=EF=BC=9B=20=E4=BF=AE=E6=94=B9=20=E4=BC=98=E5=8C=96=E5=AD=97?= =?UTF-8?q?=E7=AC=A6W=E7=9A=84=E5=AD=97=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/disk/ata/ide.c | 4 +- .../x86/drivers/disk/ata/ide_controller.c | 8 +- src/arch/x86/drivers/pci.c | 15 ++-- src/arch/x86/drivers/vesa_display.c | 3 +- src/arch/x86/include/kernel/thread.h | 2 + src/arch/x86/kernel/platform.c | 9 +-- src/driver/bus_dm.c | 5 +- src/driver/storage/disk/mbr.c | 7 +- src/driver/storage/storage_dm.c | 10 ++- src/driver/storage/storage_io.c | 6 +- src/driver/storage/volume.c | 5 +- src/driver/video_dm.c | 6 +- src/fs/fat/Makefile | 3 +- src/fs/fat/attr.c | 74 +++++++++++++++++ src/fs/fat/entry.c | 12 ++- src/fs/fat/fat.c | 34 ++++++-- src/fs/fat/include/attr.h | 10 +++ src/fs/fat/include/fat.h | 1 - src/fs/fs.c | 11 +-- src/include/driver/bus_dm.h | 3 +- src/include/driver/storage/storage_dm.h | 3 +- src/include/driver/video_dm.h | 4 +- src/include/fs/fs.h | 10 ++- src/include/kernel/bus_driver.h | 8 +- src/include/kernel/device.h | 32 +++++++- src/include/kernel/driver.h | 27 +++++++ src/include/objects/object.h | 57 ++++++++++--- src/include/objects/ops.h | 2 + src/include/objects/permission.h | 28 +++++++ src/kernel/bus_driver.c | 17 ++-- src/kernel/device.c | 9 ++- src/kernel/driver.c | 16 ++-- src/kernel/font-default.c | 18 ++--- src/kernel/main.c | 37 +++++++-- src/kernel/thread.c | 6 ++ src/objects/Makefile | 3 +- src/objects/mount.c | 6 +- src/objects/objects.c | 47 ++++++----- src/objects/ops.c | 81 +++++++++++++------ src/objects/permission.c | 20 +++++ src/objects/types.c | 14 ++-- 41 files changed, 517 insertions(+), 156 deletions(-) create mode 100644 src/fs/fat/attr.c create mode 100644 src/fs/fat/include/attr.h create mode 100644 src/include/objects/permission.h create mode 100644 src/objects/permission.c diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index d1037e7..e7d70df 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -118,6 +118,7 @@ void ide_pause(IdeChannel *channel) { void ide_device_probe(IdeChannel *channel) { int i, status, err = 0; AtaDeviceType type = ATA_DEVICE_TYPE_ATA; + ObjectAttr attr = device_object_attr; timer_init(&channel->timer); channel->device_count = 0; @@ -176,7 +177,8 @@ void ide_device_probe(IdeChannel *channel) { StorageDevice *storage_device = kmalloc_from_template(storage_device_template); - register_storage_device(&ide_device_driver, device[i], storage_device); + register_storage_device( + &ide_device_driver, device[i], storage_device, &attr); IdeDevice *ide_device = device[i]->private_data; ide_device->device = device[i]; diff --git a/src/arch/x86/drivers/disk/ata/ide_controller.c b/src/arch/x86/drivers/disk/ata/ide_controller.c index dea745c..2cf0be7 100644 --- a/src/arch/x86/drivers/disk/ata/ide_controller.c +++ b/src/arch/x86/drivers/disk/ata/ide_controller.c @@ -15,6 +15,7 @@ #include "include/ata_driver.h" #include "include/ide.h" #include "include/ide_controller.h" +#include "objects/object.h" DriverResult ide_controller_probe(PciDevice *pci_device); DriverResult ide_controller_init(Device *device); @@ -75,10 +76,11 @@ void ide_detect_channel_mode( } DriverResult ide_controller_probe(PciDevice *pci_device) { - Device *device = kmalloc_from_template(ide_controller_device_templete); - string_t name = STRING_INIT(""); + Device *device = kmalloc_from_template(ide_controller_device_templete); + string_t name = STRING_INIT(""); + ObjectAttr attr = device_object_attr; register_device( - &ide_controller_device_driver, name, pci_device->bus, device); + &ide_controller_device_driver, name, pci_device->bus, device, &attr); IdeControllerInfo *info = device->private_data; info->pci_device = pci_device; diff --git a/src/arch/x86/drivers/pci.c b/src/arch/x86/drivers/pci.c index d09f4f6..a51d4d8 100644 --- a/src/arch/x86/drivers/pci.c +++ b/src/arch/x86/drivers/pci.c @@ -6,6 +6,7 @@ * @date 2020-07 */ #include "kernel/list.h" +#include "objects/object.h" #include #include #include @@ -25,7 +26,6 @@ #include #include - LIST_HEAD(pci_driver_lh); PciDevice pci_devices[PCI_MAX_DEVICE]; @@ -259,7 +259,9 @@ DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus) { new_bus->subordinate_bus_num = pci_device->pci2pci_bridge.subordinate_bus_number; - register_bus(bus_driver, bus->controller_device, new_bus); + ObjectAttr attr = device_object_attr; + register_bus( + bus_driver, bus->controller_device, new_bus, &attr); } } } @@ -274,7 +276,8 @@ DriverResult pci_init_bus(BusDriver *bus_driver) { bus->bus_num = 0; bus->subordinate_bus_num = 0; bus->primary_bus = NULL; - register_bus(&pci_bus_driver, &pci_device, bus); + ObjectAttr attr = device_object_attr; + register_bus(&pci_bus_driver, &pci_device, bus, &attr); // printk("device id\tvendor id\theader " // "type\tclasscode\tsubclass\tprogif\trevision id\n"); return DRIVER_RESULT_OK; @@ -638,16 +641,18 @@ DriverResult pci_probe(BusDriver *bus_driver, Bus *bus) { DriverResult pci_driver_init(Driver *driver) { check_dependency(&pci_driver); pci_device_driver.bus = pci_dependencies[0].out_bus; + ObjectAttr attr = device_object_attr; DRV_RESULT_DELIVER_CALL( register_bus_controller_device, &pci_device_driver, &pci_bus_driver, - &pci_device, &pci_bus_controller_device); + &pci_device, &pci_bus_controller_device, &attr); return DRIVER_RESULT_OK; } static __init void pci_initcall(void) { register_driver(&pci_driver); register_device_driver(&pci_driver, &pci_device_driver); - register_bus_driver(&pci_driver, &pci_bus_driver); + ObjectAttr attr = driver_object_attr; + register_bus_driver(&pci_driver, &pci_bus_driver, &attr); } driver_initcall(pci_initcall); diff --git a/src/arch/x86/drivers/vesa_display.c b/src/arch/x86/drivers/vesa_display.c index 1044095..d5c4c71 100644 --- a/src/arch/x86/drivers/vesa_display.c +++ b/src/arch/x86/drivers/vesa_display.c @@ -47,9 +47,10 @@ VideoDevice vesa_display_video_device = { void register_vesa_display(void) { register_device_driver(&core_driver, &vesa_display_device_driver); + ObjectAttr attr = device_object_attr; register_video_device( &vesa_display_device_driver, &vesa_display_device, - &vesa_display_video_device); + &vesa_display_video_device, &attr); } #define SEG_ADDR2LINEAR_ADDR(addr) \ diff --git a/src/arch/x86/include/kernel/thread.h b/src/arch/x86/include/kernel/thread.h index b36e0e3..d684570 100644 --- a/src/arch/x86/include/kernel/thread.h +++ b/src/arch/x86/include/kernel/thread.h @@ -63,6 +63,7 @@ struct task_s { uint32_t elapsed_ticks; uint32_t *pgdir; uint32_t stack_magic; + size_t subject_id; uint8_t *end_flag; @@ -78,6 +79,7 @@ struct task_s { extern list_t thread_all; struct task_s *get_current_thread(); +size_t get_current_subject_id(); void init_thread(struct task_s *pthread, char *name, int priority); void thread_create( struct task_s *pthread, thread_func *function, void *func_arg); diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index d472cd5..f6d54c2 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -1,7 +1,3 @@ -#include "driver/bus_dm.h" -#include "kernel/memory.h" -#include "objects/object.h" -#include "string.h" #include #include #include @@ -17,6 +13,8 @@ #include #include #include +#include +#include BusDriverOps platform_ops = { .register_bus_hook = NULL, @@ -50,7 +48,8 @@ void platform_early_init() { void platform_init() { // 因为platform_bus是虚拟的,所以不需要注册device - register_bus_driver(&platform_driver, &platform_bus_driver); + ObjectAttr attr = driver_object_attr; + register_bus_driver(&platform_driver, &platform_bus_driver, &attr); platform_bus.object = platform_bus_driver.object; list_init(&platform_bus_driver.bus_lh); list_add_tail(&platform_bus.bus_list, &platform_bus_driver.bus_lh); diff --git a/src/driver/bus_dm.c b/src/driver/bus_dm.c index 638dcca..e046707 100644 --- a/src/driver/bus_dm.c +++ b/src/driver/bus_dm.c @@ -1,3 +1,4 @@ +#include "objects/object.h" #include #include #include @@ -27,7 +28,7 @@ struct DeviceManager bus_controller_device_manager = { DriverResult register_bus_controller_device( DeviceDriver *device_driver, BusDriver *bus_driver, Device *device, - BusControllerDevice *bus_controller_device) { + BusControllerDevice *bus_controller_device, ObjectAttr *attr) { device->device_driver = device_driver; bus_controller_device->device = device; @@ -35,6 +36,6 @@ DriverResult register_bus_controller_device( DRV_RESULT_DELIVER_CALL( register_device, device_driver, bus_controller_device->short_name, - device->bus, device); + device->bus, device, attr); return DRIVER_RESULT_OK; } diff --git a/src/driver/storage/disk/mbr.c b/src/driver/storage/disk/mbr.c index 1729b5e..d620825 100644 --- a/src/driver/storage/disk/mbr.c +++ b/src/driver/storage/disk/mbr.c @@ -1,3 +1,5 @@ +#include "kernel/device.h" +#include "kernel/memory.h" #include #include #include @@ -25,8 +27,9 @@ void parse_mbr_partition_table(StorageDevice *storage_device) { if (partition_table[i].fs_type != 0) { string_t name; string_new_with_number(&name, "Partition", 9, partition_count); - Object *object = create_object( - storage_device->object, name, OBJECT_TYPE_PARTITION); + ObjectAttr attr = device_object_attr; + attr.type = OBJECT_TYPE_PARTITION; + Object *object = create_object(storage_device->object, name, attr); Partition *partition = kmalloc(sizeof(Partition)); partition->storage_object = storage_device->device->object; diff --git a/src/driver/storage/storage_dm.c b/src/driver/storage/storage_dm.c index 98f4e13..c7d06ff 100644 --- a/src/driver/storage/storage_dm.c +++ b/src/driver/storage/storage_dm.c @@ -45,8 +45,8 @@ struct DeviceManager storage_dm = { }; DriverResult register_storage_device( - DeviceDriver *device_driver, Device *device, - StorageDevice *storage_device) { + DeviceDriver *device_driver, Device *device, StorageDevice *storage_device, + ObjectAttr *attr) { storage_device->device = device; device->dm_ext = storage_device; @@ -55,7 +55,7 @@ DriverResult register_storage_device( string_t name; string_new_with_number(&name, "Storage", 7, storage_dm_ext.device_count++); DRV_RESULT_DELIVER_CALL( - register_device, device_driver, name, device->bus, device); + register_device, device_driver, name, device->bus, device, attr); list_add_tail(&device->dm_list, &storage_dm.device_lh); device->object->in.type = TRANSFER_TYPE_BLOCK; @@ -72,7 +72,9 @@ DriverResult register_storage_device( storage_device->name = name; periodic_task_add(&storage_device->periodic_task); - storage_device->object = create_object_directory(&device_object, name); + attr->type = OBJECT_TYPE_DIRECTORY; + storage_device->object = + create_object_directory(&device_object, name, *attr); return DRIVER_RESULT_OK; } diff --git a/src/driver/storage/storage_io.c b/src/driver/storage/storage_io.c index 2b57706..1d048a9 100644 --- a/src/driver/storage/storage_io.c +++ b/src/driver/storage/storage_io.c @@ -14,7 +14,7 @@ TransferResult storage_transfer_async( Object *object, TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, void **handle) { - while (object->type == OBJECT_TYPE_SYM_LINK) { + while (object->attr.type == OBJECT_TYPE_SYM_LINK) { object = object->value.sym_link; } Device *device = object->value.device; @@ -36,7 +36,7 @@ TransferResult storage_transfer_async( TransferResult storage_transfer( Object *object, TransferDirection direction, uint8_t *buf, uint32_t position, size_t count) { - while (object->type == OBJECT_TYPE_SYM_LINK) { + while (object->attr.type == OBJECT_TYPE_SYM_LINK) { object = object->value.sym_link; } Device *device = object->value.device; @@ -59,7 +59,7 @@ TransferResult storage_transfer( TransferResult storage_is_transfer_done( Object *object, void **handle, bool *done) { - if (object->type != OBJECT_TYPE_DEVICE) { + if (object->attr.type != OBJECT_TYPE_DEVICE) { return TRANSFER_ERROR_INVALID_PARAMETER; } Device *device = object->value.device; diff --git a/src/driver/storage/volume.c b/src/driver/storage/volume.c index 250b10d..75367fc 100644 --- a/src/driver/storage/volume.c +++ b/src/driver/storage/volume.c @@ -31,8 +31,9 @@ void probe_volume(Partition *partition) { string_new_with_string_number( &name, prefix.text, prefix.length - 1, "Volume", 6, partition->index); - Object *root_object = - create_object_directory(&volumes_object, name); + ObjectAttr attr = device_object_attr; + Object *root_object = + create_object_directory(&volumes_object, name, attr); partition->object->fs_info = fs_info; object_mount(partition->object, root_object); diff --git a/src/driver/video_dm.c b/src/driver/video_dm.c index fcb77e8..d59347e 100644 --- a/src/driver/video_dm.c +++ b/src/driver/video_dm.c @@ -1,3 +1,4 @@ +#include "objects/object.h" #include #include #include @@ -44,7 +45,8 @@ DriverResult video_dm_unload(DeviceManager *manager) { } DriverResult register_video_device( - DeviceDriver *device_driver, Device *device, VideoDevice *video_device) { + DeviceDriver *device_driver, Device *device, VideoDevice *video_device, + ObjectAttr *attr) { device->dm_ext = video_device; if (device->dm_ext == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } video_device->device = device; @@ -54,7 +56,7 @@ DriverResult register_video_device( &name, "Video", 5, video_dm_ext.video_device_count++); DRV_RESULT_DELIVER_CALL( - register_device, device_driver, name, device_driver->bus, device); + register_device, device_driver, name, device_driver->bus, device, attr); list_init(&video_device->video_list_lh); list_add_tail(&device->dm_list, &video_dm.device_lh); diff --git a/src/fs/fat/Makefile b/src/fs/fat/Makefile index b4b090f..4827668 100644 --- a/src/fs/fat/Makefile +++ b/src/fs/fat/Makefile @@ -3,4 +3,5 @@ SRC += cluster.c SRC += dir.c SRC += name.c SRC += entry.c -SRC += time.c \ No newline at end of file +SRC += time.c +SRC += attr.c \ No newline at end of file diff --git a/src/fs/fat/attr.c b/src/fs/fat/attr.c new file mode 100644 index 0000000..01204f4 --- /dev/null +++ b/src/fs/fat/attr.c @@ -0,0 +1,74 @@ +#include "fs/fs.h" +#include "include/dir.h" +#include +#include +#include +#include + +FsResult fat_attr_to_sys_attr(ShortDir *short_dir, ObjectAttr *attr) { + uint8_t fat_attr = short_dir->attr; + if (fat_attr & ATTR_ARCHIVE) { + attr->size = short_dir->file_size; + attr->is_mounted = 0; + Permission *all_user = &attr->all_user_permission; + Permission *system = &attr->system_permission; + Permission *owner = &attr->owner_permission; + Permission *admin = &attr->admin_permission; + memset(&all_user->permission, 0xff, sizeof(all_user->permission)); + memset(&system->permission, 0xff, sizeof(system->permission)); + memset(&owner->permission, 0xff, sizeof(owner->permission)); + memset(&admin->permission, 0xff, sizeof(admin->permission)); + all_user->subject_id = SUBJECT_ID_ALL; + system->subject_id = SUBJECT_ID_SYSTEM; + admin->subject_id = SUBJECT_ID_ADMIN; + + if (fat_attr & ATTR_SYSTEM) { + all_user->permission.read = 0; + all_user->permission.write = 0; + all_user->permission.execute = 0; + all_user->permission.delete = 0; + all_user->permission.rename = 0; + admin->permission.delete = 0; + admin->permission.rename = 0; + admin->permission.write = 0; + owner->subject_id = SUBJECT_ID_SYSTEM; + attr->owner_id = SUBJECT_ID_SYSTEM; + } else { + owner->subject_id = SUBJECT_ID_ALL; + attr->owner_id = SUBJECT_ID_ALL; + } + if (fat_attr & ATTR_DIRECTORY) { + attr->type = OBJECT_TYPE_DIRECTORY; + if (fat_attr & ATTR_SYSTEM) { all_user->permission.execute = 1; } + } + + if (fat_attr & ATTR_READ_ONLY) { + attr->all_user_permission.permission.write = 0; + } + if (fat_attr & ATTR_HIDDEN) { + attr->all_user_permission.permission.visible = 0; + } + } + return FS_OK; +} + +FsResult fat_attr_from_sys_attr(ShortDir *short_dir, ObjectAttr *attr) { + Permission *all_user = &attr->all_user_permission; + Permission *owner = &attr->owner_permission; + + short_dir->attr = ATTR_ARCHIVE; + if (all_user->permission.write == 0 && all_user->permission.read == 1) { + short_dir->attr |= ATTR_READ_ONLY; + } + if (all_user->permission.visible == 0) { short_dir->attr |= ATTR_HIDDEN; } + if (attr->type == OBJECT_TYPE_DIRECTORY) { + short_dir->attr |= ATTR_DIRECTORY; + } else { + short_dir->file_size = attr->size; + } + if (owner->subject_id == SUBJECT_ID_SYSTEM) { + short_dir->attr |= ATTR_SYSTEM; + } + + return FS_OK; +} diff --git a/src/fs/fat/entry.c b/src/fs/fat/entry.c index e9fbcfd..1054172 100644 --- a/src/fs/fat/entry.c +++ b/src/fs/fat/entry.c @@ -1,4 +1,5 @@ #include "include/entry.h" +#include "include/attr.h" #include "include/cluster.h" #include "include/dir.h" #include "include/fat.h" @@ -165,16 +166,21 @@ PUBLIC FatDirEntry *generate_dir_entry( entry->cluster_list = dyn_array_new(sizeof(ClusterSegment), 8); get_cluster_segment(fat_info, entry); - Object *object; + Object *object; + ObjectAttr attr; + fat_attr_to_sys_attr(short_dir, &attr); + if (entry->short_dir.attr & ATTR_DIRECTORY) { FsResult result = fs_obj_create_dir( - parent_entry->object, fat_info->fs_info, entry->name, &object); + parent_entry->object, fat_info->fs_info, entry->name, &object, + &attr); if (result != FS_OK) { return NULL; } object->value.directory.data = entry; entry_cache_init(fat_info, entry, fat_info->bytes_per_cluster); } else { FsResult result = fs_obj_create_file( - parent_entry->object, fat_info->fs_info, entry->name, &object); + parent_entry->object, fat_info->fs_info, entry->name, &object, + &attr); if (result != FS_OK) { return NULL; } object->value.file.data = entry; object->value.file.offset = 0; diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c index f94d197..56d4009 100644 --- a/src/fs/fat/fat.c +++ b/src/fs/fat/fat.c @@ -1,4 +1,5 @@ #include "include/fat.h" +#include "include/attr.h" #include "include/cluster.h" #include "include/dir.h" #include "include/entry.h" @@ -33,6 +34,8 @@ FsResult fat_create_file(Object *directory, string_t name, Object **object); FsResult fat_delete_file(Object *directory, string_t name); FsResult fat_mkdir(Object *parent_obj, string_t name, Object **object); FsResult fat_rmdir(Object *parent_obj, string_t name); +FsResult fat_get_attr(Object *object, ObjectAttr *attr); +FsResult fat_set_attr(Object *object, ObjectAttr *attr); FileSystemOps fat_ops = { .fs_check = fat_check, @@ -40,11 +43,13 @@ FileSystemOps fat_ops = { }; FsFileOps fat_file_ops = { - .fs_open = fat_open, - .fs_close = fat_close, - .fs_seek = fat_seek, - .fs_read = fat_read, - .fs_write = fat_write, + .fs_open = fat_open, + .fs_close = fat_close, + .fs_seek = fat_seek, + .fs_read = fat_read, + .fs_write = fat_write, + .fs_get_attr = fat_get_attr, + .fs_set_attr = fat_set_attr, }; FsDirectoryOps fat_dir_ops = { @@ -54,6 +59,8 @@ FsDirectoryOps fat_dir_ops = { .fs_delete_file = fat_delete_file, .fs_mkdir = fat_mkdir, .fs_rmdir = fat_rmdir, + .fs_get_attr = fat_get_attr, + .fs_set_attr = fat_set_attr, }; FileSystem fat_fs = { @@ -314,6 +321,23 @@ FsResult fat_rmdir(Object *parent_obj, string_t name) { return FS_OK; } +FsResult fat_get_attr(Object *object, ObjectAttr *attr) { + FatDirEntry *entry = object->value.file.data; + fat_attr_to_sys_attr(&entry->short_dir, attr); + return FS_OK; +} + +FsResult fat_set_attr(Object *object, ObjectAttr *attr) { + FatInfo *fat_info = object->fs_info->private_data; + FatDirEntry *entry = object->value.file.data; + FatDirEntry *parent = object->parent->value.directory.data; + fat_attr_from_sys_attr(&entry->short_dir, attr); + fat_entry_write( + fat_info, parent, entry->shortname_cluster, entry->shortname_number, + (uint8_t *)&entry->short_dir); + return FS_OK; +} + void fat_initcall() { register_fs(&fat_fs); } diff --git a/src/fs/fat/include/attr.h b/src/fs/fat/include/attr.h new file mode 100644 index 0000000..98a5028 --- /dev/null +++ b/src/fs/fat/include/attr.h @@ -0,0 +1,10 @@ +#ifndef _FAT_ATTR_H +#define _FAT_ATTR_H + +#include "dir.h" +#include + +FsResult fat_attr_to_sys_attr(ShortDir *short_dir, ObjectAttr *attr); +FsResult fat_attr_from_sys_attr(ShortDir *short_dir, ObjectAttr *attr); + +#endif \ No newline at end of file diff --git a/src/fs/fat/include/fat.h b/src/fs/fat/include/fat.h index fd87542..7124f89 100644 --- a/src/fs/fat/include/fat.h +++ b/src/fs/fat/include/fat.h @@ -5,7 +5,6 @@ #include "driver/storage/disk/disk.h" #include "driver/storage/storage_dm.h" #include "kernel/block_cache.h" -#include "objects/object.h" #include #define FAT_CACHE_SIZE 2 diff --git a/src/fs/fs.c b/src/fs/fs.c index 913a6e5..a7e7e14 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c @@ -1,4 +1,3 @@ -#include "fat/include/fat.h" #include "objects/transfer.h" #include "stdint.h" #include @@ -36,8 +35,9 @@ TransferResult fs_obj_write( } FsResult fs_obj_create_file( - Object *parent, FileSystemInfo *info, string_t name, Object **object) { - *object = create_object(parent, name, OBJECT_TYPE_FILE); + Object *parent, FileSystemInfo *info, string_t name, Object **object, + ObjectAttr *attr) { + *object = create_object(parent, name, *attr); Object *out = *object; if (out == NULL) return FS_ERROR_OTHER; @@ -52,8 +52,9 @@ FsResult fs_obj_create_file( } FsResult fs_obj_create_dir( - Object *parent, FileSystemInfo *info, string_t name, Object **object) { - *object = create_object_directory(parent, name); + Object *parent, FileSystemInfo *info, string_t name, Object **object, + ObjectAttr *attr) { + *object = create_object_directory(parent, name, *attr); Object *out = *object; if (out == NULL) return FS_ERROR_OTHER; diff --git a/src/include/driver/bus_dm.h b/src/include/driver/bus_dm.h index 441f1d1..e0fc86a 100644 --- a/src/include/driver/bus_dm.h +++ b/src/include/driver/bus_dm.h @@ -3,6 +3,7 @@ #include "kernel/bus_driver.h" #include "kernel/device.h" +#include "objects/object.h" #include "string.h" typedef struct BusControllerDeviceOps { @@ -18,6 +19,6 @@ typedef struct BusControllerDevice { DriverResult register_bus_controller_device( DeviceDriver *device_driver, BusDriver *bus_driver, Device *device, - BusControllerDevice *bus_controller_device); + BusControllerDevice *bus_controller_device, ObjectAttr *attr); #endif \ No newline at end of file diff --git a/src/include/driver/storage/storage_dm.h b/src/include/driver/storage/storage_dm.h index 67e0c0d..4767813 100644 --- a/src/include/driver/storage/storage_dm.h +++ b/src/include/driver/storage/storage_dm.h @@ -5,6 +5,7 @@ #include "kernel/driver.h" #include "kernel/list.h" #include "kernel/periodic_task.h" +#include "objects/object.h" #include "string.h" #include @@ -55,7 +56,7 @@ extern DeviceManager storage_dm; DriverResult register_storage_device( struct DeviceDriver *device_driver, Device *device, - StorageDevice *storage_device); + StorageDevice *storage_device, ObjectAttr *attr); DriverResult unregister_storage_device( struct DeviceDriver *device_driver, Device *device, StorageDevice *storage_device); diff --git a/src/include/driver/video_dm.h b/src/include/driver/video_dm.h index b44dbfa..39f22e3 100644 --- a/src/include/driver/video_dm.h +++ b/src/include/driver/video_dm.h @@ -5,6 +5,7 @@ #include "kernel/device.h" #include "kernel/device_driver.h" #include "kernel/list.h" +#include "objects/object.h" #include "stdint.h" typedef struct VideoModeInfo { @@ -32,7 +33,8 @@ typedef struct VideoDeviceManager { extern struct DeviceManager video_dm; DriverResult register_video_device( - DeviceDriver *device_driver, Device *device, VideoDevice *video_device); + DeviceDriver *device_driver, Device *device, VideoDevice *video_device, + ObjectAttr *attr); DriverResult unregister_video_devce( DeviceDriver *device_driver, Device *device, VideoDevice *video_device); DriverResult video_get_video_device(int in_index, VideoDevice **out_device); diff --git a/src/include/fs/fs.h b/src/include/fs/fs.h index f88f53f..f55fbb9 100644 --- a/src/include/fs/fs.h +++ b/src/include/fs/fs.h @@ -45,6 +45,8 @@ typedef struct FsFileOps { FsResult (*fs_seek)(struct Object *object, size_t offset); FsResult (*fs_read)(struct Object *file, void *buf, size_t size); FsResult (*fs_write)(struct Object *file, void *buf, size_t size); + FsResult (*fs_get_attr)(struct Object *object, struct ObjectAttr *attr); + FsResult (*fs_set_attr)(struct Object *object, struct ObjectAttr *attr); } FsFileOps; typedef struct FsDirectoryOps { @@ -58,6 +60,8 @@ typedef struct FsDirectoryOps { FsResult (*fs_mkdir)( struct Object *parent_obj, string_t name, struct Object **object); FsResult (*fs_rmdir)(struct Object *parent_obj, string_t name); + FsResult (*fs_get_attr)(struct Object *object, struct ObjectAttr *attr); + FsResult (*fs_set_attr)(struct Object *object, struct ObjectAttr *attr); } FsDirectoryOps; typedef struct FileSystem { @@ -81,8 +85,10 @@ void register_fs(FileSystem *fs); void unregister_fs(FileSystem *fs); FsResult fs_obj_create_file( - Object *parent, FileSystemInfo *info, string_t name, Object **object); + Object *parent, FileSystemInfo *info, string_t name, Object **object, + ObjectAttr *attr); FsResult fs_obj_create_dir( - Object *parent, FileSystemInfo *info, string_t name, Object **object); + Object *parent, FileSystemInfo *info, string_t name, Object **object, + ObjectAttr *attr); #endif \ No newline at end of file diff --git a/src/include/kernel/bus_driver.h b/src/include/kernel/bus_driver.h index d166a03..f2a1f9a 100644 --- a/src/include/kernel/bus_driver.h +++ b/src/include/kernel/bus_driver.h @@ -84,12 +84,14 @@ typedef struct Bus { extern struct BusDriver *bus_drivers[BUS_TYPE_MAX]; extern struct DriverManager bus_driver_manager; -DriverResult register_bus_driver(Driver *driver, BusDriver *bus_driver); +DriverResult register_bus_driver( + Driver *driver, BusDriver *bus_driver, ObjectAttr *attr); DriverResult unregister_bus_driver(Driver *driver, BusType type); DriverResult register_bus( - BusDriver *bus_driver, Device *bus_controller_device, Bus *bus); + BusDriver *bus_driver, Device *bus_controller_device, Bus *bus, + ObjectAttr *attr); DriverResult unregister_bus(Bus *bus); -DriverResult bus_register_device(Device *device, Bus *bus); +DriverResult bus_register_device(Device *device, Bus *bus, ObjectAttr *attr); DriverResult bus_unregister_device(Device *device); #endif \ No newline at end of file diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index e250b76..ea96643 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -4,6 +4,8 @@ #include "kernel/driver.h" #include "kernel/driver_interface.h" #include "kernel/list.h" +#include "objects/object.h" +#include "objects/permission.h" #include "stdint.h" #include "string.h" #include "types.h" @@ -85,9 +87,37 @@ typedef struct Device { void *dm_ext; // 设备管理器所需的扩展信息 } Device; +static const Permission device_sys_permission = { + .subject_id = SUBJECT_ID_SYSTEM, + .permission = {1, 1, 1, 1, 1, 1, 1}, +}; +static const Permission device_all_user_permission = { + .subject_id = SUBJECT_ID_ALL, + .permission = {1, 1, 0, 1, 0, 0, 0}, +}; +static const Permission device_owner_permission = { + .subject_id = SUBJECT_ID_SYSTEM, + .permission = {1, 1, 1, 1, 1, 1, 1}, +}; +static const Permission device_admin_permission = { + .subject_id = SUBJECT_ID_ADMIN, + .permission = {1, 1, 1, 1, 0, 0, 0}, +}; + +static const ObjectAttr device_object_attr = { + .type = OBJECT_TYPE_DEVICE, + .size = sizeof(Device), + .is_mounted = false, + .owner_id = SUBJECT_ID_SYSTEM, + .all_user_permission = device_all_user_permission, + .owner_permission = device_owner_permission, + .system_permission = device_sys_permission, + .admin_permission = device_admin_permission, +}; + DriverResult register_device( struct DeviceDriver *device_driver, string_t name, struct Bus *bus, - Device *device); + Device *device, ObjectAttr *attr); DriverResult unregister_device( struct DeviceDriver *device_driver, Device *device); DriverResult unregister_child_device(ChildDevice *child_device); diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index ebaad19..7936b40 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -8,6 +8,8 @@ #include #include +#include +#include #include typedef enum { @@ -92,6 +94,31 @@ typedef struct { driver_irq_handler_t handler; } dev_irq_t; +static const Permission driver_sys_permission = { + .subject_id = SUBJECT_ID_SYSTEM, + .permission = {1, 1, 1, 1, 1, 1, 1}, +}; +static const Permission driver_all_user_permission = { + .subject_id = SUBJECT_ID_ALL, + .permission = {1, 1, 0, 1, 0, 0, 0}, +}; +static const Permission driver_owner_permission = { + .subject_id = SUBJECT_ID_SYSTEM, + .permission = {1, 1, 1, 1, 1, 1, 1}, +}; +static const Permission driver_admin_permission = { + .subject_id = SUBJECT_ID_ADMIN, + .permission = {1, 1, 1, 1, 0, 0, 0}, +}; +static const ObjectAttr driver_object_attr = { + .type = OBJECT_TYPE_DRIVER, + .size = 0, + .owner_permission = driver_owner_permission, + .system_permission = driver_sys_permission, + .all_user_permission = driver_all_user_permission, + .admin_permission = driver_admin_permission, +}; + extern struct index_node *dev; void init_dm(void); diff --git a/src/include/objects/object.h b/src/include/objects/object.h index 76841a0..cbc8d2f 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -3,9 +3,11 @@ #include "dyn_array.h" #include "kernel/list.h" +#include "objects/permission.h" #include "objects/transfer.h" #include "stdint.h" #include "string.h" +#include typedef enum ObjectResult { OBJECT_OK, @@ -15,12 +17,12 @@ typedef enum ObjectResult { OBJECT_ERROR_ILLEGAL_ARGUMENT, OBJECT_ERROR_OCCUPIED, OBJECT_ERROR_ALREADY_EXISTS, - OBJECT_ERROR_FIXED, OBJECT_ERROR_NOT_EMPTY, + OBJECT_ERROR_NO_PERMISSION, OBJECT_ERROR_OTHER, } ObjectResult; -#define OBJ_PASS(call) \ +#define OBJ_RESULT_PASS(call) \ { \ ObjectResult result = call; \ if (result != OBJECT_OK) { return result; } \ @@ -43,21 +45,33 @@ typedef enum ObjectType { OBJECT_TYPE_BUILTIN_MAX, // 表示对象系统内建类型数量的最大值 } ObjectType; +typedef struct ObjectAttr { + ObjectType type; + size_t size; + + bool is_mounted; + size_t owner_id; + Permission all_user_permission; + Permission owner_permission; + Permission system_permission; + Permission admin_permission; + + list_t permission_lh; +} ObjectAttr; + struct Partition; typedef struct Object { list_t list; - string_t name; - ObjectType type; + string_t name; struct Object *parent; TransferIn in; TransferOut out; - bool fixed; uint32_t reference; - bool is_mounted; + ObjectAttr attr; struct Object *origin; struct FileSystemInfo *fs_info; @@ -92,6 +106,29 @@ typedef struct Object { void (*release_data)(struct Object *object); } Object; +static const Permission base_obj_sys_perm = { + .subject_id = SUBJECT_ID_SYSTEM, + .permission = {1, 1, 1, 1, 0, 1, 1}, +}; +static const Permission base_obj_all_user_perm = { + .subject_id = SUBJECT_ID_ALL, + .permission = {1, 0, 0, 1, 0, 0, 0}, +}; +static const Permission base_obj_admin_perm = { + .subject_id = SUBJECT_ID_ADMIN, + .permission = {1, 1, 0, 1, 0, 0, 0}, +}; + +static const ObjectAttr base_obj_sys_attr = { + .type = OBJECT_TYPE_DIRECTORY, + .size = 0, + .owner_id = SUBJECT_ID_SYSTEM, + .owner_permission = base_obj_sys_perm, + .system_permission = base_obj_sys_perm, + .all_user_permission = base_obj_all_user_perm, + .admin_permission = base_obj_admin_perm, +}; + extern Object root_object; extern Object bus_object; extern Object driver_object; @@ -103,10 +140,10 @@ ObjectResult add_object(Object *parent, Object *child); // 通过路径打开对象,对于符号链接会自动解析 ObjectResult open_oringinal_object_by_path(char *path, Object **out_object); ObjectResult open_object_by_path(char *path, Object **object); -Object *create_object(Object *parent, string_t name, ObjectType type); -Object *create_object_directory(Object *parent, string_t name); -void object_close(Object *object); -void show_object_tree(); +Object *create_object(Object *parent, string_t name, ObjectAttr attr); +Object *create_object_directory(Object *parent, string_t name, ObjectAttr attr); +void object_close(Object *object); +void show_object_tree(); #define append_object(parent, child) \ dyn_array_append((parent)->value.directory.children, Object *, (child)); diff --git a/src/include/objects/ops.h b/src/include/objects/ops.h index 9d5472d..ef768e1 100644 --- a/src/include/objects/ops.h +++ b/src/include/objects/ops.h @@ -19,5 +19,7 @@ ObjectResult obj_create_file(Object *parent, string_t name); ObjectResult obj_delete_file(Object *parent, string_t name); ObjectResult obj_mkdir(Object *parent, string_t name); ObjectResult obj_rmdir(Object *parent, string_t name); +ObjectResult obj_get_attr(Object *object, ObjectAttr *attr); +ObjectResult obj_set_attr(Object *object, ObjectAttr *attr); #endif \ No newline at end of file diff --git a/src/include/objects/permission.h b/src/include/objects/permission.h new file mode 100644 index 0000000..4a67bd4 --- /dev/null +++ b/src/include/objects/permission.h @@ -0,0 +1,28 @@ +#ifndef _OBJECT_PERMISSION_H +#define _OBJECT_PERMISSION_H + +#include +#include + +#define SUBJECT_ID_ALL 0 +#define SUBJECT_ID_SYSTEM 1 +#define SUBJECT_ID_ADMIN 2 + +typedef struct Permission { + list_t list; + uint32_t subject_id; + struct { + uint32_t visible : 1; + uint32_t read : 1; + uint32_t write : 1; + uint32_t execute : 1; // 对于文件表示执行,对于目录表示访问 + uint32_t delete : 1; + uint32_t rename : 1; + uint32_t set_attr : 1; + } permission; +} Permission; + +struct Object; +Permission *get_permission_info(struct Object *object); + +#endif \ No newline at end of file diff --git a/src/kernel/bus_driver.c b/src/kernel/bus_driver.c index e8188fe..670135d 100644 --- a/src/kernel/bus_driver.c +++ b/src/kernel/bus_driver.c @@ -1,6 +1,5 @@ #include "kernel/driver_interface.h" #include "objects/object.h" -#include "objects/types.h" #include "string.h" #include #include @@ -51,7 +50,8 @@ DriverResult bus_driver_manager_unload(DriverManager *driver_manager) { return DRIVER_RESULT_OK; } -DriverResult register_bus_driver(Driver *driver, BusDriver *bus_driver) { +DriverResult register_bus_driver( + Driver *driver, BusDriver *bus_driver, ObjectAttr *attr) { DriverManager *manager = driver_managers[DRIVER_TYPE_BUS_DRIVER]; if (manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; @@ -69,7 +69,8 @@ DriverResult register_bus_driver(Driver *driver, BusDriver *bus_driver) { bus_drivers[bus_driver->bus_type] = bus_driver; - bus_driver->object = create_object_directory(&bus_object, bus_driver->name); + bus_driver->object = + create_object_directory(&bus_object, bus_driver->name, *attr); return DRIVER_RESULT_OK; } @@ -101,7 +102,8 @@ DriverResult unregister_bus_driver(Driver *driver, BusType type) { } DriverResult register_bus( - BusDriver *bus_driver, Device *bus_controller_device, Bus *bus) { + BusDriver *bus_driver, Device *bus_controller_device, Bus *bus, + ObjectAttr *attr) { if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; Bus *primary_bus = bus->primary_bus; @@ -119,7 +121,7 @@ DriverResult register_bus( list_init(&bus->device_lh); list_add_tail(&bus->bus_list, &bus_driver->bus_lh); - bus->object = create_object_directory(bus_driver->object, bus->name); + bus->object = create_object_directory(bus_driver->object, bus->name, *attr); BUS_OPS_CALL(bus_driver, register_bus_hook, bus); @@ -145,7 +147,7 @@ DriverResult unregister_bus(Bus *bus) { return DRIVER_RESULT_OK; } -DriverResult bus_register_device(Device *device, Bus *bus) { +DriverResult bus_register_device(Device *device, Bus *bus, ObjectAttr *attr) { BusDriver *bus_driver = bus->bus_driver; if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; @@ -155,7 +157,8 @@ DriverResult bus_register_device(Device *device, Bus *bus) { string_t name; string_new_with_number(&name, "", 0, bus->last_device_num++); - device->object = create_object(bus->object, name, OBJECT_TYPE_DEVICE); + attr->type = OBJECT_TYPE_DEVICE; + device->object = create_object(bus->object, name, *attr); device->object->value.device = device; return DRIVER_RESULT_OK; diff --git a/src/kernel/device.c b/src/kernel/device.c index f9de7ee..4717edc 100644 --- a/src/kernel/device.c +++ b/src/kernel/device.c @@ -19,7 +19,8 @@ * @return DriverResult */ DriverResult register_device( - DeviceDriver *device_driver, string_t name, Bus *bus, Device *device) { + DeviceDriver *device_driver, string_t name, Bus *bus, Device *device, + ObjectAttr *attr) { device->state = DEVICE_STATE_REGISTERED; @@ -38,11 +39,11 @@ DriverResult register_device( } list_add_tail(&device->device_list, &device_driver->device_lh); - bus_register_device(device, bus); + bus_register_device(device, bus, attr); if (name.text != NULL && name.length != 0) { - Object *object = - create_object(&device_object, name, OBJECT_TYPE_SYM_LINK); + attr->type = OBJECT_TYPE_SYM_LINK; + Object *object = create_object(&device_object, name, *attr); object->value.sym_link = device->object; } diff --git a/src/kernel/driver.c b/src/kernel/driver.c index 17daee2..feac910 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -82,7 +82,7 @@ DriverResult register_driver(Driver *driver) { list_add_tail(&driver->driver_list, &driver_lh); Object *object = - create_object(&driver_object, driver->short_name, OBJECT_TYPE_DRIVER); + create_object(&driver_object, driver->short_name, driver_object_attr); object->value.driver = driver; return DRIVER_RESULT_OK; } @@ -234,8 +234,8 @@ void init_dm(void) { } status_t driver_create(driver_func_t func, char *driver_name) { - driver_t *drv_obj; - int status; + // driver_t *drv_obj; + // int status; // drv_obj = kmalloc(sizeof(driver_t)); // if (drv_obj == NULL) { return FAILED; } @@ -320,11 +320,11 @@ void device_register_irq( void device_unregister_irq(device_t *devobj, int irq) { if (irq > 16) return; // if (list_empty(&device_irq_lists[irq])) return; - dev_irq_t *dev_irq, *next; + // dev_irq_t *dev_irq, *next; // list_for_each_owner_safe (dev_irq, next, &device_irq_lists[irq], list) { - if (dev_irq->devobj == devobj) { - list_del(&dev_irq->list); - kfree(dev_irq); - } + // if (dev_irq->devobj == devobj) { + // list_del(&dev_irq->list); + // kfree(dev_irq); + // } // } } diff --git a/src/kernel/font-default.c b/src/kernel/font-default.c index 897c16b..b2251ee 100644 --- a/src/kernel/font-default.c +++ b/src/kernel/font-default.c @@ -1491,15 +1491,15 @@ unsigned char font16[] = { // 0x57 W 0b00000000, 0b00000000, - 0b10000001, - 0b10000001, - 0b10000001, - 0b01000010, - 0b01011010, - 0b01011010, - 0b01011010, - 0b01011010, - 0b01011010, + 0b11000011, + 0b11000011, + 0b11000011, + 0b11000011, + 0b11011011, + 0b11011011, + 0b01111110, + 0b01111110, + 0b01111110, 0b01100110, 0b01100110, 0b01100110, diff --git a/src/kernel/main.c b/src/kernel/main.c index beb66ef..b46a34f 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -4,6 +4,7 @@ * @brief 内核主程序 * @date 2020-03 */ +#include "objects/permission.h" #include "string.h" #include #include @@ -47,6 +48,19 @@ void idle(void *arg); struct task_s *task_idle; extern Driver core_driver; +// void print_permission(Permission *permission) { +// printk("Subject ID:%d\n", permission->subject_id); +// printk("Permission:"); +// if (permission->permission.visible) { printk("Visible "); } +// if (permission->permission.read) { printk("Read "); } +// if (permission->permission.write) { printk("Write "); } +// if (permission->permission.execute) { printk("Execute "); } +// if (permission->permission.delete) { printk("Delete "); } +// if (permission->permission.rename) { printk("Rename "); } +// if (permission->permission.set_attr) { printk("SetAttr "); } +// printk("\n"); +// } + int main() { platform_early_init(); @@ -78,12 +92,23 @@ int main() { driver_start_all(); // uint8_t buf[512]; - Object *object; - ObjectResult result = - open_object_by_path("\\Volumes\\Storage0Volume0\\", &object); - if (result != OBJECT_OK) { printk("Open File Error!\n"); } - const string_t name = STRING_INIT("A folder"); - obj_rmdir(object, name); + // Object *object; + // ObjectResult result = + // open_object_by_path("\\Volumes\\Storage0Volume0\\kernel.elf", &object); + // if (result != OBJECT_OK) { + // printk("Open File Error!\n"); + // } else { + // ObjectAttr attr; + // obj_get_attr(object, &attr); + // printk("File Size:%d\n", attr.size); + // print_permission(&attr.all_user_permission); + // print_permission(&attr.admin_permission); + // print_permission(&attr.owner_permission); + // print_permission(&attr.system_permission); + // } + + // const string_t name = STRING_INIT("A folder"); + // obj_rmdir(object, name); // void *handle = NULL; // Object *object; diff --git a/src/kernel/thread.c b/src/kernel/thread.c index ca54141..95c64a7 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,10 @@ struct task_s *get_current_thread() { return (struct task_s *)(sp & 0xfffff000); } +size_t get_current_subject_id() { + return get_current_thread()->subject_id; +} + /** * @brief 运行内核线程 * @@ -103,6 +108,7 @@ void init_thread(struct task_s *pthread, char *name, int priority) { pthread->elapsed_ticks = 0; pthread->pgdir = NULL; pthread->stack_magic = 0x10000000; + pthread->subject_id = SUBJECT_ID_SYSTEM; } /** diff --git a/src/objects/Makefile b/src/objects/Makefile index f11f562..66a9ab7 100644 --- a/src/objects/Makefile +++ b/src/objects/Makefile @@ -1,4 +1,5 @@ SRC += objects.c SRC += types.c SRC += mount.c -SRC += ops.c \ No newline at end of file +SRC += ops.c +SRC += permission.c \ No newline at end of file diff --git a/src/objects/mount.c b/src/objects/mount.c index 24b6993..61a0882 100644 --- a/src/objects/mount.c +++ b/src/objects/mount.c @@ -3,9 +3,9 @@ #include ObjectResult object_mount(Object *origin, Object *dest) { - if (dest->is_mounted) { return OBJECT_ERROR_INVALID_OPERATION; } - dest->is_mounted = true; - dest->origin = origin; + if (dest->attr.is_mounted) { return OBJECT_ERROR_INVALID_OPERATION; } + dest->attr.is_mounted = true; + dest->origin = origin; dest->fs_info = origin->fs_info; diff --git a/src/objects/objects.c b/src/objects/objects.c index e3f2d15..67f242c 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -10,31 +10,32 @@ #include #include +const Permission sys_permission = { + .subject_id = SUBJECT_ID_SYSTEM, + .permission = {1, 1, 1, 1, 1, 1, 1}, +}; + Object root_object = { .name = STRING_INIT(""), // 根对象的名字不会起到任何作用,所以设为空 - .type = OBJECT_TYPE_DIRECTORY, .parent = NULL, - .fixed = true, + .attr = base_obj_sys_attr, + }; Object bus_object = { - .name = STRING_INIT("Bus"), - .type = OBJECT_TYPE_DIRECTORY, - .fixed = true, + .name = STRING_INIT("Bus"), + .attr = base_obj_sys_attr, }; Object driver_object = { - .name = STRING_INIT("Driver"), - .type = OBJECT_TYPE_DIRECTORY, - .fixed = true, + .name = STRING_INIT("Driver"), + .attr = base_obj_sys_attr, }; Object device_object = { - .name = STRING_INIT("Device"), - .type = OBJECT_TYPE_DIRECTORY, - .fixed = true, + .name = STRING_INIT("Device"), + .attr = base_obj_sys_attr, }; Object volumes_object = { - .name = STRING_INIT("Volumes"), - .type = OBJECT_TYPE_DIRECTORY, - .fixed = true, + .name = STRING_INIT("Volumes"), + .attr = base_obj_sys_attr, }; static inline void init_object_directory(Object *object) { @@ -100,7 +101,7 @@ ObjectResult open_oringinal_object_by_path(char *path, Object **out_object) { ObjectResult open_object_by_path(char *path, Object **object) { ObjectResult result = open_oringinal_object_by_path(path, object); if (result == OBJECT_OK) { - while ((*object)->type == OBJECT_TYPE_SYM_LINK) { + while ((*object)->attr.type == OBJECT_TYPE_SYM_LINK) { *object = (*object)->value.sym_link; } } @@ -108,7 +109,7 @@ ObjectResult open_object_by_path(char *path, Object **object) { } ObjectResult add_object(Object *parent, Object *child) { - if (parent->type != OBJECT_TYPE_DIRECTORY) { + if (parent->attr.type != OBJECT_TYPE_DIRECTORY) { return OBJECT_ERROR_INVALID_OPERATION; } @@ -118,12 +119,12 @@ ObjectResult add_object(Object *parent, Object *child) { return OBJECT_OK; } -Object *create_object(Object *parent, string_t name, ObjectType type) { +Object *create_object(Object *parent, string_t name, ObjectAttr attr) { Object *object = kmalloc(sizeof(Object)); if (object == NULL) { return NULL; } object->name = name; - object->type = type; + object->attr = attr; object->parent = parent; object->reference = 0; @@ -136,8 +137,10 @@ Object *create_object(Object *parent, string_t name, ObjectType type) { return object; } -Object *create_object_directory(Object *parent, string_t name) { - Object *object = create_object(parent, name, OBJECT_TYPE_DIRECTORY); +Object *create_object_directory( + Object *parent, string_t name, ObjectAttr attr) { + attr.type = OBJECT_TYPE_DIRECTORY; + Object *object = create_object(parent, name, attr); if (object == NULL) { return NULL; } init_object_directory(object); @@ -159,12 +162,12 @@ void print_object_directory(Object *object, int level) { printk("|\t"); } printk("|-%s", child->name.text); - if (child->type == OBJECT_TYPE_SYM_LINK) { + if (child->attr.type == OBJECT_TYPE_SYM_LINK) { printk("\t->\t"); print_symbol_link(child->value.sym_link); } printk("\n"); - if (child->type == OBJECT_TYPE_DIRECTORY) { + if (child->attr.type == OBJECT_TYPE_DIRECTORY) { print_object_directory(child, level + 1); } } diff --git a/src/objects/ops.c b/src/objects/ops.c index feceb0c..7d17292 100644 --- a/src/objects/ops.c +++ b/src/objects/ops.c @@ -1,5 +1,6 @@ #include "kernel/list.h" #include "kernel/memory.h" +#include "objects/permission.h" #include "objects/transfer.h" #include "string.h" #include @@ -14,8 +15,8 @@ ObjectResult obj_search( list_for_each_owner (child, &parent->value.directory.children, list) { if (child->name.length == name.length && strncmp(child->name.text, name.text, name.length) == 0) { - if ((is_directory && child->type == OBJECT_TYPE_DIRECTORY) || - (!is_directory && child->type != OBJECT_TYPE_DIRECTORY)) { + if ((is_directory && child->attr.type == OBJECT_TYPE_DIRECTORY) || + (!is_directory && child->attr.type != OBJECT_TYPE_DIRECTORY)) { MRET(child) = child; return OBJECT_OK; } @@ -48,6 +49,8 @@ ObjectResult obj_opendir( Object *child; ObjectResult result = obj_search(parent, &child, name, true); if (result == OBJECT_OK) { + Permission *permission = get_permission_info(child); + if (!permission->permission.execute) return OBJECT_ERROR_NO_PERMISSION; MRET(child) = child; child->reference++; return OBJECT_OK; @@ -56,8 +59,12 @@ ObjectResult obj_opendir( else if (parent->fs_info != NULL) { FsResult result = parent->fs_info->dir_ops.fs_opendir( parent->fs_info, parent->value.directory.data, name, &MRET(child)); + if (result != FS_OK) return OBJECT_ERROR_CANNOT_FIND; + ObjectAttr attr; + obj_get_attr(child, &attr); + Permission *permission = get_permission_info(child); + if (!permission->permission.execute) return OBJECT_ERROR_NO_PERMISSION; child->reference++; - if (result == FS_OK) return OBJECT_OK; } return OBJECT_ERROR_CANNOT_FIND; } @@ -66,11 +73,11 @@ ObjectResult obj_close(Object *object) { object->reference--; if (object->reference > 0) return OBJECT_OK; if (object->fs_info == NULL) return OBJECT_OK; - if (!object->is_mounted && !object->fixed) { + if (!object->attr.is_mounted) { if (object->release_data != NULL) object->release_data(object); - if (object->type == OBJECT_TYPE_FILE) { + if (object->attr.type == OBJECT_TYPE_FILE) { object->fs_info->file_ops.fs_close(object); - } else if (object->type == OBJECT_TYPE_DIRECTORY) { + } else if (object->attr.type == OBJECT_TYPE_DIRECTORY) { object->fs_info->dir_ops.fs_closedir(object); } list_del(&object->list); @@ -93,13 +100,15 @@ ObjectResult obj_create_file(Object *parent, string_t name) { } ObjectResult obj_delete_file(Object *parent, string_t name) { - Object *child; - ObjectResult result = obj_search(parent, &child, name, false); - if (result == OBJECT_OK) { - if (child->reference > 0) return OBJECT_ERROR_OCCUPIED; - if (child->fixed) return OBJECT_ERROR_FIXED; - result = obj_close(child); - } + Object *child; + // 先打开文件检查权限,再决定要不要删除 + OBJ_RESULT_PASS(obj_open(parent, &child, name)); + + if (child->reference > 0) return OBJECT_ERROR_OCCUPIED; + Permission *permission = get_permission_info(child); + if (!permission->permission.delete) return OBJECT_ERROR_NO_PERMISSION; + OBJ_RESULT_PASS(obj_close(child)); + if (parent->fs_info != NULL) { FsResult result = parent->fs_info->dir_ops.fs_delete_file(parent, name); if (result != FS_OK) return OBJECT_ERROR_OTHER; @@ -121,20 +130,42 @@ ObjectResult obj_mkdir(Object *parent, string_t name) { } ObjectResult obj_rmdir(Object *parent, string_t name) { - Object *child; - ObjectResult result = obj_search(parent, &child, name, true); + Object *child; + // 先打开检查权限,再决定要不要删除 + OBJ_RESULT_PASS(obj_open(parent, &child, name)); + + if (child->reference > 0) return OBJECT_ERROR_OCCUPIED; + Permission *permission = get_permission_info(child); + if (!permission->permission.delete) return OBJECT_ERROR_NO_PERMISSION; + if (!child->attr.is_mounted) return OBJECT_ERROR_OCCUPIED; + if (!list_empty(&child->value.directory.children)) + return OBJECT_ERROR_NOT_EMPTY; + + OBJ_RESULT_PASS(obj_close(child)); + if (parent->fs_info != NULL) { FsResult result = parent->fs_info->dir_ops.fs_rmdir(parent, name); + if (result == FS_OK) return OBJECT_OK; + else if (result == FS_ERROR_NOT_EMPTY) return OBJECT_ERROR_NOT_EMPTY; + else return OBJECT_ERROR_OTHER; + } + return OBJECT_OK; +} + +ObjectResult obj_get_attr(Object *object, ObjectAttr *attr) { + // 在打开object时会自动生成attr,直接复制即可 + *attr = object->attr; + return OBJECT_OK; +} + +ObjectResult obj_set_attr(Object *object, ObjectAttr *attr) { + Permission *permission = get_permission_info(object); + if (!permission->permission.set_attr) return OBJECT_ERROR_NO_PERMISSION; + + if (object->fs_info != NULL) { + FsResult result = object->fs_info->dir_ops.fs_set_attr(object, attr); if (result != FS_OK) return OBJECT_ERROR_OTHER; - } else { - if (result != OBJECT_OK) return OBJECT_ERROR_CANNOT_FIND; - if (child->fixed) return OBJECT_ERROR_FIXED; - if (!child->is_mounted) return OBJECT_ERROR_OCCUPIED; - if (child->reference > 0) return OBJECT_ERROR_OCCUPIED; - if (!list_empty(&child->value.directory.children)) - return OBJECT_ERROR_NOT_EMPTY; - list_del(&child->list); - kfree(child); } - return result; + object->attr = *attr; + return OBJECT_OK; } diff --git a/src/objects/permission.c b/src/objects/permission.c new file mode 100644 index 0000000..3afcb4e --- /dev/null +++ b/src/objects/permission.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include +#include + +Permission *get_permission_info(Object *object) { + size_t subject_id = get_current_subject_id(); + if (subject_id == SUBJECT_ID_SYSTEM) { + return &object->attr.system_permission; + } else if (subject_id == object->attr.owner_id) { + return &object->attr.owner_permission; + } else { + Permission *permission; + list_for_each_owner (permission, &object->attr.permission_lh, list) { + if (permission->subject_id == subject_id) return permission; + } + } + return NULL; +} \ No newline at end of file diff --git a/src/objects/types.c b/src/objects/types.c index 44d4352..7ebe5d4 100644 --- a/src/objects/types.c +++ b/src/objects/types.c @@ -1,14 +1,14 @@ -#include "kernel/list.h" #include #include +#include #include static int type_number = OBJECT_TYPE_BUILTIN_MAX; -#define DEFINE_OBJECT_TYPE(type_name) \ - { \ - .name = STRING_INIT(#type_name), .type = OBJECT_TYPE_TYPE, \ - .value.type = OBJECT_TYPE_##type_name \ +#define DEFINE_OBJECT_TYPE(type_name) \ + { \ + .name = STRING_INIT(#type_name), \ + .value.type = OBJECT_TYPE_##type_name, .attr = base_obj_sys_attr, \ } Object object_builtin_types[OBJECT_TYPE_BUILTIN_MAX] = { @@ -20,7 +20,7 @@ Object object_builtin_types[OBJECT_TYPE_BUILTIN_MAX] = { Object object_type_directory = { .name = STRING_INIT("ObjectType"), - .type = OBJECT_TYPE_DIRECTORY, + .attr = base_obj_sys_attr, }; ObjectResult init_builtin_types() { @@ -36,7 +36,7 @@ ObjectResult init_builtin_types() { Object *create_object_type(string_t name) { Object *object = - create_object(&object_type_directory, name, OBJECT_TYPE_TYPE); + create_object(&object_type_directory, name, base_obj_sys_attr); if (object == NULL) { return NULL; } object->value.type = type_number - 1; From fd272c3ddfc00b602f54768b5722a24870ef3351 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 9 Mar 2025 19:27:16 +0800 Subject: [PATCH 031/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20readdir=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=9B=20=E4=BF=AE=E5=A4=8D=20FAT=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=8D=E5=A4=84=E7=90=86=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fs/fat/dir.c | 299 ++++++++++++++++++++++------------- src/fs/fat/entry.c | 31 ++-- src/fs/fat/fat.c | 98 +++++++++--- src/fs/fat/include/cluster.h | 33 ++-- src/fs/fat/include/dir.h | 34 +++- src/fs/fat/include/fat.h | 14 ++ src/fs/fat/include/name.h | 3 + src/fs/fat/name.c | 73 +++++---- src/include/fs/fs.h | 12 +- src/include/objects/object.h | 11 ++ src/include/objects/ops.h | 5 +- src/kernel/main.c | 11 +- src/objects/objects.c | 78 +++++---- src/objects/ops.c | 77 ++++++--- 14 files changed, 521 insertions(+), 258 deletions(-) diff --git a/src/fs/fat/dir.c b/src/fs/fat/dir.c index 2bd9cac..c3cc540 100644 --- a/src/fs/fat/dir.c +++ b/src/fs/fat/dir.c @@ -3,6 +3,7 @@ #include "include/entry.h" #include "include/fat.h" #include "include/name.h" +#include "multiple_return.h" #include "types.h" #include #include @@ -11,148 +12,232 @@ #include #include -typedef struct FatCurrentEntry { - FatDirEntry *entry; - CurrentCluster cur_cluster; - int number; -} FatCurrentEntry; - -static inline void fat_first_entry( - FatInfo *fat_info, FatCurrentEntry *entry, int number) { - entry->number = number; - int index = number / fat_info->entry_per_cluster; - fat_cluster_list_get(fat_info, entry->entry, index, &entry->cur_cluster); +void fat_dir_iterator_init( + FatDirIterator *iter, FatInfo *fat_info, FatDirEntry *dir) { + iter->fat_info = fat_info; + iter->dir_entry = dir; + fat_cluster_list_get(fat_info, dir, 0, &iter->current_cluster); + iter->entry_index = 0; + if (fat_info->use_longname) { + iter->longname_buf = kmalloc(MAX_LONGNAME * sizeof(uint16_t)); + } else { + iter->longname_buf = NULL; + } + iter->longname_len = 0; + iter->checksum = 0; + iter->longname_valid = false; + iter->longname_cluster = iter->current_cluster.cluster; + iter->longname_entry_index = 0; + iter->last_cluster = 0; + iter->last_entry_index = 0; } -static inline FsResult fat_next_entry( - FatInfo *fat_info, FatCurrentEntry *entry) { - entry->number++; - if (entry->number == fat_info->entry_per_cluster) { - entry->number = 0; - FS_RESULT_PASS(fat_cluster_list_get_next( - fat_info, entry->entry, &entry->cur_cluster)); - if (entry->cur_cluster.cluster >= 0x0fffffff) - return FS_ERROR_END_OF_FILE; - } - return FS_OK; +void fat_dir_iterator_destroy(FatDirIterator *iter) { + if (iter->longname_buf != NULL) kfree(iter->longname_buf); } -static inline void fat_read_current_entry( - FatInfo *fat_info, FatCurrentEntry *entry, uint8_t *buf) { - fat_entry_read( - fat_info, entry->entry, entry->cur_cluster.cluster, entry->number, buf); +static inline FsResult fat_read_entry(FatDirIterator *iter, uint8_t *buf) { + return fat_entry_read( + iter->fat_info, iter->dir_entry, iter->current_cluster.cluster, + iter->entry_index, buf); } -// 扫描目录项 -// mode = 0 : 匹配目录项 -// mode = 1 : 扫描所有目录项 -FsResult fat32_read_dir_entry( - FatCurrentEntry *cur_entry, string_t *name, uint8_t *buf, - uint16_t *utf16_name, uint16_t **_utf16_name, int *utf16_length, - uint32_t *longname_cluster, int *longname_number) { - ShortDir *short_dir = (ShortDir *)buf; - if (short_dir->name.base[0] == 0x00) return FS_ERROR_CANNOT_FIND; - if (buf[0] == 0xe5 || buf[0] == 0x05) return FS_ERROR_NOT_MATCH; - - LongDir *long_dir = (LongDir *)buf; - if (long_dir->attr == ATTR_LONG_NAME) { - if (long_dir->order & 0x40) { - int count = long_dir->order & 0x3f; - *longname_cluster = cur_entry->cur_cluster.cluster; - *longname_number = cur_entry->number; - *_utf16_name = utf16_name + (count - 1) * 13; - *utf16_length = 0; +static inline bool is_long_entry(ShortDir *short_dir) { + return short_dir->attr == ATTR_LONG_NAME; +} + +PRIVATE void process_long_entry( + FatDirIterator *iter, uint32_t current_cluster, int current_entry_index, + LongDir *entry) { + // 检查顺序标识 + uint8_t order = entry->order & 0x3F; + if (order == 0) return; + + // 起始条目初始化缓冲区 + if (entry->order & 0x40) { + iter->longname_len = 0; + iter->checksum = entry->checksum; + iter->longname_cluster = current_cluster; + iter->longname_entry_index = current_entry_index; + iter->longname_valid = true; + } + + iter->longname_len += + read_long_name(entry, iter->longname_buf + (order - 1) * 13); +} + +PRIVATE FsResult process_short_entry( + FatDirIterator *iter, ShortDir *short_dir, uint32_t current_cluster, + int current_entry_index, DEF_MRET(string_t, name)) { + // 验证长名校验和 + if (iter->longname_len > 0) { + if (fat_checksum(&short_dir->name) != iter->checksum) { + iter->longname_len = 0; } - *utf16_length += read_long_name(long_dir, *_utf16_name); - *_utf16_name -= 13; - } else if (*utf16_length > 0) { - fat_utf16_to_utf8(utf16_name, *utf16_length + 1, name); + } + + // 生成文件名 + if (iter->longname_valid) { + fat_utf16_to_utf8(iter->longname_buf, iter->longname_len, &MRET(name)); } else { - if (short_dir->name.base[0] == '.') return FS_ERROR_NOT_MATCH; - *name = read_short_name(short_dir); + MRET(name) = read_short_name(short_dir); } + // 重置长名状态 + iter->longname_len = 0; + iter->longname_valid = false; + return FS_OK; } -FsResult search_dir( - FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, - bool is_directory, FatDirEntry **out_entry, int mode) { - FatCurrentEntry cur_entry; - cur_entry.entry = parent_entry; - - FatDirEntry *tmp_entry; +FsResult fat32_read_dir_entry( + FatDirIterator *iter, DEF_MRET(string_t, name), + DEF_MRET(ShortDir, short_dir)) { + uint8_t entry_buf[32]; + ShortDir *short_dir = (ShortDir *)entry_buf; + LongDir *long_dir; + + while (1) { + // 读取当前条目 + FS_RESULT_PASS(fat_read_entry(iter, entry_buf)); + iter->last_cluster = iter->current_cluster.cluster; + iter->last_entry_index = iter->entry_index; + // 读取完立即更新索引 + if (++iter->entry_index >= iter->fat_info->entry_per_cluster) { + // 获取下一个簇 + uint32_t next = fat_cluster_list_get_next( + iter->fat_info, iter->dir_entry, &iter->current_cluster); + if (is_eof(iter->fat_info, next)) return FS_ERROR_CANNOT_FIND; + iter->entry_index = 0; + } - uint8_t buf[0x20]; + // 处理目录结束标记 + if (entry_buf[0] == 0x00) return FS_ERROR_CANNOT_FIND; + // 跳过已删除条目 + if (entry_buf[0] == 0xE5) continue; + + if (is_long_entry(short_dir)) { + // 处理长文件名条目 + long_dir = (LongDir *)entry_buf; + process_long_entry( + iter, iter->last_cluster, iter->last_entry_index, long_dir); + } else { + MRET(short_dir) = *short_dir; + // 处理短文件名条目 + return process_short_entry( + iter, short_dir, iter->last_cluster, iter->last_entry_index, + &MRET(name)); + } + } +} +FsResult fat_read_dir_entry( + FatDirIterator *iter, DEF_MRET(string_t, name), + DEF_MRET(ShortDir, short_dir)) { + uint8_t entry_buf[32]; ShortDir *short_dir; - uint16_t *utf16_name = kmalloc(256 * sizeof(uint16_t)), *_utf16_name; - int utf16_length = 0; - uint32_t longname_cluster; - int longname_number; + uint32_t current_cluster; + int current_entry_index; + + while (1) { + // 读取当前条目 + FS_RESULT_PASS(fat_read_entry(iter, entry_buf)); + current_cluster = iter->current_cluster.cluster; + current_entry_index = iter->entry_index; + // 读取完立即更新索引 + if (++iter->entry_index >= iter->fat_info->entry_per_cluster) { + // 跳转到下一个簇 + uint32_t next = fat_cluster_list_get_next( + iter->fat_info, iter->dir_entry, &iter->current_cluster); + if (is_eof(iter->fat_info, next)) return FS_ERROR_CANNOT_FIND; + iter->entry_index = 0; + } - FsResult result; - FsResult _result = FS_OK; + short_dir = (ShortDir *)entry_buf; - string_t _name; + // 处理目录结束标记 + if (entry_buf[0] == 0x00) return FS_ERROR_CANNOT_FIND; - fat_first_entry(fat_info, &cur_entry, 0); - for (; _result == FS_OK; _result = fat_next_entry(fat_info, &cur_entry)) { - fat_read_current_entry(fat_info, &cur_entry, buf); - result = fat32_read_dir_entry( - &cur_entry, &_name, buf, utf16_name, &_utf16_name, &utf16_length, - &longname_cluster, &longname_number); + // 跳过已删除条目 + if (entry_buf[0] == 0xE5) continue; - if (result == FS_ERROR_NOT_MATCH) continue; - else if (result == FS_ERROR_CANNOT_FIND) break; + // 处理短文件名条目 + MRET(short_dir) = *short_dir; + return process_short_entry( + iter, short_dir, current_cluster, current_entry_index, &MRET(name)); + } +} - short_dir = (ShortDir *)buf; - if (utf16_length == 0) { - // 为短文件名 - longname_cluster = 0; - longname_number = 0; - } - if (short_dir->attr != ATTR_LONG_NAME) { - tmp_entry = generate_dir_entry( - fat_info, parent_entry, (ShortDir *)buf, _name, is_directory, - cur_entry.cur_cluster.cluster, cur_entry.number, - longname_cluster, longname_number); +FsResult fat32_search_dir( + FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, + bool is_directory, DEF_MRET(FatDirEntry *, entry)) { + FatDirIterator iter; + string_t _name; + ShortDir *short_dir = NULL; + fat_dir_iterator_init(&iter, fat_info, parent_entry); + while (fat32_read_dir_entry(&iter, &_name, short_dir) == FS_OK) { + if (is_directory && !(short_dir->attr & ATTR_DIRECTORY)) continue; + if (!is_directory && (short_dir->attr & ATTR_DIRECTORY)) continue; + if (strncmp(_name.text, name.text, name.length) == 0) { + fat_dir_iterator_destroy(&iter); + MRET(entry) = generate_dir_entry( + fat_info, parent_entry, short_dir, name, is_directory, + iter.last_cluster, iter.last_entry_index, iter.longname_cluster, + iter.longname_entry_index); + return FS_OK; } + } + fat_dir_iterator_destroy(&iter); + return FS_ERROR_CANNOT_FIND; +} - if (is_directory && (short_dir->attr & ATTR_DIRECTORY) == 0) continue; - if (!is_directory && (short_dir->attr & ATTR_DIRECTORY) != 0) continue; - - if (mode == 0 && strncmp(_name.text, name.text, _name.length) == 0) { - *out_entry = tmp_entry; - - parent_entry->new_entry_number = cur_entry.number + 1; - result = FS_OK; - break; +FsResult fat_search_dir( + FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, + bool is_directory, DEF_MRET(FatDirEntry *, entry)) { + FatDirIterator iter; + string_t _name; + ShortDir *short_dir = NULL; + + fat_dir_iterator_init(&iter, fat_info, parent_entry); + while (fat_read_dir_entry(&iter, &_name, short_dir) == FS_OK) { + if (is_directory && !(short_dir->attr & ATTR_DIRECTORY)) continue; + if (!is_directory && (short_dir->attr & ATTR_DIRECTORY)) continue; + if (strncmp(_name.text, name.text, name.length) == 0) { + fat_dir_iterator_destroy(&iter); + MRET(entry) = generate_dir_entry( + fat_info, parent_entry, short_dir, name, is_directory, + iter.last_cluster, iter.last_entry_index, iter.longname_cluster, + iter.longname_entry_index); + return FS_OK; } } - kfree(utf16_name); - return result; + fat_dir_iterator_destroy(&iter); + return FS_ERROR_CANNOT_FIND; } bool fat_dir_is_empty(FatInfo *fat_info, FatDirEntry *parent_entry) { - FatCurrentEntry cur_entry; - cur_entry.entry = parent_entry; + FatDirIterator iter; - uint8_t buf[0x20]; - ShortDir *short_dir = (ShortDir *)buf; + uint8_t entry_buf[0x20]; + ShortDir *short_dir = (ShortDir *)entry_buf; - FsResult _result = FS_OK; + FsResult result = FS_OK; - fat_first_entry(fat_info, &cur_entry, 0); - for (; _result == FS_OK; _result = fat_next_entry(fat_info, &cur_entry)) { - fat_read_current_entry(fat_info, &cur_entry, buf); + fat_dir_iterator_init(&iter, fat_info, parent_entry); + while (1) { + result = fat_read_entry(&iter, entry_buf); + if (result != FS_OK) break; - if (buf[0] == 0xe5 || buf[0] == 0x05) continue; + if (entry_buf[0] == 0xe5 || entry_buf[0] == 0x05) continue; if (short_dir->attr == ATTR_LONG_NAME) continue; - if (buf[0] == '.') continue; + if (entry_buf[0] == '.') continue; - if (buf[0] != 0) return false; + if (entry_buf[0] != 0) { + fat_dir_iterator_destroy(&iter); + return false; + } } + fat_dir_iterator_destroy(&iter); return true; } diff --git a/src/fs/fat/entry.c b/src/fs/fat/entry.c index 1054172..d0a51bc 100644 --- a/src/fs/fat/entry.c +++ b/src/fs/fat/entry.c @@ -123,31 +123,34 @@ PRIVATE FsResult fat_longname_entry_write( long_dir.checksum = checksum; long_dir.first_cluster = 0; long_dir.type = 0; + + uint16_t *p = utf16_name + (longdir_count - 1) * 13; for (int i = 0; i < longdir_count; i++) { long_dir.order = longdir_count - i; if (i == 0) { + long_dir.order |= 0x40; + int j = 0, k; int len = len16 % 13; - for (int j = 0; j < 5; j++) { - if (j < len) long_dir.name1[j] = utf16_name[j]; - else long_dir.name1[j] = 0xffff; + for (k = 0; k < 5; j++, k++) { + if (j < len) long_dir.name1[k] = p[j]; + else long_dir.name1[k] = 0xffff; } - for (int j = 0; j < 6; j++) { - if (j < len) long_dir.name2[j] = utf16_name[j + 5]; - else long_dir.name2[j] = 0xffff; + for (k = 0; k < 6; j++, k++) { + if (j < len) long_dir.name2[k] = p[j]; + else long_dir.name2[k] = 0xffff; } - for (int j = 0; j < 3; j++) { - if (j < len) long_dir.name3[j] = utf16_name[j + 11]; - else long_dir.name3[j] = 0xffff; + for (j = 0; j < 2; j++) { + if (j < len) long_dir.name3[k] = p[j]; + else long_dir.name3[k] = 0xffff; } } else { - memcpy(long_dir.name1, utf16_name, 5 * sizeof(uint16_t)); - memcpy(long_dir.name2, utf16_name + 5, 6 * sizeof(uint16_t)); - memcpy(long_dir.name3, utf16_name + 11, 2 * sizeof(uint16_t)); + memcpy(long_dir.name1, p, 5 * sizeof(uint16_t)); + memcpy(long_dir.name2, p + 5, 6 * sizeof(uint16_t)); + memcpy(long_dir.name3, p + 11, 2 * sizeof(uint16_t)); } - if (i == longdir_count - 1) long_dir.order |= 0x40; FS_RESULT_PASS(fat_entry_write( fat_info, parent_entry, *cluster, *number, (uint8_t *)&long_dir)); - utf16_name += 13; + p -= 13; *number = fat_increase_new_entry_number(fat_info, parent_entry, cluster); diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c index 56d4009..a288dbd 100644 --- a/src/fs/fat/fat.c +++ b/src/fs/fat/fat.c @@ -21,17 +21,19 @@ FsResult fat_check(Partition *partition); FsResult fat_mount(FileSystemInfo *fs_info, Object *root_object); FsResult fat_open( - FileSystemInfo *fs_info, void *parent, string_t name, Object **object); + FileSystemInfo *fs_info, Object *parent_obj, string_t name, + Object **object); FsResult fat_close(Object *object); FsResult fat_seek(Object *object, size_t offset); FsResult fat_read(Object *file, void *buf, size_t size); FsResult fat_write(Object *file, void *buf, size_t size); FsResult fat_opendir( - FileSystemInfo *fs_info, void *parent, string_t name, Object **object); -FsResult fat_closedir(Object *object); -FsResult fat_create_file(Object *directory, string_t name, Object **object); -FsResult fat_delete_file(Object *directory, string_t name); + FileSystemInfo *fs_info, Object *parent_obj, void **iterator); +FsResult fat_readdir(FileSystemInfo *fs_info, void *iterator, Object **object); +FsResult fat_closedir(void *iterator); +FsResult fat_create_file(Object *parent_obj, string_t name, Object **object); +FsResult fat_delete_file(Object *parent_obj, string_t name); FsResult fat_mkdir(Object *parent_obj, string_t name, Object **object); FsResult fat_rmdir(Object *parent_obj, string_t name); FsResult fat_get_attr(Object *object, ObjectAttr *attr); @@ -54,6 +56,7 @@ FsFileOps fat_file_ops = { FsDirectoryOps fat_dir_ops = { .fs_opendir = fat_opendir, + .fs_readdir = fat_readdir, .fs_closedir = fat_closedir, .fs_create_file = fat_create_file, .fs_delete_file = fat_delete_file, @@ -68,6 +71,15 @@ FileSystem fat_fs = { .ops = &fat_ops, }; +FatPrivOps fat32_priv_ops = { + .fat_search_dir = fat32_search_dir, + .fat_read_dir_entry = fat32_read_dir_entry, +}; +FatPrivOps fat_priv_ops = { + .fat_search_dir = fat_search_dir, + .fat_read_dir_entry = fat_read_dir_entry, +}; + FatType fat_type_determine(FatInfo *fat_info); FsResult fat_check(Partition *partition) { @@ -163,31 +175,30 @@ FatType fat_type_determine(FatInfo *fat_info) { fat_info->data_sectors / fat_info->bpb->BPB_SecPerClus; if (count_of_cluster < 4085) { + fat_info->max_cluster = 0xFF8; + fat_info->ops = &fat_priv_ops; return FAT_TYPE_FAT12; } else if (count_of_cluster < 65525) { + fat_info->max_cluster = 0xFFF8; + fat_info->ops = &fat_priv_ops; return FAT_TYPE_FAT16; } else { + fat_info->max_cluster = 0x0FFFFFF8; + fat_info->ops = &fat32_priv_ops; + fat_info->use_longname = true; return FAT_TYPE_FAT32; } } FsResult fat_open( - FileSystemInfo *fs_info, void *parent, string_t name, Object **object) { + FileSystemInfo *fs_info, Object *parent_obj, string_t name, + Object **object) { FatInfo *fat_info = fs_info->private_data; FatDirEntry *entry; - FsResult result = search_dir(fat_info, parent, name, false, &entry, 0); - *object = entry->object; - return result; -} - -FsResult fat_opendir( - FileSystemInfo *fs_info, void *parent, string_t name, Object **object) { - FatInfo *fat_info = fs_info->private_data; - FatDirEntry *entry; - - FsResult result = search_dir(fat_info, parent, name, true, &entry, 0); - *object = entry->object; + FsResult result = fat_info->ops->fat_search_dir( + fat_info, parent_obj->value.directory.data, name, false, &entry); + *object = entry->object; return result; } @@ -200,8 +211,43 @@ FsResult fat_close(Object *object) { return FS_OK; } -FsResult fat_closedir(Object *object) { - return fat_close(object); +FsResult fat_opendir( + FileSystemInfo *fs_info, Object *parent_obj, void **iterator) { + FatInfo *fat_info = fs_info->private_data; + FatDirEntry *parent = parent_obj->value.directory.data; + + *iterator = kmalloc(sizeof(FatDirIterator)); + if (fat_info->type == FAT_TYPE_FAT32) { + fat_dir_iterator_init(*iterator, fat_info, parent); + } else { + fat_dir_iterator_init(*iterator, fat_info, parent); + } + return FS_OK; +} + +FsResult fat_readdir(FileSystemInfo *fs_info, void *iterator, Object **object) { + FatInfo *fat_info = fs_info->private_data; + FatDirEntry *entry; + string_t name; + ShortDir *short_dir = NULL; + FatDirIterator *iter = iterator; + + FS_RESULT_PASS( + fat_info->ops->fat_read_dir_entry(iterator, &name, short_dir)); + entry = generate_dir_entry( + fat_info, iter->dir_entry, short_dir, name, + short_dir->attr & ATTR_DIRECTORY, iter->last_cluster, + iter->last_entry_index, iter->longname_cluster, + iter->longname_entry_index); + + *object = entry->object; + return FS_OK; +} + +FsResult fat_closedir(void *iterator) { + fat_dir_iterator_destroy(iterator); + kfree(iterator); + return FS_OK; } FsResult fat_seek(Object *object, size_t offset) { @@ -275,7 +321,8 @@ FsResult fat_create_file(Object *parent_obj, string_t name, Object **object) { FatInfo *fat_info = parent_obj->fs_info->private_data; FatDirEntry *entry, *parent = parent_obj->value.directory.data; - FsResult result = search_dir(fat_info, parent, name, false, &entry, 0); + FsResult result = + fat_info->ops->fat_search_dir(fat_info, parent, name, false, &entry); if (result == FS_OK) { return FS_ERROR_ALREADY_EXISTS; } fat_create_entry(fat_info, parent, name, false, &entry); @@ -288,7 +335,8 @@ FsResult fat_delete_file(Object *parent_obj, string_t name) { FatInfo *fat_info = parent_obj->fs_info->private_data; FatDirEntry *entry, *parent = parent_obj->value.directory.data; - FsResult result = search_dir(fat_info, parent, name, false, &entry, 0); + FsResult result = + fat_info->ops->fat_search_dir(fat_info, parent, name, false, &entry); if (result != FS_OK) { return result; } fat_delete_entry(fat_info, parent, entry, name); @@ -299,7 +347,8 @@ FsResult fat_mkdir(Object *parent_obj, string_t name, Object **object) { FatInfo *fat_info = parent_obj->fs_info->private_data; FatDirEntry *entry, *parent = parent_obj->value.directory.data; - FsResult result = search_dir(fat_info, parent, name, true, &entry, 0); + FsResult result = + fat_info->ops->fat_search_dir(fat_info, parent, name, true, &entry); if (result == FS_OK) { return FS_ERROR_ALREADY_EXISTS; } fat_create_entry(fat_info, parent, name, true, &entry); @@ -312,7 +361,8 @@ FsResult fat_rmdir(Object *parent_obj, string_t name) { FatInfo *fat_info = parent_obj->fs_info->private_data; FatDirEntry *entry, *parent = parent_obj->value.directory.data; - FsResult result = search_dir(fat_info, parent, name, true, &entry, 0); + FsResult result = + fat_info->ops->fat_search_dir(fat_info, parent, name, true, &entry); if (result != FS_OK) { return result; } if (!fat_dir_is_empty(fat_info, entry)) return FS_ERROR_NOT_EMPTY; diff --git a/src/fs/fat/include/cluster.h b/src/fs/fat/include/cluster.h index b3f9d88..0971d5b 100644 --- a/src/fs/fat/include/cluster.h +++ b/src/fs/fat/include/cluster.h @@ -1,10 +1,10 @@ #ifndef _FAT_CLUSTER_H #define _FAT_CLUSTER_H -#include "dir.h" #include "dyn_array.h" -#include "fat.h" #include "fs/fs.h" +#include "kernel/block_cache.h" +#include #include #include @@ -20,30 +20,37 @@ typedef struct CurrentCluster { DynArrayBlock *block; } CurrentCluster; -uint32_t cluster2sector(FatInfo *fat_info, uint32_t cluster); +struct FatInfo; +struct FatDirEntry; +uint32_t cluster2sector(struct FatInfo *fat_info, uint32_t cluster); FsResult fat_table_read( BlockCacheEntry *entry, size_t cache_size, void *private_data); FsResult fat_table_write( BlockCacheEntry *entry, size_t cache_size, void *private_data); -uint32_t get_next_cluster(FatInfo *fat_info, uint32_t clus); -void set_cluster(FatInfo *fat_info, uint32_t cluster, uint32_t data); +uint32_t get_next_cluster(struct FatInfo *fat_info, uint32_t clus); +void set_cluster(struct FatInfo *fat_info, uint32_t cluster, uint32_t data); FsResult alloc_cluster( - FatInfo *fat_info, uint32_t last_cluster, bool is_first_cluster, + struct FatInfo *fat_info, uint32_t last_cluster, bool is_first_cluster, uint32_t *out_clus); -FsResult free_cluster(FatInfo *fat_info, uint32_t cluster, uint32_t *out_clus); -bool is_eof(FatInfo *fat_info, uint32_t clus); -FsResult get_cluster_segment(FatInfo *fat_info, FatDirEntry *entry); +FsResult free_cluster( + struct FatInfo *fat_info, uint32_t cluster, uint32_t *out_clus); +bool is_eof(struct FatInfo *fat_info, uint32_t clus); +FsResult get_cluster_segment( + struct FatInfo *fat_info, struct FatDirEntry *entry); FsResult fat_cluster_list_get( - FatInfo *fat_info, FatDirEntry *entry, uint32_t index, + struct FatInfo *fat_info, struct FatDirEntry *entry, uint32_t index, CurrentCluster *cur_cluster); FsResult fat_cluster_list_get_next( - FatInfo *fat_info, FatDirEntry *entry, CurrentCluster *cur_cluster); + struct FatInfo *fat_info, struct FatDirEntry *entry, + CurrentCluster *cur_cluster); inline bool fat_cluster_list_is_last( - FatInfo *fat_info, FatDirEntry *entry, CurrentCluster *cur_cluster); + struct FatInfo *fat_info, struct FatDirEntry *entry, + CurrentCluster *cur_cluster); FsResult get_last_cluster( - FatInfo *fat_info, FatDirEntry *entry, DEF_MRET(uint32_t, last_cluster)); + struct FatInfo *fat_info, struct FatDirEntry *entry, + DEF_MRET(uint32_t, last_cluster)); #endif \ No newline at end of file diff --git a/src/fs/fat/include/dir.h b/src/fs/fat/include/dir.h index b0f56f7..fff6126 100644 --- a/src/fs/fat/include/dir.h +++ b/src/fs/fat/include/dir.h @@ -1,6 +1,7 @@ #ifndef _FAT_DIR_H #define _FAT_DIR_H +#include "cluster.h" #include "dyn_array.h" #include "fs/fs.h" #include "kernel/block_cache.h" @@ -73,9 +74,38 @@ typedef struct FatDirEntry { } FatDirEntry; struct FatInfo; -FsResult search_dir( +typedef struct FatDirIterator { + struct FatInfo *fat_info; // 文件系统信息 + FatDirEntry *dir_entry; // 当前遍历的目录项 + CurrentCluster current_cluster; // 当前簇号 + int entry_index; // 当前簇内条目索引 + uint16_t *longname_buf; // 长文件名缓存(UTF-16) + int longname_len; // 当前累积的长名长度 + uint8_t checksum; // 长名校验和 + bool longname_valid; // 长名有效性标志 + uint32_t longname_cluster; // 长名所在簇号 + int longname_entry_index; // 长名所在簇内条目索引 + uint32_t last_cluster; // 上一个簇号 + int last_entry_index; // 上一个簇内条目索引 +} FatDirIterator; + +struct FatInfo; + +void fat_dir_iterator_init( + FatDirIterator *iter, struct FatInfo *fat, FatDirEntry *dir); +void fat_dir_iterator_destroy(FatDirIterator *iter); +FsResult fat32_read_dir_entry( + FatDirIterator *iter, DEF_MRET(string_t, name), + DEF_MRET(ShortDir, short_dir)); +FsResult fat_read_dir_entry( + FatDirIterator *iter, DEF_MRET(string_t, name), + DEF_MRET(ShortDir, short_dir)); +FsResult fat32_search_dir( + struct FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, + bool is_directory, DEF_MRET(FatDirEntry *, entry)); +FsResult fat_search_dir( struct FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, - bool match_directory, FatDirEntry **out_entry, int mode); + bool is_directory, DEF_MRET(FatDirEntry *, entry)); void entry_cache_init( struct FatInfo *fat_info, FatDirEntry *entry, size_t cache_size); bool fat_dir_is_empty(struct FatInfo *fat_info, FatDirEntry *parent_entry); diff --git a/src/fs/fat/include/fat.h b/src/fs/fat/include/fat.h index 7124f89..88c1c8f 100644 --- a/src/fs/fat/include/fat.h +++ b/src/fs/fat/include/fat.h @@ -4,6 +4,7 @@ #include "dir.h" #include "driver/storage/disk/disk.h" #include "driver/storage/storage_dm.h" +#include "fs/fs.h" #include "kernel/block_cache.h" #include @@ -87,6 +88,10 @@ typedef struct FatInfo { int sector_per_cluster; int entry_per_cluster; int num_count; + int max_cluster; + bool use_longname; + + struct FatPrivOps *ops; BlockCache *fat_table_cache; @@ -95,4 +100,13 @@ typedef struct FatInfo { FatDirEntry root_entry; } FatInfo; +typedef struct FatPrivOps { + FsResult (*fat_search_dir)( + struct FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, + bool is_directory, DEF_MRET(FatDirEntry *, entry)); + FsResult (*fat_read_dir_entry)( + FatDirIterator *iter, DEF_MRET(string_t, name), + DEF_MRET(ShortDir, short_dir)); +} FatPrivOps; + #endif \ No newline at end of file diff --git a/src/fs/fat/include/name.h b/src/fs/fat/include/name.h index 277ff70..fc1625a 100644 --- a/src/fs/fat/include/name.h +++ b/src/fs/fat/include/name.h @@ -4,6 +4,8 @@ #include "fs/fs.h" #include "multiple_return.h" +#define MAX_LONGNAME 256 + typedef struct ShortName { char base[8]; char ext[3]; @@ -22,6 +24,7 @@ struct ShortDir; struct LongDir; int check_name_caps(uint8_t *name, int len); bool is_available_short_name_char(uint8_t c); +bool check_short_name(uint8_t *text, int len, int dot); NameType check_name(enum FatType type, uint8_t *text, int len); FsResult short_name_new(string_t name, ShortName *short_name); uint8_t fat_checksum(ShortName *short_name); diff --git a/src/fs/fat/name.c b/src/fs/fat/name.c index ceb578b..ec517fc 100644 --- a/src/fs/fat/name.c +++ b/src/fs/fat/name.c @@ -203,7 +203,7 @@ string_t read_short_name(ShortDir *short_dir) { name.text[j++] = '.'; for (x = 0; x < 3; x++) { char c = short_dir->name.ext[x]; - if (c == ' ') { + if (c != ' ') { if ('A' <= c && c <= 'Z') { name.text[j++] = (short_dir->nt_res & FAT32_EXT_L) ? c + 32 : c; } else { @@ -233,41 +233,51 @@ FsResult long_name2short_name( int ext_name_len = 0; char tmp_name[12] = " "; - int i, j; - for (i = 0, j = 0; i < 8; i++) { + int i, j, k; + uint8_t c; + char *q; + for (i = 0, j = 0, k = 0; k < 8; k++) { if (i < dot) { - if (is_available_short_name_char(text[i])) { - if ('a' <= text[i] && text[i] <= 'z') - short_name->base[j] = text[i] - 32; - else short_name->base[j] = text[i]; - } else if (text[i] >= 0x80) { // 跳过UTF-8字符 - flag = false; - short_name->base[j] = '_'; + c = text[i]; + q = &short_name->base[j]; + i++; + if (is_available_short_name_char(c)) { + if ('a' <= c && c <= 'z') *q = c - 32; + else *q = c; + } else if (c >= 0x80) { // 跳过UTF-8字符 + if ((c & 0xe0) == 0xc0) i++; + if ((c & 0xf0) == 0xe0) i += 2; + if ((c & 0xf8) == 0xf0) i += 3; + flag = false; + *q = '_'; } else continue; - tmp_name[j] = short_name->base[j]; + tmp_name[k] = *q; base_name_len++; - } else short_name->base[j] = ' '; - j++; + j++; + } else short_name->base[k] = ' '; } if (!is_directory) { - tmp_name[j] = '.'; - int k = j + 1; - - for (i = 0, j = 0; i < 3; i++) { - if (i < dot) { - uint8_t c = text[dot + 1 + i]; + tmp_name[j++] = '.'; + for (i = dot + 1, k = 0; k < 3; k++) { + if (i < len) { + c = text[i]; + q = &short_name->ext[k]; + i++; if (is_available_short_name_char(c)) { - if ('a' <= c && c <= 'z') short_name->ext[j] = c - 32; - else short_name->ext[j] = c; - } else if (c >= 0x80) { - flag = false; - short_name->ext[j] = '_'; + if ('a' <= c && c <= 'z') *q = c - 32; + else *q = c; + } else if (c >= 0x80) { // 跳过UTF-8字符 + if ((c & 0xe0) == 0xc0) i++; + if ((c & 0xf0) == 0xe0) i += 2; + if ((c & 0xf8) == 0xf0) i += 3; + flag = false; + *q = '_'; } else continue; - } else short_name->ext[j] = ' '; - tmp_name[k + j] = short_name->ext[j]; - j++; - ext_name_len++; + tmp_name[j] = *q; + ext_name_len++; + j++; + } else short_name->ext[k] = ' '; } } @@ -278,7 +288,8 @@ FsResult long_name2short_name( if (!flag && check_short_name((uint8_t *)short_name, 11, dot)) { // 完全满足短文件名条件,检查是否重名 - return search_dir(fat_info, parent, name, is_directory, NULL, 0); + return fat_info->ops->fat_search_dir( + fat_info, parent, name, is_directory, NULL); } else { for (int n = 1; n < 999999; n++) { // 统计位数 @@ -293,8 +304,8 @@ FsResult long_name2short_name( short_name->base[i] = '~'; // 检查是否重名 - FsResult result = - search_dir(fat_info, parent, name, is_directory, NULL, 0); + FsResult result = fat_info->ops->fat_search_dir( + fat_info, parent, name, is_directory, NULL); if (result == FS_ERROR_CANNOT_FIND) { // 找不到说明可用 return FS_OK; diff --git a/src/include/fs/fs.h b/src/include/fs/fs.h index f55fbb9..8424241 100644 --- a/src/include/fs/fs.h +++ b/src/include/fs/fs.h @@ -39,7 +39,7 @@ typedef struct FileSystemOps { struct Volume; typedef struct FsFileOps { FsResult (*fs_open)( - struct FileSystemInfo *fs_info, void *parent, string_t name, + struct FileSystemInfo *fs_info, Object *parent_obj, string_t name, struct Object **object); FsResult (*fs_close)(struct Object *object); FsResult (*fs_seek)(struct Object *object, size_t offset); @@ -51,15 +51,19 @@ typedef struct FsFileOps { typedef struct FsDirectoryOps { FsResult (*fs_opendir)( - struct FileSystemInfo *fs_info, void *parent, string_t name, - struct Object **object); - FsResult (*fs_closedir)(struct Object *object); + struct FileSystemInfo *fs_info, Object *parent_obj, void **iterator); + FsResult (*fs_readdir)( + struct FileSystemInfo *fs_info, void *iterator, Object **object); + FsResult (*fs_closedir)(void *iterator); + FsResult (*fs_create_file)( struct Object *parent_obj, string_t name, struct Object **object); FsResult (*fs_delete_file)(struct Object *parent_obj, string_t name); + FsResult (*fs_mkdir)( struct Object *parent_obj, string_t name, struct Object **object); FsResult (*fs_rmdir)(struct Object *parent_obj, string_t name); + FsResult (*fs_get_attr)(struct Object *object, struct ObjectAttr *attr); FsResult (*fs_set_attr)(struct Object *object, struct ObjectAttr *attr); } FsDirectoryOps; diff --git a/src/include/objects/object.h b/src/include/objects/object.h index cbc8d2f..acdff2a 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -80,6 +80,7 @@ typedef struct Object { struct { void *data; list_t children; + void *fs_iterator; } directory; struct Driver *driver; struct Device *device; @@ -106,6 +107,16 @@ typedef struct Object { void (*release_data)(struct Object *object); } Object; +typedef struct ObjectIterator { + Object *parent_object; + list_t *current_node; + void *fs_iterator; + enum { + ITERATOR_TYPE_MEM, + ITERATOR_TYPE_FS, + } type; +} ObjectIterator; + static const Permission base_obj_sys_perm = { .subject_id = SUBJECT_ID_SYSTEM, .permission = {1, 1, 1, 1, 0, 1, 1}, diff --git a/src/include/objects/ops.h b/src/include/objects/ops.h index ef768e1..bd14984 100644 --- a/src/include/objects/ops.h +++ b/src/include/objects/ops.h @@ -12,9 +12,10 @@ #define OBJ_WRITE_INTERRUPT(object) (object)->out.interrupt ObjectResult obj_open(Object *parent, DEF_MRET(Object *, child), string_t name); -ObjectResult obj_opendir( - Object *parent, DEF_MRET(Object *, child), string_t name); ObjectResult obj_close(Object *object); +ObjectResult obj_opendir(Object *parent, DEF_MRET(ObjectIterator *, iter)); +ObjectResult obj_readdir(ObjectIterator *iterator, DEF_MRET(Object *, object)); +ObjectResult obj_closedir(ObjectIterator *iterator); ObjectResult obj_create_file(Object *parent, string_t name); ObjectResult obj_delete_file(Object *parent, string_t name); ObjectResult obj_mkdir(Object *parent, string_t name); diff --git a/src/kernel/main.c b/src/kernel/main.c index b46a34f..f8ab27b 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -87,24 +87,17 @@ int main() { printk("Memory Size:%dM\n", get_memory_size()); thread_start( "Kernel Periodic Tasks", THREAD_DEFAULT_PRIO, periodic_task, NULL); - // init_vfs(); + do_initcalls(); driver_start_all(); // uint8_t buf[512]; // Object *object; // ObjectResult result = - // open_object_by_path("\\Volumes\\Storage0Volume0\\kernel.elf", &object); + // open_object_by_path("\\Volumes\\Storage0Volume0\\", &object); // if (result != OBJECT_OK) { // printk("Open File Error!\n"); // } else { - // ObjectAttr attr; - // obj_get_attr(object, &attr); - // printk("File Size:%d\n", attr.size); - // print_permission(&attr.all_user_permission); - // print_permission(&attr.admin_permission); - // print_permission(&attr.owner_permission); - // print_permission(&attr.system_permission); // } // const string_t name = STRING_INIT("A folder"); diff --git a/src/objects/objects.c b/src/objects/objects.c index 67f242c..63073c2 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -62,42 +62,62 @@ ObjectResult init_object_tree() { return OBJECT_OK; } -ObjectResult open_oringinal_object_by_path(char *path, Object **out_object) { - // 必须从根对象开始 - if (path[0] != '\\') { return OBJECT_ERROR_ILLEGAL_ARGUMENT; } - path++; +ObjectResult object_open(Object *parent, Object **child, char *path) { + Object *object; + ObjectResult result; + if (*path == '\0') { + *child = parent; + return OBJECT_OK; + } + + string_t name; char ascii_name[256]; - string_t name = {0, 0, ascii_name}; - Object *object = &root_object; - while (*path) { - int i = 0; - while (*path != '\0' && *path != '\\') { - ascii_name[i] = *path; - path++; - i++; - } - bool is_directory = false; - if (*path == '\\') { - is_directory = true; - path++; + char *p = path; + int i = 0; + name.text = ascii_name; + + while (*p != '\0' && *p != '\\') { + ascii_name[i] = *p; + p++; + i++; + } + bool is_directory = false; + if (*p == '\\') { + is_directory = true; + p++; + } + ascii_name[i] = '\0'; + name.length = i + 1; + name.max_length = i + 1; + + if (!is_directory) { + return obj_open(parent, child, name); + } else { + ObjectIterator *iter; + result = obj_opendir(parent, &iter); + while (1) { + result = obj_readdir(iter, &object); + if (result != OBJECT_OK) break; + if (strncmp(object->name.text, name.text, name.length) == 0) { + if (object->attr.type != OBJECT_TYPE_DIRECTORY) continue; + result = object_open(object, child, p); + obj_closedir(iter); + return result; + } } - ascii_name[i] = '\0'; - name.length = i + 1; - name.max_length = i + 1; - - Object *child; - ObjectResult result; - if (!is_directory) result = obj_open(object, &child, name); - else result = obj_opendir(object, &child, name); - if (result != OBJECT_OK) { return result; } - - object = child; } - *out_object = object; return OBJECT_OK; } +ObjectResult open_oringinal_object_by_path(char *path, Object **out_object) { + // 必须从根对象开始 + if (path[0] != '\\') { return OBJECT_ERROR_ILLEGAL_ARGUMENT; } + path++; + + return object_open(&root_object, out_object, path); +} + ObjectResult open_object_by_path(char *path, Object **object) { ObjectResult result = open_oringinal_object_by_path(path, object); if (result == OBJECT_OK) { diff --git a/src/objects/ops.c b/src/objects/ops.c index 7d17292..85d8aab 100644 --- a/src/objects/ops.c +++ b/src/objects/ops.c @@ -37,36 +37,66 @@ ObjectResult obj_open( // 如果缓存中找不到,则调用文件系统接口读取 else if (parent->fs_info != NULL) { FsResult result = parent->fs_info->file_ops.fs_open( - parent->fs_info, parent->value.directory.data, name, &MRET(child)); + parent->fs_info, parent, name, &MRET(child)); child->reference++; if (result == FS_OK) return OBJECT_OK; } return OBJECT_ERROR_CANNOT_FIND; } -ObjectResult obj_opendir( - Object *parent, DEF_MRET(Object *, child), string_t name) { - Object *child; - ObjectResult result = obj_search(parent, &child, name, true); - if (result == OBJECT_OK) { - Permission *permission = get_permission_info(child); - if (!permission->permission.execute) return OBJECT_ERROR_NO_PERMISSION; - MRET(child) = child; - child->reference++; - return OBJECT_OK; +ObjectResult obj_opendir(Object *parent, DEF_MRET(ObjectIterator *, iter)) { + ObjectIterator *iter = kmalloc(sizeof(ObjectIterator)); + iter->current_node = parent->value.directory.children.next; + iter->type = ITERATOR_TYPE_MEM; + if (parent->fs_info != NULL) { + if (parent->value.directory.fs_iterator == NULL) { + FsResult result = parent->fs_info->dir_ops.fs_opendir( + parent->fs_info, parent, &iter->fs_iterator); + if (result != FS_OK) return OBJECT_ERROR_CANNOT_FIND; + iter->type = ITERATOR_TYPE_FS; + } else { + iter->fs_iterator = parent->value.directory.fs_iterator; + } } - // 如果缓存中找不到,则调用文件系统接口读取 - else if (parent->fs_info != NULL) { - FsResult result = parent->fs_info->dir_ops.fs_opendir( - parent->fs_info, parent->value.directory.data, name, &MRET(child)); - if (result != FS_OK) return OBJECT_ERROR_CANNOT_FIND; - ObjectAttr attr; - obj_get_attr(child, &attr); - Permission *permission = get_permission_info(child); - if (!permission->permission.execute) return OBJECT_ERROR_NO_PERMISSION; - child->reference++; + MRET(iter) = iter; + + return OBJECT_OK; +} + +ObjectResult obj_readdir(ObjectIterator *iterator, DEF_MRET(Object *, object)) { + if (iterator->type == ITERATOR_TYPE_FS) { + FsResult result = iterator->parent_object->fs_info->dir_ops.fs_readdir( + iterator->parent_object->value.directory.data, + iterator->fs_iterator, &MRET(object)); + if (result == FS_ERROR_CANNOT_FIND) return OBJECT_ERROR_CANNOT_FIND; + else if (result != FS_OK) return OBJECT_ERROR_CANNOT_FIND; + } else { + if (iterator->current_node == + &iterator->parent_object->value.directory.children) { + if (iterator->fs_iterator) { + iterator->parent_object->fs_info->dir_ops.fs_readdir( + iterator->parent_object->value.directory.data, + iterator->fs_iterator, &MRET(object)); + } else return OBJECT_ERROR_CANNOT_FIND; + } + + MRET(object) = list_owner(iterator->current_node, Object, list); + iterator->current_node = iterator->current_node->next; } - return OBJECT_ERROR_CANNOT_FIND; + return OBJECT_OK; +} + +ObjectResult obj_closedir(ObjectIterator *iterator) { + if (iterator->type == ITERATOR_TYPE_FS) { + if (iterator->fs_iterator != NULL) { + FsResult result = + iterator->parent_object->fs_info->dir_ops.fs_closedir( + iterator->fs_iterator); + if (result != FS_OK) return OBJECT_ERROR_OTHER; + } + } + kfree(iterator); + return OBJECT_OK; } ObjectResult obj_close(Object *object) { @@ -78,7 +108,8 @@ ObjectResult obj_close(Object *object) { if (object->attr.type == OBJECT_TYPE_FILE) { object->fs_info->file_ops.fs_close(object); } else if (object->attr.type == OBJECT_TYPE_DIRECTORY) { - object->fs_info->dir_ops.fs_closedir(object); + object->fs_info->dir_ops.fs_closedir( + object->value.directory.fs_iterator); } list_del(&object->list); obj_close(object->parent); From 03fce7a3e24d505257575d04fa1e6d9f2dea3786 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 10 Mar 2025 16:05:50 +0800 Subject: [PATCH 032/158] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E4=B8=BASystem?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E5=88=86=E9=85=8D=E6=96=B0=E7=9A=84=E9=A1=B5?= =?UTF-8?q?=E5=AD=98=E5=82=A8task=5Fs=E9=98=B2=E6=AD=A2=E6=A0=88=E6=BA=A2?= =?UTF-8?q?=E5=87=BA=E8=A6=86=E7=9B=96=E6=8E=89task=5Fs=E7=9A=84=E5=86=85?= =?UTF-8?q?=E5=AE=B9=EF=BC=9B=20=E6=96=B0=E5=A2=9E=20=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E4=B8=93=E9=97=A8=E7=9A=84current=5Ftask=E5=8F=98=E9=87=8F?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E5=BD=93=E5=89=8D=E4=BB=BB=E5=8A=A1=E7=9A=84?= =?UTF-8?q?task=5Fs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/include/kernel/thread.h | 1 + src/kernel/thread.c | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/arch/x86/include/kernel/thread.h b/src/arch/x86/include/kernel/thread.h index d684570..d36b87f 100644 --- a/src/arch/x86/include/kernel/thread.h +++ b/src/arch/x86/include/kernel/thread.h @@ -70,6 +70,7 @@ struct task_s { struct mmap vir_page_mmap; struct memory_manage *memory_manage; + list_t wait_queue_tag; list_t general_tag; list_t all_list_tag; }; diff --git a/src/kernel/thread.c b/src/kernel/thread.c index 95c64a7..5d07d02 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -20,6 +20,8 @@ #include #include +struct task_s *current_task; + struct task_s *main_thread; list_t thread_ready; LIST_HEAD(thread_all); @@ -46,9 +48,10 @@ static uint32_t alloc_pid(void) { * @return struct task_s* */ struct task_s *get_current_thread() { - uint32_t sp; - GET_REG("esp", sp); - return (struct task_s *)(sp & 0xfffff000); + // uint32_t sp; + // GET_REG("esp", sp); + // return (struct task_s *)(sp & 0xfffff000); + return current_task; } size_t get_current_subject_id() { @@ -170,10 +173,11 @@ void thread_exit(void) { next->status = TASK_RUNNING; process_activate(next); - + current_task = next; switch_to((int *)cur, (int *)next); } else { process_activate(task_idle); + current_task = task_idle; switch_to((int *)cur, (int *)task_idle); } } @@ -236,8 +240,9 @@ void thread_unblock(struct task_s *pthread) { * */ static void make_main_thread(void) { - main_thread = get_current_thread(); - init_thread(main_thread, "System", 10); + main_thread = kernel_alloc_pages(1); + init_thread(main_thread, "System", THREAD_DEFAULT_PRIO); + current_task = main_thread; main_thread->pid = alloc_pid(); if (list_find(&main_thread->all_list_tag, &thread_all)) { @@ -277,18 +282,20 @@ void schedule(void) { } struct task_s *next; next = list_first_owner(&thread_ready, struct task_s, general_tag); - io_sti(); if (next != cur) { - list_del(thread_ready.next); + list_del(&next->general_tag); next->status = TASK_RUNNING; process_activate(next); + current_task = next; switch_to((int *)cur, (int *)next); } else { process_activate(task_idle); + current_task = task_idle; switch_to((int *)cur, (int *)task_idle); } + io_sti(); } /** From 54c8f056aebd9a1531242176f11a6328803adecb Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 10 Mar 2025 16:14:55 +0800 Subject: [PATCH 033/158] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20=E7=94=A8=E4=B8=93?= =?UTF-8?q?=E9=97=A8=E7=9A=84wait=5Fqueue=5Ftag=E6=9D=A5=E4=BB=A3=E6=9B=BF?= =?UTF-8?q?general=5Ftag=E5=8A=A0=E5=85=A5wait=5Fqueue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/wait_queue.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/kernel/wait_queue.c b/src/kernel/wait_queue.c index 8d7f341..c430ac1 100644 --- a/src/kernel/wait_queue.c +++ b/src/kernel/wait_queue.c @@ -49,7 +49,7 @@ void wait_queue_add(WaitQueue *wq) { spin_lock(&wq->lock); // 把当前线程的list tag直接挂到等待队列的list上 - list_add_tail(&task->general_tag, &wq->list_head); + list_add_tail(&task->wait_queue_tag, &wq->list_head); spin_unlock(&wq->lock); store_interrupt_status(old_status); @@ -63,7 +63,7 @@ void wait_queue_add(WaitQueue *wq) { */ WaitQueueItem *wait_queue_first(WaitQueue *wqm) { if (list_empty(&wqm->list_head)) { return NULL; } - return list_first_owner(&wqm->list_head, WaitQueueItem, general_tag); + return list_first_owner(&wqm->list_head, WaitQueueItem, wait_queue_tag); } /** @@ -74,12 +74,12 @@ WaitQueueItem *wait_queue_first(WaitQueue *wqm) { void wait_queue_wakeup(WaitQueue *wqm) { if (list_empty(&wqm->list_head)) { return; } struct task_s *thread = - list_first_owner(&wqm->list_head, struct task_s, general_tag); + list_first_owner(&wqm->list_head, struct task_s, wait_queue_tag); int old_status = load_interrupt_status(); disable_interrupt(); spin_lock(&wqm->lock); - list_del(&thread->general_tag); + list_del(&thread->wait_queue_tag); if (thread->status == TASK_BLOCKED || thread->status == TASK_WAITING || thread->status == TASK_HANGING) { @@ -105,9 +105,9 @@ void wait_queue_wakeup_all(WaitQueue *wqm) { disable_interrupt(); spin_lock(&wqm->lock); - list_for_each_owner_safe (cur, next, &wqm->list_head, general_tag) { + list_for_each_owner_safe (cur, next, &wqm->list_head, wait_queue_tag) { thread = cur; - list_del(&cur->general_tag); + list_del(&cur->wait_queue_tag); if (thread->status == TASK_BLOCKED || thread->status == TASK_WAITING || thread->status == TASK_HANGING) { thread_unblock(thread); From 2ccf5aff92964f8f01889bf3f467580959812544 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 10 Mar 2025 16:20:35 +0800 Subject: [PATCH 034/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20lookup=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=9B=20=E9=87=8D=E6=9E=84=20open=E7=AD=89?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 + src/arch/x86/include/kernel/cpu.h | 6 ++ src/arch/x86/kernel.lds | 9 ++ src/driver/storage/storage_io.c | 6 +- src/fs/fat/attr.c | 12 ++- src/fs/fat/dir.c | 103 ++++++++++++------- src/fs/fat/entry.c | 55 ++++++---- src/fs/fat/fat.c | 165 ++++++++++++++++++++---------- src/fs/fat/include/attr.h | 7 +- src/fs/fat/include/dir.h | 16 +-- src/fs/fat/include/entry.h | 10 +- src/fs/fat/include/fat.h | 16 ++- src/fs/fat/name.c | 10 +- src/include/fs/fs.h | 22 ++-- src/include/objects/object.h | 7 +- src/include/objects/ops.h | 14 ++- src/include/objects/permission.h | 3 +- src/kernel/main.c | 36 ++++--- src/objects/mount.c | 6 +- src/objects/objects.c | 70 +++++++------ src/objects/ops.c | 140 +++++++++++++------------ src/objects/permission.c | 10 +- src/objects/types.c | 12 +-- 23 files changed, 450 insertions(+), 287 deletions(-) create mode 100644 src/arch/x86/include/kernel/cpu.h diff --git a/Makefile b/Makefile index 1384fd3..9b1d1e9 100644 --- a/Makefile +++ b/Makefile @@ -89,6 +89,7 @@ writehd: $(HD_IMG) # qemu 7.1后取消了-soundhw,改用-audio qemu_dbg: $(QEMU) \ + -no-reboot \ -s -S \ -monitor stdio \ -m 1024 \ @@ -104,6 +105,7 @@ qemu_dbg: qemu: $(QEMU) \ + -no-reboot \ -monitor stdio \ -m 1024 \ -hda $(HD_IMG) \ diff --git a/src/arch/x86/include/kernel/cpu.h b/src/arch/x86/include/kernel/cpu.h new file mode 100644 index 0000000..3c9a136 --- /dev/null +++ b/src/arch/x86/include/kernel/cpu.h @@ -0,0 +1,6 @@ +#ifndef _CPU_H +#define _CPU_H + +#define DEF_PER_CPU(type, name) type name __attribute__((section(".percpu"))); + +#endif \ No newline at end of file diff --git a/src/arch/x86/kernel.lds b/src/arch/x86/kernel.lds index d6b5cc5..c48d3b5 100644 --- a/src/arch/x86/kernel.lds +++ b/src/arch/x86/kernel.lds @@ -40,6 +40,15 @@ SECTIONS { PROVIDE(__exitcall_end = .); } : text + .percpu ALIGN(64) : + { + . = ALIGN(64); + PROVIDE(__percpu_start = .); + *(.percpu) + . = ALIGN(64); + PROVIDE(__percpu_end = .); + } : data + /* data segment */ .data : { . = ALIGN(4); /* 4 bytes align */ diff --git a/src/driver/storage/storage_io.c b/src/driver/storage/storage_io.c index 1d048a9..db059f9 100644 --- a/src/driver/storage/storage_io.c +++ b/src/driver/storage/storage_io.c @@ -14,7 +14,7 @@ TransferResult storage_transfer_async( Object *object, TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, void **handle) { - while (object->attr.type == OBJECT_TYPE_SYM_LINK) { + while (object->attr->type == OBJECT_TYPE_SYM_LINK) { object = object->value.sym_link; } Device *device = object->value.device; @@ -36,7 +36,7 @@ TransferResult storage_transfer_async( TransferResult storage_transfer( Object *object, TransferDirection direction, uint8_t *buf, uint32_t position, size_t count) { - while (object->attr.type == OBJECT_TYPE_SYM_LINK) { + while (object->attr->type == OBJECT_TYPE_SYM_LINK) { object = object->value.sym_link; } Device *device = object->value.device; @@ -59,7 +59,7 @@ TransferResult storage_transfer( TransferResult storage_is_transfer_done( Object *object, void **handle, bool *done) { - if (object->attr.type != OBJECT_TYPE_DEVICE) { + if (object->attr->type != OBJECT_TYPE_DEVICE) { return TRANSFER_ERROR_INVALID_PARAMETER; } Device *device = object->value.device; diff --git a/src/fs/fat/attr.c b/src/fs/fat/attr.c index 01204f4..af93d39 100644 --- a/src/fs/fat/attr.c +++ b/src/fs/fat/attr.c @@ -1,13 +1,17 @@ #include "fs/fs.h" #include "include/dir.h" +#include "include/fat.h" +#include "kernel/driver_interface.h" #include #include #include #include -FsResult fat_attr_to_sys_attr(ShortDir *short_dir, ObjectAttr *attr) { +FsResult fat_attr_to_sys_attr( + ShortDir *short_dir, ObjectAttr *attr, FatLocation *location) { uint8_t fat_attr = short_dir->attr; if (fat_attr & ATTR_ARCHIVE) { + attr->fs_location = kmalloc_from_template(*location); attr->size = short_dir->file_size; attr->is_mounted = 0; Permission *all_user = &attr->all_user_permission; @@ -40,6 +44,8 @@ FsResult fat_attr_to_sys_attr(ShortDir *short_dir, ObjectAttr *attr) { if (fat_attr & ATTR_DIRECTORY) { attr->type = OBJECT_TYPE_DIRECTORY; if (fat_attr & ATTR_SYSTEM) { all_user->permission.execute = 1; } + } else { + attr->type = OBJECT_TYPE_FILE; } if (fat_attr & ATTR_READ_ONLY) { @@ -52,11 +58,13 @@ FsResult fat_attr_to_sys_attr(ShortDir *short_dir, ObjectAttr *attr) { return FS_OK; } -FsResult fat_attr_from_sys_attr(ShortDir *short_dir, ObjectAttr *attr) { +FsResult fat_attr_from_sys_attr( + ShortDir *short_dir, ObjectAttr *attr, FatLocation *location) { Permission *all_user = &attr->all_user_permission; Permission *owner = &attr->owner_permission; short_dir->attr = ATTR_ARCHIVE; + location = attr->fs_location; if (all_user->permission.write == 0 && all_user->permission.read == 1) { short_dir->attr |= ATTR_READ_ONLY; } diff --git a/src/fs/fat/dir.c b/src/fs/fat/dir.c index c3cc540..fac4d93 100644 --- a/src/fs/fat/dir.c +++ b/src/fs/fat/dir.c @@ -32,6 +32,12 @@ void fat_dir_iterator_init( iter->last_entry_index = 0; } +void fat_dir_iterator_next(FatDirIterator *iter) { + // 重置长名状态 + iter->longname_len = 0; + iter->longname_valid = false; +} + void fat_dir_iterator_destroy(FatDirIterator *iter) { if (iter->longname_buf != NULL) kfree(iter->longname_buf); } @@ -68,31 +74,18 @@ PRIVATE void process_long_entry( PRIVATE FsResult process_short_entry( FatDirIterator *iter, ShortDir *short_dir, uint32_t current_cluster, - int current_entry_index, DEF_MRET(string_t, name)) { + int current_entry_index) { // 验证长名校验和 if (iter->longname_len > 0) { if (fat_checksum(&short_dir->name) != iter->checksum) { iter->longname_len = 0; } } - - // 生成文件名 - if (iter->longname_valid) { - fat_utf16_to_utf8(iter->longname_buf, iter->longname_len, &MRET(name)); - } else { - MRET(name) = read_short_name(short_dir); - } - - // 重置长名状态 - iter->longname_len = 0; - iter->longname_valid = false; - return FS_OK; } FsResult fat32_read_dir_entry( - FatDirIterator *iter, DEF_MRET(string_t, name), - DEF_MRET(ShortDir, short_dir)) { + FatDirIterator *iter, DEF_MRET(ShortDir, short_dir)) { uint8_t entry_buf[32]; ShortDir *short_dir = (ShortDir *)entry_buf; LongDir *long_dir; @@ -125,15 +118,13 @@ FsResult fat32_read_dir_entry( MRET(short_dir) = *short_dir; // 处理短文件名条目 return process_short_entry( - iter, short_dir, iter->last_cluster, iter->last_entry_index, - &MRET(name)); + iter, short_dir, iter->last_cluster, iter->last_entry_index); } } } FsResult fat_read_dir_entry( - FatDirIterator *iter, DEF_MRET(string_t, name), - DEF_MRET(ShortDir, short_dir)) { + FatDirIterator *iter, DEF_MRET(ShortDir, short_dir)) { uint8_t entry_buf[32]; ShortDir *short_dir; @@ -165,26 +156,44 @@ FsResult fat_read_dir_entry( // 处理短文件名条目 MRET(short_dir) = *short_dir; return process_short_entry( - iter, short_dir, current_cluster, current_entry_index, &MRET(name)); + iter, short_dir, current_cluster, current_entry_index); } } -FsResult fat32_search_dir( +FsResult fat32_dir_lookup( FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, - bool is_directory, DEF_MRET(FatDirEntry *, entry)) { + DEF_MRET(FatLocation, location), DEF_MRET(ShortDir, short_dir)) { FatDirIterator iter; string_t _name; ShortDir *short_dir = NULL; fat_dir_iterator_init(&iter, fat_info, parent_entry); - while (fat32_read_dir_entry(&iter, &_name, short_dir) == FS_OK) { - if (is_directory && !(short_dir->attr & ATTR_DIRECTORY)) continue; - if (!is_directory && (short_dir->attr & ATTR_DIRECTORY)) continue; + while (fat32_read_dir_entry(&iter, short_dir) == FS_OK) { + // 生成文件名 + if (iter.longname_valid) { + fat_utf16_to_utf8(iter.longname_buf, iter.longname_len, &_name); + } else { + _name = read_short_name(short_dir); + } + fat_dir_iterator_next(&iter); + if (strncmp(_name.text, name.text, name.length) == 0) { + string_del(&_name); fat_dir_iterator_destroy(&iter); - MRET(entry) = generate_dir_entry( - fat_info, parent_entry, short_dir, name, is_directory, - iter.last_cluster, iter.last_entry_index, iter.longname_cluster, - iter.longname_entry_index); + MRET(location).longname_cluster = iter.longname_cluster; + MRET(location).longname_offset = iter.longname_entry_index; + MRET(location).shortname_cluster = iter.last_cluster; + MRET(location).shortname_offset = iter.last_entry_index; + MRET(location).parent_cluster = + parent_entry->short_dir.first_cluster_high << 16 | + parent_entry->short_dir.first_cluster_low; + MRET(location).first_cluster = short_dir->first_cluster_high << 16 | + short_dir->first_cluster_low; + MRET(short_dir) = *short_dir; + // MRET(entry) = generate_dir_entry( + // fat_info, parent_entry, short_dir, name, + // short_dir->attr & ATTR_DIRECTORY, iter.last_cluster, + // iter.last_entry_index, iter.longname_cluster, + // iter.longname_entry_index); return FS_OK; } } @@ -192,23 +201,41 @@ FsResult fat32_search_dir( return FS_ERROR_CANNOT_FIND; } -FsResult fat_search_dir( +FsResult fat_dir_lookup( FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, - bool is_directory, DEF_MRET(FatDirEntry *, entry)) { + DEF_MRET(FatLocation, location), DEF_MRET(ShortDir, short_dir)) { FatDirIterator iter; string_t _name; ShortDir *short_dir = NULL; fat_dir_iterator_init(&iter, fat_info, parent_entry); - while (fat_read_dir_entry(&iter, &_name, short_dir) == FS_OK) { - if (is_directory && !(short_dir->attr & ATTR_DIRECTORY)) continue; - if (!is_directory && (short_dir->attr & ATTR_DIRECTORY)) continue; + while (fat_read_dir_entry(&iter, short_dir) == FS_OK) { + // 生成文件名 + if (iter.longname_valid) { + fat_utf16_to_utf8(iter.longname_buf, iter.longname_len, &_name); + } else { + _name = read_short_name(short_dir); + } + fat_dir_iterator_next(&iter); + if (strncmp(_name.text, name.text, name.length) == 0) { + string_del(&_name); fat_dir_iterator_destroy(&iter); - MRET(entry) = generate_dir_entry( - fat_info, parent_entry, short_dir, name, is_directory, - iter.last_cluster, iter.last_entry_index, iter.longname_cluster, - iter.longname_entry_index); + MRET(location).longname_cluster = iter.longname_cluster; + MRET(location).longname_offset = iter.longname_entry_index; + MRET(location).shortname_cluster = iter.last_cluster; + MRET(location).shortname_offset = iter.last_entry_index; + MRET(location).parent_cluster = + parent_entry->short_dir.first_cluster_high << 16 | + parent_entry->short_dir.first_cluster_low; + MRET(location).first_cluster = short_dir->first_cluster_high << 16 | + short_dir->first_cluster_low; + MRET(short_dir) = *short_dir; + // MRET(entry) = generate_dir_entry( + // fat_info, parent_entry, short_dir, name, + // short_dir->attr & ATTR_DIRECTORY, iter.last_cluster, + // iter.last_entry_index, iter.longname_cluster, + // iter.longname_entry_index); return FS_OK; } } diff --git a/src/fs/fat/entry.c b/src/fs/fat/entry.c index d0a51bc..6ea78c2 100644 --- a/src/fs/fat/entry.c +++ b/src/fs/fat/entry.c @@ -160,30 +160,41 @@ PRIVATE FsResult fat_longname_entry_write( PUBLIC FatDirEntry *generate_dir_entry( FatInfo *fat_info, FatDirEntry *parent_entry, ShortDir *short_dir, - string_t name, bool is_directory, uint32_t cluster, uint32_t number, - uint32_t longname_cluster, uint32_t longname_number) { + string_t name, FatLocation *location, ObjectAttr *attr) { FatDirEntry *entry = kmalloc(sizeof(FatDirEntry)); - string_cpy(&entry->name, &name); + entry->name.text = kmalloc(name.length); + memcpy(entry->name.text, name.text, name.length); + entry->name.length = name.length; + entry->name.max_length = name.length; + memcpy(&entry->short_dir, short_dir, sizeof(ShortDir)); + bool is_directory = short_dir->attr & ATTR_DIRECTORY; + uint32_t cluster = location->shortname_cluster; + int number = location->shortname_offset; + uint32_t longname_cluster = location->longname_cluster; + int longname_number = location->longname_offset; entry->cluster_list = dyn_array_new(sizeof(ClusterSegment), 8); get_cluster_segment(fat_info, entry); - Object *object; - ObjectAttr attr; - fat_attr_to_sys_attr(short_dir, &attr); + Object *object; + ObjectAttr *_attr = attr; + if (_attr == NULL) { + _attr = kmalloc(sizeof(ObjectAttr)); + fat_attr_to_sys_attr(short_dir, _attr, location); + } - if (entry->short_dir.attr & ATTR_DIRECTORY) { + if (is_directory) { FsResult result = fs_obj_create_dir( parent_entry->object, fat_info->fs_info, entry->name, &object, - &attr); + _attr); if (result != FS_OK) { return NULL; } object->value.directory.data = entry; entry_cache_init(fat_info, entry, fat_info->bytes_per_cluster); } else { FsResult result = fs_obj_create_file( parent_entry->object, fat_info->fs_info, entry->name, &object, - &attr); + _attr); if (result != FS_OK) { return NULL; } object->value.file.data = entry; object->value.file.offset = 0; @@ -258,9 +269,13 @@ PUBLIC FsResult fat_create_entry( fat_info, parent_entry, cluster, number, (uint8_t *)&short_dir)); FatDirEntry *entry; - entry = generate_dir_entry( - fat_info, parent_entry, &short_dir, name, is_directory, cluster, number, - longname_cluster, longname_number); + FatLocation location; + location.longname_cluster = longname_cluster; + location.longname_offset = longname_number; + location.shortname_cluster = cluster; + location.shortname_offset = number; + entry = generate_dir_entry( + fat_info, parent_entry, &short_dir, name, &location, NULL); if (is_directory) { static ShortName dot = {". ", " "}; @@ -281,21 +296,21 @@ PUBLIC FsResult fat_create_entry( } PUBLIC FsResult fat_delete_entry( - FatInfo *fat_info, FatDirEntry *parent, FatDirEntry *entry, string_t name) { - uint32_t cluster = entry->shortname_cluster; - uint32_t num = entry->shortname_number; + FatInfo *fat_info, FatDirEntry *parent, FatLocation *location) { + uint32_t cluster = location->shortname_cluster; + uint32_t num = location->shortname_offset; uint8_t buf[32]; FS_RESULT_PASS(fat_entry_read(fat_info, parent, cluster, num, buf)); buf[0] = 0xe5; FS_RESULT_PASS(fat_entry_write(fat_info, parent, cluster, num, buf)); - if (fat_info->type == FAT_TYPE_FAT32 && entry->longname_cluster != 0) { - uint32_t cluster = entry->longname_cluster; - int number = entry->longname_number; + if (fat_info->type == FAT_TYPE_FAT32 && location->longname_cluster != 0) { + uint32_t cluster = location->longname_cluster; + int number = location->longname_offset; - while (cluster <= entry->shortname_cluster && - number < entry->shortname_number) { + while (cluster <= location->shortname_cluster && + number < location->shortname_offset) { FS_RESULT_PASS( fat_entry_read(fat_info, parent, cluster, number, buf)); buf[0] = 0xe5; diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c index a288dbd..784eb08 100644 --- a/src/fs/fat/fat.c +++ b/src/fs/fat/fat.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -20,9 +21,13 @@ FsResult fat_check(Partition *partition); FsResult fat_mount(FileSystemInfo *fs_info, Object *root_object); + +FsResult fat_lookup( + FileSystemInfo *fs_info, Object *parent_obj, string_t *name, + ObjectAttr **attr); FsResult fat_open( - FileSystemInfo *fs_info, Object *parent_obj, string_t name, - Object **object); + FileSystemInfo *fs_info, Object *parent_obj, ObjectAttr *attr, + string_t *name, Object **object); FsResult fat_close(Object *object); FsResult fat_seek(Object *object, size_t offset); FsResult fat_read(Object *file, void *buf, size_t size); @@ -30,12 +35,13 @@ FsResult fat_write(Object *file, void *buf, size_t size); FsResult fat_opendir( FileSystemInfo *fs_info, Object *parent_obj, void **iterator); -FsResult fat_readdir(FileSystemInfo *fs_info, void *iterator, Object **object); -FsResult fat_closedir(void *iterator); -FsResult fat_create_file(Object *parent_obj, string_t name, Object **object); -FsResult fat_delete_file(Object *parent_obj, string_t name); -FsResult fat_mkdir(Object *parent_obj, string_t name, Object **object); -FsResult fat_rmdir(Object *parent_obj, string_t name); +FsResult fat_readdir( + FileSystemInfo *fs_info, ObjectIterator *iterator, Object **object); +FsResult fat_closedir(ObjectIterator *iterator); +FsResult fat_create_file(Object *parent_obj, string_t *name, Object **object); +FsResult fat_delete_file(Object *parent_obj, ObjectAttr *attr, string_t *name); +FsResult fat_mkdir(Object *parent_obj, string_t *name, Object **object); +FsResult fat_rmdir(Object *parent_obj, ObjectAttr *attr, string_t *name); FsResult fat_get_attr(Object *object, ObjectAttr *attr); FsResult fat_set_attr(Object *object, ObjectAttr *attr); @@ -55,6 +61,7 @@ FsFileOps fat_file_ops = { }; FsDirectoryOps fat_dir_ops = { + .fs_lookup = fat_lookup, .fs_opendir = fat_opendir, .fs_readdir = fat_readdir, .fs_closedir = fat_closedir, @@ -72,11 +79,11 @@ FileSystem fat_fs = { }; FatPrivOps fat32_priv_ops = { - .fat_search_dir = fat32_search_dir, + .fat_dir_lookup = fat32_dir_lookup, .fat_read_dir_entry = fat32_read_dir_entry, }; FatPrivOps fat_priv_ops = { - .fat_search_dir = fat_search_dir, + .fat_dir_lookup = fat_dir_lookup, .fat_read_dir_entry = fat_read_dir_entry, }; @@ -190,16 +197,40 @@ FatType fat_type_determine(FatInfo *fat_info) { } } +FsResult fat_lookup( + FileSystemInfo *fs_info, Object *parent_obj, string_t *name, + ObjectAttr **attr) { + FatInfo *fat_info = fs_info->private_data; + FatDirEntry *parent_entry = parent_obj->value.directory.data; + + FatLocation location; + ShortDir short_dir; + FS_RESULT_PASS(fat_info->ops->fat_dir_lookup( + fat_info, parent_entry, *name, &location, &short_dir)); + ObjectAttr *tmp_attr = kmalloc(sizeof(ObjectAttr)); + fat_attr_to_sys_attr(&short_dir, tmp_attr, &location); + + *attr = tmp_attr; + + return FS_OK; +} + FsResult fat_open( - FileSystemInfo *fs_info, Object *parent_obj, string_t name, - Object **object) { + FileSystemInfo *fs_info, Object *parent_obj, ObjectAttr *attr, + string_t *name, Object **object) { FatInfo *fat_info = fs_info->private_data; - FatDirEntry *entry; + FatDirEntry *entry, *parent_entry = parent_obj->value.directory.data; + FatLocation *location = attr->fs_location; + ShortDir short_dir; + + fat_entry_read( + fat_info, parent_entry, location->shortname_cluster, + location->shortname_offset, (uint8_t *)&short_dir); - FsResult result = fat_info->ops->fat_search_dir( - fat_info, parent_obj->value.directory.data, name, false, &entry); + entry = generate_dir_entry( + fat_info, parent_entry, &short_dir, *name, location, attr); *object = entry->object; - return result; + return FS_OK; } FsResult fat_close(Object *object) { @@ -225,27 +256,50 @@ FsResult fat_opendir( return FS_OK; } -FsResult fat_readdir(FileSystemInfo *fs_info, void *iterator, Object **object) { +FsResult fat_readdir( + FileSystemInfo *fs_info, ObjectIterator *iterator, Object **object) { FatInfo *fat_info = fs_info->private_data; FatDirEntry *entry; string_t name; - ShortDir *short_dir = NULL; - FatDirIterator *iter = iterator; + ShortDir short_dir; + FatDirIterator *iter = iterator->fs_iterator; + Object *parent_obj = iterator->parent_object; + + FS_RESULT_PASS(fat_info->ops->fat_read_dir_entry(iter, &short_dir)); + + Object *cur; + list_for_each_owner (cur, &parent_obj->value.directory.children, list) { + FatLocation *location = cur->attr->fs_location; + if (location->shortname_cluster == iter->last_cluster && + location->shortname_offset == iter->last_entry_index) { + *object = cur; + return FS_OK; + } + } + + FatLocation location; + location.longname_cluster = iter->longname_cluster; + location.longname_offset = iter->longname_entry_index; + location.shortname_cluster = iter->last_cluster; + location.shortname_offset = iter->last_entry_index; + + // 生成文件名 + if (iter->longname_valid) { + fat_utf16_to_utf8(iter->longname_buf, iter->longname_len, &name); + } else { + name = read_short_name(&short_dir); + } + fat_dir_iterator_next(iter); - FS_RESULT_PASS( - fat_info->ops->fat_read_dir_entry(iterator, &name, short_dir)); entry = generate_dir_entry( - fat_info, iter->dir_entry, short_dir, name, - short_dir->attr & ATTR_DIRECTORY, iter->last_cluster, - iter->last_entry_index, iter->longname_cluster, - iter->longname_entry_index); + fat_info, iter->dir_entry, &short_dir, name, &location, NULL); *object = entry->object; return FS_OK; } -FsResult fat_closedir(void *iterator) { - fat_dir_iterator_destroy(iterator); +FsResult fat_closedir(ObjectIterator *iterator) { + fat_dir_iterator_destroy(iterator->fs_iterator); kfree(iterator); return FS_OK; } @@ -270,7 +324,6 @@ FsResult fat_transfer( uint32_t offset = file->value.file.offset; uint32_t readed = 0; - void *handle; while (size > 0) { uint32_t read_size = fat_info->bytes_per_cluster - offset; if (read_size > size) { read_size = size; } @@ -290,10 +343,6 @@ FsResult fat_transfer( fat_cluster_list_get_next(fat_info, entry, &cur_cluster); } } - bool done; - do { - TRANSFER_IN_IS_DONE(storage_object, &handle, &done); - } while (!done); file->value.file.offset = offset; return FS_OK; @@ -317,63 +366,75 @@ FsResult fat_write(Object *file, void *buf, size_t size) { buf, size); } -FsResult fat_create_file(Object *parent_obj, string_t name, Object **object) { +FsResult fat_create_file(Object *parent_obj, string_t *name, Object **object) { FatInfo *fat_info = parent_obj->fs_info->private_data; FatDirEntry *entry, *parent = parent_obj->value.directory.data; - FsResult result = - fat_info->ops->fat_search_dir(fat_info, parent, name, false, &entry); + FatLocation location; + ShortDir short_dir; + FsResult result = fat_info->ops->fat_dir_lookup( + fat_info, parent, *name, &location, &short_dir); if (result == FS_OK) { return FS_ERROR_ALREADY_EXISTS; } - fat_create_entry(fat_info, parent, name, false, &entry); + fat_create_entry(fat_info, parent, *name, false, &entry); *object = entry->object; return FS_OK; } -FsResult fat_delete_file(Object *parent_obj, string_t name) { +FsResult fat_delete_file(Object *parent_obj, ObjectAttr *attr, string_t *name) { FatInfo *fat_info = parent_obj->fs_info->private_data; - FatDirEntry *entry, *parent = parent_obj->value.directory.data; + FatDirEntry *parent = parent_obj->value.directory.data; - FsResult result = - fat_info->ops->fat_search_dir(fat_info, parent, name, false, &entry); - if (result != FS_OK) { return result; } + FatLocation *location = attr->fs_location; - fat_delete_entry(fat_info, parent, entry, name); + fat_delete_entry(fat_info, parent, location); return FS_OK; } -FsResult fat_mkdir(Object *parent_obj, string_t name, Object **object) { +FsResult fat_mkdir(Object *parent_obj, string_t *name, Object **object) { FatInfo *fat_info = parent_obj->fs_info->private_data; FatDirEntry *entry, *parent = parent_obj->value.directory.data; - FsResult result = - fat_info->ops->fat_search_dir(fat_info, parent, name, true, &entry); + FatLocation location; + ShortDir short_dir; + FsResult result = fat_info->ops->fat_dir_lookup( + fat_info, parent, *name, &location, &short_dir); if (result == FS_OK) { return FS_ERROR_ALREADY_EXISTS; } - fat_create_entry(fat_info, parent, name, true, &entry); + entry = generate_dir_entry( + fat_info, parent, &short_dir, *name, &location, NULL); + + fat_create_entry(fat_info, parent, *name, true, &entry); *object = entry->object; return FS_OK; } -FsResult fat_rmdir(Object *parent_obj, string_t name) { +FsResult fat_rmdir(Object *parent_obj, ObjectAttr *attr, string_t *name) { FatInfo *fat_info = parent_obj->fs_info->private_data; FatDirEntry *entry, *parent = parent_obj->value.directory.data; - FsResult result = - fat_info->ops->fat_search_dir(fat_info, parent, name, true, &entry); + FatLocation *location = attr->fs_location; + ShortDir short_dir; + FsResult result = fat_entry_read( + fat_info, parent, location->shortname_cluster, + location->shortname_offset, (uint8_t *)&short_dir); if (result != FS_OK) { return result; } + entry = + generate_dir_entry(fat_info, parent, &short_dir, *name, location, attr); + if (!fat_dir_is_empty(fat_info, entry)) return FS_ERROR_NOT_EMPTY; - fat_delete_entry(fat_info, parent, entry, name); + fat_delete_entry(fat_info, parent, location); return FS_OK; } FsResult fat_get_attr(Object *object, ObjectAttr *attr) { FatDirEntry *entry = object->value.file.data; - fat_attr_to_sys_attr(&entry->short_dir, attr); + + fat_attr_to_sys_attr(&entry->short_dir, attr, object->attr->fs_location); return FS_OK; } @@ -381,7 +442,7 @@ FsResult fat_set_attr(Object *object, ObjectAttr *attr) { FatInfo *fat_info = object->fs_info->private_data; FatDirEntry *entry = object->value.file.data; FatDirEntry *parent = object->parent->value.directory.data; - fat_attr_from_sys_attr(&entry->short_dir, attr); + fat_attr_from_sys_attr(&entry->short_dir, attr, object->attr->fs_location); fat_entry_write( fat_info, parent, entry->shortname_cluster, entry->shortname_number, (uint8_t *)&entry->short_dir); diff --git a/src/fs/fat/include/attr.h b/src/fs/fat/include/attr.h index 98a5028..af58a3f 100644 --- a/src/fs/fat/include/attr.h +++ b/src/fs/fat/include/attr.h @@ -2,9 +2,12 @@ #define _FAT_ATTR_H #include "dir.h" +#include "fat.h" #include -FsResult fat_attr_to_sys_attr(ShortDir *short_dir, ObjectAttr *attr); -FsResult fat_attr_from_sys_attr(ShortDir *short_dir, ObjectAttr *attr); +FsResult fat_attr_to_sys_attr( + ShortDir *short_dir, ObjectAttr *attr, FatLocation *location); +FsResult fat_attr_from_sys_attr( + ShortDir *short_dir, ObjectAttr *attr, FatLocation *location); #endif \ No newline at end of file diff --git a/src/fs/fat/include/dir.h b/src/fs/fat/include/dir.h index fff6126..12f620e 100644 --- a/src/fs/fat/include/dir.h +++ b/src/fs/fat/include/dir.h @@ -90,22 +90,22 @@ typedef struct FatDirIterator { } FatDirIterator; struct FatInfo; +struct FatLocation; void fat_dir_iterator_init( FatDirIterator *iter, struct FatInfo *fat, FatDirEntry *dir); +void fat_dir_iterator_next(FatDirIterator *iter); void fat_dir_iterator_destroy(FatDirIterator *iter); FsResult fat32_read_dir_entry( - FatDirIterator *iter, DEF_MRET(string_t, name), - DEF_MRET(ShortDir, short_dir)); + FatDirIterator *iter, DEF_MRET(ShortDir, short_dir)); FsResult fat_read_dir_entry( - FatDirIterator *iter, DEF_MRET(string_t, name), - DEF_MRET(ShortDir, short_dir)); -FsResult fat32_search_dir( + FatDirIterator *iter, DEF_MRET(ShortDir, short_dir)); +FsResult fat32_dir_lookup( struct FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, - bool is_directory, DEF_MRET(FatDirEntry *, entry)); -FsResult fat_search_dir( + DEF_MRET(struct FatLocation, location), DEF_MRET(ShortDir, short_dir)); +FsResult fat_dir_lookup( struct FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, - bool is_directory, DEF_MRET(FatDirEntry *, entry)); + DEF_MRET(struct FatLocation, location), DEF_MRET(ShortDir, short_dir)); void entry_cache_init( struct FatInfo *fat_info, FatDirEntry *entry, size_t cache_size); bool fat_dir_is_empty(struct FatInfo *fat_info, FatDirEntry *parent_entry); diff --git a/src/fs/fat/include/entry.h b/src/fs/fat/include/entry.h index 2ff49ef..e1315b2 100644 --- a/src/fs/fat/include/entry.h +++ b/src/fs/fat/include/entry.h @@ -13,14 +13,14 @@ FsResult fat_entry_write( struct FatInfo *fat_info, struct FatDirEntry *parent_entry, int cluster, int number, uint8_t *entry); FatDirEntry *generate_dir_entry( - struct FatInfo *fat_info, FatDirEntry *parent_entry, ShortDir *short_dir, - string_t name, bool is_directory, uint32_t cluster, uint32_t number, - uint32_t longname_cluster, uint32_t longname_number); + struct FatInfo *fat_info, struct FatDirEntry *parent_entry, + ShortDir *short_dir, string_t name, struct FatLocation *location, + ObjectAttr *attr); FsResult fat_create_entry( struct FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, bool is_directory, FatDirEntry **out_entry); FsResult fat_delete_entry( - struct FatInfo *fat_info, FatDirEntry *parent, FatDirEntry *entry, - string_t name); + struct FatInfo *fat_info, FatDirEntry *parent, + struct FatLocation *location); #endif \ No newline at end of file diff --git a/src/fs/fat/include/fat.h b/src/fs/fat/include/fat.h index 88c1c8f..f027565 100644 --- a/src/fs/fat/include/fat.h +++ b/src/fs/fat/include/fat.h @@ -100,13 +100,21 @@ typedef struct FatInfo { FatDirEntry root_entry; } FatInfo; +typedef struct FatLocation { + uint32_t longname_cluster; // 长文件名所在簇号 + uint32_t longname_offset; // 长文件名所在簇内的序号 + uint32_t shortname_cluster; // 短文件名所在簇号 + uint32_t shortname_offset; // 短文件名所在簇内的序号 + uint32_t parent_cluster; // 父目录所在簇号 + uint32_t first_cluster; // 文件数据所在簇号 +} FatLocation; + typedef struct FatPrivOps { - FsResult (*fat_search_dir)( + FsResult (*fat_dir_lookup)( struct FatInfo *fat_info, FatDirEntry *parent_entry, string_t name, - bool is_directory, DEF_MRET(FatDirEntry *, entry)); + DEF_MRET(FatLocation, location), DEF_MRET(ShortDir, short_dir)); FsResult (*fat_read_dir_entry)( - FatDirIterator *iter, DEF_MRET(string_t, name), - DEF_MRET(ShortDir, short_dir)); + FatDirIterator *iter, DEF_MRET(ShortDir, short_dir)); } FatPrivOps; #endif \ No newline at end of file diff --git a/src/fs/fat/name.c b/src/fs/fat/name.c index ec517fc..15f0607 100644 --- a/src/fs/fat/name.c +++ b/src/fs/fat/name.c @@ -286,10 +286,12 @@ FsResult long_name2short_name( name.length = base_name_len + ext_name_len + 1; name.max_length = name.length; + FatLocation location; + ShortDir short_dir; if (!flag && check_short_name((uint8_t *)short_name, 11, dot)) { // 完全满足短文件名条件,检查是否重名 - return fat_info->ops->fat_search_dir( - fat_info, parent, name, is_directory, NULL); + return fat_info->ops->fat_dir_lookup( + fat_info, parent, name, &location, &short_dir); } else { for (int n = 1; n < 999999; n++) { // 统计位数 @@ -304,8 +306,8 @@ FsResult long_name2short_name( short_name->base[i] = '~'; // 检查是否重名 - FsResult result = fat_info->ops->fat_search_dir( - fat_info, parent, name, is_directory, NULL); + FsResult result = fat_info->ops->fat_dir_lookup( + fat_info, parent, name, &location, &short_dir); if (result == FS_ERROR_CANNOT_FIND) { // 找不到说明可用 return FS_OK; diff --git a/src/include/fs/fs.h b/src/include/fs/fs.h index 8424241..9a177ca 100644 --- a/src/include/fs/fs.h +++ b/src/include/fs/fs.h @@ -39,8 +39,8 @@ typedef struct FileSystemOps { struct Volume; typedef struct FsFileOps { FsResult (*fs_open)( - struct FileSystemInfo *fs_info, Object *parent_obj, string_t name, - struct Object **object); + struct FileSystemInfo *fs_info, Object *parent_obj, ObjectAttr *attr, + string_t *name, Object **object); FsResult (*fs_close)(struct Object *object); FsResult (*fs_seek)(struct Object *object, size_t offset); FsResult (*fs_read)(struct Object *file, void *buf, size_t size); @@ -50,19 +50,25 @@ typedef struct FsFileOps { } FsFileOps; typedef struct FsDirectoryOps { + FsResult (*fs_lookup)( + struct FileSystemInfo *fs_info, Object *parent_obj, string_t *name, + ObjectAttr **attr); FsResult (*fs_opendir)( struct FileSystemInfo *fs_info, Object *parent_obj, void **iterator); FsResult (*fs_readdir)( - struct FileSystemInfo *fs_info, void *iterator, Object **object); - FsResult (*fs_closedir)(void *iterator); + struct FileSystemInfo *fs_info, ObjectIterator *iterator, + Object **object); + FsResult (*fs_closedir)(ObjectIterator *iterator); FsResult (*fs_create_file)( - struct Object *parent_obj, string_t name, struct Object **object); - FsResult (*fs_delete_file)(struct Object *parent_obj, string_t name); + struct Object *parent_obj, string_t *name, struct Object **object); + FsResult (*fs_delete_file)( + struct Object *parent_obj, ObjectAttr *attr, string_t *name); FsResult (*fs_mkdir)( - struct Object *parent_obj, string_t name, struct Object **object); - FsResult (*fs_rmdir)(struct Object *parent_obj, string_t name); + struct Object *parent_obj, string_t *name, struct Object **object); + FsResult (*fs_rmdir)( + struct Object *parent_obj, ObjectAttr *attr, string_t *name); FsResult (*fs_get_attr)(struct Object *object, struct ObjectAttr *attr); FsResult (*fs_set_attr)(struct Object *object, struct ObjectAttr *attr); diff --git a/src/include/objects/object.h b/src/include/objects/object.h index acdff2a..5679c2c 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -57,6 +57,9 @@ typedef struct ObjectAttr { Permission admin_permission; list_t permission_lh; + + struct Object *object; + void *fs_location; } ObjectAttr; struct Partition; @@ -71,7 +74,7 @@ typedef struct Object { uint32_t reference; - ObjectAttr attr; + ObjectAttr *attr; struct Object *origin; struct FileSystemInfo *fs_info; @@ -146,6 +149,8 @@ extern Object driver_object; extern Object device_object; extern Object volumes_object; +void init_object_directory(Object *object); +void init_base_obj_sys_attr(Object *object); ObjectResult init_object_tree(); ObjectResult add_object(Object *parent, Object *child); // 通过路径打开对象,对于符号链接会自动解析 diff --git a/src/include/objects/ops.h b/src/include/objects/ops.h index bd14984..e008858 100644 --- a/src/include/objects/ops.h +++ b/src/include/objects/ops.h @@ -11,15 +11,19 @@ #define OBJ_READ_INTERRUPT(object) (object)->in.interrupt #define OBJ_WRITE_INTERRUPT(object) (object)->out.interrupt -ObjectResult obj_open(Object *parent, DEF_MRET(Object *, child), string_t name); +ObjectResult obj_lookup( + Object *parent, string_t *name, DEF_MRET(ObjectAttr *, attr)); +ObjectResult obj_open( + Object *parent, ObjectAttr *attr, string_t *name, + DEF_MRET(Object *, child)); ObjectResult obj_close(Object *object); ObjectResult obj_opendir(Object *parent, DEF_MRET(ObjectIterator *, iter)); ObjectResult obj_readdir(ObjectIterator *iterator, DEF_MRET(Object *, object)); ObjectResult obj_closedir(ObjectIterator *iterator); -ObjectResult obj_create_file(Object *parent, string_t name); -ObjectResult obj_delete_file(Object *parent, string_t name); -ObjectResult obj_mkdir(Object *parent, string_t name); -ObjectResult obj_rmdir(Object *parent, string_t name); +ObjectResult obj_create_file(Object *parent, string_t *name); +ObjectResult obj_delete_file(Object *parent, ObjectAttr *attr, string_t *name); +ObjectResult obj_mkdir(Object *parent, string_t *name); +ObjectResult obj_rmdir(Object *parent, ObjectAttr *attr, string_t *name); ObjectResult obj_get_attr(Object *object, ObjectAttr *attr); ObjectResult obj_set_attr(Object *object, ObjectAttr *attr); diff --git a/src/include/objects/permission.h b/src/include/objects/permission.h index 4a67bd4..5b518ee 100644 --- a/src/include/objects/permission.h +++ b/src/include/objects/permission.h @@ -23,6 +23,7 @@ typedef struct Permission { } Permission; struct Object; -Permission *get_permission_info(struct Object *object); +struct ObjectAttr; +Permission *get_permission_info(struct ObjectAttr *attr); #endif \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index f8ab27b..93e7211 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -4,7 +4,6 @@ * @brief 内核主程序 * @date 2020-03 */ -#include "objects/permission.h" #include "string.h" #include #include @@ -91,14 +90,16 @@ int main() { do_initcalls(); driver_start_all(); - // uint8_t buf[512]; - // Object *object; - // ObjectResult result = - // open_object_by_path("\\Volumes\\Storage0Volume0\\", &object); - // if (result != OBJECT_OK) { - // printk("Open File Error!\n"); - // } else { - // } + uint8_t buf[128]; + Object *object; + ObjectResult result = open_object_by_path( + "\\Volumes\\Storage0Volume0\\boot\\grub\\grub.cfg", &object); + if (result != OBJECT_OK) { + printk("Open File Error!\n"); + } else { + TRANSFER_IN_STREAM(object, buf, 128); + printk("%s", buf); + } // const string_t name = STRING_INIT("A folder"); // obj_rmdir(object, name); @@ -107,20 +108,20 @@ int main() { // Object *object; // ObjectResult result = // open_object_by_ascii_path("\\Device\\Storage0\\Partition0", - // &object); if (result != OBJECT_OK) { printk("Open Storage0 - // Error!\n"); } uint8_t buf[512]; TRANSFER_IN_BLOCK(object)(object, - // TRANSFER_IN, buf, 0, 1, &handle); + // &object); + // if (result != OBJECT_OK) { + // } // bool is_done; // do { // TRANSFER_IN_IS_DONE(object)(object, &handle, &is_done); // } while (!is_done); - // print_hex(buf, 512); // show_object_tree(); // thread_start( - // "NetworkRxPacketProcess", THREAD_DEFAULT_PRIO, net_process_pack, NULL); + // "NetworkRxPacketProcess", THREAD_DEFAULT_PRIO, net_process_pack, + // NULL); // int ret = dhcp_main(default_net_dev); // while (ret == -4) { @@ -135,15 +136,16 @@ int main() { // netc_t *netc = netc_create(default_net_dev, ETH_TYPE_ARP, 0); // netc_set_dest(netc, broadcast_mac, NULL, 0); // router_mac = ip2mac( - // netc, ((struct ipv4_data *)netc->net_dev->info->ipv4_data)->router_ip); - // netc_delete(netc); + // netc, ((struct ipv4_data + // *)netc->net_dev->info->ipv4_data)->router_ip); netc_delete(netc); // netc = netc_create(default_net_dev, ETH_TYPE_IPV4, PROTOCOL_TCP); // netc_set_dest(netc, router_mac, dst_ip, 4); // tcp_create(netc); // tcp_bind(netc, 12345); // tcp_ipv4_connect(netc, dst_ip, 80); - // uint8_t data[] = "GET / HTTP/1.1\r\nHost: 180.101.50.188\r\nAccept: " + // uint8_t data[] = "GET / HTTP/1.1\r\nHost: + // 180.101.50.188\r\nAccept: " // "*/*\r\nConnection: keep-alive\r\n\r\n"; // uint8_t *rb = kmalloc(2048); // tcp_write(netc, data, sizeof(data)); diff --git a/src/objects/mount.c b/src/objects/mount.c index 61a0882..fc4cc71 100644 --- a/src/objects/mount.c +++ b/src/objects/mount.c @@ -3,9 +3,9 @@ #include ObjectResult object_mount(Object *origin, Object *dest) { - if (dest->attr.is_mounted) { return OBJECT_ERROR_INVALID_OPERATION; } - dest->attr.is_mounted = true; - dest->origin = origin; + if (dest->attr->is_mounted) { return OBJECT_ERROR_INVALID_OPERATION; } + dest->attr->is_mounted = true; + dest->origin = origin; dest->fs_info = origin->fs_info; diff --git a/src/objects/objects.c b/src/objects/objects.c index 63073c2..d7db4cd 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -1,12 +1,12 @@ -#include "kernel/list.h" -#include "objects/ops.h" #include #include #include +#include +#include #include #include +#include #include -#include #include #include @@ -18,30 +18,29 @@ const Permission sys_permission = { Object root_object = { .name = STRING_INIT(""), // 根对象的名字不会起到任何作用,所以设为空 .parent = NULL, - .attr = base_obj_sys_attr, }; Object bus_object = { .name = STRING_INIT("Bus"), - .attr = base_obj_sys_attr, }; Object driver_object = { .name = STRING_INIT("Driver"), - .attr = base_obj_sys_attr, }; Object device_object = { .name = STRING_INIT("Device"), - .attr = base_obj_sys_attr, }; Object volumes_object = { .name = STRING_INIT("Volumes"), - .attr = base_obj_sys_attr, }; -static inline void init_object_directory(Object *object) { +void init_object_directory(Object *object) { list_init(&object->value.directory.children); } +void init_base_obj_sys_attr(Object *object) { + object->attr = kmalloc_from_template(base_obj_sys_attr); +} + /** * @brief 初始化对象树 * @@ -53,6 +52,11 @@ ObjectResult init_object_tree() { init_object_directory(&driver_object); init_object_directory(&device_object); init_object_directory(&volumes_object); + init_base_obj_sys_attr(&root_object); + init_base_obj_sys_attr(&bus_object); + init_base_obj_sys_attr(&driver_object); + init_base_obj_sys_attr(&device_object); + init_base_obj_sys_attr(&volumes_object); add_object(&root_object, &driver_object); add_object(&root_object, &bus_object); add_object(&root_object, &device_object); @@ -62,9 +66,8 @@ ObjectResult init_object_tree() { return OBJECT_OK; } -ObjectResult object_open(Object *parent, Object **child, char *path) { - Object *object; - ObjectResult result; +ObjectResult object_open_path(Object *parent, Object **child, char *path) { + Object *object; if (*path == '\0') { *child = parent; @@ -91,23 +94,22 @@ ObjectResult object_open(Object *parent, Object **child, char *path) { name.length = i + 1; name.max_length = i + 1; - if (!is_directory) { - return obj_open(parent, child, name); - } else { - ObjectIterator *iter; - result = obj_opendir(parent, &iter); - while (1) { - result = obj_readdir(iter, &object); - if (result != OBJECT_OK) break; - if (strncmp(object->name.text, name.text, name.length) == 0) { - if (object->attr.type != OBJECT_TYPE_DIRECTORY) continue; - result = object_open(object, child, p); - obj_closedir(iter); - return result; + ObjectAttr *attr; + OBJ_RESULT_PASS(obj_lookup(parent, &name, &attr)); + if ((is_directory && attr->type == OBJECT_TYPE_DIRECTORY) || + !is_directory) { + if (attr->type == OBJECT_TYPE_DIRECTORY) { + if (attr->object != NULL) { + return object_open_path(attr->object, child, p); + } else { + OBJ_RESULT_PASS(obj_open(parent, attr, &name, &object)); + return object_open_path(object, child, p); } + } else { + return obj_open(parent, attr, &name, child); } } - return OBJECT_OK; + return OBJECT_ERROR_CANNOT_FIND; } ObjectResult open_oringinal_object_by_path(char *path, Object **out_object) { @@ -115,13 +117,13 @@ ObjectResult open_oringinal_object_by_path(char *path, Object **out_object) { if (path[0] != '\\') { return OBJECT_ERROR_ILLEGAL_ARGUMENT; } path++; - return object_open(&root_object, out_object, path); + return object_open_path(&root_object, out_object, path); } ObjectResult open_object_by_path(char *path, Object **object) { ObjectResult result = open_oringinal_object_by_path(path, object); if (result == OBJECT_OK) { - while ((*object)->attr.type == OBJECT_TYPE_SYM_LINK) { + while ((*object)->attr->type == OBJECT_TYPE_SYM_LINK) { *object = (*object)->value.sym_link; } } @@ -129,7 +131,7 @@ ObjectResult open_object_by_path(char *path, Object **object) { } ObjectResult add_object(Object *parent, Object *child) { - if (parent->attr.type != OBJECT_TYPE_DIRECTORY) { + if (parent->attr->type != OBJECT_TYPE_DIRECTORY) { return OBJECT_ERROR_INVALID_OPERATION; } @@ -144,7 +146,7 @@ Object *create_object(Object *parent, string_t name, ObjectAttr attr) { if (object == NULL) { return NULL; } object->name = name; - object->attr = attr; + object->attr = kmalloc_from_template(attr); object->parent = parent; object->reference = 0; @@ -159,8 +161,8 @@ Object *create_object(Object *parent, string_t name, ObjectAttr attr) { Object *create_object_directory( Object *parent, string_t name, ObjectAttr attr) { - attr.type = OBJECT_TYPE_DIRECTORY; - Object *object = create_object(parent, name, attr); + Object *object = create_object(parent, name, attr); + object->attr->type = OBJECT_TYPE_DIRECTORY; if (object == NULL) { return NULL; } init_object_directory(object); @@ -182,12 +184,12 @@ void print_object_directory(Object *object, int level) { printk("|\t"); } printk("|-%s", child->name.text); - if (child->attr.type == OBJECT_TYPE_SYM_LINK) { + if (child->attr->type == OBJECT_TYPE_SYM_LINK) { printk("\t->\t"); print_symbol_link(child->value.sym_link); } printk("\n"); - if (child->attr.type == OBJECT_TYPE_DIRECTORY) { + if (child->attr->type == OBJECT_TYPE_DIRECTORY) { print_object_directory(child, level + 1); } } diff --git a/src/objects/ops.c b/src/objects/ops.c index 85d8aab..d292e34 100644 --- a/src/objects/ops.c +++ b/src/objects/ops.c @@ -1,34 +1,47 @@ -#include "kernel/list.h" -#include "kernel/memory.h" -#include "objects/permission.h" -#include "objects/transfer.h" -#include "string.h" #include +#include +#include #include #include #include +#include +#include +#include -ObjectResult obj_search( - Object *parent, DEF_MRET(Object *, child), string_t name, - bool is_directory) { +ObjectResult obj_lookup_cache( + Object *parent, DEF_MRET(Object *, child), string_t *name) { Object *child; list_for_each_owner (child, &parent->value.directory.children, list) { - if (child->name.length == name.length && - strncmp(child->name.text, name.text, name.length) == 0) { - if ((is_directory && child->attr.type == OBJECT_TYPE_DIRECTORY) || - (!is_directory && child->attr.type != OBJECT_TYPE_DIRECTORY)) { - MRET(child) = child; - return OBJECT_OK; - } + if (child->name.length == name->length && + strncmp(child->name.text, name->text, name->length) == 0) { + MRET(child) = child; + return OBJECT_OK; } } return OBJECT_ERROR_CANNOT_FIND; } +ObjectResult obj_lookup( + Object *parent, string_t *name, DEF_MRET(ObjectAttr *, attr)) { + Object *child; + ObjectResult result = obj_lookup_cache(parent, &child, name); + if (result == OBJECT_OK) { + MRET(attr) = child->attr; + return OBJECT_OK; + } + if (parent->fs_info != NULL) { + FsResult result = parent->fs_info->dir_ops.fs_lookup( + parent->fs_info, parent, name, &MRET(attr)); + if (result == FS_OK) return OBJECT_OK; + } + return OBJECT_ERROR_CANNOT_FIND; +} + ObjectResult obj_open( - Object *parent, DEF_MRET(Object *, child), string_t name) { + Object *parent, ObjectAttr *attr, string_t *name, + DEF_MRET(Object *, child)) { Object *child; - ObjectResult result = obj_search(parent, &child, name, false); + ObjectResult result = obj_lookup_cache(parent, &child, name); if (result == OBJECT_OK) { MRET(child) = child; child->reference++; @@ -37,8 +50,8 @@ ObjectResult obj_open( // 如果缓存中找不到,则调用文件系统接口读取 else if (parent->fs_info != NULL) { FsResult result = parent->fs_info->file_ops.fs_open( - parent->fs_info, parent, name, &MRET(child)); - child->reference++; + parent->fs_info, parent, attr, name, &MRET(child)); + MRET(child)->reference++; if (result == FS_OK) return OBJECT_OK; } return OBJECT_ERROR_CANNOT_FIND; @@ -46,17 +59,14 @@ ObjectResult obj_open( ObjectResult obj_opendir(Object *parent, DEF_MRET(ObjectIterator *, iter)) { ObjectIterator *iter = kmalloc(sizeof(ObjectIterator)); - iter->current_node = parent->value.directory.children.next; - iter->type = ITERATOR_TYPE_MEM; if (parent->fs_info != NULL) { - if (parent->value.directory.fs_iterator == NULL) { - FsResult result = parent->fs_info->dir_ops.fs_opendir( - parent->fs_info, parent, &iter->fs_iterator); - if (result != FS_OK) return OBJECT_ERROR_CANNOT_FIND; - iter->type = ITERATOR_TYPE_FS; - } else { - iter->fs_iterator = parent->value.directory.fs_iterator; - } + iter->type = ITERATOR_TYPE_FS; + FsResult result = parent->fs_info->dir_ops.fs_opendir( + parent->fs_info, parent, &iter->fs_iterator); + if (result != FS_OK) return OBJECT_ERROR_CANNOT_FIND; + } else { + iter->type = ITERATOR_TYPE_MEM; + iter->current_node = parent->value.directory.children.next; } MRET(iter) = iter; @@ -66,18 +76,14 @@ ObjectResult obj_opendir(Object *parent, DEF_MRET(ObjectIterator *, iter)) { ObjectResult obj_readdir(ObjectIterator *iterator, DEF_MRET(Object *, object)) { if (iterator->type == ITERATOR_TYPE_FS) { FsResult result = iterator->parent_object->fs_info->dir_ops.fs_readdir( - iterator->parent_object->value.directory.data, - iterator->fs_iterator, &MRET(object)); + iterator->parent_object->value.directory.data, iterator, + &MRET(object)); if (result == FS_ERROR_CANNOT_FIND) return OBJECT_ERROR_CANNOT_FIND; else if (result != FS_OK) return OBJECT_ERROR_CANNOT_FIND; } else { if (iterator->current_node == &iterator->parent_object->value.directory.children) { - if (iterator->fs_iterator) { - iterator->parent_object->fs_info->dir_ops.fs_readdir( - iterator->parent_object->value.directory.data, - iterator->fs_iterator, &MRET(object)); - } else return OBJECT_ERROR_CANNOT_FIND; + return OBJECT_ERROR_CANNOT_FIND; } MRET(object) = list_owner(iterator->current_node, Object, list); @@ -90,8 +96,7 @@ ObjectResult obj_closedir(ObjectIterator *iterator) { if (iterator->type == ITERATOR_TYPE_FS) { if (iterator->fs_iterator != NULL) { FsResult result = - iterator->parent_object->fs_info->dir_ops.fs_closedir( - iterator->fs_iterator); + iterator->parent_object->fs_info->dir_ops.fs_closedir(iterator); if (result != FS_OK) return OBJECT_ERROR_OTHER; } } @@ -103,11 +108,11 @@ ObjectResult obj_close(Object *object) { object->reference--; if (object->reference > 0) return OBJECT_OK; if (object->fs_info == NULL) return OBJECT_OK; - if (!object->attr.is_mounted) { + if (!object->attr->is_mounted) { if (object->release_data != NULL) object->release_data(object); - if (object->attr.type == OBJECT_TYPE_FILE) { + if (object->attr->type == OBJECT_TYPE_FILE) { object->fs_info->file_ops.fs_close(object); - } else if (object->attr.type == OBJECT_TYPE_DIRECTORY) { + } else if (object->attr->type == OBJECT_TYPE_DIRECTORY) { object->fs_info->dir_ops.fs_closedir( object->value.directory.fs_iterator); } @@ -118,9 +123,9 @@ ObjectResult obj_close(Object *object) { return OBJECT_OK; } -ObjectResult obj_create_file(Object *parent, string_t name) { +ObjectResult obj_create_file(Object *parent, string_t *name) { Object *child; - ObjectResult result = obj_search(parent, &child, name, false); + ObjectResult result = obj_lookup_cache(parent, &child, name); if (result == OBJECT_OK) return OBJECT_ERROR_ALREADY_EXISTS; if (parent->fs_info != NULL) { FsResult result = @@ -130,27 +135,28 @@ ObjectResult obj_create_file(Object *parent, string_t name) { return OBJECT_OK; } -ObjectResult obj_delete_file(Object *parent, string_t name) { - Object *child; +ObjectResult obj_delete_file(Object *parent, ObjectAttr *attr, string_t *name) { // 先打开文件检查权限,再决定要不要删除 - OBJ_RESULT_PASS(obj_open(parent, &child, name)); - - if (child->reference > 0) return OBJECT_ERROR_OCCUPIED; - Permission *permission = get_permission_info(child); + Permission *permission = get_permission_info(attr); if (!permission->permission.delete) return OBJECT_ERROR_NO_PERMISSION; - OBJ_RESULT_PASS(obj_close(child)); + + if (attr->object != NULL) { + Object *child = attr->object; + if (child->reference > 0) return OBJECT_ERROR_OCCUPIED; + } if (parent->fs_info != NULL) { - FsResult result = parent->fs_info->dir_ops.fs_delete_file(parent, name); + FsResult result = + parent->fs_info->dir_ops.fs_delete_file(parent, attr, name); if (result != FS_OK) return OBJECT_ERROR_OTHER; } return OBJECT_OK; } -ObjectResult obj_mkdir(Object *parent, string_t name) { +ObjectResult obj_mkdir(Object *parent, string_t *name) { Object *child; - ObjectResult result = obj_search(parent, &child, name, true); + ObjectResult result = obj_lookup_cache(parent, &child, name); if (result == OBJECT_OK) return OBJECT_ERROR_ALREADY_EXISTS; if (parent->fs_info != NULL) { FsResult result = @@ -160,22 +166,21 @@ ObjectResult obj_mkdir(Object *parent, string_t name) { return OBJECT_OK; } -ObjectResult obj_rmdir(Object *parent, string_t name) { - Object *child; +ObjectResult obj_rmdir(Object *parent, ObjectAttr *attr, string_t *name) { // 先打开检查权限,再决定要不要删除 - OBJ_RESULT_PASS(obj_open(parent, &child, name)); - - if (child->reference > 0) return OBJECT_ERROR_OCCUPIED; - Permission *permission = get_permission_info(child); + Permission *permission = get_permission_info(attr); if (!permission->permission.delete) return OBJECT_ERROR_NO_PERMISSION; - if (!child->attr.is_mounted) return OBJECT_ERROR_OCCUPIED; - if (!list_empty(&child->value.directory.children)) - return OBJECT_ERROR_NOT_EMPTY; - OBJ_RESULT_PASS(obj_close(child)); + if (attr->object != NULL) { + Object *child = attr->object; + if (child->reference > 0) return OBJECT_ERROR_OCCUPIED; + if (!child->attr->is_mounted) return OBJECT_ERROR_OCCUPIED; + if (!list_empty(&child->value.directory.children)) + return OBJECT_ERROR_NOT_EMPTY; + } if (parent->fs_info != NULL) { - FsResult result = parent->fs_info->dir_ops.fs_rmdir(parent, name); + FsResult result = parent->fs_info->dir_ops.fs_rmdir(parent, attr, name); if (result == FS_OK) return OBJECT_OK; else if (result == FS_ERROR_NOT_EMPTY) return OBJECT_ERROR_NOT_EMPTY; else return OBJECT_ERROR_OTHER; @@ -184,19 +189,18 @@ ObjectResult obj_rmdir(Object *parent, string_t name) { } ObjectResult obj_get_attr(Object *object, ObjectAttr *attr) { - // 在打开object时会自动生成attr,直接复制即可 - *attr = object->attr; + *attr = *object->attr; return OBJECT_OK; } ObjectResult obj_set_attr(Object *object, ObjectAttr *attr) { - Permission *permission = get_permission_info(object); + Permission *permission = get_permission_info(object->attr); if (!permission->permission.set_attr) return OBJECT_ERROR_NO_PERMISSION; if (object->fs_info != NULL) { FsResult result = object->fs_info->dir_ops.fs_set_attr(object, attr); if (result != FS_OK) return OBJECT_ERROR_OTHER; } - object->attr = *attr; + *object->attr = *attr; return OBJECT_OK; } diff --git a/src/objects/permission.c b/src/objects/permission.c index 3afcb4e..dbb41f5 100644 --- a/src/objects/permission.c +++ b/src/objects/permission.c @@ -4,15 +4,15 @@ #include #include -Permission *get_permission_info(Object *object) { +Permission *get_permission_info(ObjectAttr *attr) { size_t subject_id = get_current_subject_id(); if (subject_id == SUBJECT_ID_SYSTEM) { - return &object->attr.system_permission; - } else if (subject_id == object->attr.owner_id) { - return &object->attr.owner_permission; + return &attr->system_permission; + } else if (subject_id == attr->owner_id) { + return &attr->owner_permission; } else { Permission *permission; - list_for_each_owner (permission, &object->attr.permission_lh, list) { + list_for_each_owner (permission, &attr->permission_lh, list) { if (permission->subject_id == subject_id) return permission; } } diff --git a/src/objects/types.c b/src/objects/types.c index 7ebe5d4..1be501b 100644 --- a/src/objects/types.c +++ b/src/objects/types.c @@ -5,11 +5,8 @@ static int type_number = OBJECT_TYPE_BUILTIN_MAX; -#define DEFINE_OBJECT_TYPE(type_name) \ - { \ - .name = STRING_INIT(#type_name), \ - .value.type = OBJECT_TYPE_##type_name, .attr = base_obj_sys_attr, \ - } +#define DEFINE_OBJECT_TYPE(type_name) \ + { .name = STRING_INIT(#type_name), .value.type = OBJECT_TYPE_##type_name, } Object object_builtin_types[OBJECT_TYPE_BUILTIN_MAX] = { DEFINE_OBJECT_TYPE(TYPE), DEFINE_OBJECT_TYPE(DIRECTORY), @@ -20,15 +17,16 @@ Object object_builtin_types[OBJECT_TYPE_BUILTIN_MAX] = { Object object_type_directory = { .name = STRING_INIT("ObjectType"), - .attr = base_obj_sys_attr, }; ObjectResult init_builtin_types() { - list_init(&object_type_directory.value.directory.children); + init_object_directory(&object_type_directory); + init_base_obj_sys_attr(&object_type_directory); add_object(&root_object, &object_type_directory); for (int i = 0; i < OBJECT_TYPE_BUILTIN_MAX; i++) { add_object(&object_type_directory, &object_builtin_types[i]); + init_base_obj_sys_attr(&object_builtin_types[i]); } return OBJECT_OK; From fdda1c7e1d0c95187debafcd027d8b688acfb5cd Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 10 Mar 2025 16:33:34 +0800 Subject: [PATCH 035/158] update tool --- tools/imagetool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/imagetool b/tools/imagetool index e413271..de2b403 160000 --- a/tools/imagetool +++ b/tools/imagetool @@ -1 +1 @@ -Subproject commit e41327101e70d4ce1ea4f49a123a7845b92a61eb +Subproject commit de2b403d546b5b67af8cc9004c646528769ccf4b From ae79adc07cae65fbadce5f071fbbe50d3e049eb2 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 19 Mar 2025 23:22:38 +0800 Subject: [PATCH 036/158] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E7=BB=93=E6=9E=84=EF=BC=9B=E4=BF=AE=E5=A4=8D=20=E5=B7=B2?= =?UTF-8?q?=E7=9F=A5bug=EF=BC=9B=E4=BF=AE=E6=94=B9=20storage=5Fio=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E8=AF=B7=E6=B1=82=E9=80=BB=E8=BE=91=EF=BC=9B=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20isa=E6=80=BB=E7=BA=BF=E9=A9=B1=E5=8A=A8=EF=BC=9B?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20ISA=20DMA=E9=94=81=EF=BC=8C=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E8=AE=A1=E6=95=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/8259a.c | 4 +- src/arch/x86/drivers/Makefile | 5 +- src/arch/x86/drivers/apic.c | 8 +- src/arch/x86/drivers/bus/Makefile | 2 + src/arch/x86/drivers/bus/isa/Makefile | 2 + src/arch/x86/drivers/bus/isa/dma.c | 190 ++++++++++++++++++ src/arch/x86/drivers/bus/isa/isa.c | 141 +++++++++++++ src/arch/x86/drivers/bus/pci/Makefile | 1 + src/arch/x86/drivers/{ => bus/pci}/pci.c | 13 +- src/arch/x86/drivers/disk/ata/ata_driver.c | 2 +- src/arch/x86/drivers/disk/ata/ide.c | 29 +-- .../x86/drivers/disk/ata/ide_controller.c | 6 +- .../drivers/disk/ata/include/ide_controller.h | 2 +- src/arch/x86/drivers/dma.c | 98 --------- src/arch/x86/drivers/network/rtl8139.c | 4 +- src/arch/x86/drivers/pit.c | 4 +- src/arch/x86/drivers/usb/hci/uhci.c | 2 +- src/arch/x86/drivers/vesa_display.c | 4 +- src/arch/x86/include/drivers/bus/isa/dma.h | 94 +++++++++ src/arch/x86/include/drivers/bus/isa/isa.h | 26 +++ .../x86/include/drivers/{ => bus/pci}/pci.h | 0 src/arch/x86/include/drivers/dma.h | 70 ------- src/arch/x86/include/drivers/usb/uhci.h | 2 +- src/arch/x86/include/kernel/func.h | 2 + src/arch/x86/include/kernel/thread.h | 14 +- src/arch/x86/kernel/func.asm | 12 +- src/arch/x86/kernel/platform.c | 4 + src/driver/storage/disk/disk.c | 30 +-- src/driver/storage/storage_dm.c | 6 +- src/driver/storage/storage_io.c | 8 +- src/driver/storage/storage_io_queue.c | 102 ++++++---- src/driver/time_dm.c | 2 +- src/driver/video_dm.c | 2 +- src/include/driver/storage/disk/disk.h | 19 +- src/include/kernel/device_driver.h | 4 +- src/include/kernel/dma.h | 28 +++ src/include/kernel/driver.h | 9 + src/include/kernel/driver_interface.h | 10 +- src/include/kernel/memory.h | 1 - src/include/kernel/spinlock.h | 15 ++ src/include/objects/transfer.h | 75 +++---- src/kernel/bus_driver.c | 2 +- src/kernel/condvar.c | 4 +- src/kernel/device_manager.c | 5 +- src/kernel/driver.c | 16 ++ src/kernel/driver_dependency.c | 3 +- src/kernel/thread.c | 71 ++++--- src/kernel/wait_queue.c | 30 +-- src/lib/dyn_array.c | 3 +- src/network/arp.c | 3 +- src/objects/objects.c | 12 +- 51 files changed, 820 insertions(+), 381 deletions(-) create mode 100644 src/arch/x86/drivers/bus/Makefile create mode 100644 src/arch/x86/drivers/bus/isa/Makefile create mode 100644 src/arch/x86/drivers/bus/isa/dma.c create mode 100644 src/arch/x86/drivers/bus/isa/isa.c create mode 100644 src/arch/x86/drivers/bus/pci/Makefile rename src/arch/x86/drivers/{ => bus/pci}/pci.c (95%) delete mode 100644 src/arch/x86/drivers/dma.c create mode 100644 src/arch/x86/include/drivers/bus/isa/dma.h create mode 100644 src/arch/x86/include/drivers/bus/isa/isa.h rename src/arch/x86/include/drivers/{ => bus/pci}/pci.h (100%) delete mode 100644 src/arch/x86/include/drivers/dma.h create mode 100644 src/include/kernel/dma.h diff --git a/src/arch/x86/drivers/8259a.c b/src/arch/x86/drivers/8259a.c index 09bce3c..6187b30 100644 --- a/src/arch/x86/drivers/8259a.c +++ b/src/arch/x86/drivers/8259a.c @@ -31,8 +31,8 @@ void pic_eoi(InterruptDevice *device, int irq); extern Driver core_driver; DeviceDriverOps pic_device_driver_ops = { - .register_driver_hook = NULL, - .unregister_driver_hook = NULL, + .device_driver_init = NULL, + .device_driver_uninit = NULL, }; DeviceOps pic_device_ops = { .init = pic_init, diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index 50a6d32..e993baf 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -4,8 +4,6 @@ SRC += acpi.c SRC += apic.c SRC += cpufreq.c SRC += disk.c -SRC += pci.c -SRC += dma.c #SRC += keyboard.c #SRC += mouse.c SRC += msr.c @@ -14,6 +12,7 @@ SRC += smbios.c SRC += vesa_display.c SRC += cmos.c #SRC += network/ -#SRC += sound/ +SRC += sound/ #SRC += usb/ +SRC += bus/ SRC += disk/ \ No newline at end of file diff --git a/src/arch/x86/drivers/apic.c b/src/arch/x86/drivers/apic.c index f4a097d..a87119d 100644 --- a/src/arch/x86/drivers/apic.c +++ b/src/arch/x86/drivers/apic.c @@ -85,8 +85,8 @@ uint32_t lapic_read(int index) { } DeviceDriverOps apic_device_driver_ops = { - .register_driver_hook = NULL, - .unregister_driver_hook = NULL, + .device_driver_init = NULL, + .device_driver_uninit = NULL, }; DeviceOps apic_device_ops = { .init = apic_init, @@ -103,8 +103,8 @@ InterruptDeviceOps apic_interrupt_ops = { }; DeviceDriverOps apic_timer_device_driver_ops = { - .register_driver_hook = NULL, - .unregister_driver_hook = NULL, + .device_driver_init = NULL, + .device_driver_uninit = NULL, }; DeviceOps apic_timer_device_ops = { .init = apic_timer_init, diff --git a/src/arch/x86/drivers/bus/Makefile b/src/arch/x86/drivers/bus/Makefile new file mode 100644 index 0000000..5bda361 --- /dev/null +++ b/src/arch/x86/drivers/bus/Makefile @@ -0,0 +1,2 @@ +SRC += pci/ +SRC += isa/ \ No newline at end of file diff --git a/src/arch/x86/drivers/bus/isa/Makefile b/src/arch/x86/drivers/bus/isa/Makefile new file mode 100644 index 0000000..df21898 --- /dev/null +++ b/src/arch/x86/drivers/bus/isa/Makefile @@ -0,0 +1,2 @@ +SRC += isa.c +SRC += dma.c \ No newline at end of file diff --git a/src/arch/x86/drivers/bus/isa/dma.c b/src/arch/x86/drivers/bus/isa/dma.c new file mode 100644 index 0000000..f91704c --- /dev/null +++ b/src/arch/x86/drivers/bus/isa/dma.c @@ -0,0 +1,190 @@ +/** + * @file dma.c + * @author Ryan Wang (ryan1202@foxmail.com) + * @brief (ISA)DMA驱动 + * @version 0.1 + * @date 2021-7 + */ +#include "kernel/driver.h" +#include "math.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DmaOps isa_dma_ops = { + .dma_alloc = dma_alloc_region, + .dma_free = dma_free_region, +}; + +#define DMA_MEM_BASE_ADDR 0x800000 + +Device *dma_channels[8]; // 使用DMA通道的设备 + +struct mmap dma_mem_mmap; +spinlock_t dma_spin_lock; + +int dma_lock() { + return spin_lock_irqsave(&dma_spin_lock); +} + +void dma_unlock(int flags) { + spin_unlock_irqrestore(&dma_spin_lock, flags); +} + +void dma_init() { + spinlock_init(&dma_spin_lock); + dma_mem_mmap.bits = kmalloc(DMA_MAX_REGION_COUNT / 8); + dma_mem_mmap.len = DMA_MAX_REGION_COUNT / 8; + memset(dma_mem_mmap.bits, 0, dma_mem_mmap.len); +} + +void *dma_alloc_region(void *dma, uint32_t size) { + int cnt = DIV_ROUND_UP(size, 64 * 1024); + int idx = mmap_search(&dma_mem_mmap, cnt); + if (idx == -1) return NULL; + + for (int i = 0; i < cnt; i++) { + mmap_set(&dma_mem_mmap, idx + i, 1); + } + return (void *)(DMA_MEM_BASE_ADDR + idx * DMA_REGION_SIZE); +} + +DriverResult dma_free_region(void *dma, void *ptr, uint32_t size) { + int cnt = DIV_ROUND_UP(size, 64 * 1024); + int idx = ((uint32_t)ptr - DMA_MEM_BASE_ADDR) / DMA_REGION_SIZE; + for (int i = 0; i < cnt; i++) { + mmap_set(&dma_mem_mmap, idx + i, 0); + } + return DRIVER_RESULT_OK; +} + +uint32_t get_dma_count(int channel) { + uint16_t count; + uint8_t port; + if (channel < 4) { + port = DMA0 + (channel << 1) + 1; + } else { + port = DMA1 + ((channel & 3) << 2) + 2; + } + count = io_in8(port); + count += io_in8(port) << 8; + count++; + return channel < 4 ? count : count << 1; +} + +uint32_t dma_pointer(int channel, uint32_t size) { + uint32_t result; + + int flags = dma_lock(); + dma_ff_reset(channel); + result = get_dma_count(channel); + dma_unlock(flags); + + if (result >= size || result == 0) return 0; + else return size - result; +} + +int dma_channel_use(Device *device, int *possible_ch, int len) { + for (int i = 0; i < len; i++) { + if (dma_channels[possible_ch[i]] == NULL) { + dma_channels[possible_ch[i]] = device; + return possible_ch[i]; + } + } + return -1; +} + +void dma_channel_unuse(Device *device, uint8_t channel) { + if (channel < 8) { + if (dma_channels[channel] == device) dma_channels[channel] = NULL; + } +} + +void dma_enable(unsigned int channel) { + if (channel < 4) { + io_out8(DMA1_REG_MASK, channel); + } else { + io_out8(DMA2_REG_MASK, channel & 3); + } +} + +void dma_disable(unsigned int channel) { + if (channel < 4) { + io_out8(DMA1_REG_MASK, channel | 4); + } else { + io_out8(DMA2_REG_MASK, (channel & 3) | 4); + } +} + +void dma_ff_reset(unsigned int channel) { + if (channel < 4) { + io_out8(DMA1_REG_FF_RESET, 0); + } else { + io_out8(DMA2_REG_FF_RESET, 0); + } +} + +void dma_set_mode(unsigned int channel, char mode) { + if (channel < 4) { + io_out8(DMA1_REG_MODE, mode | channel); + } else { + io_out8(DMA2_REG_MODE, mode | (channel & 3)); + } +} + +void dma_set_page(unsigned int channel, char page) { + switch (channel) { + case 0: + io_out8(DMA_PAGE0, page); + break; + case 1: + io_out8(DMA_PAGE1, page); + break; + case 2: + io_out8(DMA_PAGE2, page); + break; + case 3: + io_out8(DMA_PAGE3, page); + break; + case 5: + io_out8(DMA_PAGE5, page & 0xfe); + break; + case 6: + io_out8(DMA_PAGE6, page & 0xfe); + break; + case 7: + io_out8(DMA_PAGE7, page & 0xfe); + break; + + default: + break; + } +} + +void dma_set_addr(unsigned int channel, unsigned int addr) { + dma_set_page(channel, addr >> 16); + if (channel <= 3) { + io_out8(DMA0 + ((channel & 3) << 1), addr & 0xff); + io_out8(DMA0 + ((channel & 3) << 1), (addr >> 8) & 0xff); + } else { + io_out8(DMA1 + ((channel & 3) << 2), (addr >> 1) & 0xff); + io_out8(DMA1 + ((channel & 3) << 2), (addr >> 9) & 0xff); + } +} + +void dma_set_count(unsigned int channel, unsigned int count) { + count--; + if (channel <= 3) { + io_out8(DMA0 + ((channel & 3) << 1) + 1, count & 0xff); + io_out8(DMA0 + ((channel & 3) << 1) + 1, (count >> 8) & 0xff); + } else { + io_out8(DMA1 + ((channel & 3) << 2) + 2, (count >> 1) & 0xff); + io_out8(DMA1 + ((channel & 3) << 2) + 2, (count >> 9) & 0xff); + } +} diff --git a/src/arch/x86/drivers/bus/isa/isa.c b/src/arch/x86/drivers/bus/isa/isa.c new file mode 100644 index 0000000..8331d6e --- /dev/null +++ b/src/arch/x86/drivers/bus/isa/isa.c @@ -0,0 +1,141 @@ +#include "kernel/initcall.h" +#include "objects/object.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LIST_HEAD(isa_driver_lh); + +DriverResult isa_driver_init(Driver *driver); +DriverResult isa_probe(BusDriver *bus_driver, Bus *bus); +DriverResult isa_init_bus(BusDriver *bus_driver); + +DeviceDriverOps isa_driver_ops = { + .device_driver_init = NULL, + .device_driver_uninit = NULL, +}; +DeviceOps isa_device_ops = { + .init = NULL, + .start = NULL, + .stop = NULL, + .destroy = NULL, + .status = NULL, +}; +BusDriverOps isa_bus_driver_ops = { + .register_bus_hook = NULL, + .unregister_bus_hook = NULL, + .init = isa_init_bus, +}; +BusOps isa_bus_ops = { + .register_device_hook = NULL, + .unregister_device_hook = NULL, + .scan_bus = NULL, + .probe_device = isa_probe, +}; +BusControllerDeviceOps isa_controller_ops = { + .probe = NULL, +}; + +DriverDependency isa_dependencies[] = { + { + .in_type = DRIVER_DEPENDENCY_TYPE_BUS, + .dependency_in_bus = {BUS_TYPE_PLATFORM, 0}, + .out_bus = NULL, + }, +}; +Driver isa_driver = { + .short_name = STRING_INIT("PciDriver"), + .dependency_count = sizeof(isa_dependencies) / sizeof(DriverDependency), + .dependencies = isa_dependencies, + .init = isa_driver_init, +}; +DeviceDriver isa_device_driver = { + .name = STRING_INIT("ISA Device Driver"), + .bus = NULL, + .type = DEVICE_TYPE_BUS_CONTROLLER, + .state = DRIVER_STATE_UNREGISTERED, + .private_data_size = 0, + .ops = &isa_driver_ops, +}; +Device isa_device = { + .name = STRING_INIT("ISA Controller"), + .state = DEVICE_STATE_UNREGISTERED, + .bus = &platform_bus, + .private_data_size = 0, + .ops = &isa_device_ops, +}; +BusDriver isa_bus_driver = { + .name = STRING_INIT("ISA"), + .driver_type = DRIVER_TYPE_BUS_DRIVER, + .bus_type = BUS_TYPE_ISA, + .state = DRIVER_STATE_UNREGISTERED, + .private_data_size = 0, + .ops = &isa_bus_driver_ops, +}; +BusControllerDevice isa_bus_controller_device = { + .short_name = STRING_INIT("ISA"), + .device = &isa_device, + .bus_driver = &isa_bus_driver, + .bus_controller_ops = &isa_controller_ops, +}; +Bus isa_bus = { + .bus_num = 0, + .bus_driver = &isa_bus_driver, + .controller_device = &isa_device, + .ops = &isa_bus_ops, +}; + +DriverResult isa_register_device_driver( + DeviceDriver *device_driver, IsaOps *ops) { + IsaDeviceDriver *isa_device_driver = kmalloc(sizeof(IsaDeviceDriver)); + if (isa_device_driver == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } + + isa_device_driver->device_driver = device_driver; + isa_device_driver->ops = ops; + list_add_tail(&isa_device_driver->list, &isa_driver_lh); + + return DRIVER_RESULT_OK; +} + +DriverResult isa_probe(BusDriver *bus_driver, Bus *bus) { + IsaDeviceDriver *isa_device_driver; + list_for_each_owner (isa_device_driver, &isa_driver_lh, list) { + isa_device_driver->bus_driver = bus_driver; + isa_device_driver->bus = bus; + isa_device_driver->ops->probe(isa_device_driver); + } + return DRIVER_RESULT_OK; +} + +DriverResult isa_init_bus(BusDriver *bus_driver) { + isa_bus_driver.bus_count = 1; + + ObjectAttr attr = device_object_attr; + register_bus(&isa_bus_driver, &isa_device, &isa_bus, &attr); + return DRIVER_RESULT_OK; +} + +DriverResult isa_driver_init(Driver *driver) { + isa_device_driver.bus = isa_dependencies[0].out_bus; + ObjectAttr attr = device_object_attr; + DRIVER_RESULT_PASS(register_bus_controller_device( + &isa_device_driver, &isa_bus_driver, &isa_device, + &isa_bus_controller_device, &attr)); + return DRIVER_RESULT_OK; +} + +static void __init isa_initcall(void) { + register_driver(&isa_driver); + register_device_driver(&isa_driver, &isa_device_driver); + ObjectAttr attr = driver_object_attr; + register_bus_driver(&isa_driver, &isa_bus_driver, &attr); +} + +driver_initcall(isa_initcall); diff --git a/src/arch/x86/drivers/bus/pci/Makefile b/src/arch/x86/drivers/bus/pci/Makefile new file mode 100644 index 0000000..7a5d8a6 --- /dev/null +++ b/src/arch/x86/drivers/bus/pci/Makefile @@ -0,0 +1 @@ +SRC += pci.c \ No newline at end of file diff --git a/src/arch/x86/drivers/pci.c b/src/arch/x86/drivers/bus/pci/pci.c similarity index 95% rename from src/arch/x86/drivers/pci.c rename to src/arch/x86/drivers/bus/pci/pci.c index a51d4d8..b753f7d 100644 --- a/src/arch/x86/drivers/pci.c +++ b/src/arch/x86/drivers/bus/pci/pci.c @@ -8,7 +8,7 @@ #include "kernel/list.h" #include "objects/object.h" #include -#include +#include #include #include #include @@ -37,8 +37,8 @@ DriverResult pci_init_bus(BusDriver *bus_driver); DriverResult pci_probe(BusDriver *bus_driver, Bus *bus); DeviceDriverOps pci_driver_ops = { - .register_driver_hook = NULL, - .unregister_driver_hook = NULL, + .device_driver_init = NULL, + .device_driver_uninit = NULL, }; DeviceOps pci_device_ops = { .init = pci_device_init, @@ -639,12 +639,11 @@ DriverResult pci_probe(BusDriver *bus_driver, Bus *bus) { } DriverResult pci_driver_init(Driver *driver) { - check_dependency(&pci_driver); pci_device_driver.bus = pci_dependencies[0].out_bus; ObjectAttr attr = device_object_attr; - DRV_RESULT_DELIVER_CALL( - register_bus_controller_device, &pci_device_driver, &pci_bus_driver, - &pci_device, &pci_bus_controller_device, &attr); + DRIVER_RESULT_PASS(register_bus_controller_device( + &pci_device_driver, &pci_bus_driver, &pci_device, + &pci_bus_controller_device, &attr)); return DRIVER_RESULT_OK; } diff --git a/src/arch/x86/drivers/disk/ata/ata_driver.c b/src/arch/x86/drivers/disk/ata/ata_driver.c index a70fa96..3d8281a 100644 --- a/src/arch/x86/drivers/disk/ata/ata_driver.c +++ b/src/arch/x86/drivers/disk/ata/ata_driver.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index e7d70df..ad8a302 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -35,8 +35,8 @@ StorageDeviceOps ide_storage_device_ops = { .is_busy = ide_device_is_busy, }; DeviceDriverOps ide_device_driver_ops = { - .register_driver_hook = NULL, - .unregister_driver_hook = NULL, + .device_driver_init = NULL, + .device_driver_uninit = NULL, }; DeviceOps ide_device_ops = { .init = ide_device_init, @@ -62,9 +62,10 @@ Device ide_device_template = { .private_data_size = sizeof(IdeDevice), }; StorageDevice storage_device_template = { - .block_size = 512, - .type = STORAGE_DEVICE_TYPE_HARDDISK, - .ops = &ide_storage_device_ops, + .block_size = SECTOR_SIZE, + .max_block_per_request = 256, + .type = STORAGE_DEVICE_TYPE_HARDDISK, + .ops = &ide_storage_device_ops, }; void ide_handle_interrupt(IdeChannel *channel) { @@ -166,7 +167,7 @@ void ide_device_probe(IdeChannel *channel) { } // 5.读取设备信息 - AtaIdentifyInfo *identify = kmalloc(512); + AtaIdentifyInfo *identify = kmalloc(SECTOR_SIZE); io_stream_in_word( channel->io_base + ATA_REG_DATA, (uint32_t)identify, sizeof(AtaIdentifyInfo) / 2); @@ -211,11 +212,11 @@ DriverResult ide_device_init(Device *device) { AtaIdentifyInfo *identify = ide_device->info; if (identify->capabilities.dma_supported) { - ide_device->mode = TRANSFER_MODE_DMA; - ide_device->cmdset[ATA_CMDSET_READ] = ATA_CMD_READ_DMA_EXT; - ide_device->cmdset[ATA_CMDSET_WRITE] = ATA_CMD_WRITE_DMA_EXT; - ide_device->cmdset[ATA_CMDSET_READ] = ATA_CMD_READ_DMA; - ide_device->cmdset[ATA_CMDSET_WRITE] = ATA_CMD_WRITE_DMA; + ide_device->mode = TRANSFER_MODE_DMA; + ide_device->cmdset[ATA_CMDSET_READ_EXT] = ATA_CMD_READ_DMA_EXT; + ide_device->cmdset[ATA_CMDSET_WRITE_EXT] = ATA_CMD_WRITE_DMA_EXT; + ide_device->cmdset[ATA_CMDSET_READ] = ATA_CMD_READ_DMA; + ide_device->cmdset[ATA_CMDSET_WRITE] = ATA_CMD_WRITE_DMA; } else if (identify->pio_modes_supported) { ide_device->mode = TRANSFER_MODE_PIO; ide_device->cmdset[ATA_CMDSET_READ_EXT] = ATA_CMD_READ_PIO_EXT; @@ -223,7 +224,7 @@ DriverResult ide_device_init(Device *device) { ide_device->cmdset[ATA_CMDSET_READ] = ATA_CMD_READ_PIO; ide_device->cmdset[ATA_CMDSET_WRITE] = ATA_CMD_WRITE_PIO; } else { - return DRIVER_RESULT_UNSUPPORT_DEVICE; + return DRIVER_RESULT_UNSUPPORT_FEATURE; } return DRIVER_RESULT_OK; @@ -283,11 +284,11 @@ void ide_device_set_dma(IdeDevice *device, StorageRequest *request) { uint8_t *buffer; buffer = (uint32_t)request->buf & 3 - ? kmalloc(request->count * 512) // 未对齐则另外分配 + ? kmalloc(request->count * SECTOR_SIZE) // 未对齐则另外分配 : request->buf; // 传入的缓冲区已对齐则直接使用 request->real_buf = buffer; prdt->base_addr = vir2phy((uint32_t)buffer); - prdt->count = request->count * 512; + prdt->count = request->count * SECTOR_SIZE; prdt->sign = BIT(15); io_out_dword(channel->bmide + IDE_REG_BM_PRDT, vir2phy((uint32_t)prdt)); diff --git a/src/arch/x86/drivers/disk/ata/ide_controller.c b/src/arch/x86/drivers/disk/ata/ide_controller.c index 2cf0be7..710b9b8 100644 --- a/src/arch/x86/drivers/disk/ata/ide_controller.c +++ b/src/arch/x86/drivers/disk/ata/ide_controller.c @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include #include @@ -21,8 +21,8 @@ DriverResult ide_controller_probe(PciDevice *pci_device); DriverResult ide_controller_init(Device *device); DeviceDriverOps ide_controller_device_driver_ops = { - .register_driver_hook = NULL, - .unregister_driver_hook = NULL, + .device_driver_init = NULL, + .device_driver_uninit = NULL, }; DeviceDriver ide_controller_device_driver = { .name = STRING_INIT("IDE Controller Device Driver"), diff --git a/src/arch/x86/drivers/disk/ata/include/ide_controller.h b/src/arch/x86/drivers/disk/ata/include/ide_controller.h index 86e594e..a23612e 100644 --- a/src/arch/x86/drivers/disk/ata/include/ide_controller.h +++ b/src/arch/x86/drivers/disk/ata/include/ide_controller.h @@ -3,7 +3,7 @@ #include "bits.h" #include "driver/timer_dm.h" -#include "drivers/pci.h" +#include "drivers/bus/pci/pci.h" #include "kernel/driver_interface.h" #include "stdint.h" diff --git a/src/arch/x86/drivers/dma.c b/src/arch/x86/drivers/dma.c deleted file mode 100644 index cd96e7c..0000000 --- a/src/arch/x86/drivers/dma.c +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @file dma.c - * @author Ryan Wang (ryan1202@foxmail.com) - * @brief (ISA)DMA驱动 - * @version 0.1 - * @date 2021-7 - */ -#include -#include - -void dma_enable(unsigned int channel) -{ - if (channel < 4) { - io_out8(DMA1_REG_MASK, channel); - } else { - io_out8(DMA2_REG_MASK, channel & 3); - } -} - -void dma_disable(unsigned int channel) -{ - if (channel < 4) { - io_out8(DMA1_REG_MASK, channel | 4); - } else { - io_out8(DMA2_REG_MASK, (channel & 3) | 4); - } -} - -void dma_ff_reset(unsigned int channel) -{ - if (channel < 4) { - io_out8(DMA1_REG_FF_RESET, 0); - } else { - io_out8(DMA2_REG_FF_RESET, 0); - } -} - -void dma_set_mode(unsigned int channel, char mode) -{ - if (channel < 4) { - io_out8(DMA1_REG_MODE, mode | channel); - } else { - io_out8(DMA2_REG_MODE, mode | (channel & 3)); - } -} - -void dma_set_page(unsigned int channel, char page) -{ - switch (channel) { - case 0: - io_out8(DMA_PAGE0, page); - break; - case 1: - io_out8(DMA_PAGE1, page); - break; - case 2: - io_out8(DMA_PAGE2, page); - break; - case 3: - io_out8(DMA_PAGE3, page); - break; - case 5: - io_out8(DMA_PAGE5, page & 0xfe); - break; - case 6: - io_out8(DMA_PAGE6, page & 0xfe); - break; - case 7: - io_out8(DMA_PAGE7, page & 0xfe); - break; - - default: - break; - } -} - -void dma_set_addr(unsigned int channel, unsigned int addr) -{ - if (channel <= 3) { - io_out8(DMA0 + (channel << 1), addr & 0xff); - io_out8(DMA0 + (channel << 1), (addr >> 8) & 0xff); - } else { - io_out8(DMA1 + ((channel & 3) << 2), (addr >> 1) & 0xff); - io_out8(DMA1 + ((channel & 3) << 2), (addr >> 9) & 0xff); - } -} - -void dma_set_count(unsigned int channel, unsigned int count) -{ - count--; - if (channel <= 3) { - io_out8(DMA0 + (channel << 1) + 1, count & 0xff); - io_out8(DMA0 + (channel << 1) + 1, (count >> 8) & 0xff); - } else { - io_out8(DMA1 + ((channel & 3) << 2) + 2, count & 0xff); - io_out8(DMA1 + ((channel & 3) << 2) + 2, (count >> 8) & 0xff); - } -} diff --git a/src/arch/x86/drivers/network/rtl8139.c b/src/arch/x86/drivers/network/rtl8139.c index dfa8193..9faac95 100644 --- a/src/arch/x86/drivers/network/rtl8139.c +++ b/src/arch/x86/drivers/network/rtl8139.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -293,7 +293,7 @@ static status_t rtl8139_read( // rq = wait_queue_add(devext->rqm, sizeof(struct // read_request_s)); rreq = (struct read_request_s // *)rq->private_data; rreq->buffer = buf; rreq->length = size; - // thread_block(TASK_BLOCKED); + // thread_block(TASK_INTERRUPTIBLEED); return SUCCUESS; } diff --git a/src/arch/x86/drivers/pit.c b/src/arch/x86/drivers/pit.c index 80396f4..d4b150e 100644 --- a/src/arch/x86/drivers/pit.c +++ b/src/arch/x86/drivers/pit.c @@ -35,8 +35,8 @@ void pit_irq_handler(Device *device); extern Driver core_driver; DeviceDriverOps pit_driver_ops = { - .register_driver_hook = NULL, - .unregister_driver_hook = NULL, + .device_driver_init = NULL, + .device_driver_uninit = NULL, }; DeviceOps pit_device_ops = { .init = pit_init, diff --git a/src/arch/x86/drivers/usb/hci/uhci.c b/src/arch/x86/drivers/usb/hci/uhci.c index 55fb6a9..54385ff 100644 --- a/src/arch/x86/drivers/usb/hci/uhci.c +++ b/src/arch/x86/drivers/usb/hci/uhci.c @@ -9,7 +9,7 @@ * */ #include -#include +#include #include #include #include diff --git a/src/arch/x86/drivers/vesa_display.c b/src/arch/x86/drivers/vesa_display.c index d5c4c71..7bd3cc5 100644 --- a/src/arch/x86/drivers/vesa_display.c +++ b/src/arch/x86/drivers/vesa_display.c @@ -16,8 +16,8 @@ DriverResult vesa_display_device_init(Device *device); DriverResult vesa_display_device_start(Device *device); DeviceDriverOps vesa_display_driver_ops = { - .register_driver_hook = NULL, - .unregister_driver_hook = NULL, + .device_driver_init = NULL, + .device_driver_uninit = NULL, }; DeviceOps vesa_display_device_ops = { .init = vesa_display_device_init, diff --git a/src/arch/x86/include/drivers/bus/isa/dma.h b/src/arch/x86/include/drivers/bus/isa/dma.h new file mode 100644 index 0000000..4025247 --- /dev/null +++ b/src/arch/x86/include/drivers/bus/isa/dma.h @@ -0,0 +1,94 @@ +#ifndef _ISA_DMA_H +#define _ISA_DMA_H + +#include "stdint.h" + +#define DMA0 0x00 +#define DMA1 0xc0 + +#define DMA_ADDR0 0x00 +#define DMA_CNT0 0x01 +#define DMA_ADDR1 0x02 +#define DMA_CNT1 0x03 +#define DMA_ADDR2 0x04 +#define DMA_CNT2 0x05 +#define DMA_ADDR3 0x06 +#define DMA_CNT3 0x07 +#define DMA_ADDR4 0xc0 +#define DMA_CNT4 0xc2 +#define DMA_ADDR5 0xc4 +#define DMA_CNT5 0xc6 +#define DMA_ADDR6 0xc8 +#define DMA_CNT6 0xca +#define DMA_ADDR7 0xcc +#define DMA_CNT7 0xce + +// DMA寄存器 +#define DMA1_REG_STAT 0x08 // 状态寄存器 +#define DMA1_REG_CMD 0x08 // 命令寄存器 +#define DMA1_REG_REQ 0x09 // 请求寄存器 +#define DMA1_REG_MASK 0x0a // 屏蔽寄存器 +#define DMA1_REG_MODE 0x0b // 模式寄存器 +#define DMA1_REG_FF_RESET 0x0c // 触发器复位寄存器 +#define DMA1_REG_TEMP 0x0d // 暂存寄存器 +#define DMA1_REG_RESET 0x0d // 主DMA复位寄存器 +#define DMA1_REG_MASK_RESET 0x0e // 复位屏蔽寄存器 +#define DMA1_REG_ALL_MASK 0x0f // 多通道屏蔽寄存器 + +#define DMA2_REG_STAT 0xd0 // 状态寄存器 +#define DMA2_REG_CMD 0xd0 // 命令寄存器 +#define DMA2_REG_REQ 0xd2 // 请求寄存器 +#define DMA2_REG_MASK 0xd4 // 屏蔽寄存器 +#define DMA2_REG_MODE 0xd6 // 模式寄存器 +#define DMA2_REG_FF_RESET 0xd8 // 触发器复位寄存器 +#define DMA2_REG_TEMP 0xda // 暂存寄存器 +#define DMA2_REG_RESET 0xda // DMA复位寄存器 +#define DMA2_REG_MASK_RESET 0xdc // 复位屏蔽寄存器 +#define DMA2_REG_ALL_MASK 0xde // 多通道屏蔽寄存器 + +// 屏蔽寄存器 +#define DMA_MASK_ON 0x04 + +// DMA页寄存器 +#define DMA_PAGE0 0x87 +#define DMA_PAGE1 0x83 +#define DMA_PAGE2 0x81 +#define DMA_PAGE3 0x82 +#define DMA_PAGE5 0x8b +#define DMA_PAGE6 0x89 +#define DMA_PAGE7 0x8a + +#define DMA_MODE_READ 0x04 +#define DMA_MODE_WRITE 0x08 +#define DMA_MODE_AUTO 0x10 +#define DMA_MODE_SINGLE 0x40 +#define DMA_MODE_BLOCK 0x80 + +#define DMA_MAX_REGION_COUNT 16 +#define DMA_REGION_SIZE 64 * 1024 + +#include "kernel/dma.h" +#include "kernel/driver.h" + +extern DmaOps isa_dma_ops; + +void dma_init(); +void *dma_alloc_region(void *dma, uint32_t size); +DriverResult dma_free_region(void *dma, void *ptr, uint32_t size); + +struct Device; +int dma_channel_use(struct Device *device, int *possible_ch, int len); +void dma_channel_unuse(struct Device *device, uint8_t channel); + +int dma_lock(); +void dma_unlock(int flags); + +void dma_enable(unsigned int channel); +void dma_disable(unsigned int channel); +void dma_ff_reset(unsigned int channel); +void dma_set_mode(unsigned int channel, char mode); +void dma_set_addr(unsigned int channel, unsigned int addr); +void dma_set_count(unsigned int channel, unsigned int count); +uint32_t dma_pointer(int channel, unsigned int size); + +#endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/bus/isa/isa.h b/src/arch/x86/include/drivers/bus/isa/isa.h new file mode 100644 index 0000000..e02c3d2 --- /dev/null +++ b/src/arch/x86/include/drivers/bus/isa/isa.h @@ -0,0 +1,26 @@ +#ifndef _ISA_H +#define _ISA_H + +#include "kernel/bus_driver.h" +#include "kernel/device_driver.h" +#include "kernel/driver.h" +#include "kernel/list.h" + +struct IsaDeviceDriver; +typedef struct IsaOps { + DriverResult (*probe)(struct IsaDeviceDriver *isa_device_driver); +} IsaOps; + +typedef struct IsaDeviceDriver { + list_t list; + DeviceDriver *device_driver; + IsaOps *ops; + + BusDriver *bus_driver; + Bus *bus; +} IsaDeviceDriver; + +DriverResult isa_register_device_driver( + DeviceDriver *device_driver, IsaOps *ops); + +#endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/pci.h b/src/arch/x86/include/drivers/bus/pci/pci.h similarity index 100% rename from src/arch/x86/include/drivers/pci.h rename to src/arch/x86/include/drivers/bus/pci/pci.h diff --git a/src/arch/x86/include/drivers/dma.h b/src/arch/x86/include/drivers/dma.h deleted file mode 100644 index ba591a8..0000000 --- a/src/arch/x86/include/drivers/dma.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef _DMA_H -#define _DMA_H - -#define DMA0 0x00 -#define DMA1 0xc0 - -#define DMA_ADDR0 0x00 -#define DMA_CNT0 0x01 -#define DMA_ADDR1 0x02 -#define DMA_CNT1 0x03 -#define DMA_ADDR2 0x04 -#define DMA_CNT2 0x05 -#define DMA_ADDR3 0x06 -#define DMA_CNT3 0x07 -#define DMA_ADDR4 0xc0 -#define DMA_CNT4 0xc2 -#define DMA_ADDR5 0xc4 -#define DMA_CNT5 0xc6 -#define DMA_ADDR6 0xc8 -#define DMA_CNT6 0xca -#define DMA_ADDR7 0xcc -#define DMA_CNT7 0xce - -// DMA寄存器 -#define DMA1_REG_STAT 0x08 // 状态寄存器 -#define DMA1_REG_CMD 0x08 // 命令寄存器 -#define DMA1_REG_REQ 0x09 // 请求寄存器 -#define DMA1_REG_MASK 0x0a // 屏蔽寄存器 -#define DMA1_REG_MODE 0x0b // 模式寄存器 -#define DMA1_REG_FF_RESET 0x0c // 触发器复位寄存器 -#define DMA1_REG_TEMP 0x0d // 暂存寄存器 -#define DMA1_REG_RESET 0x0d // 主DMA复位寄存器 -#define DMA1_REG_MASK_RESET 0x0e // 复位屏蔽寄存器 -#define DMA1_REG_ALL_MASK 0x0f // 多通道屏蔽寄存器 - -#define DMA2_REG_STAT 0xd0 // 状态寄存器 -#define DMA2_REG_CMD 0xd0 // 命令寄存器 -#define DMA2_REG_REQ 0xd2 // 请求寄存器 -#define DMA2_REG_MASK 0xd4 // 屏蔽寄存器 -#define DMA2_REG_MODE 0xd6 // 模式寄存器 -#define DMA2_REG_FF_RESET 0xd8 // 触发器复位寄存器 -#define DMA2_REG_TEMP 0xda // 暂存寄存器 -#define DMA2_REG_RESET 0xda // DMA复位寄存器 -#define DMA2_REG_MASK_RESET 0xdc // 复位屏蔽寄存器 -#define DMA2_REG_ALL_MASK 0xde // 多通道屏蔽寄存器 - -// 屏蔽寄存器 -#define DMA_MASK_ON 0x04 - -// DMA页寄存器 -#define DMA_PAGE0 0x87 -#define DMA_PAGE1 0x83 -#define DMA_PAGE2 0x81 -#define DMA_PAGE3 0x82 -#define DMA_PAGE5 0x8b -#define DMA_PAGE6 0x89 -#define DMA_PAGE7 0x8a - -#define DMA_MODE_READ 0x06 -#define DMA_MODE_WRITE 0x0a - -void dma_enable(unsigned int channel); -void dma_disable(unsigned int channel); -void dma_ff_reset(unsigned int channel); -void dma_set_mode(unsigned int channel, char mode); -void dma_set_page(unsigned int channel, char page); -void dma_set_addr(unsigned int channel, unsigned int addr); -void dma_set_count(unsigned int channel, unsigned int count); - -#endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/usb/uhci.h b/src/arch/x86/include/drivers/usb/uhci.h index 5bf5f77..51571bb 100644 --- a/src/arch/x86/include/drivers/usb/uhci.h +++ b/src/arch/x86/include/drivers/usb/uhci.h @@ -2,7 +2,7 @@ #define _UHCI_H #include -#include +#include #include #include diff --git a/src/arch/x86/include/kernel/func.h b/src/arch/x86/include/kernel/func.h index 927e36d..55eee66 100644 --- a/src/arch/x86/include/kernel/func.h +++ b/src/arch/x86/include/kernel/func.h @@ -125,6 +125,8 @@ void load_idtr(int limit, int addr); int io_load_eflags(void); void io_store_eflags(int eflags); +int save_eflags_cli(void); + void exception_entry0(void); void exception_entry1(void); void exception_entry2(void); diff --git a/src/arch/x86/include/kernel/thread.h b/src/arch/x86/include/kernel/thread.h index d36b87f..3293bf5 100644 --- a/src/arch/x86/include/kernel/thread.h +++ b/src/arch/x86/include/kernel/thread.h @@ -1,6 +1,7 @@ #ifndef THREAD_H #define THREAD_H +#include "kernel/spinlock.h" #include #include #include @@ -10,9 +11,8 @@ typedef void thread_func(void *); typedef enum { TASK_RUNNING, TASK_READY, - TASK_BLOCKED, - TASK_WAITING, - TASK_HANGING, + TASK_INTERRUPTIBLE, + TASK_UNINTERRUPTIBLE, TASK_DIED } task_status_t; @@ -58,6 +58,7 @@ struct task_s { uint32_t pid; char name[32]; task_status_t status; + spinlock_t status_lock; uint8_t priority; uint8_t ticks; uint32_t elapsed_ticks; @@ -65,7 +66,9 @@ struct task_s { uint32_t stack_magic; size_t subject_id; - uint8_t *end_flag; + uint8_t *end_flag; + spinlock_t *end_flag_lock; + spinlock_t sub_thread_lock; struct mmap vir_page_mmap; struct memory_manage *memory_manage; @@ -87,7 +90,8 @@ void thread_create( struct task_s *thread_start( char *name, int priority, thread_func function, void *func_arg); void thread_exit(void); -void thread_block(task_status_t status); +void thread_set_status(task_status_t status); +void thread_wait(); void thread_unblock(struct task_s *pthread); void init_task(void); void schedule(void); diff --git a/src/arch/x86/kernel/func.asm b/src/arch/x86/kernel/func.asm index f2afebc..f53c1b7 100644 --- a/src/arch/x86/kernel/func.asm +++ b/src/arch/x86/kernel/func.asm @@ -1,6 +1,6 @@ global io_in8, io_out8, io_in16, io_out16, io_in32, io_out32 global io_read, io_write - global io_cli, io_sti, io_hlt, io_stihlt + global io_cli, io_sti, io_hlt, io_stihlt, save_eflags_cli global read_cr3, write_cr3, read_cr2, read_cr0, write_cr0, enable_paging global load_gdtr, load_idtr global io_load_eflags, io_store_eflags @@ -11,7 +11,7 @@ global stack_exception global general_protection global page_fault - global IRQ_timer, IRQ_pit, IRQ_keyboard, + global IRQ_timer, IRQ_pit, IRQ_keyboard global thread_intr_exit global switch_to @@ -122,7 +122,7 @@ INTERRUPT_ENTRY 13 INTERRUPT_ENTRY 14 INTERRUPT_ENTRY 15 -INTERRUPT_ENTRY 0, +INTERRUPT_ENTRY 0 io_in8: ;int io_in8(int port); mov edx,[esp+4] @@ -255,6 +255,12 @@ io_store_eflags: ; void io_store_eflags(int eflags); popfd ; pop eflags ret +save_eflags_cli: ; int save_eflags_cli(void); + pushfd + pop eax + cli + ret + global syscall_handler syscall_handler: push 0 diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index f6d54c2..5b5b0a7 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,7 @@ void platform_early_init() { void platform_init() { // 因为platform_bus是虚拟的,所以不需要注册device ObjectAttr attr = driver_object_attr; + list_init(&platform_driver.sub_driver_lh); register_bus_driver(&platform_driver, &platform_bus_driver, &attr); platform_bus.object = platform_bus_driver.object; list_init(&platform_bus_driver.bus_lh); @@ -61,6 +63,8 @@ void platform_init() { register_apic(); register_pit(); register_cmos(); + + dma_init(); } void platform_start_devices() { diff --git a/src/driver/storage/disk/disk.c b/src/driver/storage/disk/disk.c index e0f3824..ac7426e 100644 --- a/src/driver/storage/disk/disk.c +++ b/src/driver/storage/disk/disk.c @@ -4,41 +4,43 @@ #include TransferResult disk_transfer_in_async( - Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count, void **handle) { + Object *object, ObjectHandle *obj_handle, TransferDirection direction, + uint8_t *buf, uint32_t position, size_t count, void **handle) { Partition *partition = object->value.partition; return TRANSFER_IN_BLOCK_ASYNC( - partition->storage_object, buf, position + partition->start_lba, count, - handle); + partition->storage_object, obj_handle, buf, + position + partition->start_lba, count, handle); } TransferResult disk_transfer_in( - Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count) { + Object *object, ObjectHandle *obj_handle, TransferDirection direction, + uint8_t *buf, uint32_t position, size_t count) { Partition *partition = object->value.partition; return TRANSFER_IN_BLOCK( - partition->storage_object, buf, position + partition->start_lba, count); + partition->storage_object, obj_handle, buf, + position + partition->start_lba, count); } TransferResult disk_transfer_out_async( - Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count, void **handle) { + Object *object, ObjectHandle *obj_handle, TransferDirection direction, + uint8_t *buf, uint32_t position, size_t count, void **handle) { Partition *partition = object->value.partition; return TRANSFER_OUT_BLOCK_ASYNC( - partition->storage_object, buf, position + partition->start_lba, count, - handle); + partition->storage_object, obj_handle, buf, + position + partition->start_lba, count, handle); } TransferResult disk_transfer_out( - Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count) { + Object *object, ObjectHandle *obj_handle, TransferDirection direction, + uint8_t *buf, uint32_t position, size_t count) { Partition *partition = object->value.partition; return TRANSFER_OUT_BLOCK( - partition->storage_object, buf, position + partition->start_lba, count); + partition->storage_object, obj_handle, buf, + position + partition->start_lba, count); } TransferResult disk_is_transfer_in_done( diff --git a/src/driver/storage/storage_dm.c b/src/driver/storage/storage_dm.c index c7d06ff..e0b74b7 100644 --- a/src/driver/storage/storage_dm.c +++ b/src/driver/storage/storage_dm.c @@ -1,3 +1,4 @@ +#include "kernel/spinlock.h" #include #include #include @@ -50,6 +51,7 @@ DriverResult register_storage_device( storage_device->device = device; device->dm_ext = storage_device; + spinlock_init(&storage_device->queue_lock); list_init(&storage_device->io_queue_lh); string_t name; @@ -91,9 +93,9 @@ DriverResult unregister_storage_device( DriverResult start_storage_device(DeviceManager *manager, Device *device) { StorageDevice *storage_device = device->dm_ext; - storage_device->superblock = kmalloc(2 * 512); + storage_device->superblock = kmalloc(2 * SECTOR_SIZE); storage_transfer( - device->object, TRANSFER_IN, storage_device->superblock, 0, 2); + device->object, NULL, TRANSFER_IN, storage_device->superblock, 0, 2); if (storage_device->type == STORAGE_DEVICE_TYPE_HARDDISK) { if (disk_is_mbr(storage_device)) { diff --git a/src/driver/storage/storage_io.c b/src/driver/storage/storage_io.c index db059f9..2e79c71 100644 --- a/src/driver/storage/storage_io.c +++ b/src/driver/storage/storage_io.c @@ -12,8 +12,8 @@ #include TransferResult storage_transfer_async( - Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count, void **handle) { + Object *object, ObjectHandle *obj_handle, TransferDirection direction, + uint8_t *buf, uint32_t position, size_t count, void **handle) { while (object->attr->type == OBJECT_TYPE_SYM_LINK) { object = object->value.sym_link; } @@ -34,8 +34,8 @@ TransferResult storage_transfer_async( } TransferResult storage_transfer( - Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count) { + Object *object, ObjectHandle *obj_handle, TransferDirection direction, + uint8_t *buf, uint32_t position, size_t count) { while (object->attr->type == OBJECT_TYPE_SYM_LINK) { object = object->value.sym_link; } diff --git a/src/driver/storage/storage_io_queue.c b/src/driver/storage/storage_io_queue.c index dd5745f..7f6f555 100644 --- a/src/driver/storage/storage_io_queue.c +++ b/src/driver/storage/storage_io_queue.c @@ -1,5 +1,6 @@ #include "kernel/block_cache.h" #include "kernel/rwlock.h" +#include "kernel/spinlock.h" #include #include #include @@ -9,44 +10,56 @@ #include #include -bool storage_try_merge_request( +PRIVATE void storage_modify_merged_request( StorageRequest *new_request, StorageRequest *request) { - if (new_request->rw == request->rw) { - if (new_request->position + new_request->count >= request->position && - new_request->position <= request->position + request->count) { - if (request->next_merged_request != NULL) { - // 如果是被合并过的请求,就继续合并 - StorageRequest *last_request = request->next_merged_request; - while (last_request) { - last_request = last_request->next_merged_request; - } - - request->position = - MIN(request->position, new_request->position); - request->count = MAX(new_request->position + new_request->count, - request->position + request->count) - - request->position; - - last_request->next_merged_request = new_request; - } else { - // 如果未合并过,就新申请一个请求替换掉 - StorageRequest *req = kmalloc(sizeof(StorageRequest)); - req->buf = NULL; // 缓冲区先不申请,等到真正提交时再申请 - req->position = MIN(new_request->position, request->position); - req->count = MAX(new_request->position + new_request->count, - request->position + request->count) - - req->position; - req->rw = new_request->rw; - req->is_finished = 0; - req->storage_device = new_request->storage_device; - - req->next_merged_request = request; - request->next_merged_request = new_request; - - list_add_before(&req->list, &request->list); - list_del(&request->list); - } - return true; + StorageRequest *last_request = request->next_merged_request; + while (last_request->next_merged_request != NULL) { + last_request = last_request->next_merged_request; + } + + request->position = MIN(request->position, new_request->position); + request->count = MAX(new_request->position + new_request->count, + request->position + request->count) - + request->position; + + last_request->next_merged_request = new_request; +} + +PRIVATE void storage_new_merge_request( + StorageRequest *new_request, StorageRequest *request) { + StorageRequest *req = kmalloc(sizeof(StorageRequest)); + req->buf = NULL; // 缓冲区先不申请,等到真正提交时再申请 + req->position = MIN(new_request->position, request->position); + req->count = MAX(new_request->position + new_request->count, + request->position + request->count) - + req->position; + req->rw = new_request->rw; + req->is_finished = 0; + req->storage_device = new_request->storage_device; + + req->next_merged_request = request; + request->next_merged_request = new_request; + + list_add_before(&req->list, &request->list); + list_del(&request->list); +} + +bool storage_try_merge_request( + StorageRequest *new_request, StorageRequest *request, size_t max_count) { + if (new_request->rw == request->rw) { // 读写类型相同 + if (new_request->count + request->count > max_count) return false; + if (new_request->position + new_request->count < request->position && + new_request->position > request->position + request->count) { + // 两个请求没有交集 + return false; + } + + if (request->next_merged_request != NULL) { + // 如果是被合并过的请求,就继续合并 + storage_modify_merged_request(new_request, request); + } else { // 未合并过 + // 因为不能修改已有的请求,就新申请一个请求替换掉 + storage_new_merge_request(new_request, request); } } return false; @@ -57,24 +70,31 @@ void storage_add_request( StorageRequest *req; request->storage_device = storage_device; request->is_finished = 0; + spin_lock(&storage_device->queue_lock); if (list_empty(&storage_device->io_queue_lh)) { storage_submit_request(request); return; } list_for_each_owner (req, &storage_device->io_queue_lh, list) { - if (storage_try_merge_request(request, req)) { return; } + if (storage_try_merge_request( + request, req, storage_device->max_block_per_request)) { + return; + } if (req->position > request->position) { list_add_before(&request->list, &req->list); + spin_unlock(&storage_device->queue_lock); return; } } list_add_tail(&request->list, &storage_device->io_queue_lh); + spin_unlock(&storage_device->queue_lock); } void storage_periodic_task(void *arg) { StorageDevice *storage_device = (StorageDevice *)arg; if (!storage_device->ops->is_busy(storage_device)) { + spin_lock(&storage_device->queue_lock); if (!list_empty(&storage_device->io_queue_lh)) { StorageRequest *request = list_first_owner( &storage_device->io_queue_lh, StorageRequest, list); @@ -84,13 +104,17 @@ void storage_periodic_task(void *arg) { !list_empty(&storage_device->block_cache_lh)) { BlockCacheEntry *entry = list_first_owner( &storage_device->block_cache_lh, BlockCacheEntry, list); + rwlock_read_lock(&entry->lock); + entry->cache->write( entry, entry->cache->size, entry->cache->private_data); list_del(&entry->list); entry->dirty = false; + rwlock_read_unlock(&entry->lock); } + spin_unlock(&storage_device->queue_lock); } } @@ -115,7 +139,7 @@ void storage_submit_request(StorageRequest *request) { } else { storage_device->ops->submit_read_request(storage_device, request); } - list_del(&request->list); + if (request->list.next != NULL) list_del(&request->list); } void storage_solve_read_request(StorageRequest *request) { diff --git a/src/driver/time_dm.c b/src/driver/time_dm.c index 1126d68..b99fb5e 100644 --- a/src/driver/time_dm.c +++ b/src/driver/time_dm.c @@ -48,5 +48,5 @@ DriverResult get_current_time(TimeType type, Time *time) { if (time_device != NULL) { return time_device->ops->get_time(time_device, type, time); } - return DRIVER_RESULT_UNSUPPORT_DEVICE; + return DRIVER_RESULT_UNSUPPORT_FEATURE; } diff --git a/src/driver/video_dm.c b/src/driver/video_dm.c index d59347e..d2a59d5 100644 --- a/src/driver/video_dm.c +++ b/src/driver/video_dm.c @@ -88,7 +88,7 @@ DriverResult video_device_start(DeviceManager *manager, Device *device) { } else if (video_device->mode_info.bits_per_pixel == 32) { video_device->framebuffer_ops = &fb_ops_32; } else { - return DRIVER_RESULT_UNSUPPORT_DEVICE; + return DRIVER_RESULT_UNSUPPORT_FEATURE; } return DRIVER_RESULT_OK; diff --git a/src/include/driver/storage/disk/disk.h b/src/include/driver/storage/disk/disk.h index 6e7299d..44c297a 100644 --- a/src/include/driver/storage/disk/disk.h +++ b/src/include/driver/storage/disk/disk.h @@ -1,6 +1,7 @@ #ifndef _DISK_H #define _DISK_H +#include "objects/handle.h" #include "objects/transfer.h" #include "stdint.h" #include @@ -26,17 +27,19 @@ typedef struct Partition { } Partition; TransferResult disk_transfer_in( - struct Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count); + struct Object *object, ObjectHandle *obj_handle, + TransferDirection direction, uint8_t *buf, uint32_t position, size_t count); TransferResult disk_transfer_in_async( - struct Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count, void **handle); + struct Object *object, ObjectHandle *obj_handle, + TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, + void **handle); TransferResult disk_transfer_out( - struct Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count); + struct Object *object, ObjectHandle *obj_handle, + TransferDirection direction, uint8_t *buf, uint32_t position, size_t count); TransferResult disk_transfer_out_async( - struct Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count, void **handle); + struct Object *object, ObjectHandle *obj_handle, + TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, + void **handle); TransferResult disk_is_transfer_in_done( struct Object *object, void **handle, bool *is_done); TransferResult disk_is_transfer_out_done( diff --git a/src/include/kernel/device_driver.h b/src/include/kernel/device_driver.h index 2ca3935..c6edf34 100644 --- a/src/include/kernel/device_driver.h +++ b/src/include/kernel/device_driver.h @@ -25,8 +25,8 @@ typedef enum { struct DeviceDriver; typedef struct DeviceDriverOps { - DriverResult (*register_driver_hook)(struct DeviceDriver *driver); - DriverResult (*unregister_driver_hook)(struct DeviceDriver *driver); + DriverResult (*device_driver_init)(struct DeviceDriver *driver); + DriverResult (*device_driver_uninit)(struct DeviceDriver *driver); } DeviceDriverOps; struct Bus; diff --git a/src/include/kernel/dma.h b/src/include/kernel/dma.h new file mode 100644 index 0000000..f5592e4 --- /dev/null +++ b/src/include/kernel/dma.h @@ -0,0 +1,28 @@ +/** + * @file dma.h + * @author Jiajun Wang (ryan1202@foxmail.com) + * @brief 统一的DMA接口 + * @version 0.1 + * @date 2025-03-12 + * + * @copyright Copyright (c) 2025 + * + */ +#ifndef _DMA_H +#define _DMA_H + +#include "kernel/driver.h" +#include + +typedef struct DmaOps { + void *(*dma_alloc)(void *dma, uint32_t size); + DriverResult (*dma_free)(void *dma, void *ptr, uint32_t size); +} DmaOps; + +typedef struct Dma { + void *dma; + DmaOps *ops; + void *param; +} Dma; + +#endif \ No newline at end of file diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index 7936b40..5e2b971 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -158,9 +158,18 @@ typedef enum DriverResult { DRIVER_RESULT_OUT_OF_MEMORY, DRIVER_RESULT_NULL_POINTER, DRIVER_RESULT_UNSUPPORT_DEVICE, + DRIVER_RESULT_UNSUPPORT_FEATURE, + DRIVER_RESULT_BUSY, + DRIVER_RESULT_EXCEED_MAX_SIZE, DRIVER_RESULT_OTHER_ERROR, } DriverResult; +#define DRIVER_RESULT_PASS(func) \ + { \ + DriverResult result = func; \ + if (result != DRIVER_RESULT_OK) { return result; } \ + } + typedef enum { DRIVER_TYPE_DEVICE_DRIVER = 0, DRIVER_TYPE_BUS_DRIVER, diff --git a/src/include/kernel/driver_interface.h b/src/include/kernel/driver_interface.h index b844286..31ad895 100644 --- a/src/include/kernel/driver_interface.h +++ b/src/include/kernel/driver_interface.h @@ -28,6 +28,8 @@ #define load_interrupt_status() io_load_eflags(); #define store_interrupt_status(status) io_store_eflags(status); +#define save_and_disable_interrupt() save_eflags_cli() + #else #error Driver: Unsupport Architecture #endif @@ -52,7 +54,6 @@ typedef struct DeviceIrq { DeviceIrqHandler handler; } DeviceIrq; -#include "kernel/driver.h" #include "stdint.h" typedef struct DriverRemappedMemory { list_t list; @@ -61,12 +62,13 @@ typedef struct DriverRemappedMemory { uint32_t size; } DriverRemappedMemory; +struct Driver; enum DriverResult register_device_irq(DeviceIrq *dev_irq); enum DriverResult unregister_device_irq(DeviceIrq *dev_irq); void device_irq_handler(int irq); -DriverResult driver_remap_memory( - Driver *in_driver, uint32_t in_physical_address, uint32_t in_size, - uint32_t *out_virtual_address); +enum DriverResult driver_remap_memory( + struct Driver *in_driver, uint32_t in_physical_address, uint32_t in_size, + uint32_t *out_virtual_address); #define kmalloc_from_template(template) \ ({ \ diff --git a/src/include/kernel/memory.h b/src/include/kernel/memory.h index 73caa71..de4c7c2 100644 --- a/src/include/kernel/memory.h +++ b/src/include/kernel/memory.h @@ -2,7 +2,6 @@ #define _MEMORY_H #include "result.h" -#include #include #define PHY_MEM_BASE_ADDR 0x1000000 diff --git a/src/include/kernel/spinlock.h b/src/include/kernel/spinlock.h index 684ef69..40eb314 100644 --- a/src/include/kernel/spinlock.h +++ b/src/include/kernel/spinlock.h @@ -1,6 +1,7 @@ #ifndef _SPINLOCK_H #define _SPINLOCK_H +#include "kernel/driver_interface.h" typedef volatile int spinlock_t; #define SPINLOCK(lock) spinlock_t lock = 0; @@ -25,4 +26,18 @@ static inline void spin_unlock(volatile spinlock_t *lock) { *lock = 0; } +// 获取自旋锁的同时禁用中断并保存中断状态 +static inline int spin_lock_irqsave(spinlock_t *lock) { + int flags = save_and_disable_interrupt(); + spin_lock(lock); + return flags; +} + +// 释放自旋锁并恢复之前保存的中断状态 +static inline void spin_unlock_irqrestore( + spinlock_t *lock, unsigned long flags) { + spin_unlock(lock); + store_interrupt_status(flags); +} + #endif \ No newline at end of file diff --git a/src/include/objects/transfer.h b/src/include/objects/transfer.h index 2d34b21..f39f57c 100644 --- a/src/include/objects/transfer.h +++ b/src/include/objects/transfer.h @@ -19,26 +19,31 @@ typedef enum { } TransferDirection; struct Object; +struct ObjectHandle; typedef TransferResult (*BlockTransfer)( - struct Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count); + struct Object *object, struct ObjectHandle *obj_handle, + TransferDirection direction, uint8_t *buf, uint32_t position, size_t count); typedef TransferResult (*BlockTransferAsync)( - struct Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count, void **handle); + struct Object *object, struct ObjectHandle *obj_handle, + TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, + void **handle); typedef TransferResult (*StreamTransfer)( - struct Object *object, TransferDirection direction, uint8_t *buf, - size_t size); + struct Object *object, struct ObjectHandle *obj_handle, + TransferDirection direction, uint8_t *buf, size_t size); typedef TransferResult (*StreamTransferAsync)( - struct Object *object, TransferDirection direction, uint8_t *buf, - size_t size, void **handle); + struct Object *object, struct ObjectHandle *obj_handle, + TransferDirection direction, uint8_t *buf, size_t size, void **handle); typedef void (*InterruptTransferCallbackSingle)( - struct Object *object, void *private_data, size_t data); + struct Object *object, struct ObjectHandle *obj_handle, void *private_data, + size_t data); typedef void (*InterruptTransferCallbackMultiple)( - struct Object *object, void *private_data, void *data, size_t size); + struct Object *object, struct ObjectHandle *obj_handle, void *private_data, + void *data, size_t size); typedef TransferResult (*InterruptTransfer)( - struct Object *object, InterruptTransferCallbackSingle callback_single, + struct Object *object, struct ObjectHandle *obj_handle, + InterruptTransferCallbackSingle callback_single, InterruptTransferCallbackMultiple callback_multiple); typedef TransferResult (*IsTransferDone)( @@ -78,32 +83,32 @@ typedef struct TransferOut { }; } TransferOut; -#define TRANSFER_IN_BLOCK(object, ...) \ - ((object)->in.block(object, TRANSFER_IN, __VA_ARGS__)) -#define TRANSFER_IN_BLOCK_ASYNC(object, ...) \ - ((object)->in.block_async(object, TRANSFER_IN, __VA_ARGS__)) -#define TRANSFER_IN_STREAM(object, ...) \ - ((object)->in.stream(object, TRANSFER_IN, __VA_ARGS__)) -#define TRANSFER_IN_STREAM_ASYNC(object, ...) \ - ((object)->in.stream_async(object, TRANSFER_IN, __VA_ARGS__)) -#define TRANSFER_IN_INTTERRUPT(object, ...) \ - ((object)->in.interrupt(object, __VA_ARGS__)) +#define TRANSFER_IN_BLOCK(object, handle, ...) \ + ((object)->in.block(object, handle, TRANSFER_IN, __VA_ARGS__)) +#define TRANSFER_IN_BLOCK_ASYNC(object, handle, ...) \ + ((object)->in.block_async(object, handle, TRANSFER_IN, __VA_ARGS__)) +#define TRANSFER_IN_STREAM(object, handle, ...) \ + ((object)->in.stream(object, handle, TRANSFER_IN, __VA_ARGS__)) +#define TRANSFER_IN_STREAM_ASYNC(object, handle, ...) \ + ((object)->in.stream_async(object, handle, TRANSFER_IN, __VA_ARGS__)) +#define TRANSFER_IN_INTTERRUPT(object, handle, ...) \ + ((object)->in.interrupt(object, handle, __VA_ARGS__)) -#define TRANSFER_IN_IS_DONE(object, ...) \ - ((object)->in.is_transfer_done(object, __VA_ARGS__)) +#define TRANSFER_IN_IS_DONE(object, handle, ...) \ + ((object)->in.is_transfer_done(object, handle, __VA_ARGS__)) -#define TRANSFER_OUT_BLOCK(object, ...) \ - ((object)->in.block(object, TRANSFER_OUT, __VA_ARGS__)) -#define TRANSFER_OUT_BLOCK_ASYNC(object, ...) \ - ((object)->in.block_async(object, TRANSFER_OUT, __VA_ARGS__)) -#define TRANSFER_OUT_STREAM(object, ...) \ - ((object)->in.stream(object, TRANSFER_OUT, __VA_ARGS__)) -#define TRANSFER_OUT_STREAM_ASYNC(object, ...) \ - ((object)->in.stream_async(object, TRANSFER_OUT, __VA_ARGS__)) -#define TRANSFER_OUT_INTTERRUPT(object, ...) \ - ((object)->in.interrupt(object, __VA_ARGS__)) +#define TRANSFER_OUT_BLOCK(object, handle, ...) \ + ((object)->in.block(object, handle, TRANSFER_OUT, __VA_ARGS__)) +#define TRANSFER_OUT_BLOCK_ASYNC(object, handle, ...) \ + ((object)->in.block_async(object, handle, TRANSFER_OUT, __VA_ARGS__)) +#define TRANSFER_OUT_STREAM(object, handle, ...) \ + ((object)->in.stream(object, handle, TRANSFER_OUT, __VA_ARGS__)) +#define TRANSFER_OUT_STREAM_ASYNC(object, handle, ...) \ + ((object)->in.stream_async(object, handle, TRANSFER_OUT, __VA_ARGS__)) +#define TRANSFER_OUT_INTTERRUPT(object, handle, ...) \ + ((object)->in.interrupt(object, handle, __VA_ARGS__)) -#define TRANSFER_OUT_IS_DONE(object, ...) \ - ((object)->in.is_transfer_done(object, __VA_ARGS__)) +#define TRANSFER_OUT_IS_DONE(object, handle, ...) \ + ((object)->in.is_transfer_done(object, handle, __VA_ARGS__)) #endif \ No newline at end of file diff --git a/src/kernel/bus_driver.c b/src/kernel/bus_driver.c index 670135d..8b89bea 100644 --- a/src/kernel/bus_driver.c +++ b/src/kernel/bus_driver.c @@ -56,7 +56,7 @@ DriverResult register_bus_driver( DriverManager *manager = driver_managers[DRIVER_TYPE_BUS_DRIVER]; if (manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; - BusDriver *_bus_driver = bus_drivers[bus_driver->driver_type]; + BusDriver *_bus_driver = bus_drivers[bus_driver->bus_type]; if (_bus_driver != NULL) return DRIVER_RESULT_BUS_DRIVER_ALREADY_EXIST; bus_driver->private_data = kmalloc(bus_driver->private_data_size); diff --git a/src/kernel/condvar.c b/src/kernel/condvar.c index 600b0d5..cefed42 100644 --- a/src/kernel/condvar.c +++ b/src/kernel/condvar.c @@ -1,3 +1,4 @@ +#include "kernel/thread.h" #include void condvar_init(condvar_t *cv) { @@ -6,9 +7,10 @@ void condvar_init(condvar_t *cv) { void condvar_wait(condvar_t *cv, spinlock_t *mutex) { wait_queue_add(&cv->wait_queue); + thread_set_status(TASK_INTERRUPTIBLE); spin_unlock(mutex); - thread_block(TASK_BLOCKED); + thread_wait(); spin_lock(mutex); } diff --git a/src/kernel/device_manager.c b/src/kernel/device_manager.c index 600c98f..c433358 100644 --- a/src/kernel/device_manager.c +++ b/src/kernel/device_manager.c @@ -15,8 +15,9 @@ DriverResult register_device_manager(DeviceManager *manager) { list_init(&manager->device_lh); device_managers[manager->type] = manager; - - DEVM_OPS_CALL(manager, dm_load, manager); + if (manager->ops->dm_load != NULL) { + DRV_RESULT_DELIVER_CALL(manager->ops->dm_load, manager); + } return DRIVER_RESULT_OK; } diff --git a/src/kernel/driver.c b/src/kernel/driver.c index feac910..b861301 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -171,34 +171,50 @@ void driver_start_thread(void *arg) { SubDriver *sub_driver; list_for_each_owner (sub_driver, &driver->sub_driver_lh, sub_driver_list) { + int old_status = save_and_disable_interrupt(); struct task_s *task = thread_start( "sub_driver_start_thread", THREAD_DEFAULT_PRIO, sub_driver_start_thread, sub_driver); thread_set_end_flag(task, &end_flag); + store_interrupt_status(old_status); } + struct task_s *cur = get_current_thread(); + int flags = spin_lock_irqsave(&cur->sub_thread_lock); while (end_flag > 0) { + spin_unlock_irqrestore(&cur->sub_thread_lock, flags); schedule(); + flags = spin_lock_irqsave(&cur->sub_thread_lock); } } +// TODO:PCI检测完设备后,设备有概率未初始化直接结束 + DriverResult driver_start_all(void) { uint8_t end_flag = 0; Driver *driver; + list_for_each_owner (driver, &driver_lh, driver_list) { if (driver->state == DRIVER_STATE_UNINITED) { + int old_status = save_and_disable_interrupt(); struct task_s *task = thread_start( "driver_start_thread", THREAD_DEFAULT_PRIO, driver_start_thread, driver); thread_set_end_flag(task, &end_flag); + store_interrupt_status(old_status); } } + struct task_s *cur = get_current_thread(); + int flags = spin_lock_irqsave(&cur->sub_thread_lock); while (end_flag > 0) { + spin_unlock_irqrestore(&cur->sub_thread_lock, flags); schedule(); + flags = spin_lock_irqsave(&cur->sub_thread_lock); } + spin_unlock_irqrestore(&cur->sub_thread_lock, flags); return DRIVER_RESULT_OK; } diff --git a/src/kernel/driver_dependency.c b/src/kernel/driver_dependency.c index d871345..9688b95 100644 --- a/src/kernel/driver_dependency.c +++ b/src/kernel/driver_dependency.c @@ -22,7 +22,8 @@ DriverResult check_dependency(Driver *driver) { bus_driver->subdriver.state != SUBDRIVER_STATE_READY) { // 总线驱动还没准备好则等待 wait_queue_add(&bus_driver->subdriver.wq); - thread_block(TASK_BLOCKED); + thread_set_status(TASK_INTERRUPTIBLE); + thread_wait(); bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; } diff --git a/src/kernel/thread.c b/src/kernel/thread.c index 5d07d02..4e31f1c 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -6,6 +6,8 @@ * @date 2021-02 * */ +#include "kernel/driver_interface.h" +#include "kernel/spinlock.h" #include #include #include @@ -103,8 +105,10 @@ void init_thread(struct task_s *pthread, char *name, int priority) { if (pthread == main_thread) { pthread->status = TASK_RUNNING; } else { - pthread->status = TASK_WAITING; + pthread->status = TASK_READY; } + spinlock_init(&pthread->status_lock); + spinlock_init(&pthread->sub_thread_lock); pthread->priority = priority; pthread->kstack = (uint32_t *)((uint32_t)pthread + PAGE_SIZE); pthread->ticks = timer_get_schedule_tick(priority); @@ -158,9 +162,11 @@ void thread_exit(void) { struct task_s *cur = get_current_thread(); cur->status = TASK_DIED; + int flags = spin_lock_irqsave(cur->end_flag_lock); (*cur->end_flag)--; + spin_unlock_irqrestore(cur->end_flag_lock, flags); - list_del(&cur->general_tag); + if (cur->general_tag.next != NULL) list_del(&cur->general_tag); list_del(&cur->all_list_tag); kfree(cur); @@ -170,7 +176,9 @@ void thread_exit(void) { if (list_length(&thread_ready) > 1) { list_del(thread_ready.next); + int flags = spin_lock_irqsave(&next->status_lock); next->status = TASK_RUNNING; + spin_unlock_irqrestore(&next->status_lock, flags); process_activate(next); current_task = next; @@ -183,30 +191,47 @@ void thread_exit(void) { } void thread_set_end_flag(struct task_s *pthread, uint8_t *flag) { - (*flag)++; - pthread->end_flag = flag; + struct task_s *cur = get_current_thread(); + int flags = spin_lock_irqsave(&cur->sub_thread_lock); + int flags2 = spin_lock_irqsave(&pthread->status_lock); + if (pthread->status != TASK_DIED) { + spin_unlock_irqrestore(&pthread->status_lock, flags2); + pthread->end_flag_lock = &cur->sub_thread_lock; + (*flag)++; + pthread->end_flag = flag; + } + spin_unlock_irqrestore(&cur->sub_thread_lock, flags); } /** * @brief 阻塞当前线程 * * @param status 线程的目标状态( - * TASK_BLOCKED:阻塞 + * TASK_INTERRUPTIBLEED:阻塞 * TASK_WAITING:等待 * TASK_HANGING:挂起) */ -void thread_block(task_status_t status) { - int old_status = io_load_eflags(); - if ((status != TASK_BLOCKED) && (status != TASK_WAITING) && - (status != TASK_HANGING)) { - printk("error"); - while (1) - ; - } +void thread_set_status(task_status_t status) { struct task_s *cur_thread = get_current_thread(); + int flags = spin_lock_irqsave(&cur_thread->status_lock); cur_thread->status = status; - schedule(); - io_store_eflags(old_status); + spin_unlock_irqrestore(&cur_thread->status_lock, flags); +} + +void thread_wait() { + struct task_s *cur_thread = get_current_thread(); + int flags = spin_lock_irqsave(&cur_thread->status_lock); + if (cur_thread->status == TASK_UNINTERRUPTIBLE) { + spin_unlock_irqrestore(&cur_thread->status_lock, flags); + schedule(); + } else if (cur_thread->status == TASK_INTERRUPTIBLE) { + while (cur_thread->status == TASK_INTERRUPTIBLE) { + spin_unlock_irqrestore(&cur_thread->status_lock, flags); + schedule(); + flags = spin_lock_irqsave(&cur_thread->status_lock); + } + spin_unlock_irqrestore(&cur_thread->status_lock, flags); + } } /** @@ -215,13 +240,12 @@ void thread_block(task_status_t status) { * @param pthread 线程结构 */ void thread_unblock(struct task_s *pthread) { - int old_status = io_load_eflags(); - if ((pthread->status != TASK_BLOCKED) && - (pthread->status != TASK_WAITING) && - (pthread->status != TASK_HANGING)) { - printk("error"); - while (1) - ; + int flags = spin_lock_irqsave(&pthread->status_lock); + if ((pthread->status != TASK_INTERRUPTIBLE) && + (pthread->status != TASK_UNINTERRUPTIBLE)) { + spin_unlock_irqrestore(&pthread->status_lock, flags); + printk("Error: trying to unblock a thread not blocked\n"); + return; } if (pthread->status != TASK_READY) { if (list_find(&pthread->general_tag, &thread_ready)) { @@ -230,9 +254,10 @@ void thread_unblock(struct task_s *pthread) { ; } list_add_before(&pthread->general_tag, thread_ready.next); + pthread->status = TASK_READY; + spin_unlock_irqrestore(&pthread->status_lock, flags); } - io_store_eflags(old_status); } /** diff --git a/src/kernel/wait_queue.c b/src/kernel/wait_queue.c index c430ac1..258d1d9 100644 --- a/src/kernel/wait_queue.c +++ b/src/kernel/wait_queue.c @@ -6,6 +6,7 @@ * @date 2022-07-20 */ +#include "kernel/spinlock.h" #include "kernel/thread.h" #include #include @@ -75,19 +76,18 @@ void wait_queue_wakeup(WaitQueue *wqm) { if (list_empty(&wqm->list_head)) { return; } struct task_s *thread = list_first_owner(&wqm->list_head, struct task_s, wait_queue_tag); - int old_status = load_interrupt_status(); - disable_interrupt(); - spin_lock(&wqm->lock); + int flags = spin_lock_irqsave(&wqm->lock); list_del(&thread->wait_queue_tag); - if (thread->status == TASK_BLOCKED || thread->status == TASK_WAITING || - thread->status == TASK_HANGING) { + int flags2 = spin_lock_irqsave(&thread->status_lock); + if (thread->status == TASK_INTERRUPTIBLE || + thread->status == TASK_UNINTERRUPTIBLE) { + spin_unlock_irqrestore(&thread->status_lock, flags2); thread_unblock(thread); } - spin_unlock(&wqm->lock); - store_interrupt_status(old_status); + spin_unlock_irqrestore(&wqm->lock, flags); return; } @@ -101,20 +101,20 @@ void wait_queue_wakeup_all(WaitQueue *wqm) { WaitQueueItem *cur, *next; struct task_s *thread; - int old_status = load_interrupt_status(); - disable_interrupt(); - - spin_lock(&wqm->lock); + int old_status = spin_lock_irqsave(&wqm->lock); list_for_each_owner_safe (cur, next, &wqm->list_head, wait_queue_tag) { thread = cur; list_del(&cur->wait_queue_tag); - if (thread->status == TASK_BLOCKED || thread->status == TASK_WAITING || - thread->status == TASK_HANGING) { + + int flags2 = spin_lock_irqsave(&thread->status_lock); + if (thread->status == TASK_INTERRUPTIBLE || + thread->status == TASK_UNINTERRUPTIBLE) { + spin_unlock_irqrestore(&thread->status_lock, flags2); thread_unblock(thread); + schedule(); } } - spin_unlock(&wqm->lock); - store_interrupt_status(old_status); + spin_unlock_irqrestore(&wqm->lock, old_status); return; } diff --git a/src/lib/dyn_array.c b/src/lib/dyn_array.c index 5afc7c4..af0ac53 100644 --- a/src/lib/dyn_array.c +++ b/src/lib/dyn_array.c @@ -95,8 +95,7 @@ void *dyn_array_next_ptr( *block_offset = 0; *block = (*block)->next; } - return (void *)current_block->data + - (*block_index) * dyn_array->element_size; + return (void *)(*block)->data + (*block_offset) * dyn_array->element_size; } void dyn_array_remove(DynArray *dyn_array, void *item) { diff --git a/src/network/arp.c b/src/network/arp.c index 48e167d..578138a 100644 --- a/src/network/arp.c +++ b/src/network/arp.c @@ -15,8 +15,9 @@ uint8_t *ip2mac(netc_t *netc, uint8_t *ip) { if (cur->mac[0] != 0) { return cur->mac; } else { + // TODO: lock wait_queue_add(&cur->wq); - thread_block(TASK_BLOCKED); + thread_set_status(TASK_INTERRUPTIBLE); } } } diff --git a/src/objects/objects.c b/src/objects/objects.c index d7db4cd..03c4f64 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -38,7 +38,8 @@ void init_object_directory(Object *object) { } void init_base_obj_sys_attr(Object *object) { - object->attr = kmalloc_from_template(base_obj_sys_attr); + object->attr = kmalloc_from_template(base_obj_sys_attr); + object->attr->object = object; } /** @@ -145,10 +146,11 @@ Object *create_object(Object *parent, string_t name, ObjectAttr attr) { Object *object = kmalloc(sizeof(Object)); if (object == NULL) { return NULL; } - object->name = name; - object->attr = kmalloc_from_template(attr); - object->parent = parent; - object->reference = 0; + object->name = name; + object->attr = kmalloc_from_template(attr); + object->attr->object = object; + object->parent = parent; + object->reference = 0; ObjectResult result = add_object(parent, object); if (result != OBJECT_OK) { From 351da7bfc58984dcaf620fe1de3c43cca1907ae6 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 19 Mar 2025 23:25:05 +0800 Subject: [PATCH 037/158] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20mmap=20bug?= =?UTF-8?q?=EF=BC=9B=E6=96=B0=E5=A2=9E=20ObjectHandle=EF=BC=9B=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=20fat=5Ftransfer=E9=80=BB=E8=BE=91=EF=BC=8C=E6=8F=90?= =?UTF-8?q?=E9=AB=98=E8=BF=9E=E7=BB=AD=E7=B0=87=E7=9A=84=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=95=88=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fs/fat/cluster.c | 56 +++++++++++- src/fs/fat/dir.c | 6 +- src/fs/fat/entry.c | 5 +- src/fs/fat/fat.c | 110 +++++++++++++++++------- src/fs/fat/include/cluster.h | 4 + src/fs/fs.c | 22 +++-- src/include/const.h | 2 - src/include/driver/storage/storage_dm.h | 5 ++ src/include/driver/storage/storage_io.h | 9 +- src/include/fs/fs.h | 14 ++- src/include/objects/handle.h | 15 ++++ src/kernel/memory.c | 4 +- src/objects/Makefile | 3 +- src/objects/handle.c | 20 +++++ 14 files changed, 222 insertions(+), 53 deletions(-) create mode 100644 src/include/objects/handle.h create mode 100644 src/objects/handle.c diff --git a/src/fs/fat/cluster.c b/src/fs/fat/cluster.c index 5e05198..35363d4 100644 --- a/src/fs/fat/cluster.c +++ b/src/fs/fat/cluster.c @@ -2,6 +2,7 @@ #include "const.h" #include "include/dir.h" #include "include/fat.h" +#include "kernel/console.h" #include "multiple_return.h" #include #include @@ -26,7 +27,7 @@ FsResult fat_table_read( int count = cache_size / SECTOR_SIZE; TRANSFER_IN_BLOCK( - partition->storage_object, entry->data, + partition->storage_object, NULL, entry->data, fat_info->fat_start + entry->position, count); return FS_OK; } @@ -40,7 +41,7 @@ FsResult fat_table_write( for (int i = 0; i < fat_info->bpb->BPB_NumFATs; i++) { TRANSFER_OUT_BLOCK( - partition->storage_object, entry->data, + partition->storage_object, NULL, entry->data, fat_info->fat_start + entry->position, count); } @@ -171,7 +172,10 @@ FsResult get_cluster_segment(FatInfo *fat_info, FatDirEntry *entry) { cluster = get_next_cluster(fat_info, cluster); } segment.start = cluster; - while (!is_eof(fat_info, cluster)) { + + int offset = cluster % fat_info->bpb->BPB_BytesPerSec; + int max = cluster + fat_info->bpb->BPB_BytesPerSec - offset; + while (!is_eof(fat_info, cluster) && cluster < max) { uint32_t tmp = get_next_cluster(fat_info, cluster); if (tmp != cluster + 1) { segment.end = cluster; @@ -181,6 +185,11 @@ FsResult get_cluster_segment(FatInfo *fat_info, FatDirEntry *entry) { } cluster = tmp; } + if (cluster == max) { + segment.end = cluster; + dyn_array_append(arr, ClusterSegment, segment); + return FS_OK; + } segment.start = segment.end = 0x0fffffff; dyn_array_append(arr, ClusterSegment, segment); @@ -202,6 +211,7 @@ FsResult fat_cluster_list_get( cur_cluster->cluster = clus_seg.start + counter; cur_cluster->offset = _block_offset; cur_cluster->block = _block; + cur_cluster->index = index; return FS_OK; } counter -= length; @@ -236,9 +246,49 @@ FsResult fat_cluster_list_get_next( } cur_cluster->cluster = seg->start; } + cur_cluster->index++; return FS_OK; } +uint32_t get_remaining_continuous_clusters(CurrentCluster *cur_cluster) { + uint32_t current = cur_cluster->cluster; + ClusterSegment *seg = + &((ClusterSegment *)cur_cluster->block->data)[cur_cluster->offset]; + + return seg->end - current; +} + +void fat_cluster_list_skip( + FatDirEntry *entry, CurrentCluster *cur_cluster, int count) { + ClusterSegment *seg = + &((ClusterSegment *)cur_cluster->block->data)[cur_cluster->offset]; + uint32_t current = cur_cluster->cluster; + uint32_t end = seg->end; + if (current + count <= end) { + cur_cluster->cluster += count; + } else { + count -= end - current + 1; + cur_cluster->offset++; + if (cur_cluster->offset >= entry->cluster_list->block_size) { + cur_cluster->block = cur_cluster->block->next; + cur_cluster->offset = 0; + } + seg = + &((ClusterSegment *)cur_cluster->block->data)[cur_cluster->offset]; + while (count > seg->end - seg->start + 1) { + count -= seg->end - seg->start + 1; + cur_cluster->offset++; + if (cur_cluster->offset >= entry->cluster_list->block_size) { + cur_cluster->block = cur_cluster->block->next; + cur_cluster->offset = 0; + } + seg = &((ClusterSegment *) + cur_cluster->block->data)[cur_cluster->offset]; + } + cur_cluster->cluster = seg->start + count; + } +} + FsResult get_last_cluster( FatInfo *fat_info, FatDirEntry *entry, DEF_MRET(uint32_t, last_cluster)) { DynArray *arr = entry->cluster_list; diff --git a/src/fs/fat/dir.c b/src/fs/fat/dir.c index fac4d93..06fcbe0 100644 --- a/src/fs/fat/dir.c +++ b/src/fs/fat/dir.c @@ -165,7 +165,8 @@ FsResult fat32_dir_lookup( DEF_MRET(FatLocation, location), DEF_MRET(ShortDir, short_dir)) { FatDirIterator iter; string_t _name; - ShortDir *short_dir = NULL; + uint8_t entry_buf[0x20]; + ShortDir *short_dir = (ShortDir *)entry_buf; fat_dir_iterator_init(&iter, fat_info, parent_entry); while (fat32_read_dir_entry(&iter, short_dir) == FS_OK) { // 生成文件名 @@ -206,7 +207,8 @@ FsResult fat_dir_lookup( DEF_MRET(FatLocation, location), DEF_MRET(ShortDir, short_dir)) { FatDirIterator iter; string_t _name; - ShortDir *short_dir = NULL; + uint8_t entry_buf[0x20]; + ShortDir *short_dir = (ShortDir *)entry_buf; fat_dir_iterator_init(&iter, fat_info, parent_entry); while (fat_read_dir_entry(&iter, short_dir) == FS_OK) { diff --git a/src/fs/fat/entry.c b/src/fs/fat/entry.c index 6ea78c2..654bfe9 100644 --- a/src/fs/fat/entry.c +++ b/src/fs/fat/entry.c @@ -24,7 +24,8 @@ entry_read(BlockCacheEntry *entry, size_t cache_size, void *private_data) { int count = DIV_ROUND_UP(cache_size, fat_info->bpb->BPB_BytesPerSec); uint32_t sector = cluster2sector(fat_info, entry->position); - TRANSFER_IN_BLOCK(partition->storage_object, entry->data, sector, count); + TRANSFER_IN_BLOCK( + partition->storage_object, NULL, entry->data, sector, count); return FS_OK; } @@ -38,7 +39,7 @@ entry_write(BlockCacheEntry *entry, size_t cache_size, void *private_data) { for (int i = 0; i < fat_info->bpb->BPB_NumFATs; i++) { TRANSFER_OUT_BLOCK( - partition->storage_object, entry->data, sector, count); + partition->storage_object, NULL, entry->data, sector, count); } return FS_OK; diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c index 784eb08..cf0d279 100644 --- a/src/fs/fat/fat.c +++ b/src/fs/fat/fat.c @@ -3,6 +3,9 @@ #include "include/cluster.h" #include "include/dir.h" #include "include/entry.h" +#include "kernel/console.h" +#include "math.h" +#include "objects/handle.h" #include #include #include @@ -17,6 +20,7 @@ #include #include #include +#include #include FsResult fat_check(Partition *partition); @@ -29,9 +33,12 @@ FsResult fat_open( FileSystemInfo *fs_info, Object *parent_obj, ObjectAttr *attr, string_t *name, Object **object); FsResult fat_close(Object *object); -FsResult fat_seek(Object *object, size_t offset); -FsResult fat_read(Object *file, void *buf, size_t size); -FsResult fat_write(Object *file, void *buf, size_t size); +FsResult fat_seek(Object *file, size_t offset); +FsResult fat_read(Object *file, ObjectHandle *handle, void *buf, size_t size); +FsResult fat_write( + Object *object, ObjectHandle *handle, void *buf, size_t size); +FsResult fat_create_handle(ObjectHandle *handle); +FsResult fat_delete_handle(ObjectHandle *handle); FsResult fat_opendir( FileSystemInfo *fs_info, Object *parent_obj, void **iterator); @@ -51,13 +58,15 @@ FileSystemOps fat_ops = { }; FsFileOps fat_file_ops = { - .fs_open = fat_open, - .fs_close = fat_close, - .fs_seek = fat_seek, - .fs_read = fat_read, - .fs_write = fat_write, - .fs_get_attr = fat_get_attr, - .fs_set_attr = fat_set_attr, + .fs_open = fat_open, + .fs_close = fat_close, + .fs_seek = fat_seek, + .fs_read = fat_read, + .fs_write = fat_write, + .fs_get_attr = fat_get_attr, + .fs_set_attr = fat_set_attr, + .fs_create_handle = fat_create_handle, + .fs_delete_handle = fat_delete_handle, }; FsDirectoryOps fat_dir_ops = { @@ -309,61 +318,104 @@ FsResult fat_seek(Object *object, size_t offset) { return FS_OK; } +FsResult fat_create_handle(ObjectHandle *handle) { + if (handle == NULL || handle->object == NULL) + return FS_ERROR_INVALID_PARAMS; + Object *file = handle->object; + if (file->fs_info == NULL) return FS_ERROR_INVALID_PARAMS; + FatInfo *fat_info = file->fs_info->private_data; + CurrentCluster *cur_cluster = kmalloc(sizeof(CurrentCluster)); + if (cur_cluster == NULL) return FS_ERROR_OUT_OF_MEMORY; + fat_cluster_list_get(fat_info, file->value.file.data, 0, cur_cluster); + handle->handle_data = cur_cluster; + return FS_OK; +} + +FsResult fat_delete_handle(ObjectHandle *handle) { + if (handle == NULL) return FS_ERROR_INVALID_PARAMS; + kfree(handle->handle_data); + return FS_OK; +} + FsResult fat_transfer( BlockTransfer transfer, TransferDirection direction, IsTransferDone is_transfer_done, FatInfo *fat_info, Object *storage_object, - Object *file, void *buf, size_t size) { + Object *file, ObjectHandle *handle, void *buf, size_t size) { FatDirEntry *entry = file->value.file.data; uint32_t cluster_index = file->value.file.offset / fat_info->bytes_per_cluster; - CurrentCluster cur_cluster; - fat_cluster_list_get(fat_info, entry, cluster_index, &cur_cluster); + CurrentCluster *cur_cluster = handle->handle_data; + if (cluster_index - cur_cluster->index > 1) { + fat_cluster_list_get(fat_info, entry, cluster_index, cur_cluster); + } else if (cluster_index - cur_cluster->index == 1) { + fat_cluster_list_get_next(fat_info, entry, cur_cluster); + } - uint32_t offset = file->value.file.offset; - uint32_t readed = 0; + uint32_t offset = file->value.file.offset % fat_info->bytes_per_cluster; + uint32_t done = 0; while (size > 0) { uint32_t read_size = fat_info->bytes_per_cluster - offset; if (read_size > size) { read_size = size; } - uint32_t sector = cluster2sector(fat_info, cur_cluster.cluster); + uint32_t sector = cluster2sector(fat_info, cur_cluster->cluster); + + if (offset + read_size == fat_info->bytes_per_cluster) { + CurrentCluster next = *cur_cluster; - transfer( - storage_object, direction, buf + readed, sector, - fat_info->sector_per_cluster); + int count = 0; + int total_count = DIV_ROUND_UP(size, fat_info->bytes_per_cluster); + count = get_remaining_continuous_clusters(&next); + count = MIN(count, total_count); + fat_cluster_list_skip(entry, cur_cluster, count); - readed += read_size; - size -= read_size; - offset += read_size; + TransferResult result = transfer( + storage_object, NULL, direction, buf + done, sector, + count * fat_info->sector_per_cluster); + if (result != TRANSFER_OK) return FS_ERROR_TRANSFER; - if (offset == fat_info->bytes_per_cluster) { + done += read_size + (count - 1) * fat_info->bytes_per_cluster; + size -= read_size + (count - 1) * fat_info->bytes_per_cluster; offset = 0; - fat_cluster_list_get_next(fat_info, entry, &cur_cluster); + } else { + TransferResult result = transfer( + storage_object, NULL, direction, buf + done, sector, + fat_info->sector_per_cluster); + if (result != TRANSFER_OK) return FS_ERROR_TRANSFER; + + done += read_size; + size -= read_size; + offset += read_size; + + if (offset == fat_info->bytes_per_cluster) { + offset = 0; + fat_cluster_list_get_next(fat_info, entry, cur_cluster); + } } } - file->value.file.offset = offset; + file->value.file.offset += done; return FS_OK; } -FsResult fat_read(Object *file, void *buf, size_t size) { +FsResult fat_read(Object *file, ObjectHandle *handle, void *buf, size_t size) { FatInfo *fat_info = file->fs_info->private_data; Object *storage_object = fat_info->partition->storage_object; return fat_transfer( storage_object->in.block, TRANSFER_IN, storage_object->in.is_transfer_done, fat_info, storage_object, file, - buf, size); + handle, buf, size); } -FsResult fat_write(Object *file, void *buf, size_t size) { +FsResult fat_write(Object *file, ObjectHandle *handle, void *buf, size_t size) { FatInfo *fat_info = file->fs_info->private_data; Object *storage_object = fat_info->partition->storage_object; return fat_transfer( storage_object->out.block, TRANSFER_OUT, storage_object->out.is_transfer_done, fat_info, storage_object, file, - buf, size); + handle, buf, size); } FsResult fat_create_file(Object *parent_obj, string_t *name, Object **object) { diff --git a/src/fs/fat/include/cluster.h b/src/fs/fat/include/cluster.h index 0971d5b..0f77dac 100644 --- a/src/fs/fat/include/cluster.h +++ b/src/fs/fat/include/cluster.h @@ -17,6 +17,7 @@ typedef struct ClusterSegment { typedef struct CurrentCluster { uint32_t cluster; int offset; + int index; DynArrayBlock *block; } CurrentCluster; @@ -46,6 +47,9 @@ FsResult fat_cluster_list_get( FsResult fat_cluster_list_get_next( struct FatInfo *fat_info, struct FatDirEntry *entry, CurrentCluster *cur_cluster); +uint32_t get_remaining_continuous_clusters(CurrentCluster *cur_cluster); +void fat_cluster_list_skip( + struct FatDirEntry *entry, CurrentCluster *cur_cluster, int count); inline bool fat_cluster_list_is_last( struct FatInfo *fat_info, struct FatDirEntry *entry, CurrentCluster *cur_cluster); diff --git a/src/fs/fs.c b/src/fs/fs.c index a7e7e14..2d31c68 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c @@ -19,17 +19,27 @@ void unregister_fs(FileSystem *fs) { // 为文件系统实现对象树的接口 TransferResult fs_obj_read( - struct Object *object, TransferDirection direction, uint8_t *buf, - size_t size) { - FsResult result = object->fs_info->file_ops.fs_read(object, buf, size); + struct Object *object, struct ObjectHandle *handle, + TransferDirection direction, uint8_t *buf, size_t size) { + if (object == NULL || handle == NULL) + return TRANSFER_ERROR_INVALID_PARAMETER; + if (object->fs_info == NULL || object->fs_info->file_ops.fs_read == NULL) + return TRANSFER_ERROR_INVALID_PARAMETER; + FsResult result = + object->fs_info->file_ops.fs_read(object, handle, buf, size); if (result == FS_OK) return TRANSFER_OK; else return TRANSFER_ERROR_OTHER; } TransferResult fs_obj_write( - struct Object *object, TransferDirection direction, uint8_t *buf, - size_t size) { - FsResult result = object->fs_info->file_ops.fs_write(object, buf, size); + struct Object *object, struct ObjectHandle *handle, + TransferDirection direction, uint8_t *buf, size_t size) { + if (object == NULL || handle == NULL) + return TRANSFER_ERROR_INVALID_PARAMETER; + if (object->fs_info == NULL || object->fs_info->file_ops.fs_write == NULL) + return TRANSFER_ERROR_INVALID_PARAMETER; + FsResult result = + object->fs_info->file_ops.fs_write(object, handle, buf, size); if (result == FS_OK) return TRANSFER_OK; else return TRANSFER_ERROR_OTHER; } diff --git a/src/include/const.h b/src/include/const.h index dcd2c8e..20ea277 100644 --- a/src/include/const.h +++ b/src/include/const.h @@ -1,6 +1,4 @@ #ifndef _CONST_H #define _CONST_H -#define SECTOR_SIZE 512 - #endif \ No newline at end of file diff --git a/src/include/driver/storage/storage_dm.h b/src/include/driver/storage/storage_dm.h index 4767813..8ba61d2 100644 --- a/src/include/driver/storage/storage_dm.h +++ b/src/include/driver/storage/storage_dm.h @@ -5,6 +5,7 @@ #include "kernel/driver.h" #include "kernel/list.h" #include "kernel/periodic_task.h" +#include "kernel/spinlock.h" #include "objects/object.h" #include "string.h" #include @@ -24,6 +25,8 @@ typedef struct StorageDeviceOps { bool (*is_busy)(struct StorageDevice *storage_device); } StorageDeviceOps; +#define SECTOR_SIZE 512 + struct Object; typedef struct StorageDevice { Device *device; @@ -33,7 +36,9 @@ typedef struct StorageDevice { string_t name; uint32_t block_size; + size_t max_block_per_request; + spinlock_t queue_lock; PeriodicTask periodic_task; list_t io_queue_lh; diff --git a/src/include/driver/storage/storage_io.h b/src/include/driver/storage/storage_io.h index c2b2226..1cd4caf 100644 --- a/src/include/driver/storage/storage_io.h +++ b/src/include/driver/storage/storage_io.h @@ -1,15 +1,16 @@ #ifndef _STORAGE_IO_H #define _STORAGE_IO_H +#include #include #include TransferResult storage_transfer_async( - Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count, void **handle); + Object *object, ObjectHandle *obj_handle, TransferDirection direction, + uint8_t *buf, uint32_t position, size_t count, void **handle); TransferResult storage_transfer( - Object *object, TransferDirection direction, uint8_t *buf, - uint32_t position, size_t count); + Object *object, ObjectHandle *obj_handle, TransferDirection direction, + uint8_t *buf, uint32_t position, size_t count); TransferResult storage_is_transfer_done( Object *object, void **handle, bool *done); diff --git a/src/include/fs/fs.h b/src/include/fs/fs.h index 9a177ca..5455de4 100644 --- a/src/include/fs/fs.h +++ b/src/include/fs/fs.h @@ -1,6 +1,7 @@ #ifndef _FS_H #define _FS_H +#include "objects/handle.h" #include "string.h" #include #include @@ -18,7 +19,9 @@ typedef enum FsResult { FS_ERROR_NOT_EMPTY, FS_ERROR_END_OF_FILE, FS_ERROR_ILLEGAL_DATA, + FS_ERROR_INVALID_PARAMS, FS_ERROR_NOT_MATCH, + FS_ERROR_TRANSFER, FS_ERROR_OTHER, } FsResult; @@ -43,10 +46,17 @@ typedef struct FsFileOps { string_t *name, Object **object); FsResult (*fs_close)(struct Object *object); FsResult (*fs_seek)(struct Object *object, size_t offset); - FsResult (*fs_read)(struct Object *file, void *buf, size_t size); - FsResult (*fs_write)(struct Object *file, void *buf, size_t size); + FsResult (*fs_read)( + struct Object *object, struct ObjectHandle *handle, void *buf, + size_t size); + FsResult (*fs_write)( + struct Object *object, struct ObjectHandle *handle, void *buf, + size_t size); FsResult (*fs_get_attr)(struct Object *object, struct ObjectAttr *attr); FsResult (*fs_set_attr)(struct Object *object, struct ObjectAttr *attr); + + FsResult (*fs_create_handle)(struct ObjectHandle *handle); + FsResult (*fs_delete_handle)(struct ObjectHandle *handle); } FsFileOps; typedef struct FsDirectoryOps { diff --git a/src/include/objects/handle.h b/src/include/objects/handle.h new file mode 100644 index 0000000..e29620c --- /dev/null +++ b/src/include/objects/handle.h @@ -0,0 +1,15 @@ +#ifndef _OBJECT_HANDLE_H +#define _OBJECT_HANDLE_H + +#include "object.h" + +typedef struct ObjectHandle { + Object *object; + void *handle_data; + void *buf; +} ObjectHandle; + +ObjectHandle *object_handle_create(Object *object); +ObjectResult object_handle_delete(ObjectHandle *handle); + +#endif \ No newline at end of file diff --git a/src/kernel/memory.c b/src/kernel/memory.c index 0bbc7fd..7b52368 100644 --- a/src/kernel/memory.c +++ b/src/kernel/memory.c @@ -81,9 +81,9 @@ int mmap_search(struct mmap *btmp, unsigned int cnt) { int index_start = index_byte * 8 + index_bit; if (cnt == 1) { return index_start; } - int bit_left = btmp->len * 8 - index_start; + int bit_left = btmp->len * 8 - index_start - 1; int next_bit = index_start + 1; - int count = 0; + int count = 1; while (bit_left-- > 0) { if (!(btmp->bits[next_bit / 8] & 1 << (next_bit % 8))) { count++; diff --git a/src/objects/Makefile b/src/objects/Makefile index 66a9ab7..277cad6 100644 --- a/src/objects/Makefile +++ b/src/objects/Makefile @@ -2,4 +2,5 @@ SRC += objects.c SRC += types.c SRC += mount.c SRC += ops.c -SRC += permission.c \ No newline at end of file +SRC += permission.c +SRC += handle.c \ No newline at end of file diff --git a/src/objects/handle.c b/src/objects/handle.c new file mode 100644 index 0000000..87c591b --- /dev/null +++ b/src/objects/handle.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +ObjectHandle *object_handle_create(Object *object) { + ObjectHandle *handle = kmalloc(sizeof(ObjectHandle)); + if (handle == NULL) return NULL; + handle->object = object; + handle->buf = NULL; + handle->handle_data = NULL; + object->fs_info->file_ops.fs_create_handle(handle); + return handle; +} + +ObjectResult object_handle_delete(ObjectHandle *handle) { + handle->object->fs_info->file_ops.fs_delete_handle(handle); + kfree(handle); + return OBJECT_OK; +} \ No newline at end of file From 173f89ad16fa6d6f385c0848a1bef300d8b802fc Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 19 Mar 2025 23:31:31 +0800 Subject: [PATCH 038/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20ide=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8=E7=BB=99current=5Frequest=E5=8A=A0=E4=B8=8A=E4=BA=92?= =?UTF-8?q?=E6=96=A5=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/disk/ata/ide.c | 20 +++++++++++++++++--- src/arch/x86/drivers/disk/ata/include/ide.h | 2 ++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index ad8a302..4481eb7 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -20,6 +20,7 @@ #include "include/ata_driver.h" #include "include/ide.h" #include "include/ide_controller.h" +#include "kernel/spinlock.h" DriverResult ide_device_init(Device *device); @@ -75,9 +76,13 @@ void ide_handle_interrupt(IdeChannel *channel) { ide_print_error(channel); } - IdeDevice *ide_device = channel->ide_devices[channel->selected_device]; - StorageRequest *request = ide_device->current_request; + IdeDevice *ide_device = channel->ide_devices[channel->selected_device]; + + int flags = spin_lock_irqsave(&ide_device->request_lock); + StorageRequest *request = ide_device->current_request; ide_device->current_request = NULL; + spin_unlock_irqrestore(&ide_device->request_lock, flags); + if (ide_device->mode == TRANSFER_MODE_DMA) { uint8_t data = io_in_byte(channel->bmide + IDE_REG_BM_STATUS); io_out_byte( @@ -188,6 +193,7 @@ void ide_device_probe(IdeChannel *channel) { ide_device->info = identify; ide_device->device_num = i; ide_device->current_request = NULL; + spinlock_init(&ide_device->request_lock); channel->ide_devices[i] = ide_device; @@ -346,6 +352,7 @@ DriverResult ide_device_read_sectors( ide_wait(channel); io_out_byte(channel->io_base + ATA_REG_COMMAND, cmd); + int flags = spin_lock_irqsave(&ide_device->request_lock); ide_device->current_request = request; if (ide_device->mode == TRANSFER_MODE_PIO) { ide_device_recv_pio( @@ -356,6 +363,7 @@ DriverResult ide_device_read_sectors( channel->bmide + IDE_REG_BM_COMMAND, BIN_EN(data, IDE_BMCMD_START_STOP_BM)); } + spin_unlock_irqrestore(&ide_device->request_lock, flags); return DRIVER_RESULT_OK; } @@ -400,6 +408,7 @@ DriverResult ide_device_write_sectors( ide_wait(channel); io_out_byte(channel->io_base + ATA_REG_COMMAND, cmd); + int flags = spin_lock_irqsave(&ide_device->request_lock); ide_device->current_request = request; if (ide_device->mode == TRANSFER_MODE_PIO) { ide_device_send_pio( @@ -410,6 +419,7 @@ DriverResult ide_device_write_sectors( channel->bmide + IDE_REG_BM_COMMAND, BIN_EN(data, IDE_BMCMD_START_STOP_BM)); } + spin_unlock_irqrestore(&ide_device->request_lock, flags); return DRIVER_RESULT_OK; } @@ -417,5 +427,9 @@ bool ide_device_is_busy(StorageDevice *storage_device) { Device *device = storage_device->device; IdeDevice *ide_device = device->private_data; - return ide_device->current_request != NULL; + int flags = spin_lock_irqsave(&ide_device->request_lock); + bool result = ide_device->current_request != NULL; + spin_unlock_irqrestore(&ide_device->request_lock, flags); + + return result; } diff --git a/src/arch/x86/drivers/disk/ata/include/ide.h b/src/arch/x86/drivers/disk/ata/include/ide.h index a7941c7..adfba57 100644 --- a/src/arch/x86/drivers/disk/ata/include/ide.h +++ b/src/arch/x86/drivers/disk/ata/include/ide.h @@ -6,6 +6,7 @@ #include "driver/storage/storage_io_queue.h" #include "ide_controller.h" #include "kernel/device.h" +#include "kernel/spinlock.h" #include "stdint.h" #define IDE_IRQ0 14 @@ -27,6 +28,7 @@ typedef struct IdeDevice { TRANSFER_MODE_DMA, } mode; + spinlock_t request_lock; StorageRequest *current_request; AtaCmdIndex cmdset[ATA_CMDSET_MAX]; From d07b9fc243252d875f9b3dc785c26aae11a7454e Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 22 Mar 2025 20:46:27 +0800 Subject: [PATCH 039/158] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20IDE=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8DMA=E9=85=8D=E7=BD=AEbug=EF=BC=9B=E4=BF=AE=E5=A4=8D=20?= =?UTF-8?q?FAT=E9=A9=B1=E5=8A=A8=E7=B0=87=E8=8E=B7=E5=8F=96bug=EF=BC=9B?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E5=AD=98=E5=82=A8=E8=AE=BE=E5=A4=87IO?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=88=86=E5=89=B2=E5=8A=9F=E8=83=BD=EF=BC=9B?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=20=E5=AD=98=E5=82=A8=E8=AE=BE=E5=A4=87IO?= =?UTF-8?q?=E7=AD=89=E5=BE=85=E6=96=B9=E5=BC=8F=EF=BC=9B=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20thread=5Funblock=E6=AD=BB=E9=94=81bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/disk/ata/ide.c | 53 ++++++---- src/arch/x86/drivers/disk/ata/include/ide.h | 2 + src/driver/storage/storage_io.c | 97 ++++++++++++++----- src/driver/storage/storage_io_queue.c | 20 +++- src/driver/storage/volume.c | 3 +- src/fs/fat/cluster.c | 28 ++++-- src/fs/fat/fat.c | 8 +- src/fs/fat/include/cluster.h | 18 ++-- src/include/driver/storage/storage_io.h | 6 ++ src/include/driver/storage/storage_io_queue.h | 27 ++++-- src/include/kernel/block_cache.h | 1 - src/kernel/sync.c | 95 +++++++++--------- src/kernel/thread.c | 6 +- 13 files changed, 237 insertions(+), 127 deletions(-) diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index 4481eb7..1d2a940 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -20,7 +22,6 @@ #include "include/ata_driver.h" #include "include/ide.h" #include "include/ide_controller.h" -#include "kernel/spinlock.h" DriverResult ide_device_init(Device *device); @@ -84,12 +85,7 @@ void ide_handle_interrupt(IdeChannel *channel) { spin_unlock_irqrestore(&ide_device->request_lock, flags); if (ide_device->mode == TRANSFER_MODE_DMA) { - uint8_t data = io_in_byte(channel->bmide + IDE_REG_BM_STATUS); - io_out_byte( - channel->bmide + IDE_REG_BM_STATUS, - BIN_EN(data, IDE_BMSTATUS_INT | IDE_BMSTATUS_ERROR)); - - data = io_in_byte(channel->bmide + IDE_REG_BM_COMMAND); + uint8_t data = io_in_byte(channel->bmide + IDE_REG_BM_COMMAND); io_out_byte( channel->bmide + IDE_REG_BM_COMMAND, BIN_DIS(data, IDE_BMCMD_START_STOP_BM)); @@ -204,7 +200,7 @@ void ide_device_probe(IdeChannel *channel) { io_out_byte( channel->io_base + ATA_REG_CONTROL, BIN_DIS(data, ATA_CONTROL_NIEN)); - channel->prdt = kmalloc(sizeof(PhysicalRegionDescriptorTable)); + channel->prdt = kmalloc(sizeof(PhysicalRegionDescriptorTable) * 16); interrupt_enable_irq(channel->irq->irq); for (i = 0; i < 2; i++) { @@ -289,25 +285,39 @@ void ide_device_set_dma(IdeDevice *device, StorageRequest *request) { PhysicalRegionDescriptorTable *prdt = channel->prdt; uint8_t *buffer; - buffer = (uint32_t)request->buf & 3 - ? kmalloc(request->count * SECTOR_SIZE) // 未对齐则另外分配 - : request->buf; // 传入的缓冲区已对齐则直接使用 + buffer = (uint32_t)request->buf & 3 + ? kmalloc(request->count * SECTOR_SIZE) // 未对齐则另外分配 + : request->buf; // 传入的缓冲区已对齐则直接使用 + size_t left_size = request->count * SECTOR_SIZE; + int size; request->real_buf = buffer; - prdt->base_addr = vir2phy((uint32_t)buffer); - prdt->count = request->count * SECTOR_SIZE; - prdt->sign = BIT(15); + int i = 0; + uint32_t addr = vir2phy((uint32_t)buffer); + uint32_t offset; + while (left_size > 0 && i < IDE_MAX_PRDT_COUNT) { + offset = addr & 0xffff; // 缓冲区不能跨越64K边界 + size = MIN(left_size, 0x10000 - offset); + prdt[i].base_addr = addr; + prdt[i].count = size & 0xffff; + prdt[i].sign = 0; + left_size -= size; + addr += size; + i++; + } + prdt[i - 1].sign = BIT(15); io_out_dword(channel->bmide + IDE_REG_BM_PRDT, vir2phy((uint32_t)prdt)); - uint8_t data = io_in_byte(channel->bmide + IDE_REG_BM_STATUS); - io_out_byte( - channel->bmide + IDE_REG_BM_STATUS, - BIN_EN(data, IDE_BMSTATUS_INT | IDE_BMSTATUS_ERROR)); - - io_in_byte(channel->bmide + IDE_REG_BM_COMMAND); + uint8_t data; + data = io_in_byte(channel->bmide + IDE_REG_BM_COMMAND); data = (request->rw == 0) ? BIN_EN(data, IDE_BMCMD_READ_WRITE) : BIN_DIS(data, IDE_BMCMD_READ_WRITE); io_out_byte(channel->bmide + IDE_REG_BM_COMMAND, data); + + data = io_in_byte(channel->bmide + IDE_REG_BM_STATUS); + io_out_byte( + channel->bmide + IDE_REG_BM_STATUS, + BIN_EN(data, IDE_BMSTATUS_INT | IDE_BMSTATUS_ERROR)); } /** @@ -324,8 +334,9 @@ DriverResult ide_device_read_sectors( bool flag = false; + request->count = MIN(request->count, IDE_MAX_PRDT_COUNT * 128 - 1); // 因为没有实现对28位地址的处理,所以超过24位都使用48位地址 - if ((request->position < 0x1000000) || request->count < 0x100) { + if ((request->position < 0x1000000) || request->count <= 0x100) { flag = true; } diff --git a/src/arch/x86/drivers/disk/ata/include/ide.h b/src/arch/x86/drivers/disk/ata/include/ide.h index adfba57..f1ba992 100644 --- a/src/arch/x86/drivers/disk/ata/include/ide.h +++ b/src/arch/x86/drivers/disk/ata/include/ide.h @@ -12,6 +12,8 @@ #define IDE_IRQ0 14 #define IDE_IRQ1 15 +#define IDE_MAX_PRDT_COUNT 16 + typedef struct IdeOps { void (*set_sector)( struct Device *device, uint32_t lba0, uint32_t lba1, uint32_t count); diff --git a/src/driver/storage/storage_io.c b/src/driver/storage/storage_io.c index 2e79c71..3df0cd1 100644 --- a/src/driver/storage/storage_io.c +++ b/src/driver/storage/storage_io.c @@ -3,33 +3,84 @@ */ #include "kernel/device.h" #include "kernel/thread.h" +#include "multiple_return.h" +#include "stdint.h" #include #include #include #include #include +#include #include #include +// 检查请求大小是否超过设备允许的最大请求大小 +bool storage_check_request_size( + StorageDevice *device, StorageRequest *request) { + if (request->count > device->max_block_per_request) { return false; } + return true; +} + +// 将过大的请求分割成多个小请求 +DriverResult storage_generate_request( + StorageDevice *device, int rw, void *buf, size_t position, size_t count, + DEF_MRET(StorageRequest *, last_request)) { + // 计算需要分割成几个请求 + uint32_t num_requests = DIV_ROUND_UP(count, device->max_block_per_request); + uint32_t remaining_blocks = count; + uint32_t current_position = position; + + StorageRequest *first_request = NULL; + StorageRequest *request; + struct task_s *cur_thread = get_current_thread(); + + // uint32_t t, t0, t1, t2, t3; + // 分割请求 + for (uint32_t i = 0; i < num_requests; i++) { + // 计算当前分片的大小 + uint32_t current_count = + MIN(remaining_blocks, device->max_block_per_request); + + // 创建新的请求 + request = kmalloc(sizeof(StorageRequest)); + if (request == NULL && first_request != NULL) { + return DRIVER_RESULT_OUT_OF_MEMORY; + } + + // 设置新请求的参数 + request->position = current_position; + request->count = current_count; + request->rw = rw; + request->is_finished = 0; + request->storage_device = device; + request->next_merged_request = NULL; + request->thread = cur_thread; + + // 分配或指向原始缓冲区中对应的部分 + request->buf = buf + i * device->max_block_per_request; + + storage_add_request(device, request); + + // 更新剩余块和当前位置 + remaining_blocks -= current_count; + current_position += current_count; + if (first_request == NULL) { first_request = request; } + } + MRET(last_request) = request; + return DRIVER_RESULT_OK; +} + TransferResult storage_transfer_async( Object *object, ObjectHandle *obj_handle, TransferDirection direction, uint8_t *buf, uint32_t position, size_t count, void **handle) { while (object->attr->type == OBJECT_TYPE_SYM_LINK) { object = object->value.sym_link; } - Device *device = object->value.device; - StorageRequest *request = kmalloc(sizeof(StorageRequest)); - - request->storage_device = device->dm_ext; - request->rw = (direction == TRANSFER_IN) ? 0 : 1; - request->buf = buf; - request->position = position; - request->count = count; - request->is_finished = 0; - - *handle = (void *)request; + Device *device = object->value.device; + storage_generate_request( + device->dm_ext, (direction == TRANSFER_IN) ? 0 : 1, buf, position, + count, (StorageRequest **)handle); - storage_add_request(device->dm_ext, request); return TRANSFER_OK; } @@ -39,21 +90,21 @@ TransferResult storage_transfer( while (object->attr->type == OBJECT_TYPE_SYM_LINK) { object = object->value.sym_link; } - Device *device = object->value.device; - StorageRequest *request = kmalloc(sizeof(StorageRequest)); - - request->storage_device = device->dm_ext; - request->rw = (direction == TRANSFER_IN) ? 0 : 1; - request->buf = buf; - request->position = position; - request->count = count; - request->is_finished = 0; + Device *device = object->value.device; - storage_add_request(device->dm_ext, request); + StorageRequest *request; + StorageDevice *storage_device = device->dm_ext; + thread_set_status(TASK_INTERRUPTIBLE); + storage_generate_request( + storage_device, (direction == TRANSFER_IN) ? 0 : 1, buf, position, + count, &request); + thread_wait(); while (!request->is_finished) { - schedule(); + thread_set_status(TASK_INTERRUPTIBLE); + thread_wait(); } + return TRANSFER_OK; } diff --git a/src/driver/storage/storage_io_queue.c b/src/driver/storage/storage_io_queue.c index 7f6f555..43673d4 100644 --- a/src/driver/storage/storage_io_queue.c +++ b/src/driver/storage/storage_io_queue.c @@ -1,6 +1,7 @@ #include "kernel/block_cache.h" #include "kernel/rwlock.h" #include "kernel/spinlock.h" +#include "kernel/thread.h" #include #include #include @@ -67,14 +68,21 @@ bool storage_try_merge_request( void storage_add_request( StorageDevice *storage_device, StorageRequest *request) { - StorageRequest *req; request->storage_device = storage_device; request->is_finished = 0; + spin_lock(&storage_device->queue_lock); - if (list_empty(&storage_device->io_queue_lh)) { + + if (list_empty(&storage_device->io_queue_lh) && + !storage_device->ops->is_busy(storage_device)) { storage_submit_request(request); + spin_unlock(&storage_device->queue_lock); return; } + spin_unlock(&storage_device->queue_lock); + + StorageRequest *req; + spin_lock(&storage_device->queue_lock); list_for_each_owner (req, &storage_device->io_queue_lh, list) { if (storage_try_merge_request( request, req, storage_device->max_block_per_request)) { @@ -82,7 +90,6 @@ void storage_add_request( } if (req->position > request->position) { list_add_before(&request->list, &req->list); - spin_unlock(&storage_device->queue_lock); return; } } @@ -118,15 +125,19 @@ void storage_periodic_task(void *arg) { } } +// 需要修改storage_finish_request函数,支持分割请求的完成 void storage_finish_request(StorageRequest *storage_request) { storage_request->is_finished = true; - StorageRequest *req = storage_request->next_merged_request; + + // 处理合并请求的情况 + StorageRequest *req = storage_request->next_merged_request; if (req) { while (req) { req->is_finished = true; req = req->next_merged_request; } } + thread_unblock(storage_request->thread); } void storage_submit_request(StorageRequest *request) { @@ -143,6 +154,7 @@ void storage_submit_request(StorageRequest *request) { } void storage_solve_read_request(StorageRequest *request) { + // 处理合并请求的情况 StorageRequest *req = request->next_merged_request; if (req) { uint32_t start = request->position; diff --git a/src/driver/storage/volume.c b/src/driver/storage/volume.c index 75367fc..1eab179 100644 --- a/src/driver/storage/volume.c +++ b/src/driver/storage/volume.c @@ -18,7 +18,8 @@ void probe_volume(Partition *partition) { partition->superblock = kmalloc(2 * SECTOR_SIZE); storage_transfer( - object, TRANSFER_IN, partition->superblock, partition->start_lba, 2); + object, NULL, TRANSFER_IN, partition->superblock, partition->start_lba, + 2); if (partition->type == PARTITION_TYPE_MBR) { FileSystem *fs; diff --git a/src/fs/fat/cluster.c b/src/fs/fat/cluster.c index 35363d4..12236ee 100644 --- a/src/fs/fat/cluster.c +++ b/src/fs/fat/cluster.c @@ -1,8 +1,6 @@ #include "include/cluster.h" -#include "const.h" #include "include/dir.h" #include "include/fat.h" -#include "kernel/console.h" #include "multiple_return.h" #include #include @@ -160,11 +158,13 @@ FsResult get_cluster_segment(FatInfo *fat_info, FatDirEntry *entry) { uint32_t cluster; if (arr->size == 0) { + // 如果为空使用第一个簇 cluster = entry->short_dir.first_cluster_low; if (fat_info->type == FAT_TYPE_FAT32) { cluster |= entry->short_dir.first_cluster_high << 16; } } else { + // 否则使用最后一个簇的下一个簇 cluster = ((ClusterSegment)dyn_array_get(arr, ClusterSegment, arr->size - 1)) .end; @@ -212,6 +212,7 @@ FsResult fat_cluster_list_get( cur_cluster->offset = _block_offset; cur_cluster->block = _block; cur_cluster->index = index; + cur_cluster->entry = entry; return FS_OK; } counter -= length; @@ -241,8 +242,7 @@ FsResult fat_cluster_list_get_next( &((ClusterSegment *)cur_cluster->block->data)[cur_cluster->offset]; if (cur_cluster->offset >= (entry->cluster_list->block_size - cur_cluster->block->left_space)) { - result = get_cluster_segment(fat_info, entry); - if (result != FS_OK) return result; + FS_RESULT_PASS(get_cluster_segment(fat_info, entry)); } cur_cluster->cluster = seg->start; } @@ -250,16 +250,26 @@ FsResult fat_cluster_list_get_next( return FS_OK; } -uint32_t get_remaining_continuous_clusters(CurrentCluster *cur_cluster) { +uint32_t get_remaining_continuous_clusters( + FatInfo *fat_info, CurrentCluster *cur_cluster) { uint32_t current = cur_cluster->cluster; ClusterSegment *seg = &((ClusterSegment *)cur_cluster->block->data)[cur_cluster->offset]; + // TODO:获取下一个簇段 + if (seg->end == current) { + FsResult result = fat_cluster_list_get_next( + fat_info, cur_cluster->entry, cur_cluster); + if (result != FS_OK) return 0; + seg = + &((ClusterSegment *)cur_cluster->block->data)[cur_cluster->offset]; + } return seg->end - current; } -void fat_cluster_list_skip( - FatDirEntry *entry, CurrentCluster *cur_cluster, int count) { +FsResult fat_cluster_list_skip( + FatInfo *fat_info, FatDirEntry *entry, CurrentCluster *cur_cluster, + int count) { ClusterSegment *seg = &((ClusterSegment *)cur_cluster->block->data)[cur_cluster->offset]; uint32_t current = cur_cluster->cluster; @@ -279,6 +289,9 @@ void fat_cluster_list_skip( count -= seg->end - seg->start + 1; cur_cluster->offset++; if (cur_cluster->offset >= entry->cluster_list->block_size) { + if (cur_cluster->block->next == NULL) { + FS_RESULT_PASS(get_cluster_segment(fat_info, entry)); + } cur_cluster->block = cur_cluster->block->next; cur_cluster->offset = 0; } @@ -287,6 +300,7 @@ void fat_cluster_list_skip( } cur_cluster->cluster = seg->start + count; } + return FS_OK; } FsResult get_last_cluster( diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c index cf0d279..492b4f7 100644 --- a/src/fs/fat/fat.c +++ b/src/fs/fat/fat.c @@ -347,6 +347,7 @@ FsResult fat_transfer( file->value.file.offset / fat_info->bytes_per_cluster; CurrentCluster *cur_cluster = handle->handle_data; + if (cluster_index - cur_cluster->index > 1) { fat_cluster_list_get(fat_info, entry, cluster_index, cur_cluster); } else if (cluster_index - cur_cluster->index == 1) { @@ -367,9 +368,10 @@ FsResult fat_transfer( int count = 0; int total_count = DIV_ROUND_UP(size, fat_info->bytes_per_cluster); - count = get_remaining_continuous_clusters(&next); - count = MIN(count, total_count); - fat_cluster_list_skip(entry, cur_cluster, count); + count = get_remaining_continuous_clusters(fat_info, &next); + if (count == 0) { return FS_ERROR_END_OF_FILE; } + count = MIN(count, total_count); + fat_cluster_list_skip(fat_info, entry, cur_cluster, count); TransferResult result = transfer( storage_object, NULL, direction, buf + done, sector, diff --git a/src/fs/fat/include/cluster.h b/src/fs/fat/include/cluster.h index 0f77dac..9fb990b 100644 --- a/src/fs/fat/include/cluster.h +++ b/src/fs/fat/include/cluster.h @@ -14,11 +14,13 @@ typedef struct ClusterSegment { uint32_t end; } ClusterSegment; +struct FatDirEntry; typedef struct CurrentCluster { - uint32_t cluster; - int offset; - int index; - DynArrayBlock *block; + struct FatDirEntry *entry; + uint32_t cluster; + int offset; + int index; + DynArrayBlock *block; } CurrentCluster; struct FatInfo; @@ -47,9 +49,11 @@ FsResult fat_cluster_list_get( FsResult fat_cluster_list_get_next( struct FatInfo *fat_info, struct FatDirEntry *entry, CurrentCluster *cur_cluster); -uint32_t get_remaining_continuous_clusters(CurrentCluster *cur_cluster); -void fat_cluster_list_skip( - struct FatDirEntry *entry, CurrentCluster *cur_cluster, int count); +uint32_t get_remaining_continuous_clusters( + struct FatInfo *info, CurrentCluster *cur_cluster); +FsResult fat_cluster_list_skip( + struct FatInfo *fat_info, struct FatDirEntry *entry, + CurrentCluster *cur_cluster, int count); inline bool fat_cluster_list_is_last( struct FatInfo *fat_info, struct FatDirEntry *entry, CurrentCluster *cur_cluster); diff --git a/src/include/driver/storage/storage_io.h b/src/include/driver/storage/storage_io.h index 1cd4caf..3e06a7d 100644 --- a/src/include/driver/storage/storage_io.h +++ b/src/include/driver/storage/storage_io.h @@ -1,6 +1,7 @@ #ifndef _STORAGE_IO_H #define _STORAGE_IO_H +#include "driver/storage/storage_io_queue.h" #include #include #include @@ -14,4 +15,9 @@ TransferResult storage_transfer( TransferResult storage_is_transfer_done( Object *object, void **handle, bool *done); +struct StorageDevice; +struct StorageRequest; +bool storage_check_request_size( + struct StorageDevice *device, struct StorageRequest *request); + #endif \ No newline at end of file diff --git a/src/include/driver/storage/storage_io_queue.h b/src/include/driver/storage/storage_io_queue.h index ebd3d8a..f4be280 100644 --- a/src/include/driver/storage/storage_io_queue.h +++ b/src/include/driver/storage/storage_io_queue.h @@ -9,13 +9,17 @@ typedef struct StorageRequest { StorageDevice *storage_device; - list_t list; - bool rw; - uint8_t *buf; // 调用方传入的缓冲区 - uint8_t *real_buf; // 实际读写时使用的缓冲区 - uint64_t position; - uint32_t count; - bool is_finished; + list_t list; + bool rw; + uint8_t *buf; // 调用方传入的缓冲区 + uint8_t *real_buf; // 实际读写时使用的缓冲区 + uint64_t position; + uint32_t count; + bool is_finished; + struct task_s *thread; + + uint32_t t0l, t0h; + uint32_t t1l, t1h; struct StorageRequest *next_merged_request; } StorageRequest; @@ -24,8 +28,15 @@ void storage_add_request( StorageDevice *storage_device, StorageRequest *request); void storage_submit_request(StorageRequest *request); void storage_finish_request(StorageRequest *storage_request); - +void storage_periodic_task(void *arg); +bool storage_try_merge_request( + StorageRequest *new_request, StorageRequest *request, size_t max_count); void storage_solve_read_request(StorageRequest *request); void storage_solve_write_request(StorageRequest *request); +// 新增请求分割相关函数声明 +bool storage_check_request_size(StorageDevice *device, StorageRequest *request); +DriverResult storage_split_request( + StorageDevice *device, StorageRequest *request); + #endif \ No newline at end of file diff --git a/src/include/kernel/block_cache.h b/src/include/kernel/block_cache.h index b5c2c32..d4e0b96 100644 --- a/src/include/kernel/block_cache.h +++ b/src/include/kernel/block_cache.h @@ -5,7 +5,6 @@ #include "fs/fs.h" #include "kernel/list.h" #include "kernel/rwlock.h" -#include "stddef.h" typedef struct BlockCacheEntry { struct BlockCache *cache; diff --git a/src/kernel/sync.c b/src/kernel/sync.c index 464b858..2c83e0d 100644 --- a/src/kernel/sync.c +++ b/src/kernel/sync.c @@ -5,68 +5,65 @@ * @version 0.1 * @date 2021-07 */ +#include "kernel/thread.h" #include #include #include -void sema_init(struct semaphore *psema, uint8_t value) -{ - psema->value = value; - list_init(&psema->waiters); +void sema_init(struct semaphore *psema, uint8_t value) { + psema->value = value; + list_init(&psema->waiters); } -void lock_init(struct lock *plock) -{ - plock->holder = NULL; - plock->holder_repeat_nr = 0; - sema_init(&plock->semaphore, 1); +void lock_init(struct lock *plock) { + plock->holder = NULL; + plock->holder_repeat_nr = 0; + sema_init(&plock->semaphore, 1); } -void sema_down(struct semaphore *psema) -{ - int old_status = io_load_eflags(); - struct task_s *cur_thread = get_current_thread(); - while (psema->value == 0) { - if (list_find(&cur_thread->general_tag, &psema->waiters)) { - printk("sema_down: thread blocked has benn in waiters_list\n"); - } +void sema_down(struct semaphore *psema) { + int old_status = io_load_eflags(); + struct task_s *cur_thread = get_current_thread(); + while (psema->value == 0) { + if (list_find(&cur_thread->general_tag, &psema->waiters)) { + printk("sema_down: thread blocked has benn in waiters_list\n"); + } - list_add_tail(&cur_thread->general_tag, &psema->waiters); - thread_block(TASK_BLOCKED); - } - psema->value--; - io_store_eflags(old_status); + list_add_tail(&cur_thread->general_tag, &psema->waiters); + thread_set_status(TASK_INTERRUPTIBLE); + thread_wait(); + } + psema->value--; + io_store_eflags(old_status); } -void sema_up(struct semaphore *psema) -{ - int old_status = io_load_eflags(); - if (!list_empty(&psema->waiters)) { - struct task_s *thread_blocked = list_owner(&psema->waiters, struct task_s, general_tag); - thread_unblock(thread_blocked); - } - psema->value++; - io_store_eflags(old_status); +void sema_up(struct semaphore *psema) { + int old_status = io_load_eflags(); + if (!list_empty(&psema->waiters)) { + struct task_s *thread_blocked = + list_owner(&psema->waiters, struct task_s, general_tag); + thread_unblock(thread_blocked); + } + psema->value++; + io_store_eflags(old_status); } -void lock_acquire(struct lock *plock) -{ - if (plock->holder != get_current_thread()) { - sema_down(&plock->semaphore); - plock->holder = get_current_thread(); - plock->holder_repeat_nr = 1; - } else { - plock->holder_repeat_nr++; - } +void lock_acquire(struct lock *plock) { + if (plock->holder != get_current_thread()) { + sema_down(&plock->semaphore); + plock->holder = get_current_thread(); + plock->holder_repeat_nr = 1; + } else { + plock->holder_repeat_nr++; + } } -void lock_release(struct lock *plock) -{ - if (plock->holder_repeat_nr > 1) { - plock->holder_repeat_nr--; - return; - } - plock->holder = NULL; - plock->holder_repeat_nr = 0; - sema_up(&plock->semaphore); +void lock_release(struct lock *plock) { + if (plock->holder_repeat_nr > 1) { + plock->holder_repeat_nr--; + return; + } + plock->holder = NULL; + plock->holder_repeat_nr = 0; + sema_up(&plock->semaphore); } \ No newline at end of file diff --git a/src/kernel/thread.c b/src/kernel/thread.c index 4e31f1c..c103c89 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -231,6 +231,8 @@ void thread_wait() { flags = spin_lock_irqsave(&cur_thread->status_lock); } spin_unlock_irqrestore(&cur_thread->status_lock, flags); + } else { + spin_unlock_irqrestore(&cur_thread->status_lock, flags); } } @@ -249,9 +251,7 @@ void thread_unblock(struct task_s *pthread) { } if (pthread->status != TASK_READY) { if (list_find(&pthread->general_tag, &thread_ready)) { - printk("error"); - while (1) - ; + list_del(&pthread->general_tag); } list_add_before(&pthread->general_tag, thread_ready.next); From ea1e0d7cb9e12b18866791b0ab6aec62bed4f226 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 23 Mar 2025 23:46:05 +0800 Subject: [PATCH 040/158] =?UTF-8?q?=E9=87=8D=E6=9E=84=20=E5=B0=8F=E5=86=85?= =?UTF-8?q?=E5=AD=98=E5=88=86=E9=85=8D=E6=9C=BA=E5=88=B6=EF=BC=9B=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20=E9=83=A8=E5=88=86=E7=BA=BF=E7=A8=8B=E7=AE=A1?= =?UTF-8?q?=E7=90=86=EF=BC=9B=E9=87=8D=E6=9E=84=20=E5=AD=90=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E7=AD=89=E5=BE=85=E6=9C=BA=E5=88=B6=EF=BC=9B=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20aligned=5Flog2n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/localenv.mk | 2 +- src/arch/x86/drivers/bus/isa/isa.c | 1 + src/arch/x86/include/kernel/thread.h | 23 ++- src/arch/x86/kernel/func.asm | 4 +- src/arch/x86/kernel/page.c | 14 +- src/driver/timer_dm.c | 2 + src/fs/fat/attr.c | 1 + src/fs/fat/name.c | 1 + src/include/config.h | 4 + src/include/driver/sound/pcm.h | 152 ++++++++++++++++ src/include/kernel/memory.h | 12 ++ src/include/kernel/spinlock.h | 29 ++++ src/include/kernel/sync.h | 17 +- src/include/kernel/wait_queue.h | 5 +- src/include/math.h | 1 + src/kernel/driver.c | 51 +++--- src/kernel/memory.c | 249 ++++++++++++++++----------- src/kernel/process.c | 5 +- src/kernel/sync.c | 28 ++- src/kernel/thread.c | 204 +++++++++++++--------- src/kernel/wait_queue.c | 19 +- src/lib/math.c | 26 +++ src/objects/objects.c | 4 +- 23 files changed, 586 insertions(+), 268 deletions(-) create mode 100644 src/include/driver/sound/pcm.h diff --git a/scripts/localenv.mk b/scripts/localenv.mk index 6aa327a..bd468ff 100644 --- a/scripts/localenv.mk +++ b/scripts/localenv.mk @@ -1,6 +1,6 @@ # env var -ENV_CFLAGS := -march=i486 -fno-builtin -Wall -Wunused -m32 -std=gnu99 -fno-stack-protector -nostdinc -nostdlib -O0 +ENV_CFLAGS := -march=i486 -fno-builtin -Wall -Wunused -m32 -std=gnu11 -fno-stack-protector -nostdinc -nostdlib -O0 # kernel name & version ENV_CFLAGS += -DKERNEL_NAME=\"horizon\" -DKERNEL_VERSION=\"0.0.1\" diff --git a/src/arch/x86/drivers/bus/isa/isa.c b/src/arch/x86/drivers/bus/isa/isa.c index 8331d6e..be454b5 100644 --- a/src/arch/x86/drivers/bus/isa/isa.c +++ b/src/arch/x86/drivers/bus/isa/isa.c @@ -9,6 +9,7 @@ #include #include #include +#include #include LIST_HEAD(isa_driver_lh); diff --git a/src/arch/x86/include/kernel/thread.h b/src/arch/x86/include/kernel/thread.h index 3293bf5..a126792 100644 --- a/src/arch/x86/include/kernel/thread.h +++ b/src/arch/x86/include/kernel/thread.h @@ -4,6 +4,7 @@ #include "kernel/spinlock.h" #include #include +#include #include typedef void thread_func(void *); @@ -66,9 +67,10 @@ struct task_s { uint32_t stack_magic; size_t subject_id; - uint8_t *end_flag; - spinlock_t *end_flag_lock; - spinlock_t sub_thread_lock; + struct lock child_lock; // 保护子线程计数器的锁 + int child_count; // 当前活跃的子线程数 + struct semaphore child_sem; // 子线程完成信号量(初始为0) + struct task_s *parent; struct mmap vir_page_mmap; struct memory_manage *memory_manage; @@ -80,15 +82,18 @@ struct task_s { #define THREAD_DEFAULT_PRIO 100 -extern list_t thread_all; +extern list_t thread_all; +extern spinlock_t thread_ready_lock; struct task_s *get_current_thread(); size_t get_current_subject_id(); -void init_thread(struct task_s *pthread, char *name, int priority); -void thread_create( - struct task_s *pthread, thread_func *function, void *func_arg); +void init_thread( + struct task_s *pthread, void *stack_page, char *name, int priority); +void thread_create( + struct task_s *pthread, thread_func *function, void *func_arg); struct task_s *thread_start( - char *name, int priority, thread_func function, void *func_arg); + char *name, int priority, thread_func function, void *func_arg, + struct task_s *parent); void thread_exit(void); void thread_set_status(task_status_t status); void thread_wait(); @@ -96,6 +101,6 @@ void thread_unblock(struct task_s *pthread); void init_task(void); void schedule(void); void init_thread_memory_manage(struct task_s *thread); -void thread_set_end_flag(struct task_s *pthread, uint8_t *flag); +void thread_wait_children(struct task_s *parent); #endif \ No newline at end of file diff --git a/src/arch/x86/kernel/func.asm b/src/arch/x86/kernel/func.asm index f53c1b7..dd68f54 100644 --- a/src/arch/x86/kernel/func.asm +++ b/src/arch/x86/kernel/func.asm @@ -94,7 +94,7 @@ EXCEPTION_ENTRY 17,ERROR_CODE EXCEPTION_ENTRY 18,NO_ERROR_CODE EXCEPTION_ENTRY 19,NO_ERROR_CODE EXCEPTION_ENTRY 20,NO_ERROR_CODE -EXCEPTION_ENTRY 21,NO_ERROR_CODE +EXCEPTION_ENTRY 21,ERROR_CODE EXCEPTION_ENTRY 22,NO_ERROR_CODE EXCEPTION_ENTRY 23,ERROR_CODE EXCEPTION_ENTRY 24,ERROR_CODE @@ -257,8 +257,8 @@ io_store_eflags: ; void io_store_eflags(int eflags); save_eflags_cli: ; int save_eflags_cli(void); pushfd - pop eax cli + pop eax ret global syscall_handler diff --git a/src/arch/x86/kernel/page.c b/src/arch/x86/kernel/page.c index 9e0cd5d..8f030bd 100644 --- a/src/arch/x86/kernel/page.c +++ b/src/arch/x86/kernel/page.c @@ -20,9 +20,11 @@ extern struct VesaDisplayInfo vesa_display_info; void setup_page(void) { uint32_t *pdt = (uint32_t *)PDT_PHY_ADDR; memset((void *)PDT_PHY_ADDR, 0, PAGE_SIZE); // 清空数据 + // 0x00000000 - 0x003fffff pdt[0] = (TBL_PHY_ADDR | SIGN_RW | SIGN_SYS | SIGN_P); // 第0个页(前4MB内存):GDT、BIOS、内核主程序 + // 0xffc00000 - 0xffffffff pdt[1023] = (PDT_PHY_ADDR | SIGN_RW | SIGN_SYS | SIGN_P); // 第1023个页(最后4MB内存):页表 @@ -37,16 +39,10 @@ void setup_page(void) { addr += PAGE_SIZE; } - pdt[1] = (DMA_PT_PHY_ADDR1 | SIGN_RW | SIGN_SYS | SIGN_P); + // 0x00800000 - 0x00bfffff pdt[2] = (DMA_PT_PHY_ADDR2 | SIGN_RW | SIGN_SYS | SIGN_P); - pt = (uint32_t *)DMA_PT_PHY_ADDR1; - addr = (0x400000 | SIGN_RW | SIGN_SYS | SIGN_P); - for (i = 0; i < 1024; i++) { - pt[i] = addr; - addr += PAGE_SIZE; - } - pt = (uint32_t *)DMA_PT_PHY_ADDR2; - addr = (0x800000 | SIGN_RW | SIGN_SYS | SIGN_P); + pt = (uint32_t *)DMA_PT_PHY_ADDR2; + addr = (0x800000 | SIGN_RW | SIGN_SYS | SIGN_P); for (i = 0; i < 1024; i++) { pt[i] = addr; addr += PAGE_SIZE; diff --git a/src/driver/timer_dm.c b/src/driver/timer_dm.c index d8d2b93..3cc0e76 100644 --- a/src/driver/timer_dm.c +++ b/src/driver/timer_dm.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include diff --git a/src/fs/fat/attr.c b/src/fs/fat/attr.c index af93d39..3cf7d5e 100644 --- a/src/fs/fat/attr.c +++ b/src/fs/fat/attr.c @@ -2,6 +2,7 @@ #include "include/dir.h" #include "include/fat.h" #include "kernel/driver_interface.h" +#include #include #include #include diff --git a/src/fs/fat/name.c b/src/fs/fat/name.c index 15f0607..804992b 100644 --- a/src/fs/fat/name.c +++ b/src/fs/fat/name.c @@ -4,6 +4,7 @@ #include "math.h" #include "multiple_return.h" #include +#include #include #include diff --git a/src/include/config.h b/src/include/config.h index 15aad96..30950f1 100644 --- a/src/include/config.h +++ b/src/include/config.h @@ -1,4 +1,8 @@ #ifndef _CONFIG_H #define _CONFIG_H +#ifdef __GNUC__ +#define HAS_BUILTIN_CLZ +#endif + #endif \ No newline at end of file diff --git a/src/include/driver/sound/pcm.h b/src/include/driver/sound/pcm.h new file mode 100644 index 0000000..d792a6c --- /dev/null +++ b/src/include/driver/sound/pcm.h @@ -0,0 +1,152 @@ +#ifndef _PCM_H +#define _PCM_H + +#include "kernel/device.h" +#include "kernel/dma.h" +#include "kernel/driver.h" +#include "kernel/spinlock.h" +#include "kernel/wait_queue.h" +#include +#include + +#define PCM_STATUS_FREE 0 +#define PCM_STATUS_HOST_USING 1 +#define PCM_STATUS_DEVICE_USING 2 + +typedef enum PcmDataType { + PCM_U8, + PCM_S8, + PCM_U16LE, + PCM_U16BE, + PCM_S16LE, + PCM_S16BE, + PCM_U24LE, + PCM_U24BE, + PCM_S24LE, + PCM_S24BE, + PCM_U32LE, + PCM_U32BE, + PCM_S32LE, + PCM_S32BE, + PCM_F32LE, + PCM_F32BE, + PCM_F64LE, + PCM_F64BE, +} PcmDataType; + +typedef enum PcmTrigger { + PCM_TRIGGER_NONE, + PCM_TRIGGER_START, + PCM_TRIGGER_STOP, + PCM_TRIGGER_PAUSE, + PCM_TRIGGER_RESUME, +} PcmTrigger; + +typedef enum PcmMode { + PCM_MODE_INTERLEAVED, + PCM_MODE_NONINTERLEAVED, +} PcmMode; + +typedef enum PcmStatus { + PCM_STATUS_CLOSE, + PCM_STATUS_OPEN, + PCM_STATUS_PREPARED, + PCM_STATUS_RUNNING, + PCM_STATUS_PAUSED, +} PcmStatus; + +struct SoundDevice; +struct PcmStream; +typedef struct PcmStreamOps { + DriverResult (*open)( + struct SoundDevice *sound_device, struct PcmStream *stream); + DriverResult (*close)( + struct SoundDevice *sound_device, struct PcmStream *stream); + DriverResult (*prepare)( + struct PcmStream *pcm_stream, void *addr, size_t size); + DriverResult (*trigger)(struct PcmStream *stream, PcmTrigger trigger); + size_t (*position)(struct PcmStream *stream); + + DriverResult (*set_mode)(struct PcmStream *stream, PcmMode mode); + DriverResult (*set_default_params)(struct PcmStream *stream); + DriverResult (*set_data_type)( + struct PcmStream *stream, PcmDataType data_type); + DriverResult (*set_channel)(struct PcmStream *stream, uint8_t channel); +} PcmStreamOps; + +typedef struct PcmStream { + struct PcmDevice *pcm; + struct SoundDevice *sound_device; + PcmStreamOps *ops; + + PcmDataType data_type; + uint8_t channel; + + spinlock_t lock; + WaitQueue wq; + + uint16_t frame_bytes; // 一个帧的大小 + size_t frame_per_period; + uint32_t period_bytes; // 一个周期的大小 + + uint32_t start_threshold; + uint32_t stop_threshold; + + size_t device_ptr_base, device_period_ptr; + size_t host_ptr_base, host_period_ptr; + size_t host_ptr; + + PcmMode hw_mode, user_mode; + + void *private_data; +} PcmStream; + +typedef struct PcmOps { + DriverResult (*set_sample_rate)( + struct PcmDevice *pcm, uint32_t sample_rate); +} PcmOps; + +typedef struct PcmDevice { + struct SoundDevice *sound_device; + + PcmStatus status; + + PcmStream *play_stream; + PcmStream *record_stream; + PcmStream *current_stream; + + void *buf; + + size_t boundary; + size_t buffer_bytes; + uint8_t data_bytes; // 数据单位大小 + + uint32_t sample_rate; + Dma *dma; + + PcmOps *ops; +} PcmDevice; + +PcmDevice *sound_register_pcm( + struct SoundDevice *sound_device, PcmOps *pcm_ops, size_t size); +DriverResult pcm_register_stream( + PcmDevice *pcm, PcmStream **stream, PcmStreamOps *ops, void *private_data); +DriverResult pcm_register_dma( + PcmDevice *pcm, void *dma, void *param, DmaOps *ops); +DriverResult sound_pcm_alloc(PcmStream *stream); + +DriverResult pcm_set_data_type(PcmStream *stream, PcmDataType data_type); +DriverResult pcm_set_channel(PcmStream *stream, uint8_t channel); +DriverResult pcm_set_sample_rate(PcmDevice *pcm, uint32_t sample_rate); +DriverResult sound_pcm_open( + Object *object, int mode, DEF_MRET(PcmDevice *, pcm), + DEF_MRET(PcmStream *, stream)); +DriverResult sound_pcm_set_frame_count(PcmStream *stream, size_t count); +DriverResult sound_pcm_read( + PcmStream *stream, uint8_t *buf, uint32_t frame_count); +DriverResult sound_pcm_write( + PcmStream *stream, uint8_t *buf, uint32_t frame_count); +DriverResult sound_pcm_prepare(PcmStream *stream); +DriverResult sound_pcm_done(PcmStream *stream); + +#endif \ No newline at end of file diff --git a/src/include/kernel/memory.h b/src/include/kernel/memory.h index de4c7c2..761fa2f 100644 --- a/src/include/kernel/memory.h +++ b/src/include/kernel/memory.h @@ -1,6 +1,7 @@ #ifndef _MEMORY_H #define _MEMORY_H +#include "kernel/list.h" #include "result.h" #include @@ -17,9 +18,14 @@ #define MEMORY_BLOCKS 0x1000 #define MEMORY_BLOCK_FREE 0 // 内存信息块空闲 #define MEMORY_BLOCK_USING 1 // 内存信息块使用中 +#define MEMORY_BLOCK_ALLOCATED 2 // 内存信息块已经分配 #define MEMORY_BLOCK_MODE_SMALL 0 // 小块内存描述1024一下的内存块 #define MEMORY_BLOCK_MODE_BIG 1 // 大块内存描述4kb为单位的内存块 +#define MEMORY_FREE_LIST_COUNT 7 + +#define MEMORY_MIN_POW 5 + extern struct mmap phy_page_mmap; extern struct mmap vir_page_mmap; @@ -36,6 +42,7 @@ struct mmap { }; struct memory_block { + list_t list; unsigned int address; int size; int flags; @@ -43,6 +50,11 @@ struct memory_block { }; struct memory_manage { + // 32 64 128 256 512 1024 2048 + list_t free_blocks_list[MEMORY_FREE_LIST_COUNT]; + + int last_free_block; + struct memory_block free_blocks[MEMORY_BLOCKS]; }; diff --git a/src/include/kernel/spinlock.h b/src/include/kernel/spinlock.h index 40eb314..09a1a13 100644 --- a/src/include/kernel/spinlock.h +++ b/src/include/kernel/spinlock.h @@ -21,6 +21,10 @@ static inline void spin_lock(spinlock_t *lock) { } } +static inline int spin_try_lock(spinlock_t *lock) { + return __sync_bool_compare_and_swap(lock, 0, 1); +} + static inline void spin_unlock(volatile spinlock_t *lock) { __asm__ __volatile__("" ::: "memory"); *lock = 0; @@ -33,6 +37,31 @@ static inline int spin_lock_irqsave(spinlock_t *lock) { return flags; } +static inline int spin_try_lock_irqsave(spinlock_t *lock) { + int flags = save_and_disable_interrupt(); + if (spin_try_lock(lock)) { return flags; } + store_interrupt_status(flags); + return 0; +} + +static inline int spin_lock_two_irqsave(spinlock_t *lock1, spinlock_t *lock2) { + int flags; + int f1, f2; + while (true) { + flags = save_and_disable_interrupt(); + f1 = spin_try_lock(lock1); + f2 = spin_try_lock(lock2); + if (f1 && f2) { + return flags; + } else { + if (f1) { spin_unlock(lock1); } + if (f2) { spin_unlock(lock2); } + store_interrupt_status(flags); + } + } + return flags; +} + // 释放自旋锁并恢复之前保存的中断状态 static inline void spin_unlock_irqrestore( spinlock_t *lock, unsigned long flags) { diff --git a/src/include/kernel/sync.h b/src/include/kernel/sync.h index 7e50cd4..4e5f02f 100644 --- a/src/include/kernel/sync.h +++ b/src/include/kernel/sync.h @@ -1,23 +1,26 @@ #ifndef _SYNC_H #define _SYNC_H -#include "list.h" -#include +#include "kernel/wait_queue.h" #include struct semaphore { - uint8_t value; - struct list waiters; + uint8_t value; + WaitQueue wq; }; struct lock { - struct task_s *holder; - struct semaphore semaphore; - uint32_t holder_repeat_nr; + struct task_s *holder; + struct semaphore semaphore; + uint32_t holder_repeat_nr; }; void lock_init(struct lock *plock); void lock_acquire(struct lock *plock); void lock_release(struct lock *plock); +void sema_init(struct semaphore *psema, uint8_t value); +void sema_down(struct semaphore *psema); +void sema_up(struct semaphore *psema); + #endif \ No newline at end of file diff --git a/src/include/kernel/wait_queue.h b/src/include/kernel/wait_queue.h index 99a978d..550f7b1 100644 --- a/src/include/kernel/wait_queue.h +++ b/src/include/kernel/wait_queue.h @@ -4,19 +4,16 @@ #include "types.h" #include #include -#include typedef struct { spinlock_t lock; list_t list_head; } WaitQueue; -typedef struct task_s WaitQueueItem; - void wait_queue_init(WaitQueue *wq); bool wait_queue_empty(WaitQueue *wq); void wait_queue_add(WaitQueue *wq); -WaitQueueItem *wait_queue_first(WaitQueue *wq); +struct task_s *wait_queue_first(WaitQueue *wq); void wait_queue_wakeup(WaitQueue *wq); void wait_queue_wakeup_all(WaitQueue *wq); diff --git a/src/include/math.h b/src/include/math.h index 2a86a84..3813c5f 100644 --- a/src/include/math.h +++ b/src/include/math.h @@ -13,5 +13,6 @@ int max(int a, int b); int abs(int n); int pow(int x, int y); unsigned int find_next_pow_of_2(unsigned int n); +int aligned_log2n(unsigned int n); #endif diff --git a/src/kernel/driver.c b/src/kernel/driver.c index b861301..3c95eec 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -5,6 +5,7 @@ * @version 0.3 * @date 2022-07-20 */ +#include "kernel/sync.h" #include #include #include @@ -40,6 +41,7 @@ struct index_node *dev; // --------new-------- #include #include +#include #include LIST_HEAD(driver_lh); @@ -70,6 +72,9 @@ void print_driver_result( RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_NOT_EXIST) RESULT_CASE_PRINT(DRIVER_RESULT_NULL_POINTER) RESULT_CASE_PRINT(DRIVER_RESULT_UNSUPPORT_DEVICE) + RESULT_CASE_PRINT(DRIVER_RESULT_UNSUPPORT_FEATURE) + RESULT_CASE_PRINT(DRIVER_RESULT_BUSY) + RESULT_CASE_PRINT(DRIVER_RESULT_EXCEED_MAX_SIZE) RESULT_CASE_PRINT(DRIVER_RESULT_OTHER_ERROR) } } @@ -167,54 +172,49 @@ void driver_start_thread(void *arg) { check_dependency(driver); driver_init(driver); - uint8_t end_flag = 0; + struct task_s *cur = get_current_thread(); SubDriver *sub_driver; list_for_each_owner (sub_driver, &driver->sub_driver_lh, sub_driver_list) { int old_status = save_and_disable_interrupt(); - struct task_s *task = thread_start( - "sub_driver_start_thread", THREAD_DEFAULT_PRIO, - sub_driver_start_thread, sub_driver); - thread_set_end_flag(task, &end_flag); + char *name; + if (sub_driver->type == DRIVER_TYPE_DEVICE_DRIVER) { + DeviceDriver *dd = + container_of(sub_driver, DeviceDriver, subdriver); + name = dd->name.text; + } else if (sub_driver->type == DRIVER_TYPE_BUS_DRIVER) { + BusDriver *bd = container_of(sub_driver, BusDriver, subdriver); + name = bd->name.text; + } else name = "sub_driver_start_thread"; + thread_start( + name, THREAD_DEFAULT_PRIO, sub_driver_start_thread, sub_driver, + cur); store_interrupt_status(old_status); } - struct task_s *cur = get_current_thread(); - int flags = spin_lock_irqsave(&cur->sub_thread_lock); - while (end_flag > 0) { - spin_unlock_irqrestore(&cur->sub_thread_lock, flags); - schedule(); - flags = spin_lock_irqsave(&cur->sub_thread_lock); - } + thread_wait_children(cur); } // TODO:PCI检测完设备后,设备有概率未初始化直接结束 DriverResult driver_start_all(void) { - uint8_t end_flag = 0; Driver *driver; + struct task_s *cur = get_current_thread(); + list_for_each_owner (driver, &driver_lh, driver_list) { if (driver->state == DRIVER_STATE_UNINITED) { int old_status = save_and_disable_interrupt(); - struct task_s *task = thread_start( - "driver_start_thread", THREAD_DEFAULT_PRIO, driver_start_thread, - driver); - thread_set_end_flag(task, &end_flag); + thread_start( + driver->short_name.text, THREAD_DEFAULT_PRIO, + driver_start_thread, driver, cur); store_interrupt_status(old_status); } } - struct task_s *cur = get_current_thread(); - int flags = spin_lock_irqsave(&cur->sub_thread_lock); - while (end_flag > 0) { - spin_unlock_irqrestore(&cur->sub_thread_lock, flags); - schedule(); - flags = spin_lock_irqsave(&cur->sub_thread_lock); - } - spin_unlock_irqrestore(&cur->sub_thread_lock, flags); + thread_wait_children(cur); return DRIVER_RESULT_OK; } @@ -224,6 +224,7 @@ struct index_node *dev_open(char *path) { // if (inode == NULL) return NULL; // else inode->device->drv_obj->function.driver_open(inode->device); // return inode; + return NULL; } int dev_close(struct index_node *inode) { diff --git a/src/kernel/memory.c b/src/kernel/memory.c index 7b52368..4251414 100644 --- a/src/kernel/memory.c +++ b/src/kernel/memory.c @@ -5,6 +5,9 @@ * @version 0.1 * @date 2020-07 */ +#include "kernel/driver_interface.h" +#include "kernel/func.h" +#include "kernel/list.h" #include #include #include @@ -23,6 +26,9 @@ struct memory_manage *memory_manage; uint32_t memory_total_size; +const int memory_block_size[MEMORY_FREE_LIST_COUNT] = {32, 64, 128, 256, + 512, 1024, 2048}; + void init_memory(void) { uint16_t ards_nr = *((uint16_t *)ards_nr_addr); // ards 结构数 ards = (struct ards *)ards_addr; // ards 地址 @@ -57,6 +63,10 @@ void init_memory(void) { memory_manage = (struct memory_manage *)kernel_alloc_pages(memory_manage_pages); memset(memory_manage, 0, memory_manage_pages * PAGE_SIZE); + memory_manage->last_free_block = 0; + for (i = 0; i < MEMORY_FREE_LIST_COUNT; i++) { + list_init(&memory_manage->free_blocks_list[i]); + } for (i = 0; i < MEMORY_BLOCKS; i++) { memory_manage->free_blocks[i].size = 0; // 大小是页的数量 memory_manage->free_blocks[i].flags = 0; @@ -136,127 +146,172 @@ MemoryResult alloc_vaddr(size_t in_size, uint32_t *out_vaddr) { return MEMORY_RESULT_OK; } +int find_continuous_free_block(struct memory_manage *mm, int count) { + int k; + for (k = mm->last_free_block; k < MEMORY_BLOCKS; k++) { + if (mm->free_blocks[k].flags == MEMORY_BLOCK_FREE) { + for (int i = 0; i < count; i++) { + if (mm->free_blocks[k + i].flags != MEMORY_BLOCK_FREE) { + break; + } + } + } + } + if (k == MEMORY_BLOCKS) { + for (k = 0; k < mm->last_free_block; k++) { + for (int i = 0; i < count; i++) { + if (mm->free_blocks[k + i].flags != MEMORY_BLOCK_FREE) { + break; + } + } + } + if (k == mm->last_free_block) return -1; + } + mm->last_free_block = k + count; + return k; +} + +int find_free_block(struct memory_manage *mm) { + int i; + for (i = mm->last_free_block; i < MEMORY_BLOCKS; i++) { + if (mm->free_blocks[i].flags == MEMORY_BLOCK_FREE) { + mm->last_free_block = i; + return i; + } + } + for (i = 0; i < mm->last_free_block; i++) { + if (mm->free_blocks[i].flags == MEMORY_BLOCK_FREE) { + mm->last_free_block = i; + return i; + } + } + return -1; +} + +bool split_page(struct memory_manage *mm, size_t page_addr, int pow) { + uint32_t size = 1 << pow; + int break_cnt = PAGE_SIZE >> pow; // 打散成break_cnt个 + + int index = find_free_block(mm); + if (index == -1) return false; + index--; // 因为下面会自增,所以这里先-1 + + uint32_t addr = page_addr; + for (int i = 0; i < break_cnt; i++) { + index++; + if (mm->free_blocks[index].size || index >= MEMORY_BLOCKS) { + index = find_free_block(mm); + if (index == -1) return false; + } + mm->free_blocks[index].address = addr; + mm->free_blocks[index].size = size; + mm->free_blocks[index].flags = MEMORY_BLOCK_USING; + mm->free_blocks[index].mode = MEMORY_BLOCK_MODE_SMALL; + list_add_tail( + &mm->free_blocks[index].list, + &mm->free_blocks_list[pow - MEMORY_MIN_POW]); + addr += size; + } + return true; +} + // 默认对齐32字节 void *kmalloc(uint32_t size) { - int i; - uint32_t address; - uint32_t break_size; // 要打碎成什么大小 - uint32_t break_cnt; // 要打碎成几块 - void *new_address; + void *address; + void *new_address; if (size == 0) { return NULL; } - // 大于1024字节就用页 - if (size >= 2048) { - int pages = DIV_ROUND_UP(size, PAGE_SIZE); // 一共占多少个页 - for (i = 0; i < MEMORY_BLOCKS; i++) { - if (memory_manage->free_blocks[i].flags == - MEMORY_BLOCK_FREE) { // 找到 - address = (uint32_t)kernel_alloc_pages(pages); // 分配页 - memory_manage->free_blocks[i].address = address; - memory_manage->free_blocks[i].size = pages; // 大小是页的数量 - memory_manage->free_blocks[i].flags = MEMORY_BLOCK_USING; - memory_manage->free_blocks[i].mode = MEMORY_BLOCK_MODE_BIG; - // printk("Found pages "); - // printk("Alloc:%x idx:%d\n", address,i); - return (void *)address; - } + + int pow = MAX(aligned_log2n(size), MEMORY_MIN_POW); // 指数 + size = 1 << pow; + + int flags = save_and_disable_interrupt(); // TODO + // 大于半个页就按页分配 + if (size > 2048) { + int pages = size & ~(PAGE_SIZE - 1); // 一共占多少个页 + int index = find_free_block(memory_manage); + if (index == -1) { + store_interrupt_status(flags); + return NULL; } - } else if (0 < size && size <= 2048) { // size <= 2048 - // 对齐判断,要打散成多大 - if (0 < size && size <= 32) { - break_size = 32; - } else if (32 < size && size <= 64) { - break_size = 64; - } else if (64 < size && size <= 128) { - break_size = 128; - } else if (128 < size && size <= 256) { - break_size = 256; - } else if (256 < size && size <= 512) { - break_size = 512; - } else if (512 < size && size <= 1024) { - break_size = 1024; - } else if (1024 < size && size <= 2048) { - break_size = 2048; + address = kernel_alloc_pages(pages); // 分配页 + if (address == NULL) { + store_interrupt_status(flags); + return NULL; } + memory_manage->free_blocks[index].address = (uint32_t)address; + memory_manage->free_blocks[index].size = pages; // 大小是页的数量 + memory_manage->free_blocks[index].flags = MEMORY_BLOCK_USING; + memory_manage->free_blocks[index].mode = MEMORY_BLOCK_MODE_BIG; + store_interrupt_status(flags); + return (void *)address; + } else if (0 < size && size <= 2048) { // size <= 2048 // 第一次寻找,如果在块中没有找到,就打散一个页 - for (i = 0; i < MEMORY_BLOCKS; i++) { - if (memory_manage->free_blocks[i].size == break_size && - memory_manage->free_blocks[i].flags == - MEMORY_BLOCK_FREE) { // 找到 - address = memory_manage->free_blocks[i].address; - memory_manage->free_blocks[i].flags = MEMORY_BLOCK_USING; - // printk("Found broken "); - // printk("Alloc:%x idx:%d\n", address,i); - return (void *)address; - } + if (!list_empty( + &memory_manage->free_blocks_list[pow - MEMORY_MIN_POW])) { + struct memory_block *block = list_first_owner( + &memory_manage->free_blocks_list[pow - MEMORY_MIN_POW], + struct memory_block, list); + address = (void *)block->address; + block->flags = MEMORY_BLOCK_USING; + list_del(&block->list); + store_interrupt_status(flags); + return (void *)address; } // 如果都没有找到,分配一个页,然后打散 // 分配一个页,用来被打散 new_address = kernel_alloc_pages(1); - break_cnt = PAGE_SIZE / break_size; - - // 打散成break_cnt个 - for (i = 0; i < MEMORY_BLOCKS; i++) { - if (memory_manage->free_blocks[i].flags == - MEMORY_BLOCK_FREE) { // 找到一个可以被使用的 - // 地址增加 - - // 设置最终地址 - memory_manage->free_blocks[i].address = (uint32_t)new_address; - new_address += break_size; - // 设置size - memory_manage->free_blocks[i].size = break_size; - // 设置为可以分配 - memory_manage->free_blocks[i].flags = MEMORY_BLOCK_FREE; - // 设置为小块模式 - memory_manage->free_blocks[i].mode = MEMORY_BLOCK_MODE_SMALL; - break_cnt--; - if (break_cnt <= 0) { break; } - } + if (new_address == NULL) { + store_interrupt_status(flags); + return NULL; } - // 打散后的寻找 - for (i = 0; i < MEMORY_BLOCKS; i++) { - if (memory_manage->free_blocks[i].size == break_size && - memory_manage->free_blocks[i].flags == - MEMORY_BLOCK_FREE) { // 找到 - address = memory_manage->free_blocks[i].address; - memory_manage->free_blocks[i].flags = MEMORY_BLOCK_USING; - // printk("Found new broken "); - // printk("Alloc:%x idx:%d\n", address,i); - return (void *)address; - } + if (!split_page(memory_manage, (size_t)new_address, pow)) { + store_interrupt_status(flags); + return NULL; } + + // 打散后再寻找 + struct memory_block *block = list_first_owner( + &memory_manage->free_blocks_list[pow - MEMORY_MIN_POW], + struct memory_block, list); + address = (void *)block->address; + block->flags = MEMORY_BLOCK_ALLOCATED; + list_del(&block->list); + store_interrupt_status(flags); + return (void *)address; } // size=0或者没有找到 + store_interrupt_status(flags); return NULL; // 失败 } int kfree(void *address) { if (address == NULL) { return 0; } - int i; - uint32_t addr = (uint32_t)address; + int i; + uint32_t addr = (uint32_t)address; + struct memory_block *block; + + int flags = save_and_disable_interrupt(); for (i = 0; i < MEMORY_BLOCKS; i++) { - if (memory_manage->free_blocks[i].address == addr && - memory_manage->free_blocks[i].flags == MEMORY_BLOCK_USING) { // 找到 - if (memory_manage->free_blocks[i].mode == MEMORY_BLOCK_MODE_BIG) { - kernel_free_page( - memory_manage->free_blocks[i].address, - memory_manage->free_blocks[i].size); - memory_manage->free_blocks[i].size = - 0; // 只有大块才需要重新设置size - } else if ( - memory_manage->free_blocks[i].mode == MEMORY_BLOCK_MODE_SMALL) { - // 小块内存就清空就是了 - memset( - (void *)memory_manage->free_blocks[i].address, 0, - memory_manage->free_blocks[i].size); + block = &memory_manage->free_blocks[i]; + if (block->address == addr && block->flags == MEMORY_BLOCK_USING) { + if (block->mode == MEMORY_BLOCK_MODE_BIG) { + kernel_free_page(block->address, block->size); + block->flags = MEMORY_BLOCK_FREE; + block->size = 0; // 只有大块才需要重新设置size + store_interrupt_status(flags); + return 0; + } else if (block->mode == MEMORY_BLOCK_MODE_SMALL) { + int pow = aligned_log2n(block->size); + block->flags = MEMORY_BLOCK_USING; + list_add_tail( + &block->list, + &memory_manage->free_blocks_list[pow - MEMORY_MIN_POW]); // 存在一种情况,那就是所有被打散的内存都被释放后,可能需要释放那个页,目前还没有考虑它 // 小块不需要设置大小,因为就是打散了的块 + store_interrupt_status(flags); + return 0; } - memory_manage->free_blocks[i].flags = MEMORY_BLOCK_FREE; - - // printk("Free:%x idx:%d\n", address,i); - return 0; } } diff --git a/src/kernel/process.c b/src/kernel/process.c index 4da255a..470d328 100644 --- a/src/kernel/process.c +++ b/src/kernel/process.c @@ -107,9 +107,10 @@ void create_user_vaddr_mmap(struct task_s *user_prog) { * @param prog 进程 */ void process_excute(void *entry, struct program_struct *prog) { - struct task_s *thread = kernel_alloc_pages(1); + struct task_s *thread = kmalloc(sizeof(struct task_s)); + void *stack_page = kernel_alloc_pages(1); struct prog_segment *p; - init_thread(thread, prog->name.text, THREAD_DEFAULT_PRIO); + init_thread(thread, stack_page, prog->name.text, THREAD_DEFAULT_PRIO); create_user_vaddr_mmap(thread); thread_create(thread, start_process, entry); thread->pgdir = create_page_dir(); diff --git a/src/kernel/sync.c b/src/kernel/sync.c index 2c83e0d..b856dc7 100644 --- a/src/kernel/sync.c +++ b/src/kernel/sync.c @@ -5,14 +5,17 @@ * @version 0.1 * @date 2021-07 */ +#include "kernel/driver_interface.h" #include "kernel/thread.h" +#include "kernel/wait_queue.h" #include #include #include +#include void sema_init(struct semaphore *psema, uint8_t value) { psema->value = value; - list_init(&psema->waiters); + wait_queue_init(&psema->wq); } void lock_init(struct lock *plock) { @@ -22,30 +25,23 @@ void lock_init(struct lock *plock) { } void sema_down(struct semaphore *psema) { - int old_status = io_load_eflags(); - struct task_s *cur_thread = get_current_thread(); + int flags = save_and_disable_interrupt(); while (psema->value == 0) { - if (list_find(&cur_thread->general_tag, &psema->waiters)) { - printk("sema_down: thread blocked has benn in waiters_list\n"); - } - - list_add_tail(&cur_thread->general_tag, &psema->waiters); + store_interrupt_status(flags); thread_set_status(TASK_INTERRUPTIBLE); + wait_queue_add(&psema->wq); thread_wait(); + flags = save_and_disable_interrupt(); } psema->value--; - io_store_eflags(old_status); + store_interrupt_status(flags); } void sema_up(struct semaphore *psema) { - int old_status = io_load_eflags(); - if (!list_empty(&psema->waiters)) { - struct task_s *thread_blocked = - list_owner(&psema->waiters, struct task_s, general_tag); - thread_unblock(thread_blocked); - } + int flags = save_and_disable_interrupt(); + wait_queue_wakeup(&psema->wq); psema->value++; - io_store_eflags(old_status); + store_interrupt_status(flags); } void lock_acquire(struct lock *plock) { diff --git a/src/kernel/thread.c b/src/kernel/thread.c index c103c89..7bfb460 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -22,10 +22,11 @@ #include #include -struct task_s *current_task; +struct task_s *current_task, *dead_task = NULL; struct task_s *main_thread; list_t thread_ready; +spinlock_t thread_ready_lock; LIST_HEAD(thread_all); struct lock pid_lock; uint32_t new_pid = 0; @@ -99,7 +100,8 @@ void thread_create( * @param name 线程名 * @param priority 优先级 */ -void init_thread(struct task_s *pthread, char *name, int priority) { +void init_thread( + struct task_s *pthread, void *stack_page, char *name, int priority) { memset(pthread, 0, sizeof(struct task_s)); strcpy(pthread->name, name); if (pthread == main_thread) { @@ -108,9 +110,13 @@ void init_thread(struct task_s *pthread, char *name, int priority) { pthread->status = TASK_READY; } spinlock_init(&pthread->status_lock); - spinlock_init(&pthread->sub_thread_lock); + + lock_init(&pthread->child_lock); + pthread->child_count = 0; + sema_init(&pthread->child_sem, 0); + pthread->priority = priority; - pthread->kstack = (uint32_t *)((uint32_t)pthread + PAGE_SIZE); + pthread->kstack = (uint32_t *)((uint32_t)stack_page + PAGE_SIZE); pthread->ticks = timer_get_schedule_tick(priority); pthread->elapsed_ticks = 0; pthread->pgdir = NULL; @@ -128,33 +134,35 @@ void init_thread(struct task_s *pthread, char *name, int priority) { * @return struct task_s* 创建好的线程 */ struct task_s *thread_start( - char *name, int priority, thread_func function, void *func_arg) { - struct task_s *thread = kernel_alloc_pages(1); + char *name, int priority, thread_func function, void *func_arg, + struct task_s *parent) { + struct task_s *thread = kmalloc(sizeof(struct task_s)); + void *stack_page = kernel_alloc_pages(1); - init_thread(thread, name, priority); + init_thread(thread, stack_page, name, priority); + + if (parent != NULL) { + thread->parent = parent; + lock_acquire(&parent->child_lock); + parent->child_count++; + lock_release(&parent->child_lock); + } thread_create(thread, function, func_arg); - if (list_find(&thread->general_tag, &thread_ready)) { + printk("[Thread] %s: %#x\n", thread->name, thread); + + if (thread->general_tag.next != NULL) { printk("thread %s:start error!\n", name); while (1) ; } list_add_tail(&thread->general_tag, &thread_ready); + if (list_find(&thread->all_list_tag, &thread_all)) { printk("thread %s:start error!\n", name); while (1) ; } list_add_tail(&thread->all_list_tag, &thread_all); - /* __asm__ __volatile__( - "movl %0, %%esp; \ - pop %%ebp; \ - pop %%ebx; \ - pop %%edi; \ - pop %%esi; \ - ret" - ::"g"(thread->stack) - :"memory" - ); */ return thread; } @@ -162,54 +170,72 @@ void thread_exit(void) { struct task_s *cur = get_current_thread(); cur->status = TASK_DIED; - int flags = spin_lock_irqsave(cur->end_flag_lock); - (*cur->end_flag)--; - spin_unlock_irqrestore(cur->end_flag_lock, flags); + if (cur->parent != NULL) { + struct task_s *parent = cur->parent; + lock_acquire(&parent->child_lock); + parent->child_count--; + if (parent->child_count == 0) { + sema_up(&parent->child_sem); // 所有子线程完成,唤醒父线程 + } + lock_release(&parent->child_lock); + } if (cur->general_tag.next != NULL) list_del(&cur->general_tag); list_del(&cur->all_list_tag); - kfree(cur); + // 切换线程 + spin_lock_irqsave(&thread_ready_lock); + printk("[Thread Exit] %s, parent:%s,", cur->name, cur->parent->name); struct task_s *next; - next = list_first_owner(&thread_ready, struct task_s, general_tag); - - if (list_length(&thread_ready) > 1) { - list_del(thread_ready.next); - int flags = spin_lock_irqsave(&next->status_lock); - next->status = TASK_RUNNING; - spin_unlock_irqrestore(&next->status_lock, flags); - - process_activate(next); - current_task = next; - switch_to((int *)cur, (int *)next); + /** + * 其实本来想正常切换到队列中下一个线程的,但不知道为什么会导致父线程无法退出, + * 所以优先切换到父线程。 + */ + if (cur->parent != NULL) { + next = cur->parent; + if (next->general_tag.next != NULL) { list_del(&cur->general_tag); } + cur->ticks = cur->priority; } else { - process_activate(task_idle); - current_task = task_idle; - switch_to((int *)cur, (int *)task_idle); + next = list_first_owner(&thread_ready, struct task_s, general_tag); + if (next != cur) list_del(&next->general_tag); + else { + printk("[No ready task!]"); + next = task_idle; + } } + + // 进程将要退出,不需要恢复中断状态了 + spin_unlock(&thread_ready_lock); + printk("switch to:%s\n", next->name); + + // 3. 切换线程 + dead_task = cur; + // 激活页表并跳转 + process_activate(next); + current_task = next; + switch_to((int *)cur, (int *)next); } -void thread_set_end_flag(struct task_s *pthread, uint8_t *flag) { - struct task_s *cur = get_current_thread(); - int flags = spin_lock_irqsave(&cur->sub_thread_lock); - int flags2 = spin_lock_irqsave(&pthread->status_lock); - if (pthread->status != TASK_DIED) { - spin_unlock_irqrestore(&pthread->status_lock, flags2); - pthread->end_flag_lock = &cur->sub_thread_lock; - (*flag)++; - pthread->end_flag = flag; +void thread_wait_children(struct task_s *parent) { + // 等待子线程计数器归零 + while (1) { + lock_acquire(&parent->child_lock); + if (parent->child_count == 0) { + lock_release(&parent->child_lock); + break; + } + lock_release(&parent->child_lock); + sema_down(&parent->child_sem); // 阻塞等待信号量 } - spin_unlock_irqrestore(&cur->sub_thread_lock, flags); } /** * @brief 阻塞当前线程 * * @param status 线程的目标状态( - * TASK_INTERRUPTIBLEED:阻塞 - * TASK_WAITING:等待 - * TASK_HANGING:挂起) + * TASK_INTERRUPTIBLE:可中断阻塞 + * TASK_UNINTERRUPTIBLE:不可中断阻塞) */ void thread_set_status(task_status_t status) { struct task_s *cur_thread = get_current_thread(); @@ -221,18 +247,11 @@ void thread_set_status(task_status_t status) { void thread_wait() { struct task_s *cur_thread = get_current_thread(); int flags = spin_lock_irqsave(&cur_thread->status_lock); - if (cur_thread->status == TASK_UNINTERRUPTIBLE) { - spin_unlock_irqrestore(&cur_thread->status_lock, flags); + task_status_t status = cur_thread->status; + spin_unlock_irqrestore(&cur_thread->status_lock, flags); + + while (cur_thread->wait_queue_tag.next != NULL) { schedule(); - } else if (cur_thread->status == TASK_INTERRUPTIBLE) { - while (cur_thread->status == TASK_INTERRUPTIBLE) { - spin_unlock_irqrestore(&cur_thread->status_lock, flags); - schedule(); - flags = spin_lock_irqsave(&cur_thread->status_lock); - } - spin_unlock_irqrestore(&cur_thread->status_lock, flags); - } else { - spin_unlock_irqrestore(&cur_thread->status_lock, flags); } } @@ -246,18 +265,18 @@ void thread_unblock(struct task_s *pthread) { if ((pthread->status != TASK_INTERRUPTIBLE) && (pthread->status != TASK_UNINTERRUPTIBLE)) { spin_unlock_irqrestore(&pthread->status_lock, flags); - printk("Error: trying to unblock a thread not blocked\n"); return; } + if (pthread->status != TASK_READY) { - if (list_find(&pthread->general_tag, &thread_ready)) { + if (pthread->general_tag.next != NULL) { list_del(&pthread->general_tag); } list_add_before(&pthread->general_tag, thread_ready.next); pthread->status = TASK_READY; - spin_unlock_irqrestore(&pthread->status_lock, flags); } + spin_unlock_irqrestore(&pthread->status_lock, flags); } /** @@ -265,8 +284,9 @@ void thread_unblock(struct task_s *pthread) { * */ static void make_main_thread(void) { - main_thread = kernel_alloc_pages(1); - init_thread(main_thread, "System", THREAD_DEFAULT_PRIO); + main_thread = kmalloc(sizeof(struct task_s)); + void *stack_page = kernel_alloc_pages(1); + init_thread(main_thread, stack_page, "System", THREAD_DEFAULT_PRIO); current_task = main_thread; main_thread->pid = alloc_pid(); @@ -285,6 +305,7 @@ static void make_main_thread(void) { void init_task(void) { list_init(&thread_ready); lock_init(&pid_lock); + spinlock_init(&thread_ready_lock); make_main_thread(); } @@ -293,34 +314,47 @@ void init_task(void) { * */ void schedule(void) { - io_cli(); + int old_status; struct task_s *cur = get_current_thread(); + + old_status = save_and_disable_interrupt(); + + // 1. 判断当前线程是否需要加入到thread_ready if (cur->status == TASK_RUNNING) { - if (list_find(&cur->general_tag, &thread_ready)) { - printk("Error:Current thread is in thread_ready list!\n"); - while (1) - ; + if (cur->general_tag.next != NULL) { + printk( + "Error:Current thread(pid:%d) is in thread_ready list!\n", + cur->pid); + list_del(&cur->general_tag); } - list_add_tail(&cur->general_tag, &thread_ready); - cur->ticks = cur->priority; cur->status = TASK_READY; + list_add_tail(&cur->general_tag, &thread_ready); + cur->ticks = cur->priority; } - struct task_s *next; - next = list_first_owner(&thread_ready, struct task_s, general_tag); - if (next != cur) { - list_del(&next->general_tag); - next->status = TASK_RUNNING; - process_activate(next); + // 2. 获取下一个线程,如果没有则使用idle线程 + struct task_s *next = + list_first_owner(&thread_ready, struct task_s, general_tag); + if (next != cur) list_del(&next->general_tag); + else next = task_idle; + // 4. 改变状态并加入到thread_ready + next->status = TASK_RUNNING; - current_task = next; - switch_to((int *)cur, (int *)next); - } else { - process_activate(task_idle); - current_task = task_idle; - switch_to((int *)cur, (int *)task_idle); + // 5. 切换线程 + // 激活页表并跳转 + process_activate(next); + current_task = next; + switch_to((int *)cur, (int *)next); + // 从其他线程切回来之后,检查上一个线程是否已经结束 + if (dead_task != NULL) { + size_t stack_page = (size_t)dead_task->kstack & ~(PAGE_SIZE - 1); + kernel_free_page(stack_page, 1); + kfree(dead_task); + dead_task = NULL; } - io_sti(); + if (cur->status == TASK_READY) cur->status = TASK_RUNNING; + + store_interrupt_status(old_status); } /** diff --git a/src/kernel/wait_queue.c b/src/kernel/wait_queue.c index 258d1d9..a262b13 100644 --- a/src/kernel/wait_queue.c +++ b/src/kernel/wait_queue.c @@ -44,16 +44,17 @@ bool wait_queue_empty(WaitQueue *wq) { * @return */ void wait_queue_add(WaitQueue *wq) { - struct task_s *task = get_current_thread(); - int old_status = load_interrupt_status(); - disable_interrupt(); - spin_lock(&wq->lock); + struct task_s *task = get_current_thread(); + if (task->wait_queue_tag.next != NULL) { + printk("Error:Current thread(pid:%d) is in wait queue!\n", task->pid); + list_del(&task->wait_queue_tag); + } + int flags = spin_lock_irqsave(&wq->lock); // 把当前线程的list tag直接挂到等待队列的list上 list_add_tail(&task->wait_queue_tag, &wq->list_head); - spin_unlock(&wq->lock); - store_interrupt_status(old_status); + spin_unlock_irqrestore(&wq->lock, flags); } /** @@ -62,9 +63,9 @@ void wait_queue_add(WaitQueue *wq) { * @param wq 等待队列管理结构 * @return */ -WaitQueueItem *wait_queue_first(WaitQueue *wqm) { +struct task_s *wait_queue_first(WaitQueue *wqm) { if (list_empty(&wqm->list_head)) { return NULL; } - return list_first_owner(&wqm->list_head, WaitQueueItem, wait_queue_tag); + return list_first_owner(&wqm->list_head, struct task_s, wait_queue_tag); } /** @@ -98,7 +99,7 @@ void wait_queue_wakeup(WaitQueue *wqm) { */ void wait_queue_wakeup_all(WaitQueue *wqm) { if (list_empty(&wqm->list_head)) { return; } - WaitQueueItem *cur, *next; + struct task_s *cur, *next; struct task_s *thread; int old_status = spin_lock_irqsave(&wqm->lock); diff --git a/src/lib/math.c b/src/lib/math.c index 6af79dd..eeabac4 100644 --- a/src/lib/math.c +++ b/src/lib/math.c @@ -1,3 +1,4 @@ +#include #include int max(int a, int b) { @@ -21,6 +22,10 @@ int pow(int x, int y) { } unsigned int find_next_pow_of_2(unsigned int n) { +#ifdef HAS_BUILTIN_CLZ + if (n == 0) return 1; + return 1 << (32 - __builtin_clz(n - 1)); +#else n--; n |= n >> 1; n |= n >> 2; @@ -28,5 +33,26 @@ unsigned int find_next_pow_of_2(unsigned int n) { n |= n >> 8; n |= n >> 16; n++; +#endif return n; +} + +// 计算log2(n)的向上取整 +int aligned_log2n(unsigned int n) { +#ifdef HAS_BUILTIN_CLZ + return 32 - __builtin_clz(n - 1); +#else + // De Bruijn序列查找表(32位版本) + static const uint8_t de_bruijn_table[32] = { + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31}; + n--; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n++; + return de_bruijn_table[(n * 0x07C4ACDD) >> 27]; +#endif } \ No newline at end of file diff --git a/src/objects/objects.c b/src/objects/objects.c index 03c4f64..a7342d6 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -163,9 +163,9 @@ Object *create_object(Object *parent, string_t name, ObjectAttr attr) { Object *create_object_directory( Object *parent, string_t name, ObjectAttr attr) { - Object *object = create_object(parent, name, attr); - object->attr->type = OBJECT_TYPE_DIRECTORY; + Object *object = create_object(parent, name, attr); if (object == NULL) { return NULL; } + object->attr->type = OBJECT_TYPE_DIRECTORY; init_object_directory(object); From 90deee9c01b9c6248aaea0cd85cd1f5368aec831 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 23 Mar 2025 23:49:15 +0800 Subject: [PATCH 041/158] =?UTF-8?q?[WIP]=20=E9=87=8D=E6=9E=84=20=E5=A3=B0?= =?UTF-8?q?=E9=9F=B3=E9=A9=B1=E5=8A=A8=E6=A1=86=E6=9E=B6=EF=BC=9B=20[WIP]?= =?UTF-8?q?=20=E9=87=8D=E6=9E=84=20sb16=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/sound/Makefile | 3 +- src/arch/x86/drivers/sound/sb16.c | 5 +- src/arch/x86/drivers/sound/sb16/Makefile | 1 + src/arch/x86/drivers/sound/sb16/sb16.c | 397 +++++++++++++++++++++++ src/arch/x86/drivers/sound/sb16/sb16.h | 62 ++++ src/arch/x86/drivers/sound/sound.c | 0 src/driver/Makefile | 1 + src/driver/sound/Makefile | 2 + src/driver/sound/pcm.c | 357 ++++++++++++++++++++ src/driver/sound/sound_dm.c | 63 ++++ src/include/driver/sound/sound_dm.h | 56 ++++ src/kernel/main.c | 74 ++++- src/kernel/memtest.c | 178 ++++++++++ 13 files changed, 1182 insertions(+), 17 deletions(-) create mode 100644 src/arch/x86/drivers/sound/sb16/Makefile create mode 100644 src/arch/x86/drivers/sound/sb16/sb16.c create mode 100644 src/arch/x86/drivers/sound/sb16/sb16.h create mode 100644 src/arch/x86/drivers/sound/sound.c create mode 100644 src/driver/sound/Makefile create mode 100644 src/driver/sound/pcm.c create mode 100644 src/driver/sound/sound_dm.c create mode 100644 src/include/driver/sound/sound_dm.h create mode 100644 src/kernel/memtest.c diff --git a/src/arch/x86/drivers/sound/Makefile b/src/arch/x86/drivers/sound/Makefile index 5745963..71ee2c7 100644 --- a/src/arch/x86/drivers/sound/Makefile +++ b/src/arch/x86/drivers/sound/Makefile @@ -1 +1,2 @@ -SRC += sb16.c \ No newline at end of file +SRC += sb16/ +SRC += sound.c \ No newline at end of file diff --git a/src/arch/x86/drivers/sound/sb16.c b/src/arch/x86/drivers/sound/sb16.c index a04bcb5..f0ada53 100644 --- a/src/arch/x86/drivers/sound/sb16.c +++ b/src/arch/x86/drivers/sound/sb16.c @@ -7,7 +7,7 @@ */ #include #include -#include +#include #include #include #include @@ -16,7 +16,6 @@ #include #include #include -#include #define SB16_DSP_MIXER 0x224 #define SB16_DSP_MIXER_DATA 0x225 @@ -201,7 +200,7 @@ status_t sb16_write(device_t *dev, uint8_t *buf, uint32_t offset, size_t size) { device_extension_t *devext = dev->device_extension; while ((devext->index_w + 1) % DMA_MAX == devext->index_r) { wait_queue_add(devext->wqm, 0); - thread_block(TASK_BLOCKED); + thread_block(TASK_INTERRUPTIBLE); } uint8_t *dma_mem = (uint8_t *)(0x800000 + devext->index_w * 0x10000); memcpy(dma_mem, buf, size); diff --git a/src/arch/x86/drivers/sound/sb16/Makefile b/src/arch/x86/drivers/sound/sb16/Makefile new file mode 100644 index 0000000..dd6cd79 --- /dev/null +++ b/src/arch/x86/drivers/sound/sb16/Makefile @@ -0,0 +1 @@ +SRC += sb16.c \ No newline at end of file diff --git a/src/arch/x86/drivers/sound/sb16/sb16.c b/src/arch/x86/drivers/sound/sb16/sb16.c new file mode 100644 index 0000000..8fabd0e --- /dev/null +++ b/src/arch/x86/drivers/sound/sb16/sb16.c @@ -0,0 +1,397 @@ +#include "sb16.h" +#include "driver/interrupt_dm.h" +#include "objects/object.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DriverResult sb16_init(struct Device *dev); +DriverResult sb16_probe(IsaDeviceDriver *isa_device_driver); + +DriverResult sb16_pcm_set_default_params(PcmStream *stream); +DriverResult sb16_pcm_set_channel(PcmStream *stream, uint8_t channel); +DriverResult sb16_pcm_set_sample_rate(PcmDevice *pcm, uint32_t sample_rate); +DriverResult sb16_pcm_set_data_type(PcmStream *stream, PcmDataType type); +DriverResult sb16_play_open(SoundDevice *sound_device, PcmStream *stream); +DriverResult sb16_play_prepare( + struct PcmStream *stream, void *addr, size_t size); +DriverResult sb16_play_trigger(PcmStream *stream, PcmTrigger trigger); +size_t sb16_play_position(PcmStream *stream); + +DeviceDriverOps sb16_device_driver_ops = { + .device_driver_init = NULL, + .device_driver_uninit = NULL, +}; +DeviceOps sb16_device_ops = { + .init = sb16_init, + .start = NULL, + .destroy = NULL, + .status = NULL, + .stop = NULL, +}; +IsaOps sb16_isa_ops = { + .probe = sb16_probe, +}; +SoundDeviceOps sb16_sound_device_ops = { + .set_volume = NULL, +}; +PcmOps sb16_pcm_ops = { + .set_sample_rate = sb16_pcm_set_sample_rate, +}; +PcmStreamOps sb16_pcm_play_ops = { + .open = sb16_play_open, + .close = NULL, + .prepare = sb16_play_prepare, + .trigger = sb16_play_trigger, + .position = sb16_play_position, + + .set_default_params = sb16_pcm_set_default_params, + .set_data_type = sb16_pcm_set_data_type, + .set_channel = sb16_pcm_set_channel, +}; +PcmStreamOps sb16_pcm_record_ops = { + .open = NULL, + .close = NULL, + .prepare = NULL, + + .set_default_params = sb16_pcm_set_default_params, + .set_data_type = sb16_pcm_set_data_type, + .set_channel = sb16_pcm_set_channel, +}; + +DriverDependency sb_dependencies[] = { + { + .in_type = DRIVER_DEPENDENCY_TYPE_BUS, + .dependency_in_bus = {BUS_TYPE_ISA, 0}, + .out_bus = NULL, + }, +}; + +Driver sb_driver = { + .short_name = STRING_INIT("HorizonSoundBlasterDriver"), + .dependency_count = sizeof(sb_dependencies) / sizeof(DriverDependency), + .dependencies = sb_dependencies, +}; +DeviceDriver sb16_device_driver = { + .name = STRING_INIT("SoundBlaster16"), + .bus = NULL, + .type = DEVICE_TYPE_SOUND, + .priority = DRIVER_PRIORITY_BASIC, + .ops = &sb16_device_driver_ops, +}; +const Device sb16_device_template = { + .name = STRING_INIT("sb16"), + .device_driver = &sb16_device_driver, + .ops = &sb16_device_ops, + .private_data_size = 0, +}; +const SoundDeviceCapabilities sb16_capabilities = { + .record = 1, + .play = 1, + .set_volume = 1, + .set_sample_rate = 1, +}; +const SoundDevice sb16_sound_device_template = { + .capabilities = sb16_capabilities, + .ops = &sb16_sound_device_ops, + .type = SOUND_TYPE_PCM, +}; + +static const int sb16_possible_ports[] = {0x220, 0x240, 0x260, 0x280}; +static const int sb16_possible_dmas[] = {5, 6, 7}; +#define DMA_MAX 4 +uint32_t data_len[DMA_MAX]; + +DriverResult sb16_write(Sb16Ports *ports, uint8_t value); + +void sb16_irq_handler(Device *device) { + SoundDevice *sound_device = device->dm_ext; + Sb16Info *info = sound_device->private_data; + PcmDevice *pcm = sound_device->pcm; + PcmStream *current_stream = pcm->current_stream; + + sound_pcm_done(current_stream); + + if (info->major_ver >= 4) { + io_in8(info->ports.iack16); + } else { + io_in8(info->ports.read_status); + } +} + +DriverResult sb16_reset(Sb16Ports *ports) { + Timer timer; + timer_init(&timer); + io_out8(ports->reset, 1); + delay_ms(&timer, 1); + io_out8(ports->reset, 0); + delay_ms(&timer, 1); + for (int i = 0; i < 100000; i++) { + if (io_in8(ports->read_status) & 0x80) { + if (io_in8(ports->read) == 0xaa) { return DRIVER_RESULT_OK; } + } + } + return DRIVER_RESULT_DEVICE_NOT_EXIST; +} + +DriverResult sb16_write(Sb16Ports *ports, uint8_t value) { + for (int i = 0; i < 100000; i++) { + if ((io_in8(ports->write) & 0x80) == 0) { + io_out8(ports->write, value); + return DRIVER_RESULT_OK; + } + } + return DRIVER_RESULT_TIMEOUT; +} + +DriverResult sb16_read(Sb16Ports *ports, uint8_t *value) { + for (int i = 0; i < 100000; i++) { + if (io_in8(ports->iack16) & 0x80) { + *value = io_in8(ports->read); + return DRIVER_RESULT_OK; + } + } + return DRIVER_RESULT_TIMEOUT; +} + +DriverResult sb16_get_version( + Sb16Ports *ports, uint8_t *major_version, uint8_t *minor_version) { + sb16_write(ports, CMD_GET_DSP_VERSION); + + DRIVER_RESULT_PASS(sb16_read(ports, major_version)); + DRIVER_RESULT_PASS(sb16_read(ports, minor_version)); + + return DRIVER_RESULT_OK; +} + +DriverResult sb16_check(int port, Sb16Info **info) { + Sb16Ports ports; + ports.mixer = port + PORT_MIXER; + ports.mixer_data = port + PORT_MIXER_DATA; + ports.reset = port + PORT_RESET; + ports.read = port + PORT_READ; + ports.write = port + PORT_WRITE; + ports.read_status = port + PORT_READ_STATUS; + ports.iack16 = port + PORT_IACK16; + + uint8_t major, minor; + DRIVER_RESULT_PASS(sb16_reset(&ports)); + DRIVER_RESULT_PASS(sb16_get_version(&ports, &major, &minor)); + print_driver_info( + sb_driver, "SB16 DSP found. version:%d.%d\n", major, minor); + + *info = kmalloc(sizeof(Sb16Info)); + (*info)->ports = ports; + (*info)->major_ver = major; + (*info)->minor_ver = minor; + + return DRIVER_RESULT_OK; +} + +DriverResult sb16_probe(IsaDeviceDriver *isa_device_driver) { + for (int i = 0; i < sizeof(sb16_possible_ports) / sizeof(int); i++) { + Sb16Info *info = NULL; + if (sb16_check(sb16_possible_ports[i], &info) == DRIVER_RESULT_OK) { + Device *sb16_device = kmalloc_from_template(sb16_device_template); + SoundDevice *sb16_sound_device = + kmalloc_from_template(sb16_sound_device_template); + ObjectAttr attr = device_object_attr; + sb16_device->bus = isa_device_driver->bus; + sb16_device->private_data = info; + DRIVER_RESULT_PASS(register_sound_device( + &sb16_device_driver, sb16_device, sb16_sound_device, &attr)); + + PcmDevice *pcm = sound_register_pcm( + sb16_sound_device, &sb16_pcm_ops, 128 * 1024); + if (pcm == NULL) return DRIVER_RESULT_OUT_OF_MEMORY; + + DRIVER_RESULT_PASS(pcm_register_stream( + pcm, &pcm->play_stream, &sb16_pcm_play_ops, + &info->stream_info[0])); + DRIVER_RESULT_PASS(pcm_register_stream( + pcm, &pcm->record_stream, &sb16_pcm_record_ops, + &info->stream_info[1])); + DRIVER_RESULT_PASS(pcm_register_dma(pcm, NULL, NULL, &isa_dma_ops)); + } + } + return DRIVER_RESULT_OK; +} + +DriverResult sb16_init(struct Device *dev) { + Sb16Info *info = (Sb16Info *)dev->private_data; + DeviceIrq *irq = kmalloc(sizeof(DeviceIrq)); + // io_out8(info->ports.mixer, 0x80 /* 设置IRQ */); + // io_out8(info->ports.mixer_data, 0x02 /* IRQ5 */); + irq->irq = 5; + irq->device = dev; + irq->handler = sb16_irq_handler; + + dev->irq = irq; + register_device_irq(dev->irq); + interrupt_enable_irq(irq->irq); + + spinlock_init(&info->lock); + + memset(data_len, 0, sizeof(data_len)); + return DRIVER_RESULT_OK; +} + +DriverResult sb16_set_sample_rate(Sb16Info *info, uint16_t sample_rate) { + sb16_write(&info->ports, CMD_SET_OUTPUT_SAMPLE_RATE); + sb16_write(&info->ports, (uint8_t)(sample_rate >> 8)); + sb16_write(&info->ports, (uint8_t)sample_rate); + return DRIVER_RESULT_OK; +} + +DriverResult sb16_set_time_constant(Sb16Info *info, uint16_t sample_rate) { + uint16_t time_constant = 65536 - (256000000 / sample_rate); + sb16_write(&info->ports, CMD_SET_TIME_CONSTANT); + sb16_write(&info->ports, (uint8_t)(time_constant >> 8)); + sb16_write(&info->ports, (uint8_t)time_constant); + return DRIVER_RESULT_OK; +} + +void sb16_setup_dma( + Sb16Info *info, uint8_t channel, uint8_t mode, uint32_t addr, + uint32_t len) { + int flags = dma_lock(); + dma_disable(channel); + dma_ff_reset(channel); + dma_set_mode(channel, mode); + dma_set_addr(channel, addr); + dma_set_count(channel, len); + dma_enable(channel); + dma_unlock(flags); +} + +DriverResult sb16_set_volume(Sb16Info *info, int volume) { + int flags = spin_lock_irqsave(&info->lock); + sb16_write(&info->ports, CMD_SET_OUTPUT_SAMPLE_RATE); + sb16_write(&info->ports, (uint8_t)(volume >> 8)); + sb16_write(&info->ports, (uint8_t)volume); + spin_unlock_irqrestore(&info->lock, flags); + return DRIVER_RESULT_OK; +} + +DriverResult sb16_pcm_set_default_params(PcmStream *stream) { + stream->data_type = PCM_S16LE; + sb16_pcm_set_data_type(stream, stream->data_type); + stream->hw_mode = PCM_MODE_INTERLEAVED; + stream->user_mode = PCM_MODE_INTERLEAVED; + stream->channel = 2; + stream->pcm->data_bytes = sizeof(uint16_t); + stream->frame_bytes = sizeof(uint16_t) * stream->channel; + stream->period_bytes = 16 * 1024; + stream->frame_per_period = stream->period_bytes / stream->frame_bytes; + stream->start_threshold = 4 * 1024; + stream->stop_threshold = 1 * 1024; + return DRIVER_RESULT_OK; +} + +DriverResult sb16_pcm_set_data_type(PcmStream *stream, PcmDataType type) { + struct Sb16StreamInfo *info = stream->private_data; + if (type == PCM_U16LE) { + info->data_type &= ~BIT(STEREO_BIT); + } else if (type == PCM_S16LE) { + info->data_type |= BIT(SIGNED_BIT); + } + return DRIVER_RESULT_OK; +} + +DriverResult sb16_pcm_set_mode(PcmStream *stream, PcmMode mode) { + if (mode == PCM_MODE_INTERLEAVED) stream->hw_mode = mode; + else return DRIVER_RESULT_UNSUPPORT_FEATURE; + return DRIVER_RESULT_OK; +} + +DriverResult sb16_pcm_set_channel(PcmStream *stream, uint8_t channel) { + struct Sb16StreamInfo *info = stream->private_data; + if (channel == 1) { + info->data_type &= ~BIT(STEREO_BIT); + } else if (channel == 2) { + info->data_type |= BIT(STEREO_BIT); + } + return DRIVER_RESULT_OK; +} + +DriverResult sb16_pcm_set_sample_rate(PcmDevice *pcm, uint32_t sample_rate) { + return sb16_set_sample_rate(pcm->sound_device->private_data, sample_rate); +} + +DriverResult sb16_play_open(SoundDevice *sound_device, PcmStream *stream) { + Sb16Info *info = (Sb16Info *)sound_device->device->private_data; + info->dma_channel = dma_channel_use( + sound_device->device, (int *)sb16_possible_dmas, + sizeof(sb16_possible_dmas) / sizeof(int)); + + return DRIVER_RESULT_OK; +} + +DriverResult sb16_play_prepare(PcmStream *stream, void *addr, size_t size) { + Sb16Info *info = (Sb16Info *)stream->sound_device->device->private_data; + struct Sb16StreamInfo *stream_info = stream->private_data; + + sb16_setup_dma( + info, info->dma_channel, + DMA_MODE_SINGLE | DMA_MODE_AUTO | DMA_MODE_WRITE, (uint32_t)addr, size); + + uint16_t sample_count = stream->period_bytes >> 1; + sample_count--; + + int flags = spin_lock_irqsave(&info->lock); + sb16_write( + &info->ports, TRANSFER_16BIT | TRANSFER_PLAY | TRANSFER_AUTOINIT); + sb16_write(&info->ports, stream_info->data_type); + sb16_write(&info->ports, (uint8_t)sample_count); + sb16_write(&info->ports, (uint8_t)(sample_count >> 8)); + sb16_write(&info->ports, CMD_STOP_PLAY16); + spin_unlock_irqrestore(&info->lock, flags); + + return DRIVER_RESULT_OK; +} + +DriverResult sb16_play_trigger(PcmStream *stream, PcmTrigger trigger) { + Sb16Info *info = (Sb16Info *)stream->sound_device->device->private_data; + switch (trigger) { + case PCM_TRIGGER_START: + case PCM_TRIGGER_RESUME: + sb16_write(&info->ports, CMD_RESUME_PLAY16); + break; + case PCM_TRIGGER_STOP: + case PCM_TRIGGER_PAUSE: + sb16_write(&info->ports, CMD_STOP_PLAY16); + break; + case PCM_TRIGGER_NONE: + return DRIVER_RESULT_OTHER_ERROR; + } + return DRIVER_RESULT_OK; +} + +size_t sb16_play_position(PcmStream *stream) { + Sb16Info *info = (Sb16Info *)stream->sound_device->device->private_data; + return dma_pointer(info->dma_channel, stream->pcm->buffer_bytes); +} + +static void __init sb16_driver_entry(void) { + register_driver(&sb_driver); + register_device_driver(&sb_driver, &sb16_device_driver); + isa_register_device_driver(&sb16_device_driver, &sb16_isa_ops); +} + +driver_initcall(sb16_driver_entry); \ No newline at end of file diff --git a/src/arch/x86/drivers/sound/sb16/sb16.h b/src/arch/x86/drivers/sound/sb16/sb16.h new file mode 100644 index 0000000..64406e4 --- /dev/null +++ b/src/arch/x86/drivers/sound/sb16/sb16.h @@ -0,0 +1,62 @@ +#ifndef _SB16_H +#define _SB16_H + +#include "kernel/spinlock.h" +#include "stdint.h" + +#define PORT_MIXER 0x4 +#define PORT_MIXER_DATA 0x5 +#define PORT_RESET 0x6 +#define PORT_READ 0xa +#define PORT_WRITE 0xc +#define PORT_READ_STATUS 0xe +#define PORT_IACK16 0xf + +#define CMD_SET_TIME_CONSTANT 0x40 +#define CMD_SET_OUTPUT_SAMPLE_RATE 0x41 +#define CMD_TURN_SPEAKER_ON 0xd1 +#define CMD_TURN_SPEAKER_OFF 0xd3 +#define CMD_STOP_PLAY8 0xd0 +#define CMD_RESUME_PLAY8 0xd4 +#define CMD_STOP_PLAY16 0xd5 +#define CMD_RESUME_PLAY16 0xd6 +#define CMD_GET_DSP_VERSION 0xe1 + +#define CMD_SET_VOLUME 0x22 +#define CMD_SET_IRQ 0x80 + +#define TRANSFER_16BIT 0xb0 +#define TRANSFER_8BIT 0xc0 +#define TRANSFER_PLAY 0x00 +#define TRANSFER_RECORD 0x08 +#define TRANSFER_FIFO 0x02 +#define TRANSFER_AUTOINIT 0x04 + +#define STEREO_BIT 5 +#define SIGNED_BIT 4 + +typedef struct Sb16Ports { + int mixer; + int mixer_data; + int reset; + int read; + int write; + int read_status; + int iack16; +} Sb16Ports; + +#define SB16_MAX_DMA_REGION 4 + +typedef struct Sb16Info { + Sb16Ports ports; + uint8_t major_ver; + uint8_t minor_ver; + uint8_t dma_channel; + spinlock_t lock; + + struct Sb16StreamInfo { + uint8_t data_type; + } stream_info[2]; +} Sb16Info; + +#endif \ No newline at end of file diff --git a/src/arch/x86/drivers/sound/sound.c b/src/arch/x86/drivers/sound/sound.c new file mode 100644 index 0000000..e69de29 diff --git a/src/driver/Makefile b/src/driver/Makefile index b43abe9..645d2a7 100644 --- a/src/driver/Makefile +++ b/src/driver/Makefile @@ -1,4 +1,5 @@ SRC += storage/ +SRC += sound/ SRC += timer_dm.c SRC += interrupt_dm.c SRC += video_dm.c diff --git a/src/driver/sound/Makefile b/src/driver/sound/Makefile new file mode 100644 index 0000000..558b465 --- /dev/null +++ b/src/driver/sound/Makefile @@ -0,0 +1,2 @@ +SRC += sound_dm.c +SRC += pcm.c \ No newline at end of file diff --git a/src/driver/sound/pcm.c b/src/driver/sound/pcm.c new file mode 100644 index 0000000..a957028 --- /dev/null +++ b/src/driver/sound/pcm.c @@ -0,0 +1,357 @@ +#include "kernel/console.h" +#include "kernel/spinlock.h" +#include "kernel/thread.h" +#include "kernel/wait_queue.h" +#include "stdint.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TransferResult sound_pcm_transfer( + Object *object, struct ObjectHandle *handle, TransferDirection direction, + uint8_t *buf, size_t size); + +PcmDevice *sound_register_pcm( + SoundDevice *sound_device, PcmOps *pcm_ops, size_t size) { + PcmDevice *pcm = kmalloc(sizeof(PcmDevice)); + if (pcm == NULL) return NULL; + + sound_device->pcm = pcm; + pcm->sound_device = sound_device; + pcm->ops = pcm_ops; + pcm->buf = NULL; + pcm->buffer_bytes = size; + pcm->status = PCM_STATUS_CLOSE; + pcm->boundary = size; + while (pcm->boundary * 2 < __SIZE_MAX__ / 2 - size) + pcm->boundary *= 2; + + return pcm; +} + +DriverResult pcm_register_stream( + PcmDevice *pcm, PcmStream **stream, PcmStreamOps *ops, void *private_data) { + *stream = kmalloc(sizeof(PcmStream)); + if (*stream == NULL) return DRIVER_RESULT_OUT_OF_MEMORY; + PcmStream *s = *stream; + + s->pcm = pcm; + s->sound_device = pcm->sound_device; + s->ops = ops; + s->private_data = private_data; + // s->buf = ptr; + // s->status = ptr + sizeof(void *) * pcm->max_buf_count; + s->device_ptr_base = 0; + s->device_period_ptr = 0; + s->host_ptr_base = 0; + s->host_period_ptr = 0; + s->host_ptr = 0; + spinlock_init(&s->lock); + wait_queue_init(&s->wq); + + return DRIVER_RESULT_OK; +} + +DriverResult pcm_register_dma( + PcmDevice *pcm, void *dma, void *param, DmaOps *ops) { + Dma *_dma = kmalloc(sizeof(Dma)); + if (_dma == NULL) return DRIVER_RESULT_OUT_OF_MEMORY; + _dma->dma = dma; + _dma->param = param; + _dma->ops = ops; + pcm->dma = _dma; + return DRIVER_RESULT_OK; +} + +DriverResult sound_pcm_alloc(PcmStream *stream) { + PcmDevice *pcm = stream->pcm; + pcm->buf = pcm->dma->ops->dma_alloc(pcm->dma, pcm->buffer_bytes); + stream->device_ptr_base = stream->host_ptr_base = 0; + stream->device_period_ptr = stream->host_period_ptr = 0; + stream->host_ptr = 0; + return DRIVER_RESULT_OK; +} + +DriverResult pcm_set_data_type(PcmStream *stream, PcmDataType data_type) { + DRIVER_RESULT_PASS(stream->ops->set_data_type(stream, data_type)); + stream->data_type = data_type; + return DRIVER_RESULT_OK; +} + +DriverResult pcm_set_channel(PcmStream *stream, uint8_t channel) { + DRIVER_RESULT_PASS(stream->ops->set_channel(stream, channel)); + stream->channel = channel; + return DRIVER_RESULT_OK; +} + +DriverResult pcm_set_sample_rate(PcmDevice *pcm, uint32_t sample_rate) { + DRIVER_RESULT_PASS(pcm->ops->set_sample_rate(pcm, sample_rate)); + pcm->sample_rate = sample_rate; + return DRIVER_RESULT_OK; +} + +DriverResult sound_pcm_open( + Object *object, int mode, DEF_MRET(PcmDevice *, pcm), + DEF_MRET(PcmStream *, stream)) { + SoundDevice *sound_device = sound_get_device(object); + PcmStream *cur_stream; + + if (sound_device->type != SOUND_TYPE_PCM) + return DRIVER_RESULT_UNSUPPORT_FEATURE; + + PcmDevice *pcm = sound_device->pcm; + if (mode == SOUND_DEVICE_MODE_PLAY) { + pcm->play_stream->ops->open(sound_device, pcm->play_stream); + cur_stream = pcm->play_stream; + } else if (mode == SOUND_DEVICE_MODE_RECORED) { + pcm->record_stream->ops->open(sound_device, pcm->record_stream); + cur_stream = pcm->record_stream; + } else { + return DRIVER_RESULT_UNSUPPORT_FEATURE; + } + cur_stream->ops->set_default_params(cur_stream); + + MRET(pcm) = pcm; + MRET(stream) = cur_stream; + object->in.type = TRANSFER_TYPE_STREAM; + object->in.stream = sound_pcm_transfer; + object->out.type = TRANSFER_TYPE_STREAM; + object->out.stream = sound_pcm_transfer; + return DRIVER_RESULT_OK; +} + +DriverResult sound_pcm_set_frame_count(PcmStream *stream, size_t count) { + stream->frame_per_period = count; + stream->frame_bytes = stream->channel * stream->pcm->data_bytes; + stream->period_bytes = stream->frame_per_period * stream->frame_bytes; + return DRIVER_RESULT_OK; +} + +DriverResult sound_pcm_set_mode(PcmStream *stream, PcmMode mode) { + stream->user_mode = mode; + return stream->ops->set_mode(stream, mode); +} + +int sound_pcm_left_space(PcmStream *stream) { + int left_space = stream->device_period_ptr + stream->pcm->buffer_bytes - + (stream->host_ptr_base + stream->host_ptr); + if (left_space >= stream->pcm->boundary) { + // 跨越边界 + left_space -= stream->pcm->boundary; + } + return left_space; +} + +DriverResult sound_pcm_read( + PcmStream *stream, uint8_t *buf, uint32_t frame_count) { + // if (size > stream->pcm->max_size) return DRIVER_RESULT_EXCEED_MAX_SIZE; + // memcpy(buf, stream->buf, size); + return DRIVER_RESULT_OK; +} + +void pcm_interleaved2noninterleaved( + PcmStream *stream, uint8_t *in, uint8_t *out, uint32_t frame_count) { + PcmDevice *pcm = stream->pcm; + uint8_t *src = in; + uint8_t *dst = out; + uint8_t *_dst; + uint32_t offset = stream->period_bytes / stream->channel; + int i, j, k; + for (i = 0; i < frame_count; i++) { + _dst = dst; + for (j = 0; j < stream->channel; j++) { + for (k = 0; k < pcm->data_bytes; k++) { + _dst[k] = src[k]; + } + _dst += offset; + src += pcm->data_bytes; + } + dst += pcm->data_bytes; + } +} +void pcm_noninterleaved2interleaved( + PcmStream *stream, uint8_t *in, uint8_t *out, uint32_t frame_count) { + PcmDevice *pcm = stream->pcm; + uint8_t *src = in; + uint8_t *dst = out; + uint8_t *_src; + uint32_t offset = stream->period_bytes / stream->channel; + int i, j, k; + for (i = 0; i < frame_count; i++) { + _src = src; + for (j = 0; j < stream->channel; j++) { + for (k = 0; k < pcm->data_bytes; k++) { + dst[k] = _src[k]; + } + _src += offset; + dst += pcm->data_bytes; + } + src += pcm->data_bytes; + } +} + +DriverResult sound_pcm_write_interleaved( + PcmStream *stream, uint8_t *dst, uint8_t *src, uint32_t frame_count) { + if (frame_count > stream->frame_per_period) + return DRIVER_RESULT_EXCEED_MAX_SIZE; + if (stream->hw_mode == PCM_MODE_INTERLEAVED) { + // 模式相同,直接复制 + memcpy(dst, src, frame_count * stream->frame_bytes); + } else { + // 模式不同,需要转换 + // 输入为交织模式,输出为非交织模式 + pcm_interleaved2noninterleaved(stream, src, dst, frame_count); + } + return DRIVER_RESULT_OK; +} + +DriverResult sound_pcm_write_noninterleaved( + PcmStream *stream, uint8_t *dst, uint8_t *src, uint32_t frame_count) { + if (stream->hw_mode == PCM_MODE_NONINTERLEAVED) { + // 模式相同,直接复制 + memcpy(dst, src, frame_count * stream->frame_bytes); + } else { + // 模式不同,需要转换 + // 输入为非交织模式,输出为交织模式 + pcm_noninterleaved2interleaved(stream, src, dst, frame_count); + } + return DRIVER_RESULT_OK; +} + +DriverResult sound_pcm_write( + PcmStream *stream, uint8_t *buf, uint32_t frame_count) { + PcmDevice *pcm = stream->pcm; + uint32_t count; + uint8_t *dst, *src = buf; + + int flags = spin_lock_irqsave(&stream->lock); + int left_space = sound_pcm_left_space(stream); + + size_t writed = 0; + size_t size, left_size = frame_count * stream->frame_bytes; + while (left_size > 0) { + while (left_space == 0) { + wait_queue_add(&stream->wq); + thread_set_status(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&stream->lock, flags); + + schedule(); + + spin_lock_irqsave(&stream->lock); + left_space = sound_pcm_left_space(stream); + } + dst = pcm->buf + stream->host_ptr; + size = MIN(left_space, left_size); + size = MIN(size, pcm->buffer_bytes - stream->host_ptr); + spin_unlock_irqrestore(&stream->lock, flags); + + count = size / stream->frame_bytes; + if (stream->user_mode == PCM_MODE_INTERLEAVED) { + sound_pcm_write_interleaved(stream, dst, src, count); + } else { + sound_pcm_write_noninterleaved(stream, dst, src, count); + } + src += size; + left_space -= size; + left_size -= size; + writed += count; + + flags = spin_lock_irqsave(&stream->lock); + stream->host_ptr += size; + + if (stream->host_ptr >= pcm->buffer_bytes) { + stream->host_ptr -= pcm->buffer_bytes; + stream->host_ptr_base += pcm->buffer_bytes; + if (stream->host_ptr_base > pcm->boundary) { + stream->host_ptr_base = 0; + } + } + } + if (writed > 0) { + if ((pcm->status == PCM_STATUS_PREPARED || + pcm->status == PCM_STATUS_PAUSED)) { + if (sound_pcm_left_space(stream) >= stream->start_threshold) { + stream->ops->trigger(stream, PCM_TRIGGER_START); + pcm->status = PCM_STATUS_RUNNING; + } + } + int position = stream->host_ptr; + position -= position % stream->period_bytes; + stream->host_period_ptr = stream->host_ptr_base + position; + } + spin_unlock_irqrestore(&stream->lock, flags); + if (writed < frame_count) { return DRIVER_RESULT_BUSY; }; + + return DRIVER_RESULT_OK; +} + +DriverResult sound_pcm_prepare(PcmStream *stream) { + PcmDevice *pcm = stream->pcm; + pcm->current_stream = stream; + + pcm->status = PCM_STATUS_PREPARED; + + DRIVER_RESULT_PASS( + stream->ops->prepare(stream, pcm->buf, pcm->buffer_bytes)); + + return DRIVER_RESULT_OK; +} + +DriverResult sound_pcm_done(PcmStream *stream) { + PcmDevice *pcm = stream->pcm; + size_t position = stream->ops->position(stream); + size_t old_period_ptr = stream->device_period_ptr; + position -= position % stream->period_bytes; + + int flags = spin_lock_irqsave(&stream->lock); + + size_t new_device_base = stream->device_ptr_base; + size_t new_period_ptr = new_device_base + position; + + if (new_period_ptr < old_period_ptr) { + // 当前DMA缓冲区发生回环,切换到下一个虚拟缓冲区 + new_device_base += pcm->buffer_bytes; + new_period_ptr = new_device_base + position; + } + + if (new_period_ptr >= pcm->boundary) { + // 当前虚拟缓冲区超出边界,切换到第一个虚拟缓冲区 + new_device_base = 0; + new_period_ptr = new_device_base + position; + } + + stream->device_ptr_base = new_device_base; + stream->device_period_ptr = new_period_ptr; + + // if (sound_pcm_left_space(stream) <= stream->stop_threshold) { + // stream->ops->trigger(stream, PCM_TRIGGER_PAUSE); + // stream->pcm->status = PCM_STATUS_PAUSED; + // } + + wait_queue_wakeup(&stream->wq); + spin_unlock_irqrestore(&stream->lock, flags); + + return DRIVER_RESULT_OK; +} + +TransferResult sound_pcm_transfer( + Object *object, struct ObjectHandle *handle, TransferDirection direction, + uint8_t *buf, size_t size) { + SoundDevice *sound_device = sound_get_device(object); + PcmDevice *pcm = sound_device->pcm; + if (direction == TRANSFER_OUT) { + sound_pcm_write(pcm->play_stream, buf, size); + } else { + sound_pcm_read(pcm->record_stream, buf, size); + } + + return TRANSFER_OK; +} diff --git a/src/driver/sound/sound_dm.c b/src/driver/sound/sound_dm.c new file mode 100644 index 0000000..d099084 --- /dev/null +++ b/src/driver/sound/sound_dm.c @@ -0,0 +1,63 @@ +#include "kernel/device.h" +#include "kernel/list.h" +#include "objects/object.h" +#include +#include +#include +#include +#include + +DriverResult sound_dm_load(DeviceManager *manager); +DriverResult sound_dm_unload(DeviceManager *manager); + +DeviceManagerOps sound_dm_ops = { + .dm_load = sound_dm_load, + .dm_unload = sound_dm_unload, +}; + +SoundDeviceManager sound_dm_ext; +DeviceManager sound_dm = { + .type = DEVICE_TYPE_SOUND, + .ops = &sound_dm_ops, + .private_data = &sound_dm_ext, +}; + +DriverResult sound_dm_load(DeviceManager *manager) { + manager->private_data = kmalloc(sizeof(SoundDeviceManager)); + return DRIVER_RESULT_OK; +} + +DriverResult sound_dm_unload(DeviceManager *manager) { + kfree(manager->private_data); + return DRIVER_RESULT_OK; +} + +DriverResult register_sound_device( + DeviceDriver *driver, Device *device, SoundDevice *sound_device, + ObjectAttr *attr) { + device->dm_ext = sound_device; + sound_device->device = device; + sound_device->private_data = device->private_data; + + list_add_tail(&device->dm_list, &sound_dm.device_lh); + + string_t name; + string_new_with_number(&name, "Sound", 5, sound_dm_ext.device_count++); + DRIVER_RESULT_PASS(register_device( + device->device_driver, name, device->bus, device, attr)); + + return DRIVER_RESULT_OK; +} + +SoundDevice *sound_get_device(Object *object) { + if (object->attr->type != OBJECT_TYPE_DEVICE) return NULL; + Device *device = object->value.device; + if (device->device_driver->type != DEVICE_TYPE_SOUND) return NULL; + return device->dm_ext; +} + +SoundDeviceType sound_get_type(Object *object) { + SoundDevice *sound_device = sound_get_device(object); + if (sound_device == NULL) return SOUND_TYPE_UNKNOWN; + return sound_device->type; +} diff --git a/src/include/driver/sound/sound_dm.h b/src/include/driver/sound/sound_dm.h new file mode 100644 index 0000000..c3f7f1c --- /dev/null +++ b/src/include/driver/sound/sound_dm.h @@ -0,0 +1,56 @@ +#ifndef _SOUND_DM_H +#define _SOUND_DM_H + +#include "kernel/device.h" +#include "kernel/device_driver.h" +#include "kernel/device_manager.h" +#include "kernel/driver.h" +#include + +#define SOUND_DEVICE_MODE_PLAY 0 +#define SOUND_DEVICE_MODE_RECORED 1 + +struct SoundDevice; +typedef struct SoundDeviceOps { + DriverResult (*set_volume)(struct SoundDevice *device, int volume); +} SoundDeviceOps; + +typedef struct SoundDeviceCapabilities { + uint32_t record : 1; + uint32_t play : 1; + uint32_t set_volume : 1; + uint32_t set_sample_rate : 1; +} SoundDeviceCapabilities; + +typedef enum SoundDeviceType { + SOUND_TYPE_UNKNOWN, + SOUND_TYPE_PCM, +} SoundDeviceType; + +typedef struct SoundDevice { + Device *device; + SoundDeviceCapabilities capabilities; + SoundDeviceOps *ops; + + void *private_data; + + SoundDeviceType type; + + union { + struct PcmDevice *pcm; + }; +} SoundDevice; + +typedef struct SoundDeviceManager { + int device_count; +} SoundDeviceManager; + +extern DeviceManager sound_dm; + +DriverResult register_sound_device( + DeviceDriver *driver, Device *device, SoundDevice *sound_device, + ObjectAttr *attr); + +SoundDevice *sound_get_device(Object *object); + +#endif \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index 93e7211..11c8385 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -4,6 +4,10 @@ * @brief 内核主程序 * @date 2020-03 */ +#include "driver/sound/pcm.h" +#include "driver/sound/sound_dm.h" +#include "kernel/page.h" +#include "objects/handle.h" #include "string.h" #include #include @@ -60,18 +64,70 @@ extern Driver core_driver; // printk("\n"); // } +// void thread_play(void *arg) { +// Object *object; +// ObjectResult result = open_object_by_path("\\Device\\Sound0", &object); +// if (result != OBJECT_OK) { +// printk("Open File Error!\n"); +// } else { +// Object *file; +// result = +// open_object_by_path("\\Volumes\\Storage0Volume0\\1.pcm", &file); + +// if (result == OBJECT_OK) { +// ObjectHandle *handle = object_handle_create(file); +// PcmDevice *pcm; +// PcmStream *stream; +// // sound_pcm_open(object, SOUND_DEVICE_MODE_PLAY, &pcm, &stream); +// // sound_pcm_alloc(stream); +// // pcm_set_sample_rate(pcm, 44100); +// // pcm_set_channel(stream, 2); +// // sound_pcm_set_frame_count(stream, 4 * 1024); +// // sound_pcm_prepare(stream); +// ObjectAttr attr; +// obj_get_attr(file, &attr); +// size_t count = 2 * 64; +// size_t size = 4 * 1024 * 1024; +// uint8_t *buf = kmalloc(19 * 1024 * 1024); +// for (int i = 0; i < size / 1024 / 1024; i++) { +// printk("%dMB ", i); +// for (int j = 0; j < 8; j++) { +// TransferResult result = TRANSFER_IN_STREAM( +// file, handle, buf + (i * 16 + j) * 32 * 1024, +// 128 * 1024); +// if (result != TRANSFER_OK) { +// printk("Transfer Error!\n"); +// thread_exit(); +// } +// } +// } +// for (int i = 0; i < count; i++) { +// // io_cli(); +// printk("%d ", i); +// // io_sti(); +// // sound_pcm_write(stream, buf, 4 * 1024); +// buf += 16 * 1024; +// } +// } +// } +// } + int main() { platform_early_init(); + init_memory(); + + uint8_t *zero = 0; + register_driver_manager(&device_driver_manager); register_driver_manager(&bus_driver_manager); register_device_manager(&interrupt_dm); register_device_manager(&timer_dm); register_device_manager(&time_dm); register_device_manager(&video_dm); + register_device_manager(&sound_dm); register_device_manager(&storage_dm); - init_memory(); init_object_tree(); register_driver(&core_driver); @@ -81,25 +137,17 @@ int main() { platform_start_devices(); init_task(); - task_idle = thread_start("Idle", 1, idle, 0); + task_idle = thread_start("Idle", 1, idle, 0, NULL); io_sti(); printk("Memory Size:%dM\n", get_memory_size()); thread_start( - "Kernel Periodic Tasks", THREAD_DEFAULT_PRIO, periodic_task, NULL); + "Kernel Periodic Tasks", THREAD_DEFAULT_PRIO, periodic_task, NULL, + NULL); do_initcalls(); driver_start_all(); - uint8_t buf[128]; - Object *object; - ObjectResult result = open_object_by_path( - "\\Volumes\\Storage0Volume0\\boot\\grub\\grub.cfg", &object); - if (result != OBJECT_OK) { - printk("Open File Error!\n"); - } else { - TRANSFER_IN_STREAM(object, buf, 128); - printk("%s", buf); - } + // thread_start("play", 1000, thread_play, NULL); // const string_t name = STRING_INIT("A folder"); // obj_rmdir(object, name); diff --git a/src/kernel/memtest.c b/src/kernel/memtest.c new file mode 100644 index 0000000..b638607 --- /dev/null +++ b/src/kernel/memtest.c @@ -0,0 +1,178 @@ +#include +#include +#include +#include + +extern TimerDeviceManager timer_dm_ext; + +// 测试配置 +#define TEST_ITERATIONS 1000 // 每个测试案例的迭代次数 +#define SMALL_SIZE 32 // 小对象大小 +#define MEDIUM_SIZE 1024 // 中等对象大小 +#define LARGE_SIZE (4 * 1024) // 大对象大小(4KB) +#define HUGE_PAGE_CNT 4 // 大页分配数量 + +// 性能统计结构体 +struct perf_stats { + uint32_t total_cycles; + uint32_t max_cycles; + uint32_t min_cycles; + uint32_t alloc_fails; +}; +// 内存块记录增强 +struct mem_record { + void *ptr; + size_t size; + int is_page; + int page_cnt; // 记录分配的页数 +}; + +uint32_t rdtsc() { + uint32_t lo, hi; + __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); + return lo; +} + +uint32_t get_counter() { + Device *device = timer_dm_ext.scheduler_timer; + TimerDevice *td = device->dm_ext; + return td->counter; +} +// 初始化性能统计 +static void init_stats(struct perf_stats *stats) { + stats->total_cycles = 0; + stats->max_cycles = 0; + stats->min_cycles = __UINT32_MAX__; + stats->alloc_fails = 0; +} + +// 更新统计信息 +static void update_stats(struct perf_stats *stats, uint32_t cycles) { + stats->total_cycles += cycles; + if (cycles > stats->max_cycles) stats->max_cycles = cycles; + if (cycles < stats->min_cycles) stats->min_cycles = cycles; +} + +// 打印统计结果 +static void print_stats( + const char *test_name, const struct perf_stats *stats, int iter) { + printk("[%s] Results:\n", test_name); + printk(" Total cycles: %u\n", stats->total_cycles); + printk(" Avg cycles/op: %u\n", stats->total_cycles / iter); + printk(" Max cycles: %u\n", stats->max_cycles); + printk(" Min cycles: %u\n", stats->min_cycles); + printk(" Allocation failures: %u\n", stats->alloc_fails); +} + +void test_long_running(uint32_t minutes) { + uint32_t start_count = get_counter(); + uint32_t end_count = start_count + (minutes * 60000); // 假设counter是毫秒级 + + struct perf_stats stats; + init_stats(&stats); + uint32_t alloc_count = 0; + Timer timer; + timer_init(&timer); + + while (get_counter() < end_count) { + size_t size = (alloc_count % 5 == 0) ? LARGE_SIZE : SMALL_SIZE; + + uint32_t start = rdtsc(); + void *ptr = kmalloc(size); + uint32_t end = rdtsc(); + + if (!ptr) { + stats.alloc_fails++; + delay_ms(&timer, 10); // 背压延迟 + continue; + } + + update_stats(&stats, end - start); + alloc_count++; + + // 保持10个活跃对象 + static void *keep_alive[10]; + static int idx = 0; + if (keep_alive[idx]) { kfree(keep_alive[idx]); } + keep_alive[idx] = ptr; + idx = (idx + 1) % 10; + } + + printk("[Long Running] Ran for %u minutes\n", minutes); + print_stats("Long Running", &stats, alloc_count); +} +void test_small_allocs(void) { + struct perf_stats stats; + init_stats(&stats); + + for (int i = 0; i < TEST_ITERATIONS; i++) { + uint32_t start = rdtsc(); + void *ptr = kmalloc(SMALL_SIZE); + uint32_t end = rdtsc(); + + if (!ptr) { + stats.alloc_fails++; + continue; + } + + update_stats(&stats, end - start); + kfree(ptr); + } + + print_stats("Small Object Alloc", &stats, TEST_ITERATIONS); +} + +void test_large_page_allocs(void) { + struct perf_stats stats; + init_stats(&stats); + struct mem_record pages[HUGE_PAGE_CNT] = {0}; // 记录地址和页数 + + for (int i = 0; i < TEST_ITERATIONS; i++) { + uint32_t start = rdtsc(); + void *ptr = kernel_alloc_pages(HUGE_PAGE_CNT); + uint32_t end = rdtsc(); + + if (!ptr) { + stats.alloc_fails++; + continue; + } + + // 记录当前分配的页数 + pages[i % HUGE_PAGE_CNT].ptr = ptr; + pages[i % HUGE_PAGE_CNT].page_cnt = HUGE_PAGE_CNT; + update_stats(&stats, end - start); + + // 释放旧的页 + if (i >= HUGE_PAGE_CNT) { + struct mem_record *old = &pages[i % HUGE_PAGE_CNT]; + if (old->ptr) { + kernel_free_page((int)old->ptr, old->page_cnt); // 关键修改点 + old->ptr = NULL; + } + } + } + + // 清理残留页 + for (int i = 0; i < HUGE_PAGE_CNT; i++) { + if (pages[i].ptr) { + kernel_free_page((int)pages[i].ptr, pages[i].page_cnt); + } + } + + print_stats("Large Page Alloc", &stats, TEST_ITERATIONS); +} + +void run_memory_benchmarks(void) { + printk("===== Starting Memory Allocator Benchmarks =====\n"); + + Timer timer; + timer_init(&timer); + + // 基础测试 + test_small_allocs(); + // delay_ms(&timer, 100); + test_large_page_allocs(); + // delay_ms(&timer, 100); + + printk("===== Benchmark Suite Completed =====\n"); +} \ No newline at end of file From 9d31fefe530afbe2592553b7381455fe88428d5b Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 24 Mar 2025 23:58:26 +0800 Subject: [PATCH 042/158] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E9=80=80=E5=87=BA=E6=97=B6=E6=B2=A1=E6=9C=89=E5=B0=86=E4=B8=8B?= =?UTF-8?q?=E4=B8=80=E7=BA=BF=E7=A8=8B=E6=81=A2=E5=A4=8DRUNNING=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E7=9A=84bug=EF=BC=9B=E4=BC=98=E5=8C=96=20=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E7=BB=93=E6=9E=84=E7=9B=B8=E5=85=B3=E9=94=81=E7=9A=84?= =?UTF-8?q?=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/kernel/spinlock.h | 21 +------- src/kernel/condvar.c | 2 +- src/kernel/driver_dependency.c | 2 +- src/kernel/process.c | 7 +-- src/kernel/thread.c | 98 +++++++++++++++++++--------------- src/kernel/wait_queue.c | 17 ++---- 6 files changed, 66 insertions(+), 81 deletions(-) diff --git a/src/include/kernel/spinlock.h b/src/include/kernel/spinlock.h index 09a1a13..2895fc7 100644 --- a/src/include/kernel/spinlock.h +++ b/src/include/kernel/spinlock.h @@ -2,7 +2,8 @@ #define _SPINLOCK_H #include "kernel/driver_interface.h" -typedef volatile int spinlock_t; +extern struct task_s *current_task; +typedef volatile int spinlock_t; #define SPINLOCK(lock) spinlock_t lock = 0; @@ -44,24 +45,6 @@ static inline int spin_try_lock_irqsave(spinlock_t *lock) { return 0; } -static inline int spin_lock_two_irqsave(spinlock_t *lock1, spinlock_t *lock2) { - int flags; - int f1, f2; - while (true) { - flags = save_and_disable_interrupt(); - f1 = spin_try_lock(lock1); - f2 = spin_try_lock(lock2); - if (f1 && f2) { - return flags; - } else { - if (f1) { spin_unlock(lock1); } - if (f2) { spin_unlock(lock2); } - store_interrupt_status(flags); - } - } - return flags; -} - // 释放自旋锁并恢复之前保存的中断状态 static inline void spin_unlock_irqrestore( spinlock_t *lock, unsigned long flags) { diff --git a/src/kernel/condvar.c b/src/kernel/condvar.c index cefed42..2c64ecd 100644 --- a/src/kernel/condvar.c +++ b/src/kernel/condvar.c @@ -6,8 +6,8 @@ void condvar_init(condvar_t *cv) { } void condvar_wait(condvar_t *cv, spinlock_t *mutex) { - wait_queue_add(&cv->wait_queue); thread_set_status(TASK_INTERRUPTIBLE); + wait_queue_add(&cv->wait_queue); spin_unlock(mutex); thread_wait(); diff --git a/src/kernel/driver_dependency.c b/src/kernel/driver_dependency.c index 9688b95..616a92c 100644 --- a/src/kernel/driver_dependency.c +++ b/src/kernel/driver_dependency.c @@ -21,8 +21,8 @@ DriverResult check_dependency(Driver *driver) { if (bus_driver == NULL || bus_driver->subdriver.state != SUBDRIVER_STATE_READY) { // 总线驱动还没准备好则等待 - wait_queue_add(&bus_driver->subdriver.wq); thread_set_status(TASK_INTERRUPTIBLE); + wait_queue_add(&bus_driver->subdriver.wq); thread_wait(); bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; } diff --git a/src/kernel/process.c b/src/kernel/process.c index 470d328..e8ea140 100644 --- a/src/kernel/process.c +++ b/src/kernel/process.c @@ -5,6 +5,8 @@ * @version 0.8 * @date 2022-07-17 */ +#include "kernel/spinlock.h" +#include "kernel/thread.h" #include #include #include @@ -18,7 +20,6 @@ void thread_intr_exit(struct intr_stack *proc_stack); extern list_t thread_ready; -extern list_t thread_all; /** * @brief 用户线程的入口函数 @@ -125,10 +126,10 @@ void process_excute(void *entry, struct program_struct *prog) { } // 将该任务加入任务队列 - int old_status = io_load_eflags(); + int flags = spin_lock_irqsave(&thread_ready_lock); list_add_tail(&thread->general_tag, &thread_ready); list_add_tail(&thread->all_list_tag, &thread_all); - io_store_eflags(old_status); + io_store_eflags(flags); } /** diff --git a/src/kernel/thread.c b/src/kernel/thread.c index 7bfb460..1cd7b2c 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -23,11 +23,13 @@ #include struct task_s *current_task, *dead_task = NULL; - struct task_s *main_thread; -list_t thread_ready; -spinlock_t thread_ready_lock; -LIST_HEAD(thread_all); + +list_t thread_ready; +spinlock_t thread_ready_lock; +list_t thread_all; +spinlock_t thread_all_lock; + struct lock pid_lock; uint32_t new_pid = 0; @@ -148,21 +150,23 @@ struct task_s *thread_start( lock_release(&parent->child_lock); } thread_create(thread, function, func_arg); - printk("[Thread] %s: %#x\n", thread->name, thread); + int flags = spin_lock_irqsave(&thread_all_lock); + if (list_find(&thread->all_list_tag, &thread_all)) { + printk("[Thread Error]%s thread is already in thread_all!\n", name); + list_del(&thread->all_list_tag); + } + list_add_tail(&thread->all_list_tag, &thread_all); + spin_unlock_irqrestore(&thread_all_lock, flags); + + flags = spin_lock_irqsave(&thread_ready_lock); if (thread->general_tag.next != NULL) { - printk("thread %s:start error!\n", name); - while (1) - ; + printk("[Thread Error]%s thread is already in thread_ready!\n", name); + list_del(&thread->general_tag); } list_add_tail(&thread->general_tag, &thread_ready); + spin_unlock_irqrestore(&thread_ready_lock, flags); - if (list_find(&thread->all_list_tag, &thread_all)) { - printk("thread %s:start error!\n", name); - while (1) - ; - } - list_add_tail(&thread->all_list_tag, &thread_all); return thread; } @@ -180,34 +184,32 @@ void thread_exit(void) { lock_release(&parent->child_lock); } - if (cur->general_tag.next != NULL) list_del(&cur->general_tag); + /* + * 先从thread_all中删除,再从thread_ready中删除 + * 否则一旦被打断切换到其他线程,就无法再调度回来了 + */ + int flags = spin_lock_irqsave(&thread_all_lock); list_del(&cur->all_list_tag); + spin_unlock_irqrestore(&thread_all_lock, flags); - // 切换线程 - spin_lock_irqsave(&thread_ready_lock); - printk("[Thread Exit] %s, parent:%s,", cur->name, cur->parent->name); + flags = spin_lock_irqsave(&thread_ready_lock); + if (cur->general_tag.next != NULL) list_del(&cur->general_tag); + // 切换线程 struct task_s *next; - /** - * 其实本来想正常切换到队列中下一个线程的,但不知道为什么会导致父线程无法退出, - * 所以优先切换到父线程。 - */ - if (cur->parent != NULL) { - next = cur->parent; - if (next->general_tag.next != NULL) { list_del(&cur->general_tag); } - cur->ticks = cur->priority; - } else { - next = list_first_owner(&thread_ready, struct task_s, general_tag); - if (next != cur) list_del(&next->general_tag); - else { - printk("[No ready task!]"); - next = task_idle; - } + next = list_first_owner(&thread_ready, struct task_s, general_tag); + if (next != cur) list_del(&next->general_tag); + else { + printk("[Thread Error] No ready task!\n"); + next = task_idle; } // 进程将要退出,不需要恢复中断状态了 spin_unlock(&thread_ready_lock); - printk("switch to:%s\n", next->name); + + spin_lock(&next->status_lock); + if (next->status == TASK_READY) next->status = TASK_RUNNING; + spin_unlock(&next->status_lock); // 3. 切换线程 dead_task = cur; @@ -246,9 +248,6 @@ void thread_set_status(task_status_t status) { void thread_wait() { struct task_s *cur_thread = get_current_thread(); - int flags = spin_lock_irqsave(&cur_thread->status_lock); - task_status_t status = cur_thread->status; - spin_unlock_irqrestore(&cur_thread->status_lock, flags); while (cur_thread->wait_queue_tag.next != NULL) { schedule(); @@ -269,14 +268,18 @@ void thread_unblock(struct task_s *pthread) { } if (pthread->status != TASK_READY) { + pthread->status = TASK_READY; + spin_unlock(&pthread->status_lock); + + spin_lock(&thread_ready_lock); if (pthread->general_tag.next != NULL) { list_del(&pthread->general_tag); } list_add_before(&pthread->general_tag, thread_ready.next); - - pthread->status = TASK_READY; + spin_unlock_irqrestore(&thread_ready_lock, flags); + } else { + spin_unlock_irqrestore(&pthread->status_lock, flags); } - spin_unlock_irqrestore(&pthread->status_lock, flags); } /** @@ -291,9 +294,8 @@ static void make_main_thread(void) { main_thread->pid = alloc_pid(); if (list_find(&main_thread->all_list_tag, &thread_all)) { - printk("thread main:start error!\n"); - while (1) - ; + printk("[Thread Error] Main thread is alredy in thread list!\n"); + list_del(&main_thread->all_list_tag); } list_add_tail(&main_thread->all_list_tag, &thread_all); } @@ -304,8 +306,11 @@ static void make_main_thread(void) { */ void init_task(void) { list_init(&thread_ready); - lock_init(&pid_lock); + list_init(&thread_all); spinlock_init(&thread_ready_lock); + spinlock_init(&thread_all_lock); + + lock_init(&pid_lock); make_main_thread(); } @@ -330,6 +335,11 @@ void schedule(void) { cur->status = TASK_READY; list_add_tail(&cur->general_tag, &thread_ready); cur->ticks = cur->priority; + } else if (cur->status == TASK_INTERRUPTIBLE) { + list_add_tail(&cur->general_tag, &thread_ready); + cur->ticks = cur->priority; + } else { + printk("[Thread Status Error] %s:%d\n", cur->name, cur->status); } // 2. 获取下一个线程,如果没有则使用idle线程 diff --git a/src/kernel/wait_queue.c b/src/kernel/wait_queue.c index a262b13..605f642 100644 --- a/src/kernel/wait_queue.c +++ b/src/kernel/wait_queue.c @@ -6,6 +6,7 @@ * @date 2022-07-20 */ +#include "kernel/console.h" #include "kernel/spinlock.h" #include "kernel/thread.h" #include @@ -81,12 +82,7 @@ void wait_queue_wakeup(WaitQueue *wqm) { list_del(&thread->wait_queue_tag); - int flags2 = spin_lock_irqsave(&thread->status_lock); - if (thread->status == TASK_INTERRUPTIBLE || - thread->status == TASK_UNINTERRUPTIBLE) { - spin_unlock_irqrestore(&thread->status_lock, flags2); - thread_unblock(thread); - } + thread_unblock(thread); spin_unlock_irqrestore(&wqm->lock, flags); return; @@ -107,13 +103,8 @@ void wait_queue_wakeup_all(WaitQueue *wqm) { thread = cur; list_del(&cur->wait_queue_tag); - int flags2 = spin_lock_irqsave(&thread->status_lock); - if (thread->status == TASK_INTERRUPTIBLE || - thread->status == TASK_UNINTERRUPTIBLE) { - spin_unlock_irqrestore(&thread->status_lock, flags2); - thread_unblock(thread); - schedule(); - } + thread_unblock(thread); + schedule(); } spin_unlock_irqrestore(&wqm->lock, old_status); From bd10bf780a1c85f886ac73b9ff10b02ba52061fd Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 28 Mar 2025 16:16:12 +0800 Subject: [PATCH 043/158] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20IDE=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8DMA=E8=AF=BB=E5=86=99=E6=9C=AA=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E7=89=A9=E7=90=86=E5=9C=B0=E5=9D=80=E8=BF=9E=E7=BB=AD=E6=80=A7?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/bus/isa/dma.c | 4 +- src/arch/x86/drivers/disk/ata/Makefile | 3 +- src/arch/x86/drivers/disk/ata/dma.c | 93 ++++++++++++++++++ src/arch/x86/drivers/disk/ata/ide.c | 71 ++++---------- src/arch/x86/drivers/disk/ata/include/dma.h | 28 ++++++ src/arch/x86/drivers/disk/ata/include/ide.h | 6 -- .../drivers/disk/ata/include/ide_controller.h | 8 +- src/arch/x86/include/drivers/bus/isa/dma.h | 4 +- src/arch/x86/include/kernel/page.h | 2 +- src/arch/x86/kernel/page.c | 38 ++++---- src/driver/storage/storage_dm.c | 2 + src/driver/storage/storage_io.c | 11 ++- src/driver/storage/storage_io_queue.c | 17 +--- src/fs/fat/cluster.c | 6 +- src/fs/fat/fat.c | 1 - src/include/driver/storage/storage_dm.h | 4 + src/include/driver/storage/storage_io_queue.h | 3 +- src/include/dyn_array.h | 4 +- src/include/kernel/dma.h | 19 +++- src/include/kernel/wait_queue.h | 2 + src/include/objects/transfer.h | 1 + src/kernel/Makefile | 1 + src/kernel/dma.c | 63 ++++++++++++ src/kernel/driver.c | 1 - src/kernel/main.c | 96 +++++++++---------- src/kernel/memory.c | 10 +- src/kernel/thread.c | 12 +-- src/kernel/wait_queue.c | 44 ++++++--- 28 files changed, 370 insertions(+), 184 deletions(-) create mode 100644 src/arch/x86/drivers/disk/ata/dma.c create mode 100644 src/arch/x86/drivers/disk/ata/include/dma.h create mode 100644 src/kernel/dma.c diff --git a/src/arch/x86/drivers/bus/isa/dma.c b/src/arch/x86/drivers/bus/isa/dma.c index f91704c..da93370 100644 --- a/src/arch/x86/drivers/bus/isa/dma.c +++ b/src/arch/x86/drivers/bus/isa/dma.c @@ -44,7 +44,7 @@ void dma_init() { memset(dma_mem_mmap.bits, 0, dma_mem_mmap.len); } -void *dma_alloc_region(void *dma, uint32_t size) { +void *dma_alloc_region(Dma *dma, uint32_t size) { int cnt = DIV_ROUND_UP(size, 64 * 1024); int idx = mmap_search(&dma_mem_mmap, cnt); if (idx == -1) return NULL; @@ -55,7 +55,7 @@ void *dma_alloc_region(void *dma, uint32_t size) { return (void *)(DMA_MEM_BASE_ADDR + idx * DMA_REGION_SIZE); } -DriverResult dma_free_region(void *dma, void *ptr, uint32_t size) { +DriverResult dma_free_region(Dma *dma, void *ptr, uint32_t size) { int cnt = DIV_ROUND_UP(size, 64 * 1024); int idx = ((uint32_t)ptr - DMA_MEM_BASE_ADDR) / DMA_REGION_SIZE; for (int i = 0; i < cnt; i++) { diff --git a/src/arch/x86/drivers/disk/ata/Makefile b/src/arch/x86/drivers/disk/ata/Makefile index e238cb7..bb76895 100644 --- a/src/arch/x86/drivers/disk/ata/Makefile +++ b/src/arch/x86/drivers/disk/ata/Makefile @@ -1,3 +1,4 @@ SRC += ata_driver.c SRC += ide.c -SRC += ide_controller.c \ No newline at end of file +SRC += ide_controller.c +SRC += dma.c \ No newline at end of file diff --git a/src/arch/x86/drivers/disk/ata/dma.c b/src/arch/x86/drivers/disk/ata/dma.c new file mode 100644 index 0000000..6f3c005 --- /dev/null +++ b/src/arch/x86/drivers/disk/ata/dma.c @@ -0,0 +1,93 @@ +#include "include/dma.h" +#include "include/ide.h" +#include "include/ide_controller.h" +#include "kernel/driver.h" +#include "kernel/list.h" +#include "kernel/memory.h" +#include "stdint.h" +#include +#include +#include +#include + +/** + * 配置DMA + */ +void ata_bmdma_set_prdt(IdeDevice *device, AtaDma *ata_dma, int rw) { + IdeChannel *channel = device->channel; + + PhysicalRegionDescriptor *prds = ata_dma->prds; + DmaSegment *seg; + + int i = 0, size, left_size; + uint32_t addr, offset; + list_for_each_owner (seg, &ata_dma->segment_lh, list) { + left_size = seg->size; + addr = seg->addr; + while (left_size > 0 && i < IDE_MAX_PRDT_COUNT) { + offset = addr & 0xffff; // 缓冲区不能跨越64K边界 + size = MIN(left_size, 0x10000 - offset); + prds[i].base_addr = addr; + prds[i].count = size & 0xffff; + prds[i].sign = 0; + left_size -= size; + addr += size; + i++; + } + } + prds[i - 1].sign = BIT(15); + + io_out_dword(channel->bmide + IDE_REG_BM_PRDT, ata_dma->prdt_phy_addr); + + uint8_t data; + data = io_in_byte(channel->bmide + IDE_REG_BM_COMMAND); + data = (rw == 0) ? BIN_EN(data, IDE_BMCMD_READ_WRITE) + : BIN_DIS(data, IDE_BMCMD_READ_WRITE); + io_out_byte(channel->bmide + IDE_REG_BM_COMMAND, data); + + data = io_in_byte(channel->bmide + IDE_REG_BM_STATUS); + io_out_byte( + channel->bmide + IDE_REG_BM_STATUS, + BIN_EN(data, IDE_BMSTATUS_INT | IDE_BMSTATUS_ERROR)); +} + +DriverResult ata_bmdma_map_buffer(AtaDma *ata_dma, void *ptr, uint32_t size) { + size_t addr; + addr = (size_t)ptr; + + if (addr & 3) { + // 申请一个小的临时缓冲区处理未对齐的部分 + int size = 32 - (addr & 0x1f); + void *tmp_buf = kmalloc(size); + if (tmp_buf == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } + memcpy(tmp_buf, ptr, size); + + DmaSegment *seg = kmalloc(sizeof(DmaSegment)); + seg->vaddr = (size_t)tmp_buf; + seg->addr = vir2phy((uint32_t)tmp_buf); + seg->size = size; + list_add_tail(&seg->list, &ata_dma->segment_lh); + ptr += size; + } + + dma_split_mem(&ata_dma->segment_lh, ptr, size, ata_dma->max_segment_size); + return DRIVER_RESULT_OK; +} + +void ata_bmdma_unmap_buffer(AtaDma *ata_dma, void *ptr, uint32_t size) { + DmaSegment *seg, *next; + size_t start_ptr = (size_t)ptr; + size_t end_ptr = start_ptr + size; + void *addr = ptr; + + list_for_each_owner_safe (seg, next, &ata_dma->segment_lh, list) { + if (start_ptr > seg->vaddr || seg->vaddr >= end_ptr) { + memcpy(addr, (void *)seg->vaddr, seg->size); + // 释放临时缓冲区 + kfree((void *)seg->vaddr); + } + addr += seg->size; + list_del(&seg->list); + kfree(seg); + } +} diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index 1d2a940..5f16a82 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -20,8 +20,10 @@ #include "include/ata.h" #include "include/ata_cmd.h" #include "include/ata_driver.h" +#include "include/dma.h" #include "include/ide.h" #include "include/ide_controller.h" +#include "kernel/list.h" DriverResult ide_device_init(Device *device); @@ -66,6 +68,7 @@ Device ide_device_template = { StorageDevice storage_device_template = { .block_size = SECTOR_SIZE, .max_block_per_request = 256, + .max_segment = IDE_MAX_PRDT_COUNT, .type = STORAGE_DEVICE_TYPE_HARDDISK, .ops = &ide_storage_device_ops, }; @@ -91,7 +94,9 @@ void ide_handle_interrupt(IdeChannel *channel) { BIN_DIS(data, IDE_BMCMD_START_STOP_BM)); if (request->rw == 0) { storage_solve_read_request(request); } - if (request->buf != request->real_buf) { kfree(request->real_buf); } + // if (request->buf != request->real_buf) { kfree(request->real_buf); } + ata_bmdma_unmap_buffer( + channel->dma, request->buf, request->count * SECTOR_SIZE); } storage_finish_request(request); } @@ -200,7 +205,15 @@ void ide_device_probe(IdeChannel *channel) { io_out_byte( channel->io_base + ATA_REG_CONTROL, BIN_DIS(data, ATA_CONTROL_NIEN)); - channel->prdt = kmalloc(sizeof(PhysicalRegionDescriptorTable) * 16); + + channel->dma = kmalloc(sizeof(AtaDma)); + channel->dma->prds = + kmalloc(sizeof(PhysicalRegionDescriptor) * IDE_MAX_PRDT_COUNT); + channel->dma->prdt_phy_addr = vir2phy((uint32_t)channel->dma->prds); + channel->dma->prdt_status = 0; + channel->dma->max_segment_size = 65536; + list_init(&channel->dma->segment_lh); + interrupt_enable_irq(channel->irq->irq); for (i = 0; i < 2; i++) { @@ -276,50 +289,6 @@ void ide_device_send_pio(IdeDevice *device, uint32_t *buf, uint32_t count) { count << 8 /* count * 512 / 2 */); } -/** - * 配置DMA - */ -void ide_device_set_dma(IdeDevice *device, StorageRequest *request) { - IdeChannel *channel = device->channel; - - PhysicalRegionDescriptorTable *prdt = channel->prdt; - - uint8_t *buffer; - buffer = (uint32_t)request->buf & 3 - ? kmalloc(request->count * SECTOR_SIZE) // 未对齐则另外分配 - : request->buf; // 传入的缓冲区已对齐则直接使用 - size_t left_size = request->count * SECTOR_SIZE; - int size; - request->real_buf = buffer; - int i = 0; - uint32_t addr = vir2phy((uint32_t)buffer); - uint32_t offset; - while (left_size > 0 && i < IDE_MAX_PRDT_COUNT) { - offset = addr & 0xffff; // 缓冲区不能跨越64K边界 - size = MIN(left_size, 0x10000 - offset); - prdt[i].base_addr = addr; - prdt[i].count = size & 0xffff; - prdt[i].sign = 0; - left_size -= size; - addr += size; - i++; - } - prdt[i - 1].sign = BIT(15); - - io_out_dword(channel->bmide + IDE_REG_BM_PRDT, vir2phy((uint32_t)prdt)); - - uint8_t data; - data = io_in_byte(channel->bmide + IDE_REG_BM_COMMAND); - data = (request->rw == 0) ? BIN_EN(data, IDE_BMCMD_READ_WRITE) - : BIN_DIS(data, IDE_BMCMD_READ_WRITE); - io_out_byte(channel->bmide + IDE_REG_BM_COMMAND, data); - - data = io_in_byte(channel->bmide + IDE_REG_BM_STATUS); - io_out_byte( - channel->bmide + IDE_REG_BM_STATUS, - BIN_EN(data, IDE_BMSTATUS_INT | IDE_BMSTATUS_ERROR)); -} - /** * 从设备读取扇区,调用方保证buf与count的合法性 * @@ -341,10 +310,10 @@ DriverResult ide_device_read_sectors( } if (ide_device->mode == TRANSFER_MODE_DMA) { - ide_device_set_dma(ide_device, request); + ata_bmdma_map_buffer( + channel->dma, request->buf, request->count * SECTOR_SIZE); + ata_bmdma_set_prdt(ide_device, channel->dma, request->rw); } - request->real_buf = - (request->real_buf == NULL) ? request->buf : request->real_buf; ide_select_device(channel, ide_device->device_num); ide_wait(channel); @@ -398,8 +367,10 @@ DriverResult ide_device_write_sectors( } if (ide_device->mode == TRANSFER_MODE_DMA) { - ide_device_set_dma(ide_device, request); storage_solve_write_request(request); + ata_bmdma_map_buffer( + channel->dma, request->buf, request->count * SECTOR_SIZE); + ata_bmdma_set_prdt(ide_device, channel->dma, request->rw); } ide_select_device(channel, ide_device->device_num); diff --git a/src/arch/x86/drivers/disk/ata/include/dma.h b/src/arch/x86/drivers/disk/ata/include/dma.h new file mode 100644 index 0000000..d737f3c --- /dev/null +++ b/src/arch/x86/drivers/disk/ata/include/dma.h @@ -0,0 +1,28 @@ +#ifndef _ATA_DMA_H +#define _ATA_DMA_H + +#include "ide.h" +#include + +typedef struct PhysicalRegionDescriptor { + uint32_t base_addr; + uint16_t count; + uint16_t sign; +} __attribute__((packed)) PhysicalRegionDescriptor; + +typedef struct AtaDma { + list_t segment_lh; + + int prdt_status; + int max_segment_size; + + struct PhysicalRegionDescriptor *prds; + + uint32_t prdt_phy_addr; +} AtaDma; + +void ata_bmdma_set_prdt(IdeDevice *device, AtaDma *ata_dma, int rw); +DriverResult ata_bmdma_map_buffer(AtaDma *ata_dma, void *ptr, uint32_t size); +void ata_bmdma_unmap_buffer(AtaDma *ata_dma, void *ptr, uint32_t size); + +#endif \ No newline at end of file diff --git a/src/arch/x86/drivers/disk/ata/include/ide.h b/src/arch/x86/drivers/disk/ata/include/ide.h index f1ba992..7800be9 100644 --- a/src/arch/x86/drivers/disk/ata/include/ide.h +++ b/src/arch/x86/drivers/disk/ata/include/ide.h @@ -36,12 +36,6 @@ typedef struct IdeDevice { AtaCmdIndex cmdset[ATA_CMDSET_MAX]; } IdeDevice; -typedef struct PhysicalRegionDescriptorTable { - uint32_t base_addr; - uint16_t count; - uint16_t sign; -} __attribute__((packed)) PhysicalRegionDescriptorTable; - extern struct DeviceDriver ide_device_driver; void ide_channel0_handler(struct Device *device); diff --git a/src/arch/x86/drivers/disk/ata/include/ide_controller.h b/src/arch/x86/drivers/disk/ata/include/ide_controller.h index a23612e..88a2c0a 100644 --- a/src/arch/x86/drivers/disk/ata/include/ide_controller.h +++ b/src/arch/x86/drivers/disk/ata/include/ide_controller.h @@ -5,6 +5,7 @@ #include "driver/timer_dm.h" #include "drivers/bus/pci/pci.h" #include "kernel/driver_interface.h" +#include "kernel/spinlock.h" #include "stdint.h" #define IDE_CONTROLLER_CLASSCODE 0x01 @@ -42,9 +43,10 @@ typedef struct IdeChannelInfo { Timer timer; - int selected_device; - struct IdeDevice *ide_devices[2]; - struct PhysicalRegionDescriptorTable *prdt; + int selected_device; + struct IdeDevice *ide_devices[2]; + + struct AtaDma *dma; } IdeChannel; typedef struct IdeControllerInfo { diff --git a/src/arch/x86/include/drivers/bus/isa/dma.h b/src/arch/x86/include/drivers/bus/isa/dma.h index 4025247..c578252 100644 --- a/src/arch/x86/include/drivers/bus/isa/dma.h +++ b/src/arch/x86/include/drivers/bus/isa/dma.h @@ -73,8 +73,8 @@ extern DmaOps isa_dma_ops; void dma_init(); -void *dma_alloc_region(void *dma, uint32_t size); -DriverResult dma_free_region(void *dma, void *ptr, uint32_t size); +void *dma_alloc_region(Dma *dma, uint32_t size); +DriverResult dma_free_region(Dma *dma, void *ptr, uint32_t size); struct Device; int dma_channel_use(struct Device *device, int *possible_ch, int len); diff --git a/src/arch/x86/include/kernel/page.h b/src/arch/x86/include/kernel/page.h index 9dc4445..710521a 100644 --- a/src/arch/x86/include/kernel/page.h +++ b/src/arch/x86/include/kernel/page.h @@ -34,7 +34,7 @@ uint32_t *pde_ptr(uint32_t vaddr); uint32_t vir2phy(uint32_t vaddr); MemoryResult remap(uint32_t in_paddr, size_t in_size, uint32_t *out_vaddr); void unmap(uint32_t vaddr, size_t size); -int alloc_vir_page(void); +int alloc_vir_pages(int count); int free_vir_page(int vir_addr); void *kernel_alloc_pages(int pages); void kernel_free_page(int vaddr, int pages); diff --git a/src/arch/x86/kernel/page.c b/src/arch/x86/kernel/page.c index 8f030bd..b01fb6a 100644 --- a/src/arch/x86/kernel/page.c +++ b/src/arch/x86/kernel/page.c @@ -219,12 +219,14 @@ void unmap(uint32_t vaddr, size_t size) { * * @return int 虚拟页地址 */ -int alloc_vir_page(void) { +int alloc_vir_pages(int count) { int idx; int vir_addr; - idx = mmap_search(&vir_page_mmap, 1); + idx = mmap_search(&vir_page_mmap, count); if (idx != -1) { - mmap_set(&vir_page_mmap, idx, 1); + for (int i = 0; i < count; i++) { + mmap_set(&vir_page_mmap, idx + i, 1); + } } else { return -1; } @@ -262,30 +264,24 @@ void *kernel_alloc_pages(int pages) { int old_status = io_load_eflags(); io_cli(); - vir_page_addr = alloc_vir_page(); // 分配一个虚拟地址的页 - + vir_page_addr = alloc_vir_pages(pages); // 分配一个虚拟地址的页 + if (vir_page_addr < 0) return NULL; fill_vir_page_table( vir_page_addr, SIGN_SYS); // 把页添加到当前页目录表系统中,使他可以被使用 - if (pages == 1) { // 如果只有一个页 - memset((void *)vir_page_addr, 0, PAGE_SIZE); + vir_page_addr_more = vir_page_addr + PAGE_SIZE; // 分配一个虚拟地址的页 + for (i = 1; i < pages; i++) { + fill_vir_page_table( + vir_page_addr_more, + SIGN_SYS); // 把页添加到当前页目录表系统中,使他可以被使用 + vir_page_addr_more += PAGE_SIZE; + } - io_store_eflags(old_status); - return (void *)vir_page_addr; - } else if (pages > 1) { - for (i = 1; i < pages; i++) { - vir_page_addr_more = alloc_vir_page(); // 分配一个虚拟地址的页 - fill_vir_page_table( - vir_page_addr_more, - SIGN_SYS); // 把页添加到当前页目录表系统中,使他可以被使用 - } - memset((void *)vir_page_addr, 0, PAGE_SIZE * pages); - io_store_eflags(old_status); + memset((void *)vir_page_addr, 0, PAGE_SIZE * pages); + io_store_eflags(old_status); - return (void *)vir_page_addr; - } - return NULL; + return (void *)vir_page_addr; } /** diff --git a/src/driver/storage/storage_dm.c b/src/driver/storage/storage_dm.c index e0b74b7..6df0904 100644 --- a/src/driver/storage/storage_dm.c +++ b/src/driver/storage/storage_dm.c @@ -1,4 +1,5 @@ #include "kernel/spinlock.h" +#include "kernel/wait_queue.h" #include #include #include @@ -53,6 +54,7 @@ DriverResult register_storage_device( device->dm_ext = storage_device; spinlock_init(&storage_device->queue_lock); list_init(&storage_device->io_queue_lh); + wait_queue_init(&storage_device->wq); string_t name; string_new_with_number(&name, "Storage", 7, storage_dm_ext.device_count++); diff --git a/src/driver/storage/storage_io.c b/src/driver/storage/storage_io.c index 3df0cd1..45a31dc 100644 --- a/src/driver/storage/storage_io.c +++ b/src/driver/storage/storage_io.c @@ -2,6 +2,7 @@ * 默认的存储设备IO实现 */ #include "kernel/device.h" +#include "kernel/driver.h" #include "kernel/thread.h" #include "multiple_return.h" #include "stdint.h" @@ -94,14 +95,22 @@ TransferResult storage_transfer( StorageRequest *request; StorageDevice *storage_device = device->dm_ext; + thread_set_status(TASK_INTERRUPTIBLE); - storage_generate_request( + wait_queue_add(&storage_device->wq); + + DriverResult result = storage_generate_request( storage_device, (direction == TRANSFER_IN) ? 0 : 1, buf, position, count, &request); + if (result != DRIVER_RESULT_OK) { + wait_queue_del(&storage_device->wq); + return TRANSFER_ERROR_FAILED; + } thread_wait(); while (!request->is_finished) { thread_set_status(TASK_INTERRUPTIBLE); + wait_queue_add(&storage_device->wq); thread_wait(); } diff --git a/src/driver/storage/storage_io_queue.c b/src/driver/storage/storage_io_queue.c index 43673d4..7f54423 100644 --- a/src/driver/storage/storage_io_queue.c +++ b/src/driver/storage/storage_io_queue.c @@ -1,7 +1,7 @@ #include "kernel/block_cache.h" #include "kernel/rwlock.h" #include "kernel/spinlock.h" -#include "kernel/thread.h" +#include "kernel/wait_queue.h" #include #include #include @@ -137,7 +137,8 @@ void storage_finish_request(StorageRequest *storage_request) { req = req->next_merged_request; } } - thread_unblock(storage_request->thread); + wait_queue_wakeup_thread( + &storage_request->storage_device->wq, storage_request->thread); } void storage_submit_request(StorageRequest *request) { @@ -162,14 +163,10 @@ void storage_solve_read_request(StorageRequest *request) { uint32_t offset = (req->position - start) * request->storage_device->block_size; memcpy( - req->buf, request->real_buf + offset, + req->buf, request->buf + offset, req->count * req->storage_device->block_size); req = req->next_merged_request; } - } else if (request->buf != request->real_buf) { - memcpy( - request->buf, request->real_buf, - request->count * request->storage_device->block_size); } } @@ -182,13 +179,9 @@ void storage_solve_write_request(StorageRequest *request) { (req->position - start) * request->storage_device->block_size; // 写入需要分先后,由于合并请求时已经按顺序排列了,直接覆盖就好 memcpy( - request->real_buf + offset, req->buf, + request->buf + offset, req->buf, req->count * req->storage_device->block_size); req = req->next_merged_request; } - } else if (request->buf != request->real_buf) { - memcpy( - request->real_buf, request->buf, - request->count * request->storage_device->block_size); } } diff --git a/src/fs/fat/cluster.c b/src/fs/fat/cluster.c index 12236ee..d1b2bd5 100644 --- a/src/fs/fat/cluster.c +++ b/src/fs/fat/cluster.c @@ -204,11 +204,11 @@ FsResult fat_cluster_list_get( int counter = index; - ClusterSegment clus_seg; + ClusterSegment *clus_seg; dyn_array_foreach(arr, ClusterSegment, clus_seg) { - int length = clus_seg.end - clus_seg.start + 1; + int length = clus_seg->end - clus_seg->start + 1; if (counter < length) { - cur_cluster->cluster = clus_seg.start + counter; + cur_cluster->cluster = clus_seg->start + counter; cur_cluster->offset = _block_offset; cur_cluster->block = _block; cur_cluster->index = index; diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c index 492b4f7..b743163 100644 --- a/src/fs/fat/fat.c +++ b/src/fs/fat/fat.c @@ -3,7 +3,6 @@ #include "include/cluster.h" #include "include/dir.h" #include "include/entry.h" -#include "kernel/console.h" #include "math.h" #include "objects/handle.h" #include diff --git a/src/include/driver/storage/storage_dm.h b/src/include/driver/storage/storage_dm.h index 8ba61d2..25700c0 100644 --- a/src/include/driver/storage/storage_dm.h +++ b/src/include/driver/storage/storage_dm.h @@ -6,6 +6,7 @@ #include "kernel/list.h" #include "kernel/periodic_task.h" #include "kernel/spinlock.h" +#include "kernel/wait_queue.h" #include "objects/object.h" #include "string.h" #include @@ -37,10 +38,13 @@ typedef struct StorageDevice { uint32_t block_size; size_t max_block_per_request; + // 虚拟地址连续,而物理地址不连续的情况下,最大的连续段数 + int max_segment; spinlock_t queue_lock; PeriodicTask periodic_task; list_t io_queue_lh; + WaitQueue wq; uint8_t *superblock; diff --git a/src/include/driver/storage/storage_io_queue.h b/src/include/driver/storage/storage_io_queue.h index f4be280..1155ebf 100644 --- a/src/include/driver/storage/storage_io_queue.h +++ b/src/include/driver/storage/storage_io_queue.h @@ -11,8 +11,7 @@ typedef struct StorageRequest { list_t list; bool rw; - uint8_t *buf; // 调用方传入的缓冲区 - uint8_t *real_buf; // 实际读写时使用的缓冲区 + uint8_t *buf; uint64_t position; uint32_t count; bool is_finished; diff --git a/src/include/dyn_array.h b/src/include/dyn_array.h index 3c6ea86..4ccc603 100644 --- a/src/include/dyn_array.h +++ b/src/include/dyn_array.h @@ -62,9 +62,9 @@ bool dyn_array_is_end( struct DynArrayBlock *_block = (arr)->first_block; \ int _block_index = 0; \ int _block_offset = 0; \ - for (var = *((type *)_block->data); \ + for (var = ((type *)_block->data); \ !dyn_array_is_end(arr, _block, _block_index, _block_offset); \ - var = *((type *)dyn_array_next_ptr( \ + var = ((type *)dyn_array_next_ptr( \ arr, &_block, &_block_index, &_block_offset))) #endif \ No newline at end of file diff --git a/src/include/kernel/dma.h b/src/include/kernel/dma.h index f5592e4..d049fad 100644 --- a/src/include/kernel/dma.h +++ b/src/include/kernel/dma.h @@ -12,11 +12,16 @@ #define _DMA_H #include "kernel/driver.h" +#include "kernel/list.h" #include +struct Dma; typedef struct DmaOps { - void *(*dma_alloc)(void *dma, uint32_t size); - DriverResult (*dma_free)(void *dma, void *ptr, uint32_t size); + void *(*dma_alloc)(struct Dma *dma, uint32_t size); + DriverResult (*dma_free)(struct Dma *dma, void *ptr, uint32_t size); + + DriverResult (*dma_map_buffer)(struct Dma *dma, void *ptr, uint32_t size); + DriverResult (*dma_unmap_buffer)(struct Dma *dma, void *ptr, uint32_t size); } DmaOps; typedef struct Dma { @@ -25,4 +30,14 @@ typedef struct Dma { void *param; } Dma; +typedef struct DmaSegment { + list_t list; + size_t vaddr; + size_t addr; + size_t size; +} DmaSegment; + +DriverResult dma_split_mem( + list_t *lh, void *ptr, uint32_t size, int max_segment_size); + #endif \ No newline at end of file diff --git a/src/include/kernel/wait_queue.h b/src/include/kernel/wait_queue.h index 550f7b1..cff7c38 100644 --- a/src/include/kernel/wait_queue.h +++ b/src/include/kernel/wait_queue.h @@ -13,7 +13,9 @@ typedef struct { void wait_queue_init(WaitQueue *wq); bool wait_queue_empty(WaitQueue *wq); void wait_queue_add(WaitQueue *wq); +void wait_queue_del(WaitQueue *wq); struct task_s *wait_queue_first(WaitQueue *wq); +void wait_queue_wakeup_thread(WaitQueue *wq, struct task_s *thread); void wait_queue_wakeup(WaitQueue *wq); void wait_queue_wakeup_all(WaitQueue *wq); diff --git a/src/include/objects/transfer.h b/src/include/objects/transfer.h index f39f57c..5fd9c14 100644 --- a/src/include/objects/transfer.h +++ b/src/include/objects/transfer.h @@ -10,6 +10,7 @@ typedef enum { TRANSFER_ERROR_NOT_SUPPORTED, TRANSFER_ERROR_INVALID_PARAMETER, TRANSFER_ERROR_NO_MEMORY, + TRANSFER_ERROR_FAILED, TRANSFER_ERROR_OTHER, } TransferResult; diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 97c4cf4..2bbb7ab 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -23,6 +23,7 @@ SRC += periodic_task.c SRC += block_cache.c SRC += rwlock.c SRC += condvar.c +SRC += dma.c #INCLUDE_PATH = ../include/ ../$(ARCH)/include/ diff --git a/src/kernel/dma.c b/src/kernel/dma.c new file mode 100644 index 0000000..ee83c9f --- /dev/null +++ b/src/kernel/dma.c @@ -0,0 +1,63 @@ +#include "kernel/driver.h" +#include "kernel/list.h" +#include +#include +#include +#include + +DriverResult dma_split_mem( + list_t *lh, void *ptr, uint32_t size, int max_segment_size) { + DmaSegment *seg; + size_t addr = (size_t)ptr; + size_t end_addr = addr + size; + size_t phy_addr, old_phy_page; + int seg_size = 0, tmp_size = 0; + size_t seg_start; + size_t seg_start_vaddr; + size_t page_addr; + + // TODO:未对齐的页 + for (; addr < end_addr; addr += tmp_size) { + phy_addr = vir2phy(addr); + page_addr = phy_addr & ~(PAGE_SIZE - 1); + tmp_size = PAGE_SIZE - (phy_addr & (PAGE_SIZE - 1)); + tmp_size = MIN(tmp_size, size); + + if (seg_size == 0) { + seg_start = phy_addr; + seg_start_vaddr = addr; + seg_size = tmp_size; + } else { + if (page_addr == old_phy_page + PAGE_SIZE && + seg_size + tmp_size < max_segment_size) { + seg_size += tmp_size; + } else { + // 创建新的请求 + seg = kmalloc(sizeof(DmaSegment)); + if (seg == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } + + // 设置新请求的参数 + seg->vaddr = seg_start_vaddr; + seg->addr = seg_start; + seg->size = seg_size; + list_add_tail(&seg->list, lh); + + seg_start_vaddr = addr; + seg_start = phy_addr; + seg_size = tmp_size; + } + } + old_phy_page = page_addr; + } + if (seg_size > 0) { + seg = kmalloc(sizeof(DmaSegment)); + if (seg == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } + + // 设置新请求的参数 + seg->vaddr = seg_start_vaddr; + seg->addr = seg_start; + seg->size = seg_size; + list_add_tail(&seg->list, lh); + } + return DRIVER_RESULT_OK; +} \ No newline at end of file diff --git a/src/kernel/driver.c b/src/kernel/driver.c index 3c95eec..e618363 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -5,7 +5,6 @@ * @version 0.3 * @date 2022-07-20 */ -#include "kernel/sync.h" #include #include #include diff --git a/src/kernel/main.c b/src/kernel/main.c index 11c8385..0d172c4 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -64,53 +64,53 @@ extern Driver core_driver; // printk("\n"); // } -// void thread_play(void *arg) { -// Object *object; -// ObjectResult result = open_object_by_path("\\Device\\Sound0", &object); -// if (result != OBJECT_OK) { -// printk("Open File Error!\n"); -// } else { -// Object *file; -// result = -// open_object_by_path("\\Volumes\\Storage0Volume0\\1.pcm", &file); - -// if (result == OBJECT_OK) { -// ObjectHandle *handle = object_handle_create(file); -// PcmDevice *pcm; -// PcmStream *stream; -// // sound_pcm_open(object, SOUND_DEVICE_MODE_PLAY, &pcm, &stream); -// // sound_pcm_alloc(stream); -// // pcm_set_sample_rate(pcm, 44100); -// // pcm_set_channel(stream, 2); -// // sound_pcm_set_frame_count(stream, 4 * 1024); -// // sound_pcm_prepare(stream); -// ObjectAttr attr; -// obj_get_attr(file, &attr); -// size_t count = 2 * 64; -// size_t size = 4 * 1024 * 1024; -// uint8_t *buf = kmalloc(19 * 1024 * 1024); -// for (int i = 0; i < size / 1024 / 1024; i++) { -// printk("%dMB ", i); -// for (int j = 0; j < 8; j++) { -// TransferResult result = TRANSFER_IN_STREAM( -// file, handle, buf + (i * 16 + j) * 32 * 1024, -// 128 * 1024); -// if (result != TRANSFER_OK) { -// printk("Transfer Error!\n"); -// thread_exit(); -// } -// } -// } -// for (int i = 0; i < count; i++) { -// // io_cli(); -// printk("%d ", i); -// // io_sti(); -// // sound_pcm_write(stream, buf, 4 * 1024); -// buf += 16 * 1024; -// } -// } -// } -// } +void thread_play(void *arg) { + Object *object; + ObjectResult result = open_object_by_path("\\Device\\Sound0", &object); + if (result != OBJECT_OK) { + printk("Open File Error!\n"); + } else { + Object *file; + result = + open_object_by_path("\\Volumes\\Storage0Volume0\\1.pcm", &file); + + if (result == OBJECT_OK) { + ObjectHandle *handle = object_handle_create(file); + PcmDevice *pcm; + PcmStream *stream; + // sound_pcm_open(object, SOUND_DEVICE_MODE_PLAY, &pcm, &stream); + // sound_pcm_alloc(stream); + // pcm_set_sample_rate(pcm, 44100); + // pcm_set_channel(stream, 2); + // sound_pcm_set_frame_count(stream, 4 * 1024); + // sound_pcm_prepare(stream); + ObjectAttr attr; + obj_get_attr(file, &attr); + size_t count = 2 * 64; + size_t size = 4 * 1024 * 1024; + uint8_t *buf = kmalloc(19 * 1024 * 1024); + for (int i = 0; i < size / 1024 / 1024; i++) { + printk("%dMB ", i); + for (int j = 0; j < 8; j++) { + TransferResult result = TRANSFER_IN_STREAM( + file, handle, buf + (i * 16 + j) * 32 * 1024, + 32 * 1024); + if (result != TRANSFER_OK) { + printk("Transfer Error!\n"); + thread_exit(); + } + } + } + for (int i = 0; i < count; i++) { + // io_cli(); + printk("%d ", i); + // io_sti(); + // sound_pcm_write(stream, buf, 4 * 1024); + buf += 16 * 1024; + } + } + } +} int main() { platform_early_init(); @@ -147,7 +147,7 @@ int main() { do_initcalls(); driver_start_all(); - // thread_start("play", 1000, thread_play, NULL); + // thread_start("play", 100, thread_play, NULL, NULL); // const string_t name = STRING_INIT("A folder"); // obj_rmdir(object, name); diff --git a/src/kernel/memory.c b/src/kernel/memory.c index 4251414..6b2f4a0 100644 --- a/src/kernel/memory.c +++ b/src/kernel/memory.c @@ -6,7 +6,6 @@ * @date 2020-07 */ #include "kernel/driver_interface.h" -#include "kernel/func.h" #include "kernel/list.h" #include #include @@ -222,13 +221,10 @@ void *kmalloc(uint32_t size) { if (size == 0) { return NULL; } - int pow = MAX(aligned_log2n(size), MEMORY_MIN_POW); // 指数 - size = 1 << pow; - int flags = save_and_disable_interrupt(); // TODO // 大于半个页就按页分配 if (size > 2048) { - int pages = size & ~(PAGE_SIZE - 1); // 一共占多少个页 + int pages = (size + PAGE_SIZE - 1) >> 12; // 一共占多少个页 int index = find_free_block(memory_manage); if (index == -1) { store_interrupt_status(flags); @@ -245,7 +241,9 @@ void *kmalloc(uint32_t size) { memory_manage->free_blocks[index].mode = MEMORY_BLOCK_MODE_BIG; store_interrupt_status(flags); return (void *)address; - } else if (0 < size && size <= 2048) { // size <= 2048 + } else if (0 < size && size <= 2048) { // size <= 2048 + int pow = MAX(aligned_log2n(size), MEMORY_MIN_POW); // 指数 + size = 1 << pow; // 第一次寻找,如果在块中没有找到,就打散一个页 if (!list_empty( &memory_manage->free_blocks_list[pow - MEMORY_MIN_POW])) { diff --git a/src/kernel/thread.c b/src/kernel/thread.c index 1cd7b2c..cd1f71d 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -53,9 +53,6 @@ static uint32_t alloc_pid(void) { * @return struct task_s* */ struct task_s *get_current_thread() { - // uint32_t sp; - // GET_REG("esp", sp); - // return (struct task_s *)(sp & 0xfffff000); return current_task; } @@ -343,10 +340,11 @@ void schedule(void) { } // 2. 获取下一个线程,如果没有则使用idle线程 - struct task_s *next = - list_first_owner(&thread_ready, struct task_s, general_tag); - if (next != cur) list_del(&next->general_tag); - else next = task_idle; + struct task_s *next; + if (!list_empty(&thread_ready)) { + next = list_first_owner(&thread_ready, struct task_s, general_tag); + list_del(&next->general_tag); + } else next = task_idle; // 4. 改变状态并加入到thread_ready next->status = TASK_RUNNING; diff --git a/src/kernel/wait_queue.c b/src/kernel/wait_queue.c index 605f642..8a0e6a1 100644 --- a/src/kernel/wait_queue.c +++ b/src/kernel/wait_queue.c @@ -58,6 +58,17 @@ void wait_queue_add(WaitQueue *wq) { spin_unlock_irqrestore(&wq->lock, flags); } +void wait_queue_del(WaitQueue *wq) { + struct task_s *task = get_current_thread(); + if (task->wait_queue_tag.next != NULL) { + printk("Error:Current thread(pid:%d) is in wait queue!\n", task->pid); + list_del(&task->wait_queue_tag); + } + int flags = spin_lock_irqsave(&wq->lock); + if (task->wait_queue_tag.next != NULL) list_del(&task->wait_queue_tag); + spin_unlock_irqrestore(&wq->lock, flags); +} + /** * @brief 获取等待队列中的第一个任务 * @@ -69,22 +80,29 @@ struct task_s *wait_queue_first(WaitQueue *wqm) { return list_first_owner(&wqm->list_head, struct task_s, wait_queue_tag); } +void wait_queue_wakeup_thread(WaitQueue *wq, struct task_s *thread) { + int flags = spin_lock_irqsave(&wq->lock); + + list_del(&thread->wait_queue_tag); + + if (thread != get_current_thread()) thread_unblock(thread); + + spin_unlock_irqrestore(&wq->lock, flags); + return; +} + /** * @brief 唤醒等待队列中的第一个任务 * * @param wqm 等待队列管理结构 */ -void wait_queue_wakeup(WaitQueue *wqm) { - if (list_empty(&wqm->list_head)) { return; } +void wait_queue_wakeup(WaitQueue *wq) { + if (list_empty(&wq->list_head)) { return; } struct task_s *thread = - list_first_owner(&wqm->list_head, struct task_s, wait_queue_tag); - int flags = spin_lock_irqsave(&wqm->lock); - - list_del(&thread->wait_queue_tag); + list_first_owner(&wq->list_head, struct task_s, wait_queue_tag); - thread_unblock(thread); + wait_queue_wakeup_thread(wq, thread); - spin_unlock_irqrestore(&wqm->lock, flags); return; } @@ -93,13 +111,13 @@ void wait_queue_wakeup(WaitQueue *wqm) { * * @param wqm 等待队列管理结构 */ -void wait_queue_wakeup_all(WaitQueue *wqm) { - if (list_empty(&wqm->list_head)) { return; } +void wait_queue_wakeup_all(WaitQueue *wq) { + if (list_empty(&wq->list_head)) { return; } struct task_s *cur, *next; struct task_s *thread; - int old_status = spin_lock_irqsave(&wqm->lock); - list_for_each_owner_safe (cur, next, &wqm->list_head, wait_queue_tag) { + int old_status = spin_lock_irqsave(&wq->lock); + list_for_each_owner_safe (cur, next, &wq->list_head, wait_queue_tag) { thread = cur; list_del(&cur->wait_queue_tag); @@ -107,6 +125,6 @@ void wait_queue_wakeup_all(WaitQueue *wqm) { schedule(); } - spin_unlock_irqrestore(&wqm->lock, old_status); + spin_unlock_irqrestore(&wq->lock, old_status); return; } From ed37bab5b2ec97a0ae12058009c3277c256e8b54 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 28 Mar 2025 17:14:02 +0800 Subject: [PATCH 044/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E8=AE=A1=E6=97=B6=E5=99=A8=E6=95=B0=E5=80=BC=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=9B=E4=BF=AE=E6=94=B9=20=E4=B8=BB=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E5=AE=8C=E6=88=90=E5=90=8E=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E9=80=80=E5=87=BA=EF=BC=8C=E9=81=BF=E5=85=8D=E9=98=BB?= =?UTF-8?q?=E5=A1=9E=E5=85=B6=E4=BB=96=E7=BA=BF=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/timer.c | 5 +++++ src/include/driver/timer_dm.h | 1 + src/kernel/main.c | 21 +++++++++++---------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/driver/timer.c b/src/driver/timer.c index e5bc16f..604491a 100644 --- a/src/driver/timer.c +++ b/src/driver/timer.c @@ -1,3 +1,4 @@ +#include "stdint.h" #include #include #include @@ -63,3 +64,7 @@ void set_periodic_ms(Timer *timer, uint32_t ms) { bool timer_is_timeout(Timer *timer) { return timer->timeout == 0; } + +size_t timer_get_counter() { + return ((TimerDevice *)timer_dm_ext.scheduler_timer->dm_ext)->counter; +} diff --git a/src/include/driver/timer_dm.h b/src/include/driver/timer_dm.h index caac4bb..357b29c 100644 --- a/src/include/driver/timer_dm.h +++ b/src/include/driver/timer_dm.h @@ -65,5 +65,6 @@ void delay_ms(Timer *timer, uint32_t ms); void delay_ms_async(Timer *timer, uint32_t ms); bool timer_is_timeout(Timer *timer); DriverResult timer_set_timeout(Timer *timer, uint32_t count); +size_t timer_get_counter(); #endif \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index 0d172c4..e27a1a4 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -89,17 +89,17 @@ void thread_play(void *arg) { size_t count = 2 * 64; size_t size = 4 * 1024 * 1024; uint8_t *buf = kmalloc(19 * 1024 * 1024); + uint32_t t0, t1; for (int i = 0; i < size / 1024 / 1024; i++) { - printk("%dMB ", i); - for (int j = 0; j < 8; j++) { - TransferResult result = TRANSFER_IN_STREAM( - file, handle, buf + (i * 16 + j) * 32 * 1024, - 32 * 1024); - if (result != TRANSFER_OK) { - printk("Transfer Error!\n"); - thread_exit(); - } + t0 = timer_get_counter(); + TransferResult result = TRANSFER_IN_STREAM( + file, handle, buf + i * 1024 * 1024, 1024 * 1024); + if (result != TRANSFER_OK) { + printk("Transfer Error!\n"); + thread_exit(); } + t1 = timer_get_counter(); + printk("%d KB/s", 1024 * 1000 / (t1 - t0)); } for (int i = 0; i < count; i++) { // io_cli(); @@ -147,7 +147,7 @@ int main() { do_initcalls(); driver_start_all(); - // thread_start("play", 100, thread_play, NULL, NULL); + thread_start("play", 100, thread_play, NULL, NULL); // const string_t name = STRING_INIT("A folder"); // obj_rmdir(object, name); @@ -211,6 +211,7 @@ int main() { console_start(); + thread_exit(); for (;;) { io_hlt(); } From 6bf383acc16e69f10e7cc99d2cb0ddbeb47cfbb5 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 29 Mar 2025 22:33:09 +0800 Subject: [PATCH 045/158] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E5=86=85=E5=AD=98?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=9D=97=E7=9A=84=E6=A0=87=E8=AE=B0=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/memory.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/kernel/memory.c b/src/kernel/memory.c index 6b2f4a0..0e0dc1f 100644 --- a/src/kernel/memory.c +++ b/src/kernel/memory.c @@ -237,7 +237,7 @@ void *kmalloc(uint32_t size) { } memory_manage->free_blocks[index].address = (uint32_t)address; memory_manage->free_blocks[index].size = pages; // 大小是页的数量 - memory_manage->free_blocks[index].flags = MEMORY_BLOCK_USING; + memory_manage->free_blocks[index].flags = MEMORY_BLOCK_ALLOCATED; memory_manage->free_blocks[index].mode = MEMORY_BLOCK_MODE_BIG; store_interrupt_status(flags); return (void *)address; @@ -251,7 +251,7 @@ void *kmalloc(uint32_t size) { &memory_manage->free_blocks_list[pow - MEMORY_MIN_POW], struct memory_block, list); address = (void *)block->address; - block->flags = MEMORY_BLOCK_USING; + block->flags = MEMORY_BLOCK_ALLOCATED; list_del(&block->list); store_interrupt_status(flags); return (void *)address; @@ -292,7 +292,7 @@ int kfree(void *address) { int flags = save_and_disable_interrupt(); for (i = 0; i < MEMORY_BLOCKS; i++) { block = &memory_manage->free_blocks[i]; - if (block->address == addr && block->flags == MEMORY_BLOCK_USING) { + if (block->address == addr && block->flags == MEMORY_BLOCK_ALLOCATED) { if (block->mode == MEMORY_BLOCK_MODE_BIG) { kernel_free_page(block->address, block->size); block->flags = MEMORY_BLOCK_FREE; From dd08968cd53349be133e5c135cb0066a5c24ded6 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 29 Mar 2025 22:58:57 +0800 Subject: [PATCH 046/158] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20storage=5Fio?= =?UTF-8?q?=E5=9D=97=E5=A4=A7=E5=B0=8F=E8=AE=A1=E7=AE=97=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=BC=93=E5=86=B2=E5=8C=BA=E8=A2=AB=E8=A6=86?= =?UTF-8?q?=E7=9B=96=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/storage/storage_io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/driver/storage/storage_io.c b/src/driver/storage/storage_io.c index 45a31dc..581f578 100644 --- a/src/driver/storage/storage_io.c +++ b/src/driver/storage/storage_io.c @@ -58,7 +58,8 @@ DriverResult storage_generate_request( request->thread = cur_thread; // 分配或指向原始缓冲区中对应的部分 - request->buf = buf + i * device->max_block_per_request; + request->buf = + buf + i * device->max_block_per_request * device->block_size; storage_add_request(device, request); From e9ced0f259dfbd82903ce7d55f14412f0d7ea2db Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 30 Mar 2025 16:34:27 +0800 Subject: [PATCH 047/158] =?UTF-8?q?[WIP]=E6=96=B0=E5=A2=9E=20sb16=E5=BD=95?= =?UTF-8?q?=E9=9F=B3=E6=94=AF=E6=8C=81=EF=BC=9B=E5=88=A0=E9=99=A4=20?= =?UTF-8?q?=E9=83=A8=E5=88=86TODO=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/sound/sb16/sb16.c | 60 +++++++++++- src/driver/sound/pcm.c | 122 ++++++++++++++++++++----- src/fs/fat/cluster.c | 1 - src/kernel/dma.c | 1 - src/kernel/driver.c | 2 - src/kernel/main.c | 29 +++--- 6 files changed, 167 insertions(+), 48 deletions(-) diff --git a/src/arch/x86/drivers/sound/sb16/sb16.c b/src/arch/x86/drivers/sound/sb16/sb16.c index 8fabd0e..563789e 100644 --- a/src/arch/x86/drivers/sound/sb16/sb16.c +++ b/src/arch/x86/drivers/sound/sb16/sb16.c @@ -34,6 +34,12 @@ DriverResult sb16_play_prepare( DriverResult sb16_play_trigger(PcmStream *stream, PcmTrigger trigger); size_t sb16_play_position(PcmStream *stream); +DriverResult sb16_record_open(SoundDevice *sound_device, PcmStream *stream); +DriverResult sb16_record_prepare( + struct PcmStream *stream, void *addr, size_t size); +DriverResult sb16_record_trigger(PcmStream *stream, PcmTrigger trigger); +size_t sb16_record_position(PcmStream *stream); + DeviceDriverOps sb16_device_driver_ops = { .device_driver_init = NULL, .device_driver_uninit = NULL, @@ -66,9 +72,10 @@ PcmStreamOps sb16_pcm_play_ops = { .set_channel = sb16_pcm_set_channel, }; PcmStreamOps sb16_pcm_record_ops = { - .open = NULL, + .open = sb16_record_open, .close = NULL, - .prepare = NULL, + .prepare = sb16_record_prepare, + .trigger = sb16_record_trigger, .set_default_params = sb16_pcm_set_default_params, .set_data_type = sb16_pcm_set_data_type, @@ -388,6 +395,55 @@ size_t sb16_play_position(PcmStream *stream) { return dma_pointer(info->dma_channel, stream->pcm->buffer_bytes); } +DriverResult sb16_record_open(SoundDevice *sound_device, PcmStream *stream) { + Sb16Info *info = (Sb16Info *)sound_device->device->private_data; + info->dma_channel = dma_channel_use( + sound_device->device, (int *)sb16_possible_dmas, + sizeof(sb16_possible_dmas) / sizeof(int)); + + return DRIVER_RESULT_OK; +} + +DriverResult sb16_record_prepare(PcmStream *stream, void *addr, size_t size) { + Sb16Info *info = (Sb16Info *)stream->sound_device->device->private_data; + struct Sb16StreamInfo *stream_info = stream->private_data; + + sb16_setup_dma( + info, info->dma_channel, + DMA_MODE_SINGLE | DMA_MODE_AUTO | DMA_MODE_READ, (uint32_t)addr, size); + + uint16_t sample_count = stream->period_bytes >> 1; + sample_count--; + + int flags = spin_lock_irqsave(&info->lock); + sb16_write( + &info->ports, TRANSFER_16BIT | TRANSFER_RECORD | TRANSFER_AUTOINIT); + sb16_write(&info->ports, stream_info->data_type); + sb16_write(&info->ports, (uint8_t)sample_count); + sb16_write(&info->ports, (uint8_t)(sample_count >> 8)); + sb16_write(&info->ports, CMD_STOP_PLAY16); + spin_unlock_irqrestore(&info->lock, flags); + + return DRIVER_RESULT_OK; +} + +DriverResult sb16_record_trigger(PcmStream *stream, PcmTrigger trigger) { + Sb16Info *info = (Sb16Info *)stream->sound_device->device->private_data; + switch (trigger) { + case PCM_TRIGGER_START: + case PCM_TRIGGER_RESUME: + sb16_write(&info->ports, CMD_RESUME_PLAY16); + break; + case PCM_TRIGGER_STOP: + case PCM_TRIGGER_PAUSE: + sb16_write(&info->ports, CMD_STOP_PLAY16); + break; + case PCM_TRIGGER_NONE: + return DRIVER_RESULT_OTHER_ERROR; + } + return DRIVER_RESULT_OK; +} + static void __init sb16_driver_entry(void) { register_driver(&sb_driver); register_device_driver(&sb_driver, &sb16_device_driver); diff --git a/src/driver/sound/pcm.c b/src/driver/sound/pcm.c index a957028..9bb8f75 100644 --- a/src/driver/sound/pcm.c +++ b/src/driver/sound/pcm.c @@ -150,13 +150,6 @@ int sound_pcm_left_space(PcmStream *stream) { return left_space; } -DriverResult sound_pcm_read( - PcmStream *stream, uint8_t *buf, uint32_t frame_count) { - // if (size > stream->pcm->max_size) return DRIVER_RESULT_EXCEED_MAX_SIZE; - // memcpy(buf, stream->buf, size); - return DRIVER_RESULT_OK; -} - void pcm_interleaved2noninterleaved( PcmStream *stream, uint8_t *in, uint8_t *out, uint32_t frame_count) { PcmDevice *pcm = stream->pcm; @@ -198,7 +191,7 @@ void pcm_noninterleaved2interleaved( } } -DriverResult sound_pcm_write_interleaved( +DriverResult sound_pcm_copy_interleaved( PcmStream *stream, uint8_t *dst, uint8_t *src, uint32_t frame_count) { if (frame_count > stream->frame_per_period) return DRIVER_RESULT_EXCEED_MAX_SIZE; @@ -213,7 +206,7 @@ DriverResult sound_pcm_write_interleaved( return DRIVER_RESULT_OK; } -DriverResult sound_pcm_write_noninterleaved( +DriverResult sound_pcm_copy_noninterleaved( PcmStream *stream, uint8_t *dst, uint8_t *src, uint32_t frame_count) { if (stream->hw_mode == PCM_MODE_NONINTERLEAVED) { // 模式相同,直接复制 @@ -226,43 +219,48 @@ DriverResult sound_pcm_write_noninterleaved( return DRIVER_RESULT_OK; } -DriverResult sound_pcm_write( - PcmStream *stream, uint8_t *buf, uint32_t frame_count) { +DriverResult pcm_transfer( + PcmStream *stream, uint8_t *user_buf, uint8_t *dma_buf, + uint32_t frame_count, TransferDirection direction) { PcmDevice *pcm = stream->pcm; uint32_t count; - uint8_t *dst, *src = buf; + uint8_t *user_buf_cur = user_buf, *dma_buf_cur = dma_buf; + uint8_t *src, *dst; int flags = spin_lock_irqsave(&stream->lock); int left_space = sound_pcm_left_space(stream); - size_t writed = 0; + size_t done = 0; size_t size, left_size = frame_count * stream->frame_bytes; while (left_size > 0) { while (left_space == 0) { - wait_queue_add(&stream->wq); thread_set_status(TASK_INTERRUPTIBLE); + wait_queue_add(&stream->wq); spin_unlock_irqrestore(&stream->lock, flags); - schedule(); + thread_wait(); spin_lock_irqsave(&stream->lock); left_space = sound_pcm_left_space(stream); } - dst = pcm->buf + stream->host_ptr; - size = MIN(left_space, left_size); - size = MIN(size, pcm->buffer_bytes - stream->host_ptr); + dma_buf_cur = dma_buf + stream->host_ptr; + size = MIN(left_space, left_size); + size = MIN(size, pcm->buffer_bytes - stream->host_ptr); spin_unlock_irqrestore(&stream->lock, flags); count = size / stream->frame_bytes; + + src = (direction == TRANSFER_IN) ? dma_buf_cur : user_buf_cur; + dst = (direction == TRANSFER_IN) ? user_buf_cur : dma_buf_cur; if (stream->user_mode == PCM_MODE_INTERLEAVED) { - sound_pcm_write_interleaved(stream, dst, src, count); + sound_pcm_copy_interleaved(stream, dst, src, count); } else { - sound_pcm_write_noninterleaved(stream, dst, src, count); + sound_pcm_copy_noninterleaved(stream, dst, src, count); } - src += size; + user_buf_cur += size; left_space -= size; left_size -= size; - writed += count; + done += count; flags = spin_lock_irqsave(&stream->lock); stream->host_ptr += size; @@ -275,7 +273,8 @@ DriverResult sound_pcm_write( } } } - if (writed > 0) { + if ((direction == TRANSFER_OUT && done > 0) || + (direction == TRANSFER_IN && done < frame_count)) { if ((pcm->status == PCM_STATUS_PREPARED || pcm->status == PCM_STATUS_PAUSED)) { if (sound_pcm_left_space(stream) >= stream->start_threshold) { @@ -288,11 +287,86 @@ DriverResult sound_pcm_write( stream->host_period_ptr = stream->host_ptr_base + position; } spin_unlock_irqrestore(&stream->lock, flags); - if (writed < frame_count) { return DRIVER_RESULT_BUSY; }; + if (done < frame_count) { return DRIVER_RESULT_BUSY; }; return DRIVER_RESULT_OK; } +DriverResult sound_pcm_read( + PcmStream *stream, uint8_t *buf, uint32_t frame_count) { + return pcm_transfer( + stream, buf, stream->pcm->buf, frame_count, TRANSFER_IN); +} + +DriverResult sound_pcm_write( + PcmStream *stream, uint8_t *buf, uint32_t frame_count) { + return pcm_transfer( + stream, buf, stream->pcm->buf, frame_count, TRANSFER_OUT); + // PcmDevice *pcm = stream->pcm; + // uint32_t count; + // uint8_t *dst, *src = buf; + + // int flags = spin_lock_irqsave(&stream->lock); + // int left_space = sound_pcm_left_space(stream); + + // size_t writed = 0; + // size_t size, left_size = frame_count * stream->frame_bytes; + // while (left_size > 0) { + // while (left_space == 0) { + // thread_set_status(TASK_INTERRUPTIBLE); + // wait_queue_add(&stream->wq); + // spin_unlock_irqrestore(&stream->lock, flags); + + // thread_wait(); + + // spin_lock_irqsave(&stream->lock); + // left_space = sound_pcm_left_space(stream); + // } + // dst = pcm->buf + stream->host_ptr; + // size = MIN(left_space, left_size); + // size = MIN(size, pcm->buffer_bytes - stream->host_ptr); + // spin_unlock_irqrestore(&stream->lock, flags); + + // count = size / stream->frame_bytes; + // if (stream->user_mode == PCM_MODE_INTERLEAVED) { + // sound_pcm_copy_interleaved(stream, dst, src, count); + // } else { + // sound_pcm_copy_noninterleaved(stream, dst, src, count); + // } + // src += size; + // left_space -= size; + // left_size -= size; + // writed += count; + + // flags = spin_lock_irqsave(&stream->lock); + // stream->host_ptr += size; + + // if (stream->host_ptr >= pcm->buffer_bytes) { + // stream->host_ptr -= pcm->buffer_bytes; + // stream->host_ptr_base += pcm->buffer_bytes; + // if (stream->host_ptr_base > pcm->boundary) { + // stream->host_ptr_base = 0; + // } + // } + // } + // if (writed > 0) { + // if ((pcm->status == PCM_STATUS_PREPARED || + // pcm->status == PCM_STATUS_PAUSED)) { + // if (sound_pcm_left_space(stream) >= stream->start_threshold) { + // stream->ops->trigger(stream, PCM_TRIGGER_START); + // pcm->status = PCM_STATUS_RUNNING; + // } + // } + // int position = stream->host_ptr; + // position -= position % stream->period_bytes; + // stream->host_period_ptr = stream->host_ptr_base + position; + // } + // spin_unlock_irqrestore(&stream->lock, flags); + // if (writed < frame_count) { return DRIVER_RESULT_BUSY; }; + + // return DRIVER_RESULT_OK; +} + DriverResult sound_pcm_prepare(PcmStream *stream) { PcmDevice *pcm = stream->pcm; pcm->current_stream = stream; diff --git a/src/fs/fat/cluster.c b/src/fs/fat/cluster.c index d1b2bd5..caff24c 100644 --- a/src/fs/fat/cluster.c +++ b/src/fs/fat/cluster.c @@ -255,7 +255,6 @@ uint32_t get_remaining_continuous_clusters( uint32_t current = cur_cluster->cluster; ClusterSegment *seg = &((ClusterSegment *)cur_cluster->block->data)[cur_cluster->offset]; - // TODO:获取下一个簇段 if (seg->end == current) { FsResult result = fat_cluster_list_get_next( fat_info, cur_cluster->entry, cur_cluster); diff --git a/src/kernel/dma.c b/src/kernel/dma.c index ee83c9f..a6d57d3 100644 --- a/src/kernel/dma.c +++ b/src/kernel/dma.c @@ -16,7 +16,6 @@ DriverResult dma_split_mem( size_t seg_start_vaddr; size_t page_addr; - // TODO:未对齐的页 for (; addr < end_addr; addr += tmp_size) { phy_addr = vir2phy(addr); page_addr = phy_addr & ~(PAGE_SIZE - 1); diff --git a/src/kernel/driver.c b/src/kernel/driver.c index e618363..981d073 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -195,8 +195,6 @@ void driver_start_thread(void *arg) { thread_wait_children(cur); } -// TODO:PCI检测完设备后,设备有概率未初始化直接结束 - DriverResult driver_start_all(void) { Driver *driver; diff --git a/src/kernel/main.c b/src/kernel/main.c index e27a1a4..956237f 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -78,34 +78,27 @@ void thread_play(void *arg) { ObjectHandle *handle = object_handle_create(file); PcmDevice *pcm; PcmStream *stream; - // sound_pcm_open(object, SOUND_DEVICE_MODE_PLAY, &pcm, &stream); - // sound_pcm_alloc(stream); - // pcm_set_sample_rate(pcm, 44100); - // pcm_set_channel(stream, 2); - // sound_pcm_set_frame_count(stream, 4 * 1024); - // sound_pcm_prepare(stream); - ObjectAttr attr; + sound_pcm_open(object, SOUND_DEVICE_MODE_PLAY, &pcm, &stream); + sound_pcm_alloc(stream); + pcm_set_sample_rate(pcm, 44100); + pcm_set_channel(stream, 2); + sound_pcm_set_frame_count(stream, 4 * 1024); + sound_pcm_prepare(stream); + ObjectAttr attr; obj_get_attr(file, &attr); - size_t count = 2 * 64; - size_t size = 4 * 1024 * 1024; + size_t count = 16 * 64; + size_t size = 18 * 1024 * 1024; uint8_t *buf = kmalloc(19 * 1024 * 1024); - uint32_t t0, t1; for (int i = 0; i < size / 1024 / 1024; i++) { - t0 = timer_get_counter(); TransferResult result = TRANSFER_IN_STREAM( file, handle, buf + i * 1024 * 1024, 1024 * 1024); if (result != TRANSFER_OK) { printk("Transfer Error!\n"); thread_exit(); } - t1 = timer_get_counter(); - printk("%d KB/s", 1024 * 1000 / (t1 - t0)); } for (int i = 0; i < count; i++) { - // io_cli(); - printk("%d ", i); - // io_sti(); - // sound_pcm_write(stream, buf, 4 * 1024); + sound_pcm_write(stream, buf, 4 * 1024); buf += 16 * 1024; } } @@ -147,7 +140,7 @@ int main() { do_initcalls(); driver_start_all(); - thread_start("play", 100, thread_play, NULL, NULL); + // thread_start("play", 100, thread_play, NULL, NULL); // const string_t name = STRING_INIT("A folder"); // obj_rmdir(object, name); From f2b9b832ef37f80c14f71b3719c44180d5c9a594 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 30 Mar 2025 21:37:53 +0800 Subject: [PATCH 048/158] =?UTF-8?q?=E5=88=A0=E9=99=A4=20=E6=97=A7=E7=9A=84?= =?UTF-8?q?sb16=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/sound/sb16.c | 233 ------------------------------ 1 file changed, 233 deletions(-) delete mode 100644 src/arch/x86/drivers/sound/sb16.c diff --git a/src/arch/x86/drivers/sound/sb16.c b/src/arch/x86/drivers/sound/sb16.c deleted file mode 100644 index f0ada53..0000000 --- a/src/arch/x86/drivers/sound/sb16.c +++ /dev/null @@ -1,233 +0,0 @@ -/** - * @file sb16.c - * @author Ryan Wang (ryan1202@foxmail.com) - * @brief Sound Blaster 16驱动 - * @version 0.1 - * @date 2022-07-22 - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SB16_DSP_MIXER 0x224 -#define SB16_DSP_MIXER_DATA 0x225 -#define SB16_DSP_RESET 0x226 -#define SB16_DSP_READ 0x22a -#define SB16_DSP_WRITE 0x22c -#define SB16_DSP_READ_STATUS 0x22e -#define SB16_DESP_IACK16 0x22f - -#define SB16_CMD_SET_TIME_CONSTANT 0x40 -#define SB16_CMD_SET_OUTPUT_SAMPLE_RATE 0x41 -#define SB16_CMD_TURN_SPEAKER_ON 0xd1 -#define SB16_CMD_TURN_SPEAKER_OFF 0xd3 -#define SB16_CMD_STOP_PLAY8 0xd0 -#define SB16_CMD_RESUME_PLAY8 0xd4 -#define SB16_CMD_STOP_PLAY16 0xd5 -#define SB16_CMD_RESUME_PLAY16 0xd6 -#define SB16_CMD_GET_DSP_VERSION 0xe1 - -#define SB16_CMD_SET_VOLUME 0x22 -#define SB16_CMD_SET_IRQ 0x80 - -#define SB16_IRQ 0x05 - -static status_t sb16_enter(driver_t *drv_obj); -static status_t sb16_exit(driver_t *drv_obj); -status_t sb16_open(device_t *device); -status_t sb16_close(device_t *device); -status_t sb16_write(device_t *dev, uint8_t *buf, uint32_t offset, size_t size); - -#define DRV_NAME "Sound Blaster 16 Driver" -#define DEV_NAME "sb16" - -#define DMA_MAX 4 -uint32_t data_len[DMA_MAX]; - -driver_func_t sb16_driver = { - .driver_enter = sb16_enter, - .driver_exit = sb16_exit, - .driver_open = sb16_open, - .driver_close = sb16_close, - .driver_read = NULL, - .driver_write = sb16_write, - .driver_devctl = NULL}; - -typedef struct { - int major_ver, minor_ver; - int index_r, index_w; - spinlock_t lock; - wait_queue_manager_t *wqm; -} device_extension_t; - -void sb16_request(device_extension_t *devext); -void sb16_dma_config(uint8_t channel, uint32_t addr, uint32_t length); -void dsp_write(uint8_t value); -uint8_t dsp_read(); -status_t dsp_reset(void); -void sb16_set_sample_rate(uint16_t samplerate); - -void sb16_handler(device_t *devobj, int irq) { - device_extension_t *devext = devobj->device_extension; - dsp_write(SB16_CMD_STOP_PLAY16); - io_in8(SB16_DSP_READ_STATUS); - if (devext->major_ver >= 4) { io_in8(SB16_DESP_IACK16); } - devext->index_r = (devext->index_r + 1) % DMA_MAX; - - wait_queue_wakeup(devext->wqm); - - if (devext->index_r != devext->index_w) { sb16_request(devext); } - return; -} - -static status_t sb16_enter(driver_t *drv_obj) { - device_t *devobj; - device_extension_t *devext; - - device_create( - drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_SOUND, &devobj); - if (devobj == NULL) { - device_delete(devobj); - return FAILED; - } - devext = devobj->device_extension; - - spinlock_init(&devext->lock); - devext->wqm = create_wait_queue(); - wait_queue_init(devext->wqm); - - devext->index_r = devext->index_w = 0; - memset((void *)0x800000, 0, 0x10000); - memset((void *)0x810000, 0, 0x10000); - memset((void *)0x820000, 0, 0x10000); - memset((void *)0x830000, 0, 0x10000); - - // 复位DSP - if (dsp_reset() != SUCCUESS) { - device_delete(devobj); - return FAILED; - } - - // 获取DSP版本 - dsp_write(SB16_CMD_GET_DSP_VERSION); - devext->major_ver = dsp_read(); - devext->minor_ver = dsp_read(); - printk("[SB16]DSP Version:%d.%d\n", devext->major_ver, devext->minor_ver); - - // 设置采样率 - sb16_set_sample_rate(44100); - - device_register_irq(devobj, SB16_IRQ, sb16_handler); - return SUCCUESS; -} - -void sb16_dma_config(uint8_t channel, uint32_t addr, uint32_t length) { - dma_disable(channel); - dma_ff_reset(channel); - dma_set_mode(channel, 0x58); - dma_set_page(channel, addr >> 16); - dma_set_addr(channel, addr); - dma_set_count(channel, length); - dma_enable(channel); -} - -void dsp_write(uint8_t value) { - while (io_in8(SB16_DSP_WRITE) & 0x80) - ; - io_out8(SB16_DSP_WRITE, value); -} - -uint8_t dsp_read() { - while (!(io_in8(SB16_DSP_READ_STATUS) & 0x80)) - ; - return io_in8(SB16_DSP_READ); -} - -void sb16_set_sample_rate(uint16_t samplerate) { - dsp_write(SB16_CMD_SET_OUTPUT_SAMPLE_RATE); - dsp_write((uint8_t)(samplerate >> 8)); - dsp_write((uint8_t)samplerate); -} - -status_t dsp_reset(void) { - io_out8(SB16_DSP_RESET, 1); - // TODO: Delay - // delay(1); - io_out8(SB16_DSP_RESET, 0); - - int data = dsp_read(); - if (data != 0xaa) { - printk(COLOR_RED "[SB16]Reset Failed!\n"); - return FAILED; - } - return SUCCUESS; -} - -status_t sb16_open(device_t *device) { - memset(data_len, 0, DMA_MAX * sizeof(uint32_t)); - return SUCCUESS; -} - -status_t sb16_close(device_t *device) { - return SUCCUESS; -} - -void sb16_request(device_extension_t *devext) { - int length = data_len[devext->index_r]; - if (devext->index_r == devext->index_w) { return; } - - sb16_dma_config( - 0x05, (uint32_t)(0x800000 + devext->index_r * 0x10000), - data_len[devext->index_r]); - uint16_t sample_count = length / sizeof(int16_t) / 2 - 1; - - dsp_write(0xb0); - dsp_write(0x30); - dsp_write((uint8_t)sample_count); - dsp_write((uint8_t)(sample_count >> 8)); -} - -status_t sb16_write(device_t *dev, uint8_t *buf, uint32_t offset, size_t size) { - if (size > 64 * 1024) { return FAILED; } - device_extension_t *devext = dev->device_extension; - while ((devext->index_w + 1) % DMA_MAX == devext->index_r) { - wait_queue_add(devext->wqm, 0); - thread_block(TASK_INTERRUPTIBLE); - } - uint8_t *dma_mem = (uint8_t *)(0x800000 + devext->index_w * 0x10000); - memcpy(dma_mem, buf, size); - data_len[devext->index_w] = size; - if (devext->index_r == devext->index_w) { - devext->index_w = (devext->index_w + 1) % DMA_MAX; - sb16_request(devext); - } else { - devext->index_w = (devext->index_w + 1) % DMA_MAX; - } - - return SUCCUESS; -} - -static status_t sb16_exit(driver_t *drv_obj) { - device_t *devobj, *next; - list_for_each_owner_safe (devobj, next, &drv_obj->device_list, list) { - device_delete(devobj); - } - string_del(&drv_obj->name); - return SUCCUESS; -} - -static __init void sb16_driver_entry(void) { - if (driver_create(sb16_driver, DRV_NAME) < 0) { - printk(COLOR_RED "[driver] %s driver create failed!\n", __func__); - } -} - -driver_initcall(sb16_driver_entry); \ No newline at end of file From 651422afe07d646bc85feee74a725b7f7cc6a296 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 30 Mar 2025 21:43:55 +0800 Subject: [PATCH 049/158] =?UTF-8?q?=E5=88=A0=E9=99=A4=20vfs.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fs/vfs.c | 168 --------------------------------------------------- 1 file changed, 168 deletions(-) delete mode 100644 src/fs/vfs.c diff --git a/src/fs/vfs.c b/src/fs/vfs.c deleted file mode 100644 index 2f5c704..0000000 --- a/src/fs/vfs.c +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include -#include -#include - -struct index_node *root; - -struct index_node *vfs_mkdir(char *path) { - int length = strlen(path) - 1; - char *name = kmalloc(length); - strcpy(name, path); - if (name[length] == '/') name[length] = 0, length--; - while (name[length] != '/') - length--; - length++; - name += length; - path[length] = 0; - struct index_node *parent = vfs_opendir(path), *inode; - inode = kmalloc(sizeof(struct index_node)); - memset(inode, 0, sizeof(struct index_node)); - inode->attribute = ATTR_DIR; - inode->parent = parent; - list_add_tail(&inode->list, &parent->childs); - inode->create_date.year = inode->write_date.year = inode->last_access_date.year = - BCD2BIN(CMOS_READ(CMOS_YEAR)); - inode->create_date.month = inode->write_date.month = inode->last_access_date.month = - BCD2BIN(CMOS_READ(CMOS_MONTH)); - inode->create_date.day = inode->write_date.day = inode->last_access_date.day = - BCD2BIN(CMOS_READ(CMOS_DAY_OF_MONTH)); - inode->create_time.hour = inode->write_time.hour = inode->last_access_time.hour = - BCD2BIN(CMOS_READ(CMOS_HOURS)); - inode->create_time.minute = inode->write_time.minute = inode->last_access_time.minute = - BCD2BIN(CMOS_READ(CMOS_MINUTES)); - inode->create_time.second = inode->write_time.second = inode->last_access_time.second = - BCD2BIN(CMOS_READ(CMOS_SECONDS)); - - string_init(&inode->name); - string_new(&inode->name, name, strlen(name)); - list_init(&inode->childs); - return inode; -} - -void vfs_rm(struct index_node *inode) { - struct index_node *child, *next; - string_del(&inode->name); - if (!list_empty(&inode->childs)) { - list_for_each_owner_safe (child, next, &inode->childs, childs) { - vfs_rm(child); - } - } - list_del(&inode->list); - kfree(inode); -} - -void vfs_rename(struct index_node *inode, char *name) { - string_del(&inode->name); - string_new(&inode->name, name, strlen(name)); -} - -/* - * 函数名: vfs_find - * 描述: 找到并返回目录的inode - * 参数: - * @parent 目录的父目录 - * @name 目录的名称 - * 返回: inode 找到目录 - * NULL 找不到目录 - */ -struct index_node *vfs_find(struct index_node *parent, char *name) { - struct index_node *inode, *next; - list_for_each_owner_safe (inode, next, &parent->childs, list) { - if (strcmp(name, inode->name.text) == 0) { - if (inode->attribute == ATTR_DIR) { return inode; } - } - } - return NULL; -} - -struct index_node *vfs_open(char *path) { - struct index_node *inode = root, *tmp; - - char *name = kmalloc(strlen(path)), *p; - strcpy(name, path); - p = name; - int length; - if (*path != '/') return NULL; // 绝对路径以"/"开始 - else if (path[1] == '\0') { return root; } - p++; - while (*path != '\0') { - length = 0; - while (p[length] != '/' && p[length] != '\0') - length++; - p[length] = 0; - tmp = vfs_find(inode, p); - if (tmp == NULL) break; - else inode = tmp; - p += length + 1; - } - struct index_node *cur, *next; - list_for_each_owner_safe (cur, next, &inode->childs, list) { - if (strcmp(p, cur->name.text) == 0) { - if (cur->attribute != ATTR_DIR) { return cur; } - } - } - return NULL; -} - -void vfs_close(struct index_node *inode) { - if (inode->attribute == ATTR_FILE) { - fs_close(inode); - string_del(&inode->name); - list_del(&inode->list); - kfree(inode); - } -} - -struct index_node *vfs_opendir(char *path) { - struct index_node *inode = root; - int l = strlen(path); - char *name = kmalloc(l), *p; - strcpy(name, path); - p = name; - int length; - if (*path != '/') return NULL; // 绝对路径以"/"开始 - else if (path[1] == '\0') { return root; } - p++; - while (*path != '\0') { - length = 0; - while (p[length] != '/' && p[length] != '\0') - length++; - p[length] = 0; - inode = vfs_find(inode, p); - if (inode == NULL) return NULL; - if (p + length >= name + l && inode->attribute == ATTR_DIR) { return inode; } - p += length + 1; - } - return NULL; -} - -struct index_node *vfs_create(char *name, inode_attr_t attr, struct index_node *parent) { - struct index_node *inode = kmalloc(sizeof(struct index_node)); - list_init(&inode->childs); - string_init(&inode->name); - string_new(&inode->name, name, strlen(name)); - inode->attribute = attr; - inode->parent = parent; - if (parent != NULL) list_add_tail(&inode->list, &parent->childs); - return inode; -} - -void vfs_delete(struct index_node *inode) { - string_del(&inode->name); - list_del(&inode->list); - kfree(inode); -} - -void init_vfs(void) { - // 根目录作为名称为""的文件夹初始化 - root = kmalloc(sizeof(struct index_node)); - memset(root, 0, sizeof(struct index_node)); - root->attribute = ATTR_DIR; - - string_init(&root->name); - string_new(&root->name, "", strlen("")); - list_init(&root->childs); - - dev = vfs_mkdir("/dev/"); -} \ No newline at end of file From f4ee10a66aa10e79d36a9c1a05961316861fa2c4 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 18 Apr 2025 23:21:29 +0800 Subject: [PATCH 050/158] =?UTF-8?q?=E6=96=B0=E5=A2=9E=2016=E4=BD=8D?= =?UTF-8?q?=E5=AE=9E=E6=A8=A1=E5=BC=8FBIOS=E4=B8=AD=E6=96=AD=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E9=83=A8=E5=88=86=E6=A8=A1=E6=8B=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 1 - src/arch/x86/Makefile | 3 +- src/arch/x86/bios_emu/Makefile | 7 + src/arch/x86/bios_emu/bios_emu.c | 61 + src/arch/x86/bios_emu/decode.c | 593 ++++++++ src/arch/x86/bios_emu/includes/alu.h | 116 ++ src/arch/x86/bios_emu/includes/conditions.h | 8 + src/arch/x86/bios_emu/includes/decode.h | 79 + src/arch/x86/bios_emu/includes/flags.h | 25 + .../x86/bios_emu/includes/instructions_1.h | 278 ++++ .../x86/bios_emu/includes/instructions_2.h | 80 + src/arch/x86/bios_emu/includes/mod_rm.h | 180 +++ src/arch/x86/bios_emu/includes/operations.h | 139 ++ src/arch/x86/bios_emu/includes/prefix.h | 20 + src/arch/x86/bios_emu/includes/segment.h | 13 + src/arch/x86/bios_emu/includes/stack.h | 73 + src/arch/x86/bios_emu/mod_rm.c | 135 ++ src/arch/x86/bios_emu/operations.c | 482 ++++++ src/arch/x86/bios_emu/ops/Makefile | 10 + src/arch/x86/bios_emu/ops/alu.c | 1303 +++++++++++++++++ src/arch/x86/bios_emu/ops/bt.c | 76 + src/arch/x86/bios_emu/ops/call.c | 216 +++ src/arch/x86/bios_emu/ops/conditions.c | 98 ++ src/arch/x86/bios_emu/ops/int.c | 71 + src/arch/x86/bios_emu/ops/jmp.c | 117 ++ src/arch/x86/bios_emu/ops/mov.c | 275 ++++ src/arch/x86/bios_emu/ops/segment.c | 38 + src/arch/x86/bios_emu/ops/stack.c | 126 ++ src/arch/x86/bios_emu/ops/xchg.c | 31 + src/arch/x86/bios_emu/segment.c | 21 + src/arch/x86/bios_emu/todo.md | 205 +++ src/arch/x86/include/bios_emu/bios_emu.h | 13 + src/arch/x86/include/bios_emu/environment.h | 66 + src/arch/x86/include/bios_emu/exceptions.h | 31 + src/arch/x86/kernel/platform.c | 3 + src/include/bits.h | 6 +- src/kernel/main.c | 17 + 37 files changed, 5011 insertions(+), 5 deletions(-) create mode 100644 src/arch/x86/bios_emu/Makefile create mode 100644 src/arch/x86/bios_emu/bios_emu.c create mode 100644 src/arch/x86/bios_emu/decode.c create mode 100644 src/arch/x86/bios_emu/includes/alu.h create mode 100644 src/arch/x86/bios_emu/includes/conditions.h create mode 100644 src/arch/x86/bios_emu/includes/decode.h create mode 100644 src/arch/x86/bios_emu/includes/flags.h create mode 100644 src/arch/x86/bios_emu/includes/instructions_1.h create mode 100644 src/arch/x86/bios_emu/includes/instructions_2.h create mode 100644 src/arch/x86/bios_emu/includes/mod_rm.h create mode 100644 src/arch/x86/bios_emu/includes/operations.h create mode 100644 src/arch/x86/bios_emu/includes/prefix.h create mode 100644 src/arch/x86/bios_emu/includes/segment.h create mode 100644 src/arch/x86/bios_emu/includes/stack.h create mode 100644 src/arch/x86/bios_emu/mod_rm.c create mode 100644 src/arch/x86/bios_emu/operations.c create mode 100644 src/arch/x86/bios_emu/ops/Makefile create mode 100644 src/arch/x86/bios_emu/ops/alu.c create mode 100644 src/arch/x86/bios_emu/ops/bt.c create mode 100644 src/arch/x86/bios_emu/ops/call.c create mode 100644 src/arch/x86/bios_emu/ops/conditions.c create mode 100644 src/arch/x86/bios_emu/ops/int.c create mode 100644 src/arch/x86/bios_emu/ops/jmp.c create mode 100644 src/arch/x86/bios_emu/ops/mov.c create mode 100644 src/arch/x86/bios_emu/ops/segment.c create mode 100644 src/arch/x86/bios_emu/ops/stack.c create mode 100644 src/arch/x86/bios_emu/ops/xchg.c create mode 100644 src/arch/x86/bios_emu/segment.c create mode 100644 src/arch/x86/bios_emu/todo.md create mode 100644 src/arch/x86/include/bios_emu/bios_emu.h create mode 100644 src/arch/x86/include/bios_emu/environment.h create mode 100644 src/arch/x86/include/bios_emu/exceptions.h diff --git a/Makefile b/Makefile index 9b1d1e9..042b13b 100644 --- a/Makefile +++ b/Makefile @@ -97,7 +97,6 @@ qemu_dbg: -usb \ -device usb-kbd \ -device usb-mouse \ - -audio pa,model=sb16 \ -device rtl8139,netdev=nc1 \ -netdev user,id=nc1,hostfwd=tcp::5555-:80 \ -object filter-dump,id=f1,netdev=nc1,file=dump.dat \ diff --git a/src/arch/x86/Makefile b/src/arch/x86/Makefile index 612ba6f..f73291b 100644 --- a/src/arch/x86/Makefile +++ b/src/arch/x86/Makefile @@ -1,3 +1,4 @@ SRC += multiboot2/ SRC += kernel/ -SRC += drivers/ \ No newline at end of file +SRC += drivers/ +SRC += bios_emu/ \ No newline at end of file diff --git a/src/arch/x86/bios_emu/Makefile b/src/arch/x86/bios_emu/Makefile new file mode 100644 index 0000000..2a3507e --- /dev/null +++ b/src/arch/x86/bios_emu/Makefile @@ -0,0 +1,7 @@ +SRC += bios_emu.c +SRC += int.c +SRC += decode.c +SRC += mod_rm.c +SRC += operations.c +SRC += ops/ +SRC += segment.c \ No newline at end of file diff --git a/src/arch/x86/bios_emu/bios_emu.c b/src/arch/x86/bios_emu/bios_emu.c new file mode 100644 index 0000000..cc2f6bc --- /dev/null +++ b/src/arch/x86/bios_emu/bios_emu.c @@ -0,0 +1,61 @@ +#include "includes/stack.h" +#include +#include +#include +#include + +BiosEmuEnvironment bios_emu_env; + +#define INIT_LUT(env, arr, reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7) \ + arr[0] = &env->regs.reg0; \ + arr[1] = &env->regs.reg1; \ + arr[2] = &env->regs.reg2; \ + arr[3] = &env->regs.reg3; \ + arr[4] = &env->regs.reg4; \ + arr[5] = &env->regs.reg5; \ + arr[6] = &env->regs.reg6; \ + arr[7] = &env->regs.reg7; + +#define INIT_LUT_R8(env) \ + INIT_LUT(env, env->reg_lut_r8, al, cl, dl, bl, ah, ch, dh, bh); + +#define INIT_LUT_R16(env) \ + INIT_LUT(env, env->reg_lut_r16, ax, cx, dx, bx, sp, bp, si, di); + +#define INIT_LUT_R32(env) \ + INIT_LUT(env, env->reg_lut_r32, eax, ecx, edx, ebx, esp, ebp, esi, edi); + +void bios_emu_init(void) { + BiosEmuEnvironment *env = &bios_emu_env; + env->regs.cs = 0x0000; + env->regs.ds = 0x0000; + env->regs.es = 0x0000; + env->regs.fs = 0x0000; + env->regs.gs = 0x0000; + env->regs.eip = 0x0000; + env->regs.eflags = io_load_eflags(); + + env->regs.eax = 0; + env->regs.ebx = 0; + env->regs.ecx = 0; + env->regs.edx = 0; + env->regs.esi = 0; + env->regs.edi = 0; + env->regs.ebp = 0; + env->regs.esp = 0x7c00; + + env->default_ss = &env->regs.ds; + env->ivt = (void *)0x0000; + env->cur_ip = 0; + env->stack_bottom = STACK_POINTER16(env) - 0x2000; + + env->flags.stack_size = 0; + env->flags.operand_size = 0; + env->flags.default_operand_size = 0; + env->flags.address_size = 0; + env->flags.default_address_size = 0; + + INIT_LUT_R8(env); + INIT_LUT_R16(env); + INIT_LUT_R32(env); +} \ No newline at end of file diff --git a/src/arch/x86/bios_emu/decode.c b/src/arch/x86/bios_emu/decode.c new file mode 100644 index 0000000..00ead41 --- /dev/null +++ b/src/arch/x86/bios_emu/decode.c @@ -0,0 +1,593 @@ +#include "includes/decode.h" +#include "includes/alu.h" +#include "includes/conditions.h" +#include "includes/instructions_1.h" +#include "includes/instructions_2.h" +#include "includes/mod_rm.h" +#include "includes/operations.h" +#include "includes/prefix.h" +#include "includes/stack.h" +#include "kernel/func.h" +#include +#include +#include +#include + +BiosEmuExceptions decode_rm8_r8(BiosEmuEnvironment *env, Op2_8_8 func) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + uint8_t *rm = RM_ADDR(env, modrm); + uint8_t *r8 = env->reg_lut_r8[reg]; + + return func(env, rm, r8); +} + +BiosEmuExceptions decode_rm_r( + BiosEmuEnvironment *env, Op2_16_16 func16, Op2_32_32 func32) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + void *rm = RM_ADDR(env, modrm); + if (env->flags.operand_size == 0) { + uint16_t *r16 = env->reg_lut_r16[reg]; + return func16(env, rm, r16); + } else { + uint32_t *r32 = env->reg_lut_r32[reg]; + return func32(env, rm, r32); + } +} + +BiosEmuExceptions decode_rm_imm8( + BiosEmuEnvironment *env, Op2_16_16 func16, Op2_32_32 func32) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + + void *rm = RM_ADDR(env, modrm); + uint32_t value = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + if (env->flags.operand_size == 0) { + return func16(env, rm, (uint16_t *)&value); + } else { + return func32(env, rm, &value); + } +} + +BiosEmuExceptions decode_r_rm( + BiosEmuEnvironment *env, Op2_16_16 func16, Op2_32_32 func32) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + if (env->flags.operand_size == 0) { + void *r = env->reg_lut_r16[reg]; + return func16(env, r, RM_ADDR(env, modrm)); + } else { + void *r = env->reg_lut_r32[reg]; + return func32(env, r, RM_ADDR(env, modrm)); + } +} + +BiosEmuExceptions decode_rm_r_imm8( + BiosEmuEnvironment *env, Op3_16_16_8 func16, Op3_32_32_8 func32) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + void *rm = RM_ADDR(env, modrm); + if (env->flags.operand_size == 0) { + uint16_t *r16 = env->reg_lut_r16[reg]; + return func16(env, rm, *r16, *(uint8_t *)env->cur_ip++); + } else { + uint32_t *r32 = env->reg_lut_r32[reg]; + return func32(env, rm, *r32, *(uint8_t *)env->cur_ip++); + } +} + +BiosEmuExceptions decode_rm_r_cl( + BiosEmuEnvironment *env, Op3_16_16_8 func16, Op3_32_32_8 func32) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + void *rm = RM_ADDR(env, modrm); + if (env->flags.operand_size == 0) { + uint16_t *r16 = env->reg_lut_r16[reg]; + return func16(env, rm, *r16, env->regs.cl); + } else { + uint32_t *r32 = env->reg_lut_r32[reg]; + return func32(env, rm, *r32, env->regs.cl); + } +} + +BiosEmuExceptions decode_two_bytes_opcode(BiosEmuEnvironment *env) { + TwoBytesOpcodes *opcode = env->cur_ip; + env->cur_ip++; + env->regs.eip++; + switch ((uint8_t)*opcode) { + case OP_BT: + decode_rm_r(env, bt_16_16, bt_32_32); + break; + case OP_BTC: + decode_rm_r(env, btc_16_16, btc_32_32); + break; + case OP_BTR: + decode_rm_r(env, btr_16_16, btr_32_32); + break; + case OP_BTS: + decode_rm_r(env, bts_16_16, bts_32_32); + break; + case 0xba: + decode_0xba(env); + break; + case OP_IMUL_r_rm: + decode_imul_r_rm(env); + break; + case OP_Jcc ...(OP_Jcc + 15): + decode_jcc(env, condition_table[*opcode & 0x0f](env)); + break; + case OP_MOVZX_r_rm8: + decode_movzx_r_rm8(env); + break; + case OP_MOVZX_r_rm16: + decode_movzx_r_rm16(env); + break; + case OP_MOVSX_r_rm8: + decode_movsx_r_rm8(env); + break; + case OP_MOVSX_r_rm16: + decode_movsx_r_rm16(env); + break; + case OP_PUSH_FS: + PUSH_SREG(env, fs); + break; + case OP_PUSH_GS: + PUSH_SREG(env, gs); + break; + case OP_POP_FS: + POP_SREG(env, fs); + break; + case OP_POP_GS: + POP_SREG(env, gs); + break; + case OP_SETcc ...(OP_SETcc + 15): + decode_setcc(env, condition_table[*opcode & 0x0f](env)); + break; + case OP_SHLD_imm8: + decode_rm_r_imm8(env, shld_16_16_8, shld_32_32_8); + break; + case OP_SHLD_cl: + decode_rm_r_cl(env, shld_16_16_8, shld_32_32_8); + break; + case OP_SHRD_imm8: + decode_rm_r_imm8(env, shrd_16_16_8, shrd_32_32_8); + break; + case OP_SHRD_cl: + decode_rm_r_cl(env, shrd_16_16_8, shrd_32_32_8); + break; + default: + return InvalidOpcode; + } + return NoException; +} + +BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { + BiosEmuExceptions exception = NoException; + OneByteOpcodes *opcode = env->cur_ip; + env->cur_ip++; + env->regs.eip++; + switch ((uint8_t)*opcode) { + case OP_AAA: + decode_aaa(env); + break; + case OP_AAD: + decode_aad(env); + break; + case OP_AAM: + decode_aam(env); + break; + case OP_AAS: + decode_aas(env); + break; + case OP_CALL: + exception = decode_call(env); + break; + case OP_CALL_ptr: + exception = decode_call_ptr(env); + break; + case OP_CBW_CWDE: + decode_cbw_cwde(env); + break; + case OP_CLC: + CLC(env); + break; + case OP_CLD: + CLD(env); + break; + case OP_CLI: + CLI(env); + io_cli(); + break; + case OP_CMC: + CMC(env); + break; + case OP_CWD_CDQ: + decode_cwd_cdq(env); + break; + case OP_DAA: + decode_daa(env); + break; + case OP_DAS: + decode_das(env); + break; + case OP_DEC ...(OP_DEC + 7): + decode_dec_r(env, *opcode); + break; + case OP_IMUL_imm8: + decode_imul_r_rm_imm8(env); + break; + case OP_IMUL_imm16: + decode_imul_r_rm_imm16(env); + break; + case OP_IN8: + decode_in8(env, *(uint8_t *)env->cur_ip); + env->cur_ip++; + env->regs.eip++; + break; + case OP_IN: + decode_in(env, *(uint8_t *)env->cur_ip); + env->cur_ip += 2; + env->regs.eip += 2; + break; + case OP_IN8_dx: + decode_in8(env, env->regs.dx); + break; + case OP_IN_dx: + decode_in(env, env->regs.dx); + break; + case OP_INC ...(OP_INC + 7): + decode_inc_r(env, *opcode); + break; + case OP_INT: + exception = decode_int(env, *(uint8_t *)env->cur_ip++); + break; + case OP_IRET_IRETD: + exception = decode_iret(env); + break; + case OP_JE_JZ_8: + case OP_JG_JNLE_8: + case OP_JGE_JNL_8: + case OP_JL_JNGE_8: + case OP_JLE_JNG_8: + case OP_JBE_JNA_8: + case OP_JB_JC_JNAE_8: + case OP_JAE_JNB_JNC_8: + case OP_JA_JNBE_8: + case OP_JNE_JNZ_8: + case OP_JNO_8: + case OP_JNP_JPO_8: + case OP_JNS_8: + case OP_JO_8: + case OP_JP_JPE_8: + case OP_JS_8: + decode_jcc_8(env, condition_table[*opcode & 0x0f](env)); + break; + case OP_JMP8: + decode_jmp8(env); + break; + case OP_JMP: + decode_jmp(env); + break; + case OP_LongJMP: + decode_long_jmp_ptr16(env); + break; + case OP_LAHF: + LAHF(env); + break; + case OP_LDS: + decode_r_rm(env, lds_16_16, lds_32_32); + break; + case OP_LEA: + decode_lea(env); + break; + case OP_LES: + decode_r_rm(env, les_16_16, les_32_32); + break; + case OP_MOV_rm_r8: + decode_mov_rm_r8(env); + break; + case OP_MOV_rm_r: + decode_mov_rm_r(env); + break; + case OP_MOV_r_rm8: + decode_mov_r_rm_8(env); + break; + case OP_MOV_r_rm: + decode_mov_r_rm(env); + break; + case OP_MOV_rm_sreg: + decode_mov_rm_sreg(env); + break; + case OP_MOV_sreg_rm: + decode_mov_sreg_rm(env); + break; + case OP_MOV_a_moffs8: + decode_mov_r_moffs_8(env); + break; + case OP_MOV_a_moffs: + decode_mov_r_moffs(env); + break; + case OP_MOV_moffs8_a: + decode_mov_moffs_r_8(env); + break; + case OP_MOV_moffs_a: + decode_mov_moffs_r(env); + break; + case OP_MOV_r_imm8 ...(OP_MOV_r_imm8 + 7): + decode_mov_r_imm8(env, *opcode); + break; + case OP_MOV_r_imm ...(OP_MOV_r_imm + 7): + decode_mov_r_imm(env, *opcode); + break; + case OP_MOV_rm_imm8: + decode_mov_rm_imm8(env); + break; + case OP_MOV_rm_imm: + decode_mov_rm_imm(env); + break; + case OP_NOP: + break; + case OP_OUT8: + decode_out8(env, *(uint8_t *)env->cur_ip); + env->cur_ip++; + env->regs.eip++; + break; + case OP_OUT: + decode_out(env, *(uint8_t *)env->cur_ip); + env->cur_ip += 2; + env->regs.eip += 2; + break; + case OP_OUT8_dx: + decode_out8(env, env->regs.dx); + break; + case OP_OUT_dx: + decode_out(env, env->regs.dx); + break; + case OP_POP_rm: + decode_pop_rm(env); + break; + case OP_POP_r ...(OP_POP_r + 7): + decode_pop_r(env, *opcode); + break; + case OP_POP_DS: + POP_SREG(env, ds); + break; + case OP_POP_ES: + POP_SREG(env, es); + break; + case OP_POP_SS: + POP_SREG(env, ss); + break; + case OP_POPA_POPAD: + decode_popa_popad(env); + break; + case OP_POPF_POPFD: + if (env->flags.operand_size == 0) { + POP(env, env->regs.flags, 2); + } else { + POP(env, env->regs.eflags, 4); + } + break; + case OP_PUSH_CS: + PUSH_SREG(env, cs); + break; + case OP_PUSH_SS: + PUSH_SREG(env, ss); + break; + case OP_PUSH_DS: + PUSH_SREG(env, ds); + break; + case OP_PUSH_ES: + PUSH_SREG(env, es); + break; + case OP_PUSH_imm8: + PUSH(env, *(uint8_t *)env->cur_ip, 1); + env->regs.eip++; + break; + case OP_PUSH_imm: + if (env->flags.operand_size == 0) { + PUSH(env, *(uint16_t *)env->cur_ip, 2); + env->regs.eip += 2; + env->cur_ip += 2; + } else { + PUSH(env, *(uint32_t *)env->cur_ip, 4); + env->regs.eip += 4; + env->cur_ip += 4; + } + break; + case OP_PUSH_r ...(OP_PUSH_r + 7): + if (env->flags.operand_size == 0) { + uint16_t *reg = PLUS_RW_REG(env, *opcode); + PUSH(env, *reg, 2); + } else { + uint32_t *reg = PLUS_RD_REG(env, *opcode); + PUSH(env, *reg, 4); + } + break; + case OP_PUSHA_PUSHAD: + decode_pusha_pushad(env); + break; + case OP_PUSHF_PUSHFD: + if (env->flags.operand_size == 0) { + PUSH(env, env->regs.flags, 2); + } else { + PUSH(env, env->regs.eflags & 0x00fcffff, 4); + } + break; + case OP_RET: + exception = decode_ret_near(env, 0); + break; + case OP_LongRET: + exception = decode_ret_far(env, 0); + break; + case OP_RET_imm16: + exception = decode_ret_imm16(env); + break; + case OP_LongRET_imm16: + exception = decode_ret_far_imm16(env); + break; + case OP_SAHF: + SAHF(env); + break; + case OP_STC: + STC(env); + break; + case OP_STD: + STD(env); + break; + case OP_STI: + STI(env); + io_sti(); + break; + case OP_TEST_imm8: + calc_a_imm8(env, CALC_TEST); + break; + case OP_TEST_imm: + calc_a_imm(env, CALC_TEST); + break; + case OP_TEST_rm_r_8: + calc_rm_r_8(env, CALC_TEST); + break; + case OP_TEST_rm_r: + calc_rm_r(env, CALC_TEST); + break; + case (OP_XCHG_r + 1)...(OP_XCHG_r + 7): // XCHG ax, ax机器码与NOP指令相同 + if (env->flags.operand_size == 0) { + uint16_t *reg = PLUS_RW_REG(env, *opcode); + exception = xchg_16_16(env, reg, RM_ADDR(env, *opcode)); + } else { + uint32_t *reg = PLUS_RD_REG(env, *opcode); + exception = xchg_32_32(env, reg, RM_ADDR(env, *opcode)); + } + break; + case OP_XCHG_8: + decode_rm8_r8(env, xchg_8_8); + break; + case OP_XCHG: + decode_rm_r(env, xchg_16_16, xchg_32_32); + break; + ALU_CASE(ADC) + ALU_CASE(ADD) + ALU_CASE(AND) + ALU_CASE(XOR) + ALU_CASE(OR) + ALU_CASE(SBB) + ALU_CASE(SUB) + ALU_CASE(CMP) + case OP_TWO_BYTES: + exception = decode_two_bytes_opcode(env); + break; + case 0x80 ... 0x83: + exception = decode_0x80_0x83(env, *opcode); + break; + case 0xc0: + exception = decode_0xc0(env); + break; + case 0xc1: + exception = decode_0xc1(env); + break; + case 0xd0: + exception = decode_0xd0(env); + break; + case 0xd1: + exception = decode_0xd1(env); + break; + case 0xd2: + exception = decode_0xd2(env); + break; + case 0xd3: + exception = decode_0xd3(env); + break; + case 0xf6: + exception = decode_0xf6(env); + break; + case 0xf7: + exception = decode_0xf7(env); + break; + case 0xfe: + exception = decode_0xfe(env); + break; + case 0xff: + exception = decode_0xff(env); + break; + default: + env->regs.eip--; + env->cur_ip--; + return InvalidOpcode; + } + return exception; +} + +BiosEmuExceptions emu_run_instruction(BiosEmuEnvironment *env) { + BiosEmuPrefixes prefix; + env->default_ss = &env->regs.ds; + env->flags.operand_size = env->flags.default_operand_size; + env->flags.address_size = env->flags.default_address_size; + int flag = 1; + while (flag) { + prefix = *(BiosEmuPrefixes *)env->cur_ip; + env->cur_ip++; + env->regs.eip++; + switch ((uint8_t)prefix) { + case PREFIX_LOCK: + break; + case PREFIX_REPNE_REPNZ_BND: + break; + case PREFIX_REP_REPE_REPZ: + break; + case PREFIX_CS_OVERRIDE_BRANCH_NOT_TAKEN: + env->default_ss = &env->regs.cs; + break; + case PREFIX_SS_OVERRIDE: + env->default_ss = &env->regs.ss; + break; + case PREFIX_DS_OVERRIDE_BRANCH_TAKEN: + env->default_ss = &env->regs.ds; + break; + case PREFIX_ES_OVERRIDE: + env->default_ss = &env->regs.es; + break; + case PREFIX_FS_OVERRIDE: + env->default_ss = &env->regs.fs; + break; + case PREFIX_GS_OVERRIDE: + env->default_ss = &env->regs.gs; + break; + case PREFIX_OPERAND_SIZE_OVERRIDE: + env->flags.operand_size ^= 1; + break; + case PREFIX_ADDRSIZE_OVERRIDE: + env->flags.address_size ^= 1; + break; + default: + env->regs.eip--; + env->cur_ip--; + flag = 0; + break; + } + } + return decode_one_byte_opcode(env); +} + +BiosEmuExceptions emu_run(BiosEmuEnvironment *env) { + BiosEmuExceptions exception = NoException; + + while (exception == NoException) { + exception = emu_run_instruction(env); + if (exception != NoException) { break; } + } + + return exception; +} diff --git a/src/arch/x86/bios_emu/includes/alu.h b/src/arch/x86/bios_emu/includes/alu.h new file mode 100644 index 0000000..0f9c824 --- /dev/null +++ b/src/arch/x86/bios_emu/includes/alu.h @@ -0,0 +1,116 @@ +#ifndef _BIOS_EMU_ALU_H +#define _BIOS_EMU_ALU_H + +#include +#include + +typedef enum { + CALC_ADD = 0, + CALC_ADC, + CALC_AND, + CALC_XOR, + CALC_OR, + CALC_SUB, + CALC_SBB, + CALC_CMP, + CALC_TEST, +} CalcIndex; + +typedef void (*Calc8)(BiosEmuEnvironment *env, uint8_t *dst, uint8_t src); +typedef void (*Calc16)(BiosEmuEnvironment *env, uint16_t *dst, uint16_t src); +typedef void (*Calc32)(BiosEmuEnvironment *env, uint32_t *dst, uint32_t src); + +void calc_a_imm8(BiosEmuEnvironment *env, CalcIndex index); +void calc_a_imm(BiosEmuEnvironment *env, CalcIndex index); +void calc_rm_imm_8(BiosEmuEnvironment *env, CalcIndex index); +void calc_rm_imm(BiosEmuEnvironment *env, CalcIndex index); +void calc_rm_imm8(BiosEmuEnvironment *env, CalcIndex index); +void calc_rm_r_8(BiosEmuEnvironment *env, CalcIndex index); +void calc_rm_r(BiosEmuEnvironment *env, CalcIndex index); +void calc_r_rm_8(BiosEmuEnvironment *env, CalcIndex index); +void calc_r_rm(BiosEmuEnvironment *env, CalcIndex index); + +#define ALU_CASE(name) \ + case OP_##name##_imm8: \ + calc_a_imm8(env, CALC_##name); \ + break; \ + case OP_##name##_imm: \ + calc_a_imm(env, CALC_##name); \ + break; \ + case OP_##name##_rm_r_8: \ + calc_rm_r_8(env, CALC_##name); \ + break; \ + case OP_##name##_rm_r: \ + calc_rm_r(env, CALC_##name); \ + break; \ + case OP_##name##_r_rm_8: \ + calc_r_rm_8(env, CALC_##name); \ + break; \ + case OP_##name##_r_rm: \ + calc_r_rm(env, CALC_##name); \ + break; + +void decode_inc_r(BiosEmuEnvironment *env, uint8_t opcode); +void decode_dec_r(BiosEmuEnvironment *env, uint8_t opcode); +void decode_inc_rm(BiosEmuEnvironment *env); +void decode_dec_rm(BiosEmuEnvironment *env); +void decode_inc_rm8(BiosEmuEnvironment *env); +void decode_dec_rm8(BiosEmuEnvironment *env); + +void decode_aaa(BiosEmuEnvironment *env); +void decode_aad(BiosEmuEnvironment *env); +void decode_aam(BiosEmuEnvironment *env); +void decode_aas(BiosEmuEnvironment *env); +void decode_daa(BiosEmuEnvironment *env); +void decode_das(BiosEmuEnvironment *env); + +BiosEmuExceptions div_8(BiosEmuEnvironment *env, uint8_t value); +BiosEmuExceptions div_16(BiosEmuEnvironment *env, uint16_t value); +BiosEmuExceptions div_32(BiosEmuEnvironment *env, uint32_t value); +BiosEmuExceptions idiv_8(BiosEmuEnvironment *env, uint8_t value); +BiosEmuExceptions idiv_16(BiosEmuEnvironment *env, uint16_t value); +BiosEmuExceptions idiv_32(BiosEmuEnvironment *env, uint32_t value); + +void mul_8(BiosEmuEnvironment *env, uint8_t value); +void mul_16(BiosEmuEnvironment *env, uint16_t value); +void mul_32(BiosEmuEnvironment *env, uint32_t value); +void imul_8(BiosEmuEnvironment *env, uint8_t value); +void imul_16( + BiosEmuEnvironment *env, uint16_t *dst_hi, uint16_t *dst_lo, uint16_t src1, + uint16_t src2); +void imul_32( + BiosEmuEnvironment *env, uint32_t *dst_hi, uint32_t *dst_lo, uint32_t src1, + uint32_t src2); + +void decode_imul_r_rm_imm8(BiosEmuEnvironment *env); +void decode_imul_r_rm_imm16(BiosEmuEnvironment *env); +void decode_imul_r_rm(BiosEmuEnvironment *env); + +void neg_8(BiosEmuEnvironment *env, uint8_t *value); +void neg_16(BiosEmuEnvironment *env, uint16_t *value); +void neg_32(BiosEmuEnvironment *env, uint32_t *value); + +void rcl_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count); +void rcl_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count); +void rcl_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count); +void rcr_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count); +void rcr_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count); +void rcr_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count); +void rol_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count); +void rol_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count); +void rol_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count); +void ror_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count); +void ror_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count); +void ror_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count); + +void shl_sal_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count); +void shl_sal_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count); +void shl_sal_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count); +void shr_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count); +void shr_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count); +void shr_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count); +void sar_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count); +void sar_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count); +void sar_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count); + +#endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/conditions.h b/src/arch/x86/bios_emu/includes/conditions.h new file mode 100644 index 0000000..b4949c1 --- /dev/null +++ b/src/arch/x86/bios_emu/includes/conditions.h @@ -0,0 +1,8 @@ +#ifndef _BIOS_EMU_CONDITIONS_H +#define _BIOS_EMU_CONDITIONS_H + +#include + +extern int (*condition_table[16])(BiosEmuEnvironment *env); + +#endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/decode.h b/src/arch/x86/bios_emu/includes/decode.h new file mode 100644 index 0000000..90a94e1 --- /dev/null +++ b/src/arch/x86/bios_emu/includes/decode.h @@ -0,0 +1,79 @@ +#ifndef _BIOS_EMU_DECODE_H +#define _BIOS_EMU_DECODE_H + +#include +#include +#define PLUS_RB_REG(env, reg) (env)->reg_lut_r8[(reg) & 0x07] + +#define PLUS_RW_REG(env, reg) (env)->reg_lut_r16[(reg) & 0x07] + +#define PLUS_RD_REG(env, reg) (env)->reg_lut_r32[(reg) & 0x07] + +typedef enum OperandNum { + OPNUM_0 = 0, + OPNUM_1, + OPNUM_2, + OPNUM_3, +} OperandNum; + +typedef enum OperandDataType { + OPDT_Byte, + OPDT_Word, + OPDT_Dword, + OPDT_Qword, +} OperandDataType; + +#define DEF_OP1(type) \ + typedef BiosEmuExceptions (*Op1_##type)( \ + BiosEmuEnvironment * env, uint##type##_t * value); + +#define DEF_OP2(type1, type2) \ + typedef BiosEmuExceptions (*Op2_##type1##_##type2)( \ + BiosEmuEnvironment * env, uint##type1##_t * value1, \ + uint##type2##_t * value2); + +#define DEF_OP3_1(type, data_type_1, data_type2, data_type) \ + typedef BiosEmuExceptions (*Op3_##type##data_type)( \ + BiosEmuEnvironment * env, data_type_1 value1, data_type2 value2, \ + uint##data_type##_t value3); + +#define DEF_OP3_2(type, data_type_1, data_type) \ + DEF_OP3_1(type##data_type##_, data_type_1, uint##data_type##_t, 8); \ + DEF_OP3_1(type##data_type##_, data_type_1, uint##data_type##_t, 16); \ + DEF_OP3_1(type##data_type##_, data_type_1, uint##data_type##_t, 32); + +#define DEF_OP3_3(data_type) \ + DEF_OP3_2(data_type##_, uint##data_type##_t *, 8); \ + DEF_OP3_2(data_type##_, uint##data_type##_t *, 16); \ + DEF_OP3_2(data_type##_, uint##data_type##_t *, 32); + +typedef BiosEmuExceptions (*Op0)(BiosEmuEnvironment *env); +DEF_OP1(8); +DEF_OP1(16); +DEF_OP1(32); +DEF_OP2(8, 8); +DEF_OP2(8, 16); +DEF_OP2(8, 32); +DEF_OP2(16, 8); +DEF_OP2(16, 16); +DEF_OP2(16, 32); +DEF_OP2(32, 8); +DEF_OP2(32, 16); +DEF_OP2(32, 32); +DEF_OP3_3(8); +DEF_OP3_3(16); +DEF_OP3_3(32); + +BiosEmuExceptions decode_rm8_r8(BiosEmuEnvironment *env, Op2_8_8 func); +BiosEmuExceptions decode_rm_r( + BiosEmuEnvironment *env, Op2_16_16 func16, Op2_32_32 func32); +BiosEmuExceptions decode_rm_imm8( + BiosEmuEnvironment *env, Op2_16_16 func16, Op2_32_32 func32); +BiosEmuExceptions decode_r_rm( + BiosEmuEnvironment *env, Op2_16_16 func16, Op2_32_32 func32); +BiosEmuExceptions decode_rm_r_imm8( + BiosEmuEnvironment *env, Op3_16_16_8 func16, Op3_32_32_8 func32); +BiosEmuExceptions decode_rm_r_cl( + BiosEmuEnvironment *env, Op3_16_16_8 func16, Op3_32_32_8 func32); + +#endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/flags.h b/src/arch/x86/bios_emu/includes/flags.h new file mode 100644 index 0000000..6fd53fa --- /dev/null +++ b/src/arch/x86/bios_emu/includes/flags.h @@ -0,0 +1,25 @@ +#ifndef _BIOS_EMU_FLAGS_H +#define _BIOS_EMU_FLAGS_H + +#include + +#define CarryFlagBit 0 +#define ParityFlagBit 2 +#define AuxiliaryCarryFlagBit 4 +#define ZeroFlagBit 6 +#define SignFlagBit 7 +#define TrapFlagBit 8 +#define InterruptEnableFlagBit 9 +#define DirectionFlagBit 10 +#define OverflowFlagBit 11 +#define IOPLFlagBit 12 +#define NestedTaskFlagBit 14 + +#define ResumeFlagBit 16 +#define VirtualModeFlagBit 17 +#define AlignmentCheckFlagBit 18 +#define VirtualInterruptFlagBit 19 +#define VirtualInterruptPendingFlagBit 20 +#define IDFlagBit 21 + +#endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/instructions_1.h b/src/arch/x86/bios_emu/includes/instructions_1.h new file mode 100644 index 0000000..c400b95 --- /dev/null +++ b/src/arch/x86/bios_emu/includes/instructions_1.h @@ -0,0 +1,278 @@ +#ifndef _BIOS_EMU_INSTRUCTIONS_1_H +#define _BIOS_EMU_INSTRUCTIONS_1_H + +typedef enum OneByteOpcodes { + // One Byte Opcode Instructions A-L + OP_AAA = 0x37, + OP_AAD = 0xD5, + OP_AAM = 0xD4, + OP_AAS = 0x3F, + + OP_ADC_imm8 = 0x14, + OP_ADC_imm = 0x15, + OP_ADC_rm_r_8 = 0x10, + OP_ADC_rm_r = 0x11, + OP_ADC_r_rm_8 = 0x12, + OP_ADC_r_rm = 0x13, + + OP_ADC_ADD_rm_imm_8 = 0x80, + OP_ADC_ADD_rm_imm = 0x81, + OP_ADC_ADD_rm_imm8 = 0x83, + + OP_ADD_imm8 = 0x04, + OP_ADD_imm = 0x05, + OP_ADD_rm_r_8 = 0x00, + OP_ADD_rm_r = 0x01, + OP_ADD_r_rm_8 = 0x02, + OP_ADD_r_rm = 0x03, + + OP_AND_imm8 = 0x24, + OP_AND_imm = 0x25, + OP_AND_rm_r_8 = 0x20, + OP_AND_rm_r = 0x21, + OP_AND_r_rm_8 = 0x22, + OP_AND_r_rm = 0x23, + + OP_BOUND = 0x62, + OP_CALL = 0xE8, + OP_CALL_ptr = 0x9A, + OP_CBW_CWDE = 0x98, + OP_CLC = 0xF8, + OP_CLD = 0xFC, + OP_CLI = 0xFA, + OP_CMC = 0xF5, + + OP_CMP_imm8 = 0x3c, + OP_CMP_imm = 0x3d, + OP_CMP_rm_r_8 = 0x38, + OP_CMP_rm_r = 0x39, + OP_CMP_r_rm_8 = 0x3A, + OP_CMP_r_rm = 0x3B, + + OP_CMPS8 = 0xA6, + OP_CMPS = 0xA7, + OP_CWD_CDQ = 0x99, + OP_DAA = 0x27, + OP_DAS = 0x2F, + + OP_DEC8 = 0xFE, + OP_DEC_rm = 0xFF, + OP_DEC = 0x48, + + OP_DIV8 = 0xF6, + OP_DIV = 0xF6, + + OP_ENTER = 0xC8, + OP_HLT = 0xF4, + + OP_IDIV8 = 0xF6, + OP_IDIV = 0xF7, + + OP_IMUL8 = 0xF6, + OP_IMUL = 0xF7, + OP_IMUL_imm8 = 0x6B, + OP_IMUL_imm16 = 0x69, + + OP_IN8 = 0xE4, + OP_IN = 0xE5, + OP_IN8_dx = 0xEC, + OP_IN_dx = 0xED, + + OP_INC8 = 0xFE, + OP_INC_rm16 = 0xFF, + OP_INC_rm32 = 0xFF, + OP_INC = 0x40, + + OP_INS8 = 0x6C, + OP_INS = 0x6D, + + OP_INT3 = 0xCC, + OP_INT = 0xCD, + OP_INT0 = 0xCE, + OP_INT1 = 0xF1, + + OP_IRET_IRETD = 0xCF, + + OP_JCXZ_JECXZ_JRCXZ = 0xE3, + + OP_JE_JZ_8 = 0x74, + OP_JG_JNLE_8 = 0x7F, + OP_JGE_JNL_8 = 0x7D, + OP_JL_JNGE_8 = 0x7C, + OP_JLE_JNG_8 = 0x7E, + OP_JBE_JNA_8 = 0x76, + OP_JB_JC_JNAE_8 = 0x72, + OP_JAE_JNB_JNC_8 = 0x73, + OP_JA_JNBE_8 = 0x77, + OP_JNE_JNZ_8 = 0x75, + OP_JNO_8 = 0x71, + OP_JNP_JPO_8 = 0x7B, + OP_JNS_8 = 0x79, + OP_JO_8 = 0x70, + OP_JP_JPE_8 = 0x7A, + OP_JS_8 = 0x78, + + OP_JMP8 = 0xEB, + OP_JMP = 0xE9, + OP_JMP_rm = 0xFF, + + OP_LongJMP = 0xEA, + OP_LongJMPm = 0xFF, + + OP_LAHF = 0x9F, + OP_LDS = 0xC5, + OP_LES = 0xC4, + OP_LEA = 0x8D, + OP_LEAVE = 0xC9, + OP_LODS8 = 0xAC, + OP_LODS = 0xAD, + + // One Byte Opcode Instructions M-U + + OP_MOV_rm_r8 = 0x88, + OP_MOV_rm_r = 0x89, + OP_MOV_r_rm8 = 0x8A, + OP_MOV_r_rm = 0x8B, + + OP_MOV_rm_sreg = 0x8C, + OP_MOV_sreg_rm = 0x8E, + + OP_MOV_a_moffs8 = 0xA0, + OP_MOV_a_moffs = 0xA1, + OP_MOV_moffs8_a = 0xA2, + OP_MOV_moffs_a = 0xA3, + + OP_MOV_r_imm8 = 0xB0, + OP_MOV_r_imm = 0xB8, + OP_MOV_rm_imm8 = 0xC6, + OP_MOV_rm_imm = 0xC7, + + OP_MOVS8 = 0xA4, + OP_MOVS = 0xA5, + + OP_MUL8 = 0xF6, + OP_MUL = 0xF7, + + OP_NEG8 = 0xF6, + OP_NEG = 0xF7, + OP_NOP = 0x90, + OP_NOT8 = 0xF6, + OP_NOT = 0xF7, + + OP_OR_rm_imm_8 = 0x80, + OP_OR_rm_imm = 0x81, + OP_OR_rm_imm8 = 0x83, + + OP_OR_imm8 = 0x0C, + OP_OR_imm = 0x0D, + OP_OR_rm_r_8 = 0x08, + OP_OR_rm_r = 0x09, + OP_OR_r_rm_8 = 0x0A, + OP_OR_r_rm = 0x0B, + + OP_OUT8 = 0xE6, + OP_OUT = 0xE7, + OP_OUT8_dx = 0xEE, + OP_OUT_dx = 0xEF, + + OP_OUTS8 = 0x6E, + OP_OUTS = 0x6F, + + OP_POP_rm = 0x8F, + OP_POP_r = 0x58, + OP_POP_DS = 0x1F, + OP_POP_ES = 0x07, + OP_POP_SS = 0x17, + + OP_POPA_POPAD = 0x61, + OP_POPF_POPFD = 0x9D, + + OP_PUSH_rm = 0xFF, + OP_PUSH_r = 0x50, + OP_PUSH_imm8 = 0x6A, + OP_PUSH_imm = 0x68, + OP_PUSH_CS = 0x0E, + OP_PUSH_SS = 0x16, + OP_PUSH_DS = 0x1E, + OP_PUSH_ES = 0x06, + + OP_PUSHA_PUSHAD = 0x60, + OP_PUSHF_PUSHFD = 0x9C, + + OP_RET = 0xC3, + OP_LongRET = 0xCB, + OP_RET_imm16 = 0xC2, + OP_LongRET_imm16 = 0xCA, + + OP_SAHF = 0x9E, + + OP_SAL_SAR_SHL_SHR_8_1 = 0xD0, + OP_SAL_SAR_SHL_SHR_8_cl = 0xD2, + OP_SAL_SAR_SHL_SHR_8_imm8 = 0xC0, + + OP_SAL_SAR_SHL_SHR_1 = 0xD1, + OP_SAL_SAR_SHL_SHR_cl = 0xD3, + OP_SAL_SAR_SHL_SHR_imm8 = 0xC1, + + OP_SBB_rm_imm_8 = 0x80, + OP_SBB_rm_imm = 0x81, + OP_SBB_rm_imm8 = 0x83, + + OP_SBB_imm8 = 0x1C, + OP_SBB_imm = 0x1D, + OP_SBB_rm_r_8 = 0x18, + OP_SBB_rm_r = 0x19, + OP_SBB_r_rm_8 = 0x1A, + OP_SBB_r_rm = 0x1B, + + OP_SCAS8 = 0xAE, + OP_SCAS = 0xAF, + OP_STC = 0xF9, + OP_STD = 0xFD, + OP_STI = 0xFB, + OP_STOS8 = 0xAA, + OP_STOS = 0xAB, + + OP_SUB_rm_imm_8 = 0x80, + OP_SUB_rm_imm = 0x81, + OP_SUB_rm_imm8 = 0x83, + + OP_SUB_imm8 = 0x2C, + OP_SUB_imm = 0x2D, + OP_SUB_rm_r_8 = 0x28, + OP_SUB_rm_r = 0x29, + OP_SUB_r_rm_8 = 0x2A, + OP_SUB_r_rm = 0x2B, + + OP_TEST_imm8 = 0xA8, + OP_TEST_imm = 0xA9, + OP_TEST_rm_imm8 = 0xF6, + OP_TEST_rm_imm = 0xF7, + OP_TEST_rm_r_8 = 0x84, + OP_TEST_rm_r = 0x85, + + // One Byte Opcode Instructions W-Z + + OP_WAIT_FWAIT = 0x9B, + + OP_XCHG_r = 0x90, + OP_XCHG_8 = 0x86, + OP_XCHG = 0x87, + + OP_XLAT = 0xD7, + + OP_XOR_rm_imm_8 = 0x80, + OP_XOR_rm_imm = 0x81, + OP_XOR_rm_imm8 = 0x83, + + OP_XOR_imm8 = 0x34, + OP_XOR_imm = 0x35, + OP_XOR_rm_r_8 = 0x30, + OP_XOR_rm_r = 0x31, + OP_XOR_r_rm_8 = 0x32, + OP_XOR_r_rm = 0x33, + + OP_TWO_BYTES = 0x0F, +} OneByteOpcodes; + +#endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/instructions_2.h b/src/arch/x86/bios_emu/includes/instructions_2.h new file mode 100644 index 0000000..cd9eb34 --- /dev/null +++ b/src/arch/x86/bios_emu/includes/instructions_2.h @@ -0,0 +1,80 @@ +#ifndef _BIOS_EMU_INSTRUCTIONS_2_H +#define _BIOS_EMU_INSTRUCTIONS_2_H + +typedef enum TwoBytesOpcodes { + OP_LAR = 0x02, + OP_LSL = 0x03, + OP_SYSCALL = 0x05, + OP_CLTS = 0x06, + OP_SYSRET = 0x07, + OP_INVD = 0x08, + OP_WBINVD = 0x09, + + OP_BNDCL_BNDCU_BNDLDX_BNDMOV = 0x1A, + OP_BNDCN_BNDMK_BNDSTX_BNDMOV = 0x1B, + + OP_NOP_rm = 0x1F, + + OP_MOV_r_cr = 0x20, + OP_MOV_cr_r = 0x22, + OP_MOV_r_dr = 0x21, + OP_MOV_dr_r = 0x23, + + OP_WRMSR = 0x30, + OP_RDTSC = 0x31, + OP_RDMSR = 0x32, + OP_RDPMC = 0x33, + OP_SYSENTER = 0x34, + OP_SYSEXIT = 0x35, + OP_GETSEC = 0x36, + + OP_CMOVcc = 0x40, + + OP_MOVD_mm_rm32 = 0x6E, + OP_MOVD_rm32_mm = 0x7E, + + OP_Jcc = 0x80, + + OP_SETcc = 0x90, + + OP_POP_FS = 0xA1, + OP_POP_GS = 0xA9, + + OP_PUSH_FS = 0xA0, + OP_PUSH_GS = 0xA8, + + OP_CPUID = 0xA2, + OP_BT = 0xA3, + OP_SHLD_imm8 = 0xA4, + OP_SHLD_cl = 0xA5, + OP_RSM = 0xAA, + OP_BTS = 0xAB, + OP_SHRD_imm8 = 0xAC, + OP_SHRD_cl = 0xAD, + + OP_IMUL_r_rm = 0xAF, + + OP_CMPXCHG8 = 0xB0, + OP_CMPXCHG = 0xB1, + + OP_LSS = 0xB2, + OP_BTR = 0xB3, + OP_LFS = 0xB4, + OP_LGS = 0xB5, + + OP_MOVZX_r_rm8 = 0xB6, + OP_MOVZX_r_rm16 = 0xB7, + OP_MOVSX_r_rm8 = 0xBE, + OP_MOVSX_r_rm16 = 0xBF, + + OP_POPCNT = 0xB8, + + OP_BTC = 0xB9, + OP_BSF_TZCNT = 0xBA, + OP_BSR_LZCNT = 0xBB, + + OP_XADD_rm_r_8 = 0xC0, + OP_XADD_rm_r = 0xC1, +} TwoBytesOpcodes; + +#endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/mod_rm.h b/src/arch/x86/bios_emu/includes/mod_rm.h new file mode 100644 index 0000000..dcbb7e0 --- /dev/null +++ b/src/arch/x86/bios_emu/includes/mod_rm.h @@ -0,0 +1,180 @@ +#ifndef _BIOS_EMU_MOD_RM_H +#define _BIOS_EMU_MOD_RM_H + +#include "segment.h" +#include +#include + +// MODRM REG字段 +#define MODRM_REG(x) ((x) << 3) + +#define REG_AL (0b000) +#define REG_CL (0b001) +#define REG_DL (0b010) +#define REG_BL (0b011) +#define REG_AH (0b100) +#define REG_CH (0b101) +#define REG_DH (0b110) +#define REG_BH (0b111) + +#define REG_AX REG_AL +#define REG_CX REG_CL +#define REG_DX REG_DL +#define REG_BX REG_BL +#define REG_SP REG_AH +#define REG_BP REG_CH +#define REG_SI REG_DH +#define REG_DI REG_BH + +#define REG_EAX REG_AX +#define REG_ECX REG_CX +#define REG_EDX REG_DX +#define REG_EBX REG_BX +#define REG_ESP REG_SP +#define REG_EBP REG_BP +#define REG_ESI REG_SI +#define REG_EDI REG_DI + +// MODRM MOD字段 +#define MOD_BASE 0b00 +#define MOD_BASE_DISP8 0b01 +#define MOD_BASE_DISP16 0b10 +#define MOD_BASE_DISP32 MOD_BASE_DISP16 +#define MOD_REG 0b11 + +// MODRM RM字段 +// 16位 +// 1.base mod +#define RM_BX_SI (0b000) +#define RM_BX_DI (0b001) +#define RM_BP_SI (0b010) +#define RM_BP_DI (0b011) +#define RM_SI (0b100) +#define RM_DI (0b101) +#define RM_BP (0b110) +#define RM_BX (0b111) + +// 4.reg mod +#define RM_REG_AL (0b000) +#define RM_REG_CL (0b001) +#define RM_REG_DL (0b010) +#define RM_REG_BL (0b011) +#define RM_REG_AH (0b100) +#define RM_REG_CH (0b101) +#define RM_REG_DH (0b110) +#define RM_REG_BH (0b111) + +#define RM_REG_AX RM_REG_AL +#define RM_REG_CX RM_REG_CL +#define RM_REG_DX RM_REG_DL +#define RM_REG_BX RM_REG_BL +#define RM_REG_SP RM_REG_AH +#define RM_REG_BP RM_REG_CH +#define RM_REG_SI RM_REG_DH +#define RM_REG_DI RM_REG_BH + +#define RM_REG_EAX RM_REG_AX +#define RM_REG_ECX RM_REG_CX +#define RM_REG_EDX RM_REG_DX +#define RM_REG_EBX RM_REG_BX +#define RM_REG_ESP RM_REG_SP +#define RM_REG_EBP RM_REG_BP +#define RM_REG_ESI RM_REG_SI +#define RM_REG_EDI RM_REG_DI + +// 32位 +// 1.base mod +#define RM_EAX (0b000) +#define RM_ECX (0b001) +#define RM_EDX (0b010) +#define RM_EBX (0b011) +#define RM_EBP (0b101) +#define RM_ESI (0b110) +#define RM_EDI (0b111) + +#define RM_SREG(env, reg) \ + ({ \ + void *var; \ + switch (reg & 0x07) { \ + case 0: \ + var = &env->regs.es; \ + break; \ + case 1: \ + var = &env->regs.cs; \ + break; \ + case 2: \ + var = &env->regs.ss; \ + break; \ + case 3: \ + var = &env->regs.ds; \ + break; \ + case 4: \ + var = &env->regs.fs; \ + break; \ + case 5: \ + var = &env->regs.gs; \ + break; \ + } \ + var; \ + }) + +#define RM_ADDR(env, modrm) \ + ({ \ + void *p; \ + uint8_t mod = modrm >> 6; \ + if (mod == 0b11) { \ + if (env->flags.operand_size == 0) { \ + p = env->reg_lut_r16[modrm & 0b111]; \ + } else { \ + p = env->reg_lut_r32[modrm & 0b111]; \ + } \ + } else { \ + uint32_t segment_base = get_segment_base(env, *env->default_ss); \ + if (env->flags.address_size == 0) { \ + p = (void *)(segment_base + decode_rm_address_16(env, modrm)); \ + } else { \ + p = (void *)(segment_base + decode_rm_address_32(env, modrm)); \ + } \ + } \ + p; \ + }) + +#define RM_ADDR16(env, modrm) \ + ({ \ + void *p; \ + uint8_t mod = modrm >> 6; \ + if (mod == 0b11) { \ + p = env->reg_lut_r16[modrm & 0b111]; \ + } else { \ + uint32_t segment_base = get_segment_base(env, *env->default_ss); \ + if (env->flags.address_size == 0) { \ + p = (void *)(segment_base + decode_rm_address_16(env, modrm)); \ + } else { \ + p = (void *)(segment_base + decode_rm_address_32(env, modrm)); \ + } \ + } \ + p; \ + }) + +#define RM_ADDR32(env, modrm) \ + ({ \ + void *p; \ + uint8_t mod = modrm >> 6; \ + if (mod == 0b11) { \ + p = env->reg_lut_r32[modrm & 0b111]; \ + } else { \ + uint32_t segment_base = get_segment_base(env, *env->default_ss); \ + if (env->flags.address_size == 0) { \ + p = (void *)(segment_base + decode_rm_address_16(env, modrm)); \ + } else { \ + p = (void *)(segment_base + decode_rm_address_32(env, modrm)); \ + } \ + } \ + p; \ + }) + +size_t decode_rm_address_16(BiosEmuEnvironment *env, uint8_t modrm); +size_t decode_rm_address_32(BiosEmuEnvironment *env, uint8_t modrm); +size_t decode_rm_address(BiosEmuEnvironment *env, uint8_t modrm); + +#endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/operations.h b/src/arch/x86/bios_emu/includes/operations.h new file mode 100644 index 0000000..53d21d7 --- /dev/null +++ b/src/arch/x86/bios_emu/includes/operations.h @@ -0,0 +1,139 @@ +#ifndef _BIOS_EMU_OPERATIONS_H +#define _BIOS_EMU_OPERATIONS_H + +#include "flags.h" +#include +#include +#include + +#define CLI(env) env->regs.flags &= ~BIT(InterruptEnableFlagBit) +#define STI(env) env->regs.flags |= BIT(InterruptEnableFlagBit) +#define CLD(env) env->regs.flags &= ~BIT(DirectionFlagBit) +#define STD(env) env->regs.flags |= BIT(DirectionFlagBit) +#define CLC(env) env->regs.flags &= ~BIT(CarryFlagBit) +#define STC(env) env->regs.flags |= BIT(CarryFlagBit) +#define CMC(env) env->regs.flags ^= BIT(CarryFlagBit) + +#define LAHF(env) env->regs.ah = 0b00000010 | (env->regs.flags & 0b11010101) +#define SAHF(env) env->regs.flags = 0b00000010 | (env->regs.ah & 0b00111110) + +int ptr_within_code_segment_limit(BiosEmuEnvironment *env, uint32_t address); + +BiosEmuExceptions decode_0x80_0x83(BiosEmuEnvironment *env, uint8_t opcode); +BiosEmuExceptions decode_0xba(BiosEmuEnvironment *env); +BiosEmuExceptions decode_0xf6(BiosEmuEnvironment *env); +BiosEmuExceptions decode_0xf7(BiosEmuEnvironment *env); +BiosEmuExceptions decode_0xfe(BiosEmuEnvironment *env); +BiosEmuExceptions decode_0xff(BiosEmuEnvironment *env); + +void decode_pusha_pushad(BiosEmuEnvironment *env); + +void decode_mov_rm_r8(BiosEmuEnvironment *env); +void decode_mov_rm_r(BiosEmuEnvironment *env); +void decode_mov_r_rm_8(BiosEmuEnvironment *env); +void decode_mov_r_rm(BiosEmuEnvironment *env); +void decode_mov_rm_sreg(BiosEmuEnvironment *env); +void decode_mov_sreg_rm(BiosEmuEnvironment *env); +void decode_mov_sreg_rm(BiosEmuEnvironment *env); +void decode_mov_r_moffs_8(BiosEmuEnvironment *env); +void decode_mov_r_moffs(BiosEmuEnvironment *env); +void decode_mov_moffs_r_8(BiosEmuEnvironment *env); +void decode_mov_moffs_r(BiosEmuEnvironment *env); +void decode_mov_r_imm8(BiosEmuEnvironment *env, uint8_t opcode); +void decode_mov_r_imm(BiosEmuEnvironment *env, uint8_t opcode); +void decode_mov_rm_imm8(BiosEmuEnvironment *env); +void decode_mov_rm_imm(BiosEmuEnvironment *env); + +void decode_movzx_r_rm8(BiosEmuEnvironment *env); +void decode_movzx_r_rm16(BiosEmuEnvironment *env); +void decode_movsx_r_rm8(BiosEmuEnvironment *env); +void decode_movsx_r_rm16(BiosEmuEnvironment *env); + +void decode_jcc_8(BiosEmuEnvironment *env, int condition); +void decode_jcc(BiosEmuEnvironment *env, int condition); +void decode_jmp8(BiosEmuEnvironment *env); +void decode_jmp_near(BiosEmuEnvironment *env, int32_t offset); +void decode_jmp_far(BiosEmuEnvironment *env, uint16_t segment, uint32_t offset); +void decode_jmp(BiosEmuEnvironment *env); +void decode_long_jmp_ptr16(BiosEmuEnvironment *env); + +void decode_pop_rm(BiosEmuEnvironment *env); +void decode_pop_r(BiosEmuEnvironment *env, uint8_t opcode); +void decode_popa_popad(BiosEmuEnvironment *env); + +BiosEmuExceptions decode_call_near(BiosEmuEnvironment *env, uint32_t address); +BiosEmuExceptions decode_call(BiosEmuEnvironment *env); +BiosEmuExceptions decode_call_far( + BiosEmuEnvironment *env, uint16_t segment, uint32_t offset); +BiosEmuExceptions decode_call_ptr(BiosEmuEnvironment *env); + +BiosEmuExceptions decode_int(BiosEmuEnvironment *env, uint8_t vector); +BiosEmuExceptions decode_iret(BiosEmuEnvironment *env); + +BiosEmuExceptions decode_ret_near(BiosEmuEnvironment *env, int bytes); +BiosEmuExceptions decode_ret_far(BiosEmuEnvironment *env, int bytes); +BiosEmuExceptions decode_ret_imm16(BiosEmuEnvironment *env); +BiosEmuExceptions decode_ret_far_imm16(BiosEmuEnvironment *env); + +void decode_in8(BiosEmuEnvironment *env, uint8_t port); +void decode_in(BiosEmuEnvironment *env, uint16_t port); +void decode_out8(BiosEmuEnvironment *env, uint8_t port); +void decode_out(BiosEmuEnvironment *env, uint16_t port); + +void decode_lea(BiosEmuEnvironment *env); + +void decode_setcc(BiosEmuEnvironment *env, int condition); + +BiosEmuExceptions decode_0xc0(BiosEmuEnvironment *env); +BiosEmuExceptions decode_0xc1(BiosEmuEnvironment *env); +BiosEmuExceptions decode_0xd0(BiosEmuEnvironment *env); +BiosEmuExceptions decode_0xd1(BiosEmuEnvironment *env); +BiosEmuExceptions decode_0xd2(BiosEmuEnvironment *env); +BiosEmuExceptions decode_0xd3(BiosEmuEnvironment *env); + +BiosEmuExceptions xchg_8_8( + BiosEmuEnvironment *env, uint8_t *addr1, uint8_t *addr2); +BiosEmuExceptions xchg_16_16( + BiosEmuEnvironment *env, uint16_t *addr1, uint16_t *addr2); +BiosEmuExceptions xchg_32_32( + BiosEmuEnvironment *env, uint32_t *addr1, uint32_t *addr2); + +BiosEmuExceptions lds_16_16( + BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr); +BiosEmuExceptions lds_32_32( + BiosEmuEnvironment *env, uint32_t *reg, uint32_t *addr); +BiosEmuExceptions les_16_16( + BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr); +BiosEmuExceptions les_32_32( + BiosEmuEnvironment *env, uint32_t *reg, uint32_t *addr); + +BiosEmuExceptions shld_16_16_8( + BiosEmuEnvironment *env, uint16_t *dest, uint16_t reg, uint8_t count); +BiosEmuExceptions shld_32_32_8( + BiosEmuEnvironment *env, uint32_t *dest, uint32_t reg, uint8_t count); +BiosEmuExceptions shrd_16_16_8( + BiosEmuEnvironment *env, uint16_t *dest, uint16_t reg, uint8_t count); +BiosEmuExceptions shrd_32_32_8( + BiosEmuEnvironment *env, uint32_t *dest, uint32_t reg, uint8_t count); + +void decode_cbw_cwde(BiosEmuEnvironment *env); +void decode_cwd_cdq(BiosEmuEnvironment *env); + +BiosEmuExceptions bt_16_16( + BiosEmuEnvironment *env, uint16_t *addr, uint16_t *bit); +BiosEmuExceptions bt_32_32( + BiosEmuEnvironment *env, uint32_t *addr, uint32_t *bit); +BiosEmuExceptions btc_16_16( + BiosEmuEnvironment *env, uint16_t *addr, uint16_t *bit); +BiosEmuExceptions btc_32_32( + BiosEmuEnvironment *env, uint32_t *addr, uint32_t *bit); +BiosEmuExceptions btr_16_16( + BiosEmuEnvironment *env, uint16_t *addr, uint16_t *bit); +BiosEmuExceptions btr_32_32( + BiosEmuEnvironment *env, uint32_t *addr, uint32_t *bit); +BiosEmuExceptions bts_16_16( + BiosEmuEnvironment *env, uint16_t *addr, uint16_t *bit); +BiosEmuExceptions bts_32_32( + BiosEmuEnvironment *env, uint32_t *addr, uint32_t *bit); + +#endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/prefix.h b/src/arch/x86/bios_emu/includes/prefix.h new file mode 100644 index 0000000..f6d1724 --- /dev/null +++ b/src/arch/x86/bios_emu/includes/prefix.h @@ -0,0 +1,20 @@ +#ifndef _BIOS_EMU_PREFIX_H +#define _BIOS_EMU_PREFIX_H + +typedef enum BiosEmuPrefixs { + PREFIX_LOCK = 0xF0, + PREFIX_REPNE_REPNZ_BND = 0xF2, + PREFIX_REP_REPE_REPZ = 0xF3, + + PREFIX_CS_OVERRIDE_BRANCH_NOT_TAKEN = 0x2E, + PREFIX_SS_OVERRIDE = 0x36, + PREFIX_DS_OVERRIDE_BRANCH_TAKEN = 0x3E, + PREFIX_ES_OVERRIDE = 0x26, + PREFIX_FS_OVERRIDE = 0x64, + PREFIX_GS_OVERRIDE = 0x65, + + PREFIX_OPERAND_SIZE_OVERRIDE = 0x66, + PREFIX_ADDRSIZE_OVERRIDE = 0x67, +} BiosEmuPrefixes; + +#endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/segment.h b/src/arch/x86/bios_emu/includes/segment.h new file mode 100644 index 0000000..c432813 --- /dev/null +++ b/src/arch/x86/bios_emu/includes/segment.h @@ -0,0 +1,13 @@ +#ifndef _BIOS_EMU_SEGMENT_H +#define _BIOS_EMU_SEGMENT_H + +#include +#include + +size_t get_segment_base(BiosEmuEnvironment *env, uint32_t segment); + +uint8_t fetch_data_8(BiosEmuEnvironment *env, uint32_t segment, size_t addr); +uint8_t fetch_data_16(BiosEmuEnvironment *env, uint32_t segment, size_t addr); +uint8_t fetch_data_32(BiosEmuEnvironment *env, uint32_t segment, size_t addr); + +#endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/stack.h b/src/arch/x86/bios_emu/includes/stack.h new file mode 100644 index 0000000..1d6318f --- /dev/null +++ b/src/arch/x86/bios_emu/includes/stack.h @@ -0,0 +1,73 @@ +#ifndef _BIOS_EMU_STACK_H +#define _BIOS_EMU_STACK_H + +#define STACK_POINTER16(env) ((env->regs.ss << 4) + env->regs.sp) +#define STACK_POINTER32(env) env->regs.esp + +#define PUSH16(env, data, size) \ + { \ + env->regs.sp -= size; \ + if (size == 1) { *(uint8_t *)STACK_POINTER16(env) = data; } \ + if (size == 2) { *(uint16_t *)STACK_POINTER16(env) = data; } \ + if (size == 4) { *(uint32_t *)STACK_POINTER16(env) = data; } \ + } +#define PUSH32(env, data, size) \ + { \ + env->regs.esp -= size; \ + if (size == 1) { *(uint8_t *)STACK_POINTER32(env) = data; } \ + if (size == 2) { *(uint16_t *)STACK_POINTER32(env) = data; } \ + if (size == 4) { *(uint32_t *)STACK_POINTER32(env) = data; } \ + } + +#define POP16(env, data, size) \ + { \ + if (size == 1) { \ + (data) = *(uint8_t *)STACK_POINTER16(env); \ + } else if (size == 2) { \ + (data) = *(uint16_t *)STACK_POINTER16(env); \ + } else if (size == 4) { \ + (data) = *(uint32_t *)STACK_POINTER16(env); \ + } \ + env->regs.sp += size; \ + } +#define POP32(env, data, size) \ + { \ + if (size == 1) { \ + (data) = *(uint8_t *)STACK_POINTER32(env); \ + } else if (size == 2) { \ + (data) = *(uint16_t *)STACK_POINTER32(env); \ + } else if (size == 4) { \ + (data) = *(uint32_t *)STACK_POINTER32(env); \ + } \ + env->regs.esp += size; \ + } + +#define PUSH(env, data, size) \ + if (env->flags.stack_size == 0) { \ + PUSH16(env, data, size); \ + } else { \ + PUSH32(env, data, size); \ + } + +#define POP(env, data, size) \ + if (env->flags.stack_size == 0) { \ + POP16(env, data, size); \ + } else { \ + POP32(env, data, size); \ + } + +#define PUSH_SREG(env, sreg) \ + if (env->flags.operand_size == 0) { \ + PUSH(env, env->regs.sreg, 2); \ + } else { \ + PUSH(env, env->regs.sreg, 4); \ + } + +#define POP_SREG(env, sreg) \ + if (env->flags.operand_size == 0) { \ + POP(env, env->regs.sreg, 2); \ + } else { \ + POP(env, env->regs.sreg, 4); \ + } + +#endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/mod_rm.c b/src/arch/x86/bios_emu/mod_rm.c new file mode 100644 index 0000000..7c177db --- /dev/null +++ b/src/arch/x86/bios_emu/mod_rm.c @@ -0,0 +1,135 @@ +#include "includes/mod_rm.h" +#include +#include + +size_t decode_rm_address_16(BiosEmuEnvironment *env, uint8_t modrm) { + uint8_t mod = (modrm >> 6) & 0b11; + uint8_t rm = modrm & 0b111; + + uint16_t offset; + switch (rm) { + case RM_BX_SI: // [BX + SI] + offset = env->regs.bx + env->regs.si; + break; + case RM_BX_DI: // [BX + DI] + offset = env->regs.bx + env->regs.di; + break; + case RM_BP_SI: // [BP + SI] + offset = env->regs.bp + env->regs.si; + break; + case RM_BP_DI: // [BP + DI] + offset = env->regs.bp + env->regs.di; + break; + case RM_SI: // [SI] + offset = env->regs.si; + break; + case RM_DI: // [DI] + offset = env->regs.di; + break; + case RM_BP: // [BP] + offset = env->regs.bp; + break; + case RM_BX: // [BX] + offset = env->regs.bx; + break; + } + + switch (mod) { + case MOD_BASE: + if (rm == 0b110) { + // disp16 + offset = *(uint16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + env->regs.eip &= 0xffff; + env->cur_ip = (void *)((env->regs.cs << 4) + env->regs.eip); + } else if (rm == 0b111) { + // [BX] + offset = env->regs.bx; + } + break; + case MOD_BASE_DISP8: + offset += *(int8_t *)env->cur_ip; + env->cur_ip += 1; + env->regs.eip += 1; + env->regs.eip &= 0xffff; + env->cur_ip = (void *)((env->regs.cs << 4) + env->regs.eip); + break; + case MOD_BASE_DISP16: + offset += *(uint16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + env->regs.eip &= 0xffff; + env->cur_ip = (void *)((env->regs.cs << 4) + env->regs.eip); + break; + default: + break; + } + + return offset; +} + +size_t decode_rm_address_32(BiosEmuEnvironment *env, uint8_t modrm) { + uint8_t mod = (modrm >> 6) & 0b11; + uint8_t rm = modrm & 0b111; + + uint32_t offset = 0; + if (mod != 0b11) { + switch (rm) { + case RM_EAX: // [EAX] + offset = env->regs.eax; + break; + case RM_ECX: // [ECX] + offset = env->regs.ecx; + break; + case RM_EDX: // [EDX] + offset = env->regs.edx; + break; + case RM_EBX: // [EBX] + offset = env->regs.ebx; + break; + case RM_EBP: // [EBP] + offset = env->regs.ebp; + break; + case RM_ESI: // [DSI] + offset = env->regs.esi; + break; + case RM_EDI: // [EDI] + offset = env->regs.edi; + break; + } + } + + switch (mod) { + case MOD_BASE: + if (rm == 0b101) { + // disp32 + offset = *(uint32_t *)env->cur_ip; + env->cur_ip += 4; + env->regs.eip += 4; + } + break; + case MOD_BASE_DISP8: + offset += *(int8_t *)env->cur_ip; + env->cur_ip += 1; + env->regs.eip += 1; + break; + case MOD_BASE_DISP32: + offset += *(uint32_t *)env->cur_ip; + env->cur_ip += 4; + env->regs.eip += 4; + break; + default: + break; + } + + return offset; +} + +size_t decode_rm_address(BiosEmuEnvironment *env, uint8_t modrm) { + if (env->flags.address_size == 0) { + return decode_rm_address_16(env, modrm); + } else { + return decode_rm_address_32(env, modrm); + } +} diff --git a/src/arch/x86/bios_emu/operations.c b/src/arch/x86/bios_emu/operations.c new file mode 100644 index 0000000..08ef0e4 --- /dev/null +++ b/src/arch/x86/bios_emu/operations.c @@ -0,0 +1,482 @@ +#include "includes/operations.h" +#include "bios_emu/exceptions.h" +#include "includes/alu.h" +#include "includes/decode.h" +#include "includes/mod_rm.h" +#include "includes/segment.h" +#include "includes/stack.h" +#include "kernel/func.h" +#include +#include + +int ptr_within_code_segment_limit(BiosEmuEnvironment *env, uint32_t address) { + // uint32_t segment = env->regs.cs; + // if (env->flags.address_size == 0) { + // return (address < (segment << 4) + 0xffff) && address >= (segment << 4); + // } + return 1; +} + +BiosEmuExceptions decode_0x80_0x83(BiosEmuEnvironment *env, uint8_t opcode) { + static const CalcIndex index_table[8] = { + /* 0b000 */ CALC_ADD, + /* 0b001 */ CALC_OR, + /* 0b010 */ CALC_ADC, + /* 0b011 */ CALC_SBB, + /* 0b100 */ CALC_AND, + /* 0b101 */ CALC_SUB, + /* 0b110 */ CALC_XOR, + /* 0b111 */ CALC_CMP}; + uint8_t modrm = *(uint8_t *)env->cur_ip; + uint8_t sel = (modrm >> 3) & 0b111; + CalcIndex index = index_table[sel & 0b111]; + + switch (opcode & 0b11) { + case 0b00: + calc_rm_imm_8(env, index); + break; + case 0b01: + calc_rm_imm(env, index); + break; + case 0b10: + return InvalidOpcode; + case 0b11: + calc_rm_imm8(env, index); + break; + } + return NoException; +} + +BiosEmuExceptions decode_0xba(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip; + uint8_t sel = (modrm >> 3) & 0b111; + + switch (sel) { + case 0b100: + decode_rm_imm8(env, bt_16_16, bt_32_32); + break; + case 0b101: + decode_rm_imm8(env, bts_16_16, bts_32_32); + break; + case 0b110: + decode_rm_imm8(env, btr_16_16, btr_32_32); + break; + case 0b111: + decode_rm_imm8(env, btc_16_16, btc_32_32); + break; + default: + env->cur_ip--; + env->regs.eip--; + return InvalidOpcode; + } + return NoException; +} + +void (*rotate_shift_8[8])( + BiosEmuEnvironment *env, uint8_t *value, uint8_t count) = { + rol_8, ror_8, rcl_8, rcr_8, shl_sal_8, shr_8, shl_sal_8, sar_8}; +void (*rotate_shift16[8])( + BiosEmuEnvironment *env, uint16_t *value, uint8_t count) = { + rol_16, ror_16, rcl_16, rcr_16, shl_sal_16, shr_16, shl_sal_16, sar_16}; +void (*rotate_shift32[8])( + BiosEmuEnvironment *env, uint32_t *value, uint8_t count) = { + rol_32, ror_32, rcl_32, rcr_32, shl_sal_32, shr_32, shl_sal_32, sar_32}; + +BiosEmuExceptions decode_0xc0(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip; + env->cur_ip++; + env->regs.eip++; + uint8_t sel = (modrm >> 3) & 0b111; + + rotate_shift_8[sel](env, RM_ADDR(env, modrm), *(uint8_t *)env->cur_ip); + env->regs.eip++; + env->cur_ip++; + + return NoException; +} + +BiosEmuExceptions decode_0xc1(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip; + env->cur_ip++; + env->regs.eip++; + uint8_t sel = (modrm >> 3) & 0b111; + + if (env->flags.operand_size == 0) { + rotate_shift16[sel](env, RM_ADDR(env, modrm), *(uint8_t *)env->cur_ip); + env->regs.eip++; + env->cur_ip++; + } else { + rotate_shift32[sel](env, RM_ADDR(env, modrm), *(uint8_t *)env->cur_ip); + env->regs.eip++; + env->cur_ip++; + } + + return NoException; +} + +BiosEmuExceptions decode_0xd0(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip; + env->cur_ip++; + env->regs.eip++; + uint8_t sel = (modrm >> 3) & 0b111; + + rotate_shift_8[sel](env, RM_ADDR(env, modrm), 1); + + return NoException; +} + +BiosEmuExceptions decode_0xd1(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip; + env->cur_ip++; + env->regs.eip++; + uint8_t sel = (modrm >> 3) & 0b111; + + if (env->flags.operand_size == 0) { + rotate_shift16[sel](env, RM_ADDR(env, modrm), 1); + } else { + rotate_shift32[sel](env, RM_ADDR(env, modrm), 1); + } + + return NoException; +} + +BiosEmuExceptions decode_0xd2(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip; + env->cur_ip++; + env->regs.eip++; + uint8_t sel = (modrm >> 3) & 0b111; + + rotate_shift_8[sel](env, RM_ADDR(env, modrm), env->regs.cl); + + return NoException; +} + +BiosEmuExceptions decode_0xd3(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip; + env->cur_ip++; + env->regs.eip++; + uint8_t sel = (modrm >> 3) & 0b111; + + if (env->flags.operand_size == 0) { + rotate_shift16[sel](env, RM_ADDR(env, modrm), env->regs.cl); + } else { + rotate_shift32[sel](env, RM_ADDR(env, modrm), env->regs.cl); + } + + return NoException; +} + +BiosEmuExceptions decode_0xf6(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip; + env->cur_ip++; + env->regs.eip++; + uint8_t sel = (modrm >> 3) & 0b111; + + if (sel == 0) { + env->cur_ip--; + env->regs.eip--; + calc_rm_imm8(env, CALC_TEST); + return NoException; + } + + void *p = RM_ADDR(env, modrm); + uint8_t *addr = env->flags.operand_size == 0 + ? (uint8_t *)((env->regs.cs << 4) + (size_t)p) + : p; + + BiosEmuExceptions exception = NoException; + switch (sel) { + case 0b010: + *addr = ~(*addr); + break; + case 0b011: + neg_8(env, addr); + break; + case 0b100: + mul_8(env, *addr); + break; + case 0b101: + imul_8(env, *addr); + break; + case 0b110: + exception = div_8(env, *addr); + break; + case 0b111: + exception = idiv_8(env, *addr); + break; + } + return exception; +} + +BiosEmuExceptions decode_0xf7(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip; + env->cur_ip++; + env->regs.eip++; + uint8_t sel = (modrm >> 3) & 0b111; + + uint8_t *p = (uint8_t *)RM_ADDR(env, modrm); + + BiosEmuExceptions exception = NoException; + switch (sel) { + case 0b000: + env->cur_ip--; + env->regs.eip--; + calc_rm_imm(env, CALC_TEST); + break; + case 0b010: + if (env->flags.operand_size == 0) { + *(uint16_t *)p = ~(*(uint16_t *)p); + } else { + *(uint32_t *)p = ~(*(uint32_t *)p); + } + break; + case 0b011: + if (env->flags.operand_size == 0) { + neg_16(env, (uint16_t *)p); + } else { + neg_32(env, (uint32_t *)p); + } + break; + case 0b100: + if (env->flags.operand_size == 0) { + mul_16(env, *(uint16_t *)p); + } else { + mul_32(env, *(uint32_t *)p); + } + break; + case 0b101: + if (env->flags.operand_size == 0) { + imul_16( + env, &env->regs.dx, &env->regs.ax, env->regs.ax, + *(uint16_t *)p); + } else { + imul_32( + env, &env->regs.edx, &env->regs.eax, env->regs.eax, + *(uint16_t *)p); + } + break; + case 0b110: + exception = !env->flags.operand_size ? div_16(env, *(uint16_t *)p) + : div_32(env, *(uint32_t *)p); + break; + case 0b111: + exception = !env->flags.operand_size ? idiv_16(env, *(uint16_t *)p) + : idiv_32(env, *(uint32_t *)p); + break; + } + return exception; +} + +BiosEmuExceptions decode_0xfe(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + switch ((modrm >> 3) & 0b111) { + case 0b000: + // INC r/m + decode_inc_rm8(env); + break; + case 0b001: + // DEC r/m + decode_dec_rm8(env); + break; + default: + env->regs.eip--; + env->cur_ip--; + return InvalidOpcode; + } + return NoException; +} + +BiosEmuExceptions decode_0xff(BiosEmuEnvironment *env) { + BiosEmuExceptions exception = NoException; + uint8_t modrm = *(uint8_t *)env->cur_ip++; + uint8_t sel = (modrm >> 3) & 0b111; + env->regs.eip++; + switch (sel) { + case 0b000: + // INC r/m + decode_inc_rm(env); + break; + case 0b001: + // DEC r/m + decode_dec_rm(env); + break; + case 0b010: + // CALL r/m + if (modrm >> 6 == 0b11) { + if (env->flags.operand_size == 0) { + uint16_t *reg = env->reg_lut_r16[modrm & 0b111]; + decode_call_near(env, *reg); + } else { + uint32_t *reg = env->reg_lut_r32[modrm & 0b111]; + decode_call_near(env, *reg); + } + } else { + if (env->flags.operand_size == 0) { + uint16_t address = decode_rm_address_16(env, modrm); + address = fetch_data_16(env, *env->default_ss, address); + decode_call_near(env, address); + } else { + uint32_t address = decode_rm_address_32(env, modrm); + address = fetch_data_32(env, *env->default_ss, address); + decode_call_near(env, address); + } + } + break; + case 0b011: + // CALL m16:16/32 + if (env->flags.operand_size == 0) { + uint16_t address = decode_rm_address_16(env, modrm); + address = fetch_data_16(env, *env->default_ss, address); + uint16_t segment = + fetch_data_16(env, *env->default_ss, address + 2); + decode_call_far(env, segment, address); + } else { + uint32_t address = decode_rm_address_32(env, modrm); + address = fetch_data_32(env, *env->default_ss, address); + uint32_t segment = + fetch_data_32(env, *env->default_ss, address + 4); + decode_call_far(env, segment, address); + } + break; + case 0b100: + // JMP r/m + if (modrm >> 6 == 0b11) { + if (env->flags.operand_size == 0) { + uint16_t *reg = env->reg_lut_r16[modrm & 0b111]; + decode_jmp_near(env, *reg); + } else { + uint32_t *reg = env->reg_lut_r32[modrm & 0b111]; + decode_jmp_near(env, *reg); + } + } else { + if (env->flags.operand_size == 0) { + uint16_t address = decode_rm_address_16(env, modrm); + address = fetch_data_16(env, *env->default_ss, address); + decode_jmp_near(env, (int16_t)address); + } else { + uint32_t address = decode_rm_address_32(env, modrm); + address = fetch_data_32(env, *env->default_ss, address); + decode_jmp_near(env, (int32_t)address); + } + } + break; + case 0b101: + // Long JMP + if (env->flags.operand_size == 0) { + uint16_t address = decode_rm_address_16(env, modrm); + address = fetch_data_16(env, *env->default_ss, address); + uint16_t segment = + fetch_data_16(env, *env->default_ss, address + 2); + decode_jmp_far(env, segment, address); + } else { + uint32_t address = decode_rm_address_32(env, modrm); + address = fetch_data_32(env, *env->default_ss, address); + uint32_t segment = + fetch_data_32(env, *env->default_ss, address + 4); + decode_jmp_far(env, segment, address); + } + break; + case 0b110: + // PUSH r/m16 + if (modrm >> 6 == 0b11) { + // PUSH r16 + if (env->flags.operand_size == 0) { + uint16_t *reg = env->reg_lut_r16[modrm & 0b111]; + PUSH(env, *reg, 2); + } else { + uint32_t *reg = env->reg_lut_r32[modrm & 0b111]; + PUSH(env, *reg, 4); + } + } else { + // PUSH [r/m16] + if (env->flags.operand_size == 0) { + uint16_t val = decode_rm_address_16(env, modrm); + val = fetch_data_16(env, *env->default_ss, val); + PUSH(env, val, 2); + } else { + uint32_t val = decode_rm_address_32(env, modrm); + val = fetch_data_32(env, *env->default_ss, val); + PUSH(env, val, 4); + } + } + break; + default: + env->regs.eip--; + env->cur_ip--; + exception = InvalidOpcode; + } + return exception; +} + +void decode_in8(BiosEmuEnvironment *env, uint8_t port) { + env->regs.al = io_in8(port); +} + +void decode_in(BiosEmuEnvironment *env, uint16_t port) { + if (env->flags.operand_size == 0) { + env->regs.ax = io_in16(port); + } else { + env->regs.eax = io_in32(port); + } +} + +void decode_out8(BiosEmuEnvironment *env, uint8_t port) { + io_out8(port, env->regs.al); +} + +void decode_out(BiosEmuEnvironment *env, uint16_t port) { + if (env->flags.operand_size == 0) { + io_out16(port, env->regs.ax); + } else { + io_out32(port, env->regs.eax); + } +} + +void decode_lea(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + size_t address; + if (env->flags.address_size == 0) { + address = decode_rm_address_16(env, modrm); + } else { + address = decode_rm_address_32(env, modrm); + } + if (env->flags.operand_size == 0) { + uint16_t *dst = env->reg_lut_r16[reg]; + *dst = (uint16_t)address; + } else { + uint32_t *dst = env->reg_lut_r32[reg]; + *dst = (uint32_t)address; + } + return; +} + +void decode_setcc(BiosEmuEnvironment *env, int condition) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + + uint8_t *addr = RM_ADDR(env, modrm); + *addr = condition ? 1 : 0; + return; +} + +void decode_cbw_cwde(BiosEmuEnvironment *env) { + if (env->flags.operand_size == 0) { + env->regs.ax = (int16_t)(int8_t)env->regs.al; + } else { + env->regs.eax = (int32_t)(int16_t)env->regs.ax; + } + return; +} + +void decode_cwd_cdq(BiosEmuEnvironment *env) { + if (env->flags.operand_size == 0) { + env->regs.dx = ((int32_t)(int16_t)env->regs.ax) >> 16; + } else { + env->regs.edx = (env->regs.eax >> 31) ? 0xffffffff : 0; + } + return; +} diff --git a/src/arch/x86/bios_emu/ops/Makefile b/src/arch/x86/bios_emu/ops/Makefile new file mode 100644 index 0000000..786ad17 --- /dev/null +++ b/src/arch/x86/bios_emu/ops/Makefile @@ -0,0 +1,10 @@ +SRC += mov.c +SRC += alu.c +SRC += jmp.c +SRC += stack.c +SRC += call.c +SRC += conditions.c +SRC += int.c +SRC += xchg.c +SRC += segment.c +SRC += bt.c \ No newline at end of file diff --git a/src/arch/x86/bios_emu/ops/alu.c b/src/arch/x86/bios_emu/ops/alu.c new file mode 100644 index 0000000..bf6a067 --- /dev/null +++ b/src/arch/x86/bios_emu/ops/alu.c @@ -0,0 +1,1303 @@ +#include "../includes/alu.h" +#include "../includes/decode.h" +#include "../includes/flags.h" +#include "../includes/mod_rm.h" +#include "bits.h" +#include +#include +#include + +#define SET_FLAG(x, bit) \ + env->regs.flags = \ + (x) ? env->regs.flags | BIT(bit) : env->regs.flags & ~BIT(bit) + +#define SET_CARRY_FLAG(x) SET_FLAG(x, CarryFlagBit) +#define SET_OVERFLOW_FLAG(x) SET_FLAG(x, OverflowFlagBit) +#define SET_SIGN_FLAG(x) SET_FLAG(x, SignFlagBit) + +#define SIGN_FLAG8(x) SET_SIGN_FLAG(x >> 7) +#define SIGN_FLAG16(x) SET_SIGN_FLAG(x >> 15) +#define SIGN_FLAG32(x) SET_SIGN_FLAG(x >> 31) + +static inline uint8_t calc_parity(uint8_t x) { + x ^= x >> 4; + x &= 0x0F; + return (0x6996 >> x) & 1; +} + +void set_test_flag(BiosEmuEnvironment *env, uint32_t x) { + env->regs.flags = x == 0 ? env->regs.flags | BIT(ZeroFlagBit) + : env->regs.flags & ~BIT(ZeroFlagBit); + env->regs.flags = + (calc_parity(x) ? env->regs.flags | BIT(ParityFlagBit) + : env->regs.flags & ~BIT(ParityFlagBit)); + env->regs.flags &= ~BIT(CarryFlagBit); + env->regs.flags &= ~BIT(OverflowFlagBit); + return; +} + +static void test_8(BiosEmuEnvironment *env, uint8_t *dst, uint8_t src) { + uint8_t temp = *dst & src; + + SIGN_FLAG8(temp); + set_test_flag(env, temp); + return; +} + +static void test_16(BiosEmuEnvironment *env, uint16_t *dst, uint16_t src) { + uint16_t temp = *dst & src; + + SIGN_FLAG16(temp); + set_test_flag(env, temp); + return; +} + +static void test_32(BiosEmuEnvironment *env, uint32_t *dst, uint32_t src) { + uint32_t temp = *dst & src; + + SIGN_FLAG32(temp); + set_test_flag(env, temp); + return; +} + +void set_zf_pf(BiosEmuEnvironment *env, uint32_t x) { + env->regs.flags = x == 0 ? env->regs.flags | BIT(ZeroFlagBit) + : env->regs.flags & ~BIT(ZeroFlagBit); + env->regs.flags = + (calc_parity(x) ? env->regs.flags | BIT(ParityFlagBit) + : env->regs.flags & ~BIT(ParityFlagBit)); + return; +} + +static void add_8(BiosEmuEnvironment *env, uint8_t *dst, uint8_t src) { + uint8_t ans; + int overflow = __builtin_add_overflow(*dst, src, &ans); + + SET_CARRY_FLAG(*dst > ~src); + SET_OVERFLOW_FLAG(overflow); + SIGN_FLAG8(ans); + set_zf_pf(env, ans); + *dst = ans; + return; +} + +static void add_16(BiosEmuEnvironment *env, uint16_t *dst, uint16_t src) { + uint16_t ans; + int overflow = __builtin_add_overflow(*dst, src, &ans); + + SET_CARRY_FLAG(*dst > ~src); + SET_OVERFLOW_FLAG(overflow); + SIGN_FLAG16(ans); + set_zf_pf(env, ans); + *dst = ans; + return; +} + +static void add_32(BiosEmuEnvironment *env, uint32_t *dst, uint32_t src) { + uint32_t ans; + int overflow = __builtin_add_overflow(*dst, src, &ans); + + SET_CARRY_FLAG(*dst > ~src); + SET_OVERFLOW_FLAG(overflow); + SIGN_FLAG32(ans); + set_zf_pf(env, ans); + *dst = ans; + return; +} + +static void adc_8(BiosEmuEnvironment *env, uint8_t *dst, uint8_t src) { + uint8_t carry = !!(env->regs.flags & BIT(CarryFlagBit)); + add_8(env, dst, src + carry); + return; +} + +static void adc_16(BiosEmuEnvironment *env, uint16_t *dst, uint16_t src) { + uint8_t carry = !!(env->regs.flags & BIT(CarryFlagBit)); + add_16(env, dst, src + carry); + return; +} + +static void adc_32(BiosEmuEnvironment *env, uint32_t *dst, uint32_t src) { + uint8_t carry = !!(env->regs.flags & BIT(CarryFlagBit)); + add_32(env, dst, src + carry); + return; +} + +static void sub_8(BiosEmuEnvironment *env, uint8_t *dst, uint8_t src) { + uint8_t ans; + int overflow = __builtin_sub_overflow(*dst, src, &ans); + + SET_CARRY_FLAG(*dst < src); + SET_OVERFLOW_FLAG(overflow); + SIGN_FLAG8(ans); + set_zf_pf(env, ans); + *dst = ans; + return; +} + +static void sub_16(BiosEmuEnvironment *env, uint16_t *dst, uint16_t src) { + uint16_t ans; + int overflow = __builtin_sub_overflow(*dst, src, &ans); + + SET_CARRY_FLAG(*dst < src); + SET_OVERFLOW_FLAG(overflow); + SIGN_FLAG16(ans); + set_zf_pf(env, ans); + *dst = ans; + return; +} + +static void sub_32(BiosEmuEnvironment *env, uint32_t *dst, uint32_t src) { + uint32_t ans; + int overflow = __builtin_sub_overflow(*dst, src, &ans); + + SET_CARRY_FLAG(*dst < src); + SET_OVERFLOW_FLAG(overflow); + SIGN_FLAG32(ans); + set_zf_pf(env, ans); + *dst = ans; + return; +} + +static void sbb_8(BiosEmuEnvironment *env, uint8_t *dst, uint8_t src) { + uint8_t carry = !!(env->regs.flags & BIT(CarryFlagBit)); + sub_8(env, dst, src + carry); + return; +} + +static void sbb_16(BiosEmuEnvironment *env, uint16_t *dst, uint16_t src) { + uint8_t carry = !!(env->regs.flags & BIT(CarryFlagBit)); + sub_16(env, dst, src + carry); + return; +} + +static void sbb_32(BiosEmuEnvironment *env, uint32_t *dst, uint32_t src) { + uint8_t carry = !!(env->regs.flags & BIT(CarryFlagBit)); + sub_32(env, dst, src + carry); + return; +} + +static void and_8(BiosEmuEnvironment *env, uint8_t *dst, uint8_t src) { + uint8_t ans = *dst & src; + + SIGN_FLAG8(ans); + set_test_flag(env, ans); + *dst = ans; + return; +} + +static void and_16(BiosEmuEnvironment *env, uint16_t *dst, uint16_t src) { + uint16_t ans = *dst & src; + + SIGN_FLAG16(ans); + set_test_flag(env, ans); + *dst = ans; + return; +} + +static void and_32(BiosEmuEnvironment *env, uint32_t *dst, uint32_t src) { + uint32_t ans = *dst & src; + + SIGN_FLAG32(ans); + set_test_flag(env, ans); + *dst = ans; + return; +} + +static void xor_8(BiosEmuEnvironment *env, uint8_t *dst, uint8_t src) { + uint8_t ans = *dst ^ src; + + SIGN_FLAG8(ans); + set_test_flag(env, ans); + *dst = ans; + return; +} + +static void xor_16(BiosEmuEnvironment *env, uint16_t *dst, uint16_t src) { + uint16_t ans = *dst ^ src; + + SIGN_FLAG16(ans); + set_test_flag(env, ans); + *dst = ans; + return; +} + +static void xor_32(BiosEmuEnvironment *env, uint32_t *dst, uint32_t src) { + uint32_t ans = *dst ^ src; + + SIGN_FLAG32(ans); + set_test_flag(env, ans); + *dst = ans; + return; +} + +static void or_8(BiosEmuEnvironment *env, uint8_t *dst, uint8_t src) { + uint8_t ans = *dst | src; + + SIGN_FLAG8(ans); + set_test_flag(env, ans); + *dst = ans; + return; +} + +static void or_16(BiosEmuEnvironment *env, uint16_t *dst, uint16_t src) { + uint16_t ans = *dst | src; + + SIGN_FLAG16(ans); + set_test_flag(env, ans); + *dst = ans; + return; +} + +static void or_32(BiosEmuEnvironment *env, uint32_t *dst, uint32_t src) { + uint32_t ans = *dst | src; + + SIGN_FLAG32(ans); + set_test_flag(env, ans); + *dst = ans; + return; +} + +static void cmp_8(BiosEmuEnvironment *env, uint8_t *dst, uint8_t src) { + uint16_t ans; + int overflow = __builtin_sub_overflow(*dst, src, &ans); + + SET_CARRY_FLAG(*dst < src); + SET_OVERFLOW_FLAG(overflow); + SIGN_FLAG16(ans); + set_zf_pf(env, ans); + return; +} + +static void cmp_16(BiosEmuEnvironment *env, uint16_t *dst, uint16_t src) { + uint16_t ans; + int overflow = __builtin_sub_overflow(*dst, src, &ans); + + SET_CARRY_FLAG(*dst < src); + SET_OVERFLOW_FLAG(overflow); + SIGN_FLAG16(ans); + set_zf_pf(env, ans); + return; +} + +static void cmp_32(BiosEmuEnvironment *env, uint32_t *dst, uint32_t src) { + uint32_t ans; + int overflow = __builtin_sub_overflow(*dst, src, &ans); + + SET_CARRY_FLAG(*dst < src); + SET_OVERFLOW_FLAG(overflow); + SIGN_FLAG32(ans); + set_zf_pf(env, ans); + return; +} + +Calc8 calc8[] = { + [CALC_ADD] = add_8, [CALC_ADC] = adc_8, [CALC_AND] = and_8, + [CALC_XOR] = xor_8, [CALC_OR] = or_8, [CALC_SBB] = sbb_8, + [CALC_SUB] = sub_8, [CALC_CMP] = cmp_8, [CALC_TEST] = test_8, +}; + +Calc16 calc16[] = { + [CALC_ADD] = add_16, [CALC_ADC] = adc_16, [CALC_AND] = and_16, + [CALC_XOR] = xor_16, [CALC_OR] = or_16, [CALC_SBB] = sbb_16, + [CALC_SUB] = sub_16, [CALC_CMP] = cmp_16, [CALC_TEST] = test_16, +}; + +Calc32 calc32[] = { + [CALC_ADD] = add_32, [CALC_ADC] = adc_32, [CALC_AND] = and_32, + [CALC_XOR] = xor_32, [CALC_OR] = or_32, [CALC_SBB] = sbb_32, + [CALC_SUB] = sub_32, [CALC_CMP] = cmp_32, [CALC_TEST] = test_32, +}; + +void calc_a_imm8(BiosEmuEnvironment *env, CalcIndex index) { + uint8_t imm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + + calc8[index](env, &env->regs.al, imm); + return; +} + +void calc_a_imm(BiosEmuEnvironment *env, CalcIndex index) { + if (env->flags.operand_size == 0) { + uint16_t imm = *(uint16_t *)env->cur_ip; + env->regs.eip += 2; + env->cur_ip += 2; + calc16[index](env, &env->regs.ax, imm); + } else { + uint32_t imm = *(uint32_t *)env->cur_ip; + env->regs.eip += 4; + env->cur_ip += 4; + calc32[index](env, &env->regs.eax, imm); + } + return; +} + +void calc_rm_imm_8(BiosEmuEnvironment *env, CalcIndex index) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + + uint8_t *dst = RM_ADDR(env, modrm); + uint8_t imm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + + calc8[index](env, dst, imm); + return; +} + +void calc_rm_imm(BiosEmuEnvironment *env, CalcIndex index) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + + if (env->flags.operand_size == 0) { + uint16_t *dst = RM_ADDR(env, modrm); + uint16_t imm = *(uint16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + + calc16[index](env, dst, imm); + } else { + uint32_t *dst = RM_ADDR(env, modrm); + uint32_t imm = *(uint32_t *)env->cur_ip; + env->cur_ip += 4; + env->regs.eip += 4; + + calc32[index](env, dst, imm); + } + return; +} + +void calc_rm_imm8(BiosEmuEnvironment *env, CalcIndex index) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + + if (env->flags.operand_size == 0) { + uint16_t *dst = RM_ADDR(env, modrm); + uint8_t imm = *(uint8_t *)env->cur_ip; + env->cur_ip++; + env->regs.eip++; + + calc16[index](env, dst, (uint16_t)imm); + } else { + uint32_t *dst = RM_ADDR(env, modrm); + uint8_t imm = *(uint8_t *)env->cur_ip; + env->cur_ip++; + env->regs.eip++; + + calc32[index](env, dst, (uint32_t)imm); + } + return; +} + +void calc_rm_r_8(BiosEmuEnvironment *env, CalcIndex index) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + uint8_t *dst = RM_ADDR(env, modrm); + uint8_t *src = env->reg_lut_r8[reg]; + + calc8[index](env, dst, *src); + return; +} + +void calc_rm_r(BiosEmuEnvironment *env, CalcIndex index) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + if (env->flags.operand_size == 0) { + uint16_t *dst = RM_ADDR(env, modrm); + uint16_t *src = env->reg_lut_r16[reg]; + + calc16[index](env, dst, *src); + } else { + uint32_t *dst = RM_ADDR(env, modrm); + uint32_t *src = env->reg_lut_r32[reg]; + + calc32[index](env, dst, *src); + } + return; +} +void calc_r_rm_8(BiosEmuEnvironment *env, CalcIndex index) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + uint8_t *dst = env->reg_lut_r8[reg]; + uint8_t *src = RM_ADDR(env, modrm); + + calc8[index](env, dst, *src); + return; +} + +void calc_r_rm(BiosEmuEnvironment *env, CalcIndex index) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + if (env->flags.operand_size == 0) { + uint16_t *dst = env->reg_lut_r16[reg]; + uint16_t *src = RM_ADDR(env, modrm); + + calc16[index](env, dst, *src); + } else { + uint32_t *dst = env->reg_lut_r32[reg]; + uint32_t *src = RM_ADDR(env, modrm); + + calc32[index](env, dst, *src); + } + return; +} + +void decode_inc_r(BiosEmuEnvironment *env, uint8_t opcode) { + if (env->flags.operand_size == 0) { + uint16_t *dst = PLUS_RW_REG(env, opcode); + int overflow = __builtin_add_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } else { + uint32_t *dst = PLUS_RD_REG(env, opcode); + __builtin_add_overflow(*dst, 1, dst); + int overflow = __builtin_add_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } + return; +} + +void decode_dec_r(BiosEmuEnvironment *env, uint8_t opcode) { + if (env->flags.operand_size == 0) { + uint16_t *dst = PLUS_RW_REG(env, opcode); + int overflow = __builtin_sub_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } else { + uint32_t *dst = PLUS_RD_REG(env, opcode); + int overflow = __builtin_sub_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } + return; +} + +void decode_inc_rm(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t mod = modrm >> 6; + + if (mod == 0b11) { + uint8_t reg = modrm & 0b111; + if (env->flags.operand_size == 0) { + uint16_t *dst = env->reg_lut_r16[reg]; + int overflow = __builtin_add_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } else { + uint32_t *dst = env->reg_lut_r32[reg]; + int overflow = __builtin_add_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } + return; + } else { + if (env->flags.operand_size == 0) { + uint16_t *dst = RM_ADDR16(env, modrm); + int overflow = __builtin_add_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } else { + uint32_t *dst = RM_ADDR32(env, modrm); + int overflow = __builtin_add_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } + } + return; +} + +void decode_dec_rm(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t mod = modrm >> 6; + + if (mod == 0b11) { + uint8_t reg = modrm & 0b111; + if (env->flags.operand_size == 0) { + uint16_t *dst = env->reg_lut_r16[reg]; + int overflow = __builtin_sub_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } else { + uint32_t *dst = env->reg_lut_r32[reg]; + int overflow = __builtin_sub_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } + return; + } else { + if (env->flags.operand_size == 0) { + uint16_t *dst = RM_ADDR16(env, modrm); + int overflow = __builtin_sub_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } else { + uint32_t *dst = RM_ADDR32(env, modrm); + int overflow = __builtin_sub_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } + } + return; +} + +void decode_inc_rm8(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t mod = modrm >> 6; + + if (mod == 0b11) { + uint8_t reg = modrm & 0b111; + uint8_t *dst = env->reg_lut_r8[reg]; + int overflow = __builtin_add_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } else { + uint8_t *dst = RM_ADDR(env, modrm); + int overflow = __builtin_add_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } + return; +} + +void decode_dec_rm8(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t mod = modrm >> 6; + + if (mod == 0b11) { + uint8_t reg = modrm & 0b111; + uint8_t *dst = env->reg_lut_r8[reg]; + int overflow = __builtin_sub_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } else { + uint8_t *dst = RM_ADDR(env, modrm); + int overflow = __builtin_sub_overflow(*dst, 1, dst); + SET_OVERFLOW_FLAG(overflow); + set_zf_pf(env, *dst); + } + return; +} + +void decode_aaa(BiosEmuEnvironment *env) { + if (env->regs.al > 0x9f || env->regs.flags & BIT(AuxiliaryCarryFlagBit)) { + env->regs.ax += 0x106; + SET_FLAG(1, AuxiliaryCarryFlagBit); + } else { + SET_FLAG(0, AuxiliaryCarryFlagBit); + } + return; +} + +void decode_aad(BiosEmuEnvironment *env) { + uint8_t base = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + env->regs.al = (env->regs.al + (env->regs.ah * base)) & 0xff; + env->regs.ah = 0; + + SIGN_FLAG8(env->regs.al); + SET_FLAG(env->regs.al == 0, ZeroFlagBit); + SET_FLAG(calc_parity(env->regs.al), ParityFlagBit); + return; +} + +void decode_aam(BiosEmuEnvironment *env) { + uint8_t base = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + env->regs.ah = env->regs.al / base; + env->regs.al = env->regs.al % base; + + SIGN_FLAG8(env->regs.al); + SET_FLAG(env->regs.al == 0, ZeroFlagBit); + SET_FLAG(calc_parity(env->regs.al), ParityFlagBit); + return; +} + +void decode_aas(BiosEmuEnvironment *env) { + if (env->regs.al > 0x0f || env->regs.flags & BIT(AuxiliaryCarryFlagBit)) { + env->regs.al -= 6; + env->regs.ah -= 1; + env->regs.al &= 0x0f; + env->regs.flags |= BIT(AuxiliaryCarryFlagBit) | BIT(CarryFlagBit); + } else { + env->regs.flags &= ~(BIT(AuxiliaryCarryFlagBit) | BIT(CarryFlagBit)); + env->regs.al &= 0x0f; + } + return; +} + +void decode_daa(BiosEmuEnvironment *env) { + uint8_t old_al = env->regs.al; + uint8_t old_cf = env->regs.flags & BIT(CarryFlagBit); + SET_CARRY_FLAG(0); + if ((env->regs.al & 0x0f) > 9 || + env->regs.flags & BIT(AuxiliaryCarryFlagBit)) { + env->regs.al += 0x06; + + env->regs.flags |= old_cf | BIT(AuxiliaryCarryFlagBit); + /* (uint8_t)~6 == 255 - 6*/ + /* old_al > 255 - 6 => old_al + 6 > 255 */ + (old_al > (uint8_t)~6) ? (env->regs.flags |= BIT(CarryFlagBit)) + : (env->regs.flags &= ~BIT(CarryFlagBit)); + } else { + SET_FLAG(0, AuxiliaryCarryFlagBit); + } + if (env->regs.al > 0x99 || old_cf) { + env->regs.al += 0x60; + SET_CARRY_FLAG(1); + } else { + SET_CARRY_FLAG(0); + } + return; +} + +void decode_das(BiosEmuEnvironment *env) { + uint8_t old_al = env->regs.al; + uint8_t old_cf = env->regs.flags & BIT(CarryFlagBit); + SET_CARRY_FLAG(0); + if ((env->regs.al & 0x0f) > 9 || + env->regs.flags & BIT(AuxiliaryCarryFlagBit)) { + env->regs.al -= 0x06; + + env->regs.flags |= old_cf | BIT(AuxiliaryCarryFlagBit); + (old_al < (uint8_t)-6) ? (env->regs.flags |= BIT(CarryFlagBit)) + : (env->regs.flags &= ~BIT(CarryFlagBit)); + } else { + SET_FLAG(0, AuxiliaryCarryFlagBit); + } + if (env->regs.al > 0x99 || old_cf) { + env->regs.al -= 0x60; + SET_CARRY_FLAG(1); + } +} + +BiosEmuExceptions div_8(BiosEmuEnvironment *env, uint8_t value) { + if (value == 0) { return DivideError; } + + uint16_t dividend = env->regs.ax; + uint8_t divisor = env->regs.al; + + uint16_t temp1 = dividend / divisor; + uint16_t temp2 = dividend % divisor; + + if (temp1 > 0xff) { + return DivideError; + } else { + env->regs.al = temp1; + env->regs.ah = temp2; + } + return NoException; +} + +BiosEmuExceptions div_16(BiosEmuEnvironment *env, uint16_t value) { + if (value == 0) { return DivideError; } + + uint32_t dividend = env->regs.dx << 16 | env->regs.ax; + + uint32_t temp1 = dividend / value; + uint16_t temp2 = dividend % value; + if (temp1 > 0xffff) { + return DivideError; + } else { + env->regs.ax = temp1; + env->regs.dx = temp2; + } + + return NoException; +} + +void div_64_32( + uint64_t a, uint32_t b, uint64_t *quotient, uint32_t *remainder) { + int ans = 0; + uint64_t tmp = 0; + int max = 64; + if (b > a) { + *quotient = 0; + *remainder = a; + return; + } + for (int i = 0; i < 64; i++) { + int j = 0; + do { + tmp = b << j; + j++; + } while (tmp < a && j < max); + j--; + if (j == 0) break; + ans |= 1 << (j - 1); + a -= b << (j - 1); + } + *quotient = ans; + *remainder = a; +} + +BiosEmuExceptions div_32(BiosEmuEnvironment *env, uint32_t value) { + if (value == 0) { return DivideError; } + + uint64_t dividend = ((uint64_t)env->regs.edx << 32) | env->regs.eax; + + uint64_t temp1; + uint32_t temp2; + div_64_32(dividend, value, &temp1, &temp2); + if (temp1 > 0xffffffff) { + return DivideError; + } else { + env->regs.eax = temp1; + env->regs.edx = temp2; + } + + return NoException; +} + +BiosEmuExceptions idiv_8(BiosEmuEnvironment *env, uint8_t value) { + if (value == 0) { return DivideError; } + + uint16_t dividend = env->regs.ax; + uint8_t divisor = env->regs.al; + + uint16_t temp1 = dividend / divisor; + uint16_t temp2 = dividend % divisor; + + if (temp1 >> 7 && temp1 >> 7 != -1) { + return DivideError; + } else { + env->regs.al = temp1; + env->regs.ah = temp2; + } + return NoException; +} + +BiosEmuExceptions idiv_16(BiosEmuEnvironment *env, uint16_t value) { + if (value == 0) { return DivideError; } + + uint32_t dividend = env->regs.dx << 16 | env->regs.ax; + + uint32_t temp1 = dividend / value; + uint16_t temp2 = dividend % value; + if (temp1 >> 15 && temp1 >> 15 != -1) { + return DivideError; + } else { + env->regs.ax = temp1; + env->regs.dx = temp2; + } + + return NoException; +} + +BiosEmuExceptions idiv_32(BiosEmuEnvironment *env, uint32_t value) { + if (value == 0) { return DivideError; } + + uint64_t dividend = ((uint64_t)env->regs.edx << 32) | env->regs.eax; + + uint64_t temp1; + uint32_t temp2; + div_64_32(dividend, value, &temp1, &temp2); + if (temp1 >> 31 && temp1 >> 31 != -1) { + return DivideError; + } else { + env->regs.eax = temp1; + env->regs.edx = temp2; + } + + return NoException; +} + +void mul_8(BiosEmuEnvironment *env, uint8_t value) { + uint16_t ans = env->regs.al * value; + env->regs.ax = ans; + SET_OVERFLOW_FLAG(ans >> 8); +} + +void mul_16(BiosEmuEnvironment *env, uint16_t value) { + uint32_t ans = env->regs.ax * value; + env->regs.ax = ans & 0xffff; + env->regs.dx = ans >> 16; + SET_OVERFLOW_FLAG(ans >> 16); +} + +void mul_32(BiosEmuEnvironment *env, uint32_t value) { + uint64_t ans = env->regs.eax * value; + env->regs.ax = ans & 0xffffffff; + env->regs.dx = ans >> 32; + SET_OVERFLOW_FLAG(ans >> 32); +} + +void imul_8(BiosEmuEnvironment *env, uint8_t value) { + int16_t ans = (int16_t)(int8_t)env->regs.al * (int16_t)(int8_t)value; + env->regs.ax = ans; + SET_OVERFLOW_FLAG(ans >> 7 != 0 && ans >> 7 != -1); +} + +void imul_16( + BiosEmuEnvironment *env, uint16_t *dst_hi, uint16_t *dst_lo, uint16_t src1, + uint16_t src2) { + int32_t ans = (int32_t)(int16_t)src1 * (int32_t)(int16_t)src2; + *dst_hi = ans >> 16; + *dst_lo = ans & 0xffff; + SET_OVERFLOW_FLAG(ans >> 15 != 0 && ans >> 15 != -1); +} + +void imul_32( + BiosEmuEnvironment *env, uint32_t *dst_hi, uint32_t *dst_lo, uint32_t src1, + uint32_t src2) { + int64_t ans = (int64_t)(int32_t)src1 * (int64_t)(int32_t)src2; + *dst_hi = ans >> 32; + *dst_lo = ans & 0xffffffff; + SET_OVERFLOW_FLAG(ans >> 31 != 0 && ans >> 31 != -1); +} + +void decode_imul_r_rm_imm8(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + uint8_t imm = *(uint8_t *)env->cur_ip; + env->cur_ip++; + env->regs.eip++; + + if (env->flags.operand_size == 0) { + uint16_t tmp; + uint16_t *dst = env->reg_lut_r16[reg]; + uint16_t *value = RM_ADDR(env, modrm); + imul_16(env, &tmp, dst, *value, imm); + } else { + uint32_t tmp; + uint32_t *dst = env->reg_lut_r32[reg]; + uint32_t *value = RM_ADDR(env, modrm); + imul_32(env, &tmp, dst, *value, imm); + } + return; +} + +void decode_imul_r_rm_imm16(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + if (env->flags.operand_size == 0) { + uint16_t tmp; + uint16_t *dst = env->reg_lut_r16[reg]; + uint16_t *value = RM_ADDR(env, modrm); + uint16_t imm = *(uint16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + imul_16(env, &tmp, dst, *value, imm); + } else { + uint32_t tmp; + uint32_t *dst = env->reg_lut_r32[reg]; + uint32_t *value = RM_ADDR(env, modrm); + uint32_t imm = *(uint32_t *)env->cur_ip; + env->cur_ip += 4; + env->regs.eip += 4; + imul_32(env, &tmp, dst, *value, imm); + } + return; +} + +void decode_imul_r_rm(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + if (env->flags.operand_size == 0) { + uint16_t tmp; + uint16_t *dst = env->reg_lut_r16[reg]; + uint16_t *value = RM_ADDR(env, modrm); + imul_16(env, &tmp, dst, *dst, *value); + } else { + uint32_t tmp; + uint32_t *dst = env->reg_lut_r32[reg]; + uint32_t *value = RM_ADDR(env, modrm); + imul_32(env, &tmp, dst, *dst, *value); + } + return; +} + +void neg_8(BiosEmuEnvironment *env, uint8_t *value) { + int8_t ans = 0 - *value; + SET_CARRY_FLAG(ans == 0); + *value = ans; + return; +} + +void neg_16(BiosEmuEnvironment *env, uint16_t *value) { + int16_t ans = 0 - (int16_t)*value; + SET_CARRY_FLAG(ans == 0); + *value = ans; + return; +} + +void neg_32(BiosEmuEnvironment *env, uint32_t *value) { + int32_t ans = 0 - (int32_t)*value; + SET_CARRY_FLAG(ans == 0); + *value = ans; + return; +} + +void rcl_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 9; + if (temp_count == 0) return; + + uint8_t old_carry = (env->regs.flags >> CarryFlagBit) & 1; + uint8_t new_carry = (*value >> (8 - temp_count)) & 1; + uint8_t ans = (*value << temp_count) | (old_carry << (temp_count - 1)); + + ans |= (*value >> (8 - temp_count + 1)); + + SET_CARRY_FLAG(new_carry); + if ((count & 0x1f) == 1) SET_OVERFLOW_FLAG((ans >> 7) ^ new_carry); + *value = ans; + return; +} + +void rcl_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 17; + if (temp_count == 0) return; + + uint8_t old_carry = (env->regs.flags >> CarryFlagBit) & 1; + uint8_t new_carry = (*value >> (16 - temp_count)) & 1; + uint16_t ans = + ((*value << temp_count) & 0xff) | (old_carry << (temp_count - 1)); + + ans |= (*value >> (16 - temp_count + 1)); + + SET_CARRY_FLAG(new_carry); + if ((count & 0x1f) == 1) SET_OVERFLOW_FLAG((ans >> 15) ^ new_carry); + *value = ans; + return; +} + +void rcl_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 33; + if (temp_count == 0) return; + + uint8_t old_carry = (env->regs.flags >> CarryFlagBit) & 1; + uint8_t new_carry = (*value >> (32 - temp_count)) & 1; + uint32_t ans = + ((*value << temp_count) & 0xff) | (old_carry << (temp_count - 1)); + + ans |= (*value >> (32 - temp_count + 1)); + + SET_CARRY_FLAG(new_carry); + if ((count & 0x1f) == 1) SET_OVERFLOW_FLAG((ans >> 31) ^ new_carry); + *value = ans; + return; +} + +void rcr_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 9; + if (temp_count == 0) return; + + uint8_t old_carry = (env->regs.flags >> CarryFlagBit) & 1; + uint8_t new_carry = (*value >> (temp_count - 1)) & 1; + uint8_t ans = (*value >> temp_count) | (old_carry << (8 - temp_count)); + + ans |= (*value << (8 - temp_count + 1)); + + SET_CARRY_FLAG(new_carry); + if ((*value & 0x1f) == 1) SET_OVERFLOW_FLAG((ans >> 7) ^ old_carry); + *value = ans; + return; +} + +void rcr_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 17; + if (temp_count == 0) return; + + uint8_t old_carry = (env->regs.flags >> CarryFlagBit) & 1; + uint8_t new_carry = (*value >> (temp_count - 1)) & 1; + uint16_t ans = (*value >> temp_count) | (old_carry << (16 - temp_count)); + + ans |= (*value << (16 - temp_count + 1)); + + SET_CARRY_FLAG(new_carry); + if ((*value & 0x1f) == 1) SET_OVERFLOW_FLAG((ans >> 15) ^ old_carry); + *value = ans; + return; +} + +void rcr_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 33; + if (temp_count == 0) return; + + uint8_t old_carry = (env->regs.flags >> CarryFlagBit) & 1; + uint8_t new_carry = (*value >> (temp_count - 1)) & 1; + uint32_t ans = (*value >> temp_count) | (old_carry << (32 - temp_count)); + + ans |= (*value << (32 - temp_count + 1)); + + SET_CARRY_FLAG(new_carry); + if ((*value & 0x1f) == 1) SET_OVERFLOW_FLAG((ans >> 31) ^ old_carry); + *value = ans; + return; +} + +void rol_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 9; + if (temp_count == 0) return; + + uint8_t ans = (*value << temp_count) | (*value >> (8 - temp_count)); + + if (ans & 0x1f) { + SET_CARRY_FLAG(ans & 1); + if ((ans & 0x1f) == 1) SET_OVERFLOW_FLAG((ans >> 7) ^ (ans & 1)); + } + *value = ans; + return; +} + +void rol_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 17; + if (temp_count == 0) return; + + uint16_t ans = (*value << temp_count) | (*value >> (16 - temp_count)); + + if (ans & 0x1f) { + SET_CARRY_FLAG(ans & 1); + if ((ans & 0x1f) == 1) SET_OVERFLOW_FLAG((ans >> 15) ^ (ans & 1)); + } + *value = ans; + return; +} + +void rol_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 17; + if (temp_count == 0) return; + + uint32_t ans = (*value << temp_count) | (*value >> (32 - temp_count)); + + if (ans & 0x1f) { + SET_CARRY_FLAG(ans & 1); + if ((ans & 0x1f) == 1) SET_OVERFLOW_FLAG((ans >> 31) ^ (ans & 1)); + } + *value = ans; + return; +} + +void ror_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 9; + if (temp_count == 0) return; + + uint8_t ans = (*value >> temp_count) | (*value << (8 - temp_count)); + + uint8_t msb = ans >> 7; + if (ans & 0x1f) { + SET_CARRY_FLAG(msb); + if ((ans & 0x1f) == 1) SET_OVERFLOW_FLAG(msb ^ (ans >> 6)); + } + *value = ans; + return; +} + +void ror_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 17; + if (temp_count == 0) return; + + uint16_t ans = (*value >> temp_count) | (*value << (16 - temp_count)); + + uint8_t msb = ans >> 15; + if (ans & 0x1f) { + SET_CARRY_FLAG(msb); + if ((ans & 0x1f) == 1) SET_OVERFLOW_FLAG(msb ^ (ans >> 14)); + } + *value = ans; + return; +} + +void ror_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 17; + if (temp_count == 0) return; + + uint32_t ans = (*value >> temp_count) | (*value << (32 - temp_count)); + + uint8_t msb = ans >> 31; + if (ans & 0x1f) { + SET_CARRY_FLAG(msb); + if ((ans & 0x1f) == 1) SET_OVERFLOW_FLAG(msb ^ (ans >> 30)); + } + *value = ans; + return; +} + +void shl_sal_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 9; + if (temp_count == 0) return; + + uint8_t ans = (*value << temp_count); + + uint8_t carry = (*value >> (8 - temp_count)) & 1; + SET_CARRY_FLAG(carry); + if ((count & 0x1f) == 1) SET_OVERFLOW_FLAG((ans >> 7) ^ carry); + *value = ans; + return; +} + +void shl_sal_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 17; + if (temp_count == 0) return; + + uint16_t ans = (*value << temp_count); + + uint8_t carry = (*value >> (16 - temp_count)) & 1; + SET_CARRY_FLAG(carry); + if ((count & 0x1f) == 1) SET_OVERFLOW_FLAG((ans >> 15) ^ carry); + *value = ans; + return; +} + +void shl_sal_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 33; + if (temp_count == 0) return; + + uint16_t ans = (*value << temp_count); + + uint8_t carry = (*value >> (32 - temp_count)) & 1; + SET_CARRY_FLAG(carry); + if ((count & 0x1f) == 1) SET_OVERFLOW_FLAG((ans >> 31) ^ carry); + *value = ans; + return; +} + +void shr_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 9; + if (temp_count == 0) return; + + uint8_t ans = (*value >> temp_count); + + uint8_t carry = (*value >> (temp_count - 1)) & 1; + SET_CARRY_FLAG(carry); + if ((count & 0x1f) == 1) SET_OVERFLOW_FLAG(*value >> 7); + *value = ans; + return; +} + +void shr_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 17; + if (temp_count == 0) return; + + uint16_t ans = (*value >> temp_count); + + uint8_t carry = (*value >> (temp_count - 1)) & 1; + SET_CARRY_FLAG(carry); + if ((count & 0x1f) == 1) SET_OVERFLOW_FLAG(*value >> 15); + *value = ans; + return; +} + +void shr_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 33; + if (temp_count == 0) return; + + uint32_t ans = (*value >> temp_count); + + uint8_t carry = (*value >> (temp_count - 1)) & 1; + SET_CARRY_FLAG(carry); + if ((count & 0x1f) == 1) SET_OVERFLOW_FLAG(*value >> 31); + *value = ans; + return; +} + +void sar_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 9; + if (temp_count == 0) return; + + uint8_t ans = ((int8_t)*value >> temp_count); + + uint8_t carry = ((int8_t)*value >> (temp_count - 1)) & 1; + SET_CARRY_FLAG(carry); + if ((count & 0x1f) == 1) SET_OVERFLOW_FLAG(0); + *value = ans; + return; +} + +void sar_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 17; + if (temp_count == 0) return; + + uint16_t ans = ((int16_t)*value >> temp_count); + + uint8_t carry = ((int16_t)*value >> (temp_count - 1)) & 1; + SET_CARRY_FLAG(carry); + if ((count & 0x1f) == 1) SET_OVERFLOW_FLAG(0); + *value = ans; + return; +} + +void sar_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count) { + uint8_t temp_count = (count & 0x1f) % 33; + if (temp_count == 0) return; + + uint32_t ans = ((int32_t)*value >> temp_count); + + uint8_t carry = ((int32_t)*value >> (temp_count - 1)) & 1; + SET_CARRY_FLAG(carry); + if ((count & 0x1f) == 1) SET_OVERFLOW_FLAG(0); + *value = ans; + return; +} + +BiosEmuExceptions shld_16_16_8( + BiosEmuEnvironment *env, uint16_t *dest, uint16_t reg, uint8_t count) { + uint8_t temp_count = count % 32; + if (temp_count == 0 || count > 16) return NoException; + + uint16_t ans = (*dest << temp_count) | (reg >> (16 - temp_count)); + + uint8_t carry = (reg >> (16 - temp_count)) & 1; + SET_CARRY_FLAG(carry); + set_zf_pf(env, ans); + *dest = ans; + return NoException; +} + +BiosEmuExceptions shld_32_32_8( + BiosEmuEnvironment *env, uint32_t *dest, uint32_t reg, uint8_t count) { + uint8_t temp_count = count % 32; + if (temp_count == 0 || count > 32) return NoException; + + uint32_t ans = (*dest << temp_count) | (reg >> (32 - temp_count)); + + uint8_t carry = (reg >> (32 - temp_count)) & 1; + SET_CARRY_FLAG(carry); + set_zf_pf(env, ans); + *dest = ans; + return NoException; +} + +BiosEmuExceptions shrd_16_16_8( + BiosEmuEnvironment *env, uint16_t *dest, uint16_t reg, uint8_t count) { + uint8_t temp_count = count % 32; + if (temp_count == 0 || count > 16) return NoException; + + uint16_t ans = (*dest >> temp_count) | (reg << (16 - temp_count)); + + uint8_t carry = (reg >> (temp_count - 1)) & 1; + SET_CARRY_FLAG(carry); + set_zf_pf(env, ans); + *dest = ans; + return NoException; +} + +BiosEmuExceptions shrd_32_32_8( + BiosEmuEnvironment *env, uint32_t *dest, uint32_t reg, uint8_t count) { + uint8_t temp_count = count % 32; + if (temp_count == 0 || count > 32) return NoException; + + uint32_t ans = (*dest >> temp_count) | (reg << (32 - temp_count)); + + uint8_t carry = (reg >> (temp_count - 1)) & 1; + SET_CARRY_FLAG(carry); + set_zf_pf(env, ans); + *dest = ans; + return NoException; +} diff --git a/src/arch/x86/bios_emu/ops/bt.c b/src/arch/x86/bios_emu/ops/bt.c new file mode 100644 index 0000000..9bf28cd --- /dev/null +++ b/src/arch/x86/bios_emu/ops/bt.c @@ -0,0 +1,76 @@ +#include "../includes/flags.h" +#include +#include +#include +#include +#include + +BiosEmuExceptions bt_16_16( + BiosEmuEnvironment *env, uint16_t *addr, uint16_t *bit) { + uint16_t mask = 1 << (*bit & 0x0f); + env->regs.flags &= ~BIT(CarryFlagBit); + if (*addr & mask) { env->regs.flags |= BIT(CarryFlagBit); } + return NoException; +} + +BiosEmuExceptions bt_32_32( + BiosEmuEnvironment *env, uint32_t *addr, uint32_t *bit) { + uint32_t mask = 1 << (*bit & 0x1f); + env->regs.flags &= ~BIT(CarryFlagBit); + if (*addr & mask) { env->regs.flags |= BIT(CarryFlagBit); } + return NoException; +} + +BiosEmuExceptions btc_16_16( + BiosEmuEnvironment *env, uint16_t *addr, uint16_t *bit) { + uint16_t mask = 1 << (*bit & 0x0f); + env->regs.flags &= ~BIT(CarryFlagBit); + if (*addr & mask) { env->regs.flags |= BIT(CarryFlagBit); } + *addr ^= mask; + return NoException; +} + +BiosEmuExceptions btc_32_32( + BiosEmuEnvironment *env, uint32_t *addr, uint32_t *bit) { + uint32_t mask = 1 << (*bit & 0x1f); + env->regs.flags &= ~BIT(CarryFlagBit); + if (*addr & mask) { env->regs.flags |= BIT(CarryFlagBit); } + *addr ^= mask; + return NoException; +} + +BiosEmuExceptions btr_16_16( + BiosEmuEnvironment *env, uint16_t *addr, uint16_t *bit) { + uint16_t mask = 1 << (*bit & 0x0f); + env->regs.flags &= ~BIT(CarryFlagBit); + if (*addr & mask) { env->regs.flags |= BIT(CarryFlagBit); } + *addr &= ~mask; + return NoException; +} + +BiosEmuExceptions btr_32_32( + BiosEmuEnvironment *env, uint32_t *addr, uint32_t *bit) { + uint32_t mask = 1 << (*bit & 0x1f); + env->regs.flags &= ~BIT(CarryFlagBit); + if (*addr & mask) { env->regs.flags |= BIT(CarryFlagBit); } + *addr &= ~mask; + return NoException; +} + +BiosEmuExceptions bts_16_16( + BiosEmuEnvironment *env, uint16_t *addr, uint16_t *bit) { + uint16_t mask = 1 << (*bit & 0x0f); + env->regs.flags &= ~BIT(CarryFlagBit); + if (*addr & mask) { env->regs.flags |= BIT(CarryFlagBit); } + *addr |= mask; + return NoException; +} + +BiosEmuExceptions bts_32_32( + BiosEmuEnvironment *env, uint32_t *addr, uint32_t *bit) { + uint32_t mask = 1 << (*bit & 0x1f); + env->regs.flags &= ~BIT(CarryFlagBit); + if (*addr & mask) { env->regs.flags |= BIT(CarryFlagBit); } + *addr |= mask; + return NoException; +} diff --git a/src/arch/x86/bios_emu/ops/call.c b/src/arch/x86/bios_emu/ops/call.c new file mode 100644 index 0000000..a1306b7 --- /dev/null +++ b/src/arch/x86/bios_emu/ops/call.c @@ -0,0 +1,216 @@ +#include "../includes/operations.h" +#include "../includes/stack.h" +#include +#include +#include + +BiosEmuExceptions decode_call_near(BiosEmuEnvironment *env, uint32_t address) { + if (env->flags.operand_size == 0) { + if (!ptr_within_code_segment_limit(env, address)) + return GeneralProtection; + if (env->flags.stack_size == 0) { + if (STACK_POINTER16(env) < env->stack_bottom + 2) { + return StackFault; + } + } else { + if (STACK_POINTER32(env) < env->stack_bottom + 2) { + return StackFault; + } + } + PUSH(env, env->regs.ip, 2); + env->cur_ip = (void *)((env->regs.cs << 4) + address); + env->regs.eip = address; + } else { + if (!ptr_within_code_segment_limit(env, address)) + return GeneralProtection; + if (env->flags.stack_size == 0) { + if (STACK_POINTER16(env) < env->stack_bottom + 4) { + return StackFault; + } + } else { + if (STACK_POINTER32(env) < env->stack_bottom + 4) { + return StackFault; + } + } + PUSH(env, env->regs.eip, 4); + env->cur_ip = (void *)address; + env->regs.eip = address; + } + return NoException; +} + +BiosEmuExceptions decode_call(BiosEmuEnvironment *env) { + if (env->flags.operand_size == 0) { + uint16_t offset = *(uint16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + env->regs.eip &= 0xffff; + env->cur_ip = (void *)((env->regs.cs << 4) + env->regs.eip); + return decode_call_near(env, (env->regs.eip + offset) & 0xffff); + } else { + uint32_t offset = *(uint32_t *)env->cur_ip; + env->cur_ip += 4; + env->regs.eip += 4; + return decode_call_near(env, env->regs.eip + offset); + } +} + +BiosEmuExceptions decode_call_far( + BiosEmuEnvironment *env, uint16_t segment, uint32_t offset) { + if (env->flags.operand_size == 0) { + if (env->flags.stack_size == 0) { + if (STACK_POINTER16(env) < env->stack_bottom + 4) { + return StackFault; + } + PUSH16(env, env->regs.cs, 2); + PUSH16(env, env->regs.ip, 2); + } else { + if (STACK_POINTER32(env) < env->stack_bottom + 4) { + return StackFault; + } + PUSH32(env, env->regs.cs, 2); + PUSH32(env, env->regs.ip, 2); + } + env->regs.cs = segment; + env->regs.eip = offset & 0xffff; + env->cur_ip = (void *)((segment << 4) + env->regs.eip); + } else { + if (offset >> 16 != 0) return GeneralProtection; // 实模式 + if (env->flags.stack_size == 0) { + if (STACK_POINTER16(env) < env->stack_bottom + 6) { + return StackFault; + } + PUSH16(env, env->regs.cs, 4); + PUSH16(env, env->regs.eip, 4); + } else { + if (STACK_POINTER32(env) < env->stack_bottom + 6) { + return StackFault; + } + PUSH32(env, env->regs.cs, 4); + PUSH32(env, env->regs.eip, 4); + } + env->regs.cs = segment; + env->regs.eip = offset; + env->cur_ip = (void *)env->regs.eip; + } + return NoException; +} + +BiosEmuExceptions decode_call_ptr(BiosEmuEnvironment *env) { + uint16_t segment = *(uint16_t *)env->cur_ip; + if (env->flags.operand_size == 0) { + uint16_t offset = *(uint16_t *)(env->cur_ip + 2); + env->cur_ip += 4; + env->regs.eip += 4; + env->regs.eip &= 0xffff; + env->cur_ip = (void *)((env->regs.cs << 4) + env->regs.eip); + return decode_call_far(env, segment, offset); + } else { + uint32_t offset = *(uint32_t *)env->cur_ip; + env->cur_ip += 6; + env->regs.eip += 6; + return decode_call_far(env, segment, offset); + } +} + +BiosEmuExceptions decode_ret_near(BiosEmuEnvironment *env, int bytes) { + uint32_t temp_eip; + if (env->flags.operand_size == 0) { + if (env->flags.stack_size == 0) { + if (STACK_POINTER16(env) < env->stack_bottom + 2) { + return StackFault; + } + POP16(env, temp_eip, 2); + env->regs.sp += bytes; + } else { + if (STACK_POINTER32(env) < env->stack_bottom + 2) { + return StackFault; + } + POP32(env, temp_eip, 2); + env->regs.esp += bytes; + } + temp_eip &= 0xffff; + if (!ptr_within_code_segment_limit(env, temp_eip)) + return GeneralProtection; + env->regs.eip = temp_eip; + env->cur_ip = (void *)((env->regs.cs << 4) + env->regs.eip); + } else { + if (env->flags.stack_size == 0) { + if (STACK_POINTER16(env) < env->stack_bottom + 4) { + return StackFault; + } + POP16(env, temp_eip, 4); + env->regs.sp += bytes; + } else { + if (STACK_POINTER32(env) < env->stack_bottom + 4) { + return StackFault; + } + POP32(env, temp_eip, 4); + env->regs.esp += bytes; + } + env->regs.eip = temp_eip; + env->cur_ip = (void *)env->regs.eip; + } + return NoException; +} + +BiosEmuExceptions decode_ret_far(BiosEmuEnvironment *env, int bytes) { + uint16_t segment; + uint32_t temp_eip; + if (env->flags.operand_size == 0) { + if (env->flags.stack_size == 0) { + if (STACK_POINTER16(env) < env->stack_bottom + 4) { + return StackFault; + } + POP16(env, temp_eip, 2); + POP16(env, segment, 2); + env->regs.sp += bytes; + } else { + if (STACK_POINTER32(env) < env->stack_bottom + 4) { + return StackFault; + } + POP32(env, temp_eip, 2); + POP32(env, segment, 2); + env->regs.esp += bytes; + } + temp_eip &= 0xffff; + if (!ptr_within_code_segment_limit(env, temp_eip)) + return GeneralProtection; + env->regs.cs = segment; + env->regs.eip = temp_eip; + env->cur_ip = (void *)((segment << 4) + env->regs.eip); + } else { + if (env->flags.stack_size == 0) { + if (STACK_POINTER16(env) < env->stack_bottom + 8) { + return StackFault; + } + POP16(env, env->regs.eip, 4); + POP16(env, segment, 4); + env->regs.sp += bytes; + } else { + if (STACK_POINTER32(env) < env->stack_bottom + 8) { + return StackFault; + } + POP32(env, env->regs.eip, 4); + POP32(env, segment, 4); + env->regs.esp += bytes; + } + env->regs.cs = segment; + env->cur_ip = (void *)env->regs.eip; + } + return NoException; +} + +BiosEmuExceptions decode_ret_imm16(BiosEmuEnvironment *env) { + uint16_t offset = *(uint16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + return decode_ret_near(env, offset); +} + +BiosEmuExceptions decode_ret_far_imm16(BiosEmuEnvironment *env) { + uint16_t offset = *(uint16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + return decode_ret_far(env, offset); +} diff --git a/src/arch/x86/bios_emu/ops/conditions.c b/src/arch/x86/bios_emu/ops/conditions.c new file mode 100644 index 0000000..5356209 --- /dev/null +++ b/src/arch/x86/bios_emu/ops/conditions.c @@ -0,0 +1,98 @@ +#include "../includes/flags.h" +#include +#include +#include + +int condition_o(BiosEmuEnvironment *env) { + // OF=1 + return env->regs.flags & BIT(OverflowFlagBit); +} + +int condition_no(BiosEmuEnvironment *env) { + // OF=0 + return !(env->regs.flags & BIT(OverflowFlagBit)); +} + +int condition_b_c_nae(BiosEmuEnvironment *env) { + // CF=1 + return env->regs.flags & BIT(CarryFlagBit); +} + +int condition_ae_nb_nc(BiosEmuEnvironment *env) { + // CF=0 + return !(env->regs.flags & BIT(CarryFlagBit)); +} + +int condition_e_z(BiosEmuEnvironment *env) { + // ZF=1 + return env->regs.flags & BIT(ZeroFlagBit); +} + +int condition_ne_nz(BiosEmuEnvironment *env) { + // ZF=0 + return !(env->regs.flags & BIT(ZeroFlagBit)); +} + +int condition_be_na(BiosEmuEnvironment *env) { + // CF=1 && ZF=1 + return (env->regs.flags & BIT(CarryFlagBit)) && + (env->regs.flags & BIT(ZeroFlagBit)); +} + +int condition_a_nbe(BiosEmuEnvironment *env) { + // CF=0 && ZF=0 + return !(env->regs.flags & BIT(CarryFlagBit)) && + !(env->regs.flags & BIT(ZeroFlagBit)); +} + +int condition_s(BiosEmuEnvironment *env) { + // SF=1 + return env->regs.flags & BIT(SignFlagBit); +} + +int condition_ns(BiosEmuEnvironment *env) { + // SF=0 + return !(env->regs.flags & BIT(SignFlagBit)); +} + +int condition_p_pe(BiosEmuEnvironment *env) { + // PF=1 + return env->regs.flags & BIT(ParityFlagBit); +} + +int condition_np_po(BiosEmuEnvironment *env) { + // PF=0 + return !(env->regs.flags & BIT(ParityFlagBit)); +} + +int condition_l_nge(BiosEmuEnvironment *env) { + // SF!=OF + return !!(env->regs.flags & BIT(SignFlagBit)) != + !!(env->regs.flags & BIT(OverflowFlagBit)); +} + +int condition_nl_ge(BiosEmuEnvironment *env) { + // SF=OF + return !!(env->regs.flags & BIT(SignFlagBit)) == + !!(env->regs.flags & BIT(OverflowFlagBit)); +} + +int condition_le_ng(BiosEmuEnvironment *env) { + // ZF=1 || SF!=OF + return (env->regs.flags & BIT(ZeroFlagBit)) || + !!(env->regs.flags & BIT(SignFlagBit)) != + !!(env->regs.flags & BIT(OverflowFlagBit)); +} + +int condition_nle_g(BiosEmuEnvironment *env) { + // ZF=0 && SF=OF + return !(env->regs.flags & BIT(ZeroFlagBit)) && + !!(env->regs.flags & BIT(SignFlagBit)) == + !!(env->regs.flags & BIT(OverflowFlagBit)); +} + +int (*condition_table[16])(BiosEmuEnvironment *env) = { + condition_o, condition_no, condition_b_c_nae, condition_ae_nb_nc, + condition_e_z, condition_ne_nz, condition_be_na, condition_a_nbe, + condition_s, condition_ns, condition_p_pe, condition_np_po, + condition_l_nge, condition_nl_ge, condition_le_ng, condition_nle_g}; diff --git a/src/arch/x86/bios_emu/ops/int.c b/src/arch/x86/bios_emu/ops/int.c new file mode 100644 index 0000000..d1f89aa --- /dev/null +++ b/src/arch/x86/bios_emu/ops/int.c @@ -0,0 +1,71 @@ +#include "../includes/flags.h" +#include "../includes/operations.h" +#include "../includes/stack.h" +#include +#include +#include +#include +#include + +BiosEmuExceptions emu_interrupt(int vector) { + BiosEmuEnvironment *env = &bios_emu_env; + env->stop_condition = IntDone; + env->int_entry_stack = STACK_POINTER16(env); + + decode_int(env, vector); + + return emu_run(env); +} + +BiosEmuExceptions decode_int(BiosEmuEnvironment *env, uint8_t vector) { + env->regs.eip++; + if (vector > 255) return GeneralProtection; + if (env->stack_bottom + 6 > STACK_POINTER16(env)) return StackFault; + + PUSH(env, env->regs.flags, 2); + env->regs.flags = BIN_DIS( + env->regs.flags, BIT(InterruptEnableFlagBit) | BIT(TrapFlagBit) | + BIT(AlignmentCheckFlagBit)); + PUSH(env, env->regs.cs, 2); + PUSH(env, env->regs.ip, 2); + + env->regs.cs = env->ivt[vector].segment; + env->regs.ip = env->ivt[vector].offset; + + env->cur_ip = (void *)((env->regs.cs << 4) + env->regs.ip); + + return NoException; +} + +BiosEmuExceptions decode_iret(BiosEmuEnvironment *env) { + if (env->flags.operand_size == 0) { + if (env->flags.stack_size == 0) { + POP16(env, env->regs.eip, 2); + POP16(env, env->regs.cs, 2); + POP16(env, env->regs.flags, 2); + } else { + POP32(env, env->regs.eip, 2); + POP32(env, env->regs.cs, 2); + POP32(env, env->regs.flags, 2); + } + } else { + if (env->flags.stack_size == 0) { + POP16(env, env->regs.eip, 4); + POP16(env, env->regs.cs, 4); + POP16(env, env->regs.eflags, 4); + } else { + uint32_t temp_eflags; + POP32(env, env->regs.eip, 4); + POP32(env, env->regs.cs, 4); + POP32(env, temp_eflags, 4); + env->regs.eflags = + (temp_eflags & 0x257FD5) | (env->regs.eflags & 0x1A0000); + } + } + BiosEmuExceptions exception = NoException; + // 通过栈地址检测是否完成中断功能调用 + if (env->int_entry_stack == STACK_POINTER16(env)) { + exception = EventInterruptDone; + } + return exception; +} \ No newline at end of file diff --git a/src/arch/x86/bios_emu/ops/jmp.c b/src/arch/x86/bios_emu/ops/jmp.c new file mode 100644 index 0000000..37ddbae --- /dev/null +++ b/src/arch/x86/bios_emu/ops/jmp.c @@ -0,0 +1,117 @@ +#include "../includes/operations.h" +#include +#include +#include + +void decode_jcc_8(BiosEmuEnvironment *env, int condition) { + int8_t offset = *(int8_t *)env->cur_ip++; + env->regs.eip++; + if (env->flags.operand_size == 0) { + if (condition) { + env->cur_ip += offset; + env->regs.eip += offset; + env->regs.eip &= 0xffff; + env->cur_ip = (void *)((env->regs.cs << 4) + env->regs.eip); + } + } else { + if (condition) { + env->cur_ip += offset; + env->regs.eip += offset; + } + } + return; +} + +void decode_jcc(BiosEmuEnvironment *env, int condition) { + if (env->flags.address_size == 0) { + int16_t offset = *(int16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + if (condition) { + env->cur_ip += offset; + env->regs.eip += offset; + env->regs.eip &= 0xffff; + env->cur_ip = (void *)((env->regs.cs << 4) + env->regs.eip); + } + } else { + int32_t offset = *(int32_t *)env->cur_ip; + env->cur_ip += 4; + env->regs.eip += 4; + if (condition) { + env->cur_ip += offset; + env->regs.eip += offset; + } + } + return; +} + +void decode_jmp8(BiosEmuEnvironment *env) { + int8_t offset = *(int8_t *)env->cur_ip++; + env->regs.eip++; + env->cur_ip += offset; + env->regs.eip += offset; + if (env->flags.operand_size == 0) { + env->regs.eip &= 0xffff; + env->cur_ip = (void *)((env->regs.cs << 4) + env->regs.eip); + } + return; +} + +void decode_jmp_near(BiosEmuEnvironment *env, int32_t offset) { + if (env->flags.operand_size == 0) { + env->cur_ip += offset; + env->regs.eip += offset; + env->regs.eip &= 0xffff; + env->cur_ip = (void *)((env->regs.cs << 4) + env->regs.eip); + } else { + env->cur_ip += offset; + env->regs.eip += offset; + } + return; +} + +void decode_jmp_far( + BiosEmuEnvironment *env, uint16_t segment, uint32_t offset) { + env->regs.cs = segment; + if (env->flags.operand_size == 0) { + env->regs.eip = offset & 0xffff; + env->cur_ip = (void *)((segment << 4) + env->regs.eip); + } else { + env->regs.eip = offset; + env->cur_ip = (void *)env->regs.eip; + } + return; +} + +void decode_jmp(BiosEmuEnvironment *env) { + if (env->flags.address_size == 0) { + int16_t offset = *(int16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + decode_jmp_near(env, offset); + } else { + int32_t offset = *(int32_t *)env->cur_ip; + env->cur_ip += 4; + env->regs.eip += 4; + decode_jmp_near(env, offset); + } +} + +void decode_long_jmp_ptr16(BiosEmuEnvironment *env) { + uint16_t segment = *(uint16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + if (env->flags.operand_size == 0) { + uint16_t offset = *(uint16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + env->regs.eip &= 0xffff; + env->cur_ip = (void *)((env->regs.cs << 4) + env->regs.eip); + decode_jmp_far(env, segment, offset); + } else { + uint32_t offset = *(uint32_t *)env->cur_ip; + env->cur_ip += 4; + env->regs.eip += 4; + decode_jmp_far(env, segment, offset); + } +} diff --git a/src/arch/x86/bios_emu/ops/mov.c b/src/arch/x86/bios_emu/ops/mov.c new file mode 100644 index 0000000..0c9a5ea --- /dev/null +++ b/src/arch/x86/bios_emu/ops/mov.c @@ -0,0 +1,275 @@ +#include "../includes/decode.h" +#include "../includes/mod_rm.h" +#include "../includes/operations.h" +#include +#include +#include + +void decode_mov_rm_r8(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + uint8_t *dst = RM_ADDR(env, modrm); + uint8_t *src = env->reg_lut_r8[reg]; + *dst = *src; + return; +} + +void decode_mov_rm_r(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + if (env->flags.operand_size == 0) { + uint16_t *dst = RM_ADDR16(env, modrm); + uint16_t *src = env->reg_lut_r16[reg]; + *dst = *src; + } else { + uint32_t *dst = RM_ADDR32(env, modrm); + uint32_t *src = env->reg_lut_r32[reg]; + *dst = *src; + } + + return; +} + +void decode_mov_r_rm_8(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + uint8_t *dst = env->reg_lut_r8[reg]; + uint8_t *src = RM_ADDR(env, modrm); + *dst = *src; + return; +} + +void decode_mov_r_rm(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + if (env->flags.operand_size == 0) { + uint16_t *dst = env->reg_lut_r16[reg]; + uint32_t *src = RM_ADDR16(env, modrm); + *dst = *src; + } else { + uint32_t *dst = env->reg_lut_r32[reg]; + uint32_t *src = RM_ADDR32(env, modrm); + *dst = *src; + } + + return; +} + +void decode_mov_rm_sreg(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + void *dst = RM_ADDR(env, modrm); + if (env->flags.operand_size == 0) { + uint16_t *src = RM_SREG(env, reg); + *(uint16_t *)dst = *src; + } else { + uint32_t *src = RM_SREG(env, reg); + *(uint32_t *)dst = *src; + } + return; +} + +void decode_mov_sreg_rm(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + uint16_t *dst = RM_SREG(env, reg); + uint16_t *src = RM_ADDR(env, modrm); + *dst = *src; + return; +} + +void decode_mov_r_moffs_8(BiosEmuEnvironment *env) { + uint32_t segment = *env->default_ss; + + void *src = (void *)get_segment_base(env, segment); + uint32_t offset; + if (env->flags.address_size == 0) { + offset = *(uint16_t *)env->cur_ip; + env->regs.eip += 2; + env->cur_ip += 2; + } else { + offset = *(uint32_t *)env->cur_ip; + env->regs.eip += 4; + env->cur_ip += 4; + } + src = (void *)((size_t)src + offset); + env->regs.al = *(uint8_t *)src; + return; +} + +void decode_mov_r_moffs(BiosEmuEnvironment *env) { + uint32_t segment = *env->default_ss; + + void *src = (void *)get_segment_base(env, segment); + uint32_t offset; + if (env->flags.address_size == 0) { + offset = *(uint16_t *)env->cur_ip; + env->regs.eip += 2; + env->cur_ip += 2; + } else { + offset = *(uint32_t *)env->cur_ip; + env->regs.eip += 4; + env->cur_ip += 4; + } + src = (void *)((size_t)src + offset); + if (env->flags.operand_size == 0) env->regs.ax = *(uint16_t *)src; + else env->regs.eax = *(uint32_t *)src; + return; +} + +void decode_mov_moffs_r_8(BiosEmuEnvironment *env) { + uint32_t segment = *env->default_ss; + + void *dst = (void *)get_segment_base(env, segment); + uint32_t offset; + if (env->flags.address_size == 0) { + offset = *(uint16_t *)env->cur_ip; + env->regs.eip += 2; + env->cur_ip += 2; + } else { + offset = *(uint32_t *)env->cur_ip; + env->regs.eip += 4; + env->cur_ip += 4; + } + dst = (void *)((size_t)dst + offset); + + *(uint8_t *)dst = env->regs.al; + return; +} + +void decode_mov_moffs_r(BiosEmuEnvironment *env) { + uint32_t segment = *env->default_ss; + + void *dst = (void *)get_segment_base(env, segment); + uint32_t offset; + if (env->flags.address_size == 0) { + offset = *(uint16_t *)env->cur_ip; + env->regs.eip += 2; + env->cur_ip += 2; + } else { + offset = *(uint32_t *)env->cur_ip; + env->regs.eip += 4; + env->cur_ip += 4; + } + dst = (void *)((size_t)dst + offset); + if (env->flags.operand_size == 0) *(uint16_t *)dst = env->regs.ax; + else *(uint32_t *)dst = env->regs.eax; + return; +} + +void decode_mov_r_imm8(BiosEmuEnvironment *env, uint8_t opcode) { + uint8_t *reg = PLUS_RB_REG(env, opcode); + *reg = *(uint8_t *)env->cur_ip++; + env->regs.eip++; +} + +void decode_mov_r_imm(BiosEmuEnvironment *env, uint8_t opcode) { + if (env->flags.operand_size == 0) { + uint16_t *reg = PLUS_RW_REG(env, opcode); + *reg = *(uint16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + } else { + uint32_t *reg = PLUS_RD_REG(env, opcode); + *reg = *(uint32_t *)env->cur_ip; + env->cur_ip += 4; + env->regs.eip += 4; + } +} + +void decode_mov_rm_imm8(BiosEmuEnvironment *env) { + uint8_t *val; + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + + val = RM_ADDR(env, modrm); + *val = *(uint8_t *)env->cur_ip++; + env->regs.eip++; +} + +void decode_mov_rm_imm(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + + if (env->flags.operand_size == 0) { + uint16_t *val = RM_ADDR16(env, modrm); + + *val = *(uint16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + } else { + uint32_t *val = RM_ADDR32(env, modrm); + + *val = *(uint32_t *)env->cur_ip; + env->cur_ip += 4; + env->regs.eip += 4; + } +} + +void decode_movzx_r_rm8(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + if (env->flags.operand_size == 0) { + uint16_t *dst = env->reg_lut_r16[reg]; + uint8_t *src = RM_ADDR16(env, modrm); + *dst = (uint16_t)*src; + } else { + uint32_t *dst = env->reg_lut_r32[reg]; + uint8_t *src = RM_ADDR32(env, modrm); + *dst = (uint32_t)*src; + } + return; +} + +void decode_movzx_r_rm16(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + uint32_t *dst = env->reg_lut_r32[reg]; + uint16_t *src = RM_ADDR32(env, modrm); + *dst = (uint32_t)*src; + return; +} + +void decode_movsx_r_rm8(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + if (env->flags.operand_size == 0) { + uint16_t *dst = env->reg_lut_r16[reg]; + int8_t *src = RM_ADDR16(env, modrm); + *dst = (int16_t)*src; + } else { + uint32_t *dst = env->reg_lut_r32[reg]; + int8_t *src = RM_ADDR32(env, modrm); + *dst = (int32_t)*src; + } + return; +} + +void decode_movsx_r_rm16(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + uint32_t *dst = env->reg_lut_r32[reg]; + int16_t *src = RM_ADDR32(env, modrm); + *dst = (int32_t)*src; + return; +} diff --git a/src/arch/x86/bios_emu/ops/segment.c b/src/arch/x86/bios_emu/ops/segment.c new file mode 100644 index 0000000..b4c3eac --- /dev/null +++ b/src/arch/x86/bios_emu/ops/segment.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +BiosEmuExceptions lds_16_16( + BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr) { + env->regs.ds = *addr++; + *reg = *addr; + + return NoException; +} + +BiosEmuExceptions lds_32_32( + BiosEmuEnvironment *env, uint32_t *reg, uint32_t *addr) { + env->regs.ds = *(uint16_t *)addr; + addr = (uint32_t *)((uint16_t *)addr + 1); + *reg = *addr; + + return NoException; +} + +BiosEmuExceptions les_16_16( + BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr) { + env->regs.es = *addr++; + *reg = *addr; + + return NoException; +} + +BiosEmuExceptions les_32_32( + BiosEmuEnvironment *env, uint32_t *reg, uint32_t *addr) { + env->regs.es = *(uint16_t *)addr; + addr = (uint32_t *)((uint16_t *)addr + 1); + *reg = *addr; + + return NoException; +} \ No newline at end of file diff --git a/src/arch/x86/bios_emu/ops/stack.c b/src/arch/x86/bios_emu/ops/stack.c new file mode 100644 index 0000000..744e1d6 --- /dev/null +++ b/src/arch/x86/bios_emu/ops/stack.c @@ -0,0 +1,126 @@ +#include "../includes/stack.h" +#include "../includes/decode.h" +#include "../includes/mod_rm.h" +#include "../includes/operations.h" +#include +#include +#include + +void decode_pusha_pushad(BiosEmuEnvironment *env) { + if (env->flags.operand_size == 0) { + if (env->flags.stack_size == 0) { + uint16_t temp_sp = env->regs.sp; + PUSH16(env, env->regs.ax, 2); + PUSH16(env, env->regs.cx, 2); + PUSH16(env, env->regs.dx, 2); + PUSH16(env, env->regs.bx, 2); + PUSH16(env, temp_sp, 2); + PUSH16(env, env->regs.bp, 2); + PUSH16(env, env->regs.si, 2); + PUSH16(env, env->regs.di, 2); + } else { + uint16_t temp_sp = env->regs.sp; + PUSH32(env, env->regs.eax, 2); + PUSH32(env, env->regs.ecx, 2); + PUSH32(env, env->regs.edx, 2); + PUSH32(env, env->regs.ebx, 2); + PUSH32(env, temp_sp, 2); + PUSH32(env, env->regs.ebp, 2); + PUSH32(env, env->regs.esi, 2); + PUSH32(env, env->regs.edi, 2); + } + } else { + if (env->flags.stack_size == 0) { + uint32_t temp_esp = env->regs.esp; + PUSH16(env, env->regs.eax, 4); + PUSH16(env, env->regs.ecx, 4); + PUSH16(env, env->regs.edx, 4); + PUSH16(env, env->regs.ebx, 4); + PUSH16(env, temp_esp, 4); + PUSH16(env, env->regs.ebp, 4); + PUSH16(env, env->regs.esi, 4); + PUSH16(env, env->regs.edi, 4); + } else { + uint32_t temp_esp = env->regs.esp; + PUSH32(env, env->regs.eax, 4); + PUSH32(env, env->regs.ecx, 4); + PUSH32(env, env->regs.edx, 4); + PUSH32(env, env->regs.ebx, 4); + PUSH32(env, temp_esp, 4); + PUSH32(env, env->regs.ebp, 4); + PUSH32(env, env->regs.esi, 4); + PUSH32(env, env->regs.edi, 4); + } + } + return; +} + +void decode_pop_rm(BiosEmuEnvironment *env) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + + if (env->flags.operand_size == 0) { + uint16_t *addr = RM_ADDR16(env, modrm); + POP(env, *addr, 2); + } else { + uint32_t *addr = RM_ADDR32(env, modrm); + POP(env, *addr, 4); + } + return; +} + +void decode_pop_r(BiosEmuEnvironment *env, uint8_t opcode) { + if (env->flags.operand_size == 0) { + uint16_t *dst = PLUS_RW_REG(env, opcode); + POP(env, *dst, 2); + } else { + uint32_t *dst = PLUS_RD_REG(env, opcode); + POP(env, *dst, 4); + } + return; +} + +void decode_popa_popad(BiosEmuEnvironment *env) { + if (env->flags.operand_size == 0) { + if (env->flags.stack_size == 0) { + POP16(env, env->regs.di, 2); + POP16(env, env->regs.si, 2); + POP16(env, env->regs.bp, 2); + env->regs.sp += 2; + POP16(env, env->regs.bx, 2); + POP16(env, env->regs.dx, 2); + POP16(env, env->regs.cx, 2); + POP16(env, env->regs.ax, 2); + } else { + POP32(env, env->regs.di, 2); + POP32(env, env->regs.si, 2); + POP32(env, env->regs.bp, 2); + env->regs.esp += 2; + POP32(env, env->regs.bx, 2); + POP32(env, env->regs.dx, 2); + POP32(env, env->regs.cx, 2); + POP32(env, env->regs.ax, 2); + } + } else { + if (env->flags.stack_size == 0) { + POP16(env, env->regs.edi, 4); + POP16(env, env->regs.esi, 4); + POP16(env, env->regs.ebp, 4); + env->regs.sp += 4; + POP16(env, env->regs.ebx, 4); + POP16(env, env->regs.edx, 4); + POP16(env, env->regs.ecx, 4); + POP16(env, env->regs.eax, 4); + } else { + POP32(env, env->regs.edi, 4); + POP32(env, env->regs.esi, 4); + POP32(env, env->regs.ebp, 4); + env->regs.esp += 4; + POP32(env, env->regs.ebx, 4); + POP32(env, env->regs.edx, 4); + POP32(env, env->regs.ecx, 4); + POP32(env, env->regs.eax, 4); + } + } + return; +} \ No newline at end of file diff --git a/src/arch/x86/bios_emu/ops/xchg.c b/src/arch/x86/bios_emu/ops/xchg.c new file mode 100644 index 0000000..a1146e6 --- /dev/null +++ b/src/arch/x86/bios_emu/ops/xchg.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +BiosEmuExceptions xchg_8_8( + BiosEmuEnvironment *env, uint8_t *addr1, uint8_t *addr2) { + uint8_t tmp = *addr1; + *addr1 = *addr2; + *addr2 = tmp; + + return NoException; +} + +BiosEmuExceptions xchg_16_16( + BiosEmuEnvironment *env, uint16_t *addr1, uint16_t *addr2) { + uint16_t tmp = *addr1; + *addr1 = *addr2; + *addr2 = tmp; + + return NoException; +} + +BiosEmuExceptions xchg_32_32( + BiosEmuEnvironment *env, uint16_t *addr1, uint16_t *addr2) { + uint16_t tmp = *addr1; + *addr1 = *addr2; + *addr2 = tmp; + + return NoException; +} diff --git a/src/arch/x86/bios_emu/segment.c b/src/arch/x86/bios_emu/segment.c new file mode 100644 index 0000000..39fab3e --- /dev/null +++ b/src/arch/x86/bios_emu/segment.c @@ -0,0 +1,21 @@ +#include +#include + +size_t get_segment_base(BiosEmuEnvironment *env, uint32_t segment) { + return segment << 4; +} + +uint8_t fetch_data_8(BiosEmuEnvironment *env, uint32_t segment, size_t addr) { + size_t segment_base = get_segment_base(env, segment); + return *(uint8_t *)(segment_base + addr); +} + +uint8_t fetch_data_16(BiosEmuEnvironment *env, uint32_t segment, size_t addr) { + size_t segment_base = get_segment_base(env, segment); + return *(uint16_t *)(segment_base + addr); +} + +uint8_t fetch_data_32(BiosEmuEnvironment *env, uint32_t segment, size_t addr) { + size_t segment_base = get_segment_base(env, segment); + return *(uint32_t *)(segment_base + addr); +} \ No newline at end of file diff --git a/src/arch/x86/bios_emu/todo.md b/src/arch/x86/bios_emu/todo.md new file mode 100644 index 0000000..eb2763f --- /dev/null +++ b/src/arch/x86/bios_emu/todo.md @@ -0,0 +1,205 @@ +## 英特尔手册中列出的实模式下可用的指令及已实现的指令(部分指令未验证是否正确执行): + +The following instructions make up the core instruction set for the 8086 processor. If backwards compatibility to the Intel 286 and Intel 8086 processors is required, only these instructions should be used in a new program written to run in real-address mode. + + - Move (MOV) instructions that move operands between general-purpose registers, segment registers, and between memory and general-purpose registers. + - [x] MOV + + - The exchange (XCHG) instruction. + - [x] XCHG + + - Load segment register instructions LDS and LES. + - [x] LDS + - [x] LES + + - Arithmetic instructions ADD, ADC, SUB, SBB, MUL, IMUL, DIV, IDIV, INC, DEC, CMP, and NEG. + - [x] ADD + - [x] ADC + - [x] SUB + - [x] SBB + - [x] MUL + - [x] IMUL + - [x] DIV + - [x] IDIV + - [x] INC + - [x] DEC + - [x] CMP + - [x] NEG + + - Logical instructions AND, OR, XOR, and NOT. + - [x] AND + - [x] OR + - [x] XOR + - [x] NOT + + - Decimal instructions DAA, DAS, AAA, AAS, AAM, and AAD. + - [x] DAA + - [x] DAS + - [x] AAA + - [x] AAS + - [x] AAM + - [x] AAD + + - Stack instructions PUSH and POP (to general-purpose registers and segment registers). + - [x] PUSH + - [x] POP + + - Type conversion instructions CWD, CDQ, CBW, and CWDE. + - [x] CWD + - [x] CDQ + - [x] CBW + - [x] CWDE + + - Shift and rotate instructions SAL, SHL, SHR, SAR, ROL, ROR, RCL, and RCR. + - [x] SAL + - [x] SHL + - [x] SHR + - [x] SAR + - [x] ROL + - [x] ROR + - [x] RCL + - [x] RCR + + - TEST instruction. + - [x] TEST + + - Control instructions JMP, Jcc, CALL, RET, LOOP, LOOPE, and LOOPNE. + - [x] JMP + - [x] Jcc + - [x] CALL + - [x] RET + - [ ] LOOP + - [ ] LOOPE + - [ ] LOOPNE + + - Interrupt instructions INT n, INTO, and IRET. + - [x] INT n + - [ ] INTO + - [x] IRET + + - EFLAGS control instructions STC, CLC, CMC, CLD, STD, LAHF, SAHF, PUSHF, and POPF. + - [x] STC + - [x] CLC + - [x] CMC + - [x] CLD + - [x] STD + - [x] LAHF + - [x] SAHF + - [x] PUSHF + - [x] POPF + + - I/O instructions IN, INS, OUT, and OUTS. + - [x] IN + - [ ] INS + - [x] OUT + - [ ] OUTS + + - Load effective address (LEA) instruction, and translate (XLATB) instruction. + - [x] LEA + - [ ] XLATB + + - LOCK prefix. + - [ ] LOCK + + - Repeat prefixes REP, REPE, REPZ, REPNE, and REPNZ. + - [ ] REP + - [ ] REPE + - [ ] REPZ + - [ ] REPNE + - [ ] REPNZ + + - Processor halt (HLT) instruction. + - [ ] HLT + + - No operation (NOP) instruction. + - [x] NOP + +The following instructions, added to later IA-32 processors (some in the Intel 286 processor and the remainder in the Intel386 processor), can be executed in real-address mode, if backwards compatibility to the Intel 8086 processor is not required. + + - Move (MOV) instructions that operate on the control and debug registers. + - [ ] MOV + + - Load segment register instructions LSS, LFS, and LGS. + - [ ] LSS + - [ ] LFS + - [ ] LGS + + - Generalized multiply instructions and multiply immediate data. + - [x] + + - Shift and rotate by immediate counts. + - [x] + + - Stack instructions PUSHA, PUSHAD, POPA, POPAD, and PUSH immediate data. + - [ ] PUSHA + - [ ] PUSHAD + - [ ] POPA + - [ ] POPAD + - [x] PUSH + + - Move with sign extension instructions MOVSX and MOVZX. + - [x] MOVSX + - [x] MOVZX + + - Long-displacement Jcc instructions. + - [x] Jcc + + - Exchange instructions CMPXCHG, CMPXCHG8B, and XADD. + - [ ] CMPXCHG + - [ ] CMPXCHG8B + - [ ] XADD + + - String instructions MOVS, CMPS, SCAS, LODS, and STOS. + - [ ] MOVS + - [ ] CMPS + - [ ] SCAS + - [ ] LODS + - [ ] STOS + + - Bit test and bit scan instructions BT, BTS, BTR, BTC, BSF, and BSR; the byte-set-on condition instruction SETcc; and the byte swap (BSWAP) instruction. + - [x] BT + - [x] BTS + - [x] BTR + - [x] BTC + - [ ] BSF + - [ ] BSR + - [x] SETcc + - [ ] BSWAP + + - Double shift instructions SHLD and SHRD. + - [x] SHLD + - [x] SHRD + + - EFLAGS control instructions PUSHF and POPF. + - [ ] PUSHF + - [ ] POPF + + - ENTER and LEAVE control instructions. + - [ ] ENTER + - [ ] LEAVE + + - BOUND instruction. + - [ ] + + - CPU identification (CPUID) instruction. + - [ ] CPUID + + - System instructions CLTS, INVD, WINVD, INVLPG, LGDT, SGDT, LIDT, SIDT, LMSW, SMSW, RDMSR, WRMSR, RDTSC, and RDPMC. + - [ ] CLTS + - [ ] INVD + - [ ] WINVD + - [ ] INVLPG + - [ ] LGDT + - [ ] SGDT + - [ ] LIDT + - [ ] SIDT + - [ ] LMSW + - [ ] SMSW + - [ ] RDMSR + - [ ] WRMSR + - [ ] RDTSC + - [ ] RDPMC + +--- + +### (也许?)遥远的未来可能的改进方向:采用转译而非模拟的方式执行 \ No newline at end of file diff --git a/src/arch/x86/include/bios_emu/bios_emu.h b/src/arch/x86/include/bios_emu/bios_emu.h new file mode 100644 index 0000000..079b2d1 --- /dev/null +++ b/src/arch/x86/include/bios_emu/bios_emu.h @@ -0,0 +1,13 @@ +#ifndef _BIOS_EMU_H +#define _BIOS_EMU_H + +#include +#include + +extern BiosEmuEnvironment bios_emu_env; + +void bios_emu_init(void); +BiosEmuExceptions emu_run(BiosEmuEnvironment *env); +BiosEmuExceptions emu_interrupt(int vector); + +#endif \ No newline at end of file diff --git a/src/arch/x86/include/bios_emu/environment.h b/src/arch/x86/include/bios_emu/environment.h new file mode 100644 index 0000000..1d5cbc5 --- /dev/null +++ b/src/arch/x86/include/bios_emu/environment.h @@ -0,0 +1,66 @@ +#ifndef _BIOS_EMU_ENVIRONMENT_H +#define _BIOS_EMU_ENVIRONMENT_H + +#include + +#define DEF_GENERIC_REG(name) \ + union { \ + struct { \ + uint8_t name##l; \ + uint8_t name##h; \ + }; \ + uint16_t name##x; \ + uint32_t e##name##x; \ + }; +#define DEF_OTHER_REG(name) \ + union { \ + uint16_t name; \ + uint32_t e##name; \ + }; + +typedef struct BiosEmuEnvironment { + // The CPU state + struct { + DEF_GENERIC_REG(a); + DEF_GENERIC_REG(b); + DEF_GENERIC_REG(c); + DEF_GENERIC_REG(d); + DEF_OTHER_REG(si); + DEF_OTHER_REG(di); + DEF_OTHER_REG(bp); + DEF_OTHER_REG(sp); + DEF_OTHER_REG(flags); + DEF_OTHER_REG(ip); + uint32_t cs, ds, es, fs, gs, ss; + } regs; + + void *cur_ip; + uint32_t stack_bottom; + struct { + uint16_t offset; + uint16_t segment; + } *ivt; + struct { + uint8_t stack_size : 1; // 0:16bit, 1:32bit + uint8_t operand_size : 2; // 0:16bit, 1:32bit + uint8_t default_operand_size : 1; + uint8_t address_size : 1; // 0:16bit, 1:32bit + uint8_t default_address_size : 1; + } flags; + uint32_t *default_ss; + + // 寄存器地址查找表 + // 0:al, 1:cl, 2:dl, 3:bl, 4:ah, 5:ch, 6:dh, 7:bh + uint8_t *reg_lut_r8[8]; + // 0:ax, 1:cx, 2:dx, 3:bx, 4:sp, 5:bp, 6:si, 7:di + uint16_t *reg_lut_r16[8]; + // 0:eax, 1:ecx, 2:edx, 3:ebx, 4:esp, 5:ebp, 6:esi, 7:edi + uint32_t *reg_lut_r32[8]; + + enum { + IntDone, + } stop_condition; + size_t int_entry_stack; // 进入中断时的栈指针 +} BiosEmuEnvironment; + +#endif \ No newline at end of file diff --git a/src/arch/x86/include/bios_emu/exceptions.h b/src/arch/x86/include/bios_emu/exceptions.h new file mode 100644 index 0000000..ab4ce49 --- /dev/null +++ b/src/arch/x86/include/bios_emu/exceptions.h @@ -0,0 +1,31 @@ +#ifndef _BIOS_EMU_EXCEPTIONS +#define _BIOS_EMU_EXCEPTIONS + +typedef enum BiosEmuExceptions { + // x86支持的异常,下划线开头的异常是实模式不支持的 + DivideError, + DebugException, + NMIInterrupt, + Breakpoint, + Overflow, + BOUNDRangeExceeded, + InvalidOpcode, + DeviceNotAvailable, + DoubleFault, + _Reserved1, + _InvalidTSS, + _SegmentNotPresent, + StackFault, + GeneralProtection, + _PageFault, + _Reserved2, + FloatPointError, + _AlignmentCheck, + MachineCheck, + + // 下面是自定义的 + NoException, + EventInterruptDone, +} BiosEmuExceptions; + +#endif \ No newline at end of file diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index 5b5b0a7..2e7c471 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -1,3 +1,4 @@ +#include "bios_emu/bios_emu.h" #include #include #include @@ -58,6 +59,8 @@ void platform_init() { read_features(); + bios_emu_init(); + register_vesa_display(); register_pic(); register_apic(); diff --git a/src/include/bits.h b/src/include/bits.h index 0889bc3..5e0bf70 100644 --- a/src/include/bits.h +++ b/src/include/bits.h @@ -23,12 +23,12 @@ #define HOST2LE_WORD(n) (n) #define HOST2LE_DWORD(n) (n) -#define BIT(n) (1 << n) +#define BIT(n) (1 << (n)) #define BIT_FFS_R(n) (bsf(n)) // 从低到高找到第一个非0位的位置 #define BIT_FFS_L(n) (bsr(n)) // 从高到低找到第一个非0位的位置 -#define BIN_EN(n, x) ((n) | x) -#define BIN_DIS(n, x) ((n) & ~x) +#define BIN_EN(n, x) ((n) | (x)) +#define BIN_DIS(n, x) ((n) & ~(x)) #define BIN_IS_DIS(n, x) (!((n) & (x))) #define BIN_IS_EN(n, x) ((!BIN_IS_DIS(n, x))) diff --git a/src/kernel/main.c b/src/kernel/main.c index 956237f..0482c38 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -4,8 +4,11 @@ * @brief 内核主程序 * @date 2020-03 */ +#include "bios_emu/bios_emu.h" +#include "bios_emu/exceptions.h" #include "driver/sound/pcm.h" #include "driver/sound/sound_dm.h" +#include "drivers/vesa_display.h" #include "kernel/page.h" #include "objects/handle.h" #include "string.h" @@ -140,6 +143,20 @@ int main() { do_initcalls(); driver_start_all(); + // bios_emu_env.regs.ax = 0x4f02; + // bios_emu_env.regs.bx = 0x4192; // 1920x1080x32bit模式 + // BiosEmuExceptions exception = emu_interrupt(0x10); // 调用BIOS 0x10中断 + // VideoDevice *video_device; + // video_get_video_device(0, &video_device); + // video_device->mode_info.width = 1920; + // video_device->mode_info.height = 1080; + // init_console(); // 重置控制台配置 + // if (exception == EventInterruptDone) { + // printk("VBE Call Result: %d\n", bios_emu_env.regs.ax); + // } else { + // printk("VBE Error: %d\n", exception); + // } + // thread_start("play", 100, thread_play, NULL, NULL); // const string_t name = STRING_INIT("A folder"); From 8154949d20478412de7cf8f530ba92ec2231a1ef Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 20 Apr 2025 12:03:39 +0800 Subject: [PATCH 051/158] =?UTF-8?q?bios=5Femu:=20=E6=96=B0=E5=A2=9E=20MOVS?= =?UTF-8?q?,CMPS,LODS,STOS,SCAS=E6=8C=87=E4=BB=A4=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/bios_emu/decode.c | 107 ++++++++++++++++++++ src/arch/x86/bios_emu/includes/alu.h | 10 ++ src/arch/x86/bios_emu/includes/decode.h | 11 ++ src/arch/x86/bios_emu/includes/operations.h | 14 +++ src/arch/x86/bios_emu/includes/segment.h | 14 +++ src/arch/x86/bios_emu/ops/alu.c | 48 +++++++++ src/arch/x86/bios_emu/ops/mov.c | 35 +++++++ src/arch/x86/bios_emu/segment.c | 5 + src/arch/x86/bios_emu/todo.md | 20 ++-- src/arch/x86/include/bios_emu/environment.h | 4 +- 10 files changed, 257 insertions(+), 11 deletions(-) diff --git a/src/arch/x86/bios_emu/decode.c b/src/arch/x86/bios_emu/decode.c index 00ead41..1592340 100644 --- a/src/arch/x86/bios_emu/decode.c +++ b/src/arch/x86/bios_emu/decode.c @@ -6,6 +6,7 @@ #include "includes/mod_rm.h" #include "includes/operations.h" #include "includes/prefix.h" +#include "includes/segment.h" #include "includes/stack.h" #include "kernel/func.h" #include @@ -102,6 +103,47 @@ BiosEmuExceptions decode_rm_r_cl( } } +void decode_string_instructions_8( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + OpStr opstr_8) { + int repeat_times; + + if (env->regs.flags & BIT(DirectionFlagBit)) { + delta_dst = -delta_dst; + delta_src = -delta_src; + } + + if (env->flags.operand_size == 0) { + repeat_times = (env->flags.repeat) ? env->regs.cx : 1; + } else { + repeat_times = (env->flags.repeat) ? env->regs.ecx : 1; + } + opstr_8(env, dst, delta_dst, src, delta_src, repeat_times); + return; +} + +void decode_string_instructions_16( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + OpStr opstr_16, OpStr opstr_32) { + int repeat_times; + + if (env->regs.flags & BIT(DirectionFlagBit)) { + delta_dst = -delta_dst; + delta_src = -delta_src; + } + + if (env->flags.operand_size == 0) { + repeat_times = (env->flags.repeat) ? env->regs.cx : 1; + delta_dst <<= 1; + opstr_16(env, dst, delta_dst, src, delta_src, repeat_times); + } else { + repeat_times = (env->flags.repeat) ? env->regs.ecx : 1; + delta_dst <<= 2; + opstr_32(env, dst, delta_dst, src, delta_src, repeat_times); + } + return; +} + BiosEmuExceptions decode_two_bytes_opcode(BiosEmuEnvironment *env) { TwoBytesOpcodes *opcode = env->cur_ip; env->cur_ip++; @@ -213,6 +255,18 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { case OP_CMC: CMC(env); break; + case OP_CMPS8: { + void *src = GET_REG_POINTER(env, ds, si); + void *dst = GET_REG_POINTER(env, es, di); + decode_string_instructions_8(env, dst, 1, src, 1, cmps_8); + break; + } + case OP_CMPS: { + void *src = GET_REG_POINTER(env, ds, si); + void *dst = GET_REG_POINTER(env, es, di); + decode_string_instructions_16(env, dst, 1, src, 1, cmps_16, cmps_32); + break; + } case OP_CWD_CDQ: decode_cwd_cdq(env); break; @@ -295,6 +349,18 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { case OP_LES: decode_r_rm(env, les_16_16, les_32_32); break; + case OP_LODS8: { + void *src = GET_REG_POINTER(env, ds, si); + void *dst = &env->regs.al; + decode_string_instructions_8(env, dst, 0, src, 1, movs_8); + break; + } + case OP_LODS: { + void *src = GET_REG_POINTER(env, ds, si); + void *dst = GET_REG_ADDR(env, ax); + decode_string_instructions_16(env, dst, 0, src, 1, movs_16, movs_32); + break; + } case OP_MOV_rm_r8: decode_mov_rm_r8(env); break; @@ -337,6 +403,18 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { case OP_MOV_rm_imm: decode_mov_rm_imm(env); break; + case OP_MOVS8: { + void *src = GET_REG_POINTER(env, ds, si); + void *dst = GET_REG_POINTER(env, es, di); + decode_string_instructions_8(env, dst, 1, src, 1, movs_8); + break; + } + case OP_MOVS: { + void *src = GET_REG_POINTER(env, ds, si); + void *dst = GET_REG_POINTER(env, es, di); + decode_string_instructions_16(env, dst, 1, src, 1, movs_16, movs_32); + break; + } case OP_NOP: break; case OP_OUT8: @@ -441,6 +519,18 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { case OP_SAHF: SAHF(env); break; + case OP_SCAS8: { + void *src = GET_REG_POINTER(env, es, di); + void *dst = &env->regs.al; + decode_string_instructions_8(env, dst, 0, src, 1, cmps_8); + break; + } + case OP_SCAS: { + void *src = GET_REG_POINTER(env, es, di); + void *dst = GET_REG_ADDR(env, ax); + decode_string_instructions_16(env, dst, 0, src, 1, cmps_16, cmps_32); + break; + } case OP_STC: STC(env); break; @@ -451,6 +541,18 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { STI(env); io_sti(); break; + case OP_STOS8: { + void *src = &env->regs.al; + void *dst = (void *)get_phy_addr(env, env->regs.es, env->regs.di); + decode_string_instructions_8(env, dst, 1, src, 0, movs_8); + break; + } + case OP_STOS: { + void *src = GET_REG_ADDR(env, ax); + void *dst = (void *)get_phy_addr(env, env->regs.es, env->regs.di); + decode_string_instructions_16(env, dst, 1, src, 0, movs_16, movs_32); + break; + } case OP_TEST_imm8: calc_a_imm8(env, CALC_TEST); break; @@ -535,6 +637,7 @@ BiosEmuExceptions emu_run_instruction(BiosEmuEnvironment *env) { env->default_ss = &env->regs.ds; env->flags.operand_size = env->flags.default_operand_size; env->flags.address_size = env->flags.default_address_size; + env->flags.repeat = 0; int flag = 1; while (flag) { prefix = *(BiosEmuPrefixes *)env->cur_ip; @@ -544,8 +647,12 @@ BiosEmuExceptions emu_run_instruction(BiosEmuEnvironment *env) { case PREFIX_LOCK: break; case PREFIX_REPNE_REPNZ_BND: + env->flags.repeat = 1; + env->flags.rep_e_ne = 0; break; case PREFIX_REP_REPE_REPZ: + env->flags.repeat = 1; + env->flags.rep_e_ne = 1; break; case PREFIX_CS_OVERRIDE_BRANCH_NOT_TAKEN: env->default_ss = &env->regs.cs; diff --git a/src/arch/x86/bios_emu/includes/alu.h b/src/arch/x86/bios_emu/includes/alu.h index 0f9c824..7afeec4 100644 --- a/src/arch/x86/bios_emu/includes/alu.h +++ b/src/arch/x86/bios_emu/includes/alu.h @@ -113,4 +113,14 @@ void sar_8(BiosEmuEnvironment *env, uint8_t *value, uint8_t count); void sar_16(BiosEmuEnvironment *env, uint16_t *value, uint8_t count); void sar_32(BiosEmuEnvironment *env, uint32_t *value, uint8_t count); +void cmps_8( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); +void cmps_16( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); +void cmps_32( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); + #endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/decode.h b/src/arch/x86/bios_emu/includes/decode.h index 90a94e1..06959e2 100644 --- a/src/arch/x86/bios_emu/includes/decode.h +++ b/src/arch/x86/bios_emu/includes/decode.h @@ -23,6 +23,17 @@ typedef enum OperandDataType { OPDT_Qword, } OperandDataType; +#define GET_REG_ADDR(env, reg) \ + ({ \ + void *addr; \ + if (env->flags.operand_size == 0) { \ + addr = &env->regs.reg; \ + } else { \ + addr = &env->regs.e##reg; \ + } \ + addr; \ + }) + #define DEF_OP1(type) \ typedef BiosEmuExceptions (*Op1_##type)( \ BiosEmuEnvironment * env, uint##type##_t * value); diff --git a/src/arch/x86/bios_emu/includes/operations.h b/src/arch/x86/bios_emu/includes/operations.h index 53d21d7..963f143 100644 --- a/src/arch/x86/bios_emu/includes/operations.h +++ b/src/arch/x86/bios_emu/includes/operations.h @@ -136,4 +136,18 @@ BiosEmuExceptions bts_16_16( BiosEmuExceptions bts_32_32( BiosEmuEnvironment *env, uint32_t *addr, uint32_t *bit); +typedef void (*OpStr)( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); +void decode_movs(BiosEmuEnvironment *env, OpStr movs_16, OpStr movs_32); +void movs_8( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); +void movs_16( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); +void movs_32( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); + #endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/segment.h b/src/arch/x86/bios_emu/includes/segment.h index c432813..0cfff57 100644 --- a/src/arch/x86/bios_emu/includes/segment.h +++ b/src/arch/x86/bios_emu/includes/segment.h @@ -5,9 +5,23 @@ #include size_t get_segment_base(BiosEmuEnvironment *env, uint32_t segment); +size_t get_phy_addr(BiosEmuEnvironment *env, uint32_t segment, size_t addr); uint8_t fetch_data_8(BiosEmuEnvironment *env, uint32_t segment, size_t addr); uint8_t fetch_data_16(BiosEmuEnvironment *env, uint32_t segment, size_t addr); uint8_t fetch_data_32(BiosEmuEnvironment *env, uint32_t segment, size_t addr); +#define GET_REG_POINTER(env, segment, reg) \ + ({ \ + void *addr; \ + if (env->flags.operand_size == 0) { \ + addr = \ + (void *)get_phy_addr(env, env->regs.segment, env->regs.reg); \ + } else { \ + addr = (void *)get_phy_addr( \ + env, env->regs.segment, env->regs.e##reg); \ + } \ + addr; \ + }) + #endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/ops/alu.c b/src/arch/x86/bios_emu/ops/alu.c index bf6a067..2439088 100644 --- a/src/arch/x86/bios_emu/ops/alu.c +++ b/src/arch/x86/bios_emu/ops/alu.c @@ -1301,3 +1301,51 @@ BiosEmuExceptions shrd_32_32_8( *dest = ans; return NoException; } + +void cmps_8( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times) { + int condition = 1; + int i; + for (i = repeat_times; i > 0 && condition; i--) { + cmp_8(env, dst, *(uint8_t *)src); + + dst += delta_dst; + src += delta_src; + condition = + ((env->regs.flags >> ZeroFlagBit) & 1) == env->flags.rep_e_ne; + } + env->regs.cx = (env->flags.repeat) ? i : env->regs.cx; +} + +void cmps_16( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times) { + int condition = 1; + int i; + for (i = repeat_times; i > 0 && condition; i--) { + cmp_32(env, dst, *(uint16_t *)src); + + dst += delta_dst; + src += delta_src; + condition = + ((env->regs.flags >> ZeroFlagBit) & 1) == env->flags.rep_e_ne; + } + env->regs.cx = (env->flags.repeat) ? i : env->regs.cx; +} + +void cmps_32( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times) { + int condition = 1; + int i; + for (i = repeat_times; i > 0 && condition; i--) { + cmp_32(env, dst, *(uint32_t *)src); + + dst += delta_dst; + src += delta_src; + condition = + ((env->regs.flags >> ZeroFlagBit) & 1) == env->flags.rep_e_ne; + } + env->regs.ecx = (env->flags.repeat) ? i : env->regs.ecx; +} diff --git a/src/arch/x86/bios_emu/ops/mov.c b/src/arch/x86/bios_emu/ops/mov.c index 0c9a5ea..74a4f93 100644 --- a/src/arch/x86/bios_emu/ops/mov.c +++ b/src/arch/x86/bios_emu/ops/mov.c @@ -1,4 +1,5 @@ #include "../includes/decode.h" +#include "../includes/flags.h" #include "../includes/mod_rm.h" #include "../includes/operations.h" #include @@ -273,3 +274,37 @@ void decode_movsx_r_rm16(BiosEmuEnvironment *env) { *dst = (int32_t)*src; return; } + +void movs_8( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times) { + for (int i = 0; i < repeat_times; i++) { + *(uint8_t *)dst = *(uint8_t *)src; + + dst += delta_dst; + src += delta_src; + } + return; +} + +void movs_16( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times) { + for (int i = 0; i < repeat_times; i++) { + *(uint16_t *)dst = *(uint16_t *)src; + + dst += delta_dst; + src += delta_src; + } +} + +void movs_32( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times) { + for (int i = 0; i < repeat_times; i++) { + *(uint32_t *)dst = *(uint32_t *)src; + + dst += delta_dst; + src += delta_src; + } +} diff --git a/src/arch/x86/bios_emu/segment.c b/src/arch/x86/bios_emu/segment.c index 39fab3e..79c6b27 100644 --- a/src/arch/x86/bios_emu/segment.c +++ b/src/arch/x86/bios_emu/segment.c @@ -5,6 +5,11 @@ size_t get_segment_base(BiosEmuEnvironment *env, uint32_t segment) { return segment << 4; } +size_t get_phy_addr(BiosEmuEnvironment *env, uint32_t segment, size_t addr) { + size_t segment_base = get_segment_base(env, segment); + return segment_base + addr; +} + uint8_t fetch_data_8(BiosEmuEnvironment *env, uint32_t segment, size_t addr) { size_t segment_base = get_segment_base(env, segment); return *(uint8_t *)(segment_base + addr); diff --git a/src/arch/x86/bios_emu/todo.md b/src/arch/x86/bios_emu/todo.md index eb2763f..67cf671 100644 --- a/src/arch/x86/bios_emu/todo.md +++ b/src/arch/x86/bios_emu/todo.md @@ -102,11 +102,11 @@ The following instructions make up the core instruction set for the 8086 process - [ ] LOCK - Repeat prefixes REP, REPE, REPZ, REPNE, and REPNZ. - - [ ] REP - - [ ] REPE - - [ ] REPZ - - [ ] REPNE - - [ ] REPNZ + - [x] REP + - [x] REPE + - [x] REPZ + - [x] REPNE + - [x] REPNZ - Processor halt (HLT) instruction. - [ ] HLT @@ -150,11 +150,11 @@ The following instructions, added to later IA-32 processors (some in the Intel 2 - [ ] XADD - String instructions MOVS, CMPS, SCAS, LODS, and STOS. - - [ ] MOVS - - [ ] CMPS - - [ ] SCAS - - [ ] LODS - - [ ] STOS + - [x] MOVS + - [x] CMPS + - [x] SCAS + - [x] LODS + - [x] STOS - Bit test and bit scan instructions BT, BTS, BTR, BTC, BSF, and BSR; the byte-set-on condition instruction SETcc; and the byte swap (BSWAP) instruction. - [x] BT diff --git a/src/arch/x86/include/bios_emu/environment.h b/src/arch/x86/include/bios_emu/environment.h index 1d5cbc5..a191425 100644 --- a/src/arch/x86/include/bios_emu/environment.h +++ b/src/arch/x86/include/bios_emu/environment.h @@ -41,8 +41,10 @@ typedef struct BiosEmuEnvironment { uint16_t segment; } *ivt; struct { + uint8_t repeat : 1; + uint8_t rep_e_ne : 1; // 0:repne/repnz, 1:repe/repz uint8_t stack_size : 1; // 0:16bit, 1:32bit - uint8_t operand_size : 2; // 0:16bit, 1:32bit + uint8_t operand_size : 1; // 0:16bit, 1:32bit uint8_t default_operand_size : 1; uint8_t address_size : 1; // 0:16bit, 1:32bit uint8_t default_address_size : 1; From 955fbf901055fc86eef943b7bb7b769f0b7eaa7e Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 20 Apr 2025 12:19:51 +0800 Subject: [PATCH 052/158] =?UTF-8?q?bios=5Femu:=20=E6=96=B0=E5=A2=9E=20LOOP?= =?UTF-8?q?,LOOPE,LOOPNE,INTO=E6=8C=87=E4=BB=A4=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/bios_emu/decode.c | 41 +++++++++++++++++++ .../x86/bios_emu/includes/instructions_1.h | 6 ++- src/arch/x86/bios_emu/todo.md | 8 ++-- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/arch/x86/bios_emu/decode.c b/src/arch/x86/bios_emu/decode.c index 1592340..ba12a19 100644 --- a/src/arch/x86/bios_emu/decode.c +++ b/src/arch/x86/bios_emu/decode.c @@ -307,6 +307,11 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { case OP_INT: exception = decode_int(env, *(uint8_t *)env->cur_ip++); break; + case OP_INTO: + if (env->regs.flags & BIT(OverflowFlagBit)) { + exception = decode_int(env, 4); + } + break; case OP_IRET_IRETD: exception = decode_iret(env); break; @@ -361,6 +366,42 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { decode_string_instructions_16(env, dst, 0, src, 1, movs_16, movs_32); break; } + case OP_LOOP: { + uint32_t count; + if (env->flags.operand_size == 0) { + env->regs.cx--; + count = env->regs.cx; + } else { + env->regs.ecx--; + count = env->regs.ecx; + } + if (count) decode_jmp8(env); + break; + } + case OP_LOOPE: { + uint32_t count; + if (env->flags.operand_size == 0) { + env->regs.cx--; + count = env->regs.cx; + } else { + env->regs.ecx--; + count = env->regs.ecx; + } + if (count) decode_jcc(env, condition_table[4](env)); + break; + } + case OP_LOOPNE: { + uint32_t count; + if (env->flags.operand_size == 0) { + env->regs.cx--; + count = env->regs.cx; + } else { + env->regs.ecx--; + count = env->regs.ecx; + } + if (count) decode_jcc(env, condition_table[5](env)); + break; + } case OP_MOV_rm_r8: decode_mov_rm_r8(env); break; diff --git a/src/arch/x86/bios_emu/includes/instructions_1.h b/src/arch/x86/bios_emu/includes/instructions_1.h index c400b95..163f9cb 100644 --- a/src/arch/x86/bios_emu/includes/instructions_1.h +++ b/src/arch/x86/bios_emu/includes/instructions_1.h @@ -88,7 +88,7 @@ typedef enum OneByteOpcodes { OP_INT3 = 0xCC, OP_INT = 0xCD, - OP_INT0 = 0xCE, + OP_INTO = 0xCE, OP_INT1 = 0xF1, OP_IRET_IRETD = 0xCF, @@ -127,6 +127,10 @@ typedef enum OneByteOpcodes { OP_LODS8 = 0xAC, OP_LODS = 0xAD, + OP_LOOP = 0xE2, + OP_LOOPE = 0xE1, + OP_LOOPNE = 0xE0, + // One Byte Opcode Instructions M-U OP_MOV_rm_r8 = 0x88, diff --git a/src/arch/x86/bios_emu/todo.md b/src/arch/x86/bios_emu/todo.md index 67cf671..dd38fdb 100644 --- a/src/arch/x86/bios_emu/todo.md +++ b/src/arch/x86/bios_emu/todo.md @@ -68,13 +68,13 @@ The following instructions make up the core instruction set for the 8086 process - [x] Jcc - [x] CALL - [x] RET - - [ ] LOOP - - [ ] LOOPE - - [ ] LOOPNE + - [x] LOOP + - [x] LOOPE + - [x] LOOPNE - Interrupt instructions INT n, INTO, and IRET. - [x] INT n - - [ ] INTO + - [x] INTO - [x] IRET - EFLAGS control instructions STC, CLC, CMC, CLD, STD, LAHF, SAHF, PUSHF, and POPF. From 966d5fb1df608e705340c237134764a4cf9d0137 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 20 Apr 2025 16:38:05 +0800 Subject: [PATCH 053/158] =?UTF-8?q?bios=5Femu:=20=E6=96=B0=E5=A2=9EINS,OUT?= =?UTF-8?q?S,HLT,XLAT=E6=8C=87=E4=BB=A4=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/bios_emu/decode.c | 36 +++++++++++++ src/arch/x86/bios_emu/includes/operations.h | 19 +++++++ src/arch/x86/bios_emu/operations.c | 60 +++++++++++++++++++++ src/arch/x86/bios_emu/todo.md | 8 +-- src/arch/x86/include/bios_emu/exceptions.h | 1 + 5 files changed, 120 insertions(+), 4 deletions(-) diff --git a/src/arch/x86/bios_emu/decode.c b/src/arch/x86/bios_emu/decode.c index ba12a19..8e6f908 100644 --- a/src/arch/x86/bios_emu/decode.c +++ b/src/arch/x86/bios_emu/decode.c @@ -279,6 +279,9 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { case OP_DEC ...(OP_DEC + 7): decode_dec_r(env, *opcode); break; + case OP_HLT: + exception = EventHalted; + break; case OP_IMUL_imm8: decode_imul_r_rm_imm8(env); break; @@ -301,6 +304,18 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { case OP_IN_dx: decode_in(env, env->regs.dx); break; + case OP_INS8: { + void *src = &env->regs.dx; + void *dst = GET_REG_POINTER(env, ds, si); + decode_string_instructions_8(env, dst, 0, src, 1, ins_8); + break; + } + case OP_INS: { + void *src = &env->regs.dx; + void *dst = GET_REG_POINTER(env, ds, si); + decode_string_instructions_16(env, dst, 0, src, 1, ins_16, ins_32); + break; + } case OP_INC ...(OP_INC + 7): decode_inc_r(env, *opcode); break; @@ -474,6 +489,18 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { case OP_OUT_dx: decode_out(env, env->regs.dx); break; + case OP_OUTS8: { + void *src = GET_REG_POINTER(env, ds, si); + void *dst = &env->regs.dx; + decode_string_instructions_8(env, dst, 1, src, 0, outs_8); + break; + } + case OP_OUTS: { + void *src = GET_REG_POINTER(env, ds, si); + void *dst = &env->regs.dx; + decode_string_instructions_16(env, dst, 1, src, 0, outs_16, outs_32); + break; + } case OP_POP_rm: decode_pop_rm(env); break; @@ -621,6 +648,15 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { case OP_XCHG: decode_rm_r(env, xchg_16_16, xchg_32_32); break; + case OP_XLAT: + if (env->flags.operand_size == 0) { + env->regs.al = *(uint8_t *)get_phy_addr( + env, env->regs.ds, env->regs.bx + env->regs.al); + } else { + env->regs.al = *(uint32_t *)get_phy_addr( + env, env->regs.ds, env->regs.ebx + env->regs.al); + } + break; ALU_CASE(ADC) ALU_CASE(ADD) ALU_CASE(AND) diff --git a/src/arch/x86/bios_emu/includes/operations.h b/src/arch/x86/bios_emu/includes/operations.h index 963f143..3960bb6 100644 --- a/src/arch/x86/bios_emu/includes/operations.h +++ b/src/arch/x86/bios_emu/includes/operations.h @@ -150,4 +150,23 @@ void movs_32( BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, int repeat_times); +void ins_8( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); +void ins_16( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); +void ins_32( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); +void outs_8( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); +void outs_16( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); +void outs_32( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times); + #endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/operations.c b/src/arch/x86/bios_emu/operations.c index 08ef0e4..82d0403 100644 --- a/src/arch/x86/bios_emu/operations.c +++ b/src/arch/x86/bios_emu/operations.c @@ -433,6 +433,66 @@ void decode_out(BiosEmuEnvironment *env, uint16_t port) { } } +void ins_8( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times) { + __asm__ volatile("cld;" + "rep insb;" + : + : "D"(dst), "S"(src), "c"(env->regs.cx), "d"(env->regs.dx) + : "cc", "memory"); +} + +void ins_16( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times) { + __asm__ volatile("cld;" + "rep insw;" + : + : "D"(dst), "S"(src), "c"(env->regs.cx), "d"(env->regs.dx) + : "cc", "memory"); +} + +void ins_32( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times) { + __asm__ volatile("cld;" + "rep insl;" + : + : "D"(dst), "S"(src), "c"(env->regs.ecx), "d"(env->regs.dx) + : "cc", "memory"); +} + +void outs_8( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times) { + __asm__ volatile("cld;" + "rep outsb;" + : + : "D"(dst), "S"(src), "c"(env->regs.cx), "d"(env->regs.dx) + : "cc", "memory"); +} + +void outs_16( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times) { + __asm__ volatile("cld;" + "rep outsw;" + : + : "D"(dst), "S"(src), "c"(env->regs.cx), "d"(env->regs.dx) + : "cc", "memory"); +} + +void outs_32( + BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, + int repeat_times) { + __asm__ volatile("cld;" + "rep outsl;" + : + : "D"(dst), "S"(src), "c"(env->regs.ecx), "d"(env->regs.dx) + : "cc", "memory"); +} + void decode_lea(BiosEmuEnvironment *env) { uint8_t modrm = *(uint8_t *)env->cur_ip++; env->regs.eip++; diff --git a/src/arch/x86/bios_emu/todo.md b/src/arch/x86/bios_emu/todo.md index dd38fdb..e17bcd3 100644 --- a/src/arch/x86/bios_emu/todo.md +++ b/src/arch/x86/bios_emu/todo.md @@ -90,13 +90,13 @@ The following instructions make up the core instruction set for the 8086 process - I/O instructions IN, INS, OUT, and OUTS. - [x] IN - - [ ] INS + - [x] INS - [x] OUT - - [ ] OUTS + - [x] OUTS - Load effective address (LEA) instruction, and translate (XLATB) instruction. - [x] LEA - - [ ] XLATB + - [x] XLATB - LOCK prefix. - [ ] LOCK @@ -109,7 +109,7 @@ The following instructions make up the core instruction set for the 8086 process - [x] REPNZ - Processor halt (HLT) instruction. - - [ ] HLT + - [x] HLT - No operation (NOP) instruction. - [x] NOP diff --git a/src/arch/x86/include/bios_emu/exceptions.h b/src/arch/x86/include/bios_emu/exceptions.h index ab4ce49..382c45c 100644 --- a/src/arch/x86/include/bios_emu/exceptions.h +++ b/src/arch/x86/include/bios_emu/exceptions.h @@ -26,6 +26,7 @@ typedef enum BiosEmuExceptions { // 下面是自定义的 NoException, EventInterruptDone, + EventHalted, } BiosEmuExceptions; #endif \ No newline at end of file From 24467d052e6e648f5d4df0e863b0d21d80f2b778 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 20 Apr 2025 16:55:50 +0800 Subject: [PATCH 054/158] =?UTF-8?q?bios=5Femu:=20=E6=96=B0=E5=A2=9E=20LSS,?= =?UTF-8?q?LFS,LGS=E6=8C=87=E4=BB=A4=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/bios_emu/decode.c | 9 ++++ src/arch/x86/bios_emu/includes/operations.h | 12 +++++ src/arch/x86/bios_emu/ops/segment.c | 52 ++++++++------------- src/arch/x86/bios_emu/todo.md | 18 +++---- 4 files changed, 49 insertions(+), 42 deletions(-) diff --git a/src/arch/x86/bios_emu/decode.c b/src/arch/x86/bios_emu/decode.c index 8e6f908..49fa4b4 100644 --- a/src/arch/x86/bios_emu/decode.c +++ b/src/arch/x86/bios_emu/decode.c @@ -170,6 +170,15 @@ BiosEmuExceptions decode_two_bytes_opcode(BiosEmuEnvironment *env) { case OP_Jcc ...(OP_Jcc + 15): decode_jcc(env, condition_table[*opcode & 0x0f](env)); break; + case OP_LSS: + decode_rm_r(env, lss_16_16, lss_32_32); + break; + case OP_LFS: + decode_rm_r(env, lfs_16_16, lfs_32_32); + break; + case OP_LGS: + decode_rm_r(env, lgs_16_16, lgs_32_32); + break; case OP_MOVZX_r_rm8: decode_movzx_r_rm8(env); break; diff --git a/src/arch/x86/bios_emu/includes/operations.h b/src/arch/x86/bios_emu/includes/operations.h index 3960bb6..5a0caeb 100644 --- a/src/arch/x86/bios_emu/includes/operations.h +++ b/src/arch/x86/bios_emu/includes/operations.h @@ -102,10 +102,22 @@ BiosEmuExceptions lds_16_16( BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr); BiosEmuExceptions lds_32_32( BiosEmuEnvironment *env, uint32_t *reg, uint32_t *addr); +BiosEmuExceptions lss_16_16( + BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr); +BiosEmuExceptions lss_32_32( + BiosEmuEnvironment *env, uint32_t *reg, uint32_t *addr); BiosEmuExceptions les_16_16( BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr); BiosEmuExceptions les_32_32( BiosEmuEnvironment *env, uint32_t *reg, uint32_t *addr); +BiosEmuExceptions lfs_16_16( + BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr); +BiosEmuExceptions lfs_32_32( + BiosEmuEnvironment *env, uint32_t *reg, uint32_t *addr); +BiosEmuExceptions lgs_16_16( + BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr); +BiosEmuExceptions lgs_32_32( + BiosEmuEnvironment *env, uint32_t *reg, uint32_t *addr); BiosEmuExceptions shld_16_16_8( BiosEmuEnvironment *env, uint16_t *dest, uint16_t reg, uint8_t count); diff --git a/src/arch/x86/bios_emu/ops/segment.c b/src/arch/x86/bios_emu/ops/segment.c index b4c3eac..0258b72 100644 --- a/src/arch/x86/bios_emu/ops/segment.c +++ b/src/arch/x86/bios_emu/ops/segment.c @@ -3,36 +3,22 @@ #include #include -BiosEmuExceptions lds_16_16( - BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr) { - env->regs.ds = *addr++; - *reg = *addr; - - return NoException; -} - -BiosEmuExceptions lds_32_32( - BiosEmuEnvironment *env, uint32_t *reg, uint32_t *addr) { - env->regs.ds = *(uint16_t *)addr; - addr = (uint32_t *)((uint16_t *)addr + 1); - *reg = *addr; - - return NoException; -} - -BiosEmuExceptions les_16_16( - BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr) { - env->regs.es = *addr++; - *reg = *addr; - - return NoException; -} - -BiosEmuExceptions les_32_32( - BiosEmuEnvironment *env, uint32_t *reg, uint32_t *addr) { - env->regs.es = *(uint16_t *)addr; - addr = (uint32_t *)((uint16_t *)addr + 1); - *reg = *addr; - - return NoException; -} \ No newline at end of file +#define DEF_LXS(sreg) \ + BiosEmuExceptions l##sreg##_16_16( \ + BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr) { \ + env->regs.sreg = *addr++; \ + *reg = *addr; \ + return NoException; \ + } \ + BiosEmuExceptions l##sreg##_32_32( \ + BiosEmuEnvironment *env, uint32_t *reg, uint32_t *addr) { \ + env->regs.ds = *(uint16_t *)addr; \ + addr = (uint32_t *)((uint16_t *)addr + 1); \ + return NoException; \ + } + +DEF_LXS(ds) +DEF_LXS(ss) +DEF_LXS(es) +DEF_LXS(fs) +DEF_LXS(gs) \ No newline at end of file diff --git a/src/arch/x86/bios_emu/todo.md b/src/arch/x86/bios_emu/todo.md index e17bcd3..704d10a 100644 --- a/src/arch/x86/bios_emu/todo.md +++ b/src/arch/x86/bios_emu/todo.md @@ -120,9 +120,9 @@ The following instructions, added to later IA-32 processors (some in the Intel 2 - [ ] MOV - Load segment register instructions LSS, LFS, and LGS. - - [ ] LSS - - [ ] LFS - - [ ] LGS + - [x] LSS + - [x] LFS + - [x] LGS - Generalized multiply instructions and multiply immediate data. - [x] @@ -131,10 +131,10 @@ The following instructions, added to later IA-32 processors (some in the Intel 2 - [x] - Stack instructions PUSHA, PUSHAD, POPA, POPAD, and PUSH immediate data. - - [ ] PUSHA - - [ ] PUSHAD - - [ ] POPA - - [ ] POPAD + - [x] PUSHA + - [x] PUSHAD + - [x] POPA + - [x] POPAD - [x] PUSH - Move with sign extension instructions MOVSX and MOVZX. @@ -171,8 +171,8 @@ The following instructions, added to later IA-32 processors (some in the Intel 2 - [x] SHRD - EFLAGS control instructions PUSHF and POPF. - - [ ] PUSHF - - [ ] POPF + - [x] PUSHF + - [x] POPF - ENTER and LEAVE control instructions. - [ ] ENTER From a89defd0723f11794c6acc6a7b794c9258896d21 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 20 Apr 2025 17:26:48 +0800 Subject: [PATCH 055/158] =?UTF-8?q?bios=5Femu:=20=E6=96=B0=E5=A2=9E=20CMPX?= =?UTF-8?q?CHG,XADD,BSF,BSR=E6=8C=87=E4=BB=A4=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/bios_emu/decode.c | 18 ++++++ src/arch/x86/bios_emu/includes/flags.h | 12 ++++ .../x86/bios_emu/includes/instructions_2.h | 6 +- src/arch/x86/bios_emu/includes/operations.h | 23 +++++++ src/arch/x86/bios_emu/operations.c | 50 +++++++++++++++ src/arch/x86/bios_emu/ops/alu.c | 12 ---- src/arch/x86/bios_emu/ops/xchg.c | 61 +++++++++++++++++++ src/arch/x86/bios_emu/todo.md | 8 +-- 8 files changed, 171 insertions(+), 19 deletions(-) diff --git a/src/arch/x86/bios_emu/decode.c b/src/arch/x86/bios_emu/decode.c index 49fa4b4..90d023f 100644 --- a/src/arch/x86/bios_emu/decode.c +++ b/src/arch/x86/bios_emu/decode.c @@ -149,6 +149,12 @@ BiosEmuExceptions decode_two_bytes_opcode(BiosEmuEnvironment *env) { env->cur_ip++; env->regs.eip++; switch ((uint8_t)*opcode) { + case OP_BSF_TZCNT: + decode_rm_r(env, bsf_16_16, bsf_32_32); + break; + case OP_BSR_LZCNT: + decode_rm_r(env, bsr_16_16, bsr_32_32); + break; case OP_BT: decode_rm_r(env, bt_16_16, bt_32_32); break; @@ -161,6 +167,12 @@ BiosEmuExceptions decode_two_bytes_opcode(BiosEmuEnvironment *env) { case OP_BTS: decode_rm_r(env, bts_16_16, bts_32_32); break; + case OP_CMPXCHG8: + decode_rm8_r8(env, cmpxchg_8_8); + break; + case OP_CMPXCHG: + decode_rm_r(env, cmpxchg_16_16, cmpxchg_32_32); + break; case 0xba: decode_0xba(env); break; @@ -218,6 +230,12 @@ BiosEmuExceptions decode_two_bytes_opcode(BiosEmuEnvironment *env) { case OP_SHRD_cl: decode_rm_r_cl(env, shrd_16_16_8, shrd_32_32_8); break; + case OP_XADD_rm_r_8: + decode_rm8_r8(env, xadd_8_8); + break; + case OP_XADD_rm_r: + decode_rm_r(env, xadd_16_16, xadd_32_32); + break; default: return InvalidOpcode; } diff --git a/src/arch/x86/bios_emu/includes/flags.h b/src/arch/x86/bios_emu/includes/flags.h index 6fd53fa..92296f2 100644 --- a/src/arch/x86/bios_emu/includes/flags.h +++ b/src/arch/x86/bios_emu/includes/flags.h @@ -22,4 +22,16 @@ #define VirtualInterruptPendingFlagBit 20 #define IDFlagBit 21 +#define SET_FLAG(x, bit) \ + env->regs.flags = \ + (x) ? env->regs.flags | BIT(bit) : env->regs.flags & ~BIT(bit) + +#define SET_CARRY_FLAG(x) SET_FLAG(x, CarryFlagBit) +#define SET_OVERFLOW_FLAG(x) SET_FLAG(x, OverflowFlagBit) +#define SET_SIGN_FLAG(x) SET_FLAG(x, SignFlagBit) + +#define SIGN_FLAG8(x) SET_SIGN_FLAG(x >> 7) +#define SIGN_FLAG16(x) SET_SIGN_FLAG(x >> 15) +#define SIGN_FLAG32(x) SET_SIGN_FLAG(x >> 31) + #endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/includes/instructions_2.h b/src/arch/x86/bios_emu/includes/instructions_2.h index cd9eb34..290926f 100644 --- a/src/arch/x86/bios_emu/includes/instructions_2.h +++ b/src/arch/x86/bios_emu/includes/instructions_2.h @@ -69,9 +69,9 @@ typedef enum TwoBytesOpcodes { OP_POPCNT = 0xB8, - OP_BTC = 0xB9, - OP_BSF_TZCNT = 0xBA, - OP_BSR_LZCNT = 0xBB, + OP_BTC = 0xBB, + OP_BSF_TZCNT = 0xBC, + OP_BSR_LZCNT = 0xBD, OP_XADD_rm_r_8 = 0xC0, OP_XADD_rm_r = 0xC1, diff --git a/src/arch/x86/bios_emu/includes/operations.h b/src/arch/x86/bios_emu/includes/operations.h index 5a0caeb..32f81b6 100644 --- a/src/arch/x86/bios_emu/includes/operations.h +++ b/src/arch/x86/bios_emu/includes/operations.h @@ -98,6 +98,20 @@ BiosEmuExceptions xchg_16_16( BiosEmuExceptions xchg_32_32( BiosEmuEnvironment *env, uint32_t *addr1, uint32_t *addr2); +BiosEmuExceptions cmpxchg_8_8( + BiosEmuEnvironment *env, uint8_t *addr1, uint8_t *addr2); +BiosEmuExceptions cmpxchg_16_16( + BiosEmuEnvironment *env, uint16_t *addr1, uint16_t *addr2); +BiosEmuExceptions cmpxchg_32_32( + BiosEmuEnvironment *env, uint32_t *addr1, uint32_t *addr2); + +BiosEmuExceptions xadd_8_8( + BiosEmuEnvironment *env, uint8_t *addr1, uint8_t *addr2); +BiosEmuExceptions xadd_16_16( + BiosEmuEnvironment *env, uint16_t *addr1, uint16_t *addr2); +BiosEmuExceptions xadd_32_32( + BiosEmuEnvironment *env, uint32_t *addr1, uint32_t *addr2); + BiosEmuExceptions lds_16_16( BiosEmuEnvironment *env, uint16_t *reg, uint16_t *addr); BiosEmuExceptions lds_32_32( @@ -181,4 +195,13 @@ void outs_32( BiosEmuEnvironment *env, void *dst, int delta_dst, void *src, int delta_src, int repeat_times); +BiosEmuExceptions bsf_16_16( + BiosEmuEnvironment *env, uint16_t *dst, uint16_t *src); +BiosEmuExceptions bsf_32_32( + BiosEmuEnvironment *env, uint32_t *dst, uint32_t *src); +BiosEmuExceptions bsr_16_16( + BiosEmuEnvironment *env, uint16_t *dst, uint16_t *src); +BiosEmuExceptions bsr_32_32( + BiosEmuEnvironment *env, uint32_t *dst, uint32_t *src); + #endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/operations.c b/src/arch/x86/bios_emu/operations.c index 82d0403..9e4671a 100644 --- a/src/arch/x86/bios_emu/operations.c +++ b/src/arch/x86/bios_emu/operations.c @@ -540,3 +540,53 @@ void decode_cwd_cdq(BiosEmuEnvironment *env) { } return; } + +BiosEmuExceptions bsf_16_16( + BiosEmuEnvironment *env, uint16_t *dst, uint16_t *src) { + uint16_t x = *src; + for (int i = 0; i < 16; i++) { + if (x & 1) { + *dst = i; + return NoException; + } + x >>= 1; + } + return NoException; +} + +BiosEmuExceptions bsf_32_32( + BiosEmuEnvironment *env, uint32_t *dst, uint32_t *src) { + uint32_t x = *src; + for (int i = 0; i < 32; i++) { + if (x & 1) { + *dst = i; + return NoException; + } + x >>= 1; + } + return NoException; +} + +BiosEmuExceptions bsr_16_16( + BiosEmuEnvironment *env, uint16_t *dst, uint16_t *src) { + uint16_t x = *src; + for (int i = 15; i >= 0; i--) { + if (x >> i) { + *dst = i; + return NoException; + } + } + return NoException; +} + +BiosEmuExceptions bsr_32_32( + BiosEmuEnvironment *env, uint32_t *dst, uint32_t *src) { + uint32_t x = *src; + for (int i = 31; i >= 0; i--) { + if (x >> i) { + *dst = i; + return NoException; + } + } + return NoException; +} diff --git a/src/arch/x86/bios_emu/ops/alu.c b/src/arch/x86/bios_emu/ops/alu.c index 2439088..24dc33b 100644 --- a/src/arch/x86/bios_emu/ops/alu.c +++ b/src/arch/x86/bios_emu/ops/alu.c @@ -7,18 +7,6 @@ #include #include -#define SET_FLAG(x, bit) \ - env->regs.flags = \ - (x) ? env->regs.flags | BIT(bit) : env->regs.flags & ~BIT(bit) - -#define SET_CARRY_FLAG(x) SET_FLAG(x, CarryFlagBit) -#define SET_OVERFLOW_FLAG(x) SET_FLAG(x, OverflowFlagBit) -#define SET_SIGN_FLAG(x) SET_FLAG(x, SignFlagBit) - -#define SIGN_FLAG8(x) SET_SIGN_FLAG(x >> 7) -#define SIGN_FLAG16(x) SET_SIGN_FLAG(x >> 15) -#define SIGN_FLAG32(x) SET_SIGN_FLAG(x >> 31) - static inline uint8_t calc_parity(uint8_t x) { x ^= x >> 4; x &= 0x0F; diff --git a/src/arch/x86/bios_emu/ops/xchg.c b/src/arch/x86/bios_emu/ops/xchg.c index a1146e6..e39f120 100644 --- a/src/arch/x86/bios_emu/ops/xchg.c +++ b/src/arch/x86/bios_emu/ops/xchg.c @@ -1,3 +1,4 @@ +#include "../includes/flags.h" #include #include #include @@ -29,3 +30,63 @@ BiosEmuExceptions xchg_32_32( return NoException; } + +BiosEmuExceptions cmpxchg_8_8( + BiosEmuEnvironment *env, uint8_t *addr1, uint8_t *addr2) { + if (*addr1 == *addr2) { + env->regs.al = *addr2; + SET_FLAG(1, ZeroFlagBit); + } else { + env->regs.al = *addr1; + SET_FLAG(0, ZeroFlagBit); + } + return NoException; +} + +BiosEmuExceptions cmpxchg_16_16( + BiosEmuEnvironment *env, uint16_t *addr1, uint16_t *addr2) { + if (*addr1 == *addr2) { + env->regs.ax = *addr2; + SET_FLAG(1, ZeroFlagBit); + } else { + env->regs.ax = *addr1; + SET_FLAG(0, ZeroFlagBit); + } + return NoException; +} + +BiosEmuExceptions cmpxchg_32_32( + BiosEmuEnvironment *env, uint32_t *addr1, uint32_t *addr2) { + if (*addr1 == *addr2) { + env->regs.eax = *addr2; + SET_FLAG(1, ZeroFlagBit); + } else { + env->regs.eax = *addr1; + SET_FLAG(0, ZeroFlagBit); + } + return NoException; +} + +BiosEmuExceptions xadd_8_8( + BiosEmuEnvironment *env, uint8_t *addr1, uint8_t *addr2) { + uint8_t tmp = *addr1; + *addr1 = *addr2 + *addr1; + *addr2 = tmp; + return NoException; +} + +BiosEmuExceptions xadd_16_16( + BiosEmuEnvironment *env, uint16_t *addr1, uint16_t *addr2) { + uint16_t tmp = *addr1; + *addr1 = *addr2 + *addr1; + *addr2 = tmp; + return NoException; +} + +BiosEmuExceptions xadd_32_32( + BiosEmuEnvironment *env, uint32_t *addr1, uint32_t *addr2) { + uint32_t tmp = *addr1; + *addr1 = *addr2 + *addr1; + *addr2 = tmp; + return NoException; +} diff --git a/src/arch/x86/bios_emu/todo.md b/src/arch/x86/bios_emu/todo.md index 704d10a..4ab829c 100644 --- a/src/arch/x86/bios_emu/todo.md +++ b/src/arch/x86/bios_emu/todo.md @@ -145,9 +145,9 @@ The following instructions, added to later IA-32 processors (some in the Intel 2 - [x] Jcc - Exchange instructions CMPXCHG, CMPXCHG8B, and XADD. - - [ ] CMPXCHG + - [x] CMPXCHG - [ ] CMPXCHG8B - - [ ] XADD + - [x] XADD - String instructions MOVS, CMPS, SCAS, LODS, and STOS. - [x] MOVS @@ -161,8 +161,8 @@ The following instructions, added to later IA-32 processors (some in the Intel 2 - [x] BTS - [x] BTR - [x] BTC - - [ ] BSF - - [ ] BSR + - [x] BSF + - [x] BSR - [x] SETcc - [ ] BSWAP From b0c148936c43f8385a6e775423bd690ab09f3c21 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 21 Apr 2025 20:12:42 +0800 Subject: [PATCH 056/158] =?UTF-8?q?bios=5Femu:=20=E6=96=B0=E5=A2=9EENTER,L?= =?UTF-8?q?EAVE=E6=8C=87=E4=BB=A4=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/bios_emu/decode.c | 27 +++++++ .../x86/bios_emu/includes/instructions_2.h | 1 + src/arch/x86/bios_emu/includes/operations.h | 5 ++ src/arch/x86/bios_emu/operations.c | 72 +++++++++++++++++++ src/arch/x86/bios_emu/ops/xchg.c | 7 ++ src/arch/x86/bios_emu/todo.md | 6 +- 6 files changed, 115 insertions(+), 3 deletions(-) diff --git a/src/arch/x86/bios_emu/decode.c b/src/arch/x86/bios_emu/decode.c index 90d023f..b2d05c4 100644 --- a/src/arch/x86/bios_emu/decode.c +++ b/src/arch/x86/bios_emu/decode.c @@ -14,6 +14,23 @@ #include #include +BiosEmuExceptions nop_16(BiosEmuEnvironment *env, uint16_t *addr1) { + return NoException; +} + +BiosEmuExceptions decode_r( + BiosEmuEnvironment *env, Op1_16 func16, Op1_32 func32) { + uint8_t reg = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + if (env->flags.operand_size == 0) { + uint16_t *r16 = env->reg_lut_r16[reg]; + return func16(env, r16); + } else { + uint32_t *r32 = env->reg_lut_r32[reg]; + return func32(env, r32); + } +} + BiosEmuExceptions decode_rm8_r8(BiosEmuEnvironment *env, Op2_8_8 func) { uint8_t modrm = *(uint8_t *)env->cur_ip++; env->regs.eip++; @@ -155,6 +172,10 @@ BiosEmuExceptions decode_two_bytes_opcode(BiosEmuEnvironment *env) { case OP_BSR_LZCNT: decode_rm_r(env, bsr_16_16, bsr_32_32); break; + case OP_BSWAP: + env->flags.operand_size = 1; // BSWAP只有32位操作数 + decode_r(env, nop_16, bswap_32); + break; case OP_BT: decode_rm_r(env, bt_16_16, bt_32_32); break; @@ -297,6 +318,9 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { case OP_CWD_CDQ: decode_cwd_cdq(env); break; + case OP_ENTER: + exception = decode_enter(env); + break; case OP_DAA: decode_daa(env); break; @@ -393,6 +417,9 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { case OP_LEA: decode_lea(env); break; + case OP_LEAVE: + decode_leave(env); + break; case OP_LES: decode_r_rm(env, les_16_16, les_32_32); break; diff --git a/src/arch/x86/bios_emu/includes/instructions_2.h b/src/arch/x86/bios_emu/includes/instructions_2.h index 290926f..1fe599e 100644 --- a/src/arch/x86/bios_emu/includes/instructions_2.h +++ b/src/arch/x86/bios_emu/includes/instructions_2.h @@ -72,6 +72,7 @@ typedef enum TwoBytesOpcodes { OP_BTC = 0xBB, OP_BSF_TZCNT = 0xBC, OP_BSR_LZCNT = 0xBD, + OP_BSWAP = 0xC8, OP_XADD_rm_r_8 = 0xC0, OP_XADD_rm_r = 0xC1, diff --git a/src/arch/x86/bios_emu/includes/operations.h b/src/arch/x86/bios_emu/includes/operations.h index 32f81b6..b82cdc7 100644 --- a/src/arch/x86/bios_emu/includes/operations.h +++ b/src/arch/x86/bios_emu/includes/operations.h @@ -204,4 +204,9 @@ BiosEmuExceptions bsr_16_16( BiosEmuExceptions bsr_32_32( BiosEmuEnvironment *env, uint32_t *dst, uint32_t *src); +BiosEmuExceptions bswap_32(BiosEmuEnvironment *env, uint32_t *addr); + +BiosEmuExceptions decode_enter(BiosEmuEnvironment *env); +BiosEmuExceptions decode_leave(BiosEmuEnvironment *env); + #endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/operations.c b/src/arch/x86/bios_emu/operations.c index 9e4671a..8fe1ee4 100644 --- a/src/arch/x86/bios_emu/operations.c +++ b/src/arch/x86/bios_emu/operations.c @@ -590,3 +590,75 @@ BiosEmuExceptions bsr_32_32( } return NoException; } + +BiosEmuExceptions decode_enter(BiosEmuEnvironment *env) { + uint16_t alloc_size = *(uint16_t *)env->cur_ip; + env->cur_ip += 2; + env->regs.eip += 2; + + uint8_t nesting_level = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + + uint32_t frame_temp; + if (env->flags.operand_size == 0) { + PUSH(env, env->regs.bp, 2); + frame_temp = env->regs.sp; + } else { + PUSH(env, env->regs.ebp, 4); + frame_temp = env->regs.esp; + } + + if (nesting_level == 0) { + nesting_level = 1; + } else { + if (env->flags.operand_size == 0) { + if (env->flags.stack_size == 0) { + for (int i = 1; i < nesting_level; i++) { + env->regs.bp -= 2; + PUSH16(env, env->regs.bp, 2); + } + PUSH16(env, frame_temp, 2); + } else { + for (int i = 1; i < nesting_level; i++) { + env->regs.ebp -= 2; + PUSH32(env, env->regs.ebp, 4); + } + PUSH32(env, frame_temp, 2); + } + } else { + if (env->flags.stack_size == 0) { + for (int i = 1; i < nesting_level; i++) { + env->regs.bp -= 4; + PUSH16(env, env->regs.bp, 2); + } + PUSH16(env, frame_temp, 4); + } else { + for (int i = 1; i < nesting_level; i++) { + env->regs.ebp -= 4; + PUSH32(env, env->regs.ebp, 4); + } + PUSH32(env, frame_temp, 4); + } + } + } + + if (env->flags.operand_size == 0) { + env->regs.bp = frame_temp; + env->regs.sp -= alloc_size; + } else { + env->regs.ebp = frame_temp; + env->regs.esp -= alloc_size; + } + return NoException; +} + +BiosEmuExceptions decode_leave(BiosEmuEnvironment *env) { + if (env->flags.operand_size == 0) { + env->regs.sp = env->regs.bp; + POP(env, env->regs.bp, 2); + } else { + env->regs.esp = env->regs.ebp; + POP(env, env->regs.ebp, 4); + } + return NoException; +} diff --git a/src/arch/x86/bios_emu/ops/xchg.c b/src/arch/x86/bios_emu/ops/xchg.c index e39f120..9921765 100644 --- a/src/arch/x86/bios_emu/ops/xchg.c +++ b/src/arch/x86/bios_emu/ops/xchg.c @@ -90,3 +90,10 @@ BiosEmuExceptions xadd_32_32( *addr2 = tmp; return NoException; } + +BiosEmuExceptions bswap_32(BiosEmuEnvironment *env, uint32_t *addr) { + uint32_t tmp = *addr; + *addr = ((tmp & 0x000000FF) << 24) | ((tmp & 0x0000FF00) << 8) | + ((tmp & 0x00FF0000) >> 8) | ((tmp & 0xFF000000) >> 24); + return NoException; +} diff --git a/src/arch/x86/bios_emu/todo.md b/src/arch/x86/bios_emu/todo.md index 4ab829c..48261a8 100644 --- a/src/arch/x86/bios_emu/todo.md +++ b/src/arch/x86/bios_emu/todo.md @@ -164,7 +164,7 @@ The following instructions, added to later IA-32 processors (some in the Intel 2 - [x] BSF - [x] BSR - [x] SETcc - - [ ] BSWAP + - [x] BSWAP - Double shift instructions SHLD and SHRD. - [x] SHLD @@ -175,8 +175,8 @@ The following instructions, added to later IA-32 processors (some in the Intel 2 - [x] POPF - ENTER and LEAVE control instructions. - - [ ] ENTER - - [ ] LEAVE + - [x] ENTER + - [x] LEAVE - BOUND instruction. - [ ] From 61719a635235637c8bda4da41a9caf05cdca3de8 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 21 Apr 2025 20:24:25 +0800 Subject: [PATCH 057/158] =?UTF-8?q?bios=5Femu:=20=E6=96=B0=E5=A2=9EBOUND?= =?UTF-8?q?=E6=8C=87=E4=BB=A4=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/bios_emu/decode.c | 3 +++ src/arch/x86/bios_emu/includes/operations.h | 5 +++++ src/arch/x86/bios_emu/operations.c | 18 ++++++++++++++++++ src/arch/x86/bios_emu/todo.md | 2 +- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/arch/x86/bios_emu/decode.c b/src/arch/x86/bios_emu/decode.c index b2d05c4..3bfb8ca 100644 --- a/src/arch/x86/bios_emu/decode.c +++ b/src/arch/x86/bios_emu/decode.c @@ -281,6 +281,9 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { case OP_AAS: decode_aas(env); break; + case OP_BOUND: + decode_r_rm(env, bound_16_16, bound_32_32); + break; case OP_CALL: exception = decode_call(env); break; diff --git a/src/arch/x86/bios_emu/includes/operations.h b/src/arch/x86/bios_emu/includes/operations.h index b82cdc7..1b52d6a 100644 --- a/src/arch/x86/bios_emu/includes/operations.h +++ b/src/arch/x86/bios_emu/includes/operations.h @@ -209,4 +209,9 @@ BiosEmuExceptions bswap_32(BiosEmuEnvironment *env, uint32_t *addr); BiosEmuExceptions decode_enter(BiosEmuEnvironment *env); BiosEmuExceptions decode_leave(BiosEmuEnvironment *env); +BiosEmuExceptions bound_16_16( + BiosEmuEnvironment *env, uint16_t *reg, uint16_t *src); +BiosEmuExceptions bound_32_32( + BiosEmuEnvironment *env, uint32_t *reg, uint32_t *src); + #endif \ No newline at end of file diff --git a/src/arch/x86/bios_emu/operations.c b/src/arch/x86/bios_emu/operations.c index 8fe1ee4..36cb4a9 100644 --- a/src/arch/x86/bios_emu/operations.c +++ b/src/arch/x86/bios_emu/operations.c @@ -662,3 +662,21 @@ BiosEmuExceptions decode_leave(BiosEmuEnvironment *env) { } return NoException; } + +BiosEmuExceptions bound_16_16( + BiosEmuEnvironment *env, uint16_t *reg, uint16_t *src) { + uint16_t lower_bound = src[0]; + uint16_t upper_bound = src[1]; + + if (*reg < lower_bound || *reg > upper_bound) { return BOUNDRangeExceeded; } + return NoException; +} + +BiosEmuExceptions bound_32_32( + BiosEmuEnvironment *env, uint32_t *reg, uint32_t *src) { + uint32_t lower_bound = src[0]; + uint32_t upper_bound = src[1]; + + if (*reg < lower_bound || *reg > upper_bound) { return BOUNDRangeExceeded; } + return NoException; +} diff --git a/src/arch/x86/bios_emu/todo.md b/src/arch/x86/bios_emu/todo.md index 48261a8..4770c9e 100644 --- a/src/arch/x86/bios_emu/todo.md +++ b/src/arch/x86/bios_emu/todo.md @@ -179,7 +179,7 @@ The following instructions, added to later IA-32 processors (some in the Intel 2 - [x] LEAVE - BOUND instruction. - - [ ] + - [x] BOUND - CPU identification (CPUID) instruction. - [ ] CPUID From faef3295b2b19e2b378e582014124af43af18786 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 21 Apr 2025 20:51:58 +0800 Subject: [PATCH 058/158] =?UTF-8?q?bios=5Femu:=20=E9=87=8D=E6=9E=84=20?= =?UTF-8?q?=E9=83=A8=E5=88=86MOV,XCHG=E6=8C=87=E4=BB=A4,LEA=E6=8C=87?= =?UTF-8?q?=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/bios_emu/decode.c | 37 ++++++----- src/arch/x86/bios_emu/includes/operations.h | 12 ++-- src/arch/x86/bios_emu/operations.c | 5 +- src/arch/x86/bios_emu/ops/mov.c | 74 +++------------------ 4 files changed, 41 insertions(+), 87 deletions(-) diff --git a/src/arch/x86/bios_emu/decode.c b/src/arch/x86/bios_emu/decode.c index 3bfb8ca..038ca43 100644 --- a/src/arch/x86/bios_emu/decode.c +++ b/src/arch/x86/bios_emu/decode.c @@ -73,6 +73,17 @@ BiosEmuExceptions decode_rm_imm8( } } +BiosEmuExceptions decode_r8_rm8(BiosEmuEnvironment *env, Op2_8_8 func) { + uint8_t modrm = *(uint8_t *)env->cur_ip++; + env->regs.eip++; + uint8_t reg = (modrm >> 3) & 0b111; + + uint8_t *rm = RM_ADDR(env, modrm); + uint8_t *r8 = env->reg_lut_r8[reg]; + + return func(env, r8, rm); +} + BiosEmuExceptions decode_r_rm( BiosEmuEnvironment *env, Op2_16_16 func16, Op2_32_32 func32) { uint8_t modrm = *(uint8_t *)env->cur_ip++; @@ -282,7 +293,7 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { decode_aas(env); break; case OP_BOUND: - decode_r_rm(env, bound_16_16, bound_32_32); + exception = decode_r_rm(env, bound_16_16, bound_32_32); break; case OP_CALL: exception = decode_call(env); @@ -418,7 +429,7 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { decode_r_rm(env, lds_16_16, lds_32_32); break; case OP_LEA: - decode_lea(env); + exception = decode_lea(env); break; case OP_LEAVE: decode_leave(env); @@ -475,16 +486,16 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { break; } case OP_MOV_rm_r8: - decode_mov_rm_r8(env); + exception = decode_rm8_r8(env, mov_8_8); break; case OP_MOV_rm_r: - decode_mov_rm_r(env); + exception = decode_rm_r(env, mov_16_16, mov_32_32); break; case OP_MOV_r_rm8: - decode_mov_r_rm_8(env); + exception = decode_r8_rm8(env, mov_8_8); break; case OP_MOV_r_rm: - decode_mov_r_rm(env); + exception = decode_r_rm(env, mov_16_16, mov_32_32); break; case OP_MOV_rm_sreg: decode_mov_rm_sreg(env); @@ -511,7 +522,7 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { decode_mov_r_imm(env, *opcode); break; case OP_MOV_rm_imm8: - decode_mov_rm_imm8(env); + exception = decode_rm_imm8(env, mov_16_16, mov_32_32); break; case OP_MOV_rm_imm: decode_mov_rm_imm(env); @@ -691,19 +702,13 @@ BiosEmuExceptions decode_one_byte_opcode(BiosEmuEnvironment *env) { calc_rm_r(env, CALC_TEST); break; case (OP_XCHG_r + 1)...(OP_XCHG_r + 7): // XCHG ax, ax机器码与NOP指令相同 - if (env->flags.operand_size == 0) { - uint16_t *reg = PLUS_RW_REG(env, *opcode); - exception = xchg_16_16(env, reg, RM_ADDR(env, *opcode)); - } else { - uint32_t *reg = PLUS_RD_REG(env, *opcode); - exception = xchg_32_32(env, reg, RM_ADDR(env, *opcode)); - } + exception = decode_r_rm(env, xchg_16_16, xchg_32_32); break; case OP_XCHG_8: - decode_rm8_r8(env, xchg_8_8); + exception = decode_rm8_r8(env, xchg_8_8); break; case OP_XCHG: - decode_rm_r(env, xchg_16_16, xchg_32_32); + exception = decode_rm_r(env, xchg_16_16, xchg_32_32); break; case OP_XLAT: if (env->flags.operand_size == 0) { diff --git a/src/arch/x86/bios_emu/includes/operations.h b/src/arch/x86/bios_emu/includes/operations.h index 1b52d6a..0e0668d 100644 --- a/src/arch/x86/bios_emu/includes/operations.h +++ b/src/arch/x86/bios_emu/includes/operations.h @@ -28,10 +28,11 @@ BiosEmuExceptions decode_0xff(BiosEmuEnvironment *env); void decode_pusha_pushad(BiosEmuEnvironment *env); -void decode_mov_rm_r8(BiosEmuEnvironment *env); -void decode_mov_rm_r(BiosEmuEnvironment *env); -void decode_mov_r_rm_8(BiosEmuEnvironment *env); -void decode_mov_r_rm(BiosEmuEnvironment *env); +BiosEmuExceptions mov_8_8(BiosEmuEnvironment *env, uint8_t *dst, uint8_t *src); +BiosEmuExceptions mov_16_16( + BiosEmuEnvironment *env, uint16_t *dst, uint16_t *src); +BiosEmuExceptions mov_32_32( + BiosEmuEnvironment *env, uint32_t *dst, uint32_t *src); void decode_mov_rm_sreg(BiosEmuEnvironment *env); void decode_mov_sreg_rm(BiosEmuEnvironment *env); void decode_mov_sreg_rm(BiosEmuEnvironment *env); @@ -41,7 +42,6 @@ void decode_mov_moffs_r_8(BiosEmuEnvironment *env); void decode_mov_moffs_r(BiosEmuEnvironment *env); void decode_mov_r_imm8(BiosEmuEnvironment *env, uint8_t opcode); void decode_mov_r_imm(BiosEmuEnvironment *env, uint8_t opcode); -void decode_mov_rm_imm8(BiosEmuEnvironment *env); void decode_mov_rm_imm(BiosEmuEnvironment *env); void decode_movzx_r_rm8(BiosEmuEnvironment *env); @@ -80,7 +80,7 @@ void decode_in(BiosEmuEnvironment *env, uint16_t port); void decode_out8(BiosEmuEnvironment *env, uint8_t port); void decode_out(BiosEmuEnvironment *env, uint16_t port); -void decode_lea(BiosEmuEnvironment *env); +BiosEmuExceptions decode_lea(BiosEmuEnvironment *env); void decode_setcc(BiosEmuEnvironment *env, int condition); diff --git a/src/arch/x86/bios_emu/operations.c b/src/arch/x86/bios_emu/operations.c index 36cb4a9..5f71d92 100644 --- a/src/arch/x86/bios_emu/operations.c +++ b/src/arch/x86/bios_emu/operations.c @@ -493,12 +493,13 @@ void outs_32( : "cc", "memory"); } -void decode_lea(BiosEmuEnvironment *env) { +BiosEmuExceptions decode_lea(BiosEmuEnvironment *env) { uint8_t modrm = *(uint8_t *)env->cur_ip++; env->regs.eip++; uint8_t reg = (modrm >> 3) & 0b111; size_t address; + if (modrm >> 6 == 0b11) { return InvalidOpcode; } if (env->flags.address_size == 0) { address = decode_rm_address_16(env, modrm); } else { @@ -511,7 +512,7 @@ void decode_lea(BiosEmuEnvironment *env) { uint32_t *dst = env->reg_lut_r32[reg]; *dst = (uint32_t)address; } - return; + return NoException; } void decode_setcc(BiosEmuEnvironment *env, int condition) { diff --git a/src/arch/x86/bios_emu/ops/mov.c b/src/arch/x86/bios_emu/ops/mov.c index 74a4f93..290d87a 100644 --- a/src/arch/x86/bios_emu/ops/mov.c +++ b/src/arch/x86/bios_emu/ops/mov.c @@ -1,67 +1,25 @@ #include "../includes/decode.h" -#include "../includes/flags.h" #include "../includes/mod_rm.h" #include "../includes/operations.h" #include #include #include -void decode_mov_rm_r8(BiosEmuEnvironment *env) { - uint8_t modrm = *(uint8_t *)env->cur_ip++; - env->regs.eip++; - uint8_t reg = (modrm >> 3) & 0b111; - - uint8_t *dst = RM_ADDR(env, modrm); - uint8_t *src = env->reg_lut_r8[reg]; - *dst = *src; - return; +BiosEmuExceptions mov_8_8(BiosEmuEnvironment *env, uint8_t *dst, uint8_t *src) { + *dst = *src; + return NoException; } -void decode_mov_rm_r(BiosEmuEnvironment *env) { - uint8_t modrm = *(uint8_t *)env->cur_ip++; - env->regs.eip++; - uint8_t reg = (modrm >> 3) & 0b111; - - if (env->flags.operand_size == 0) { - uint16_t *dst = RM_ADDR16(env, modrm); - uint16_t *src = env->reg_lut_r16[reg]; - *dst = *src; - } else { - uint32_t *dst = RM_ADDR32(env, modrm); - uint32_t *src = env->reg_lut_r32[reg]; - *dst = *src; - } - - return; +BiosEmuExceptions mov_16_16( + BiosEmuEnvironment *env, uint16_t *dst, uint16_t *src) { + *dst = *src; + return NoException; } -void decode_mov_r_rm_8(BiosEmuEnvironment *env) { - uint8_t modrm = *(uint8_t *)env->cur_ip++; - env->regs.eip++; - uint8_t reg = (modrm >> 3) & 0b111; - - uint8_t *dst = env->reg_lut_r8[reg]; - uint8_t *src = RM_ADDR(env, modrm); - *dst = *src; - return; -} - -void decode_mov_r_rm(BiosEmuEnvironment *env) { - uint8_t modrm = *(uint8_t *)env->cur_ip++; - env->regs.eip++; - uint8_t reg = (modrm >> 3) & 0b111; - - if (env->flags.operand_size == 0) { - uint16_t *dst = env->reg_lut_r16[reg]; - uint32_t *src = RM_ADDR16(env, modrm); - *dst = *src; - } else { - uint32_t *dst = env->reg_lut_r32[reg]; - uint32_t *src = RM_ADDR32(env, modrm); - *dst = *src; - } - - return; +BiosEmuExceptions mov_32_32( + BiosEmuEnvironment *env, uint32_t *dst, uint32_t *src) { + *dst = *src; + return NoException; } void decode_mov_rm_sreg(BiosEmuEnvironment *env) { @@ -190,16 +148,6 @@ void decode_mov_r_imm(BiosEmuEnvironment *env, uint8_t opcode) { } } -void decode_mov_rm_imm8(BiosEmuEnvironment *env) { - uint8_t *val; - uint8_t modrm = *(uint8_t *)env->cur_ip++; - env->regs.eip++; - - val = RM_ADDR(env, modrm); - *val = *(uint8_t *)env->cur_ip++; - env->regs.eip++; -} - void decode_mov_rm_imm(BiosEmuEnvironment *env) { uint8_t modrm = *(uint8_t *)env->cur_ip++; env->regs.eip++; From 4b38b80edd6e977bd169aaa24904dd1b6233704a Mon Sep 17 00:00:00 2001 From: Jiajun Wang <42348859+Ryan1202@users.noreply.github.com> Date: Wed, 7 May 2025 21:46:26 +0800 Subject: [PATCH 059/158] docs: Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8ab1a17..8ad6092 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ 是个半成品。。。

+真正的主分支:[master](https://github.com/Ryan1202/Horizon-Operating-System/tree/master) + ## 环境 建议使用```VSCode```开发 From 4e48935dd62804109e247a90677ffd3a7f4d6020 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 24 Apr 2025 10:44:10 +0800 Subject: [PATCH 060/158] =?UTF-8?q?=E8=B0=83=E6=95=B4arch/x86/drivers,=20d?= =?UTF-8?q?river/=E7=9B=AE=E5=BD=95=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/Makefile | 6 ++++-- src/arch/x86/drivers/{ => interrupt}/8259a.c | 0 src/arch/x86/drivers/interrupt/Makefile | 2 ++ src/arch/x86/drivers/{ => interrupt}/apic.c | 0 src/arch/x86/drivers/network/Makefile | 2 +- src/arch/x86/drivers/timer/Makefile | 1 + src/arch/x86/drivers/{ => timer}/pit.c | 0 src/driver/Makefile | 4 ++-- src/driver/timer/Makefile | 2 ++ src/driver/{ => timer}/timer.c | 0 src/driver/{ => timer}/timer_dm.c | 0 11 files changed, 12 insertions(+), 5 deletions(-) rename src/arch/x86/drivers/{ => interrupt}/8259a.c (100%) create mode 100644 src/arch/x86/drivers/interrupt/Makefile rename src/arch/x86/drivers/{ => interrupt}/apic.c (100%) create mode 100644 src/arch/x86/drivers/timer/Makefile rename src/arch/x86/drivers/{ => timer}/pit.c (100%) create mode 100644 src/driver/timer/Makefile rename src/driver/{ => timer}/timer.c (100%) rename src/driver/{ => timer}/timer_dm.c (100%) diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index e993baf..cbc9794 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -11,8 +11,10 @@ SRC += pit.c SRC += smbios.c SRC += vesa_display.c SRC += cmos.c -#SRC += network/ +SRC += network/ SRC += sound/ #SRC += usb/ SRC += bus/ -SRC += disk/ \ No newline at end of file +SRC += disk/ +SRC += interrupt/ +SRC += timer/ \ No newline at end of file diff --git a/src/arch/x86/drivers/8259a.c b/src/arch/x86/drivers/interrupt/8259a.c similarity index 100% rename from src/arch/x86/drivers/8259a.c rename to src/arch/x86/drivers/interrupt/8259a.c diff --git a/src/arch/x86/drivers/interrupt/Makefile b/src/arch/x86/drivers/interrupt/Makefile new file mode 100644 index 0000000..65abe54 --- /dev/null +++ b/src/arch/x86/drivers/interrupt/Makefile @@ -0,0 +1,2 @@ +SRC += 8259a.c +SRC += apic.c \ No newline at end of file diff --git a/src/arch/x86/drivers/apic.c b/src/arch/x86/drivers/interrupt/apic.c similarity index 100% rename from src/arch/x86/drivers/apic.c rename to src/arch/x86/drivers/interrupt/apic.c diff --git a/src/arch/x86/drivers/network/Makefile b/src/arch/x86/drivers/network/Makefile index 70ea5a5..8b44d87 100644 --- a/src/arch/x86/drivers/network/Makefile +++ b/src/arch/x86/drivers/network/Makefile @@ -1 +1 @@ -SRC += rtl8139.c \ No newline at end of file +SRC += rtl8139/ \ No newline at end of file diff --git a/src/arch/x86/drivers/timer/Makefile b/src/arch/x86/drivers/timer/Makefile new file mode 100644 index 0000000..3b044b4 --- /dev/null +++ b/src/arch/x86/drivers/timer/Makefile @@ -0,0 +1 @@ +SRC += pit.c \ No newline at end of file diff --git a/src/arch/x86/drivers/pit.c b/src/arch/x86/drivers/timer/pit.c similarity index 100% rename from src/arch/x86/drivers/pit.c rename to src/arch/x86/drivers/timer/pit.c diff --git a/src/driver/Makefile b/src/driver/Makefile index 645d2a7..3f2e35f 100644 --- a/src/driver/Makefile +++ b/src/driver/Makefile @@ -1,9 +1,9 @@ SRC += storage/ SRC += sound/ -SRC += timer_dm.c +SRC += timer/ +SRC += network/ SRC += interrupt_dm.c SRC += video_dm.c SRC += video.c SRC += bus_dm.c -SRC += timer.c SRC += time_dm.c \ No newline at end of file diff --git a/src/driver/timer/Makefile b/src/driver/timer/Makefile new file mode 100644 index 0000000..e3dda15 --- /dev/null +++ b/src/driver/timer/Makefile @@ -0,0 +1,2 @@ +SRC += timer_dm.c +SRC += timer.c \ No newline at end of file diff --git a/src/driver/timer.c b/src/driver/timer/timer.c similarity index 100% rename from src/driver/timer.c rename to src/driver/timer/timer.c diff --git a/src/driver/timer_dm.c b/src/driver/timer/timer_dm.c similarity index 100% rename from src/driver/timer_dm.c rename to src/driver/timer/timer_dm.c From c51823c9687579865af2c89948c9ec2b20b7b1ae Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 13 May 2025 23:37:55 +0800 Subject: [PATCH 061/158] =?UTF-8?q?timer:=20=E6=96=B0=E5=A2=9E=20=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E6=8C=87=E5=AE=9A=E6=97=B6=E9=97=B4=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E8=AE=A1=E6=95=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/timer/timer.c | 2 +- src/include/driver/timer_dm.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/driver/timer/timer.c b/src/driver/timer/timer.c index 604491a..9754fef 100644 --- a/src/driver/timer/timer.c +++ b/src/driver/timer/timer.c @@ -1,8 +1,8 @@ -#include "stdint.h" #include #include #include #include +#include extern TimerDeviceManager timer_dm_ext; diff --git a/src/include/driver/timer_dm.h b/src/include/driver/timer_dm.h index 357b29c..9396acd 100644 --- a/src/include/driver/timer_dm.h +++ b/src/include/driver/timer_dm.h @@ -59,6 +59,7 @@ DriverResult register_timer_device( DeviceDriver *device_driver, Device *device, TimerDevice *timer_device); DriverResult timer_init(Timer *timer); void timer_irq_handler(Device *device); +uint32_t timer_count_ms(Timer *timer, uint32_t ms); int timer_get_schedule_tick(int priority); DriverResult timer_set_frequency(Device *device, uint32_t frequency); void delay_ms(Timer *timer, uint32_t ms); From 19f2afafbf1e3c0962bea66de706a64deaab9bda Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 13 May 2025 23:40:40 +0800 Subject: [PATCH 062/158] =?UTF-8?q?spinlock:=20=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?=E9=80=9A=E8=BF=87DEBUG=E5=AE=8F=E5=AE=9E=E7=8E=B0=E5=8F=AF?= =?UTF-8?q?=E9=80=89=E7=9A=84=E6=94=AF=E6=8C=81=E4=BF=9D=E5=AD=98=E5=AF=B9?= =?UTF-8?q?spinlock=E5=8A=A0=E9=94=81=E7=9A=84=E7=BA=BF=E7=A8=8B=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/kernel/spinlock.h | 41 ++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/include/kernel/spinlock.h b/src/include/kernel/spinlock.h index 2895fc7..aa13849 100644 --- a/src/include/kernel/spinlock.h +++ b/src/include/kernel/spinlock.h @@ -3,7 +3,9 @@ #include "kernel/driver_interface.h" extern struct task_s *current_task; -typedef volatile int spinlock_t; + +#ifndef DEBUG +typedef volatile int spinlock_t; #define SPINLOCK(lock) spinlock_t lock = 0; @@ -14,21 +16,50 @@ static inline void spinlock_init(spinlock_t *lock) { lock = 0; } +#define SPINLOCK_GET(lock) *lock +#else +typedef volatile struct { + int lock; + struct task_s *owner; +} spinlock_t; + +#define SPINLOCK(lock) spinlock_t lock = {0, NULL}; + +#define SPINLOCK_INIT(lock) \ + { (lock) = {0, NULL}; } + +#define SPINLOCK_GET(lock) lock->lock +static inline void spinlock_init(spinlock_t *lock) { + lock->lock = 0; + lock->owner = NULL; +} +#endif + static inline void spin_lock(spinlock_t *lock) { // 使用gcc提供的__sync_bool_compare_and_swap()实现原子操作 - while (!__sync_bool_compare_and_swap(lock, 0, 1)) { - while (*lock) + while (!__sync_bool_compare_and_swap(&SPINLOCK_GET(lock), 0, 1)) { + while (SPINLOCK_GET(lock)) ; } +#ifdef DEBUG + lock->owner = current_task; +#endif } static inline int spin_try_lock(spinlock_t *lock) { - return __sync_bool_compare_and_swap(lock, 0, 1); + int ret = __sync_bool_compare_and_swap(&SPINLOCK_GET(lock), 0, 1); +#ifdef DEBUG + if (ret) lock->owner = current_task; +#endif + return ret; } static inline void spin_unlock(volatile spinlock_t *lock) { __asm__ __volatile__("" ::: "memory"); - *lock = 0; + SPINLOCK_GET(lock) = 0; +#ifdef DEBUG + lock->owner = NULL; +#endif } // 获取自旋锁的同时禁用中断并保存中断状态 From b1c234a1139dd518f398f3a4c67ff6dda96b9bec Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 13 May 2025 23:43:57 +0800 Subject: [PATCH 063/158] =?UTF-8?q?driver:=20=E4=BF=AE=E5=A4=8D=20bus=5Fdr?= =?UTF-8?q?iver=E5=88=9D=E5=A7=8B=E5=8C=96=E5=AE=8C=E6=88=90=E6=9C=AA?= =?UTF-8?q?=E8=83=BD=E6=9B=B4=E6=96=B0=E7=8A=B6=E6=80=81=E7=9A=84bug?= =?UTF-8?q?=EF=BC=9B=E4=BC=98=E5=8C=96=20driver=5Fdendency=E7=AD=89?= =?UTF-8?q?=E5=BE=85=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/driver.c | 2 +- src/kernel/driver_dependency.c | 4 ++-- src/kernel/wait_queue.c | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/kernel/driver.c b/src/kernel/driver.c index 981d073..31261a6 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -141,7 +141,6 @@ void sub_driver_start_thread(void *arg) { if (device->ops->init != NULL) { device->ops->init(device); } if (device->ops->start != NULL) { device->ops->start(device); } } - device_driver->subdriver.state = SUBDRIVER_STATE_READY; } else if (sub_driver->type == DRIVER_TYPE_BUS_DRIVER) { BusDriver *bus_driver = container_of(sub_driver, BusDriver, subdriver); if (bus_driver->ops->init != NULL) { @@ -164,6 +163,7 @@ void sub_driver_start_thread(void *arg) { } } } + sub_driver->state = SUBDRIVER_STATE_READY; } void driver_start_thread(void *arg) { diff --git a/src/kernel/driver_dependency.c b/src/kernel/driver_dependency.c index 616a92c..30e91d7 100644 --- a/src/kernel/driver_dependency.c +++ b/src/kernel/driver_dependency.c @@ -18,8 +18,8 @@ DriverResult check_dependency(Driver *driver) { Bus *bus; BusDriver *bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; - if (bus_driver == NULL || - bus_driver->subdriver.state != SUBDRIVER_STATE_READY) { + while (bus_driver == NULL || + bus_driver->subdriver.state != SUBDRIVER_STATE_READY) { // 总线驱动还没准备好则等待 thread_set_status(TASK_INTERRUPTIBLE); wait_queue_add(&bus_driver->subdriver.wq); diff --git a/src/kernel/wait_queue.c b/src/kernel/wait_queue.c index 8a0e6a1..9ecf42c 100644 --- a/src/kernel/wait_queue.c +++ b/src/kernel/wait_queue.c @@ -122,7 +122,6 @@ void wait_queue_wakeup_all(WaitQueue *wq) { list_del(&cur->wait_queue_tag); thread_unblock(thread); - schedule(); } spin_unlock_irqrestore(&wq->lock, old_status); From 5028cbb8d4ee0ce4efecf2b39d01ee814be902f3 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 23 May 2025 23:57:48 +0800 Subject: [PATCH 064/158] =?UTF-8?q?objects:=20=E4=BF=AE=E5=A4=8D=20TRANSFE?= =?UTF-8?q?R=5FOUT=5FXXX=E5=AE=8F=E5=AE=9A=E4=B9=89=E6=8C=87=E5=90=91in?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/objects/transfer.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/include/objects/transfer.h b/src/include/objects/transfer.h index 5fd9c14..0739cd9 100644 --- a/src/include/objects/transfer.h +++ b/src/include/objects/transfer.h @@ -99,17 +99,17 @@ typedef struct TransferOut { ((object)->in.is_transfer_done(object, handle, __VA_ARGS__)) #define TRANSFER_OUT_BLOCK(object, handle, ...) \ - ((object)->in.block(object, handle, TRANSFER_OUT, __VA_ARGS__)) + ((object)->out.block(object, handle, TRANSFER_OUT, __VA_ARGS__)) #define TRANSFER_OUT_BLOCK_ASYNC(object, handle, ...) \ - ((object)->in.block_async(object, handle, TRANSFER_OUT, __VA_ARGS__)) + ((object)->out.block_async(object, handle, TRANSFER_OUT, __VA_ARGS__)) #define TRANSFER_OUT_STREAM(object, handle, ...) \ - ((object)->in.stream(object, handle, TRANSFER_OUT, __VA_ARGS__)) + ((object)->out.stream(object, handle, TRANSFER_OUT, __VA_ARGS__)) #define TRANSFER_OUT_STREAM_ASYNC(object, handle, ...) \ - ((object)->in.stream_async(object, handle, TRANSFER_OUT, __VA_ARGS__)) + ((object)->out.stream_async(object, handle, TRANSFER_OUT, __VA_ARGS__)) #define TRANSFER_OUT_INTTERRUPT(object, handle, ...) \ - ((object)->in.interrupt(object, handle, __VA_ARGS__)) + ((object)->out.interrupt(object, handle, __VA_ARGS__)) #define TRANSFER_OUT_IS_DONE(object, handle, ...) \ - ((object)->in.is_transfer_done(object, handle, __VA_ARGS__)) + ((object)->out.is_transfer_done(object, handle, __VA_ARGS__)) #endif \ No newline at end of file From 6fd17847d55b056c1edac2646c3fa38bead1a8dd Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 5 Aug 2025 22:57:42 +0800 Subject: [PATCH 065/158] =?UTF-8?q?thread:=20=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?=E9=98=B2=E6=8A=A2=E5=8D=A0=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/include/kernel/thread.h | 58 +++++++++++++++++++++++++++- src/kernel/thread.c | 8 ++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/arch/x86/include/kernel/thread.h b/src/arch/x86/include/kernel/thread.h index a126792..0481ff1 100644 --- a/src/arch/x86/include/kernel/thread.h +++ b/src/arch/x86/include/kernel/thread.h @@ -67,6 +67,10 @@ struct task_s { uint32_t stack_magic; size_t subject_id; + struct { + uint8_t need_resched : 1; // 是否需要调度 + } flags; + struct lock child_lock; // 保护子线程计数器的锁 int child_count; // 当前活跃的子线程数 struct semaphore child_sem; // 子线程完成信号量(初始为0) @@ -80,11 +84,61 @@ struct task_s { list_t all_list_tag; }; -#define THREAD_DEFAULT_PRIO 100 - +extern uint32_t preempt_count; extern list_t thread_all; extern spinlock_t thread_ready_lock; +extern struct task_s *current_task; + +#define THREAD_DEFAULT_PRIO 100 + +#define PREEMPT_COUNT_MASK 0xff0000 +#define HARDIRQ_COUNT_MASK 0xff00 +#define SOFTIRQ_COUNT_MASK 0xff +#define PREEMPT_COUNT_SHIFT 16 +#define HARDIRQ_COUNT_SHIFT 8 +#define SOFTIRQ_COUNT_SHIFT 0 + +#define softirq_count() \ + ((preempt_count & SOFTIRQ_COUNT_MASK) >> SOFTIRQ_COUNT_SHIFT) +#define hardirq_count() \ + ((preempt_count & HARDIRQ_COUNT_MASK) >> HARDIRQ_COUNT_SHIFT) +#define preempt_count() \ + ((preempt_count & PREEMPT_COUNT_MASK) >> PREEMPT_COUNT_SHIFT) + +#define in_softirq() ((preempt_count & SOFTIRQ_COUNT_MASK) != 0) +#define in_hardirq() ((preempt_count & HARDIRQ_COUNT_MASK) != 0) +#define can_preempt() \ + ((preempt_count & (PREEMPT_COUNT_MASK | HARDIRQ_COUNT_MASK)) == 0) + +static inline bool need_resched(void) { + return current_task != NULL && current_task->flags.need_resched; +} + +static inline void hardirq_enter(void) { + preempt_count += 1 << HARDIRQ_COUNT_SHIFT; +} + +static inline void hardirq_exit(void) { + preempt_count -= 1 << HARDIRQ_COUNT_SHIFT; +} + +static inline void softirq_enter(void) { + preempt_count += 1 << SOFTIRQ_COUNT_SHIFT; +} + +static inline void softirq_exit(void) { + preempt_count -= 1 << SOFTIRQ_COUNT_SHIFT; +} + +static inline void disable_preempt(void) { + preempt_count += 1 << PREEMPT_COUNT_SHIFT; +} + +static inline void enable_preempt(void) { + preempt_count -= 1 << PREEMPT_COUNT_SHIFT; +} + struct task_s *get_current_thread(); size_t get_current_subject_id(); void init_thread( diff --git a/src/kernel/thread.c b/src/kernel/thread.c index cd1f71d..80b793c 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -22,6 +22,8 @@ #include #include +uint32_t preempt_count = 0; // 预防抢占计数 + struct task_s *current_task, *dead_task = NULL; struct task_s *main_thread; @@ -121,6 +123,7 @@ void init_thread( pthread->pgdir = NULL; pthread->stack_magic = 0x10000000; pthread->subject_id = SUBJECT_ID_SYSTEM; + pthread->flags.need_resched = 0; } /** @@ -319,6 +322,11 @@ void schedule(void) { int old_status; struct task_s *cur = get_current_thread(); + if (!can_preempt()) { + // 如果不能抢占,直接返回 + return; + } + old_status = save_and_disable_interrupt(); // 1. 判断当前线程是否需要加入到thread_ready From 5d219933d14226d3dd11dcdd89af59644e5d5e79 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 5 Aug 2025 22:59:25 +0800 Subject: [PATCH 066/158] =?UTF-8?q?driver:=20driver=5Fdependency=E5=8A=A0?= =?UTF-8?q?=E5=85=A5=E9=98=B2=E6=8A=A2=E5=8D=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/driver.c | 3 ++- src/kernel/driver_dependency.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/kernel/driver.c b/src/kernel/driver.c index 31261a6..0ebda5b 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -141,11 +141,13 @@ void sub_driver_start_thread(void *arg) { if (device->ops->init != NULL) { device->ops->init(device); } if (device->ops->start != NULL) { device->ops->start(device); } } + sub_driver->state = SUBDRIVER_STATE_READY; } else if (sub_driver->type == DRIVER_TYPE_BUS_DRIVER) { BusDriver *bus_driver = container_of(sub_driver, BusDriver, subdriver); if (bus_driver->ops->init != NULL) { bus_driver->ops->init(bus_driver); } + sub_driver->state = SUBDRIVER_STATE_READY; Bus *bus; list_for_each_owner (bus, &bus_driver->bus_lh, bus_list) { @@ -163,7 +165,6 @@ void sub_driver_start_thread(void *arg) { } } } - sub_driver->state = SUBDRIVER_STATE_READY; } void driver_start_thread(void *arg) { diff --git a/src/kernel/driver_dependency.c b/src/kernel/driver_dependency.c index 30e91d7..cda3a58 100644 --- a/src/kernel/driver_dependency.c +++ b/src/kernel/driver_dependency.c @@ -1,3 +1,5 @@ +#include "kernel/driver_interface.h" +#include "kernel/spinlock.h" #include #include #include @@ -18,6 +20,8 @@ DriverResult check_dependency(Driver *driver) { Bus *bus; BusDriver *bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; + + disable_preempt(); // 禁用中断防止执行过程中被调度打断导致在进入等待循环前被“唤醒” while (bus_driver == NULL || bus_driver->subdriver.state != SUBDRIVER_STATE_READY) { // 总线驱动还没准备好则等待 @@ -26,6 +30,7 @@ DriverResult check_dependency(Driver *driver) { thread_wait(); bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; } + enable_preempt(); int j = 0; list_for_each_owner (bus, &bus_driver->bus_lh, bus_list) { From 6f5b79a9a173a297ac77b7f3de723e2bf72b4975 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 5 Aug 2025 23:01:31 +0800 Subject: [PATCH 067/158] =?UTF-8?q?interrupt:=20=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?=E8=BD=AF=E4=B8=AD=E6=96=AD=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/kernel/descriptor.c | 21 +++++++++++++++++-- src/include/kernel/driver.h | 1 + src/include/kernel/softirq.h | 30 +++++++++++++++++++++++++++ src/kernel/Makefile | 1 + src/kernel/softirq.c | 35 ++++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 src/include/kernel/softirq.h create mode 100644 src/kernel/softirq.c diff --git a/src/arch/x86/kernel/descriptor.c b/src/arch/x86/kernel/descriptor.c index 922a778..c8cd5c6 100644 --- a/src/arch/x86/kernel/descriptor.c +++ b/src/arch/x86/kernel/descriptor.c @@ -5,6 +5,8 @@ * @version 1.2 * @date 2022-07-31 */ +#include "kernel/driver_interface.h" +#include "kernel/thread.h" #include #include #include @@ -14,6 +16,7 @@ #include #include #include +#include #include #include @@ -337,15 +340,30 @@ void exception_handler( ; } +void irq_return(void) { + if (need_resched() && preempt_count() == 0) { + get_current_thread()->flags.need_resched = 0; + schedule(); + } +} + void do_irq(int irq) { // if (use_apic) { // apic_eoi(); // } else { // pic_eoi(irq); // } - interrupt_eoi(irq); + hardirq_enter(); device_irq_handler(irq); irq_table[irq](irq); + + interrupt_eoi(irq); + hardirq_exit(); + enable_interrupt(); + + do_softirq(); + + irq_return(); } void default_irq_handler(int irq) { @@ -354,7 +372,6 @@ void default_irq_handler(int irq) { // } else { // pic_eoi(irq); // } - interrupt_eoi(irq); } void irq_enable(int irq) { diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index 5e2b971..ebccfce 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -161,6 +161,7 @@ typedef enum DriverResult { DRIVER_RESULT_UNSUPPORT_FEATURE, DRIVER_RESULT_BUSY, DRIVER_RESULT_EXCEED_MAX_SIZE, + DRIVER_RESULT_INVALID_TYPE, DRIVER_RESULT_OTHER_ERROR, } DriverResult; diff --git a/src/include/kernel/softirq.h b/src/include/kernel/softirq.h new file mode 100644 index 0000000..952964a --- /dev/null +++ b/src/include/kernel/softirq.h @@ -0,0 +1,30 @@ +#ifndef _SOFTIRQ_H +#define _SOFTIRQ_H + +#include +#include + +#define pending_softirq() ({ softirq.pending = 1; }) + +typedef enum SoftirqType { + SOFTIRQ_TIMER, + SOFTIRQ_NETWORK, + SOFTIRQ_BLOCK, + SOFTIRQ_SCHEDULER, + SOFTIRQ_MAX +} SoftirqType; + +typedef struct Softirq { + uint8_t pending : 1; +} Softirq; + +typedef struct SoftirqHandler { + void (*handler)(); +} SoftirqHandler; + +extern Softirq softirq; + +void do_softirq(void); +DriverResult softirq_register_handler(SoftirqType type, void (*handler)(void)); + +#endif \ No newline at end of file diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 2bbb7ab..19b854e 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -24,6 +24,7 @@ SRC += block_cache.c SRC += rwlock.c SRC += condvar.c SRC += dma.c +SRC += softirq.c #INCLUDE_PATH = ../include/ ../$(ARCH)/include/ diff --git a/src/kernel/softirq.c b/src/kernel/softirq.c new file mode 100644 index 0000000..972deb1 --- /dev/null +++ b/src/kernel/softirq.c @@ -0,0 +1,35 @@ +#include "kernel/softirq.h" +#include "kernel/driver.h" +#include "kernel/thread.h" + +Softirq softirq = {0}; + +SoftirqHandler softirq_handlers[SOFTIRQ_MAX]; + +void do_softirq(void) { + if (softirq.pending && !in_softirq()) { + disable_preempt(); + softirq_enter(); + + for (int i = 0; i < SOFTIRQ_MAX; i++) { + if (softirq_handlers[i].handler != NULL) { + softirq_handlers[i].handler(); + } + } + + softirq.pending = 0; + softirq_exit(); + enable_preempt(); + } +} + +DriverResult softirq_register_handler(SoftirqType type, void (*handler)(void)) { + if (type == SOFTIRQ_MAX) { return DRIVER_RESULT_INVALID_TYPE; } + if (softirq_handlers[type].handler != NULL) { + return DRIVER_RESULT_DEVICE_DRIVER_CONFLICT; + } + + softirq_handlers[type].handler = handler; + + return DRIVER_RESULT_OK; +} From a93d13c553f1770357450eb9c515502fb211f3aa Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 5 Aug 2025 23:02:38 +0800 Subject: [PATCH 068/158] =?UTF-8?q?objects:=20=E5=8A=A0=E5=85=A5fs=5Finfo?= =?UTF-8?q?=E9=9D=9E=E7=A9=BA=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fs/fat/fat.c | 1 - src/objects/handle.c | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c index b743163..32c6d0a 100644 --- a/src/fs/fat/fat.c +++ b/src/fs/fat/fat.c @@ -19,7 +19,6 @@ #include #include #include -#include #include FsResult fat_check(Partition *partition); diff --git a/src/objects/handle.c b/src/objects/handle.c index 87c591b..80086ec 100644 --- a/src/objects/handle.c +++ b/src/objects/handle.c @@ -9,12 +9,16 @@ ObjectHandle *object_handle_create(Object *object) { handle->object = object; handle->buf = NULL; handle->handle_data = NULL; - object->fs_info->file_ops.fs_create_handle(handle); + if (handle->object->fs_info != NULL) { + object->fs_info->file_ops.fs_create_handle(handle); + } return handle; } ObjectResult object_handle_delete(ObjectHandle *handle) { - handle->object->fs_info->file_ops.fs_delete_handle(handle); + if (handle->object->fs_info != NULL) { + handle->object->fs_info->file_ops.fs_delete_handle(handle); + } kfree(handle); return OBJECT_OK; } \ No newline at end of file From 1a2b45312f3571cd34f938405099fac7fc5e3a64 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 5 Aug 2025 23:03:48 +0800 Subject: [PATCH 069/158] =?UTF-8?q?lib:=20=E9=87=8D=E6=9E=84=20=E9=9A=8F?= =?UTF-8?q?=E6=9C=BA=E6=95=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/include/kernel/func.h | 7 +++++ src/arch/x86/kernel/platform.c | 7 ++++- src/include/random.h | 10 +++++++ src/include/stdlib.h | 7 ----- src/lib/Makefile | 2 +- src/lib/rand.c | 12 --------- src/lib/random.c | 42 ++++++++++++++++++++++++++++++ 7 files changed, 66 insertions(+), 21 deletions(-) create mode 100644 src/include/random.h delete mode 100644 src/include/stdlib.h delete mode 100644 src/lib/rand.c create mode 100644 src/lib/random.c diff --git a/src/arch/x86/include/kernel/func.h b/src/arch/x86/include/kernel/func.h index 55eee66..3f53aaf 100644 --- a/src/arch/x86/include/kernel/func.h +++ b/src/arch/x86/include/kernel/func.h @@ -1,6 +1,7 @@ #ifndef _FUNC_H #define _FUNC_H +#include #define CR0_PE 0x01 #define CR0_MP 0x02 #define CR0_EM 0x04 @@ -109,6 +110,12 @@ static inline unsigned int bsf(unsigned int x) { return index; } +static inline uint64_t read_tsc(void) { + unsigned int low, high; + __asm__ __volatile__("rdtsc" : "=a"(low), "=d"(high)); + return ((uint64_t)high << 32) | low; +} + #define GET_REG(reg, var) __asm__ __volatile__("mov %%" reg ", %0" : "=g"(var)); int read_cr3(); diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index 2e7c471..f9331c8 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -1,4 +1,5 @@ -#include "bios_emu/bios_emu.h" +#include "stdint.h" +#include #include #include #include @@ -14,8 +15,10 @@ #include #include #include +#include #include #include +#include #include BusDriverOps platform_ops = { @@ -68,6 +71,8 @@ void platform_init() { register_cmos(); dma_init(); + + if (cpu_check_feature(CPUID_FEAT_TSC)) rand_seed((uint32_t)read_tsc()); } void platform_start_devices() { diff --git a/src/include/random.h b/src/include/random.h new file mode 100644 index 0000000..ae3687f --- /dev/null +++ b/src/include/random.h @@ -0,0 +1,10 @@ +#ifndef _RANDOM_H +#define _RANDOM_H + +#include + +void rand_seed(uint32_t seed); +uint32_t rand(void); +uint32_t splitmix(uint32_t x); + +#endif \ No newline at end of file diff --git a/src/include/stdlib.h b/src/include/stdlib.h deleted file mode 100644 index 6a712db..0000000 --- a/src/include/stdlib.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef STDLIB_H -#define STDLIB_H - -void srand(unsigned long seed); -int rand(); - -#endif \ No newline at end of file diff --git a/src/lib/Makefile b/src/lib/Makefile index c1f8a1d..11e6552 100644 --- a/src/lib/Makefile +++ b/src/lib/Makefile @@ -2,5 +2,5 @@ SRC += ctype.c SRC += math.c SRC += string.c SRC += vsprintf.c -SRC += rand.c +SRC += random.c SRC += dyn_array.c \ No newline at end of file diff --git a/src/lib/rand.c b/src/lib/rand.c deleted file mode 100644 index 179b5e9..0000000 --- a/src/lib/rand.c +++ /dev/null @@ -1,12 +0,0 @@ -#include - -static unsigned long int __seed = 1; - -void srand(unsigned long seed) { - __seed = seed; -} - -int rand() { - __seed = __seed * 1103515245 + 12345; - return (int)(__seed >> 16) % 0x7fff; -} \ No newline at end of file diff --git a/src/lib/random.c b/src/lib/random.c new file mode 100644 index 0000000..7810ad7 --- /dev/null +++ b/src/lib/random.c @@ -0,0 +1,42 @@ +#include + +#define GOLDEN_RATIO_32 0x9e3779b9u +#define SPLITMIX32_MUL1 0x85ebca6bu +#define SPLITMIX32_MUL2 0xc2b2ae35u + +static uint32_t xorshift_state = 0; + +uint32_t splitmix(uint32_t x); + +void rand_seed(uint32_t seed) { + uint32_t a = (uint32_t)(void *)&a; // 栈地址 + uint32_t b = (uint32_t)(void *)rand_seed; // 函数地址 + uint32_t c = (uint32_t)(void *)__builtin_return_address(0); // 返回地址 + + xorshift_state = seed ^ a ^ b ^ c ? seed : GOLDEN_RATIO_32; + + xorshift_state = splitmix(xorshift_state); // 使用splitmix算法 +} + +uint32_t rand(void) { + if (xorshift_state == 0) { + xorshift_state = GOLDEN_RATIO_32; // 避免状态为0 + rand_seed(xorshift_state); + } + uint32_t x = xorshift_state; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + xorshift_state = x; + return x; +} + +uint32_t splitmix(uint32_t x) { + x += GOLDEN_RATIO_32; + x ^= x >> 16; + x *= SPLITMIX32_MUL1; + x ^= x >> 13; + x *= SPLITMIX32_MUL2; + x ^= x >> 16; + return x; +} \ No newline at end of file From f6237cf0d8320d5a0258318cb760a7e1efdbbbce Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 5 Aug 2025 23:05:32 +0800 Subject: [PATCH 070/158] =?UTF-8?q?x86:=20=E6=96=B0=E5=A2=9E=20=E5=86=85?= =?UTF-8?q?=E5=AD=98=E5=B1=8F=E9=9A=9C=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Makefile | 2 +- src/arch/x86/include/kernel/x86_barrier.h | 15 +++++++++++++++ src/include/kernel/barrier.h | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/arch/x86/include/kernel/x86_barrier.h create mode 100644 src/include/kernel/barrier.h diff --git a/src/Makefile b/src/Makefile index e84c0fd..1f6aad2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,7 +8,7 @@ endif X_ASFLAGS := $(ENV_AFLAGS) -I $(ARCH_DIR)/include/ -g X_CFLAGS := $(ENV_CFLAGS) -fno-strict-aliasing -g ifeq ($(ARCH), x86) -X_CFLAGS += -DARCH_X86 +X_CFLAGS += -DARCH_X86=32 endif X_INCDIRS := ../include/ ./include/ $(ARCH_DIR)/include/ diff --git a/src/arch/x86/include/kernel/x86_barrier.h b/src/arch/x86/include/kernel/x86_barrier.h new file mode 100644 index 0000000..73ab979 --- /dev/null +++ b/src/arch/x86/include/kernel/x86_barrier.h @@ -0,0 +1,15 @@ +#ifndef _X86_BARRIER_H +#define _X86_BARRIER_H + +#if ARCH_X86 == 32 +#define memory_barrier() \ + __asm__ __volatile__("lock; addl $0,0(%%esp)" ::: "memory") +#define read_memory_barrier() memory_barrier() +#define write_memory_barrier() memory_barrier() +#else +#define memory_barrier() __asm__ __volatile__("mfence" ::: "memory") +#define read_memory_barrier() __asm__ __volatile__("lfence" ::: "memory") +#define write_memory_barrier() __asm__ __volatile__("sfence" ::: "memory") +#endif + +#endif \ No newline at end of file diff --git a/src/include/kernel/barrier.h b/src/include/kernel/barrier.h new file mode 100644 index 0000000..bfdd106 --- /dev/null +++ b/src/include/kernel/barrier.h @@ -0,0 +1,18 @@ +#ifndef _BARRIER_H +#define _BARRIER_H + +#ifdef ARCH_X86 +#include +#else + +#define memory_barrier() __asm__ __volatile__("" ::: "memory") +#define read_memory_barrier() memory_barrier() +#define wrie_memory_barrier() memory_barrier() + +#endif + +#define mb() memory_barrier() +#define rmb() read_memory_barrier() +#define wmb() write_memory_barrier() + +#endif \ No newline at end of file From c090c66944ff5d87267eb73e5a5708dc38d18f0b Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 9 Aug 2025 18:15:14 +0800 Subject: [PATCH 071/158] =?UTF-8?q?kernel:=20=E6=96=B0=E5=A2=9E=20list=5Fi?= =?UTF-8?q?n=5Flist()=E6=A3=80=E6=B5=8B=E6=98=AF=E5=90=A6=E4=BD=8D?= =?UTF-8?q?=E4=BA=8E=E6=9C=89=E6=95=88=E9=93=BE=E8=A1=A8=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/storage/storage_io_queue.c | 4 +- src/include/kernel/list.h | 69 +++++++++++++++++---------- src/kernel/block_cache.c | 4 +- src/kernel/thread.c | 12 ++--- src/kernel/wait_queue.c | 6 +-- 5 files changed, 57 insertions(+), 38 deletions(-) diff --git a/src/driver/storage/storage_io_queue.c b/src/driver/storage/storage_io_queue.c index 7f54423..2bd4ead 100644 --- a/src/driver/storage/storage_io_queue.c +++ b/src/driver/storage/storage_io_queue.c @@ -107,7 +107,7 @@ void storage_periodic_task(void *arg) { &storage_device->io_queue_lh, StorageRequest, list); storage_submit_request(request); } else if ( - storage_device->block_cache_lh.next != NULL && + list_in_list(&storage_device->block_cache_lh) && !list_empty(&storage_device->block_cache_lh)) { BlockCacheEntry *entry = list_first_owner( &storage_device->block_cache_lh, BlockCacheEntry, list); @@ -151,7 +151,7 @@ void storage_submit_request(StorageRequest *request) { } else { storage_device->ops->submit_read_request(storage_device, request); } - if (request->list.next != NULL) list_del(&request->list); + if (list_in_list(&request->list)) list_del(&request->list); // TODO: bug } void storage_solve_read_request(StorageRequest *request) { diff --git a/src/include/kernel/list.h b/src/include/kernel/list.h index 2aaf90e..605be61 100644 --- a/src/include/kernel/list.h +++ b/src/include/kernel/list.h @@ -20,12 +20,17 @@ typedef struct list { #define LIST_HEAD(name) struct list name = LIST_HEAD_INIT(name) +static inline bool list_in_list(const struct list *node) { + return (node->next != NULL && node->prev != NULL); +} + static inline void list_init(struct list *list) { list->next = list; list->prev = list; } -static inline void __list_add(struct list *_new, struct list *prev, struct list *next) { +static inline void __list_add( + struct list *_new, struct list *prev, struct list *next) { next->prev = _new; _new->next = next; _new->prev = prev; @@ -117,11 +122,13 @@ static inline void list_move_tail(struct list *node, struct list *head) { list_add_tail(node, head); } -static inline int list_is_first(const struct list *node, const struct list *head) { +static inline int list_is_first( + const struct list *node, const struct list *head) { return (node->prev == head); // 节点的前一个是否为链表头 } -static inline int list_is_last(const struct list *node, const struct list *head) { +static inline int list_is_last( + const struct list *node, const struct list *head) { return (node->next == head); // 节点的后一个是否为链表头 } @@ -131,9 +138,11 @@ static inline int list_empty(const struct list *head) { #define list_owner(ptr, type, member) container_of(ptr, type, member) -#define list_first_owner(head, type, member) list_owner((head)->next, type, member) +#define list_first_owner(head, type, member) \ + list_owner((head)->next, type, member) -#define list_last_owner(head, type, member) list_owner((head)->prev, type, member) +#define list_last_owner(head, type, member) \ + list_owner((head)->prev, type, member) #define list_first_owner_or_null(head, type, member) \ ({ \ @@ -149,11 +158,14 @@ static inline int list_empty(const struct list *head) { __pos != __head ? list_owner(__pos, type, member) : NULL; \ }) -#define list_next_owner(pos, member) list_owner((pos)->member.next, typeof(*(pos)), member) +#define list_next_owner(pos, member) \ + list_owner((pos)->member.next, typeof(*(pos)), member) -#define list_prev_onwer(pos, member) list_owner((pos)->member.prev, typeof(*(pos)), member) +#define list_prev_onwer(pos, member) \ + list_owner((pos)->member.prev, typeof(*(pos)), member) -#define list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next) +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) static inline int list_find(struct list *list, struct list *head) { struct list *node; @@ -175,28 +187,35 @@ static inline int list_length(struct list *head) { return n; } -#define list_for_each_prev(pos, head) for (pos = (head)->prev; pos != (head); pos = pos->prev) +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) -#define list_for_each_safe(pos, _next, head) \ - for (pos = (head)->next, _next = pos->next; pos != (head); pos = _next, _next = pos->next) +#define list_for_each_safe(pos, _next, head) \ + for (pos = (head)->next, _next = pos->next; pos != (head); \ + pos = _next, _next = pos->next) -#define list_for_each_prev_safe(pos, _prev, head) \ - for (pos = (head)->prev, _prev = pos->prev; pos != (head); pos = _prev, _prev = pos->prev) +#define list_for_each_prev_safe(pos, _prev, head) \ + for (pos = (head)->prev, _prev = pos->prev; pos != (head); \ + pos = _prev, _prev = pos->prev) -#define list_for_each_owner(pos, head, member) \ - for (pos = list_first_owner(head, typeof(*pos), member); &pos->member != (head); \ - pos = list_next_owner(pos, member)) +#define list_for_each_owner(pos, head, member) \ + for (pos = list_first_owner(head, typeof(*pos), member); \ + &pos->member != (head); pos = list_next_owner(pos, member)) -#define list_for_each_owner_reverse(pos, head, member) \ - for (pos = list_last_owner(head, typeof(*pos), member); &pos->member != (head); \ - pos = list_prev_onwer(pos, member)) +#define list_for_each_owner_reverse(pos, head, member) \ + for (pos = list_last_owner(head, typeof(*pos), member); \ + &pos->member != (head); pos = list_prev_onwer(pos, member)) -#define list_for_each_owner_safe(pos, next, head, member) \ - for (pos = list_first_owner(head, typeof(*pos), member), next = list_next_owner(pos, member); \ - &pos->member != (head); pos = next, next = list_next_owner(next, member)) +#define list_for_each_owner_safe(pos, next, head, member) \ + for (pos = list_first_owner(head, typeof(*pos), member), \ + next = list_next_owner(pos, member); \ + &pos->member != (head); \ + pos = next, next = list_next_owner(next, member)) -#define list_for_each_owner_reverse_safe(pos, prev, head, member) \ - for (pos = list_last_owner(head, typeof(*pos), member), prev = list_prev_onwer(pos, member); \ - &pos->member != (head); pos = prev, prev = list_prev_onwer(prev, member)) +#define list_for_each_owner_reverse_safe(pos, prev, head, member) \ + for (pos = list_last_owner(head, typeof(*pos), member), \ + prev = list_prev_onwer(pos, member); \ + &pos->member != (head); \ + pos = prev, prev = list_prev_onwer(prev, member)) #endif \ No newline at end of file diff --git a/src/kernel/block_cache.c b/src/kernel/block_cache.c index fb5520a..0f4696a 100644 --- a/src/kernel/block_cache.c +++ b/src/kernel/block_cache.c @@ -119,8 +119,8 @@ void block_cache_read_done(BlockCacheEntry *entry) { void block_cache_write_done( StorageDevice *storage_device, BlockCacheEntry *entry) { - if (storage_device->block_cache_lh.next != NULL && - entry->list.prev == NULL) { + if (list_in_list(&storage_device->block_cache_lh) && + list_in_list(&entry->list)) { list_add_tail(&entry->list, &storage_device->block_cache_lh); } rwlock_write_unlock(&entry->lock); diff --git a/src/kernel/thread.c b/src/kernel/thread.c index 80b793c..0bca44f 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -160,7 +160,7 @@ struct task_s *thread_start( spin_unlock_irqrestore(&thread_all_lock, flags); flags = spin_lock_irqsave(&thread_ready_lock); - if (thread->general_tag.next != NULL) { + if (list_in_list(&thread->general_tag)) { printk("[Thread Error]%s thread is already in thread_ready!\n", name); list_del(&thread->general_tag); } @@ -193,7 +193,7 @@ void thread_exit(void) { spin_unlock_irqrestore(&thread_all_lock, flags); flags = spin_lock_irqsave(&thread_ready_lock); - if (cur->general_tag.next != NULL) list_del(&cur->general_tag); + if (list_in_list(&cur->general_tag)) list_del(&cur->general_tag); // 切换线程 struct task_s *next; @@ -249,7 +249,7 @@ void thread_set_status(task_status_t status) { void thread_wait() { struct task_s *cur_thread = get_current_thread(); - while (cur_thread->wait_queue_tag.next != NULL) { + while (list_in_list(&cur_thread->wait_queue_tag)) { schedule(); } } @@ -272,10 +272,10 @@ void thread_unblock(struct task_s *pthread) { spin_unlock(&pthread->status_lock); spin_lock(&thread_ready_lock); - if (pthread->general_tag.next != NULL) { + if (list_in_list(&pthread->general_tag)) { list_del(&pthread->general_tag); } - list_add_before(&pthread->general_tag, thread_ready.next); + list_add_after(&pthread->general_tag, &thread_ready); spin_unlock_irqrestore(&thread_ready_lock, flags); } else { spin_unlock_irqrestore(&pthread->status_lock, flags); @@ -331,7 +331,7 @@ void schedule(void) { // 1. 判断当前线程是否需要加入到thread_ready if (cur->status == TASK_RUNNING) { - if (cur->general_tag.next != NULL) { + if (list_in_list(&cur->general_tag)) { printk( "Error:Current thread(pid:%d) is in thread_ready list!\n", cur->pid); diff --git a/src/kernel/wait_queue.c b/src/kernel/wait_queue.c index 9ecf42c..ba6cc9e 100644 --- a/src/kernel/wait_queue.c +++ b/src/kernel/wait_queue.c @@ -46,7 +46,7 @@ bool wait_queue_empty(WaitQueue *wq) { */ void wait_queue_add(WaitQueue *wq) { struct task_s *task = get_current_thread(); - if (task->wait_queue_tag.next != NULL) { + if (list_in_list(&task->wait_queue_tag)) { printk("Error:Current thread(pid:%d) is in wait queue!\n", task->pid); list_del(&task->wait_queue_tag); } @@ -60,12 +60,12 @@ void wait_queue_add(WaitQueue *wq) { void wait_queue_del(WaitQueue *wq) { struct task_s *task = get_current_thread(); - if (task->wait_queue_tag.next != NULL) { + if (list_in_list(&task->wait_queue_tag)) { printk("Error:Current thread(pid:%d) is in wait queue!\n", task->pid); list_del(&task->wait_queue_tag); } int flags = spin_lock_irqsave(&wq->lock); - if (task->wait_queue_tag.next != NULL) list_del(&task->wait_queue_tag); + if (list_in_list(&task->wait_queue_tag)) list_del(&task->wait_queue_tag); spin_unlock_irqrestore(&wq->lock, flags); } From d66044b1053d290267f936d9c53c54202e5e1441 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 18 Aug 2025 23:21:21 +0800 Subject: [PATCH 072/158] =?UTF-8?q?timer:=20=E6=96=B0=E5=A2=9E=E5=9B=9E?= =?UTF-8?q?=E8=B0=83=E5=AE=9A=E6=97=B6=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/timer/timer.c | 45 ++++++++++++++++++++++------------- src/driver/timer/timer_dm.c | 20 ++++++++-------- src/include/driver/timer_dm.h | 16 ++++++++++--- 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/src/driver/timer/timer.c b/src/driver/timer/timer.c index 9754fef..32a0ba7 100644 --- a/src/driver/timer/timer.c +++ b/src/driver/timer/timer.c @@ -1,3 +1,4 @@ +#include "kernel/list.h" #include #include #include @@ -14,22 +15,40 @@ DriverResult timer_init(Timer *timer) { DriverResult timer_set_timeout(Timer *timer, uint32_t count) { if (timer->timer_device == NULL) return DRIVER_RESULT_DEVICE_NOT_EXIST; - timer->timeout = timer->timer_device->counter + count; + uint32_t counter = timer->timer_device->counter; + timer->timeout = counter + count; + timer->will_wrap = (timer->timeout > counter) ? false : true; + return DRIVER_RESULT_OK; +} + +DriverResult timer_callback_enable(Timer *timer) { + if (timer == NULL || timer->timer_device == NULL) + return DRIVER_RESULT_DEVICE_NOT_EXIST; // 在插入时排序 - if (!list_empty(&timer->timer_device->timer_list_lh)) { - Timer *last_timer = - list_last_owner(&timer->timer_device->timer_list_lh, Timer, list); + if (!list_empty(&timer->timer_device->timer_callback_lh)) { + Timer *last_timer = list_last_owner( + &timer->timer_device->timer_callback_lh, Timer, list); while (last_timer->timeout > timer->timeout) { - last_timer = list_prev_onwer(last_timer, list); + last_timer = list_prev_owner(last_timer, list); } list_add_after(&timer->list, &last_timer->list); } else { - list_add_tail(&timer->list, &timer->timer_device->timer_list_lh); + list_add_tail(&timer->list, &timer->timer_device->timer_callback_lh); } return DRIVER_RESULT_OK; } +DriverResult timer_callback_cancel(Timer *timer) { + if (timer == NULL || timer->timer_device == NULL) + return DRIVER_RESULT_DEVICE_NOT_EXIST; + + if (list_in_list(&timer->list)) list_del(&timer->list); + else return DRIVER_RESULT_OTHER_ERROR; + + return DRIVER_RESULT_OK; +} + uint32_t timer_count_ms(Timer *timer, uint32_t ms) { uint32_t freq = timer->timer_device->current_frequency; if (freq < 1000) { @@ -41,28 +60,22 @@ uint32_t timer_count_ms(Timer *timer, uint32_t ms) { void delay_ms(Timer *timer, uint32_t ms) { uint32_t count = timer_count_ms(timer, ms); - timer->period = 0; timer_set_timeout(timer, count); - while (timer->timeout != 0) + while (!timer_is_timeout(timer)) ; } void delay_ms_async(Timer *timer, uint32_t ms) { uint32_t count = timer_count_ms(timer, ms); - timer->period = 0; timer_set_timeout(timer, count); // 设置完立即返回 } -void set_periodic_ms(Timer *timer, uint32_t ms) { - uint32_t count = timer_count_ms(timer, ms); - timer->period = count; - timer_set_timeout(timer, count); -} - bool timer_is_timeout(Timer *timer) { - return timer->timeout == 0; + uint32_t counter = timer->timer_device->counter; + return timer->will_wrap ? timer->timeout >= counter + : timer->timeout <= counter; } size_t timer_get_counter() { diff --git a/src/driver/timer/timer_dm.c b/src/driver/timer/timer_dm.c index 3cc0e76..a68c664 100644 --- a/src/driver/timer/timer_dm.c +++ b/src/driver/timer/timer_dm.c @@ -105,14 +105,13 @@ void timer_irq_handler(Device *device) { timer_device->counter++; Timer *cur, *next; - list_for_each_owner_safe (cur, next, &timer_device->timer_list_lh, list) { - if (cur->timeout > timer_device->counter) { break; } + list_for_each_owner_safe ( + cur, next, &timer_device->timer_callback_lh, list) { + if (!timer_is_timeout(cur)) { break; } + list_del(&cur->list); - if (cur->period) { - timer_set_timeout(cur, cur->period); - } else { - cur->timeout = 0; - } + cur->timeout = 0; + if (cur->callback != NULL) cur->callback(cur->arg); } if (!list_empty(&thread_all)) { @@ -122,7 +121,7 @@ void timer_irq_handler(Device *device) { cur_thread->elapsed_ticks++; if (cur_thread->ticks == 0) { - schedule(); + cur_thread->flags.need_resched = 1; } else { cur_thread->ticks--; } @@ -136,7 +135,7 @@ DriverResult register_timer_device( device->dm_ext = timer_device; timer_device->device = device; - list_init(&timer_device->timer_list_lh); + list_init(&timer_device->timer_callback_lh); list_add_tail(&device->dm_list, &timer_dm.device_lh); return DRIVER_RESULT_OK; @@ -145,7 +144,8 @@ DriverResult register_timer_device( DriverResult unregister_timer_device( DeviceDriver *device_driver, Device *device, TimerDevice *timer_device) { Timer *timer, *next; - list_for_each_owner_safe (timer, next, &timer_device->timer_list_lh, list) { + list_for_each_owner_safe ( + timer, next, &timer_device->timer_callback_lh, list) { timer->timer_device = NULL; timer->timeout = 0; list_del(&timer->list); diff --git a/src/include/driver/timer_dm.h b/src/include/driver/timer_dm.h index 9396acd..339786f 100644 --- a/src/include/driver/timer_dm.h +++ b/src/include/driver/timer_dm.h @@ -3,6 +3,7 @@ #include "kernel/device.h" #include "kernel/device_driver.h" +#include "kernel/list.h" #include "result.h" #include "stdint.h" @@ -27,7 +28,7 @@ typedef struct TimerOps { } TimerOps; typedef struct TimerDevice { - list_t timer_list_lh; + list_t timer_callback_lh; Device *device; uint32_t current_frequency; @@ -41,12 +42,18 @@ typedef struct TimerDevice { TimerOps *timer_ops; } TimerDevice; +typedef void (*TimerCallback)(void *arg); + typedef struct Timer { list_t list; TimerDevice *timer_device; - uint32_t timeout; - uint32_t period; + + bool will_wrap; // 计时器是否会溢出导致从0重新开始计数 + uint32_t timeout; // 计时器超时时间 + + TimerCallback callback; + void *arg; } Timer; typedef struct TimerDeviceManager { @@ -68,4 +75,7 @@ bool timer_is_timeout(Timer *timer); DriverResult timer_set_timeout(Timer *timer, uint32_t count); size_t timer_get_counter(); +DriverResult timer_callback_enable(Timer *timer); +DriverResult timer_callback_cancel(Timer *timer); + #endif \ No newline at end of file From 30914d680622eb98c2cb015b44577d7f12c2e36b Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 18 Aug 2025 23:22:04 +0800 Subject: [PATCH 073/158] =?UTF-8?q?list:=20=E4=BF=AE=E5=A4=8D=20list=5Fpre?= =?UTF-8?q?v=5Fowner=20=E5=AE=8F=E7=9A=84=E6=8B=BC=E5=86=99=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/kernel/list.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/include/kernel/list.h b/src/include/kernel/list.h index 605be61..3b4d7a2 100644 --- a/src/include/kernel/list.h +++ b/src/include/kernel/list.h @@ -161,7 +161,7 @@ static inline int list_empty(const struct list *head) { #define list_next_owner(pos, member) \ list_owner((pos)->member.next, typeof(*(pos)), member) -#define list_prev_onwer(pos, member) \ +#define list_prev_owner(pos, member) \ list_owner((pos)->member.prev, typeof(*(pos)), member) #define list_for_each(pos, head) \ @@ -204,7 +204,7 @@ static inline int list_length(struct list *head) { #define list_for_each_owner_reverse(pos, head, member) \ for (pos = list_last_owner(head, typeof(*pos), member); \ - &pos->member != (head); pos = list_prev_onwer(pos, member)) + &pos->member != (head); pos = list_prev_owner(pos, member)) #define list_for_each_owner_safe(pos, next, head, member) \ for (pos = list_first_owner(head, typeof(*pos), member), \ @@ -214,8 +214,8 @@ static inline int list_length(struct list *head) { #define list_for_each_owner_reverse_safe(pos, prev, head, member) \ for (pos = list_last_owner(head, typeof(*pos), member), \ - prev = list_prev_onwer(pos, member); \ + prev = list_prev_owner(pos, member); \ &pos->member != (head); \ - pos = prev, prev = list_prev_onwer(prev, member)) + pos = prev, prev = list_prev_owner(prev, member)) #endif \ No newline at end of file From 3d21f8539fd4d7c619b11e26dcf14664a7644189 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 18 Aug 2025 23:23:00 +0800 Subject: [PATCH 074/158] =?UTF-8?q?driver:=20=E6=96=B0=E5=A2=9E=20print=5F?= =?UTF-8?q?warning=E5=AE=8F=EF=BC=9B=E4=BF=AE=E6=94=B9=20print=5Ferror?= =?UTF-8?q?=E5=AE=8F=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/kernel/driver_interface.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/include/kernel/driver_interface.h b/src/include/kernel/driver_interface.h index 31ad895..4121c15 100644 --- a/src/include/kernel/driver_interface.h +++ b/src/include/kernel/driver_interface.h @@ -38,7 +38,9 @@ #define print_error_with_position(str, ...) \ printk(COLOR_RED __FILE__ " Line %d: " str, __LINE__, ##__VA_ARGS__) #define print_error(source, str, ...) \ - printk(COLOR_RED "[%s]" str, source, ##__VA_ARGS__) + printk(COLOR_RED "[" source "]" str, ##__VA_ARGS__) +#define print_warning(source, str, ...) \ + printk(COLOR_YELLOW "[%s]" str, source, ##__VA_ARGS__) #define print_device_info(device, str, ...) \ printk("[%s]" str, device->name.text, ##__VA_ARGS__) #define print_driver_info(driver, str, ...) \ From d7b41c4c3b31f0221d43b4a399e79849780f7710 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 18 Aug 2025 23:23:47 +0800 Subject: [PATCH 075/158] =?UTF-8?q?objects:=20=E6=96=B0=E5=A2=9ETransferRe?= =?UTF-8?q?sult=E9=94=99=E8=AF=AF=E7=B1=BB=E5=9E=8BTRANSFER=5FERROR=5FEXCE?= =?UTF-8?q?ED=5FMAX=5FSIZE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/objects/transfer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/objects/transfer.h b/src/include/objects/transfer.h index 0739cd9..0479953 100644 --- a/src/include/objects/transfer.h +++ b/src/include/objects/transfer.h @@ -12,6 +12,7 @@ typedef enum { TRANSFER_ERROR_NO_MEMORY, TRANSFER_ERROR_FAILED, TRANSFER_ERROR_OTHER, + TRANSFER_ERROR_EXCEED_MAX_SIZE, } TransferResult; typedef enum { From b32131ad417582526ea46f22273847cdffddbece Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 18 Aug 2025 23:26:07 +0800 Subject: [PATCH 076/158] =?UTF-8?q?driver&thread&wait=5Fqueue:=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=20=E5=8F=AF=E4=B8=AD=E6=96=AD=E9=98=BB=E5=A1=9E?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/driver_dependency.c | 4 ++++ src/kernel/thread.c | 5 +++-- src/kernel/wait_queue.c | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/kernel/driver_dependency.c b/src/kernel/driver_dependency.c index cda3a58..ba8ec26 100644 --- a/src/kernel/driver_dependency.c +++ b/src/kernel/driver_dependency.c @@ -27,7 +27,11 @@ DriverResult check_dependency(Driver *driver) { // 总线驱动还没准备好则等待 thread_set_status(TASK_INTERRUPTIBLE); wait_queue_add(&bus_driver->subdriver.wq); + + enable_preempt(); thread_wait(); + disable_preempt(); + bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; } enable_preempt(); diff --git a/src/kernel/thread.c b/src/kernel/thread.c index 0bca44f..e23766a 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -249,7 +249,8 @@ void thread_set_status(task_status_t status) { void thread_wait() { struct task_s *cur_thread = get_current_thread(); - while (list_in_list(&cur_thread->wait_queue_tag)) { + while (cur_thread->status == TASK_INTERRUPTIBLE) { + // while (list_in_list(&cur_thread->wait_queue_tag)) { schedule(); } } @@ -354,7 +355,7 @@ void schedule(void) { list_del(&next->general_tag); } else next = task_idle; // 4. 改变状态并加入到thread_ready - next->status = TASK_RUNNING; + if (next->status == TASK_READY) next->status = TASK_RUNNING; // 5. 切换线程 // 激活页表并跳转 diff --git a/src/kernel/wait_queue.c b/src/kernel/wait_queue.c index ba6cc9e..f3db9a2 100644 --- a/src/kernel/wait_queue.c +++ b/src/kernel/wait_queue.c @@ -85,7 +85,7 @@ void wait_queue_wakeup_thread(WaitQueue *wq, struct task_s *thread) { list_del(&thread->wait_queue_tag); - if (thread != get_current_thread()) thread_unblock(thread); + thread_unblock(thread); spin_unlock_irqrestore(&wq->lock, flags); return; From 502d15d8ca896a9291b786062fe4dd9ac90fa6ad Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 19 Aug 2025 01:05:50 +0800 Subject: [PATCH 077/158] =?UTF-8?q?rtl8139&network:=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20RTL8139=E9=A9=B1=E5=8A=A8=E7=A8=8B=E5=BA=8F=EF=BC=9B?= =?UTF-8?q?=E9=87=8D=E6=9E=84=20=E7=BD=91=E7=BB=9C=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8=E7=A8=8B=E5=BA=8F=E7=AE=A1=E7=90=86=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=EF=BC=9B=20=E9=87=8D=E6=9E=84=20ethernet,=20arp,=20ip?= =?UTF-8?q?v4,=20udp,=20dhcp=E5=8D=8F=E8=AE=AE=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Makefile | 2 +- src/arch/x86/drivers/network/rtl8139/Makefile | 1 + .../x86/drivers/network/rtl8139/rtl8139.c | 345 +++++++++++ .../x86/drivers/network/rtl8139/rtl8139.h | 176 ++++++ src/driver/network/Makefile | 7 + src/driver/network/buffer.c | 67 +++ src/driver/network/conn.c | 40 ++ src/driver/network/ethernet/Makefile | 1 + src/driver/network/ethernet/ethernet.c | 87 +++ src/driver/network/mii.c | 55 ++ src/driver/network/network.c | 62 ++ src/driver/network/network_dm.c | 71 +++ src/driver/network/protocols/Makefile | 4 + src/driver/network/protocols/arp.c | 59 ++ src/driver/network/protocols/dhcp.c | 543 ++++++++++++++++++ src/driver/network/protocols/ipv4.c | 137 +++++ src/driver/network/protocols/udp.c | 179 ++++++ src/include/driver/network/buffer.h | 37 ++ src/include/driver/network/conn.h | 94 +++ .../driver/network/ethernet/ethernet.h | 41 ++ src/include/driver/network/mii.h | 49 ++ src/include/driver/network/net_queue.h | 13 + src/include/driver/network/network.h | 17 + src/include/driver/network/network_dm.h | 78 +++ src/include/driver/network/protocols/arp.h | 27 + src/include/driver/network/protocols/dhcp.h | 170 ++++++ src/include/driver/network/protocols/ipv4.h | 49 ++ .../driver/network/protocols/protocols.h | 17 + src/include/driver/network/protocols/udp.h | 29 + src/kernel/driver.c | 56 +- src/kernel/main.c | 63 +- src/network/dhcp.c | 8 +- src/network/tcp.c | 2 +- 33 files changed, 2536 insertions(+), 50 deletions(-) create mode 100644 src/arch/x86/drivers/network/rtl8139/Makefile create mode 100644 src/arch/x86/drivers/network/rtl8139/rtl8139.c create mode 100644 src/arch/x86/drivers/network/rtl8139/rtl8139.h create mode 100644 src/driver/network/Makefile create mode 100644 src/driver/network/buffer.c create mode 100644 src/driver/network/conn.c create mode 100644 src/driver/network/ethernet/Makefile create mode 100644 src/driver/network/ethernet/ethernet.c create mode 100644 src/driver/network/mii.c create mode 100644 src/driver/network/network.c create mode 100644 src/driver/network/network_dm.c create mode 100644 src/driver/network/protocols/Makefile create mode 100644 src/driver/network/protocols/arp.c create mode 100644 src/driver/network/protocols/dhcp.c create mode 100644 src/driver/network/protocols/ipv4.c create mode 100644 src/driver/network/protocols/udp.c create mode 100644 src/include/driver/network/buffer.h create mode 100644 src/include/driver/network/conn.h create mode 100644 src/include/driver/network/ethernet/ethernet.h create mode 100644 src/include/driver/network/mii.h create mode 100644 src/include/driver/network/net_queue.h create mode 100644 src/include/driver/network/network.h create mode 100644 src/include/driver/network/network_dm.h create mode 100644 src/include/driver/network/protocols/arp.h create mode 100644 src/include/driver/network/protocols/dhcp.h create mode 100644 src/include/driver/network/protocols/ipv4.h create mode 100644 src/include/driver/network/protocols/protocols.h create mode 100644 src/include/driver/network/protocols/udp.h diff --git a/src/Makefile b/src/Makefile index 1f6aad2..a75331d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,7 +21,7 @@ LD := $(ENV_LD) export AS LD export ARCH_DIR -SRC := $(ARCH_DIR)/ fs/ driver/ kernel/ lib/ network/ objects/ +SRC := $(ARCH_DIR)/ fs/ driver/ kernel/ lib/ objects/ NAME := kernel.elf diff --git a/src/arch/x86/drivers/network/rtl8139/Makefile b/src/arch/x86/drivers/network/rtl8139/Makefile new file mode 100644 index 0000000..bf49a87 --- /dev/null +++ b/src/arch/x86/drivers/network/rtl8139/Makefile @@ -0,0 +1 @@ +SRC += rtl8139.c \ No newline at end of file diff --git a/src/arch/x86/drivers/network/rtl8139/rtl8139.c b/src/arch/x86/drivers/network/rtl8139/rtl8139.c new file mode 100644 index 0000000..a9b038d --- /dev/null +++ b/src/arch/x86/drivers/network/rtl8139/rtl8139.c @@ -0,0 +1,345 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "driver/network/buffer.h" +#include "driver/network/net_queue.h" +#include "driver/network/network.h" +#include "kernel/softirq.h" +#include "kernel/thread.h" +#include "objects/transfer.h" +#include "rtl8139.h" + +DriverResult rtl8139_init(Device *device); +DriverResult rtl8139_start(Device *device); +DriverResult rtl8139_pci_probe(PciDevice *pci_device); +TransferResult rtl8139_send(NetworkDevice *device, void *buf, int length); + +DeviceDriverOps rtl8139_device_driver_ops = { + .device_driver_init = NULL, + .device_driver_uninit = NULL, +}; +PciDriverOps rtl8139_pci_driver_ops = { + .probe = rtl8139_pci_probe, +}; +DeviceOps rtl8139_device_ops = { + .init = rtl8139_init, + .start = rtl8139_start, + .destroy = NULL, + .status = NULL, + .stop = NULL, +}; +NetworkDeviceOps rtl8139_net_device_ops = { + .send = rtl8139_send, +}; + +DriverDependency rtl8139_dependencies[] = { + { + .in_type = DRIVER_DEPENDENCY_TYPE_BUS, + .dependency_in_bus = {BUS_TYPE_PCI, 0}, + .out_bus = NULL, + }, +}; +Driver rtl8139_driver = { + .short_name = STRING_INIT("HorizonRtl8139Driver"), + .dependency_count = sizeof(rtl8139_dependencies) / sizeof(DriverDependency), + .dependencies = rtl8139_dependencies, +}; +DeviceDriver rtl8139_device_driver = { + .name = STRING_INIT("RTL8139"), + .bus = NULL, + .type = DEVICE_TYPE_ETHERNET, + .priority = DRIVER_PRIORITY_BASIC, + .ops = &rtl8139_device_driver_ops, +}; +PciDriver rtl8139_pci_driver = { + .driver = &rtl8139_driver, + .device_driver = &rtl8139_device_driver, + .find_type = FIND_BY_VENDORID_DEVICEID, + .vendor_device = {RTL8139_VENDOR_ID, RTL8139_DEVICE_ID}, + .ops = &rtl8139_pci_driver_ops, +}; +const Device rtl8139_device_template = { + .name = STRING_INIT("RTL8139"), + .device_driver = &rtl8139_device_driver, + .ops = &rtl8139_device_ops, + .private_data_size = sizeof(Rtl8139Device), +}; +const NetworkDevice rtl8139_network_device_template = { + .head_size = 0, + .tail_size = 0, + .type = NETWORK_TYPE_ETHERNET, + .ops = &rtl8139_net_device_ops, +}; + +void rtl8139_handler(Device *device) { + Rtl8139Device *rtl_device = device->private_data; + + spin_lock(&rtl_device->lock); + int status = io_in_word(rtl_device->io_base + REG_ISR); + + if (status == 0xffff) goto end; + + io_out_word(rtl_device->io_base + REG_ISR, status); + if (status & IMR_TOK) { + rtl_device->tx_done_idx = (rtl_device->tx_done_idx + 1) % TX_DESC_NR; + } + if (status & IMR_ROK) pending_softirq(); + if (status & IMR_RXOVW) print_error("RTL8139", "RX Overflow\n"); + if (status & IMR_FOVW) print_error("RTL8139", "FIFO Overflow\n"); + if (status & IMR_PUN_LINKCHG) { print_device_info(device, "Link Changed"); } + +end: + spin_unlock(&rtl_device->lock); +} + +void rtl8139_net_rx_handler(void *data) { + // TODO: SMP防重入 + Rtl8139Device *device = data; + uint8_t cmd = io_in_byte(device->io_base + RTL8139_CR); + uint32_t rx_status; + while (!(cmd & RTL8139_CR_BUFE)) { + int i = device->rx_offset; + rx_status = LE2HOST_DWORD(*(uint32_t *)(device->rx_buffer + i)); + uint16_t length = (rx_status >> 16) - 4; + i += 4; + if (length >= ETH_HEADER_SIZE && (rx_status & RTL8139_RX_STAT_ROK)) { + NetBuffer *net_buffer = net_buffer_create(length); + net_buffer_init(net_buffer, length, 0, length); + void *buffer = net_buffer->ptr; + + if (i + length >= RTL8139_RECV_BUF_SIZE) { + memcpy( + buffer, device->rx_buffer + i, RTL8139_RECV_BUF_SIZE - i); + i = RTL8139_RECV_BUF_SIZE - i; + memcpy(buffer + i, device->rx_buffer + i, length - i); + } else { + memcpy(buffer, device->rx_buffer + i, length); + } + eth_recv(net_buffer); + } else { + printk( + "[RTL8139]RX Error: status %#04x,size %#04x, cur %#04x\n", + rx_status, length + 4, device->rx_offset); + } + device->rx_offset = (device->rx_offset + length + 8 + 3) & + ~3; // +8:4字节CRC和4字节包头;+3:4字节对齐用 + device->rx_offset %= RTL8139_RECV_BUF_SIZE; + io_out_word(device->io_base + RTL8139_CAPR, device->rx_offset - 0x10); + + cmd = io_in8(device->io_base + RTL8139_CR); + } +} + +PRIVATE int mdio_read(Mii *mii, uint8_t reg_addr) { + Rtl8139Device *device = mii->net_dev->device->private_data; + int reg = rtl8139_mii_reg_map[reg_addr]; + if (reg == 0 || reg_addr > 8) { return 0; } + + return io_in_word(device->io_base + reg); +} + +PRIVATE void mdio_write(Mii *mii, uint8_t reg_addr, uint16_t data) { + Rtl8139Device *device = mii->net_dev->device->private_data; + int reg = rtl8139_mii_reg_map[reg_addr]; + if (reg == 0 || reg_addr > 8) { return; } + + if (reg_addr == 0) { + io_out_byte(device->io_base + REG_9346CR, BIT(7) | BIT(6)); + io_out_word(device->io_base + reg, data); + io_out_byte(device->io_base + REG_9346CR, 0); + } else { + io_out_word(device->io_base + reg, data); + } +} + +TransferResult rtl8139_send(NetworkDevice *device, void *buf, int length) { + Rtl8139Device *rtl_device = device->device->private_data; + if (length > ETH_MAX_FRAME_SIZE) { + print_error("RTL8139", "Too long packet"); + return TRANSFER_ERROR_EXCEED_MAX_SIZE; + } + + int index = rtl_device->tx_write_idx; + memcpy(rtl_device->tx_buffer[index], buf, length); + + int flags = spin_lock_irqsave(&rtl_device->lock); + wmb(); + io_out_dword( + rtl_device->io_base + REG_TSDN(index), rtl_device->tx_flag | length); + rtl_device->tx_write_idx = (index + 1) % TX_DESC_NR; + if (rtl_device->tx_write_idx == rtl_device->tx_done_idx) { + // 缓冲区已满,关闭队列 + net_queue_block(&rtl_device->net_device->tx_queue, NQ_BLOCKER_DRIVER); + } + spin_unlock_irqrestore(&rtl_device->lock, flags); + + return TRANSFER_OK; +} + +DriverResult rtl8139_init(Device *device) { + Rtl8139Device *rtl_device = device->private_data; + rtl_device->io_base = rtl_device->pci_device->common.bar[0].base_addr; + rtl_device->io_len = rtl_device->pci_device->common.bar[0].length; + rtl_device->mmio_base = rtl_device->pci_device->common.bar[1].base_addr; + rtl_device->mmio_len = rtl_device->pci_device->common.bar[1].length; + rtl_device->net_device = device->dm_ext; + rtl_device->mii.net_dev = device->dm_ext; + rtl_device->mii.mdio_read = mdio_read; + rtl_device->mii.mdio_write = mdio_write; + rtl_device->net_device->ethernet = + kmalloc_from_template(rtl8139_network_device_template); + timer_init(&rtl_device->timer); + SPINLOCK_INIT(rtl_device->lock); + + return DRIVER_RESULT_OK; +} + +void rtl8139_reset(Rtl8139Device *device) { + io_out_byte(device->io_base + REG_CR, CR_RST); + + uint32_t counter = timer_get_counter() + timer_count_ms(&device->timer, 10); + while (timer_get_counter() < counter && + (io_in_byte(device->io_base + REG_CR) & CR_RST)) { + // 等待重置完成 + } +} + +DriverResult rtl8139_start(Device *device) { + Rtl8139Device *rtl_device = device->private_data; + pci_enable_bus_mastering(rtl_device->pci_device); + + if (rtl_device->chipset >= RTL8139B) { + uint8_t config1 = io_in_byte(rtl_device->io_base + REG_CONFIG1); + config1 |= CFG1_PMEN; + // 使CONFIG寄存器可写 + io_out_byte(rtl_device->io_base + REG_9346CR, BIT(7) | BIT(6)); + io_out_byte(rtl_device->io_base + REG_CONFIG1, config1); + // 恢复正常模式 + io_out_byte(rtl_device->io_base + REG_9346CR, 0); + } else { + uint8_t data = io_in_byte(rtl_device->io_base + REG_CONFIG1); + data &= ~(CFG1_SLEEP | CFG1_PWRDN); + io_out_byte(rtl_device->chipset, data); + } + + rtl8139_reset(rtl_device); + + uint8_t mac_addr[6]; + for (int i = 0; i < 6; i++) { + mac_addr[i] = io_in_byte(rtl_device->io_base + REG_IDRN(i)); + } + NetworkDevice *net_device = device->dm_ext; + eth_set_mac_address(net_device->ethernet, mac_addr); + print_device_info( + device, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac_addr[0], + mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + + net_init_mii(&rtl_device->mii); + + // 启用RX和TX + io_out_byte(rtl_device->io_base + REG_CR, CR_RE | CR_TE); + + // 配置接收缓冲区 + rtl_device->rx_buffer = kmalloc(RTL8139_RECV_BUF_SIZE); + rtl_device->rx_buffer_phy = vir2phy((size_t)rtl_device->rx_buffer); + io_out_dword(rtl_device->io_base + REG_RBSTART, rtl_device->rx_buffer_phy); + io_out_dword( + rtl_device->io_base + REG_RCR, RXFTH_NONE | RBLEN | MXDMA | RCR_AER | + RCR_AR | RCR_WRAP | RCR_AB | RCR_AM | + RCR_APM | RCR_AAP); + + // 配置发送缓冲区 + rtl_device->tx_flag = ((256) >> 5) << 16; + io_out_dword(rtl_device->io_base + REG_TCR, MXDMA | TCR_TXRR(2)); + for (int i = 0; i < TX_DESC_NR; i++) { + rtl_device->tx_buffer[i] = kmalloc(ETH_MAX_FRAME_SIZE); + rtl_device->tx_buffer_phy[i] = + vir2phy((size_t)rtl_device->tx_buffer[i]); + io_out_dword( + rtl_device->io_base + REG_TSADN(i), rtl_device->tx_buffer_phy[i]); + } + + // 清空丢包计数器 + io_out_word(rtl_device->io_base + REG_MPC, 0); + + // 允许接收所有多播 + io_out_dword(rtl_device->io_base + REG_MARN(0), 0xffffffff); + io_out_dword(rtl_device->io_base + REG_MARN(4), 0xffffffff); + + // 配置中断 + io_out_word( + rtl_device->io_base + REG_IMR, + IMR_ROK | IMR_RER | IMR_TOK | IMR_TER | IMR_RXOVW | IMR_PUN_LINKCHG | + IMR_FOVW | IMR_LEN_CHG | IMR_TIMEOUT | IMR_SERR); + + device->irq = kmalloc(sizeof(DeviceIrq)); + device->irq->device = device; + device->irq->irq = rtl_device->pci_device->irqline; + device->irq->handler = rtl8139_handler; + + rtl_device->net_rx.handler = rtl8139_net_rx_handler; + rtl_device->net_rx.data = rtl_device; + network_softirq_register(&rtl_device->net_rx); + + register_device_irq(device->irq); + interrupt_enable_irq(rtl_device->pci_device->irqline); + + return DRIVER_RESULT_OK; +} + +DriverResult rtl8139_pci_probe(PciDevice *pci_device) { + uint32_t io_base = pci_device->common.bar[0].base_addr; + uint32_t data = io_in_dword(io_base + RTL8139_TCR); + Rtl8139Chipset chipset = RTL_UNKNOWN; + + data &= HWVERID_MASK; + for (int i = 0; i < sizeof(hwrevid) / sizeof(uint32_t) / 2; i++) { + if (data == hwrevid[i][1]) { + chipset = hwrevid[i][0]; + break; + } + } + if (chipset == RTL_UNKNOWN) { return DRIVER_RESULT_UNSUPPORT_DEVICE; } + + Device *device = kmalloc_from_template(rtl8139_device_template); + NetworkDevice *network_device = + kmalloc_from_template(rtl8139_network_device_template); + ObjectAttr attr = device_object_attr; + device->bus = pci_device->bus; + register_network_device( + &rtl8139_device_driver, device, network_device, &attr); + + Rtl8139Device *rtl_device = device->private_data; + rtl_device->pci_device = pci_device; + rtl_device->chipset = chipset; + + return DRIVER_RESULT_OK; +} + +static __init void rtl8139_initcall(void) { + register_driver(&rtl8139_driver); + register_device_driver(&rtl8139_driver, &rtl8139_device_driver); + pci_register_driver(&rtl8139_driver, &rtl8139_pci_driver); +} + +driver_initcall(rtl8139_initcall); \ No newline at end of file diff --git a/src/arch/x86/drivers/network/rtl8139/rtl8139.h b/src/arch/x86/drivers/network/rtl8139/rtl8139.h new file mode 100644 index 0000000..6ac8043 --- /dev/null +++ b/src/arch/x86/drivers/network/rtl8139/rtl8139.h @@ -0,0 +1,176 @@ +#ifndef _RTL8139_H +#define _RTL8139_H + +#include "driver/network/mii.h" +#include "driver/network/network.h" +#include "driver/network/network_dm.h" +#include "driver/timer_dm.h" +#include "drivers/bus/pci/pci.h" +#include "kernel/softirq.h" +#include "kernel/spinlock.h" +#include +#include + +#define RTL8139_VENDOR_ID 0x10ec +#define RTL8139_DEVICE_ID 0x8139 + +#define TX_DESC_NR 4 + +// IDR和MAR寄存器都要按4个字节读写 +#define REG_IDRN(n) (0 + (n)) +#define REG_MARN(n) (8 + (n)) +#define REG_TSDN(n) (0x10 + ((n) << 2)) +#define REG_TSADN(n) (0x20 + ((n) << 2)) +#define REG_RBSTART 0x30 +#define REG_CR 0x37 +#define REG_IMR 0x3c +#define REG_ISR 0x3e +#define REG_TCR 0x40 +#define REG_RCR 0x44 +#define REG_MPC 0x4c +#define REG_9346CR 0x50 +#define REG_CONFIG0 0x51 +#define REG_CONFIG1 0x52 +#define REG_BMCR 0x62 +#define REG_BMSR 0x64 +#define REG_ANAR 0x66 +#define REG_ANLPAR 0x68 +#define REG_ANER 0x6a + +#define CR_BUFE BIT(0) +#define CR_TE BIT(2) +#define CR_RE BIT(3) +#define CR_RST BIT(4) + +#define CFG1_DVRLOAD BIT(5) +#define CFG1_LWACT BIT(4) +#define CFG1_MEMMAP BIT(3) +#define CFG1_IOMAP BIT(2) +#define CFG1_VPD BIT(1) +#define CFG1_PMEN BIT(0) + +#define IMR_ROK BIT(0) +#define IMR_RER BIT(1) +#define IMR_TOK BIT(2) +#define IMR_TER BIT(3) +#define IMR_RXOVW BIT(4) +#define IMR_PUN_LINKCHG BIT(5) +#define IMR_FOVW BIT(6) +#define IMR_LEN_CHG BIT(13) +#define IMR_TIMEOUT BIT(14) +#define IMR_SERR BIT(15) + +/** + * 有资料提到RTL8139和RTL8139A没有CONFIG1寄存器, + * 然而QEMU和Linux代码中都提到了对于这两个芯片存在SLEEP和PWRDN这两位, + * 但我没找到相关文档,只能先写上 + */ +#define CFG1_SLEEP BIT(1) +#define CFG1_PWRDN BIT(0) + +#define RTL8139_HWVERID(a, b, c, d, e, f, g) \ + (a << 30 | b << 29 | c << 28 | d << 27 | e << 26 | f << 23 | g << 22) +#define HWVERID_MASK RTL8139_HWVERID(1, 1, 1, 1, 1, 1, 1) + +#define IMR_ALL \ + RTL8139_IMR_SERR | RTL8139_IMR_TimeOut | RTL8139_IMR_LenChg | \ + RTL8139_IMR_FOVW | RTL8139_IMR_TER | RTL8139_IMR_TOK | \ + RTL8139_IMR_RER | RTL8139_IMR_ROK + +#define RCR_RXFTH(n) ((n & 0x07) << 13) +#define RCR_RBLEN(n) ((n & 0x03) << 11) +#define RCR_MXDMA(n) ((n & 0x07) << 8) +#define RCR_WRAP BIT(7) +#define RCR_AER BIT(5) +#define RCR_AR BIT(4) +#define RCR_AB BIT(3) +#define RCR_AM BIT(2) +#define RCR_APM BIT(1) +#define RCR_AAP BIT(0) + +#define TCR_CRC BIT(16) +#define TCR_TXRR(n) ((n & 0x0f) << 4) +#define TCR_CLRABT BIT(0) + +#define RBLEN_64K 0x03 +#define RBLEN_32K 0x02 +#define RBLEN_16K 0x01 +#define RBLEN_8K 0x00 + +#define MXDMA_16B 0b000 +#define MXDMA_32B 0b001 +#define MXDMA_64B 0b010 +#define MXDMA_128B 0b011 +#define MXDMA_256B 0b100 +#define MXDMA_512B 0b101 +#define MXDMA_1024B 0b110 +#define MXDMA_UNLIMITED 0b111 + +#define MXDMA RCR_MXDMA(MXDMA_1024B) +#define RXFTH_NONE RCR_RXFTH(0x07) +#define RECV_BUF_LEN RBLEN_16K +#define RBLEN RCR_RBLEN(RECV_BUF_LEN) + +#define RTL8139_RECV_BUF_SIZE (8192 << RECV_BUF_LEN) + 16 + 1500 + +typedef enum Rtl8139Chipset { + RTL8139 = 0, + RTL8139A, + RTL8139AG, + RTL8139B, + RTL8130, + RTL8139C, + RTL8100, + RTL8139D, + RTL8139CP, + RTL8101, + RTL_UNKNOWN, +} Rtl8139Chipset; + +typedef struct Rtl8139Device { + Timer timer; + PciDevice *pci_device; + NetworkDevice *net_device; + uint32_t io_base, io_len; + uint32_t mmio_base, mmio_len; + Rtl8139Chipset chipset; + Mii mii; + spinlock_t lock; + NetRxHandler net_rx; + + void *rx_buffer; + size_t rx_buffer_phy; + uint32_t rx_offset; + + uint32_t tx_flag; + uint8_t tx_write_idx; + uint8_t tx_done_idx; + void *tx_buffer[TX_DESC_NR]; + size_t tx_buffer_phy[TX_DESC_NR]; +} Rtl8139Device; + +static const int hwrevid[][2] = { + { RTL8139, RTL8139_HWVERID(1, 1, 0, 0, 0, 0, 0)}, + { RTL8139A, RTL8139_HWVERID(1, 1, 1, 0, 0, 0, 0)}, + {RTL8139AG, RTL8139_HWVERID(1, 1, 1, 0, 1, 0, 0)}, + { RTL8139B, RTL8139_HWVERID(1, 1, 1, 1, 0, 0, 0)}, + { RTL8130, RTL8139_HWVERID(1, 1, 1, 1, 0, 0, 0)}, + { RTL8139C, RTL8139_HWVERID(1, 1, 1, 0, 1, 0, 0)}, + {RTL8139CP, RTL8139_HWVERID(1, 1, 1, 0, 1, 1, 0)}, + { RTL8100, RTL8139_HWVERID(1, 1, 1, 1, 0, 1, 0)}, + { RTL8139D, RTL8139_HWVERID(1, 1, 1, 0, 1, 0, 1)}, + { RTL8101, RTL8139_HWVERID(1, 1, 1, 0, 1, 1, 1)}, +}; + +static const int rtl8139_mii_reg_map[] = { + REG_BMCR, // MII_BMCR + REG_BMSR, // MII_BMSR + 0, // MII_PHYID1 + 0, // MII_PHYID2 + REG_ANAR, // MII_ANAR + REG_ANLPAR, // MII_ANLPAR + REG_ANER, // MII_ANER + 0, // MII_ANNPTR +}; + +#endif \ No newline at end of file diff --git a/src/driver/network/Makefile b/src/driver/network/Makefile new file mode 100644 index 0000000..d487faa --- /dev/null +++ b/src/driver/network/Makefile @@ -0,0 +1,7 @@ +SRC += network_dm.c +SRC += network.c +SRC += mii.c +SRC += conn.c +SRC += buffer.c +SRC += ethernet/ +SRC += protocols/ \ No newline at end of file diff --git a/src/driver/network/buffer.c b/src/driver/network/buffer.c new file mode 100644 index 0000000..32928e6 --- /dev/null +++ b/src/driver/network/buffer.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include + +NetBuffer *net_buffer_create(uint16_t size) { + NetBuffer *buffer = kmalloc(sizeof(NetBuffer)); + if (buffer == NULL) { return NULL; } + buffer->ptr = kmalloc(size); + if (buffer->ptr == NULL) { + kfree(buffer); + return NULL; + } + buffer->size = size; + return buffer; +} + +void net_buffer_init( + NetBuffer *buffer, uint16_t size, uint16_t head, uint16_t tail) { + buffer->size = size; + + buffer->head = buffer->ptr + head; + buffer->data = buffer->ptr + head; + buffer->tail = buffer->ptr + tail; +} + +void net_buffer_reset(NetBuffer *buffer) { + buffer->head = buffer->data; + buffer->tail = buffer->data; +} + +void conn_header_alloc(NetworkConnection *conn, uint16_t size) { + conn->buffer->head -= size; +} + +void conn_header_free(NetworkConnection *conn, uint16_t size) { + conn->buffer->head += size; +} + +void conn_tail_alloc(NetworkConnection *conn, uint16_t size) { + conn->buffer->tail += size; +} + +void conn_tail_free(NetworkConnection *conn, uint16_t size) { + conn->buffer->tail -= size; +} + +ProtocolResult net_buffer_data_alloc(NetBuffer *buffer, uint16_t size) { + if (buffer->tail + size > buffer->ptr + buffer->size) { + // 如果数据超过了缓冲区的大小,则不进行写入 + return PROTO_ERROR_EXCEED_MAX_SIZE; + } + buffer->tail += size; + return PROTO_OK; +} + +ProtocolResult conn_put(NetworkConnection *conn, uint16_t size) { + NetBuffer *buffer = conn->buffer; + if (buffer->tail + size > buffer->ptr + buffer->size) { + // 如果数据超过了缓冲区的大小,则不进行写入 + return PROTO_ERROR_EXCEED_MAX_SIZE; + } + buffer->tail += size; + + return PROTO_OK; +} diff --git a/src/driver/network/conn.c b/src/driver/network/conn.c new file mode 100644 index 0000000..f057cf1 --- /dev/null +++ b/src/driver/network/conn.c @@ -0,0 +1,40 @@ +#include "kernel/list.h" +#include "kernel/spinlock.h" +#include "kernel/thread.h" +#include "objects/object.h" +#include +#include +#include +#include + +NetworkConnection *net_create_conn(Object *object) { + if (object->attr->type != OBJECT_TYPE_DEVICE) { return NULL; } + NetworkConnection *conn = kmalloc(sizeof(NetworkConnection)); + if (conn == NULL) { return NULL; } + conn->object = object; + conn->handle = object_handle_create(object); + conn->net_device = object->value.device->dm_ext; + + conn->thread = get_current_thread(); + + conn->phy_protocol = PHY_PROTO_NONE; + conn->dl_protocol = DL_PROTO_NONE; + conn->net_protocol = NET_PROTO_NONE; + conn->trans_protocol = TRANS_PROTO_NONE; + + spinlock_init(&conn->recv_lock); + list_init(&conn->recv_lh); + return conn; +} + +void net_destroy_conn(NetworkConnection *conn) { + // NetProtocol *protocol = conn->protocols; + // while (protocol != NULL) { + // NetProtocol *next = protocol->next; + // protocol->ops.destroy(conn, protocol->context); + // kfree(protocol); + // protocol = next; + // } + object_handle_delete(conn->handle); + kfree(conn); +} diff --git a/src/driver/network/ethernet/Makefile b/src/driver/network/ethernet/Makefile new file mode 100644 index 0000000..c21cbb6 --- /dev/null +++ b/src/driver/network/ethernet/Makefile @@ -0,0 +1 @@ +SRC += ethernet.c \ No newline at end of file diff --git a/src/driver/network/ethernet/ethernet.c b/src/driver/network/ethernet/ethernet.c new file mode 100644 index 0000000..ba6d582 --- /dev/null +++ b/src/driver/network/ethernet/ethernet.c @@ -0,0 +1,87 @@ +/** + * @file ethernet.c + * @author Jiajun Wang (ryan1202@foxmail.com) + * @brief Ethernet II + * + * Reference: + * IEEE 802.3: IEEE Standard for Ethernet + * RFC 894: A Standard for the Transmission of IP Datagrams over Ethernet + * Networks + * + */ +#include "driver/network/protocols/ipv4.h" +#include "driver/network/protocols/protocols.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +NetProtocol ethernet_protocol = { + .head_size = 14, + .tail_size = 0, +}; + +const uint8_t eth_broadcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + +void eth_set_mac_address(EthernetDevice *device, uint8_t *mac_addr) { + memcpy(device->mac_addr, mac_addr, 6); +} + +void eth_get_mac_address(EthernetDevice *device, uint8_t *mac_addr) { + memcpy(mac_addr, device->mac_addr, 6); +} + +void eth_register(NetworkConnection *conn) { + EthernetDevice *eth_device = conn->net_device->ethernet; + conn->phy_protocol = PHY_PROTO_ETHERNET; + eth_get_mac_address(eth_device, conn->ethernet.mac); + NET_BUF_RESV_HEAD(conn, 14); +} + +ProtocolResult eth_wrap( + NetworkConnection *conn, const uint8_t *dst_addr, uint16_t protocol) { + conn_header_alloc(conn, 14); + EthernetHeader *header = (EthernetHeader *)conn->buffer->head; + memcpy(header->dst_mac, dst_addr, 6); + memcpy(header->src_mac, conn->ethernet.mac, 6); + + int content_size = CONN_CONTENT_SIZE(conn); + if (content_size > ETH_MAX_FRAME_SIZE) return PROTO_ERROR_EXCEED_MAX_SIZE; + if (content_size < ETH_MIN_FRAME_SIZE) { + // 填充最小帧长度 + memset(conn->buffer->tail, 0, ETH_MIN_FRAME_SIZE - content_size); + conn->buffer->tail = conn->buffer->head + ETH_MIN_FRAME_SIZE; + } + header->protocol_type = HOST2BE_WORD(protocol); + + return PROTO_OK; +} + +ProtocolResult eth_recv(NetBuffer *net_buffer) { + EthernetHeader *header = (EthernetHeader *)net_buffer->data; + int size = net_buffer->tail - net_buffer->data; + if (size < ETH_HEADER_SIZE) { return PROTO_ERROR_UNSUPPORT; } + if (size > ETH_MAX_FRAME_SIZE) { return PROTO_ERROR_EXCEED_MAX_SIZE; } + + net_buffer->data += sizeof(EthernetHeader); + + ProtocolResult result = PROTO_OK; + switch (BE2HOST_WORD(header->protocol_type)) { + case ETH_PROTO_TYPE_IPV4: + result = ipv4_recv(net_buffer); + break; + case ETH_PROTO_TYPE_ARP: + break; + default: + result = PROTO_ERROR_UNSUPPORT; + } + + return result; +} diff --git a/src/driver/network/mii.c b/src/driver/network/mii.c new file mode 100644 index 0000000..5754f1d --- /dev/null +++ b/src/driver/network/mii.c @@ -0,0 +1,55 @@ +#include "kernel/console.h" +#include "kernel/driver_interface.h" +#include +#include +#include +#include + +bool mii_is_linked(Mii *mii) { + uint32_t data = mii->mdio_read(mii, MII_REG_BMSR); + return !!(data & MII_BMSR_LINK_STATUS); +} + +MiiMediaType mii_check_media_type(uint32_t negotiation) { + MiiMediaType type = MMT_UNKNOWN; + if (negotiation & BIT(5)) type = MMT_10HALF; + if (negotiation & BIT(6)) type = MMT_10FULL; + if (negotiation & BIT(7)) type = MMT_100HALF; + if (negotiation & BIT(8)) type = MMT_100FULL; + if (negotiation & BIT(9)) type = MMT_100T4; + + return type; +} + +/** + * @brief 通过MII接口初始化网卡配置 + * + */ +DriverResult net_init_mii(Mii *mii) { + bool linked = mii_is_linked(mii); + + if (!linked) { + print_device_info(mii->net_dev->device, "MII: No link detected"); + mii->net_dev->state = NET_STATE_NO_CARRIER; + return DRIVER_RESULT_OK; + } + print_device_info(mii->net_dev->device, "MII: Link detected\n"); + mii->net_dev->state = NET_STATE_RUNNING; + + uint32_t anar = mii->mdio_read(mii, MII_REG_ANAR); // 本地能力 + uint32_t anlpar = mii->mdio_read(mii, MII_REG_ANLPAR); // 对端能力 + uint32_t support = anar & anlpar; // 计算双方都支持的特性 + MiiMediaType media_type = mii_check_media_type(support); + + print_device_info(mii->net_dev->device, "MII: Media type: "); + int speed = (media_type >> 1) & 0b111; + int duplex = media_type & 1; + if (speed == 0) printk("10Mbps "); + else if (speed == 1) printk("100Mbps "); + if (duplex) printk("Full Duplex"); + else printk("Half Duplex"); + printk("\n"); + + mii->full_duplex = duplex; + return DRIVER_RESULT_OK; +} \ No newline at end of file diff --git a/src/driver/network/network.c b/src/driver/network/network.c new file mode 100644 index 0000000..68be280 --- /dev/null +++ b/src/driver/network/network.c @@ -0,0 +1,62 @@ +#include "driver/network/network.h" +#include "driver/network/buffer.h" +#include "driver/network/conn.h" +#include "kernel/list.h" +#include +#include +#include +#include +#include +#include +#include + +LIST_HEAD(net_rx_lh); + +void net_queue_block(NetworkQueue *queue, int blocker) { + queue->blocker = blocker; +} + +bool net_queue_is_blocked(NetworkQueue *queue, int blocker) { + return (queue->blocker & blocker) == blocker; +} + +TransferResult network_transfer( + struct Object *object, struct ObjectHandle *obj_handle, + TransferDirection direction, uint8_t *buf, size_t size) { + Device *device = object->value.device; + NetworkDevice *net_device = device->dm_ext; + if (net_device->ops->send == NULL) { return TRANSFER_ERROR_NOT_SUPPORTED; } + if (net_queue_is_blocked(&net_device->tx_queue, NQ_BLOCKER_DRIVER)) { + return TRANSFER_ERROR_FAILED; + } + return net_device->ops->send(net_device, buf, size); +} + +DriverResult network_softirq_register(NetRxHandler *handler) { + list_add_tail(&handler->list, &net_rx_lh); + return DRIVER_RESULT_OK; +} + +void network_softirq_handler(void) { + NetRxHandler *handler; + list_for_each_owner (handler, &net_rx_lh, list) { + if (handler->handler) { + handler->handler(handler->data); + } else { + printk("[Network] Rx handler is NULL, skipping.\n"); + } + } +} + +NetBuffer *network_recv(NetworkConnection *conn) { + NetBuffer *net_buffer = NULL; + if (!list_empty(&conn->recv_lh)) { + disable_preempt(); + spin_lock(&conn->recv_lock); + net_buffer = list_first_owner(&conn->recv_lh, NetBuffer, list); + list_del(&net_buffer->list); + spin_unlock(&conn->recv_lock); + enable_preempt(); + } + return net_buffer; +} diff --git a/src/driver/network/network_dm.c b/src/driver/network/network_dm.c new file mode 100644 index 0000000..d2b2769 --- /dev/null +++ b/src/driver/network/network_dm.c @@ -0,0 +1,71 @@ +#include "driver/network/network.h" +#include "kernel/softirq.h" +#include "objects/transfer.h" +#include +#include +#include +#include +#include +#include +#include +#include + +DriverResult network_dm_load(DeviceManager *manager); +DriverResult network_dm_unload(DeviceManager *manager); + +DeviceManagerOps network_dm_ops = { + .dm_load = network_dm_load, + .dm_unload = network_dm_unload, +}; + +NetworkDeviceManager network_dm_ext; +DeviceManager network_dm = { + .type = DEVICE_TYPE_ETHERNET, + .ops = &network_dm_ops, + .private_data = &network_dm_ext, +}; + +DriverResult network_dm_load(DeviceManager *manager) { + manager->private_data = kmalloc(sizeof(NetworkDeviceManager)); + softirq_register_handler(SOFTIRQ_NETWORK, network_softirq_handler); + return DRIVER_RESULT_OK; +} + +DriverResult network_dm_unload(DeviceManager *manager) { + kfree(manager->private_data); + return DRIVER_RESULT_OK; +} + +DriverResult register_network_device( + DeviceDriver *driver, Device *device, NetworkDevice *network_device, + ObjectAttr *attr) { + device->dm_ext = network_device; + network_device->device = device; + network_device->private_data = device->private_data; + network_device->state = NET_STATE_INITED; + network_device->tx_queue.blocker = 0; + list_add_tail(&device->dm_list, &network_dm.device_lh); + + string_t name; + string_new_with_number(&name, "Network", 7, network_dm_ext.device_count++); + DRIVER_RESULT_PASS(register_device( + device->device_driver, name, device->bus, device, attr)); + + device->object->out.type = TRANSFER_TYPE_STREAM; + device->object->out.stream = network_transfer; + + return DRIVER_RESULT_OK; +} + +NetworkDevice *network_get_device(Object *object) { + if (object->attr->type != OBJECT_TYPE_DEVICE) return NULL; + Device *device = object->value.device; + if (device->device_driver->type != DEVICE_TYPE_SOUND) return NULL; + return device->dm_ext; +} + +NetworkDeviceType network_get_type(Object *object) { + NetworkDevice *network_device = network_get_device(object); + if (network_device == NULL) return NETWORK_TYPE_UNKNOWN; + return network_device->type; +} diff --git a/src/driver/network/protocols/Makefile b/src/driver/network/protocols/Makefile new file mode 100644 index 0000000..7c662b6 --- /dev/null +++ b/src/driver/network/protocols/Makefile @@ -0,0 +1,4 @@ +SRC += arp.c +SRC += ipv4.c +SRC += dhcp.c +SRC += udp.c \ No newline at end of file diff --git a/src/driver/network/protocols/arp.c b/src/driver/network/protocols/arp.c new file mode 100644 index 0000000..80cd25d --- /dev/null +++ b/src/driver/network/protocols/arp.c @@ -0,0 +1,59 @@ +/** + * @file arp.c + * @author Jiajun Wang (ryan1202@foxmail.com) + * @brief ARP + * + * Reference: + * RFC 826: An Ethernet Address Resolution Protocol + * + */ +#include +#include +#include +#include +#include +#include +#include + +ProtocolResult arp_wrap( + NetworkConnection *conn, uint8_t *dst_haddr, uint8_t *dst_paddr, + uint16_t opcode) { + uint16_t htype = 0, ptype = 0; + uint8_t hlen = 0, plen = 0; + uint8_t *src_haddr, *src_paddr; + switch (conn->phy_protocol) { + case PHY_PROTO_ETHERNET: + src_haddr = conn->ethernet.mac; + hlen = 6; + htype = HOST2BE_WORD(ARP_HTYPE_ETH); + break; + default: + return PROTO_ERROR_UNSUPPORT; + } + switch (conn->net_protocol) { + case NET_PROTO_IPV4: + src_paddr = conn->ipv4.ip; + plen = 4; + ptype = HOST2BE_WORD(ETH_TYPE_IPV4); + break; + default: + return PROTO_ERROR_UNSUPPORT; + } + + ArpHeader *arp_header = (ArpHeader *)conn->buffer->data; + arp_header->htype = htype; + arp_header->ptype = ptype; + arp_header->hlen = hlen; + arp_header->plen = plen; + arp_header->opcode = HOST2BE_WORD(opcode); + + void *p = conn->buffer->head + sizeof(ArpHeader); + + memcpy(p, src_haddr, hlen); + memcpy(p + hlen, src_paddr, plen); + p += hlen + plen; + memcpy(p, dst_haddr, hlen); + memcpy(p + hlen, dst_paddr, plen); + + return PROTO_OK; +} \ No newline at end of file diff --git a/src/driver/network/protocols/dhcp.c b/src/driver/network/protocols/dhcp.c new file mode 100644 index 0000000..fd9933a --- /dev/null +++ b/src/driver/network/protocols/dhcp.c @@ -0,0 +1,543 @@ +/** + * @file dhcp.c + * @author Jiajun Wang (ryan1202@foxmail.com) + * @brief DHCP + * + * Reference: + * RFC 2131: Dynamic Host Configuration Protocol + * RFC 1533: DHCP Options and BOOTP Vendor Extensions + */ +#include "bits.h" +#include "driver/network/buffer.h" +#include "driver/network/ethernet/ethernet.h" +#include "driver/timer_dm.h" +#include "kernel/driver_interface.h" +#include "objects/transfer.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OPTION_SET_BASE(buf, len, type, value) \ + { \ + *buf = type; \ + buf++; \ + *buf = len; \ + buf++; \ + *buf = value; \ + buf++; \ + } +#define OPTION_SET_HEADER(buf, len, type) \ + { \ + *buf = type; \ + buf++; \ + *buf = len; \ + buf++; \ + } + +#define DHCP_INIT_TIMEOUT(dhcp) \ + ({ \ + dhcp->retry_times = 0; \ + DHCP_RETRANSMIT_DELAY(dhcp->retry_times); \ + }) +#define DHCP_SET_TIMEOUT(dhcp, timeout) \ + { \ + timer_set_timeout(&dhcp->timeout_timer, timeout); \ + timer_callback_enable(&dhcp->timeout_timer); \ + } + +static uint8_t dhcp_discover_option_list[] = { + DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_ROUTER, DHCP_OPTION_BROADCAST_ADDRESS, + DHCP_OPTION_DOMAIN_NAME_SERVER, DHCP_OPTION_NTP_SERVERS}; +const int dhcp_discover_option_list_size = sizeof(dhcp_discover_option_list); + +ProtocolResult dhcp_discover(DhcpClient *dhcp); +ProtocolResult dhcp_select(DhcpClient *dhcp); +void *dhcp_create_message(DhcpClient *dhcp, DhcpHeader *header, uint8_t op); +ProtocolResult dhcp_send(DhcpClient *dhcp, uint16_t len); +void dhcp_reset(DhcpClient *dhcp, NetworkConnection *conn); + +ProtocolResult dhcp_retransmit(DhcpClient *dhcp) { + TransferResult result = NETWORK_SEND(dhcp->device, dhcp->conn); + if (result != TRANSFER_OK) { + printk("[DHCP] Failed to send DHCP message: %d\n", result); + return PROTO_ERROR_SEND_FAILED; + } + + int timeout = DHCP_RETRANSMIT_DELAY(dhcp->retry_times); + DHCP_SET_TIMEOUT(dhcp, timeout); + + return PROTO_OK; +} + +void dhcp_timeout_handler(void *arg) { + DhcpClient *dhcp = arg; + if (dhcp != NULL) { + dhcp->retry_times++; + switch (dhcp->state) { + case DHCP_STAT_SELECTING: + case DHCP_STAT_REQUESTING: + case DHCP_STAT_RENEWING: + case DHCP_STAT_REBINDING: + dhcp_retransmit(dhcp); + break; + } + } +} + +void dhcp_ip_lease_handler(void *arg) { + DhcpClient *dhcp = arg; + if (dhcp->state == DHCP_STAT_REBINDING) { + dhcp_reset(dhcp, dhcp->conn); + dhcp_discover(dhcp); + } else { + print_error( + "DHCP", "Lease expired in unexpected state: %d\n", dhcp->state); + } +} + +void dhcp_renew_handler(void *arg) { + DhcpClient *dhcp = arg; + if (dhcp->state == DHCP_STAT_BOUND) { + uint8_t *ptr = + dhcp_create_message(dhcp, dhcp->conn->buffer->data, DHCP_REQUEST); + + // TODO: 设置Max Message Size + + OPTION_SET_HEADER( + ptr, dhcp_discover_option_list_size, + DHCP_OPTION_PARAMETER_REQUEST_LIST); + for (int i = 0; i < dhcp_discover_option_list_size; i++, ptr++) { + *ptr = dhcp_discover_option_list[i]; + } + + *ptr = DHCP_OPTION_END; + + int len = 4 /* magic cookie */ + + 3 /* message type */ + + 2 + + dhcp_discover_option_list_size /* parameter request list */ + + 1 /* end */; + + int initial_timeout = DHCP_INIT_TIMEOUT(dhcp); + DHCP_SET_TIMEOUT(dhcp, initial_timeout); + + ProtocolResult result = dhcp_send(dhcp, sizeof(DhcpHeader) + len); + if (result != PROTO_OK) return; + + dhcp->state = DHCP_STAT_RENEWING; + } +} + +void dhcp_rebind_handler(void *arg) { + DhcpClient *dhcp = arg; + if (dhcp->state == DHCP_STAT_RENEWING) { + uint8_t *ptr = + dhcp_create_message(dhcp, dhcp->conn->buffer->data, DHCP_REQUEST); + + // TODO: 设置Max Message Size + + OPTION_SET_HEADER( + ptr, dhcp_discover_option_list_size, + DHCP_OPTION_PARAMETER_REQUEST_LIST); + for (int i = 0; i < dhcp_discover_option_list_size; i++, ptr++) { + *ptr = dhcp_discover_option_list[i]; + } + + *ptr = DHCP_OPTION_END; + + int len = 4 /* magic cookie */ + + 3 /* message type */ + + 2 + + dhcp_discover_option_list_size /* parameter request list */ + + 1 /* end */; + + int initial_timeout = DHCP_INIT_TIMEOUT(dhcp); + DHCP_SET_TIMEOUT(dhcp, initial_timeout); + + ProtocolResult result = dhcp_send(dhcp, sizeof(DhcpHeader) + len); + if (result != PROTO_OK) return; + + dhcp->state = DHCP_STAT_REBINDING; + } +} + +void dhcp_offer_handler( + DhcpClient *dhcp, NetworkConnection *conn, DhcpHeader *header, + uint16_t indexes[DOI_MAX]) { + // 直接选择收到的第一个OFFER的DHCP服务器 + + int index_sid = indexes[DOI_SERVER_ID]; + if (index_sid != 0) { + timer_callback_cancel(&dhcp->timeout_timer); + + memcpy(dhcp->server_ip_addr, &header->options[index_sid], 4); + memcpy(dhcp->ip_addr, &header->yiaddr, 4); + + dhcp_select(dhcp); + } +} + +void dhcp_ack_handler( + DhcpClient *dhcp, NetworkConnection *conn, uint16_t indexes[DOI_MAX]) { + DhcpHeader *header = conn->buffer->data; + *(uint32_t *)conn->ipv4.subnet_mask = 0; + *(uint32_t *)conn->ipv4.gateway_ip = 0; + + if (indexes[DOI_SUBNET_MASK] != 0) { + *(uint32_t *)conn->ipv4.subnet_mask = + *(uint32_t *)&header->options[indexes[DOI_SUBNET_MASK]]; + } + + if (indexes[DOI_ROUTER] != 0) { + *(uint32_t *)conn->ipv4.gateway_ip = + *(uint32_t *)&header->options[indexes[DOI_ROUTER]]; + } + + if (indexes[DOI_IP_LEASE_TIME] != 0) { + dhcp->t0 = BE2HOST_DWORD( + *(uint32_t *)&header->options[indexes[DOI_IP_LEASE_TIME]]); + } + + if (indexes[DOI_RENEWAL_TIME] != 0) { + dhcp->t1 = BE2HOST_DWORD( + *(uint32_t *)&header->options[indexes[DOI_RENEWAL_TIME]]); + } else { + dhcp->t1 = dhcp->t0 / 2; + } + + if (indexes[DOI_REBINDING_TIME] != 0) { + dhcp->t2 = BE2HOST_DWORD( + *(uint32_t *)&header->options[indexes[DOI_REBINDING_TIME]]); + } else { + dhcp->t2 = dhcp->t0 * 7 / 8; + } +} + +void dhcp_nak_handler(DhcpClient *dhcp, NetworkConnection *conn) { + dhcp_reset(dhcp, conn); + + dhcp_discover(dhcp); +} + +void dhcp_set_timers(DhcpClient *dhcp) { + timer_set_timeout(&dhcp->lease_timer, dhcp->t0 * 1000); + timer_callback_enable(&dhcp->lease_timer); + + timer_set_timeout(&dhcp->renew_timer, dhcp->t1 * 1000); + timer_callback_enable(&dhcp->renew_timer); + + timer_set_timeout(&dhcp->rebind_timer, dhcp->t2 * 1000); + timer_callback_enable(&dhcp->rebind_timer); +} + +void dhcp_parse_options( + NetBuffer *net_buffer, DhcpHeader *header, uint16_t (*indexes)[8], + uint16_t *offset) { + uint16_t *idx = *indexes; + *offset = 4; + uint16_t end = + net_buffer->tail - net_buffer->data - offsetof(DhcpHeader, options); + while (header->options[*offset] != DHCP_OPTION_END && *offset < end) { + uint8_t option = header->options[(*offset)++]; + uint8_t length = header->options[(*offset)++]; + switch (option) { + case DHCP_OPTION_PAD: + (*offset)--; + break; + case DHCP_OPTION_SUBNET_MASK: + idx[DOI_SUBNET_MASK] = *offset; + break; + case DHCP_OPTION_ROUTER: + idx[DOI_ROUTER] = *offset; + break; + case DHCP_OPTION_DOMAIN_NAME_SERVER: + idx[DOI_DNS] = *offset; + break; + case DHCP_OPTION_IP_ADDRESS_LEASE_TIME: + idx[DOI_IP_LEASE_TIME] = *offset; + break; + case DHCP_OPTION_MESSAGE_TYPE: + idx[DOI_MESSAGE_TYPE] = *offset; + break; + case DHCP_OPTION_SERVER_IDENTIFIER: + idx[DOI_SERVER_ID] = *offset; + break; + case DHCP_OPTION_RENEWAL_TIME: + idx[DOI_RENEWAL_TIME] = *offset; + break; + case DHCP_OPTION_REBINDING_TIME: + idx[DOI_REBINDING_TIME] = *offset; + break; + default: + break; + } + *offset += length; + } +} + +void dhcp_rx_handler(NetworkConnection *conn, NetBuffer *net_buffer) { + DhcpClient *dhcp = (DhcpClient *)conn->udp.private_data; + DhcpHeader *header = (DhcpHeader *)net_buffer->data; + + if (dhcp == NULL) goto end; + if (net_buffer->tail - net_buffer->data < sizeof(DhcpHeader)) { + print_warning("DHCP", "Received packet too small\n"); + goto end; + } + if (header->op != DHCP_OP_BOOTREPLY) { + print_warning("DHCP", "Received packet is not a DHCP reply\n"); + goto end; + } + if (memcmp(dhcp->haddr, header->chaddr, dhcp->haddr_len) != 0) { + print_warning("DHCP", "Received packet is not for this client\n"); + goto end; + } + if (BE2HOST_DWORD(header->xid) != dhcp->xid) { + print_warning("DHCP", "Received packet is not for this transaction\n"); + goto end; + } + + uint16_t indexes[DOI_MAX] = {0}; + uint16_t offset; + dhcp_parse_options(net_buffer, header, &indexes, &offset); + + uint8_t msg_type = header->options[indexes[DOI_MESSAGE_TYPE]]; + if (msg_type == DHCP_ACK) { + // 收到ACK,表示成功获取IP地址 + if (dhcp->state == DHCP_STAT_REQUESTING || + dhcp->state == DHCP_STAT_REBOOTING) { + dhcp->state = DHCP_STAT_BOUND; + memcpy(dhcp->ip_addr, &header->yiaddr, 4); + memcpy(dhcp->server_ip_addr, &header->siaddr, 4); + + timer_callback_cancel(&dhcp->timeout_timer); + printk( + "[DHCP]Successfully bound to IP: %d.%d.%d.%d\n", + dhcp->ip_addr[0], dhcp->ip_addr[1], dhcp->ip_addr[2], + dhcp->ip_addr[3]); + + // TODO: 检查地址冲突 + + dhcp_ack_handler(dhcp, conn, indexes); + dhcp_set_timers(dhcp); + } else if ( + dhcp->state == DHCP_STAT_RENEWING || + dhcp->state == DHCP_STAT_REBINDING) { + dhcp_ack_handler(dhcp, conn, indexes); + dhcp_set_timers(dhcp); + } + } else if (msg_type == DHCP_NAK) { + if (dhcp->state == DHCP_STAT_REQUESTING || + dhcp->state == DHCP_STAT_REBOOTING || + dhcp->state == DHCP_STAT_REBINDING || + dhcp->state == DHCP_STAT_RENEWING) { + dhcp_nak_handler(dhcp, conn); + } + } else if (msg_type == DHCP_OFFER && dhcp->state == DHCP_STAT_SELECTING) { + dhcp_offer_handler(dhcp, conn, header, indexes); + } + +end: + kfree(net_buffer->ptr); + kfree(net_buffer); +} + +void *dhcp_create_message(DhcpClient *dhcp, DhcpHeader *header, uint8_t op) { + net_buffer_reset(dhcp->conn->buffer); + header->op = DHCP_OP_BOOTREQUEST; + header->hlen = dhcp->haddr_len; + header->htype = DHCP_HTYPE_ETHERNET; + header->hops = 0; + header->xid = HOST2BE_DWORD(dhcp->xid); + + header->ciaddr = *((uint32_t *)dhcp->ip_addr); + header->yiaddr = 0; + header->siaddr = 0; + header->giaddr = 0; + memcpy(header->chaddr, dhcp->haddr, dhcp->haddr_len); + + uint8_t *ptr = (uint8_t *)&header->options; + *(uint32_t *)ptr = HOST2BE_DWORD(DHCP_MAGIC_COOKIE); + ptr += 4; + OPTION_SET_BASE(ptr, 1, DHCP_OPTION_MESSAGE_TYPE, op); + + return ptr; +} + +ProtocolResult dhcp_send(DhcpClient *dhcp, uint16_t len) { + ProtocolResult result = conn_put(dhcp->conn, len); + if (result != PROTO_OK) { + printk("[DHCP] Failed to put DHCP message: %d\n", result); + return result; + } + + udp_wrap( + dhcp->conn, UDP_PORT_DHCP_CLIENT, + UDP_PORT_DHCP_SERVER); // DHCP客户端端口68,服务器端口67 + if (dhcp->state == DHCP_STAT_SELECTING || + dhcp->state == DHCP_STAT_REQUESTING || + dhcp->state == DHCP_STAT_RENEWING) { + ipv4_wrap( + dhcp->conn, IP_PROTO_UDP, (uint8_t *)&ipv4_broadcast_addr, 64); + } else { + ipv4_wrap(dhcp->conn, IP_PROTO_UDP, dhcp->server_ip_addr, 64); + } + switch (dhcp->device->type) { + case NETWORK_TYPE_ETHERNET: + eth_wrap(dhcp->conn, dhcp->server_haddr, ETH_PROTO_TYPE_IPV4); + break; + case NETWORK_TYPE_UNKNOWN: + return PROTO_ERROR_UNSUPPORT; + } + + TransferResult tresult = NETWORK_SEND(dhcp->device, dhcp->conn); + if (tresult != TRANSFER_OK) { + printk("[DHCP] Failed to send DHCP message: %d\n", tresult); + return PROTO_ERROR_OTHER; + } + return PROTO_OK; +} + +ProtocolResult dhcp_discover(DhcpClient *dhcp) { + // 申请新地址 + dhcp->state = DHCP_STAT_SELECTING; + + *((uint32_t *)dhcp->ip_addr) = 0; + uint8_t *ptr = + dhcp_create_message(dhcp, dhcp->conn->buffer->data, DHCP_DISCOVER); + + OPTION_SET_HEADER( + ptr, dhcp_discover_option_list_size, + DHCP_OPTION_PARAMETER_REQUEST_LIST); + for (int i = 0; i < dhcp_discover_option_list_size; i++, ptr++) { + *ptr = dhcp_discover_option_list[i]; + } + + *ptr = DHCP_OPTION_END; + + int len = 4 /* magic cookie */ + + 3 /* message type */ + + 2 + dhcp_discover_option_list_size /* parameter request list */ + + 1 /* end */; + + int initial_timeout = DHCP_INIT_TIMEOUT(dhcp); + DHCP_SET_TIMEOUT(dhcp, initial_timeout); + + ProtocolResult result = dhcp_send(dhcp, sizeof(DhcpHeader) + len); + if (result != PROTO_OK) return result; + + return PROTO_OK; +} + +ProtocolResult dhcp_select(DhcpClient *dhcp) { + // 选择IP地址 + dhcp->state = DHCP_STAT_REQUESTING; + + uint8_t *ptr = + dhcp_create_message(dhcp, dhcp->conn->buffer->data, DHCP_REQUEST); + + // TODO: 设置Max Message Size + + // 设置请求的IP地址 + OPTION_SET_HEADER(ptr, 4, DHCP_OPTION_REQUESTED_IP_ADDRESS); + *(uint32_t *)ptr = *((uint32_t *)dhcp->ip_addr); + ptr += 4; + + // 设置服务器ID(IP地址) + OPTION_SET_HEADER(ptr, 4, DHCP_OPTION_SERVER_IDENTIFIER); + *(uint32_t *)ptr = *((uint32_t *)dhcp->server_ip_addr); + ptr += 4; + + OPTION_SET_HEADER( + ptr, dhcp_discover_option_list_size, + DHCP_OPTION_PARAMETER_REQUEST_LIST); + for (int i = 0; i < dhcp_discover_option_list_size; i++, ptr++) { + *ptr = dhcp_discover_option_list[i]; + } + + *ptr = DHCP_OPTION_END; + + int len = 4 /* magic cookie */ + + 3 /* message type */ + + 6 /* requested ip address */ + + 6 /* server identifier */ + + 2 + dhcp_discover_option_list_size /* parameter request list */ + + 1 /* end */; + + int initial_timeout = DHCP_INIT_TIMEOUT(dhcp); + DHCP_SET_TIMEOUT(dhcp, initial_timeout); + + ProtocolResult result = dhcp_send(dhcp, sizeof(DhcpHeader) + len); + if (result != PROTO_OK) return result; + + return PROTO_OK; +} + +void dhcp_init(DhcpClient *dhcp, NetworkConnection *conn) { + dhcp->conn = conn; + conn->udp.private_data = dhcp; + + udp_bind(dhcp->conn, UDP_PORT_DHCP_CLIENT); + udp_set_callback(conn, dhcp_rx_handler); + + timer_init(&dhcp->timeout_timer); + timer_init(&dhcp->lease_timer); + timer_init(&dhcp->renew_timer); + timer_init(&dhcp->rebind_timer); + dhcp->timeout_timer.callback = dhcp_timeout_handler; + dhcp->lease_timer.callback = dhcp_ip_lease_handler; + dhcp->renew_timer.callback = dhcp_renew_handler; + dhcp->rebind_timer.callback = dhcp_rebind_handler; + dhcp->timeout_timer.arg = dhcp; + dhcp->lease_timer.arg = dhcp; + dhcp->renew_timer.arg = dhcp; + dhcp->rebind_timer.arg = dhcp; +} + +void dhcp_reset(DhcpClient *dhcp, NetworkConnection *conn) { + dhcp->state = DHCP_STAT_INIT; + dhcp->xid = rand(); + + net_buffer_init(conn->buffer, 576, 0, 0); + eth_register(conn); + ipv4_register(conn, NULL); + udp_register(conn); + + switch (dhcp->device->type) { + case NETWORK_TYPE_ETHERNET: + dhcp->haddr_len = ETH_IDENTIFIER_SIZE; + dhcp->haddr_type = DHCP_HTYPE_ETHERNET; + memcpy(dhcp->haddr, dhcp->device->ethernet->mac_addr, dhcp->haddr_len); + memcpy(dhcp->server_haddr, eth_broadcast_mac, dhcp->haddr_len); + break; + default: + break; + } + *(uint32_t *)dhcp->server_ip_addr = ipv4_broadcast_addr; +} + +ProtocolResult dhcp_start(NetworkDevice *device) { + ProtocolResult result; + + DhcpClient *dhcp = kmalloc(sizeof(DhcpClient)); + + dhcp->device = device; + + NetworkConnection *conn = net_create_conn(device->device->object); + conn->buffer = net_buffer_create(576); + + dhcp_init(dhcp, conn); + + dhcp_reset(dhcp, conn); + + result = dhcp_discover(dhcp); + + return result; +} \ No newline at end of file diff --git a/src/driver/network/protocols/ipv4.c b/src/driver/network/protocols/ipv4.c new file mode 100644 index 0000000..ccc19bf --- /dev/null +++ b/src/driver/network/protocols/ipv4.c @@ -0,0 +1,137 @@ +/** + * @file ipv4.c + * @author Jiajun Wang (ryan1202@foxmail.com) + * @brief IPv4 + * + * Reference: + * RFC 791: INTERNET PROTOCOL + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +SPINLOCK(ipv4_id_lock); +uint16_t ipv4_id_counter = 0; + +const uint32_t ipv4_broadcast_addr = 0xffffffff; +const uint32_t ipv4_null_addr = 0x00000000; + +void ipv4_register(NetworkConnection *conn, uint8_t *ip_addr) { + conn->net_protocol = NET_PROTO_IPV4; + if (ip_addr) { + memcpy(conn->ipv4.ip, ip_addr, 4); + } else { + memset(conn->ipv4.ip, 0, 4); + } + // 默认禁用分段 + conn->ipv4.fragment.enable_fragment = 0; + conn->ipv4.fragment.last_fragment = 0; + conn->ipv4.fragment.frag_offset = 0; + conn->ipv4.id = 0; + NET_BUF_RESV_HEAD(conn, sizeof(Ipv4Header)); +} + +void ipv4_enable_fragment(NetworkConnection *conn) { + conn->ipv4.fragment.enable_fragment = 1; + conn->ipv4.fragment.last_fragment = 0; + conn->ipv4.fragment.frag_offset = 0; + + spin_lock(&ipv4_id_lock); + if (ipv4_id_counter == 0) ipv4_id_counter = rand() & 0xffff; + conn->ipv4.id = ipv4_id_counter++; + spin_unlock(&ipv4_id_lock); +} + +void ipv4_checksum(Ipv4Header *header) { + uint32_t sum = 0; + uint16_t *data = (void *)header; + uint8_t len = sizeof(Ipv4Header); + + header->checksum = 0; + + for (size_t i = 0; i < len / 2; i++) { + sum += data[i]; + if (sum > 0xFFFF) sum = (sum & 0xFFFF) + (sum >> 16); + } + header->checksum = ~((uint16_t)sum); +}; + +ProtocolResult ipv4_wrap( + NetworkConnection *conn, uint16_t protocol, uint8_t *dst_ip, uint8_t ttl) { + uint16_t size = CONN_CONTENT_SIZE(conn); + + conn_header_alloc(conn, sizeof(Ipv4Header)); + Ipv4Header *ipv4_header = (Ipv4Header *)conn->buffer->head; + ipv4_header->ver_len = (0x4 << 4) | (20 >> 2); // IPv4, 20字节 + ipv4_header->tos = 0; // Type of Service + ipv4_header->total_len = HOST2BE_WORD(sizeof(Ipv4Header) + size); + ipv4_header->id = HOST2BE_WORD(conn->ipv4.id); + + ipv4_header->flags_frag_offset = HOST2BE_WORD( + conn->ipv4.fragment.enable_fragment << 14 | + conn->ipv4.fragment.last_fragment << 15 | + conn->ipv4.fragment.frag_offset); + + ipv4_header->ttl = ttl; + ipv4_header->protocol = protocol; + ipv4_header->checksum = 0; + memcpy(ipv4_header->src_ip, conn->ipv4.ip, 4); + if (dst_ip) { + memcpy(ipv4_header->dst_ip, dst_ip, 4); + } else { + *(uint32_t *)ipv4_header->dst_ip = 0xffffffff; // 广播地址 + } + ipv4_checksum(ipv4_header); + + conn->ipv4.header = ipv4_header; + + return PROTO_OK; +} + +ProtocolResult ipv4_recv(NetBuffer *net_buffer) { + Ipv4Header *ipv4_header = (Ipv4Header *)net_buffer->data; + int size = net_buffer->tail - net_buffer->data; + + if (size < sizeof(Ipv4Header)) return PROTO_ERROR_UNSUPPORT; + + if ((ipv4_header->ver_len >> 4) != 0x4) return PROTO_ERROR_UNSUPPORT; + + if (ipv4_header->checksum != 0) { + uint16_t checksum = ipv4_header->checksum; + ipv4_checksum(ipv4_header); + if (ipv4_header->checksum != checksum) return PROTO_ERROR_CHECKSUM; + } + + uint16_t frag_offset = HOST2BE_WORD(ipv4_header->flags_frag_offset); + bool mf = (frag_offset & 0x2000) != 0; // More Fragments,还有分片 + frag_offset &= 0x1FFF; + if (frag_offset || mf) { + // 处理分片 + return PROTO_ERROR_UNSUPPORT; // 暂不支持分片 + } + + net_buffer->data += sizeof(Ipv4Header); + + ProtocolResult result = PROTO_OK; + switch (ipv4_header->protocol) { + case IP_PROTO_UDP: + result = udp_recv(net_buffer, ipv4_header); + break; + case IP_PROTO_TCP: + break; + case IP_PROTO_ICMP: + break; + default: + result = PROTO_ERROR_UNSUPPORT; + } + + return result; +} diff --git a/src/driver/network/protocols/udp.c b/src/driver/network/protocols/udp.c new file mode 100644 index 0000000..6dada94 --- /dev/null +++ b/src/driver/network/protocols/udp.c @@ -0,0 +1,179 @@ +/** + * @file udp.c + * @author Jiajun Wang (ryan1202@foxmail.com) + * @brief UDP + * + * Reference: + * RFC 768: User Datagram Protocol + * + */ +#include "bits.h" +#include "driver/network/buffer.h" +#include "driver/network/protocols/protocols.h" +#include "kernel/memory.h" +#include "kernel/spinlock.h" +#include "kernel/thread.h" +#include +#include +#include +#include +#include +#include + +#define UDP_CHECKSUM_ADD(sum, data) \ + sum += (data); \ + if (sum > 0xFFFF) sum = (sum & 0xFFFF) + (sum >> 16); + +LIST_HEAD(udp_lh); + +uint16_t udp_checksum( + NetBuffer *net_buffer, void *ip[2], int ip_len, UdpHeader *udp_header) { + uint16_t *data = (uint16_t *)udp_header; + uint32_t sum = 0; + uint16_t len = net_buffer->tail - net_buffer->data; + + // 清除校验和 + udp_header->checksum = 0; + + // 计算伪头部校验和 + for (int j = 0; j < ip_len / 2; j++) { + UDP_CHECKSUM_ADD(sum, ((uint16_t *)ip[0])[j]); + } + for (int j = 0; j < ip_len / 2; j++) { + UDP_CHECKSUM_ADD(sum, ((uint16_t *)ip[1])[j]); + } + UDP_CHECKSUM_ADD(sum, HOST2BE_WORD(IP_PROTO_UDP)); + UDP_CHECKSUM_ADD(sum, udp_header->length); + + // 计算UDP头部和数据的校验和 + for (size_t i = 0; i < len / 2; i++) { + UDP_CHECKSUM_ADD(sum, data[i]); + } + + if (len % 2) { // 如果长度是奇数,补齐一个字节 + sum += ((uint8_t *)data)[len - 1]; + } + + return ~((uint16_t)(sum + (sum >> 16))); +} + +void udp_register(NetworkConnection *conn) { + conn->trans_protocol = TRANS_PROTO_UDP; + NET_BUF_RESV_HEAD(conn, sizeof(UdpHeader)); +} + +void udp_enqueue_packet(NetworkConnection *conn, NetBuffer *net_buffer) { + disable_preempt(); + spin_lock(&conn->recv_lock); + + list_add_tail(&net_buffer->list, &conn->recv_lh); + + spin_unlock(&conn->recv_lock); + thread_unblock(conn->thread); + enable_preempt(); +} + +/* + * 设置UDP回调函数 + */ +void udp_set_callback( + NetworkConnection *conn, + void (*callback)(NetworkConnection *conn, NetBuffer *buffer)) { + if (conn != NULL && conn->trans_protocol == TRANS_PROTO_UDP && + callback != NULL) { + conn->udp.callback = callback; + } else { + printk("[UDP] Invalid connection or callback function\n"); + } +} + +void udp_wrap(NetworkConnection *conn, uint16_t src_port, uint16_t dst_port) { + uint16_t size = CONN_CONTENT_SIZE(conn); + conn_header_alloc(conn, sizeof(UdpHeader)); + UdpHeader *udp_header = (UdpHeader *)conn->buffer->head; + udp_header->src_port = HOST2BE_WORD(src_port); + udp_header->dst_port = HOST2BE_WORD(dst_port); + udp_header->length = HOST2BE_WORD(sizeof(UdpHeader) + size); + udp_header->checksum = 0; // 暂时不计算校验和 +} + +void udp_bind(NetworkConnection *conn, uint16_t port) { + Ipv4ConnInfo *conn_info = &conn->ipv4.conn_info; + if (list_in_list(&conn_info->list)) return; // 已经绑定了端口 + conn_info->local.port = port; + list_add_tail(&conn_info->list, &udp_lh); +} + +void udp_unbind(NetworkConnection *conn) { + Ipv4ConnInfo *conn_info = &conn->ipv4.conn_info; + if (!list_in_list(&conn_info->list)) return; // 没有绑定端口 + list_del(&conn_info->list); +} + +ProtocolResult udp_recv(NetBuffer *net_buffer, Ipv4Header *ipv4_header) { + UdpHeader *udp_header = (UdpHeader *)net_buffer->data; + int size = net_buffer->tail - net_buffer->data; + + int length = BE2HOST_WORD(udp_header->length); + if (length < sizeof(UdpHeader)) return PROTO_ERROR_UNSUPPORT; // 数据包太小 + if (length > size) return PROTO_ERROR_EXCEED_MAX_SIZE; // 长度不合法 + + // TODO: 先检查目标是否为本机IP + + // 计算校验和(如果需要) + if (udp_header->checksum != 0) { + uint16_t checksum = udp_header->checksum; + void *ip[2] = { + ipv4_header->src_ip, // 源IP地址 + ipv4_header->dst_ip, // 目的IP地址 + }; + + uint16_t calc_checksum = udp_checksum(net_buffer, ip, 4, udp_header); + if (calc_checksum != checksum) { return PROTO_ERROR_CHECKSUM; } + } + + net_buffer->data += sizeof(UdpHeader); + + // IPv4 + Ipv4ConnInfo *info, *next; + if (list_empty(&udp_lh)) { + // 没有绑定的连接 + goto drop; + } + list_for_each_owner_safe (info, next, &udp_lh, list) { + if (info->local.port == BE2HOST_WORD(udp_header->dst_port) && + (info->remote.port == 0 || + info->remote.port == BE2HOST_WORD(udp_header->src_port))) { + if (memcmp(info->local.ip, ipv4_header->dst_ip, 4)) { + if (memcmp( + info->local.ip, (void *)&ipv4_null_addr, + 4) || // 不是发送到0.0.0.0 + memcmp( + ipv4_header->dst_ip, (void *)&ipv4_broadcast_addr, + 4)) // 也不是广播 + continue; + } + + // 找到匹配的连接 + NetworkConnection *conn = + container_of(info, NetworkConnection, ipv4.conn_info); + + if (conn->udp.callback) { + conn->udp.callback(conn, net_buffer); + } else { + goto drop; + } + + return PROTO_OK; + } + } + if (info->list.next == &udp_lh) { + // 没有找到匹配的连接,丢弃数据包 + drop: + kfree(net_buffer->ptr); + kfree(net_buffer); + return PROTO_DROP; + } + + return PROTO_OK; +} diff --git a/src/include/driver/network/buffer.h b/src/include/driver/network/buffer.h new file mode 100644 index 0000000..1743d13 --- /dev/null +++ b/src/include/driver/network/buffer.h @@ -0,0 +1,37 @@ +#ifndef _NET_BUFFER_H +#define _NET_BUFFER_H + +#include "kernel/list.h" +#include "protocols/protocols.h" +#include + +#define NET_BUF_RESV_HEAD(conn, n) \ + (conn)->buffer->head += (n); \ + (conn)->buffer->data += (n); \ + (conn)->buffer->tail += (n) + +typedef struct NetBuffer { + list_t list; + + void *ptr; // 缓冲区的地址 + uint16_t size; // 缓冲区的大小 + + void *head; // 包头的起始地址 + void *data; // 数据的起始地址 + void *tail; // 数据的结束地址,也是包尾的起始地址 +} NetBuffer; + +NetBuffer *net_buffer_create(uint16_t size); +void net_buffer_init( + NetBuffer *buffer, uint16_t size, uint16_t head, uint16_t tail); + +struct NetworkConnection; +ProtocolResult net_buffer_data_alloc(NetBuffer *buffer, uint16_t size); +void net_buffer_reset(NetBuffer *buffer); +void conn_header_alloc(struct NetworkConnection *conn, uint16_t size); +void conn_header_free(struct NetworkConnection *conn, uint16_t size); +void conn_tail_alloc(struct NetworkConnection *conn, uint16_t size); +void conn_tail_free(struct NetworkConnection *conn, uint16_t size); +ProtocolResult conn_put(struct NetworkConnection *conn, uint16_t size); + +#endif \ No newline at end of file diff --git a/src/include/driver/network/conn.h b/src/include/driver/network/conn.h new file mode 100644 index 0000000..522b9f9 --- /dev/null +++ b/src/include/driver/network/conn.h @@ -0,0 +1,94 @@ +#ifndef _NET_CONN_H +#define _NET_CONN_H + +#include "buffer.h" +#include "driver/network/ethernet/ethernet.h" +#include "driver/network/network_dm.h" +#include "driver/network/protocols/ipv4.h" +#include "kernel/list.h" +#include "kernel/spinlock.h" +#include "kernel/thread.h" +#include "kernel/wait_queue.h" +#include "objects/handle.h" +#include "objects/object.h" +#include + +#define NET_CONN_MAX_PROTOCOLS 8 + +#define CONN_CONTENT_SIZE(conn) ((conn)->buffer->tail - (conn)->buffer->head) + +struct NetworkConnection; +typedef struct NetProtocol { + uint16_t head_size; + uint16_t tail_size; +} NetProtocol; + +typedef struct NetworkConnection { + Object *object; + ObjectHandle *handle; + NetworkDevice *net_device; + + NetBuffer *buffer; + + struct task_s *thread; + + // physical layer protocol + enum { + PHY_PROTO_NONE, + PHY_PROTO_ETHERNET, + } phy_protocol; + union { + struct { + uint8_t mac[6]; + } ethernet; + }; + + // data link layer protocol + enum { + DL_PROTO_NONE, + DL_PROTO_ARP, + } dl_protocol; + union {}; + + // network layer protocol + enum { + NET_PROTO_NONE, + NET_PROTO_IPV4, + } net_protocol; + union { + struct { + uint16_t id; + uint8_t ip[4]; // IPv4地址 + struct { + uint16_t enable_fragment : 1; + uint16_t last_fragment : 1; + uint16_t frag_offset : 13; + } fragment; + struct Ipv4ConnInfo conn_info; // 连接信息 + + uint8_t subnet_mask[4]; + uint8_t gateway_ip[4]; + } ipv4; + }; + + // transport layer protocol + enum { + TRANS_PROTO_NONE, + TRANS_PROTO_TCP, + TRANS_PROTO_UDP, + } trans_protocol; + union { + struct { + void *private_data; + void (*callback)( + struct NetworkConnection *conn, NetBuffer *net_buffer); + } udp; + }; + spinlock_t recv_lock; + list_t recv_lh; +} NetworkConnection; + +NetworkConnection *net_create_conn(Object *object); +void net_destroy_conn(NetworkConnection *conn); + +#endif \ No newline at end of file diff --git a/src/include/driver/network/ethernet/ethernet.h b/src/include/driver/network/ethernet/ethernet.h new file mode 100644 index 0000000..86cea5f --- /dev/null +++ b/src/include/driver/network/ethernet/ethernet.h @@ -0,0 +1,41 @@ +#ifndef _NETWORK_ETHERNET_H +#define _NETWORK_ETHERNET_H + +#include "driver/network/buffer.h" +#include "driver/network/network_dm.h" +#include "driver/network/protocols/protocols.h" +#include + +#define ETH_MAX_FRAME_SIZE 1792 +#define ETH_MIN_FRAME_SIZE 60 +#define ETH_IDENTIFIER_SIZE 6 + +#define ETH_HEADER_SIZE 14 + +#define ETH_PROTO_TYPE_IPV4 0x0800 +#define ETH_PROTO_TYPE_ARP 0x0806 + +typedef struct EthernetHeader { + uint8_t dst_mac[ETH_IDENTIFIER_SIZE]; + uint8_t src_mac[ETH_IDENTIFIER_SIZE]; + uint16_t protocol_type; // Network layer protocol type +} EthernetHeader; + +typedef struct EthernetDevice { + NetworkDevice *net_device; + uint8_t mac_addr[ETH_IDENTIFIER_SIZE]; +} EthernetDevice; + +void eth_set_mac_address(EthernetDevice *device, uint8_t *mac_addr); +void eth_get_mac_address(EthernetDevice *device, uint8_t *mac_addr); + +struct NetworkConnection; + +extern const uint8_t eth_broadcast_mac[6]; + +void eth_register(struct NetworkConnection *conn); +ProtocolResult eth_wrap( + struct NetworkConnection *conn, const uint8_t *dst_addr, uint16_t protocol); +ProtocolResult eth_recv(NetBuffer *net_buffer); + +#endif \ No newline at end of file diff --git a/src/include/driver/network/mii.h b/src/include/driver/network/mii.h new file mode 100644 index 0000000..c55bba1 --- /dev/null +++ b/src/include/driver/network/mii.h @@ -0,0 +1,49 @@ +#ifndef _NETWORK_MII_H +#define _NETWORK_MII_H + +#include "network_dm.h" +#include +#include + +#define MII_REG_BMCR 0x00 +#define MII_REG_BMSR 0x01 +#define MII_REG_PHYID1 0x02 +#define MII_REG_PHYID2 0x03 +#define MII_REG_ANAR 0x04 +#define MII_REG_ANLPAR 0x05 + +#define MII_BMSR_EXT_CAP BIT(0) +#define MII_BMSR_JABBER_DETECTED BIT(1) +#define MII_BMSR_LINK_STATUS BIT(2) +#define MII_BMSR_AUTO_NEG BIT(3) +#define MII_BMSR_REMOTE_FAULT BIT(4) +#define MII_BMSR_AUTO_NEG_COMPLETE BIT(5) +#define MII_BMSR_EXT_STAT BIT(8) +#define MII_BMSR_10_HALF_DUPLEX BIT(11) +#define MII_BMSR_10_FULL_DUPLEX BIT(12) +#define MII_BMSR_100_HALF_DUPLEX BIT(13) +#define MII_BMSR_100_FULL_DUPLEX BIT(14) +#define MII_BMSR_100_T4 BIT(15) + +typedef enum MiiMediaType { + MMT_10HALF = 0b00000, + MMT_10FULL = 0b00001, + MMT_100HALF = 0b00010, + MMT_100FULL = 0b00011, + MMT_100T4 = 0b10010, + MMT_UNKNOWN, +} MiiMediaType; + +typedef struct Mii { + NetworkDevice *net_dev; + + uint32_t phy_id; + uint32_t full_duplex : 1; // 1: 全双工, 0: 半双工 + + int (*mdio_read)(struct Mii *mii, uint8_t reg_addr); + void (*mdio_write)(struct Mii *mii, uint8_t reg_addr, uint16_t data); +} Mii; + +DriverResult net_init_mii(Mii *mii); + +#endif \ No newline at end of file diff --git a/src/include/driver/network/net_queue.h b/src/include/driver/network/net_queue.h new file mode 100644 index 0000000..e0f1c1d --- /dev/null +++ b/src/include/driver/network/net_queue.h @@ -0,0 +1,13 @@ +#ifndef _NETWORK_QUEUE_H +#define _NETWORK_QUEUE_H + +#include +#include +#define NQ_BLOCKER_DRIVER BIT(0) +#define NQ_BLOCKER_SYSTEM BIT(1) + +typedef struct NetworkQueue { + uint8_t blocker; +} NetworkQueue; + +#endif \ No newline at end of file diff --git a/src/include/driver/network/network.h b/src/include/driver/network/network.h new file mode 100644 index 0000000..b25e316 --- /dev/null +++ b/src/include/driver/network/network.h @@ -0,0 +1,17 @@ +#ifndef _NETWORK_H +#define _NETWORK_H + +#include "kernel/list.h" +#include +#include + +typedef struct NetRxHandler { + list_t list; // 链表节点 + void (*handler)(void *data); + void *data; // 处理函数的私有数据 +} NetRxHandler; + +DriverResult network_softirq_register(NetRxHandler *handler); +void network_softirq_handler(void); + +#endif \ No newline at end of file diff --git a/src/include/driver/network/network_dm.h b/src/include/driver/network/network_dm.h new file mode 100644 index 0000000..b1fef7c --- /dev/null +++ b/src/include/driver/network/network_dm.h @@ -0,0 +1,78 @@ +#ifndef _NETWORK_DM_H +#define _NETWORK_DM_H + +#include "kernel/device.h" +#include "kernel/device_driver.h" +#include "kernel/device_manager.h" +#include "kernel/driver.h" +#include "net_queue.h" +#include "objects/transfer.h" +#include + +#define NETWORK_SEND(device, conn) \ + ((device)->ops->send( \ + device, conn->buffer->head, conn->buffer->tail - conn->buffer->head)) + +struct NetworkDevice; +typedef struct NetworkDeviceOps { + TransferResult (*send)(struct NetworkDevice *device, void *buf, int length); +} NetworkDeviceOps; + +typedef struct NetworkDeviceCapabilities { +} NetworkDeviceCapabilities; + +typedef enum NetworkDeviceType { + NETWORK_TYPE_UNKNOWN, + NETWORK_TYPE_ETHERNET, +} NetworkDeviceType; + +typedef enum NetworkDeviceState { + NET_STATE_INITED, + NET_STATE_NO_CARRIER, + NET_STATE_RUNNING, +} NetworkDeviceState; + +typedef struct NetworkDevice { + Device *device; + NetworkDeviceCapabilities capabilities; + NetworkDeviceOps *ops; + + uint16_t head_size; + uint16_t tail_size; + + NetworkDeviceState state; + NetworkQueue tx_queue; + + void *private_data; + + NetworkDeviceType type; + union { + struct EthernetDevice *ethernet; + }; + + union { + uint8_t ipv4[4]; + }; +} NetworkDevice; + +typedef struct NetworkDeviceManager { + int device_count; +} NetworkDeviceManager; + +extern DeviceManager network_dm; + +DriverResult register_network_device( + DeviceDriver *driver, Device *device, NetworkDevice *network_device, + ObjectAttr *attr); + +NetworkDevice *network_get_device(Object *object); + +struct NetworkConnection; +void net_queue_block(NetworkQueue *queue, int blocker); +bool net_queue_is_blocked(NetworkQueue *queue, int blocker); +TransferResult network_transfer( + struct Object *object, struct ObjectHandle *obj_handle, + TransferDirection direction, uint8_t *buf, size_t size); +struct NetBuffer *network_recv(struct NetworkConnection *conn); + +#endif \ No newline at end of file diff --git a/src/include/driver/network/protocols/arp.h b/src/include/driver/network/protocols/arp.h new file mode 100644 index 0000000..0e15b81 --- /dev/null +++ b/src/include/driver/network/protocols/arp.h @@ -0,0 +1,27 @@ +#ifndef _ARP_H +#define _ARP_H + +#include "../conn.h" +#include "protocols.h" +#include + +#define ARP_HTYPE_ETH 0x0001 + +#define ARP_TYPE 0x0806 + +#define ARP_OP_REQUEST 0x0001 +#define ARP_OP_REPLY 0x0002 + +typedef struct ArpHeader { + uint16_t htype; + uint16_t ptype; + uint8_t hlen; + uint8_t plen; + uint16_t opcode; +} __attribute__((packed)) ArpHeader; + +ProtocolResult arp_wrap( + NetworkConnection *conn, uint8_t *dst_haddr, uint8_t *dst_paddr, + uint16_t opcode); + +#endif \ No newline at end of file diff --git a/src/include/driver/network/protocols/dhcp.h b/src/include/driver/network/protocols/dhcp.h new file mode 100644 index 0000000..0a44333 --- /dev/null +++ b/src/include/driver/network/protocols/dhcp.h @@ -0,0 +1,170 @@ +#ifndef _DHCP_H +#define _DHCP_H + +#include "driver/network/conn.h" +#include "driver/network/network_dm.h" +#include "driver/timer_dm.h" +#include "math.h" +#include "stdint.h" + +#define DHCP_OP_BOOTREQUEST 1 +#define DHCP_OP_BOOTREPLY 2 +#define DHCP_HTYPE_ETHERNET 1 + +/** + * DHCP Options + * RFC 1533 + */ +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_SUBNET_MASK 1 +#define DHCP_OPTION_TIME_OFFSET 2 +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_TIMER_SERVER 4 +#define DHCP_OPTION_NAME_SERVER 5 +#define DHCP_OPTION_DOMAIN_NAME_SERVER 6 +#define DHCP_OPTION_LOG_SERVER 7 +#define DHCP_OPTION_COOKIE_SERVER 8 +#define DHCP_OPTION_LPR_SERVER 9 +#define DHCP_OPTION_IMPRESS_SERVER 10 +#define DHCP_OPTION_RESOURCE_LOCATION 11 +#define DHCP_OPTION_HOST_NAME 12 +#define DHCP_OPTION_BOOT_SIZE 13 +#define DHCP_OPTION_MERIT_DUMP_FILE 14 +#define DHCP_OPTION_DOMAIN_NAME 15 +#define DHCP_OPTION_SWAP_SERVER 16 +#define DHCP_OPTION_ROOT_PATH 17 +#define DHCP_OPTION_EXTENSIONS_PATH 18 +#define DHCP_OPTION_IP_FORWARDING 19 +#define DHCP_OPTION_NON_LOCAL_SOURCE_ROUTING 20 +#define DHCP_OPTION_POLICY_FILTER 21 +#define DHCP_OPTION_MAX_DATAGRAM_REASSEMBLY 22 +#define DHCP_OPTION_DEFAULT_IP_TIME_TO_LIVE 23 +#define DHCP_OPTION_PATH_MTU_AGING_TIMEOUT 24 +#define DHCP_OPTION_PATH_MTU_PLATEAU_TABLE 25 +#define DHCP_OPTION_INTERFACE_MTU 26 +#define DHCP_OPTION_ALL_SUBNETS_ARE_LOCAL 27 +#define DHCP_OPTION_BROADCAST_ADDRESS 28 +#define DHCP_OPTION_PERFORM_MASK_DISCOVERY 29 +#define DHCP_OPTION_MASK_SUPPLIER 30 +#define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31 +#define DHCP_OPTION_ROUTER_SOLICITATION_ADDRESS 32 +#define DHCP_OPTION_STATIC_ROUTE 33 +#define DHCP_OPTION_TRAILER_ENCAPSULATION 34 +#define DHCP_OPTION_ARP_CACHE_TIMEOUT 35 +#define DHCP_OPTION_ETHERNET_ENCAPSULATION 36 +#define DHCP_OPTION_TCP_DEFAULT_TTL 37 +#define DHCP_OPTION_TCP_KEEPALIVE_INTERVAL 38 +#define DHCP_OPTION_TCP_KEEPALIVE_GARBAGE 39 +#define DHCP_OPTION_NIS_DOMAIN 40 +#define DHCP_OPTION_NIS_SERVERS 41 +#define DHCP_OPTION_NTP_SERVERS 42 +#define DHCP_OPTION_VENDOR_SPECIFIC_INFO 43 +#define DHCP_OPTION_NETBIOS_NAME_SERVER 44 +#define DHCP_OPTION_NETBIOS_DATAGRAM_SERVER 45 +#define DHCP_OPTION_NETBIOS_NODE_TYPE 46 +#define DHCP_OPTION_NETBIOS_SCOPE 47 +#define DHCP_OPTION_FONT_SERVERS 48 +#define DHCP_OPTION_X_DISPLAY_MANAGER 49 +#define DHCP_OPTION_REQUESTED_IP_ADDRESS 50 +#define DHCP_OPTION_IP_ADDRESS_LEASE_TIME 51 +#define DHCP_OPTION_OVERLOAD 52 +#define DHCP_OPTION_MESSAGE_TYPE 53 +#define DHCP_OPTION_SERVER_IDENTIFIER 54 +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 +#define DHCP_OPTION_MESSAGE 56 +#define DHCP_OPTION_MAX_SIZE 57 +#define DHCP_OPTION_RENEWAL_TIME 58 +#define DHCP_OPTION_REBINDING_TIME 59 +#define DHCP_OPTION_VENDOR_CLASS_IDENTIFIER 60 +#define DHCP_OPTION_CLIENT_IDENTIFIER 61 +#define DHCP_OPTION_END 255 + +#define DHCP_MAGIC_COOKIE 0x63825363 // 99, 130, 83, 99 + +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +#define DHCP_RETRANSMIT_DELAY(retry_times) \ + MIN(1 << (retry_times + 2), 64) * 1000 + +typedef enum { + DOI_SUBNET_MASK, + DOI_ROUTER, + DOI_DNS, + DOI_SERVER_ID, + DOI_IP_LEASE_TIME, + DOI_MESSAGE_TYPE, + DOI_RENEWAL_TIME, + DOI_REBINDING_TIME, + DOI_MAX, +} DhcpOptionIndex; + +/** + * DHCP Client状态 + * 定义于RFC1541 Figure 5: State-transition diagram for DHCP client + */ +typedef enum { + DHCP_STAT_BOUND, + DHCP_STAT_INIT, + DHCP_STAT_INIT_REBOOT, + DHCP_STAT_REBINDING, + DHCP_STAT_REBOOTING, + DHCP_STAT_RENEWING, + DHCP_STAT_REQUESTING, + DHCP_STAT_SELECTING, + DHCP_FAILED, // 非RFC中包含的状态,表示重传失败退出 +} DhcpClientState; + +typedef struct { + NetworkDevice *device; + DhcpClientState state; + NetworkConnection *conn; + Timer timeout_timer; + Timer lease_timer; + Timer rebind_timer; + Timer renew_timer; + uint32_t t0, t1, t2; + + uint32_t xid; + uint8_t haddr_len; // 硬件地址长度 + uint8_t haddr_type; // 硬件地址类型 + uint8_t haddr[8]; // 硬件地址 + uint8_t ip_addr[4]; // IP地址 + uint8_t server_ip_addr[4]; // 服务器IP地址 + uint8_t server_haddr[8]; // 服务器硬件地址 + uint8_t gateway_ip_addr[4]; // 网关IP地址 + + int retry_times; // 重传次数 +} DhcpClient; + +/** + * DHCP报文头部结构 + * RFC 1541 Figure 1: Format of a DHCP message + */ +typedef struct { + uint8_t op; // Message type + uint8_t htype; // Hardware address type + uint8_t hlen; // Hardware address length + uint8_t hops; // Hops + uint32_t xid; // Transaction ID + uint16_t secs; // Seconds elapsed + uint16_t flags; // Flags + uint32_t ciaddr; // Client IP address + uint32_t yiaddr; // Your IP address + uint32_t siaddr; // Server IP address + uint32_t giaddr; // Gateway IP address + uint8_t chaddr[16]; // Client hardware address + uint8_t sname[64]; // Server name + uint8_t file[128]; // Boot file name + uint8_t options[0]; // Options field +} DhcpHeader; + +ProtocolResult dhcp_start(NetworkDevice *device); + +#endif \ No newline at end of file diff --git a/src/include/driver/network/protocols/ipv4.h b/src/include/driver/network/protocols/ipv4.h new file mode 100644 index 0000000..b45ef41 --- /dev/null +++ b/src/include/driver/network/protocols/ipv4.h @@ -0,0 +1,49 @@ +#ifndef _IPV4_H +#define _IPV4_H + +#include "kernel/list.h" +#include "protocols.h" +#include + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_TCP 6 +#define IP_PROTO_UDP 17 + +typedef struct Ipv4Header { + uint8_t ver_len; // Version and Internet Header Length + uint8_t tos; // Type of Service + uint16_t total_len; // Total Length + uint16_t id; // Identification + uint16_t flags_frag_offset; // Flags and Fragment Offset + uint8_t ttl; // Time to Live + uint8_t protocol; // Protocol + uint16_t checksum; // Header Checksum + uint8_t src_ip[4]; // Source IP Address + uint8_t dst_ip[4]; // Destination IP Address + uint8_t options[0]; // Options +} __attribute__((packed)) Ipv4Header; + +typedef struct Ipv4Endpoint { + uint8_t ip[4]; // IP地址 + uint16_t port; // 端口号 +} Ipv4Endpoint; + +typedef struct Ipv4ConnInfo { + list_t list; + Ipv4Endpoint local; // 本地IP和端口 + Ipv4Endpoint remote; // 远程IP和端口 +} Ipv4ConnInfo; + +extern const uint32_t ipv4_broadcast_addr; +extern const uint32_t ipv4_null_addr; + +struct NetworkConnection; +struct NetBuffer; +void ipv4_register(struct NetworkConnection *conn, uint8_t *ip_addr); +void ipv4_enable_fragment(struct NetworkConnection *conn); +ProtocolResult ipv4_wrap( + struct NetworkConnection *conn, uint16_t protocol, uint8_t *dst_ip, + uint8_t ttl); +ProtocolResult ipv4_recv(struct NetBuffer *net_buffer); + +#endif \ No newline at end of file diff --git a/src/include/driver/network/protocols/protocols.h b/src/include/driver/network/protocols/protocols.h new file mode 100644 index 0000000..453fd2a --- /dev/null +++ b/src/include/driver/network/protocols/protocols.h @@ -0,0 +1,17 @@ +#ifndef _NET_PROTOCOLS_H +#define _NET_PROTOCOLS_H + +#include + +typedef enum { + PROTO_OK, + PROTO_DROP, + PROTO_ERROR_UNSUPPORT, + PROTO_ERROR_EXCEED_MAX_SIZE, + PROTO_ERROR_NULL_PTR, + PROTO_ERROR_CHECKSUM, + PROTO_ERROR_SEND_FAILED, + PROTO_ERROR_OTHER, +} ProtocolResult; + +#endif \ No newline at end of file diff --git a/src/include/driver/network/protocols/udp.h b/src/include/driver/network/protocols/udp.h new file mode 100644 index 0000000..e4ce13d --- /dev/null +++ b/src/include/driver/network/protocols/udp.h @@ -0,0 +1,29 @@ +#ifndef _UDP_H +#define _UDP_H + +#include "driver/network/buffer.h" +#include "driver/network/protocols/ipv4.h" +#include + +#define UDP_PORT_DHCP_SERVER 67 +#define UDP_PORT_DHCP_CLIENT 68 + +typedef struct { + uint16_t src_port; // 源端口 + uint16_t dst_port; // 目的端口 + uint16_t length; // 数据长度 + uint16_t checksum; // 校验和 +} __attribute__((packed)) UdpHeader; + +struct NetworkConnection; +void udp_register(struct NetworkConnection *conn); +void udp_wrap( + struct NetworkConnection *conn, uint16_t src_port, uint16_t dst_port); +void udp_set_callback( + struct NetworkConnection *conn, + void (*callback)(struct NetworkConnection *conn, NetBuffer *buffer)); +void udp_bind(struct NetworkConnection *conn, uint16_t port); +void udp_unbind(struct NetworkConnection *conn); +ProtocolResult udp_recv(NetBuffer *net_buffer, Ipv4Header *ipv4_header); + +#endif \ No newline at end of file diff --git a/src/kernel/driver.c b/src/kernel/driver.c index 0ebda5b..124aaec 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -245,7 +245,7 @@ int dev_ioctl(struct index_node *inode, uint32_t cmd, uint32_t arg) { } void init_dm(void) { - init_network(); + // init_network(); } status_t driver_create(driver_func_t func, char *driver_name) { @@ -281,34 +281,34 @@ void driver_inited() { status_t device_create( driver_t *driver, unsigned long device_extension_size, char *name, dev_type_t type, device_t **device) { - device_t *devobj = kmalloc(sizeof(device_t) + device_extension_size); - devobj->type = type; - spinlock_init(&devobj->lock); - if (devobj == NULL) { return FAILED; } - list_init(&devobj->list); - if (device_extension_size > 0) { - devobj->device_extension = (void *)(devobj + 1); - } else { - devobj->device_extension = NULL; - } - if (string_new(&devobj->name, name, DEVICE_MAX_NAME_LEN)) { - kfree(devobj); - return FAILED; - } + // device_t *devobj = kmalloc(sizeof(device_t) + device_extension_size); + // devobj->type = type; + // spinlock_init(&devobj->lock); + // if (devobj == NULL) { return FAILED; } + // list_init(&devobj->list); + // if (device_extension_size > 0) { + // devobj->device_extension = (void *)(devobj + 1); + // } else { + // devobj->device_extension = NULL; + // } + // if (string_new(&devobj->name, name, DEVICE_MAX_NAME_LEN)) { + // kfree(devobj); + // return FAILED; + // } - devobj->drv_obj = driver; - list_add_tail(&devobj->list, &driver->device_list); - *device = devobj; - - if (type == DEV_ETH_NET) { - eth_dm.dm_register(ð_dm, devobj, name); - driver->dm = ð_dm; - } else { - // devobj->inode = vfs_create(name, ATTR_DEV, dev); - devobj->inode->device = devobj; - // devobj->inode->f_ops = device_fops; - devobj->inode->fp = kmalloc(sizeof(struct file)); - } + // devobj->drv_obj = driver; + // list_add_tail(&devobj->list, &driver->device_list); + // *device = devobj; + + // if (type == DEV_ETH_NET) { + // eth_dm.dm_register(ð_dm, devobj, name); + // driver->dm = ð_dm; + // } else { + // // devobj->inode = vfs_create(name, ATTR_DEV, dev); + // devobj->inode->device = devobj; + // // devobj->inode->f_ops = device_fops; + // devobj->inode->fp = kmalloc(sizeof(struct file)); + // } return SUCCUESS; } diff --git a/src/kernel/main.c b/src/kernel/main.c index 0482c38..58d00cd 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -4,21 +4,27 @@ * @brief 内核主程序 * @date 2020-03 */ -#include "bios_emu/bios_emu.h" -#include "bios_emu/exceptions.h" -#include "driver/sound/pcm.h" -#include "driver/sound/sound_dm.h" -#include "drivers/vesa_display.h" -#include "kernel/page.h" -#include "objects/handle.h" -#include "string.h" +#include "driver/network/buffer.h" +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include #include #include +#include #include #include #include @@ -33,22 +39,16 @@ #include #include #include +#include #include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include #include +#include void idle(void *arg); struct task_s *task_idle; @@ -108,6 +108,8 @@ void thread_play(void *arg) { } } +void network_timer_init(void); + int main() { platform_early_init(); @@ -123,6 +125,7 @@ int main() { register_device_manager(&video_dm); register_device_manager(&sound_dm); register_device_manager(&storage_dm); + register_device_manager(&network_dm); init_object_tree(); @@ -143,6 +146,32 @@ int main() { do_initcalls(); driver_start_all(); + Object *net; + ObjectResult result = open_object_by_path("\\Device\\Network0", &net); + if (result == OBJECT_OK) { + dhcp_start(net->value.device->dm_ext); + // uint8_t dst_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + // uint8_t dst_ip[] = {10, 0, 2, 2}; + // uint8_t udp_data[] = "Hello, World!"; + + // NetworkConnection *conn = net_create_conn(net); + // conn->buffer = net_buffer_create(128); + // net_buffer_init(conn->buffer, 128, 0, 0); + + // eth_register(conn); + // ipv4_register(conn, NULL); + // udp_register(conn); + + // // conn_put(conn, udp_data, sizeof(udp_data)); + + // udp_wrap(conn, 1234, 22); + // ipv4_wrap(conn, IP_PROTO_UDP, dst_ip, 64); + // eth_wrap(conn, dst_mac, ETH_PROTO_TYPE_IPV4); + // TRANSFER_OUT_STREAM( + // net, conn->handle, conn->buffer->head, + // conn->buffer->tail - conn->buffer->head); + } + // bios_emu_env.regs.ax = 0x4f02; // bios_emu_env.regs.bx = 0x4192; // 1920x1080x32bit模式 // BiosEmuExceptions exception = emu_interrupt(0x10); // 调用BIOS 0x10中断 diff --git a/src/network/dhcp.c b/src/network/dhcp.c index 5546052..62dad46 100644 --- a/src/network/dhcp.c +++ b/src/network/dhcp.c @@ -6,8 +6,8 @@ #include #include #include +#include #include -#include uint8_t dhcp_magic_cookie[4] = {99, 130, 83, 99}; @@ -50,7 +50,8 @@ int dhcp_main(net_device_t *net_dev) { udp_send(netc, (uint16_t *)buf, sizeof(dhcp_basic_t) + 8); netc_read(netc, buf, sizeof(dhcp_basic_t) + 4); - if (memcmp(buf + sizeof(dhcp_basic_t), dhcp_magic_cookie, 4) != 0) return -2; + if (memcmp(buf + sizeof(dhcp_basic_t), dhcp_magic_cookie, 4) != 0) + return -2; netc_read(netc, &option, sizeof(option)); netc_read(netc, &len, sizeof(len)); if (option != DHCP_OPTION_MSG_TYPE) return -3; @@ -106,7 +107,8 @@ int dhcp_main(net_device_t *net_dev) { udp_send(netc, (uint16_t *)buf, sizeof(dhcp_basic_t) + 20); netc_read(netc, buf, sizeof(dhcp_basic_t) + 4); - if (memcmp(buf + sizeof(dhcp_basic_t), dhcp_magic_cookie, 4) != 0) return -2; + if (memcmp(buf + sizeof(dhcp_basic_t), dhcp_magic_cookie, 4) != 0) + return -2; ipv4_set_ip(netc, ((dhcp_basic_t *)buf)->yiAddr); netc_read(netc, &option, sizeof(option)); netc_read(netc, &len, sizeof(len)); diff --git a/src/network/tcp.c b/src/network/tcp.c index 2419e89..6296f9c 100644 --- a/src/network/tcp.c +++ b/src/network/tcp.c @@ -9,8 +9,8 @@ #include #include #include +#include #include -#include #include From 082da62ccc1496940b083c7319b1f0ee0bd5a30f Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 20 Aug 2025 01:37:21 +0800 Subject: [PATCH 078/158] =?UTF-8?q?ipv4:=20=E5=88=A0=E9=99=A4=20=E4=BF=9D?= =?UTF-8?q?=E5=AD=98ipv4=E5=A4=B4=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/protocols/ipv4.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/driver/network/protocols/ipv4.c b/src/driver/network/protocols/ipv4.c index ccc19bf..0c68947 100644 --- a/src/driver/network/protocols/ipv4.c +++ b/src/driver/network/protocols/ipv4.c @@ -91,8 +91,6 @@ ProtocolResult ipv4_wrap( } ipv4_checksum(ipv4_header); - conn->ipv4.header = ipv4_header; - return PROTO_OK; } From 798f3d411742924758341ad33bf26da2b296845b Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 20 Aug 2025 01:38:48 +0800 Subject: [PATCH 079/158] =?UTF-8?q?dhcp:=20=E4=BF=AE=E6=94=B9=20=E5=B0=86?= =?UTF-8?q?=E7=BB=91=E5=AE=9Audp=E7=AB=AF=E5=8F=A3=E5=8F=8A=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E5=9B=9E=E8=B0=83=E5=87=BD=E6=95=B0=E7=9A=84=E6=AD=A5?= =?UTF-8?q?=E9=AA=A4=E7=A7=BB=E5=88=B0dhcp=5Freset=E4=B8=AD=E5=AE=8C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/protocols/dhcp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/driver/network/protocols/dhcp.c b/src/driver/network/protocols/dhcp.c index fd9933a..4e9042a 100644 --- a/src/driver/network/protocols/dhcp.c +++ b/src/driver/network/protocols/dhcp.c @@ -484,9 +484,6 @@ void dhcp_init(DhcpClient *dhcp, NetworkConnection *conn) { dhcp->conn = conn; conn->udp.private_data = dhcp; - udp_bind(dhcp->conn, UDP_PORT_DHCP_CLIENT); - udp_set_callback(conn, dhcp_rx_handler); - timer_init(&dhcp->timeout_timer); timer_init(&dhcp->lease_timer); timer_init(&dhcp->renew_timer); @@ -510,6 +507,9 @@ void dhcp_reset(DhcpClient *dhcp, NetworkConnection *conn) { ipv4_register(conn, NULL); udp_register(conn); + udp_bind(dhcp->conn, UDP_PORT_DHCP_CLIENT); + udp_set_callback(conn, dhcp_rx_handler); + switch (dhcp->device->type) { case NETWORK_TYPE_ETHERNET: dhcp->haddr_len = ETH_IDENTIFIER_SIZE; From 6c7017c30171753be80ef660d47ac2666947621c Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 20 Aug 2025 20:56:51 +0800 Subject: [PATCH 080/158] =?UTF-8?q?script:=20=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?=E5=9C=A8mac=E4=B8=8B=E7=BC=96=E8=AF=91=E7=9A=84=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + Makefile | 17 ++++++++++++++--- install_grub.py | 5 ++++- qemu-linux.cfg | 7 +++++++ qemu-macos.cfg | 7 +++++++ qemu-windows.cfg | 7 +++++++ scripts/define.mk | 14 +++++++------- scripts/localenv.mk | 2 +- 8 files changed, 48 insertions(+), 12 deletions(-) create mode 100644 qemu-linux.cfg create mode 100644 qemu-macos.cfg create mode 100644 qemu-windows.cfg diff --git a/.gitignore b/.gitignore index f98f72a..fd0e92e 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,4 @@ fixdep *.log *.dat *.idx +dump.pcap diff --git a/Makefile b/Makefile index 042b13b..f10f0e2 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +UNAME_S := $(shell uname -s) + DD = dd CP = cp GRUB_MKIMG = grub-mkimage @@ -13,6 +15,14 @@ ifeq ($(ARCH), x86) TARGET_PLATFORM = i386-pc endif +ifeq ($(UNAME_S),Linux) + QEMU_CFG = qemu-linux.cfg +else ifeq ($(UNAME_S),Darwin) + QEMU_CFG = qemu-macos.cfg +else ifeq ($(OS),Windows_NT) + QEMU_CFG = qemu-windows.cfg +endif + FD_IMG = ./horizon.img HD_IMG = ./hd0.img HD_SIZE = 64M @@ -99,7 +109,8 @@ qemu_dbg: -device usb-mouse \ -device rtl8139,netdev=nc1 \ -netdev user,id=nc1,hostfwd=tcp::5555-:80 \ - -object filter-dump,id=f1,netdev=nc1,file=dump.dat \ + -object filter-dump,id=f1,netdev=nc1,file=dump.pcap \ + -readconfig $(QEMU_CFG) \ -boot c qemu: @@ -110,8 +121,8 @@ qemu: -hda $(HD_IMG) \ -usb \ -device usb-mouse \ - -audio pa,model=sb16 \ -device rtl8139,netdev=nc1 \ -netdev user,id=nc1,hostfwd=tcp::5555-:80 \ - -object filter-dump,id=f1,netdev=nc1,file=dump.dat \ + -object filter-dump,id=f1,netdev=nc1,file=dump.pcap \ + -readconfig $(QEMU_CFG) \ -boot c \ No newline at end of file diff --git a/install_grub.py b/install_grub.py index a438b5c..335aac7 100644 --- a/install_grub.py +++ b/install_grub.py @@ -14,7 +14,10 @@ disk_dir_path = 'disk' grub_cfg_path = 'grub.cfg' prefix_path = "/boot/grub/" -grub_mkimage_path = "grub-mkimage" +if os.uname().sysname == "Darwin": + grub_mkimage_path = "x86_64-elf-grub-mkimage" +else: + grub_mkimage_path = "grub-mkimage" default_mods =\ "minicmd normal gzio gcry_crc verifiers terminal \ priority_queue gettext extcmd datetime crypto bufio boot \ diff --git a/qemu-linux.cfg b/qemu-linux.cfg new file mode 100644 index 0000000..1eea83c --- /dev/null +++ b/qemu-linux.cfg @@ -0,0 +1,7 @@ +[audiodev "snd0"] +driver = "pa" +id = "snd0" + +[device "sb16"] +driver = "sb16" +audiodev = "snd0" \ No newline at end of file diff --git a/qemu-macos.cfg b/qemu-macos.cfg new file mode 100644 index 0000000..9781a47 --- /dev/null +++ b/qemu-macos.cfg @@ -0,0 +1,7 @@ +[audiodev "snd0"] +driver = "coreaudio" +id = "snd0" + +[device "sb16"] +driver = "sb16" +audiodev = "snd0" \ No newline at end of file diff --git a/qemu-windows.cfg b/qemu-windows.cfg new file mode 100644 index 0000000..22f544a --- /dev/null +++ b/qemu-windows.cfg @@ -0,0 +1,7 @@ +[audiodev "snd0"] +driver = "dsound" +id = "snd0" + +[device "sb16"] +driver = "sb16" +audiodev = "snd0" \ No newline at end of file diff --git a/scripts/define.mk b/scripts/define.mk index 5e0a6cc..d1c4cb3 100644 --- a/scripts/define.mk +++ b/scripts/define.mk @@ -59,19 +59,19 @@ endif export ECHO_RM ECHO_CC ECHO_CXX ECHO_AS ECHO_LD ECHO_AR ECHO_OUTPUT ECHO_HOSTCC -CROSS_COMPILE ?= +CROSS_COMPILE ?= # Make variables (CC, etc...) -AS := $(CROSS_COMPILE)clang -x assembler-with-cpp -CC := $(CROSS_COMPILE)clang -CPP := $(CROSS_COMPILE)clang -E -CXX := $(CROSS_COMPILE)clang++ -LD := $(CROSS_COMPILE)lld +AS := $(CROSS_COMPILE)clang --target=x86_64-elf -x assembler-with-cpp +CC := $(CROSS_COMPILE)clang --target=x86_64-elf +CPP := $(CROSS_COMPILE)clang --target=x86_64-elf -E +CXX := $(CROSS_COMPILE)clang++ --target=x86_64-elf +LD := $(CROSS_COMPILE)ld AR := $(CROSS_COMPILE)ar OC := $(CROSS_COMPILE)objcopy OD := $(CROSS_COMPILE)objdump NM := $(CROSS_COMPILE)nm -HOSTCC := gcc +HOSTCC := clang export AS AR CC LD CPP CXX OC OD NM HOSTCC \ No newline at end of file diff --git a/scripts/localenv.mk b/scripts/localenv.mk index bd468ff..6aa6071 100644 --- a/scripts/localenv.mk +++ b/scripts/localenv.mk @@ -11,7 +11,7 @@ ENV_APP_LD_SCRIPT := -T ../apps/app.lds # MacOS special ifeq ($(shell uname),Darwin) - ENV_LD := i386-elf-ld -m elf_i386 + ENV_LD := x86_64-elf-ld -m elf_i386 else ENV_LD := ld -m elf_i386 endif From 47a79a97ae27e8e4d42446d6b8395063e8c206e8 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 20 Aug 2025 20:57:26 +0800 Subject: [PATCH 081/158] =?UTF-8?q?dhcp:=20=E4=BF=AE=E5=A4=8D=20=E7=BB=AD?= =?UTF-8?q?=E7=A7=9F=E7=9A=84=E9=80=BB=E8=BE=91=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/protocols/dhcp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/driver/network/protocols/dhcp.c b/src/driver/network/protocols/dhcp.c index 4e9042a..0451d3e 100644 --- a/src/driver/network/protocols/dhcp.c +++ b/src/driver/network/protocols/dhcp.c @@ -105,6 +105,7 @@ void dhcp_ip_lease_handler(void *arg) { void dhcp_renew_handler(void *arg) { DhcpClient *dhcp = arg; if (dhcp->state == DHCP_STAT_BOUND) { + // TODO: 单播 uint8_t *ptr = dhcp_create_message(dhcp, dhcp->conn->buffer->data, DHCP_REQUEST); @@ -128,16 +129,16 @@ void dhcp_renew_handler(void *arg) { int initial_timeout = DHCP_INIT_TIMEOUT(dhcp); DHCP_SET_TIMEOUT(dhcp, initial_timeout); + dhcp->state = DHCP_STAT_RENEWING; ProtocolResult result = dhcp_send(dhcp, sizeof(DhcpHeader) + len); if (result != PROTO_OK) return; - - dhcp->state = DHCP_STAT_RENEWING; } } void dhcp_rebind_handler(void *arg) { DhcpClient *dhcp = arg; if (dhcp->state == DHCP_STAT_RENEWING) { + // TODO: 广播 uint8_t *ptr = dhcp_create_message(dhcp, dhcp->conn->buffer->data, DHCP_REQUEST); @@ -161,10 +162,9 @@ void dhcp_rebind_handler(void *arg) { int initial_timeout = DHCP_INIT_TIMEOUT(dhcp); DHCP_SET_TIMEOUT(dhcp, initial_timeout); + dhcp->state = DHCP_STAT_REBINDING; ProtocolResult result = dhcp_send(dhcp, sizeof(DhcpHeader) + len); if (result != PROTO_OK) return; - - dhcp->state = DHCP_STAT_REBINDING; } } @@ -383,7 +383,7 @@ ProtocolResult dhcp_send(DhcpClient *dhcp, uint16_t len) { UDP_PORT_DHCP_SERVER); // DHCP客户端端口68,服务器端口67 if (dhcp->state == DHCP_STAT_SELECTING || dhcp->state == DHCP_STAT_REQUESTING || - dhcp->state == DHCP_STAT_RENEWING) { + dhcp->state == DHCP_STAT_REBINDING) { ipv4_wrap( dhcp->conn, IP_PROTO_UDP, (uint8_t *)&ipv4_broadcast_addr, 64); } else { From dce42abdadc4f58df16301593cf7b99422db2453 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 22 Aug 2025 01:33:46 +0800 Subject: [PATCH 082/158] =?UTF-8?q?network&ehthernet:=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20=E5=9C=B0=E5=9D=80=E5=8F=91=E7=8E=B0=E4=B8=93=E7=94=A8conn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/network_dm.c | 17 +++++++++++++++++ src/include/driver/network/ethernet/ethernet.h | 5 +++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/driver/network/network_dm.c b/src/driver/network/network_dm.c index d2b2769..69b268b 100644 --- a/src/driver/network/network_dm.c +++ b/src/driver/network/network_dm.c @@ -1,3 +1,6 @@ +#include "driver/network/buffer.h" +#include "driver/network/conn.h" +#include "driver/network/ethernet/ethernet.h" #include "driver/network/network.h" #include "kernel/softirq.h" #include "objects/transfer.h" @@ -54,6 +57,20 @@ DriverResult register_network_device( device->object->out.type = TRANSFER_TYPE_STREAM; device->object->out.stream = network_transfer; + switch (network_device->type) { + case NETWORK_TYPE_ETHERNET: { + EthernetDevice *eth_device = kmalloc(sizeof(EthernetDevice)); + network_device->ethernet = eth_device; + eth_device->arp_conn = net_create_conn(device->object); + conn_buffer(eth_device->arp_conn) = net_buffer_create(128); + net_buffer_init(conn_buffer(eth_device->arp_conn), 128, 0, 0); + eth_register(eth_device->arp_conn); + break; + } + default: + break; + } + return DRIVER_RESULT_OK; } diff --git a/src/include/driver/network/ethernet/ethernet.h b/src/include/driver/network/ethernet/ethernet.h index 86cea5f..bf184b2 100644 --- a/src/include/driver/network/ethernet/ethernet.h +++ b/src/include/driver/network/ethernet/ethernet.h @@ -22,8 +22,9 @@ typedef struct EthernetHeader { } EthernetHeader; typedef struct EthernetDevice { - NetworkDevice *net_device; - uint8_t mac_addr[ETH_IDENTIFIER_SIZE]; + struct NetworkConnection *arp_conn; + NetworkDevice *net_device; + uint8_t mac_addr[ETH_IDENTIFIER_SIZE]; } EthernetDevice; void eth_set_mac_address(EthernetDevice *device, uint8_t *mac_addr); From 8a803d93c1aa2f20779b0ac56f82cac9e701364d Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 22 Aug 2025 01:38:03 +0800 Subject: [PATCH 083/158] =?UTF-8?q?network&arp:=20=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?=E9=82=BB=E5=B1=85=E5=8F=91=E7=8E=B0=E7=B3=BB=E7=BB=9F=EF=BC=9B?= =?UTF-8?q?=20network:=20=E4=BF=AE=E6=94=B9=20NetBuffer=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E4=B8=8D=E5=86=8D=E4=BD=BF=E7=94=A8NetworkCo?= =?UTF-8?q?nnection=E4=BD=9C=E4=B8=BA=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../x86/drivers/network/rtl8139/rtl8139.c | 4 +- src/driver/network/Makefile | 1 + src/driver/network/buffer.c | 19 +- src/driver/network/ethernet/ethernet.c | 19 +- src/driver/network/neighbour.c | 78 ++++++++ src/driver/network/network_dm.c | 2 + src/driver/network/protocols/arp.c | 166 ++++++++++++++---- src/driver/network/protocols/dhcp.c | 18 +- src/driver/network/protocols/ipv4.c | 10 +- src/driver/network/protocols/udp.c | 6 +- src/include/driver/network/buffer.h | 10 +- src/include/driver/network/conn.h | 2 + .../driver/network/ethernet/ethernet.h | 5 +- src/include/driver/network/neighbour.h | 60 +++++++ src/include/driver/network/network_dm.h | 2 +- src/include/driver/network/protocols/arp.h | 10 +- src/include/driver/network/protocols/ipv4.h | 2 + 17 files changed, 338 insertions(+), 76 deletions(-) create mode 100644 src/driver/network/neighbour.c create mode 100644 src/include/driver/network/neighbour.h diff --git a/src/arch/x86/drivers/network/rtl8139/rtl8139.c b/src/arch/x86/drivers/network/rtl8139/rtl8139.c index a9b038d..cd7b64d 100644 --- a/src/arch/x86/drivers/network/rtl8139/rtl8139.c +++ b/src/arch/x86/drivers/network/rtl8139/rtl8139.c @@ -135,7 +135,7 @@ void rtl8139_net_rx_handler(void *data) { } else { memcpy(buffer, device->rx_buffer + i, length); } - eth_recv(net_buffer); + eth_recv(device->net_device, net_buffer); } else { printk( "[RTL8139]RX Error: status %#04x,size %#04x, cur %#04x\n", @@ -206,8 +206,6 @@ DriverResult rtl8139_init(Device *device) { rtl_device->mii.net_dev = device->dm_ext; rtl_device->mii.mdio_read = mdio_read; rtl_device->mii.mdio_write = mdio_write; - rtl_device->net_device->ethernet = - kmalloc_from_template(rtl8139_network_device_template); timer_init(&rtl_device->timer); SPINLOCK_INIT(rtl_device->lock); diff --git a/src/driver/network/Makefile b/src/driver/network/Makefile index d487faa..a92df03 100644 --- a/src/driver/network/Makefile +++ b/src/driver/network/Makefile @@ -3,5 +3,6 @@ SRC += network.c SRC += mii.c SRC += conn.c SRC += buffer.c +SRC += neighbour.c SRC += ethernet/ SRC += protocols/ \ No newline at end of file diff --git a/src/driver/network/buffer.c b/src/driver/network/buffer.c index 32928e6..cb4c8c0 100644 --- a/src/driver/network/buffer.c +++ b/src/driver/network/buffer.c @@ -30,20 +30,20 @@ void net_buffer_reset(NetBuffer *buffer) { buffer->tail = buffer->data; } -void conn_header_alloc(NetworkConnection *conn, uint16_t size) { - conn->buffer->head -= size; +void net_buffer_header_alloc(NetBuffer *buffer, uint16_t size) { + buffer->head -= size; } -void conn_header_free(NetworkConnection *conn, uint16_t size) { - conn->buffer->head += size; +void net_buffer_header_free(NetBuffer *buffer, uint16_t size) { + buffer->head += size; } -void conn_tail_alloc(NetworkConnection *conn, uint16_t size) { - conn->buffer->tail += size; +void net_buffer_tail_alloc(NetBuffer *buffer, uint16_t size) { + buffer->tail += size; } -void conn_tail_free(NetworkConnection *conn, uint16_t size) { - conn->buffer->tail -= size; +void net_buffer_tail_free(NetBuffer *buffer, uint16_t size) { + buffer->tail -= size; } ProtocolResult net_buffer_data_alloc(NetBuffer *buffer, uint16_t size) { @@ -55,8 +55,7 @@ ProtocolResult net_buffer_data_alloc(NetBuffer *buffer, uint16_t size) { return PROTO_OK; } -ProtocolResult conn_put(NetworkConnection *conn, uint16_t size) { - NetBuffer *buffer = conn->buffer; +ProtocolResult net_buffer_put(NetBuffer *buffer, uint16_t size) { if (buffer->tail + size > buffer->ptr + buffer->size) { // 如果数据超过了缓冲区的大小,则不进行写入 return PROTO_ERROR_EXCEED_MAX_SIZE; diff --git a/src/driver/network/ethernet/ethernet.c b/src/driver/network/ethernet/ethernet.c index ba6d582..3f13164 100644 --- a/src/driver/network/ethernet/ethernet.c +++ b/src/driver/network/ethernet/ethernet.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -46,25 +47,26 @@ void eth_register(NetworkConnection *conn) { } ProtocolResult eth_wrap( - NetworkConnection *conn, const uint8_t *dst_addr, uint16_t protocol) { - conn_header_alloc(conn, 14); - EthernetHeader *header = (EthernetHeader *)conn->buffer->head; + NetBuffer *buffer, uint8_t *mac_addr, const uint8_t *dst_addr, + uint16_t protocol) { + net_buffer_header_alloc(buffer, 14); + EthernetHeader *header = (EthernetHeader *)buffer->head; memcpy(header->dst_mac, dst_addr, 6); - memcpy(header->src_mac, conn->ethernet.mac, 6); + memcpy(header->src_mac, mac_addr, 6); - int content_size = CONN_CONTENT_SIZE(conn); + int content_size = buffer->tail - buffer->head; if (content_size > ETH_MAX_FRAME_SIZE) return PROTO_ERROR_EXCEED_MAX_SIZE; if (content_size < ETH_MIN_FRAME_SIZE) { // 填充最小帧长度 - memset(conn->buffer->tail, 0, ETH_MIN_FRAME_SIZE - content_size); - conn->buffer->tail = conn->buffer->head + ETH_MIN_FRAME_SIZE; + memset(buffer->tail, 0, ETH_MIN_FRAME_SIZE - content_size); + buffer->tail = buffer->head + ETH_MIN_FRAME_SIZE; } header->protocol_type = HOST2BE_WORD(protocol); return PROTO_OK; } -ProtocolResult eth_recv(NetBuffer *net_buffer) { +ProtocolResult eth_recv(NetworkDevice *device, NetBuffer *net_buffer) { EthernetHeader *header = (EthernetHeader *)net_buffer->data; int size = net_buffer->tail - net_buffer->data; if (size < ETH_HEADER_SIZE) { return PROTO_ERROR_UNSUPPORT; } @@ -78,6 +80,7 @@ ProtocolResult eth_recv(NetBuffer *net_buffer) { result = ipv4_recv(net_buffer); break; case ETH_PROTO_TYPE_ARP: + result = arp_recv(device, net_buffer); break; default: result = PROTO_ERROR_UNSUPPORT; diff --git a/src/driver/network/neighbour.c b/src/driver/network/neighbour.c new file mode 100644 index 0000000..c2caf35 --- /dev/null +++ b/src/driver/network/neighbour.c @@ -0,0 +1,78 @@ +#include "driver/network/network_dm.h" +#include "driver/network/protocols/arp.h" +#include "kernel/driver.h" +#include "kernel/list.h" +#include "kernel/spinlock.h" +#include +#include +#include +#include + +NeighbourTable neighbour_table; +int neighbour_max_retries = 5; + +void neighbour_init(void) { + for (int i = 0; i < NEIGH_BUCKET_SIZE; i++) { + list_init(&neighbour_table.buckets[i]); + spinlock_init(&neighbour_table.lock[i]); + } +} + +NeighbourEntry *neighbour_entry_create( + NetworkDevice *device, NeighbourKey hash_key, uint8_t *addr, + uint8_t length) { + NeighbourEntry *entry = kmalloc(sizeof(NeighbourEntry) + length); + if (!entry) { return NULL; } + + hash_key %= NEIGH_BUCKET_SIZE; + + spinlock_init(&entry->lock); + entry->key = hash_key; + entry->state = NEIGH_STATE_NONE; + entry->device = device; + memset(entry->haddr, 0, sizeof(entry->haddr)); + memcpy(entry->ip_addr, addr, length); + + // list_init(&entry->list); + + switch (device->type) { + case NETWORK_TYPE_ETHERNET: + entry->ops = &arp_proto_ops; + break; + default: + break; + } + + entry->ip_length = length; + memcpy(entry->ip_addr, addr, length); + + NeighbourTable *table = &neighbour_table; + spin_lock(&table->lock[hash_key]); + list_add_tail(&entry->list, &table->buckets[hash_key]); + spin_unlock(&table->lock[hash_key]); + + return entry; +} + +NeighbourEntry *neighbour_table_lookup( + NetworkDevice *device, NeighbourKey hash_key, uint8_t *ip_addr, + uint8_t ip_length) { + NeighbourEntry *entry = NULL; + + hash_key %= NEIGH_BUCKET_SIZE; + spin_lock(&neighbour_table.lock[hash_key]); + list_for_each_owner (entry, &neighbour_table.buckets[hash_key], list) { + if (ip_length == entry->ip_length && + memcmp(entry->ip_addr, ip_addr, ip_length) == 0) { + spin_unlock(&neighbour_table.lock[hash_key]); + return entry; + } + } + spin_unlock(&neighbour_table.lock[hash_key]); + + entry = neighbour_entry_create(device, hash_key, ip_addr, ip_length); + + entry->ops->request(entry, NULL); + + return entry; +} diff --git a/src/driver/network/network_dm.c b/src/driver/network/network_dm.c index 69b268b..8f484da 100644 --- a/src/driver/network/network_dm.c +++ b/src/driver/network/network_dm.c @@ -4,6 +4,7 @@ #include "driver/network/network.h" #include "kernel/softirq.h" #include "objects/transfer.h" +#include #include #include #include @@ -31,6 +32,7 @@ DeviceManager network_dm = { DriverResult network_dm_load(DeviceManager *manager) { manager->private_data = kmalloc(sizeof(NetworkDeviceManager)); softirq_register_handler(SOFTIRQ_NETWORK, network_softirq_handler); + neighbour_init(); return DRIVER_RESULT_OK; } diff --git a/src/driver/network/protocols/arp.c b/src/driver/network/protocols/arp.c index 80cd25d..575d9c3 100644 --- a/src/driver/network/protocols/arp.c +++ b/src/driver/network/protocols/arp.c @@ -7,53 +7,149 @@ * RFC 826: An Ethernet Address Resolution Protocol * */ +#include "driver/network/buffer.h" +#include "driver/network/ethernet/ethernet.h" +#include "driver/network/network_dm.h" +#include "kernel/list.h" +#include "kernel/spinlock.h" #include #include +#include #include #include #include #include #include -ProtocolResult arp_wrap( - NetworkConnection *conn, uint8_t *dst_haddr, uint8_t *dst_paddr, - uint16_t opcode) { - uint16_t htype = 0, ptype = 0; - uint8_t hlen = 0, plen = 0; - uint8_t *src_haddr, *src_paddr; - switch (conn->phy_protocol) { - case PHY_PROTO_ETHERNET: - src_haddr = conn->ethernet.mac; - hlen = 6; - htype = HOST2BE_WORD(ARP_HTYPE_ETH); - break; - default: - return PROTO_ERROR_UNSUPPORT; +void arp_send_request(NeighbourEntry *entry, void *arg); + +NeighbourProtoOps arp_proto_ops = { + .request = arp_send_request, +}; + +ProtocolResult arp_recv(NetworkDevice *device, NetBuffer *net_buffer) { + ArpHeader *arp_header = (ArpHeader *)net_buffer->data; + + void *p = (void *)(arp_header + 1); + void *src_haddr = p; + void *src_paddr = p + arp_header->hlen; + void *dst_haddr = p + arp_header->hlen + arp_header->plen; + void *dst_paddr = p + arp_header->hlen * 2 + arp_header->plen; + + // 检查硬件类型 + uint16_t htype = BE2HOST_WORD(arp_header->htype); + uint8_t haddr[8]; + uint8_t *mac_addr = device->ethernet->mac_addr; + if (htype == ARP_HTYPE_ETH && device->type == NETWORK_TYPE_ETHERNET) { + if (arp_header->hlen == ETH_IDENTIFIER_SIZE) { + if (memcmp(dst_haddr, eth_broadcast_mac, arp_header->hlen) == 0) { + // 处理广播地址 + p = mac_addr; + goto next; + } else if (memcmp(dst_haddr, mac_addr, arp_header->hlen) == 0) { + // 处理本地地址 + p = dst_haddr; + goto next; + } + } } - switch (conn->net_protocol) { - case NET_PROTO_IPV4: - src_paddr = conn->ipv4.ip; - plen = 4; - ptype = HOST2BE_WORD(ETH_TYPE_IPV4); - break; - default: - return PROTO_ERROR_UNSUPPORT; + return PROTO_ERROR_UNSUPPORT; // 不支持的硬件类型 +next: + memcpy(haddr, p, arp_header->hlen); + + bool merge_flag = false; + NeighbourKey hash_key = NEIGH_BUCKET_SIZE; + + // 检查协议类型 + uint8_t *paddr = NULL; + uint16_t ptype = BE2HOST_WORD(arp_header->ptype); + if (ptype == ETH_TYPE_IPV4 && arp_header->plen == 4) { + hash_key = ipv4_hash(src_paddr) % NEIGH_BUCKET_SIZE; + paddr = device->ipv4_addr; + } else { + return PROTO_ERROR_UNSUPPORT; // 不支持的协议类型 } - ArpHeader *arp_header = (ArpHeader *)conn->buffer->data; - arp_header->htype = htype; - arp_header->ptype = ptype; - arp_header->hlen = hlen; - arp_header->plen = plen; - arp_header->opcode = HOST2BE_WORD(opcode); + if (hash_key >= NEIGH_BUCKET_SIZE) { return PROTO_ERROR_UNSUPPORT; } - void *p = conn->buffer->head + sizeof(ArpHeader); + NeighbourEntry *entry, *next; + spin_lock(&neighbour_table.lock[hash_key]); + list_for_each_owner_safe ( + entry, next, &neighbour_table.buckets[hash_key], list) { + spin_lock(&entry->lock); + if (arp_header->plen == entry->ip_length && + memcmp(entry->ip_addr, src_paddr, arp_header->plen) == 0) { + merge_flag = true; + break; + } + spin_unlock(&entry->lock); + } + spin_unlock(&neighbour_table.lock[hash_key]); - memcpy(p, src_haddr, hlen); - memcpy(p + hlen, src_paddr, plen); - p += hlen + plen; - memcpy(p, dst_haddr, hlen); - memcpy(p + hlen, dst_paddr, plen); + if (!merge_flag) { + // Create a new neighbour entry + entry = neighbour_entry_create( + device, hash_key, src_paddr, arp_header->plen); + if (!entry) return PROTO_ERROR_OTHER; + + spin_lock(&entry->lock); + } else { + } + entry->state = NEIGH_STATE_REACHABLE; + memcpy(entry->haddr, src_haddr, arp_header->hlen); + spin_unlock(&entry->lock); + + uint16_t opcode = BE2HOST_WORD(arp_header->opcode); + if (opcode == ARP_OP_REQUEST) { + memcpy(dst_haddr, src_haddr, arp_header->hlen); + memcpy(dst_paddr, src_paddr, arp_header->plen); + memcpy(src_haddr, haddr, arp_header->hlen); + memcpy(src_paddr, paddr, arp_header->plen); + arp_header->opcode = HOST2BE_WORD(ARP_OP_REPLY); + device->ops->send( + device, net_buffer->head, net_buffer->tail - net_buffer->head); + } return PROTO_OK; -} \ No newline at end of file +} + +void arp_send_request(NeighbourEntry *entry, void *arg) { + NetworkDevice *device = entry->device; + EthernetDevice *eth_device = device->ethernet; + NetworkConnection *conn = eth_device->arp_conn; + + // Fill in the ARP request details + ArpHeader *arp_header = (ArpHeader *)conn_buffer(conn)->data; + arp_header->htype = HOST2BE_WORD(ARP_HTYPE_ETH); + arp_header->ptype = HOST2BE_WORD(ETH_TYPE_IPV4); + arp_header->hlen = 6; + arp_header->plen = 4; + arp_header->opcode = HOST2BE_WORD(ARP_OP_REQUEST); + + void *p = (void *)(arp_header + 1); + void *src_haddr = p; + void *src_paddr = p + arp_header->hlen; + void *dst_haddr = p + arp_header->hlen + arp_header->plen; + void *dst_paddr = p + arp_header->hlen * 2 + arp_header->plen; + + // Copy the sender's hardware and protocol addresses + memcpy(src_haddr, eth_device->mac_addr, arp_header->hlen); + memcpy(src_paddr, device->ipv4_addr, arp_header->plen); + + // Copy the target's hardware and protocol addresses + uint8_t eth_dst_addr[ETH_IDENTIFIER_SIZE] = {0}; + memcpy(dst_haddr, eth_dst_addr, arp_header->hlen); + memcpy(dst_paddr, entry->ip_addr, arp_header->plen); + + uint8_t size = + sizeof(ArpHeader) + arp_header->hlen * 2 + arp_header->plen * 2; + net_buffer_put(conn_buffer(conn), size); + + // Send the ARP request + eth_wrap( + conn_buffer(conn), device->ethernet->mac_addr, eth_broadcast_mac, + ETH_TYPE_ARP); + entry->state = NEIGH_STATE_WAITING; + + NETWORK_SEND(device, eth_device->arp_conn); +} diff --git a/src/driver/network/protocols/dhcp.c b/src/driver/network/protocols/dhcp.c index 0451d3e..ee871f8 100644 --- a/src/driver/network/protocols/dhcp.c +++ b/src/driver/network/protocols/dhcp.c @@ -10,6 +10,7 @@ #include "bits.h" #include "driver/network/buffer.h" #include "driver/network/ethernet/ethernet.h" +#include "driver/network/neighbour.h" #include "driver/timer_dm.h" #include "kernel/driver_interface.h" #include "objects/transfer.h" @@ -282,6 +283,13 @@ void dhcp_parse_options( } } +void dhcp_check_addr(DhcpClient *dhcp) { + NeighbourKey key = ipv4_hash(dhcp->server_ip_addr); + NeighbourEntry *entry = + neighbour_table_lookup(dhcp->device, key, dhcp->server_ip_addr, 4); + memcpy(dhcp->server_haddr, entry->haddr, dhcp->haddr_len); +} + void dhcp_rx_handler(NetworkConnection *conn, NetBuffer *net_buffer) { DhcpClient *dhcp = (DhcpClient *)conn->udp.private_data; DhcpHeader *header = (DhcpHeader *)net_buffer->data; @@ -324,6 +332,7 @@ void dhcp_rx_handler(NetworkConnection *conn, NetBuffer *net_buffer) { dhcp->ip_addr[3]); // TODO: 检查地址冲突 + dhcp_check_addr(dhcp); dhcp_ack_handler(dhcp, conn, indexes); dhcp_set_timers(dhcp); @@ -372,7 +381,7 @@ void *dhcp_create_message(DhcpClient *dhcp, DhcpHeader *header, uint8_t op) { } ProtocolResult dhcp_send(DhcpClient *dhcp, uint16_t len) { - ProtocolResult result = conn_put(dhcp->conn, len); + ProtocolResult result = net_buffer_put(dhcp->conn->buffer, len); if (result != PROTO_OK) { printk("[DHCP] Failed to put DHCP message: %d\n", result); return result; @@ -391,7 +400,9 @@ ProtocolResult dhcp_send(DhcpClient *dhcp, uint16_t len) { } switch (dhcp->device->type) { case NETWORK_TYPE_ETHERNET: - eth_wrap(dhcp->conn, dhcp->server_haddr, ETH_PROTO_TYPE_IPV4); + eth_wrap( + dhcp->conn->buffer, dhcp->device->ethernet->mac_addr, + dhcp->server_haddr, ETH_PROTO_TYPE_IPV4); break; case NETWORK_TYPE_UNKNOWN: return PROTO_ERROR_UNSUPPORT; @@ -502,6 +513,9 @@ void dhcp_reset(DhcpClient *dhcp, NetworkConnection *conn) { dhcp->state = DHCP_STAT_INIT; dhcp->xid = rand(); + memset(dhcp->ip_addr, 0, sizeof(dhcp->ip_addr)); + memset(dhcp->server_ip_addr, 0, sizeof(dhcp->server_ip_addr)); + memset(dhcp->server_haddr, 0, sizeof(dhcp->server_haddr)); net_buffer_init(conn->buffer, 576, 0, 0); eth_register(conn); ipv4_register(conn, NULL); diff --git a/src/driver/network/protocols/ipv4.c b/src/driver/network/protocols/ipv4.c index 0c68947..1451bab 100644 --- a/src/driver/network/protocols/ipv4.c +++ b/src/driver/network/protocols/ipv4.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,11 @@ uint16_t ipv4_id_counter = 0; const uint32_t ipv4_broadcast_addr = 0xffffffff; const uint32_t ipv4_null_addr = 0x00000000; +NeighbourKey ipv4_hash(uint8_t ip[4]) { + uint32_t ip32 = *(uint32_t *)ip; + return (ip32 ^ (ip32 >> 16)) % NEIGH_BUCKET_SIZE; +} + void ipv4_register(NetworkConnection *conn, uint8_t *ip_addr) { conn->net_protocol = NET_PROTO_IPV4; if (ip_addr) { @@ -68,8 +74,8 @@ ProtocolResult ipv4_wrap( NetworkConnection *conn, uint16_t protocol, uint8_t *dst_ip, uint8_t ttl) { uint16_t size = CONN_CONTENT_SIZE(conn); - conn_header_alloc(conn, sizeof(Ipv4Header)); - Ipv4Header *ipv4_header = (Ipv4Header *)conn->buffer->head; + net_buffer_header_alloc(conn_buffer(conn), sizeof(Ipv4Header)); + Ipv4Header *ipv4_header = (Ipv4Header *)conn_buffer(conn)->head; ipv4_header->ver_len = (0x4 << 4) | (20 >> 2); // IPv4, 20字节 ipv4_header->tos = 0; // Type of Service ipv4_header->total_len = HOST2BE_WORD(sizeof(Ipv4Header) + size); diff --git a/src/driver/network/protocols/udp.c b/src/driver/network/protocols/udp.c index 6dada94..b08bf50 100644 --- a/src/driver/network/protocols/udp.c +++ b/src/driver/network/protocols/udp.c @@ -89,8 +89,8 @@ void udp_set_callback( void udp_wrap(NetworkConnection *conn, uint16_t src_port, uint16_t dst_port) { uint16_t size = CONN_CONTENT_SIZE(conn); - conn_header_alloc(conn, sizeof(UdpHeader)); - UdpHeader *udp_header = (UdpHeader *)conn->buffer->head; + net_buffer_header_alloc(conn_buffer(conn), sizeof(UdpHeader)); + UdpHeader *udp_header = (UdpHeader *)conn_buffer(conn)->head; udp_header->src_port = HOST2BE_WORD(src_port); udp_header->dst_port = HOST2BE_WORD(dst_port); udp_header->length = HOST2BE_WORD(sizeof(UdpHeader) + size); @@ -116,7 +116,7 @@ ProtocolResult udp_recv(NetBuffer *net_buffer, Ipv4Header *ipv4_header) { int length = BE2HOST_WORD(udp_header->length); if (length < sizeof(UdpHeader)) return PROTO_ERROR_UNSUPPORT; // 数据包太小 - if (length > size) return PROTO_ERROR_EXCEED_MAX_SIZE; // 长度不合法 + if (length > size) return PROTO_ERROR_EXCEED_MAX_SIZE; // 长度不合法 // TODO: 先检查目标是否为本机IP diff --git a/src/include/driver/network/buffer.h b/src/include/driver/network/buffer.h index 1743d13..4431324 100644 --- a/src/include/driver/network/buffer.h +++ b/src/include/driver/network/buffer.h @@ -28,10 +28,10 @@ void net_buffer_init( struct NetworkConnection; ProtocolResult net_buffer_data_alloc(NetBuffer *buffer, uint16_t size); void net_buffer_reset(NetBuffer *buffer); -void conn_header_alloc(struct NetworkConnection *conn, uint16_t size); -void conn_header_free(struct NetworkConnection *conn, uint16_t size); -void conn_tail_alloc(struct NetworkConnection *conn, uint16_t size); -void conn_tail_free(struct NetworkConnection *conn, uint16_t size); -ProtocolResult conn_put(struct NetworkConnection *conn, uint16_t size); +void net_buffer_header_alloc(NetBuffer *buffer, uint16_t size); +void net_buffer_header_free(NetBuffer *buffer, uint16_t size); +void net_buffer_tail_alloc(NetBuffer *buffer, uint16_t size); +void net_buffer_tail_free(NetBuffer *buffer, uint16_t size); +ProtocolResult net_buffer_put(NetBuffer *buffer, uint16_t size); #endif \ No newline at end of file diff --git a/src/include/driver/network/conn.h b/src/include/driver/network/conn.h index 522b9f9..e5debd3 100644 --- a/src/include/driver/network/conn.h +++ b/src/include/driver/network/conn.h @@ -17,6 +17,8 @@ #define CONN_CONTENT_SIZE(conn) ((conn)->buffer->tail - (conn)->buffer->head) +#define conn_buffer(conn) ((conn)->buffer) + struct NetworkConnection; typedef struct NetProtocol { uint16_t head_size; diff --git a/src/include/driver/network/ethernet/ethernet.h b/src/include/driver/network/ethernet/ethernet.h index bf184b2..0f6280b 100644 --- a/src/include/driver/network/ethernet/ethernet.h +++ b/src/include/driver/network/ethernet/ethernet.h @@ -36,7 +36,8 @@ extern const uint8_t eth_broadcast_mac[6]; void eth_register(struct NetworkConnection *conn); ProtocolResult eth_wrap( - struct NetworkConnection *conn, const uint8_t *dst_addr, uint16_t protocol); -ProtocolResult eth_recv(NetBuffer *net_buffer); + struct NetBuffer *buffer, uint8_t *mac_addr, const uint8_t *dst_addr, + uint16_t protocol); +ProtocolResult eth_recv(NetworkDevice *device, NetBuffer *net_buffer); #endif \ No newline at end of file diff --git a/src/include/driver/network/neighbour.h b/src/include/driver/network/neighbour.h new file mode 100644 index 0000000..2377071 --- /dev/null +++ b/src/include/driver/network/neighbour.h @@ -0,0 +1,60 @@ +#ifndef NEIGHBOUR_H +#define NEIGHBOUR_H + +#include "driver/network/network_dm.h" +#include "kernel/list.h" +#include "kernel/spinlock.h" +#include + +#define NEIGH_BUCKET_SIZE 32 + +typedef enum { + NEIGH_STATE_NONE, + NEIGH_STATE_WAITING, + NEIGH_STATE_REACHABLE, + NEIGH_STATE_STALE, + NEIGH_STATE_FAILED, +} NeighbourState; + +typedef uint32_t NeighbourKey; + +struct NeighbourEntry; +typedef struct { + void (*request)(struct NeighbourEntry *entry, void *arg); +} NeighbourProtoOps; + +typedef struct NeighbourEntry { + list_t list; + spinlock_t lock; + + NeighbourKey key; + NeighbourState state; + uint8_t haddr[8]; // Hardware address (MAC address) + NetworkDevice *device; + + void *arg; + NeighbourProtoOps *ops; + + list_t pending_lh; + + uint8_t ip_length; + uint8_t ip_addr[0]; +} NeighbourEntry; + +typedef struct NeighbourTable { + list_t buckets[NEIGH_BUCKET_SIZE]; + spinlock_t lock[NEIGH_BUCKET_SIZE]; +} NeighbourTable; + +extern int neighbour_max_retries; +extern NeighbourTable neighbour_table; + +void neighbour_init(void); +NeighbourEntry *neighbour_entry_create( + NetworkDevice *device, NeighbourKey hash_key, uint8_t *addr, + uint8_t length); +NeighbourEntry *neighbour_table_lookup( + NetworkDevice *device, NeighbourKey hash_key, uint8_t *ip_addr, + uint8_t ip_length); + +#endif \ No newline at end of file diff --git a/src/include/driver/network/network_dm.h b/src/include/driver/network/network_dm.h index b1fef7c..571897d 100644 --- a/src/include/driver/network/network_dm.h +++ b/src/include/driver/network/network_dm.h @@ -51,7 +51,7 @@ typedef struct NetworkDevice { }; union { - uint8_t ipv4[4]; + uint8_t ipv4_addr[4]; }; } NetworkDevice; diff --git a/src/include/driver/network/protocols/arp.h b/src/include/driver/network/protocols/arp.h index 0e15b81..3735160 100644 --- a/src/include/driver/network/protocols/arp.h +++ b/src/include/driver/network/protocols/arp.h @@ -1,8 +1,8 @@ #ifndef _ARP_H #define _ARP_H -#include "../conn.h" -#include "protocols.h" +#include "driver/network/conn.h" +#include "driver/network/protocols/protocols.h" #include #define ARP_HTYPE_ETH 0x0001 @@ -20,8 +20,8 @@ typedef struct ArpHeader { uint16_t opcode; } __attribute__((packed)) ArpHeader; -ProtocolResult arp_wrap( - NetworkConnection *conn, uint8_t *dst_haddr, uint8_t *dst_paddr, - uint16_t opcode); +extern NeighbourProtoOps arp_proto_ops; + +ProtocolResult arp_recv(NetworkDevice *device, NetBuffer *net_buffer); #endif \ No newline at end of file diff --git a/src/include/driver/network/protocols/ipv4.h b/src/include/driver/network/protocols/ipv4.h index b45ef41..e60bb33 100644 --- a/src/include/driver/network/protocols/ipv4.h +++ b/src/include/driver/network/protocols/ipv4.h @@ -1,6 +1,7 @@ #ifndef _IPV4_H #define _IPV4_H +#include "driver/network/neighbour.h" #include "kernel/list.h" #include "protocols.h" #include @@ -45,5 +46,6 @@ ProtocolResult ipv4_wrap( struct NetworkConnection *conn, uint16_t protocol, uint8_t *dst_ip, uint8_t ttl); ProtocolResult ipv4_recv(struct NetBuffer *net_buffer); +NeighbourKey ipv4_hash(uint8_t ip[4]); #endif \ No newline at end of file From cdd725e342fba9b60e3bab3569cad85125886e09 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 23 Aug 2025 00:44:49 +0800 Subject: [PATCH 084/158] =?UTF-8?q?[WIP]network&arp&dhcp:=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=9C=B0=E5=9D=80=E5=86=B2=E7=AA=81=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/network_dm.c | 3 + src/driver/network/protocols/Makefile | 3 +- src/driver/network/protocols/acd.c | 76 +++++++++++++++++++ src/driver/network/protocols/arp.c | 48 +++++++++++- src/driver/network/protocols/dhcp.c | 3 + .../driver/network/ethernet/ethernet.h | 10 +++ src/include/driver/network/neighbour.h | 2 + src/include/driver/network/protocols/acd.h | 26 +++++++ src/include/driver/network/protocols/arp.h | 2 + 9 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 src/driver/network/protocols/acd.c create mode 100644 src/include/driver/network/protocols/acd.h diff --git a/src/driver/network/network_dm.c b/src/driver/network/network_dm.c index 8f484da..d167956 100644 --- a/src/driver/network/network_dm.c +++ b/src/driver/network/network_dm.c @@ -2,6 +2,7 @@ #include "driver/network/conn.h" #include "driver/network/ethernet/ethernet.h" #include "driver/network/network.h" +#include "driver/timer_dm.h" #include "kernel/softirq.h" #include "objects/transfer.h" #include @@ -63,9 +64,11 @@ DriverResult register_network_device( case NETWORK_TYPE_ETHERNET: { EthernetDevice *eth_device = kmalloc(sizeof(EthernetDevice)); network_device->ethernet = eth_device; + eth_device->acd_state = ACD_STATE_NONE; eth_device->arp_conn = net_create_conn(device->object); conn_buffer(eth_device->arp_conn) = net_buffer_create(128); net_buffer_init(conn_buffer(eth_device->arp_conn), 128, 0, 0); + timer_init(ð_device->timer); eth_register(eth_device->arp_conn); break; } diff --git a/src/driver/network/protocols/Makefile b/src/driver/network/protocols/Makefile index 7c662b6..69eb0a2 100644 --- a/src/driver/network/protocols/Makefile +++ b/src/driver/network/protocols/Makefile @@ -1,4 +1,5 @@ SRC += arp.c SRC += ipv4.c SRC += dhcp.c -SRC += udp.c \ No newline at end of file +SRC += udp.c +SRC += acd.c \ No newline at end of file diff --git a/src/driver/network/protocols/acd.c b/src/driver/network/protocols/acd.c new file mode 100644 index 0000000..881c026 --- /dev/null +++ b/src/driver/network/protocols/acd.c @@ -0,0 +1,76 @@ +/** + * @file acd.c + * @author your name (you@domain.com) + * @brief Address Conflict Detection + * References: + * - RFC5227: IPv4 Address Conflict Detection + */ +#include "driver/network/ethernet/ethernet.h" +#include "driver/network/neighbour.h" +#include "driver/network/network_dm.h" +#include "driver/network/protocols/ipv4.h" +#include "driver/network/protocols/protocols.h" +#include "driver/timer_dm.h" +#include +#include +#include + +void acd_timer_callback(void *arg) { + NetworkDevice *device = arg; + EthernetDevice *eth_device = device->ethernet; + + switch (eth_device->acd_state) { + case ACD_STATE_PROBE: + if (eth_device->probe_count < ACD_PROBE_NUM) { + eth_device->probe_count++; + timer_set_timeout(ð_device->timer, ACD_PROBE_MIN * 1000); + timer_callback_enable(ð_device->timer); + + NeighbourKey key = ipv4_hash(device->ipv4_addr); + NeighbourEntry *entry = + neighbour_table_lookup(device, key, device->ipv4_addr, 4); + arp_send_request(entry, arg); + } else { + eth_device->acd_state = ACD_STATE_ANNOUNCE; + } + case ACD_STATE_ANNOUNCE: + if (eth_device->announce_count < ACD_ANNOUNCE_NUM) { + eth_device->announce_count++; + timer_set_timeout(ð_device->timer, ACD_ANNOUNCE_INTERVAL * 1000); + timer_callback_enable(ð_device->timer); + arp_announce(device, device->ipv4_addr); + } else { + eth_device->acd_state = ACD_STATE_IN_USE; + } + break; + default: + break; + } +} + +ProtocolResult acd_conflict_detected() { +} + +void acd_probe(NetworkDevice *device) { + EthernetDevice *eth_device = device->ethernet; + eth_device->probe_count = 0; + + eth_device->timer.callback = acd_timer_callback; + eth_device->timer.arg = device; + + eth_device->acd_state = ACD_STATE_PROBE; + timer_set_timeout(ð_device->timer, ACD_PROBE_WAIT * 1000); + timer_callback_enable(ð_device->timer); +} + +void acd_announce(NetworkDevice *device) { + EthernetDevice *eth_device = device->ethernet; + eth_device->announce_count = 0; + + eth_device->timer.callback = acd_timer_callback; + eth_device->timer.arg = device; + + eth_device->acd_state = ACD_STATE_ANNOUNCE; + timer_set_timeout(ð_device->timer, ACD_ANNOUNCE_WAIT * 1000); + timer_callback_enable(ð_device->timer); +} diff --git a/src/driver/network/protocols/arp.c b/src/driver/network/protocols/arp.c index 575d9c3..3ac532a 100644 --- a/src/driver/network/protocols/arp.c +++ b/src/driver/network/protocols/arp.c @@ -15,16 +15,17 @@ #include #include #include +#include #include #include #include #include #include -void arp_send_request(NeighbourEntry *entry, void *arg); - NeighbourProtoOps arp_proto_ops = { - .request = arp_send_request, + .request = arp_send_request, + .probe = acd_probe, + .announce = acd_announce, }; ProtocolResult arp_recv(NetworkDevice *device, NetBuffer *net_buffer) { @@ -66,6 +67,10 @@ ProtocolResult arp_recv(NetworkDevice *device, NetBuffer *net_buffer) { if (ptype == ETH_TYPE_IPV4 && arp_header->plen == 4) { hash_key = ipv4_hash(src_paddr) % NEIGH_BUCKET_SIZE; paddr = device->ipv4_addr; + if (memcmp(src_paddr, paddr, 4) == 0) { + // 源地址与本机IP冲突 + acd_conflict_detected(); + } } else { return PROTO_ERROR_UNSUPPORT; // 不支持的协议类型 } @@ -153,3 +158,40 @@ void arp_send_request(NeighbourEntry *entry, void *arg) { NETWORK_SEND(device, eth_device->arp_conn); } + +void arp_announce(NetworkDevice *device, uint8_t *ip_addr) { + EthernetDevice *eth_device = device->ethernet; + NetworkConnection *conn = eth_device->arp_conn; + + // Fill in the ARP request details + ArpHeader *arp_header = (ArpHeader *)conn_buffer(conn)->data; + arp_header->htype = HOST2BE_WORD(ARP_HTYPE_ETH); + arp_header->ptype = HOST2BE_WORD(ETH_TYPE_IPV4); + arp_header->hlen = ETH_IDENTIFIER_SIZE; + arp_header->plen = 4; + arp_header->opcode = HOST2BE_WORD(ARP_OP_REQUEST); + + void *p = (void *)(arp_header + 1); + void *src_haddr = p; + void *src_paddr = p + arp_header->hlen; + void *dst_haddr = p + arp_header->hlen + arp_header->plen; + void *dst_paddr = p + arp_header->hlen * 2 + arp_header->plen; + + // Copy the sender's hardware and protocol addresses + memcpy(src_haddr, eth_device->mac_addr, arp_header->hlen); + memcpy(src_paddr, ip_addr, arp_header->plen); + + // Copy the target's hardware and protocol addresses + memcpy(dst_haddr, eth_broadcast_mac, arp_header->hlen); + memcpy(dst_paddr, ip_addr, arp_header->plen); + + uint8_t size = + sizeof(ArpHeader) + arp_header->hlen * 2 + arp_header->plen * 2; + net_buffer_put(conn_buffer(conn), size); + + // Send the ARP request + eth_wrap( + conn_buffer(conn), device->ethernet->mac_addr, eth_broadcast_mac, + ETH_TYPE_ARP); + NETWORK_SEND(device, conn); +} diff --git a/src/driver/network/protocols/dhcp.c b/src/driver/network/protocols/dhcp.c index ee871f8..6b1dcca 100644 --- a/src/driver/network/protocols/dhcp.c +++ b/src/driver/network/protocols/dhcp.c @@ -11,6 +11,7 @@ #include "driver/network/buffer.h" #include "driver/network/ethernet/ethernet.h" #include "driver/network/neighbour.h" +#include "driver/network/protocols/acd.h" #include "driver/timer_dm.h" #include "kernel/driver_interface.h" #include "objects/transfer.h" @@ -287,6 +288,8 @@ void dhcp_check_addr(DhcpClient *dhcp) { NeighbourKey key = ipv4_hash(dhcp->server_ip_addr); NeighbourEntry *entry = neighbour_table_lookup(dhcp->device, key, dhcp->server_ip_addr, 4); + entry->ops->probe(dhcp->device); + entry->ops->announce(dhcp->device); memcpy(dhcp->server_haddr, entry->haddr, dhcp->haddr_len); } diff --git a/src/include/driver/network/ethernet/ethernet.h b/src/include/driver/network/ethernet/ethernet.h index 0f6280b..14455eb 100644 --- a/src/include/driver/network/ethernet/ethernet.h +++ b/src/include/driver/network/ethernet/ethernet.h @@ -4,6 +4,7 @@ #include "driver/network/buffer.h" #include "driver/network/network_dm.h" #include "driver/network/protocols/protocols.h" +#include "driver/timer_dm.h" #include #define ETH_MAX_FRAME_SIZE 1792 @@ -22,6 +23,15 @@ typedef struct EthernetHeader { } EthernetHeader; typedef struct EthernetDevice { + Timer timer; + uint8_t probe_count, announce_count; + enum { + ACD_STATE_NONE, + ACD_STATE_PROBE, + ACD_STATE_ANNOUNCE, + ACD_STATE_IN_USE, + } acd_state; + struct NetworkConnection *arp_conn; NetworkDevice *net_device; uint8_t mac_addr[ETH_IDENTIFIER_SIZE]; diff --git a/src/include/driver/network/neighbour.h b/src/include/driver/network/neighbour.h index 2377071..37887de 100644 --- a/src/include/driver/network/neighbour.h +++ b/src/include/driver/network/neighbour.h @@ -21,6 +21,8 @@ typedef uint32_t NeighbourKey; struct NeighbourEntry; typedef struct { void (*request)(struct NeighbourEntry *entry, void *arg); + void (*probe)(struct NetworkDevice *device); + void (*announce)(struct NetworkDevice *device); } NeighbourProtoOps; typedef struct NeighbourEntry { diff --git a/src/include/driver/network/protocols/acd.h b/src/include/driver/network/protocols/acd.h new file mode 100644 index 0000000..cdfc2ef --- /dev/null +++ b/src/include/driver/network/protocols/acd.h @@ -0,0 +1,26 @@ +#ifndef _ACD_H +#define _ACD_H + +#include +#include + +#define ACD_PROBE_WAIT 1 // initial random delay (1 second) +#define ACD_PROBE_NUM 3 // number of probe packets +#define ACD_PROBE_MIN 1 // minimum delay until repeated probe (1 second) +#define ACD_PROBE_MAX 2 // maximum delay until repeated probe (2 seconds) + +#define ACD_ANNOUNCE_WAIT 2 // delay before announcing (2 seconds) +#define ACD_ANNOUNCE_NUM 2 // number of announce packets +#define ACD_ANNOUNCE_INTERVAL 2 // time between announce packets (2 seconds) + +#define ACD_MAX_CONFLICTS 10 // max conflicts before rate-limiting (10 seconds) +#define ACD_RATE_LIMIT_INTERVAL \ + 60 // delay between successive attempts (60 seconds) +#define ACD_DEFEND_INTERVAL \ + 10 // minimum interval between defensive ARPs (10 seconds) + +ProtocolResult acd_conflict_detected(); +void acd_probe(NetworkDevice *device); +void acd_announce(NetworkDevice *device); + +#endif \ No newline at end of file diff --git a/src/include/driver/network/protocols/arp.h b/src/include/driver/network/protocols/arp.h index 3735160..85508b5 100644 --- a/src/include/driver/network/protocols/arp.h +++ b/src/include/driver/network/protocols/arp.h @@ -23,5 +23,7 @@ typedef struct ArpHeader { extern NeighbourProtoOps arp_proto_ops; ProtocolResult arp_recv(NetworkDevice *device, NetBuffer *net_buffer); +void arp_send_request(NeighbourEntry *entry, void *arg); +void arp_announce(NetworkDevice *device, uint8_t *ip_addr); #endif \ No newline at end of file From d30937e1794bd58cb5667510ee1232aa2eed5650 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 23 Aug 2025 14:08:17 +0800 Subject: [PATCH 085/158] =?UTF-8?q?dhcp&acd&arp:=20=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?=E5=AF=B9=E5=9C=B0=E5=9D=80=E5=86=B2=E7=AA=81=E7=9A=84=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/protocols/acd.c | 13 ++++++-- src/driver/network/protocols/arp.c | 5 ++-- src/driver/network/protocols/dhcp.c | 30 ++++++++++++++++++- .../driver/network/ethernet/ethernet.h | 3 +- src/include/driver/network/protocols/acd.h | 2 +- 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/driver/network/protocols/acd.c b/src/driver/network/protocols/acd.c index 881c026..798a823 100644 --- a/src/driver/network/protocols/acd.c +++ b/src/driver/network/protocols/acd.c @@ -31,7 +31,8 @@ void acd_timer_callback(void *arg) { neighbour_table_lookup(device, key, device->ipv4_addr, 4); arp_send_request(entry, arg); } else { - eth_device->acd_state = ACD_STATE_ANNOUNCE; + // 确认没有冲突,发送公告 + acd_announce(device); } case ACD_STATE_ANNOUNCE: if (eth_device->announce_count < ACD_ANNOUNCE_NUM) { @@ -40,7 +41,7 @@ void acd_timer_callback(void *arg) { timer_callback_enable(ð_device->timer); arp_announce(device, device->ipv4_addr); } else { - eth_device->acd_state = ACD_STATE_IN_USE; + eth_device->acd_state = ACD_STATE_NONE; } break; default: @@ -48,7 +49,13 @@ void acd_timer_callback(void *arg) { } } -ProtocolResult acd_conflict_detected() { +ProtocolResult acd_conflict_detected(NetworkDevice *device) { + EthernetDevice *eth_device = device->ethernet; + timer_callback_cancel(ð_device->timer); + eth_device->acd_state = ACD_STATE_CONFLICT; + if (eth_device->acd_conflict_callback) + eth_device->acd_conflict_callback(device); + return PROTO_OK; } void acd_probe(NetworkDevice *device) { diff --git a/src/driver/network/protocols/arp.c b/src/driver/network/protocols/arp.c index 3ac532a..a7e1ef9 100644 --- a/src/driver/network/protocols/arp.c +++ b/src/driver/network/protocols/arp.c @@ -69,7 +69,7 @@ ProtocolResult arp_recv(NetworkDevice *device, NetBuffer *net_buffer) { paddr = device->ipv4_addr; if (memcmp(src_paddr, paddr, 4) == 0) { // 源地址与本机IP冲突 - acd_conflict_detected(); + acd_conflict_detected(device); } } else { return PROTO_ERROR_UNSUPPORT; // 不支持的协议类型 @@ -182,7 +182,8 @@ void arp_announce(NetworkDevice *device, uint8_t *ip_addr) { memcpy(src_paddr, ip_addr, arp_header->plen); // Copy the target's hardware and protocol addresses - memcpy(dst_haddr, eth_broadcast_mac, arp_header->hlen); + uint8_t haddr[8] = {0}; + memcpy(dst_haddr, haddr, arp_header->hlen); memcpy(dst_paddr, ip_addr, arp_header->plen); uint8_t size = diff --git a/src/driver/network/protocols/dhcp.c b/src/driver/network/protocols/dhcp.c index 6b1dcca..b8f1189 100644 --- a/src/driver/network/protocols/dhcp.c +++ b/src/driver/network/protocols/dhcp.c @@ -83,6 +83,11 @@ void dhcp_timeout_handler(void *arg) { if (dhcp != NULL) { dhcp->retry_times++; switch (dhcp->state) { + case DHCP_STAT_INIT: + // 刚发送完DHCPDECLINE,需要重新请求 + dhcp_reset(dhcp, dhcp->conn); + dhcp_discover(dhcp); + break; case DHCP_STAT_SELECTING: case DHCP_STAT_REQUESTING: case DHCP_STAT_RENEWING: @@ -93,6 +98,30 @@ void dhcp_timeout_handler(void *arg) { } } +void dhcp_ip_conflict_handler(void *arg) { + DhcpClient *dhcp = arg; + + // 发送DHCPDECLINE + if (dhcp->state == DHCP_STAT_BOUND) { + memset(dhcp->ip_addr, ipv4_null_addr, 4); + memset(dhcp->server_ip_addr, ipv4_null_addr, 4); + uint8_t *ptr = + dhcp_create_message(dhcp, dhcp->conn->buffer->data, DHCP_DECLINE); + + *ptr = DHCP_OPTION_END; + + int len = 4 /* magic cookie */ + + 3 /* message type */ + + 1 /* end */; + dhcp_send(dhcp, sizeof(DhcpHeader) + len); + + // 至少等待10秒 + dhcp->state = DHCP_STAT_INIT; + timer_set_timeout(&dhcp->timeout_timer, 10 * 1000); + timer_callback_enable(&dhcp->timeout_timer); + } +} + void dhcp_ip_lease_handler(void *arg) { DhcpClient *dhcp = arg; if (dhcp->state == DHCP_STAT_REBINDING) { @@ -289,7 +318,6 @@ void dhcp_check_addr(DhcpClient *dhcp) { NeighbourEntry *entry = neighbour_table_lookup(dhcp->device, key, dhcp->server_ip_addr, 4); entry->ops->probe(dhcp->device); - entry->ops->announce(dhcp->device); memcpy(dhcp->server_haddr, entry->haddr, dhcp->haddr_len); } diff --git a/src/include/driver/network/ethernet/ethernet.h b/src/include/driver/network/ethernet/ethernet.h index 14455eb..c2b9d43 100644 --- a/src/include/driver/network/ethernet/ethernet.h +++ b/src/include/driver/network/ethernet/ethernet.h @@ -29,8 +29,9 @@ typedef struct EthernetDevice { ACD_STATE_NONE, ACD_STATE_PROBE, ACD_STATE_ANNOUNCE, - ACD_STATE_IN_USE, + ACD_STATE_CONFLICT, } acd_state; + void (*acd_conflict_callback)(NetworkDevice *device); struct NetworkConnection *arp_conn; NetworkDevice *net_device; diff --git a/src/include/driver/network/protocols/acd.h b/src/include/driver/network/protocols/acd.h index cdfc2ef..bf5d0a2 100644 --- a/src/include/driver/network/protocols/acd.h +++ b/src/include/driver/network/protocols/acd.h @@ -19,7 +19,7 @@ #define ACD_DEFEND_INTERVAL \ 10 // minimum interval between defensive ARPs (10 seconds) -ProtocolResult acd_conflict_detected(); +ProtocolResult acd_conflict_detected(NetworkDevice *device); void acd_probe(NetworkDevice *device); void acd_announce(NetworkDevice *device); From b8da81ec8172c7f53c13b069674b292e5effa663 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 26 Aug 2025 22:02:37 +0800 Subject: [PATCH 086/158] =?UTF-8?q?lib:=20=E6=96=B0=E5=A2=9Emd5,fnv1/fnv1a?= =?UTF-8?q?/fnv0=E5=93=88=E5=B8=8C=E5=87=BD=E6=95=B0=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/hash.h | 12 +++ src/lib/Makefile | 3 +- src/lib/hash/Makefile | 2 + src/lib/hash/fnv.c | 37 +++++++++ src/lib/hash/md5.c | 185 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 src/include/hash.h create mode 100644 src/lib/hash/Makefile create mode 100644 src/lib/hash/fnv.c create mode 100644 src/lib/hash/md5.c diff --git a/src/include/hash.h b/src/include/hash.h new file mode 100644 index 0000000..899911c --- /dev/null +++ b/src/include/hash.h @@ -0,0 +1,12 @@ +#ifndef _HASH_H +#define _HASH_H + +#include + +uint32_t fnv1_hash_32(const void *data, int len); +uint32_t fnv1a_hash_32(const void *data, int len); +uint32_t fnv0_hash_32(const void *data, int len); + +void md5(uint8_t digest[16], const uint8_t *data, size_t len); + +#endif \ No newline at end of file diff --git a/src/lib/Makefile b/src/lib/Makefile index 11e6552..ff8ef39 100644 --- a/src/lib/Makefile +++ b/src/lib/Makefile @@ -3,4 +3,5 @@ SRC += math.c SRC += string.c SRC += vsprintf.c SRC += random.c -SRC += dyn_array.c \ No newline at end of file +SRC += dyn_array.c +SRC += hash/ \ No newline at end of file diff --git a/src/lib/hash/Makefile b/src/lib/hash/Makefile new file mode 100644 index 0000000..c93104c --- /dev/null +++ b/src/lib/hash/Makefile @@ -0,0 +1,2 @@ +SRC += fnv.c +SRC += md5.c \ No newline at end of file diff --git a/src/lib/hash/fnv.c b/src/lib/hash/fnv.c new file mode 100644 index 0000000..6ce8322 --- /dev/null +++ b/src/lib/hash/fnv.c @@ -0,0 +1,37 @@ +#include + +#define FNV_32_PRIME 0x01000193 + +uint32_t fnv1_hash_32(const void *data, int len) { + const uint32_t fnv_offset_basis = 0x811c9dc5; // 2166136261 + + const uint8_t *p = (const uint8_t *)data; + uint32_t hash = fnv_offset_basis; + for (int i = 0; i < len; i++) { + hash *= FNV_32_PRIME; + hash ^= (uint32_t)(p[i]); + } + return hash; +} + +uint32_t fnv1a_hash_32(const void *data, int len) { + const uint32_t fnv_offset_basis = 0x811c9dc5; // 2166136261 + + const uint8_t *p = (const uint8_t *)data; + uint32_t hash = fnv_offset_basis; + for (int i = 0; i < len; i++) { + hash ^= (uint32_t)(p[i]); + hash *= FNV_32_PRIME; + } + return hash; +} + +uint32_t fnv0_hash_32(const void *data, int len) { + const uint8_t *p = (const uint8_t *)data; + uint32_t hash = 0; + for (int i = 0; i < len; i++) { + hash *= FNV_32_PRIME; + hash ^= (uint32_t)(p[i]); + } + return hash; +} diff --git a/src/lib/hash/md5.c b/src/lib/hash/md5.c new file mode 100644 index 0000000..5e96b2a --- /dev/null +++ b/src/lib/hash/md5.c @@ -0,0 +1,185 @@ +/** + * @file md5.c + * @author Jiajun Wang (ryan1202@foxmail.com) + * @brief MD5 + * Reference: + * RFC1321: The MD5 Message-Digest Algorithm + * + */ +#include +#include +#include +#include + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + +#define FF(a, b, c, d, x, s, ac) \ + { \ + (a) += F((b), (c), (d)) + (x) + (ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + { \ + (a) += G((b), (c), (d)) + (x) + (ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + { \ + (a) += H((b), (c), (d)) + (x) + (ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + { \ + (a) += I((b), (c), (d)) + (x) + (ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } + +PRIVATE void md5_transform(uint32_t state[4], const uint8_t block[64]) { + uint32_t a = state[0], b = state[1], c = state[2], d = state[3]; + uint32_t x[16]; + + for (int i = 0; i < 16; i++) { + x[i] = HOST2LE_DWORD(((uint32_t *)block)[i]); + } + + /* Round 1 */ + FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ + FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ + GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ + II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + memset32(x, 0, 16); +} + +void md5(uint8_t digest[16], const uint8_t *data, size_t len) { + // 初始化MD5状态 + uint32_t state[4] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476}; + + size_t i; + uint64_t bit_len = len * 8; + // 处理数据 + for (i = 0; i + 63 < len; i += 64) { + md5_transform(state, data + i); + } + + uint8_t buffer[64]; + size_t rem = len - i; + memcpy(buffer, data + i, rem); + + buffer[rem] = 0x80; + rem++; + + if (rem > 56) { + memset(buffer + rem, 0, 64 - rem); + md5_transform(state, buffer); + memset(buffer + rem, 0, rem - 56); + } else { + memset(buffer + rem, 0, 56 - rem); + } + + for (int j = 0; j < 8; j++) + buffer[56 + j] = (uint8_t)(bit_len >> (j * 8)); + + md5_transform(state, buffer); + + // 输出结果 + for (size_t i = 0; i < 4; i++) { + ((uint32_t *)digest)[i] = LE2HOST_DWORD(state[i]); + } +} \ No newline at end of file From 069238a0c08ee2860e689277b8a70a700df8a266 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 27 Aug 2025 19:14:32 +0800 Subject: [PATCH 087/158] =?UTF-8?q?udp:=20=E7=AE=80=E5=8C=96udp=5Frecv?= =?UTF-8?q?=E7=9A=84=E4=B8=A2=E5=8C=85=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/protocols/udp.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/driver/network/protocols/udp.c b/src/driver/network/protocols/udp.c index b08bf50..fdf04b2 100644 --- a/src/driver/network/protocols/udp.c +++ b/src/driver/network/protocols/udp.c @@ -167,13 +167,9 @@ ProtocolResult udp_recv(NetBuffer *net_buffer, Ipv4Header *ipv4_header) { return PROTO_OK; } } - if (info->list.next == &udp_lh) { - // 没有找到匹配的连接,丢弃数据包 - drop: - kfree(net_buffer->ptr); - kfree(net_buffer); - return PROTO_DROP; - } - - return PROTO_OK; + // 没有找到匹配的连接,丢弃数据包 +drop: + kfree(net_buffer->ptr); + kfree(net_buffer); + return PROTO_DROP; } From fbe0095602b071cd5d99ce5ea0ea904e9bf9e476 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 30 Aug 2025 01:33:10 +0800 Subject: [PATCH 088/158] =?UTF-8?q?memory:=20=E6=96=B0=E5=A2=9E=E5=88=86?= =?UTF-8?q?=E9=85=8D=E8=BF=9E=E7=BB=AD=E9=A1=B5=E5=86=85=E5=AD=98kernel=5F?= =?UTF-8?q?alloc=5Fcontinuous=5Fpages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/include/kernel/page.h | 4 +- src/arch/x86/kernel/page.c | 68 ++++++++++++++++++++++++------ 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/src/arch/x86/include/kernel/page.h b/src/arch/x86/include/kernel/page.h index 710521a..9038875 100644 --- a/src/arch/x86/include/kernel/page.h +++ b/src/arch/x86/include/kernel/page.h @@ -37,10 +37,12 @@ void unmap(uint32_t vaddr, size_t size); int alloc_vir_pages(int count); int free_vir_page(int vir_addr); void *kernel_alloc_pages(int pages); +void *kernel_alloc_continuous_pages(int pages); void kernel_free_page(int vaddr, int pages); -void fill_vir_page_table(uint32_t vaddr, uint8_t sign); +void fill_vir_page_table(uint32_t vaddr, uint32_t paddr, uint8_t sign); void clean_vir_page_table(uint32_t vaddr); uint32_t alloc_mem_page(void); +uint32_t alloc_mem_pages(int pages); uint32_t free_mem_page(int address); void *thread_get_page(struct task_s *thread, uint32_t vaddr); uint32_t thread_alloc_vir_page(struct task_s *thread); diff --git a/src/arch/x86/kernel/page.c b/src/arch/x86/kernel/page.c index b01fb6a..c883330 100644 --- a/src/arch/x86/kernel/page.c +++ b/src/arch/x86/kernel/page.c @@ -267,13 +267,13 @@ void *kernel_alloc_pages(int pages) { vir_page_addr = alloc_vir_pages(pages); // 分配一个虚拟地址的页 if (vir_page_addr < 0) return NULL; fill_vir_page_table( - vir_page_addr, + vir_page_addr, alloc_mem_page(), SIGN_SYS); // 把页添加到当前页目录表系统中,使他可以被使用 vir_page_addr_more = vir_page_addr + PAGE_SIZE; // 分配一个虚拟地址的页 for (i = 1; i < pages; i++) { fill_vir_page_table( - vir_page_addr_more, + vir_page_addr_more, alloc_mem_page(), SIGN_SYS); // 把页添加到当前页目录表系统中,使他可以被使用 vir_page_addr_more += PAGE_SIZE; } @@ -284,6 +284,32 @@ void *kernel_alloc_pages(int pages) { return (void *)vir_page_addr; } +/** + * @brief 分配物理地址连续的页 + * + * @param pages 页数 + * @return void* 起始地址 + */ +void *kernel_alloc_continuous_pages(int pages) { + size_t vir_page_addr = 0; + + int old_status = io_load_eflags(); + io_cli(); + + vir_page_addr = alloc_vir_pages(pages); + + size_t paddr = alloc_mem_pages(pages); + for (int i = 0; i < pages; i++) { + fill_vir_page_table( + vir_page_addr + i * PAGE_SIZE, paddr + i * PAGE_SIZE, + SIGN_SYS); // 把页添加到当前页目录表系统中,使他可以被使用 + } + if (!paddr) return NULL; + io_store_eflags(old_status); + + return (void *)vir_page_addr; +} + /** * @brief 释放内核页 * @@ -321,7 +347,7 @@ void kernel_free_page(int vaddr, int pages) { * @param vaddr 虚拟内存地址 * @param sign 是用户内存还是系统内存(SIGN_SYS:系统内存,SIGN_USER:用户内存) */ -void fill_vir_page_table(uint32_t vaddr, uint8_t sign) { +void fill_vir_page_table(uint32_t vaddr, uint32_t paddr, uint8_t sign) { uint32_t *pde, *pte; pde = pde_ptr(vaddr); if (((*pde) & 0x00000001) != 0x00000001) { // 不存在页表 @@ -329,12 +355,10 @@ void fill_vir_page_table(uint32_t vaddr, uint8_t sign) { pt |= SIGN_RW | SIGN_P | (sign & SIGN_US); *pde = pt; // 填写页目录项为页表的地址 } - pte = pte_ptr(vaddr); - if (((*pte) & 0x00000001) != 0x00000001) { // 不存在页表项 - uint32_t page = alloc_mem_page(); // 分配页地址 - page |= SIGN_RW | SIGN_P | (sign & SIGN_US); - *pte = page; // 填写页表项为页的地址 - } + pte = pte_ptr(vaddr); + uint32_t page = paddr; + page |= SIGN_RW | SIGN_P | (sign & SIGN_US); + *pte = page; // 填写页表项为页的地址 } /** @@ -371,6 +395,24 @@ uint32_t alloc_mem_page(void) { return mem_addr; } +uint32_t alloc_mem_pages(int pages) { + int addr = 0; + int idx; + int mem_addr; + idx = mmap_search(&phy_page_mmap, pages); + if (idx != -1) { + for (int i = 0; i < pages; i++) { + mmap_set(&phy_page_mmap, idx + i, 1); + } + } else { + return (int)NULL; + } + mem_addr = idx * 0x1000 + PHY_MEM_BASE_ADDR; + + return mem_addr; + return addr; +} + /** * @brief 释放一个物理页 * @@ -403,7 +445,7 @@ void *thread_get_page(struct task_s *thread, uint32_t vaddr) { mmap_set(&thread->vir_page_mmap, idx, 1); - fill_vir_page_table(vaddr, SIGN_USER); + fill_vir_page_table(vaddr, alloc_mem_page(), SIGN_USER); return (void *)vaddr; } @@ -456,7 +498,7 @@ void *thread_alloc_page(struct task_s *thread, int pages) { vir_page_addr = thread_alloc_vir_page(thread); // 分配一个虚拟地址的页 fill_vir_page_table( - vir_page_addr, + vir_page_addr, alloc_mem_page(), SIGN_USER); // 把页添加到当前页目录表系统中,使他可以被使用 if (pages == 1) { // 如果只有一个页 @@ -467,7 +509,7 @@ void *thread_alloc_page(struct task_s *thread, int pages) { vir_page_addr_more = thread_alloc_vir_page(thread); // 分配一个虚拟地址的页 fill_vir_page_table( - vir_page_addr_more, + vir_page_addr_more, alloc_mem_page(), SIGN_USER); // 把页添加到当前页目录表系统中,使他可以被使用 } memset((void *)vir_page_addr, 0, PAGE_SIZE * pages); @@ -535,7 +577,7 @@ MemoryResult thread_use_page( MEMORY_RESULT_DELIVER_CALL(remap, pt & 0xfffff000, PAGE_SIZE, &pt); pte = (uint32_t *)(pt + ((vaddr & 0x003ff000) >> 12) * 4); - if (((*pte) & 0x00000001) != 0x00000001) { // 不存在页表项 + if (((*pte) & 0x00000001) != 0x00000001) { // 不存在页表项 *pte = addr | SIGN_P | SIGN_RW | SIGN_USER; // 填写页表项为页的地址 addr += PAGE_SIZE; } From 1135303190b4de39dee40ad08e1b3bd121a86791 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 30 Aug 2025 01:34:11 +0800 Subject: [PATCH 089/158] =?UTF-8?q?fix:=20rtl8139:=20=E4=BF=AE=E5=A4=8DDMA?= =?UTF-8?q?=E7=8E=AF=E5=BD=A2=E7=BC=93=E5=86=B2=E5=8C=BA=E7=AE=A1=E7=90=86?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../x86/drivers/network/rtl8139/rtl8139.c | 75 ++++++++++++++----- .../x86/drivers/network/rtl8139/rtl8139.h | 3 +- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/src/arch/x86/drivers/network/rtl8139/rtl8139.c b/src/arch/x86/drivers/network/rtl8139/rtl8139.c index cd7b64d..ae8928f 100644 --- a/src/arch/x86/drivers/network/rtl8139/rtl8139.c +++ b/src/arch/x86/drivers/network/rtl8139/rtl8139.c @@ -26,6 +26,7 @@ #include "driver/network/network.h" #include "kernel/softirq.h" #include "kernel/thread.h" +#include "network/eth.h" #include "objects/transfer.h" #include "rtl8139.h" @@ -89,6 +90,7 @@ const NetworkDevice rtl8139_network_device_template = { .tail_size = 0, .type = NETWORK_TYPE_ETHERNET, .ops = &rtl8139_net_device_ops, + .mtu = ETH_MTU, }; void rtl8139_handler(Device *device) { @@ -99,14 +101,48 @@ void rtl8139_handler(Device *device) { if (status == 0xffff) goto end; - io_out_word(rtl_device->io_base + REG_ISR, status); + int _status = 0; if (status & IMR_TOK) { rtl_device->tx_done_idx = (rtl_device->tx_done_idx + 1) % TX_DESC_NR; + _status |= IMR_TOK; } - if (status & IMR_ROK) pending_softirq(); - if (status & IMR_RXOVW) print_error("RTL8139", "RX Overflow\n"); - if (status & IMR_FOVW) print_error("RTL8139", "FIFO Overflow\n"); - if (status & IMR_PUN_LINKCHG) { print_device_info(device, "Link Changed"); } + if (status & IMR_TER) { + print_error("RTL8139", "TX Error\n"); + _status |= IMR_TER; + } + if (status & IMR_ROK) { + pending_softirq(); + _status |= IMR_ROK; + } + if (status & IMR_RER) { + print_error("RTL8139", "RX Error\n"); + _status |= IMR_RER; + } + if (status & IMR_RXOVW) { + print_error("RTL8139", "RX Overflow\n"); + _status |= IMR_RXOVW; + } + if (status & IMR_FOVW) { + print_error("RTL8139", "FIFO Overflow\n"); + _status |= IMR_FOVW; + } + if (status & IMR_PUN_LINKCHG) { + print_device_info(device, "Link Changed"); + _status |= IMR_PUN_LINKCHG; + } + if (status & IMR_LEN_CHG) { + print_device_info(device, "Length Changed"); + _status |= IMR_LEN_CHG; + } + if (status & IMR_TIMEOUT) { + print_error("RTL8139", "TX Timeout\n"); + _status |= IMR_TIMEOUT; + } + if (status & IMR_SERR) { + print_error("RTL8139", "System Error\n"); + _status |= IMR_SERR; + } + io_out_word(rtl_device->io_base + REG_ISR, _status); end: spin_unlock(&rtl_device->lock); @@ -120,30 +156,33 @@ void rtl8139_net_rx_handler(void *data) { while (!(cmd & RTL8139_CR_BUFE)) { int i = device->rx_offset; rx_status = LE2HOST_DWORD(*(uint32_t *)(device->rx_buffer + i)); - uint16_t length = (rx_status >> 16) - 4; + uint16_t length = (rx_status >> 16); + int packet_len = length - 4; i += 4; - if (length >= ETH_HEADER_SIZE && (rx_status & RTL8139_RX_STAT_ROK)) { - NetBuffer *net_buffer = net_buffer_create(length); - net_buffer_init(net_buffer, length, 0, length); + if (packet_len >= ETH_HEADER_SIZE && + (rx_status & RTL8139_RX_STAT_ROK)) { + NetBuffer *net_buffer = net_buffer_create(packet_len); + net_buffer_init(net_buffer, packet_len, 0, packet_len); void *buffer = net_buffer->ptr; - if (i + length >= RTL8139_RECV_BUF_SIZE) { + if (i + packet_len >= RTL8139_RECV_BUF_SIZE) { + int first_len = RTL8139_RECV_BUF_SIZE - i; + memcpy(buffer, device->rx_buffer + i, first_len); memcpy( - buffer, device->rx_buffer + i, RTL8139_RECV_BUF_SIZE - i); - i = RTL8139_RECV_BUF_SIZE - i; - memcpy(buffer + i, device->rx_buffer + i, length - i); + buffer + first_len, device->rx_buffer + i, + packet_len - first_len); } else { - memcpy(buffer, device->rx_buffer + i, length); + memcpy(buffer, device->rx_buffer + i, packet_len); } eth_recv(device->net_device, net_buffer); } else { printk( "[RTL8139]RX Error: status %#04x,size %#04x, cur %#04x\n", - rx_status, length + 4, device->rx_offset); + rx_status, packet_len, device->rx_offset); } - device->rx_offset = (device->rx_offset + length + 8 + 3) & + device->rx_offset = (device->rx_offset + length + 4 + 3) & ~3; // +8:4字节CRC和4字节包头;+3:4字节对齐用 - device->rx_offset %= RTL8139_RECV_BUF_SIZE; + device->rx_offset &= RTL8139_RX_READ_POINTER_MASK; io_out_word(device->io_base + RTL8139_CAPR, device->rx_offset - 0x10); cmd = io_in8(device->io_base + RTL8139_CR); @@ -258,7 +297,7 @@ DriverResult rtl8139_start(Device *device) { io_out_byte(rtl_device->io_base + REG_CR, CR_RE | CR_TE); // 配置接收缓冲区 - rtl_device->rx_buffer = kmalloc(RTL8139_RECV_BUF_SIZE); + rtl_device->rx_buffer = kernel_alloc_continuous_pages(8 << RECV_BUF_LEN); rtl_device->rx_buffer_phy = vir2phy((size_t)rtl_device->rx_buffer); io_out_dword(rtl_device->io_base + REG_RBSTART, rtl_device->rx_buffer_phy); io_out_dword( diff --git a/src/arch/x86/drivers/network/rtl8139/rtl8139.h b/src/arch/x86/drivers/network/rtl8139/rtl8139.h index 6ac8043..2117d94 100644 --- a/src/arch/x86/drivers/network/rtl8139/rtl8139.h +++ b/src/arch/x86/drivers/network/rtl8139/rtl8139.h @@ -111,7 +111,8 @@ #define RECV_BUF_LEN RBLEN_16K #define RBLEN RCR_RBLEN(RECV_BUF_LEN) -#define RTL8139_RECV_BUF_SIZE (8192 << RECV_BUF_LEN) + 16 + 1500 +#define RTL8139_RECV_BUF_SIZE (8192 << RECV_BUF_LEN) +#define RTL8139_RX_READ_POINTER_MASK (((8192 << RECV_BUF_LEN) - 1) & ~3) typedef enum Rtl8139Chipset { RTL8139 = 0, From 9ff9c9cccb90697222927a8d7a86f07ad2022d76 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 30 Aug 2025 01:36:07 +0800 Subject: [PATCH 090/158] =?UTF-8?q?ethernet:=20=E4=BF=AE=E5=A4=8D=E4=BF=AE?= =?UTF-8?q?=E6=94=B9tail=E6=8C=87=E9=92=88=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/ethernet/ethernet.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/driver/network/ethernet/ethernet.c b/src/driver/network/ethernet/ethernet.c index 3f13164..0a98245 100644 --- a/src/driver/network/ethernet/ethernet.c +++ b/src/driver/network/ethernet/ethernet.c @@ -59,7 +59,6 @@ ProtocolResult eth_wrap( if (content_size < ETH_MIN_FRAME_SIZE) { // 填充最小帧长度 memset(buffer->tail, 0, ETH_MIN_FRAME_SIZE - content_size); - buffer->tail = buffer->head + ETH_MIN_FRAME_SIZE; } header->protocol_type = HOST2BE_WORD(protocol); From df650a503026f1e9fd91774f93e458d989c9fa6f Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 30 Aug 2025 01:37:31 +0800 Subject: [PATCH 091/158] =?UTF-8?q?network:=20NetBuffer=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20=E6=B8=85=E9=99=A4=E6=95=B0=E6=8D=AE=E5=8A=9F?= =?UTF-8?q?=E8=83=BDnet=5Fbuffer=5Fclean=5Fdata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/buffer.c | 4 ++++ src/include/driver/network/buffer.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/driver/network/buffer.c b/src/driver/network/buffer.c index cb4c8c0..02685b1 100644 --- a/src/driver/network/buffer.c +++ b/src/driver/network/buffer.c @@ -30,6 +30,10 @@ void net_buffer_reset(NetBuffer *buffer) { buffer->tail = buffer->data; } +void net_buffer_clean_data(NetBuffer *buffer) { + buffer->tail = buffer->data; +} + void net_buffer_header_alloc(NetBuffer *buffer, uint16_t size) { buffer->head -= size; } diff --git a/src/include/driver/network/buffer.h b/src/include/driver/network/buffer.h index 4431324..414372d 100644 --- a/src/include/driver/network/buffer.h +++ b/src/include/driver/network/buffer.h @@ -28,6 +28,7 @@ void net_buffer_init( struct NetworkConnection; ProtocolResult net_buffer_data_alloc(NetBuffer *buffer, uint16_t size); void net_buffer_reset(NetBuffer *buffer); +void net_buffer_clean_data(NetBuffer *buffer); void net_buffer_header_alloc(NetBuffer *buffer, uint16_t size); void net_buffer_header_free(NetBuffer *buffer, uint16_t size); void net_buffer_tail_alloc(NetBuffer *buffer, uint16_t size); From 75dac87eccf2d09539d3acf2c267a91e2f858a04 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 30 Aug 2025 01:39:50 +0800 Subject: [PATCH 092/158] =?UTF-8?q?[WIP]network&tcp:=20=E6=96=B0=E5=A2=9Et?= =?UTF-8?q?cp=E6=94=AF=E6=8C=81;=20dchp&acd&ipv4:=20=E4=BF=AE=E5=A4=8D=20i?= =?UTF-8?q?p=E5=9C=B0=E5=9D=80=E5=A1=AB=E5=86=99=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/conn.c | 72 +++ src/driver/network/protocols/Makefile | 3 +- src/driver/network/protocols/acd.c | 7 +- src/driver/network/protocols/arp.c | 6 +- src/driver/network/protocols/dhcp.c | 23 +- src/driver/network/protocols/ipv4.c | 58 +- src/driver/network/protocols/tcp.c | 609 ++++++++++++++++++ src/driver/network/protocols/udp.c | 2 +- src/include/driver/network/conn.h | 20 +- src/include/driver/network/network_dm.h | 8 +- src/include/driver/network/protocols/ipv4.h | 9 +- .../driver/network/protocols/protocols.h | 5 + src/include/driver/network/protocols/tcp.h | 174 +++++ 13 files changed, 969 insertions(+), 27 deletions(-) create mode 100644 src/driver/network/protocols/tcp.c create mode 100644 src/include/driver/network/protocols/tcp.h diff --git a/src/driver/network/conn.c b/src/driver/network/conn.c index f057cf1..cb2add7 100644 --- a/src/driver/network/conn.c +++ b/src/driver/network/conn.c @@ -1,3 +1,6 @@ +#include "driver/network/ethernet/ethernet.h" +#include "driver/network/protocols/ipv4.h" +#include "driver/network/protocols/protocols.h" #include "kernel/list.h" #include "kernel/spinlock.h" #include "kernel/thread.h" @@ -6,6 +9,7 @@ #include #include #include +#include NetworkConnection *net_create_conn(Object *object) { if (object->attr->type != OBJECT_TYPE_DEVICE) { return NULL; } @@ -21,6 +25,7 @@ NetworkConnection *net_create_conn(Object *object) { conn->dl_protocol = DL_PROTO_NONE; conn->net_protocol = NET_PROTO_NONE; conn->trans_protocol = TRANS_PROTO_NONE; + conn->tcp.info = NULL; spinlock_init(&conn->recv_lock); list_init(&conn->recv_lh); @@ -38,3 +43,70 @@ void net_destroy_conn(NetworkConnection *conn) { object_handle_delete(conn->handle); kfree(conn); } + +ProtocolResult conn_wrap(NetworkConnection *conn, ProtocolLevel level) { + if (conn == NULL) { return PROTO_ERROR_NULL_PTR; } + uint16_t trans_protocol = 0; + uint16_t net_protocol = 0; + uint8_t dst_mac[8] = {0}; + + switch (level) { + case PROTO_LEVEL_TRANSPORT: + case PROTO_LEVEL_NETWORK: + if (trans_protocol == 0) { + switch (conn->trans_protocol) { + case TRANS_PROTO_UDP: + trans_protocol = IP_PROTO_UDP; + break; + case TRANS_PROTO_TCP: + trans_protocol = IP_PROTO_TCP; + break; + default: + break; + } + } + switch (conn->net_protocol) { + case NET_PROTO_IPV4: + ipv4_wrap(conn, trans_protocol, CONN_REMOTE_IP(conn), 64); + ipv4_lookup_mac( + conn->net_device, conn->ipv4.conn_info.remote.ip, dst_mac); + break; + default: + return PROTO_ERROR_UNSUPPORT; + } + case PROTO_LEVEL_DATA_LINK: + switch (conn->dl_protocol) { + default: + break; + } + case PROTO_LEVEL_PHYSICAL: + if (net_protocol == 0) { + switch (conn->net_protocol) { + case NET_PROTO_IPV4: + net_protocol = ETH_PROTO_TYPE_IPV4; + break; + default: + return PROTO_ERROR_UNSUPPORT; + } + } + if (net_protocol == 0) { + switch (conn->dl_protocol) { + case DL_PROTO_ARP: + net_protocol = ETH_PROTO_TYPE_ARP; + break; + default: + return PROTO_ERROR_UNSUPPORT; + } + } + switch (conn->phy_protocol) { + case PHY_PROTO_ETHERNET: + eth_wrap(conn->buffer, conn->ethernet.mac, dst_mac, net_protocol); + break; + default: + return PROTO_ERROR_UNSUPPORT; + } + break; + } + + return PROTO_OK; +} diff --git a/src/driver/network/protocols/Makefile b/src/driver/network/protocols/Makefile index 69eb0a2..df2b998 100644 --- a/src/driver/network/protocols/Makefile +++ b/src/driver/network/protocols/Makefile @@ -2,4 +2,5 @@ SRC += arp.c SRC += ipv4.c SRC += dhcp.c SRC += udp.c -SRC += acd.c \ No newline at end of file +SRC += acd.c +SRC += tcp.c \ No newline at end of file diff --git a/src/driver/network/protocols/acd.c b/src/driver/network/protocols/acd.c index 798a823..52b8032 100644 --- a/src/driver/network/protocols/acd.c +++ b/src/driver/network/protocols/acd.c @@ -26,20 +26,21 @@ void acd_timer_callback(void *arg) { timer_set_timeout(ð_device->timer, ACD_PROBE_MIN * 1000); timer_callback_enable(ð_device->timer); - NeighbourKey key = ipv4_hash(device->ipv4_addr); + NeighbourKey key = ipv4_hash(device->ipv4.ip); NeighbourEntry *entry = - neighbour_table_lookup(device, key, device->ipv4_addr, 4); + neighbour_table_lookup(device, key, device->ipv4.ip, 4); arp_send_request(entry, arg); } else { // 确认没有冲突,发送公告 acd_announce(device); } + break; case ACD_STATE_ANNOUNCE: if (eth_device->announce_count < ACD_ANNOUNCE_NUM) { eth_device->announce_count++; timer_set_timeout(ð_device->timer, ACD_ANNOUNCE_INTERVAL * 1000); timer_callback_enable(ð_device->timer); - arp_announce(device, device->ipv4_addr); + arp_announce(device, device->ipv4.ip); } else { eth_device->acd_state = ACD_STATE_NONE; } diff --git a/src/driver/network/protocols/arp.c b/src/driver/network/protocols/arp.c index a7e1ef9..a6f4741 100644 --- a/src/driver/network/protocols/arp.c +++ b/src/driver/network/protocols/arp.c @@ -66,7 +66,7 @@ ProtocolResult arp_recv(NetworkDevice *device, NetBuffer *net_buffer) { uint16_t ptype = BE2HOST_WORD(arp_header->ptype); if (ptype == ETH_TYPE_IPV4 && arp_header->plen == 4) { hash_key = ipv4_hash(src_paddr) % NEIGH_BUCKET_SIZE; - paddr = device->ipv4_addr; + paddr = device->ipv4.ip; if (memcmp(src_paddr, paddr, 4) == 0) { // 源地址与本机IP冲突 acd_conflict_detected(device); @@ -123,6 +123,8 @@ void arp_send_request(NeighbourEntry *entry, void *arg) { EthernetDevice *eth_device = device->ethernet; NetworkConnection *conn = eth_device->arp_conn; + net_buffer_reset(conn->buffer); + // Fill in the ARP request details ArpHeader *arp_header = (ArpHeader *)conn_buffer(conn)->data; arp_header->htype = HOST2BE_WORD(ARP_HTYPE_ETH); @@ -139,7 +141,7 @@ void arp_send_request(NeighbourEntry *entry, void *arg) { // Copy the sender's hardware and protocol addresses memcpy(src_haddr, eth_device->mac_addr, arp_header->hlen); - memcpy(src_paddr, device->ipv4_addr, arp_header->plen); + memcpy(src_paddr, device->ipv4.ip, arp_header->plen); // Copy the target's hardware and protocol addresses uint8_t eth_dst_addr[ETH_IDENTIFIER_SIZE] = {0}; diff --git a/src/driver/network/protocols/dhcp.c b/src/driver/network/protocols/dhcp.c index b8f1189..8b9a139 100644 --- a/src/driver/network/protocols/dhcp.c +++ b/src/driver/network/protocols/dhcp.c @@ -14,6 +14,7 @@ #include "driver/network/protocols/acd.h" #include "driver/timer_dm.h" #include "kernel/driver_interface.h" +#include "kernel/thread.h" #include "objects/transfer.h" #include #include @@ -216,18 +217,20 @@ void dhcp_offer_handler( } void dhcp_ack_handler( - DhcpClient *dhcp, NetworkConnection *conn, uint16_t indexes[DOI_MAX]) { - DhcpHeader *header = conn->buffer->data; - *(uint32_t *)conn->ipv4.subnet_mask = 0; - *(uint32_t *)conn->ipv4.gateway_ip = 0; + DhcpClient *dhcp, NetworkConnection *conn, DhcpHeader *header, + uint16_t indexes[DOI_MAX]) { + NetworkDevice *device = conn->net_device; + *(uint32_t *)device->ipv4.subnet_mask = 0; + *(uint32_t *)device->ipv4.gateway_ip = 0; + memcpy(device->ipv4.ip, dhcp->ip_addr, 4); if (indexes[DOI_SUBNET_MASK] != 0) { - *(uint32_t *)conn->ipv4.subnet_mask = + *(uint32_t *)device->ipv4.subnet_mask = *(uint32_t *)&header->options[indexes[DOI_SUBNET_MASK]]; } if (indexes[DOI_ROUTER] != 0) { - *(uint32_t *)conn->ipv4.gateway_ip = + *(uint32_t *)device->ipv4.gateway_ip = *(uint32_t *)&header->options[indexes[DOI_ROUTER]]; } @@ -318,7 +321,9 @@ void dhcp_check_addr(DhcpClient *dhcp) { NeighbourEntry *entry = neighbour_table_lookup(dhcp->device, key, dhcp->server_ip_addr, 4); entry->ops->probe(dhcp->device); - memcpy(dhcp->server_haddr, entry->haddr, dhcp->haddr_len); + if (entry->state == NEIGH_STATE_REACHABLE) { + memcpy(dhcp->server_haddr, entry->haddr, dhcp->haddr_len); + } } void dhcp_rx_handler(NetworkConnection *conn, NetBuffer *net_buffer) { @@ -365,12 +370,12 @@ void dhcp_rx_handler(NetworkConnection *conn, NetBuffer *net_buffer) { // TODO: 检查地址冲突 dhcp_check_addr(dhcp); - dhcp_ack_handler(dhcp, conn, indexes); + dhcp_ack_handler(dhcp, conn, header, indexes); dhcp_set_timers(dhcp); } else if ( dhcp->state == DHCP_STAT_RENEWING || dhcp->state == DHCP_STAT_REBINDING) { - dhcp_ack_handler(dhcp, conn, indexes); + dhcp_ack_handler(dhcp, conn, header, indexes); dhcp_set_timers(dhcp); } } else if (msg_type == DHCP_NAK) { diff --git a/src/driver/network/protocols/ipv4.c b/src/driver/network/protocols/ipv4.c index 1451bab..79b482c 100644 --- a/src/driver/network/protocols/ipv4.c +++ b/src/driver/network/protocols/ipv4.c @@ -7,6 +7,9 @@ * RFC 791: INTERNET PROTOCOL * */ +#include "driver/network/network_dm.h" +#include "driver/network/protocols/tcp.h" +#include "kernel/thread.h" #include #include #include @@ -33,9 +36,9 @@ NeighbourKey ipv4_hash(uint8_t ip[4]) { void ipv4_register(NetworkConnection *conn, uint8_t *ip_addr) { conn->net_protocol = NET_PROTO_IPV4; if (ip_addr) { - memcpy(conn->ipv4.ip, ip_addr, 4); + memcpy(CONN_LOCAL_IP(conn), ip_addr, 4); } else { - memset(conn->ipv4.ip, 0, 4); + memcpy(CONN_LOCAL_IP(conn), conn->net_device->ipv4.ip, 4); } // 默认禁用分段 conn->ipv4.fragment.enable_fragment = 0; @@ -72,10 +75,11 @@ void ipv4_checksum(Ipv4Header *header) { ProtocolResult ipv4_wrap( NetworkConnection *conn, uint16_t protocol, uint8_t *dst_ip, uint8_t ttl) { - uint16_t size = CONN_CONTENT_SIZE(conn); + uint16_t size = CONN_PACKET_SIZE(conn); net_buffer_header_alloc(conn_buffer(conn), sizeof(Ipv4Header)); Ipv4Header *ipv4_header = (Ipv4Header *)conn_buffer(conn)->head; + conn->ipv4.header = ipv4_header; ipv4_header->ver_len = (0x4 << 4) | (20 >> 2); // IPv4, 20字节 ipv4_header->tos = 0; // Type of Service ipv4_header->total_len = HOST2BE_WORD(sizeof(Ipv4Header) + size); @@ -89,7 +93,7 @@ ProtocolResult ipv4_wrap( ipv4_header->ttl = ttl; ipv4_header->protocol = protocol; ipv4_header->checksum = 0; - memcpy(ipv4_header->src_ip, conn->ipv4.ip, 4); + memcpy(ipv4_header->src_ip, CONN_LOCAL_IP(conn), 4); if (dst_ip) { memcpy(ipv4_header->dst_ip, dst_ip, 4); } else { @@ -100,9 +104,20 @@ ProtocolResult ipv4_wrap( return PROTO_OK; } +void ipv4_rewrap(NetworkConnection *conn) { + Ipv4Header *ipv4_header = conn->ipv4.header; + if (!ipv4_header) return; + + ipv4_header->total_len = + HOST2BE_WORD(conn->buffer->tail - (void *)ipv4_header); + ipv4_header->checksum = 0; + ipv4_checksum(ipv4_header); +} + ProtocolResult ipv4_recv(NetBuffer *net_buffer) { Ipv4Header *ipv4_header = (Ipv4Header *)net_buffer->data; int size = net_buffer->tail - net_buffer->data; + int length = ipv4_get_packet_length(ipv4_header); if (size < sizeof(Ipv4Header)) return PROTO_ERROR_UNSUPPORT; @@ -130,6 +145,8 @@ ProtocolResult ipv4_recv(NetBuffer *net_buffer) { result = udp_recv(net_buffer, ipv4_header); break; case IP_PROTO_TCP: + result = tcp_recv( + net_buffer, length, ipv4_header->src_ip, ipv4_header->dst_ip, 4); break; case IP_PROTO_ICMP: break; @@ -139,3 +156,36 @@ ProtocolResult ipv4_recv(NetBuffer *net_buffer) { return result; } + +ProtocolResult ipv4_lookup_mac( + NetworkDevice *device, uint8_t ip[4], uint8_t mac[8]) { + if (!ip || !mac) return PROTO_ERROR_NULL_PTR; + NeighbourKey hash_key; + uint32_t subnet_mask = *(uint32_t *)device->ipv4.subnet_mask; + uint32_t gateway_ip = *(uint32_t *)device->ipv4.gateway_ip; + uint32_t _ip = *(uint32_t *)ip; + + NeighbourEntry *entry; + if ((_ip & subnet_mask) == (gateway_ip & subnet_mask)) { + // 在子网内 + hash_key = ipv4_hash(ip); + entry = neighbour_table_lookup(device, hash_key, ip, 4); + } else { + // 在子网外 + hash_key = ipv4_hash(device->ipv4.gateway_ip); + entry = neighbour_table_lookup( + device, hash_key, device->ipv4.gateway_ip, 4); + } + + if (entry == NULL) return PROTO_ERROR_CANNOT_FIND; + while (entry->state == NEIGH_STATE_WAITING) { + schedule(); + } + memcpy(mac, entry->haddr, 8); + return PROTO_OK; +} + +uint16_t ipv4_get_packet_length(Ipv4Header *ipv4_header) { + return BE2HOST_WORD(ipv4_header->total_len) - + ((ipv4_header->ver_len & 0x0F) << 2); +} diff --git a/src/driver/network/protocols/tcp.c b/src/driver/network/protocols/tcp.c new file mode 100644 index 0000000..469ad42 --- /dev/null +++ b/src/driver/network/protocols/tcp.c @@ -0,0 +1,609 @@ +/** + * @file tcp.c + * @author Jiajun Wang (ryan1202@foxmail.com) + * @brief TCP + * References: + * RFC793: Transmission Control Protocol + * RFC6528: Defending against Sequence Number Attacks + * RFC6298: Computing TCP's Retransmission Timer + * + */ +#include "bits.h" +#include "driver/network/buffer.h" +#include "driver/network/network_dm.h" +#include "driver/network/protocols/protocols.h" +#include "driver/timer_dm.h" +#include "kernel/memory.h" +#include "kernel/spinlock.h" +#include "kernel/thread.h" +#include "math.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define TCP_CHECKSUM_ADD(sum, data) \ + sum += (data); \ + if (sum > 0xFFFF) sum = (sum & 0xFFFF) + (sum >> 16); + +SPINLOCK(tcp_lock); +LIST_HEAD(tcp_lh); + +const int send_win_default_size = 32768; +const int recv_win_default_size = 32768; + +const int min_ephemeral_port = 32768; +const int max_ephemeral_port = 65535; + +const int tcp_max_retries = 15; + +const int tcp_fin_timeout = 60; + +void tcp_timeout_handler(void *arg); +void tcp_reset_conn(NetworkConnection *conn, Tcp *tcp); +void tcp_send(Tcp *tcp, NetworkConnection *conn, bool set_timer); + +uint16_t tcp_checksum( + TcpHeader *header, int length, const uint8_t *src_ip, const uint8_t *dst_ip, + int ip_len) { + uint8_t *data = (uint8_t *)header; + uint32_t sum = 0; + + // 清除校验和 + header->checksum = 0; + + // 计算伪头部校验和 + for (int j = 0; j < ip_len; j += 2) { + sum += (src_ip[j] << 8 | src_ip[j + 1]); + sum += (dst_ip[j] << 8 | dst_ip[j + 1]); + } + sum += IP_PROTO_TCP; + sum += length; + + // 计算TCP头部和数据的校验和 + int i; + for (i = 0; i + 2 <= length; i += 2) { + sum += data[i] << 8 | data[i + 1]; + sum = (sum & 0xffff0000) ? ((sum >> 16) + (sum & 0xffff)) : sum; + } + + if (length % 2) { // 如果长度是奇数,补齐一个字节 + sum += data[length - 1] << 8; + } + + while (sum & 0xffff0000) { + sum = (sum >> 16) + (sum & 0xffff); + } + + sum = ~((uint16_t)(sum)) & 0xffff; + return sum; +} + +void tcp_register(NetworkConnection *conn) { + conn->trans_protocol = TRANS_PROTO_TCP; + if (conn->tcp.info == NULL) { conn->tcp.info = kmalloc(sizeof(Tcp)); } + Tcp *tcp = conn->tcp.info; + tcp->header_size = sizeof(TcpHeader) + 4; + NET_BUF_RESV_HEAD(conn, tcp->header_size); +} + +uint32_t tcp_generate_isn(void *ip_port_pair, int len) { + static uint32_t counter = 0; + uint32_t isn = timer_get_counter(); + counter++; + + isn += fnv1_hash_32(ip_port_pair, len); + isn += counter; + + return isn; +} + +void tcp_compute_retransmission_timer(Tcp *tcp, int r) { + if (tcp == NULL) return; + + if (r == 0) { + if (tcp->rtt == 0) { + // 还没完成RTT测量 + tcp->rto = 1; + } + } else { + if (tcp->rtt == 0) { + // 完成初次RTT测量 + tcp->srtt = r; + tcp->rtt = r / 2; + tcp->rto = tcp->srtt + MAX(1, 4 * tcp->rtt); + } else { + // 完成后续RTT测量 + tcp->rtt = (3 * tcp->rtt + 1 * abs(tcp->srtt - r)) / 4; + tcp->srtt = (7 * tcp->srtt + 1 * r) / 8; + tcp->rto = tcp->srtt + MAX(1, 4 * tcp->rtt); + } + tcp->rto = MIN(tcp->rto, 60); // 最长1分钟 + } +} + +ProtocolResult tcp_bind(NetworkConnection *conn, uint16_t port) { + if (conn->tcp.info == NULL) { return PROTO_ERROR_NULL_PTR; } + Ipv4ConnInfo *conn_info = &conn->ipv4.conn_info; + if (list_in_list(&conn_info->list)) + return PROTO_ERROR_REBIND; // 已经绑定了端口 + + Ipv4ConnInfo *info; + spin_lock(&tcp_lock); + list_for_each_owner (info, &tcp_lh, list) { + if (info->local.port == port || + memcmp(info->local.ip, conn_info->local.ip, 4)) { + spin_unlock(&tcp_lock); + return PROTO_ERROR_PORT_CONFLICT; // 端口冲突 + } + } + conn_info->local.port = port; + + Tcp *tcp = conn->tcp.info; + tcp->cur.seq = 0; + tcp->cur.ack = 0; + tcp->state = TCP_STATE_CLOSED; + tcp->recv_window = kmalloc(recv_win_default_size); + tcp->recv.next = 0; + tcp->recv.window = recv_win_default_size; + tcp->recv.total_size = recv_win_default_size; + tcp->recv.read = 0; + tcp->rtt = tcp->rto = tcp->srtt = 0; + tcp_compute_retransmission_timer(tcp, 0); + timer_init(&tcp->timeout_timer); + tcp->timeout_timer.callback = tcp_timeout_handler; + tcp->timeout_timer.arg = tcp; + + conn->tcp.info->conn = conn; + conn->tcp.info->thread = get_current_thread(); + + list_add_tail(&conn->ipv4.conn_info.list, &tcp_lh); + spin_unlock(&tcp_lock); + return PROTO_OK; +} + +ProtocolResult tcp_connect( + NetworkConnection *conn, uint8_t *dst_ip, uint16_t dst_port) { + Tcp *tcp = conn->tcp.info; + if (conn->tcp.info == NULL) { return PROTO_ERROR_NULL_PTR; } + if (tcp->state != TCP_STATE_CLOSED) { + // 如果没有绑定端口,随机绑定一个大于32768的端口 + uint16_t port = min_ephemeral_port + + (rand() % (max_ephemeral_port - min_ephemeral_port)); + int count = max_ephemeral_port - min_ephemeral_port + 1; + while (count-- > 0) { + ProtocolResult result = tcp_bind(conn, port); + if (result == PROTO_OK) break; + else if (result != PROTO_ERROR_PORT_CONFLICT) { return result; } + port += 1; + } + } + + Ipv4ConnInfo *conn_info = &conn->ipv4.conn_info; + memcpy(conn_info->remote.ip, dst_ip, 4); + conn_info->remote.port = dst_port; + + tcp->send.iss = + tcp_generate_isn(&conn_info, sizeof(Ipv4ConnInfo) - sizeof(list_t)); + tcp->cur.seq = tcp->send.iss; + // 构造SYN报文 + net_buffer_header_alloc(conn->buffer, tcp->header_size); + tcp->header = (TcpHeader *)conn->buffer->head; + TcpHeader *header = tcp->header; + header->src_port = HOST2BE_WORD(conn_info->local.port); + header->dest_port = HOST2BE_WORD(conn_info->remote.port); + header->seq = HOST2BE_DWORD(tcp->cur.seq); + header->ack = 0; + header->data_offset = (tcp->header_size / 4) << 4; + header->flags = TCP_FLAG_SYN; + header->window_size = HOST2BE_WORD(tcp->recv.window); + header->urgent_pointer = 0; + header->checksum = 0; + header->checksum = HOST2BE_WORD(tcp_checksum( + header, tcp->header_size, conn_info->local.ip, conn_info->remote.ip, + 4)); + + conn_wrap(conn, PROTO_LEVEL_NETWORK); + + tcp->state = TCP_STATE_SYN_SENT; + + timer_set_timeout(&tcp->timeout_timer, tcp->rto * 1000); + timer_callback_enable(&tcp->timeout_timer); + NETWORK_SEND(conn->net_device, conn); + + thread_set_status(TASK_INTERRUPTIBLE); + thread_wait(); + + if (tcp->state != TCP_STATE_ESTABLISHED) return PROTO_ERROR_CONNECT_FAILED; + // 建立连接后再真正分配发送窗口 + tcp->send.unack = 0; + tcp->send.next = 0; + tcp->send.wl1 = tcp->cur.ack; + tcp->send.wl2 = tcp->cur.seq; + tcp->send.total_size = send_win_default_size; + tcp->send.window = MIN(tcp->send.total_size, tcp->send.remote_window_size); + tcp->send_window = kmalloc(tcp->send.total_size); + + return PROTO_OK; +} + +ProtocolResult tcp_send_data( + NetworkConnection *conn, uint8_t *buf, int length) { + if (conn == NULL || buf == NULL || length <= 0) { + return PROTO_ERROR_NULL_PTR; + } + + Tcp *tcp = conn->tcp.info; + if (tcp == NULL) { return PROTO_ERROR_NULL_PTR; } + + int used_space = tcp->send.next - tcp->send.unack; + used_space = + (used_space >= 0) ? used_space : used_space + tcp->send.total_size; + int space = tcp->send.total_size - used_space; + if (space < length) { return PROTO_ERROR_NO_SPACE_LEFT; } + + // 将数据放入发送缓冲区 + if (tcp->send.unack < tcp->send.next) { + int size1 = MIN(length, tcp->send.total_size - tcp->send.next); + int size2 = MAX(length - size1, 0); + memcpy(tcp->send_window + tcp->send.next, buf, size1); + memcpy(tcp->send_window, buf + size1, size2); + } else { + int size = MIN(length, space); + memcpy(tcp->send_window + tcp->send.next, buf, size); + } + tcp->send.next = (tcp->send.next + length) % tcp->send.total_size; + used_space += length; + + // 发送数据 + int total_size = 0; + int max = MIN(tcp->mss, tcp->send.window); + if (tcp->send.unack < tcp->send.next) { + int size = MIN(max, used_space); + memcpy(conn->buffer->data, tcp->send_window + tcp->send.unack, size); + tcp->send.unack += size; + tcp->send.unack %= tcp->send.total_size; + total_size = size; + } else { + int size1 = MIN(max, tcp->send.total_size - tcp->send.unack); + int size2 = MIN(MIN(max - size1, tcp->send.next), used_space - size1); + memcpy(conn->buffer->data, tcp->send_window + tcp->send.unack, size1); + memcpy(conn->buffer->data + size1, tcp->send_window, size2); + tcp->send.next += size1 + size2; + tcp->send.next %= tcp->send.total_size; + total_size = size1 + size2; + } + net_buffer_put(conn_buffer(conn), total_size); + tcp->header->flags = TCP_FLAG_PSH; + tcp->header->flags |= TCP_FLAG_ACK; + tcp_send(tcp, conn, true); + return PROTO_OK; +} + +ProtocolResult tcp_half_close(NetworkConnection *conn, Tcp *tcp) { + while (tcp->send.unack < tcp->send.next) {} + net_buffer_clean_data(conn->buffer); + tcp->header->flags = TCP_FLAG_FIN | TCP_FLAG_ACK; + tcp->state = TCP_STATE_FIN_WAIT1; + + kfree(tcp->send_window); + tcp->send.window = 0; + tcp->send_window = NULL; + tcp_send(tcp, conn, true); + return PROTO_OK; +} + +ProtocolResult tcp_shutdown(NetworkConnection *conn, uint8_t how) { + if (conn == NULL) return PROTO_ERROR_NULL_PTR; + if (conn->trans_protocol != TRANS_PROTO_TCP) return PROTO_ERROR_UNSUPPORT; + + Tcp *tcp = conn->tcp.info; + if (tcp == NULL) return PROTO_ERROR_NULL_PTR; + + switch (how) { + case TCP_SHUT_RD: + break; + case TCP_SHUT_WR: + tcp_half_close(conn, tcp); + break; + case TCP_SHUT_RDWR: + break; + default: + return PROTO_ERROR_UNSUPPORT; + } + + return PROTO_OK; +} + +void tcp_reset(NetworkConnection *conn) { + if (conn == NULL) return; + if (conn->trans_protocol != TRANS_PROTO_TCP) return; + Tcp *tcp = conn->tcp.info; + tcp_reset_conn(conn, tcp); +} + +void tcp_reset_conn(NetworkConnection *conn, Tcp *tcp) { + if (conn == NULL || tcp == NULL) return; + + net_buffer_clean_data(conn->buffer); + tcp->state = TCP_STATE_CLOSED; + TcpHeader *tcp_header = tcp->header; + tcp_header->flags = TCP_FLAG_RST; + tcp_header->ack = 0; + tcp_header->checksum = HOST2BE_WORD(tcp_checksum( + tcp_header, tcp->header_size, conn->ipv4.conn_info.local.ip, + conn->ipv4.conn_info.remote.ip, 4)); + kfree(tcp->send_window); + kfree(tcp->recv_window); + + NETWORK_SEND(conn->net_device, conn); +} + +void tcp_send(Tcp *tcp, NetworkConnection *conn, bool set_timer) { + TcpHeader *tcp_header = tcp->header; + tcp_header->seq = HOST2BE_DWORD(tcp->cur.seq); + tcp_header->ack = HOST2BE_DWORD(tcp->cur.ack); + tcp_header->window_size = HOST2BE_WORD(tcp->recv.window); + + tcp_header->checksum = tcp_checksum( + tcp_header, CONN_CONTENT_SIZE(conn) + tcp->header_size, + conn->ipv4.conn_info.local.ip, conn->ipv4.conn_info.remote.ip, 4); + tcp_header->checksum = HOST2BE_WORD(tcp_header->checksum); + + // 如果没有设置重传计时则设置一个 + if (set_timer && timer_is_timeout(&tcp->timeout_timer)) { + timer_set_timeout(&tcp->timeout_timer, tcp->rto * 1000); + timer_callback_enable(&tcp->timeout_timer); + } + ipv4_rewrap(conn); + NETWORK_SEND(conn->net_device, conn); +} + +void tcp_ack(NetworkConnection *conn, Tcp *tcp, uint8_t extra_flag) { + if (conn == NULL || tcp == NULL) return; + + TcpHeader *tcp_header = tcp->header; + + tcp_header->flags = extra_flag; + + tcp_header->flags |= TCP_FLAG_ACK; + tcp_send(tcp, conn, true); +} + +void tcp_ack_handler( + Tcp *tcp, TcpHeader *header, NetBuffer *net_buffer, int length) { + uint32_t seq = BE2HOST_DWORD(header->seq); + uint32_t ack = BE2HOST_DWORD(header->ack); + + if (length > 0) { + if (tcp->recv_window != NULL) { + int size1 = MIN(tcp->recv.total_size - tcp->recv.next, length); + // size2 = min(length - size1, tcp->recv.window - size1) + // 由于由发送方保证了tcp->recv.window ≥ length,所以直接使用length - + // size1 + int size2 = length - size1; + memcpy(tcp->recv_window + tcp->recv.next, net_buffer->data, size1); + memcpy(tcp->recv_window, net_buffer->data + size1, size2); + tcp->recv.next += length; + tcp->recv.next %= tcp->recv.total_size; + tcp->recv.window -= length; + tcp->send.wl1 = seq; + } + + tcp->cur.ack = seq + length; + tcp_ack(tcp->conn, tcp, 0); + } + + uint32_t acked = ack - tcp->send.wl2; + if (acked > 0) { + tcp->send.unack += acked; + tcp->send.unack %= tcp->send.total_size; + tcp->send.wl2 = ack; + + tcp->cur.seq += acked; + net_buffer_clean_data(tcp->conn->buffer); + } +} + +void tcp_timeout_handler(void *arg) { + if (arg == NULL) return; + Tcp *tcp = arg; + + switch (tcp->state) { // 超时重传 + case TCP_STATE_SYN_SENT: + case TCP_STATE_SYN_RECEIVED: + case TCP_STATE_ESTABLISHED: + case TCP_STATE_FIN_WAIT1: + tcp->retry_times++; + if (tcp->retry_times < tcp_max_retries) { + tcp->rto <<= 1; // 指数退避 + tcp->rto = MIN(tcp->rto, 60); + if (tcp->state == TCP_STATE_SYN_SENT || + tcp->state == TCP_STATE_SYN_RECEIVED) + tcp->rto = MIN(tcp->rto, 3); + timer_set_timeout(&tcp->timeout_timer, tcp->rto * 1000); + timer_callback_enable(&tcp->timeout_timer); + tcp_send(tcp, tcp->conn, true); + } else { + tcp_reset_conn(tcp->conn, tcp); + } + break; + case TCP_STATE_FIN_WAIT2: + // 进入FIN_WAIT_2后对方一直不发送FIN,强制关闭 + tcp_reset_conn(tcp->conn, tcp); + break; + case TCP_STATE_TIME_WAIT: + // 2MSL时间到,关闭连接 + tcp->state = TCP_STATE_CLOSED; + kfree(tcp->recv_window); + tcp->recv_window = NULL; + break; + default: + break; + } +} + +void tcp_rx_handler( + NetworkConnection *conn, TcpHeader *tcp_header, NetBuffer *net_buffer, + int length) { + Tcp *tcp = conn->tcp.info; + bool syn_flag = tcp_header->flags & TCP_FLAG_SYN; + bool ack_flag = tcp_header->flags & TCP_FLAG_ACK; + uint32_t seq = BE2HOST_DWORD(tcp_header->seq); + uint32_t ack = BE2HOST_DWORD(tcp_header->ack); + + uint8_t extra_flags = 0; + if (tcp_header->flags & TCP_FLAG_RST) { tcp->state = TCP_STATE_CLOSED; } + switch (tcp->state) { + case TCP_STATE_CLOSED: + tcp_reset_conn(conn, tcp); + break; + case TCP_STATE_LISTEN: + if (syn_flag) { + tcp->recv.irs = seq; + tcp->cur.ack = seq + 1; + tcp->send.remote_window_size = + BE2HOST_WORD(tcp_header->window_size); + tcp->state = TCP_STATE_SYN_RECEIVED; + extra_flags |= TCP_FLAG_SYN; + tcp_ack(conn, tcp, extra_flags); + } + break; + case TCP_STATE_SYN_SENT: + // 处理SYN + if (!syn_flag) { + // 异常,重置连接 + tcp_reset_conn(conn, tcp); + break; + } else { + tcp->send.remote_window_size = + BE2HOST_WORD(tcp_header->window_size); + tcp->recv.irs = seq; + tcp->cur.ack = seq + 1; + tcp->state = TCP_STATE_SYN_RECEIVED; + } + case TCP_STATE_SYN_RECEIVED: + timer_callback_cancel(&tcp->timeout_timer); + // 处理ACK + if (ack != tcp->cur.seq + 1) { + tcp_reset_conn(conn, tcp); + break; + } + if (ack_flag) { + tcp->cur.seq = ack; + tcp->state = TCP_STATE_ESTABLISHED; + } + tcp_ack(conn, tcp, extra_flags); + thread_unblock(tcp->thread); + break; + case TCP_STATE_ESTABLISHED: + tcp_ack_handler(tcp, tcp_header, net_buffer, length); + if (tcp_header->flags & TCP_FLAG_FIN) { + tcp->cur.seq = ack; + tcp->cur.ack = seq + 1; + tcp->state = TCP_STATE_CLOSE_WAIT; + tcp_ack(conn, tcp, extra_flags); + break; + } + break; + case TCP_STATE_CLOSING: + if (ack_flag && ack == tcp->cur.seq + 1) { + tcp->cur.seq = ack; + tcp->state = TCP_STATE_CLOSE_WAIT; + extra_flags |= TCP_FLAG_FIN; + } + tcp_ack(conn, tcp, extra_flags); + break; + case TCP_STATE_CLOSE_WAIT: + tcp_reset_conn(conn, tcp); + break; + case TCP_STATE_FIN_WAIT1: + if (ack_flag) tcp_ack_handler(tcp, tcp_header, net_buffer, length); + if (ack_flag && ack == tcp->cur.seq + 1) { + tcp->cur.seq = ack; + tcp->state = TCP_STATE_FIN_WAIT2; + extra_flags |= TCP_FLAG_FIN; + + timer_callback_cancel(&tcp->timeout_timer); + timer_set_timeout(&tcp->timeout_timer, tcp_fin_timeout * 1000); + timer_callback_enable(&tcp->timeout_timer); + } + if (tcp_header->flags & TCP_FLAG_FIN) { + tcp->cur.ack = seq + 1; + tcp->state = TCP_STATE_CLOSING; + } + break; + case TCP_STATE_FIN_WAIT2: + if (ack_flag) tcp_ack_handler(tcp, tcp_header, net_buffer, length); + if (tcp_header->flags & TCP_FLAG_FIN) { + tcp->cur.ack = seq + 1; + tcp->state = TCP_STATE_TIME_WAIT; + extra_flags |= TCP_FLAG_ACK; + + timer_callback_cancel(&tcp->timeout_timer); + timer_set_timeout(&tcp->timeout_timer, 2 * TCP_MSL * 1000); + timer_callback_enable(&tcp->timeout_timer); + tcp_ack(conn, tcp, extra_flags); + } + break; + case TCP_STATE_LAST_ACK: + if (ack_flag && ack == tcp->cur.seq + 1) { + tcp->cur.seq = ack; + tcp->state = TCP_STATE_CLOSED; + thread_unblock(tcp->thread); + } + break; + case TCP_STATE_TIME_WAIT: + tcp_reset_conn(conn, tcp); + break; + } +} + +ProtocolResult tcp_recv( + NetBuffer *net_buffer, int length, uint8_t *src_ip, uint8_t *dst_ip, + int ip_len) { + TcpHeader *tcp_header = (TcpHeader *)net_buffer->data; + + int header_length = (tcp_header->data_offset >> 4) * 4; + if (header_length < sizeof(TcpHeader)) + return PROTO_ERROR_UNSUPPORT; // 数据包太小 + int data_length = length - header_length; + + uint16_t checksum = tcp_header->checksum; + uint16_t calc_checksum = + tcp_checksum(tcp_header, length, src_ip, dst_ip, ip_len); + if (HOST2BE_WORD(calc_checksum) != checksum) return PROTO_ERROR_CHECKSUM; + + net_buffer->data += header_length; + + if (list_empty(&tcp_lh)) { + // 没有绑定的连接 + goto drop; + } + Ipv4ConnInfo *info, *next; + spin_lock(&tcp_lock); + list_for_each_owner_safe (info, next, &tcp_lh, list) { + if (info->local.port == BE2HOST_WORD(tcp_header->dest_port) && + (info->remote.port == BE2HOST_WORD(tcp_header->src_port))) { + if (memcmp(info->local.ip, dst_ip, ip_len) == 0 && + memcmp(info->remote.ip, src_ip, ip_len) == 0) { + NetworkConnection *conn = + container_of(info, NetworkConnection, ipv4.conn_info); + tcp_rx_handler(conn, tcp_header, net_buffer, data_length); + + spin_unlock(&tcp_lock); + return PROTO_OK; + } + } + } + // 没有找到匹配的连接,丢弃数据包 +drop: + // TODO: 改成发送RST + kfree(net_buffer->ptr); + kfree(net_buffer); + return PROTO_DROP; +} diff --git a/src/driver/network/protocols/udp.c b/src/driver/network/protocols/udp.c index fdf04b2..9376aa3 100644 --- a/src/driver/network/protocols/udp.c +++ b/src/driver/network/protocols/udp.c @@ -88,7 +88,7 @@ void udp_set_callback( } void udp_wrap(NetworkConnection *conn, uint16_t src_port, uint16_t dst_port) { - uint16_t size = CONN_CONTENT_SIZE(conn); + uint16_t size = CONN_PACKET_SIZE(conn); net_buffer_header_alloc(conn_buffer(conn), sizeof(UdpHeader)); UdpHeader *udp_header = (UdpHeader *)conn_buffer(conn)->head; udp_header->src_port = HOST2BE_WORD(src_port); diff --git a/src/include/driver/network/conn.h b/src/include/driver/network/conn.h index e5debd3..d2d194b 100644 --- a/src/include/driver/network/conn.h +++ b/src/include/driver/network/conn.h @@ -15,7 +15,8 @@ #define NET_CONN_MAX_PROTOCOLS 8 -#define CONN_CONTENT_SIZE(conn) ((conn)->buffer->tail - (conn)->buffer->head) +#define CONN_PACKET_SIZE(conn) ((conn)->buffer->tail - (conn)->buffer->head) +#define CONN_CONTENT_SIZE(conn) ((conn)->buffer->tail - (conn)->buffer->data) #define conn_buffer(conn) ((conn)->buffer) @@ -25,6 +26,7 @@ typedef struct NetProtocol { uint16_t tail_size; } NetProtocol; +struct Tcp; typedef struct NetworkConnection { Object *object; ObjectHandle *handle; @@ -60,16 +62,13 @@ typedef struct NetworkConnection { union { struct { uint16_t id; - uint8_t ip[4]; // IPv4地址 struct { uint16_t enable_fragment : 1; uint16_t last_fragment : 1; uint16_t frag_offset : 13; } fragment; + Ipv4Header *header; struct Ipv4ConnInfo conn_info; // 连接信息 - - uint8_t subnet_mask[4]; - uint8_t gateway_ip[4]; } ipv4; }; @@ -85,12 +84,23 @@ typedef struct NetworkConnection { void (*callback)( struct NetworkConnection *conn, NetBuffer *net_buffer); } udp; + struct { + struct Tcp *info; + } tcp; }; spinlock_t recv_lock; list_t recv_lh; } NetworkConnection; +typedef enum ProtocolLevel { + PROTO_LEVEL_TRANSPORT, + PROTO_LEVEL_NETWORK, + PROTO_LEVEL_DATA_LINK, + PROTO_LEVEL_PHYSICAL +} ProtocolLevel; + NetworkConnection *net_create_conn(Object *object); void net_destroy_conn(NetworkConnection *conn); +ProtocolResult conn_wrap(NetworkConnection *conn, ProtocolLevel level); #endif \ No newline at end of file diff --git a/src/include/driver/network/network_dm.h b/src/include/driver/network/network_dm.h index 571897d..5f39df4 100644 --- a/src/include/driver/network/network_dm.h +++ b/src/include/driver/network/network_dm.h @@ -39,6 +39,7 @@ typedef struct NetworkDevice { uint16_t head_size; uint16_t tail_size; + int mtu; NetworkDeviceState state; NetworkQueue tx_queue; @@ -51,7 +52,12 @@ typedef struct NetworkDevice { }; union { - uint8_t ipv4_addr[4]; + struct { + uint8_t ip[4]; + + uint8_t subnet_mask[4]; + uint8_t gateway_ip[4]; + } ipv4; }; } NetworkDevice; diff --git a/src/include/driver/network/protocols/ipv4.h b/src/include/driver/network/protocols/ipv4.h index e60bb33..9bc2bad 100644 --- a/src/include/driver/network/protocols/ipv4.h +++ b/src/include/driver/network/protocols/ipv4.h @@ -10,6 +10,9 @@ #define IP_PROTO_TCP 6 #define IP_PROTO_UDP 17 +#define CONN_LOCAL_IP(conn) conn->ipv4.conn_info.local.ip +#define CONN_REMOTE_IP(conn) conn->ipv4.conn_info.remote.ip + typedef struct Ipv4Header { uint8_t ver_len; // Version and Internet Header Length uint8_t tos; // Type of Service @@ -30,9 +33,9 @@ typedef struct Ipv4Endpoint { } Ipv4Endpoint; typedef struct Ipv4ConnInfo { - list_t list; Ipv4Endpoint local; // 本地IP和端口 Ipv4Endpoint remote; // 远程IP和端口 + list_t list; } Ipv4ConnInfo; extern const uint32_t ipv4_broadcast_addr; @@ -45,7 +48,11 @@ void ipv4_enable_fragment(struct NetworkConnection *conn); ProtocolResult ipv4_wrap( struct NetworkConnection *conn, uint16_t protocol, uint8_t *dst_ip, uint8_t ttl); +void ipv4_rewrap(struct NetworkConnection *conn); ProtocolResult ipv4_recv(struct NetBuffer *net_buffer); NeighbourKey ipv4_hash(uint8_t ip[4]); +ProtocolResult ipv4_lookup_mac( + NetworkDevice *device, uint8_t ip[4], uint8_t mac[8]); +uint16_t ipv4_get_packet_length(Ipv4Header *ipv4_header); #endif \ No newline at end of file diff --git a/src/include/driver/network/protocols/protocols.h b/src/include/driver/network/protocols/protocols.h index 453fd2a..e786760 100644 --- a/src/include/driver/network/protocols/protocols.h +++ b/src/include/driver/network/protocols/protocols.h @@ -10,7 +10,12 @@ typedef enum { PROTO_ERROR_EXCEED_MAX_SIZE, PROTO_ERROR_NULL_PTR, PROTO_ERROR_CHECKSUM, + PROTO_ERROR_CONNECT_FAILED, PROTO_ERROR_SEND_FAILED, + PROTO_ERROR_REBIND, + PROTO_ERROR_PORT_CONFLICT, + PROTO_ERROR_CANNOT_FIND, + PROTO_ERROR_NO_SPACE_LEFT, PROTO_ERROR_OTHER, } ProtocolResult; diff --git a/src/include/driver/network/protocols/tcp.h b/src/include/driver/network/protocols/tcp.h new file mode 100644 index 0000000..1d10f03 --- /dev/null +++ b/src/include/driver/network/protocols/tcp.h @@ -0,0 +1,174 @@ +#ifndef _TCP_H +#define _TCP_H + +#include "driver/network/conn.h" +#include +#include + +#define TCP_FLAG_FIN 0x01 +#define TCP_FLAG_SYN 0x02 +#define TCP_FLAG_RST 0x04 +#define TCP_FLAG_PSH 0x08 +#define TCP_FLAG_ACK 0x10 +#define TCP_FLAG_URG 0x20 + +#define TCP_OPTION_END 0 +#define TCP_OPTION_NOP 1 +#define TCP_OPTION_MSS 2 + +#define TCP_SHUT_WR 0 +#define TCP_SHUT_RD 1 +#define TCP_SHUT_RDWR 2 + +#define TCP_MSL 120 + +typedef struct { + uint16_t src_port; + uint16_t dest_port; + uint32_t seq; + uint32_t ack; + uint8_t data_offset; + uint8_t flags; + uint16_t window_size; + uint16_t checksum; + uint16_t urgent_pointer; + uint8_t options[0]; +} TcpHeader; + +// +---------+ ---------\ active OPEN +// | CLOSED | \ ----------- +// +---------+<---------\ \ create TCB +// | ^ \ \ snd SYN +// passive OPEN | | CLOSE \ \. +// ------------ | | ---------- \ \. +// create TCB | | delete TCB \ \. +// V | \ \. +// +---------+ CLOSE | \. +// | LISTEN | ---------- | | +// +---------+ delete TCB | | +// rcv SYN | | SEND | | +// ----------- | | ------- | V +// +---------+ snd SYN,ACK / \ snd SYN +---------+ +// | |<----------------- ------------------>| | +// | SYN | rcv SYN | SYN | +// | RCVD |<-----------------------------------------------| SENT | +// | | snd ACK | | +// | |------------------ -------------------| | +// +---------+ rcv ACK of SYN \ / rcv SYN,ACK +---------+ +// | -------------- | | ----------- +// | x | | snd ACK +// | V V +// | CLOSE +---------+ +// | ------- | ESTAB | +// | snd FIN +---------+ +// | CLOSE | | rcv FIN +// V ------- | | ------- +// +---------+ snd FIN / \ snd ACK +---------+ +// | FIN |<----------------- ------------------>| CLOSE | +// | WAIT-1 |------------------ | WAIT | +// +---------+ rcv FIN \ +---------+ +// | rcv ACK of FIN ------- | CLOSE | +// | -------------- snd ACK | ------- | +// V x V snd FIN V +// +---------+ +---------+ +---------+ +// |FINWAIT-2| | CLOSING | | LAST-ACK| +// +---------+ +---------+ +---------+ +// | rcv ACK of FIN | rcv ACK of FIN | +// | rcv FIN -------------- | Timeout=2MSL -------------- | +// | ------- x V ------------ x V +// \ snd ACK +---------+delete TCB +---------+ +// ------------------------>|TIME WAIT|------------------>| CLOSED | +// +---------+ +---------+ +typedef enum { + TCP_STATE_LISTEN, + TCP_STATE_SYN_SENT, + TCP_STATE_SYN_RECEIVED, + TCP_STATE_ESTABLISHED, + TCP_STATE_FIN_WAIT1, + TCP_STATE_FIN_WAIT2, + TCP_STATE_CLOSE_WAIT, + TCP_STATE_CLOSING, + TCP_STATE_LAST_ACK, + TCP_STATE_TIME_WAIT, + TCP_STATE_CLOSED, +} TcpState; + +typedef struct Tcp { + NetworkConnection *conn; + TcpState state; + TcpHeader *header; + int header_size; + int mss; + + struct task_s *thread; + + // Send Sequence Space + // 1 2 3 4 + // ----------|----------|----------|---------- + // SND.UNA SND.NXT SND.UNA + // +SND.WND + + // 1 - old sequence numbers which have been acknowledged + // 2 - sequence numbers of unacknowledged data + // 3 - sequence numbers allowed for new data transmission + // 4 - future sequence numbers which are not yet allowed + struct { + uint32_t unack; // send unacknowledged + uint32_t next; // send next + uint32_t window; // send window + uint32_t urg_p; // send urgent pointer + uint32_t wl1; // segment sequence number used for last window update + uint32_t + wl2; // segment acknowledgment number used for last window update + uint32_t iss; // initial send sequence number + uint32_t total_size; + + uint32_t remote_window_size; + } send; + uint8_t *send_window; + // Receive Sequence Space + // 1 2 3 + // ----------|----------|---------- + // RCV.NXT RCV.NXT + // +RCV.WND + + // 1 - old sequence numbers which have been acknowledged + // 2 - sequence numbers allowed for new reception + // 3 - future sequence numbers which are not yet allowed + struct { + uint32_t next; // receive next + uint32_t window; // receive window + uint32_t urg_p; // receive urgent pointer + uint32_t irs; // initial receive sequence number + uint32_t total_size; + + uint32_t read; + } recv; + uint8_t *recv_window; + + struct { + uint32_t seq; // segment sequence number + uint32_t ack; // segment acknowledgment number + uint32_t len; // segment length + uint32_t window; // segment window + uint32_t urg_p; // segment urgent pointer + uint32_t prc; // segment precedence value + } cur; + + int rtt, srtt, rto; + int retry_times; + Timer timeout_timer; +} Tcp; + +void tcp_register(NetworkConnection *conn); +ProtocolResult tcp_bind(NetworkConnection *conn, uint16_t port); +ProtocolResult tcp_connect( + NetworkConnection *conn, uint8_t *dst_ip, uint16_t dst_port); +ProtocolResult tcp_send_data(NetworkConnection *conn, uint8_t *buf, int length); +void tcp_reset(NetworkConnection *conn); +ProtocolResult tcp_shutdown(NetworkConnection *conn, uint8_t how); +ProtocolResult tcp_recv( + NetBuffer *net_buffer, int length, uint8_t *src_ip, uint8_t *dst_ip, + int ip_len); + +#endif \ No newline at end of file From 61d3f5cd5391c8832632c5c6b06d8c1a5d0132ce Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 5 Sep 2025 23:50:11 +0800 Subject: [PATCH 093/158] =?UTF-8?q?script:=20=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=88=86=E6=9E=90=E5=B9=B6=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E7=9A=84grub=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 4 +- tools/grub/grub_dep_detect.py | 85 +++++++++++++++++++ install_grub.py => tools/grub/install_grub.py | 26 +++--- 3 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 tools/grub/grub_dep_detect.py rename install_grub.py => tools/grub/install_grub.py (82%) diff --git a/Makefile b/Makefile index f10f0e2..eed9a11 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,8 @@ KERNEL_ELF = $(KERNEL_SRC)/kernel.elf IMAGETOOL = $(TOOL_SRC)/bin/imagetool +INSTALL_GRUB_SCRIPT = $(TOOL_SRC)/grub/install_grub.py + .PHONY: cld cld: kernel libs @@ -61,7 +63,7 @@ run: kernel libs qemu run_dbg: kernel libs qemu_dbg hd: tool - $(PYTHON) ./install_grub.py \ + $(PYTHON) $(INSTALL_GRUB_SCRIPT) \ --image $(HD_IMG) \ --fs fat32 \ --platform $(TARGET_PLATFORM) diff --git a/tools/grub/grub_dep_detect.py b/tools/grub/grub_dep_detect.py new file mode 100644 index 0000000..c5270a0 --- /dev/null +++ b/tools/grub/grub_dep_detect.py @@ -0,0 +1,85 @@ +import os +from collections import deque + +class GrubModDependencyResolver: + def __init__(self, mod_dir): + self.mod_dir = mod_dir + self.dep_map = {} + + def _read_deps_from_elf(self, path): + with open(path, 'rb') as f: + magic = f.read(4) + if magic != b'\x7fELF': + print("Not an ELF file:", path) + return [] + byte_len = f.read(1) + if byte_len == b'\x01': + byte_len = 4 + elif byte_len == b'\x02': + byte_len = 8 + else: + print("Unknown ELF class:", path) + return [] + endian = f.read(1) + if endian == b'\x01': + is_little = True + elif endian == b'\x02': + is_little = False + else: + print("Unknown ELF endianness:", path) + return [] + f.seek(24 + byte_len * 2) + shoff = int.from_bytes(f.read(4), 'little' if is_little else 'big') + f.seek(10, os.SEEK_CUR) + shentsize = int.from_bytes(f.read(2), 'little' if is_little else 'big') + shnum = int.from_bytes(f.read(2), 'little' if is_little else 'big') + shstrndx = int.from_bytes(f.read(2), 'little' if is_little else 'big') + + f.seek(shoff + shentsize * shstrndx + 12 + byte_len) + shstroff = int.from_bytes(f.read(byte_len), 'little' if is_little else 'big') + + for _ in range(shnum): + f.seek(shoff) + sh_name_index = int.from_bytes(f.read(4), 'little' if is_little else 'big') + f.seek(shstroff + sh_name_index) + name = f.read(8) + if name == b'.moddeps': + f.seek(shoff + 12 + byte_len) + sh_offset = int.from_bytes(f.read(byte_len), 'little' if is_little else 'big') + sh_size = int.from_bytes(f.read(4), 'little' if is_little else 'big') + f.seek(sh_offset) + data = f.read(sh_size) + return [d.decode('utf-8') for d in data.split(b'\x00') if d] + f.seek(shoff + 12 + byte_len) + sh_offset = int.from_bytes(f.read(byte_len), 'little' if is_little else 'big') + sh_size = int.from_bytes(f.read(4), 'little' if is_little else 'big') + shoff += shentsize + + return [] + + def resolve_dependencies(self, mods = []): + all_deps = set(mods) + queue = deque(mods if isinstance(mods, list) else [mods]) + while queue: + mod = queue.popleft() + if mod not in all_deps: + all_deps.add(mod) + deps = self._read_deps_from_elf(os.path.join(self.mod_dir, mod + '.mod')) + for dep in deps: + if dep not in all_deps: + queue.append(dep) + all_deps.add(dep) + return list(all_deps) + +if __name__ == "__main__": + import sys + if len(sys.argv) < 3: + print("Usage: python grub_dep_detect.py [ ...]") + sys.exit(1) + + mod_dir = sys.argv[1] + mods = sys.argv[2:] + + resolver = GrubModDependencyResolver(mod_dir) + all_deps = resolver.resolve_dependencies(mods) + print("All dependencies:", all_deps) \ No newline at end of file diff --git a/install_grub.py b/tools/grub/install_grub.py similarity index 82% rename from install_grub.py rename to tools/grub/install_grub.py index 335aac7..bbd75b0 100644 --- a/install_grub.py +++ b/tools/grub/install_grub.py @@ -3,9 +3,10 @@ import shutil import struct import argparse +from grub_dep_detect import GrubModDependencyResolver # 定义变量 -imagetool_path = '\"tools/bin/imagetool\"' +imagetool_path = os.path.join('tools', 'bin', 'imagetool') hd_img_path = 'hd0.img' hd_size = '64M' embed_area_size = '1M' @@ -14,19 +15,16 @@ disk_dir_path = 'disk' grub_cfg_path = 'grub.cfg' prefix_path = "/boot/grub/" -if os.uname().sysname == "Darwin": +if os.name == "Darwin": grub_mkimage_path = "x86_64-elf-grub-mkimage" else: grub_mkimage_path = "grub-mkimage" default_mods =\ -"minicmd normal gzio gcry_crc verifiers terminal \ -priority_queue gettext extcmd datetime crypto bufio boot \ -biosdisk part_gpt part_msdos fat ext2 fshelp net multiboot2 \ -all_video gfxterm" +"normal biosdisk part_gpt part_msdos fat ext2 multiboot2 all_video" def run_command(command, hide=False): if not hide: - print("excute command: ", command) + print("execute command: ", command) subprocess.run(command, shell=True, text=True, check=True) def write_boot_sector(image_path, boot_img_path): @@ -73,9 +71,9 @@ def install_grub(disk_image_path, grub_dir_path, platform, fs, mods): # 检查 boot.img 是否存在 if not os.path.isfile(boot_img_path): # 复制 boot.img - grub_dir_path += platform + "/" - if not os.path.isfile(grub_dir_path + 'boot.img'): - print(f"{grub_dir_path}boot.img不存在,请检查") + _grub_dir_path = os.path.join(grub_dir_path, platform) + if not os.path.isfile(os.path.join(_grub_dir_path, 'boot.img')): + print(f"{_grub_dir_path}boot.img不存在,请检查") return shutil.copy(os.path.join(grub_dir_path, 'boot.img'), boot_img_path) @@ -84,7 +82,9 @@ def install_grub(disk_image_path, grub_dir_path, platform, fs, mods): if fs[0:3] == "fat": prefix_device += "msdos1" prefix_device += ')' - run_command(f"{grub_mkimage_path} -O {platform} -o {core_image_path} --prefix \"{prefix_device + prefix_path}\" {mods}") + resolver = GrubModDependencyResolver(os.path.join(grub_dir_path, platform)) + all_deps = " ".join(resolver.resolve_dependencies(mods.split())) + run_command(f"{grub_mkimage_path} -O {platform} -o {core_image_path} --prefix \"{prefix_device + prefix_path}\" {all_deps}") # 写入引导扇区 write_boot_sector(disk_image_path, boot_img_path) @@ -107,9 +107,7 @@ def install_grub(disk_image_path, grub_dir_path, platform, fs, mods): if os.name == 'nt': print("检测到为Windows,请输入grub路径:") path = input() - if path[-1] != '/': - path += '/' grub_dir_path = path - grub_mkimage_path = path + grub_mkimage_path + grub_mkimage_path = os.path.join(grub_dir_path, "grub-mkimage") install_grub(args.image, grub_dir_path, args.platform, args.fs, args.mods) From 70306588eef974a119241e4cc1e5ad4642666168 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 6 Sep 2025 01:53:34 +0800 Subject: [PATCH 094/158] =?UTF-8?q?script:=20=E6=96=B0=E5=A2=9E=20install?= =?UTF-8?q?=5Fgrub.py=E5=AF=B9=E4=BA=8E=E4=BA=A4=E5=8F=89=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E9=93=BE=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/grub/install_grub.py | 54 +++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/tools/grub/install_grub.py b/tools/grub/install_grub.py index bbd75b0..54ed343 100644 --- a/tools/grub/install_grub.py +++ b/tools/grub/install_grub.py @@ -15,10 +15,9 @@ disk_dir_path = 'disk' grub_cfg_path = 'grub.cfg' prefix_path = "/boot/grub/" -if os.name == "Darwin": - grub_mkimage_path = "x86_64-elf-grub-mkimage" -else: - grub_mkimage_path = "grub-mkimage" +cross_prefix = "" +default_grub_dir = "/usr/lib/grub/" +grub_mkimage_path = "" default_mods =\ "normal biosdisk part_gpt part_msdos fat ext2 multiboot2 all_video" @@ -101,13 +100,48 @@ def install_grub(disk_image_path, grub_dir_path, platform, fs, mods): parser.add_argument("--platform", help="目标平台", required=True) parser.add_argument("--fs", help="文件系统", required=True) parser.add_argument("--mods", help="要额外附加的模块", default=default_mods) + parser.add_argument("--grub-dir", help=f"GRUB平台目录(如{default_grub_dir})", default=default_grub_dir) + parser.add_argument("--grub-mkimage", help="grub-mkimage路径") args = parser.parse_args() - grub_dir_path = "/usr/lib/grub/" - if os.name == 'nt': - print("检测到为Windows,请输入grub路径:") - path = input() - grub_dir_path = path - grub_mkimage_path = os.path.join(grub_dir_path, "grub-mkimage") + grub_mkimage_path = "grub-mkimage" + if args.grub_dir == None: + # 使用了默认设置,检查一下 + if os.name == "Darwin": + if args.grub_mkimage == None: + if args.platform == "i386-pc": + cross_prefix = "i686-elf-" + elif args.platform == "x86_64-efi": + cross_prefix = "x86_64-elf-" + grub_mkimage_path = cross_prefix + grub_mkimage_path + + def get_brew_prefix(): + try: + result = subprocess.run(['brew', '--prefix', cross_prefix + 'grub'], capture_output=True, text=True, check=True) + return result.stdout.strip() + except subprocess.CalledProcessError: + print("Error: Unable to get Homebrew prefix. Make sure Homebrew is installed.") + exit(1) + brew_prefix = get_brew_prefix() + + versions = sorted(os.listdir(brew_prefix)) + latest_version = versions[-1] + grub_dir_path = os.path.join(brew_prefix, latest_version, 'lib', cross_prefix[:-1], 'grub') + grub_mkimage_path = cross_prefix + grub_mkimage_path + elif os.name == "nt": + print("检测到为Windows,请输入grub路径:") + path = input() + grub_dir_path = path + if args.grub_mkimage == None: + grub_mkimage_path = cross_prefix + grub_mkimage_path + grub_mkimage_path = os.path.join(grub_dir_path, grub_mkimage_path) + else: + grub_mkimage_path = args.grub_mkimage + else: + if args.grub_mkimage != None: + grub_mkimage_path = args.grub_mkimage + else: + if args.grub_mkimage != None: + grub_mkimage_path = args.grub_mkimage install_grub(args.image, grub_dir_path, args.platform, args.fs, args.mods) From 0ad3a865d815d69f357206fd877156f56477e3c4 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 6 Sep 2025 16:25:10 +0800 Subject: [PATCH 095/158] =?UTF-8?q?doc:=20=E6=96=B0=E5=A2=9E=20Grub?= =?UTF-8?q?=E5=AE=89=E8=A3=85=E8=AF=B4=E6=98=8E=E5=8F=8A=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E6=94=AF=E6=8C=81=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ad6092..3876d78 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,28 @@ - python(3.12.3) - rust:[Install Rust - Rust Programming Language(rust-lang.org)](https://www.rust-lang.org/tools/install) +### Grub + +在虚拟机中运行使用grub引导,所以需要先安装grub + +#### Windows + +使用Windows需要先下载 [Grub for Windows (2.12)](https://ftp.gnu.org/gnu/grub/grub-2.12-for-windows.zip) 并解压,在执行安装脚本时会提示输入grub路径 + +#### macOS + +使用macOS需要使用homebrew安装i686-elf-grub + +``` +brew install i686-elf-grub +``` + +#### Linux + +大多数Linux发行版默认使用grub引导,`install_grub.py`脚本可以自动从`/usr/lib/grub`找到模块目录 + +如果不是或者使用的并非x86 pc,需要自行安装grub + ### VSCode 需要安装的插件: @@ -44,7 +66,7 @@ > > qemu 7.1开始不再支持-soundhw, > -> qemu 7.1之前的版本要把Makefile中的 +> qemu 7.1之前的版本要把 > ``` > -audio pa,model=sb16 > ``` From cd87b03852fc58b9f1db4bed0d95da33c35b6064 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 11 Sep 2025 14:19:34 +0800 Subject: [PATCH 096/158] =?UTF-8?q?tcp:=20tcp=5Fshutdown=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E4=BB=85=E5=85=B3=E9=97=AD=E8=AF=BB=E3=80=81=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E8=AF=BB=E5=86=99=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/protocols/tcp.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/driver/network/protocols/tcp.c b/src/driver/network/protocols/tcp.c index 469ad42..6596416 100644 --- a/src/driver/network/protocols/tcp.c +++ b/src/driver/network/protocols/tcp.c @@ -306,11 +306,16 @@ ProtocolResult tcp_shutdown(NetworkConnection *conn, uint8_t how) { switch (how) { case TCP_SHUT_RD: + kfree(tcp->recv_window); + tcp->recv_window = NULL; break; case TCP_SHUT_WR: tcp_half_close(conn, tcp); break; case TCP_SHUT_RDWR: + kfree(tcp->recv_window); + tcp->recv_window = NULL; + tcp_half_close(conn, tcp); break; default: return PROTO_ERROR_UNSUPPORT; @@ -391,10 +396,10 @@ void tcp_ack_handler( tcp->recv.next += length; tcp->recv.next %= tcp->recv.total_size; tcp->recv.window -= length; - tcp->send.wl1 = seq; } - tcp->cur.ack = seq + length; + tcp->send.wl1 = seq; + tcp->cur.ack = seq + length; tcp_ack(tcp->conn, tcp, 0); } From 8ce2e25e9db6b3dfb88bdd76f3aca7f0c418b9d4 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 11 Sep 2025 14:38:09 +0800 Subject: [PATCH 097/158] =?UTF-8?q?tcp:=20=E6=96=B0=E5=A2=9Ertt=E6=B5=8B?= =?UTF-8?q?=E9=87=8F=E4=B8=8Erto=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/protocols/tcp.c | 51 ++++++++++++++-------- src/include/driver/network/protocols/tcp.h | 9 ++-- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/driver/network/protocols/tcp.c b/src/driver/network/protocols/tcp.c index 6596416..5c31a95 100644 --- a/src/driver/network/protocols/tcp.c +++ b/src/driver/network/protocols/tcp.c @@ -41,7 +41,7 @@ const int max_ephemeral_port = 65535; const int tcp_max_retries = 15; -const int tcp_fin_timeout = 60; +const int tcp_fin_timeout = 60 * 1000; void tcp_timeout_handler(void *arg); void tcp_reset_conn(NetworkConnection *conn, Tcp *tcp); @@ -106,23 +106,23 @@ void tcp_compute_retransmission_timer(Tcp *tcp, int r) { if (tcp == NULL) return; if (r == 0) { - if (tcp->rtt == 0) { + if (tcp->rttvar == 0) { // 还没完成RTT测量 - tcp->rto = 1; + tcp->rto = 1 * 1000; } } else { - if (tcp->rtt == 0) { + if (tcp->rttvar == 0) { // 完成初次RTT测量 - tcp->srtt = r; - tcp->rtt = r / 2; - tcp->rto = tcp->srtt + MAX(1, 4 * tcp->rtt); + tcp->srtt = r; + tcp->rttvar = r / 2; + tcp->rto = tcp->srtt + MAX(1 * 1000, 4 * tcp->rttvar); } else { // 完成后续RTT测量 - tcp->rtt = (3 * tcp->rtt + 1 * abs(tcp->srtt - r)) / 4; - tcp->srtt = (7 * tcp->srtt + 1 * r) / 8; - tcp->rto = tcp->srtt + MAX(1, 4 * tcp->rtt); + tcp->rttvar = (3 * tcp->rttvar + 1 * abs(tcp->srtt - r)) / 4; + tcp->srtt = (7 * tcp->srtt + 1 * r) / 8; + tcp->rto = tcp->srtt + MAX(1 * 1000, 4 * tcp->rttvar); } - tcp->rto = MIN(tcp->rto, 60); // 最长1分钟 + tcp->rto = MIN(tcp->rto, 60 * 1000); // 最长1分钟 } } @@ -152,7 +152,7 @@ ProtocolResult tcp_bind(NetworkConnection *conn, uint16_t port) { tcp->recv.window = recv_win_default_size; tcp->recv.total_size = recv_win_default_size; tcp->recv.read = 0; - tcp->rtt = tcp->rto = tcp->srtt = 0; + tcp->rttvar = tcp->rto = tcp->srtt = 0; tcp_compute_retransmission_timer(tcp, 0); timer_init(&tcp->timeout_timer); tcp->timeout_timer.callback = tcp_timeout_handler; @@ -211,7 +211,8 @@ ProtocolResult tcp_connect( tcp->state = TCP_STATE_SYN_SENT; - timer_set_timeout(&tcp->timeout_timer, tcp->rto * 1000); + timer_set_timeout( + &tcp->timeout_timer, timer_count_ms(&tcp->timeout_timer, tcp->rto)); timer_callback_enable(&tcp->timeout_timer); NETWORK_SEND(conn->net_device, conn); @@ -227,6 +228,7 @@ ProtocolResult tcp_connect( tcp->send.total_size = send_win_default_size; tcp->send.window = MIN(tcp->send.total_size, tcp->send.remote_window_size); tcp->send_window = kmalloc(tcp->send.total_size); + tcp->send_time = timer_get_counter(); return PROTO_OK; } @@ -359,9 +361,14 @@ void tcp_send(Tcp *tcp, NetworkConnection *conn, bool set_timer) { conn->ipv4.conn_info.local.ip, conn->ipv4.conn_info.remote.ip, 4); tcp_header->checksum = HOST2BE_WORD(tcp_header->checksum); + if (tcp->send_time == 0) { + tcp->send_time = timer_get_counter(); + tcp->send_seq = tcp->cur.seq; + } // 如果没有设置重传计时则设置一个 if (set_timer && timer_is_timeout(&tcp->timeout_timer)) { - timer_set_timeout(&tcp->timeout_timer, tcp->rto * 1000); + timer_set_timeout( + &tcp->timeout_timer, timer_count_ms(&tcp->timeout_timer, tcp->rto)); timer_callback_enable(&tcp->timeout_timer); } ipv4_rewrap(conn); @@ -385,6 +392,11 @@ void tcp_ack_handler( uint32_t ack = BE2HOST_DWORD(header->ack); if (length > 0) { + if (ack >= tcp->send_seq && tcp->send_seq != 0) { + int rtt = timer_get_counter() - tcp->send_time; + tcp_compute_retransmission_timer(tcp, rtt); + tcp->send_seq = 0; + } if (tcp->recv_window != NULL) { int size1 = MIN(tcp->recv.total_size - tcp->recv.next, length); // size2 = min(length - size1, tcp->recv.window - size1) @@ -430,7 +442,9 @@ void tcp_timeout_handler(void *arg) { if (tcp->state == TCP_STATE_SYN_SENT || tcp->state == TCP_STATE_SYN_RECEIVED) tcp->rto = MIN(tcp->rto, 3); - timer_set_timeout(&tcp->timeout_timer, tcp->rto * 1000); + timer_set_timeout( + &tcp->timeout_timer, + timer_count_ms(&tcp->timeout_timer, tcp->rto)); timer_callback_enable(&tcp->timeout_timer); tcp_send(tcp, tcp->conn, true); } else { @@ -534,7 +548,9 @@ void tcp_rx_handler( extra_flags |= TCP_FLAG_FIN; timer_callback_cancel(&tcp->timeout_timer); - timer_set_timeout(&tcp->timeout_timer, tcp_fin_timeout * 1000); + timer_set_timeout( + &tcp->timeout_timer, + timer_count_ms(&tcp->timeout_timer, tcp_fin_timeout)); timer_callback_enable(&tcp->timeout_timer); } if (tcp_header->flags & TCP_FLAG_FIN) { @@ -550,7 +566,8 @@ void tcp_rx_handler( extra_flags |= TCP_FLAG_ACK; timer_callback_cancel(&tcp->timeout_timer); - timer_set_timeout(&tcp->timeout_timer, 2 * TCP_MSL * 1000); + uint32_t count = timer_count_ms(&tcp->timeout_timer, 2 * TCP_MSL); + timer_set_timeout(&tcp->timeout_timer, count); timer_callback_enable(&tcp->timeout_timer); tcp_ack(conn, tcp, extra_flags); } diff --git a/src/include/driver/network/protocols/tcp.h b/src/include/driver/network/protocols/tcp.h index 1d10f03..8858a24 100644 --- a/src/include/driver/network/protocols/tcp.h +++ b/src/include/driver/network/protocols/tcp.h @@ -20,7 +20,7 @@ #define TCP_SHUT_RD 1 #define TCP_SHUT_RDWR 2 -#define TCP_MSL 120 +#define TCP_MSL 120 * 1000 typedef struct { uint16_t src_port; @@ -155,9 +155,10 @@ typedef struct Tcp { uint32_t prc; // segment precedence value } cur; - int rtt, srtt, rto; - int retry_times; - Timer timeout_timer; + uint32_t send_time, send_seq; + int rttvar, srtt, rto; + int retry_times; + Timer timeout_timer; } Tcp; void tcp_register(NetworkConnection *conn); From 14c77c5c3d67afa7db99f885fd5215b0eccb5e14 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 11 Sep 2025 22:01:13 +0800 Subject: [PATCH 098/158] =?UTF-8?q?tcp:=20=E6=96=B0=E5=A2=9E=20MSS?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/ethernet/ethernet.c | 1 + src/driver/network/protocols/tcp.c | 81 ++++++++++++++++--- src/include/driver/network/conn.h | 1 + .../driver/network/ethernet/ethernet.h | 2 + src/include/driver/network/protocols/ipv4.h | 2 + src/include/driver/network/protocols/tcp.h | 7 +- 6 files changed, 81 insertions(+), 13 deletions(-) diff --git a/src/driver/network/ethernet/ethernet.c b/src/driver/network/ethernet/ethernet.c index 0a98245..db4aa5b 100644 --- a/src/driver/network/ethernet/ethernet.c +++ b/src/driver/network/ethernet/ethernet.c @@ -43,6 +43,7 @@ void eth_register(NetworkConnection *conn) { EthernetDevice *eth_device = conn->net_device->ethernet; conn->phy_protocol = PHY_PROTO_ETHERNET; eth_get_mac_address(eth_device, conn->ethernet.mac); + conn->mtu = ETH_MTU; NET_BUF_RESV_HEAD(conn, 14); } diff --git a/src/driver/network/protocols/tcp.c b/src/driver/network/protocols/tcp.c index 5c31a95..af67309 100644 --- a/src/driver/network/protocols/tcp.c +++ b/src/driver/network/protocols/tcp.c @@ -86,9 +86,7 @@ uint16_t tcp_checksum( void tcp_register(NetworkConnection *conn) { conn->trans_protocol = TRANS_PROTO_TCP; if (conn->tcp.info == NULL) { conn->tcp.info = kmalloc(sizeof(Tcp)); } - Tcp *tcp = conn->tcp.info; - tcp->header_size = sizeof(TcpHeader) + 4; - NET_BUF_RESV_HEAD(conn, tcp->header_size); + NET_BUF_RESV_HEAD(conn, sizeof(TcpHeader)); } uint32_t tcp_generate_isn(void *ip_port_pair, int len) { @@ -144,6 +142,7 @@ ProtocolResult tcp_bind(NetworkConnection *conn, uint16_t port) { conn_info->local.port = port; Tcp *tcp = conn->tcp.info; + tcp->mss = conn->mtu - sizeof(Ipv4Header) - sizeof(TcpHeader); tcp->cur.seq = 0; tcp->cur.ack = 0; tcp->state = TCP_STATE_CLOSED; @@ -191,21 +190,30 @@ ProtocolResult tcp_connect( tcp_generate_isn(&conn_info, sizeof(Ipv4ConnInfo) - sizeof(list_t)); tcp->cur.seq = tcp->send.iss; // 构造SYN报文 - net_buffer_header_alloc(conn->buffer, tcp->header_size); - tcp->header = (TcpHeader *)conn->buffer->head; + net_buffer_header_alloc(conn->buffer, sizeof(TcpHeader)); + tcp->header = (TcpHeader *)conn->buffer->head; + + int option_len = 4 /* Max Segment Size */; TcpHeader *header = tcp->header; header->src_port = HOST2BE_WORD(conn_info->local.port); header->dest_port = HOST2BE_WORD(conn_info->remote.port); header->seq = HOST2BE_DWORD(tcp->cur.seq); header->ack = 0; - header->data_offset = (tcp->header_size / 4) << 4; + header->data_offset = ((sizeof(TcpHeader) + option_len) / 4) << 4; header->flags = TCP_FLAG_SYN; header->window_size = HOST2BE_WORD(tcp->recv.window); header->urgent_pointer = 0; - header->checksum = 0; - header->checksum = HOST2BE_WORD(tcp_checksum( - header, tcp->header_size, conn_info->local.ip, conn_info->remote.ip, - 4)); + + // TCP Options算在NetBuffer的data区域内 + header->options[0] = TCP_OPTION_MSS; + header->options[1] = 4; + *(uint16_t *)(header->options + 2) = HOST2BE_WORD(tcp->mss); + net_buffer_put(conn->buffer, option_len); + + header->checksum = 0; + int length = sizeof(TcpHeader) + CONN_CONTENT_SIZE(conn); + header->checksum = HOST2BE_WORD(tcp_checksum( + header, length, conn_info->local.ip, conn_info->remote.ip, 4)); conn_wrap(conn, PROTO_LEVEL_NETWORK); @@ -342,7 +350,7 @@ void tcp_reset_conn(NetworkConnection *conn, Tcp *tcp) { tcp_header->flags = TCP_FLAG_RST; tcp_header->ack = 0; tcp_header->checksum = HOST2BE_WORD(tcp_checksum( - tcp_header, tcp->header_size, conn->ipv4.conn_info.local.ip, + tcp_header, sizeof(TcpHeader), conn->ipv4.conn_info.local.ip, conn->ipv4.conn_info.remote.ip, 4)); kfree(tcp->send_window); kfree(tcp->recv_window); @@ -355,9 +363,10 @@ void tcp_send(Tcp *tcp, NetworkConnection *conn, bool set_timer) { tcp_header->seq = HOST2BE_DWORD(tcp->cur.seq); tcp_header->ack = HOST2BE_DWORD(tcp->cur.ack); tcp_header->window_size = HOST2BE_WORD(tcp->recv.window); + tcp_header->data_offset = ((sizeof(TcpHeader)) >> 2) << 4; tcp_header->checksum = tcp_checksum( - tcp_header, CONN_CONTENT_SIZE(conn) + tcp->header_size, + tcp_header, CONN_CONTENT_SIZE(conn) + sizeof(TcpHeader), conn->ipv4.conn_info.local.ip, conn->ipv4.conn_info.remote.ip, 4); tcp_header->checksum = HOST2BE_WORD(tcp_header->checksum); @@ -466,6 +475,35 @@ void tcp_timeout_handler(void *arg) { } } +void tcp_options_handler( + TcpHeader *tcp_header, TcpOptionIndex indexes[TOI_MAX]) { + int options_size = + ((tcp_header->data_offset & 0xf0) >> 2) - sizeof(TcpHeader); + if (options_size <= 0) return; + + uint8_t *options = (uint8_t *)(tcp_header + 1); + int i = 0; + while (i < options_size) { + uint8_t kind = options[i]; + i++; + if (kind == TCP_OPTION_END) break; + else if (kind == TCP_OPTION_NOP) continue; + else { + if (i >= options_size) break; + uint8_t length = options[i]; + if (i + length - 1 > options_size) break; + switch (kind) { + case TCP_OPTION_MSS: + indexes[TOI_MSS] = i + 1; + break; + default: + break; + } + i += length - 1; + } + } +} + void tcp_rx_handler( NetworkConnection *conn, TcpHeader *tcp_header, NetBuffer *net_buffer, int length) { @@ -477,18 +515,28 @@ void tcp_rx_handler( uint8_t extra_flags = 0; if (tcp_header->flags & TCP_FLAG_RST) { tcp->state = TCP_STATE_CLOSED; } + + TcpOptionIndex indexes[TOI_MAX] = {TOI_MAX}; + tcp_options_handler(tcp_header, indexes); switch (tcp->state) { case TCP_STATE_CLOSED: tcp_reset_conn(conn, tcp); break; case TCP_STATE_LISTEN: if (syn_flag) { + if (indexes[TOI_MSS] < TOI_MAX) { + uint16_t mss = BE2HOST_WORD( + *(uint16_t *)(tcp_header->options + indexes[TOI_MSS])); + tcp->mss = MIN(mss, tcp->mss); + } + tcp->recv.irs = seq; tcp->cur.ack = seq + 1; tcp->send.remote_window_size = BE2HOST_WORD(tcp_header->window_size); tcp->state = TCP_STATE_SYN_RECEIVED; extra_flags |= TCP_FLAG_SYN; + net_buffer_clean_data(tcp->conn->buffer); tcp_ack(conn, tcp, extra_flags); } break; @@ -506,6 +554,11 @@ void tcp_rx_handler( tcp->state = TCP_STATE_SYN_RECEIVED; } case TCP_STATE_SYN_RECEIVED: + if (indexes[TOI_MSS] < TOI_MAX) { + uint16_t mss = BE2HOST_WORD( + *(uint16_t *)(tcp_header->options + indexes[TOI_MSS])); + tcp->mss = MIN(mss, tcp->mss); + } timer_callback_cancel(&tcp->timeout_timer); // 处理ACK if (ack != tcp->cur.seq + 1) { @@ -516,6 +569,7 @@ void tcp_rx_handler( tcp->cur.seq = ack; tcp->state = TCP_STATE_ESTABLISHED; } + net_buffer_clean_data(tcp->conn->buffer); tcp_ack(conn, tcp, extra_flags); thread_unblock(tcp->thread); break; @@ -525,6 +579,7 @@ void tcp_rx_handler( tcp->cur.seq = ack; tcp->cur.ack = seq + 1; tcp->state = TCP_STATE_CLOSE_WAIT; + net_buffer_clean_data(tcp->conn->buffer); tcp_ack(conn, tcp, extra_flags); break; } @@ -535,6 +590,7 @@ void tcp_rx_handler( tcp->state = TCP_STATE_CLOSE_WAIT; extra_flags |= TCP_FLAG_FIN; } + net_buffer_clean_data(tcp->conn->buffer); tcp_ack(conn, tcp, extra_flags); break; case TCP_STATE_CLOSE_WAIT: @@ -569,6 +625,7 @@ void tcp_rx_handler( uint32_t count = timer_count_ms(&tcp->timeout_timer, 2 * TCP_MSL); timer_set_timeout(&tcp->timeout_timer, count); timer_callback_enable(&tcp->timeout_timer); + net_buffer_clean_data(tcp->conn->buffer); tcp_ack(conn, tcp, extra_flags); } break; diff --git a/src/include/driver/network/conn.h b/src/include/driver/network/conn.h index d2d194b..c7cf67f 100644 --- a/src/include/driver/network/conn.h +++ b/src/include/driver/network/conn.h @@ -46,6 +46,7 @@ typedef struct NetworkConnection { uint8_t mac[6]; } ethernet; }; + int mtu; // data link layer protocol enum { diff --git a/src/include/driver/network/ethernet/ethernet.h b/src/include/driver/network/ethernet/ethernet.h index c2b9d43..81a6672 100644 --- a/src/include/driver/network/ethernet/ethernet.h +++ b/src/include/driver/network/ethernet/ethernet.h @@ -16,6 +16,8 @@ #define ETH_PROTO_TYPE_IPV4 0x0800 #define ETH_PROTO_TYPE_ARP 0x0806 +#define ETH_MTU 1500 + typedef struct EthernetHeader { uint8_t dst_mac[ETH_IDENTIFIER_SIZE]; uint8_t src_mac[ETH_IDENTIFIER_SIZE]; diff --git a/src/include/driver/network/protocols/ipv4.h b/src/include/driver/network/protocols/ipv4.h index 9bc2bad..0db0a76 100644 --- a/src/include/driver/network/protocols/ipv4.h +++ b/src/include/driver/network/protocols/ipv4.h @@ -10,6 +10,8 @@ #define IP_PROTO_TCP 6 #define IP_PROTO_UDP 17 +#define IPv4_DEFAULT_MSS 536 + #define CONN_LOCAL_IP(conn) conn->ipv4.conn_info.local.ip #define CONN_REMOTE_IP(conn) conn->ipv4.conn_info.remote.ip diff --git a/src/include/driver/network/protocols/tcp.h b/src/include/driver/network/protocols/tcp.h index 8858a24..0f4a05a 100644 --- a/src/include/driver/network/protocols/tcp.h +++ b/src/include/driver/network/protocols/tcp.h @@ -22,6 +22,7 @@ #define TCP_MSL 120 * 1000 +// TCP头部,options不算在头部内 typedef struct { uint16_t src_port; uint16_t dest_port; @@ -35,6 +36,11 @@ typedef struct { uint8_t options[0]; } TcpHeader; +typedef enum { + TOI_MSS = 0, + TOI_MAX, +} TcpOptionIndex; + // +---------+ ---------\ active OPEN // | CLOSED | \ ----------- // +---------+<---------\ \ create TCB @@ -97,7 +103,6 @@ typedef struct Tcp { NetworkConnection *conn; TcpState state; TcpHeader *header; - int header_size; int mss; struct task_s *thread; From b4dc9395fa78068da8b6575170887ae9eb4a9b52 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 11 Sep 2025 22:16:26 +0800 Subject: [PATCH 099/158] update .gitignore --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index fd0e92e..88b88e3 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,14 @@ Mkfile.old dkms.conf compile_commands.json +# Cache +__pycache__/ +*.pyc +.cache/ + +# Rubbish +.DS_Store + # Others /disk/ tools/bin/ From 2098dd2b48db1bd436eed55a66876d766603165c Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 11 Sep 2025 22:18:24 +0800 Subject: [PATCH 100/158] =?UTF-8?q?network&protocols:=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?network=E7=9B=AE=E5=BD=95=E7=BB=93=E6=9E=84=EF=BC=8C=E5=B0=86?= =?UTF-8?q?=E4=B8=8Eipv4=E7=9B=B8=E5=85=B3=E5=8D=8F=E8=AE=AE=E7=A7=BB?= =?UTF-8?q?=E5=88=B0ipv4/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/conn.c | 2 +- src/driver/network/ethernet/ethernet.c | 4 ++-- src/driver/network/neighbour.c | 2 +- src/driver/network/protocols/Makefile | 5 +---- src/driver/network/protocols/ipv4/Makefile | 4 ++++ src/driver/network/protocols/{ => ipv4}/acd.c | 6 +++--- src/driver/network/protocols/{ => ipv4}/arp.c | 4 ++-- src/driver/network/protocols/{ => ipv4}/dhcp.c | 6 +++--- src/driver/network/protocols/{ => ipv4}/ipv4.c | 2 +- src/driver/network/protocols/tcp.c | 2 +- src/driver/network/protocols/udp.c | 2 +- src/include/driver/network/conn.h | 2 +- src/include/driver/network/protocols/{ => ipv4}/acd.h | 0 src/include/driver/network/protocols/{ => ipv4}/arp.h | 0 src/include/driver/network/protocols/{ => ipv4}/dhcp.h | 0 src/include/driver/network/protocols/{ => ipv4}/ipv4.h | 2 +- src/include/driver/network/protocols/udp.h | 2 +- 17 files changed, 23 insertions(+), 22 deletions(-) create mode 100644 src/driver/network/protocols/ipv4/Makefile rename src/driver/network/protocols/{ => ipv4}/acd.c (94%) rename src/driver/network/protocols/{ => ipv4}/arp.c (98%) rename src/driver/network/protocols/{ => ipv4}/dhcp.c (99%) rename src/driver/network/protocols/{ => ipv4}/ipv4.c (99%) rename src/include/driver/network/protocols/{ => ipv4}/acd.h (100%) rename src/include/driver/network/protocols/{ => ipv4}/arp.h (100%) rename src/include/driver/network/protocols/{ => ipv4}/dhcp.h (100%) rename src/include/driver/network/protocols/{ => ipv4}/ipv4.h (97%) diff --git a/src/driver/network/conn.c b/src/driver/network/conn.c index cb2add7..2a15e4a 100644 --- a/src/driver/network/conn.c +++ b/src/driver/network/conn.c @@ -1,5 +1,5 @@ #include "driver/network/ethernet/ethernet.h" -#include "driver/network/protocols/ipv4.h" +#include "driver/network/protocols/ipv4/ipv4.h" #include "driver/network/protocols/protocols.h" #include "kernel/list.h" #include "kernel/spinlock.h" diff --git a/src/driver/network/ethernet/ethernet.c b/src/driver/network/ethernet/ethernet.c index db4aa5b..558a358 100644 --- a/src/driver/network/ethernet/ethernet.c +++ b/src/driver/network/ethernet/ethernet.c @@ -9,14 +9,14 @@ * Networks * */ -#include "driver/network/protocols/ipv4.h" +#include "driver/network/protocols/ipv4/ipv4.h" #include "driver/network/protocols/protocols.h" #include #include #include #include #include -#include +#include #include #include #include diff --git a/src/driver/network/neighbour.c b/src/driver/network/neighbour.c index c2caf35..2f410af 100644 --- a/src/driver/network/neighbour.c +++ b/src/driver/network/neighbour.c @@ -1,5 +1,5 @@ #include "driver/network/network_dm.h" -#include "driver/network/protocols/arp.h" +#include "driver/network/protocols/ipv4/arp.h" #include "kernel/driver.h" #include "kernel/list.h" #include "kernel/spinlock.h" diff --git a/src/driver/network/protocols/Makefile b/src/driver/network/protocols/Makefile index df2b998..dcd9585 100644 --- a/src/driver/network/protocols/Makefile +++ b/src/driver/network/protocols/Makefile @@ -1,6 +1,3 @@ -SRC += arp.c -SRC += ipv4.c -SRC += dhcp.c +SRC += ipv4/ SRC += udp.c -SRC += acd.c SRC += tcp.c \ No newline at end of file diff --git a/src/driver/network/protocols/ipv4/Makefile b/src/driver/network/protocols/ipv4/Makefile new file mode 100644 index 0000000..65b5490 --- /dev/null +++ b/src/driver/network/protocols/ipv4/Makefile @@ -0,0 +1,4 @@ +SRC += acd.c +SRC += arp.c +SRC += dhcp.c +SRC += ipv4.c \ No newline at end of file diff --git a/src/driver/network/protocols/acd.c b/src/driver/network/protocols/ipv4/acd.c similarity index 94% rename from src/driver/network/protocols/acd.c rename to src/driver/network/protocols/ipv4/acd.c index 52b8032..0f75249 100644 --- a/src/driver/network/protocols/acd.c +++ b/src/driver/network/protocols/ipv4/acd.c @@ -8,11 +8,11 @@ #include "driver/network/ethernet/ethernet.h" #include "driver/network/neighbour.h" #include "driver/network/network_dm.h" -#include "driver/network/protocols/ipv4.h" +#include "driver/network/protocols/ipv4/ipv4.h" #include "driver/network/protocols/protocols.h" #include "driver/timer_dm.h" -#include -#include +#include +#include #include void acd_timer_callback(void *arg) { diff --git a/src/driver/network/protocols/arp.c b/src/driver/network/protocols/ipv4/arp.c similarity index 98% rename from src/driver/network/protocols/arp.c rename to src/driver/network/protocols/ipv4/arp.c index a6f4741..ff11a6f 100644 --- a/src/driver/network/protocols/arp.c +++ b/src/driver/network/protocols/ipv4/arp.c @@ -15,8 +15,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include diff --git a/src/driver/network/protocols/dhcp.c b/src/driver/network/protocols/ipv4/dhcp.c similarity index 99% rename from src/driver/network/protocols/dhcp.c rename to src/driver/network/protocols/ipv4/dhcp.c index 8b9a139..2d400bc 100644 --- a/src/driver/network/protocols/dhcp.c +++ b/src/driver/network/protocols/ipv4/dhcp.c @@ -11,15 +11,15 @@ #include "driver/network/buffer.h" #include "driver/network/ethernet/ethernet.h" #include "driver/network/neighbour.h" -#include "driver/network/protocols/acd.h" +#include "driver/network/protocols/ipv4/acd.h" #include "driver/timer_dm.h" #include "kernel/driver_interface.h" #include "kernel/thread.h" #include "objects/transfer.h" #include #include -#include -#include +#include +#include #include #include #include diff --git a/src/driver/network/protocols/ipv4.c b/src/driver/network/protocols/ipv4/ipv4.c similarity index 99% rename from src/driver/network/protocols/ipv4.c rename to src/driver/network/protocols/ipv4/ipv4.c index 79b482c..b30ed1b 100644 --- a/src/driver/network/protocols/ipv4.c +++ b/src/driver/network/protocols/ipv4/ipv4.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/driver/network/protocols/tcp.c b/src/driver/network/protocols/tcp.c index af67309..e967bcd 100644 --- a/src/driver/network/protocols/tcp.c +++ b/src/driver/network/protocols/tcp.c @@ -18,7 +18,7 @@ #include "kernel/thread.h" #include "math.h" #include -#include +#include #include #include #include diff --git a/src/driver/network/protocols/udp.c b/src/driver/network/protocols/udp.c index 9376aa3..268dc81 100644 --- a/src/driver/network/protocols/udp.c +++ b/src/driver/network/protocols/udp.c @@ -14,7 +14,7 @@ #include "kernel/spinlock.h" #include "kernel/thread.h" #include -#include +#include #include #include #include diff --git a/src/include/driver/network/conn.h b/src/include/driver/network/conn.h index c7cf67f..14a2278 100644 --- a/src/include/driver/network/conn.h +++ b/src/include/driver/network/conn.h @@ -4,7 +4,7 @@ #include "buffer.h" #include "driver/network/ethernet/ethernet.h" #include "driver/network/network_dm.h" -#include "driver/network/protocols/ipv4.h" +#include "driver/network/protocols/ipv4/ipv4.h" #include "kernel/list.h" #include "kernel/spinlock.h" #include "kernel/thread.h" diff --git a/src/include/driver/network/protocols/acd.h b/src/include/driver/network/protocols/ipv4/acd.h similarity index 100% rename from src/include/driver/network/protocols/acd.h rename to src/include/driver/network/protocols/ipv4/acd.h diff --git a/src/include/driver/network/protocols/arp.h b/src/include/driver/network/protocols/ipv4/arp.h similarity index 100% rename from src/include/driver/network/protocols/arp.h rename to src/include/driver/network/protocols/ipv4/arp.h diff --git a/src/include/driver/network/protocols/dhcp.h b/src/include/driver/network/protocols/ipv4/dhcp.h similarity index 100% rename from src/include/driver/network/protocols/dhcp.h rename to src/include/driver/network/protocols/ipv4/dhcp.h diff --git a/src/include/driver/network/protocols/ipv4.h b/src/include/driver/network/protocols/ipv4/ipv4.h similarity index 97% rename from src/include/driver/network/protocols/ipv4.h rename to src/include/driver/network/protocols/ipv4/ipv4.h index 0db0a76..5fec21c 100644 --- a/src/include/driver/network/protocols/ipv4.h +++ b/src/include/driver/network/protocols/ipv4/ipv4.h @@ -3,7 +3,7 @@ #include "driver/network/neighbour.h" #include "kernel/list.h" -#include "protocols.h" +#include #include #define IP_PROTO_ICMP 1 diff --git a/src/include/driver/network/protocols/udp.h b/src/include/driver/network/protocols/udp.h index e4ce13d..0196a6f 100644 --- a/src/include/driver/network/protocols/udp.h +++ b/src/include/driver/network/protocols/udp.h @@ -2,7 +2,7 @@ #define _UDP_H #include "driver/network/buffer.h" -#include "driver/network/protocols/ipv4.h" +#include "driver/network/protocols/ipv4/ipv4.h" #include #define UDP_PORT_DHCP_SERVER 67 From bc38eaf5f73d5ea67a117a53eaa3232604ba2a25 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 13 Sep 2025 18:43:06 +0800 Subject: [PATCH 101/158] =?UTF-8?q?network&neighbour:=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20=E8=87=AA=E5=8A=A8=E5=AD=A6=E4=B9=A0ip->mac=E5=85=B3?= =?UTF-8?q?=E7=B3=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/ethernet/ethernet.c | 4 ++- src/driver/network/neighbour.c | 13 ++++++++- src/driver/network/protocols/ipv4/arp.c | 1 + src/driver/network/protocols/ipv4/dhcp.c | 1 + src/driver/network/protocols/ipv4/ipv4.c | 27 ++++++++++++++++--- src/include/driver/network/conn.h | 1 - src/include/driver/network/neighbour.h | 8 +++++- .../driver/network/protocols/ipv4/ipv4.h | 7 +++-- 8 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/driver/network/ethernet/ethernet.c b/src/driver/network/ethernet/ethernet.c index 558a358..4b9fa03 100644 --- a/src/driver/network/ethernet/ethernet.c +++ b/src/driver/network/ethernet/ethernet.c @@ -77,7 +77,9 @@ ProtocolResult eth_recv(NetworkDevice *device, NetBuffer *net_buffer) { ProtocolResult result = PROTO_OK; switch (BE2HOST_WORD(header->protocol_type)) { case ETH_PROTO_TYPE_IPV4: - result = ipv4_recv(net_buffer); + ipv4_neigh_update( + device, net_buffer, header->src_mac, ETH_IDENTIFIER_SIZE); + result = ipv4_recv(device, net_buffer); break; case ETH_PROTO_TYPE_ARP: result = arp_recv(device, net_buffer); diff --git a/src/driver/network/neighbour.c b/src/driver/network/neighbour.c index 2f410af..192bd60 100644 --- a/src/driver/network/neighbour.c +++ b/src/driver/network/neighbour.c @@ -30,6 +30,7 @@ NeighbourEntry *neighbour_entry_create( entry->key = hash_key; entry->state = NEIGH_STATE_NONE; entry->device = device; + entry->hlen = 0; memset(entry->haddr, 0, sizeof(entry->haddr)); memcpy(entry->ip_addr, addr, length); @@ -54,7 +55,7 @@ NeighbourEntry *neighbour_entry_create( return entry; } -NeighbourEntry *neighbour_table_lookup( +NeighbourEntry *neighbour_table_try_lookup( NetworkDevice *device, NeighbourKey hash_key, uint8_t *ip_addr, uint8_t ip_length) { NeighbourEntry *entry = NULL; @@ -70,6 +71,16 @@ NeighbourEntry *neighbour_table_lookup( } spin_unlock(&neighbour_table.lock[hash_key]); + return NULL; +} + +NeighbourEntry *neighbour_table_lookup( + NetworkDevice *device, NeighbourKey hash_key, uint8_t *ip_addr, + uint8_t ip_length) { + NeighbourEntry *entry = + neighbour_table_try_lookup(device, hash_key, ip_addr, ip_length); + if (entry != NULL) return entry; + entry = neighbour_entry_create(device, hash_key, ip_addr, ip_length); entry->ops->request(entry, NULL); diff --git a/src/driver/network/protocols/ipv4/arp.c b/src/driver/network/protocols/ipv4/arp.c index ff11a6f..9ff7491 100644 --- a/src/driver/network/protocols/ipv4/arp.c +++ b/src/driver/network/protocols/ipv4/arp.c @@ -101,6 +101,7 @@ ProtocolResult arp_recv(NetworkDevice *device, NetBuffer *net_buffer) { } else { } entry->state = NEIGH_STATE_REACHABLE; + entry->hlen = arp_header->hlen; memcpy(entry->haddr, src_haddr, arp_header->hlen); spin_unlock(&entry->lock); diff --git a/src/driver/network/protocols/ipv4/dhcp.c b/src/driver/network/protocols/ipv4/dhcp.c index 2d400bc..c55e26b 100644 --- a/src/driver/network/protocols/ipv4/dhcp.c +++ b/src/driver/network/protocols/ipv4/dhcp.c @@ -322,6 +322,7 @@ void dhcp_check_addr(DhcpClient *dhcp) { neighbour_table_lookup(dhcp->device, key, dhcp->server_ip_addr, 4); entry->ops->probe(dhcp->device); if (entry->state == NEIGH_STATE_REACHABLE) { + entry->hlen = dhcp->haddr_len; memcpy(dhcp->server_haddr, entry->haddr, dhcp->haddr_len); } } diff --git a/src/driver/network/protocols/ipv4/ipv4.c b/src/driver/network/protocols/ipv4/ipv4.c index b30ed1b..43e5a9b 100644 --- a/src/driver/network/protocols/ipv4/ipv4.c +++ b/src/driver/network/protocols/ipv4/ipv4.c @@ -8,16 +8,16 @@ * */ #include "driver/network/network_dm.h" -#include "driver/network/protocols/tcp.h" -#include "kernel/thread.h" #include #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -48,6 +48,27 @@ void ipv4_register(NetworkConnection *conn, uint8_t *ip_addr) { NET_BUF_RESV_HEAD(conn, sizeof(Ipv4Header)); } +void ipv4_neigh_update( + NetworkDevice *device, NetBuffer *buffer, uint8_t *mac, int hlen) { + if (!buffer || !mac) return; + Ipv4Header *ipv4_header = (Ipv4Header *)buffer->data; + uint8_t *ip = ipv4_header->src_ip; + + uint32_t _ip = *(uint32_t *)ip; + if (_ip == ipv4_null_addr || _ip == ipv4_broadcast_addr) return; + + NeighbourKey hash_key = ipv4_hash(ip); + NeighbourEntry *entry = neighbour_table_try_lookup(device, hash_key, ip, 4); + if (entry == NULL) { + entry = neighbour_entry_create(device, hash_key, ip, 4); + if (entry == NULL) return; + } + spin_lock(&entry->lock); + entry->state = NEIGH_STATE_REACHABLE; + memcpy(entry->haddr, mac, hlen); + spin_unlock(&entry->lock); +} + void ipv4_enable_fragment(NetworkConnection *conn) { conn->ipv4.fragment.enable_fragment = 1; conn->ipv4.fragment.last_fragment = 0; @@ -114,7 +135,7 @@ void ipv4_rewrap(NetworkConnection *conn) { ipv4_checksum(ipv4_header); } -ProtocolResult ipv4_recv(NetBuffer *net_buffer) { +ProtocolResult ipv4_recv(NetworkDevice *device, NetBuffer *net_buffer) { Ipv4Header *ipv4_header = (Ipv4Header *)net_buffer->data; int size = net_buffer->tail - net_buffer->data; int length = ipv4_get_packet_length(ipv4_header); diff --git a/src/include/driver/network/conn.h b/src/include/driver/network/conn.h index 14a2278..e67129f 100644 --- a/src/include/driver/network/conn.h +++ b/src/include/driver/network/conn.h @@ -8,7 +8,6 @@ #include "kernel/list.h" #include "kernel/spinlock.h" #include "kernel/thread.h" -#include "kernel/wait_queue.h" #include "objects/handle.h" #include "objects/object.h" #include diff --git a/src/include/driver/network/neighbour.h b/src/include/driver/network/neighbour.h index 37887de..dfccff5 100644 --- a/src/include/driver/network/neighbour.h +++ b/src/include/driver/network/neighbour.h @@ -31,7 +31,10 @@ typedef struct NeighbourEntry { NeighbourKey key; NeighbourState state; - uint8_t haddr[8]; // Hardware address (MAC address) + + int hlen; + uint8_t haddr[8]; // Hardware address (MAC address) + NetworkDevice *device; void *arg; @@ -55,6 +58,9 @@ void neighbour_init(void); NeighbourEntry *neighbour_entry_create( NetworkDevice *device, NeighbourKey hash_key, uint8_t *addr, uint8_t length); +NeighbourEntry *neighbour_table_try_lookup( + NetworkDevice *device, NeighbourKey hash_key, uint8_t *ip_addr, + uint8_t ip_length); NeighbourEntry *neighbour_table_lookup( NetworkDevice *device, NeighbourKey hash_key, uint8_t *ip_addr, uint8_t ip_length); diff --git a/src/include/driver/network/protocols/ipv4/ipv4.h b/src/include/driver/network/protocols/ipv4/ipv4.h index 5fec21c..fcee452 100644 --- a/src/include/driver/network/protocols/ipv4/ipv4.h +++ b/src/include/driver/network/protocols/ipv4/ipv4.h @@ -51,8 +51,11 @@ ProtocolResult ipv4_wrap( struct NetworkConnection *conn, uint16_t protocol, uint8_t *dst_ip, uint8_t ttl); void ipv4_rewrap(struct NetworkConnection *conn); -ProtocolResult ipv4_recv(struct NetBuffer *net_buffer); -NeighbourKey ipv4_hash(uint8_t ip[4]); +ProtocolResult ipv4_recv( + struct NetworkDevice *device, struct NetBuffer *net_buffer); +NeighbourKey ipv4_hash(uint8_t ip[4]); +void ipv4_neigh_update( + NetworkDevice *device, struct NetBuffer *buffer, uint8_t *mac, int hlen); ProtocolResult ipv4_lookup_mac( NetworkDevice *device, uint8_t ip[4], uint8_t mac[8]); uint16_t ipv4_get_packet_length(Ipv4Header *ipv4_header); From 426a6e1d13578dab2b39faebf68275c6f27e7864 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 13 Sep 2025 22:46:21 +0800 Subject: [PATCH 102/158] =?UTF-8?q?dhcp&arp:=20=E4=BF=AE=E5=A4=8D=20?= =?UTF-8?q?=E5=9C=A8DHCP=20Requesting=E9=98=B6=E6=AE=B5=E4=B8=8D=E5=9B=9E?= =?UTF-8?q?=E5=A4=8DARP=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/protocols/ipv4/arp.c | 25 +++++++++++++----------- src/driver/network/protocols/ipv4/dhcp.c | 4 ++++ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/driver/network/protocols/ipv4/arp.c b/src/driver/network/protocols/ipv4/arp.c index 9ff7491..f908047 100644 --- a/src/driver/network/protocols/ipv4/arp.c +++ b/src/driver/network/protocols/ipv4/arp.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -43,14 +42,16 @@ ProtocolResult arp_recv(NetworkDevice *device, NetBuffer *net_buffer) { uint8_t *mac_addr = device->ethernet->mac_addr; if (htype == ARP_HTYPE_ETH && device->type == NETWORK_TYPE_ETHERNET) { if (arp_header->hlen == ETH_IDENTIFIER_SIZE) { - if (memcmp(dst_haddr, eth_broadcast_mac, arp_header->hlen) == 0) { - // 处理广播地址 - p = mac_addr; - goto next; - } else if (memcmp(dst_haddr, mac_addr, arp_header->hlen) == 0) { + if (memcmp(dst_haddr, mac_addr, arp_header->hlen) == 0) { // 处理本地地址 p = dst_haddr; goto next; + } else if ( + memcmp(dst_haddr, eth_broadcast_mac, arp_header->hlen) == 0 || + memcmp(dst_haddr, eth_null_mac, arp_header->hlen) == 0) { + // 处理其他地址 + p = mac_addr; + goto next; } } } @@ -64,7 +65,7 @@ ProtocolResult arp_recv(NetworkDevice *device, NetBuffer *net_buffer) { // 检查协议类型 uint8_t *paddr = NULL; uint16_t ptype = BE2HOST_WORD(arp_header->ptype); - if (ptype == ETH_TYPE_IPV4 && arp_header->plen == 4) { + if (ptype == ETH_PROTO_TYPE_IPV4 && arp_header->plen == 4) { hash_key = ipv4_hash(src_paddr) % NEIGH_BUCKET_SIZE; paddr = device->ipv4.ip; if (memcmp(src_paddr, paddr, 4) == 0) { @@ -91,6 +92,8 @@ ProtocolResult arp_recv(NetworkDevice *device, NetBuffer *net_buffer) { } spin_unlock(&neighbour_table.lock[hash_key]); + if (memcmp(dst_paddr, device->ipv4.ip, 4)) return PROTO_OK; + if (!merge_flag) { // Create a new neighbour entry entry = neighbour_entry_create( @@ -129,7 +132,7 @@ void arp_send_request(NeighbourEntry *entry, void *arg) { // Fill in the ARP request details ArpHeader *arp_header = (ArpHeader *)conn_buffer(conn)->data; arp_header->htype = HOST2BE_WORD(ARP_HTYPE_ETH); - arp_header->ptype = HOST2BE_WORD(ETH_TYPE_IPV4); + arp_header->ptype = HOST2BE_WORD(ETH_PROTO_TYPE_IPV4); arp_header->hlen = 6; arp_header->plen = 4; arp_header->opcode = HOST2BE_WORD(ARP_OP_REQUEST); @@ -156,7 +159,7 @@ void arp_send_request(NeighbourEntry *entry, void *arg) { // Send the ARP request eth_wrap( conn_buffer(conn), device->ethernet->mac_addr, eth_broadcast_mac, - ETH_TYPE_ARP); + ETH_PROTO_TYPE_ARP); entry->state = NEIGH_STATE_WAITING; NETWORK_SEND(device, eth_device->arp_conn); @@ -169,7 +172,7 @@ void arp_announce(NetworkDevice *device, uint8_t *ip_addr) { // Fill in the ARP request details ArpHeader *arp_header = (ArpHeader *)conn_buffer(conn)->data; arp_header->htype = HOST2BE_WORD(ARP_HTYPE_ETH); - arp_header->ptype = HOST2BE_WORD(ETH_TYPE_IPV4); + arp_header->ptype = HOST2BE_WORD(ETH_PROTO_TYPE_IPV4); arp_header->hlen = ETH_IDENTIFIER_SIZE; arp_header->plen = 4; arp_header->opcode = HOST2BE_WORD(ARP_OP_REQUEST); @@ -196,6 +199,6 @@ void arp_announce(NetworkDevice *device, uint8_t *ip_addr) { // Send the ARP request eth_wrap( conn_buffer(conn), device->ethernet->mac_addr, eth_broadcast_mac, - ETH_TYPE_ARP); + ETH_PROTO_TYPE_ARP); NETWORK_SEND(device, conn); } diff --git a/src/driver/network/protocols/ipv4/dhcp.c b/src/driver/network/protocols/ipv4/dhcp.c index c55e26b..a773756 100644 --- a/src/driver/network/protocols/ipv4/dhcp.c +++ b/src/driver/network/protocols/ipv4/dhcp.c @@ -211,6 +211,8 @@ void dhcp_offer_handler( memcpy(dhcp->server_ip_addr, &header->options[index_sid], 4); memcpy(dhcp->ip_addr, &header->yiaddr, 4); + memcpy(conn->net_device->ipv4.ip, dhcp->ip_addr, 4); + memcpy(conn->ipv4.conn_info.local.ip, dhcp->ip_addr, 4); dhcp_select(dhcp); } @@ -223,6 +225,7 @@ void dhcp_ack_handler( *(uint32_t *)device->ipv4.subnet_mask = 0; *(uint32_t *)device->ipv4.gateway_ip = 0; memcpy(device->ipv4.ip, dhcp->ip_addr, 4); + memcpy(conn->ipv4.conn_info.local.ip, dhcp->ip_addr, 4); if (indexes[DOI_SUBNET_MASK] != 0) { *(uint32_t *)device->ipv4.subnet_mask = @@ -550,6 +553,7 @@ void dhcp_reset(DhcpClient *dhcp, NetworkConnection *conn) { dhcp->state = DHCP_STAT_INIT; dhcp->xid = rand(); + memcpy(conn->net_device->ipv4.ip, &ipv4_null_addr, 4); memset(dhcp->ip_addr, 0, sizeof(dhcp->ip_addr)); memset(dhcp->server_ip_addr, 0, sizeof(dhcp->server_ip_addr)); memset(dhcp->server_haddr, 0, sizeof(dhcp->server_haddr)); From 1237dc8d6109fdc3477c504700b5d45ae7ec134a Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 14 Sep 2025 19:17:34 +0800 Subject: [PATCH 103/158] =?UTF-8?q?udp:=20=E6=96=B0=E5=A2=9E=20=E5=AF=B9?= =?UTF-8?q?=E7=89=B9=E6=AE=8A=E7=9B=AE=E7=9A=84=E5=9C=B0=E5=9D=80=E7=9A=84?= =?UTF-8?q?=E5=A4=84=E7=90=86=EF=BC=9B=20arp:=20=E4=BF=AE=E5=A4=8D=20?= =?UTF-8?q?=E5=8F=91=E9=80=81announce=E5=89=8D=E6=9C=AA=E6=B8=85=E7=A9=BAb?= =?UTF-8?q?uffer=E5=AF=BC=E8=87=B4=E5=8F=91=E9=80=81=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E7=9A=84bug=EF=BC=9B=20ipv4:=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20=E5=AF=B9=E6=97=A0=E7=BD=91=E5=85=B3=E5=9C=B0?= =?UTF-8?q?=E5=9D=80=E6=83=85=E5=86=B5=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/conn.c | 11 +++++++---- src/driver/network/ethernet/ethernet.c | 1 + src/driver/network/protocols/ipv4/arp.c | 2 ++ src/driver/network/protocols/ipv4/ipv4.c | 3 +++ src/driver/network/protocols/udp.c | 19 +++++++++++-------- .../driver/network/ethernet/ethernet.h | 1 + .../driver/network/protocols/protocols.h | 1 + 7 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/driver/network/conn.c b/src/driver/network/conn.c index 2a15e4a..cad92e7 100644 --- a/src/driver/network/conn.c +++ b/src/driver/network/conn.c @@ -50,6 +50,7 @@ ProtocolResult conn_wrap(NetworkConnection *conn, ProtocolLevel level) { uint16_t net_protocol = 0; uint8_t dst_mac[8] = {0}; + ProtocolResult result = PROTO_OK; switch (level) { case PROTO_LEVEL_TRANSPORT: case PROTO_LEVEL_NETWORK: @@ -67,8 +68,9 @@ ProtocolResult conn_wrap(NetworkConnection *conn, ProtocolLevel level) { } switch (conn->net_protocol) { case NET_PROTO_IPV4: - ipv4_wrap(conn, trans_protocol, CONN_REMOTE_IP(conn), 64); - ipv4_lookup_mac( + result = ipv4_wrap(conn, trans_protocol, CONN_REMOTE_IP(conn), 64); + if (result != PROTO_OK) return result; + result = ipv4_lookup_mac( conn->net_device, conn->ipv4.conn_info.remote.ip, dst_mac); break; default: @@ -100,7 +102,8 @@ ProtocolResult conn_wrap(NetworkConnection *conn, ProtocolLevel level) { } switch (conn->phy_protocol) { case PHY_PROTO_ETHERNET: - eth_wrap(conn->buffer, conn->ethernet.mac, dst_mac, net_protocol); + result = eth_wrap( + conn->buffer, conn->ethernet.mac, dst_mac, net_protocol); break; default: return PROTO_ERROR_UNSUPPORT; @@ -108,5 +111,5 @@ ProtocolResult conn_wrap(NetworkConnection *conn, ProtocolLevel level) { break; } - return PROTO_OK; + return result; } diff --git a/src/driver/network/ethernet/ethernet.c b/src/driver/network/ethernet/ethernet.c index 4b9fa03..24746a5 100644 --- a/src/driver/network/ethernet/ethernet.c +++ b/src/driver/network/ethernet/ethernet.c @@ -30,6 +30,7 @@ NetProtocol ethernet_protocol = { }; const uint8_t eth_broadcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +const uint8_t eth_null_mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; void eth_set_mac_address(EthernetDevice *device, uint8_t *mac_addr) { memcpy(device->mac_addr, mac_addr, 6); diff --git a/src/driver/network/protocols/ipv4/arp.c b/src/driver/network/protocols/ipv4/arp.c index f908047..800f5e7 100644 --- a/src/driver/network/protocols/ipv4/arp.c +++ b/src/driver/network/protocols/ipv4/arp.c @@ -169,6 +169,8 @@ void arp_announce(NetworkDevice *device, uint8_t *ip_addr) { EthernetDevice *eth_device = device->ethernet; NetworkConnection *conn = eth_device->arp_conn; + net_buffer_reset(conn->buffer); + // Fill in the ARP request details ArpHeader *arp_header = (ArpHeader *)conn_buffer(conn)->data; arp_header->htype = HOST2BE_WORD(ARP_HTYPE_ETH); diff --git a/src/driver/network/protocols/ipv4/ipv4.c b/src/driver/network/protocols/ipv4/ipv4.c index 43e5a9b..9ca770c 100644 --- a/src/driver/network/protocols/ipv4/ipv4.c +++ b/src/driver/network/protocols/ipv4/ipv4.c @@ -193,6 +193,9 @@ ProtocolResult ipv4_lookup_mac( entry = neighbour_table_lookup(device, hash_key, ip, 4); } else { // 在子网外 + if (gateway_ip == ipv4_null_addr) { + return PROTO_ERROR_CANNOT_FIND_ROUTE; + } hash_key = ipv4_hash(device->ipv4.gateway_ip); entry = neighbour_table_lookup( device, hash_key, device->ipv4.gateway_ip, 4); diff --git a/src/driver/network/protocols/udp.c b/src/driver/network/protocols/udp.c index 268dc81..2998f97 100644 --- a/src/driver/network/protocols/udp.c +++ b/src/driver/network/protocols/udp.c @@ -144,19 +144,22 @@ ProtocolResult udp_recv(NetBuffer *net_buffer, Ipv4Header *ipv4_header) { if (info->local.port == BE2HOST_WORD(udp_header->dst_port) && (info->remote.port == 0 || info->remote.port == BE2HOST_WORD(udp_header->src_port))) { + NetworkConnection *conn = + container_of(info, NetworkConnection, ipv4.conn_info); if (memcmp(info->local.ip, ipv4_header->dst_ip, 4)) { - if (memcmp( - info->local.ip, (void *)&ipv4_null_addr, - 4) || // 不是发送到0.0.0.0 - memcmp( - ipv4_header->dst_ip, (void *)&ipv4_broadcast_addr, - 4)) // 也不是广播 + if ((memcmp( + conn->net_device->ipv4.ip, (void *)&ipv4_null_addr, + 4)) && // 本机已有IP地址 + (memcmp( + info->local.ip, (void *)&ipv4_null_addr, + 4) || // 不是发送到0.0.0.0 + memcmp( + ipv4_header->dst_ip, (void *)&ipv4_broadcast_addr, + 4))) // 也不是广播 continue; } // 找到匹配的连接 - NetworkConnection *conn = - container_of(info, NetworkConnection, ipv4.conn_info); if (conn->udp.callback) { conn->udp.callback(conn, net_buffer); diff --git a/src/include/driver/network/ethernet/ethernet.h b/src/include/driver/network/ethernet/ethernet.h index 81a6672..d4a0e78 100644 --- a/src/include/driver/network/ethernet/ethernet.h +++ b/src/include/driver/network/ethernet/ethernet.h @@ -46,6 +46,7 @@ void eth_get_mac_address(EthernetDevice *device, uint8_t *mac_addr); struct NetworkConnection; extern const uint8_t eth_broadcast_mac[6]; +extern const uint8_t eth_null_mac[6]; void eth_register(struct NetworkConnection *conn); ProtocolResult eth_wrap( diff --git a/src/include/driver/network/protocols/protocols.h b/src/include/driver/network/protocols/protocols.h index e786760..89c5e28 100644 --- a/src/include/driver/network/protocols/protocols.h +++ b/src/include/driver/network/protocols/protocols.h @@ -16,6 +16,7 @@ typedef enum { PROTO_ERROR_PORT_CONFLICT, PROTO_ERROR_CANNOT_FIND, PROTO_ERROR_NO_SPACE_LEFT, + PROTO_ERROR_CANNOT_FIND_ROUTE, PROTO_ERROR_OTHER, } ProtocolResult; From a29a5dd5a23ffd0880e39dc15c62616eb58e0a8d Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 14 Sep 2025 23:30:23 +0800 Subject: [PATCH 104/158] =?UTF-8?q?protocols&ipv4:=20=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?icmp=20echo=20message=E5=9B=9E=E5=A4=8D=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- .../x86/drivers/network/rtl8139/rtl8139.c | 3 +- src/driver/network/ethernet/ethernet.c | 22 ++++- src/driver/network/neighbour.c | 1 - src/driver/network/network.c | 26 ++++++ src/driver/network/protocols/ipv4/Makefile | 1 + src/driver/network/protocols/ipv4/icmp.c | 93 +++++++++++++++++++ src/driver/network/protocols/ipv4/ipv4.c | 6 +- .../driver/network/ethernet/ethernet.h | 5 +- src/include/driver/network/network_dm.h | 4 + .../driver/network/protocols/ipv4/icmp.h | 44 +++++++++ .../driver/network/protocols/ipv4/ipv4.h | 4 +- .../driver/network/protocols/protocols.h | 8 ++ 13 files changed, 211 insertions(+), 8 deletions(-) create mode 100644 src/driver/network/protocols/ipv4/icmp.c create mode 100644 src/include/driver/network/protocols/ipv4/icmp.h diff --git a/Makefile b/Makefile index eed9a11..521dbee 100644 --- a/Makefile +++ b/Makefile @@ -110,7 +110,7 @@ qemu_dbg: -device usb-kbd \ -device usb-mouse \ -device rtl8139,netdev=nc1 \ - -netdev user,id=nc1,hostfwd=tcp::5555-:80 \ + -netdev vmnet-host,id=nc1 \ -object filter-dump,id=f1,netdev=nc1,file=dump.pcap \ -readconfig $(QEMU_CFG) \ -boot c diff --git a/src/arch/x86/drivers/network/rtl8139/rtl8139.c b/src/arch/x86/drivers/network/rtl8139/rtl8139.c index ae8928f..ee2fb8a 100644 --- a/src/arch/x86/drivers/network/rtl8139/rtl8139.c +++ b/src/arch/x86/drivers/network/rtl8139/rtl8139.c @@ -174,7 +174,8 @@ void rtl8139_net_rx_handler(void *data) { } else { memcpy(buffer, device->rx_buffer + i, packet_len); } - eth_recv(device->net_device, net_buffer); + protocol_recv( + device->net_device, net_buffer, NETWORK_TYPE_ETHERNET); } else { printk( "[RTL8139]RX Error: status %#04x,size %#04x, cur %#04x\n", diff --git a/src/driver/network/ethernet/ethernet.c b/src/driver/network/ethernet/ethernet.c index 24746a5..343fa4a 100644 --- a/src/driver/network/ethernet/ethernet.c +++ b/src/driver/network/ethernet/ethernet.c @@ -67,7 +67,22 @@ ProtocolResult eth_wrap( return PROTO_OK; } -ProtocolResult eth_recv(NetworkDevice *device, NetBuffer *net_buffer) { +ProtocolResult eth_reply(NetworkDevice *device, NetBuffer *buffer) { + EthernetHeader *header = (EthernetHeader *)buffer->head; + uint8_t tmp[ETH_IDENTIFIER_SIZE]; + if (memcmp(header->dst_mac, eth_broadcast_mac, ETH_IDENTIFIER_SIZE) == 0) { + // 广播包不回复 + return PROTO_ERROR_CANNOT_FIND_ROUTE; + } + memcpy(tmp, header->dst_mac, ETH_IDENTIFIER_SIZE); + memcpy(header->dst_mac, header->src_mac, ETH_IDENTIFIER_SIZE); + memcpy(header->src_mac, tmp, ETH_IDENTIFIER_SIZE); + return PROTO_OK; +} + +ProtocolResult eth_recv( + NetworkDevice *device, NetBuffer *net_buffer, ProtocolReplyCallback *stack, + int stack_size) { EthernetHeader *header = (EthernetHeader *)net_buffer->data; int size = net_buffer->tail - net_buffer->data; if (size < ETH_HEADER_SIZE) { return PROTO_ERROR_UNSUPPORT; } @@ -76,11 +91,14 @@ ProtocolResult eth_recv(NetworkDevice *device, NetBuffer *net_buffer) { net_buffer->data += sizeof(EthernetHeader); ProtocolResult result = PROTO_OK; + + *stack++ = eth_reply; + stack_size--; switch (BE2HOST_WORD(header->protocol_type)) { case ETH_PROTO_TYPE_IPV4: ipv4_neigh_update( device, net_buffer, header->src_mac, ETH_IDENTIFIER_SIZE); - result = ipv4_recv(device, net_buffer); + result = ipv4_recv(device, net_buffer, stack, stack_size); break; case ETH_PROTO_TYPE_ARP: result = arp_recv(device, net_buffer); diff --git a/src/driver/network/neighbour.c b/src/driver/network/neighbour.c index 192bd60..34ebbc7 100644 --- a/src/driver/network/neighbour.c +++ b/src/driver/network/neighbour.c @@ -1,6 +1,5 @@ #include "driver/network/network_dm.h" #include "driver/network/protocols/ipv4/arp.h" -#include "kernel/driver.h" #include "kernel/list.h" #include "kernel/spinlock.h" #include diff --git a/src/driver/network/network.c b/src/driver/network/network.c index 68be280..2ac91f0 100644 --- a/src/driver/network/network.c +++ b/src/driver/network/network.c @@ -1,6 +1,7 @@ #include "driver/network/network.h" #include "driver/network/buffer.h" #include "driver/network/conn.h" +#include "driver/network/protocols/protocols.h" #include "kernel/list.h" #include #include @@ -60,3 +61,28 @@ NetBuffer *network_recv(NetworkConnection *conn) { } return net_buffer; } + +ProtocolResult protocol_recv( + NetworkDevice *device, NetBuffer *net_buffer, NetworkDeviceType type) { + ProtocolReplyCallback callback_stack[NET_CONN_MAX_PROTOCOLS]; + switch (type) { + case NETWORK_TYPE_ETHERNET: + return eth_recv( + device, net_buffer, callback_stack, NET_CONN_MAX_PROTOCOLS); + default: + return PROTO_ERROR_UNSUPPORT; + } +} + +ProtocolResult protocol_reply( + NetworkDevice *device, NetBuffer *net_buffer, ProtocolReplyCallback *stack, + int stack_size) { + ProtocolResult result = PROTO_OK; + while (stack_size++ < NET_CONN_MAX_PROTOCOLS) { + result = (*--stack)(device, net_buffer); + if (result != PROTO_OK) { return result; } + } + device->ops->send( + device, net_buffer->head, net_buffer->tail - net_buffer->head); + return result; +} diff --git a/src/driver/network/protocols/ipv4/Makefile b/src/driver/network/protocols/ipv4/Makefile index 65b5490..441e15d 100644 --- a/src/driver/network/protocols/ipv4/Makefile +++ b/src/driver/network/protocols/ipv4/Makefile @@ -1,4 +1,5 @@ SRC += acd.c SRC += arp.c SRC += dhcp.c +SRC += icmp.c SRC += ipv4.c \ No newline at end of file diff --git a/src/driver/network/protocols/ipv4/icmp.c b/src/driver/network/protocols/ipv4/icmp.c new file mode 100644 index 0000000..c804449 --- /dev/null +++ b/src/driver/network/protocols/ipv4/icmp.c @@ -0,0 +1,93 @@ +#include "driver/network/network_dm.h" +#include +#include +#include +#include +#include + +ProtocolResult icmp_recv_unsupport( + NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, + IcmpHeader *icmp_header, ProtocolReplyCallback *stack, int stack_size); +ProtocolResult icmp_recv_echo_message( + NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, + IcmpHeader *icmp_header, ProtocolReplyCallback *stack, int stack_size); + +ProtocolResult (*icmp_recv_handlers[17])( + NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, + IcmpHeader *icmp_header, ProtocolReplyCallback *stack, int stack_size) = { + [ICMP_TYPE_ECHO] = icmp_recv_echo_message, + [ICMP_TYPE_ECHO_REPLY] = icmp_recv_unsupport, + [ICMP_TYPE_DEST_UNREACHABLE] = icmp_recv_unsupport, + [ICMP_TYPE_SOURCE_QUENCH] = icmp_recv_unsupport, + [ICMP_TYPE_REDIRECT] = icmp_recv_unsupport, + [ICMP_TYPE_TIME_EXCEEDED] = icmp_recv_unsupport, + [ICMP_TYPE_PARAM_PROBLEM] = icmp_recv_unsupport, + [ICMP_TYPE_TIMESTAMP] = icmp_recv_unsupport, + [ICMP_TYPE_TIMESTAMP_REPLY] = icmp_recv_unsupport, + [ICMP_TYPE_INFO_REQUEST] = icmp_recv_unsupport, + [ICMP_TYPE_INFO_REPLY] = icmp_recv_unsupport, + [1 ... 2] = icmp_recv_unsupport, + [6 ... 7] = icmp_recv_unsupport, + [9 ... 10] = icmp_recv_unsupport, +}; + +uint16_t icmp_checksum(IcmpHeader *header, int length) { + uint32_t sum = 0; + uint16_t *data = (void *)header; + + header->checksum = 0; + + for (size_t i = 0; i < length / 2; i++) { + sum += data[i]; + if (sum > 0xFFFF) sum = (sum & 0xFFFF) + (sum >> 16); + } + return ~((uint16_t)sum); +}; + +ProtocolResult icmp_recv( + NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, + ProtocolReplyCallback *stack, int stack_size) { + IcmpHeader *icmp_header = (IcmpHeader *)net_buffer->data; + if (net_buffer->tail - net_buffer->data < sizeof(IcmpHeader)) { + return PROTO_ERROR_UNSUPPORT; + } + + uint16_t checksum = icmp_header->checksum; + if (icmp_checksum(icmp_header, net_buffer->tail - net_buffer->data) != + checksum) { + return PROTO_ERROR_CHECKSUM; + } + + if (icmp_header->type < 17) { + return icmp_recv_handlers[icmp_header->type]( + device, net_buffer, header, icmp_header, stack, stack_size); + } + return PROTO_ERROR_UNSUPPORT; +} + +ProtocolResult icmp_recv_unsupport( + NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, + IcmpHeader *icmp_header, ProtocolReplyCallback *stack, int stack_size) { + return PROTO_ERROR_UNSUPPORT; +} + +ProtocolResult icmp_recv_echo_message( + NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, + IcmpHeader *icmp_header, ProtocolReplyCallback *stack, int stack_size) { + if (net_buffer->tail - net_buffer->data < 8) { + return PROTO_ERROR_UNSUPPORT; + } + uint32_t ip = *((uint32_t *)header->dst_ip); + *((uint32_t *)header->dst_ip) = *((uint32_t *)header->src_ip); + *((uint32_t *)header->src_ip) = ip; + ipv4_checksum(header); + + icmp_header->type = ICMP_TYPE_ECHO_REPLY; + icmp_header->checksum = 0; + icmp_header->checksum = + icmp_checksum(icmp_header, net_buffer->tail - net_buffer->data); + + protocol_reply(device, net_buffer, stack, stack_size); + + return PROTO_OK; +} \ No newline at end of file diff --git a/src/driver/network/protocols/ipv4/ipv4.c b/src/driver/network/protocols/ipv4/ipv4.c index 9ca770c..b4f0186 100644 --- a/src/driver/network/protocols/ipv4/ipv4.c +++ b/src/driver/network/protocols/ipv4/ipv4.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -135,7 +136,9 @@ void ipv4_rewrap(NetworkConnection *conn) { ipv4_checksum(ipv4_header); } -ProtocolResult ipv4_recv(NetworkDevice *device, NetBuffer *net_buffer) { +ProtocolResult ipv4_recv( + NetworkDevice *device, NetBuffer *net_buffer, ProtocolReplyCallback *stack, + int stack_size) { Ipv4Header *ipv4_header = (Ipv4Header *)net_buffer->data; int size = net_buffer->tail - net_buffer->data; int length = ipv4_get_packet_length(ipv4_header); @@ -170,6 +173,7 @@ ProtocolResult ipv4_recv(NetworkDevice *device, NetBuffer *net_buffer) { net_buffer, length, ipv4_header->src_ip, ipv4_header->dst_ip, 4); break; case IP_PROTO_ICMP: + result = icmp_recv(device, net_buffer, ipv4_header, stack, stack_size); break; default: result = PROTO_ERROR_UNSUPPORT; diff --git a/src/include/driver/network/ethernet/ethernet.h b/src/include/driver/network/ethernet/ethernet.h index d4a0e78..484a9e5 100644 --- a/src/include/driver/network/ethernet/ethernet.h +++ b/src/include/driver/network/ethernet/ethernet.h @@ -52,6 +52,9 @@ void eth_register(struct NetworkConnection *conn); ProtocolResult eth_wrap( struct NetBuffer *buffer, uint8_t *mac_addr, const uint8_t *dst_addr, uint16_t protocol); -ProtocolResult eth_recv(NetworkDevice *device, NetBuffer *net_buffer); +ProtocolResult eth_reply(NetworkDevice *device, NetBuffer *buffer); +ProtocolResult eth_recv( + NetworkDevice *device, NetBuffer *net_buffer, ProtocolReplyCallback *stack, + int stack_size); #endif \ No newline at end of file diff --git a/src/include/driver/network/network_dm.h b/src/include/driver/network/network_dm.h index 5f39df4..4f5b6aa 100644 --- a/src/include/driver/network/network_dm.h +++ b/src/include/driver/network/network_dm.h @@ -7,6 +7,7 @@ #include "kernel/driver.h" #include "net_queue.h" #include "objects/transfer.h" +#include "protocols/protocols.h" #include #define NETWORK_SEND(device, conn) \ @@ -80,5 +81,8 @@ TransferResult network_transfer( struct Object *object, struct ObjectHandle *obj_handle, TransferDirection direction, uint8_t *buf, size_t size); struct NetBuffer *network_recv(struct NetworkConnection *conn); +ProtocolResult protocol_recv( + NetworkDevice *device, struct NetBuffer *net_buffer, + NetworkDeviceType type); #endif \ No newline at end of file diff --git a/src/include/driver/network/protocols/ipv4/icmp.h b/src/include/driver/network/protocols/ipv4/icmp.h new file mode 100644 index 0000000..c3a5778 --- /dev/null +++ b/src/include/driver/network/protocols/ipv4/icmp.h @@ -0,0 +1,44 @@ +#ifndef _ICMP_H +#define _ICMP_H + +#include +#include +#include +#include +#include + +#define ICMP_TYPE_ECHO_REPLY 0 +#define ICMP_TYPE_DEST_UNREACHABLE 3 +#define ICMP_TYPE_SOURCE_QUENCH 4 +#define ICMP_TYPE_REDIRECT 5 +#define ICMP_TYPE_ECHO 8 +#define ICMP_TYPE_TIME_EXCEEDED 11 +#define ICMP_TYPE_PARAM_PROBLEM 12 +#define ICMP_TYPE_TIMESTAMP 13 +#define ICMP_TYPE_TIMESTAMP_REPLY 14 +#define ICMP_TYPE_INFO_REQUEST 15 +#define ICMP_TYPE_INFO_REPLY 16 + +typedef struct { + uint8_t type; + uint8_t code; + uint16_t checksum; + union { + uint32_t unused; + struct { + uint8_t pointer; + uint8_t unused[3]; + } param; + uint8_t gateway_ip[4]; + struct { + uint16_t id; + uint16_t seq; + } info; + }; +} __attribute__((packed)) IcmpHeader; + +ProtocolResult icmp_recv( + NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, + ProtocolReplyCallback *stack, int stack_size); + +#endif \ No newline at end of file diff --git a/src/include/driver/network/protocols/ipv4/ipv4.h b/src/include/driver/network/protocols/ipv4/ipv4.h index fcee452..72fc8cf 100644 --- a/src/include/driver/network/protocols/ipv4/ipv4.h +++ b/src/include/driver/network/protocols/ipv4/ipv4.h @@ -46,13 +46,15 @@ extern const uint32_t ipv4_null_addr; struct NetworkConnection; struct NetBuffer; void ipv4_register(struct NetworkConnection *conn, uint8_t *ip_addr); +void ipv4_checksum(Ipv4Header *header); void ipv4_enable_fragment(struct NetworkConnection *conn); ProtocolResult ipv4_wrap( struct NetworkConnection *conn, uint16_t protocol, uint8_t *dst_ip, uint8_t ttl); void ipv4_rewrap(struct NetworkConnection *conn); ProtocolResult ipv4_recv( - struct NetworkDevice *device, struct NetBuffer *net_buffer); + struct NetworkDevice *device, struct NetBuffer *net_buffer, + ProtocolReplyCallback *stack, int stack_size); NeighbourKey ipv4_hash(uint8_t ip[4]); void ipv4_neigh_update( NetworkDevice *device, struct NetBuffer *buffer, uint8_t *mac, int hlen); diff --git a/src/include/driver/network/protocols/protocols.h b/src/include/driver/network/protocols/protocols.h index 89c5e28..5643fd0 100644 --- a/src/include/driver/network/protocols/protocols.h +++ b/src/include/driver/network/protocols/protocols.h @@ -20,4 +20,12 @@ typedef enum { PROTO_ERROR_OTHER, } ProtocolResult; +struct NetworkDevice; +struct NetBuffer; +typedef ProtocolResult (*ProtocolReplyCallback)( + struct NetworkDevice *device, struct NetBuffer *net_buffer); +ProtocolResult protocol_reply( + struct NetworkDevice *device, struct NetBuffer *net_buffer, + ProtocolReplyCallback *stack, int stack_size); + #endif \ No newline at end of file From 573a68318f3dc88f4b643893b990b9e53b792a78 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 15 Sep 2025 19:57:29 +0800 Subject: [PATCH 105/158] =?UTF-8?q?udp:=20=E7=AE=80=E5=8C=96=E5=B9=B6?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9C=B0=E5=9D=80=E5=8C=B9=E9=85=8D=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=9B=20tcp:=20=E4=BF=AE=E5=A4=8D=20=E6=8C=87?= =?UTF-8?q?=E6=95=B0=E9=80=80=E9=81=BF=E6=97=B6=E6=97=B6=E9=97=B4=E5=8D=95?= =?UTF-8?q?=E4=BD=8D=E9=94=99=E8=AF=AF=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/protocols/tcp.c | 4 ++-- src/driver/network/protocols/udp.c | 13 +++---------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/driver/network/protocols/tcp.c b/src/driver/network/protocols/tcp.c index e967bcd..7876845 100644 --- a/src/driver/network/protocols/tcp.c +++ b/src/driver/network/protocols/tcp.c @@ -447,10 +447,10 @@ void tcp_timeout_handler(void *arg) { tcp->retry_times++; if (tcp->retry_times < tcp_max_retries) { tcp->rto <<= 1; // 指数退避 - tcp->rto = MIN(tcp->rto, 60); + tcp->rto = MIN(tcp->rto, 60 * 1000); if (tcp->state == TCP_STATE_SYN_SENT || tcp->state == TCP_STATE_SYN_RECEIVED) - tcp->rto = MIN(tcp->rto, 3); + tcp->rto = MIN(tcp->rto, 3 * 1000); timer_set_timeout( &tcp->timeout_timer, timer_count_ms(&tcp->timeout_timer, tcp->rto)); diff --git a/src/driver/network/protocols/udp.c b/src/driver/network/protocols/udp.c index 2998f97..ea6696c 100644 --- a/src/driver/network/protocols/udp.c +++ b/src/driver/network/protocols/udp.c @@ -136,10 +136,6 @@ ProtocolResult udp_recv(NetBuffer *net_buffer, Ipv4Header *ipv4_header) { // IPv4 Ipv4ConnInfo *info, *next; - if (list_empty(&udp_lh)) { - // 没有绑定的连接 - goto drop; - } list_for_each_owner_safe (info, next, &udp_lh, list) { if (info->local.port == BE2HOST_WORD(udp_header->dst_port) && (info->remote.port == 0 || @@ -147,15 +143,12 @@ ProtocolResult udp_recv(NetBuffer *net_buffer, Ipv4Header *ipv4_header) { NetworkConnection *conn = container_of(info, NetworkConnection, ipv4.conn_info); if (memcmp(info->local.ip, ipv4_header->dst_ip, 4)) { - if ((memcmp( - conn->net_device->ipv4.ip, (void *)&ipv4_null_addr, - 4)) && // 本机已有IP地址 - (memcmp( + if (memcmp( info->local.ip, (void *)&ipv4_null_addr, - 4) || // 不是发送到0.0.0.0 + 4) != 0 && // 不是发送到0.0.0.0 memcmp( ipv4_header->dst_ip, (void *)&ipv4_broadcast_addr, - 4))) // 也不是广播 + 4) != 0) // 也不是广播 continue; } From 55dd7e0aa6cd13992c896d68bbe6915c4241a7e4 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 15 Sep 2025 20:00:18 +0800 Subject: [PATCH 106/158] =?UTF-8?q?ipv4:=20=E4=BF=AE=E5=A4=8D=20DF?= =?UTF-8?q?=E6=A0=87=E5=BF=97=E8=AE=BE=E7=BD=AE=E9=94=99=E8=AF=AF=E7=9A=84?= =?UTF-8?q?bug=EF=BC=9B=20conn&tcp&udp:=20=E6=96=B0=E5=A2=9E=20=E9=80=9A?= =?UTF-8?q?=E7=94=A8=E8=BF=9E=E6=8E=A5=E7=8A=B6=E6=80=81=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- src/driver/network/conn.c | 1 + src/driver/network/protocols/ipv4/ipv4.c | 2 +- src/driver/network/protocols/tcp.c | 17 +++++++++++++---- src/driver/network/protocols/udp.c | 2 ++ src/include/driver/network/conn.h | 11 ++++++++++- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 521dbee..b7f2f63 100644 --- a/Makefile +++ b/Makefile @@ -110,7 +110,7 @@ qemu_dbg: -device usb-kbd \ -device usb-mouse \ -device rtl8139,netdev=nc1 \ - -netdev vmnet-host,id=nc1 \ + -netdev user,id=nc1 \ -object filter-dump,id=f1,netdev=nc1,file=dump.pcap \ -readconfig $(QEMU_CFG) \ -boot c diff --git a/src/driver/network/conn.c b/src/driver/network/conn.c index cad92e7..b2b090e 100644 --- a/src/driver/network/conn.c +++ b/src/driver/network/conn.c @@ -18,6 +18,7 @@ NetworkConnection *net_create_conn(Object *object) { conn->object = object; conn->handle = object_handle_create(object); conn->net_device = object->value.device->dm_ext; + conn->state = CONN_STATE_INIT; conn->thread = get_current_thread(); diff --git a/src/driver/network/protocols/ipv4/ipv4.c b/src/driver/network/protocols/ipv4/ipv4.c index b4f0186..3bb4a90 100644 --- a/src/driver/network/protocols/ipv4/ipv4.c +++ b/src/driver/network/protocols/ipv4/ipv4.c @@ -108,7 +108,7 @@ ProtocolResult ipv4_wrap( ipv4_header->id = HOST2BE_WORD(conn->ipv4.id); ipv4_header->flags_frag_offset = HOST2BE_WORD( - conn->ipv4.fragment.enable_fragment << 14 | + (!conn->ipv4.fragment.enable_fragment) << 14 | conn->ipv4.fragment.last_fragment << 15 | conn->ipv4.fragment.frag_offset); diff --git a/src/driver/network/protocols/tcp.c b/src/driver/network/protocols/tcp.c index 7876845..2cd5136 100644 --- a/src/driver/network/protocols/tcp.c +++ b/src/driver/network/protocols/tcp.c @@ -142,7 +142,7 @@ ProtocolResult tcp_bind(NetworkConnection *conn, uint16_t port) { conn_info->local.port = port; Tcp *tcp = conn->tcp.info; - tcp->mss = conn->mtu - sizeof(Ipv4Header) - sizeof(TcpHeader); + tcp->mss = conn->pmtu - sizeof(Ipv4Header) - sizeof(TcpHeader); tcp->cur.seq = 0; tcp->cur.ack = 0; tcp->state = TCP_STATE_CLOSED; @@ -217,7 +217,8 @@ ProtocolResult tcp_connect( conn_wrap(conn, PROTO_LEVEL_NETWORK); - tcp->state = TCP_STATE_SYN_SENT; + tcp->state = TCP_STATE_SYN_SENT; + conn->state = CONN_STATE_OPENING; timer_set_timeout( &tcp->timeout_timer, timer_count_ms(&tcp->timeout_timer, tcp->rto)); @@ -299,6 +300,7 @@ ProtocolResult tcp_half_close(NetworkConnection *conn, Tcp *tcp) { net_buffer_clean_data(conn->buffer); tcp->header->flags = TCP_FLAG_FIN | TCP_FLAG_ACK; tcp->state = TCP_STATE_FIN_WAIT1; + conn->state = CONN_STATE_CLOSING; kfree(tcp->send_window); tcp->send.window = 0; @@ -466,7 +468,8 @@ void tcp_timeout_handler(void *arg) { break; case TCP_STATE_TIME_WAIT: // 2MSL时间到,关闭连接 - tcp->state = TCP_STATE_CLOSED; + tcp->state = TCP_STATE_CLOSED; + tcp->conn->state = CONN_STATE_CLOSED; kfree(tcp->recv_window); tcp->recv_window = NULL; break; @@ -514,7 +517,10 @@ void tcp_rx_handler( uint32_t ack = BE2HOST_DWORD(tcp_header->ack); uint8_t extra_flags = 0; - if (tcp_header->flags & TCP_FLAG_RST) { tcp->state = TCP_STATE_CLOSED; } + if (tcp_header->flags & TCP_FLAG_RST) { + tcp->state = TCP_STATE_CLOSED; + conn->state = CONN_STATE_CLOSED; + } TcpOptionIndex indexes[TOI_MAX] = {TOI_MAX}; tcp_options_handler(tcp_header, indexes); @@ -568,6 +574,7 @@ void tcp_rx_handler( if (ack_flag) { tcp->cur.seq = ack; tcp->state = TCP_STATE_ESTABLISHED; + conn->state = CONN_STATE_OPENED; } net_buffer_clean_data(tcp->conn->buffer); tcp_ack(conn, tcp, extra_flags); @@ -579,6 +586,7 @@ void tcp_rx_handler( tcp->cur.seq = ack; tcp->cur.ack = seq + 1; tcp->state = TCP_STATE_CLOSE_WAIT; + conn->state = CONN_STATE_CLOSING; net_buffer_clean_data(tcp->conn->buffer); tcp_ack(conn, tcp, extra_flags); break; @@ -633,6 +641,7 @@ void tcp_rx_handler( if (ack_flag && ack == tcp->cur.seq + 1) { tcp->cur.seq = ack; tcp->state = TCP_STATE_CLOSED; + conn->state = CONN_STATE_CLOSED; thread_unblock(tcp->thread); } break; diff --git a/src/driver/network/protocols/udp.c b/src/driver/network/protocols/udp.c index ea6696c..8e926b9 100644 --- a/src/driver/network/protocols/udp.c +++ b/src/driver/network/protocols/udp.c @@ -102,12 +102,14 @@ void udp_bind(NetworkConnection *conn, uint16_t port) { if (list_in_list(&conn_info->list)) return; // 已经绑定了端口 conn_info->local.port = port; list_add_tail(&conn_info->list, &udp_lh); + conn->state = CONN_STATE_OPENED; } void udp_unbind(NetworkConnection *conn) { Ipv4ConnInfo *conn_info = &conn->ipv4.conn_info; if (!list_in_list(&conn_info->list)) return; // 没有绑定端口 list_del(&conn_info->list); + conn->state = CONN_STATE_CLOSED; } ProtocolResult udp_recv(NetBuffer *net_buffer, Ipv4Header *ipv4_header) { diff --git a/src/include/driver/network/conn.h b/src/include/driver/network/conn.h index e67129f..3600ed9 100644 --- a/src/include/driver/network/conn.h +++ b/src/include/driver/network/conn.h @@ -30,6 +30,15 @@ typedef struct NetworkConnection { Object *object; ObjectHandle *handle; NetworkDevice *net_device; + enum { + CONN_STATE_INIT, + CONN_STATE_OPENING, + CONN_STATE_OPENED, + CONN_STATE_CLOSING, + CONN_STATE_CLOSED, + CONN_STATE_HOST_UNREACHABLE, + CONN_STATE_NET_UNREACHABLE, + } state; NetBuffer *buffer; @@ -45,7 +54,7 @@ typedef struct NetworkConnection { uint8_t mac[6]; } ethernet; }; - int mtu; + int pmtu; // data link layer protocol enum { From 0315a9d7d3320a3e7e86291d7dfe8e9f0e9e896d Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 15 Sep 2025 20:01:05 +0800 Subject: [PATCH 107/158] =?UTF-8?q?icmp:=20=E6=96=B0=E5=A2=9E=20UNREACHABL?= =?UTF-8?q?E=E6=B6=88=E6=81=AF=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/ethernet/ethernet.c | 2 +- src/driver/network/protocols/ipv4/icmp.c | 54 ++++++++++---- src/driver/network/protocols/tcp.c | 71 +++++++++++++++++++ src/driver/network/protocols/udp.c | 36 +++++++++- .../driver/network/protocols/ipv4/icmp.h | 11 +++ src/include/driver/network/protocols/tcp.h | 3 + src/include/driver/network/protocols/udp.h | 2 + 7 files changed, 161 insertions(+), 18 deletions(-) diff --git a/src/driver/network/ethernet/ethernet.c b/src/driver/network/ethernet/ethernet.c index 343fa4a..073b241 100644 --- a/src/driver/network/ethernet/ethernet.c +++ b/src/driver/network/ethernet/ethernet.c @@ -44,7 +44,7 @@ void eth_register(NetworkConnection *conn) { EthernetDevice *eth_device = conn->net_device->ethernet; conn->phy_protocol = PHY_PROTO_ETHERNET; eth_get_mac_address(eth_device, conn->ethernet.mac); - conn->mtu = ETH_MTU; + conn->pmtu = ETH_MTU; NET_BUF_RESV_HEAD(conn, 14); } diff --git a/src/driver/network/protocols/ipv4/icmp.c b/src/driver/network/protocols/ipv4/icmp.c index c804449..6a1eb65 100644 --- a/src/driver/network/protocols/ipv4/icmp.c +++ b/src/driver/network/protocols/ipv4/icmp.c @@ -3,21 +3,24 @@ #include #include #include +#include +#include #include -ProtocolResult icmp_recv_unsupport( - NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, - IcmpHeader *icmp_header, ProtocolReplyCallback *stack, int stack_size); -ProtocolResult icmp_recv_echo_message( - NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, - IcmpHeader *icmp_header, ProtocolReplyCallback *stack, int stack_size); +#define ICMP_RECV_MSG_DEF(type) \ + ProtocolResult icmp_recv_##type( \ + NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, \ + IcmpHeader *icmp_header, ProtocolReplyCallback *stack, int stack_size) +ICMP_RECV_MSG_DEF(unsupport); +ICMP_RECV_MSG_DEF(unreachable); +ICMP_RECV_MSG_DEF(echo); ProtocolResult (*icmp_recv_handlers[17])( NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, IcmpHeader *icmp_header, ProtocolReplyCallback *stack, int stack_size) = { - [ICMP_TYPE_ECHO] = icmp_recv_echo_message, + [ICMP_TYPE_ECHO] = icmp_recv_echo, [ICMP_TYPE_ECHO_REPLY] = icmp_recv_unsupport, - [ICMP_TYPE_DEST_UNREACHABLE] = icmp_recv_unsupport, + [ICMP_TYPE_DEST_UNREACHABLE] = icmp_recv_unreachable, [ICMP_TYPE_SOURCE_QUENCH] = icmp_recv_unsupport, [ICMP_TYPE_REDIRECT] = icmp_recv_unsupport, [ICMP_TYPE_TIME_EXCEEDED] = icmp_recv_unsupport, @@ -65,15 +68,38 @@ ProtocolResult icmp_recv( return PROTO_ERROR_UNSUPPORT; } -ProtocolResult icmp_recv_unsupport( - NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, - IcmpHeader *icmp_header, ProtocolReplyCallback *stack, int stack_size) { +ICMP_RECV_MSG_DEF(unsupport) { return PROTO_ERROR_UNSUPPORT; } -ProtocolResult icmp_recv_echo_message( - NetworkDevice *device, NetBuffer *net_buffer, Ipv4Header *header, - IcmpHeader *icmp_header, ProtocolReplyCallback *stack, int stack_size) { +ICMP_RECV_MSG_DEF(unreachable) { + Ipv4Header *msg_header = + (Ipv4Header *)(icmp_header + 8); // ICMP头部后面紧跟着的是IP头部 + switch (icmp_header->code) { + case ICMP_UNREACHABLE_NET: + case ICMP_UNREACHABLE_HOST: + case ICMP_UNREACHABLE_PROTOCOL: + case ICMP_UNREACHABLE_PORT: + tcp_notify_unreachable( + msg_header + 1, msg_header->src_ip, msg_header->dst_ip, 4, + icmp_header->code); + udp_notify_unreachable( + msg_header + 1, msg_header->src_ip, msg_header->dst_ip, 4, + icmp_header->code); + break; + case ICMP_UNREACHABLE_NEEDFRAG: + tcp_update_mtu( + msg_header->src_ip, msg_header->dst_ip, 4, + BE2HOST_WORD(icmp_header->pmtu.mtu)); + break; + case ICMP_UNREACHABLE_SRCFAIL: + default: + return PROTO_ERROR_UNSUPPORT; + } + return PROTO_OK; +} + +ICMP_RECV_MSG_DEF(echo) { if (net_buffer->tail - net_buffer->data < 8) { return PROTO_ERROR_UNSUPPORT; } diff --git a/src/driver/network/protocols/tcp.c b/src/driver/network/protocols/tcp.c index 2cd5136..a5d1a05 100644 --- a/src/driver/network/protocols/tcp.c +++ b/src/driver/network/protocols/tcp.c @@ -18,6 +18,7 @@ #include "kernel/thread.h" #include "math.h" #include +#include #include #include #include @@ -695,3 +696,73 @@ ProtocolResult tcp_recv( kfree(net_buffer); return PROTO_DROP; } + +void tcp_notify_unreachable( + void *data, uint8_t *src_ip, uint8_t *dst_ip, int ip_len, int code) { + Ipv4ConnInfo *info, *next; + NetworkConnection *conn; + TcpHeader *header = (TcpHeader *)data; + bool flag = false; + + spin_lock(&tcp_lock); + list_for_each_owner_safe (info, next, &tcp_lh, list) { + if (info->local.port == BE2HOST_WORD(header->dest_port) && + (info->remote.port == BE2HOST_WORD(header->src_port))) { + if (memcmp(info->local.ip, dst_ip, ip_len) == 0 && + memcmp(info->remote.ip, src_ip, ip_len) == 0) { + flag = true; + break; + } + } + } + spin_unlock(&tcp_lock); + if (!flag) return; + + conn = container_of(info, NetworkConnection, ipv4.conn_info); + switch (code) { + case ICMP_UNREACHABLE_NET: + tcp_reset_conn(conn, conn->tcp.info); + conn->state = CONN_STATE_NET_UNREACHABLE; + break; + case ICMP_UNREACHABLE_HOST: + tcp_reset_conn(conn, conn->tcp.info); + conn->state = CONN_STATE_HOST_UNREACHABLE; + break; + default: + break; + } +} + +void tcp_update_mtu(uint8_t *src_ip, uint8_t *dst_ip, int ip_len, int mtu) { + Ipv4ConnInfo *info, *next; + NetworkConnection *conn; + bool flag = false; + + spin_lock(&tcp_lock); + list_for_each_owner_safe (info, next, &tcp_lh, list) { + // if (memcmp(info->local.ip, dst_ip, ip_len) == 0 && + // memcmp(info->remote.ip, src_ip, ip_len) == 0) { + flag = true; + break; + // } + } + spin_unlock(&tcp_lock); + if (!flag) return; + + conn = container_of(info, NetworkConnection, ipv4.conn_info); + Tcp *tcp = conn->tcp.info; + if (mtu < conn->pmtu && mtu > 0) { + mtu = MIN(MAX(IPv4_DEFAULT_MSS, mtu), conn->pmtu); + conn->pmtu = mtu; + tcp->mss = mtu - sizeof(Ipv4Header) - sizeof(TcpHeader); + if (conn->state == CONN_STATE_OPENED) { + conn->buffer->tail = + MIN(conn->buffer->tail, conn->buffer->data + tcp->mss); + ipv4_rewrap(conn); + NETWORK_SEND(conn->net_device, conn); + } + } else if (mtu > conn->pmtu) { + conn->pmtu = mtu; + tcp->mss = mtu - sizeof(Ipv4Header) - sizeof(TcpHeader); + } +} diff --git a/src/driver/network/protocols/udp.c b/src/driver/network/protocols/udp.c index 8e926b9..f3f4690 100644 --- a/src/driver/network/protocols/udp.c +++ b/src/driver/network/protocols/udp.c @@ -146,10 +146,10 @@ ProtocolResult udp_recv(NetBuffer *net_buffer, Ipv4Header *ipv4_header) { container_of(info, NetworkConnection, ipv4.conn_info); if (memcmp(info->local.ip, ipv4_header->dst_ip, 4)) { if (memcmp( - info->local.ip, (void *)&ipv4_null_addr, + info->local.ip, (void *)&ipv4_null_addr, 4) != 0 && // 不是发送到0.0.0.0 - memcmp( - ipv4_header->dst_ip, (void *)&ipv4_broadcast_addr, + memcmp( + ipv4_header->dst_ip, (void *)&ipv4_broadcast_addr, 4) != 0) // 也不是广播 continue; } @@ -171,3 +171,33 @@ ProtocolResult udp_recv(NetBuffer *net_buffer, Ipv4Header *ipv4_header) { kfree(net_buffer); return PROTO_DROP; } + +void udp_notify_unreachable( + void *data, uint8_t *src_ip, uint8_t *dst_ip, int ip_len, int code) { + Ipv4ConnInfo *info, *next; + NetworkConnection *conn; + UdpHeader *udp_header = (UdpHeader *)data; + + bool flag = false; + list_for_each_owner_safe (info, next, &udp_lh, list) { + if (info->local.port == BE2HOST_WORD(udp_header->dst_port) && + (info->remote.port == 0 || + info->remote.port == BE2HOST_WORD(udp_header->src_port))) { + conn = container_of(info, NetworkConnection, ipv4.conn_info); + if (memcmp(info->local.ip, dst_ip, 4)) { + if (memcmp( + info->local.ip, (void *)&ipv4_null_addr, + 4) != 0 && // 不是发送到0.0.0.0 + memcmp( + dst_ip, (void *)&ipv4_broadcast_addr, + 4) != 0) // 也不是广播 + continue; + } + + // 找到匹配的连接 + flag = true; + break; + } + } + if (!flag) return; +} diff --git a/src/include/driver/network/protocols/ipv4/icmp.h b/src/include/driver/network/protocols/ipv4/icmp.h index c3a5778..d3adcb5 100644 --- a/src/include/driver/network/protocols/ipv4/icmp.h +++ b/src/include/driver/network/protocols/ipv4/icmp.h @@ -19,6 +19,13 @@ #define ICMP_TYPE_INFO_REQUEST 15 #define ICMP_TYPE_INFO_REPLY 16 +#define ICMP_UNREACHABLE_NET 0 +#define ICMP_UNREACHABLE_HOST 1 +#define ICMP_UNREACHABLE_PROTOCOL 2 +#define ICMP_UNREACHABLE_PORT 3 +#define ICMP_UNREACHABLE_NEEDFRAG 4 +#define ICMP_UNREACHABLE_SRCFAIL 5 + typedef struct { uint8_t type; uint8_t code; @@ -29,6 +36,10 @@ typedef struct { uint8_t pointer; uint8_t unused[3]; } param; + struct { + uint16_t unused; + uint16_t mtu; + } pmtu; uint8_t gateway_ip[4]; struct { uint16_t id; diff --git a/src/include/driver/network/protocols/tcp.h b/src/include/driver/network/protocols/tcp.h index 0f4a05a..7b168ef 100644 --- a/src/include/driver/network/protocols/tcp.h +++ b/src/include/driver/network/protocols/tcp.h @@ -176,5 +176,8 @@ ProtocolResult tcp_shutdown(NetworkConnection *conn, uint8_t how); ProtocolResult tcp_recv( NetBuffer *net_buffer, int length, uint8_t *src_ip, uint8_t *dst_ip, int ip_len); +void tcp_notify_unreachable( + void *data, uint8_t *src_ip, uint8_t *dst_ip, int ip_len, int code); +void tcp_update_mtu(uint8_t *src_ip, uint8_t *dst_ip, int ip_len, int mtu); #endif \ No newline at end of file diff --git a/src/include/driver/network/protocols/udp.h b/src/include/driver/network/protocols/udp.h index 0196a6f..68e48ab 100644 --- a/src/include/driver/network/protocols/udp.h +++ b/src/include/driver/network/protocols/udp.h @@ -25,5 +25,7 @@ void udp_set_callback( void udp_bind(struct NetworkConnection *conn, uint16_t port); void udp_unbind(struct NetworkConnection *conn); ProtocolResult udp_recv(NetBuffer *net_buffer, Ipv4Header *ipv4_header); +void udp_notify_unreachable( + void *data, uint8_t *src_ip, uint8_t *dst_ip, int ip_len, int code); #endif \ No newline at end of file From 83b7bf6adf7cd0f3f47f100114f143f46e33d062 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 16 Sep 2025 00:15:23 +0800 Subject: [PATCH 108/158] =?UTF-8?q?RTL8139:=20=E5=A2=9E=E5=A4=A7=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E7=BC=93=E5=86=B2=E5=8C=BA=E5=A4=A7=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/network/rtl8139/rtl8139.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/x86/drivers/network/rtl8139/rtl8139.h b/src/arch/x86/drivers/network/rtl8139/rtl8139.h index 2117d94..ced4bcb 100644 --- a/src/arch/x86/drivers/network/rtl8139/rtl8139.h +++ b/src/arch/x86/drivers/network/rtl8139/rtl8139.h @@ -108,7 +108,7 @@ #define MXDMA RCR_MXDMA(MXDMA_1024B) #define RXFTH_NONE RCR_RXFTH(0x07) -#define RECV_BUF_LEN RBLEN_16K +#define RECV_BUF_LEN RBLEN_64K #define RBLEN RCR_RBLEN(RECV_BUF_LEN) #define RTL8139_RECV_BUF_SIZE (8192 << RECV_BUF_LEN) From 355f1fb0b86535b739da5d12977032ea2cc73e93 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 16 Sep 2025 00:16:43 +0800 Subject: [PATCH 109/158] =?UTF-8?q?tcp:=20=E4=BF=AE=E5=A4=8D=20=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E8=BF=9E=E6=8E=A5=E8=BF=87=E7=A8=8B=E4=B8=ADack?= =?UTF-8?q?=E7=9A=84=E5=A4=84=E7=90=86=E9=94=99=E8=AF=AF=EF=BC=9B=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20tcp=5Frecv=5Fdata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/protocols/tcp.c | 79 ++++++++++++++----- .../driver/network/protocols/protocols.h | 4 + src/include/driver/network/protocols/tcp.h | 3 + 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/src/driver/network/protocols/tcp.c b/src/driver/network/protocols/tcp.c index a5d1a05..3479b8a 100644 --- a/src/driver/network/protocols/tcp.c +++ b/src/driver/network/protocols/tcp.c @@ -13,6 +13,7 @@ #include "driver/network/network_dm.h" #include "driver/network/protocols/protocols.h" #include "driver/timer_dm.h" +#include "kernel/console.h" #include "kernel/memory.h" #include "kernel/spinlock.h" #include "kernel/thread.h" @@ -46,7 +47,7 @@ const int tcp_fin_timeout = 60 * 1000; void tcp_timeout_handler(void *arg); void tcp_reset_conn(NetworkConnection *conn, Tcp *tcp); -void tcp_send(Tcp *tcp, NetworkConnection *conn, bool set_timer); +void tcp_send_packet(Tcp *tcp, NetworkConnection *conn, bool set_timer); uint16_t tcp_checksum( TcpHeader *header, int length, const uint8_t *src_ip, const uint8_t *dst_ip, @@ -292,7 +293,44 @@ ProtocolResult tcp_send_data( net_buffer_put(conn_buffer(conn), total_size); tcp->header->flags = TCP_FLAG_PSH; tcp->header->flags |= TCP_FLAG_ACK; - tcp_send(tcp, conn, true); + tcp_send_packet(tcp, conn, true); + return PROTO_OK; +} + +ProtocolResult tcp_recv_data(Tcp *tcp, void *buffer, uint32_t *length) { + if (tcp == NULL || buffer == NULL || length == NULL) + return PROTO_ERROR_NULL_PTR; + uint32_t next = tcp->recv.next; + uint32_t read = tcp->recv.read; + uint32_t len = *length; + int real_length; + if (next >= read) { + real_length = MIN(len, next - read); + memcpy(buffer, tcp->recv_window + read, real_length); + tcp->recv.read += real_length; + } else { + int size1 = MIN(len, tcp->recv.total_size - read); + int size2 = MIN(len - size1, next); + real_length = size1 + size2; + memcpy(buffer, tcp->recv_window + read, size1); + memcpy((uint8_t *)buffer + size1, tcp->recv_window, size2); + tcp->recv.read += size1 + size2; + } + if (real_length == 0) { + switch (tcp->conn->state) { + case CONN_STATE_INIT: + case CONN_STATE_OPENING: + case CONN_STATE_CLOSED: + return PROTO_ERROR_NOT_CONNECTED; + case CONN_STATE_NET_UNREACHABLE: + return PROTO_ERROR_NET_UNREACHABLE; + case CONN_STATE_HOST_UNREACHABLE: + return PROTO_ERROR_HOST_UNREACHABLE; + default: + break; + } + } + *length = real_length; return PROTO_OK; } @@ -306,7 +344,7 @@ ProtocolResult tcp_half_close(NetworkConnection *conn, Tcp *tcp) { kfree(tcp->send_window); tcp->send.window = 0; tcp->send_window = NULL; - tcp_send(tcp, conn, true); + tcp_send_packet(tcp, conn, true); return PROTO_OK; } @@ -361,7 +399,7 @@ void tcp_reset_conn(NetworkConnection *conn, Tcp *tcp) { NETWORK_SEND(conn->net_device, conn); } -void tcp_send(Tcp *tcp, NetworkConnection *conn, bool set_timer) { +void tcp_send_packet(Tcp *tcp, NetworkConnection *conn, bool set_timer) { TcpHeader *tcp_header = tcp->header; tcp_header->seq = HOST2BE_DWORD(tcp->cur.seq); tcp_header->ack = HOST2BE_DWORD(tcp->cur.ack); @@ -377,6 +415,10 @@ void tcp_send(Tcp *tcp, NetworkConnection *conn, bool set_timer) { tcp->send_time = timer_get_counter(); tcp->send_seq = tcp->cur.seq; } + if (tcp_header->flags & TCP_FLAG_FIN) { + // 记录FIN的序号,用于后续确认 + tcp->cur.fin_seq = tcp->cur.seq; + } // 如果没有设置重传计时则设置一个 if (set_timer && timer_is_timeout(&tcp->timeout_timer)) { timer_set_timeout( @@ -395,7 +437,7 @@ void tcp_ack(NetworkConnection *conn, Tcp *tcp, uint8_t extra_flag) { tcp_header->flags = extra_flag; tcp_header->flags |= TCP_FLAG_ACK; - tcp_send(tcp, conn, true); + tcp_send_packet(tcp, conn, true); } void tcp_ack_handler( @@ -458,7 +500,7 @@ void tcp_timeout_handler(void *arg) { &tcp->timeout_timer, timer_count_ms(&tcp->timeout_timer, tcp->rto)); timer_callback_enable(&tcp->timeout_timer); - tcp_send(tcp, tcp->conn, true); + tcp_send_packet(tcp, tcp->conn, true); } else { tcp_reset_conn(tcp->conn, tcp); } @@ -585,18 +627,19 @@ void tcp_rx_handler( tcp_ack_handler(tcp, tcp_header, net_buffer, length); if (tcp_header->flags & TCP_FLAG_FIN) { tcp->cur.seq = ack; - tcp->cur.ack = seq + 1; - tcp->state = TCP_STATE_CLOSE_WAIT; - conn->state = CONN_STATE_CLOSING; + tcp->cur.ack++; + tcp->state = TCP_STATE_CLOSE_WAIT; + conn->state = CONN_STATE_CLOSING; net_buffer_clean_data(tcp->conn->buffer); tcp_ack(conn, tcp, extra_flags); break; } break; case TCP_STATE_CLOSING: - if (ack_flag && ack == tcp->cur.seq + 1) { + if (ack_flag) tcp_ack_handler(tcp, tcp_header, net_buffer, length); + if (ack_flag && ack > tcp->cur.fin_seq) { tcp->cur.seq = ack; - tcp->state = TCP_STATE_CLOSE_WAIT; + tcp->state = TCP_STATE_TIME_WAIT; extra_flags |= TCP_FLAG_FIN; } net_buffer_clean_data(tcp->conn->buffer); @@ -607,7 +650,7 @@ void tcp_rx_handler( break; case TCP_STATE_FIN_WAIT1: if (ack_flag) tcp_ack_handler(tcp, tcp_header, net_buffer, length); - if (ack_flag && ack == tcp->cur.seq + 1) { + if (ack_flag && ack > tcp->cur.fin_seq) { tcp->cur.seq = ack; tcp->state = TCP_STATE_FIN_WAIT2; extra_flags |= TCP_FLAG_FIN; @@ -619,15 +662,15 @@ void tcp_rx_handler( timer_callback_enable(&tcp->timeout_timer); } if (tcp_header->flags & TCP_FLAG_FIN) { - tcp->cur.ack = seq + 1; - tcp->state = TCP_STATE_CLOSING; + tcp->cur.ack++; + tcp->state = TCP_STATE_CLOSING; } break; case TCP_STATE_FIN_WAIT2: if (ack_flag) tcp_ack_handler(tcp, tcp_header, net_buffer, length); if (tcp_header->flags & TCP_FLAG_FIN) { - tcp->cur.ack = seq + 1; - tcp->state = TCP_STATE_TIME_WAIT; + tcp->cur.ack++; + tcp->state = TCP_STATE_TIME_WAIT; extra_flags |= TCP_FLAG_ACK; timer_callback_cancel(&tcp->timeout_timer); @@ -639,17 +682,17 @@ void tcp_rx_handler( } break; case TCP_STATE_LAST_ACK: - if (ack_flag && ack == tcp->cur.seq + 1) { + if (ack_flag && ack > tcp->cur.fin_seq) { tcp->cur.seq = ack; tcp->state = TCP_STATE_CLOSED; conn->state = CONN_STATE_CLOSED; - thread_unblock(tcp->thread); } break; case TCP_STATE_TIME_WAIT: tcp_reset_conn(conn, tcp); break; } + thread_unblock(tcp->thread); } ProtocolResult tcp_recv( diff --git a/src/include/driver/network/protocols/protocols.h b/src/include/driver/network/protocols/protocols.h index 5643fd0..e8dfbd8 100644 --- a/src/include/driver/network/protocols/protocols.h +++ b/src/include/driver/network/protocols/protocols.h @@ -17,6 +17,10 @@ typedef enum { PROTO_ERROR_CANNOT_FIND, PROTO_ERROR_NO_SPACE_LEFT, PROTO_ERROR_CANNOT_FIND_ROUTE, + PROTO_ERROR_NOT_CONNECTED, + PROTO_ERROR_NET_UNREACHABLE, + PROTO_ERROR_HOST_UNREACHABLE, + PROTO_ERROR_PORT_UNREACHABLE, PROTO_ERROR_OTHER, } ProtocolResult; diff --git a/src/include/driver/network/protocols/tcp.h b/src/include/driver/network/protocols/tcp.h index 7b168ef..8803558 100644 --- a/src/include/driver/network/protocols/tcp.h +++ b/src/include/driver/network/protocols/tcp.h @@ -158,6 +158,8 @@ typedef struct Tcp { uint32_t window; // segment window uint32_t urg_p; // segment urgent pointer uint32_t prc; // segment precedence value + + uint32_t fin_seq; } cur; uint32_t send_time, send_seq; @@ -171,6 +173,7 @@ ProtocolResult tcp_bind(NetworkConnection *conn, uint16_t port); ProtocolResult tcp_connect( NetworkConnection *conn, uint8_t *dst_ip, uint16_t dst_port); ProtocolResult tcp_send_data(NetworkConnection *conn, uint8_t *buf, int length); +ProtocolResult tcp_recv_data(Tcp *tcp, void *buffer, uint32_t *length); void tcp_reset(NetworkConnection *conn); ProtocolResult tcp_shutdown(NetworkConnection *conn, uint8_t how); ProtocolResult tcp_recv( From e4f4e303e03c43b1eadf792c7d6310567a6344be Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 16 Sep 2025 01:26:08 +0800 Subject: [PATCH 110/158] =?UTF-8?q?tcp:=20=E6=96=B0=E5=A2=9E=20tcp=5Fliste?= =?UTF-8?q?n=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/network/protocols/tcp.c | 127 +++++++++++++++++---- src/include/driver/network/protocols/tcp.h | 1 + 2 files changed, 105 insertions(+), 23 deletions(-) diff --git a/src/driver/network/protocols/tcp.c b/src/driver/network/protocols/tcp.c index 3479b8a..bd6cc09 100644 --- a/src/driver/network/protocols/tcp.c +++ b/src/driver/network/protocols/tcp.c @@ -47,7 +47,8 @@ const int tcp_fin_timeout = 60 * 1000; void tcp_timeout_handler(void *arg); void tcp_reset_conn(NetworkConnection *conn, Tcp *tcp); -void tcp_send_packet(Tcp *tcp, NetworkConnection *conn, bool set_timer); +void tcp_send_packet( + Tcp *tcp, NetworkConnection *conn, uint8_t option_size, bool set_timer); uint16_t tcp_checksum( TcpHeader *header, int length, const uint8_t *src_ip, const uint8_t *dst_ip, @@ -244,6 +245,44 @@ ProtocolResult tcp_connect( return PROTO_OK; } +ProtocolResult tcp_listen(NetworkConnection *conn) { + if (conn->tcp.info == NULL) { return PROTO_ERROR_NULL_PTR; } + Tcp *tcp = conn->tcp.info; + if (tcp->state != TCP_STATE_CLOSED) return PROTO_ERROR_REBIND; + + net_buffer_header_alloc(conn->buffer, sizeof(TcpHeader)); + tcp->header = (TcpHeader *)conn->buffer->head; + + tcp->mss = conn->pmtu - sizeof(Ipv4Header) - sizeof(TcpHeader); + tcp->cur.seq = 0; + tcp->cur.ack = 0; + tcp->state = TCP_STATE_LISTEN; + tcp->recv_window = kmalloc(recv_win_default_size); + tcp->recv.next = 0; + tcp->recv.window = recv_win_default_size; + tcp->recv.total_size = recv_win_default_size; + tcp->recv.read = 0; + tcp->rttvar = tcp->rto = tcp->srtt = 0; + tcp_compute_retransmission_timer(tcp, 0); + timer_init(&tcp->timeout_timer); + tcp->timeout_timer.callback = tcp_timeout_handler; + tcp->timeout_timer.arg = tcp; + conn_wrap(conn, PROTO_LEVEL_NETWORK); + + thread_set_status(TASK_INTERRUPTIBLE); + thread_wait(); + + tcp->send.unack = 0; + tcp->send.next = 0; + tcp->send.wl1 = tcp->cur.ack; + tcp->send.wl2 = tcp->cur.seq; + tcp->send.total_size = send_win_default_size; + tcp->send.window = MIN(tcp->send.total_size, tcp->send.remote_window_size); + tcp->send_window = kmalloc(tcp->send.total_size); + tcp->send_time = timer_get_counter(); + return PROTO_OK; +} + ProtocolResult tcp_send_data( NetworkConnection *conn, uint8_t *buf, int length) { if (conn == NULL || buf == NULL || length <= 0) { @@ -273,6 +312,7 @@ ProtocolResult tcp_send_data( used_space += length; // 发送数据 + net_buffer_clean_data(tcp->conn->buffer); int total_size = 0; int max = MIN(tcp->mss, tcp->send.window); if (tcp->send.unack < tcp->send.next) { @@ -293,7 +333,7 @@ ProtocolResult tcp_send_data( net_buffer_put(conn_buffer(conn), total_size); tcp->header->flags = TCP_FLAG_PSH; tcp->header->flags |= TCP_FLAG_ACK; - tcp_send_packet(tcp, conn, true); + tcp_send_packet(tcp, conn, 0, true); return PROTO_OK; } @@ -344,7 +384,7 @@ ProtocolResult tcp_half_close(NetworkConnection *conn, Tcp *tcp) { kfree(tcp->send_window); tcp->send.window = 0; tcp->send_window = NULL; - tcp_send_packet(tcp, conn, true); + tcp_send_packet(tcp, conn, 0, true); return PROTO_OK; } @@ -399,12 +439,13 @@ void tcp_reset_conn(NetworkConnection *conn, Tcp *tcp) { NETWORK_SEND(conn->net_device, conn); } -void tcp_send_packet(Tcp *tcp, NetworkConnection *conn, bool set_timer) { +void tcp_send_packet( + Tcp *tcp, NetworkConnection *conn, uint8_t option_size, bool set_timer) { TcpHeader *tcp_header = tcp->header; tcp_header->seq = HOST2BE_DWORD(tcp->cur.seq); tcp_header->ack = HOST2BE_DWORD(tcp->cur.ack); tcp_header->window_size = HOST2BE_WORD(tcp->recv.window); - tcp_header->data_offset = ((sizeof(TcpHeader)) >> 2) << 4; + tcp_header->data_offset = ((sizeof(TcpHeader) + option_size) >> 2) << 4; tcp_header->checksum = tcp_checksum( tcp_header, CONN_CONTENT_SIZE(conn) + sizeof(TcpHeader), @@ -429,7 +470,9 @@ void tcp_send_packet(Tcp *tcp, NetworkConnection *conn, bool set_timer) { NETWORK_SEND(conn->net_device, conn); } -void tcp_ack(NetworkConnection *conn, Tcp *tcp, uint8_t extra_flag) { +void tcp_ack( + NetworkConnection *conn, Tcp *tcp, uint8_t option_size, + uint8_t extra_flag) { if (conn == NULL || tcp == NULL) return; TcpHeader *tcp_header = tcp->header; @@ -437,7 +480,7 @@ void tcp_ack(NetworkConnection *conn, Tcp *tcp, uint8_t extra_flag) { tcp_header->flags = extra_flag; tcp_header->flags |= TCP_FLAG_ACK; - tcp_send_packet(tcp, conn, true); + tcp_send_packet(tcp, conn, option_size, true); } void tcp_ack_handler( @@ -466,7 +509,7 @@ void tcp_ack_handler( tcp->send.wl1 = seq; tcp->cur.ack = seq + length; - tcp_ack(tcp->conn, tcp, 0); + tcp_ack(tcp->conn, tcp, 0, 0); } uint32_t acked = ack - tcp->send.wl2; @@ -478,6 +521,7 @@ void tcp_ack_handler( tcp->cur.seq += acked; net_buffer_clean_data(tcp->conn->buffer); } + printk("acked: %d seq=%d\n", acked, tcp->cur.seq - tcp->send.iss); } void tcp_timeout_handler(void *arg) { @@ -500,7 +544,7 @@ void tcp_timeout_handler(void *arg) { &tcp->timeout_timer, timer_count_ms(&tcp->timeout_timer, tcp->rto)); timer_callback_enable(&tcp->timeout_timer); - tcp_send_packet(tcp, tcp->conn, true); + tcp_send_packet(tcp, tcp->conn, 0, true); } else { tcp_reset_conn(tcp->conn, tcp); } @@ -552,7 +596,7 @@ void tcp_options_handler( void tcp_rx_handler( NetworkConnection *conn, TcpHeader *tcp_header, NetBuffer *net_buffer, - int length) { + int length, uint8_t *src_ip, int ip_len) { Tcp *tcp = conn->tcp.info; bool syn_flag = tcp_header->flags & TCP_FLAG_SYN; bool ack_flag = tcp_header->flags & TCP_FLAG_ACK; @@ -579,6 +623,17 @@ void tcp_rx_handler( tcp->mss = MIN(mss, tcp->mss); } + conn->ipv4.conn_info.remote.port = + BE2HOST_WORD(tcp_header->src_port); + memcpy(conn->ipv4.conn_info.remote.ip, src_ip, ip_len); + memcpy(conn->ipv4.header->dst_ip, src_ip, ip_len); + tcp->header->src_port = + HOST2BE_WORD(conn->ipv4.conn_info.local.port); + tcp->header->dest_port = + HOST2BE_WORD(conn->ipv4.conn_info.remote.port); + tcp->send.iss = tcp_generate_isn( + &conn->ipv4.conn_info, sizeof(Ipv4ConnInfo) - sizeof(list_t)); + tcp->cur.seq = tcp->send.iss; tcp->recv.irs = seq; tcp->cur.ack = seq + 1; tcp->send.remote_window_size = @@ -586,7 +641,11 @@ void tcp_rx_handler( tcp->state = TCP_STATE_SYN_RECEIVED; extra_flags |= TCP_FLAG_SYN; net_buffer_clean_data(tcp->conn->buffer); - tcp_ack(conn, tcp, extra_flags); + tcp_header->options[0] = TCP_OPTION_MSS; + tcp_header->options[1] = 4; + *(uint16_t *)(tcp_header->options + 2) = HOST2BE_WORD(tcp->mss); + net_buffer_put(tcp->conn->buffer, 4); + tcp_ack(conn, tcp, 4, extra_flags); } break; case TCP_STATE_SYN_SENT: @@ -602,7 +661,6 @@ void tcp_rx_handler( tcp->cur.ack = seq + 1; tcp->state = TCP_STATE_SYN_RECEIVED; } - case TCP_STATE_SYN_RECEIVED: if (indexes[TOI_MSS] < TOI_MAX) { uint16_t mss = BE2HOST_WORD( *(uint16_t *)(tcp_header->options + indexes[TOI_MSS])); @@ -610,17 +668,37 @@ void tcp_rx_handler( } timer_callback_cancel(&tcp->timeout_timer); // 处理ACK - if (ack != tcp->cur.seq + 1) { - tcp_reset_conn(conn, tcp); - break; - } if (ack_flag) { + if (ack != tcp->cur.seq + 1) { + tcp_reset_conn(conn, tcp); + break; + } tcp->cur.seq = ack; + conn->state = CONN_STATE_OPENED; tcp->state = TCP_STATE_ESTABLISHED; + } + net_buffer_clean_data(tcp->conn->buffer); + tcp_ack(conn, tcp, 0, extra_flags); + thread_unblock(tcp->thread); + break; + case TCP_STATE_SYN_RECEIVED: + if (indexes[TOI_MSS] < TOI_MAX) { + uint16_t mss = BE2HOST_WORD( + *(uint16_t *)(tcp_header->options + indexes[TOI_MSS])); + tcp->mss = MIN(mss, tcp->mss); + } + timer_callback_cancel(&tcp->timeout_timer); + // 处理ACK + if (ack_flag) { + if (ack != tcp->cur.seq + 1) { + tcp_reset_conn(conn, tcp); + break; + } + tcp->cur.seq = ack; conn->state = CONN_STATE_OPENED; + tcp->state = TCP_STATE_ESTABLISHED; } net_buffer_clean_data(tcp->conn->buffer); - tcp_ack(conn, tcp, extra_flags); thread_unblock(tcp->thread); break; case TCP_STATE_ESTABLISHED: @@ -631,7 +709,7 @@ void tcp_rx_handler( tcp->state = TCP_STATE_CLOSE_WAIT; conn->state = CONN_STATE_CLOSING; net_buffer_clean_data(tcp->conn->buffer); - tcp_ack(conn, tcp, extra_flags); + tcp_ack(conn, tcp, 0, extra_flags); break; } break; @@ -643,7 +721,7 @@ void tcp_rx_handler( extra_flags |= TCP_FLAG_FIN; } net_buffer_clean_data(tcp->conn->buffer); - tcp_ack(conn, tcp, extra_flags); + tcp_ack(conn, tcp, 0, extra_flags); break; case TCP_STATE_CLOSE_WAIT: tcp_reset_conn(conn, tcp); @@ -678,7 +756,7 @@ void tcp_rx_handler( timer_set_timeout(&tcp->timeout_timer, count); timer_callback_enable(&tcp->timeout_timer); net_buffer_clean_data(tcp->conn->buffer); - tcp_ack(conn, tcp, extra_flags); + tcp_ack(conn, tcp, 0, extra_flags); } break; case TCP_STATE_LAST_ACK: @@ -720,12 +798,15 @@ ProtocolResult tcp_recv( spin_lock(&tcp_lock); list_for_each_owner_safe (info, next, &tcp_lh, list) { if (info->local.port == BE2HOST_WORD(tcp_header->dest_port) && - (info->remote.port == BE2HOST_WORD(tcp_header->src_port))) { + (info->remote.port == BE2HOST_WORD(tcp_header->src_port) || + info->remote.port == 0)) { if (memcmp(info->local.ip, dst_ip, ip_len) == 0 && - memcmp(info->remote.ip, src_ip, ip_len) == 0) { + (memcmp(info->remote.ip, src_ip, ip_len) == 0 || + memcmp(info->remote.ip, &ipv4_null_addr, ip_len) == 0)) { NetworkConnection *conn = container_of(info, NetworkConnection, ipv4.conn_info); - tcp_rx_handler(conn, tcp_header, net_buffer, data_length); + tcp_rx_handler( + conn, tcp_header, net_buffer, data_length, src_ip, ip_len); spin_unlock(&tcp_lock); return PROTO_OK; diff --git a/src/include/driver/network/protocols/tcp.h b/src/include/driver/network/protocols/tcp.h index 8803558..a7cdb30 100644 --- a/src/include/driver/network/protocols/tcp.h +++ b/src/include/driver/network/protocols/tcp.h @@ -172,6 +172,7 @@ void tcp_register(NetworkConnection *conn); ProtocolResult tcp_bind(NetworkConnection *conn, uint16_t port); ProtocolResult tcp_connect( NetworkConnection *conn, uint8_t *dst_ip, uint16_t dst_port); +ProtocolResult tcp_listen(NetworkConnection *conn); ProtocolResult tcp_send_data(NetworkConnection *conn, uint8_t *buf, int length); ProtocolResult tcp_recv_data(Tcp *tcp, void *buffer, uint32_t *length); void tcp_reset(NetworkConnection *conn); From 95c90c0290e933a9a01402e5b0b52762d413f502 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 16 Sep 2025 21:53:48 +0800 Subject: [PATCH 111/158] =?UTF-8?q?isa:=20=E4=BF=AE=E5=A4=8D=20=E5=91=BD?= =?UTF-8?q?=E5=90=8D=E9=94=99=E8=AF=AF=EF=BC=9B=20device=5Fdriver:=20?= =?UTF-8?q?=E5=88=A0=E9=99=A4=20=E6=97=A0=E7=94=A8=E7=9A=84bus=E5=AD=97?= =?UTF-8?q?=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/bus/isa/isa.c | 6 ++---- src/arch/x86/drivers/bus/pci/pci.c | 4 +--- src/arch/x86/drivers/cmos.c | 2 -- src/arch/x86/drivers/interrupt/8259a.c | 5 ++--- src/arch/x86/drivers/interrupt/apic.c | 2 -- src/arch/x86/drivers/network/rtl8139/rtl8139.c | 1 - src/arch/x86/drivers/sound/sb16/sb16.c | 1 - src/arch/x86/drivers/timer/pit.c | 1 - src/arch/x86/drivers/vesa_display.c | 2 +- src/driver/video_dm.c | 2 +- src/include/kernel/device_driver.h | 1 - 11 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/arch/x86/drivers/bus/isa/isa.c b/src/arch/x86/drivers/bus/isa/isa.c index be454b5..cdc9215 100644 --- a/src/arch/x86/drivers/bus/isa/isa.c +++ b/src/arch/x86/drivers/bus/isa/isa.c @@ -52,14 +52,13 @@ DriverDependency isa_dependencies[] = { }, }; Driver isa_driver = { - .short_name = STRING_INIT("PciDriver"), + .short_name = STRING_INIT("IsaDriver"), .dependency_count = sizeof(isa_dependencies) / sizeof(DriverDependency), .dependencies = isa_dependencies, .init = isa_driver_init, }; DeviceDriver isa_device_driver = { .name = STRING_INIT("ISA Device Driver"), - .bus = NULL, .type = DEVICE_TYPE_BUS_CONTROLLER, .state = DRIVER_STATE_UNREGISTERED, .private_data_size = 0, @@ -124,8 +123,7 @@ DriverResult isa_init_bus(BusDriver *bus_driver) { } DriverResult isa_driver_init(Driver *driver) { - isa_device_driver.bus = isa_dependencies[0].out_bus; - ObjectAttr attr = device_object_attr; + ObjectAttr attr = device_object_attr; DRIVER_RESULT_PASS(register_bus_controller_device( &isa_device_driver, &isa_bus_driver, &isa_device, &isa_bus_controller_device, &attr)); diff --git a/src/arch/x86/drivers/bus/pci/pci.c b/src/arch/x86/drivers/bus/pci/pci.c index b753f7d..fbd9daa 100644 --- a/src/arch/x86/drivers/bus/pci/pci.c +++ b/src/arch/x86/drivers/bus/pci/pci.c @@ -77,7 +77,6 @@ Driver pci_driver = { }; DeviceDriver pci_device_driver = { .name = STRING_INIT("PCI Device Driver"), - .bus = NULL, .type = DEVICE_TYPE_BUS_CONTROLLER, .state = DRIVER_STATE_UNREGISTERED, .private_data_size = 0, @@ -639,8 +638,7 @@ DriverResult pci_probe(BusDriver *bus_driver, Bus *bus) { } DriverResult pci_driver_init(Driver *driver) { - pci_device_driver.bus = pci_dependencies[0].out_bus; - ObjectAttr attr = device_object_attr; + ObjectAttr attr = device_object_attr; DRIVER_RESULT_PASS(register_bus_controller_device( &pci_device_driver, &pci_bus_driver, &pci_device, &pci_bus_controller_device, &attr)); diff --git a/src/arch/x86/drivers/cmos.c b/src/arch/x86/drivers/cmos.c index 28caadb..d9f5079 100644 --- a/src/arch/x86/drivers/cmos.c +++ b/src/arch/x86/drivers/cmos.c @@ -3,7 +3,6 @@ #include #include #include -#include extern Driver core_driver; @@ -26,7 +25,6 @@ TimeDeviceOps rtc_time_device_ops = { DeviceDriver rtc_device_driver = { .name = STRING_INIT("RTC"), - .bus = &platform_bus, .type = DEVICE_TYPE_TIME, .priority = DRIVER_PRIORITY_BASIC, .ops = &rtc_device_driver_ops, diff --git a/src/arch/x86/drivers/interrupt/8259a.c b/src/arch/x86/drivers/interrupt/8259a.c index 6187b30..d19c798 100644 --- a/src/arch/x86/drivers/interrupt/8259a.c +++ b/src/arch/x86/drivers/interrupt/8259a.c @@ -51,7 +51,6 @@ InterruptDeviceOps pic_interrupt_ops = { DeviceDriver pic_device_driver = { .name = STRING_INIT("PIC Driver"), .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, - .bus = &platform_bus, .priority = DRIVER_PRIORITY_BASIC, .state = DRIVER_STATE_UNREGISTERED, .ops = &pic_device_driver_ops, @@ -85,8 +84,8 @@ DriverResult pic_init(Device *device) { io_out_byte(PIC0_IMR, 0xff); // 屏蔽主PIC的所有中断 io_out_byte(PIC1_IMR, 0xff); // 屏蔽从PIC的所有中断 - io_out_byte(PIC0_ICW1, 0x11); // 级联,边沿触发 - io_out_byte(PIC0_ICW2, 0x20); // 起始中断向量号位0x20(0x00~0x1f为内部中断) + io_out_byte(PIC0_ICW1, 0x11); // 级联,边沿触发 + io_out_byte(PIC0_ICW2, 0x20); // 起始中断向量号位0x20(0x00~0x1f为内部中断) io_out_byte(PIC0_ICW3, 1 << 2); // IRQ2用于连接从PIC // 全嵌套模式,非缓冲模式,手动结束中断,x86处理器 io_out_byte(PIC0_ICW4, 0x01); diff --git a/src/arch/x86/drivers/interrupt/apic.c b/src/arch/x86/drivers/interrupt/apic.c index a87119d..65a0e16 100644 --- a/src/arch/x86/drivers/interrupt/apic.c +++ b/src/arch/x86/drivers/interrupt/apic.c @@ -119,7 +119,6 @@ TimerOps apic_timer_ops = { DeviceDriver apic_device_driver = { .name = STRING_INIT("APIC"), - .bus = &platform_bus, .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, .priority = DRIVER_PRIORITY_BASIC, .state = DRIVER_STATE_UNREGISTERED, @@ -138,7 +137,6 @@ InterruptDevice apic_interrupt_device = { DeviceDriver apic_timer_device_driver = { .name = STRING_INIT("APIC Timer"), - .bus = &platform_bus, .type = DEVICE_TYPE_TIMER, .priority = DRIVER_PRIORITY_BASIC, .state = DRIVER_STATE_UNREGISTERED, diff --git a/src/arch/x86/drivers/network/rtl8139/rtl8139.c b/src/arch/x86/drivers/network/rtl8139/rtl8139.c index ee2fb8a..858358c 100644 --- a/src/arch/x86/drivers/network/rtl8139/rtl8139.c +++ b/src/arch/x86/drivers/network/rtl8139/rtl8139.c @@ -67,7 +67,6 @@ Driver rtl8139_driver = { }; DeviceDriver rtl8139_device_driver = { .name = STRING_INIT("RTL8139"), - .bus = NULL, .type = DEVICE_TYPE_ETHERNET, .priority = DRIVER_PRIORITY_BASIC, .ops = &rtl8139_device_driver_ops, diff --git a/src/arch/x86/drivers/sound/sb16/sb16.c b/src/arch/x86/drivers/sound/sb16/sb16.c index 563789e..796b03c 100644 --- a/src/arch/x86/drivers/sound/sb16/sb16.c +++ b/src/arch/x86/drivers/sound/sb16/sb16.c @@ -97,7 +97,6 @@ Driver sb_driver = { }; DeviceDriver sb16_device_driver = { .name = STRING_INIT("SoundBlaster16"), - .bus = NULL, .type = DEVICE_TYPE_SOUND, .priority = DRIVER_PRIORITY_BASIC, .ops = &sb16_device_driver_ops, diff --git a/src/arch/x86/drivers/timer/pit.c b/src/arch/x86/drivers/timer/pit.c index d4b150e..9539675 100644 --- a/src/arch/x86/drivers/timer/pit.c +++ b/src/arch/x86/drivers/timer/pit.c @@ -56,7 +56,6 @@ DeviceIrq pit_irq = { DeviceDriver pit_device_driver = { .name = STRING_INIT("PIT"), - .bus = &platform_bus, .type = DEVICE_TYPE_TIMER, .priority = DRIVER_PRIORITY_BASIC, .state = DRIVER_STATE_UNREGISTERED, diff --git a/src/arch/x86/drivers/vesa_display.c b/src/arch/x86/drivers/vesa_display.c index 7bd3cc5..929cc9e 100644 --- a/src/arch/x86/drivers/vesa_display.c +++ b/src/arch/x86/drivers/vesa_display.c @@ -29,7 +29,6 @@ DeviceOps vesa_display_device_ops = { DeviceDriver vesa_display_device_driver = { .name = STRING_INIT("VESA Display Device Driver"), - .bus = &platform_bus, .type = DEVICE_TYPE_VIDEO, .priority = DRIVER_PRIORITY_BASIC, .state = DRIVER_STATE_UNREGISTERED, @@ -37,6 +36,7 @@ DeviceDriver vesa_display_device_driver = { }; Device vesa_display_device = { .name = STRING_INIT("Vesa Display"), + .bus = &platform_bus, .device_driver = &vesa_display_device_driver, .ops = &vesa_display_device_ops, .private_data_size = 0, diff --git a/src/driver/video_dm.c b/src/driver/video_dm.c index d2a59d5..6fde5f2 100644 --- a/src/driver/video_dm.c +++ b/src/driver/video_dm.c @@ -56,7 +56,7 @@ DriverResult register_video_device( &name, "Video", 5, video_dm_ext.video_device_count++); DRV_RESULT_DELIVER_CALL( - register_device, device_driver, name, device_driver->bus, device, attr); + register_device, device_driver, name, device->bus, device, attr); list_init(&video_device->video_list_lh); list_add_tail(&device->dm_list, &video_dm.device_lh); diff --git a/src/include/kernel/device_driver.h b/src/include/kernel/device_driver.h index c6edf34..a994f0f 100644 --- a/src/include/kernel/device_driver.h +++ b/src/include/kernel/device_driver.h @@ -37,7 +37,6 @@ typedef struct DeviceDriver { list_t bus_list; list_t device_lh; - struct Bus *bus; string_t name; DeviceType type; DriverPriority priority; From da1b47068abca76f9f539197965abb9848551ad1 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 17 Sep 2025 16:36:36 +0800 Subject: [PATCH 112/158] =?UTF-8?q?usb&uhci:=20=E9=87=8D=E6=9E=84=20uhci?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8=EF=BC=8C=E9=80=82=E9=85=8D=E6=96=B0=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8=E6=A1=86=E6=9E=B6=EF=BC=9B=E7=AE=80=E5=8C=96=20contro?= =?UTF-8?q?l=20transcation=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 5 +- src/Makefile | 2 +- src/arch/x86/drivers/Makefile | 2 +- src/arch/x86/drivers/usb/Makefile | 4 - src/arch/x86/drivers/usb/hci/hci.c | 0 src/arch/x86/drivers/usb/hci/uhci.c | 280 +++++++++++------- src/arch/x86/drivers/usb/hci/uhci/packet.c | 158 ++++++---- src/arch/x86/drivers/usb/hci/uhci/skeleton.c | 63 ++-- src/arch/x86/drivers/usb/hub.c | 41 --- src/arch/x86/drivers/usb/usb.c | 97 ------ .../x86/include/drivers/usb/descriptors.h | 87 ++++++ src/arch/x86/include/drivers/usb/func.h | 42 ++- src/arch/x86/include/drivers/usb/hcd.h | 52 ++-- src/arch/x86/include/drivers/usb/hub.h | 2 +- src/arch/x86/include/drivers/usb/uhci.h | 65 ++-- src/arch/x86/include/drivers/usb/usb.h | 189 ++++-------- src/driver/Makefile | 1 + src/driver/usb/Makefile | 2 + src/driver/usb/usb-core/Makefile | 4 + .../usb => driver/usb/usb-core}/func.c | 145 +++++---- .../drivers/usb => driver/usb/usb-core}/hcd.c | 16 +- src/driver/usb/usb-core/hub.c | 45 +++ src/driver/usb/usb-core/usb.c | 73 +++++ src/driver/usb/usb_dm.c | 21 ++ src/drivers/Makefile | 1 + src/drivers/bus/Makefile | 1 + src/drivers/bus/usb.c | 104 +++++++ src/include/drivers/bus/usb.h | 17 ++ src/include/kernel/device.h | 1 + src/kernel/driver.c | 2 +- 30 files changed, 882 insertions(+), 640 deletions(-) create mode 100644 src/arch/x86/drivers/usb/hci/hci.c delete mode 100644 src/arch/x86/drivers/usb/hub.c delete mode 100644 src/arch/x86/drivers/usb/usb.c create mode 100644 src/arch/x86/include/drivers/usb/descriptors.h create mode 100644 src/driver/usb/Makefile create mode 100644 src/driver/usb/usb-core/Makefile rename src/{arch/x86/drivers/usb => driver/usb/usb-core}/func.c (53%) rename src/{arch/x86/drivers/usb => driver/usb/usb-core}/hcd.c (64%) create mode 100644 src/driver/usb/usb-core/hub.c create mode 100644 src/driver/usb/usb-core/usb.c create mode 100644 src/driver/usb/usb_dm.c create mode 100644 src/drivers/Makefile create mode 100644 src/drivers/bus/Makefile create mode 100644 src/drivers/bus/usb.c create mode 100644 src/include/drivers/bus/usb.h diff --git a/Makefile b/Makefile index b7f2f63..8cba072 100644 --- a/Makefile +++ b/Makefile @@ -107,10 +107,11 @@ qemu_dbg: -m 1024 \ -hda $(HD_IMG) \ -usb \ + -device piix3-usb-uhci \ -device usb-kbd \ -device usb-mouse \ -device rtl8139,netdev=nc1 \ - -netdev user,id=nc1 \ + -netdev user,id=nc1,hostfwd=tcp::5555-:80 \ -object filter-dump,id=f1,netdev=nc1,file=dump.pcap \ -readconfig $(QEMU_CFG) \ -boot c @@ -122,6 +123,8 @@ qemu: -m 1024 \ -hda $(HD_IMG) \ -usb \ + -device piix3-usb-uhci \ + -device usb-kbd \ -device usb-mouse \ -device rtl8139,netdev=nc1 \ -netdev user,id=nc1,hostfwd=tcp::5555-:80 \ diff --git a/src/Makefile b/src/Makefile index a75331d..81d095d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,7 +21,7 @@ LD := $(ENV_LD) export AS LD export ARCH_DIR -SRC := $(ARCH_DIR)/ fs/ driver/ kernel/ lib/ objects/ +SRC := $(ARCH_DIR)/ fs/ driver/ drivers/ kernel/ lib/ objects/ NAME := kernel.elf diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index cbc9794..7091601 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -13,7 +13,7 @@ SRC += vesa_display.c SRC += cmos.c SRC += network/ SRC += sound/ -#SRC += usb/ +SRC += usb/ SRC += bus/ SRC += disk/ SRC += interrupt/ diff --git a/src/arch/x86/drivers/usb/Makefile b/src/arch/x86/drivers/usb/Makefile index 380d31f..cacfec5 100644 --- a/src/arch/x86/drivers/usb/Makefile +++ b/src/arch/x86/drivers/usb/Makefile @@ -1,5 +1 @@ -SRC += hcd.c -SRC += func.c -SRC += hub.c -SRC += usb.c SRC += hci/ \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/hci/hci.c b/src/arch/x86/drivers/usb/hci/hci.c new file mode 100644 index 0000000..e69de29 diff --git a/src/arch/x86/drivers/usb/hci/uhci.c b/src/arch/x86/drivers/usb/hci/uhci.c index 54385ff..69000d9 100644 --- a/src/arch/x86/drivers/usb/hci/uhci.c +++ b/src/arch/x86/drivers/usb/hci/uhci.c @@ -8,19 +8,30 @@ * 目前仅仅只是初始化了UHCI而已,其他涉及USB协议的东西都还没做 * */ +#include "driver/bus_dm.h" +#include "driver/timer_dm.h" +#include "kernel/driver_interface.h" +#include "kernel/list.h" +#include "kernel/thread.h" +#include "objects/object.h" #include #include +#include #include #include #include #include #include #include +#include +#include #include +#include #include #include #include #include +#include #include #include @@ -31,31 +42,72 @@ #define DRV_NAME "Universal Serial Bus(USB) Driver" #define DEV_NAME "Universal Host Controller Interface(UHCI)" -static status_t uhci_enter(driver_t *drv_obj); -static status_t uhci_exit(driver_t *drv_obj); - -extern usb_hcd_interface_t uhci_interface; - -driver_func_t uhci_driver = { - .driver_enter = uhci_enter, - .driver_exit = uhci_exit, - .driver_open = NULL, - .driver_close = NULL, - .driver_read = NULL, - .driver_write = NULL, - .driver_devctl = NULL}; - -void uhci_port_reset(uhci_t *devext, int port); -void uhci_port_init(usb_hcd_t *hcd, int port); +void uhci_register(Driver *driver); +DriverResult uhci_init(Device *device); +DriverResult uhci_start(Device *device); +DriverResult uhci_pci_probe(PciDevice *pci_device); + +extern UsbHcdOps uhci_interface; + +DeviceDriverOps uhci_device_driver_ops = { + .device_driver_init = NULL, + .device_driver_uninit = NULL, +}; +PciDriverOps uhci_pci_driver_ops = { + .probe = uhci_pci_probe, +}; +DeviceOps uhci_device_ops = { + .init = uhci_init, + .start = uhci_start, + .destroy = NULL, + .status = NULL, + .stop = NULL, +}; + +DeviceDriver uhci_device_driver = { + .name = STRING_INIT("uhci"), + .type = DEVICE_TYPE_BUS_CONTROLLER, + .priority = DRIVER_PRIORITY_BASIC, + .ops = &uhci_device_driver_ops, +}; +PciDriver uhci_pci_driver = { + .driver = &usb_driver, + .device_driver = &uhci_device_driver, + .find_type = FIND_BY_CLASSCODE_SUBCLASS_PROGIF, + .class_subclass_progif = {UHCI_CLASSID, UHCI_SUBCLASSID, UHCI_PROGIF}, + .ops = &uhci_pci_driver_ops, +}; +BusControllerDevice uhci_bus_controller_device = { + .short_name = STRING_INIT("UHCI Controller"), + .device = NULL, // 由probe函数设置 + .bus_driver = &usb_bus_driver, + .bus_controller_ops = NULL, +}; +const Device uhci_device_template = { + .name = STRING_INIT("UHCI Controller"), + .device_driver = &uhci_device_driver, + .ops = &uhci_device_ops, + .private_data_size = sizeof(Uhci), +}; +HciInit uhci_hci_init = { + .init = uhci_register, +}; +// const UsbHciDevice uhci_hci_device_template = { +// .head_size = 0, +// .tail_size = 0, +// }; + +void uhci_port_reset(Uhci *devext, int port); +void uhci_port_init(UsbHcd *hcd, int port); void uhci_handler(int irq) { return; } -void uhci_print_status(uhci_t *devext) { - uint16_t status = io_in16(devext->io_base + UHCI_REG_STS); +void uhci_print_status(Uhci *devext) { + uint16_t status = io_in_word(devext->io_base + UHCI_REG_STS); printk("\n[UHCI]Status:\n"); - if (status & 0x20) { printk("[UHCI]HCHalted.\n"); } + if (status & 0x20) { printk("[UHCI]HC Halted.\n"); } if (status & 0x10) { printk("[UHCI]HC Process Error.\n"); } if (status & 0x08) { printk("[UHCI]Host System Error.\n"); } if (status & 0x04) { printk("[UHCI]Resume Detect.\n"); } @@ -63,111 +115,64 @@ void uhci_print_status(uhci_t *devext) { printk("[UHCI]Interrupt:%d\n", status & 0x01); } -void uhci_reset(uhci_t *devext) { - int i; +void uhci_reset(Uhci *uhci) { + // io_out16(uhci->io_base+UHCI_REG_USBINTR, 0); //禁用UHCI的所有中断 + io_out_word( + uhci->io_base + UHCI_REG_CMD, UHCI_CMD_GLBRESET | UHCI_CMD_HCRESET); + delay_ms(&uhci->timer, 10); + io_out_word(uhci->io_base + UHCI_REG_CMD, 0); - // io_out16(devext->io_base+UHCI_REG_USBINTR, 0); //禁用UHCI的所有中断 - io_out16(devext->io_base + UHCI_REG_CMD, UHCI_CMD_GLBRESET); - // TODO: Delay - // delay(50 / 10); // 至少50ms - io_out16(devext->io_base + UHCI_REG_CMD, 0); - - devext->port_cnt = - (devext->device->bar[4].length - UHCI_PORTSC1) / 2; // 有多少接口 - for (i = 2; i < devext->port_cnt; i++) // 逐个检测是否有效 + for (int i = 2; i < uhci->port_cnt; i++) // 逐个检测是否有效 { - uint16_t value = io_in16(UHCI_PORTSC1 + i * 2); + uint16_t value = io_in_word(UHCI_PORTSC1 + i * 2); if (((value & 0x80) == 0) || value == 0xffff) { - devext->port_cnt = i; + uhci->port_cnt = i; break; } } } -static status_t uhci_enter(driver_t *drv_obj) { - device_t *devobj; - uhci_t *devext; - - device_create(drv_obj, sizeof(uhci_t), DEV_NAME, DEV_USB, &devobj); - devext = devobj->device_extension; - - // devext->device = - // pci_get_device_ByClassFull(UHCI_CLASSID, UHCI_SUBCLASSID, UHCI_PROGIF); - if (devext->device == NULL) { - printk(COLOR_YELLOW "\n[UHCI]Cannot find UHCI controller!\n"); - device_delete(devobj); - return NODEV; - } - printk("UHCI\n"); - - devext->io_base = devext->device->bar[4].base_addr & 0xfffffff0; - - // pci_enable_bus_mastering(devext->device); - // pci_enable_io_space(devext->device); - - uhci_reset(devext); - uint16_t intr = io_in16(devext->io_base + UHCI_REG_USBINTR); - io_out16( - devext->io_base + UHCI_REG_USBINTR, - intr | UHCI_INTR_SPI | UHCI_INTR_IOC | UHCI_INTR_RESUME | - UHCI_INTR_CRC); - devext->fl.frames_vir = (uint32_t *)kernel_alloc_pages(1); - devext->fl.frames_phy = - (uint32_t *)vir2phy((uint32_t)devext->fl.frames_vir); - uhci_skel_init(devext); - - io_out16(devext->io_base + UHCI_FRNUM, 0); - io_out32(devext->io_base + UHCI_FRBASEADD, (uint32_t)devext->fl.frames_phy); - - uint16_t cmd = io_in16(devext->io_base + UHCI_REG_CMD); - io_out16(devext->io_base + UHCI_REG_CMD, cmd | UHCI_CMD_RUN); - - usb_hcd_t *hcd = - usb_hcd_register(devobj, DEV_NAME, devext->port_cnt, &uhci_interface); - - int i; - for (i = 0; i < devext->port_cnt; i++) { - uhci_port_init(hcd, i); - } +void uhci_port_reset(Uhci *uhci, int port) { + // 重置 + uint32_t io_port = uhci->io_base + UHCI_PORTSC1 + port * 2; - return SUCCUESS; -} + uint16_t value = io_in_word(io_port); + io_out_word(io_port, BIN_EN(value, UHCI_PORT_SC_RESET)); -void uhci_port_reset(uhci_t *devext, int port) { - // 重置 - uint32_t io_port = devext->io_base + UHCI_PORTSC1 + port * 2; + delay_ms(&uhci->timer, 50); - io_out16(io_port, UHCI_PORT_SC_RESET); - // TODO: Delay - // delay(50 / 10); - uint32_t value = io_in16(io_port); - io_out16(io_port, BIN_DIS(value, UHCI_PORT_SC_RESET)); + value = io_in_word(io_port); + io_out_word(io_port, BIN_DIS(value, UHCI_PORT_SC_RESET)); do { - value = io_in16(io_port); + value = io_in_word(io_port); } while (BIN_IS_EN(value, UHCI_PORT_SC_RESET)); - // TODO: Delay - // delay(10 / 10); + delay_ms(&uhci->timer, 10); + + if (value & UHCI_PORT_SC_CONNECTED) { + io_out_word(io_port, BIN_EN(value, UHCI_PORT_SC_ENABLE)); + } // 使能 - io_out16( - io_port, - UHCI_PORT_SC_CONN_CHG | UHCI_PORT_SC_EN_CHG | UHCI_PORT_SC_ENABLE); - io_in16(io_port); - // TODO: Delay - // delay(10 / 10); + value = io_in_word(io_port); + io_out_word( + io_port, BIN_EN(value, UHCI_PORT_SC_CONN_CHG | UHCI_PORT_SC_EN_CHG)); + io_in_word(io_port); + + delay_ms(&uhci->timer, 10); } -void uhci_port_init(usb_hcd_t *hcd, int port) { - uhci_t *devext = (uhci_t *)hcd->device->device_extension; - uint32_t io_port = devext->io_base + UHCI_PORTSC1 + port * 2; - usb_hcd_port_t *hcd_port = &hcd->ports[port]; +void uhci_port_init(UsbHcd *hcd, int port) { + Uhci *devext = (Uhci *)hcd->device->private_data; + uint32_t io_port = devext->io_base + UHCI_PORTSC1 + port * 2; + UsbHcdPort *hcd_port = &hcd->ports[port]; // 获取端口信息 - uint32_t port_status = io_in16(io_port); + uint32_t port_status = io_in_word(io_port); // 重置端口,注册设备 if (BIN_IS_EN(port_status, UHCI_PORT_SC_CONNECTED)) { - usb_device_t *usb_device = usb_create_device( + printk("[UHCI]port %d connected.\n", port); + UsbDevice *usb_device = usb_create_device( BIN_IS_EN(port_status, UHCI_PORT_SC_LOWSPEED) ? USB_SPEED_LOW : USB_SPEED_FULL, 0); @@ -178,7 +183,7 @@ void uhci_port_init(usb_hcd_t *hcd, int port) { } // 输出端口信息 - port_status = io_in16(io_port); + port_status = io_in_word(io_port); hcd_port->connected = BIN_IS_EN(port_status, UHCI_PORT_SC_CONNECTED); hcd_port->enable = BIN_IS_EN(port_status, UHCI_PORT_SC_ENABLE); hcd_port->suspend = BIN_IS_EN(port_status, UHCI_PORT_SC_SUSPEND); @@ -193,19 +198,70 @@ void uhci_port_init(usb_hcd_t *hcd, int port) { : "FullSpeed"); } -static status_t uhci_exit(driver_t *drv_obj) { - device_t *devobj, *next; - list_for_each_owner_safe (devobj, next, &drv_obj->device_list, list) { - device_delete(devobj); +DriverResult uhci_init(Device *device) { + Uhci *uhci = device->private_data; + + timer_init(&uhci->timer); + uhci_reset(uhci); + uint16_t intr = io_in_word(uhci->io_base + UHCI_REG_USBINTR); + intr |= UHCI_INTR_SPI | UHCI_INTR_IOC | UHCI_INTR_RESUME | UHCI_INTR_CRC; + io_out_word(uhci->io_base + UHCI_REG_USBINTR, intr); + + return DRIVER_RESULT_OK; +} + +DriverResult uhci_start(Device *device) { + Uhci *uhci = device->private_data; + uhci->fl.frames_vir = (uint32_t *)kernel_alloc_pages(1); + uhci->fl.frames_phy = (uint32_t *)vir2phy((uint32_t)uhci->fl.frames_vir); + uhci_skel_init(uhci); + + pci_device_write16(uhci->device, UHCI_PCI_REG_LEGSUP, 0x2000); + pci_enable_bus_mastering(uhci->device); + + io_out_word(uhci->io_base + UHCI_FRNUM, 0); + io_out_dword(uhci->io_base + UHCI_FRBASEADD, (uint32_t)uhci->fl.frames_phy); + + uint16_t cmd = io_in_word(uhci->io_base + UHCI_REG_CMD); + io_out_word(uhci->io_base + UHCI_REG_CMD, cmd | UHCI_CMD_RUN); + + for (int i = 0; i < uhci->port_cnt; i++) { + uhci_port_init(uhci->hcd, i); } - string_del(&drv_obj->name); - return SUCCUESS; + + return DRIVER_RESULT_OK; +} + +DriverResult uhci_pci_probe(PciDevice *pci_device) { + uint32_t io_base = pci_device->common.bar[4].base_addr & 0xfffffff0; + if (io_base == 0) { return DRIVER_RESULT_UNSUPPORT_DEVICE; } + + Device *device = kmalloc_from_template(uhci_device_template); + device->bus = pci_device->bus; + + ObjectAttr attr = driver_object_attr; + register_bus_controller_device( + &uhci_device_driver, &usb_bus_driver, device, + &uhci_bus_controller_device, &attr); + Uhci *uhci = device->private_data; + uhci->device = pci_device; + uhci->io_base = io_base; + uhci->port_cnt = (pci_device->common.bar[4].length - UHCI_PORTSC1) / 2; + + UsbHcd *hcd = + usb_hcd_register(device, DEV_NAME, uhci->port_cnt, &uhci_interface); + uhci->hcd = hcd; + + return DRIVER_RESULT_OK; +} + +void uhci_register(Driver *driver) { + register_device_driver(driver, &uhci_device_driver); + pci_register_driver(driver, &uhci_pci_driver); } static __init void uhci_driver_entry(void) { - if (driver_create(uhci_driver, DRV_NAME) < 0) { - printk(COLOR_RED "[driver] %s driver create failed!\n", __func__); - } + list_add_tail(&uhci_hci_init.list, &hci_lh); } driver_initcall(uhci_driver_entry); \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/hci/uhci/packet.c b/src/arch/x86/drivers/usb/hci/uhci/packet.c index 96d084b..8bde628 100644 --- a/src/arch/x86/drivers/usb/hci/uhci/packet.c +++ b/src/arch/x86/drivers/usb/hci/uhci/packet.c @@ -1,3 +1,4 @@ +#include "driver/timer_dm.h" #include #include #include @@ -9,32 +10,57 @@ #include #include -usb_hcd_interface_t uhci_interface = { - .control_transaction_in = uhci_control_transaction_in, - .control_transaction_out = uhci_control_transaction_out, +#define DEFAULT_TD_COUNT 4 + +void *uhci_create_sched(void); + +UsbHcdOps uhci_interface = { + .create_sched = uhci_create_sched, + .ctrl_transfer_in = uhci_ctrl_transfer_in, + .ctrl_transfer_out = uhci_ctrl_transfer_out, }; +void *uhci_create_sched(void) { + UhciSched *sched = kmalloc(sizeof(UhciSched)); + sched->qh.qh_addr_phy = vir2phy((uint32_t)&sched->qh); + sched->qh.qe_link = UHCI_TERMINATE; + sched->qh.qh_link = UHCI_TERMINATE; + sched->td_count = DEFAULT_TD_COUNT; + sched->td_index = 0; + sched->tds = kmalloc(sizeof(UhciTd) * sched->td_count); + + for (int i = 0; i < sched->td_count; i++) { + sched->tds[i].link = UHCI_TERMINATE; + sched->tds[i].td_addr_phy = vir2phy((uint32_t)&sched->tds[i]); + } + return sched; +} + void uhci_send_token_packet( - usb_transfer_t *transfer, uhci_qh_t *qh, uint8_t data_toggle, void *buffer, - uint8_t packet_id, int length) { - usb_device_t *usb_device = transfer->device; - uhci_td_t *td = kmalloc(sizeof(uhci_td_t)); + UsbDevice *device, UsbEndpoint *ep, UhciQh *qh, uint8_t data_toggle, + void *buffer, uint8_t packet_id, int length) { + UsbDevice *usb_device = device; + UhciSched *sched = ep->sched; + if (sched->td_index >= sched->td_count) { + printk("[UHCI]UhciSched td is full.\n"); + return; + } + UhciTd *td = &sched->tds[sched->td_index++]; td->packet_id = packet_id; td->device_addr = usb_device->address & 0x7f; - td->endpoint = transfer->ep->endpoint & 0x0f; + td->endpoint = ep->endpoint & 0x0f; td->data_toggle = data_toggle; - td->max_length = length - 1; + td->max_length = length > 0 ? (length - 1) : 0; td->active = 1; td->actlen = 0; - td->td_addr_phy = vir2phy((uint32_t)td); + if (buffer != NULL) td->buf_addr_phy = vir2phy((uint32_t)buffer); + else td->buf_addr_phy = 0; - if (buffer != NULL) { td->buf_addr_phy = vir2phy((uint32_t)buffer); } - - td->prev_ptr = qh->last_ptr; - uhci_td_t *last_td = (uhci_td_t *)qh->last_ptr; + td->prev_ptr = qh->last_ptr; + UhciTd *last_td = (UhciTd *)qh->last_ptr; if (last_td != NULL) { last_td->link = BIN_EN( BIN_DIS(td->td_addr_phy, UHCI_QH_TD_SELECT), UHCI_VERTICAL_FIRST); @@ -46,58 +72,70 @@ void uhci_send_token_packet( qh->last_ptr = (uint32_t)td; } -int uhci_setup_packet( - usb_device_t *device, usb_transfer_t *transfer, uhci_qh_t *qh, void *buffer, +static inline int uhci_setup_transcation( + UsbDevice *device, UsbEndpoint *ep, UhciQh *qh, void *buffer, uint32_t length) { uhci_send_token_packet( - transfer, qh, 0, buffer, USB_PACKET_ID_SETUP, length); + device, ep, qh, 0, buffer, USB_PACKET_ID_SETUP, length); return 0; } -int uhci_in_packet( - usb_device_t *device, usb_transfer_t *transfer, uhci_qh_t *qh, void *buffer, - uint32_t length) { - uhci_send_token_packet(transfer, qh, 1, buffer, USB_PACKET_ID_IN, length); +static inline int uhci_in_transcation( + UsbDevice *device, UsbEndpoint *ep, UhciQh *qh, int data_toggle, + void *buffer, uint32_t length) { + uhci_send_token_packet( + device, ep, qh, data_toggle, buffer, USB_PACKET_ID_IN, length); return 0; } -int uhci_out_packet( - usb_device_t *device, usb_transfer_t *transfer, uhci_qh_t *qh, void *buffer, - uint32_t length) { - uhci_send_token_packet(transfer, qh, 1, buffer, USB_PACKET_ID_OUT, length); +static inline int uhci_out_transcation( + UsbDevice *device, UsbEndpoint *ep, UhciQh *qh, int data_toggle, + void *buffer, uint32_t length) { + uhci_send_token_packet( + device, ep, qh, data_toggle, buffer, USB_PACKET_ID_OUT, length); return 0; } -int uhci_wait_transfer(uhci_qh_t *qh) { - int timeout = 150; - uhci_td_t *td = (uhci_td_t *)qh->last_ptr; +int uhci_wait_transfer(UhciQh *qh) { + Timer timer; + timer_init(&timer); + int timeout = 150; + UhciTd *td = (UhciTd *)qh->last_ptr; while (timeout > 0) { if (td->active == 0) { return 1; } - // TODO: Delay - // delay(10 / 10); + delay_ms(&timer, 10); timeout--; } + td = &(((UhciSched *)qh)->tds[0]); + uint32_t *raw = (uint32_t *)td; // TD 在内存首地址 + printk( + "TD raw: w0=%08x w1=%08x w2=%08x w3=%08x\n", raw[0], raw[1], raw[2], + raw[3]); + printk( + " decoded: pid=%02x dev=%u ep=%u toggle=%u maxlen=%u active=%u\n", + td->packet_id, td->device_addr, td->endpoint, td->data_toggle, + td->max_length, td->active); printk("[UHCI]td %#08x(phy %#08x) timeout.", td, td->td_addr_phy); return -1; } -usb_setup_status_t uhci_control_transaction_in( - usb_hcd_t *hcd, usb_device_t *device, usb_transfer_t *transfer, - void *buffer, uint32_t data_length, usb_request_t *usb_req) { - uhci_qh_t *qh = kmalloc(sizeof(uhci_qh_t)); - qh->qh_addr_phy = vir2phy((uint32_t)qh); - qh->qe_link = UHCI_TERMINATE; - qh->qh_link = UHCI_TERMINATE; - uhci_setup_packet(device, transfer, qh, usb_req, 8); - uhci_in_packet(device, transfer, qh, buffer, data_length); - uhci_out_packet(device, transfer, qh, NULL, 0x800); - - uhci_skel_add_qh(hcd->device->device_extension, qh, LOW_SPEED); +UsbSetupStatus uhci_ctrl_transfer_in( + UsbHcd *hcd, UsbDevice *device, void *buffer, uint32_t data_length, + UsbRequest *usb_req) { + UhciSched *sched = device->ep0->sched; + UhciQh *qh = &sched->qh; + qh->qe_link = UHCI_TERMINATE; + qh->qh_link = UHCI_TERMINATE; + uhci_setup_transcation(device, device->ep0, qh, usb_req, 8); + uhci_in_transcation(device, device->ep0, qh, 0, buffer, data_length); + uhci_out_transcation(device, device->ep0, qh, 1, NULL, 0); + + uhci_skel_add_qh(hcd->device->private_data, qh, LOW_SPEED); uhci_wait_transfer(qh); - uhci_td_t *last_td = (uhci_td_t *)qh->last_ptr; - usb_setup_status_t result; + UhciTd *last_td = (UhciTd *)qh->last_ptr; + UsbSetupStatus result; if (last_td->stalled) { result = USB_SETUP_STALLED; @@ -112,29 +150,30 @@ usb_setup_status_t uhci_control_transaction_in( } else { result = USB_SETUP_SUCCESS; } - uhci_skel_del_qh(hcd->device->device_extension, qh, LOW_SPEED); + uhci_skel_del_qh(hcd->device->private_data, qh, LOW_SPEED); + sched->td_index = 0; return result; } -usb_setup_status_t uhci_control_transaction_out( - usb_hcd_t *hcd, usb_device_t *device, usb_transfer_t *transfer, - void *buffer, uint32_t data_length, usb_request_t *usb_req) { - uhci_qh_t *qh = kmalloc(sizeof(uhci_qh_t)); - qh->qh_addr_phy = vir2phy((uint32_t)qh); - qh->qe_link = UHCI_TERMINATE; - qh->qh_link = UHCI_TERMINATE; - uhci_setup_packet(device, transfer, qh, usb_req, 8); +UsbSetupStatus uhci_ctrl_transfer_out( + UsbHcd *hcd, UsbDevice *device, void *buffer, uint32_t data_length, + UsbRequest *usb_req) { + UhciSched *sched = device->ep0->sched; + UhciQh *qh = &sched->qh; + qh->qe_link = UHCI_TERMINATE; + qh->qh_link = UHCI_TERMINATE; + uhci_setup_transcation(device, device->ep0, qh, usb_req, 8); if (data_length != 0) { - uhci_out_packet(device, transfer, qh, buffer, data_length); + uhci_out_transcation(device, device->ep0, qh, 0, buffer, data_length); } - uhci_in_packet(device, transfer, qh, NULL, 0x800); + uhci_in_transcation(device, device->ep0, qh, 1, NULL, 0); - uhci_skel_add_qh(hcd->device->device_extension, qh, LOW_SPEED); + uhci_skel_add_qh(hcd->device->private_data, qh, LOW_SPEED); uhci_wait_transfer(qh); - uhci_td_t *last_td = (uhci_td_t *)qh->last_ptr; - usb_setup_status_t result; + UhciTd *last_td = (UhciTd *)qh->last_ptr; + UsbSetupStatus result; if (last_td->stalled) { result = USB_SETUP_STALLED; @@ -149,7 +188,8 @@ usb_setup_status_t uhci_control_transaction_out( } else { result = USB_SETUP_SUCCESS; } - uhci_skel_del_qh(hcd->device->device_extension, qh, LOW_SPEED); + uhci_skel_del_qh(hcd->device->private_data, qh, LOW_SPEED); + sched->td_index = 0; return result; } diff --git a/src/arch/x86/drivers/usb/hci/uhci/skeleton.c b/src/arch/x86/drivers/usb/hci/uhci/skeleton.c index 0de1700..8c5608d 100644 --- a/src/arch/x86/drivers/usb/hci/uhci/skeleton.c +++ b/src/arch/x86/drivers/usb/hci/uhci/skeleton.c @@ -3,15 +3,14 @@ #include #include -void uhci_skel_init(uhci_t *devext) { - int i; +void uhci_skel_init(Uhci *uhci) { + int i; + UhciQh *qhs; - struct uhci_qh *qhs; + uhci->skel = kmalloc(sizeof(UhciSkel)); + qhs = uhci->skel->qh; - devext->skel = kmalloc(sizeof(struct uhci_skel)); - qhs = devext->skel->qh; - - memset32(devext->fl.frames_vir, 1, 1024); + memset32(uhci->fl.frames_vir, 1, 1024); qhs[TIME_1MS].qh_addr_phy = vir2phy((uint32_t)&qhs[TIME_1MS]); qhs[TIME_1MS].next_ptr = (uint32_t)&qhs[LOW_SPEED]; @@ -32,8 +31,8 @@ void uhci_skel_init(uhci_t *devext) { // 构建结束的QH和TD - uhci_td_t *term_td = (uhci_td_t *)kmalloc(sizeof(uhci_td_t)); - memset(term_td, 0, sizeof(uhci_td_t)); + UhciTd *term_td = (UhciTd *)kmalloc(sizeof(UhciTd)); + memset(term_td, 0, sizeof(UhciTd)); term_td->max_length = 0x7ff; term_td->device_addr = 0x7f; @@ -49,52 +48,46 @@ void uhci_skel_init(uhci_t *devext) { int irq = 1 + BIT_FFS_R(i + FRAMELIST_SIZE); if (irq > 7) irq = 7; - devext->fl.frames_vir[i] = + uhci->fl.frames_vir[i] = BIN_EN(vir2phy((uint32_t)&qhs[irq]), UHCI_QH_TD_SELECT); i++; } } -void uhci_skel_add_qh(uhci_t *devext, uhci_qh_t *qh, enum uhci_skel_type type) { - uhci_qh_t *last_qh = ((uhci_qh_t *)devext->skel->qh[type].last_ptr); +void uhci_skel_add_qh(Uhci *uhci, UhciQh *qh, UhciSkelType type) { + UhciQh *last_qh = ((UhciQh *)uhci->skel->qh[type].last_ptr); if (last_qh != NULL) { qh->qh_link = last_qh->qh_link; last_qh->next_ptr = (uint32_t)qh; - last_qh->qh_link = BIN_EN(qh->qh_addr_phy, UHCI_QH_TD_SELECT); qh->prev_ptr = (uint32_t)last_qh; + last_qh->qh_link = BIN_EN(qh->qh_addr_phy, UHCI_QH_TD_SELECT); } else { - devext->skel->qh[type].qe_link = - BIN_EN(qh->qh_addr_phy, UHCI_QH_TD_SELECT); qh->qh_link = UHCI_TERMINATE; + uhci->skel->qh[type].qe_link = + BIN_EN(qh->qh_addr_phy, UHCI_QH_TD_SELECT); } - devext->skel->qh[type].last_ptr = (uint32_t)qh; + uhci->skel->qh[type].last_ptr = (uint32_t)qh; } -void uhci_skel_del_qh(uhci_t *devext, uhci_qh_t *qh, enum uhci_skel_type type) { +void uhci_skel_del_qh(Uhci *uhci, UhciQh *qh, UhciSkelType type) { if (qh->prev_ptr != 0) { if (qh->next_ptr != 0) { - uhci_qh_t *next_qh = (uhci_qh_t *)qh->next_ptr; - uhci_qh_t *prev_qh = (uhci_qh_t *)qh->prev_ptr; - prev_qh->next_ptr = qh->next_ptr; - next_qh->prev_ptr = qh->prev_ptr; + UhciQh *next_qh = (UhciQh *)qh->next_ptr; + UhciQh *prev_qh = (UhciQh *)qh->prev_ptr; + prev_qh->next_ptr = qh->next_ptr; + next_qh->prev_ptr = qh->prev_ptr; } } else { if (qh->next_ptr != 0) { - uhci_qh_t *next_qh = (uhci_qh_t *)qh->next_ptr; - next_qh->prev_ptr = 0; - devext->skel->qh[type].qe_link = qh->qh_link; + UhciQh *next_qh = (UhciQh *)qh->next_ptr; + next_qh->prev_ptr = qh->prev_ptr; + uhci->skel->qh[type].qe_link = qh->qh_link; } else { - devext->skel->qh[type].qe_link = UHCI_TERMINATE; - devext->skel->qh[type].last_ptr = 0; + uhci->skel->qh[type].qe_link = UHCI_TERMINATE; + uhci->skel->qh[type].last_ptr = 0; } } - - uhci_td_t *td = (uhci_td_t *)qh->last_ptr; - uhci_td_t *tmp; - while (td) { - tmp = (uhci_td_t *)td->prev_ptr; - kfree((void *)td); - td = tmp; - } - kfree(qh); + qh->next_ptr = 0; + qh->prev_ptr = 0; + qh->last_ptr = 0; } \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/hub.c b/src/arch/x86/drivers/usb/hub.c deleted file mode 100644 index 318b2a4..0000000 --- a/src/arch/x86/drivers/usb/hub.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -void usb_init_hub(usb_hcd_t *hcd, usb_device_t *device) { - usb_endpoint_t ep = usb_default_ep; - hcd->device_count++; - usb_set_address(hcd, device, &ep, hcd->device_count); - // TODO: Delay - // delay(2); - device->address = hcd->device_count; - struct usb_hub_descriptor *desc = usb_get_hub_descriptor(hcd, device, &ep); - usb_show_hub_descriptor(desc); - - uint32_t status = usb_get_hub_status(hcd, device, &ep); - - int i; - for (i = 1; i <= desc->bNbrPorts; i++) { - - usb_set_port_feature(hcd, device, &ep, i, HUB_FEAT_PORT_POWER); - // TODO: Delay - // delay(50 / 10); - usb_set_port_feature(hcd, device, &ep, i, HUB_FEAT_PORT_RESET); - // delay(200 / 10); - - status = usb_get_port_status(hcd, device, &ep, i); - if (BIN_IS_EN(status, USB_PORT_STAT_CONNECTION)) { - usb_device_t *dev = usb_create_device( - (BIN_IS_EN(status, USB_PORT_STAT_LOW_SPEED) ? USB_SPEED_LOW - : USB_SPEED_FULL), - 0); - usb_init_device(hcd, dev); - // TODO: Delay - // delay(100 / 10); - } - } -} \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/usb.c b/src/arch/x86/drivers/usb/usb.c deleted file mode 100644 index 35cea00..0000000 --- a/src/arch/x86/drivers/usb/usb.c +++ /dev/null @@ -1,97 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -usb_device_t *usb_create_device(usb_device_speed_t speed, uint8_t address) { - usb_device_t *device = (usb_device_t *)kmalloc(sizeof(usb_device_t)); - device->desc = kmalloc(sizeof(struct usb_device_descriptor)); - device->speed = speed; - device->address = address; - return device; -} - -int usb_destroy_device(usb_device_t *device) { - return kfree(device); -} - -usb_request_t *usb_create_request( - uint8_t direction, uint8_t type, uint8_t recipient, uint8_t request_id, - uint8_t value_hi, uint8_t value_lo, uint16_t index, uint16_t length) { - usb_request_t *request = (usb_request_t *)kmalloc(sizeof(usb_request_t)); - request->bmRequestType = direction << 7 | type << 5 | recipient; - request->bRequest = request_id; - request->wValue = HOST2LE_WORD(value_hi << 8 | value_lo); - request->wIndex = HOST2LE_WORD(index); - request->wLength = HOST2LE_WORD(length); - return request; -} - -usb_endpoint_t usb_default_ep = { - .endpoint = 0, - .transfer_type = USB_EP_CONTROL, - .direction = USB_EP_OUT, - .max_packet_size = 64, -}; - -usb_endpoint_t *usb_create_endpoint( - uint8_t endpoint, enum ep_transfer_type transfer_type, - enum ep_direction direction, uint16_t max_packet_size) { - usb_endpoint_t *ep = (usb_endpoint_t *)kmalloc(sizeof(usb_endpoint_t)); - ep->endpoint = endpoint; - ep->transfer_type = transfer_type; - ep->direction = direction; - ep->max_packet_size = max_packet_size; - return ep; -} - -usb_transfer_t *usb_create_transfer( - usb_device_t *device, usb_endpoint_t *endpoint) { - usb_transfer_t *transfer = - (usb_transfer_t *)kmalloc(sizeof(usb_transfer_t)); - transfer->device = device; - transfer->ep = endpoint; - return transfer; -} - -int usb_init_device(usb_hcd_t *hcd, usb_device_t *device) { - usb_endpoint_t ep = usb_default_ep; - struct usb_device_descriptor *desc = - usb_get_device_descriptor(hcd, device, &ep); - usb_show_device_descriptor(hcd, device, &ep, desc); - hcd->device_count++; - usb_set_address(hcd, device, &ep, hcd->device_count); - // TODO: Delay - // delay(2); - - device->address = hcd->device_count; - usb_get_config_descriptor(hcd, device, &ep); - usb_set_config(hcd, device, &ep, 1); - - if (desc->bDeviceClass == USB_CLASS_HUB) { usb_init_hub(hcd, device); } - return 0; -} - -usb_setup_status_t usb_control_transaction_in( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, void *buffer, - usb_request_t *usb_req, uint32_t length) { - - usb_transfer_t *transfer = usb_create_transfer(device, ep); - - return hcd->interface->control_transaction_in( - hcd, device, transfer, buffer, length, usb_req); -} - -usb_setup_status_t usb_control_transaction_out( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, void *buffer, - usb_request_t *usb_req, uint32_t length) { - - usb_transfer_t *transfer = usb_create_transfer(device, ep); - - return hcd->interface->control_transaction_out( - hcd, device, transfer, buffer, length, usb_req); -} \ No newline at end of file diff --git a/src/arch/x86/include/drivers/usb/descriptors.h b/src/arch/x86/include/drivers/usb/descriptors.h new file mode 100644 index 0000000..0cb8cc0 --- /dev/null +++ b/src/arch/x86/include/drivers/usb/descriptors.h @@ -0,0 +1,87 @@ +#ifndef _USB_DESCRIPTORS_H +#define _USB_DESCRIPTORS_H + +#include + +#define USB_DESC_TYPE_DEVICE 0x01 +#define USB_DESC_TYPE_CONFIG 0x02 +#define USB_DESC_TYPE_STRING 0x03 +#define USB_DESC_TYPE_INTERFACE 0x04 +#define USB_DESC_TYPE_ENDPOINT 0x05 +#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06 +#define USB_DESC_TYPE_OTHER_SPEED_CONFIG 0x07 +#define USB_DESC_TYPE_INTERFACE_POWER 0x08 + +#define USB_DESC_TYPE_DEVICE_SIZE 18 +#define USB_DESC_TYPE_CONFIG_SIZE 9 +#define USB_DESC_TYPE_HUB_SIZE 9 + +#define USB_DESC_TYPE_HUB 0x29 + +struct UsbDeviceDescriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} __attribute__((packed)); + +struct UsbConfigDescriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; +} __attribute__((packed)); + +struct UsbInterfaceDescriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; +} __attribute__((packed)); + +struct UsbEndpointDescriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; +} __attribute__((packed)); + +struct UsbStringDescriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wData[]; +} __attribute__((packed)); + +struct UsbHubDescriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bNbrPorts; + uint16_t wHubCharacteristics; + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; + uint8_t DeviceRemovable; + uint8_t PortPwrCtrlMask; +} __attribute__((packed)); + +#endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/usb/func.h b/src/arch/x86/include/drivers/usb/func.h index 07218cf..8d7d1fb 100644 --- a/src/arch/x86/include/drivers/usb/func.h +++ b/src/arch/x86/include/drivers/usb/func.h @@ -5,37 +5,35 @@ #define REQ_GET_PORT_STATUS_SIZE 4 -struct usb_device_descriptor *usb_get_device_descriptor( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep); -struct usb_config_descriptor *usb_get_config_descriptor( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep); +struct UsbDeviceDescriptor *usb_get_device_descriptor( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep); +struct UsbConfigDescriptor *usb_get_config_descriptor( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep); -uint8_t usb_get_config( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep); -usb_setup_status_t usb_set_config( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, uint8_t config); +uint8_t usb_get_config(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep); +UsbSetupStatus usb_set_config( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t config); -struct usb_hub_descriptor *usb_get_hub_descriptor( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep); +struct UsbHubDescriptor *usb_get_hub_descriptor( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep); -usb_setup_status_t usb_set_address( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, uint32_t address); +UsbSetupStatus usb_set_address( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint32_t address); -usb_setup_status_t usb_set_port_feature( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, uint8_t port, +UsbSetupStatus usb_set_port_feature( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t port, uint16_t feature); -uint32_t usb_get_hub_status( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep); +uint32_t usb_get_hub_status(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep); uint32_t usb_get_port_status( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, uint8_t port); + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t port); -struct usb_string_descriptor *usb_get_string_descriptor( - usb_hcd_t *hcd, usb_device_t *device, uint8_t index, usb_endpoint_t *ep); +struct UsbStringDescriptor *usb_get_string_descriptor( + UsbHcd *hcd, UsbDevice *device, uint8_t index, UsbEndpoint *ep); void usb_show_device_descriptor( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, - struct usb_device_descriptor *desc); -void usb_show_hub_descriptor(struct usb_hub_descriptor *desc); + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, + struct UsbDeviceDescriptor *desc); +void usb_show_hub_descriptor(struct UsbHubDescriptor *desc); #endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/usb/hcd.h b/src/arch/x86/include/drivers/usb/hcd.h index baed3ff..b5bd485 100644 --- a/src/arch/x86/include/drivers/usb/hcd.h +++ b/src/arch/x86/include/drivers/usb/hcd.h @@ -1,51 +1,51 @@ #ifndef HCD_H #define HCD_H +#include +#include #include #include #include #include -struct usb_device; -struct usb_transfer; -struct usb_request; +struct UsbDevice; +struct UsbTransfer; +struct UsbRequest; -typedef struct usb_hcd_port { - uint32_t port; - struct usb_hcd *hcd; +typedef struct UsbHcdPort { + uint32_t port; + struct UsbHcd *hcd; uint8_t suspend; uint8_t enable; uint8_t connected; -} usb_hcd_port_t; +} UsbHcdPort; -typedef struct usb_hcd_interface { - enum usb_setup_status (*control_transaction_in)( - struct usb_hcd *hcd, struct usb_device *device, - struct usb_transfer *transfer, void *buffer, uint32_t data_length, - struct usb_request *usb_req); - enum usb_setup_status (*control_transaction_out)( - struct usb_hcd *hcd, struct usb_device *device, - struct usb_transfer *transfer, void *buffer, uint32_t data_length, - struct usb_request *usb_req); -} usb_hcd_interface_t; +typedef struct UsbHcdOps { + void *(*create_sched)(void); + enum UsbSetupStatus (*ctrl_transfer_in)( + struct UsbHcd *hcd, struct UsbDevice *device, void *buffer, + uint32_t data_length, struct UsbRequest *usb_req); + enum UsbSetupStatus (*ctrl_transfer_out)( + struct UsbHcd *hcd, struct UsbDevice *device, void *buffer, + uint32_t data_length, struct UsbRequest *usb_req); +} UsbHcdOps; -typedef struct usb_hcd { - list_t list; - usb_hcd_port_t *ports; +typedef struct UsbHcd { + list_t list; + UsbHcdPort *ports; - usb_hcd_interface_t *interface; + UsbHcdOps *ops; string_t *name; - device_t *device; + Device *device; uint8_t device_count; list_t usb_devices; -} usb_hcd_t; +} UsbHcd; -usb_hcd_t *usb_hcd_register( - device_t *device, char *name, uint32_t port_cnt, - usb_hcd_interface_t *interface); +UsbHcd *usb_hcd_register( + Device *device, char *name, uint32_t port_cnt, UsbHcdOps *interface); #endif // HCD_H \ No newline at end of file diff --git a/src/arch/x86/include/drivers/usb/hub.h b/src/arch/x86/include/drivers/usb/hub.h index 4c5e11b..21f7333 100644 --- a/src/arch/x86/include/drivers/usb/hub.h +++ b/src/arch/x86/include/drivers/usb/hub.h @@ -23,6 +23,6 @@ #define HUB_FEAT_PORT_TEST 21 #define HUB_FEAT_PORT_INDICATOR 22 -void usb_init_hub(usb_hcd_t *hcd, usb_device_t *device); +void usb_init_hub(UsbHcd *hcd, UsbDevice *device); #endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/usb/uhci.h b/src/arch/x86/include/drivers/usb/uhci.h index 51571bb..0496a2f 100644 --- a/src/arch/x86/include/drivers/usb/uhci.h +++ b/src/arch/x86/include/drivers/usb/uhci.h @@ -1,7 +1,9 @@ #ifndef _UHCI_H #define _UHCI_H +#include "drivers/usb/hcd.h" #include +#include #include #include #include @@ -17,6 +19,8 @@ #define UHCI_PORTSC1 0x10 #define UHCI_PORTSC2 0x12 +#define UHCI_PCI_REG_LEGSUP 0xc0 + #define UHCI_CMD_RUN 0x01 #define UHCI_CMD_HCRESET 0x02 #define UHCI_CMD_GLBRESET 0x04 @@ -64,12 +68,12 @@ #define UHCI_QH_TD_SELECT BIT(1) // 1:QH, 0:TD #define UHCI_TERMINATE BIT(0) -struct uhci_frame_list { +typedef struct UhciFrameList { uint32_t *frames_vir; uint32_t *frames_phy; -}; +} UhciFrameList; -typedef struct uhci_qh { +typedef struct UhciQh { // 硬件用 uint32_t qh_link; uint32_t qe_link; @@ -79,9 +83,9 @@ typedef struct uhci_qh { uint32_t last_ptr; uint32_t next_ptr; uint32_t align[2]; // 用于对齐16字节 -} uhci_qh_t; +} __attribute__((packed)) UhciQh; -typedef struct uhci_td { +typedef struct UhciTd { uint32_t link; // TD control and status @@ -116,22 +120,31 @@ typedef struct uhci_td { uint32_t prev_ptr; uint32_t td_addr_phy; uint32_t software_use[2]; -} __attribute__((packed)) uhci_td_t; +} __attribute__((packed)) UhciTd; + +typedef struct UhciSched { + UhciQh qh; + uint8_t td_count; + uint8_t td_index; + UhciTd *tds; +} UhciSched; -struct uhci_skel { - struct uhci_qh qh[11]; // 1ms, 2ms, 4ms, 8ms, 16ms, 32ms, 64ms, 128ms -}; +typedef struct UhciSkel { + struct UhciQh qh[11]; // 1ms, 2ms, 4ms, 8ms, 16ms, 32ms, 64ms, 128ms +} UhciSkel; typedef struct { - struct pci_device *device; - uint32_t io_base; - struct uhci_frame_list fl; - uint8_t port_cnt; + PciDevice *device; + uint32_t io_base; + UhciFrameList fl; + uint8_t port_cnt; + Timer timer; - struct uhci_skel *skel; -} uhci_t; + UhciSkel *skel; + UsbHcd *hcd; +} Uhci; -enum uhci_skel_type { +typedef enum UhciSkelType { TIME_1MS = 0, TIME_2MS, TIME_4MS, @@ -143,18 +156,18 @@ enum uhci_skel_type { LOW_SPEED, FULL_SPEED, TERM, -}; +} UhciSkelType; -void uhci_skel_init(uhci_t *devext); +void uhci_skel_init(Uhci *uhci); -void uhci_skel_add_qh(uhci_t *devext, uhci_qh_t *qh, enum uhci_skel_type type); -void uhci_skel_del_qh(uhci_t *devext, uhci_qh_t *qh, enum uhci_skel_type type); +void uhci_skel_add_qh(Uhci *uhci, UhciQh *qh, UhciSkelType type); +void uhci_skel_del_qh(Uhci *uhci, UhciQh *qh, UhciSkelType type); -usb_setup_status_t uhci_control_transaction_in( - usb_hcd_t *hcd, usb_device_t *device, usb_transfer_t *transfer, - void *buffer, uint32_t data_length, usb_request_t *usb_req); -usb_setup_status_t uhci_control_transaction_out( - usb_hcd_t *hcd, usb_device_t *device, usb_transfer_t *transfer, - void *buffer, uint32_t data_length, usb_request_t *usb_req); +UsbSetupStatus uhci_ctrl_transfer_in( + UsbHcd *hcd, UsbDevice *device, void *buffer, uint32_t data_length, + UsbRequest *usb_req); +UsbSetupStatus uhci_ctrl_transfer_out( + UsbHcd *hcd, UsbDevice *device, void *buffer, uint32_t data_length, + UsbRequest *usb_req); #endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/usb/usb.h b/src/arch/x86/include/drivers/usb/usb.h index 3013d0d..e19d3f1 100644 --- a/src/arch/x86/include/drivers/usb/usb.h +++ b/src/arch/x86/include/drivers/usb/usb.h @@ -1,6 +1,7 @@ #ifndef _USB_H #define _USB_H +#include #include #include #include @@ -29,21 +30,6 @@ #define USB_REQ_GET_INTERFACE 0x0a #define USB_REQ_SYNC_FRAME 0x0c -#define USB_DESC_TYPE_DEVICE 0x01 -#define USB_DESC_TYPE_CONFIG 0x02 -#define USB_DESC_TYPE_STRING 0x03 -#define USB_DESC_TYPE_INTERFACE 0x04 -#define USB_DESC_TYPE_ENDPOINT 0x05 -#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06 -#define USB_DESC_TYPE_OTHER_SPEED_CONFIG 0x07 -#define USB_DESC_TYPE_INTERFACE_POWER 0x08 - -#define USB_DESC_TYPE_DEVICE_SIZE 18 -#define USB_DESC_TYPE_CONFIG_SIZE 9 -#define USB_DESC_TYPE_HUB_SIZE 9 - -#define USB_DESC_TYPE_HUB 0x29 - #define USB_PACKET_ID_IN 0x69 #define USB_PACKET_ID_OUT 0xe1 #define USB_PACKET_ID_SETUP 0x2d @@ -69,167 +55,104 @@ #define USB_PORT_STAT_TEST BIT(11) #define USB_PORT_STAT_INDICATOR BIT(12) -struct usb_device_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdUSB; - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint8_t bMaxPacketSize0; - uint16_t idVendor; - uint16_t idProduct; - uint16_t bcdDevice; - uint8_t iManufacturer; - uint8_t iProduct; - uint8_t iSerialNumber; - uint8_t bNumConfigurations; -} __attribute__((packed)); - -struct usb_config_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumInterfaces; - uint8_t bConfigurationValue; - uint8_t iConfiguration; - uint8_t bmAttributes; - uint8_t bMaxPower; -} __attribute__((packed)); - -struct usb_interface_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bInterfaceNumber; - uint8_t bAlternateSetting; - uint8_t bNumEndpoints; - uint8_t bInterfaceClass; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; - uint8_t iInterface; -} __attribute__((packed)); - -struct usb_endpoint_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bEndpointAddress; - uint8_t bmAttributes; - uint16_t wMaxPacketSize; - uint8_t bInterval; -} __attribute__((packed)); - -struct usb_string_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wData[]; -} __attribute__((packed)); - -struct usb_hub_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bNbrPorts; - uint16_t wHubCharacteristics; - uint8_t bPwrOn2PwrGood; - uint8_t bHubContrCurrent; - uint8_t DeviceRemovable; - uint8_t PortPwrCtrlMask; -} __attribute__((packed)); - -typedef enum usb_device_speed { +#define USB_BUILD_REQUEST( \ + direction, type, recipient, request_id, value_hi, value_lo, index, length) \ + { \ + .bmRequestType = direction << 7 | type << 5 | recipient, \ + .bRequest = request_id, \ + .wValue = HOST2LE_WORD(value_hi << 8 | value_lo), \ + .wIndex = HOST2LE_WORD(index), \ + .wLength = HOST2LE_WORD(length), \ + } + +typedef enum UsbDeviceSpeed { USB_SPEED_LOW, USB_SPEED_FULL, USB_SPEED_HIGH, -} usb_device_speed_t; +} UsbDeviceSpeed; -typedef struct usb_device { +typedef struct UsbDevice { list_t list; uint8_t address; list_t ep_lh; list_t interface_lh; - struct usb_device_descriptor *desc; - usb_device_speed_t speed; -} usb_device_t; + struct UsbDeviceDescriptor *desc; + UsbDeviceSpeed speed; + + struct UsbEndpoint *ep0; +} UsbDevice; + +typedef enum { + USB_EP_CONTROL, + USB_EP_ISOCHRONOUS, + USB_EP_BULK, + USB_EP_INTERRUPT, +} UsbEpTransferType; + +typedef enum { + USB_EP_OUT, + USB_EP_IN, +} UsbEpDirection; -typedef struct usb_endpoint { +typedef struct UsbEndpoint { list_t list; - uint8_t endpoint; - enum ep_transfer_type { - USB_EP_CONTROL, - USB_EP_ISOCHRONOUS, - USB_EP_BULK, - USB_EP_INTERRUPT, - } transfer_type; - enum ep_direction { - USB_EP_OUT, - USB_EP_IN, - } direction; - uint16_t max_packet_size; -} usb_endpoint_t; - -typedef struct usb_interface { + uint8_t endpoint; + UsbEpTransferType transfer_type; + UsbEpDirection direction; + uint16_t max_packet_size; + + void *sched; +} UsbEndpoint; + +typedef struct UsbInterface { list_t list; uint8_t interface; uint8_t class; uint8_t subclass; uint8_t protocol; -} usb_interface_t; - -typedef struct usb_transfer { - usb_device_t *device; - usb_endpoint_t *ep; -} usb_transfer_t; +} UsbInterface; -typedef enum usb_status { +typedef enum UsbStatus { USB_STATUS_ACK, USB_STATUS_NAK, USB_STATUS_STALL, USB_STATUS_NYET, USB_STATUS_ERR, -} usb_status_t; +} UsbStatus; -typedef enum usb_setup_status { +typedef enum UsbSetupStatus { USB_SETUP_SUCCESS, USB_SETUP_NAK_RECV, USB_SETUP_STALLED, USB_SETUP_CRC_TIMEOUT_ERR, USB_SETUP_BITSTUFF_ERR, USB_SETUP_DATABUFFER_ERR, -} usb_setup_status_t; +} UsbSetupStatus; -typedef struct usb_request { +typedef struct UsbRequest { uint8_t bmRequestType; uint8_t bRequest; uint16_t wValue; uint16_t wIndex; uint16_t wLength; -} usb_request_t; +} __attribute__((packed)) UsbRequest; -extern usb_endpoint_t usb_default_ep; +extern UsbEndpoint usb_ep0; -usb_device_t *usb_create_device(usb_device_speed_t speed, uint8_t address); -int usb_destroy_device(usb_device_t *device); +UsbDevice *usb_create_device(UsbDeviceSpeed speed, uint8_t address); +int usb_destroy_device(UsbDevice *device); -usb_request_t *usb_create_request( +UsbRequest *usb_create_request( uint8_t direction, uint8_t type, uint8_t recipient, uint8_t request_id, uint8_t value_hi, uint8_t value_lo, uint16_t index, uint16_t length); -usb_endpoint_t *usb_create_endpoint( - uint8_t endpoint, enum ep_transfer_type transfer_type, - enum ep_direction direction, uint16_t max_packet_size); - -usb_transfer_t *usb_create_transfer( - usb_device_t *device, usb_endpoint_t *endpoint); - -int usb_init_device(usb_hcd_t *hcd, usb_device_t *device); +UsbEndpoint *usb_create_endpoint( + UsbHcd *hcd, uint8_t endpoint, UsbEpTransferType transfer_type, + UsbEpDirection direction, uint16_t max_packet_size); -usb_setup_status_t usb_control_transaction_in( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, void *buffer, - usb_request_t *usb_req, uint32_t length); -usb_setup_status_t usb_control_transaction_out( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, void *buffer, - usb_request_t *usb_req, uint32_t length); +int usb_init_device(UsbHcd *hcd, UsbDevice *device); #endif \ No newline at end of file diff --git a/src/driver/Makefile b/src/driver/Makefile index 3f2e35f..39f9a8f 100644 --- a/src/driver/Makefile +++ b/src/driver/Makefile @@ -2,6 +2,7 @@ SRC += storage/ SRC += sound/ SRC += timer/ SRC += network/ +SRC += usb/ SRC += interrupt_dm.c SRC += video_dm.c SRC += video.c diff --git a/src/driver/usb/Makefile b/src/driver/usb/Makefile new file mode 100644 index 0000000..ed15285 --- /dev/null +++ b/src/driver/usb/Makefile @@ -0,0 +1,2 @@ +SRC += usb_dm.c +SRC += usb-core/ \ No newline at end of file diff --git a/src/driver/usb/usb-core/Makefile b/src/driver/usb/usb-core/Makefile new file mode 100644 index 0000000..c206bc9 --- /dev/null +++ b/src/driver/usb/usb-core/Makefile @@ -0,0 +1,4 @@ +SRC += func.c +SRC += hub.c +SRC += usb.c +SRC += hcd.c \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/func.c b/src/driver/usb/usb-core/func.c similarity index 53% rename from src/arch/x86/drivers/usb/func.c rename to src/driver/usb/usb-core/func.c index d665e85..abbbe29 100644 --- a/src/arch/x86/drivers/usb/func.c +++ b/src/driver/usb/usb-core/func.c @@ -1,48 +1,50 @@ +#include #include #include #include #include #include #include +#include -struct usb_device_descriptor *usb_get_device_descriptor( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep) { - struct usb_device_descriptor *desc = - kmalloc(sizeof(struct usb_device_descriptor)); +struct UsbDeviceDescriptor *usb_get_device_descriptor( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { + struct UsbDeviceDescriptor *desc = + kmalloc(sizeof(struct UsbDeviceDescriptor)); - usb_request_t *usb_req = usb_create_request( + UsbRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_GET_DESCRIPTOR, USB_DESC_TYPE_DEVICE, 0, 0, USB_DESC_TYPE_DEVICE_SIZE); - usb_control_transaction_in( - hcd, device, ep, desc, usb_req, USB_DESC_TYPE_DEVICE_SIZE); + + hcd->ops->ctrl_transfer_in( + hcd, device, desc, USB_DESC_TYPE_DEVICE_SIZE, &usb_req); return desc; } -struct usb_config_descriptor *usb_get_config_descriptor( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep) { - struct usb_config_descriptor *desc = - kmalloc(sizeof(struct usb_config_descriptor)); +struct UsbConfigDescriptor *usb_get_config_descriptor( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { + struct UsbConfigDescriptor *desc = + kmalloc(sizeof(struct UsbConfigDescriptor)); - usb_request_t *usb_req = usb_create_request( + UsbRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_GET_DESCRIPTOR, USB_DESC_TYPE_CONFIG, 0, 0, USB_DESC_TYPE_CONFIG_SIZE); - usb_control_transaction_in( - hcd, device, ep, desc, usb_req, USB_DESC_TYPE_CONFIG_SIZE); + hcd->ops->ctrl_transfer_in( + hcd, device, desc, USB_DESC_TYPE_CONFIG_SIZE, &usb_req); - uint8_t *buffer = kmalloc(desc->wTotalLength); - usb_req->wLength = desc->wTotalLength; - usb_control_transaction_in( - hcd, device, ep, buffer, usb_req, desc->wTotalLength); + uint8_t *buffer = kmalloc(desc->wTotalLength); + usb_req.wLength = desc->wTotalLength; + hcd->ops->ctrl_transfer_in(hcd, device, buffer, usb_req.wLength, &usb_req); int length = desc->wTotalLength; while (length > 0) { uint8_t type = buffer[1]; if (type == USB_DESC_TYPE_INTERFACE) { - struct usb_interface_descriptor *interface_desc = - (struct usb_interface_descriptor *)buffer; - usb_interface_t *interface = kmalloc(sizeof(usb_interface_t)); + struct UsbInterfaceDescriptor *interface_desc = + (struct UsbInterfaceDescriptor *)buffer; + UsbInterface *interface = kmalloc(sizeof(UsbInterface)); interface->interface = interface_desc->bInterfaceNumber; interface->class = interface_desc->bInterfaceClass; @@ -52,11 +54,11 @@ struct usb_config_descriptor *usb_get_config_descriptor( list_add_tail(&interface->list, &device->interface_lh); } else if (type == USB_DESC_TYPE_ENDPOINT) { - struct usb_endpoint_descriptor *endpoint_desc = - (struct usb_endpoint_descriptor *)buffer; + struct UsbEndpointDescriptor *endpoint_desc = + (struct UsbEndpointDescriptor *)buffer; - usb_endpoint_t *ep = usb_create_endpoint( - endpoint_desc->bEndpointAddress & 0x0f, + UsbEndpoint *ep = usb_create_endpoint( + hcd, endpoint_desc->bEndpointAddress & 0x0f, endpoint_desc->bmAttributes & 0x03, endpoint_desc->bEndpointAddress >> 7, endpoint_desc->wMaxPacketSize & 0x07ff); @@ -69,109 +71,104 @@ struct usb_config_descriptor *usb_get_config_descriptor( return desc; } -uint8_t usb_get_config( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep) { +uint8_t usb_get_config(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { uint8_t config; - usb_request_t *usb_req = usb_create_request( + UsbRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_GET_CONFIGURATION, 0, 0, 0, 1); - usb_control_transaction_in(hcd, device, ep, &config, usb_req, 1); + hcd->ops->ctrl_transfer_in(hcd, device, &config, 1, &usb_req); return config; } -usb_setup_status_t usb_set_config( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, uint8_t config) { +UsbSetupStatus usb_set_config( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t config) { - usb_request_t *usb_req = usb_create_request( + UsbRequest usb_req = USB_BUILD_REQUEST( USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_SET_CONFIGURATION, config, 0, 0, 0); - - return usb_control_transaction_out(hcd, device, ep, NULL, usb_req, 0); + return hcd->ops->ctrl_transfer_out(hcd, device, NULL, 0, &usb_req); } -struct usb_hub_descriptor *usb_get_hub_descriptor( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep) { - struct usb_hub_descriptor *desc = - kmalloc(sizeof(struct usb_hub_descriptor)); +struct UsbHubDescriptor *usb_get_hub_descriptor( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { + struct UsbHubDescriptor *desc = kmalloc(sizeof(struct UsbHubDescriptor)); - usb_request_t *usb_req = usb_create_request( + UsbRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_DEVICE, USB_REQ_GET_DESCRIPTOR, USB_DESC_TYPE_HUB, 0, 0, USB_DESC_TYPE_HUB_SIZE); - usb_control_transaction_in( - hcd, device, ep, desc, usb_req, USB_DESC_TYPE_HUB_SIZE); + hcd->ops->ctrl_transfer_in( + hcd, device, desc, USB_DESC_TYPE_HUB_SIZE, &usb_req); return desc; } -uint32_t usb_get_hub_status( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep) { +uint32_t usb_get_hub_status(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { uint32_t stat; - usb_request_t *usb_req = usb_create_request( + UsbRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_GET_STATUS, 0, 0, 0, 4); - usb_control_transaction_in(hcd, device, ep, &stat, usb_req, 4); + hcd->ops->ctrl_transfer_in(hcd, device, &stat, 4, &usb_req); return stat; } uint32_t usb_get_port_status( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, uint8_t port) { + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t port) { uint32_t stat; - usb_request_t *usb_req = usb_create_request( + UsbRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_OTHER, USB_REQ_GET_STATUS, 0, 0, port, REQ_GET_PORT_STATUS_SIZE); - usb_control_transaction_in( - hcd, device, ep, &stat, usb_req, REQ_GET_PORT_STATUS_SIZE); + hcd->ops->ctrl_transfer_in( + hcd, device, &stat, REQ_GET_PORT_STATUS_SIZE, &usb_req); return stat; } -struct usb_string_descriptor *usb_get_string_descriptor( - usb_hcd_t *hcd, usb_device_t *device, uint8_t index, usb_endpoint_t *ep) { +struct UsbStringDescriptor *usb_get_string_descriptor( + UsbHcd *hcd, UsbDevice *device, uint8_t index, UsbEndpoint *ep) { uint8_t buffer[2]; - usb_request_t *usb_req = usb_create_request( + UsbRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_GET_DESCRIPTOR, USB_DESC_TYPE_STRING, index, 0x0409, 2); - usb_control_transaction_in(hcd, device, ep, buffer, usb_req, 2); + hcd->ops->ctrl_transfer_in(hcd, device, buffer, 2, &usb_req); - struct usb_string_descriptor *desc = - kmalloc(sizeof(struct usb_string_descriptor) + buffer[0]); - usb_req->wLength = buffer[0]; - usb_control_transaction_in(hcd, device, ep, desc, usb_req, buffer[0]); + struct UsbStringDescriptor *desc = + kmalloc(sizeof(struct UsbStringDescriptor) + buffer[0]); + usb_req.wLength = buffer[0]; + hcd->ops->ctrl_transfer_in(hcd, device, desc, buffer[0], &usb_req); return desc; } -usb_setup_status_t usb_set_address( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, - uint32_t address) { +UsbSetupStatus usb_set_address( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint32_t address) { - usb_request_t *req = usb_create_request( + UsbRequest req = USB_BUILD_REQUEST( USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_SET_ADDRESS, address >> 8, address & 0xff, 0, 0); - return usb_control_transaction_out(hcd, device, ep, NULL, req, 0); + return hcd->ops->ctrl_transfer_out(hcd, device, NULL, 0, &req); } -usb_setup_status_t usb_set_port_feature( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, uint8_t port, +UsbSetupStatus usb_set_port_feature( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t port, uint16_t feature) { - usb_request_t *req = usb_create_request( + UsbRequest req = USB_BUILD_REQUEST( USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_OTHER, USB_REQ_SET_FEATURE, feature >> 8, feature & 0xff, port, 0); - return usb_control_transaction_out(hcd, device, ep, NULL, req, 0); + return hcd->ops->ctrl_transfer_out(hcd, device, NULL, 0, &req); } void usb_show_device_descriptor( - usb_hcd_t *hcd, usb_device_t *device, usb_endpoint_t *ep, - struct usb_device_descriptor *desc) { - printk("USB Device Descriptor:\n"); + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, + struct UsbDeviceDescriptor *desc) { + printk("\nUSB Device Descriptor:\n"); printk("Length: %d\n", desc->bLength); printk("DescriptorType: %d\n", desc->bDescriptorType); printk( @@ -188,7 +185,7 @@ void usb_show_device_descriptor( desc->bcdDevice & 0xff); printk("Manufacturer: "); - struct usb_string_descriptor *str1 = + struct UsbStringDescriptor *str1 = usb_get_string_descriptor(hcd, device, desc->iManufacturer, ep); for (int i = 0; i < (str1->bLength - 2) / 2; i++) { printk("%c", str1->wData[i]); @@ -196,7 +193,7 @@ void usb_show_device_descriptor( printk("\n"); printk("Product: "); - struct usb_string_descriptor *str2 = + struct UsbStringDescriptor *str2 = usb_get_string_descriptor(hcd, device, desc->iProduct, ep); for (int i = 0; i < (str2->bLength - 2) / 2; i++) { printk("%c", str2->wData[i]); @@ -204,7 +201,7 @@ void usb_show_device_descriptor( printk("\n"); printk("Serial Number: "); - struct usb_string_descriptor *str3 = + struct UsbStringDescriptor *str3 = usb_get_string_descriptor(hcd, device, desc->iSerialNumber, ep); for (int i = 0; i < (str3->bLength - 2) / 2; i++) { printk("%c", str3->wData[i]); @@ -214,8 +211,8 @@ void usb_show_device_descriptor( printk("Number of Configurations: %d\n", desc->bNumConfigurations); } -void usb_show_hub_descriptor(struct usb_hub_descriptor *desc) { - printk("USB Hub Descriptor:\n"); +void usb_show_hub_descriptor(struct UsbHubDescriptor *desc) { + printk("\nUSB Hub Descriptor:\n"); printk("Length: %d\n", desc->bLength); printk("DescriptorType: %d\n", desc->bDescriptorType); printk("Number of Ports: %d\n", desc->bNbrPorts); diff --git a/src/arch/x86/drivers/usb/hcd.c b/src/driver/usb/usb-core/hcd.c similarity index 64% rename from src/arch/x86/drivers/usb/hcd.c rename to src/driver/usb/usb-core/hcd.c index aea7c18..0735525 100644 --- a/src/arch/x86/drivers/usb/hcd.c +++ b/src/driver/usb/usb-core/hcd.c @@ -1,7 +1,10 @@ +#include "kernel/spinlock.h" +#include #include #include #include #include +#include #include #include #include @@ -9,25 +12,26 @@ #include LIST_HEAD(hcd_list); +SPINLOCK(bus_num_lock); +uint8_t new_bus_num = 0; -usb_hcd_t *usb_hcd_register( - device_t *device, char *name, uint32_t port_cnt, - usb_hcd_interface_t *interface) { - usb_hcd_t *hcd = kmalloc(sizeof(usb_hcd_t)); +UsbHcd *usb_hcd_register( + Device *device, char *name, uint32_t port_cnt, UsbHcdOps *interface) { + UsbHcd *hcd = kmalloc(sizeof(UsbHcd)); if (hcd == NULL) return NULL; list_add_tail(&hcd->list, &hcd_list); hcd->device = device; hcd->device_count = 0; - hcd->interface = interface; + hcd->ops = interface; string_t *string = kmalloc(sizeof(string_t)); string_init(string); string_new(string, name, strlen(name)); hcd->name = string; - hcd->ports = kmalloc(sizeof(usb_hcd_port_t) * port_cnt); + hcd->ports = kmalloc(sizeof(UsbHcdPort) * port_cnt); for (int i = 0; i < port_cnt; i++) { hcd->ports[i].port = i; diff --git a/src/driver/usb/usb-core/hub.c b/src/driver/usb/usb-core/hub.c new file mode 100644 index 0000000..93dabd8 --- /dev/null +++ b/src/driver/usb/usb-core/hub.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void usb_init_hub(UsbHcd *hcd, UsbDevice *device) { + Timer timer; + UsbEndpoint *ep0 = + usb_create_endpoint(hcd, 0, USB_EP_CONTROL, USB_EP_OUT, 64); + device->ep0 = ep0; + timer_init(&timer); + + hcd->device_count++; + usb_set_address(hcd, device, ep0, hcd->device_count); + delay_ms(&timer, 2); + device->address = hcd->device_count; + + struct UsbHubDescriptor *desc = usb_get_hub_descriptor(hcd, device, ep0); + // usb_show_hub_descriptor(desc); + uint32_t status = usb_get_hub_status(hcd, device, ep0); + + int i; + for (i = 1; i <= desc->bNbrPorts; i++) { + + usb_set_port_feature(hcd, device, ep0, i, HUB_FEAT_PORT_POWER); + delay_ms(&timer, 50); + usb_set_port_feature(hcd, device, ep0, i, HUB_FEAT_PORT_RESET); + delay_ms(&timer, 200); + + status = usb_get_port_status(hcd, device, ep0, i); + if (BIN_IS_EN(status, USB_PORT_STAT_CONNECTION)) { + UsbDevice *dev = usb_create_device( + (BIN_IS_EN(status, USB_PORT_STAT_LOW_SPEED) ? USB_SPEED_LOW + : USB_SPEED_FULL), + 0); + usb_init_device(hcd, dev); + delay_ms(&timer, 100); + } + } +} \ No newline at end of file diff --git a/src/driver/usb/usb-core/usb.c b/src/driver/usb/usb-core/usb.c new file mode 100644 index 0000000..37626bd --- /dev/null +++ b/src/driver/usb/usb-core/usb.c @@ -0,0 +1,73 @@ +#include "kernel/list.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +UsbDevice *usb_create_device(UsbDeviceSpeed speed, uint8_t address) { + UsbDevice *device = (UsbDevice *)kmalloc(sizeof(UsbDevice)); + list_init(&device->ep_lh); + device->desc = kmalloc(sizeof(struct UsbDeviceDescriptor)); + device->speed = speed; + device->address = address; + return device; +} + +int usb_destroy_device(UsbDevice *device) { + return kfree(device); +} + +UsbRequest *usb_create_request( + uint8_t direction, uint8_t type, uint8_t recipient, uint8_t request_id, + uint8_t value_hi, uint8_t value_lo, uint16_t index, uint16_t length) { + UsbRequest *request = (UsbRequest *)kmalloc(sizeof(UsbRequest)); + request->bmRequestType = direction << 7 | type << 5 | recipient; + request->bRequest = request_id; + request->wValue = HOST2LE_WORD(value_hi << 8 | value_lo); + request->wIndex = HOST2LE_WORD(index); + request->wLength = HOST2LE_WORD(length); + return request; +} + +UsbEndpoint *usb_create_endpoint( + UsbHcd *hcd, uint8_t endpoint, UsbEpTransferType transfer_type, + UsbEpDirection direction, uint16_t max_packet_size) { + UsbEndpoint *ep = (UsbEndpoint *)kmalloc(sizeof(UsbEndpoint)); + ep->endpoint = endpoint; + ep->transfer_type = transfer_type; + ep->direction = direction; + ep->max_packet_size = max_packet_size; + + ep->sched = hcd->ops->create_sched(); + return ep; +} + +int usb_init_device(UsbHcd *hcd, UsbDevice *device) { + UsbEndpoint *ep0 = + usb_create_endpoint(hcd, 0, USB_EP_CONTROL, USB_EP_OUT, 64); + device->ep0 = ep0; + + struct UsbDeviceDescriptor *desc = + usb_get_device_descriptor(hcd, device, ep0); + // usb_show_device_descriptor(hcd, device, ep0, desc); + hcd->device_count++; + usb_set_address(hcd, device, ep0, hcd->device_count); + + Timer timer; + timer_init(&timer); + delay_ms(&timer, 2); + + device->address = hcd->device_count; + usb_get_config_descriptor(hcd, device, ep0); + + usb_set_config(hcd, device, ep0, 1); + + if (desc->bDeviceClass == USB_CLASS_HUB) { usb_init_hub(hcd, device); } + return 0; +} \ No newline at end of file diff --git a/src/driver/usb/usb_dm.c b/src/driver/usb/usb_dm.c new file mode 100644 index 0000000..2efde00 --- /dev/null +++ b/src/driver/usb/usb_dm.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include +#include +#include + +// DriverResult usb_dm_load(DeviceManager *manager); +// DriverResult usb_dm_unload(DeviceManager *manager); + +DeviceManagerOps usb_dm_ops = { + .dm_load = NULL, + .dm_unload = NULL, +}; + +// UsbDeviceManager usb_dm_ext; +DeviceManager usb_dm = { + .type = DEVICE_TYPE_USB, .ops = &usb_dm_ops, + // .private_data = &usb_dm_ext, +}; \ No newline at end of file diff --git a/src/drivers/Makefile b/src/drivers/Makefile new file mode 100644 index 0000000..8de20a2 --- /dev/null +++ b/src/drivers/Makefile @@ -0,0 +1 @@ +SRC += bus/ \ No newline at end of file diff --git a/src/drivers/bus/Makefile b/src/drivers/bus/Makefile new file mode 100644 index 0000000..347720f --- /dev/null +++ b/src/drivers/bus/Makefile @@ -0,0 +1 @@ +SRC += usb.c \ No newline at end of file diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c new file mode 100644 index 0000000..7b3ecb3 --- /dev/null +++ b/src/drivers/bus/usb.c @@ -0,0 +1,104 @@ +#include "drivers/bus/usb.h" +#include "kernel/device.h" +#include "kernel/device_driver.h" +#include "kernel/driver.h" +#include "kernel/list.h" +#include "objects/object.h" +#include +#include +#include +#include +#include +#include + +LIST_HEAD(hci_lh); + +BusDriverOps usb_bus_driver_ops = { + .register_bus_hook = NULL, + .unregister_bus_hook = NULL, + .init = NULL, +}; +DeviceDriverOps usb_device_driver_ops = { + .device_driver_init = NULL, + .device_driver_uninit = NULL, +}; +BusOps usb_bus_ops = { + .register_device_hook = NULL, + .unregister_device_hook = NULL, + .scan_bus = NULL, + .probe_device = NULL, +}; +DeviceOps usb_device_ops = { + .init = NULL, + .start = NULL, + .stop = NULL, + .destroy = NULL, + .status = NULL, +}; +BusControllerDeviceOps usb_bus_controller_ops = { + .probe = NULL, +}; + +DriverDependency usb_dependencies[] = { + { + .in_type = DRIVER_DEPENDENCY_TYPE_BUS, + .dependency_in_bus = {BUS_TYPE_PCI, 0}, + .out_bus = NULL, + }, +}; +Driver usb_driver = { + .short_name = STRING_INIT("UsbDriver"), + .dependency_count = sizeof(usb_dependencies) / sizeof(DriverDependency), + .dependencies = usb_dependencies, + .init = NULL, +}; +BusDriver usb_bus_driver = { + .driver_type = DRIVER_TYPE_BUS_DRIVER, + .bus_type = BUS_TYPE_PCI, + .state = DRIVER_STATE_UNREGISTERED, + .private_data_size = 0, + .ops = &usb_bus_driver_ops, +}; +DeviceDriver usb_device_driver = { + .name = STRING_INIT("USB Device Driver"), + .type = DEVICE_TYPE_BUS_CONTROLLER, + .state = DRIVER_STATE_UNREGISTERED, + .private_data_size = 0, + .ops = &usb_device_driver_ops, +}; +Device usb_device = { + .name = STRING_INIT("System USB Controller"), + .state = DEVICE_STATE_UNREGISTERED, + .bus = &platform_bus, + .private_data_size = 0, + .ops = &usb_device_ops, +}; +BusControllerDevice usb_bus_controller_device = { + .short_name = STRING_INIT("USB Bus Controller"), + .device = &usb_device, + .bus_driver = &usb_bus_driver, + .bus_controller_ops = NULL, +}; +Bus usb_bus = { + .bus_num = 0, + .ops = &usb_bus_ops, + .bus_driver = &usb_bus_driver, + .name = STRING_INIT("Universal Serial Bus"), + .controller_device = &usb_device, +}; + +static __init void usb_bus_driver_entry(void) { + register_driver(&usb_driver); + register_device_driver(&usb_driver, &usb_device_driver); + ObjectAttr attr = device_object_attr; + register_bus_controller_device( + &usb_device_driver, &usb_bus_driver, &usb_device, + &usb_bus_controller_device, &attr); + + HciInit *hci_init; + list_for_each_owner (hci_init, &hci_lh, list) { + if (hci_init->init) hci_init->init(&usb_driver); + } +} + +driver_initcall(usb_bus_driver_entry); diff --git a/src/include/drivers/bus/usb.h b/src/include/drivers/bus/usb.h new file mode 100644 index 0000000..4e8c486 --- /dev/null +++ b/src/include/drivers/bus/usb.h @@ -0,0 +1,17 @@ +#ifndef _BUS_USB_H +#define _BUS_USB_H + +#include +#include +#include + +extern BusDriver usb_bus_driver; +extern Driver usb_driver; +extern list_t hci_lh; + +typedef struct HciInit { + list_t list; + void (*init)(Driver *driver); +} HciInit; + +#endif \ No newline at end of file diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index ea96643..7c756c6 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -32,6 +32,7 @@ typedef enum { DEVICE_TYPE_BUS_CONTROLLER, DEVICE_TYPE_ETHERNET, DEVICE_TYPE_TIME, // 时间设备(如:Unix时间戳/UTC时间) + DEVICE_TYPE_USB, DEVICE_TYPE_MAX, } DeviceType; diff --git a/src/kernel/driver.c b/src/kernel/driver.c index 124aaec..6354594 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -147,7 +147,6 @@ void sub_driver_start_thread(void *arg) { if (bus_driver->ops->init != NULL) { bus_driver->ops->init(bus_driver); } - sub_driver->state = SUBDRIVER_STATE_READY; Bus *bus; list_for_each_owner (bus, &bus_driver->bus_lh, bus_list) { @@ -164,6 +163,7 @@ void sub_driver_start_thread(void *arg) { bus->ops->probe_device(bus_driver, bus); } } + sub_driver->state = SUBDRIVER_STATE_READY; } } From a651b1c1229c820399a9b3230647aeb4e9bb9149 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 17 Sep 2025 21:17:17 +0800 Subject: [PATCH 113/158] =?UTF-8?q?usb:=20=E4=BF=AE=E6=94=B9=20usb-core?= =?UTF-8?q?=E5=A4=B4=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/usb/hci/uhci.c | 5 ++--- src/arch/x86/drivers/usb/hci/uhci/packet.c | 4 ++-- src/arch/x86/include/drivers/usb/uhci.h | 4 ++-- src/driver/usb/usb-core/func.c | 6 +++--- src/driver/usb/usb-core/hcd.c | 4 ++-- src/driver/usb/usb-core/hub.c | 10 +++++----- src/driver/usb/usb-core/usb.c | 8 ++++---- .../drivers => include/driver}/usb/descriptors.h | 0 .../x86/include/drivers => include/driver}/usb/func.h | 2 +- .../x86/include/drivers => include/driver}/usb/hcd.h | 0 .../x86/include/drivers => include/driver}/usb/hub.h | 2 +- .../x86/include/drivers => include/driver}/usb/usb.h | 2 +- 12 files changed, 23 insertions(+), 24 deletions(-) rename src/{arch/x86/include/drivers => include/driver}/usb/descriptors.h (100%) rename src/{arch/x86/include/drivers => include/driver}/usb/func.h (97%) rename src/{arch/x86/include/drivers => include/driver}/usb/hcd.h (100%) rename src/{arch/x86/include/drivers => include/driver}/usb/hub.h (95%) rename src/{arch/x86/include/drivers => include/driver}/usb/usb.h (99%) diff --git a/src/arch/x86/drivers/usb/hci/uhci.c b/src/arch/x86/drivers/usb/hci/uhci.c index 69000d9..925505b 100644 --- a/src/arch/x86/drivers/usb/hci/uhci.c +++ b/src/arch/x86/drivers/usb/hci/uhci.c @@ -12,15 +12,14 @@ #include "driver/timer_dm.h" #include "kernel/driver_interface.h" #include "kernel/list.h" -#include "kernel/thread.h" #include "objects/object.h" #include +#include +#include #include #include #include -#include #include -#include #include #include #include diff --git a/src/arch/x86/drivers/usb/hci/uhci/packet.c b/src/arch/x86/drivers/usb/hci/uhci/packet.c index 8bde628..3ee1a98 100644 --- a/src/arch/x86/drivers/usb/hci/uhci/packet.c +++ b/src/arch/x86/drivers/usb/hci/uhci/packet.c @@ -1,9 +1,9 @@ #include "driver/timer_dm.h" #include +#include +#include #include -#include #include -#include #include #include #include diff --git a/src/arch/x86/include/drivers/usb/uhci.h b/src/arch/x86/include/drivers/usb/uhci.h index 0496a2f..faab483 100644 --- a/src/arch/x86/include/drivers/usb/uhci.h +++ b/src/arch/x86/include/drivers/usb/uhci.h @@ -1,11 +1,11 @@ #ifndef _UHCI_H #define _UHCI_H -#include "drivers/usb/hcd.h" #include #include +#include +#include #include -#include #include #define FRAMELIST_SIZE 1024 diff --git a/src/driver/usb/usb-core/func.c b/src/driver/usb/usb-core/func.c index abbbe29..d534752 100644 --- a/src/driver/usb/usb-core/func.c +++ b/src/driver/usb/usb-core/func.c @@ -1,6 +1,6 @@ -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/src/driver/usb/usb-core/hcd.c b/src/driver/usb/usb-core/hcd.c index 0735525..2653a59 100644 --- a/src/driver/usb/usb-core/hcd.c +++ b/src/driver/usb/usb-core/hcd.c @@ -1,8 +1,8 @@ #include "kernel/spinlock.h" +#include +#include #include -#include #include -#include #include #include #include diff --git a/src/driver/usb/usb-core/hub.c b/src/driver/usb/usb-core/hub.c index 93dabd8..984591e 100644 --- a/src/driver/usb/usb-core/hub.c +++ b/src/driver/usb/usb-core/hub.c @@ -1,11 +1,11 @@ #include #include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include #include void usb_init_hub(UsbHcd *hcd, UsbDevice *device) { diff --git a/src/driver/usb/usb-core/usb.c b/src/driver/usb/usb-core/usb.c index 37626bd..344a13b 100644 --- a/src/driver/usb/usb-core/usb.c +++ b/src/driver/usb/usb-core/usb.c @@ -1,11 +1,11 @@ #include "kernel/list.h" #include #include +#include +#include +#include +#include #include -#include -#include -#include -#include #include #include #include diff --git a/src/arch/x86/include/drivers/usb/descriptors.h b/src/include/driver/usb/descriptors.h similarity index 100% rename from src/arch/x86/include/drivers/usb/descriptors.h rename to src/include/driver/usb/descriptors.h diff --git a/src/arch/x86/include/drivers/usb/func.h b/src/include/driver/usb/func.h similarity index 97% rename from src/arch/x86/include/drivers/usb/func.h rename to src/include/driver/usb/func.h index 8d7d1fb..48fe2e3 100644 --- a/src/arch/x86/include/drivers/usb/func.h +++ b/src/include/driver/usb/func.h @@ -1,7 +1,7 @@ #ifndef _USB_FUNC_H #define _USB_FUNC_H -#include +#include #define REQ_GET_PORT_STATUS_SIZE 4 diff --git a/src/arch/x86/include/drivers/usb/hcd.h b/src/include/driver/usb/hcd.h similarity index 100% rename from src/arch/x86/include/drivers/usb/hcd.h rename to src/include/driver/usb/hcd.h diff --git a/src/arch/x86/include/drivers/usb/hub.h b/src/include/driver/usb/hub.h similarity index 95% rename from src/arch/x86/include/drivers/usb/hub.h rename to src/include/driver/usb/hub.h index 21f7333..82c665b 100644 --- a/src/arch/x86/include/drivers/usb/hub.h +++ b/src/include/driver/usb/hub.h @@ -1,7 +1,7 @@ #ifndef _USB_HUB_H #define _USB_HUB_H -#include +#include #define HUB_FEAT_C_LOCAL_POWER 0 #define HUB_FEAT_C_OVER_CURRENT 1 diff --git a/src/arch/x86/include/drivers/usb/usb.h b/src/include/driver/usb/usb.h similarity index 99% rename from src/arch/x86/include/drivers/usb/usb.h rename to src/include/driver/usb/usb.h index e19d3f1..83f7277 100644 --- a/src/arch/x86/include/drivers/usb/usb.h +++ b/src/include/driver/usb/usb.h @@ -2,7 +2,7 @@ #define _USB_H #include -#include +#include #include #include #include From 7b60d89d98798a7291a95dc51e755c2b913a987e Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 18 Sep 2025 15:01:13 +0800 Subject: [PATCH 114/158] =?UTF-8?q?font:=20=E4=BF=AE=E5=A4=8D=E5=AD=97?= =?UTF-8?q?=E4=BD=93'\'=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/font-default.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/font-default.c b/src/kernel/font-default.c index b2251ee..e5ca688 100644 --- a/src/kernel/font-default.c +++ b/src/kernel/font-default.c @@ -1585,7 +1585,7 @@ unsigned char font16[] = { 0b00001000, 0b00000100, 0b00000100, - 0000000010, + 0b00000010, 0b00000010, 0b00000011, 0b00000000, From 2984e43f6743b7a73391b3611653d97175b15fe2 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 18 Sep 2025 15:02:03 +0800 Subject: [PATCH 115/158] =?UTF-8?q?types:=20=E4=BF=AE=E5=A4=8D=20VOLUME?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/objects/types.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/objects/types.c b/src/objects/types.c index 1be501b..717d09a 100644 --- a/src/objects/types.c +++ b/src/objects/types.c @@ -5,14 +5,18 @@ static int type_number = OBJECT_TYPE_BUILTIN_MAX; -#define DEFINE_OBJECT_TYPE(type_name) \ - { .name = STRING_INIT(#type_name), .value.type = OBJECT_TYPE_##type_name, } +#define DEFINE_OBJECT_TYPE(type_name) \ + { \ + .name = STRING_INIT(#type_name), \ + .value.type = OBJECT_TYPE_##type_name, \ + } Object object_builtin_types[OBJECT_TYPE_BUILTIN_MAX] = { DEFINE_OBJECT_TYPE(TYPE), DEFINE_OBJECT_TYPE(DIRECTORY), DEFINE_OBJECT_TYPE(DRIVER), DEFINE_OBJECT_TYPE(DEVICE), DEFINE_OBJECT_TYPE(FILE), DEFINE_OBJECT_TYPE(VALUE), DEFINE_OBJECT_TYPE(SYM_LINK), DEFINE_OBJECT_TYPE(PARTITION), + DEFINE_OBJECT_TYPE(VOLUME), }; Object object_type_directory = { @@ -27,6 +31,7 @@ ObjectResult init_builtin_types() { for (int i = 0; i < OBJECT_TYPE_BUILTIN_MAX; i++) { add_object(&object_type_directory, &object_builtin_types[i]); init_base_obj_sys_attr(&object_builtin_types[i]); + object_builtin_types[i].attr->type = OBJECT_TYPE_TYPE; } return OBJECT_OK; From ff813e816829c159a6fb86caa5071c247c020562 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 18 Sep 2025 15:02:35 +0800 Subject: [PATCH 116/158] =?UTF-8?q?lib:=20=E7=AE=80=E5=8C=96itoa=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/string.h | 4 ++-- src/lib/string.c | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/include/string.h b/src/include/string.h index 6077c55..46769d1 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -13,7 +13,7 @@ #define STRING_MAX_LEN 256 #define STRING_INIT(str) \ - { .text = str "\0", .length = sizeof(str), .max_length = sizeof(str) } + {.text = str "\0", .length = sizeof(str), .max_length = sizeof(str)} typedef struct _string { unsigned int length; @@ -31,7 +31,7 @@ int string_new_with_string_number( void string_del(string_t *string); int string_cpy(string_t *dest, string_t *src); -char *itoa(char **ps, int val, int base); +char *itoa(char *ps, int val, int base); int atoi(const char *src); char *itoa16_align(char *str, int num); diff --git a/src/lib/string.c b/src/lib/string.c index 512cd66..ba9f51a 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -143,13 +143,14 @@ int strncmp(const char *s1, const char *s2, int n) { return (*s1 - *s2); } -char *itoa(char **ps, int val, int base) { +char *itoa(char *ps, int val, int base) { int m = val % base; int q = val / base; if (q) { itoa(ps, q, base); } - *(*ps)++ = (m < 10) ? (m + '0') : (m - 10 + 'A'); + *ps = (m < 10) ? (m + '0') : (m - 10 + 'A'); + ps++; - return *ps; + return ps; } int atoi(const char *src) { From cbe690333937c827599eead8cf4efc08046bbd9b Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 18 Sep 2025 15:06:53 +0800 Subject: [PATCH 117/158] =?UTF-8?q?device:=20=E5=8A=A0=E5=85=A5ops?= =?UTF-8?q?=E9=9D=9E=E7=A9=BA=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/disk/ata/ide_controller.c | 3 +-- src/driver/bus_dm.c | 2 +- src/driver/interrupt_dm.c | 10 +++++----- src/driver/network/network_dm.c | 2 +- src/driver/sound/sound_dm.c | 2 +- src/driver/storage/storage_dm.c | 2 +- src/driver/video_dm.c | 2 +- src/include/kernel/device.h | 2 +- src/include/kernel/driver.h | 4 ++-- src/kernel/device.c | 11 ++++++++--- src/kernel/driver.c | 4 ++-- 11 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/arch/x86/drivers/disk/ata/ide_controller.c b/src/arch/x86/drivers/disk/ata/ide_controller.c index 710b9b8..1feaea5 100644 --- a/src/arch/x86/drivers/disk/ata/ide_controller.c +++ b/src/arch/x86/drivers/disk/ata/ide_controller.c @@ -77,10 +77,9 @@ void ide_detect_channel_mode( DriverResult ide_controller_probe(PciDevice *pci_device) { Device *device = kmalloc_from_template(ide_controller_device_templete); - string_t name = STRING_INIT(""); ObjectAttr attr = device_object_attr; register_device( - &ide_controller_device_driver, name, pci_device->bus, device, &attr); + &ide_controller_device_driver, NULL, pci_device->bus, device, &attr); IdeControllerInfo *info = device->private_data; info->pci_device = pci_device; diff --git a/src/driver/bus_dm.c b/src/driver/bus_dm.c index e046707..55a3e7e 100644 --- a/src/driver/bus_dm.c +++ b/src/driver/bus_dm.c @@ -35,7 +35,7 @@ DriverResult register_bus_controller_device( bus_controller_device->bus_driver = bus_driver; DRV_RESULT_DELIVER_CALL( - register_device, device_driver, bus_controller_device->short_name, + register_device, device_driver, &bus_controller_device->short_name, device->bus, device, attr); return DRIVER_RESULT_OK; } diff --git a/src/driver/interrupt_dm.c b/src/driver/interrupt_dm.c index 8a4b6a3..1e3fa19 100644 --- a/src/driver/interrupt_dm.c +++ b/src/driver/interrupt_dm.c @@ -37,30 +37,30 @@ DriverResult check_intterupt_ops(InterruptDevice *interrupt_device) { if (!interrupt_device->interrupt_ops) { print_error_with_position( "%s has no operations\n", interrupt_device->device->name.text); - return DRIVER_RESULT_DEVICE_DRIVER_HAVE_NO_OPS; + return DRIVER_RESULT_NO_OPS; } if (!interrupt_device->interrupt_ops->disable_irq) { print_error_with_position( "%s has no disable_irq operation\n", interrupt_device->device->name.text); - return DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS; + return DRIVER_RESULT_INCOMPLETABLE_OPS; } if (!interrupt_device->interrupt_ops->enable_irq) { print_error_with_position( "%s has no enable_irq operation\n", interrupt_device->device->name.text); - return DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS; + return DRIVER_RESULT_INCOMPLETABLE_OPS; } if (!interrupt_device->interrupt_ops->eoi) { print_error_with_position( "%s has no eoi operation\n", interrupt_device->device->name.text); - return DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS; + return DRIVER_RESULT_INCOMPLETABLE_OPS; } if (!interrupt_device->interrupt_ops->redirect_irq) { print_error_with_position( "%s has no redirect_irq operation\n", interrupt_device->device->name.text); - return DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS; + return DRIVER_RESULT_INCOMPLETABLE_OPS; } return DRIVER_RESULT_OK; } diff --git a/src/driver/network/network_dm.c b/src/driver/network/network_dm.c index d167956..7e87223 100644 --- a/src/driver/network/network_dm.c +++ b/src/driver/network/network_dm.c @@ -55,7 +55,7 @@ DriverResult register_network_device( string_t name; string_new_with_number(&name, "Network", 7, network_dm_ext.device_count++); DRIVER_RESULT_PASS(register_device( - device->device_driver, name, device->bus, device, attr)); + device->device_driver, &name, device->bus, device, attr)); device->object->out.type = TRANSFER_TYPE_STREAM; device->object->out.stream = network_transfer; diff --git a/src/driver/sound/sound_dm.c b/src/driver/sound/sound_dm.c index d099084..7a0e043 100644 --- a/src/driver/sound/sound_dm.c +++ b/src/driver/sound/sound_dm.c @@ -44,7 +44,7 @@ DriverResult register_sound_device( string_t name; string_new_with_number(&name, "Sound", 5, sound_dm_ext.device_count++); DRIVER_RESULT_PASS(register_device( - device->device_driver, name, device->bus, device, attr)); + device->device_driver, &name, device->bus, device, attr)); return DRIVER_RESULT_OK; } diff --git a/src/driver/storage/storage_dm.c b/src/driver/storage/storage_dm.c index 6df0904..b6a7c9a 100644 --- a/src/driver/storage/storage_dm.c +++ b/src/driver/storage/storage_dm.c @@ -59,7 +59,7 @@ DriverResult register_storage_device( string_t name; string_new_with_number(&name, "Storage", 7, storage_dm_ext.device_count++); DRV_RESULT_DELIVER_CALL( - register_device, device_driver, name, device->bus, device, attr); + register_device, device_driver, &name, device->bus, device, attr); list_add_tail(&device->dm_list, &storage_dm.device_lh); device->object->in.type = TRANSFER_TYPE_BLOCK; diff --git a/src/driver/video_dm.c b/src/driver/video_dm.c index 6fde5f2..8d3a769 100644 --- a/src/driver/video_dm.c +++ b/src/driver/video_dm.c @@ -56,7 +56,7 @@ DriverResult register_video_device( &name, "Video", 5, video_dm_ext.video_device_count++); DRV_RESULT_DELIVER_CALL( - register_device, device_driver, name, device->bus, device, attr); + register_device, device_driver, &name, device->bus, device, attr); list_init(&video_device->video_list_lh); list_add_tail(&device->dm_list, &video_dm.device_lh); diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index 7c756c6..8ac7dd1 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -117,7 +117,7 @@ static const ObjectAttr device_object_attr = { }; DriverResult register_device( - struct DeviceDriver *device_driver, string_t name, struct Bus *bus, + struct DeviceDriver *device_driver, string_t *name, struct Bus *bus, Device *device, ObjectAttr *attr); DriverResult unregister_device( struct DeviceDriver *device_driver, Device *device); diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index ebccfce..3c6dba5 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -151,8 +151,8 @@ typedef enum DriverResult { DRIVER_RESULT_DEVICE_MANAGER_NOT_EXIST, DRIVER_RESULT_DEVICE_NOT_EXIST, DRIVER_RESULT_DEVICE_DRIVER_CONFLICT, - DRIVER_RESULT_DEVICE_DRIVER_HAVE_NO_OPS, - DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS, + DRIVER_RESULT_NO_OPS, + DRIVER_RESULT_INCOMPLETABLE_OPS, DRIVER_RESULT_NO_VALID_CHILD_DEVICE, DRIVER_RESULT_INVALID_IRQ_NUMBER, DRIVER_RESULT_OUT_OF_MEMORY, diff --git a/src/kernel/device.c b/src/kernel/device.c index 4717edc..6f85a3a 100644 --- a/src/kernel/device.c +++ b/src/kernel/device.c @@ -1,3 +1,4 @@ +#include "kernel/console.h" #include #include #include @@ -19,8 +20,12 @@ * @return DriverResult */ DriverResult register_device( - DeviceDriver *device_driver, string_t name, Bus *bus, Device *device, + DeviceDriver *device_driver, string_t *name, Bus *bus, Device *device, ObjectAttr *attr) { + if (device->ops == NULL) { + printk(COLOR_RED "Error: Device %s has no ops!\n", device->name.text); + return DRIVER_RESULT_NO_OPS; + } device->state = DEVICE_STATE_REGISTERED; @@ -41,9 +46,9 @@ DriverResult register_device( bus_register_device(device, bus, attr); - if (name.text != NULL && name.length != 0) { + if (name != NULL && name->text != NULL && name->length != 0) { attr->type = OBJECT_TYPE_SYM_LINK; - Object *object = create_object(&device_object, name, *attr); + Object *object = create_object(&device_object, *name, *attr); object->value.sym_link = device->object; } diff --git a/src/kernel/driver.c b/src/kernel/driver.c index 6354594..01cfc5b 100644 --- a/src/kernel/driver.c +++ b/src/kernel/driver.c @@ -59,8 +59,8 @@ void print_driver_result( RESULT_CASE_PRINT(DRIVER_RESULT_OK) RESULT_CASE_PRINT(DRIVER_RESULT_TIMEOUT) RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_DRIVER_CONFLICT) - RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_DRIVER_HAVE_NO_OPS) - RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_DRIVER_HAVE_INCOMPLETABLE_OPS) + RESULT_CASE_PRINT(DRIVER_RESULT_NO_OPS) + RESULT_CASE_PRINT(DRIVER_RESULT_INCOMPLETABLE_OPS) RESULT_CASE_PRINT(DRIVER_RESULT_NO_VALID_CHILD_DEVICE) RESULT_CASE_PRINT(DRIVER_RESULT_INVALID_IRQ_NUMBER) RESULT_CASE_PRINT(DRIVER_RESULT_OUT_OF_MEMORY) From 4b65ca1a2bdbc14e8100a5f5b53efe34303bf91d Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 18 Sep 2025 15:08:00 +0800 Subject: [PATCH 118/158] =?UTF-8?q?page:=20=E5=B0=86=E7=AC=AC0=E9=A1=B5?= =?UTF-8?q?=E8=AE=BE=E4=B8=BA=E4=B8=8D=E5=8F=AF=E8=AE=BF=E9=97=AE=EF=BC=9B?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=BA=9B=E6=B6=89=E5=8F=8A=E7=A9=BA?= =?UTF-8?q?=E6=8C=87=E9=92=88=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/kernel/page.c | 1 + src/arch/x86/kernel/platform.c | 1 + src/include/kernel/ards.h | 4 ++-- src/include/kernel/list.h | 6 +++--- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/arch/x86/kernel/page.c b/src/arch/x86/kernel/page.c index c883330..e8f82a5 100644 --- a/src/arch/x86/kernel/page.c +++ b/src/arch/x86/kernel/page.c @@ -38,6 +38,7 @@ void setup_page(void) { pt[i] = addr; addr += PAGE_SIZE; } + pt[0] &= ~SIGN_P; // 0x00000000不可用 // 0x00800000 - 0x00bfffff pdt[2] = (DMA_PT_PHY_ADDR2 | SIGN_RW | SIGN_SYS | SIGN_P); diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index f9331c8..c611496 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -59,6 +59,7 @@ void platform_init() { platform_bus.object = platform_bus_driver.object; list_init(&platform_bus_driver.bus_lh); list_add_tail(&platform_bus.bus_list, &platform_bus_driver.bus_lh); + list_init(&platform_bus.device_lh); read_features(); diff --git a/src/include/kernel/ards.h b/src/include/kernel/ards.h index 24e0ca1..e748818 100644 --- a/src/include/kernel/ards.h +++ b/src/include/kernel/ards.h @@ -3,8 +3,8 @@ #include -#define ARDS_ADDR 0x500 // ARDS结构从哪儿开始储存 -#define ARDS_NR (0x500 + 0x100 - 4) // 记录的ards数量 +#define ARDS_ADDR 0x1500 // ARDS结构从哪儿开始储存 +#define ARDS_NR (0x1500 + 0x100 - 4) // 记录的ards数量 /* ards结构体 diff --git a/src/include/kernel/list.h b/src/include/kernel/list.h index 3b4d7a2..9370576 100644 --- a/src/include/kernel/list.h +++ b/src/include/kernel/list.h @@ -15,8 +15,7 @@ typedef struct list { struct list *next; } list_t; -#define LIST_HEAD_INIT(name) \ - { &(name), &(name) } +#define LIST_HEAD_INIT(name) {&(name), &(name)} #define LIST_HEAD(name) struct list name = LIST_HEAD_INIT(name) @@ -133,7 +132,8 @@ static inline int list_is_last( } static inline int list_empty(const struct list *head) { - return (head->next == head); // 链表头的下一个是否为自己 + return (head->next == head) || !head->next || + !head->prev; // 链表头的下一个是否为自己 } #define list_owner(ptr, type, member) container_of(ptr, type, member) From 290c9940f250a4e5fbdbc397417f454420fd37d9 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 18 Sep 2025 15:08:51 +0800 Subject: [PATCH 119/158] =?UTF-8?q?usb&uhci:=20=E5=B0=86usb=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E6=B3=A8=E5=86=8C=E5=88=B0object=20tree=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/usb/hci/uhci.c | 45 +++++++++---------- src/arch/x86/drivers/usb/hci/uhci/packet.c | 2 +- src/arch/x86/include/drivers/usb/uhci.h | 1 + src/driver/usb/usb-core/func.c | 1 + src/driver/usb/usb-core/hcd.c | 50 +++++++++++++++------ src/driver/usb/usb-core/hub.c | 2 + src/driver/usb/usb-core/usb.c | 49 ++++++++++++++------- src/driver/usb/usb_dm.c | 51 +++++++++++++++++++--- src/drivers/bus/usb.c | 20 ++------- src/include/driver/usb/func.h | 23 +++++----- src/include/driver/usb/hcd.h | 11 +++-- src/include/driver/usb/hub.h | 2 +- src/include/driver/usb/usb.h | 24 ++++------ src/include/driver/usb/usb_dm.h | 39 +++++++++++++++++ src/include/drivers/bus/usb.h | 1 + 15 files changed, 219 insertions(+), 102 deletions(-) create mode 100644 src/include/driver/usb/usb_dm.h diff --git a/src/arch/x86/drivers/usb/hci/uhci.c b/src/arch/x86/drivers/usb/hci/uhci.c index 925505b..3861a61 100644 --- a/src/arch/x86/drivers/usb/hci/uhci.c +++ b/src/arch/x86/drivers/usb/hci/uhci.c @@ -8,11 +8,9 @@ * 目前仅仅只是初始化了UHCI而已,其他涉及USB协议的东西都还没做 * */ -#include "driver/bus_dm.h" #include "driver/timer_dm.h" #include "kernel/driver_interface.h" #include "kernel/list.h" -#include "objects/object.h" #include #include #include @@ -38,15 +36,16 @@ #define UHCI_SUBCLASSID 0x03 #define UHCI_PROGIF 0x00 -#define DRV_NAME "Universal Serial Bus(USB) Driver" -#define DEV_NAME "Universal Host Controller Interface(UHCI)" +#define DRV_NAME "Universal Serial Bus(USB) Driver" +#define DEV_NAME "UHCI" +#define DEV_FULL_NAME "Universal Host Controller Interface(UHCI)" void uhci_register(Driver *driver); DriverResult uhci_init(Device *device); DriverResult uhci_start(Device *device); DriverResult uhci_pci_probe(PciDevice *pci_device); -extern UsbHcdOps uhci_interface; +extern UsbHcdOps uhci_ops; DeviceDriverOps uhci_device_driver_ops = { .device_driver_init = NULL, @@ -76,12 +75,6 @@ PciDriver uhci_pci_driver = { .class_subclass_progif = {UHCI_CLASSID, UHCI_SUBCLASSID, UHCI_PROGIF}, .ops = &uhci_pci_driver_ops, }; -BusControllerDevice uhci_bus_controller_device = { - .short_name = STRING_INIT("UHCI Controller"), - .device = NULL, // 由probe函数设置 - .bus_driver = &usb_bus_driver, - .bus_controller_ops = NULL, -}; const Device uhci_device_template = { .name = STRING_INIT("UHCI Controller"), .device_driver = &uhci_device_driver, @@ -172,6 +165,7 @@ void uhci_port_init(UsbHcd *hcd, int port) { if (BIN_IS_EN(port_status, UHCI_PORT_SC_CONNECTED)) { printk("[UHCI]port %d connected.\n", port); UsbDevice *usb_device = usb_create_device( + hcd, BIN_IS_EN(port_status, UHCI_PORT_SC_LOWSPEED) ? USB_SPEED_LOW : USB_SPEED_FULL, 0); @@ -235,21 +229,28 @@ DriverResult uhci_pci_probe(PciDevice *pci_device) { uint32_t io_base = pci_device->common.bar[4].base_addr & 0xfffffff0; if (io_base == 0) { return DRIVER_RESULT_UNSUPPORT_DEVICE; } - Device *device = kmalloc_from_template(uhci_device_template); - device->bus = pci_device->bus; + Device *device = kmalloc_from_template(uhci_device_template); + device->bus = pci_device->bus; + uint8_t port_cnt = (pci_device->common.bar[4].length - UHCI_PORTSC1) / 2; + + uint16_t status; + for (int i = 0; i < port_cnt; i++) { + status = io_in_word(io_base + UHCI_PORTSC1 + i * 2); + if ((status & 0x80) == 0 || status == 0xffff) { + port_cnt = i; + break; + } + } + + UsbHcd *hcd = usb_hcd_register( + &uhci_device_driver, device, DEV_NAME, sizeof(DEV_NAME), port_cnt, + &uhci_ops); - ObjectAttr attr = driver_object_attr; - register_bus_controller_device( - &uhci_device_driver, &usb_bus_driver, device, - &uhci_bus_controller_device, &attr); Uhci *uhci = device->private_data; uhci->device = pci_device; uhci->io_base = io_base; - uhci->port_cnt = (pci_device->common.bar[4].length - UHCI_PORTSC1) / 2; - - UsbHcd *hcd = - usb_hcd_register(device, DEV_NAME, uhci->port_cnt, &uhci_interface); - uhci->hcd = hcd; + uhci->port_cnt = port_cnt; + uhci->hcd = hcd; return DRIVER_RESULT_OK; } diff --git a/src/arch/x86/drivers/usb/hci/uhci/packet.c b/src/arch/x86/drivers/usb/hci/uhci/packet.c index 3ee1a98..b146b8f 100644 --- a/src/arch/x86/drivers/usb/hci/uhci/packet.c +++ b/src/arch/x86/drivers/usb/hci/uhci/packet.c @@ -14,7 +14,7 @@ void *uhci_create_sched(void); -UsbHcdOps uhci_interface = { +UsbHcdOps uhci_ops = { .create_sched = uhci_create_sched, .ctrl_transfer_in = uhci_ctrl_transfer_in, .ctrl_transfer_out = uhci_ctrl_transfer_out, diff --git a/src/arch/x86/include/drivers/usb/uhci.h b/src/arch/x86/include/drivers/usb/uhci.h index faab483..2c57c05 100644 --- a/src/arch/x86/include/drivers/usb/uhci.h +++ b/src/arch/x86/include/drivers/usb/uhci.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include diff --git a/src/driver/usb/usb-core/func.c b/src/driver/usb/usb-core/func.c index d534752..4d50cbb 100644 --- a/src/driver/usb/usb-core/func.c +++ b/src/driver/usb/usb-core/func.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include diff --git a/src/driver/usb/usb-core/hcd.c b/src/driver/usb/usb-core/hcd.c index 2653a59..85820d7 100644 --- a/src/driver/usb/usb-core/hcd.c +++ b/src/driver/usb/usb-core/hcd.c @@ -1,3 +1,7 @@ +#include "driver/bus_dm.h" +#include "driver/usb/usb_dm.h" +#include "kernel/bus_driver.h" +#include "kernel/device_driver.h" #include "kernel/spinlock.h" #include #include @@ -12,27 +16,47 @@ #include LIST_HEAD(hcd_list); -SPINLOCK(bus_num_lock); -uint8_t new_bus_num = 0; + +extern BusOps usb_bus_ops; UsbHcd *usb_hcd_register( - Device *device, char *name, uint32_t port_cnt, UsbHcdOps *interface) { + DeviceDriver *device_driver, Device *device, char *name, int name_len, + uint32_t port_cnt, UsbHcdOps *ops) { + BusControllerDevice *bus_controller_device = + kmalloc(sizeof(BusControllerDevice)); + string_new(&bus_controller_device->short_name, name, name_len); + bus_controller_device->bus_controller_ops = NULL; + + ObjectAttr attr = driver_object_attr; + register_bus_controller_device( + device_driver, &usb_bus_driver, device, bus_controller_device, &attr); + + uint8_t bus_num; + spin_lock(&usb_dm_ext.hcd_count_lock); + bus_num = usb_dm_ext.hcd_count++; + spin_unlock(&usb_dm_ext.hcd_count_lock); + + char bus_name[4]; + char *next = itoa(bus_name, bus_num, 10); + *next = '\0'; + Bus *bus = kmalloc(sizeof(Bus)); + bus->bus_num = bus_num; + bus->ops = &usb_bus_ops; + string_new(&bus->name, bus_name, next - bus_name); + register_bus(&usb_bus_driver, device, bus, &attr); + UsbHcd *hcd = kmalloc(sizeof(UsbHcd)); if (hcd == NULL) return NULL; list_add_tail(&hcd->list, &hcd_list); - hcd->device = device; - hcd->device_count = 0; - - hcd->ops = interface; - - string_t *string = kmalloc(sizeof(string_t)); - string_init(string); - string_new(string, name, strlen(name)); - hcd->name = string; + hcd->bus_ctrlr_device = bus_controller_device; + hcd->device = bus_controller_device->device; + hcd->device_count = 0; + hcd->bus = bus; + hcd->ops = ops; + string_new(&hcd->name, name, name_len); hcd->ports = kmalloc(sizeof(UsbHcdPort) * port_cnt); - for (int i = 0; i < port_cnt; i++) { hcd->ports[i].port = i; hcd->ports[i].hcd = hcd; diff --git a/src/driver/usb/usb-core/hub.c b/src/driver/usb/usb-core/hub.c index 984591e..c761c0c 100644 --- a/src/driver/usb/usb-core/hub.c +++ b/src/driver/usb/usb-core/hub.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,7 @@ void usb_init_hub(UsbHcd *hcd, UsbDevice *device) { status = usb_get_port_status(hcd, device, ep0, i); if (BIN_IS_EN(status, USB_PORT_STAT_CONNECTION)) { UsbDevice *dev = usb_create_device( + hcd, (BIN_IS_EN(status, USB_PORT_STAT_LOW_SPEED) ? USB_SPEED_LOW : USB_SPEED_FULL), 0); diff --git a/src/driver/usb/usb-core/usb.c b/src/driver/usb/usb-core/usb.c index 344a13b..aa79404 100644 --- a/src/driver/usb/usb-core/usb.c +++ b/src/driver/usb/usb-core/usb.c @@ -1,22 +1,37 @@ +#include "kernel/bus_driver.h" +#include "kernel/device.h" #include "kernel/list.h" +#include "objects/object.h" #include #include #include #include #include #include +#include #include #include #include #include -UsbDevice *usb_create_device(UsbDeviceSpeed speed, uint8_t address) { - UsbDevice *device = (UsbDevice *)kmalloc(sizeof(UsbDevice)); - list_init(&device->ep_lh); - device->desc = kmalloc(sizeof(struct UsbDeviceDescriptor)); - device->speed = speed; - device->address = address; - return device; +UsbDevice *usb_create_device( + UsbHcd *hcd, UsbDeviceSpeed speed, uint8_t address) { + Device *device = kmalloc(sizeof(Device)); + device->private_data_size = 0; + device->ops = NULL; + device->state = DEVICE_STATE_UNREGISTERED; + device->bus = hcd->bus; + + UsbDevice *usb_device = (UsbDevice *)kmalloc(sizeof(UsbDevice)); + list_init(&usb_device->ep_lh); + list_init(&usb_device->interface_lh); + usb_device->desc = kmalloc(sizeof(struct UsbDeviceDescriptor)); + usb_device->speed = speed; + usb_device->address = address; + usb_device->state = USB_STATE_UNINITED; + usb_device->device = device; + + return usb_device; } int usb_destroy_device(UsbDevice *device) { @@ -48,26 +63,30 @@ UsbEndpoint *usb_create_endpoint( return ep; } -int usb_init_device(UsbHcd *hcd, UsbDevice *device) { +int usb_init_device(UsbHcd *hcd, UsbDevice *usb_device) { UsbEndpoint *ep0 = usb_create_endpoint(hcd, 0, USB_EP_CONTROL, USB_EP_OUT, 64); - device->ep0 = ep0; + usb_device->ep0 = ep0; struct UsbDeviceDescriptor *desc = - usb_get_device_descriptor(hcd, device, ep0); + usb_get_device_descriptor(hcd, usb_device, ep0); // usb_show_device_descriptor(hcd, device, ep0, desc); hcd->device_count++; - usb_set_address(hcd, device, ep0, hcd->device_count); + usb_set_address(hcd, usb_device, ep0, hcd->device_count); Timer timer; timer_init(&timer); delay_ms(&timer, 2); - device->address = hcd->device_count; - usb_get_config_descriptor(hcd, device, ep0); + usb_device->address = hcd->device_count; + usb_get_config_descriptor(hcd, usb_device, ep0); + + usb_set_config(hcd, usb_device, ep0, 1); - usb_set_config(hcd, device, ep0, 1); + ObjectAttr attr = device_object_attr; + register_usb_device( + hcd->device->device_driver, usb_device->device, usb_device, &attr); - if (desc->bDeviceClass == USB_CLASS_HUB) { usb_init_hub(hcd, device); } + if (desc->bDeviceClass == USB_CLASS_HUB) { usb_init_hub(hcd, usb_device); } return 0; } \ No newline at end of file diff --git a/src/driver/usb/usb_dm.c b/src/driver/usb/usb_dm.c index 2efde00..e1ca9b0 100644 --- a/src/driver/usb/usb_dm.c +++ b/src/driver/usb/usb_dm.c @@ -1,3 +1,11 @@ +#include "kernel/bus_driver.h" +#include "kernel/spinlock.h" +#include "objects/transfer.h" +#include "string.h" +#include +#include +#include +#include #include #include #include @@ -6,16 +14,49 @@ #include #include -// DriverResult usb_dm_load(DeviceManager *manager); +DriverResult usb_dm_load(DeviceManager *manager); // DriverResult usb_dm_unload(DeviceManager *manager); +UsbDeviceManager usb_dm_ext; DeviceManagerOps usb_dm_ops = { - .dm_load = NULL, + .dm_load = usb_dm_load, .dm_unload = NULL, }; // UsbDeviceManager usb_dm_ext; DeviceManager usb_dm = { - .type = DEVICE_TYPE_USB, .ops = &usb_dm_ops, - // .private_data = &usb_dm_ext, -}; \ No newline at end of file + .type = DEVICE_TYPE_USB, + .ops = &usb_dm_ops, + .private_data = &usb_dm_ext, +}; + +DriverResult usb_dm_load(DeviceManager *manager) { + spinlock_init(&usb_dm_ext.hcd_count_lock); + usb_dm_ext.hcd_count = 0; + return DRIVER_RESULT_OK; +} + +DriverResult register_usb_device( + DeviceDriver *driver, Device *device, UsbDevice *usb_device, + ObjectAttr *attr) { + device->dm_ext = usb_device; + usb_device->state = USB_STATE_UNINITED; + usb_device->device = device; + usb_device->device->ops = &usb_device_ops; + list_add_tail(&device->dm_list, &usb_dm.device_lh); + + char _name[4]; + char *next = itoa(_name, device->bus->bus_num, 10); + *next = '\0'; + + string_t name; + string_new(&name, _name, next - _name); + DRIVER_RESULT_PASS( + register_device(driver, NULL, device->bus, device, attr)); + + // 不可直接传输数据 + device->object->in.type = TRANSFER_TYPE_NONE; + device->object->out.type = TRANSFER_TYPE_NONE; + + return DRIVER_RESULT_OK; +} diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c index 7b3ecb3..df9af5f 100644 --- a/src/drivers/bus/usb.c +++ b/src/drivers/bus/usb.c @@ -35,9 +35,6 @@ DeviceOps usb_device_ops = { .destroy = NULL, .status = NULL, }; -BusControllerDeviceOps usb_bus_controller_ops = { - .probe = NULL, -}; DriverDependency usb_dependencies[] = { { @@ -53,8 +50,9 @@ Driver usb_driver = { .init = NULL, }; BusDriver usb_bus_driver = { + .name = STRING_INIT("USB"), .driver_type = DRIVER_TYPE_BUS_DRIVER, - .bus_type = BUS_TYPE_PCI, + .bus_type = BUS_TYPE_USB, .state = DRIVER_STATE_UNREGISTERED, .private_data_size = 0, .ops = &usb_bus_driver_ops, @@ -79,21 +77,11 @@ BusControllerDevice usb_bus_controller_device = { .bus_driver = &usb_bus_driver, .bus_controller_ops = NULL, }; -Bus usb_bus = { - .bus_num = 0, - .ops = &usb_bus_ops, - .bus_driver = &usb_bus_driver, - .name = STRING_INIT("Universal Serial Bus"), - .controller_device = &usb_device, -}; static __init void usb_bus_driver_entry(void) { - register_driver(&usb_driver); - register_device_driver(&usb_driver, &usb_device_driver); ObjectAttr attr = device_object_attr; - register_bus_controller_device( - &usb_device_driver, &usb_bus_driver, &usb_device, - &usb_bus_controller_device, &attr); + register_driver(&usb_driver); + register_bus_driver(&usb_driver, &usb_bus_driver, &attr); HciInit *hci_init; list_for_each_owner (hci_init, &hci_lh, list) { diff --git a/src/include/driver/usb/func.h b/src/include/driver/usb/func.h index 48fe2e3..2f80b24 100644 --- a/src/include/driver/usb/func.h +++ b/src/include/driver/usb/func.h @@ -6,33 +6,34 @@ #define REQ_GET_PORT_STATUS_SIZE 4 struct UsbDeviceDescriptor *usb_get_device_descriptor( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep); + UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep); struct UsbConfigDescriptor *usb_get_config_descriptor( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep); + UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep); -uint8_t usb_get_config(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep); +uint8_t usb_get_config(UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep); UsbSetupStatus usb_set_config( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t config); + UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep, uint8_t config); struct UsbHubDescriptor *usb_get_hub_descriptor( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep); + UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep); UsbSetupStatus usb_set_address( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint32_t address); + UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep, uint32_t address); UsbSetupStatus usb_set_port_feature( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t port, + UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep, uint8_t port, uint16_t feature); -uint32_t usb_get_hub_status(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep); +uint32_t usb_get_hub_status( + UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep); uint32_t usb_get_port_status( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t port); + UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep, uint8_t port); struct UsbStringDescriptor *usb_get_string_descriptor( - UsbHcd *hcd, UsbDevice *device, uint8_t index, UsbEndpoint *ep); + UsbHcd *hcd, struct UsbDevice *device, uint8_t index, UsbEndpoint *ep); void usb_show_device_descriptor( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, + UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep, struct UsbDeviceDescriptor *desc); void usb_show_hub_descriptor(struct UsbHubDescriptor *desc); diff --git a/src/include/driver/usb/hcd.h b/src/include/driver/usb/hcd.h index b5bd485..846029c 100644 --- a/src/include/driver/usb/hcd.h +++ b/src/include/driver/usb/hcd.h @@ -1,6 +1,7 @@ #ifndef HCD_H #define HCD_H +#include "driver/bus_dm.h" #include #include #include @@ -37,8 +38,11 @@ typedef struct UsbHcd { UsbHcdOps *ops; - string_t *name; - Device *device; + string_t name; + + BusControllerDevice *bus_ctrlr_device; + Device *device; + Bus *bus; uint8_t device_count; @@ -46,6 +50,7 @@ typedef struct UsbHcd { } UsbHcd; UsbHcd *usb_hcd_register( - Device *device, char *name, uint32_t port_cnt, UsbHcdOps *interface); + DeviceDriver *device_driver, Device *device, char *name, int name_len, + uint32_t port_cnt, UsbHcdOps *ops); #endif // HCD_H \ No newline at end of file diff --git a/src/include/driver/usb/hub.h b/src/include/driver/usb/hub.h index 82c665b..18ae937 100644 --- a/src/include/driver/usb/hub.h +++ b/src/include/driver/usb/hub.h @@ -23,6 +23,6 @@ #define HUB_FEAT_PORT_TEST 21 #define HUB_FEAT_PORT_INDICATOR 22 -void usb_init_hub(UsbHcd *hcd, UsbDevice *device); +void usb_init_hub(UsbHcd *hcd, struct UsbDevice *device); #endif \ No newline at end of file diff --git a/src/include/driver/usb/usb.h b/src/include/driver/usb/usb.h index 83f7277..d8f0169 100644 --- a/src/include/driver/usb/usb.h +++ b/src/include/driver/usb/usb.h @@ -71,18 +71,11 @@ typedef enum UsbDeviceSpeed { USB_SPEED_HIGH, } UsbDeviceSpeed; -typedef struct UsbDevice { - list_t list; - uint8_t address; - - list_t ep_lh; - list_t interface_lh; - - struct UsbDeviceDescriptor *desc; - UsbDeviceSpeed speed; - - struct UsbEndpoint *ep0; -} UsbDevice; +typedef enum { + USB_STATE_UNINITED, // 未被枚举 + USB_STATE_INITED, // 已被枚举 + USB_STATE_ACTIVE, // 正常工作 +} UsbDeviceState; typedef enum { USB_EP_CONTROL, @@ -143,8 +136,9 @@ typedef struct UsbRequest { extern UsbEndpoint usb_ep0; -UsbDevice *usb_create_device(UsbDeviceSpeed speed, uint8_t address); -int usb_destroy_device(UsbDevice *device); +struct UsbDevice *usb_create_device( + UsbHcd *hcd, UsbDeviceSpeed speed, uint8_t address); +int usb_destroy_device(struct UsbDevice *device); UsbRequest *usb_create_request( uint8_t direction, uint8_t type, uint8_t recipient, uint8_t request_id, @@ -153,6 +147,6 @@ UsbEndpoint *usb_create_endpoint( UsbHcd *hcd, uint8_t endpoint, UsbEpTransferType transfer_type, UsbEpDirection direction, uint16_t max_packet_size); -int usb_init_device(UsbHcd *hcd, UsbDevice *device); +int usb_init_device(UsbHcd *hcd, struct UsbDevice *device); #endif \ No newline at end of file diff --git a/src/include/driver/usb/usb_dm.h b/src/include/driver/usb/usb_dm.h new file mode 100644 index 0000000..318b9be --- /dev/null +++ b/src/include/driver/usb/usb_dm.h @@ -0,0 +1,39 @@ +#ifndef _USB_DM_H +#define _USB_DM_H + +#include +#include +#include +#include +#include + +typedef struct UsbDevice { + list_t list; + uint8_t address; + + list_t ep_lh; + list_t interface_lh; + + UsbDeviceState state; + Device *device; + + struct UsbDeviceDescriptor *desc; + UsbDeviceSpeed speed; + struct UsbEndpoint *ep0; + + void *private_data; +} UsbDevice; + +typedef struct { + uint8_t hcd_count; + spinlock_t hcd_count_lock; +} UsbDeviceManager; + +extern UsbDeviceManager usb_dm_ext; +extern DeviceManager usb_dm; + +DriverResult register_usb_device( + DeviceDriver *driver, Device *device, UsbDevice *usb_device, + ObjectAttr *attr); + +#endif \ No newline at end of file diff --git a/src/include/drivers/bus/usb.h b/src/include/drivers/bus/usb.h index 4e8c486..1ccc02a 100644 --- a/src/include/drivers/bus/usb.h +++ b/src/include/drivers/bus/usb.h @@ -8,6 +8,7 @@ extern BusDriver usb_bus_driver; extern Driver usb_driver; extern list_t hci_lh; +extern DeviceOps usb_device_ops; typedef struct HciInit { list_t list; From 30f880313a99e7567d0013d99312e91ba7c16a08 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 18 Sep 2025 18:33:16 +0800 Subject: [PATCH 120/158] =?UTF-8?q?uhci:=20=E6=94=B9=E7=94=A8=E7=8B=AC?= =?UTF-8?q?=E7=AB=8B=E7=BA=BF=E7=A8=8B=E5=AE=8C=E6=88=90=E7=AB=AF=E5=8F=A3?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E5=92=8C=E8=AE=BE=E5=A4=87=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/usb/hci/uhci.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/arch/x86/drivers/usb/hci/uhci.c b/src/arch/x86/drivers/usb/hci/uhci.c index 3861a61..df69118 100644 --- a/src/arch/x86/drivers/usb/hci/uhci.c +++ b/src/arch/x86/drivers/usb/hci/uhci.c @@ -11,6 +11,7 @@ #include "driver/timer_dm.h" #include "kernel/driver_interface.h" #include "kernel/list.h" +#include "kernel/thread.h" #include #include #include @@ -203,6 +204,20 @@ DriverResult uhci_init(Device *device) { return DRIVER_RESULT_OK; } +void uhci_probe_thread(void *arg) { + Uhci *uhci = (Uhci *)arg; + for (int i = 0; i < uhci->port_cnt; i++) { + uhci_port_init(uhci->hcd, i); + } +} + +void uhci_probe(Device *device) { + // 通过独立线程初始化,避免usb初始化长时间的等待导致系统阻塞 + thread_start( + "UHCI Probe", THREAD_DEFAULT_PRIO, uhci_probe_thread, + device->private_data, NULL); +} + DriverResult uhci_start(Device *device) { Uhci *uhci = device->private_data; uhci->fl.frames_vir = (uint32_t *)kernel_alloc_pages(1); @@ -218,9 +233,7 @@ DriverResult uhci_start(Device *device) { uint16_t cmd = io_in_word(uhci->io_base + UHCI_REG_CMD); io_out_word(uhci->io_base + UHCI_REG_CMD, cmd | UHCI_CMD_RUN); - for (int i = 0; i < uhci->port_cnt; i++) { - uhci_port_init(uhci->hcd, i); - } + uhci_probe(device); return DRIVER_RESULT_OK; } From 3a8113c981ec8539252199cc372fb46290e4393a Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 18 Sep 2025 20:13:59 +0800 Subject: [PATCH 121/158] =?UTF-8?q?kernel&driver:=20=E5=B0=86=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8=E6=A1=86=E6=9E=B6=E4=BB=A3=E7=A0=81=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E5=88=B0kernel/driver/=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/Makefile | 10 +--------- src/kernel/driver/Makefile | 9 +++++++++ src/kernel/{ => driver}/bus_driver.c | 0 src/kernel/{ => driver}/device.c | 0 src/kernel/{ => driver}/device_driver.c | 0 src/kernel/{ => driver}/device_manager.c | 0 src/kernel/{ => driver}/dma.c | 0 src/kernel/{ => driver}/driver.c | 0 src/kernel/{ => driver}/driver_dependency.c | 0 src/kernel/{ => driver}/driver_interface.c | 0 src/kernel/{ => driver}/driver_manager.c | 0 11 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 src/kernel/driver/Makefile rename src/kernel/{ => driver}/bus_driver.c (100%) rename src/kernel/{ => driver}/device.c (100%) rename src/kernel/{ => driver}/device_driver.c (100%) rename src/kernel/{ => driver}/device_manager.c (100%) rename src/kernel/{ => driver}/dma.c (100%) rename src/kernel/{ => driver}/driver.c (100%) rename src/kernel/{ => driver}/driver_dependency.c (100%) rename src/kernel/{ => driver}/driver_interface.c (100%) rename src/kernel/{ => driver}/driver_manager.c (100%) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 19b854e..9db9776 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -6,14 +6,6 @@ SRC += memory.c SRC += sync.c SRC += thread.c SRC += initcall.c -SRC += driver.c -SRC += bus_driver.c -SRC += device_driver.c -SRC += device_manager.c -SRC += driver_manager.c -SRC += driver_interface.c -SRC += driver_dependency.c -SRC += device.c SRC += process.c SRC += syscall.c SRC += app.c @@ -23,8 +15,8 @@ SRC += periodic_task.c SRC += block_cache.c SRC += rwlock.c SRC += condvar.c -SRC += dma.c SRC += softirq.c +SRC += driver/ #INCLUDE_PATH = ../include/ ../$(ARCH)/include/ diff --git a/src/kernel/driver/Makefile b/src/kernel/driver/Makefile new file mode 100644 index 0000000..7b86bf6 --- /dev/null +++ b/src/kernel/driver/Makefile @@ -0,0 +1,9 @@ +SRC += bus_driver.c +SRC += device_driver.c +SRC += device_manager.c +SRC += device.c +SRC += dma.c +SRC += driver_dependency.c +SRC += driver_interface.c +SRC += driver_manager.c +SRC += driver.c \ No newline at end of file diff --git a/src/kernel/bus_driver.c b/src/kernel/driver/bus_driver.c similarity index 100% rename from src/kernel/bus_driver.c rename to src/kernel/driver/bus_driver.c diff --git a/src/kernel/device.c b/src/kernel/driver/device.c similarity index 100% rename from src/kernel/device.c rename to src/kernel/driver/device.c diff --git a/src/kernel/device_driver.c b/src/kernel/driver/device_driver.c similarity index 100% rename from src/kernel/device_driver.c rename to src/kernel/driver/device_driver.c diff --git a/src/kernel/device_manager.c b/src/kernel/driver/device_manager.c similarity index 100% rename from src/kernel/device_manager.c rename to src/kernel/driver/device_manager.c diff --git a/src/kernel/dma.c b/src/kernel/driver/dma.c similarity index 100% rename from src/kernel/dma.c rename to src/kernel/driver/dma.c diff --git a/src/kernel/driver.c b/src/kernel/driver/driver.c similarity index 100% rename from src/kernel/driver.c rename to src/kernel/driver/driver.c diff --git a/src/kernel/driver_dependency.c b/src/kernel/driver/driver_dependency.c similarity index 100% rename from src/kernel/driver_dependency.c rename to src/kernel/driver/driver_dependency.c diff --git a/src/kernel/driver_interface.c b/src/kernel/driver/driver_interface.c similarity index 100% rename from src/kernel/driver_interface.c rename to src/kernel/driver/driver_interface.c diff --git a/src/kernel/driver_manager.c b/src/kernel/driver/driver_manager.c similarity index 100% rename from src/kernel/driver_manager.c rename to src/kernel/driver/driver_manager.c From 235d94db54c4ff4b216f58bbbf93ba26139a6be7 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 18 Sep 2025 21:52:06 +0800 Subject: [PATCH 122/158] =?UTF-8?q?driver:=20=E7=AE=80=E5=8C=96DriverResul?= =?UTF-8?q?t=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/bus/pci/pci.c | 4 ++-- src/arch/x86/drivers/interrupt/apic.c | 2 +- src/arch/x86/drivers/sound/sb16/sb16.c | 2 +- src/driver/timer/timer.c | 6 +++--- src/driver/video_dm.c | 2 +- src/include/kernel/driver.h | 7 ++----- src/kernel/driver/bus_driver.c | 16 ++++++++-------- src/kernel/driver/device.c | 2 +- src/kernel/driver/device_driver.c | 4 ++-- src/kernel/driver/driver.c | 8 +++----- src/kernel/driver/driver_dependency.c | 4 ++-- src/kernel/driver/driver_manager.c | 2 +- 12 files changed, 27 insertions(+), 32 deletions(-) diff --git a/src/arch/x86/drivers/bus/pci/pci.c b/src/arch/x86/drivers/bus/pci/pci.c index fbd9daa..7d86401 100644 --- a/src/arch/x86/drivers/bus/pci/pci.c +++ b/src/arch/x86/drivers/bus/pci/pci.c @@ -216,7 +216,7 @@ DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus) { for (j = 0; j < PCI_MAX_FUNC; j++) { DriverResult result = pci_scan_device(bus, bus->bus_num, i, j, &pci_device); - if (result == DRIVER_RESULT_DEVICE_NOT_EXIST) { + if (result == DRIVER_RESULT_NOT_EXIST) { continue; } else if (result == DRIVER_RESULT_NULL_POINTER) { print_error_with_position( @@ -336,7 +336,7 @@ DriverResult pci_scan_device( uint32_t value = pci_read32(bus_num, device_num, function_num, 0); uint16_t vendorID = value & 0xffff; uint16_t deviceID = value >> 16; - if (vendorID == 0xffff) { return DRIVER_RESULT_DEVICE_NOT_EXIST; } + if (vendorID == 0xffff) { return DRIVER_RESULT_NOT_EXIST; } value = pci_read32(bus_num, device_num, function_num, 0x0c); uint8_t bist = value >> 24; diff --git a/src/arch/x86/drivers/interrupt/apic.c b/src/arch/x86/drivers/interrupt/apic.c index 65a0e16..9e5d953 100644 --- a/src/arch/x86/drivers/interrupt/apic.c +++ b/src/arch/x86/drivers/interrupt/apic.c @@ -232,7 +232,7 @@ DriverResult apic_driver_init(struct DeviceDriver *driver) { mask_8259a(); xapic_init(driver); } else { - return DRIVER_RESULT_DEVICE_NOT_EXIST; + return DRIVER_RESULT_NOT_EXIST; } return DRIVER_RESULT_OK; } diff --git a/src/arch/x86/drivers/sound/sb16/sb16.c b/src/arch/x86/drivers/sound/sb16/sb16.c index 796b03c..e6edaf4 100644 --- a/src/arch/x86/drivers/sound/sb16/sb16.c +++ b/src/arch/x86/drivers/sound/sb16/sb16.c @@ -153,7 +153,7 @@ DriverResult sb16_reset(Sb16Ports *ports) { if (io_in8(ports->read) == 0xaa) { return DRIVER_RESULT_OK; } } } - return DRIVER_RESULT_DEVICE_NOT_EXIST; + return DRIVER_RESULT_NOT_EXIST; } DriverResult sb16_write(Sb16Ports *ports, uint8_t value) { diff --git a/src/driver/timer/timer.c b/src/driver/timer/timer.c index 32a0ba7..7322432 100644 --- a/src/driver/timer/timer.c +++ b/src/driver/timer/timer.c @@ -14,7 +14,7 @@ DriverResult timer_init(Timer *timer) { } DriverResult timer_set_timeout(Timer *timer, uint32_t count) { - if (timer->timer_device == NULL) return DRIVER_RESULT_DEVICE_NOT_EXIST; + if (timer->timer_device == NULL) return DRIVER_RESULT_NOT_EXIST; uint32_t counter = timer->timer_device->counter; timer->timeout = counter + count; timer->will_wrap = (timer->timeout > counter) ? false : true; @@ -24,7 +24,7 @@ DriverResult timer_set_timeout(Timer *timer, uint32_t count) { DriverResult timer_callback_enable(Timer *timer) { if (timer == NULL || timer->timer_device == NULL) - return DRIVER_RESULT_DEVICE_NOT_EXIST; + return DRIVER_RESULT_NOT_EXIST; // 在插入时排序 if (!list_empty(&timer->timer_device->timer_callback_lh)) { Timer *last_timer = list_last_owner( @@ -41,7 +41,7 @@ DriverResult timer_callback_enable(Timer *timer) { DriverResult timer_callback_cancel(Timer *timer) { if (timer == NULL || timer->timer_device == NULL) - return DRIVER_RESULT_DEVICE_NOT_EXIST; + return DRIVER_RESULT_NOT_EXIST; if (list_in_list(&timer->list)) list_del(&timer->list); else return DRIVER_RESULT_OTHER_ERROR; diff --git a/src/driver/video_dm.c b/src/driver/video_dm.c index 8d3a769..6988e6f 100644 --- a/src/driver/video_dm.c +++ b/src/driver/video_dm.c @@ -109,5 +109,5 @@ DriverResult video_get_video_device(int in_index, VideoDevice **out_device) { } i++; } - return DRIVER_RESULT_DEVICE_NOT_EXIST; + return DRIVER_RESULT_NOT_EXIST; } diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index 3c6dba5..dc43ee7 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -145,11 +145,8 @@ void driver_inited(); typedef enum DriverResult { DRIVER_RESULT_OK, DRIVER_RESULT_TIMEOUT, - DRIVER_RESULT_BUS_DRIVER_ALREADY_EXIST, - DRIVER_RESULT_BUS_DRIVER_NOT_EXIST, - DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST, - DRIVER_RESULT_DEVICE_MANAGER_NOT_EXIST, - DRIVER_RESULT_DEVICE_NOT_EXIST, + DRIVER_RESULT_ALREADY_EXIST, + DRIVER_RESULT_NOT_EXIST, DRIVER_RESULT_DEVICE_DRIVER_CONFLICT, DRIVER_RESULT_NO_OPS, DRIVER_RESULT_INCOMPLETABLE_OPS, diff --git a/src/kernel/driver/bus_driver.c b/src/kernel/driver/bus_driver.c index 8b89bea..4c4fcb0 100644 --- a/src/kernel/driver/bus_driver.c +++ b/src/kernel/driver/bus_driver.c @@ -54,10 +54,10 @@ DriverResult register_bus_driver( Driver *driver, BusDriver *bus_driver, ObjectAttr *attr) { DriverManager *manager = driver_managers[DRIVER_TYPE_BUS_DRIVER]; - if (manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; + if (manager == NULL) return DRIVER_RESULT_NOT_EXIST; BusDriver *_bus_driver = bus_drivers[bus_driver->bus_type]; - if (_bus_driver != NULL) return DRIVER_RESULT_BUS_DRIVER_ALREADY_EXIST; + if (_bus_driver != NULL) return DRIVER_RESULT_ALREADY_EXIST; bus_driver->private_data = kmalloc(bus_driver->private_data_size); bus_driver->state = DRIVER_STATE_UNINITED; @@ -78,10 +78,10 @@ DriverResult register_bus_driver( DriverResult unregister_bus_driver(Driver *driver, BusType type) { DriverManager *manager = driver_managers[DRIVER_TYPE_BUS_DRIVER]; - if (manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; + if (manager == NULL) return DRIVER_RESULT_NOT_EXIST; BusDriver *bus_driver = bus_drivers[type]; - if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + if (bus_driver == NULL) return DRIVER_RESULT_NOT_EXIST; // TODO: delete_object(&bus_driver->object); @@ -104,7 +104,7 @@ DriverResult unregister_bus_driver(Driver *driver, BusType type) { DriverResult register_bus( BusDriver *bus_driver, Device *bus_controller_device, Bus *bus, ObjectAttr *attr) { - if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + if (bus_driver == NULL) return DRIVER_RESULT_NOT_EXIST; Bus *primary_bus = bus->primary_bus; Bus *tmp_bus = bus; @@ -130,7 +130,7 @@ DriverResult register_bus( DriverResult unregister_bus(Bus *bus) { BusDriver *bus_driver = bus->bus_driver; - if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + if (bus_driver == NULL) return DRIVER_RESULT_NOT_EXIST; // TODO: delete_object(&bus->object); @@ -149,7 +149,7 @@ DriverResult unregister_bus(Bus *bus) { DriverResult bus_register_device(Device *device, Bus *bus, ObjectAttr *attr) { BusDriver *bus_driver = bus->bus_driver; - if (bus_driver == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + if (bus_driver == NULL) return DRIVER_RESULT_NOT_EXIST; device->bus = bus; list_add_tail(&device->bus_list, &bus->device_lh); @@ -166,7 +166,7 @@ DriverResult bus_register_device(Device *device, Bus *bus, ObjectAttr *attr) { DriverResult bus_unregister_device(Device *device) { Bus *bus = device->bus; - if (bus == NULL) return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + if (bus == NULL) return DRIVER_RESULT_NOT_EXIST; BUS_OPS_CALL(bus, unregister_device_hook, device); list_del(&device->bus_list); diff --git a/src/kernel/driver/device.c b/src/kernel/driver/device.c index 6f85a3a..8af2870 100644 --- a/src/kernel/driver/device.c +++ b/src/kernel/driver/device.c @@ -89,7 +89,7 @@ DriverResult init_device(Device *device) { if (device->ops->init != NULL) { DriverResult result = device->ops->init(device); if (result != DRIVER_RESULT_OK) { - if (result != DRIVER_RESULT_DEVICE_NOT_EXIST) { + if (result != DRIVER_RESULT_NOT_EXIST) { DRV_PRINT_RESULT(result, device->ops->init, device); return result; } else { diff --git a/src/kernel/driver/device_driver.c b/src/kernel/driver/device_driver.c index 23f3246..0f7f873 100644 --- a/src/kernel/driver/device_driver.c +++ b/src/kernel/driver/device_driver.c @@ -58,7 +58,7 @@ DriverResult register_device_driver( Driver *driver, DeviceDriver *device_driver) { DriverManager *manager = driver_managers[DRIVER_TYPE_DEVICE_DRIVER]; - if (manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; + if (manager == NULL) return DRIVER_RESULT_NOT_EXIST; list_init(&device_driver->device_lh); device_driver->private_data = kmalloc(device_driver->private_data_size); @@ -79,7 +79,7 @@ DriverResult unregister_device_driver( Driver *driver, DeviceDriver *device_driver) { DriverManager *manager = driver_managers[device_driver->type]; - if (manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; + if (manager == NULL) return DRIVER_RESULT_NOT_EXIST; DRV_RESULT_DELIVER_CALL( unregister_sub_driver, driver, &device_driver->subdriver); diff --git a/src/kernel/driver/driver.c b/src/kernel/driver/driver.c index 01cfc5b..c4694a1 100644 --- a/src/kernel/driver/driver.c +++ b/src/kernel/driver/driver.c @@ -64,14 +64,12 @@ void print_driver_result( RESULT_CASE_PRINT(DRIVER_RESULT_NO_VALID_CHILD_DEVICE) RESULT_CASE_PRINT(DRIVER_RESULT_INVALID_IRQ_NUMBER) RESULT_CASE_PRINT(DRIVER_RESULT_OUT_OF_MEMORY) - RESULT_CASE_PRINT(DRIVER_RESULT_BUS_DRIVER_ALREADY_EXIST) - RESULT_CASE_PRINT(DRIVER_RESULT_BUS_DRIVER_NOT_EXIST) - RESULT_CASE_PRINT(DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST) - RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_MANAGER_NOT_EXIST) - RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_NOT_EXIST) + RESULT_CASE_PRINT(DRIVER_RESULT_ALREADY_EXIST) + RESULT_CASE_PRINT(DRIVER_RESULT_NOT_EXIST) RESULT_CASE_PRINT(DRIVER_RESULT_NULL_POINTER) RESULT_CASE_PRINT(DRIVER_RESULT_UNSUPPORT_DEVICE) RESULT_CASE_PRINT(DRIVER_RESULT_UNSUPPORT_FEATURE) + RESULT_CASE_PRINT(DRIVER_RESULT_INVALID_TYPE) RESULT_CASE_PRINT(DRIVER_RESULT_BUSY) RESULT_CASE_PRINT(DRIVER_RESULT_EXCEED_MAX_SIZE) RESULT_CASE_PRINT(DRIVER_RESULT_OTHER_ERROR) diff --git a/src/kernel/driver/driver_dependency.c b/src/kernel/driver/driver_dependency.c index ba8ec26..44a6705 100644 --- a/src/kernel/driver/driver_dependency.c +++ b/src/kernel/driver/driver_dependency.c @@ -15,7 +15,7 @@ DriverResult check_dependency(Driver *driver) { for (int i = 0; i < count; i++) { if (deps[i].in_type == DRIVER_DEPENDENCY_TYPE_BUS) { if (deps[i].dependency_in_bus.type > BUS_TYPE_MAX) { - return DRIVER_RESULT_BUS_DRIVER_NOT_EXIST; + return DRIVER_RESULT_NOT_EXIST; } Bus *bus; @@ -46,7 +46,7 @@ DriverResult check_dependency(Driver *driver) { } } else if (deps[i].in_type == DRIVER_DEPENDENCY_TYPE_DEVICE) { if (deps[i].in_device_type > DEVICE_TYPE_MAX) { - return DRIVER_RESULT_DEVICE_MANAGER_NOT_EXIST; + return DRIVER_RESULT_NOT_EXIST; } // TODO: device依赖 } diff --git a/src/kernel/driver/driver_manager.c b/src/kernel/driver/driver_manager.c index d0548a4..5292c26 100644 --- a/src/kernel/driver/driver_manager.c +++ b/src/kernel/driver/driver_manager.c @@ -23,7 +23,7 @@ DriverResult register_driver_manager(DriverManager *driver_manager) { DriverResult unregister_driver_manager(DriverManager *driver_manager) { DriverManager *old_manager = driver_managers[driver_manager->type]; - if (old_manager == NULL) return DRIVER_RESULT_DRIVER_MANAGER_NOT_EXIST; + if (old_manager == NULL) return DRIVER_RESULT_NOT_EXIST; DM_OPS_CALL(old_manager, dm_unload_hook, old_manager); driver_managers[driver_manager->type] = NULL; From b3701ae21bdc82f5b9e5c05d224779a737adffb8 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 18 Sep 2025 21:52:41 +0800 Subject: [PATCH 123/158] =?UTF-8?q?driver:=20=E6=96=B0=E5=A2=9E=20dynamic?= =?UTF-8?q?=5Fdevice=5Fmanager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/kernel/device.h | 1 + src/include/kernel/dynamic_device_manager.h | 32 ++++++++++++++++++ src/kernel/driver/Makefile | 3 +- src/kernel/driver/dynamic_device_manager.c | 37 +++++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 src/include/kernel/dynamic_device_manager.h create mode 100644 src/kernel/driver/dynamic_device_manager.c diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index 8ac7dd1..0d43e28 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -68,6 +68,7 @@ typedef struct Device { list_t bus_list; list_t device_list; list_t dm_list; + list_t new_device_list; string_t name; DeviceState state; struct DeviceDriver *device_driver; diff --git a/src/include/kernel/dynamic_device_manager.h b/src/include/kernel/dynamic_device_manager.h new file mode 100644 index 0000000..8c4c03a --- /dev/null +++ b/src/include/kernel/dynamic_device_manager.h @@ -0,0 +1,32 @@ +#ifndef _DYNAMIC_DM_H +#define _DYNAMIC_DM_H + +#include +#include +#include + +struct DynamicDevice; +typedef struct DynamicDeviceEvents { + void (*probe)(DeviceManager *ddm); + void (*remove)(struct DynamicDevice *device); +} DynamicDeviceEvents; + +typedef struct DynamicDevice { + list_t list; + + Device *device; +} DynamicDevice; + +typedef struct DynamicDeviceManager { + list_t list; + list_t dynamic_device_lh; + + DeviceManager *device_manager; + DynamicDeviceEvents *events; +} DynamicDeviceManager; + +DriverResult register_dynamic_device_manager( + DynamicDeviceEvents *events, DeviceManager *device_manager); +void dynamic_device_manager(void *arg); + +#endif \ No newline at end of file diff --git a/src/kernel/driver/Makefile b/src/kernel/driver/Makefile index 7b86bf6..d13ac0c 100644 --- a/src/kernel/driver/Makefile +++ b/src/kernel/driver/Makefile @@ -6,4 +6,5 @@ SRC += dma.c SRC += driver_dependency.c SRC += driver_interface.c SRC += driver_manager.c -SRC += driver.c \ No newline at end of file +SRC += driver.c +SRC += dynamic_device_manager.c \ No newline at end of file diff --git a/src/kernel/driver/dynamic_device_manager.c b/src/kernel/driver/dynamic_device_manager.c new file mode 100644 index 0000000..c084f3e --- /dev/null +++ b/src/kernel/driver/dynamic_device_manager.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#include + +LIST_HEAD(dynamic_device_manager_lh); +LIST_HEAD(new_device_lh); + +DriverResult register_dynamic_device_manager( + DynamicDeviceEvents *events, DeviceManager *device_manager) { + DynamicDeviceManager *ddm = kmalloc(sizeof(DynamicDeviceManager)); + ddm->device_manager = device_manager; + ddm->events = events; + list_init(&ddm->dynamic_device_lh); + list_add_tail(&ddm->list, &dynamic_device_manager_lh); + + return DRIVER_RESULT_OK; +} + +void dynamic_device_manager(void *arg) { + DynamicDeviceManager *ddm; + Device *device, *next; + while (true) { + list_for_each_owner (ddm, &dynamic_device_manager_lh, list) { + ddm->events->probe(ddm->device_manager); + } + list_for_each_owner_safe ( + device, next, &new_device_lh, new_device_list) { + list_del(&device->new_device_list); + init_and_start(device); + } + schedule(); + } +} From e70730c447e54216db07f9b64d1c19e60a72489a Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 22 Sep 2025 14:04:42 +0800 Subject: [PATCH 124/158] =?UTF-8?q?lib:=20=E6=96=B0=E5=A2=9Ealigned=5Fdown?= =?UTF-8?q?=5Flog2n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/math.h | 3 ++- src/kernel/memory.c | 14 +++++++------- src/lib/math.c | 23 +++++++++++++++++++++-- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/include/math.h b/src/include/math.h index 3813c5f..995bdb4 100644 --- a/src/include/math.h +++ b/src/include/math.h @@ -13,6 +13,7 @@ int max(int a, int b); int abs(int n); int pow(int x, int y); unsigned int find_next_pow_of_2(unsigned int n); -int aligned_log2n(unsigned int n); +int aligned_up_log2n(unsigned int n); +int aligned_down_log2n(unsigned int n); #endif diff --git a/src/kernel/memory.c b/src/kernel/memory.c index 0e0dc1f..1929448 100644 --- a/src/kernel/memory.c +++ b/src/kernel/memory.c @@ -107,7 +107,7 @@ int mmap_search(struct mmap *btmp, unsigned int cnt) { void mmap_set(struct mmap *btmp, unsigned int bit_index, int value) { unsigned int byte_idx = bit_index / 8; // 向下取整用于索引数组下标 - unsigned int bit_odd = bit_index % 8; // 取余用于索引数组内的位 + unsigned int bit_odd = bit_index % 8; // 取余用于索引数组内的位 /* 一般都会用个0x1这样的数对字节中的位操作, * 将1任意移动后再取反,或者先取反再移位,可用来对位置0操作。*/ @@ -236,13 +236,13 @@ void *kmalloc(uint32_t size) { return NULL; } memory_manage->free_blocks[index].address = (uint32_t)address; - memory_manage->free_blocks[index].size = pages; // 大小是页的数量 - memory_manage->free_blocks[index].flags = MEMORY_BLOCK_ALLOCATED; - memory_manage->free_blocks[index].mode = MEMORY_BLOCK_MODE_BIG; + memory_manage->free_blocks[index].size = pages; // 大小是页的数量 + memory_manage->free_blocks[index].flags = MEMORY_BLOCK_ALLOCATED; + memory_manage->free_blocks[index].mode = MEMORY_BLOCK_MODE_BIG; store_interrupt_status(flags); return (void *)address; - } else if (0 < size && size <= 2048) { // size <= 2048 - int pow = MAX(aligned_log2n(size), MEMORY_MIN_POW); // 指数 + } else if (0 < size && size <= 2048) { // size <= 2048 + int pow = MAX(aligned_up_log2n(size), MEMORY_MIN_POW); // 指数 size = 1 << pow; // 第一次寻找,如果在块中没有找到,就打散一个页 if (!list_empty( @@ -300,7 +300,7 @@ int kfree(void *address) { store_interrupt_status(flags); return 0; } else if (block->mode == MEMORY_BLOCK_MODE_SMALL) { - int pow = aligned_log2n(block->size); + int pow = aligned_up_log2n(block->size); block->flags = MEMORY_BLOCK_USING; list_add_tail( &block->list, diff --git a/src/lib/math.c b/src/lib/math.c index eeabac4..fbca6ea 100644 --- a/src/lib/math.c +++ b/src/lib/math.c @@ -38,7 +38,7 @@ unsigned int find_next_pow_of_2(unsigned int n) { } // 计算log2(n)的向上取整 -int aligned_log2n(unsigned int n) { +int aligned_up_log2n(unsigned int n) { #ifdef HAS_BUILTIN_CLZ return 32 - __builtin_clz(n - 1); #else @@ -55,4 +55,23 @@ int aligned_log2n(unsigned int n) { n++; return de_bruijn_table[(n * 0x07C4ACDD) >> 27]; #endif -} \ No newline at end of file +} + +int aligned_down_log2n(unsigned int n) { +#ifdef HAS_BUILTIN_CLZ + return 31 - __builtin_clz(n); +#else + // De Bruijn序列查找表(32位版本) + static const uint8_t de_bruijn_table[32] = { + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31}; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n >>= 1; + n++; + return de_bruijn_table[(n * 0x07C4ACDD) >> 27]; +#endif +} From 7801ac9ad2111b2e6a6c59a13a14fd296081a220 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 22 Sep 2025 14:05:56 +0800 Subject: [PATCH 125/158] =?UTF-8?q?driver:=20=E6=8F=90=E5=89=8D=E5=94=A4?= =?UTF-8?q?=E9=86=92=E7=AD=89=E5=BE=85=E4=B8=AD=E7=9A=84driver?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/driver/driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kernel/driver/driver.c b/src/kernel/driver/driver.c index c4694a1..6d2740b 100644 --- a/src/kernel/driver/driver.c +++ b/src/kernel/driver/driver.c @@ -147,13 +147,14 @@ void sub_driver_start_thread(void *arg) { } Bus *bus; + sub_driver->state = SUBDRIVER_STATE_READY; + wait_queue_wakeup_all(&bus_driver->subdriver.wq); list_for_each_owner (bus, &bus_driver->bus_lh, bus_list) { // 先等待Bus Controller Device就绪 while (bus->controller_device->device_driver->subdriver.state != SUBDRIVER_STATE_READY) { schedule(); } - wait_queue_wakeup_all(&bus_driver->subdriver.wq); if (bus->ops->scan_bus != NULL) { bus->ops->scan_bus(bus_driver, bus); } @@ -161,7 +162,6 @@ void sub_driver_start_thread(void *arg) { bus->ops->probe_device(bus_driver, bus); } } - sub_driver->state = SUBDRIVER_STATE_READY; } } From 2c23f923fabcd1d48d47dd1c63897ac72939a641 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 22 Sep 2025 14:06:31 +0800 Subject: [PATCH 126/158] =?UTF-8?q?lib:=20=E6=96=B0=E5=A2=9EBIT=5FFFZ=5FL?= =?UTF-8?q?=E5=92=8CBIT=5FFFZ=5FR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/bits.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/include/bits.h b/src/include/bits.h index 5e0bf70..98a516f 100644 --- a/src/include/bits.h +++ b/src/include/bits.h @@ -24,8 +24,10 @@ #define HOST2LE_DWORD(n) (n) #define BIT(n) (1 << (n)) -#define BIT_FFS_R(n) (bsf(n)) // 从低到高找到第一个非0位的位置 -#define BIT_FFS_L(n) (bsr(n)) // 从高到低找到第一个非0位的位置 +#define BIT_FFS_R(n) (bsf(n)) // 从低到高找到第一个非0位的位置 +#define BIT_FFS_L(n) (bsr(n)) // 从高到低找到第一个非0位的位置 +#define BIT_FFZ_R(n) (bsf(~(n))) // 从低到高找到第一个为0位的位置 +#define BIT_FFZ_L(n) (bsr(~(n))) // 从高到低找到第一个为0位的位置 #define BIN_EN(n, x) ((n) | (x)) #define BIN_DIS(n, x) ((n) & ~(x)) From 3a05f97b3bf3e3a1ed7f5d633225ce15be810686 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 22 Sep 2025 14:07:23 +0800 Subject: [PATCH 127/158] =?UTF-8?q?hcd&uhci:=20=E6=96=B0=E5=A2=9E=E4=B8=AD?= =?UTF-8?q?=E6=96=AD=E4=BC=A0=E8=BE=93=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/usb/hci/uhci.c | 107 ++++++-- src/arch/x86/drivers/usb/hci/uhci/packet.c | 271 ++++++++++++++----- src/arch/x86/drivers/usb/hci/uhci/skeleton.c | 93 ++++--- src/arch/x86/include/drivers/usb/uhci.h | 60 ++-- src/include/driver/usb/hcd.h | 16 +- 5 files changed, 390 insertions(+), 157 deletions(-) diff --git a/src/arch/x86/drivers/usb/hci/uhci.c b/src/arch/x86/drivers/usb/hci/uhci.c index df69118..9cd6042 100644 --- a/src/arch/x86/drivers/usb/hci/uhci.c +++ b/src/arch/x86/drivers/usb/hci/uhci.c @@ -9,10 +9,13 @@ * */ #include "driver/timer_dm.h" +#include "driver/usb/descriptors.h" #include "kernel/driver_interface.h" #include "kernel/list.h" +#include "kernel/softirq.h" #include "kernel/thread.h" #include +#include #include #include #include @@ -85,16 +88,73 @@ const Device uhci_device_template = { HciInit uhci_hci_init = { .init = uhci_register, }; -// const UsbHciDevice uhci_hci_device_template = { -// .head_size = 0, -// .tail_size = 0, -// }; void uhci_port_reset(Uhci *devext, int port); -void uhci_port_init(UsbHcd *hcd, int port); +void uhci_port_init(UsbHcd *hcd, UsbEndpoint *ep0, int port); -void uhci_handler(int irq) { - return; +void uhci_handler(Device *device) { + Uhci *uhci = device->private_data; + UhciQh *qhs = uhci->skel->qh, *qh; + + // 清除UHCI状态寄存器 + uint16_t status = io_in_word(uhci->io_base + UHCI_REG_STS); + if (status == 0) return; + if (status & UHCI_STAT_INTERRUPT) { + io_out_word(uhci->io_base + UHCI_REG_STS, UHCI_STAT_INTERRUPT); + } + if (status & UHCI_STAT_ERROR_INT) { + print_error("UHCI", "Error Interrupt"); + io_out_word(uhci->io_base + UHCI_REG_STS, UHCI_STAT_ERROR_INT); + } + if (status & UHCI_STAT_RESUME_DETECT) { + print_error("UHCI", "Resume Detect"); + io_out_word(uhci->io_base + UHCI_REG_STS, UHCI_STAT_RESUME_DETECT); + } + if (status & UHCI_STAT_HOST_SYSTEM_ERROR) { + print_error("UHCI", "Host System Error"); + io_out_word(uhci->io_base + UHCI_REG_STS, UHCI_STAT_HOST_SYSTEM_ERROR); + } + if (status & UHCI_STAT_HC_PROCESS_ERROR) { + print_error("UHCI", "HC Process Error"); + io_out_word(uhci->io_base + UHCI_REG_STS, UHCI_STAT_HC_PROCESS_ERROR); + } + if (status & UHCI_STAT_HC_HALTED) { + print_error("UHCI", "HC Halted"); + io_out_word(uhci->io_base + UHCI_REG_STS, UHCI_STAT_HC_HALTED); + } + + for (int i = 0; i < UHCI_SKEL_QH_COUNT; i++) { + if (qhs[i].qe_link == UHCI_TERMINATE) continue; + if (!(qhs[i].qe_link & UHCI_QH_TD_SELECT)) continue; + // 每一个Endpoint都有一个对应的QH,这个QH下只有TD + qh = (UhciQh *)qhs[i].first_qh; + if (qh->endpoint == NULL) continue; + while (qh != NULL && qh->first_td != NULL) { + UhciTd *td = (UhciTd *)qh->first_td; + qh = qh->next; + while (td != NULL) { + if (td->active || !td->interrupt_on_complete) { + td = td->next; + continue; + } + // 传输完成 + td->interrupt_on_complete = 0; + if (td->urb != NULL) { + td->urb->actual_len += td->actlen; + td->urb->status = + td->stalled ? USB_STATUS_STALL + : (td->crc_timeout_Error | td->bitstuff_Error | + td->databuffer_Error) + ? USB_STATUS_ERR + : td->NAK_received ? USB_STATUS_NAK + : USB_STATUS_ACK; + list_add_tail(&td->urb->list, &urb_lh); + pending_softirq(); + } + td = td->next; + } + } + } } void uhci_print_status(Uhci *devext) { @@ -154,7 +214,7 @@ void uhci_port_reset(Uhci *uhci, int port) { delay_ms(&uhci->timer, 10); } -void uhci_port_init(UsbHcd *hcd, int port) { +void uhci_port_init(UsbHcd *hcd, UsbEndpoint *ep0, int port) { Uhci *devext = (Uhci *)hcd->device->private_data; uint32_t io_port = devext->io_base + UHCI_PORTSC1 + port * 2; UsbHcdPort *hcd_port = &hcd->ports[port]; @@ -164,16 +224,23 @@ void uhci_port_init(UsbHcd *hcd, int port) { // 重置端口,注册设备 if (BIN_IS_EN(port_status, UHCI_PORT_SC_CONNECTED)) { + UsbDeviceSpeed speed = BIN_IS_EN(port_status, UHCI_PORT_SC_LOWSPEED) + ? USB_SPEED_LOW + : USB_SPEED_FULL; printk("[UHCI]port %d connected.\n", port); - UsbDevice *usb_device = usb_create_device( - hcd, - BIN_IS_EN(port_status, UHCI_PORT_SC_LOWSPEED) ? USB_SPEED_LOW - : USB_SPEED_FULL, - 0); + UsbDevice *usb_device = usb_create_device(hcd, speed, 0); uhci_port_reset(devext, port); - usb_init_device(hcd, usb_device); + struct UsbEndpointDescriptor *endpoint_desc = + kmalloc(sizeof(struct UsbEndpointDescriptor)); + endpoint_desc->bLength = sizeof(struct UsbEndpointDescriptor); + endpoint_desc->bDescriptorType = USB_DESC_TYPE_ENDPOINT; + endpoint_desc->bEndpointAddress = USB_EP_OUT << 7 | 0; // ep0 out + endpoint_desc->bmAttributes = USB_EP_CONTROL; + endpoint_desc->wMaxPacketSize = HOST2LE_WORD(64); + endpoint_desc->bInterval = 0; + usb_init_device(hcd, ep0, endpoint_desc, usb_device); } // 输出端口信息 @@ -205,9 +272,10 @@ DriverResult uhci_init(Device *device) { } void uhci_probe_thread(void *arg) { - Uhci *uhci = (Uhci *)arg; + Uhci *uhci = (Uhci *)arg; + UsbEndpoint *endpoints = kmalloc(sizeof(UsbEndpoint) * uhci->port_cnt); for (int i = 0; i < uhci->port_cnt; i++) { - uhci_port_init(uhci->hcd, i); + uhci_port_init(uhci->hcd, &endpoints[i], i); } } @@ -235,6 +303,13 @@ DriverResult uhci_start(Device *device) { uhci_probe(device); + device->irq = kmalloc(sizeof(DeviceIrq)); + device->irq->device = device; + device->irq->irq = uhci->device->irqline; + device->irq->handler = uhci_handler; + register_device_irq(device->irq); + interrupt_enable_irq(device->irq->irq); + return DRIVER_RESULT_OK; } diff --git a/src/arch/x86/drivers/usb/hci/uhci/packet.c b/src/arch/x86/drivers/usb/hci/uhci/packet.c index b146b8f..d37ae6a 100644 --- a/src/arch/x86/drivers/usb/hci/uhci/packet.c +++ b/src/arch/x86/drivers/usb/hci/uhci/packet.c @@ -1,6 +1,11 @@ #include "driver/timer_dm.h" +#include "driver/usb/usb_dm.h" +#include "kernel/barrier.h" +#include "kernel/list.h" +#include "math.h" #include #include +#include #include #include #include @@ -9,105 +14,160 @@ #include #include #include +#include #define DEFAULT_TD_COUNT 4 -void *uhci_create_sched(void); +void *uhci_create_pipeline(UsbDevice *usb_device, UsbEndpoint *endpoint); + +void uhci_add_interrupt_transfer( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, + struct UsbRequestBlock *urb); +void uhci_interrupt_transfer(UsbHcd *hcd, UsbEndpoint *ep); UsbHcdOps uhci_ops = { - .create_sched = uhci_create_sched, - .ctrl_transfer_in = uhci_ctrl_transfer_in, - .ctrl_transfer_out = uhci_ctrl_transfer_out, + .create_pipeline = uhci_create_pipeline, + .ctrl_transfer_in = uhci_ctrl_transfer_in, + .ctrl_transfer_out = uhci_ctrl_transfer_out, + .add_interrupt_transfer = uhci_add_interrupt_transfer, + .interrupt_transfer = uhci_interrupt_transfer, }; -void *uhci_create_sched(void) { - UhciSched *sched = kmalloc(sizeof(UhciSched)); - sched->qh.qh_addr_phy = vir2phy((uint32_t)&sched->qh); - sched->qh.qe_link = UHCI_TERMINATE; - sched->qh.qh_link = UHCI_TERMINATE; - sched->td_count = DEFAULT_TD_COUNT; - sched->td_index = 0; - sched->tds = kmalloc(sizeof(UhciTd) * sched->td_count); - - for (int i = 0; i < sched->td_count; i++) { - sched->tds[i].link = UHCI_TERMINATE; - sched->tds[i].td_addr_phy = vir2phy((uint32_t)&sched->tds[i]); +void *uhci_create_pipeline(UsbDevice *usb_device, UsbEndpoint *endpoint) { + UhciPipeline *pipe = kmalloc(sizeof(UhciPipeline)); + pipe->qh.qe_link = UHCI_TERMINATE; + pipe->qh.qh_link = UHCI_TERMINATE; + pipe->qh.endpoint = endpoint; + + uint8_t ep_type = endpoint->desc->bmAttributes & 0x03; + if (ep_type == USB_EP_INTERRUPT) { + pipe->td_count = 2; // 1个正式TD和1个备用TD + + // 向下对齐后最大128 + int type = + aligned_down_log2n(endpoint->desc->bInterval | 1 /* 保证最小为1 */); + uhci_skel_add_qh( + usb_device->hcd->device->private_data, &pipe->qh, type); + } else if (ep_type == USB_EP_CONTROL) { + pipe->td_count = 3; // SETUP, DATA, STATUS 3个阶段 + + uhci_skel_add_qh( + usb_device->hcd->device->private_data, &pipe->qh, ASYNC); + } else { + pipe->td_count = DEFAULT_TD_COUNT; + uhci_skel_add_qh( + usb_device->hcd->device->private_data, &pipe->qh, ASYNC); + } + pipe->td_used = 0; + pipe->pre_alloc_td = kmalloc(sizeof(UhciTd) * pipe->td_count); + list_init(&pipe->pipe_lh); + + for (int i = 0; i < pipe->td_count; i++) { + pipe->pre_alloc_td[i].link = UHCI_TERMINATE; + } + return pipe; +} + +UhciTd *uhci_alloc_td(UhciPipeline *pipe) { + UhciTd *td; + int index = BIT_FFZ_R(pipe->td_used); + if (index >= pipe->td_count) { + td = kmalloc(sizeof(UhciTd)); + } else { + td = &pipe->pre_alloc_td[index]; + pipe->td_used |= (1 << index); + } + return td; +} + +void uhci_free_td(UhciPipeline *pipe, UhciTd *td) { + int index = (td - pipe->pre_alloc_td); + if (index >= 0 && index < pipe->td_count) { + pipe->td_used &= ~(1 << index); + } else { + kfree(td); + } +} + +void uhci_free_all_td(UhciPipeline *pipe) { + UhciTd *td, *next; + list_for_each_owner_safe (td, next, &pipe->pipe_lh, list) { + list_del(&td->list); + uhci_free_td(pipe, td); } - return sched; } -void uhci_send_token_packet( +UhciTd *uhci_send_token_packet( UsbDevice *device, UsbEndpoint *ep, UhciQh *qh, uint8_t data_toggle, void *buffer, uint8_t packet_id, int length) { - UsbDevice *usb_device = device; - UhciSched *sched = ep->sched; - if (sched->td_index >= sched->td_count) { - printk("[UHCI]UhciSched td is full.\n"); - return; - } - UhciTd *td = &sched->tds[sched->td_index++]; + UsbDevice *usb_device = device; + UhciPipeline *pipe = ep->pipe; + UhciTd *td = uhci_alloc_td(pipe); + memset(td, 0, sizeof(UhciTd)); - td->packet_id = packet_id; - td->device_addr = usb_device->address & 0x7f; - td->endpoint = ep->endpoint & 0x0f; - td->data_toggle = data_toggle; - td->max_length = length > 0 ? (length - 1) : 0; + td->packet_id = packet_id; + td->device_addr = usb_device->address & 0x7f; + td->endpoint = ep->desc->bEndpointAddress & 0x0f; + td->data_toggle = data_toggle; + td->max_length = length > 0 ? (length - 1) : 0x7ff; + td->lowspeed_device = (usb_device->speed == USB_SPEED_LOW) ? 1 : 0; td->active = 1; td->actlen = 0; + td->error_count = 3; + if (buffer != NULL) td->buf_addr_phy = vir2phy((uint32_t)buffer); else td->buf_addr_phy = 0; - td->prev_ptr = qh->last_ptr; - UhciTd *last_td = (UhciTd *)qh->last_ptr; - if (last_td != NULL) { - last_td->link = BIN_EN( - BIN_DIS(td->td_addr_phy, UHCI_QH_TD_SELECT), UHCI_VERTICAL_FIRST); + if (!list_empty(&pipe->pipe_lh)) { + UhciTd *last_td = list_last_owner(&pipe->pipe_lh, UhciTd, list); + list_add_tail(&td->list, &pipe->pipe_lh); + last_td->link = BIN_DIS(vir2phy((uint32_t)td), UHCI_QH_TD_SELECT); + last_td->link = BIN_EN(last_td->link, UHCI_VERTICAL_FIRST); + last_td->next = td; } else { - qh->qe_link = BIN_DIS(td->td_addr_phy, UHCI_QH_TD_SELECT); + list_add_tail(&td->list, &pipe->pipe_lh); + qh->first_td = td; } td->link = UHCI_TERMINATE; - - qh->last_ptr = (uint32_t)td; + return td; } -static inline int uhci_setup_transcation( +static inline UhciTd *uhci_setup_transcation( UsbDevice *device, UsbEndpoint *ep, UhciQh *qh, void *buffer, uint32_t length) { - uhci_send_token_packet( + return uhci_send_token_packet( device, ep, qh, 0, buffer, USB_PACKET_ID_SETUP, length); - return 0; } -static inline int uhci_in_transcation( +static inline UhciTd *uhci_in_transcation( UsbDevice *device, UsbEndpoint *ep, UhciQh *qh, int data_toggle, void *buffer, uint32_t length) { - uhci_send_token_packet( + return uhci_send_token_packet( device, ep, qh, data_toggle, buffer, USB_PACKET_ID_IN, length); - return 0; } -static inline int uhci_out_transcation( +static inline UhciTd *uhci_out_transcation( UsbDevice *device, UsbEndpoint *ep, UhciQh *qh, int data_toggle, void *buffer, uint32_t length) { - uhci_send_token_packet( + return uhci_send_token_packet( device, ep, qh, data_toggle, buffer, USB_PACKET_ID_OUT, length); - return 0; } int uhci_wait_transfer(UhciQh *qh) { Timer timer; timer_init(&timer); - int timeout = 150; - UhciTd *td = (UhciTd *)qh->last_ptr; + int timeout = 150; + UhciPipeline *pipe = (UhciPipeline *)qh; + // UhciTd *td = &pipe->tds[pipe->td_index - 1]; + UhciTd *td = qh->first_td; while (timeout > 0) { if (td->active == 0) { return 1; } delay_ms(&timer, 10); timeout--; } - td = &(((UhciSched *)qh)->tds[0]); uint32_t *raw = (uint32_t *)td; // TD 在内存首地址 printk( "TD raw: w0=%08x w1=%08x w2=%08x w3=%08x\n", raw[0], raw[1], raw[2], @@ -116,25 +176,30 @@ int uhci_wait_transfer(UhciQh *qh) { " decoded: pid=%02x dev=%u ep=%u toggle=%u maxlen=%u active=%u\n", td->packet_id, td->device_addr, td->endpoint, td->data_toggle, td->max_length, td->active); - printk("[UHCI]td %#08x(phy %#08x) timeout.", td, td->td_addr_phy); + printk("[UHCI]td %#08x(phy %#08x) timeout.\n", td, vir2phy((uint32_t)td)); return -1; } UsbSetupStatus uhci_ctrl_transfer_in( UsbHcd *hcd, UsbDevice *device, void *buffer, uint32_t data_length, - UsbRequest *usb_req) { - UhciSched *sched = device->ep0->sched; - UhciQh *qh = &sched->qh; - qh->qe_link = UHCI_TERMINATE; - qh->qh_link = UHCI_TERMINATE; + UsbControlRequest *usb_req) { + UhciPipeline *pipe = device->ep0->pipe; + UhciQh *qh = &pipe->qh; + qh->qe_link = UHCI_TERMINATE; + qh->qh_link = UHCI_TERMINATE; uhci_setup_transcation(device, device->ep0, qh, usb_req, 8); uhci_in_transcation(device, device->ep0, qh, 0, buffer, data_length); - uhci_out_transcation(device, device->ep0, qh, 1, NULL, 0); + UhciTd *last_td = uhci_out_transcation(device, device->ep0, qh, 1, NULL, 0); + UhciTd *first_td = qh->first_td; + qh->qe_link = BIN_DIS(vir2phy((uint32_t)first_td), UHCI_QH_TD_SELECT); - uhci_skel_add_qh(hcd->device->private_data, qh, LOW_SPEED); - uhci_wait_transfer(qh); + if (uhci_wait_transfer(qh) < 0) { + // 超时 + uhci_free_all_td(pipe); + return USB_SETUP_CRC_TIMEOUT_ERR; + } + qh->qe_link = UHCI_TERMINATE; - UhciTd *last_td = (UhciTd *)qh->last_ptr; UsbSetupStatus result; if (last_td->stalled) { @@ -150,29 +215,33 @@ UsbSetupStatus uhci_ctrl_transfer_in( } else { result = USB_SETUP_SUCCESS; } - uhci_skel_del_qh(hcd->device->private_data, qh, LOW_SPEED); - sched->td_index = 0; + uhci_free_all_td(pipe); return result; } UsbSetupStatus uhci_ctrl_transfer_out( UsbHcd *hcd, UsbDevice *device, void *buffer, uint32_t data_length, - UsbRequest *usb_req) { - UhciSched *sched = device->ep0->sched; - UhciQh *qh = &sched->qh; - qh->qe_link = UHCI_TERMINATE; - qh->qh_link = UHCI_TERMINATE; + UsbControlRequest *usb_req) { + UhciPipeline *pipe = device->ep0->pipe; + UhciQh *qh = &pipe->qh; + qh->qe_link = UHCI_TERMINATE; + qh->qh_link = UHCI_TERMINATE; uhci_setup_transcation(device, device->ep0, qh, usb_req, 8); if (data_length != 0) { uhci_out_transcation(device, device->ep0, qh, 0, buffer, data_length); } - uhci_in_transcation(device, device->ep0, qh, 1, NULL, 0); + UhciTd *last_td = uhci_in_transcation(device, device->ep0, qh, 1, NULL, 0); + UhciTd *first_td = qh->first_td; + qh->qe_link = BIN_DIS(vir2phy((uint32_t)first_td), UHCI_QH_TD_SELECT); - uhci_skel_add_qh(hcd->device->private_data, qh, LOW_SPEED); - uhci_wait_transfer(qh); + if (uhci_wait_transfer(qh) < 0) { + // 超时 + uhci_free_all_td(pipe); + return USB_SETUP_CRC_TIMEOUT_ERR; + } + qh->qe_link = UHCI_TERMINATE; - UhciTd *last_td = (UhciTd *)qh->last_ptr; UsbSetupStatus result; if (last_td->stalled) { @@ -188,8 +257,64 @@ UsbSetupStatus uhci_ctrl_transfer_out( } else { result = USB_SETUP_SUCCESS; } - uhci_skel_del_qh(hcd->device->private_data, qh, LOW_SPEED); - sched->td_index = 0; + uhci_free_all_td(pipe); return result; } + +void uhci_add_interrupt_transfer( + UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, UsbRequestBlock *urb) { + UhciPipeline *pipe = ep->pipe; + UhciQh *qh = &pipe->qh; + UhciTd *td, *_td; + qh->qe_link = UHCI_TERMINATE; + if (ep->desc->bEndpointAddress >> 7 == USB_EP_IN) { + td = uhci_in_transcation( + device, ep, qh, ep->data_toggle, urb->buffer, + ep->desc->wMaxPacketSize); + _td = uhci_in_transcation( + device, ep, qh, ep->data_toggle ^ 1, urb->buffer, + ep->desc->wMaxPacketSize); + } else { + td = uhci_out_transcation( + device, ep, qh, ep->data_toggle, urb->buffer, + ep->desc->wMaxPacketSize); + _td = uhci_out_transcation( + device, ep, qh, ep->data_toggle ^ 1, urb->buffer, + ep->desc->wMaxPacketSize); + } + + UhciTd *first_td = qh->first_td; + qh->qe_link = BIN_DIS(vir2phy((uint32_t)first_td), UHCI_QH_TD_SELECT); + td->urb = urb; + _td->urb = urb; + td->interrupt_on_complete = 1; // 传输完成后中断通知 + _td->interrupt_on_complete = 0; + wmb(); +} + +void uhci_interrupt_transfer(UsbHcd *hcd, UsbEndpoint *ep) { + UhciPipeline *pipe = ep->pipe; + + UhciTd *first_td = pipe->qh.first_td; + UhciTd *next = first_td->next; + + ep->data_toggle ^= 1; + + first_td->data_toggle = ep->data_toggle; + first_td->stalled = 0; + first_td->crc_timeout_Error = 0; + first_td->bitstuff_Error = 0; + first_td->NAK_received = 0; + first_td->databuffer_Error = 0; + + first_td->active = 1; + first_td->actlen = 0; + first_td->interrupt_on_complete = 1; + + next->data_toggle = ep->data_toggle ^ 1; + next->active = 1; + + // 2. 挂回 QH + pipe->qh.qe_link = BIN_DIS(vir2phy((uint32_t)first_td), UHCI_QH_TD_SELECT); +} diff --git a/src/arch/x86/drivers/usb/hci/uhci/skeleton.c b/src/arch/x86/drivers/usb/hci/uhci/skeleton.c index 8c5608d..11d52ec 100644 --- a/src/arch/x86/drivers/usb/hci/uhci/skeleton.c +++ b/src/arch/x86/drivers/usb/hci/uhci/skeleton.c @@ -2,6 +2,7 @@ #include #include #include +#include void uhci_skel_init(Uhci *uhci) { int i; @@ -12,22 +13,20 @@ void uhci_skel_init(Uhci *uhci) { memset32(uhci->fl.frames_vir, 1, 1024); - qhs[TIME_1MS].qh_addr_phy = vir2phy((uint32_t)&qhs[TIME_1MS]); - qhs[TIME_1MS].next_ptr = (uint32_t)&qhs[LOW_SPEED]; + uint32_t phy = vir2phy((uint32_t)&qhs[TIME_1MS]); + qhs[TIME_1MS].next = &qhs[ASYNC]; qhs[TIME_1MS].qh_link = - BIN_EN(vir2phy(qhs[TIME_1MS].next_ptr), UHCI_QH_TD_SELECT); + BIN_EN(vir2phy((uint32_t)qhs[TIME_1MS].next), UHCI_QH_TD_SELECT); qhs[TIME_1MS].qe_link = UHCI_TERMINATE; for (i = 1; i < 8; i++) { - qhs[i].qh_addr_phy = vir2phy((uint32_t)&qhs[i]); - qhs[i].next_ptr = (uint32_t)&qhs[TIME_1MS]; - qhs[i].qh_link = BIN_EN(qhs[TIME_1MS].qh_addr_phy, UHCI_QH_TD_SELECT); + qhs[i].next = &qhs[TIME_1MS]; + qhs[i].qh_link = BIN_EN(phy, UHCI_QH_TD_SELECT); qhs[i].qe_link = UHCI_TERMINATE; } - qhs[LOW_SPEED].qh_addr_phy = vir2phy((uint32_t)&qhs[LOW_SPEED]); - qhs[LOW_SPEED].next_ptr = (uint32_t)&qhs[TERM]; - qhs[LOW_SPEED].qh_link = - BIN_EN(vir2phy(qhs[LOW_SPEED].next_ptr), UHCI_QH_TD_SELECT); - qhs[LOW_SPEED].qe_link = UHCI_TERMINATE; + qhs[ASYNC].next = &qhs[TERM]; + qhs[ASYNC].qh_link = + BIN_EN(vir2phy((uint32_t)qhs[ASYNC].next), UHCI_QH_TD_SELECT); + qhs[ASYNC].qe_link = UHCI_TERMINATE; // 构建结束的QH和TD @@ -37,16 +36,16 @@ void uhci_skel_init(Uhci *uhci) { term_td->max_length = 0x7ff; term_td->device_addr = 0x7f; term_td->packet_id = USB_PACKET_ID_IN; - term_td->td_addr_phy = vir2phy((uint32_t)term_td); - term_td->link = term_td->td_addr_phy; + term_td->link = vir2phy((uint32_t)term_td); - qhs[TERM].qh_link = UHCI_TERMINATE; - qhs[TERM].qe_link = term_td->td_addr_phy; + qhs[TERM].qh_link = UHCI_TERMINATE; + qhs[TERM].qe_link = term_td->link; + qhs[TERM].first_td = term_td; i = 0; while (i < 1024) { int irq = 1 + BIT_FFS_R(i + FRAMELIST_SIZE); - if (irq > 7) irq = 7; + if (irq > 7) irq = 0; uhci->fl.frames_vir[i] = BIN_EN(vir2phy((uint32_t)&qhs[irq]), UHCI_QH_TD_SELECT); @@ -55,39 +54,49 @@ void uhci_skel_init(Uhci *uhci) { } void uhci_skel_add_qh(Uhci *uhci, UhciQh *qh, UhciSkelType type) { - UhciQh *last_qh = ((UhciQh *)uhci->skel->qh[type].last_ptr); - if (last_qh != NULL) { - qh->qh_link = last_qh->qh_link; - last_qh->next_ptr = (uint32_t)qh; - qh->prev_ptr = (uint32_t)last_qh; - last_qh->qh_link = BIN_EN(qh->qh_addr_phy, UHCI_QH_TD_SELECT); + UhciQh *first_qh = uhci->skel->qh[type].first_qh; + if (qh->enqueued) return; // 已经被添加 + if (first_qh != NULL) { + qh->qh_link = uhci->skel->qh[type].qe_link; + qh->next = first_qh; + uhci->skel->qh[type].first_qh = qh; + uhci->skel->qh[type].qe_link = + BIN_EN(vir2phy((uint32_t)qh), UHCI_QH_TD_SELECT); } else { qh->qh_link = UHCI_TERMINATE; uhci->skel->qh[type].qe_link = - BIN_EN(qh->qh_addr_phy, UHCI_QH_TD_SELECT); + BIN_EN(vir2phy((uint32_t)qh), UHCI_QH_TD_SELECT); } - uhci->skel->qh[type].last_ptr = (uint32_t)qh; + qh->enqueued = 1; + uhci->skel->qh[type].first_qh = qh; } void uhci_skel_del_qh(Uhci *uhci, UhciQh *qh, UhciSkelType type) { - if (qh->prev_ptr != 0) { - if (qh->next_ptr != 0) { - UhciQh *next_qh = (UhciQh *)qh->next_ptr; - UhciQh *prev_qh = (UhciQh *)qh->prev_ptr; - prev_qh->next_ptr = qh->next_ptr; - next_qh->prev_ptr = qh->prev_ptr; - } - } else { - if (qh->next_ptr != 0) { - UhciQh *next_qh = (UhciQh *)qh->next_ptr; - next_qh->prev_ptr = qh->prev_ptr; - uhci->skel->qh[type].qe_link = qh->qh_link; - } else { - uhci->skel->qh[type].qe_link = UHCI_TERMINATE; - uhci->skel->qh[type].last_ptr = 0; + UhciQh *_qh, *prev = NULL; + UhciQh *ptr = uhci->skel->qh[type].first_qh; + while (ptr != NULL) { + _qh = ptr; + if (_qh == qh) { + // Found the QH to delete + if (prev != NULL) { + prev->next = qh->next; + prev->qh_link = qh->qh_link; + } else if (qh->next != NULL) { + uhci->skel->qh[type].first_qh = qh->next; + uhci->skel->qh[type].qe_link = + BIN_EN(vir2phy((uint32_t)qh->next), UHCI_QH_TD_SELECT); + } else { + uhci->skel->qh[type].qe_link = UHCI_TERMINATE; + } + _qh->qh_link = UHCI_TERMINATE; + _qh->next = 0; + break; } + prev = _qh; + ptr = _qh->next; } - qh->next_ptr = 0; - qh->prev_ptr = 0; - qh->last_ptr = 0; + qh->qe_link = UHCI_TERMINATE; + if (qh->first_td != NULL) uhci_free_all_td((UhciPipeline *)qh); + qh->first_td = NULL; + qh->enqueued = 0; } \ No newline at end of file diff --git a/src/arch/x86/include/drivers/usb/uhci.h b/src/arch/x86/include/drivers/usb/uhci.h index 2c57c05..8427a89 100644 --- a/src/arch/x86/include/drivers/usb/uhci.h +++ b/src/arch/x86/include/drivers/usb/uhci.h @@ -1,6 +1,8 @@ #ifndef _UHCI_H #define _UHCI_H +#include "driver/usb/urb.h" +#include "kernel/list.h" #include #include #include @@ -45,6 +47,13 @@ #define UHCI_PORT_SC_CONN_CHG BIT(1) #define UHCI_PORT_SC_CONNECTED BIT(0) +#define UHCI_STAT_HC_HALTED BIT(5) +#define UHCI_STAT_HC_PROCESS_ERROR BIT(4) +#define UHCI_STAT_HOST_SYSTEM_ERROR BIT(3) +#define UHCI_STAT_RESUME_DETECT BIT(2) +#define UHCI_STAT_ERROR_INT BIT(1) +#define UHCI_STAT_INTERRUPT BIT(0) + #define UHCI_STAT_SPEED BIT(29) #define UHCI_STAT_ERROR_LIMIT_BIT 27 #define UHCI_STAT_LSD BIT(26) @@ -69,6 +78,8 @@ #define UHCI_QH_TD_SELECT BIT(1) // 1:QH, 0:TD #define UHCI_TERMINATE BIT(0) +#define UHCI_SKEL_QH_COUNT 11 + typedef struct UhciFrameList { uint32_t *frames_vir; uint32_t *frames_phy; @@ -76,15 +87,17 @@ typedef struct UhciFrameList { typedef struct UhciQh { // 硬件用 - uint32_t qh_link; - uint32_t qe_link; + uint32_t qh_link; + uint32_t qe_link; // 软件用 - uint32_t qh_addr_phy; - uint32_t prev_ptr; - uint32_t last_ptr; - uint32_t next_ptr; - uint32_t align[2]; // 用于对齐16字节 -} __attribute__((packed)) UhciQh; + uint8_t enqueued : 1; + struct UhciQh *next; + union { + struct UhciQh *first_qh; + struct UhciTd *first_td; + }; + UsbEndpoint *endpoint; +} __attribute__((packed, aligned(16))) UhciQh; typedef struct UhciTd { uint32_t link; @@ -118,20 +131,24 @@ typedef struct UhciTd { uint32_t buf_addr_phy; // software use - uint32_t prev_ptr; - uint32_t td_addr_phy; - uint32_t software_use[2]; -} __attribute__((packed)) UhciTd; + list_t list; + struct UhciTd *next; + UsbRequestBlock *urb; +} __attribute__((packed, aligned(16))) UhciTd; typedef struct UhciSched { - UhciQh qh; + UhciQh qh; + uint8_t td_count; - uint8_t td_index; - UhciTd *tds; -} UhciSched; + uint8_t td_used; // bitmap + UhciTd *pre_alloc_td; // 预分配的TD + + list_t pipe_lh; +} UhciPipeline; typedef struct UhciSkel { - struct UhciQh qh[11]; // 1ms, 2ms, 4ms, 8ms, 16ms, 32ms, 64ms, 128ms + struct UhciQh + qh[UHCI_SKEL_QH_COUNT]; // 1ms, 2ms, 4ms, 8ms, 16ms, 32ms, 64ms, 128ms } UhciSkel; typedef struct { @@ -154,8 +171,7 @@ typedef enum UhciSkelType { TIME_32MS, TIME_64MS, TIME_128MS, - LOW_SPEED, - FULL_SPEED, + ASYNC, TERM, } UhciSkelType; @@ -164,11 +180,13 @@ void uhci_skel_init(Uhci *uhci); void uhci_skel_add_qh(Uhci *uhci, UhciQh *qh, UhciSkelType type); void uhci_skel_del_qh(Uhci *uhci, UhciQh *qh, UhciSkelType type); +void uhci_free_all_td(UhciPipeline *pipe); + UsbSetupStatus uhci_ctrl_transfer_in( UsbHcd *hcd, UsbDevice *device, void *buffer, uint32_t data_length, - UsbRequest *usb_req); + UsbControlRequest *usb_req); UsbSetupStatus uhci_ctrl_transfer_out( UsbHcd *hcd, UsbDevice *device, void *buffer, uint32_t data_length, - UsbRequest *usb_req); + UsbControlRequest *usb_req); #endif \ No newline at end of file diff --git a/src/include/driver/usb/hcd.h b/src/include/driver/usb/hcd.h index 846029c..20d2c8a 100644 --- a/src/include/driver/usb/hcd.h +++ b/src/include/driver/usb/hcd.h @@ -10,8 +10,9 @@ #include struct UsbDevice; -struct UsbTransfer; -struct UsbRequest; +struct UsbRequestBlock; +struct UsbControlRequest; +struct UsbEndpoint; typedef struct UsbHcdPort { uint32_t port; @@ -23,13 +24,18 @@ typedef struct UsbHcdPort { } UsbHcdPort; typedef struct UsbHcdOps { - void *(*create_sched)(void); + void *(*create_pipeline)( + struct UsbDevice *usb_device, struct UsbEndpoint *endpoint); enum UsbSetupStatus (*ctrl_transfer_in)( struct UsbHcd *hcd, struct UsbDevice *device, void *buffer, - uint32_t data_length, struct UsbRequest *usb_req); + uint32_t data_length, struct UsbControlRequest *usb_req); enum UsbSetupStatus (*ctrl_transfer_out)( struct UsbHcd *hcd, struct UsbDevice *device, void *buffer, - uint32_t data_length, struct UsbRequest *usb_req); + uint32_t data_length, struct UsbControlRequest *usb_req); + void (*add_interrupt_transfer)( + struct UsbHcd *hcd, struct UsbDevice *device, struct UsbEndpoint *ep, + struct UsbRequestBlock *urb); + void (*interrupt_transfer)(struct UsbHcd *hcd, struct UsbEndpoint *ep); } UsbHcdOps; typedef struct UsbHcd { From 22642789ce4d85edcdbc35764f36a1e23fb56065 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 22 Sep 2025 14:07:59 +0800 Subject: [PATCH 128/158] =?UTF-8?q?timer:=20=E5=9C=A8delay=5Fms=E4=B8=AD?= =?UTF-8?q?=E4=BF=9D=E8=AF=81=E4=B8=AD=E6=96=AD=E5=BC=80=E5=90=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/timer/timer.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/driver/timer/timer.c b/src/driver/timer/timer.c index 7322432..3064139 100644 --- a/src/driver/timer/timer.c +++ b/src/driver/timer/timer.c @@ -1,3 +1,5 @@ +#include "kernel/driver_interface.h" +#include "kernel/func.h" #include "kernel/list.h" #include #include @@ -62,8 +64,11 @@ void delay_ms(Timer *timer, uint32_t ms) { uint32_t count = timer_count_ms(timer, ms); timer_set_timeout(timer, count); + uint32_t status = load_interrupt_status(); + enable_interrupt(); while (!timer_is_timeout(timer)) ; + store_interrupt_status(status); } void delay_ms_async(Timer *timer, uint32_t ms) { From 48834aad536f11b3681aedec03e5a46684b86e6a Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 22 Sep 2025 14:09:52 +0800 Subject: [PATCH 129/158] =?UTF-8?q?usb:=20=E6=96=B0=E5=A2=9Eusb=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E9=A9=B1=E5=8A=A8=E6=94=AF=E6=8C=81=EF=BC=9B=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E4=BC=A0=E8=BE=93=E7=AE=A1=E7=90=86=E7=BB=93=E6=9E=84?= =?UTF-8?q?UsbRequestBlock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/usb/Makefile | 1 + src/driver/usb/usb-core/Makefile | 5 +- src/driver/usb/usb-core/func.c | 88 +++++++++++-------- src/driver/usb/usb-core/hub.c | 60 +++++++------ src/driver/usb/usb-core/urb.c | 28 ++++++ src/driver/usb/usb-core/usb.c | 33 ++++---- src/driver/usb/usb_dm.c | 41 ++++++++- src/driver/usb/usb_driver.c | 9 ++ src/drivers/Makefile | 3 +- src/include/driver/usb/descriptors.h | 59 +++++++++++++ src/include/driver/usb/func.h | 51 ++++++++++- src/include/driver/usb/hub.h | 2 +- src/include/driver/usb/urb.h | 26 ++++++ src/include/driver/usb/usb.h | 94 +++++++++++++++++---- src/include/driver/usb/usb_dm.h | 1 + src/include/driver/usb/usb_driver.h | 23 +++++ src/include/kernel/device.h | 3 +- src/include/kernel/dynamic_device_manager.h | 2 + src/include/kernel/softirq.h | 1 + src/kernel/driver/bus_driver.c | 3 +- 20 files changed, 428 insertions(+), 105 deletions(-) create mode 100644 src/driver/usb/usb-core/urb.c create mode 100644 src/driver/usb/usb_driver.c create mode 100644 src/include/driver/usb/urb.h create mode 100644 src/include/driver/usb/usb_driver.h diff --git a/src/driver/usb/Makefile b/src/driver/usb/Makefile index ed15285..c986b7f 100644 --- a/src/driver/usb/Makefile +++ b/src/driver/usb/Makefile @@ -1,2 +1,3 @@ SRC += usb_dm.c +SRC += usb_driver.c SRC += usb-core/ \ No newline at end of file diff --git a/src/driver/usb/usb-core/Makefile b/src/driver/usb/usb-core/Makefile index c206bc9..ecedd10 100644 --- a/src/driver/usb/usb-core/Makefile +++ b/src/driver/usb/usb-core/Makefile @@ -1,4 +1,5 @@ SRC += func.c SRC += hub.c -SRC += usb.c -SRC += hcd.c \ No newline at end of file +SRC += usb.c +SRC += hcd.c +SRC += urb.c \ No newline at end of file diff --git a/src/driver/usb/usb-core/func.c b/src/driver/usb/usb-core/func.c index 4d50cbb..67fadf8 100644 --- a/src/driver/usb/usb-core/func.c +++ b/src/driver/usb/usb-core/func.c @@ -8,63 +8,81 @@ #include #include -struct UsbDeviceDescriptor *usb_get_device_descriptor( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { - struct UsbDeviceDescriptor *desc = - kmalloc(sizeof(struct UsbDeviceDescriptor)); +void *usb_get_descriptor( + UsbHcd *hcd, UsbDevice *device, uint8_t type, uint8_t recipient, + uint8_t index, UsbEndpoint *ep, uint8_t value_hi, uint8_t value_lo, + uint16_t desc_size) { + void *desc = kmalloc(desc_size); - UsbRequest usb_req = USB_BUILD_REQUEST( - USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, - USB_REQ_GET_DESCRIPTOR, USB_DESC_TYPE_DEVICE, 0, 0, - USB_DESC_TYPE_DEVICE_SIZE); + UsbControlRequest usb_req = USB_BUILD_REQUEST( + USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_STANDARD, recipient, + USB_REQ_GET_DESCRIPTOR, value_hi, value_lo, index, desc_size); - hcd->ops->ctrl_transfer_in( - hcd, device, desc, USB_DESC_TYPE_DEVICE_SIZE, &usb_req); + hcd->ops->ctrl_transfer_in(hcd, device, desc, desc_size, &usb_req); + return desc; +} + +void *usb_set_descriptor( + UsbHcd *hcd, UsbDevice *device, uint8_t type, uint8_t recipient, + uint8_t index, UsbEndpoint *ep, uint8_t value_hi, uint8_t value_lo, + uint16_t desc_size) { + void *desc = kmalloc(desc_size); + + UsbControlRequest usb_req = USB_BUILD_REQUEST( + USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_STANDARD, recipient, + USB_REQ_SET_DESCRIPTOR, value_hi, value_lo, index, desc_size); + + hcd->ops->ctrl_transfer_out(hcd, device, desc, desc_size, &usb_req); return desc; } struct UsbConfigDescriptor *usb_get_config_descriptor( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { + UsbHcd *hcd, UsbDevice *usb_device, UsbEndpoint *ep) { struct UsbConfigDescriptor *desc = kmalloc(sizeof(struct UsbConfigDescriptor)); - UsbRequest usb_req = USB_BUILD_REQUEST( + UsbControlRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_GET_DESCRIPTOR, USB_DESC_TYPE_CONFIG, 0, 0, USB_DESC_TYPE_CONFIG_SIZE); hcd->ops->ctrl_transfer_in( - hcd, device, desc, USB_DESC_TYPE_CONFIG_SIZE, &usb_req); + hcd, usb_device, desc, USB_DESC_TYPE_CONFIG_SIZE, &usb_req); uint8_t *buffer = kmalloc(desc->wTotalLength); usb_req.wLength = desc->wTotalLength; - hcd->ops->ctrl_transfer_in(hcd, device, buffer, usb_req.wLength, &usb_req); + hcd->ops->ctrl_transfer_in( + hcd, usb_device, buffer, usb_req.wLength, &usb_req); - int length = desc->wTotalLength; + UsbInterface *interface = NULL; + int ep_num; + int length = desc->wTotalLength; while (length > 0) { uint8_t type = buffer[1]; if (type == USB_DESC_TYPE_INTERFACE) { struct UsbInterfaceDescriptor *interface_desc = (struct UsbInterfaceDescriptor *)buffer; - UsbInterface *interface = kmalloc(sizeof(UsbInterface)); + interface = kmalloc( + sizeof(UsbInterface) + + sizeof(UsbEndpoint *) * interface_desc->bNumEndpoints); - interface->interface = interface_desc->bInterfaceNumber; - interface->class = interface_desc->bInterfaceClass; - interface->subclass = interface_desc->bInterfaceSubClass; - interface->protocol = interface_desc->bInterfaceProtocol; + interface->usb_driver = NULL; + interface->desc = interface_desc; - list_add_tail(&interface->list, &device->interface_lh); + list_add_tail(&interface->list, &usb_device->interface_lh); + ep_num = 0; } else if (type == USB_DESC_TYPE_ENDPOINT) { struct UsbEndpointDescriptor *endpoint_desc = (struct UsbEndpointDescriptor *)buffer; - UsbEndpoint *ep = usb_create_endpoint( - hcd, endpoint_desc->bEndpointAddress & 0x0f, - endpoint_desc->bmAttributes & 0x03, - endpoint_desc->bEndpointAddress >> 7, - endpoint_desc->wMaxPacketSize & 0x07ff); + UsbEndpoint *ep = kmalloc(sizeof(UsbEndpoint)); + usb_init_endpoint(usb_device, ep, endpoint_desc); - list_add_tail(&ep->list, &device->ep_lh); + if (interface) { + interface->endpoints[ep_num] = ep; + ep_num++; + } + list_add_tail(&ep->list, &usb_device->ep_lh); } length -= buffer[0]; buffer += buffer[0]; @@ -75,7 +93,7 @@ struct UsbConfigDescriptor *usb_get_config_descriptor( uint8_t usb_get_config(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { uint8_t config; - UsbRequest usb_req = USB_BUILD_REQUEST( + UsbControlRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_GET_CONFIGURATION, 0, 0, 0, 1); hcd->ops->ctrl_transfer_in(hcd, device, &config, 1, &usb_req); @@ -86,7 +104,7 @@ uint8_t usb_get_config(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { UsbSetupStatus usb_set_config( UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t config) { - UsbRequest usb_req = USB_BUILD_REQUEST( + UsbControlRequest usb_req = USB_BUILD_REQUEST( USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_SET_CONFIGURATION, config, 0, 0, 0); return hcd->ops->ctrl_transfer_out(hcd, device, NULL, 0, &usb_req); @@ -96,7 +114,7 @@ struct UsbHubDescriptor *usb_get_hub_descriptor( UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { struct UsbHubDescriptor *desc = kmalloc(sizeof(struct UsbHubDescriptor)); - UsbRequest usb_req = USB_BUILD_REQUEST( + UsbControlRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_DEVICE, USB_REQ_GET_DESCRIPTOR, USB_DESC_TYPE_HUB, 0, 0, USB_DESC_TYPE_HUB_SIZE); @@ -108,7 +126,7 @@ struct UsbHubDescriptor *usb_get_hub_descriptor( uint32_t usb_get_hub_status(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { uint32_t stat; - UsbRequest usb_req = USB_BUILD_REQUEST( + UsbControlRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_GET_STATUS, 0, 0, 0, 4); hcd->ops->ctrl_transfer_in(hcd, device, &stat, 4, &usb_req); @@ -119,7 +137,7 @@ uint32_t usb_get_port_status( UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t port) { uint32_t stat; - UsbRequest usb_req = USB_BUILD_REQUEST( + UsbControlRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_OTHER, USB_REQ_GET_STATUS, 0, 0, port, REQ_GET_PORT_STATUS_SIZE); hcd->ops->ctrl_transfer_in( @@ -131,7 +149,7 @@ struct UsbStringDescriptor *usb_get_string_descriptor( UsbHcd *hcd, UsbDevice *device, uint8_t index, UsbEndpoint *ep) { uint8_t buffer[2]; - UsbRequest usb_req = USB_BUILD_REQUEST( + UsbControlRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_GET_DESCRIPTOR, USB_DESC_TYPE_STRING, index, 0x0409, 2); @@ -148,7 +166,7 @@ struct UsbStringDescriptor *usb_get_string_descriptor( UsbSetupStatus usb_set_address( UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint32_t address) { - UsbRequest req = USB_BUILD_REQUEST( + UsbControlRequest req = USB_BUILD_REQUEST( USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_SET_ADDRESS, address >> 8, address & 0xff, 0, 0); @@ -159,7 +177,7 @@ UsbSetupStatus usb_set_port_feature( UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t port, uint16_t feature) { - UsbRequest req = USB_BUILD_REQUEST( + UsbControlRequest req = USB_BUILD_REQUEST( USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_OTHER, USB_REQ_SET_FEATURE, feature >> 8, feature & 0xff, port, 0); diff --git a/src/driver/usb/usb-core/hub.c b/src/driver/usb/usb-core/hub.c index c761c0c..5ab40b2 100644 --- a/src/driver/usb/usb-core/hub.c +++ b/src/driver/usb/usb-core/hub.c @@ -7,40 +7,48 @@ #include #include #include +#include #include -void usb_init_hub(UsbHcd *hcd, UsbDevice *device) { - Timer timer; - UsbEndpoint *ep0 = - usb_create_endpoint(hcd, 0, USB_EP_CONTROL, USB_EP_OUT, 64); - device->ep0 = ep0; +void usb_init_hub(UsbHcd *hcd, UsbEndpoint *ep0, UsbDevice *usb_device) { + Timer timer; timer_init(&timer); - hcd->device_count++; - usb_set_address(hcd, device, ep0, hcd->device_count); - delay_ms(&timer, 2); - device->address = hcd->device_count; - - struct UsbHubDescriptor *desc = usb_get_hub_descriptor(hcd, device, ep0); + // TODO: UsbHub + struct UsbHubDescriptor *desc = + usb_get_hub_descriptor(hcd, usb_device, ep0); // usb_show_hub_descriptor(desc); - uint32_t status = usb_get_hub_status(hcd, device, ep0); + uint32_t status = usb_get_hub_status(hcd, usb_device, ep0); - int i; + int i; + UsbSetupStatus status2; + UsbEndpoint *endpoints = kmalloc(sizeof(UsbEndpoint) * desc->bNbrPorts); for (i = 1; i <= desc->bNbrPorts; i++) { - - usb_set_port_feature(hcd, device, ep0, i, HUB_FEAT_PORT_POWER); - delay_ms(&timer, 50); - usb_set_port_feature(hcd, device, ep0, i, HUB_FEAT_PORT_RESET); - delay_ms(&timer, 200); - - status = usb_get_port_status(hcd, device, ep0, i); + status = usb_get_port_status(hcd, usb_device, ep0, i); if (BIN_IS_EN(status, USB_PORT_STAT_CONNECTION)) { - UsbDevice *dev = usb_create_device( - hcd, - (BIN_IS_EN(status, USB_PORT_STAT_LOW_SPEED) ? USB_SPEED_LOW - : USB_SPEED_FULL), - 0); - usb_init_device(hcd, dev); + status2 = usb_set_port_feature( + hcd, usb_device, ep0, i, HUB_FEAT_PORT_POWER); + if (status2 == USB_SETUP_CRC_TIMEOUT_ERR) { continue; } + delay_ms(&timer, 50); + status2 = usb_set_port_feature( + hcd, usb_device, ep0, i, HUB_FEAT_PORT_RESET); + if (status2 == USB_SETUP_CRC_TIMEOUT_ERR) { continue; } + delay_ms(&timer, 200); + + UsbDeviceSpeed speed = + BIN_IS_EN(status, USB_PORT_STAT_LOW_SPEED) ? USB_SPEED_LOW + : BIN_IS_EN(status, USB_PORT_STAT_HIGH_SPEED) ? USB_SPEED_HIGH + : USB_SPEED_FULL; + UsbDevice *dev = usb_create_device(hcd, speed, 0); + struct UsbEndpointDescriptor *endpoint_desc = + kmalloc(sizeof(struct UsbEndpointDescriptor)); + endpoint_desc->bLength = sizeof(struct UsbEndpointDescriptor); + endpoint_desc->bDescriptorType = USB_DESC_TYPE_ENDPOINT; + endpoint_desc->bEndpointAddress = USB_EP_OUT << 7 | 0; // ep0 out + endpoint_desc->bmAttributes = USB_EP_CONTROL; + endpoint_desc->wMaxPacketSize = HOST2LE_WORD(64); + endpoint_desc->bInterval = 0; + usb_init_device(hcd, &endpoints[i - 1], endpoint_desc, dev); delay_ms(&timer, 100); } } diff --git a/src/driver/usb/usb-core/urb.c b/src/driver/usb/usb-core/urb.c new file mode 100644 index 0000000..4380892 --- /dev/null +++ b/src/driver/usb/usb-core/urb.c @@ -0,0 +1,28 @@ +#include "driver/usb/usb.h" +#include +#include +#include + +LIST_HEAD(urb_lh); + +void usb_softirq_handler(void) { + UsbRequestBlock *urb, *next; + list_for_each_owner_safe (urb, next, &urb_lh, list) { + list_del(&urb->list); + if (urb->complete != NULL) { urb->complete(urb); } + } +} + +UsbRequestBlock *usb_create_urb( + UsbEndpoint *ep, void *context, uint8_t *buffer, uint32_t len, + void (*complete)(struct UsbRequestBlock *urb)) { + UsbRequestBlock *urb = kmalloc(sizeof(UsbRequestBlock)); + urb->ep = ep; + urb->context = context; + urb->buffer = buffer; + urb->len = len; + urb->actual_len = 0; + urb->status = USB_STATUS_ACK; + urb->complete = complete; + return urb; +} diff --git a/src/driver/usb/usb-core/usb.c b/src/driver/usb/usb-core/usb.c index aa79404..9998093 100644 --- a/src/driver/usb/usb-core/usb.c +++ b/src/driver/usb/usb-core/usb.c @@ -1,4 +1,3 @@ -#include "kernel/bus_driver.h" #include "kernel/device.h" #include "kernel/list.h" #include "objects/object.h" @@ -30,6 +29,7 @@ UsbDevice *usb_create_device( usb_device->address = address; usb_device->state = USB_STATE_UNINITED; usb_device->device = device; + usb_device->hcd = hcd; return usb_device; } @@ -38,10 +38,11 @@ int usb_destroy_device(UsbDevice *device) { return kfree(device); } -UsbRequest *usb_create_request( +UsbControlRequest *usb_create_request( uint8_t direction, uint8_t type, uint8_t recipient, uint8_t request_id, uint8_t value_hi, uint8_t value_lo, uint16_t index, uint16_t length) { - UsbRequest *request = (UsbRequest *)kmalloc(sizeof(UsbRequest)); + UsbControlRequest *request = + (UsbControlRequest *)kmalloc(sizeof(UsbControlRequest)); request->bmRequestType = direction << 7 | type << 5 | recipient; request->bRequest = request_id; request->wValue = HOST2LE_WORD(value_hi << 8 | value_lo); @@ -50,22 +51,18 @@ UsbRequest *usb_create_request( return request; } -UsbEndpoint *usb_create_endpoint( - UsbHcd *hcd, uint8_t endpoint, UsbEpTransferType transfer_type, - UsbEpDirection direction, uint16_t max_packet_size) { - UsbEndpoint *ep = (UsbEndpoint *)kmalloc(sizeof(UsbEndpoint)); - ep->endpoint = endpoint; - ep->transfer_type = transfer_type; - ep->direction = direction; - ep->max_packet_size = max_packet_size; +void usb_init_endpoint( + UsbDevice *usb_device, UsbEndpoint *ep, + struct UsbEndpointDescriptor *desc) { + ep->desc = desc; - ep->sched = hcd->ops->create_sched(); - return ep; + ep->pipe = usb_device->hcd->ops->create_pipeline(usb_device, ep); } -int usb_init_device(UsbHcd *hcd, UsbDevice *usb_device) { - UsbEndpoint *ep0 = - usb_create_endpoint(hcd, 0, USB_EP_CONTROL, USB_EP_OUT, 64); +int usb_init_device( + UsbHcd *hcd, UsbEndpoint *ep0, struct UsbEndpointDescriptor *ep_desc, + UsbDevice *usb_device) { + usb_init_endpoint(usb_device, ep0, ep_desc); usb_device->ep0 = ep0; struct UsbDeviceDescriptor *desc = @@ -87,6 +84,8 @@ int usb_init_device(UsbHcd *hcd, UsbDevice *usb_device) { register_usb_device( hcd->device->device_driver, usb_device->device, usb_device, &attr); - if (desc->bDeviceClass == USB_CLASS_HUB) { usb_init_hub(hcd, usb_device); } + if (desc->bDeviceClass == USB_CLASS_HUB) { + usb_init_hub(hcd, ep0, usb_device); + } return 0; } \ No newline at end of file diff --git a/src/driver/usb/usb_dm.c b/src/driver/usb/usb_dm.c index e1ca9b0..8066a47 100644 --- a/src/driver/usb/usb_dm.c +++ b/src/driver/usb/usb_dm.c @@ -3,21 +3,33 @@ #include "objects/transfer.h" #include "string.h" #include +#include #include #include +#include #include #include #include #include #include +#include #include #include +#include #include +#include +list_t usb_driver_lh[USB_INTERFACE_TYPE_MAX]; + +void usb_dm_probe(DeviceManager *dm); DriverResult usb_dm_load(DeviceManager *manager); // DriverResult usb_dm_unload(DeviceManager *manager); UsbDeviceManager usb_dm_ext; +DynamicDeviceEvents usb_dm_events = { + .probe = usb_dm_probe, + .remove = NULL, +}; DeviceManagerOps usb_dm_ops = { .dm_load = usb_dm_load, .dm_unload = NULL, @@ -33,14 +45,41 @@ DeviceManager usb_dm = { DriverResult usb_dm_load(DeviceManager *manager) { spinlock_init(&usb_dm_ext.hcd_count_lock); usb_dm_ext.hcd_count = 0; + for (int i = 0; i < USB_INTERFACE_TYPE_MAX; i++) { + list_init(&usb_driver_lh[i]); + } + register_dynamic_device_manager(&usb_dm_events, manager); + softirq_register_handler(SOFTIRQ_USB, usb_softirq_handler); return DRIVER_RESULT_OK; } +void usb_dm_probe(DeviceManager *dm) { + UsbDriver *usb_driver; + Device *device; + UsbInterface *interface; + list_for_each_owner (device, &dm->device_lh, dm_list) { + UsbDevice *usb_device = (UsbDevice *)device->dm_ext; + if (usb_device->state == USB_STATE_INITED) { + list_for_each_owner (interface, &usb_device->interface_lh, list) { + if (interface->usb_driver != NULL) { continue; } + uint8_t interface_type = + usb_interface_map[interface->desc->bInterfaceClass]; + list_for_each_owner ( + usb_driver, &usb_driver_lh[interface_type], list) { + if (usb_driver->probe != NULL) { + usb_driver->probe(usb_device, interface); + } + } + } + } + } +} + DriverResult register_usb_device( DeviceDriver *driver, Device *device, UsbDevice *usb_device, ObjectAttr *attr) { device->dm_ext = usb_device; - usb_device->state = USB_STATE_UNINITED; + usb_device->state = USB_STATE_INITED; usb_device->device = device; usb_device->device->ops = &usb_device_ops; list_add_tail(&device->dm_list, &usb_dm.device_lh); diff --git a/src/driver/usb/usb_driver.c b/src/driver/usb/usb_driver.c new file mode 100644 index 0000000..c1463d7 --- /dev/null +++ b/src/driver/usb/usb_driver.c @@ -0,0 +1,9 @@ +#include +#include +#include + +DriverResult register_usb_driver(UsbDriver *usb_driver) { + list_add_tail( + &usb_driver->list, &usb_driver_lh[usb_driver->interface_type]); + return DRIVER_RESULT_OK; +} \ No newline at end of file diff --git a/src/drivers/Makefile b/src/drivers/Makefile index 8de20a2..1460fd8 100644 --- a/src/drivers/Makefile +++ b/src/drivers/Makefile @@ -1 +1,2 @@ -SRC += bus/ \ No newline at end of file +SRC += bus/ +SRC += usb/ \ No newline at end of file diff --git a/src/include/driver/usb/descriptors.h b/src/include/driver/usb/descriptors.h index 0cb8cc0..ef16379 100644 --- a/src/include/driver/usb/descriptors.h +++ b/src/include/driver/usb/descriptors.h @@ -16,6 +16,10 @@ #define USB_DESC_TYPE_CONFIG_SIZE 9 #define USB_DESC_TYPE_HUB_SIZE 9 +#define USB_DESCRIPTOR_TYPE_STANDARD 0 +#define USB_DESCRIPTOR_TYPE_CLASS 1 +#define USB_DESCRIPTOR_TYPE_VENDOR 2 + #define USB_DESC_TYPE_HUB 0x29 struct UsbDeviceDescriptor { @@ -84,4 +88,59 @@ struct UsbHubDescriptor { uint8_t PortPwrCtrlMask; } __attribute__((packed)); +// USB HID Descriptors + +typedef enum { + USB_HID_LAYOUT_NOT_SUPPORTED = 0x00, + USB_HID_LAYOUT_ARABIC = 0x01, + USB_HID_LAYOUT_BELGIAN = 0x02, + USB_HID_LAYOUT_CANADIAN_BILINGUAL = 0x03, + USB_HID_LAYOUT_CANADIAN_FRENCH = 0x04, + USB_HID_LAYOUT_CZECH = 0x05, + USB_HID_LAYOUT_DANISH = 0x06, + USB_HID_LAYOUT_FINNISH = 0x07, + USB_HID_LAYOUT_FRENCH = 0x08, + USB_HID_LAYOUT_GERMAN = 0x09, + USB_HID_LAYOUT_GREEK = 0x0A, + USB_HID_LAYOUT_HEBREW = 0x0B, + USB_HID_LAYOUT_HUNGARIAN = 0x0C, + USB_HID_LAYOUT_INTERNATIONAL = 0x0D, + USB_HID_LAYOUT_ITALIAN = 0x0E, + USB_HID_LAYOUT_JAPANESE = 0x0F, + USB_HID_LAYOUT_KOREAN = 0x10, + USB_HID_LAYOUT_LATIN_AMERICAN = 0x11, + USB_HID_LAYOUT_NETHERLANDS_DUTCH = 0x12, + USB_HID_LAYOUT_NORWEGIAN = 0x13, + USB_HID_LAYOUT_PERSIAN_FARSI = 0x14, + USB_HID_LAYOUT_POLISH = 0x15, + USB_HID_LAYOUT_PORTUGUESE = 0x16, + USB_HID_LAYOUT_RUSSIAN = 0x17, + USB_HID_LAYOUT_SLOVAK = 0x18, + USB_HID_LAYOUT_SPANISH = 0x19, + USB_HID_LAYOUT_SWEDISH = 0x1A, + USB_HID_LAYOUT_SWISS_FRENCH = 0x1B, + USB_HID_LAYOUT_SWISS_GERMAN = 0x1C, + USB_HID_LAYOUT_SWITZERLAND = 0x1D, + USB_HID_LAYOUT_CHINESE_BOPOMOFO = 0x1E, + USB_HID_LAYOUT_TURKISH_Q = 0x1F, + USB_HID_LAYOUT_TURKISH_F = 0x20, + USB_HID_LAYOUT_ENGLISH_UK = 0x21, + USB_HID_LAYOUT_ENGLISH_US = 0x22, + USB_HID_LAYOUT_YUGOSLAVIA = 0x23, + USB_HID_LAYOUT_TURKISH_Q2 = 0x24, + USB_HID_LAYOUT_MAX = 0x25, +} UsbHidKeyboardLayout; + +struct UsbHidDescriptorHeader { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; + uint8_t bCountryCode; + uint8_t bNumDescriptors; + struct { + uint8_t bReportDescriptorType; + uint16_t wReportDescriptorLength; + } reports[0]; +} __attribute__((packed)); + #endif \ No newline at end of file diff --git a/src/include/driver/usb/func.h b/src/include/driver/usb/func.h index 2f80b24..463bf05 100644 --- a/src/include/driver/usb/func.h +++ b/src/include/driver/usb/func.h @@ -5,8 +5,55 @@ #define REQ_GET_PORT_STATUS_SIZE 4 -struct UsbDeviceDescriptor *usb_get_device_descriptor( - UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep); +void *usb_get_descriptor( + UsbHcd *hcd, struct UsbDevice *device, uint8_t type, uint8_t recipient, + uint8_t index, UsbEndpoint *ep, uint8_t value_hi, uint8_t value_lo, + uint16_t desc_size); +#define usb_get_standard_descriptor( \ + hcd, device, recipient, index, ep, value_hi, value_lo, desc_size) \ + usb_get_descriptor( \ + hcd, device, USB_REQ_TYPE_STANDARD, recipient, index, ep, value_hi, \ + value_lo, desc_size) +#define usb_get_class_descriptor( \ + hcd, device, recipient, index, ep, value_hi, value_lo, desc_size) \ + usb_get_descriptor( \ + hcd, device, USB_REQ_TYPE_CLASS, recipient, index, ep, value_hi, \ + value_lo, desc_size) +#define usb_get_vendor_descriptor( \ + hcd, device, recipient, index, ep, value_hi, value_lo, desc_size) \ + usb_get_descriptor( \ + hcd, device, USB_REQ_TYPE_VENDOR, recipient, index, ep, value_hi, \ + value_lo, desc_size) + +#define usb_get_device_descriptor(hcd, device, ep) \ + usb_get_standard_descriptor( \ + hcd, device, USB_REQ_RECIPIENT_DEVICE, 0, ep, USB_DESC_TYPE_DEVICE, 0, \ + sizeof(struct UsbDeviceDescriptor)) +#define usb_get_interface_descriptor(hcd, device, ep) \ + usb_get_standard_descriptor( \ + hcd, device, USB_REQ_RECIPIENT_DEVICE, 0, ep, USB_DESC_TYPE_INTERFACE, \ + 0, sizeof(struct UsbInterfaceDescriptor)) + +void *usb_set_descriptor( + UsbHcd *hcd, struct UsbDevice *device, uint8_t type, uint8_t recipient, + uint8_t index, UsbEndpoint *ep, uint8_t value_hi, uint8_t value_lo, + uint16_t desc_size); +#define usb_set_standard_descriptor( \ + hcd, device, recipient, index, ep, value_hi, value_lo, desc_size) \ + usb_set_descriptor( \ + hcd, device, USB_REQ_TYPE_STANDARD, recipient, index, ep, value_hi, \ + value_lo, desc_size) +#define usb_set_class_descriptor( \ + hcd, device, recipient, index, ep, value_hi, value_lo, desc_size) \ + usb_set_descriptor( \ + hcd, device, USB_REQ_TYPE_CLASS, recipient, index, ep, value_hi, \ + value_lo, desc_size) +#define usb_set_vendor_descriptor( \ + hcd, device, recipient, index, ep, value_hi, value_lo, desc_size) \ + usb_set_descriptor( \ + hcd, device, USB_REQ_TYPE_VENDOR, recipient, index, ep, value_hi, \ + value_lo, desc_size) + struct UsbConfigDescriptor *usb_get_config_descriptor( UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep); diff --git a/src/include/driver/usb/hub.h b/src/include/driver/usb/hub.h index 18ae937..9142a2e 100644 --- a/src/include/driver/usb/hub.h +++ b/src/include/driver/usb/hub.h @@ -23,6 +23,6 @@ #define HUB_FEAT_PORT_TEST 21 #define HUB_FEAT_PORT_INDICATOR 22 -void usb_init_hub(UsbHcd *hcd, struct UsbDevice *device); +void usb_init_hub(UsbHcd *hcd, UsbEndpoint *ep0, struct UsbDevice *usb_device); #endif \ No newline at end of file diff --git a/src/include/driver/usb/urb.h b/src/include/driver/usb/urb.h new file mode 100644 index 0000000..9528fb9 --- /dev/null +++ b/src/include/driver/usb/urb.h @@ -0,0 +1,26 @@ +#ifndef _USB_URB_H +#define _USB_URB_H + +#include +#include + +typedef struct UsbRequestBlock { + list_t list; + UsbEndpoint *ep; + void *context; + uint8_t *buffer; + uint32_t len; + uint32_t actual_len; + UsbStatus status; + + void (*complete)(struct UsbRequestBlock *urb); +} UsbRequestBlock; + +extern list_t urb_lh; + +void usb_softirq_handler(void); +UsbRequestBlock *usb_create_urb( + UsbEndpoint *ep, void *context, uint8_t *buffer, uint32_t len, + void (*complete)(struct UsbRequestBlock *urb)); + +#endif \ No newline at end of file diff --git a/src/include/driver/usb/usb.h b/src/include/driver/usb/usb.h index d8f0169..0c454ba 100644 --- a/src/include/driver/usb/usb.h +++ b/src/include/driver/usb/usb.h @@ -1,6 +1,7 @@ #ifndef _USB_H #define _USB_H +#include "driver/usb/descriptors.h" #include #include #include @@ -65,6 +66,35 @@ .wLength = HOST2LE_WORD(length), \ } +typedef enum UsbInterfaceType { + USB_INTERFACE_TYPE_DEVICE = 0, + USB_INTERFACE_TYPE_AUDIO, + USB_INTERFACE_TYPE_COMM, + USB_INTERFACE_TYPE_HID, + USB_INTERFACE_TYPE_PHYSICAL, + USB_INTERFACE_TYPE_IMAGE, + USB_INTERFACE_TYPE_PRINTER, + USB_INTERFACE_TYPE_MASS_STORAGE, + USB_INTERFACE_TYPE_HUB, + USB_INTERFACE_TYPE_CDC_DATA, + USB_INTERFACE_TYPE_SMART_CARD, + USB_INTERFACE_TYPE_CONTENT_SECURITY, + USB_INTERFACE_TYPE_VIDEO, + USB_INTERFACE_TYPE_PERSONAL_HEALTHCARE, + USB_INTERFACE_TYPE_AUDIO_VIDEO, + USB_INTERFACE_TYPE_BILLBOARD, + USB_INTERFACE_TYPE_TYPE_C_BRIDGE, + USB_INTERFACE_TYPE_BULK_DISPLAY_PROTOCOL, + USB_INTERFACE_TYPE_MTCP, + USB_INTERFACE_TYPE_I3C, + USB_INTERFACE_TYPE_DIAGNOSTIC, + USB_INTERFACE_TYPE_WIRELESS_CONTROLLER, + USB_INTERFACE_TYPE_MISCELLANEOUS, + USB_INTERFACE_TYPE_APPLICATION_SPECIFIC, + USB_INTERFACE_TYPE_VENDOR_SPECIFIC, + USB_INTERFACE_TYPE_MAX, +} UsbInterfaceType; + typedef enum UsbDeviceSpeed { USB_SPEED_LOW, USB_SPEED_FULL, @@ -78,7 +108,7 @@ typedef enum { } UsbDeviceState; typedef enum { - USB_EP_CONTROL, + USB_EP_CONTROL = 0, USB_EP_ISOCHRONOUS, USB_EP_BULK, USB_EP_INTERRUPT, @@ -92,21 +122,21 @@ typedef enum { typedef struct UsbEndpoint { list_t list; - uint8_t endpoint; - UsbEpTransferType transfer_type; - UsbEpDirection direction; - uint16_t max_packet_size; + struct UsbEndpointDescriptor *desc; + + void *pipe; - void *sched; + uint8_t data_toggle; } UsbEndpoint; typedef struct UsbInterface { list_t list; - uint8_t interface; - uint8_t class; - uint8_t subclass; - uint8_t protocol; + struct UsbDriver *usb_driver; + + struct UsbInterfaceDescriptor *desc; + + UsbEndpoint *endpoints[0]; } UsbInterface; typedef enum UsbStatus { @@ -126,13 +156,41 @@ typedef enum UsbSetupStatus { USB_SETUP_DATABUFFER_ERR, } UsbSetupStatus; -typedef struct UsbRequest { +typedef struct UsbControlRequest { uint8_t bmRequestType; uint8_t bRequest; uint16_t wValue; uint16_t wIndex; uint16_t wLength; -} __attribute__((packed)) UsbRequest; +} __attribute__((packed)) UsbControlRequest; + +static const uint8_t usb_interface_map[] = { + [USB_INTERFACE_TYPE_DEVICE] = 0x00, + [USB_INTERFACE_TYPE_AUDIO] = 0x01, + [USB_INTERFACE_TYPE_COMM] = 0x02, + [USB_INTERFACE_TYPE_HID] = 0x03, + [USB_INTERFACE_TYPE_PHYSICAL] = 0x04, + [USB_INTERFACE_TYPE_IMAGE] = 0x05, + [USB_INTERFACE_TYPE_PRINTER] = 0x06, + [USB_INTERFACE_TYPE_MASS_STORAGE] = 0x07, + [USB_INTERFACE_TYPE_HUB] = 0x08, + [USB_INTERFACE_TYPE_CDC_DATA] = 0x09, + [USB_INTERFACE_TYPE_SMART_CARD] = 0x0a, + [USB_INTERFACE_TYPE_CONTENT_SECURITY] = 0x0b, + [USB_INTERFACE_TYPE_VIDEO] = 0x0c, + [USB_INTERFACE_TYPE_PERSONAL_HEALTHCARE] = 0x0d, + [USB_INTERFACE_TYPE_AUDIO_VIDEO] = 0x0e, + [USB_INTERFACE_TYPE_BILLBOARD] = 0x0f, + [USB_INTERFACE_TYPE_TYPE_C_BRIDGE] = 0x10, + [USB_INTERFACE_TYPE_BULK_DISPLAY_PROTOCOL] = 0x11, + [USB_INTERFACE_TYPE_MTCP] = 0x12, + [USB_INTERFACE_TYPE_I3C] = 0x13, + [USB_INTERFACE_TYPE_DIAGNOSTIC] = 0x14, + [USB_INTERFACE_TYPE_WIRELESS_CONTROLLER] = 0x3c, + [USB_INTERFACE_TYPE_MISCELLANEOUS] = 0xef, + [USB_INTERFACE_TYPE_APPLICATION_SPECIFIC] = 0xfe, + [USB_INTERFACE_TYPE_VENDOR_SPECIFIC] = 0xff, +}; extern UsbEndpoint usb_ep0; @@ -140,13 +198,15 @@ struct UsbDevice *usb_create_device( UsbHcd *hcd, UsbDeviceSpeed speed, uint8_t address); int usb_destroy_device(struct UsbDevice *device); -UsbRequest *usb_create_request( +UsbControlRequest *usb_create_request( uint8_t direction, uint8_t type, uint8_t recipient, uint8_t request_id, uint8_t value_hi, uint8_t value_lo, uint16_t index, uint16_t length); -UsbEndpoint *usb_create_endpoint( - UsbHcd *hcd, uint8_t endpoint, UsbEpTransferType transfer_type, - UsbEpDirection direction, uint16_t max_packet_size); +void usb_init_endpoint( + struct UsbDevice *usb_device, UsbEndpoint *ep, + struct UsbEndpointDescriptor *desc); -int usb_init_device(UsbHcd *hcd, struct UsbDevice *device); +int usb_init_device( + UsbHcd *hcd, UsbEndpoint *ep0, struct UsbEndpointDescriptor *ep_desc, + struct UsbDevice *usb_device); #endif \ No newline at end of file diff --git a/src/include/driver/usb/usb_dm.h b/src/include/driver/usb/usb_dm.h index 318b9be..7853959 100644 --- a/src/include/driver/usb/usb_dm.h +++ b/src/include/driver/usb/usb_dm.h @@ -15,6 +15,7 @@ typedef struct UsbDevice { list_t interface_lh; UsbDeviceState state; + UsbHcd *hcd; Device *device; struct UsbDeviceDescriptor *desc; diff --git a/src/include/driver/usb/usb_driver.h b/src/include/driver/usb/usb_driver.h new file mode 100644 index 0000000..0b2e6bc --- /dev/null +++ b/src/include/driver/usb/usb_driver.h @@ -0,0 +1,23 @@ +#ifndef _USB_DEVICE_DRIVER_H +#define _USB_DEVICE_DRIVER_H + +#include +#include +#include + +typedef struct UsbDriver { + list_t list; + + Driver *driver; + UsbInterfaceType interface_type; + + DriverResult (*probe)( + struct UsbDevice *device, struct UsbInterface *interface); + DriverResult (*remove)(struct UsbDevice *device); +} UsbDriver; + +extern list_t usb_driver_lh[USB_INTERFACE_TYPE_MAX]; + +DriverResult register_usb_driver(UsbDriver *usb_driver); + +#endif \ No newline at end of file diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index 0d43e28..6826c78 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -26,8 +26,7 @@ typedef enum { DEVICE_TYPE_TIMER, // 定时器设备 DEVICE_TYPE_VIDEO, DEVICE_TYPE_STORAGE, - DEVICE_TYPE_MOUSE, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_INPUT, DEVICE_TYPE_SOUND, DEVICE_TYPE_BUS_CONTROLLER, DEVICE_TYPE_ETHERNET, diff --git a/src/include/kernel/dynamic_device_manager.h b/src/include/kernel/dynamic_device_manager.h index 8c4c03a..2fa4251 100644 --- a/src/include/kernel/dynamic_device_manager.h +++ b/src/include/kernel/dynamic_device_manager.h @@ -25,6 +25,8 @@ typedef struct DynamicDeviceManager { DynamicDeviceEvents *events; } DynamicDeviceManager; +extern list_t new_device_lh; + DriverResult register_dynamic_device_manager( DynamicDeviceEvents *events, DeviceManager *device_manager); void dynamic_device_manager(void *arg); diff --git a/src/include/kernel/softirq.h b/src/include/kernel/softirq.h index 952964a..cde7f65 100644 --- a/src/include/kernel/softirq.h +++ b/src/include/kernel/softirq.h @@ -8,6 +8,7 @@ typedef enum SoftirqType { SOFTIRQ_TIMER, + SOFTIRQ_USB, SOFTIRQ_NETWORK, SOFTIRQ_BLOCK, SOFTIRQ_SCHEDULER, diff --git a/src/kernel/driver/bus_driver.c b/src/kernel/driver/bus_driver.c index 4c4fcb0..345cd84 100644 --- a/src/kernel/driver/bus_driver.c +++ b/src/kernel/driver/bus_driver.c @@ -155,8 +155,9 @@ DriverResult bus_register_device(Device *device, Bus *bus, ObjectAttr *attr) { list_add_tail(&device->bus_list, &bus->device_lh); BUS_OPS_CALL(bus, register_device_hook, device); + // TODO: 名字冲突 string_t name; - string_new_with_number(&name, "", 0, bus->last_device_num++); + string_new_with_number(&name, "_", 1, bus->last_device_num++); attr->type = OBJECT_TYPE_DEVICE; device->object = create_object(bus->object, name, *attr); device->object->value.device = device; From a94cd1564fc19adf4f2e9a762fa1df1f4fac62d4 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 22 Sep 2025 14:12:00 +0800 Subject: [PATCH 130/158] =?UTF-8?q?[WIP]hid&keyboard&mouse:=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20=E5=9F=BA=E7=A1=80HID=E9=94=AE=E9=BC=A0=E6=8A=A5?= =?UTF-8?q?=E5=91=8A=E8=AF=BB=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/drivers/usb/Makefile | 1 + src/drivers/usb/hid/Makefile | 3 + src/drivers/usb/hid/hid.c | 75 +++++++++++++++++ src/drivers/usb/hid/keyboard.c | 129 +++++++++++++++++++++++++++++ src/drivers/usb/hid/mouse.c | 124 +++++++++++++++++++++++++++ src/include/drivers/usb/hid.h | 23 +++++ src/include/drivers/usb/keyboard.h | 32 +++++++ src/include/drivers/usb/mouse.h | 32 +++++++ 8 files changed, 419 insertions(+) create mode 100644 src/drivers/usb/Makefile create mode 100644 src/drivers/usb/hid/Makefile create mode 100644 src/drivers/usb/hid/hid.c create mode 100644 src/drivers/usb/hid/keyboard.c create mode 100644 src/drivers/usb/hid/mouse.c create mode 100644 src/include/drivers/usb/hid.h create mode 100644 src/include/drivers/usb/keyboard.h create mode 100644 src/include/drivers/usb/mouse.h diff --git a/src/drivers/usb/Makefile b/src/drivers/usb/Makefile new file mode 100644 index 0000000..c1fbaa7 --- /dev/null +++ b/src/drivers/usb/Makefile @@ -0,0 +1 @@ +SRC += hid/ \ No newline at end of file diff --git a/src/drivers/usb/hid/Makefile b/src/drivers/usb/hid/Makefile new file mode 100644 index 0000000..49bfe7d --- /dev/null +++ b/src/drivers/usb/hid/Makefile @@ -0,0 +1,3 @@ +SRC += hid.c +SRC += mouse.c +SRC += keyboard.c \ No newline at end of file diff --git a/src/drivers/usb/hid/hid.c b/src/drivers/usb/hid/hid.c new file mode 100644 index 0000000..41b4705 --- /dev/null +++ b/src/drivers/usb/hid/hid.c @@ -0,0 +1,75 @@ +#include "drivers/usb/hid.h" +#include "driver/usb/usb.h" +#include "driver/usb/usb_driver.h" +#include "string.h" +#include +#include +#include +#include +#include + +DriverResult usb_hid_probe(UsbDevice *device, UsbInterface *interface); + +DriverDependency usb_hid_dependencies[] = { + { + .in_type = DRIVER_DEPENDENCY_TYPE_BUS, + .dependency_in_bus = {BUS_TYPE_USB, 0}, + .out_bus = NULL, + }, +}; + +Driver usb_hid_driver = { + .short_name = STRING_INIT("HID"), + .dependency_count = sizeof(usb_hid_dependencies) / sizeof(DriverDependency), + .dependencies = usb_hid_dependencies, + .init = NULL, +}; +UsbDriver usb_hid_usb_driver = { + .driver = &usb_hid_driver, + .interface_type = USB_INTERFACE_TYPE_HID, + .probe = usb_hid_probe, + .remove = NULL, +}; + +DriverResult usb_hid_probe(UsbDevice *usb_device, UsbInterface *interface) { + switch (interface->desc->bInterfaceSubClass) { + case USB_HID_SUBCLASS_NO: + // printk("HID Interface Found\n"); + return DRIVER_RESULT_UNSUPPORT_DEVICE; + case USB_HID_SUBCLASS_BOOT: + // printk("HID Boot Interface Found\n"); + break; + } + + switch (interface->desc->bInterfaceProtocol) { + case USB_HID_PROTOCOL_NONE: + printk("HID Protocol: None\n"); + break; + case USB_HID_PROTOCOL_KEYBOARD: + // printk("HID Protocol: Keyboard\n"); + if (interface->desc->bInterfaceSubClass == USB_HID_SUBCLASS_BOOT) { + usb_hid_keyboard_probe(usb_device, interface); + } + break; + case USB_HID_PROTOCOL_MOUSE: + // printk("HID Protocol: Mouse\n"); + if (interface->desc->bInterfaceSubClass == USB_HID_SUBCLASS_BOOT) { + // 先用基础功能,TODO: Report Descriptor + usb_hid_mouse_probe(usb_device, interface); + } + break; + default: + printk( + "HID Protocol: Unknown (%d)\n", + interface->desc->bInterfaceProtocol); + break; + } + return DRIVER_RESULT_OK; +} + +static __init void usb_hid_driver_entry(void) { + register_driver(&usb_hid_driver); + register_usb_driver(&usb_hid_usb_driver); +} + +driver_initcall(usb_hid_driver_entry); diff --git a/src/drivers/usb/hid/keyboard.c b/src/drivers/usb/hid/keyboard.c new file mode 100644 index 0000000..cb526a3 --- /dev/null +++ b/src/drivers/usb/hid/keyboard.c @@ -0,0 +1,129 @@ +#include "driver/usb/descriptors.h" +#include "driver/usb/usb_dm.h" +#include "kernel/dynamic_device_manager.h" +#include "kernel/list.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DeviceDriver usb_hid_keyboard_device_driver; + +DriverResult usb_hid_keyboard_init(Device *device); +DriverResult usb_hid_keyboard_start(Device *device); + +DeviceDriverOps usb_hid_keyboard_device_driver_ops = { + .device_driver_init = NULL, + .device_driver_uninit = NULL, +}; +DeviceOps usb_hid_keyboard_device_ops = { + .init = usb_hid_keyboard_init, + .start = usb_hid_keyboard_start, + .destroy = NULL, + .status = NULL, + .stop = NULL, +}; + +DeviceDriver usb_hid_keyboard_device_driver = { + .name = STRING_INIT("USB HID Keyboard Driver"), + .priority = DRIVER_PRIORITY_GENERAL, + .type = DEVICE_TYPE_USB, + .private_data_size = 0, + .ops = &usb_hid_keyboard_device_driver_ops, +}; + +void usb_hid_keyboard_handler(UsbRequestBlock *urb) { + UsbHidKeyboardReport *report = (UsbHidKeyboardReport *)urb->buffer; + UsbHidKeyboard *keyboard = urb->context; + UsbDevice *usb_device = keyboard->usb_device; + if (urb->status == USB_STATUS_ACK) { + printk( + "Keyboard Report: Keycode: M:0x%02x 0x%02x 0x%02x 0x%02x 0x%02x " + "0x%02x " + "0x%02x\n", + report->modifier_keys, report->keycodes[0], report->keycodes[1], + report->keycodes[2], report->keycodes[3], report->keycodes[4], + report->keycodes[5]); + urb->ep->data_toggle ^= 1; + usb_device->hcd->ops->interrupt_transfer(usb_device->hcd, urb->ep); + } else { + printk("Keyboard URB Error: %d\n", urb->status); + } +} + +DriverResult usb_hid_keyboard_init(Device *device) { + UsbHidKeyboard *keyboard = device->private_data; + struct UsbInterfaceDescriptor *interface = keyboard->interface->desc; + + UsbEndpoint *ep; + for (int i = 0; i < interface->bNumEndpoints; i++) { + ep = keyboard->interface->endpoints[i]; + if ((ep->desc->bmAttributes & 0x03) == USB_EP_INTERRUPT && + (ep->desc->bEndpointAddress >> 7) == USB_EP_IN) { + // 找到中断输入端点 + printk( + "Keyboard Interrupt IN Endpoint Found: 0x%02x\n", + ep->desc->bEndpointAddress); + + int size = ep->desc->wMaxPacketSize & 0x7ff; + keyboard->buffer = kmalloc(size); + keyboard->urb = usb_create_urb( + ep, keyboard, keyboard->buffer, size, usb_hid_keyboard_handler); + break; + } + } + return DRIVER_RESULT_OK; +} + +DriverResult usb_hid_keyboard_start(Device *device) { + UsbHidKeyboard *keyboard = device->private_data; + UsbEndpoint *ep = keyboard->urb->ep; + ep->data_toggle = 1; + keyboard->usb_device->hcd->ops->add_interrupt_transfer( + keyboard->usb_device->hcd, keyboard->usb_device, ep, keyboard->urb); + // UsbControlRequest req = USB_BUILD_REQUEST( + // USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_INTERFACE, + // 0x0b, 0x00, 0x00, keyboard->interface->desc->bInterfaceNumber, 0); + // uint8_t data = 0; + // keyboard->usb_device->hcd->ops->ctrl_transfer_out( + // keyboard->usb_device->hcd, keyboard->usb_device, &data, 0, &req); + return DRIVER_RESULT_OK; +} + +DriverResult usb_hid_keyboard_probe( + UsbDevice *usb_device, UsbInterface *interface) { + Device *device = kmalloc(sizeof(Device)); + device->private_data_size = sizeof(UsbHidKeyboard); + string_new(&device->name, "USB HID Keyboard", 14); + device->device_driver = &usb_hid_keyboard_device_driver; + device->ops = &usb_hid_keyboard_device_ops; + device->state = DEVICE_STATE_UNREGISTERED; + interface->usb_driver = &usb_hid_usb_driver; + + ObjectAttr attr = device_object_attr; + register_device( + &usb_hid_keyboard_device_driver, &device->name, usb_device->device->bus, + device, &attr); + + UsbHidKeyboard *keyboard = device->private_data; + keyboard->device = device; + keyboard->usb_device = usb_device; + keyboard->interface = interface; + + list_add_tail(&device->new_device_list, &new_device_lh); + + return DRIVER_RESULT_OK; +} + +static __init void usb_hid_keyboard_initcall() { + register_device_driver(&usb_hid_driver, &usb_hid_keyboard_device_driver); +} + +driver_initcall(usb_hid_keyboard_initcall); diff --git a/src/drivers/usb/hid/mouse.c b/src/drivers/usb/hid/mouse.c new file mode 100644 index 0000000..008776a --- /dev/null +++ b/src/drivers/usb/hid/mouse.c @@ -0,0 +1,124 @@ +#include "driver/usb/descriptors.h" +#include "driver/usb/usb_dm.h" +#include "kernel/dynamic_device_manager.h" +#include "kernel/list.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DeviceDriver usb_hid_mouse_device_driver; + +DriverResult usb_hid_mouse_init(Device *device); +DriverResult usb_hid_mouse_start(Device *device); + +DeviceDriverOps usb_hid_mouse_device_driver_ops = { + .device_driver_init = NULL, + .device_driver_uninit = NULL, +}; +DeviceOps usb_hid_mouse_device_ops = { + .init = usb_hid_mouse_init, + .start = usb_hid_mouse_start, + .destroy = NULL, + .status = NULL, + .stop = NULL, +}; + +DeviceDriver usb_hid_mouse_device_driver = { + .name = STRING_INIT("USB HID Mouse Driver"), + .priority = DRIVER_PRIORITY_GENERAL, + .type = DEVICE_TYPE_USB, + .private_data_size = 0, + .ops = &usb_hid_mouse_device_driver_ops, +}; + +void usb_hid_mouse_handler(UsbRequestBlock *urb) { + UsbHidMouseReport *report = (UsbHidMouseReport *)urb->buffer; + UsbHidMouse *mouse = urb->context; + UsbDevice *usb_device = mouse->usb_device; + if (urb->status == USB_STATUS_ACK) { + printk( + "Mouse Report: Buttons: 0x%02x, X: %d, Y: %d\n", report->buttons, + report->x, report->y); + urb->ep->data_toggle ^= 1; + usb_device->hcd->ops->interrupt_transfer(usb_device->hcd, urb->ep); + } else { + printk("Mouse URB Error: %d\n", urb->status); + } +} + +DriverResult usb_hid_mouse_init(Device *device) { + UsbHidMouse *mouse = device->private_data; + struct UsbInterfaceDescriptor *interface = mouse->interface->desc; + + UsbEndpoint *ep; + for (int i = 0; i < interface->bNumEndpoints; i++) { + ep = mouse->interface->endpoints[i]; + if ((ep->desc->bmAttributes & 0x03) == USB_EP_INTERRUPT && + (ep->desc->bEndpointAddress >> 7) == USB_EP_IN) { + // 找到中断输入端点 + printk( + "Mouse Interrupt IN Endpoint Found: 0x%02x\n", + ep->desc->bEndpointAddress); + + int size = ep->desc->wMaxPacketSize & 0x7ff; + mouse->buffer = kmalloc(size); + mouse->urb = usb_create_urb( + ep, mouse, mouse->buffer, size, usb_hid_mouse_handler); + break; + } + } + return DRIVER_RESULT_OK; +} + +DriverResult usb_hid_mouse_start(Device *device) { + UsbHidMouse *mouse = device->private_data; + UsbEndpoint *ep = mouse->urb->ep; + ep->data_toggle = 1; + mouse->usb_device->hcd->ops->add_interrupt_transfer( + mouse->usb_device->hcd, mouse->usb_device, ep, mouse->urb); + // UsbControlRequest req = USB_BUILD_REQUEST( + // USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_INTERFACE, + // 0x0b, 0x00, 0x00, mouse->interface->desc->bInterfaceNumber, 0); + // uint8_t data = 0; + // mouse->usb_device->hcd->ops->ctrl_transfer_out( + // mouse->usb_device->hcd, mouse->usb_device, &data, 0, &req); + return DRIVER_RESULT_OK; +} + +DriverResult usb_hid_mouse_probe( + UsbDevice *usb_device, UsbInterface *interface) { + Device *device = kmalloc(sizeof(Device)); + device->private_data_size = sizeof(UsbHidMouse); + string_new(&device->name, "USB HID Mouse", 14); + device->device_driver = &usb_hid_mouse_device_driver; + device->ops = &usb_hid_mouse_device_ops; + device->state = DEVICE_STATE_UNREGISTERED; + interface->usb_driver = &usb_hid_usb_driver; + + ObjectAttr attr = device_object_attr; + register_device( + &usb_hid_mouse_device_driver, &device->name, usb_device->device->bus, + device, &attr); + + UsbHidMouse *mouse = device->private_data; + mouse->device = device; + mouse->usb_device = usb_device; + mouse->interface = interface; + + list_add_tail(&device->new_device_list, &new_device_lh); + + return DRIVER_RESULT_OK; +} + +static __init void usb_hid_mouse_initcall() { + register_device_driver(&usb_hid_driver, &usb_hid_mouse_device_driver); +} + +driver_initcall(usb_hid_mouse_initcall); diff --git a/src/include/drivers/usb/hid.h b/src/include/drivers/usb/hid.h new file mode 100644 index 0000000..1621bd6 --- /dev/null +++ b/src/include/drivers/usb/hid.h @@ -0,0 +1,23 @@ +#ifndef _USB_HID_H +#define _USB_HID_H + +#include +#include + +extern Driver usb_hid_driver; + +typedef enum { + USB_HID_SUBCLASS_NO = 0x00, + USB_HID_SUBCLASS_BOOT = 0x01, +} UsbHidSubClass; + +typedef enum { + USB_HID_PROTOCOL_NONE = 0x00, + USB_HID_PROTOCOL_KEYBOARD = 0x01, + USB_HID_PROTOCOL_MOUSE = 0x02, +} UsbHidProtocol; + +extern Driver usb_hid_driver; +extern UsbDriver usb_hid_usb_driver; + +#endif \ No newline at end of file diff --git a/src/include/drivers/usb/keyboard.h b/src/include/drivers/usb/keyboard.h new file mode 100644 index 0000000..80e42c3 --- /dev/null +++ b/src/include/drivers/usb/keyboard.h @@ -0,0 +1,32 @@ +#ifndef _USB_HID_KEYBOARD_H +#define _USB_HID_KEYBOARD_H + +#include "driver/usb/usb.h" +#include "driver/usb/usb_dm.h" +#include +#include +#include +#include + +typedef struct { + uint8_t modifier_keys; + uint8_t reserved; + uint8_t keycodes[6]; +} __attribute__((packed)) UsbHidKeyboardReport; + +typedef struct { + Device *device; + UsbDevice *usb_device; + UsbInterface *interface; + UsbRequestBlock *urb; + + uint8_t *buffer; +} UsbHidKeyboard; + +extern DeviceOps usb_hid_keyboard_device_ops; +extern DeviceDriver usb_hid_keyboard_device_driver; + +DriverResult usb_hid_keyboard_probe( + UsbDevice *usb_device, UsbInterface *interface); + +#endif \ No newline at end of file diff --git a/src/include/drivers/usb/mouse.h b/src/include/drivers/usb/mouse.h new file mode 100644 index 0000000..4ea8c25 --- /dev/null +++ b/src/include/drivers/usb/mouse.h @@ -0,0 +1,32 @@ +#ifndef _USB_HID_MOUSE_H +#define _USB_HID_MOUSE_H + +#include "driver/usb/usb.h" +#include "driver/usb/usb_dm.h" +#include +#include +#include +#include + +typedef struct { + uint8_t buttons; + int8_t x; + int8_t y; +} __attribute__((packed)) UsbHidMouseReport; + +typedef struct { + Device *device; + UsbDevice *usb_device; + UsbInterface *interface; + UsbRequestBlock *urb; + + uint8_t *buffer; +} UsbHidMouse; + +extern DeviceOps usb_hid_mouse_device_ops; +extern DeviceDriver usb_hid_mouse_device_driver; + +DriverResult usb_hid_mouse_probe( + UsbDevice *usb_device, UsbInterface *interface); + +#endif \ No newline at end of file From 654df74b9535706a116835471707f8c036fe8334 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 23 Sep 2025 16:32:49 +0800 Subject: [PATCH 131/158] =?UTF-8?q?usb:=20=E6=96=B0=E5=A2=9EUsbHub?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0=E7=BB=93=E6=9E=84=EF=BC=9B=20uhci:=20?= =?UTF-8?q?=E5=B0=86uhci=E6=8A=BD=E8=B1=A1=E4=B8=BAUsb=20Root=20Hub?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/usb/hci/uhci.c | 131 ++++++++++++++++++++++++---- src/driver/usb/usb-core/func.c | 38 +++++--- src/driver/usb/usb-core/hub.c | 38 ++++---- src/driver/usb/usb-core/usb.c | 13 ++- src/include/driver/usb/func.h | 15 ++-- src/include/driver/usb/hub.h | 25 +++++- src/include/driver/usb/usb.h | 3 +- src/include/driver/usb/usb_dm.h | 1 + 8 files changed, 206 insertions(+), 58 deletions(-) diff --git a/src/arch/x86/drivers/usb/hci/uhci.c b/src/arch/x86/drivers/usb/hci/uhci.c index 9cd6042..47ac4ba 100644 --- a/src/arch/x86/drivers/usb/hci/uhci.c +++ b/src/arch/x86/drivers/usb/hci/uhci.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -44,12 +45,20 @@ #define DEV_NAME "UHCI" #define DEV_FULL_NAME "Universal Host Controller Interface(UHCI)" +extern UsbHcdOps uhci_ops; + +uint32_t uhci_get_hub_status(UsbHub *hub); +uint32_t uhci_get_port_status(UsbHub *hub, uint8_t port); +UsbSetupStatus uhci_clear_port_feature( + UsbHub *hub, uint8_t port, uint16_t feature); +UsbSetupStatus uhci_set_port_feature( + UsbHub *hub, uint8_t port, uint16_t feature); void uhci_register(Driver *driver); DriverResult uhci_init(Device *device); DriverResult uhci_start(Device *device); DriverResult uhci_pci_probe(PciDevice *pci_device); - -extern UsbHcdOps uhci_ops; +void uhci_port_reset(Uhci *devext, int port); +void uhci_port_init(UsbHub *hub, UsbHcd *hcd, int port); DeviceDriverOps uhci_device_driver_ops = { .device_driver_init = NULL, @@ -65,6 +74,13 @@ DeviceOps uhci_device_ops = { .status = NULL, .stop = NULL, }; +UsbHubOps uhci_root_hub_ops = { + .init = NULL, + .clear_port_feature = uhci_clear_port_feature, + .set_port_feature = uhci_set_port_feature, + .get_hub_status = uhci_get_hub_status, + .get_port_status = uhci_get_port_status, +}; DeviceDriver uhci_device_driver = { .name = STRING_INIT("uhci"), @@ -89,9 +105,6 @@ HciInit uhci_hci_init = { .init = uhci_register, }; -void uhci_port_reset(Uhci *devext, int port); -void uhci_port_init(UsbHcd *hcd, UsbEndpoint *ep0, int port); - void uhci_handler(Device *device) { Uhci *uhci = device->private_data; UhciQh *qhs = uhci->skel->qh, *qh; @@ -157,15 +170,79 @@ void uhci_handler(Device *device) { } } -void uhci_print_status(Uhci *devext) { - uint16_t status = io_in_word(devext->io_base + UHCI_REG_STS); - printk("\n[UHCI]Status:\n"); - if (status & 0x20) { printk("[UHCI]HC Halted.\n"); } - if (status & 0x10) { printk("[UHCI]HC Process Error.\n"); } - if (status & 0x08) { printk("[UHCI]Host System Error.\n"); } - if (status & 0x04) { printk("[UHCI]Resume Detect.\n"); } - printk("[UHCI]Error Int:%d\n", status & 0x02); - printk("[UHCI]Interrupt:%d\n", status & 0x01); +UsbSetupStatus uhci_clear_port_feature( + UsbHub *hub, uint8_t port, uint16_t feature) { + UsbHcd *hcd = hub->hcd; + Uhci *uhci = (Uhci *)hcd->device->private_data; + uint32_t io_port = uhci->io_base + UHCI_PORTSC1 + port * 2; + uint16_t value = io_in_word(io_port); + switch (feature) { + case HUB_FEAT_PORT_ENABLE: + io_out_word(io_port, BIN_DIS(value, UHCI_PORT_SC_ENABLE)); + break; + case HUB_FEAT_C_PORT_CONNECTION: + io_out_word(io_port, BIN_EN(value, UHCI_PORT_SC_CONN_CHG)); + break; + case HUB_FEAT_C_PORT_ENABLE: + io_out_word(io_port, BIN_EN(value, UHCI_PORT_SC_EN_CHG)); + break; + case HUB_FEAT_C_PORT_RESET: + io_out_word(io_port, BIN_DIS(value, UHCI_PORT_SC_RESET)); + break; + default: + return USB_SETUP_STALLED; + } +} + +uint32_t uhci_get_hub_status(UsbHub *hub) { + return 0b00; +} + +uint32_t uhci_get_port_status(UsbHub *hub, uint8_t port) { + UsbHcd *hcd = hub->hcd; + Uhci *uhci = (Uhci *)hcd->device->private_data; + uint32_t io_port = uhci->io_base + UHCI_PORTSC1 + port * 2; + uint16_t uhci_port_status = io_in_word(io_port); + uint16_t usb_port_status; + + usb_port_status = (uhci_port_status & UHCI_PORT_SC_CONNECTED) | + (uhci_port_status & UHCI_PORT_SC_ENABLE) >> 1 | + (uhci_port_status & UHCI_PORT_SC_SUSPEND) >> 10 | + (uhci_port_status & UHCI_PORT_SC_RESET) >> 5 | + USB_PORT_STAT_POWER | + (uhci_port_status & UHCI_PORT_SC_LOWSPEED); + return usb_port_status; +} + +UsbSetupStatus uhci_set_port_feature( + UsbHub *hub, uint8_t port, uint16_t feature) { + UsbHcd *hcd = hub->hcd; + Uhci *uhci = (Uhci *)hcd->device->private_data; + uint32_t io_port = uhci->io_base + UHCI_PORTSC1 + port * 2; + uint16_t value = io_in_word(io_port); + switch (feature) { + case HUB_FEAT_PORT_RESET: + io_out_word(io_port, BIN_EN(value, UHCI_PORT_SC_RESET)); + delay_ms(&uhci->timer, 50); + value = io_in_word(io_port); + io_out_word(io_port, BIN_DIS(value, UHCI_PORT_SC_RESET)); + do { + value = io_in_word(io_port); + } while (BIN_IS_EN(value, UHCI_PORT_SC_RESET)); + delay_ms(&uhci->timer, 10); + if (value & UHCI_PORT_SC_CONNECTED) { + io_out_word(io_port, BIN_EN(value, UHCI_PORT_SC_ENABLE)); + } + break; + case HUB_FEAT_PORT_SUSPEND: + io_out_word(io_port, BIN_EN(value, UHCI_PORT_SC_SUSPEND)); + break; + case HUB_FEAT_PORT_POWER: + break; + default: + return USB_SETUP_STALLED; + } + return USB_SETUP_SUCCESS; } void uhci_reset(Uhci *uhci) { @@ -214,7 +291,7 @@ void uhci_port_reset(Uhci *uhci, int port) { delay_ms(&uhci->timer, 10); } -void uhci_port_init(UsbHcd *hcd, UsbEndpoint *ep0, int port) { +void uhci_port_init(UsbHub *hub, UsbHcd *hcd, int port) { Uhci *devext = (Uhci *)hcd->device->private_data; uint32_t io_port = devext->io_base + UHCI_PORTSC1 + port * 2; UsbHcdPort *hcd_port = &hcd->ports[port]; @@ -228,10 +305,11 @@ void uhci_port_init(UsbHcd *hcd, UsbEndpoint *ep0, int port) { ? USB_SPEED_LOW : USB_SPEED_FULL; printk("[UHCI]port %d connected.\n", port); - UsbDevice *usb_device = usb_create_device(hcd, speed, 0); + UsbDevice *usb_device = usb_create_device(hcd, hub, speed, 0); uhci_port_reset(devext, port); + UsbEndpoint *ep0 = kmalloc(sizeof(UsbEndpoint)); struct UsbEndpointDescriptor *endpoint_desc = kmalloc(sizeof(struct UsbEndpointDescriptor)); endpoint_desc->bLength = sizeof(struct UsbEndpointDescriptor); @@ -272,10 +350,25 @@ DriverResult uhci_init(Device *device) { } void uhci_probe_thread(void *arg) { - Uhci *uhci = (Uhci *)arg; - UsbEndpoint *endpoints = kmalloc(sizeof(UsbEndpoint) * uhci->port_cnt); + Uhci *uhci = (Uhci *)arg; + + UsbHub *hub = kmalloc(sizeof(UsbHub)); + hub->usb_device = NULL; + hub->ops = &uhci_root_hub_ops; + + struct UsbHubDescriptor *desc = kmalloc(sizeof(struct UsbHubDescriptor)); + hub->desc = desc; + desc->bLength = 9; + desc->bDescriptorType = USB_DESC_TYPE_HUB; + desc->bNbrPorts = uhci->port_cnt; + desc->wHubCharacteristics = HOST2LE_WORD(0x0009); // 无电源开关,单独供电 + desc->bPwrOn2PwrGood = 0; + desc->bHubContrCurrent = 0; + memset(&desc->DeviceRemovable, 0xff, 8); // 都是可移除的 + memset(&desc->PortPwrCtrlMask, 0xff, 8); // 都是电源控制的 + for (int i = 0; i < uhci->port_cnt; i++) { - uhci_port_init(uhci->hcd, &endpoints[i], i); + uhci_port_init(hub, uhci->hcd, i); } } diff --git a/src/driver/usb/usb-core/func.c b/src/driver/usb/usb-core/func.c index 67fadf8..7aa91bc 100644 --- a/src/driver/usb/usb-core/func.c +++ b/src/driver/usb/usb-core/func.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -110,9 +111,10 @@ UsbSetupStatus usb_set_config( return hcd->ops->ctrl_transfer_out(hcd, device, NULL, 0, &usb_req); } -struct UsbHubDescriptor *usb_get_hub_descriptor( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { - struct UsbHubDescriptor *desc = kmalloc(sizeof(struct UsbHubDescriptor)); +struct UsbHubDescriptor *usb_get_hub_descriptor(UsbHub *hub) { + UsbDevice *device = hub->usb_device; + UsbHcd *hcd = device->hcd; + struct UsbHubDescriptor *desc = kmalloc(sizeof(struct UsbHubDescriptor)); UsbControlRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_DEVICE, @@ -123,8 +125,10 @@ struct UsbHubDescriptor *usb_get_hub_descriptor( return desc; } -uint32_t usb_get_hub_status(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { - uint32_t stat; +uint32_t usb_get_hub_status(UsbHub *hub) { + uint32_t stat; + UsbDevice *device = hub->usb_device; + UsbHcd *hcd = device->hcd; UsbControlRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, @@ -133,9 +137,10 @@ uint32_t usb_get_hub_status(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { return stat; } -uint32_t usb_get_port_status( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t port) { - uint32_t stat; +uint32_t usb_get_port_status(UsbHub *hub, uint8_t port) { + uint32_t stat; + UsbDevice *device = hub->usb_device; + UsbHcd *hcd = device->hcd; UsbControlRequest usb_req = USB_BUILD_REQUEST( USB_REQ_DEVICE_TO_HOST, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_OTHER, @@ -173,9 +178,22 @@ UsbSetupStatus usb_set_address( return hcd->ops->ctrl_transfer_out(hcd, device, NULL, 0, &req); } +UsbSetupStatus usb_clear_port_feature( + UsbHub *hub, uint8_t port, uint16_t feature) { + UsbDevice *device = hub->usb_device; + UsbHcd *hcd = device->hcd; + + UsbControlRequest req = USB_BUILD_REQUEST( + USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_OTHER, + USB_REQ_CLEAR_FEATURE, feature >> 8, feature & 0xff, port, 0); + + return hcd->ops->ctrl_transfer_out(hcd, device, NULL, 0, &req); +} + UsbSetupStatus usb_set_port_feature( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t port, - uint16_t feature) { + UsbHub *hub, uint8_t port, uint16_t feature) { + UsbDevice *device = hub->usb_device; + UsbHcd *hcd = device->hcd; UsbControlRequest req = USB_BUILD_REQUEST( USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_OTHER, diff --git a/src/driver/usb/usb-core/hub.c b/src/driver/usb/usb-core/hub.c index 5ab40b2..9b5e518 100644 --- a/src/driver/usb/usb-core/hub.c +++ b/src/driver/usb/usb-core/hub.c @@ -10,36 +10,40 @@ #include #include -void usb_init_hub(UsbHcd *hcd, UsbEndpoint *ep0, UsbDevice *usb_device) { +UsbHubOps usb_hub_ops = { + .init = NULL, + .clear_port_feature = usb_clear_port_feature, + .set_port_feature = usb_set_port_feature, + .get_hub_status = usb_get_hub_status, + .get_port_status = usb_get_port_status, +}; + +void usb_init_hub( + UsbHcd *hcd, UsbHub *hub, UsbEndpoint *ep0, UsbDevice *usb_device) { Timer timer; timer_init(&timer); - // TODO: UsbHub - struct UsbHubDescriptor *desc = - usb_get_hub_descriptor(hcd, usb_device, ep0); - // usb_show_hub_descriptor(desc); - uint32_t status = usb_get_hub_status(hcd, usb_device, ep0); + uint32_t status = hub->ops->get_hub_status(hub); int i; UsbSetupStatus status2; - UsbEndpoint *endpoints = kmalloc(sizeof(UsbEndpoint) * desc->bNbrPorts); - for (i = 1; i <= desc->bNbrPorts; i++) { - status = usb_get_port_status(hcd, usb_device, ep0, i); + UsbEndpoint *endpoints = + kmalloc(sizeof(UsbEndpoint) * hub->desc->bNbrPorts); + for (i = 1; i <= hub->desc->bNbrPorts; i++) { + status = hub->ops->get_port_status(hub, i); if (BIN_IS_EN(status, USB_PORT_STAT_CONNECTION)) { - status2 = usb_set_port_feature( - hcd, usb_device, ep0, i, HUB_FEAT_PORT_POWER); - if (status2 == USB_SETUP_CRC_TIMEOUT_ERR) { continue; } - delay_ms(&timer, 50); - status2 = usb_set_port_feature( - hcd, usb_device, ep0, i, HUB_FEAT_PORT_RESET); - if (status2 == USB_SETUP_CRC_TIMEOUT_ERR) { continue; } + status2 = hub->ops->set_port_feature(hub, i, HUB_FEAT_PORT_POWER); + if (status2 == USB_SETUP_CRC_TIMEOUT_ERR) continue; + delay_ms(&timer, hub->desc->bPwrOn2PwrGood * 2); + status2 = hub->ops->set_port_feature(hub, i, HUB_FEAT_PORT_RESET); + if (status2 == USB_SETUP_CRC_TIMEOUT_ERR) continue; delay_ms(&timer, 200); UsbDeviceSpeed speed = BIN_IS_EN(status, USB_PORT_STAT_LOW_SPEED) ? USB_SPEED_LOW : BIN_IS_EN(status, USB_PORT_STAT_HIGH_SPEED) ? USB_SPEED_HIGH : USB_SPEED_FULL; - UsbDevice *dev = usb_create_device(hcd, speed, 0); + UsbDevice *dev = usb_create_device(hcd, hub, speed, 0); struct UsbEndpointDescriptor *endpoint_desc = kmalloc(sizeof(struct UsbEndpointDescriptor)); endpoint_desc->bLength = sizeof(struct UsbEndpointDescriptor); diff --git a/src/driver/usb/usb-core/usb.c b/src/driver/usb/usb-core/usb.c index 9998093..3271c6c 100644 --- a/src/driver/usb/usb-core/usb.c +++ b/src/driver/usb/usb-core/usb.c @@ -14,7 +14,7 @@ #include UsbDevice *usb_create_device( - UsbHcd *hcd, UsbDeviceSpeed speed, uint8_t address) { + UsbHcd *hcd, UsbHub *hub, UsbDeviceSpeed speed, uint8_t address) { Device *device = kmalloc(sizeof(Device)); device->private_data_size = 0; device->ops = NULL; @@ -30,6 +30,7 @@ UsbDevice *usb_create_device( usb_device->state = USB_STATE_UNINITED; usb_device->device = device; usb_device->hcd = hcd; + usb_device->hub = hub; return usb_device; } @@ -85,7 +86,15 @@ int usb_init_device( hcd->device->device_driver, usb_device->device, usb_device, &attr); if (desc->bDeviceClass == USB_CLASS_HUB) { - usb_init_hub(hcd, ep0, usb_device); + UsbHub *hub = kmalloc(sizeof(UsbHub)); + hub->usb_device = usb_device; + hub->ops = &usb_hub_ops; + hub->hcd = hcd; + + hub->desc = usb_get_hub_descriptor(hub); + // usb_show_hub_descriptor(desc); + + usb_init_hub(hcd, hub, ep0, usb_device); } return 0; } \ No newline at end of file diff --git a/src/include/driver/usb/func.h b/src/include/driver/usb/func.h index 463bf05..9d275a6 100644 --- a/src/include/driver/usb/func.h +++ b/src/include/driver/usb/func.h @@ -1,6 +1,7 @@ #ifndef _USB_FUNC_H #define _USB_FUNC_H +#include #include #define REQ_GET_PORT_STATUS_SIZE 4 @@ -61,20 +62,18 @@ uint8_t usb_get_config(UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep); UsbSetupStatus usb_set_config( UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep, uint8_t config); -struct UsbHubDescriptor *usb_get_hub_descriptor( - UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep); +struct UsbHubDescriptor *usb_get_hub_descriptor(UsbHub *hub); UsbSetupStatus usb_set_address( UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep, uint32_t address); +UsbSetupStatus usb_clear_port_feature( + UsbHub *hub, uint8_t port, uint16_t feature); UsbSetupStatus usb_set_port_feature( - UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep, uint8_t port, - uint16_t feature); + UsbHub *hub, uint8_t port, uint16_t feature); -uint32_t usb_get_hub_status( - UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep); -uint32_t usb_get_port_status( - UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep, uint8_t port); +uint32_t usb_get_hub_status(UsbHub *hub); +uint32_t usb_get_port_status(UsbHub *hub, uint8_t port); struct UsbStringDescriptor *usb_get_string_descriptor( UsbHcd *hcd, struct UsbDevice *device, uint8_t index, UsbEndpoint *ep); diff --git a/src/include/driver/usb/hub.h b/src/include/driver/usb/hub.h index 9142a2e..89dbbbe 100644 --- a/src/include/driver/usb/hub.h +++ b/src/include/driver/usb/hub.h @@ -2,6 +2,8 @@ #define _USB_HUB_H #include +#include +#include #define HUB_FEAT_C_LOCAL_POWER 0 #define HUB_FEAT_C_OVER_CURRENT 1 @@ -23,6 +25,27 @@ #define HUB_FEAT_PORT_TEST 21 #define HUB_FEAT_PORT_INDICATOR 22 -void usb_init_hub(UsbHcd *hcd, UsbEndpoint *ep0, struct UsbDevice *usb_device); +typedef struct UsbHub { + UsbDevice *usb_device; + UsbHcd *hcd; + + struct UsbHubDescriptor *desc; + struct UsbHubOps *ops; +} UsbHub; + +typedef struct UsbHubOps { + void (*init)(struct UsbHub *hub); + UsbSetupStatus (*clear_port_feature)( + struct UsbHub *hub, uint8_t port, uint16_t feature); + UsbSetupStatus (*set_port_feature)( + struct UsbHub *hub, uint8_t port, uint16_t feature); + uint32_t (*get_hub_status)(struct UsbHub *hub); + uint32_t (*get_port_status)(struct UsbHub *hub, uint8_t port); +} UsbHubOps; + +extern UsbHubOps usb_hub_ops; + +void usb_init_hub( + UsbHcd *hcd, UsbHub *hub, UsbEndpoint *ep0, struct UsbDevice *usb_device); #endif \ No newline at end of file diff --git a/src/include/driver/usb/usb.h b/src/include/driver/usb/usb.h index 0c454ba..2fc7bf1 100644 --- a/src/include/driver/usb/usb.h +++ b/src/include/driver/usb/usb.h @@ -194,8 +194,9 @@ static const uint8_t usb_interface_map[] = { extern UsbEndpoint usb_ep0; +struct UsbHub; struct UsbDevice *usb_create_device( - UsbHcd *hcd, UsbDeviceSpeed speed, uint8_t address); + UsbHcd *hcd, struct UsbHub *hub, UsbDeviceSpeed speed, uint8_t address); int usb_destroy_device(struct UsbDevice *device); UsbControlRequest *usb_create_request( diff --git a/src/include/driver/usb/usb_dm.h b/src/include/driver/usb/usb_dm.h index 7853959..159e53b 100644 --- a/src/include/driver/usb/usb_dm.h +++ b/src/include/driver/usb/usb_dm.h @@ -17,6 +17,7 @@ typedef struct UsbDevice { UsbDeviceState state; UsbHcd *hcd; Device *device; + struct UsbHub *hub; struct UsbDeviceDescriptor *desc; UsbDeviceSpeed speed; From 378b1e9e5c50805e0dabcddcedfa676a57f24a02 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 23 Sep 2025 17:29:43 +0800 Subject: [PATCH 132/158] =?UTF-8?q?uhci&hid:=20=E5=88=A0=E5=8E=BB=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/usb/hci/uhci.c | 17 ++++------------- src/arch/x86/drivers/usb/hci/uhci/packet.c | 19 ++++++++++--------- src/drivers/usb/hid/mouse.c | 10 ---------- 3 files changed, 14 insertions(+), 32 deletions(-) diff --git a/src/arch/x86/drivers/usb/hci/uhci.c b/src/arch/x86/drivers/usb/hci/uhci.c index 47ac4ba..3b12024 100644 --- a/src/arch/x86/drivers/usb/hci/uhci.c +++ b/src/arch/x86/drivers/usb/hci/uhci.c @@ -57,7 +57,7 @@ void uhci_register(Driver *driver); DriverResult uhci_init(Device *device); DriverResult uhci_start(Device *device); DriverResult uhci_pci_probe(PciDevice *pci_device); -void uhci_port_reset(Uhci *devext, int port); +void uhci_port_reset(Uhci *uhci, int port); void uhci_port_init(UsbHub *hub, UsbHcd *hcd, int port); DeviceDriverOps uhci_device_driver_ops = { @@ -192,6 +192,7 @@ UsbSetupStatus uhci_clear_port_feature( default: return USB_SETUP_STALLED; } + return USB_SETUP_SUCCESS; } uint32_t uhci_get_hub_status(UsbHub *hub) { @@ -222,17 +223,7 @@ UsbSetupStatus uhci_set_port_feature( uint16_t value = io_in_word(io_port); switch (feature) { case HUB_FEAT_PORT_RESET: - io_out_word(io_port, BIN_EN(value, UHCI_PORT_SC_RESET)); - delay_ms(&uhci->timer, 50); - value = io_in_word(io_port); - io_out_word(io_port, BIN_DIS(value, UHCI_PORT_SC_RESET)); - do { - value = io_in_word(io_port); - } while (BIN_IS_EN(value, UHCI_PORT_SC_RESET)); - delay_ms(&uhci->timer, 10); - if (value & UHCI_PORT_SC_CONNECTED) { - io_out_word(io_port, BIN_EN(value, UHCI_PORT_SC_ENABLE)); - } + uhci_port_reset(uhci, port); break; case HUB_FEAT_PORT_SUSPEND: io_out_word(io_port, BIN_EN(value, UHCI_PORT_SC_SUSPEND)); @@ -269,7 +260,7 @@ void uhci_port_reset(Uhci *uhci, int port) { uint16_t value = io_in_word(io_port); io_out_word(io_port, BIN_EN(value, UHCI_PORT_SC_RESET)); - delay_ms(&uhci->timer, 50); + delay_ms(&uhci->timer, 10); value = io_in_word(io_port); io_out_word(io_port, BIN_DIS(value, UHCI_PORT_SC_RESET)); diff --git a/src/arch/x86/drivers/usb/hci/uhci/packet.c b/src/arch/x86/drivers/usb/hci/uhci/packet.c index d37ae6a..cfa55ec 100644 --- a/src/arch/x86/drivers/usb/hci/uhci/packet.c +++ b/src/arch/x86/drivers/usb/hci/uhci/packet.c @@ -158,16 +158,17 @@ static inline UhciTd *uhci_out_transcation( int uhci_wait_transfer(UhciQh *qh) { Timer timer; timer_init(&timer); - int timeout = 150; - UhciPipeline *pipe = (UhciPipeline *)qh; - // UhciTd *td = &pipe->tds[pipe->td_index - 1]; - UhciTd *td = qh->first_td; - while (timeout > 0) { - if (td->active == 0) { return 1; } - - delay_ms(&timer, 10); - timeout--; + UhciTd *td = qh->first_td; + while (td->active) { + if (td->active == 0) { break; } + + delay_ms(&timer, 1); } + if (!(td->crc_timeout_Error | td->bitstuff_Error | td->databuffer_Error | + td->stalled | td->NAK_received)) + return 0; + + // 发送错误 uint32_t *raw = (uint32_t *)td; // TD 在内存首地址 printk( "TD raw: w0=%08x w1=%08x w2=%08x w3=%08x\n", raw[0], raw[1], raw[2], diff --git a/src/drivers/usb/hid/mouse.c b/src/drivers/usb/hid/mouse.c index 008776a..82ba333 100644 --- a/src/drivers/usb/hid/mouse.c +++ b/src/drivers/usb/hid/mouse.c @@ -63,10 +63,6 @@ DriverResult usb_hid_mouse_init(Device *device) { if ((ep->desc->bmAttributes & 0x03) == USB_EP_INTERRUPT && (ep->desc->bEndpointAddress >> 7) == USB_EP_IN) { // 找到中断输入端点 - printk( - "Mouse Interrupt IN Endpoint Found: 0x%02x\n", - ep->desc->bEndpointAddress); - int size = ep->desc->wMaxPacketSize & 0x7ff; mouse->buffer = kmalloc(size); mouse->urb = usb_create_urb( @@ -83,12 +79,6 @@ DriverResult usb_hid_mouse_start(Device *device) { ep->data_toggle = 1; mouse->usb_device->hcd->ops->add_interrupt_transfer( mouse->usb_device->hcd, mouse->usb_device, ep, mouse->urb); - // UsbControlRequest req = USB_BUILD_REQUEST( - // USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_INTERFACE, - // 0x0b, 0x00, 0x00, mouse->interface->desc->bInterfaceNumber, 0); - // uint8_t data = 0; - // mouse->usb_device->hcd->ops->ctrl_transfer_out( - // mouse->usb_device->hcd, mouse->usb_device, &data, 0, &req); return DRIVER_RESULT_OK; } From 4768fc0fd71bb992c7344216c6987bd3debcabaa Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 23 Sep 2025 17:30:19 +0800 Subject: [PATCH 133/158] =?UTF-8?q?usb:=20=E6=8F=90=E9=AB=98hub=E7=AB=AF?= =?UTF-8?q?=E5=8F=A3=E5=88=9D=E5=A7=8B=E5=8C=96=E6=95=88=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/usb/usb-core/hub.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/driver/usb/usb-core/hub.c b/src/driver/usb/usb-core/hub.c index 9b5e518..1e8b0f7 100644 --- a/src/driver/usb/usb-core/hub.c +++ b/src/driver/usb/usb-core/hub.c @@ -29,16 +29,30 @@ void usb_init_hub( UsbSetupStatus status2; UsbEndpoint *endpoints = kmalloc(sizeof(UsbEndpoint) * hub->desc->bNbrPorts); - for (i = 1; i <= hub->desc->bNbrPorts; i++) { - status = hub->ops->get_port_status(hub, i); - if (BIN_IS_EN(status, USB_PORT_STAT_CONNECTION)) { - status2 = hub->ops->set_port_feature(hub, i, HUB_FEAT_PORT_POWER); + + uint32_t port_status[hub->desc->bNbrPorts]; + for (i = 0; i < hub->desc->bNbrPorts; i++) { + port_status[i] = hub->ops->get_port_status(hub, i + 1); + if (BIN_IS_EN(port_status[i], USB_PORT_STAT_CONNECTION)) { + status2 = + hub->ops->set_port_feature(hub, i + 1, HUB_FEAT_PORT_POWER); if (status2 == USB_SETUP_CRC_TIMEOUT_ERR) continue; - delay_ms(&timer, hub->desc->bPwrOn2PwrGood * 2); - status2 = hub->ops->set_port_feature(hub, i, HUB_FEAT_PORT_RESET); + } + } + delay_ms(&timer, hub->desc->bPwrOn2PwrGood * 2); + + for (i = 0; i < hub->desc->bNbrPorts; i++) { + if (BIN_IS_EN(port_status[i], USB_PORT_STAT_CONNECTION)) { + status2 = + hub->ops->set_port_feature(hub, i + 1, HUB_FEAT_PORT_RESET); if (status2 == USB_SETUP_CRC_TIMEOUT_ERR) continue; - delay_ms(&timer, 200); + } + } + delay_ms(&timer, 200); + for (i = 0; i < hub->desc->bNbrPorts; i++) { + status = port_status[i]; + if (BIN_IS_EN(status, USB_PORT_STAT_CONNECTION)) { UsbDeviceSpeed speed = BIN_IS_EN(status, USB_PORT_STAT_LOW_SPEED) ? USB_SPEED_LOW : BIN_IS_EN(status, USB_PORT_STAT_HIGH_SPEED) ? USB_SPEED_HIGH @@ -52,8 +66,8 @@ void usb_init_hub( endpoint_desc->bmAttributes = USB_EP_CONTROL; endpoint_desc->wMaxPacketSize = HOST2LE_WORD(64); endpoint_desc->bInterval = 0; - usb_init_device(hcd, &endpoints[i - 1], endpoint_desc, dev); - delay_ms(&timer, 100); + usb_init_device(hcd, &endpoints[i], endpoint_desc, dev); } } + delay_ms(&timer, 100); } \ No newline at end of file From 03ac8f464e45a340347dea0943d84c6d2f8185ae Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 23 Sep 2025 17:42:23 +0800 Subject: [PATCH 134/158] =?UTF-8?q?time:=20=E4=BF=AE=E5=A4=8D=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E5=88=86=E9=85=8DTimeDeviceManager=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/time_dm.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/driver/time_dm.c b/src/driver/time_dm.c index b99fb5e..a6da36c 100644 --- a/src/driver/time_dm.c +++ b/src/driver/time_dm.c @@ -9,8 +9,8 @@ DriverResult timer_dm_load(DeviceManager *manager); DriverResult timer_dm_unload(DeviceManager *manager); DeviceManagerOps time_dm_ops = { - .dm_load = timer_dm_load, - .dm_unload = timer_dm_unload, + .dm_load = NULL, + .dm_unload = NULL, }; TimeDeviceManager time_dm_ext; @@ -20,16 +20,6 @@ DeviceManager time_dm = { .private_data = &time_dm_ext, }; -DriverResult time_dm_load(DeviceManager *manager) { - manager->private_data = kmalloc(sizeof(TimeDeviceManager)); - return DRIVER_RESULT_OK; -} - -DriverResult time_dm_unload(DeviceManager *manager) { - kfree(manager->private_data); - return DRIVER_RESULT_OK; -} - DriverResult register_time_device( DeviceDriver *driver, Device *device, TimeDevice *time_device) { device->dm_ext = time_device; From 19da6584b588a07e21176f43ac40a94e2071ea5a Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 24 Sep 2025 01:17:22 +0800 Subject: [PATCH 135/158] =?UTF-8?q?driver:=20=E6=96=B0=E5=A2=9EInputManage?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/Makefile | 1 + src/driver/input/Makefile | 1 + src/driver/input/input_dm.c | 86 +++++++++++++++++++++++++++++ src/drivers/usb/hid/keyboard.c | 62 +++++++++++++++++++-- src/drivers/usb/hid/mouse.c | 29 ++++++++-- src/include/driver/input/input_dm.h | 63 +++++++++++++++++++++ src/include/drivers/usb/keyboard.h | 2 + src/include/drivers/usb/mouse.h | 2 + 8 files changed, 237 insertions(+), 9 deletions(-) create mode 100644 src/driver/input/Makefile create mode 100644 src/driver/input/input_dm.c create mode 100644 src/include/driver/input/input_dm.h diff --git a/src/driver/Makefile b/src/driver/Makefile index 39f9a8f..5a4a0a4 100644 --- a/src/driver/Makefile +++ b/src/driver/Makefile @@ -3,6 +3,7 @@ SRC += sound/ SRC += timer/ SRC += network/ SRC += usb/ +SRC += input/ SRC += interrupt_dm.c SRC += video_dm.c SRC += video.c diff --git a/src/driver/input/Makefile b/src/driver/input/Makefile new file mode 100644 index 0000000..35201cf --- /dev/null +++ b/src/driver/input/Makefile @@ -0,0 +1 @@ +SRC += input_dm.c \ No newline at end of file diff --git a/src/driver/input/input_dm.c b/src/driver/input/input_dm.c new file mode 100644 index 0000000..e64fef6 --- /dev/null +++ b/src/driver/input/input_dm.c @@ -0,0 +1,86 @@ +#include "kernel/driver.h" +#include "string.h" +#include +#include +#include +#include +#include +#include +#include + +string_t input_object = STRING_INIT("Input"); + +DriverResult input_dm_load(DeviceManager *manager); + +DeviceManagerOps input_dm_ops = { + .dm_load = input_dm_load, + .dm_unload = NULL, +}; +InputDeviceManager input_dm_ext; +DeviceManager input_dm = { + .type = DEVICE_TYPE_INPUT, + .ops = &input_dm_ops, + .private_data = &input_dm_ext, +}; + +DriverResult input_dm_load(DeviceManager *manager) { + ObjectAttr attr = base_obj_sys_attr; + create_object_directory(&device_object, input_object, attr); + memset(input_dm_ext.device_count, 0, sizeof(input_dm_ext.device_count)); + + input_dm_ext.key_events = + kmalloc(sizeof(KeyEvent) * INPUT_EVENT_QUEUE_SIZE); + input_dm_ext.key_event_w = 0; + input_dm_ext.key_event_r = 0; + input_dm_ext.pointer_events = + kmalloc(sizeof(PointerEvent) * INPUT_EVENT_QUEUE_SIZE); + input_dm_ext.pointer_event_w = 0; + input_dm_ext.pointer_event_r = 0; + return DRIVER_RESULT_OK; +} + +DriverResult register_input_device( + DeviceDriver *device_driver, Device *device, Bus *bus, + InputDevice *input_device) { + device->dm_ext = input_device; + input_device->device = device; + + int id = input_dm_ext.device_count[input_device->type]++; + string_t name; + if (input_device->type == INPUT_TYPE_KEYBOARD) { + string_new_with_number(&name, "Keyboard", 8, id); + } else if (input_device->type == INPUT_TYPE_MOUSE) { + string_new_with_number(&name, "Mouse", 5, id); + } else { + string_new_with_number(&name, "Input", 5, id); + } + ObjectAttr attr = device_object_attr; + register_device(device_driver, &name, bus, device, &attr); + + return DRIVER_RESULT_OK; +} + +KeyEvent *new_key_event() { + if (input_dm_ext.key_event_w == input_dm_ext.key_event_r) { + // 队列满,丢弃最旧的事件 + input_dm_ext.key_event_r = + (input_dm_ext.key_event_r + 1) % INPUT_EVENT_QUEUE_SIZE; + } + KeyEvent *event = &input_dm_ext.key_events[input_dm_ext.key_event_w]; + input_dm_ext.key_event_w = + (input_dm_ext.key_event_w + 1) % INPUT_EVENT_QUEUE_SIZE; + return event; +} + +PointerEvent *new_pointer_event() { + if (input_dm_ext.pointer_event_w == input_dm_ext.pointer_event_r) { + // 队列满,丢弃最旧的事件 + input_dm_ext.pointer_event_r = + (input_dm_ext.pointer_event_r + 1) % INPUT_EVENT_QUEUE_SIZE; + } + PointerEvent *event = + &input_dm_ext.pointer_events[input_dm_ext.pointer_event_w]; + input_dm_ext.pointer_event_w = + (input_dm_ext.pointer_event_w + 1) % INPUT_EVENT_QUEUE_SIZE; + return event; +} diff --git a/src/drivers/usb/hid/keyboard.c b/src/drivers/usb/hid/keyboard.c index cb526a3..703d97d 100644 --- a/src/drivers/usb/hid/keyboard.c +++ b/src/drivers/usb/hid/keyboard.c @@ -2,6 +2,7 @@ #include "driver/usb/usb_dm.h" #include "kernel/dynamic_device_manager.h" #include "kernel/list.h" +#include #include #include #include @@ -38,6 +39,9 @@ DeviceDriver usb_hid_keyboard_device_driver = { .private_data_size = 0, .ops = &usb_hid_keyboard_device_driver_ops, }; +InputDevice usb_hid_keyboard_input_device = { + .type = INPUT_TYPE_KEYBOARD, +}; void usb_hid_keyboard_handler(UsbRequestBlock *urb) { UsbHidKeyboardReport *report = (UsbHidKeyboardReport *)urb->buffer; @@ -51,6 +55,57 @@ void usb_hid_keyboard_handler(UsbRequestBlock *urb) { report->modifier_keys, report->keycodes[0], report->keycodes[1], report->keycodes[2], report->keycodes[3], report->keycodes[4], report->keycodes[5]); + if (report->modifier_keys != keyboard->last_keys[0]) { + for (int i = 0; i < 8; i++) { + uint8_t mask = 1 << i; + if ((report->modifier_keys & mask) | + (keyboard->last_keys[0] & mask)) { + KeyEvent *event = new_key_event(); + event->page = 0; + event->keycode = INPUT_KEY_EVENT_MODIFIER_BASE + i; + if (keyboard->last_keys[0] & mask) { + event->pressed = 0; + } else { + event->pressed = 1; + } + } + } + } + if (memcmp(&keyboard->last_keys[1], report->keycodes, 6) != 0) { + // 有按键变化 + for (int i = 0; i < 6; i++) { + if (report->keycodes[i] == keyboard->last_keys[i + 1]) { + continue; + } + + bool found1 = false, found2 = false; + for (int j = i; j < 6; j++) { + if (report->keycodes[i] == keyboard->last_keys[j + 1]) { + found1 = true; + } + if (keyboard->last_keys[i + 1] == report->keycodes[j]) { + found2 = true; + } + if (found1 && found2) break; + } + if (!found1) { + KeyEvent *event = new_key_event(); + event->page = 0; + event->keycode = + INPUT_KEY_EVENT_KEYBOARD_BASE + report->keycodes[i]; + event->pressed = 1; + } + if (!found2) { + KeyEvent *event = new_key_event(); + event->page = 0; + event->keycode = INPUT_KEY_EVENT_KEYBOARD_BASE + + keyboard->last_keys[i + 1]; + event->pressed = 0; + } + } + } + memcpy(&keyboard->last_keys[1], report->keycodes, 6); + keyboard->last_keys[0] = report->modifier_keys; urb->ep->data_toggle ^= 1; usb_device->hcd->ops->interrupt_transfer(usb_device->hcd, urb->ep); } else { @@ -107,10 +162,9 @@ DriverResult usb_hid_keyboard_probe( device->state = DEVICE_STATE_UNREGISTERED; interface->usb_driver = &usb_hid_usb_driver; - ObjectAttr attr = device_object_attr; - register_device( - &usb_hid_keyboard_device_driver, &device->name, usb_device->device->bus, - device, &attr); + register_input_device( + &usb_hid_keyboard_device_driver, device, usb_device->device->bus, + &usb_hid_keyboard_input_device); UsbHidKeyboard *keyboard = device->private_data; keyboard->device = device; diff --git a/src/drivers/usb/hid/mouse.c b/src/drivers/usb/hid/mouse.c index 82ba333..60752e0 100644 --- a/src/drivers/usb/hid/mouse.c +++ b/src/drivers/usb/hid/mouse.c @@ -1,3 +1,4 @@ +#include "driver/input/input_dm.h" #include "driver/usb/descriptors.h" #include "driver/usb/usb_dm.h" #include "kernel/dynamic_device_manager.h" @@ -37,6 +38,9 @@ DeviceDriver usb_hid_mouse_device_driver = { .private_data_size = 0, .ops = &usb_hid_mouse_device_driver_ops, }; +InputDevice usb_hid_mouse_input_device = { + .type = INPUT_TYPE_MOUSE, +}; void usb_hid_mouse_handler(UsbRequestBlock *urb) { UsbHidMouseReport *report = (UsbHidMouseReport *)urb->buffer; @@ -46,6 +50,22 @@ void usb_hid_mouse_handler(UsbRequestBlock *urb) { printk( "Mouse Report: Buttons: 0x%02x, X: %d, Y: %d\n", report->buttons, report->x, report->y); + if (report->x != 0 || report->y != 0) { + PointerEvent *event = new_pointer_event(); + if (event) { + event->type = POINTER_TYPE_MOVE; + event->dx = report->x; + event->dy = report->y; + } + } + if ((report->buttons & 7) != (mouse->last_buttons & 7)) { + KeyEvent *event = new_key_event(); + if (event) { + event->keycode = report->buttons + INPUT_KEY_EVENT_MOUSE_BASE; + event->pressed = 1; + event->page = 0; + } + } urb->ep->data_toggle ^= 1; usb_device->hcd->ops->interrupt_transfer(usb_device->hcd, urb->ep); } else { @@ -86,16 +106,15 @@ DriverResult usb_hid_mouse_probe( UsbDevice *usb_device, UsbInterface *interface) { Device *device = kmalloc(sizeof(Device)); device->private_data_size = sizeof(UsbHidMouse); - string_new(&device->name, "USB HID Mouse", 14); + string_new(&device->name, "UsbHidMouse", 12); device->device_driver = &usb_hid_mouse_device_driver; device->ops = &usb_hid_mouse_device_ops; device->state = DEVICE_STATE_UNREGISTERED; interface->usb_driver = &usb_hid_usb_driver; - ObjectAttr attr = device_object_attr; - register_device( - &usb_hid_mouse_device_driver, &device->name, usb_device->device->bus, - device, &attr); + register_input_device( + &usb_hid_mouse_device_driver, device, usb_device->device->bus, + &usb_hid_mouse_input_device); UsbHidMouse *mouse = device->private_data; mouse->device = device; diff --git a/src/include/driver/input/input_dm.h b/src/include/driver/input/input_dm.h new file mode 100644 index 0000000..7b974c5 --- /dev/null +++ b/src/include/driver/input/input_dm.h @@ -0,0 +1,63 @@ +#ifndef _INPUT_DM_H +#define _INPUT_DM_H + +#include +#include +#include +#include +#include + +#define INPUT_EVENT_QUEUE_SIZE 256 + +#define INPUT_KEY_EVENT_MOUSE_BASE 0 +#define INPUT_KEY_EVENT_MODIFIER_BASE 8 +#define INPUT_KEY_EVENT_KEYBOARD_BASE 16 + +typedef enum { + INPUT_TYPE_UNKNOWN, + INPUT_TYPE_KEYBOARD, + INPUT_TYPE_MOUSE, + INPUT_TYPE_MAX, +} InputDeviceType; + +typedef struct InputDevice { + Device *device; + InputDeviceType type; +} InputDevice; + +typedef struct KeyEvent { + uint8_t keycode; + uint8_t pressed; // 1: pressed, 0: released + uint8_t page; +} KeyEvent; + +typedef struct PointerEvent { + int16_t dx; + int16_t dy; + enum { + POINTER_TYPE_MOVE, + POINTER_TYPE_SCROLL, + POINTER_TYPE_PRESSURE, + } type; +} PointerEvent; + +typedef struct InputDeviceManager { + int device_count[INPUT_TYPE_MAX]; + + int key_event_w, key_event_r; + KeyEvent *key_events; + + int pointer_event_w, pointer_event_r; + PointerEvent *pointer_events; +} InputDeviceManager; + +DriverResult register_input_device( + DeviceDriver *device_driver, Device *device, Bus *bus, + InputDevice *input_device); + +extern DeviceManager input_dm; + +KeyEvent *new_key_event(); +PointerEvent *new_pointer_event(); + +#endif \ No newline at end of file diff --git a/src/include/drivers/usb/keyboard.h b/src/include/drivers/usb/keyboard.h index 80e42c3..d6620dd 100644 --- a/src/include/drivers/usb/keyboard.h +++ b/src/include/drivers/usb/keyboard.h @@ -21,6 +21,8 @@ typedef struct { UsbRequestBlock *urb; uint8_t *buffer; + + uint8_t last_keys[7]; } UsbHidKeyboard; extern DeviceOps usb_hid_keyboard_device_ops; diff --git a/src/include/drivers/usb/mouse.h b/src/include/drivers/usb/mouse.h index 4ea8c25..3b0ff73 100644 --- a/src/include/drivers/usb/mouse.h +++ b/src/include/drivers/usb/mouse.h @@ -21,6 +21,8 @@ typedef struct { UsbRequestBlock *urb; uint8_t *buffer; + + uint8_t last_buttons; } UsbHidMouse; extern DeviceOps usb_hid_mouse_device_ops; From afe14240609791f87e52dae41e1f5bb7a8a2d37b Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 24 Sep 2025 17:27:27 +0800 Subject: [PATCH 136/158] =?UTF-8?q?driver:=20=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?=E4=B8=B2=E5=8F=A3=E9=A9=B1=E5=8A=A8=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 6 +- src/arch/x86/drivers/Makefile | 1 + src/arch/x86/drivers/serial.c | 233 ++++++++++++++++++++++++++ src/arch/x86/include/drivers/serial.h | 51 ++++++ src/arch/x86/kernel/platform.c | 14 +- src/driver/Makefile | 1 + src/driver/serial/Makefile | 1 + src/driver/serial/serial_dm.c | 66 ++++++++ src/include/driver/serial/serial_dm.h | 53 ++++++ src/include/kernel/device.h | 2 + src/kernel/driver/device_manager.c | 2 + 11 files changed, 426 insertions(+), 4 deletions(-) create mode 100644 src/arch/x86/drivers/serial.c create mode 100644 src/arch/x86/include/drivers/serial.h create mode 100644 src/driver/serial/Makefile create mode 100644 src/driver/serial/serial_dm.c create mode 100644 src/include/driver/serial/serial_dm.h diff --git a/Makefile b/Makefile index 8cba072..04a8b22 100644 --- a/Makefile +++ b/Makefile @@ -103,9 +103,9 @@ qemu_dbg: $(QEMU) \ -no-reboot \ -s -S \ - -monitor stdio \ + -serial stdio \ -m 1024 \ - -hda $(HD_IMG) \ + -drive file=$(HD_IMG),if=ide,format=raw \ -usb \ -device piix3-usb-uhci \ -device usb-kbd \ @@ -121,7 +121,7 @@ qemu: -no-reboot \ -monitor stdio \ -m 1024 \ - -hda $(HD_IMG) \ + -drive file=$(HD_IMG),if=ide,format=raw \ -usb \ -device piix3-usb-uhci \ -device usb-kbd \ diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index 7091601..73afae8 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -8,6 +8,7 @@ SRC += disk.c #SRC += mouse.c SRC += msr.c SRC += pit.c +SRC += serial.c SRC += smbios.c SRC += vesa_display.c SRC += cmos.c diff --git a/src/arch/x86/drivers/serial.c b/src/arch/x86/drivers/serial.c new file mode 100644 index 0000000..2e7786d --- /dev/null +++ b/src/arch/x86/drivers/serial.c @@ -0,0 +1,233 @@ +#include "drivers/serial.h" +#include "driver/interrupt_dm.h" +#include "driver/serial/serial_dm.h" +#include "string.h" +#include +#include +#include +#include +#include +#include +#include +#include + +extern Driver core_driver; + +DriverResult serial_init(Device *device); +DriverResult serial_start(Device *device); +DriverResult serial_self_test(SerialDevice *serial_device); +void serial_set_baud_rate( + SerialDevice *serial_device, SerialBaudRate baud_rate); +void serial_set_recv_mode( + SerialDevice *serial_device, SerialReceiveMode recv_mode); +void serial_set_recv_mode( + SerialDevice *serial_device, SerialReceiveMode recv_mode); + +DeviceDriverOps serial_device_driver_ops = { + .device_driver_init = NULL, + .device_driver_uninit = NULL, +}; +DeviceOps serial_device_ops = { + .init = serial_init, + .start = serial_start, + .stop = NULL, + .destroy = NULL, + .status = NULL, +}; +SerialDeviceOps serial_serial_device_ops = { + .self_test = serial_self_test, + .set_baud_rate = serial_set_baud_rate, + .set_recv_mode = serial_set_recv_mode, +}; + +DeviceDriver serial_device_driver = { + .name = STRING_INIT("Serial"), + .type = DEVICE_TYPE_SERIAL, + .priority = DRIVER_PRIORITY_BASIC, + .ops = &serial_device_driver_ops, + .state = DRIVER_STATE_UNREGISTERED, +}; + +const uint16_t serial_ports[] = { + SERIAL_COM1_BASE, + SERIAL_COM2_BASE, + SERIAL_COM3_BASE, + SERIAL_COM4_BASE, +}; +const int serial_irqs[] = { + SERIAL_COM1_IRQ, + SERIAL_COM2_IRQ, + SERIAL_COM3_IRQ, + SERIAL_COM4_IRQ, +}; + +string_t name = STRING_INIT("Serial"); + +void serial_irq_handler(Device *device) { + SerialDevice *serial_device = device->dm_ext; + Serial *serial = device->private_data; + uint16_t base_port = serial->base_port; + uint8_t status = + io_in_byte(base_port + SERIAL_UART_REG_INTERRUPT_IDENTIFICATION); + + // 判断中断类型 + if (!(status & 0x01)) { + // 接收数据可用 + while (io_in_byte(base_port + SERIAL_UART_REG_LINE_STATUS) & 0x01) { + uint8_t data = io_in_byte(base_port + SERIAL_UART_REG_DATA); + // 处理接收到的数据(例如存入缓冲区) + if (serial_device->receive != NULL) { + serial_device->receive(data); + } + io_out_byte(base_port + SERIAL_UART_REG_DATA, data); // 回显 + } + } + if (status & 0x02) { + // 发送缓冲区空 + // 可以发送更多数据 + } + if (status & 0x04) { + // 接收线路状态改变 + } + if (status & 0x08) { + // 接收数据超时 + } + if (status & 0x10) { + // 接收FIFO达到触发点 + } +} + +bool serial_probe(int base_port) { + io_out_byte(base_port + SERIAL_UART_REG_SCRATCH, SERIAL_TEST_MAGIC_1); + uint8_t val = io_in_byte(base_port + SERIAL_UART_REG_SCRATCH); + if (val != SERIAL_TEST_MAGIC_1) return false; + io_out_byte(base_port + SERIAL_UART_REG_SCRATCH, SERIAL_TEST_MAGIC_2); + val = io_in_byte(base_port + SERIAL_UART_REG_SCRATCH); + return val == SERIAL_TEST_MAGIC_2; +} + +DriverResult serial_self_test(SerialDevice *serial_device) { + Serial *serial = serial_device->device->private_data; + uint16_t base_port = serial->base_port; + uint8_t val = io_in_byte(base_port + SERIAL_UART_REG_LINE_STATUS); + + // 禁用中断 + io_out_byte(base_port + SERIAL_UART_REG_INTERRUPT_ENABLE, 0x00); + + io_out_byte(base_port + SERIAL_UART_REG_MODEM_CONTROL, 0x1E); + // 测试发送和接收 + io_out_byte(base_port + SERIAL_UART_REG_DATA, 0x5A); + if (io_in_byte(base_port + SERIAL_UART_REG_DATA) != 0x5A) + return DRIVER_RESULT_OTHER_ERROR; + + io_out_byte(base_port + SERIAL_UART_REG_MODEM_CONTROL, 0x0F); + io_out_byte(base_port + SERIAL_UART_REG_INTERRUPT_ENABLE, val); + + return DRIVER_RESULT_OK; +} + +void serial_set_baud_rate( + SerialDevice *serial_device, SerialBaudRate baud_rate) { + Serial *serial = serial_device->device->private_data; + uint16_t base_port = serial->base_port; + + uint16_t divisor = SERIAL_RATE_DIVISION; + switch (baud_rate) { + case SERIAL_BAUD_115200: + divisor = SERIAL_RATE_115200_DIVISION; + break; + case SERIAL_BAUD_57600: + divisor = SERIAL_RATE_57600_DIVISION; + break; + case SERIAL_BAUD_38400: + divisor = SERIAL_RATE_38400_DIVISION; + break; + case SERIAL_BAUD_19200: + divisor = SERIAL_RATE_19200_DIVISION; + break; + case SERIAL_BAUD_9600: + divisor = SERIAL_RATE_9600_DIVISION; + break; + } + + // 启用 DLAB + io_out_byte(base_port + SERIAL_UART_REG_LINE_CONTROL, 0x80); + // 设置波特率 + io_out_byte(base_port + SERIAL_UART_REG_DIVISOR_LATCH_LOW, divisor & 0xff); + io_out_byte(base_port + SERIAL_UART_REG_DIVISOR_LATCH_HIGH, divisor >> 8); + // 禁用 DLAB + io_out_byte(base_port + SERIAL_UART_REG_LINE_CONTROL, 0x03); +} + +void serial_set_recv_mode( + SerialDevice *serial_device, SerialReceiveMode recv_mode) { + Serial *serial = serial_device->device->private_data; + uint16_t base_port = serial->base_port; + if (recv_mode == SERIAL_RECV_MODE_HIGH_THROUGHPUT) { + // 启用 FIFO,清空接收和发送 FIFO,设置触发点为 14 字节 + io_out_byte(base_port + SERIAL_UART_REG_FIFO_CONTROL, 0xC7); + } else { + // 启用 FIFO,清空接收和发送 FIFO,设置触发点为 1 字节 + io_out_byte(base_port + SERIAL_UART_REG_FIFO_CONTROL, 0x81); + } +} + +DriverResult serial_init(Device *device) { + Serial *serial = device->private_data; + uint16_t base_port = serial->base_port; + + // 禁用中断 + io_out_byte(base_port + SERIAL_UART_REG_INTERRUPT_ENABLE, 0x00); + // 8 位数据位,无奇偶校验,1 位停止位,禁用 DLAB + io_out_byte(base_port + SERIAL_UART_REG_LINE_CONTROL, 0x03); + // 启用 FIFO,清空接收和发送 FIFO,设置触发点为 8 字节 + io_out_byte(base_port + SERIAL_UART_REG_FIFO_CONTROL, 0x87); + // 设置 RTS 和 DSR + io_out_byte(base_port + SERIAL_UART_REG_MODEM_CONTROL, 0x0B); + + DeviceIrq *irq = kmalloc(sizeof(DeviceIrq)); + irq->device = device; + irq->irq = serial->irq; + irq->handler = serial_irq_handler; + device->irq = irq; + register_device_irq(irq); + + return DRIVER_RESULT_OK; +} + +DriverResult serial_start(Device *device) { + Serial *serial = device->private_data; + uint16_t base_port = serial->base_port; + + // 启用接收中断 + io_out_byte(base_port + SERIAL_UART_REG_INTERRUPT_ENABLE, 0x01); + interrupt_enable_irq(serial->irq); + return DRIVER_RESULT_OK; +} + +void register_serial() { + serial_device_driver.ops = &serial_device_driver_ops; + register_device_driver(&core_driver, &serial_device_driver); + + for (int i = 0; i < sizeof(serial_ports) / sizeof(serial_ports[0]); i++) { + if (serial_probe(serial_ports[i])) { + SerialDevice *serial_device = kmalloc(sizeof(SerialDevice)); + Device *device = kmalloc(sizeof(Device)); + serial_device->device = device; + serial_device->ops = &serial_serial_device_ops; + device->name = name; + device->state = DEVICE_STATE_UNREGISTERED; + device->private_data_size = sizeof(Serial); + device->ops = &serial_device_ops; + device->max_child_device = 0; + + register_serial_device( + &serial_device_driver, device, &platform_bus, serial_device); + + Serial *serial = device->private_data; + serial->base_port = serial_ports[i]; + serial->irq = serial_irqs[i]; + serial->device = device; + } + } +} \ No newline at end of file diff --git a/src/arch/x86/include/drivers/serial.h b/src/arch/x86/include/drivers/serial.h new file mode 100644 index 0000000..e4fb401 --- /dev/null +++ b/src/arch/x86/include/drivers/serial.h @@ -0,0 +1,51 @@ +#ifndef _SERIAL_H +#define _SERIAL_H + +#include +#include +#include +#include +#include + +#define SERIAL_COM1_BASE 0x3F8 +#define SERIAL_COM2_BASE 0x2F8 +#define SERIAL_COM3_BASE 0x3E8 +#define SERIAL_COM4_BASE 0x2E8 + +#define SERIAL_RATE_115200_DIVISION 1 +#define SERIAL_RATE_57600_DIVISION 2 +#define SERIAL_RATE_38400_DIVISION 3 +#define SERIAL_RATE_19200_DIVISION 6 +#define SERIAL_RATE_9600_DIVISION 12 + +#define SERIAL_RATE_DIVISION SERIAL_RATE_115200_DIVISION + +#define SERIAL_COM1_IRQ 4 +#define SERIAL_COM2_IRQ 3 +#define SERIAL_COM3_IRQ 4 +#define SERIAL_COM4_IRQ 3 + +#define SERIAL_UART_REG_DATA 0 +#define SERIAL_UART_REG_DIVISOR_LATCH_LOW 0 +#define SERIAL_UART_REG_INTERRUPT_ENABLE 1 +#define SERIAL_UART_REG_DIVISOR_LATCH_HIGH 1 +#define SERIAL_UART_REG_INTERRUPT_IDENTIFICATION 2 +#define SERIAL_UART_REG_FIFO_CONTROL 2 +#define SERIAL_UART_REG_LINE_CONTROL 3 +#define SERIAL_UART_REG_MODEM_CONTROL 4 +#define SERIAL_UART_REG_LINE_STATUS 5 +#define SERIAL_UART_REG_MODEM_STATUS 6 +#define SERIAL_UART_REG_SCRATCH 7 + +#define SERIAL_TEST_MAGIC_1 0x55 +#define SERIAL_TEST_MAGIC_2 0xAA + +typedef struct { + Device *device; + uint16_t base_port; + uint8_t irq; +} Serial; + +void register_serial(); + +#endif \ No newline at end of file diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index c611496..9defca7 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -1,3 +1,4 @@ +#include "driver/serial/serial_dm.h" #include "stdint.h" #include #include @@ -6,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +67,7 @@ void platform_init() { bios_emu_init(); + register_serial(); register_vesa_display(); register_pic(); register_apic(); @@ -76,11 +79,20 @@ void platform_init() { if (cpu_check_feature(CPUID_FEAT_TSC)) rand_seed((uint32_t)read_tsc()); } +void serial_receive(uint8_t data) { + printk("%c", data); +} + void platform_start_devices() { + Object *serial_object; init_and_start(&vesa_display_device); init_console(); - print_features(); interrupt_dm_start(); // 启动由interrupt_dm选择的中断控制器 + + open_object_by_path("\\Device\\Serial0", &serial_object); + serial_device_open(serial_object, SERIAL_BAUD_115200, serial_receive); + + print_features(); DRV_RESULT_PRINT_CALL(init_and_start, &pit_device); DRV_RESULT_PRINT_CALL(init_and_start, &apic_timer_device); DRV_RESULT_PRINT_CALL(init_and_start, &rtc_device); diff --git a/src/driver/Makefile b/src/driver/Makefile index 5a4a0a4..ab34f77 100644 --- a/src/driver/Makefile +++ b/src/driver/Makefile @@ -4,6 +4,7 @@ SRC += timer/ SRC += network/ SRC += usb/ SRC += input/ +SRC += serial/ SRC += interrupt_dm.c SRC += video_dm.c SRC += video.c diff --git a/src/driver/serial/Makefile b/src/driver/serial/Makefile new file mode 100644 index 0000000..135a857 --- /dev/null +++ b/src/driver/serial/Makefile @@ -0,0 +1 @@ +SRC += serial_dm.c \ No newline at end of file diff --git a/src/driver/serial/serial_dm.c b/src/driver/serial/serial_dm.c new file mode 100644 index 0000000..6311c81 --- /dev/null +++ b/src/driver/serial/serial_dm.c @@ -0,0 +1,66 @@ +#include "kernel/driver.h" +#include "string.h" +#include +#include +#include +#include +#include +#include +#include +#include + +string_t serial_object = STRING_INIT("Serial"); + +DriverResult serial_dm_load(DeviceManager *manager); + +DeviceManagerOps serial_dm_ops = { + .dm_load = serial_dm_load, + .dm_unload = NULL, +}; +SerialDeviceManager serial_dm_ext; +DeviceManager serial_dm = { + .type = DEVICE_TYPE_SERIAL, + .ops = &serial_dm_ops, + .private_data = &serial_dm_ext, +}; + +DriverResult serial_dm_load(DeviceManager *manager) { + serial_dm_ext.device_count = 0; + return DRIVER_RESULT_OK; +} + +DriverResult register_serial_device( + DeviceDriver *device_driver, Device *device, Bus *bus, + SerialDevice *serial_device) { + device->dm_ext = serial_device; + device->device_driver = device_driver; + serial_device->device = device; + + int id = serial_dm_ext.device_count++; + string_t name; + string_new_with_number(&name, "Serial", 6, id); + ObjectAttr attr = device_object_attr; + register_device(device_driver, &name, bus, device, &attr); + + return DRIVER_RESULT_OK; +} + +DriverResult serial_device_open( + Object *serial_object, SerialBaudRate baud_rate, + void (*receive)(uint8_t data)) { + Device *device = serial_object->value.device; + SerialDevice *serial_device = device->dm_ext; + + DRIVER_RESULT_PASS(init_device(device)); + + serial_device->ops->set_baud_rate(serial_device, baud_rate); + serial_device->ops->set_recv_mode( + serial_device, SERIAL_RECV_MODE_LOW_LATENCY); + DRIVER_RESULT_PASS(serial_device->ops->self_test(serial_device)); + + serial_device->receive = receive; + + DRIVER_RESULT_PASS(start_device(device)); + + return DRIVER_RESULT_OK; +} diff --git a/src/include/driver/serial/serial_dm.h b/src/include/driver/serial/serial_dm.h new file mode 100644 index 0000000..6a4d2dc --- /dev/null +++ b/src/include/driver/serial/serial_dm.h @@ -0,0 +1,53 @@ +#ifndef _SERIAL_DM_H +#define _SERIAL_DM_H + +#include "kernel/driver.h" +#include +#include +#include +#include +#include + +typedef enum SerialBaudRate { + SERIAL_BAUD_115200, + SERIAL_BAUD_57600, + SERIAL_BAUD_38400, + SERIAL_BAUD_19200, + SERIAL_BAUD_9600, +} SerialBaudRate; + +typedef enum SerialReceiveMode { + SERIAL_RECV_MODE_LOW_LATENCY, + SERIAL_RECV_MODE_HIGH_THROUGHPUT, +} SerialReceiveMode; + +struct SerialDevice; +typedef struct SerialDeviceOps { + DriverResult (*self_test)(struct SerialDevice *serial); + void (*set_baud_rate)( + struct SerialDevice *serial, SerialBaudRate baud_rate); + void (*set_recv_mode)( + struct SerialDevice *serial, SerialReceiveMode recv_mode); +} SerialDeviceOps; + +typedef struct SerialDevice { + Device *device; + SerialDeviceOps *ops; + + void (*receive)(uint8_t data); +} SerialDevice; + +typedef struct SerialDeviceManager { + int device_count; +} SerialDeviceManager; + +extern DeviceManager serial_dm; + +DriverResult register_serial_device( + DeviceDriver *device_driver, Device *device, Bus *bus, + SerialDevice *serial_device); +DriverResult serial_device_open( + Object *serial_object, SerialBaudRate baud_rate, + void (*receive)(uint8_t data)); + +#endif \ No newline at end of file diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index 6826c78..adc90cd 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -32,6 +32,7 @@ typedef enum { DEVICE_TYPE_ETHERNET, DEVICE_TYPE_TIME, // 时间设备(如:Unix时间戳/UTC时间) DEVICE_TYPE_USB, + DEVICE_TYPE_SERIAL, DEVICE_TYPE_MAX, } DeviceType; @@ -124,6 +125,7 @@ DriverResult unregister_device( DriverResult unregister_child_device(ChildDevice *child_device); DriverResult register_child_device(Device *device, int private_data_size); DriverResult init_device(Device *device); +DriverResult start_device(Device *device); DriverResult init_and_start(Device *device); #endif \ No newline at end of file diff --git a/src/kernel/driver/device_manager.c b/src/kernel/driver/device_manager.c index c433358..a015de0 100644 --- a/src/kernel/driver/device_manager.c +++ b/src/kernel/driver/device_manager.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -15,6 +16,7 @@ DriverResult register_device_manager(DeviceManager *manager) { list_init(&manager->device_lh); device_managers[manager->type] = manager; + list_add_tail(&manager->dm_list, &device_driver_manager.dm_lh); if (manager->ops->dm_load != NULL) { DRV_RESULT_DELIVER_CALL(manager->ops->dm_load, manager); } From 2a2b22d4e57fc44a69669ca85039d1dfefa10cba Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 24 Sep 2025 22:06:00 +0800 Subject: [PATCH 137/158] =?UTF-8?q?driver:=20=E4=BF=AE=E6=94=B9VIDEO?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E7=B1=BB=E5=9E=8B=E5=90=8D=E4=B8=BAFRAMEBUFF?= =?UTF-8?q?ER?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/vesa_display.c | 25 ++-- src/driver/Makefile | 3 +- src/driver/framebuffer/Makefile | 2 + .../{video.c => framebuffer/framebuffer.c} | 62 +++++----- src/driver/framebuffer/framebuffer_dm.c | 115 ++++++++++++++++++ src/driver/video_dm.c | 113 ----------------- .../driver/{video.h => framebuffer/fb.h} | 22 ++-- src/include/driver/framebuffer/fb_dm.h | 42 +++++++ src/include/driver/video_dm.h | 41 ------- src/include/kernel/device.h | 2 +- src/kernel/console.c | 38 +++--- src/kernel/main.c | 77 ++++-------- 12 files changed, 257 insertions(+), 285 deletions(-) create mode 100644 src/driver/framebuffer/Makefile rename src/driver/{video.c => framebuffer/framebuffer.c} (72%) create mode 100644 src/driver/framebuffer/framebuffer_dm.c delete mode 100644 src/driver/video_dm.c rename src/include/driver/{video.h => framebuffer/fb.h} (52%) create mode 100644 src/include/driver/framebuffer/fb_dm.h delete mode 100644 src/include/driver/video_dm.h diff --git a/src/arch/x86/drivers/vesa_display.c b/src/arch/x86/drivers/vesa_display.c index 929cc9e..e30ae72 100644 --- a/src/arch/x86/drivers/vesa_display.c +++ b/src/arch/x86/drivers/vesa_display.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -29,7 +29,7 @@ DeviceOps vesa_display_device_ops = { DeviceDriver vesa_display_device_driver = { .name = STRING_INIT("VESA Display Device Driver"), - .type = DEVICE_TYPE_VIDEO, + .type = DEVICE_TYPE_FRAMEBUFFER, .priority = DRIVER_PRIORITY_BASIC, .state = DRIVER_STATE_UNREGISTERED, .ops = &vesa_display_driver_ops, @@ -41,16 +41,16 @@ Device vesa_display_device = { .ops = &vesa_display_device_ops, .private_data_size = 0, }; -VideoDevice vesa_display_video_device = { +FrameBufferDevice vesa_display_fb_device = { .device = &vesa_display_device, }; void register_vesa_display(void) { register_device_driver(&core_driver, &vesa_display_device_driver); ObjectAttr attr = device_object_attr; - register_video_device( + register_framebuffer_device( &vesa_display_device_driver, &vesa_display_device, - &vesa_display_video_device, &attr); + &vesa_display_fb_device, &attr); } #define SEG_ADDR2LINEAR_ADDR(addr) \ @@ -72,14 +72,13 @@ DriverResult vesa_display_device_init(Device *device) { } DriverResult vesa_display_device_start(Device *device) { - vesa_display_info.vram = (uint8_t *)VRAM_VIR_ADDR; - VideoDevice *video_device = device->dm_ext; - video_device->mode_info.width = vesa_display_info.width; - video_device->mode_info.height = vesa_display_info.height; - video_device->mode_info.bits_per_pixel = vesa_display_info.BitsPerPixel; - video_device->mode_info.bytes_per_pixel = - vesa_display_info.BitsPerPixel / 8; - video_device->framebuffer_address = vesa_display_info.vram; + vesa_display_info.vram = (uint8_t *)VRAM_VIR_ADDR; + FrameBufferDevice *fb_device = device->dm_ext; + fb_device->mode_info.width = vesa_display_info.width; + fb_device->mode_info.height = vesa_display_info.height; + fb_device->mode_info.bits_per_pixel = vesa_display_info.BitsPerPixel; + fb_device->mode_info.bytes_per_pixel = vesa_display_info.BitsPerPixel / 8; + fb_device->framebuffer_address = vesa_display_info.vram; return DRIVER_RESULT_OK; } diff --git a/src/driver/Makefile b/src/driver/Makefile index ab34f77..e9a42a6 100644 --- a/src/driver/Makefile +++ b/src/driver/Makefile @@ -5,8 +5,7 @@ SRC += network/ SRC += usb/ SRC += input/ SRC += serial/ +SRC += framebuffer/ SRC += interrupt_dm.c -SRC += video_dm.c -SRC += video.c SRC += bus_dm.c SRC += time_dm.c \ No newline at end of file diff --git a/src/driver/framebuffer/Makefile b/src/driver/framebuffer/Makefile new file mode 100644 index 0000000..70e0116 --- /dev/null +++ b/src/driver/framebuffer/Makefile @@ -0,0 +1,2 @@ +SRC += framebuffer_dm.c +SRC += framebuffer.c \ No newline at end of file diff --git a/src/driver/video.c b/src/driver/framebuffer/framebuffer.c similarity index 72% rename from src/driver/video.c rename to src/driver/framebuffer/framebuffer.c index 18d8897..5f2ddf8 100644 --- a/src/driver/video.c +++ b/src/driver/framebuffer/framebuffer.c @@ -1,8 +1,8 @@ -#include -#include +#include +#include #include -extern struct VideoDeviceManager video_dm_ext; +extern struct FrameBufferDeviceManager video_dm_ext; void write_pixel_rgbto8(uint8_t *vram, uint8_t r, uint8_t g, uint8_t b) { *vram = (r * 6 / 256) + (g * 6 / 256) * 6 + (b * 6 / 256) * 36; } @@ -65,11 +65,11 @@ FramebufferOps fb_ops_32 = { * @param color 颜色 */ void inline write_pixel( - VideoDevice *video_device, int x, int y, uint32_t color) { - uint8_t *vram = video_device->framebuffer_address; - vram += (y * video_device->mode_info.width + x) * - (video_device->mode_info.bits_per_pixel / 8); - video_device->framebuffer_ops->write_pixel_raw(vram, color); + FrameBufferDevice *fb_device, int x, int y, uint32_t color) { + uint8_t *vram = fb_device->framebuffer_address; + vram += (y * fb_device->mode_info.width + x) * + (fb_device->mode_info.bits_per_pixel / 8); + fb_device->framebuffer_ops->write_pixel_raw(vram, color); } /** @@ -82,17 +82,18 @@ void inline write_pixel( * @param b 蓝色 */ void inline write_pixel_rgb( - VideoDevice *video_device, int x, int y, uint8_t r, uint8_t g, uint8_t b) { - uint8_t *vram = video_device->framebuffer_address; - vram += (y * video_device->mode_info.width + x) * - (video_device->mode_info.bits_per_pixel / 8); - video_device->framebuffer_ops->write_pixel_rgb(vram, r, g, b); + FrameBufferDevice *fb_device, int x, int y, uint8_t r, uint8_t g, + uint8_t b) { + uint8_t *vram = fb_device->framebuffer_address; + vram += (y * fb_device->mode_info.width + x) * + (fb_device->mode_info.bits_per_pixel / 8); + fb_device->framebuffer_ops->write_pixel_rgb(vram, r, g, b); } /** * @brief 画矩形 * - * @param video_device 显示设备 + * @param fb_device 显示设备 * @param x x坐标 * @param y y坐标 * @param width 宽度 @@ -100,15 +101,16 @@ void inline write_pixel_rgb( * @param color 颜色 */ void draw_rect( - VideoDevice *video_device, int x, int y, int width, int height, int color) { - int bpp = video_device->mode_info.bytes_per_pixel; + FrameBufferDevice *fb_device, int x, int y, int width, int height, + int color) { + int bpp = fb_device->mode_info.bytes_per_pixel; int x0, y0; - uint8_t *vram = video_device->framebuffer_address + - (y * video_device->mode_info.width + x) * bpp; - int delta = (video_device->mode_info.width - width) * bpp; + uint8_t *vram = fb_device->framebuffer_address + + (y * fb_device->mode_info.width + x) * bpp; + int delta = (fb_device->mode_info.width - width) * bpp; for (y0 = 0; y0 < height; y0++) { for (x0 = 0; x0 < width; x0++) { - video_device->framebuffer_ops->write_pixel_raw(vram, color); + fb_device->framebuffer_ops->write_pixel_raw(vram, color); vram += bpp; } vram += delta; @@ -127,16 +129,16 @@ void draw_rect( * @param b 蓝色 */ void draw_rect_rgb( - VideoDevice *video_device, int x, int y, int width, int height, uint8_t r, - uint8_t g, uint8_t b) { - int bpp = video_device->mode_info.bytes_per_pixel; + FrameBufferDevice *fb_device, int x, int y, int width, int height, + uint8_t r, uint8_t g, uint8_t b) { + int bpp = fb_device->mode_info.bytes_per_pixel; int x0, y0; - uint8_t *vram = video_device->framebuffer_address + - (y * video_device->mode_info.width + x) * bpp; - int delta = (video_device->mode_info.width - width) * bpp; + uint8_t *vram = fb_device->framebuffer_address + + (y * fb_device->mode_info.width + x) * bpp; + int delta = (fb_device->mode_info.width - width) * bpp; for (y0 = y; y0 < y + height; y0++) { for (x0 = 0; x0 < width; x0++) { - video_device->framebuffer_ops->write_pixel_rgb(vram, r, g, b); + fb_device->framebuffer_ops->write_pixel_rgb(vram, r, g, b); vram += bpp; } vram += delta; @@ -152,7 +154,7 @@ void draw_rect_rgb( * @param color 颜色 */ void print_word( - FramebufferOps *ops, VideoModeInfo *mode_info, uint8_t *vram, + FramebufferOps *ops, FrameBufferModeInfo *mode_info, uint8_t *vram, uint8_t *ascii, int color) { int i; char d; @@ -191,8 +193,8 @@ void print_word( * @param b 蓝色 */ void print_word_rgb( - FramebufferOps *ops, VideoModeInfo *mode_info, uint8_t *vram, char *ascii, - uint8_t r, uint8_t g, uint8_t b) { + FramebufferOps *ops, FrameBufferModeInfo *mode_info, uint8_t *vram, + char *ascii, uint8_t r, uint8_t g, uint8_t b) { int i; char d; uint8_t bpp = mode_info->bytes_per_pixel; diff --git a/src/driver/framebuffer/framebuffer_dm.c b/src/driver/framebuffer/framebuffer_dm.c new file mode 100644 index 0000000..2c5143a --- /dev/null +++ b/src/driver/framebuffer/framebuffer_dm.c @@ -0,0 +1,115 @@ +#include "objects/object.h" +#include +#include +#include +#include +#include +#include +#include +#include + +DriverResult framebuffer_device_start(DeviceManager *manager, Device *device); + +DeviceManagerOps framebuffer_dm_ops = { + .dm_load = NULL, + .dm_unload = NULL, + + .init_device_hook = NULL, + .start_device_hook = framebuffer_device_start, + .stop_device_hook = NULL, + .destroy_device_hook = NULL, +}; + +FrameBufferDeviceManager framebuffer_dm_ext; + +struct DeviceManager framebuffer_dm = { + .type = DEVICE_TYPE_FRAMEBUFFER, + + .ops = &framebuffer_dm_ops, + + .private_data = &framebuffer_dm_ext, +}; + +DriverResult framebuffer_dm_load(DeviceManager *manager) { + FrameBufferDeviceManager *framebuffer_manager = manager->private_data; + framebuffer_manager->main_display_device = NULL; + + return DRIVER_RESULT_OK; +} + +DriverResult framebuffer_dm_unload(DeviceManager *manager) { + FrameBufferDeviceManager *framebuffer_manager = manager->private_data; + framebuffer_manager->main_display_device = NULL; + + return DRIVER_RESULT_OK; +} + +DriverResult register_framebuffer_device( + DeviceDriver *device_driver, Device *device, + FrameBufferDevice *framebuffer_device, ObjectAttr *attr) { + device->dm_ext = framebuffer_device; + if (device->dm_ext == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } + framebuffer_device->device = device; + + string_t name; + string_new_with_number( + &name, "FrameBuffer", 5, framebuffer_dm_ext.fb_device_count++); + + DRV_RESULT_DELIVER_CALL( + register_device, device_driver, &name, device->bus, device, attr); + + list_init(&framebuffer_device->fb_list_lh); + list_add_tail(&device->dm_list, &framebuffer_dm.device_lh); + + return DRIVER_RESULT_OK; +} + +DriverResult unregister_framebuffer_devce( + DeviceDriver *device_driver, Device *device, + FrameBufferDevice *framebuffer_device) { + list_del(&framebuffer_device->fb_list_lh); + return DRIVER_RESULT_OK; +} + +DriverResult framebuffer_device_start(DeviceManager *manager, Device *device) { + FrameBufferDevice *framebuffer_device = (FrameBufferDevice *)device->dm_ext; + + if (framebuffer_dm_ext.main_display_device == NULL) { + framebuffer_dm_ext.main_display_device = device; + } + if (framebuffer_device->framebuffer_address == NULL) { + return DRIVER_RESULT_OTHER_ERROR; + } + if (framebuffer_device->mode_info.bits_per_pixel == 8) { + framebuffer_device->framebuffer_ops = &fb_ops_8; + } else if (framebuffer_device->mode_info.bits_per_pixel == 16) { + framebuffer_device->framebuffer_ops = &fb_ops_16; + } else if (framebuffer_device->mode_info.bits_per_pixel == 24) { + framebuffer_device->framebuffer_ops = &fb_ops_24; + } else if (framebuffer_device->mode_info.bits_per_pixel == 32) { + framebuffer_device->framebuffer_ops = &fb_ops_32; + } else { + return DRIVER_RESULT_UNSUPPORT_FEATURE; + } + + return DRIVER_RESULT_OK; +} + +DriverResult framebuffer_get_device( + int in_index, FrameBufferDevice **out_device) { + Device *device; + if (in_index == 0) { + *out_device = framebuffer_dm_ext.main_display_device->dm_ext; + return DRIVER_RESULT_OK; + } + int i = 0; + list_for_each_owner (device, &framebuffer_dm.device_lh, dm_list) { + if (device == framebuffer_dm_ext.main_display_device) { continue; } + if (i == in_index) { + *out_device = device->dm_ext; + return DRIVER_RESULT_OK; + } + i++; + } + return DRIVER_RESULT_NOT_EXIST; +} diff --git a/src/driver/video_dm.c b/src/driver/video_dm.c deleted file mode 100644 index 6988e6f..0000000 --- a/src/driver/video_dm.c +++ /dev/null @@ -1,113 +0,0 @@ -#include "objects/object.h" -#include -#include -#include -#include -#include -#include -#include -#include - -DriverResult video_device_start(DeviceManager *manager, Device *device); - -DeviceManagerOps video_dm_ops = { - .dm_load = NULL, - .dm_unload = NULL, - - .init_device_hook = NULL, - .start_device_hook = video_device_start, - .stop_device_hook = NULL, - .destroy_device_hook = NULL, -}; - -VideoDeviceManager video_dm_ext; - -struct DeviceManager video_dm = { - .type = DEVICE_TYPE_VIDEO, - - .ops = &video_dm_ops, - - .private_data = &video_dm_ext, -}; - -DriverResult video_dm_load(DeviceManager *manager) { - VideoDeviceManager *video_manager = manager->private_data; - video_manager->main_display_device = NULL; - - return DRIVER_RESULT_OK; -} - -DriverResult video_dm_unload(DeviceManager *manager) { - VideoDeviceManager *video_manager = manager->private_data; - video_manager->main_display_device = NULL; - - return DRIVER_RESULT_OK; -} - -DriverResult register_video_device( - DeviceDriver *device_driver, Device *device, VideoDevice *video_device, - ObjectAttr *attr) { - device->dm_ext = video_device; - if (device->dm_ext == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } - video_device->device = device; - - string_t name; - string_new_with_number( - &name, "Video", 5, video_dm_ext.video_device_count++); - - DRV_RESULT_DELIVER_CALL( - register_device, device_driver, &name, device->bus, device, attr); - - list_init(&video_device->video_list_lh); - list_add_tail(&device->dm_list, &video_dm.device_lh); - - return DRIVER_RESULT_OK; -} - -DriverResult unregister_video_devce( - DeviceDriver *device_driver, Device *device, VideoDevice *video_device) { - list_del(&video_device->video_list_lh); - return DRIVER_RESULT_OK; -} - -DriverResult video_device_start(DeviceManager *manager, Device *device) { - VideoDevice *video_device = (VideoDevice *)device->dm_ext; - - if (video_dm_ext.main_display_device == NULL) { - video_dm_ext.main_display_device = device; - } - if (video_device->framebuffer_address == NULL) { - return DRIVER_RESULT_OTHER_ERROR; - } - if (video_device->mode_info.bits_per_pixel == 8) { - video_device->framebuffer_ops = &fb_ops_8; - } else if (video_device->mode_info.bits_per_pixel == 16) { - video_device->framebuffer_ops = &fb_ops_16; - } else if (video_device->mode_info.bits_per_pixel == 24) { - video_device->framebuffer_ops = &fb_ops_24; - } else if (video_device->mode_info.bits_per_pixel == 32) { - video_device->framebuffer_ops = &fb_ops_32; - } else { - return DRIVER_RESULT_UNSUPPORT_FEATURE; - } - - return DRIVER_RESULT_OK; -} - -DriverResult video_get_video_device(int in_index, VideoDevice **out_device) { - Device *device; - if (in_index == 0) { - *out_device = video_dm_ext.main_display_device->dm_ext; - return DRIVER_RESULT_OK; - } - int i = 0; - list_for_each_owner (device, &video_dm.device_lh, dm_list) { - if (device == video_dm_ext.main_display_device) { continue; } - if (i == in_index) { - *out_device = device->dm_ext; - return DRIVER_RESULT_OK; - } - i++; - } - return DRIVER_RESULT_NOT_EXIST; -} diff --git a/src/include/driver/video.h b/src/include/driver/framebuffer/fb.h similarity index 52% rename from src/include/driver/video.h rename to src/include/driver/framebuffer/fb.h index 7b5de28..6c5c65b 100644 --- a/src/include/driver/video.h +++ b/src/include/driver/framebuffer/fb.h @@ -1,6 +1,6 @@ -#ifndef _DRIVER_VIDEO_H -#define _DRIVER_VIDEO_H -// TODO: video.h改名 +#ifndef _DRIVER_FRAMEBUFFER_H +#define _DRIVER_FRAMEBUFFER_H + #include "stdint.h" typedef struct FramebufferOps { @@ -8,24 +8,24 @@ typedef struct FramebufferOps { void (*write_pixel_rgb)(uint8_t *vram, uint8_t r, uint8_t g, uint8_t b); } FramebufferOps; -struct VideoDevice; -struct VideoModeInfo; +struct FrameBufferDevice; +struct FrameBufferModeInfo; void inline write_pixel( - struct VideoDevice *video_device, int x, int y, uint32_t color); + struct FrameBufferDevice *fb_device, int x, int y, uint32_t color); void inline write_pixel_rgb( - struct VideoDevice *video_device, int x, int y, uint8_t r, uint8_t g, + struct FrameBufferDevice *fb_device, int x, int y, uint8_t r, uint8_t g, uint8_t b); void draw_rect( - struct VideoDevice *video_device, int x, int y, int width, int height, + struct FrameBufferDevice *fb_device, int x, int y, int width, int height, int color); void draw_rect_rgb( - struct VideoDevice *video_device, int x, int y, int width, int height, + struct FrameBufferDevice *fb_device, int x, int y, int width, int height, uint8_t r, uint8_t g, uint8_t b); void print_word( - FramebufferOps *ops, struct VideoModeInfo *mode_info, uint8_t *vram, + FramebufferOps *ops, struct FrameBufferModeInfo *mode_info, uint8_t *vram, uint8_t *ascii, int color); void print_word_rgb( - FramebufferOps *ops, struct VideoModeInfo *mode_info, uint8_t *vram, + FramebufferOps *ops, struct FrameBufferModeInfo *mode_info, uint8_t *vram, char *ascii, uint8_t r, uint8_t g, uint8_t b); extern FramebufferOps fb_ops_8; diff --git a/src/include/driver/framebuffer/fb_dm.h b/src/include/driver/framebuffer/fb_dm.h new file mode 100644 index 0000000..7c16934 --- /dev/null +++ b/src/include/driver/framebuffer/fb_dm.h @@ -0,0 +1,42 @@ +#ifndef _FRAMEBUFFER_DM_H +#define _FRAMEBUFFER_DM_H + +#include "kernel/device.h" +#include "kernel/device_driver.h" +#include "kernel/list.h" +#include "objects/object.h" +#include "stdint.h" +#include + +typedef struct FrameBufferModeInfo { + uint16_t width; + uint16_t height; + uint8_t bits_per_pixel; + uint8_t bytes_per_pixel; +} FrameBufferModeInfo; + +typedef struct FrameBufferDevice { + list_t fb_list_lh; + + Device *device; + FrameBufferModeInfo mode_info; + uint8_t *framebuffer_address; + + FramebufferOps *framebuffer_ops; +} FrameBufferDevice; + +typedef struct FrameBufferDeviceManager { + Device *main_display_device; + uint8_t fb_device_count; +} FrameBufferDeviceManager; + +extern struct DeviceManager framebuffer_dm; + +DriverResult register_framebuffer_device( + DeviceDriver *device_driver, Device *device, FrameBufferDevice *fb_device, + ObjectAttr *attr); +DriverResult unregister_framebuffer_devce( + DeviceDriver *device_driver, Device *device, FrameBufferDevice *fb_device); +DriverResult framebuffer_get_device( + int in_index, FrameBufferDevice **out_device); +#endif \ No newline at end of file diff --git a/src/include/driver/video_dm.h b/src/include/driver/video_dm.h deleted file mode 100644 index 39f22e3..0000000 --- a/src/include/driver/video_dm.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _VIDEO_DM_H -#define _VIDEO_DM_H - -#include "driver/video.h" -#include "kernel/device.h" -#include "kernel/device_driver.h" -#include "kernel/list.h" -#include "objects/object.h" -#include "stdint.h" - -typedef struct VideoModeInfo { - uint16_t width; - uint16_t height; - uint8_t bits_per_pixel; - uint8_t bytes_per_pixel; -} VideoModeInfo; - -typedef struct VideoDevice { - list_t video_list_lh; - - Device *device; - VideoModeInfo mode_info; - uint8_t *framebuffer_address; - - FramebufferOps *framebuffer_ops; -} VideoDevice; - -typedef struct VideoDeviceManager { - Device *main_display_device; - uint8_t video_device_count; -} VideoDeviceManager; - -extern struct DeviceManager video_dm; - -DriverResult register_video_device( - DeviceDriver *device_driver, Device *device, VideoDevice *video_device, - ObjectAttr *attr); -DriverResult unregister_video_devce( - DeviceDriver *device_driver, Device *device, VideoDevice *video_device); -DriverResult video_get_video_device(int in_index, VideoDevice **out_device); -#endif \ No newline at end of file diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index adc90cd..e608e42 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -24,7 +24,7 @@ typedef enum { DEVICE_TYPE_UNKNOWN = 0, DEVICE_TYPE_INTERRUPT_CONTROLLER, DEVICE_TYPE_TIMER, // 定时器设备 - DEVICE_TYPE_VIDEO, + DEVICE_TYPE_FRAMEBUFFER, DEVICE_TYPE_STORAGE, DEVICE_TYPE_INPUT, DEVICE_TYPE_SOUND, diff --git a/src/kernel/console.c b/src/kernel/console.c index 300a5eb..df9ae0d 100644 --- a/src/kernel/console.c +++ b/src/kernel/console.c @@ -5,8 +5,8 @@ * @version 0.3 * @date 2022-07-15 */ -#include -#include +#include +#include #include #include #include @@ -16,7 +16,7 @@ #include struct console { - struct VideoDevice *video_device; + FrameBufferDevice *fb_device; uint8_t *vram; uint8_t *cur_vram; @@ -37,15 +37,15 @@ struct console console; * */ void init_console(void) { - video_get_video_device(0, &console.video_device); + framebuffer_get_device(0, &console.fb_device); - console.vram = console.video_device->framebuffer_address; + console.vram = console.fb_device->framebuffer_address; console.cur_vram = console.vram; console.font = font16; console.cur_x = 0; console.cur_y = 0; - console.width = console.video_device->mode_info.width / 10; - console.height = console.video_device->mode_info.height / 16; + console.width = console.fb_device->mode_info.width / 10; + console.height = console.fb_device->mode_info.height / 16; console.color = 0xc0c0c0; console.flag = CMD_FLAG_OUTPUT; } @@ -107,9 +107,9 @@ void console_input(char c) void scroll_screen(void) { int i, j; - int screen_width = console.video_device->mode_info.width; - int screen_height = console.video_device->mode_info.height; - int bpp = console.video_device->mode_info.bytes_per_pixel; + int screen_width = console.fb_device->mode_info.width; + int screen_height = console.fb_device->mode_info.height; + int bpp = console.fb_device->mode_info.bytes_per_pixel; uint32_t *dst = (uint32_t *)console.vram; uint32_t *src = (uint32_t *)(console.vram + 16 * screen_width * bpp); @@ -120,7 +120,7 @@ void scroll_screen(void) { src += 1; } } - draw_rect(console.video_device, 0, screen_height - 16, screen_width, 16, 0); + draw_rect(console.fb_device, 0, screen_height - 16, screen_width, 16, 0); } /** @@ -131,14 +131,14 @@ void scroll_screen(void) { */ void print_char(unsigned char c, unsigned int color) { if (c > 127) { c = '?'; } - int bpp = console.video_device->mode_info.bytes_per_pixel; + int bpp = console.fb_device->mode_info.bytes_per_pixel; print_word( - console.video_device->framebuffer_ops, &console.video_device->mode_info, + console.fb_device->framebuffer_ops, &console.fb_device->mode_info, console.cur_vram + 1 * bpp, console.font + c * 16, color); console.cur_x++; console.cur_vram += 10 * bpp; if (console.cur_x >= console.width) { - int screen_width = console.video_device->mode_info.width; + int screen_width = console.fb_device->mode_info.width; console.cur_x = 0; console.cur_y++; console.cur_vram = @@ -164,8 +164,8 @@ int printk(const char *fmt, ...) { char *p = buf, c; int len = i; - int bpp = console.video_device->mode_info.bytes_per_pixel; - int screen_width = console.video_device->mode_info.width; + int bpp = console.fb_device->mode_info.bytes_per_pixel; + int screen_width = console.fb_device->mode_info.width; while (len) { c = *p++; if (c == '<' && len == i) { @@ -243,7 +243,7 @@ int printk(const char *fmt, ...) { console.cur_x--; console.cur_vram -= 10 * bpp; draw_rect( - console.video_device, console.cur_x * 10 + 1, + console.fb_device, console.cur_x * 10 + 1, console.cur_y * 16, 8, 16, 0); } } @@ -258,8 +258,8 @@ int printk(const char *fmt, ...) { break; default: draw_rect( - console.video_device, console.cur_x * 10, console.cur_y * 16, - 10, 16, 0); + console.fb_device, console.cur_x * 10, console.cur_y * 16, 10, + 16, 0); print_char(c, color); break; } diff --git a/src/kernel/main.c b/src/kernel/main.c index 58d00cd..93bb5f6 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -4,18 +4,20 @@ * @brief 内核主程序 * @date 2020-03 */ -#include "driver/network/buffer.h" +#include "driver/input/input_dm.h" +#include "driver/network/network_dm.h" #include #include #include +#include #include #include #include -#include -#include -#include +#include +#include #include #include +#include #include #include #include @@ -23,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -35,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -117,17 +119,20 @@ int main() { uint8_t *zero = 0; + init_object_tree(); + register_driver_manager(&device_driver_manager); register_driver_manager(&bus_driver_manager); register_device_manager(&interrupt_dm); register_device_manager(&timer_dm); register_device_manager(&time_dm); - register_device_manager(&video_dm); + register_device_manager(&framebuffer_dm); register_device_manager(&sound_dm); register_device_manager(&storage_dm); register_device_manager(&network_dm); - - init_object_tree(); + register_device_manager(&usb_dm); + register_device_manager(&input_dm); + register_device_manager(&serial_dm); register_driver(&core_driver); driver_init(&core_driver); @@ -146,6 +151,10 @@ int main() { do_initcalls(); driver_start_all(); + thread_start( + "Dynamic Device Manager", THREAD_DEFAULT_PRIO, dynamic_device_manager, + NULL, NULL); + Object *net; ObjectResult result = open_object_by_path("\\Device\\Network0", &net); if (result == OBJECT_OK) { @@ -175,10 +184,10 @@ int main() { // bios_emu_env.regs.ax = 0x4f02; // bios_emu_env.regs.bx = 0x4192; // 1920x1080x32bit模式 // BiosEmuExceptions exception = emu_interrupt(0x10); // 调用BIOS 0x10中断 - // VideoDevice *video_device; - // video_get_video_device(0, &video_device); - // video_device->mode_info.width = 1920; - // video_device->mode_info.height = 1080; + // FrameBufferDevice *fb_device; + // framebuffer_get_device(0, &fb_device); + // fb_device->mode_info.width = 1920; + // fb_device->mode_info.height = 1080; // init_console(); // 重置控制台配置 // if (exception == EventInterruptDone) { // printk("VBE Call Result: %d\n", bios_emu_env.regs.ax); @@ -206,48 +215,6 @@ int main() { // show_object_tree(); - // thread_start( - // "NetworkRxPacketProcess", THREAD_DEFAULT_PRIO, net_process_pack, - // NULL); - - // int ret = dhcp_main(default_net_dev); - // while (ret == -4) { - // ret = dhcp_main(default_net_dev); - // } - // if (ret < 0) { printk("[DHCP]ipv4 address request failed!\n"); } - // struct ipv4_data *ipv4 = default_net_dev->info->ipv4_data; - // memcpy(ipv4->ip_addr, (uint8_t[4]){10, 0, 2, 15}, 4); - // memcpy(ipv4->router_ip, (uint8_t[4]){10, 0, 2, 2}, 4); - - // uint8_t dst_ip[4] = {180, 101, 50, 188}, *router_mac; - // netc_t *netc = netc_create(default_net_dev, ETH_TYPE_ARP, 0); - // netc_set_dest(netc, broadcast_mac, NULL, 0); - // router_mac = ip2mac( - // netc, ((struct ipv4_data - // *)netc->net_dev->info->ipv4_data)->router_ip); netc_delete(netc); - - // netc = netc_create(default_net_dev, ETH_TYPE_IPV4, PROTOCOL_TCP); - // netc_set_dest(netc, router_mac, dst_ip, 4); - // tcp_create(netc); - // tcp_bind(netc, 12345); - // tcp_ipv4_connect(netc, dst_ip, 80); - // uint8_t data[] = "GET / HTTP/1.1\r\nHost: - // 180.101.50.188\r\nAccept: " - // "*/*\r\nConnection: keep-alive\r\n\r\n"; - // uint8_t *rb = kmalloc(2048); - // tcp_write(netc, data, sizeof(data)); - // int len = 10499; - // int i, tmp; - // do { - // tmp = tcp_read(netc, rb, 1152); - // len -= tmp; - // // for (i = 0; i < tmp; i++) { - // // printk("%c", rb[i]); - // // } - // } while (len > 0); - // printk("\nend.\n"); - // tcp_ipv4_close(netc); - console_start(); thread_exit(); From e76f62a83121634d4f88b0a4de2965206fe08a46 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 25 Sep 2025 20:11:56 +0800 Subject: [PATCH 138/158] =?UTF-8?q?console:=20=E9=87=8D=E6=9E=84console?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81FrameBuffer=E5=92=8CSerial=E5=90=8E?= =?UTF-8?q?=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- src/arch/x86/drivers/serial.c | 32 +- src/arch/x86/drivers/smbios.c | 15 +- src/arch/x86/include/drivers/serial.h | 3 + src/driver/framebuffer/Makefile | 3 +- src/driver/framebuffer/console_backend.c | 278 ++++++++++++++++++ src/driver/framebuffer/framebuffer.c | 16 +- src/driver/framebuffer/framebuffer_dm.c | 38 ++- .../driver/framebuffer/console_backend.h | 48 +++ src/include/driver/framebuffer/fb_dm.h | 4 + src/include/kernel/console.h | 71 +++-- src/include/kernel/driver_interface.h | 14 +- src/kernel/console.c | 272 ++--------------- src/kernel/driver/device.c | 2 + 14 files changed, 492 insertions(+), 306 deletions(-) create mode 100644 src/driver/framebuffer/console_backend.c create mode 100644 src/include/driver/framebuffer/console_backend.h diff --git a/Makefile b/Makefile index 04a8b22..5ea9845 100644 --- a/Makefile +++ b/Makefile @@ -119,7 +119,7 @@ qemu_dbg: qemu: $(QEMU) \ -no-reboot \ - -monitor stdio \ + -serial stdio \ -m 1024 \ -drive file=$(HD_IMG),if=ide,format=raw \ -usb \ diff --git a/src/arch/x86/drivers/serial.c b/src/arch/x86/drivers/serial.c index 2e7786d..dc3561b 100644 --- a/src/arch/x86/drivers/serial.c +++ b/src/arch/x86/drivers/serial.c @@ -3,6 +3,7 @@ #include "driver/serial/serial_dm.h" #include "string.h" #include +#include #include #include #include @@ -22,6 +23,8 @@ void serial_set_recv_mode( SerialDevice *serial_device, SerialReceiveMode recv_mode); void serial_set_recv_mode( SerialDevice *serial_device, SerialReceiveMode recv_mode); +void serial_console_backend_put_string( + void *context, const char *string, int length); DeviceDriverOps serial_device_driver_ops = { .device_driver_init = NULL, @@ -63,6 +66,20 @@ const int serial_irqs[] = { string_t name = STRING_INIT("Serial"); +void serial_console_backend_put_string( + void *context, const char *string, int length) { + Serial *serial = context; + if (serial->device->state != DEVICE_STATE_ACTIVE) return; + + for (int i = 0; i < length; i++) { + // 等待直到可以发送数据 + while (!( + io_in_byte(serial->base_port + SERIAL_UART_REG_LINE_STATUS) & 0x20)) + ; + io_out_byte(serial->base_port + SERIAL_UART_REG_DATA, string[i]); + } +} + void serial_irq_handler(Device *device) { SerialDevice *serial_device = device->dm_ext; Serial *serial = device->private_data; @@ -76,10 +93,15 @@ void serial_irq_handler(Device *device) { while (io_in_byte(base_port + SERIAL_UART_REG_LINE_STATUS) & 0x01) { uint8_t data = io_in_byte(base_port + SERIAL_UART_REG_DATA); // 处理接收到的数据(例如存入缓冲区) + if (data == 127) data = '\b'; + if (data == '\r') data = '\n'; if (serial_device->receive != NULL) { - serial_device->receive(data); + if (data == '\b') { + serial_device->receive('\b'); + serial_device->receive(' '); + serial_device->receive('\b'); + } else serial_device->receive(data); } - io_out_byte(base_port + SERIAL_UART_REG_DATA, data); // 回显 } } if (status & 0x02) { @@ -192,6 +214,9 @@ DriverResult serial_init(Device *device) { device->irq = irq; register_device_irq(irq); + serial->console_backend.init = NULL; + serial->console_backend.put_string = serial_console_backend_put_string; + return DRIVER_RESULT_OK; } @@ -202,6 +227,9 @@ DriverResult serial_start(Device *device) { // 启用接收中断 io_out_byte(base_port + SERIAL_UART_REG_INTERRUPT_ENABLE, 0x01); interrupt_enable_irq(serial->irq); + + console_register_backend(&serial->console_backend, serial); + return DRIVER_RESULT_OK; } diff --git a/src/arch/x86/drivers/smbios.c b/src/arch/x86/drivers/smbios.c index 800349e..80119e8 100644 --- a/src/arch/x86/drivers/smbios.c +++ b/src/arch/x86/drivers/smbios.c @@ -31,9 +31,11 @@ void init_smbios(void) { } EntryPoint = (struct SMBIOSEntryPoint *)mem; - struct SMBIOSHeader *header = (struct SMBIOSHeader *)EntryPoint->TableAddress; - mem = (unsigned char *)EntryPoint->TableAddress; - while ((unsigned int)mem < EntryPoint->TableAddress + EntryPoint->TableLength) { + struct SMBIOSHeader *header = + (struct SMBIOSHeader *)EntryPoint->TableAddress; + mem = (unsigned char *)EntryPoint->TableAddress; + while ((unsigned int)mem < + EntryPoint->TableAddress + EntryPoint->TableLength) { smbios_tables[header->Type] = (unsigned int)mem; switch (header->Type) { case 0: @@ -47,15 +49,16 @@ void init_smbios(void) { break; case 4: processor = (struct Processor_info *)mem; - printk(COLOR_AQUA "\nCPU Max Speed: %dMHz\n", processor->MaxSpeed); - printk(COLOR_AQUA "\nCPU Speed: %dMHz\n", processor->CurrentSpeed); + printk(COLOR_CYAN "\nCPU Max Speed: %dMHz\n", processor->MaxSpeed); + printk(COLOR_CYAN "\nCPU Speed: %dMHz\n", processor->CurrentSpeed); break; default: break; } mem += header->Length; - while (mem - (unsigned char *)header < EntryPoint->TableLength - 1 && (mem[0] || mem[1])) + while (mem - (unsigned char *)header < EntryPoint->TableLength - 1 && + (mem[0] || mem[1])) mem++; mem += 2; header = (struct SMBIOSHeader *)mem; diff --git a/src/arch/x86/include/drivers/serial.h b/src/arch/x86/include/drivers/serial.h index e4fb401..80ba866 100644 --- a/src/arch/x86/include/drivers/serial.h +++ b/src/arch/x86/include/drivers/serial.h @@ -1,6 +1,7 @@ #ifndef _SERIAL_H #define _SERIAL_H +#include #include #include #include @@ -44,6 +45,8 @@ typedef struct { Device *device; uint16_t base_port; uint8_t irq; + + ConsoleBackend console_backend; } Serial; void register_serial(); diff --git a/src/driver/framebuffer/Makefile b/src/driver/framebuffer/Makefile index 70e0116..7a3df55 100644 --- a/src/driver/framebuffer/Makefile +++ b/src/driver/framebuffer/Makefile @@ -1,2 +1,3 @@ SRC += framebuffer_dm.c -SRC += framebuffer.c \ No newline at end of file +SRC += framebuffer.c +SRC += console_backend.c \ No newline at end of file diff --git a/src/driver/framebuffer/console_backend.c b/src/driver/framebuffer/console_backend.c new file mode 100644 index 0000000..e31d5e7 --- /dev/null +++ b/src/driver/framebuffer/console_backend.c @@ -0,0 +1,278 @@ +#include "driver/framebuffer/console_backend.h" +#include "kernel/driver_interface.h" +#include "kernel/periodic_task.h" +#include "kernel/spinlock.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void fb_console_backend_update(void *arg); + +void fb_console_backend_init(void *context) { + FrameBufferDevice *fb_device = context; + FrameBufferConsoleBackend *backend = &fb_device->console_backend; + + backend->fb_device = fb_device; + backend->font = font16; + backend->width = fb_device->mode_info.width / 10; + backend->real_height = fb_device->mode_info.height / 16; + backend->height = backend->real_height + 1; // 多出4行用于滚屏 + + backend->buffer_size = backend->width * backend->height; + backend->text_buffer = kmalloc(backend->buffer_size); + backend->current = backend->text_buffer; + backend->last_update = backend->text_buffer; + backend->line_ends = kmalloc(backend->height * sizeof(char *)); + backend->line_widths = kmalloc(backend->height * sizeof(uint16_t)); + for (int i = 0; i < backend->height; i++) { + backend->line_ends[i] = backend->text_buffer; + backend->line_widths[i] = 0; + } + + backend->x = backend->y = 0; + backend->last_update_y = 0; + backend->last_update_x = 0; + + backend->default_fg_color = FB_DEFAULT_FG_COLOR; + backend->default_bg_color = FB_DEFAULT_BG_COLOR; + backend->foreground_color = backend->default_fg_color; + backend->background_color = backend->default_bg_color; + + backend->periodic_task.func = fb_console_backend_update; + backend->periodic_task.arg = backend; + periodic_task_add(&backend->periodic_task); + + spinlock_init(&backend->lock); +} + +void fb_console_backend_scroll(FrameBufferConsoleBackend *backend, int lines) { + FrameBufferDevice *fb_device = backend->fb_device; + + int bpp = fb_device->mode_info.bytes_per_pixel; + int line_length = fb_device->mode_info.width * bpp; + uint8_t *vram = fb_device->framebuffer_address; + uint8_t *src_vram = vram + (lines * 16 * line_length); + uint8_t *dst_vram = vram; + + int width, offset = backend->line_ends[lines - 1] - backend->text_buffer; + width = MAX(backend->line_widths[0], backend->line_widths[lines]); + width *= 10 * bpp; + for (int j = 0; j < 16; j++) { + memcpy(dst_vram, src_vram, width); + src_vram += line_length; + dst_vram += line_length; + } + for (int i = 1; i < backend->real_height - lines; i++) { + width = MAX(backend->line_widths[i], backend->line_widths[i + lines]); + width *= 10 * bpp; + for (int j = 0; j < 16; j++) { + memcpy(dst_vram, src_vram, width); + src_vram += line_length; + dst_vram += line_length; + } + } + for (int i = backend->real_height - lines; i < backend->real_height; i++) { + draw_rect( + fb_device, 0, i * 16, backend->line_widths[i] * 10, 16, + backend->background_color); + } + memcpy( + backend->text_buffer, backend->text_buffer + offset, + backend->buffer_size - offset); + memcpy( + &backend->line_widths[0], &backend->line_widths[lines], + (backend->height - lines) * sizeof(uint16_t)); + for (int i = lines; i < backend->height; i++) { + backend->line_ends[i - lines] = backend->line_ends[i] - offset; + } + for (int i = backend->height - lines; i < backend->height; i++) { + backend->line_ends[i] = backend->text_buffer + backend->buffer_size; + backend->line_widths[i] = 0; + } + backend->y -= lines; + backend->last_update_y -= lines; + backend->current -= offset; + backend->last_update -= offset; +} + +void fb_console_backend_control( + FrameBufferConsoleBackend *backend, char *current) { + const uint32_t color_map1[8] = { + 0x000000, 0xaa0000, 0x00aa00, 0xaa5500, + 0x0000aa, 0xaa00aa, 0x00aaaa, 0xaaaaaa, + }; + const uint32_t color_map2[8] = { + 0x555555, 0xff5555, 0x55ff55, 0xffff55, + 0x5555ff, 0xff55ff, 0x55ffff, 0xffffff, + }; + int param1 = -1, param2 = -1; + + if (*current >= '0' && *current <= '9') { + param1 = *current - '0'; + current++; + } + while (*current >= '0' && *current <= '9') { + param1 = param1 * 10 + (*current - '0'); + current++; + } + + if (*current == ';') { + current++; + if (*current >= '0' && *current <= '9') { + param2 = *current - '0'; + current++; + } + while (*current >= '0' && *current <= '9') { + param2 = param2 * 10 + (*current - '0'); + current++; + } + } + + switch (*current++) { + case 'm': { + if (param1 == -1) { + backend->foreground_color = backend->default_fg_color; + backend->background_color = backend->default_bg_color; + } else if (param1 == 1) { + if (param2 >= 30 && param2 <= 37) { + backend->foreground_color = color_map2[(param2 - 30) & 7]; + } else if (param2 >= 40 && param2 <= 47) { + backend->background_color = color_map2[(param2 - 40) & 7]; + } + } else if (param1 >= 30 && param1 <= 37) { + backend->foreground_color = color_map1[(param1 - 30) & 7]; + } else if (param1 >= 40 && param1 <= 47) { + backend->background_color = color_map1[(param1 - 40) & 7]; + } + } + default: + break; + } + backend->last_update = current; +} + +void fb_console_backend_update(void *arg) { + FrameBufferConsoleBackend *backend = arg; + + int status = spin_try_lock_irqsave(&backend->lock); + if (status == 0) return; + + FrameBufferDevice *fb_device = backend->fb_device; + int bpp = backend->fb_device->mode_info.bytes_per_pixel; + int screen_w = backend->fb_device->mode_info.width; + int line_length = screen_w * bpp; + uint8_t *vram = backend->fb_device->framebuffer_address; + uint8_t *cur_vram = vram + (backend->last_update_y * 16 * screen_w + + backend->last_update_x * 10) * + bpp; + + char *current = backend->last_update; + if (backend->y >= backend->real_height) { + fb_console_backend_scroll( + backend, backend->y - backend->real_height + 1); + cur_vram = vram + (backend->last_update_y * 16 * screen_w + + backend->last_update_x * 10) * + bpp; + current = backend->last_update; + } + while (current < backend->current) { + if (current == backend->line_ends[backend->last_update_y]) { + backend->last_update_y++; + backend->last_update_x = 0; + cur_vram = vram + backend->last_update_y * 16 * line_length; + continue; + } + if (current[0] == '\033') { + if (current[1] == '[') { + current += 2; + fb_console_backend_control(backend, current); + current = backend->last_update; + continue; + } + } + draw_rect( + fb_device, backend->last_update_x * 10, backend->last_update_y * 16, + 10, 16, backend->background_color); + print_word( + fb_device->framebuffer_ops, &fb_device->mode_info, cur_vram, + backend->font + (*current) * 16, backend->foreground_color); + cur_vram += 10 * bpp; + backend->last_update_x++; + current++; + } + if (current == backend->line_ends[backend->last_update_y]) { + backend->last_update_y++; + } + backend->last_update = backend->current; + backend->last_update_y = backend->y; + backend->last_update_x = backend->x; + + spin_unlock_irqrestore(&backend->lock, status); +} + +void fb_console_backend_put_string( + void *context, const char *string, int length) { + FrameBufferDevice *fb_device = context; + FrameBufferConsoleBackend *backend = &fb_device->console_backend; + + spin_lock(&backend->lock); + for (int i = 0; i < length; i++) { + bool new_line = false; + if (string[i] == '\033') { + bool flag = true; + *backend->current++ = string[i++]; + *backend->current++ = string[i++]; + while (flag) { + *backend->current++ = string[i]; + if (string[i] >= 'a' && string[i] <= 'z') flag = false; + if (string[i] >= 'A' && string[i] <= 'Z') flag = false; + i++; + } + i--; + } else if (string[i] == '\n') { + new_line = true; + } else if (string[i] == '\b') { + backend->current--; + + backend->x = MAX(backend->x - 1, 0); + backend->line_widths[backend->y] = + MAX(backend->line_widths[backend->y] - 1, 0); + if (backend->y == backend->last_update_y) { + backend->last_update_x = backend->x; + } + } else if (string[i] == '\t') { + do { + *backend->current++ = ' '; + backend->x++; + backend->line_widths[backend->y]++; + } while (backend->x & 3); + backend->line_widths[backend->y] = + MIN(backend->line_widths[backend->y], backend->width); + if (backend->x >= backend->width) new_line = true; + } else { + *backend->current++ = string[i]; + backend->x++; + backend->line_widths[backend->y]++; + if (backend->x >= backend->width) new_line = true; + } + if (new_line) { + backend->line_ends[backend->y++] = backend->current; + + backend->x = 0; + if (backend->y >= backend->height) { + // 超过最大行数,滚屏 + spin_unlock(&backend->lock); + fb_console_backend_scroll(backend, 1); + spin_lock(&backend->lock); + } + } + } + if (list_empty(&thread_all)) { fb_console_backend_update(backend); } + spin_unlock(&backend->lock); +} diff --git a/src/driver/framebuffer/framebuffer.c b/src/driver/framebuffer/framebuffer.c index 5f2ddf8..e2e35c8 100644 --- a/src/driver/framebuffer/framebuffer.c +++ b/src/driver/framebuffer/framebuffer.c @@ -162,21 +162,21 @@ void print_word( int delta = (mode_info->width - 8) * bpp; for (i = 0; i < 16; i++) { d = ascii[i]; - if (d & 0x80) { ops->write_pixel_raw(vram, color); } + if (d & 0x80) ops->write_pixel_raw(vram, color); vram += bpp; - if (d & 0x40) { ops->write_pixel_raw(vram, color); } + if (d & 0x40) ops->write_pixel_raw(vram, color); vram += bpp; - if (d & 0x20) { ops->write_pixel_raw(vram, color); } + if (d & 0x20) ops->write_pixel_raw(vram, color); vram += bpp; - if (d & 0x10) { ops->write_pixel_raw(vram, color); } + if (d & 0x10) ops->write_pixel_raw(vram, color); vram += bpp; - if (d & 0x08) { ops->write_pixel_raw(vram, color); } + if (d & 0x08) ops->write_pixel_raw(vram, color); vram += bpp; - if (d & 0x04) { ops->write_pixel_raw(vram, color); } + if (d & 0x04) ops->write_pixel_raw(vram, color); vram += bpp; - if (d & 0x02) { ops->write_pixel_raw(vram, color); } + if (d & 0x02) ops->write_pixel_raw(vram, color); vram += bpp; - if (d & 0x01) { ops->write_pixel_raw(vram, color); } + if (d & 0x01) ops->write_pixel_raw(vram, color); vram += bpp; vram += delta; } diff --git a/src/driver/framebuffer/framebuffer_dm.c b/src/driver/framebuffer/framebuffer_dm.c index 2c5143a..cdaaa0f 100644 --- a/src/driver/framebuffer/framebuffer_dm.c +++ b/src/driver/framebuffer/framebuffer_dm.c @@ -1,4 +1,5 @@ #include "objects/object.h" +#include #include #include #include @@ -45,11 +46,11 @@ DriverResult framebuffer_dm_unload(DeviceManager *manager) { } DriverResult register_framebuffer_device( - DeviceDriver *device_driver, Device *device, - FrameBufferDevice *framebuffer_device, ObjectAttr *attr) { - device->dm_ext = framebuffer_device; + DeviceDriver *device_driver, Device *device, FrameBufferDevice *fb_device, + ObjectAttr *attr) { + device->dm_ext = fb_device; if (device->dm_ext == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } - framebuffer_device->device = device; + fb_device->device = device; string_t name; string_new_with_number( @@ -58,13 +59,17 @@ DriverResult register_framebuffer_device( DRV_RESULT_DELIVER_CALL( register_device, device_driver, &name, device->bus, device, attr); - list_init(&framebuffer_device->fb_list_lh); + list_init(&fb_device->fb_list_lh); list_add_tail(&device->dm_list, &framebuffer_dm.device_lh); + ConsoleBackend *backend = &fb_device->console_backend.backend; + backend->init = fb_console_backend_init; + backend->put_string = fb_console_backend_put_string; + return DRIVER_RESULT_OK; } -DriverResult unregister_framebuffer_devce( +DriverResult unregister_framebuffer_device( DeviceDriver *device_driver, Device *device, FrameBufferDevice *framebuffer_device) { list_del(&framebuffer_device->fb_list_lh); @@ -72,25 +77,26 @@ DriverResult unregister_framebuffer_devce( } DriverResult framebuffer_device_start(DeviceManager *manager, Device *device) { - FrameBufferDevice *framebuffer_device = (FrameBufferDevice *)device->dm_ext; + FrameBufferDevice *fb_device = (FrameBufferDevice *)device->dm_ext; if (framebuffer_dm_ext.main_display_device == NULL) { framebuffer_dm_ext.main_display_device = device; } - if (framebuffer_device->framebuffer_address == NULL) { + if (fb_device->framebuffer_address == NULL) { return DRIVER_RESULT_OTHER_ERROR; } - if (framebuffer_device->mode_info.bits_per_pixel == 8) { - framebuffer_device->framebuffer_ops = &fb_ops_8; - } else if (framebuffer_device->mode_info.bits_per_pixel == 16) { - framebuffer_device->framebuffer_ops = &fb_ops_16; - } else if (framebuffer_device->mode_info.bits_per_pixel == 24) { - framebuffer_device->framebuffer_ops = &fb_ops_24; - } else if (framebuffer_device->mode_info.bits_per_pixel == 32) { - framebuffer_device->framebuffer_ops = &fb_ops_32; + if (fb_device->mode_info.bits_per_pixel == 8) { + fb_device->framebuffer_ops = &fb_ops_8; + } else if (fb_device->mode_info.bits_per_pixel == 16) { + fb_device->framebuffer_ops = &fb_ops_16; + } else if (fb_device->mode_info.bits_per_pixel == 24) { + fb_device->framebuffer_ops = &fb_ops_24; + } else if (fb_device->mode_info.bits_per_pixel == 32) { + fb_device->framebuffer_ops = &fb_ops_32; } else { return DRIVER_RESULT_UNSUPPORT_FEATURE; } + console_register_backend(&fb_device->console_backend.backend, fb_device); return DRIVER_RESULT_OK; } diff --git a/src/include/driver/framebuffer/console_backend.h b/src/include/driver/framebuffer/console_backend.h new file mode 100644 index 0000000..4fffcd0 --- /dev/null +++ b/src/include/driver/framebuffer/console_backend.h @@ -0,0 +1,48 @@ +#ifndef FB_CONSOLE_BACKEND_H +#define FB_CONSOLE_BACKEND_H + +#include "kernel/spinlock.h" +#include +#include +#include + +#define FB_DEFAULT_FG_COLOR 0xAAAAAA +#define FB_DEFAULT_BG_COLOR 0x000000 + +typedef struct { + ConsoleBackend backend; + + struct FrameBufferDevice *fb_device; + + char **line_ends; + uint16_t *line_widths; + char *text_buffer; + char *current; + char *last_update; + int buffer_size; + + uint8_t *font; + + uint16_t width; + uint16_t height; + uint16_t real_height; + + uint16_t x, y; + uint16_t last_update_y; + uint16_t last_update_x; + + uint32_t foreground_color; + uint32_t default_fg_color; + uint32_t background_color; + uint32_t default_bg_color; + + PeriodicTask periodic_task; + + spinlock_t lock; +} FrameBufferConsoleBackend; + +void fb_console_backend_init(void *context); +void fb_console_backend_put_string( + void *context, const char *string, int length); + +#endif \ No newline at end of file diff --git a/src/include/driver/framebuffer/fb_dm.h b/src/include/driver/framebuffer/fb_dm.h index 7c16934..feaa8d1 100644 --- a/src/include/driver/framebuffer/fb_dm.h +++ b/src/include/driver/framebuffer/fb_dm.h @@ -6,7 +6,9 @@ #include "kernel/list.h" #include "objects/object.h" #include "stdint.h" +#include #include +#include typedef struct FrameBufferModeInfo { uint16_t width; @@ -23,6 +25,8 @@ typedef struct FrameBufferDevice { uint8_t *framebuffer_address; FramebufferOps *framebuffer_ops; + + FrameBufferConsoleBackend console_backend; } FrameBufferDevice; typedef struct FrameBufferDeviceManager { diff --git a/src/include/kernel/console.h b/src/include/kernel/console.h index 7966eb8..46e082d 100644 --- a/src/include/kernel/console.h +++ b/src/include/kernel/console.h @@ -5,29 +5,62 @@ #define CMD_FLAG_INPUT 0 #define CMD_FLAG_OUTPUT 1 -#define COLOR_BLACK "<0>" -#define COLOR_BLUE "<1>" -#define COLOR_GREEN "<2>" -#define COLOR_AQUA "<3>" -#define COLOR_RED "<4>" -#define COLOR_PURPLE "<5>" -#define COLOR_YELLOW "<6>" -#define COLOR_WHITE "<7>" -#define COLOR_GRAY "<8>" -#define COLOR_LBLUE "<9>" -#define COLOR_LGREEN "" -#define COLOR_LAQUA "" -#define COLOR_LRED "" -#define COLOR_LPURPLE "" -#define COLOR_LYELLOW "" -#define COLOR_BWHITE "" +#define COLOR_BLACK "\033[30m" +#define COLOR_RED "\033[31m" +#define COLOR_GREEN "\033[32m" +#define COLOR_BROWN "\033[33m" +#define COLOR_BLUE "\033[34m" +#define COLOR_MAGENTA "\033[35m" +#define COLOR_CYAN "\033[36m" +#define COLOR_WHITE "\033[37m" +#define COLOR_GRAY "\033[1;30m" +#define COLOR_BBLACK "\033[1;30m" +#define COLOR_BRED "\033[1;31m" +#define COLOR_BGREEN "\033[1;32m" +#define COLOR_BYELLOW "\033[1;33m" +#define COLOR_BBLUE "\033[1;34m" +#define COLOR_BMAGENTA "\033[1;35m" +#define COLOR_BCYAN "\033[1;36m" +#define COLOR_BWHITE "\033[1;37m" +#define COLOR_RESET "\033[m" + +#define COLOR_BG_BLACK "\033[40m" +#define COLOR_BG_RED "\033[41m" +#define COLOR_BG_GREEN "\033[42m" +#define COLOR_BG_BROWN "\033[43m" +#define COLOR_BG_BLUE "\033[44m" +#define COLOR_BG_MAGENTA "\033[45m" +#define COLOR_BG_CYAN "\033[46m" +#define COLOR_BG_WHITE "\033[47m" +#define COLOR_BG_GRAY "\033[1;40m" +#define COLOR_BG_BBLACK "\033[1;40m" +#define COLOR_BG_BRED "\033[1;41m" +#define COLOR_BG_BGREEN "\033[1;42m" +#define COLOR_BG_BYELLOW "\033[1;43m" +#define COLOR_BG_BBLUE "\033[1;44m" +#define COLOR_BG_BMAGENTA "\033[1;45m" +#define COLOR_BG_BCYAN "\033[1;46m" +#define COLOR_BG_BWHITE "\033[1;47m" + +#define print_string(str) put_string(str, strlen(str)) void init_console(void); void console_start(void); -void console_set_cursor(int x, int y); -void console_input(char c); -void print_char(unsigned char c, unsigned int color); int printk(const char *fmt, ...); void print_hex(unsigned char *s, int length); +// -----------new----------- + +#include + +typedef struct ConsoleBackend { + list_t list; + void *context; + + void (*init)(void *context); + void (*put_string)(void *context, const char *string, int length); +} ConsoleBackend; + +void console_register_backend(ConsoleBackend *backend, void *context); + #endif \ No newline at end of file diff --git a/src/include/kernel/driver_interface.h b/src/include/kernel/driver_interface.h index 4121c15..f1c1550 100644 --- a/src/include/kernel/driver_interface.h +++ b/src/include/kernel/driver_interface.h @@ -35,16 +35,18 @@ #endif #include -#define print_error_with_position(str, ...) \ - printk(COLOR_RED __FILE__ " Line %d: " str, __LINE__, ##__VA_ARGS__) +#define print_error_with_position(str, ...) \ + printk( \ + COLOR_RED __FILE__ " Line %d: " str COLOR_RESET, __LINE__, \ + ##__VA_ARGS__) #define print_error(source, str, ...) \ - printk(COLOR_RED "[" source "]" str, ##__VA_ARGS__) + printk(COLOR_RED "[" source "]" str COLOR_RESET, ##__VA_ARGS__) #define print_warning(source, str, ...) \ - printk(COLOR_YELLOW "[%s]" str, source, ##__VA_ARGS__) + printk(COLOR_BYELLOW "[%s]" str COLOR_RESET, source, ##__VA_ARGS__) #define print_device_info(device, str, ...) \ - printk("[%s]" str, device->name.text, ##__VA_ARGS__) + printk("[%s]" str COLOR_RESET, device->name.text, ##__VA_ARGS__) #define print_driver_info(driver, str, ...) \ - printk("[%s]" str, driver.short_name.text, ##__VA_ARGS__) + printk("[%s]" str COLOR_RESET, driver.short_name.text, ##__VA_ARGS__) #include "kernel/list.h" struct Device; diff --git a/src/kernel/console.c b/src/kernel/console.c index df9ae0d..2bfa63c 100644 --- a/src/kernel/console.c +++ b/src/kernel/console.c @@ -9,142 +9,41 @@ #include #include #include +#include #include #include #include -#include #include -struct console { - FrameBufferDevice *fb_device; +LIST_HEAD(console_backend_lh); - uint8_t *vram; - uint8_t *cur_vram; - uint8_t *font; - int start_x, start_y; - int cur_x, cur_y; - int width, height; - int color; - int flag; -}; - -int command_length = 0; -char command[CMD_MAX_LENGTH]; -struct console console; +void console_register_backend(ConsoleBackend *backend, void *context) { + if (backend == NULL || backend->put_string == NULL) return; + backend->context = context; + list_add_tail(&backend->list, &console_backend_lh); + if (backend->init) { backend->init(context); } +} /** * @brief 初始化控制台的配置 * */ void init_console(void) { - framebuffer_get_device(0, &console.fb_device); - - console.vram = console.fb_device->framebuffer_address; - console.cur_vram = console.vram; - console.font = font16; - console.cur_x = 0; - console.cur_y = 0; - console.width = console.fb_device->mode_info.width / 10; - console.height = console.fb_device->mode_info.height / 16; - console.color = 0xc0c0c0; - console.flag = CMD_FLAG_OUTPUT; -} - -/** - * @brief 打印">" - * - */ -void console_start(void) { - printk("\n>"); - console.start_x = 1; - console.start_y = console.cur_y + 1; - console.flag = CMD_FLAG_INPUT; -} - -/** - * @brief 设置光标位置 - * - * @param x 光标的x坐标 - * @param y 光标的y坐标 - */ -void console_set_cursor(int x, int y) { - console.cur_x = x; - console.cur_y = y; } -/* -void console_input(char c) -{ - int i; - char str[2]; - if (console.flag == CMD_FLAG_INPUT) - { - if (c != '\n') - { - if (command_length < CMD_MAX_LENGTH - 1) - { - command[command_length] = c; - command_length++; - str[0] = c; - str[1] = '\0'; - printk(str); - } - } - else - { - for (i = 0; i <= command_length; i++) - { - command[i] = 0; - } - command_length = 0; - printk("\n"); - console_start(); - //运行程序 or 其他操作 - } +void put_string(const char *string, int length) { + ConsoleBackend *backend; + list_for_each_owner (backend, &console_backend_lh, list) { + backend->put_string(backend->context, string, length); } } -*/ - -void scroll_screen(void) { - int i, j; - int screen_width = console.fb_device->mode_info.width; - int screen_height = console.fb_device->mode_info.height; - int bpp = console.fb_device->mode_info.bytes_per_pixel; - - uint32_t *dst = (uint32_t *)console.vram; - uint32_t *src = (uint32_t *)(console.vram + 16 * screen_width * bpp); - for (j = 0; j < console.height - 1; j++) { - for (i = 0; i < screen_width * bpp * 16 / 4; i++) { - *dst = *src; - dst += 1; - src += 1; - } - } - draw_rect(console.fb_device, 0, screen_height - 16, screen_width, 16, 0); -} /** - * @brief 打印一个字符 + * @brief 打印">" * - * @param c 字符 - * @param color 颜色 */ -void print_char(unsigned char c, unsigned int color) { - if (c > 127) { c = '?'; } - int bpp = console.fb_device->mode_info.bytes_per_pixel; - print_word( - console.fb_device->framebuffer_ops, &console.fb_device->mode_info, - console.cur_vram + 1 * bpp, console.font + c * 16, color); - console.cur_x++; - console.cur_vram += 10 * bpp; - if (console.cur_x >= console.width) { - int screen_width = console.fb_device->mode_info.width; - console.cur_x = 0; - console.cur_y++; - console.cur_vram = - console.vram + console.cur_y * 16 * screen_width * bpp; - } - if (console.cur_y >= console.height) { scroll_screen(); } +void console_start(void) { + put_string("\n>", 2); } /** @@ -155,135 +54,14 @@ void print_char(unsigned char c, unsigned int color) { * @return int 字符串长度 */ int printk(const char *fmt, ...) { - int i, color = console.color; + int i; char buf[256]; va_list arg; va_start(arg, fmt); i = vsprintf(buf, fmt, arg); - va_end(); - - char *p = buf, c; - int len = i; - int bpp = console.fb_device->mode_info.bytes_per_pixel; - int screen_width = console.fb_device->mode_info.width; - while (len) { - c = *p++; - if (c == '<' && len == i) { - if (*(p + 1) == '>') { - switch (*p) { - case '0': - color = 0x000000; - break; - case '1': - color = 0x0037da; - break; - case '2': - color = 0x13a104; - break; - case '3': - color = 0x3a96dd; - break; - case '4': - color = 0xc50f1f; - break; - case '5': - color = 0x881798; - break; - case '6': - color = 0xffff00; - break; - case '7': - color = 0xcccccc; - break; - case '8': - color = 0x767676; - break; - case '9': - color = 0x3878ff; - break; - case 'a': - color = 0x16c60c; - break; - case 'b': - color = 0x61d6d6; - break; - case 'c': - color = 0xe74856; - break; - case 'd': - color = 0xb4009e; - break; - case 'e': - color = 0xf9f1a5; - break; - case 'f': - color = 0xf2f2f2; - break; - - default: - break; - } - p += 2; - - len -= 3; - c = *p++; - } - } - switch (c) { - case '\n': - console.cur_y++; - console.cur_x = 0; - console.cur_vram = - console.vram + console.cur_y * 16 * screen_width * bpp; - break; - case '\b': - if (console.flag == CMD_FLAG_INPUT) { - if (console.cur_x != console.start_x && - console.cur_y != console.start_y) { - console.cur_x--; - console.cur_vram -= 10 * bpp; - draw_rect( - console.fb_device, console.cur_x * 10 + 1, - console.cur_y * 16, 8, 16, 0); - } - } - break; - case '\t': { - int tab = 4 - console.cur_x % 4; - console.cur_x += tab; - console.cur_vram += tab * 10 * bpp; - break; - } - case '\r': - break; - default: - draw_rect( - console.fb_device, console.cur_x * 10, console.cur_y * 16, 10, - 16, 0); - print_char(c, color); - break; - } - if (console.cur_x > console.width) { - console.cur_x = 0; - console.cur_y++; - console.cur_vram = - console.vram + console.cur_y * 16 * screen_width * bpp; - } - if (console.cur_y >= console.height) { - print_char('\n', color); - if (console.cur_y < 0) { console.cur_y = 0; } - if (console.cur_y > console.height - 1) { - console.cur_y = console.height - 1; - } - if (console.flag == CMD_FLAG_INPUT) { - console.start_y = console.cur_y; - } - console.cur_vram = - console.vram + console.cur_y * 16 * screen_width * bpp; - } - len--; - } + va_end(arg); + put_string(buf, i); return i; } @@ -299,29 +77,29 @@ void print_hex(unsigned char *s, int length) { printk("\nData is too long!\n"); return; } - printk("\n 0 1 2 3 4 5 6 7 8 9 A B C D E F " - "0123456789ABCDEF\n"); + print_string("\n 0 1 2 3 4 5 6 7 8 9 A B C D E F " + "0123456789ABCDEF\n"); for (i = 0; i < DIV_ROUND_UP(length, 16); i++) { printk("%08X ", i * 16); for (j = 0; j < 16; j++) { if (j < length - i * 16) { printk("%02X ", s[i * 16 + j]); } else { - printk(" "); + print_string(" "); } } - printk(" "); + print_string(" "); for (j = 0; j < 16; j++) { if (j < length - i * 16) { if (s[i * 16 + j] < 32 || s[i * 16 + j] > 126) { - printk("."); + print_string("."); } else { printk("%c", s[i * 16 + j]); } } else { - printk(" "); + print_string(" "); } } - printk("\n"); + print_string("\n"); } } \ No newline at end of file diff --git a/src/kernel/driver/device.c b/src/kernel/driver/device.c index 8af2870..fe46d0d 100644 --- a/src/kernel/driver/device.c +++ b/src/kernel/driver/device.c @@ -98,6 +98,7 @@ DriverResult init_device(Device *device) { } } DEVM_OPS_CALL(manager, init_device_hook, manager, device); + device->state = DEVICE_STATE_READY; return DRIVER_RESULT_OK; } @@ -106,6 +107,7 @@ DriverResult start_device(Device *device) { DEV_OPS_CALL(device, start, device); DEVM_OPS_CALL(manager, start_device_hook, manager, device); device->device_driver->subdriver.state = SUBDRIVER_STATE_READY; + device->state = DEVICE_STATE_ACTIVE; return DRIVER_RESULT_OK; } From 5ce66c073b79767d4a1527b89356c354955d6b51 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 27 Sep 2025 19:35:53 +0800 Subject: [PATCH 139/158] =?UTF-8?q?fs&storage:=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E9=94=99=E8=AF=AF=E7=9A=84=E5=A4=B4=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + CMakeLists.txt | 35 +++++++++++++++++++++ src/CMakeLists.txt | 55 +++++++++++++++++++++++++++++++++ src/driver/storage/storage_dm.c | 1 - src/fs/fat/fat.c | 1 - src/include/fs/fs.h | 1 - src/include/string.h | 1 - src/kernel/main.c | 1 - src/todo.md | 1 + 9 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 src/CMakeLists.txt create mode 100644 src/todo.md diff --git a/.gitignore b/.gitignore index 88b88e3..593ecd2 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ Module.symvers Mkfile.old dkms.conf compile_commands.json +build/ # Cache __pycache__/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1a904af --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.24) +project(HorizonOS C ASM) + +set(CMAKE_C_STANDARD 11) +enable_language(ASM) + +# 内核 +add_subdirectory(src) + +# 库 +#add_subdirectory(libs) + +# 工具 (Rust) +add_custom_target(tools + COMMAND cargo build --manifest-path ${CMAKE_SOURCE_DIR}/tools/imagetool/Cargo.toml --release + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tools/imagetool +) + +# 应用 +#add_subdirectory(apps) + +# qemu run +add_custom_target(run + COMMAND ${CMAKE_COMMAND} -E echo "Running QEMU..." + # 后续可以写具体 qemu 命令 + COMMAND "qemu-system-x86_64" -no-reboot -monitor stdio -m 1024 + -hda ${CMAKE_SOURCE_DIR}/hd0.img + -usb + -device usb-mouse + -device rtl8139,netdev=nc1 + -netdev user,id=nc1,hostfwd=tcp::5555-:80 + -object filter-dump,id=f1,netdev=nc1,file=dump.pcap + -readconfig ${CMAKE_SOURCE_DIR}/qemu-linux.cfg + -boot c +) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..174765e --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,55 @@ +cmake_minimum_required(VERSION 3.24) +project(HorizonOSKernel C ASM) + +# 开启 ASM 支持 +enable_language(ASM) + +# include 目录 +include_directories( + ${CMAKE_SOURCE_DIR}/src/include + ${CMAKE_SOURCE_DIR}/src/arch/x86/include +) + +# 汇编文件列表 +file(GLOB_RECURSE ASM_SRCS + arch/x86/boot/*.asm + arch/x86/kernel/*.asm +) + +# C 文件列表 +file(GLOB_RECURSE C_SRCS + arch/x86/**/*.c + fs/**/*.c + driver/**/*.c + kernel/*.c + lib/**/*.c + objects/**/*.c +) +list(REMOVE_ITEM C_SRCS + "${CMAKE_SOURCE_DIR}/src/arch/x86/drivers/network/rtl8139.c" + "${CMAKE_SOURCE_DIR}/src/arch/x86/drivers/usb/**.c" +) + + +# 输出内核 ELF +add_executable(kernel.elf ${C_SRCS} ${ASM_SRCS}) + +if(APPLE) + set(CMAKE_LINKER x86_64-elf-ld) +else() + set(CMAKE_LINKER ld) +endif() +set(CMAKE_EXE_LINKER_FLAGS "-m elf_i386 -g -no-pie -T ${CMAKE_SOURCE_DIR}/src/arch/x86/kernel.lds") + + +set_source_files_properties(${ASM_SRCS} PROPERTIES COMPILE_FLAGS "-g -f elf") + +# 链接器脚本 +set_target_properties(kernel.elf PROPERTIES LINK_FLAGS "-T ${CMAKE_SOURCE_DIR}/src/arch/x86/kernel.lds") + +# 编译选项 +target_compile_options(kernel.elf PRIVATE + -march=i486 -fno-builtin -Wall -Wunused -m32 -std=gnu11 + -fno-stack-protector -nostdinc -nostdlib -O0 -DARCH_X86=32 + -DKERNEL_NAME=\"horizon\" -DKERNEL_VERSION=\"0.0.1\" +) diff --git a/src/driver/storage/storage_dm.c b/src/driver/storage/storage_dm.c index b6a7c9a..646c261 100644 --- a/src/driver/storage/storage_dm.c +++ b/src/driver/storage/storage_dm.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c index 32c6d0a..84b4e24 100644 --- a/src/fs/fat/fat.c +++ b/src/fs/fat/fat.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include diff --git a/src/include/fs/fs.h b/src/include/fs/fs.h index 5455de4..f58c177 100644 --- a/src/include/fs/fs.h +++ b/src/include/fs/fs.h @@ -3,7 +3,6 @@ #include "objects/handle.h" #include "string.h" -#include #include #include #include diff --git a/src/include/string.h b/src/include/string.h index 46769d1..0c71543 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -8,7 +8,6 @@ #ifndef _LIB_STRING_H_ #define _LIB_STRING_H_ -#include "stddef.h" #include "stdint.h" #define STRING_MAX_LEN 256 diff --git a/src/kernel/main.c b/src/kernel/main.c index 93bb5f6..550e480 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/src/todo.md b/src/todo.md new file mode 100644 index 0000000..65072c3 --- /dev/null +++ b/src/todo.md @@ -0,0 +1 @@ + - [ ] 驱动生命周期新增AfterInitialized,在所有驱动初始化完成后运行 \ No newline at end of file From fe535db931dd36fbdf27498b05ec804910f2fa5c Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 27 Sep 2025 19:47:55 +0800 Subject: [PATCH 140/158] =?UTF-8?q?kernel&driver:=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=97=A7=E7=9A=84=E4=BB=A3=E7=A0=81=E5=8F=8A=E5=AF=B9=E6=97=A7?= =?UTF-8?q?=E5=A4=B4=E6=96=87=E4=BB=B6=E7=9A=84=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/Makefile | 4 +- src/arch/x86/drivers/network/rtl8139.c | 375 ------------ .../x86/drivers/network/rtl8139/rtl8139.c | 16 +- src/include/fs/vfs.h | 119 ---- src/include/kernel/driver.h | 112 +--- src/include/kernel/process.h | 14 +- src/include/network/arp.h | 38 -- src/include/network/dhcp.h | 52 -- src/include/network/eth.h | 33 - src/include/network/ipv4.h | 51 -- src/include/network/netpack.h | 32 - src/include/network/network.h | 72 --- src/include/network/tcp.h | 95 --- src/include/network/udp.h | 28 - src/kernel/app.c | 38 +- src/kernel/driver/driver.c | 143 ----- src/kernel/elf.c | 13 +- src/kernel/process.c | 78 +-- src/network/Makefile | 7 - src/network/arp.c | 74 --- src/network/dhcp.c | 134 ---- src/network/eth.c | 105 ---- src/network/ipv4.c | 133 ---- src/network/network.c | 159 ----- src/network/tcp.c | 573 ------------------ src/network/udp.c | 103 ---- 26 files changed, 83 insertions(+), 2518 deletions(-) delete mode 100644 src/arch/x86/drivers/network/rtl8139.c delete mode 100644 src/include/fs/vfs.h delete mode 100644 src/include/network/arp.h delete mode 100644 src/include/network/dhcp.h delete mode 100644 src/include/network/eth.h delete mode 100644 src/include/network/ipv4.h delete mode 100644 src/include/network/netpack.h delete mode 100644 src/include/network/network.h delete mode 100644 src/include/network/tcp.h delete mode 100644 src/include/network/udp.h delete mode 100644 src/network/Makefile delete mode 100644 src/network/arp.c delete mode 100644 src/network/dhcp.c delete mode 100644 src/network/eth.c delete mode 100644 src/network/ipv4.c delete mode 100644 src/network/network.c delete mode 100644 src/network/tcp.c delete mode 100644 src/network/udp.c diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index 73afae8..28b0f80 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -1,6 +1,6 @@ -SRC += 8042.c +#SRC += 8042.c SRC += 8259a.c -SRC += acpi.c +#SRC += acpi.c SRC += apic.c SRC += cpufreq.c SRC += disk.c diff --git a/src/arch/x86/drivers/network/rtl8139.c b/src/arch/x86/drivers/network/rtl8139.c deleted file mode 100644 index 9faac95..0000000 --- a/src/arch/x86/drivers/network/rtl8139.c +++ /dev/null @@ -1,375 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define RTL8139_VENDOR_ID 0x10ec -#define RTL8139_DEVICE_ID 0x8139 - -#define DRV_NAME "Horizon Basic Network Driver" -#define DEV_NAME "RTL8139" - -#define CHIP_INFO_NR 10 -#define TX_DESC_NR 4 - -#define CHIP_HAS_LWAKE 0x01 - -#define IMR_ALL \ - RTL8139_IMR_SERR | RTL8139_IMR_TimeOut | RTL8139_IMR_LenChg | \ - RTL8139_IMR_FOVW | RTL8139_IMR_TER | RTL8139_IMR_TOK | \ - RTL8139_IMR_RER | RTL8139_IMR_ROK -#define RXFTH_NONE RTL8139_RCR_RXFTH(0x07) - -#define RBLEN_64K 0x03 -#define RBLEN_32K 0x02 -#define RBLEN_16K 0x01 -#define RBLEN_8K 0x00 - -#define RECV_BUF_LEN RBLEN_16K -#define RBLEN RTL8139_RCR_RBLEN(RECV_BUF_LEN) - -#define RTL8139_RECV_BUF_SIZE (8192 << RECV_BUF_LEN) + 16 + 1500 - -static status_t rtl8139_enter(driver_t *drv_obj); -static status_t rtl8139_exit(driver_t *drv_obj); -static status_t rtl8139_open(struct _device_s *dev); -static status_t rtl8139_close(struct _device_s *dev); -static status_t rtl8139_write( - struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); -static status_t rtl8139_read( - struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); -static status_t rtl8139_ioctl( - struct _device_s *dev, uint32_t func_num, uint32_t value); - -driver_func_t rtl8139_driver = { - .driver_enter = rtl8139_enter, - .driver_exit = rtl8139_exit, - .driver_open = rtl8139_open, - .driver_close = rtl8139_close, - .driver_read = rtl8139_read, - .driver_write = rtl8139_write, - .driver_devctl = rtl8139_ioctl, -}; - -struct read_request_s { - uint8_t *buffer; - uint32_t length; -}; - -typedef struct { - struct pci_device *device; - uint32_t io_base; - uint32_t irq; - - uint8_t mac_addr[6]; - struct chip_info *info; - - int8_t tx_idx_w; // 写入到第几个缓冲区了 - int8_t tx_idx_done; // 处理到第几个缓冲区了 - uint32_t tx_flags; // 传输标志 - uint8_t *tx_buffer[TX_DESC_NR]; - uint32_t tx_buffer_phy[TX_DESC_NR]; - - wait_queue_manager_t *wqm; - wait_queue_manager_t *rqm; - - uint16_t rx_offset; - uint8_t *rx_buffer; - uint32_t rx_buffer_phy; - - uint8_t *tmpbuffer; -} device_extension_t; - -struct chip_info { - const char *name; - uint32_t hwverid; - uint32_t flag; -} chips[CHIP_INFO_NR] = { - { "RTL8139", 0b110000000 << 22, 0}, - { "RTL8139A", 0b111000000 << 22, 0}, - { "RTL8139A-G", 0b111010000 << 22, 0}, - { "RTL8139B", 0b111100000 << 22, CHIP_HAS_LWAKE}, - { "RTL8130", 0b111110000 << 22, CHIP_HAS_LWAKE}, - { "RTL8139C", 0b111010000 << 22, CHIP_HAS_LWAKE}, - { "RTL8100", 0b111100010 << 22, CHIP_HAS_LWAKE}, - {"RTL8100B/8139D", 0b111010001 << 22, CHIP_HAS_LWAKE}, - { "RTL8101", 0b111010011 << 22, CHIP_HAS_LWAKE}, -}; - -void rtl8139_handler(device_t *devobj, int irq) { - device_extension_t *devext = (device_extension_t *)devobj->device_extension; - uint16_t status = io_in16(devext->io_base + RTL8139_ISR); - uint16_t length; - int i; - - // printk("[RTL8139]Status:%#0x\t", status); - io_out16( - devext->io_base + RTL8139_ISR, - status & ~(RTL8139_ISR_FOVW | RTL8139_ISR_RXOVW | RTL8139_ISR_ROK | - RTL8139_ISR_TER)); - if (status & RTL8139_ISR_TOK) { - // if (!wait_queue_empty(devext->wqm)) { - // wait_queue_wakeup_all(devext->wqm); } printk("idx_w:%d - // idx_done:%d+1\n", devext->tx_idx_w, devext->tx_idx_done); - devext->tx_idx_done = (devext->tx_idx_done + 1) % TX_DESC_NR; - io_out16(devext->io_base + RTL8139_ISR, RTL8139_ISR_TOK); - } - if (status & RTL8139_ISR_ROK) { - uint8_t cmd; - uint32_t rx_status; - do { - i = devext->rx_offset; - rx_status = LE2HOST_DWORD(*(uint32_t *)(devext->rx_buffer + i)); - length = (rx_status >> 16) - 4; - i += 4; - if (length >= sizeof(eth_frame_t) && - (rx_status & RTL8139_RX_STAT_ROK)) { - uint8_t *buffer = kmalloc(length); - if (i + length >= RTL8139_RECV_BUF_SIZE) { - memcpy( - buffer, devext->rx_buffer + i, - RTL8139_RECV_BUF_SIZE - i); - i = RTL8139_RECV_BUF_SIZE - i; - memcpy(buffer + i, devext->rx_buffer + i, length - i); - } else { - memcpy(buffer, devext->rx_buffer + i, length); - } - net_rx_raw_pack(ETH_FRAME, buffer, length); - } else { - printk( - "[RTL8139]RX Error: status %04x,size %04x, cur %04x\n", - rx_status, length + 4, devext->rx_offset); - } - devext->rx_offset = (devext->rx_offset + length + 8 + 3) & - ~3; // +8:4字节CRC和4字节包头;+3:4字节对齐用 - devext->rx_offset %= RTL8139_RECV_BUF_SIZE; - io_out16(devext->io_base + RTL8139_CAPR, devext->rx_offset - 0x10); - io_out16(devext->io_base + RTL8139_ISR, RTL8139_ISR_ROK); - cmd = io_in8(devext->io_base + RTL8139_CR); - } while (!(cmd & RTL8139_CR_BUFE)); // 缓冲区不为空 - } - // printk("\n"); - return; -} - -static status_t rtl8139_enter(driver_t *drv_obj) { - device_t *devobj; - device_extension_t *devext; - int i; - - device_create( - drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_ETH_NET, &devobj); - devext = devobj->device_extension; - - // devext->device = pci_get_device_ById(RTL8139_VENDOR_ID, - // RTL8139_DEVICE_ID); - if (devext->device == NULL) { - printk(COLOR_YELLOW "\n[RTL8139]Cannot find device!\n"); - device_delete(devobj); - return NODEV; - } - - // pci_enable_bus_mastering(devext->device); - // devext->io_base = pci_device_get_io_addr(devext->device); - devext->irq = devext->device->irqline; - - // 初始化RTL8139 - io_out8(devext->io_base + RTL8139_CONFIG1, 0x00); // 通电 - io_out8(devext->io_base + RTL8139_CR, RTL8139_CR_RST); // 重置 - int f = 1; - for (i = 0; i < 1000; i++) { - if (!(io_in8(devext->io_base + RTL8139_CR) & 0x10)) { - f = 0; - break; - } - } - if (f) { return FAILED; } - - // 判断型号 - uint32_t hwverid = io_in32(devext->io_base + RTL8139_TCR) & 0x7cc00000; - for (i = 0; i < CHIP_INFO_NR; i++) { - if (chips[i].hwverid == hwverid) { - devext->info = &chips[i]; - break; - } - } - - // 读取MAC地址 - for (i = 0; i < 6; i++) { - devext->mac_addr[i] = io_in8(devext->io_base + RTL8139_IDRN(i)); - } - printk( - "[RTL8139]MAC Address:%02x:%02x:%02x:%02x:%02x:%02x\n", - devext->mac_addr[0], devext->mac_addr[1], devext->mac_addr[2], - devext->mac_addr[3], devext->mac_addr[4], devext->mac_addr[5]); - - io_out8(devext->io_base + RTL8139_9346CR, 0xc0); // Unlock - - // 分配接收缓冲区 - devext->rx_offset = 0; - devext->rx_buffer = kmalloc(RTL8139_RECV_BUF_SIZE); - if (devext->rx_buffer == NULL) { return FAILED; } - devext->rx_buffer_phy = vir2phy((uint32_t)devext->rx_buffer); - io_out32(devext->io_base + RTL8139_RBSTART, devext->rx_buffer_phy); - devext->tmpbuffer = kmalloc(ETH_MAX_FRAME_SIZE); - - // 分配发送缓冲区 - for (i = 0; i < TX_DESC_NR; i++) { - devext->tx_buffer[i] = kmalloc(ETH_MAX_FRAME_SIZE); - devext->tx_buffer_phy[i] = vir2phy((uint32_t)devext->tx_buffer[i]); - } - - io_out16(devext->io_base + RTL8139_MPC, 0); - io_out16(devext->io_base + RTL8139_BMCR, 0x3100); - io_out8(devext->io_base + RTL8139_MSR, 0x40); - - io_out32( - devext->io_base + RTL8139_RCR, - RXFTH_NONE | RBLEN | RTL8139_RCR_MXDMA(0x07) | RTL8139_RCR_AER | - RTL8139_RCR_AR | RTL8139_RCR_WRAP | RTL8139_RCR_AB | - RTL8139_RCR_AM | RTL8139_RCR_APM | RTL8139_RCR_AAP); - io_out32( - devext->io_base + RTL8139_TCR, - RTL8139_TCR_MXDMA(0x07) | RTL8139_TCR_TXRR(2)); - - io_out32(devext->io_base + RTL8139_MARN(0), 0xffffffff); - io_out32(devext->io_base + RTL8139_MARN(4), 0xffffffff); - - io_out8(devext->io_base + RTL8139_BMCR, 0x00); // Lock - - devext->tx_idx_w = 0; - devext->tx_idx_done = 0; - devext->wqm = create_wait_queue(); - devext->rqm = create_wait_queue(); - wait_queue_init(devext->wqm); - wait_queue_init(devext->rqm); - - io_out8( - devext->io_base + RTL8139_CR, - RTL8139_CR_RE | RTL8139_CR_TE); // 允许接收和发送 - for (i = 0; i < TX_DESC_NR; i++) { - io_out32(devext->io_base + RTL8139_TSADN(i), devext->tx_buffer_phy[i]); - io_in32(devext->io_base + RTL8139_TSADN(i)); - } - devext->tx_flags = ((256) << 11) & 0x3f0000; - - device_register_irq(devobj, devext->irq, &rtl8139_handler); - - return SUCCUESS; -} - -static status_t rtl8139_open(struct _device_s *dev) { - device_extension_t *devext = (device_extension_t *)dev->device_extension; - io_out32(devext->io_base + RTL8139_MPC, 0); - io_out16(devext->io_base + RTL8139_MULINT, 0); - - // 启用中断 - io_out16(devext->io_base + RTL8139_IMR, IMR_ALL); - - return SUCCUESS; -} - -static status_t rtl8139_read( - struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size) { - device_extension_t *devext = dev->device_extension; - wait_queue_t *rq; - struct read_request_s *rreq; - - // rq = wait_queue_add(devext->rqm, sizeof(struct - // read_request_s)); rreq = (struct read_request_s - // *)rq->private_data; rreq->buffer = buf; rreq->length = size; - // thread_block(TASK_INTERRUPTIBLEED); - - return SUCCUESS; -} - -static status_t rtl8139_write( - struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size) { - device_extension_t *devext = dev->device_extension; - wait_queue_t *wq; - uint32_t idx; - - if (size > ETH_MAX_FRAME_SIZE) { return FAILED; } - - // printk(" idx_w:%d idx_done:%d\n", devext->tx_idx_w, - // devext->tx_idx_done); while ((io_in32(devext->io_base + - // RTL8139_TSDN(devext->tx_idx_w)) & RTL8139_TSR_OWN)) - // ; - while ((devext->tx_idx_w + 1) % TX_DESC_NR == devext->tx_idx_done) {} - idx = devext->tx_idx_w; - devext->tx_idx_w = (devext->tx_idx_w + 1) % TX_DESC_NR; - memcpy(devext->tx_buffer[idx], buf, size); - io_out32(devext->io_base + RTL8139_TSDN(idx), size); - io_in32(devext->io_base + RTL8139_TSDN(idx)); - - return SUCCUESS; -} - -static status_t rtl8139_ioctl( - struct _device_s *dev, uint32_t func_num, uint32_t value) { - int i; - - device_extension_t *devext = dev->device_extension; - - switch (func_num) { - case NET_FUNC_GET_MTU: { - uint32_t *p = (uint32_t *)value; - *p = ETH_MTU; - break; - } - case NET_FUNC_GET_MAC_ADDR: { - uint8_t *addr = (uint8_t *)value; - for (i = 0; i < 6; i++) { - addr[i] = devext->mac_addr[i]; - } - break; - } - case NET_FUNC_SET_MAC_ADDR: { - uint8_t *addr = (uint8_t *)value; - for (i = 0; i < 6; i++) { - devext->mac_addr[i] = addr[i]; - } - break; - } - } - return SUCCUESS; -} - -static status_t rtl8139_close(struct _device_s *dev) { - device_extension_t *devext = dev->device_extension; - io_out16(devext->io_base + RTL8139_IMR, 0); - - return SUCCUESS; -} - -static status_t rtl8139_exit(driver_t *drv_obj) { - device_t *devobj, *next; - list_for_each_owner_safe (devobj, next, &drv_obj->device_list, list) { - device_delete(devobj); - } - string_del(&drv_obj->name); - return SUCCUESS; -} - -static __init void rtl8139_driver_entry(void) { - if (driver_create(rtl8139_driver, DRV_NAME) < 0) { - printk(COLOR_RED "[driver] %s driver create failed!\n", __func__); - } -} - -driver_initcall(rtl8139_driver_entry); diff --git a/src/arch/x86/drivers/network/rtl8139/rtl8139.c b/src/arch/x86/drivers/network/rtl8139/rtl8139.c index 858358c..8e71e8f 100644 --- a/src/arch/x86/drivers/network/rtl8139/rtl8139.c +++ b/src/arch/x86/drivers/network/rtl8139/rtl8139.c @@ -1,7 +1,11 @@ +#include "rtl8139.h" #include #include +#include #include #include +#include +#include #include #include #include @@ -15,21 +19,15 @@ #include #include #include +#include #include +#include #include +#include #include #include #include -#include "driver/network/buffer.h" -#include "driver/network/net_queue.h" -#include "driver/network/network.h" -#include "kernel/softirq.h" -#include "kernel/thread.h" -#include "network/eth.h" -#include "objects/transfer.h" -#include "rtl8139.h" - DriverResult rtl8139_init(Device *device); DriverResult rtl8139_start(Device *device); DriverResult rtl8139_pci_probe(PciDevice *pci_device); diff --git a/src/include/fs/vfs.h b/src/include/fs/vfs.h deleted file mode 100644 index 265f0c8..0000000 --- a/src/include/fs/vfs.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef _VFS_H -#define _VFS_H - -#include -#include -#include -#include -#include - -// 实 - -struct directory { - struct index_node *inode; - - unsigned int dir_start; // 文件夹目录项所在的簇号 - unsigned int dir_offset; // 文件夹目录项在簇内的位置 - - unsigned int start; // 文件夹数据所在的簇号 -}; - -struct file { - struct index_node *inode; - - unsigned int dir_start; // 文件目录项所在的簇号 - unsigned int dir_offset; // 文件目录项在簇内的位置 - - unsigned int start; // 文件数据所在的簇号 - unsigned int offset; - unsigned int cur_pos; - unsigned int mode; - size_t size; - - uint32_t *index_table; - - void *private_data; -}; - -// 虚 - -struct file_operations { - struct index_node *(*open)(char *path); - int (*close)(struct index_node *inode); - int (*read)(struct index_node *inode, uint8_t *buffer, uint32_t length); - int (*write)(struct index_node *inode, uint8_t *buffer, uint32_t length); - int (*seek)(struct index_node *inode, unsigned int offset, unsigned int origin); - int (*ioctl)(struct index_node *inode, uint32_t cmd, uint32_t arg); -}; - -/* -struct index_node_operations -{ - struct index_node * (*create)(struct index_node *inode, struct dir_block *dir, int mode); - int (*delete)(struct index_node *inode, struct dir_block *dir); - struct index_node (*find)(struct index_node *parent_inode, struct dir_block *dir); - struct index_node * (*mkdir)(struct dir_block *dir, int mode, char *name); - int (*rmdir)(struct index_node *inode, struct dir_block *dir); - int (*rename)(struct index_node *inode, struct dir_block *dir, char *name); -}; -*/ -typedef enum { ATTR_FILE, ATTR_DIR, ATTR_DEV } inode_attr_t; - -struct index_node { - inode_attr_t attribute; - - struct index_node *parent; - list_t list, childs; - string_t name; - union { - struct file *fp; - struct directory *dir; - }; - struct _device_s *device; - struct _partition_s *part; - struct file_operations f_ops; - - date create_date; // 创建日期 - time create_time; // 创建时间 - date write_date; // 修改日期 - time write_time; // 修改时间 - date last_access_date; // 最后访问日期 - time last_access_time; // 最后访问时间 -}; - -typedef struct _file_request { - list_t list; - void *buffer; - union { - struct { - uint32_t offset; - uint32_t length; - } rw; - struct { - uint32_t offset; - uint32_t origin; - } seek; - struct { - uint32_t cmd; - uint32_t arg; - } ioctl; - }; - -} file_request_t; - -extern struct index_node *root; - -void init_vfs(void); - -// 以下函数只对虚拟节点进行操作,不对实际文件造成影响 -struct index_node *vfs_find(struct index_node *parent, char *name); -struct index_node *vfs_mkdir(char *path); -void vfs_rm(struct index_node *inode); -void vfs_rename(struct index_node *inode, char *name); -struct index_node *vfs_open(char *path); -struct index_node *vfs_opendir(char *path); -struct index_node *vfs_create(char *name, inode_attr_t attr, struct index_node *parent); -void vfs_delete(struct index_node *inode); -void vfs_close(struct index_node *inode); - -#endif \ No newline at end of file diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index dc43ee7..bb99bfe 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -1,99 +1,14 @@ #ifndef _DRIVER_H #define _DRIVER_H -#include "kernel/wait_queue.h" -#include "stdint.h" -#define DRIVER_MAX_NAME_LEN 64 -#define DEVICE_MAX_NAME_LEN 64 - #include #include +#include #include #include +#include #include -typedef enum { - UNSUPPORT = -3, - NODEV = -2, - FAILED = -1, - SUCCUESS = 0, - UNKNOWN, -} status_t; - -typedef enum { - DEV_UNKNOWN = 0, - DEV_STORAGE, - DEV_MANAGER, - DEV_KEYBOARD, - DEV_MOUSE, - DEV_USB, - DEV_SOUND, - DEV_ETH_NET, -} dev_type_t; - -typedef struct _device_s { - list_t list; - spinlock_t lock; - dev_type_t type; - - struct index_node *inode; - struct _driver_s *drv_obj; - void *device_extension; - string_t name; -} device_t; - -typedef struct { - status_t (*driver_enter)(struct _driver_s *drv); - status_t (*driver_exit)(struct _driver_s *drv); - status_t (*driver_open)(struct _device_s *dev); - status_t (*driver_close)(struct _device_s *dev); - status_t (*driver_read)( - struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); - status_t (*driver_write)( - struct _device_s *dev, uint8_t *buf, uint32_t offset, size_t size); - status_t (*driver_devctl)( - struct _device_s *dev, uint32_t func_num, uint32_t value); -} driver_func_t; - -#define DEV_READ(device, buf, offset, size) \ - device->drv_obj->function.driver_read( \ - device, (uint8_t *)buf, (uint32_t)offset, (size_t)size) -#define DEV_WRITE(device, buf, offset, size) \ - device->drv_obj->function.driver_write( \ - device, (uint8_t *)buf, (uint32_t)offset, (size_t)size) -#define DEV_CTL(device, func, value) \ - device->drv_obj->function.driver_devctl( \ - device, (uint32_t)func, (uint32_t)value) - -typedef struct _device_manager_s { - string_t name; - list_t dev_listhead; - void *private_data; - - void (*dm_register)( - struct _device_manager_s *dm, struct _device_s *dev, char *name); - void (*dm_unregister)(struct _device_manager_s *dm, struct _device_s *dev); - - void (*drv_inited)(struct _device_manager_s *dm); -} device_manager_t; - -typedef struct _driver_s { - list_t list; - list_t device_list; - string_t name; - - driver_func_t function; - - struct _device_manager_s *dm; -} driver_t; - -typedef void (*driver_irq_handler_t)(device_t *devobj, int irq); -typedef struct { - list_t list; - device_t *devobj; - driver_irq_handler_t handler; -} dev_irq_t; - static const Permission driver_sys_permission = { .subject_id = SUBJECT_ID_SYSTEM, .permission = {1, 1, 1, 1, 1, 1, 1}, @@ -119,29 +34,6 @@ static const ObjectAttr driver_object_attr = { .admin_permission = driver_admin_permission, }; -extern struct index_node *dev; - -void init_dm(void); -void dm_start(void); -struct index_node *dev_open(char *path); -int dev_close(struct index_node *inode); -int dev_read(struct index_node *inode, uint8_t *buffer, uint32_t length); -int dev_write(struct index_node *inode, uint8_t *buffer, uint32_t length); -int dev_ioctl(struct index_node *inode, uint32_t cmd, uint32_t arg); -status_t driver_create(driver_func_t func, char *driver_name); -status_t device_create( - driver_t *driver, unsigned long device_extension_size, char *name, - dev_type_t type, device_t **device); -void device_delete(device_t *device); -void device_register_irq( - device_t *devobj, int irq, driver_irq_handler_t handler); -void device_unregister_irq(device_t *devobj, int irq); -void driver_inited(); - -// --------new-------- - -#include "result.h" - typedef enum DriverResult { DRIVER_RESULT_OK, DRIVER_RESULT_TIMEOUT, diff --git a/src/include/kernel/process.h b/src/include/kernel/process.h index 836ed08..75ab5a6 100644 --- a/src/include/kernel/process.h +++ b/src/include/kernel/process.h @@ -7,12 +7,12 @@ #define USER_STACK3_ADDR 0xffbff000 #define USER_START_ADDR 0X80000000 -void start_process(void *filename); -void process_excute(void *filename, struct program_struct *prog); -void page_dir_activate(struct task_s *thread); -void process_activate(struct task_s *thread); -MemoryResult process_load_segment( - struct task_s *thread, struct index_node *inode, unsigned long offset, - unsigned long filesz, unsigned long memsz, unsigned long vaddr); +void start_process(void *filename); +void process_excute(void *filename, struct program_struct *prog); +void page_dir_activate(struct task_s *thread); +void process_activate(struct task_s *thread); +// MemoryResult process_load_segment( +// struct task_s *thread, struct index_node *inode, unsigned long offset, +// unsigned long filesz, unsigned long memsz, unsigned long vaddr); #endif \ No newline at end of file diff --git a/src/include/network/arp.h b/src/include/network/arp.h deleted file mode 100644 index ef23393..0000000 --- a/src/include/network/arp.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef ARP_H -#define ARP_H - -#include "../stdint.h" -#include -#include -#include - -#define ARP_HWTYPE_ETH 0x0001 - -#define ARP_PTTYPE_IPV4 0x0800 - -#define ARP_REQUEST 1 -#define ARP_REPLY 2 - -typedef struct { - uint16_t hwtype, pttype; - uint8_t hwlen, ptlen; - uint16_t opcode; - uint8_t src_hw_addr[6]; - uint8_t src_ip[4]; - uint8_t dst_hw_addr[6]; - uint8_t dst_ip[4]; -} __attribute__((packed)) arp_pack_t; - -typedef struct { - uint8_t ip[4]; - uint8_t mac[6]; - list_t list; - - WaitQueue wq; -} arp_cache_t; - -uint8_t *ip2mac(netc_t *netc, uint8_t *ip); -void send_arp(netc_t *netc, uint8_t *dst_ip, uint16_t opcode); -void arp_read(uint8_t *buf, uint16_t offset, uint16_t length); - -#endif \ No newline at end of file diff --git a/src/include/network/dhcp.h b/src/include/network/dhcp.h deleted file mode 100644 index 27216a4..0000000 --- a/src/include/network/dhcp.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef DHCP_H -#define DHCP_H - -#include "../stdint.h" -#include - -#define DHCP_OP_REQUEST 1 -#define DHCP_OP_REPLY 2 - -#define DHCP_DISCOVER 1 -#define DHCP_OFFER 2 -#define DHCP_REQUEST 3 -#define DHCP_DECLINE 4 -#define DHCP_ACK 5 -#define DHCP_NAK 6 -#define DHCP_RELEASE 7 -#define DHCP_INFORM 8 -#define DHCP_FORCERENEW 9 - -#define DHCP_OPTION_SUBNET_MASK 1 -#define DHCP_OPTION_TIME_OFFSET 2 -#define DHCP_OPTION_ROUTER 3 -#define DHCP_OPTION_DOMAIN_SERVER 6 -#define DHCP_OPTION_LEASE_TIME 51 -#define DHCP_OPTION_MSG_TYPE 53 -#define DHCP_OPTION_SERVER_ID 54 -#define DHCP_OPTION_END 255 - -typedef struct { - uint8_t Op; - uint8_t htype, hlen, hops; - uint32_t xID; - uint16_t secs; - uint16_t flags; - uint8_t ciAddr[4]; // 客户端IP地址 - uint8_t yiAddr[4]; // 服务器分配给客户端的IP地址 - uint8_t siAddr[4]; // 下一个服务器的IP地址 - uint8_t giAddr[4]; // 第一个中继的IP地址 - uint8_t chAddr[16]; // 客户端的MAC地址 - uint8_t sname[64]; - uint8_t file[128]; -} __attribute__((packed)) dhcp_basic_t; - -typedef struct { - uint8_t server_ip[4]; - uint8_t server_id; - uint32_t lease_time; -} dhcp_info_t; - -int dhcp_main(net_device_t *net_dev); - -#endif \ No newline at end of file diff --git a/src/include/network/eth.h b/src/include/network/eth.h deleted file mode 100644 index e4cf212..0000000 --- a/src/include/network/eth.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef ETH_H -#define ETH_H - -#include -#include -#include -#include -#include - -#define ETH_MAX_FRAME_SIZE 1536 -#define ETH_MIN_FRAME_SIZE 60 -#define ETH_MTU 1500 - -#define ETH_TYPE_IPV4 0x0800 -#define ETH_TYPE_IPV6 0x86dd -#define ETH_TYPE_ARP 0x0806 -#define ETH_TYPE_802_1Q 0x8100 - -typedef void (*eth_handler_t)(device_manager_t *eth_dm, uint8_t *buf, uint16_t size); - -typedef struct eth_frame_s { - uint8_t dest_mac[6]; - uint8_t src_mac[6]; - uint16_t type; -} __attribute__((packed)) eth_frame_t; - -extern device_manager_t eth_dm; - -void eth_handler(net_rx_pack_t *pack, uint8_t *buf, uint16_t size); -int eth_read(netc_t *netc, uint8_t *buffer, uint32_t length); -int eth_write(netc_t *netc, uint8_t *buffer, uint32_t length); - -#endif \ No newline at end of file diff --git a/src/include/network/ipv4.h b/src/include/network/ipv4.h deleted file mode 100644 index 0770c58..0000000 --- a/src/include/network/ipv4.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef IPV4_H -#define IPV4_H - -#include "../stdint.h" -#include "netpack.h" -#include "network.h" - -#define IPV4_FLAG_DF 0x02 -#define IPV4_FLAG_MF 0x04 - -typedef struct ipv4_header_s { - uint8_t IHL : 4; - uint8_t Version : 4; - uint8_t TypeOfService; - uint16_t TotalLength; - uint16_t Identification; - uint16_t Offset; - uint8_t TimetoLive; - uint8_t Protocol; - uint16_t HeaderChecksum; - uint8_t SourceAddress[4]; - uint8_t DestinationAddress[4]; - uint8_t *Options; -} __attribute__((packed)) ipv4_header_t; - -struct ipv4_data { - uint8_t ip_addr[4]; - uint8_t subnet_mask[4]; - uint8_t router_ip[4]; - uint8_t dns_server_ip[4]; - spinlock_t idlock; - uint16_t counter; - uint16_t mtu; -}; - -typedef struct { - uint16_t src_port, dst_port; - list_t list; -} ipv4_conn_t; - -extern uint8_t broadcast_ipv4_addr[4]; - -void ipv4_init(net_device_t *netdev); -int ipv4_send(netc_t *netc, uint8_t *dst_ip, uint8_t DF, uint8_t ttl, uint8_t protocol, uint8_t *data, - uint32_t datalen); -void ipv4_read(net_rx_pack_t *pack, uint8_t *buf, uint16_t offset, uint16_t length); -void ipv4_get_ip(netc_t *netc, uint8_t *ip); -void ipv4_set_ip(netc_t *netc, uint8_t *ip); -int ipv4_get_mtu(netc_t *netc); - -#endif \ No newline at end of file diff --git a/src/include/network/netpack.h b/src/include/network/netpack.h deleted file mode 100644 index fa5680f..0000000 --- a/src/include/network/netpack.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NETPACK_H -#define NETPACK_H - -#include "kernel/list.h" -#include "network/network.h" -#include "network/tcp.h" -#include "network/udp.h" -#include "stdint.h" - -typedef struct net_rx_pack_s { - list_t list; - - enum frame_type { - ETH_FRAME, - } type; - uint8_t *src_ip_addr; - uint8_t src_ip_len; - uint32_t proto_start; - uint32_t data_len; - - uint8_t *data; - uint32_t len; -} net_rx_pack_t; - -extern list_t net_rx_tcp_lh; - -void net_process_pack(void *arg); -void net_rx_raw_pack(enum frame_type type, uint8_t *buf, uint32_t length); -void net_raw2tcp_pack(net_rx_pack_t *pack, uint8_t ip_len, uint8_t *p_addr, uint32_t start, uint32_t len); -void net_raw2udp_pack(net_rx_pack_t *pack, uint32_t start, uint32_t len); - -#endif \ No newline at end of file diff --git a/src/include/network/network.h b/src/include/network/network.h deleted file mode 100644 index 33eb122..0000000 --- a/src/include/network/network.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef NETWORK_H -#define NETWORK_H - -#include "kernel/spinlock.h" -#include -#include -#include -#include -#include -#include - -#define NET_MAX_BUFFER_SIZE 4096 - -#define NET_FUNC_GET_MTU 0x00 -#define NET_FUNC_GET_MAC_ADDR 0x01 -#define NET_FUNC_SET_MAC_ADDR 0x02 - -struct network_info { - uint8_t mac[6]; - void *ipv4_data; - void *dhcp_data; - - list_t list; -}; - -typedef struct netc_s { - struct task_s *thread; - struct net_device_s *net_dev; - - spinlock_t spin_lock; - - uint8_t *recv_buffer; - uint32_t recv_offset; - uint32_t recv_len; - - uint16_t protocol; - uint16_t proto_id; - list_t proto_list; - void *proto_private; - uint16_t app_protocl; - uint32_t app_proto_id; - void *app_private; - - uint8_t dst_mac[6]; - uint8_t *dst_laddr, dst_laddr_len; -} netc_t; - -typedef struct net_device_s { - struct network_info *info; - device_t *device; - int enable; - - list_t list; - - int (*net_read)(struct netc_s *netc, uint8_t *buffer, uint32_t length); - int (*net_write)(struct netc_s *netc, uint8_t *buffer, uint32_t length); -} net_device_t; - -extern net_device_t *default_net_dev; - -extern uint8_t broadcast_mac[6]; - -void init_network(void); -netc_t *netc_create(net_device_t *net_dev, uint16_t protocol, uint16_t app_protocol); -int netc_delete(netc_t *netc); -void netc_set_dest(netc_t *netc, uint8_t dst_mac[6], uint8_t *dst_laddr, uint8_t dst_laddr_len); -int netc_read(netc_t *netc, uint8_t *buf, uint32_t size); -void netc_drop_all(netc_t *netc); -void netc_ip_send(netc_t *netc, uint8_t *ip, uint8_t DF, uint8_t proto, uint8_t *buf, uint32_t size); -int netc_get_mtu(netc_t *netc); - -#endif \ No newline at end of file diff --git a/src/include/network/tcp.h b/src/include/network/tcp.h deleted file mode 100644 index 6e424af..0000000 --- a/src/include/network/tcp.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef TCP_H -#define TCP_H - -#include "driver/timer_dm.h" -#include "kernel/list.h" -#include "network.h" -#include - -#define TCP_FLAG_FIN 0x01 -#define TCP_FLAG_SYN 0x02 -#define TCP_FLAG_RST 0x04 -#define TCP_FLAG_PSH 0x08 -#define TCP_FLAG_ACK 0x10 -#define TCP_FLAG_URG 0x20 -#define TCP_FLAG_ECE 0x40 -#define TCP_FLAG_CWRC 0x80 - -#define TCP_MAX_WINDOW_SIZE 65536 -#define TCP_MSL_MS 2 * 60 * 1000 - -#define TCP_OPTION_END 0 -#define TCP_OPTION_NOP 1 -#define TCP_OPTION_MSS 2 - -#define TCP_PORT_NR 65536 - -typedef struct tcp_header_s { - uint16_t src_port, dst_port; - uint32_t seq; - uint32_t ack; - uint8_t offset; - uint8_t flags; - uint16_t window; - uint16_t checksum; - uint16_t urgent_pointer; -} __attribute__((packed)) tcp_header_t; - -typedef enum { - TCP_STAT_CLOSED = 0, - TCP_STAT_SYN_SENT, - TCP_STAT_ESTABLISHED, - TCP_STAT_LISTEN, - TCP_STAT_SYN_RCVD, - TCP_STAT_FIN_WAIT1, - TCP_STAT_FIN_WAIT2, - TCP_STAT_CLOSING, - TCP_STAT_TIME_WAIT, - TCP_STAT_CLOSE_WAIT, - TCP_STAT_LAST_ACK, -} tcp_status_t; - -typedef struct { - struct netc_s *netc; - uint16_t src_port, dst_port; - uint8_t dst_ip[4]; - list_t list; - - uint8_t *header_buf; - - uint16_t mss; - - struct recv_win { - uint8_t *mem; - uint32_t size; - uint32_t head, tail; // 读窗口的头尾指针 - uint32_t unacked; // 待确认的数据大小 - uint32_t acked; // 已确认未读取的数据大小 - uint32_t recved; // 已接收的数据大小 - } rwin; - - struct send_win { - uint8_t *mem; - uint32_t size; - uint32_t head, tail; // 写窗口的头尾指针 - uint32_t unacked; // 未确认的数据大小 - uint32_t sended; // 已发送的数据大小 - } swin; - - tcp_status_t status; - uint32_t wait_ms, seq, ack; - Timer timer; -} tcp_conn_t; - -#define PROTOCOL_TCP 0x06 -void tcp_create(netc_t *netc); -int tcp_bind(netc_t *netc, uint16_t src_port); -int tcp_ipv4_connect(netc_t *netc, uint8_t *ip, uint16_t dst_port); -void tcp_ipv4_close(netc_t *netc); -void tcp_recv( - uint8_t *buf, uint16_t offset, uint16_t length, uint8_t *ip, - uint8_t ip_len); -int tcp_write(netc_t *netc, uint8_t *buf, uint32_t length); -int tcp_read(netc_t *netc, uint8_t *buf, uint32_t length); - -#endif \ No newline at end of file diff --git a/src/include/network/udp.h b/src/include/network/udp.h deleted file mode 100644 index c11972d..0000000 --- a/src/include/network/udp.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef UDP_H -#define UDP_H - -#include "../stdint.h" -#include "network.h" - -typedef struct udp_head_s { - uint16_t SourcePort; - uint16_t DestinationPort; - uint16_t Length; - uint16_t Checksum; -} __attribute__((packed)) udp_head_t; - -typedef struct { - struct netc_s *netc; - uint16_t src_port, dst_port; - uint8_t dst_ip[4]; - list_t list; -} udp_conn_t; - -#define PROTOCOL_UDP 0x11 - -int udp_bind(netc_t *netc, uint8_t ip[4], uint16_t src_port, uint16_t dst_port); -int udp_unbind(netc_t *netc); -void udp_send(netc_t *netc, uint16_t *data, uint16_t datalen); -void udp_read(uint8_t *buf, uint16_t offset, uint16_t length); - -#endif \ No newline at end of file diff --git a/src/kernel/app.c b/src/kernel/app.c index 1725473..6a515bc 100644 --- a/src/kernel/app.c +++ b/src/kernel/app.c @@ -19,25 +19,25 @@ * @param path 应用程序的路径 */ void run_app(char *path) { - struct program_struct *prog = kmalloc(sizeof(struct program_struct)); - // prog->inode = fs_open(path); - if (prog->inode == NULL) { printk("Cannot find file %s!", path); } - string_init(&prog->name); - string_init(&prog->filename); - string_init(&prog->path); - string_cpy(&prog->filename, &prog->inode->name); - string_new(&prog->path, path, 255); + // struct program_struct *prog = kmalloc(sizeof(struct program_struct)); + // // prog->inode = fs_open(path); + // if (prog->inode == NULL) { printk("Cannot find file %s!", path); } + // string_init(&prog->name); + // string_init(&prog->filename); + // string_init(&prog->path); + // string_cpy(&prog->filename, &prog->inode->name); + // string_new(&prog->path, path, 255); - char sign[4]; - prog->inode->f_ops.read(prog->inode, (uint8_t *)sign, 4); - if (strncmp(sign, "\177ELF", 4) == 0) { - string_cpy(&prog->name, &prog->filename); - list_init(&prog->seg_head); - unsigned int *entry = elf_load(prog); - process_excute(entry, prog); - } else { - printk( - "Unsupport Executable File or Command %s!", prog->inode->name.text); - } + // char sign[4]; + // prog->inode->f_ops.read(prog->inode, (uint8_t *)sign, 4); + // if (strncmp(sign, "\177ELF", 4) == 0) { + // string_cpy(&prog->name, &prog->filename); + // list_init(&prog->seg_head); + // unsigned int *entry = elf_load(prog); + // process_excute(entry, prog); + // } else { + // printk( + // "Unsupport Executable File or Command %s!", prog->inode->name.text); + // } // fs_close(prog->inode); } \ No newline at end of file diff --git a/src/kernel/driver/driver.c b/src/kernel/driver/driver.c index 6d2740b..da464dd 100644 --- a/src/kernel/driver/driver.c +++ b/src/kernel/driver/driver.c @@ -6,7 +6,6 @@ * @date 2022-07-20 */ #include -#include #include #include #include @@ -18,25 +17,11 @@ #include #include #include - -#include -#include #include #include LIST_HEAD(driver_list_head); -struct index_node *dev; - -// struct file_operations device_fops = { -// .open = dev_open, -// .close = dev_close, -// .read = dev_read, -// .write = dev_write, -// .ioctl = dev_ioctl, -// .seek = fs_seek, -// }; - // --------new-------- #include #include @@ -213,131 +198,3 @@ DriverResult driver_start_all(void) { thread_wait_children(cur); return DRIVER_RESULT_OK; } - -// --------old--------- -struct index_node *dev_open(char *path) { - // struct index_node *inode = vfs_open(path); - // if (inode == NULL) return NULL; - // else inode->device->drv_obj->function.driver_open(inode->device); - // return inode; - return NULL; -} - -int dev_close(struct index_node *inode) { - return inode->device->drv_obj->function.driver_close(inode->device); -} - -int dev_read(struct index_node *inode, uint8_t *buffer, uint32_t length) { - return inode->device->drv_obj->function.driver_read( - inode->device, (uint8_t *)buffer, inode->fp->offset, length); -} - -int dev_write(struct index_node *inode, uint8_t *buffer, uint32_t length) { - return inode->device->drv_obj->function.driver_write( - inode->device, (uint8_t *)buffer, inode->fp->offset, length); -} - -int dev_ioctl(struct index_node *inode, uint32_t cmd, uint32_t arg) { - return inode->device->drv_obj->function.driver_devctl( - inode->device, cmd, arg); -} - -void init_dm(void) { - // init_network(); -} - -status_t driver_create(driver_func_t func, char *driver_name) { - // driver_t *drv_obj; - // int status; - - // drv_obj = kmalloc(sizeof(driver_t)); - // if (drv_obj == NULL) { return FAILED; } - // if (func.driver_enter == NULL) { return FAILED; } - // list_init(&drv_obj->device_list); - // list_init(&drv_obj->list); - // drv_obj->function = func; - // status = drv_obj->function.driver_enter(drv_obj); - // if (status == NODEV) { - // printk("[driver manager]Cannot found device:%s\n", driver_name); - // } else if (status != SUCCUESS) { - // return FAILED; - // } - // string_init(&drv_obj->name); - // string_new(&drv_obj->name, driver_name, DRIVER_MAX_NAME_LEN); - // list_add_tail(&drv_obj->list, &driver_list_head); - - return SUCCUESS; -} - -void driver_inited() { - driver_t *cur; - list_for_each_owner (cur, &driver_list_head, list) { - if (cur->dm != NULL) { cur->dm->drv_inited(cur->dm); } - } -} - -status_t device_create( - driver_t *driver, unsigned long device_extension_size, char *name, - dev_type_t type, device_t **device) { - // device_t *devobj = kmalloc(sizeof(device_t) + device_extension_size); - // devobj->type = type; - // spinlock_init(&devobj->lock); - // if (devobj == NULL) { return FAILED; } - // list_init(&devobj->list); - // if (device_extension_size > 0) { - // devobj->device_extension = (void *)(devobj + 1); - // } else { - // devobj->device_extension = NULL; - // } - // if (string_new(&devobj->name, name, DEVICE_MAX_NAME_LEN)) { - // kfree(devobj); - // return FAILED; - // } - - // devobj->drv_obj = driver; - // list_add_tail(&devobj->list, &driver->device_list); - // *device = devobj; - - // if (type == DEV_ETH_NET) { - // eth_dm.dm_register(ð_dm, devobj, name); - // driver->dm = ð_dm; - // } else { - // // devobj->inode = vfs_create(name, ATTR_DEV, dev); - // devobj->inode->device = devobj; - // // devobj->inode->f_ops = device_fops; - // devobj->inode->fp = kmalloc(sizeof(struct file)); - // } - - return SUCCUESS; -} - -void device_delete(device_t *device) { - if (device == NULL) { return; } - driver_t *driver = device->drv_obj; - if (!list_find(&device->list, &driver->device_list)) { return; } - list_del(&device->list); - string_del(&driver->name); - kfree(device); -} - -void device_register_irq( - device_t *devobj, int irq, driver_irq_handler_t handler) { - if (irq > 16) return; - // if (list_empty(&device_irq_lists[irq])) irq_enable(irq); - dev_irq_t *dev_irq = kmalloc(sizeof(dev_irq_t)); - dev_irq->devobj = devobj; - dev_irq->handler = handler; - // list_add_tail(&dev_irq->list, &device_irq_lists[irq]); -} - -void device_unregister_irq(device_t *devobj, int irq) { - if (irq > 16) return; - // if (list_empty(&device_irq_lists[irq])) return; - // dev_irq_t *dev_irq, *next; - // list_for_each_owner_safe (dev_irq, next, &device_irq_lists[irq], list) { - // if (dev_irq->devobj == devobj) { - // list_del(&dev_irq->list); - // kfree(dev_irq); - // } - // } -} diff --git a/src/kernel/elf.c b/src/kernel/elf.c index 87b81f9..c0cc38b 100644 --- a/src/kernel/elf.c +++ b/src/kernel/elf.c @@ -19,11 +19,12 @@ */ unsigned int *elf_load(struct program_struct *prog) { struct elf32_header header; - prog->inode->f_ops.seek(prog->inode, 0, 0); - prog->inode->f_ops.read(prog->inode, (uint8_t *)&header, sizeof(struct elf32_header)); + // seek(prog->inode, 0, 0); + // read(prog->inode, (uint8_t *)&header, sizeof(struct elf32_header)); - if (memcmp(header.e_ident, "\177ELF\1\1\1", 7) || header.e_type != ELF32_ET_EXEC || - header.e_machine != ELF32_EM_386 || header.e_version != 1 || header.e_phnum > 1024 || + if (memcmp(header.e_ident, "\177ELF\1\1\1", 7) || + header.e_type != ELF32_ET_EXEC || header.e_machine != ELF32_EM_386 || + header.e_version != 1 || header.e_phnum > 1024 || header.e_phentsize != sizeof(struct elf32_program_header)) { printk("Error:unsupported executable file!\n"); return NULL; @@ -37,8 +38,8 @@ unsigned int *elf_load(struct program_struct *prog) { prog->phnum = header.e_phnum; for (i = 0; i < header.e_phnum; i++) { memset(&pheader, 0, prog_header_size); - prog->inode->f_ops.seek(prog->inode, prog_header_off, 0); - prog->inode->f_ops.read(prog->inode, (uint8_t *)&pheader, prog_header_size); + // seek(prog->inode, prog_header_off, 0); + // read(prog->inode, (uint8_t *)&pheader, prog_header_size); if (pheader.p_type == PT_LOAD) { struct prog_segment *progseg = kmalloc(sizeof(struct prog_segment)); progseg->vaddr = pheader.p_vaddr; diff --git a/src/kernel/process.c b/src/kernel/process.c index e8ea140..7ad7f86 100644 --- a/src/kernel/process.c +++ b/src/kernel/process.c @@ -107,30 +107,30 @@ void create_user_vaddr_mmap(struct task_s *user_prog) { * @param entry 程序的入口 * @param prog 进程 */ -void process_excute(void *entry, struct program_struct *prog) { - struct task_s *thread = kmalloc(sizeof(struct task_s)); - void *stack_page = kernel_alloc_pages(1); - struct prog_segment *p; - init_thread(thread, stack_page, prog->name.text, THREAD_DEFAULT_PRIO); - create_user_vaddr_mmap(thread); - thread_create(thread, start_process, entry); - thread->pgdir = create_page_dir(); - init_thread_memory_manage(thread); - list_for_each_owner (p, &prog->seg_head, list) { - MemoryResult result = process_load_segment( - thread, prog->inode, p->offset, p->filesz, p->memsz, p->vaddr); - if (result != MEMORY_RESULT_OK) { - printk("Load segment failed\n"); - return; - } - } +// void process_excute(void *entry, struct program_struct *prog) { +// struct task_s *thread = kmalloc(sizeof(struct task_s)); +// void *stack_page = kernel_alloc_pages(1); +// struct prog_segment *p; +// init_thread(thread, stack_page, prog->name.text, THREAD_DEFAULT_PRIO); +// create_user_vaddr_mmap(thread); +// thread_create(thread, start_process, entry); +// thread->pgdir = create_page_dir(); +// init_thread_memory_manage(thread); +// list_for_each_owner (p, &prog->seg_head, list) { +// MemoryResult result = process_load_segment( +// thread, prog->inode, p->offset, p->filesz, p->memsz, p->vaddr); +// if (result != MEMORY_RESULT_OK) { +// printk("Load segment failed\n"); +// return; +// } +// } - // 将该任务加入任务队列 - int flags = spin_lock_irqsave(&thread_ready_lock); - list_add_tail(&thread->general_tag, &thread_ready); - list_add_tail(&thread->all_list_tag, &thread_all); - io_store_eflags(flags); -} +// // 将该任务加入任务队列 +// int flags = spin_lock_irqsave(&thread_ready_lock); +// list_add_tail(&thread->general_tag, &thread_ready); +// list_add_tail(&thread->all_list_tag, &thread_all); +// io_store_eflags(flags); +// } /** * @brief 为进程加载段 @@ -143,21 +143,21 @@ void process_excute(void *entry, struct program_struct *prog) { * @param vaddr 段的虚拟地址 * @return int 成功为0,失败为-1 */ -MemoryResult process_load_segment( - struct task_s *thread, struct index_node *inode, unsigned long offset, - unsigned long filesz, unsigned long memsz, unsigned long vaddr) { - unsigned long size0 = PAGE_SIZE - (vaddr & 0xfff); - unsigned long page_num = 1; - if (memsz > size0) { page_num += DIV_ROUND_UP(memsz - size0, PAGE_SIZE); } +// MemoryResult process_load_segment( +// struct task_s *thread, struct index_node *inode, unsigned long offset, +// unsigned long filesz, unsigned long memsz, unsigned long vaddr) { +// unsigned long size0 = PAGE_SIZE - (vaddr & 0xfff); +// unsigned long page_num = 1; +// if (memsz > size0) { page_num += DIV_ROUND_UP(memsz - size0, PAGE_SIZE); } - uint32_t *addr = kernel_alloc_pages(page_num); - MEMORY_RESULT_DELIVER_CALL( - thread_use_page, thread, vaddr, vir2phy((uint32_t)addr), page_num); +// uint32_t *addr = kernel_alloc_pages(page_num); +// MEMORY_RESULT_DELIVER_CALL( +// thread_use_page, thread, vaddr, vir2phy((uint32_t)addr), page_num); - inode->f_ops.seek(inode, offset, 0); - inode->f_ops.read(inode, (uint8_t *)(addr + (vaddr & 0xfff)), filesz); - if (memsz > filesz) { - memset((void *)(addr + (vaddr & 0xfff) + filesz), 0, memsz - filesz); - } - return MEMORY_RESULT_OK; -} \ No newline at end of file +// seek(inode, offset, 0); +// read(inode, (uint8_t *)(addr + (vaddr & 0xfff)), filesz); +// if (memsz > filesz) { +// memset((void *)(addr + (vaddr & 0xfff) + filesz), 0, memsz - filesz); +// } +// return MEMORY_RESULT_OK; +// } \ No newline at end of file diff --git a/src/network/Makefile b/src/network/Makefile deleted file mode 100644 index d88c4da..0000000 --- a/src/network/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -SRC += network.c -SRC += eth.c -SRC += arp.c -SRC += ipv4.c -SRC += udp.c -SRC += dhcp.c -SRC += tcp.c \ No newline at end of file diff --git a/src/network/arp.c b/src/network/arp.c deleted file mode 100644 index 578138a..0000000 --- a/src/network/arp.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include -#include -#include -#include - -LIST_HEAD(arp_cache_lh); - -uint8_t *ip2mac(netc_t *netc, uint8_t *ip) { - arp_cache_t *cur, *next; - arp_cache_t *cache; - list_for_each_owner_safe (cur, next, &arp_cache_lh, list) { - if (memcmp(cur->ip, ip, 4) == 0) { - if (cur->mac[0] != 0) { - return cur->mac; - } else { - // TODO: lock - wait_queue_add(&cur->wq); - thread_set_status(TASK_INTERRUPTIBLE); - } - } - } - - cache = kmalloc(sizeof(arp_cache_t)); - memcpy(cache->ip, ip, 4); - wait_queue_init(&cache->wq); - list_add_tail(&cache->list, &arp_cache_lh); - send_arp(netc, ip, ARP_REQUEST); - while (cache->mac[0] == 0) {} - return cache->mac; -} - -void send_arp(netc_t *netc, uint8_t *dst_ip, uint16_t opcode) { - arp_pack_t pack; - - pack.hwtype = HOST2BE_WORD(ARP_HWTYPE_ETH); - pack.pttype = HOST2BE_WORD(ARP_PTTYPE_IPV4); - pack.hwlen = 6; - pack.ptlen = 4; - pack.opcode = HOST2BE_WORD(opcode); - - memcpy(pack.src_hw_addr, netc->net_dev->info->mac, 6); - ipv4_get_ip(netc, pack.src_ip); - memcpy(pack.dst_ip, dst_ip, 4); - memcpy(pack.dst_hw_addr, netc->dst_mac, 6); - - netc->net_dev->net_write(netc, (uint8_t *)&pack, sizeof(arp_pack_t)); -} - -void arp_read(uint8_t *buf, uint16_t offset, uint16_t length) { - arp_pack_t *arp; - arp_cache_t *cur, *next; - - arp = (arp_pack_t *)(buf + offset); - arp->hwtype = BE2HOST_WORD(arp->hwtype); - arp->pttype = BE2HOST_WORD(arp->pttype); - arp->opcode = BE2HOST_WORD(arp->opcode); - - if (arp->opcode == ARP_REPLY) { - list_for_each_owner_safe (cur, next, &arp_cache_lh, list) { - if (memcmp(cur->ip, arp->src_ip, 4) == 0) { - if (cur->mac[0] == 0) { - memcpy(cur->mac, arp->src_hw_addr, 6); - wait_queue_wakeup_all(&cur->wq); - } else { - memcpy(cur->mac, arp->src_hw_addr, 6); - } - return; - } - } - } - return; -} diff --git a/src/network/dhcp.c b/src/network/dhcp.c deleted file mode 100644 index 62dad46..0000000 --- a/src/network/dhcp.c +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint8_t dhcp_magic_cookie[4] = {99, 130, 83, 99}; - -int dhcp_main(net_device_t *net_dev) { - uint8_t *buf = kmalloc(sizeof(dhcp_basic_t) + 20); - device_t *device = net_dev->device; - netc_t *netc; - dhcp_basic_t dhcp; - dhcp_info_t *dhcp_info = kmalloc(sizeof(dhcp_info_t)); - uint8_t option = DHCP_OPTION_END, len, msg_type; - - int flag; - - net_dev->info->dhcp_data = dhcp_info; - - memset(&dhcp, 0, sizeof(dhcp_basic_t)); - dhcp.Op = DHCP_OP_REQUEST; - if (device->type == DEV_ETH_NET) { - dhcp.htype = 1; - dhcp.hlen = 6; - } else { - return -1; - } - dhcp.hops = 0; - dhcp.xID = HOST2BE_DWORD(rand()); - dhcp.secs = 0; - dhcp.flags = HOST2BE_WORD(0x8000); - memcpy(dhcp.chAddr, net_dev->info->mac, 6); - - memcpy(buf, &dhcp, sizeof(dhcp_basic_t)); - memcpy(buf + sizeof(dhcp_basic_t), dhcp_magic_cookie, 4); - buf[sizeof(dhcp_basic_t) + 4] = DHCP_OPTION_MSG_TYPE; - buf[sizeof(dhcp_basic_t) + 5] = 1; - buf[sizeof(dhcp_basic_t) + 6] = DHCP_DISCOVER; - buf[sizeof(dhcp_basic_t) + 7] = DHCP_OPTION_END; - - netc = netc_create(net_dev, ETH_TYPE_IPV4, PROTOCOL_UDP); - netc_set_dest(netc, broadcast_mac, NULL, 0); - if (udp_bind(netc, broadcast_ipv4_addr, 68, 67) < 0) return -1; - - udp_send(netc, (uint16_t *)buf, sizeof(dhcp_basic_t) + 8); - netc_read(netc, buf, sizeof(dhcp_basic_t) + 4); - if (memcmp(buf + sizeof(dhcp_basic_t), dhcp_magic_cookie, 4) != 0) - return -2; - netc_read(netc, &option, sizeof(option)); - netc_read(netc, &len, sizeof(len)); - if (option != DHCP_OPTION_MSG_TYPE) return -3; - netc_read(netc, &msg_type, len); - if (msg_type != DHCP_OFFER) return -3; - - memcpy(dhcp_info->server_ip, ((dhcp_basic_t *)buf)->siAddr, 4); - - struct ipv4_data *ipv4 = (struct ipv4_data *)netc->net_dev->info->ipv4_data; - flag = 1; - while (flag) { - netc_read(netc, &option, sizeof(option)); - netc_read(netc, &len, sizeof(len)); - switch (option) { - case DHCP_OPTION_END: - flag = 0; - break; - case DHCP_OPTION_SERVER_ID: - netc_read(netc, (uint8_t *)&dhcp_info->server_id, 4); - break; - case DHCP_OPTION_ROUTER: - netc_read(netc, ipv4->router_ip, len); - break; - case DHCP_OPTION_SUBNET_MASK: - netc_read(netc, ipv4->subnet_mask, len); - break; - case DHCP_OPTION_DOMAIN_SERVER: - netc_read(netc, ipv4->dns_server_ip, len); - break; - case DHCP_OPTION_LEASE_TIME: - netc_read(netc, (uint8_t *)&dhcp_info->lease_time, 4); - dhcp_info->lease_time = BE2HOST_DWORD(dhcp_info->lease_time); - break; - - default: - break; - } - } - netc_drop_all(netc); - - uint8_t *options = buf + sizeof(dhcp_basic_t) + 4; - memcpy(buf, &dhcp, sizeof(dhcp_basic_t)); - options[0] = DHCP_OPTION_MSG_TYPE; - options[1] = 1; - options[2] = DHCP_REQUEST; - options[3] = DHCP_OPTION_SERVER_ID; - options[4] = 4; - memcpy(options + 5, &dhcp_info->server_id, 4); - options[9] = DHCP_OPTION_LEASE_TIME; - options[10] = 4; - *((uint32_t *)(options + 11)) = HOST2BE_DWORD(dhcp_info->lease_time); - options[15] = DHCP_OPTION_END; - udp_send(netc, (uint16_t *)buf, sizeof(dhcp_basic_t) + 20); - - netc_read(netc, buf, sizeof(dhcp_basic_t) + 4); - if (memcmp(buf + sizeof(dhcp_basic_t), dhcp_magic_cookie, 4) != 0) - return -2; - ipv4_set_ip(netc, ((dhcp_basic_t *)buf)->yiAddr); - netc_read(netc, &option, sizeof(option)); - netc_read(netc, &len, sizeof(len)); - if (option != DHCP_OPTION_MSG_TYPE) return -3; - netc_read(netc, &msg_type, len); - if (msg_type == DHCP_NAK) return -4; - else if (msg_type != DHCP_ACK) return -3; - while (1) { - netc_read(netc, &option, 1); - if (option != DHCP_OPTION_END) { - netc_read(netc, &len, 1); - netc_read(netc, buf, len); - } else { - break; - } - } - - netc_drop_all(netc); - udp_unbind(netc); - netc_delete(netc); - - return 0; -} \ No newline at end of file diff --git a/src/network/eth.c b/src/network/eth.c deleted file mode 100644 index 6ea602c..0000000 --- a/src/network/eth.c +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void eth_device_register(struct _device_manager_s *dm, device_t *device, char *name); -void eth_device_unregister(struct _device_manager_s *dm, device_t *device); -void eth_driver_inited(struct _device_manager_s *dm); - -device_manager_t eth_dm = { - .name = {0, 0, NULL}, - .private_data = eth_handler, - .dm_register = eth_device_register, - .dm_unregister = eth_device_unregister, - .drv_inited = eth_driver_inited, -}; - -int eth_read(netc_t *netc, uint8_t *buffer, uint32_t length) { - // device_t *device = list_owner(&inode->device->listm, device_t, listm); - // return device->drv_obj->function.driver_read(device, buffer, 0, length); - return 0; -} - -int eth_write(netc_t *netc, uint8_t *buffer, uint32_t length) { - eth_frame_t *frame; - uint16_t size = MAX(ETH_MIN_FRAME_SIZE, length + 14); - uint8_t *buf = kmalloc(size); - frame = (eth_frame_t *)buf; - - memcpy(frame->src_mac, netc->net_dev->info->mac, 6); - memcpy(frame->dest_mac, netc->dst_mac, 6); - frame->type = HOST2BE_WORD(netc->protocol); - memcpy(buf + 14, buffer, length); - memset(buf + length + 14, 0, size - length - 14); - DEV_WRITE(netc->net_dev->device, buf, 0, size); - kfree(buf); - return 0; -} - -void eth_handler(net_rx_pack_t *pack, uint8_t *buf, uint16_t size) { - eth_frame_t *frame; - - frame = (eth_frame_t *)buf; - frame->type = BE2HOST_WORD(frame->type); - switch (frame->type) { - case ETH_TYPE_IPV4: - ipv4_read(pack, buf, sizeof(eth_frame_t), size - sizeof(eth_frame_t)); - break; - case ETH_TYPE_ARP: - arp_read(buf, sizeof(eth_frame_t), size - sizeof(eth_frame_t)); - break; - - default: - break; - } -} - -void eth_device_register(struct _device_manager_s *dm, device_t *device, char *name) { - net_device_t *net_dev; - string_init(&device->name); - string_new(&device->name, name, strlen(name)); - net_dev = kmalloc(sizeof(net_device_t)); - net_dev->info = kmalloc(sizeof(struct network_info)); - net_dev->device = device; - net_dev->enable = 1; - list_add_tail(&net_dev->list, &dm->dev_listhead); - ipv4_init(net_dev); - - if (default_net_dev == NULL) { default_net_dev = net_dev; } -} - -void eth_device_unregister(struct _device_manager_s *dm, device_t *device) { - net_device_t *cur, *next; - string_del(&device->name); - list_for_each_owner_safe (cur, next, &dm->dev_listhead, list) { - if (cur->device == device) { - list_del(&cur->list); - return; - } - } -} - -void eth_driver_inited(struct _device_manager_s *dm) { - status_t stat; - net_device_t *cur, *next; - list_for_each_owner_safe (cur, next, &dm->dev_listhead, list) { - stat = cur->device->drv_obj->function.driver_open(cur->device); - DEV_CTL(cur->device, NET_FUNC_GET_MAC_ADDR, cur->info->mac); - if (stat != SUCCUESS) { - cur->enable = 0; - } else { - cur->net_read = ð_read; - cur->net_write = ð_write; - } - } -} diff --git a/src/network/ipv4.c b/src/network/ipv4.c deleted file mode 100644 index 77e3964..0000000 --- a/src/network/ipv4.c +++ /dev/null @@ -1,133 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint8_t broadcast_ipv4_addr[4] = {0xff, 0xff, 0xff, 0xff}; - -void ipv4_init(net_device_t *netdev) { - struct ipv4_data *data; - struct network_info *net = netdev->info; - - net->ipv4_data = kmalloc(sizeof(struct ipv4_data)); - data = (struct ipv4_data *)net->ipv4_data; - memset(data->ip_addr, 0, 4); - spinlock_init(&data->idlock); - data->counter = 0; - memset(data->ip_addr, 0, 6); - DEV_CTL(netdev->device, NET_FUNC_GET_MTU, &data->mtu); - data->mtu -= 20; // 去掉ip头的长度 -} - -void ipv4_send_pack( - netc_t *netc, uint8_t *dst_ip, uint8_t flags, uint8_t id, uint8_t ttl, - uint8_t protocol, uint8_t offset, uint8_t *data, uint16_t datalen) { - int i; - uint32_t chksum = 0; - ipv4_header_t *header; - net_device_t *net_dev = netc->net_dev; - struct ipv4_data *ipv4 = (struct ipv4_data *)net_dev->info->ipv4_data; - - uint16_t *buf = kmalloc(20 + datalen); - header = (ipv4_header_t *)buf; - - header->Version = 4; - header->IHL = 20 / 4; - header->TypeOfService = 0; - header->TotalLength = HOST2BE_WORD(20 + datalen); - header->Identification = HOST2BE_WORD(id); - header->Offset = HOST2BE_WORD((offset >> 3) | (flags << 13)); - header->TimetoLive = ttl; - header->Protocol = protocol; - header->HeaderChecksum = 0; // 先置0防止影响checksum计算 - memcpy(header->SourceAddress, ipv4->ip_addr, 4); - memcpy(header->DestinationAddress, dst_ip, 4); - memcpy((uint8_t *)buf + 20, data + offset, datalen); - - for (i = 0; i < 20 / sizeof(uint16_t); i++) { - chksum += BE2HOST_WORD(buf[i]); - } - header->HeaderChecksum = - HOST2BE_WORD(~(uint16_t)((chksum & 0xffff) + (chksum >> 16))); - - net_dev->net_write(netc, (uint8_t *)buf, datalen + 20); - - kfree(buf); -} - -int ipv4_send( - netc_t *netc, uint8_t *dst_ip, uint8_t DF, uint8_t ttl, uint8_t protocol, - uint8_t *data, uint32_t datalen) { - uint32_t i, id; - uint32_t len; - net_device_t *net_dev = netc->net_dev; - struct ipv4_data *ipv4 = (struct ipv4_data *)net_dev->info->ipv4_data; - - if (netc->dst_mac[0] == 0) return -1; - - i = 0; - len = datalen; - - spin_lock(&ipv4->idlock); - id = ipv4->counter++; - spin_unlock(&ipv4->idlock); - - while (len > ipv4->mtu) { - if (DF) { return -1; } // 不允许分片则直接退出 - ipv4_send_pack( - netc, dst_ip, 1, id, ttl, protocol, i * ipv4->mtu, data, ipv4->mtu); - i++; - } - ipv4_send_pack( - netc, dst_ip, 0, id, ttl, protocol, i * ipv4->mtu, data, - datalen % ipv4->mtu); - return 0; -} - -void ipv4_read( - net_rx_pack_t *pack, uint8_t *buf, uint16_t offset, uint16_t length) { - ipv4_header_t *header = (ipv4_header_t *)(buf + offset); - - header->HeaderChecksum = BE2HOST_WORD(header->HeaderChecksum); - header->Identification = BE2HOST_WORD(header->Identification); - header->Offset = BE2HOST_WORD(header->Offset); - header->TotalLength = BE2HOST_WORD(header->TotalLength); - - switch (header->Protocol) { - case PROTOCOL_TCP: - net_raw2tcp_pack( - pack, 4, header->SourceAddress, offset + 20, - header->TotalLength - 20); - break; - case PROTOCOL_UDP: - net_raw2udp_pack(pack, offset + 20, header->TotalLength - 20); - break; - - default: - kfree(pack->data); - kfree(pack); - break; - } -} - -void ipv4_get_ip(netc_t *netc, uint8_t *ip) { - struct ipv4_data *ipv4 = (struct ipv4_data *)netc->net_dev->info->ipv4_data; - memcpy(ip, ipv4->ip_addr, 4); -} - -void ipv4_set_ip(netc_t *netc, uint8_t *ip) { - struct ipv4_data *ipv4 = (struct ipv4_data *)netc->net_dev->info->ipv4_data; - memcpy(ipv4->ip_addr, ip, 4); -} - -int ipv4_get_mtu(netc_t *netc) { - struct ipv4_data *ipv4 = (struct ipv4_data *)netc->net_dev->info->ipv4_data; - return ipv4->mtu; -} diff --git a/src/network/network.c b/src/network/network.c deleted file mode 100644 index b6f03c8..0000000 --- a/src/network/network.c +++ /dev/null @@ -1,159 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -LIST_HEAD(net_rx_raw_pack_lh); -LIST_HEAD(net_rx_tcp_lh); -LIST_HEAD(net_rx_udp_lh); - -const int default_ttl = 64; - -uint8_t broadcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - -net_device_t *default_net_dev; - -void init_network(void) { - default_net_dev = NULL; - list_init(ð_dm.dev_listhead); -} - -netc_t *netc_create( - net_device_t *net_dev, uint16_t protocol, uint16_t app_protocol) { - netc_t *netc = kmalloc(sizeof(netc_t)); - - spinlock_init(&netc->spin_lock); - - netc->net_dev = net_dev; - netc->thread = get_current_thread(); - netc->proto_private = NULL; - netc->app_private = NULL; - netc->recv_buffer = kmalloc(NET_MAX_BUFFER_SIZE); - netc->recv_offset = 0; - netc->recv_len = 0; - netc->protocol = protocol; - netc->app_protocl = app_protocol; - return netc; -} - -int netc_delete(netc_t *netc) { - if (netc->proto_private != NULL) { kfree(netc->proto_private); } - if (netc->app_private != NULL) { kfree(netc->app_private); } - kfree(netc); - return 0; -} - -void netc_set_dest( - netc_t *netc, uint8_t dst_mac[6], uint8_t *dst_laddr, - uint8_t dst_laddr_len) { - memcpy(netc->dst_mac, dst_mac, 6); - if (dst_laddr != NULL) { - memcpy(netc->dst_laddr, dst_laddr, dst_laddr_len); - } -} - -int netc_read(netc_t *netc, uint8_t *buf, uint32_t size) { - while (netc->recv_len == 0) {} - - int real_size = MIN(netc->recv_len, size); - if (netc->recv_offset + real_size > NET_MAX_BUFFER_SIZE) { - int tmp = NET_MAX_BUFFER_SIZE - netc->recv_offset; - memcpy(buf, netc->recv_buffer + netc->recv_offset, tmp); - memcpy(buf + tmp, netc->recv_buffer, real_size - tmp); - netc->recv_offset = real_size - tmp; - netc->recv_len -= real_size; - } else { - memcpy(buf, netc->recv_buffer + netc->recv_offset, real_size); - netc->recv_offset += real_size; - netc->recv_len -= real_size; - } - return real_size; -} - -void netc_drop_all(netc_t *netc) { - netc->recv_offset = 0; - netc->recv_len = 0; -} - -void netc_ip_send( - netc_t *netc, uint8_t *ip, uint8_t DF, uint8_t proto, uint8_t *buf, - uint32_t size) { - if (netc->protocol == ETH_TYPE_IPV4) { - ipv4_send(netc, ip, DF, default_ttl, proto, buf, size); - } -} - -int netc_get_mtu(netc_t *netc) { - switch (netc->protocol) { - case ETH_TYPE_IPV4: - return ipv4_get_mtu(netc); - break; - default: - break; - } -} - -void net_process_pack(void *arg) { - net_rx_pack_t *pack_cur, *next; - while (1) { - if (!list_empty(&net_rx_raw_pack_lh)) { - list_for_each_owner_safe ( - pack_cur, next, &net_rx_raw_pack_lh, list) { - list_del(&pack_cur->list); - switch (pack_cur->type) { - case ETH_FRAME: - eth_handler(pack_cur, pack_cur->data, pack_cur->data_len); - break; - default: - break; - } - } - list_for_each_owner_safe (pack_cur, next, &net_rx_tcp_lh, list) { - list_del(&pack_cur->list); - tcp_recv( - pack_cur->data, pack_cur->proto_start, pack_cur->data_len, - pack_cur->src_ip_addr, pack_cur->src_ip_len); - } - // kfree(pack_cur->data); - kfree(pack_cur); - } else { - schedule(); - } - } -} - -void net_rx_raw_pack(enum frame_type type, uint8_t *buf, uint32_t length) { - - net_rx_pack_t *pack = kmalloc(sizeof(net_rx_pack_t)); - pack->type = type; - pack->data = buf; - pack->len = length; - list_add_tail(&pack->list, &net_rx_raw_pack_lh); -} - -void net_raw2tcp_pack( - net_rx_pack_t *pack, uint8_t ip_len, uint8_t *ip_addr, uint32_t start, - uint32_t len) { - pack->proto_start = start; - pack->src_ip_len = ip_len; - pack->src_ip_addr = ip_addr; - pack->data_len = len; - list_add_tail(&pack->list, &net_rx_tcp_lh); -} - -void net_raw2udp_pack(net_rx_pack_t *pack, uint32_t start, uint32_t len) { - pack->proto_start = start; - pack->data_len = len; - list_add_tail(&pack->list, &net_rx_tcp_lh); -} diff --git a/src/network/tcp.c b/src/network/tcp.c deleted file mode 100644 index 6296f9c..0000000 --- a/src/network/tcp.c +++ /dev/null @@ -1,573 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -SPINLOCK(tcp_lock); -LIST_HEAD(tcp_lh); - -const int rmem_defualt_size = 32768; -const int wmem_defualt_size = 16384; - -uint16_t tcp_checksum( - netc_t *netc, uint8_t dst_ip[4], uint8_t *buf, uint32_t length) { - int i; - uint8_t src_ip[4]; - uint32_t chksum = 0; - ipv4_get_ip(netc, src_ip); - chksum += (src_ip[0] << 8) + src_ip[1]; - chksum += (src_ip[2] << 8) + src_ip[3]; - chksum += (dst_ip[0] << 8) + dst_ip[1]; - chksum += (dst_ip[2] << 8) + dst_ip[3]; - chksum += PROTOCOL_TCP; - chksum += length; - for (i = 0; i < length / sizeof(uint16_t); i++) { - chksum += (buf[i * 2] << 8) + buf[i * 2 + 1]; - } - if (length % sizeof(uint16_t)) { chksum += buf[length - 1] << 8; } - while (chksum & 0xffff0000) { - chksum = (chksum >> 16) + (chksum & 0xffff); - } - - return (~chksum) & 0xffff; -} - -int tcp_send_for_status_change(netc_t *netc, uint8_t *buf, int length) { - tcp_conn_t *conn = (tcp_conn_t *)netc->app_private; - tcp_status_t status = conn->status; - - netc_ip_send(netc, conn->dst_ip, 0, PROTOCOL_TCP, buf, length); - - conn->wait_ms = 600; - timer_init(&conn->timer); - delay_ms_async(&conn->timer, conn->wait_ms); - while (conn->status == status) { - if (!timer_is_timeout(&conn->timer)) { - while (!timer_is_timeout(&conn->timer)) - ; - conn->wait_ms *= 2; - if (conn->wait_ms >= 120000) { return -1; } - netc_ip_send(netc, conn->dst_ip, 0, PROTOCOL_TCP, buf, length); - delay_ms_async(&conn->timer, conn->wait_ms); - } - } - timer_init(&conn->timer); - return 0; -} - -int tcp_send(netc_t *netc, uint8_t *buf, int length) { - tcp_conn_t *conn = (tcp_conn_t *)netc->app_private; - uint8_t *sendbuf = kmalloc(sizeof(tcp_header_t) + length); - tcp_header_t *header = (tcp_header_t *)sendbuf; - - memcpy(header, conn->header_buf, sizeof(tcp_header_t)); - - header->seq = HOST2BE_DWORD(conn->seq); - header->ack = HOST2BE_DWORD(conn->ack); - header->flags = TCP_FLAG_PSH | TCP_FLAG_ACK; - header->ack = HOST2BE_DWORD(conn->ack); - header->window = - HOST2BE_WORD(conn->rwin.size - conn->rwin.acked - conn->rwin.recved); - header->urgent_pointer = 0; - - memcpy(sendbuf + sizeof(tcp_header_t), buf, length); - header->checksum = 0; - header->checksum = HOST2BE_WORD(tcp_checksum( - netc, conn->dst_ip, sendbuf, sizeof(tcp_header_t) + length)); - - conn->swin.unacked += length; - conn->swin.sended -= length; - - netc_ip_send( - netc, conn->dst_ip, 0, PROTOCOL_TCP, sendbuf, - sizeof(tcp_header_t) + length); - - conn->wait_ms = 600; - timer_init(&conn->timer); - delay_ms_async(&conn->timer, conn->wait_ms); - while (conn->swin.unacked) { - if (!timer_is_timeout(&conn->timer)) { - while (!timer_is_timeout(&conn->timer)) - ; - conn->wait_ms *= 2; - if (conn->wait_ms >= 120000) { return -1; } - netc_ip_send( - netc, conn->dst_ip, 0, PROTOCOL_TCP, sendbuf, - sizeof(tcp_header_t) + length); - delay_ms_async(&conn->timer, conn->wait_ms); - } - } - kfree(sendbuf); - return 0; -} - -int wait_for_status_change(netc_t *netc) { - tcp_conn_t *conn = (tcp_conn_t *)netc->app_private; - tcp_status_t status = conn->status; - int i = 0; - - conn->wait_ms = 1000; - timer_init(&conn->timer); - delay_ms_async(&conn->timer, conn->wait_ms); - while (conn->status == status) { - if (!timer_is_timeout(&conn->timer)) { - while (!timer_is_timeout(&conn->timer)) - ; - i++; - if (i > 10) return -1; - } - } - return 0; -} - -void tcp_analyse_option(netc_t *netc, uint8_t *buf) { - int i = 0; - tcp_conn_t *conn = (tcp_conn_t *)netc->app_private; - uint8_t option_size = - (((tcp_header_t *)buf)->offset >> 4) * 4 - sizeof(tcp_header_t); - buf += sizeof(tcp_header_t); - - while (i < option_size) { - switch (buf[i]) { - case TCP_OPTION_END: - return; - case TCP_OPTION_NOP: - break; - case TCP_OPTION_MSS: - conn->mss = - MIN(conn->mss, BE2HOST_WORD(*(uint16_t *)(buf + i + 2))); - break; - default: - break; - } - } -} - -void tcp_create(netc_t *netc) { - tcp_conn_t *conn; - netc->app_private = kmalloc(sizeof(tcp_conn_t)); - conn = (tcp_conn_t *)netc->app_private; - conn->netc = netc; -} - -int tcp_bind(netc_t *netc, uint16_t src_port) { - tcp_conn_t *conn = (tcp_conn_t *)netc->app_private, *cur, *next; - - spin_lock(&tcp_lock); - list_for_each_owner_safe (cur, next, &tcp_lh, list) { - if (cur->src_port == src_port) { return -1; } - } - list_add_tail(&conn->list, &tcp_lh); - spin_unlock(&tcp_lock); - - conn->src_port = src_port; - conn->seq = rand(); - conn->ack = 0; - - conn->rwin.mem = kmalloc(rmem_defualt_size); - - conn->rwin.size = rmem_defualt_size; - conn->swin.size = 0; - conn->rwin.acked = 0; - conn->rwin.unacked = 0; - conn->swin.unacked = 0; - conn->rwin.recved = 0; - conn->swin.sended = 0; - conn->rwin.head = 0; - conn->swin.head = 0; - conn->rwin.tail = 0; - conn->swin.tail = 0; - - conn->mss = netc_get_mtu(netc) - sizeof(tcp_header_t); - - conn->status = TCP_STAT_CLOSED; - return 0; -} - -int tcp_unbind(netc_t *netc) { - tcp_conn_t *conn = (tcp_conn_t *)netc->app_private; - spin_lock(&tcp_lock); - list_del(&conn->list); - list_add_tail(&conn->list, &tcp_lh); - return 0; -} - -int tcp_ipv4_connect(netc_t *netc, uint8_t *ip, uint16_t dst_port) { - tcp_header_t *header; - tcp_conn_t *conn; - int tcp_length = sizeof(tcp_header_t) + 4; - - conn = (tcp_conn_t *)netc->app_private; - conn->header_buf = kmalloc(sizeof(tcp_header_t)); - header = (tcp_header_t *)conn->header_buf; - - conn->dst_port = dst_port; - memcpy(conn->dst_ip, ip, 4); - - // TCP第一次握手 - - header->src_port = HOST2BE_WORD(conn->src_port); - header->dst_port = HOST2BE_WORD(conn->dst_port); - header->seq = HOST2BE_DWORD(conn->seq); - header->ack = 0; - header->offset = (tcp_length / 4) << 4; - header->flags = TCP_FLAG_SYN; - header->window = HOST2BE_WORD(rmem_defualt_size); - header->urgent_pointer = 0; - header->checksum = 0; - - // 设置TCP Option最大分片大小(Maximum segment size) - conn->header_buf[sizeof(tcp_header_t) + 0] = TCP_OPTION_MSS; - conn->header_buf[sizeof(tcp_header_t) + 1] = 4; // 该Option长度为4字节 - *(uint16_t *)(conn->header_buf + sizeof(tcp_header_t) + 2) = - HOST2BE_WORD(1460); - - header->checksum = HOST2BE_WORD( - tcp_checksum(netc, conn->dst_ip, conn->header_buf, tcp_length)); - - conn->status = TCP_STAT_SYN_SENT; - - conn->seq += 1; - tcp_send_for_status_change(netc, conn->header_buf, tcp_length); // 发送SYN包 - tcp_length = sizeof(tcp_header_t); - header->offset = (tcp_length / 4) << 4; - if (conn->status == TCP_STAT_CLOSED) { - kfree(conn->rwin.mem); - // Timer - // timer_free(conn->timer); - kfree(conn); - return -1; - } - - conn->swin.mem = (uint8_t *)kmalloc(conn->swin.size); - - // 第二次握手 - - // 回应ACK - header->seq = HOST2BE_DWORD(conn->seq); - header->ack = HOST2BE_DWORD(conn->ack); - header->flags = TCP_FLAG_ACK; - header->checksum = 0; - header->checksum = HOST2BE_WORD( - tcp_checksum(netc, conn->dst_ip, conn->header_buf, tcp_length)); - netc_ip_send( - netc, conn->dst_ip, 0, PROTOCOL_TCP, conn->header_buf, tcp_length); - - return 0; -} - -int tcp_listen(netc_t *netc) { - tcp_header_t *header; - tcp_conn_t *conn; - int tcp_length = sizeof(tcp_header_t); - - conn = (tcp_conn_t *)netc->app_private; - - conn->status = TCP_STAT_LISTEN; - if (wait_for_status_change(netc) != 0) return -1; - - conn->header_buf = kmalloc(tcp_length); - header = (tcp_header_t *)conn->header_buf; - header->src_port = HOST2BE_WORD(conn->src_port); - header->dst_port = HOST2BE_WORD(conn->dst_port); - header->seq = HOST2BE_DWORD(conn->seq); - header->ack = HOST2BE_DWORD(conn->ack); - header->offset = (tcp_length / 4) << 4; - header->flags = TCP_FLAG_SYN | TCP_FLAG_ACK; - header->window = HOST2BE_WORD(rmem_defualt_size); - header->urgent_pointer = 0; - header->checksum = 0; - header->checksum = HOST2BE_WORD( - tcp_checksum(netc, conn->dst_ip, conn->header_buf, tcp_length)); - - conn->seq += 1; - tcp_send_for_status_change(netc, conn->header_buf, tcp_length); - if (conn->status != TCP_STAT_ESTABLISHED) return -2; - return 0; -} - -void tcp_ipv4_close(netc_t *netc) { - tcp_header_t *header; - tcp_conn_t *conn = (tcp_conn_t *)netc->app_private; - header = (tcp_header_t *)conn->header_buf; - - header->seq = HOST2BE_DWORD(conn->seq); - header->ack = HOST2BE_DWORD(conn->ack); - header->flags = TCP_FLAG_FIN | TCP_FLAG_ACK; - header->window = - HOST2BE_WORD(conn->rwin.size - conn->rwin.recved - conn->rwin.acked); - header->urgent_pointer = 0; - header->checksum = 0; - header->checksum = HOST2BE_WORD(tcp_checksum( - netc, conn->dst_ip, conn->header_buf, sizeof(tcp_header_t))); - - conn->status = TCP_STAT_FIN_WAIT1; - conn->seq += 1; - tcp_send_for_status_change(netc, conn->header_buf, sizeof(tcp_header_t)); - - if (conn->status == TCP_STAT_FIN_WAIT2) { - if (wait_for_status_change(netc) != 0) goto end; - } - if (conn->status == TCP_STAT_TIME_WAIT) { - header->seq = HOST2BE_DWORD(conn->seq); - header->ack = HOST2BE_DWORD(conn->ack); - header->flags = TCP_FLAG_ACK; - header->checksum = 0; - header->checksum = HOST2BE_WORD(tcp_checksum( - netc, conn->dst_ip, conn->header_buf, sizeof(tcp_header_t))); - - netc_ip_send( - netc, conn->dst_ip, 0, PROTOCOL_TCP, conn->header_buf, - sizeof(tcp_header_t)); - - conn->wait_ms = 2 * TCP_MSL_MS; - - delay_ms_async(&conn->timer, conn->wait_ms); - while (!timer_is_timeout(&conn->timer)) - ; - } -end: - kfree(conn->rwin.mem); - kfree(conn); - return; -} - -void tcp_recv( - uint8_t *buf, uint16_t offset, uint16_t length, uint8_t *ip, - uint8_t ip_len) { - netc_t *netc; - tcp_header_t *tcp_head = (tcp_header_t *)(buf + offset); - uint16_t chksum = tcp_head->checksum; - tcp_header_t *header; - int flag = 1; - int len, head_len; - - uint16_t src_port = BE2HOST_WORD(tcp_head->src_port); - uint16_t dst_port = BE2HOST_WORD(tcp_head->dst_port); - - tcp_conn_t *conn, *cur, *next; - spin_lock(&tcp_lock); - list_for_each_owner_safe (cur, next, &tcp_lh, list) { - if (cur->src_port == dst_port) { - if ((cur->dst_port == src_port && - memcmp(cur->dst_ip, ip, ip_len) == 0) || - cur->status == TCP_STAT_LISTEN) { - conn = cur; - flag = 0; - break; - } - } - } - spin_unlock(&tcp_lock); - - if (flag || conn->status == TCP_STAT_CLOSED) { return; } - netc = conn->netc; - - tcp_head->checksum = 0; - if (chksum != HOST2BE_WORD(tcp_checksum( - netc, netc->dst_laddr, buf + offset, length))) { - return; - } - if (tcp_head->flags & TCP_FLAG_RST) { conn->status = TCP_STAT_CLOSED; } - - header = (tcp_header_t *)conn->header_buf; - head_len = (tcp_head->offset & 0xf0) >> 2; - len = length - head_len; - - uint32_t r_seq = BE2HOST_DWORD(tcp_head->seq); - uint32_t r_ack = BE2HOST_DWORD(tcp_head->ack); - - switch (conn->status) { - case TCP_STAT_LISTEN: - if (tcp_head->flags & TCP_FLAG_SYN) { - conn->ack = r_seq; - conn->dst_port = BE2HOST_WORD(tcp_head->dst_port); - memcpy(conn->dst_ip, ip, ip_len); - conn->status = TCP_STAT_SYN_RCVD; - } - break; - case TCP_STAT_SYN_SENT: - if (tcp_head->flags & TCP_FLAG_SYN) { - conn->swin.size = - MIN(wmem_defualt_size, BE2HOST_WORD(tcp_head->window)); - conn->ack = r_seq; - } - if (tcp_head->flags & TCP_FLAG_ACK) { - if (conn->seq == r_ack) { conn->status = TCP_STAT_ESTABLISHED; } - } - len = 1; - break; - case TCP_STAT_SYN_RCVD: - if (tcp_head->flags & TCP_FLAG_ACK) { - if (r_ack == conn->seq) { - conn->ack = r_seq; - conn->status = TCP_STAT_ESTABLISHED; - } - } - len = 1; - break; - case TCP_STAT_ESTABLISHED: - // printk("TCP seq=%04X, ack=%04X\n", r_seq, r_ack); - if (len > 0) { - if (conn->rwin.recved + len < conn->rwin.size) { - memcpy( - conn->rwin.mem + conn->rwin.head + conn->rwin.acked + - conn->rwin.recved, - buf + offset + head_len, len); - } else { - int tmp = conn->rwin.size - conn->rwin.recved; - memcpy( - conn->rwin.mem + conn->rwin.head + conn->rwin.acked + - conn->rwin.recved, - buf + offset + head_len, tmp); - memcpy( - conn->rwin.mem, buf + offset + head_len + tmp, len - tmp); - } - conn->rwin.recved += len; - } - // 先处理ACK信息 - uint32_t add = 0; - if (tcp_head->flags & TCP_FLAG_ACK) { - add = len; - if (conn->seq < r_ack) { // 对方确认己方发送的数据 - uint32_t tmp = r_ack - conn->seq; - conn->swin.unacked -= tmp; - conn->seq += tmp; - conn->swin.head = (conn->swin.head + tmp) % conn->swin.size; - conn->swin.tail = (conn->swin.tail + tmp) % conn->swin.size; - } - if ((add > 0 && list_empty(&net_rx_tcp_lh)) || - tcp_head->flags & TCP_FLAG_PSH) { - header->seq = HOST2BE_DWORD(conn->seq); - header->ack = HOST2BE_DWORD(conn->ack + add); - header->flags = TCP_FLAG_ACK; - header->window = - HOST2BE_WORD(conn->rwin.size - conn->rwin.recved); - header->urgent_pointer = 0; - header->checksum = 0; - header->checksum = HOST2BE_WORD(tcp_checksum( - netc, conn->dst_ip, conn->header_buf, - sizeof(tcp_header_t))); - conn->swin.head = (conn->swin.head + conn->rwin.unacked + add) % - conn->swin.size; - conn->swin.tail = (conn->swin.tail + conn->rwin.unacked + add) % - conn->swin.size; - // 发送ACK包表示确认收到 - conn->rwin.acked += conn->rwin.unacked + add; - conn->rwin.recved -= conn->rwin.unacked + add; - conn->rwin.unacked = 0; - netc_ip_send( - netc, conn->dst_ip, 0, PROTOCOL_TCP, conn->header_buf, - sizeof(tcp_header_t)); - } else { - conn->rwin.unacked += add; - } - } - if (tcp_head->flags & TCP_FLAG_FIN) { - header->seq = HOST2BE_DWORD(conn->seq); - header->ack = HOST2BE_DWORD(conn->ack + len); - header->flags = TCP_FLAG_ACK; - header->window = HOST2BE_WORD(conn->rwin.size - conn->rwin.recved); - header->urgent_pointer = 0; - header->checksum = 0; - header->flags |= TCP_FLAG_FIN; - header->checksum = HOST2BE_WORD(tcp_checksum( - netc, conn->dst_ip, conn->header_buf, sizeof(tcp_header_t))); - netc_ip_send( - netc, conn->dst_ip, 0, PROTOCOL_TCP, conn->header_buf, - sizeof(tcp_header_t)); - if (conn->swin.unacked == 0) { - conn->status = TCP_STAT_LAST_ACK; - } else { - conn->status = TCP_STAT_CLOSE_WAIT; - } - } - break; - case TCP_STAT_FIN_WAIT1: - if (tcp_head->flags & TCP_FLAG_ACK) { - if (conn->seq == r_ack) { - conn->status = TCP_STAT_FIN_WAIT2; - kfree(conn->swin.mem); - conn->ack = r_seq; - if (tcp_head->flags & TCP_FLAG_FIN) { - conn->status = TCP_STAT_TIME_WAIT; - } - } - } - break; - case TCP_STAT_FIN_WAIT2: - if (tcp_head->flags & TCP_FLAG_FIN) { - conn->status = TCP_STAT_TIME_WAIT; - } - if (len == 0) { len = 1; } - break; - case TCP_STAT_LAST_ACK: - if (tcp_head->flags & TCP_FLAG_ACK) { conn->status = TCP_STAT_CLOSED; } - break; - - default: - break; - } - conn->ack += len; -} - -int tcp_write(netc_t *netc, uint8_t *buf, uint32_t length) { - tcp_conn_t *conn = (tcp_conn_t *)netc->app_private; - int tmp; - - tmp = conn->swin.size - conn->swin.unacked - conn->swin.sended; - - do { - tmp = MIN(MIN(length, tmp), conn->mss); - memcpy(conn->swin.mem + conn->swin.sended, buf, tmp); - length -= tmp; - buf += tmp; - conn->swin.sended = (conn->swin.sended + tmp) % conn->swin.size; - tcp_send(netc, conn->swin.mem + conn->swin.unacked, tmp); - } while (length > 0); - return 0; -} - -/** - * @brief 读取TCP数据 - * - * @param netc - * @param buf 数据缓冲区 - * @param length 读取的数据长度 - * @return int 实际读取的数据长度 - */ -int tcp_read(netc_t *netc, uint8_t *buf, uint32_t length) { - tcp_conn_t *conn = (tcp_conn_t *)netc->app_private; - int i = 0; - while (conn->rwin.acked == 0) { - i++; - // TODO: Delay - // delay(1); - if (i == 1000) { break; } - } - - /** - * @brief 同时增加head和tail,减小acked,释放部分空间 - * - */ - if (conn->rwin.acked > 0) { - int size = MIN(conn->rwin.acked, length); - memcpy(buf, conn->rwin.mem + conn->rwin.head, size); - conn->rwin.head = (conn->rwin.head + size) % conn->rwin.size; - conn->rwin.tail = (conn->rwin.tail + size) % conn->rwin.size; - conn->rwin.acked -= size; - return size; - } - return 0; -} diff --git a/src/network/udp.c b/src/network/udp.c deleted file mode 100644 index 5d14388..0000000 --- a/src/network/udp.c +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -SPINLOCK(udp_lock); -LIST_HEAD(udp_lh); - -int udp_bind(netc_t *netc, uint8_t ip[4], uint16_t src_port, uint16_t dst_port) { - udp_conn_t *conn, *cur, *next; - netc->app_private = kmalloc(sizeof(udp_conn_t)); - - conn = (udp_conn_t *)netc->app_private; - conn->netc = netc; - - spin_lock(&udp_lock); - list_for_each_owner_safe (cur, next, &udp_lh, list) { - if (cur->src_port == src_port) { return -1; } - } - list_add_tail(&conn->list, &udp_lh); - spin_unlock(&udp_lock); - - conn->src_port = src_port; - conn->dst_port = dst_port; - memcpy(conn->dst_ip, ip, 4); - return 0; -} - -int udp_unbind(netc_t *netc) { - udp_conn_t *conn = (udp_conn_t *)netc->app_private; - spin_lock(&udp_lock); - list_del(&conn->list); - list_add_tail(&conn->list, &udp_lh); - return 0; -} - -void udp_send(netc_t *netc, uint16_t *data, uint16_t datalen) { - uint32_t chksum = 0, i; - udp_head_t *udp_head; - udp_conn_t *conn = (udp_conn_t *)netc->app_private; - uint16_t *buf = kmalloc(sizeof(udp_head_t) + datalen); - uint8_t src_ip[4]; - udp_head = (udp_head_t *)buf; - ipv4_get_ip(netc, src_ip); - - udp_head->SourcePort = HOST2BE_WORD(conn->src_port); - udp_head->DestinationPort = HOST2BE_WORD(conn->dst_port); - udp_head->Length = HOST2BE_WORD(sizeof(udp_head_t) + datalen); - udp_head->Checksum = 0; // 为了方便计算,先置0 - memcpy((uint8_t *)buf + sizeof(udp_head_t), data, datalen); - - // 计算校验和 - // UDP伪首部 - for (i = 0; i < 4 / sizeof(uint16_t); i++) { - chksum += (src_ip[i * 2] << 8) + src_ip[i * 2 + 1]; - chksum += (conn->dst_ip[i * 2] << 8) + conn->dst_ip[i * 2 + 1]; - } - chksum += PROTOCOL_UDP; - chksum += HOST2BE_WORD(udp_head->Length); - // UDP首部 - for (i = 0; i < (sizeof(udp_head_t) + datalen) / sizeof(uint16_t); i++) { - chksum += BE2HOST_WORD(buf[i]); - } - udp_head->Checksum = HOST2BE_WORD(~(uint16_t)((chksum & 0xffff) + (chksum >> 16))); - - ipv4_send(netc, conn->dst_ip, 0, 64, PROTOCOL_UDP, (uint8_t *)buf, sizeof(udp_head_t) + datalen); - kfree(buf); -} - -void udp_read(uint8_t *buf, uint16_t offset, uint16_t length) { - netc_t *netc; - udp_head_t *udp_head = (udp_head_t *)(buf + offset); - udp_conn_t *conn, *cur, *next; - int flag = 1; - - udp_head->DestinationPort = BE2HOST_WORD(udp_head->DestinationPort); - udp_head->SourcePort = BE2HOST_WORD(udp_head->SourcePort); - - spin_lock(&udp_lock); - list_for_each_owner_safe (cur, next, &udp_lh, list) { - if (cur->dst_port == udp_head->SourcePort && cur->src_port == udp_head->DestinationPort) { - conn = cur; - flag = 0; - break; - } - } - spin_unlock(&udp_lock); - if (flag) { return; } - netc = conn->netc; - - uint32_t off = (netc->recv_offset + netc->recv_len) % NET_MAX_BUFFER_SIZE; - if (off + length - sizeof(udp_head_t) > NET_MAX_BUFFER_SIZE) { - int tmp = NET_MAX_BUFFER_SIZE - netc->recv_offset; - memcpy(netc->recv_buffer + off, buf + offset + sizeof(udp_head_t), tmp); - memcpy(netc->recv_buffer, buf + offset + sizeof(udp_head_t) + tmp, length - sizeof(udp_head_t) - tmp); - } else { - memcpy(netc->recv_buffer + off, buf + offset + sizeof(udp_head_t), length - sizeof(udp_head_t)); - } - netc->recv_len += length - sizeof(udp_head_t); -} \ No newline at end of file From 374c273240c8e62fc03275d8bd31f6134f48dfd0 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sat, 27 Sep 2025 19:54:28 +0800 Subject: [PATCH 141/158] =?UTF-8?q?driver:=20=E8=B0=83=E6=95=B4=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/framebuffer/Makefile | 1 + .../drivers/{ => framebuffer}/vesa_display.c | 0 src/arch/x86/drivers/input/8042/8042.c | 197 ++++++++++++++++++ src/arch/x86/drivers/input/8042/Makefile | 3 + .../x86/drivers/{ => input/8042}/keyboard.c | 0 src/arch/x86/drivers/{ => input/8042}/mouse.c | 0 src/arch/x86/drivers/input/Makefile | 1 + 7 files changed, 202 insertions(+) create mode 100644 src/arch/x86/drivers/framebuffer/Makefile rename src/arch/x86/drivers/{ => framebuffer}/vesa_display.c (100%) create mode 100644 src/arch/x86/drivers/input/8042/8042.c create mode 100644 src/arch/x86/drivers/input/8042/Makefile rename src/arch/x86/drivers/{ => input/8042}/keyboard.c (100%) rename src/arch/x86/drivers/{ => input/8042}/mouse.c (100%) create mode 100644 src/arch/x86/drivers/input/Makefile diff --git a/src/arch/x86/drivers/framebuffer/Makefile b/src/arch/x86/drivers/framebuffer/Makefile new file mode 100644 index 0000000..7b30860 --- /dev/null +++ b/src/arch/x86/drivers/framebuffer/Makefile @@ -0,0 +1 @@ +SRC += vesa_display.c \ No newline at end of file diff --git a/src/arch/x86/drivers/vesa_display.c b/src/arch/x86/drivers/framebuffer/vesa_display.c similarity index 100% rename from src/arch/x86/drivers/vesa_display.c rename to src/arch/x86/drivers/framebuffer/vesa_display.c diff --git a/src/arch/x86/drivers/input/8042/8042.c b/src/arch/x86/drivers/input/8042/8042.c new file mode 100644 index 0000000..e343fa8 --- /dev/null +++ b/src/arch/x86/drivers/input/8042/8042.c @@ -0,0 +1,197 @@ +/** + * @file 8042.c + * @author Ryan Wang (ryan1202@foxmail.com) + * @brief 8042控制器的驱动 + * @version 0.1 + * @date 2021-06 + */ +#include +#include +#include +#include +#include +#include + +// static status_t i8042_enter(driver_t *drv_obj); +// static status_t i8042_exit(driver_t *drv_obj); + +#define DRV_NAME "General PS/2 Driver" +#define DEV_NAME "ps2controller" + +// typedef struct { +// bool is_dual_channel; +// bool is_p1_avail, is_p2_avail; + +// uint8_t p1_dev_type, p2_dev_type; +// } device_extension_t; + +// driver_func_t i8042_driver = { +// .driver_enter = i8042_enter, +// .driver_exit = i8042_exit, +// .driver_open = NULL, +// .driver_close = NULL, +// .driver_read = NULL, +// .driver_write = NULL, +// .driver_devctl = NULL, +// }; + +int i8042_get_status(uint8_t type) { + int data = io_in8(I8042_PORT_STAT); + return data & type; +} + +void i8042_wait_ctr_send_ready(void) { + for (;;) { + if ((io_in8(I8042_PORT_STAT) & I8042_STAT_INBUF) == + 0) { // 输入缓存区为空 + return; + } + } +} + +void i8042_send_cmd(int command) { + io_out8(I8042_PORT_CMD, command); + i8042_wait_ctr_send_ready(); +} + +int i8042_read_data(void) { + return io_in8(I8042_PORT_DATA); +} + +void i8042_write_data(int data) { + io_out8(I8042_PORT_DATA, data); +} + +// static status_t i8042_enter(driver_t *drv_obj) { +// device_t *devobj; +// device_extension_t *devext; + +// device_create( +// drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_MANAGER, &devobj); +// devext = devobj->device_extension; + +// // 1.禁用设备 +// i8042_send_cmd(I8042_CMD_DISABLE_P1); // 禁用第一个PS/2端口 +// i8042_send_cmd(I8042_CMD_DISABLE_P2); // 禁用第二个PS/2端口(如果有) + +// // 2.配置控制器 +// i8042_send_cmd(I8042_CMD_WRITE); +// i8042_write_data( +// I8042_CFG_TRANS1 | I8042_CFG_SYS_FLAG | I8042_CFG_INT2 | +// I8042_CFG_INT1); + +// // 3.控制器自检 +// i8042_send_cmd(I8042_CMD_TEST_CTL); +// if (i8042_read_data() != 0x55) { +// printk("[i8042]PS/2 Controller Self test failed!\n"); +// device_delete(devobj); +// return FAILED; +// } + +// // 4.检测是否为双通道 +// i8042_send_cmd(I8042_CMD_ENABLE_P2); +// devext->is_dual_channel = (i8042_read_data() & I8042_CFG_CLK2) == 0; +// if (devext->is_dual_channel) { // 存在第二个通道则禁用第二个通道 +// i8042_send_cmd(I8042_CMD_DISABLE_P2); + +// i8042_send_cmd(I8042_CMD_READ); +// uint8_t tmp = i8042_read_data(); + +// i8042_send_cmd(I8042_CMD_WRITE); +// i8042_write_data(tmp & ~I8042_CFG_INT2 | I8042_CFG_CLK2); +// } + +// // 5.接口测试 +// i8042_send_cmd(I8042_CMD_TEST_P1); +// if (i8042_read_data() != 0x00) { +// printk("[i8042]PS/2 Port 1 test failed!\n"); +// devext->is_p1_avail = false; +// } else { +// devext->is_p1_avail = true; +// } +// if (devext->is_dual_channel) { +// i8042_send_cmd(I8042_CMD_TEST_P1); +// if (i8042_read_data() != 0x00) { +// printk("[i8042]PS/2 Port 2 test failed!\n"); +// devext->is_p2_avail = false; +// } else { +// devext->is_p2_avail = true; +// } +// } + +// int i = 0; +// if (devext->is_p1_avail) { +// // 6.启用端口 +// i8042_send_cmd(I8042_CMD_ENABLE_P1); +// // 7.重置设备 +// i8042_write_data(I8042_CMD_RESET_DEV); + +// for (i = 0; i < 2; i++) { +// if (i8042_read_data() == 0xfc) { +// printk("[i8042]PS/2 Port1 Device reset failed!\n"); +// } +// } +// if (i8042_get_status(I8042_STAT_OUTBUF)) { +// devext->p1_dev_type = i8042_read_data(); +// } else { // AT键盘没有设备类型的响应 +// devext->p2_dev_type = 0xff; +// printk("[i8042]Found PS/2 device 1.Type: AT Keyboard\n"); +// } +// } +// if (devext->is_p2_avail) { +// // 6.启用端口 +// i8042_send_cmd(I8042_CMD_ENABLE_P2); + +// i8042_send_cmd(I8042_CMD_READ); +// uint8_t tmp = i8042_read_data(); + +// i8042_send_cmd(I8042_CMD_WRITE); +// i8042_write_data(tmp | I8042_CFG_INT2); +// // 7.重置设备 +// i8042_send_cmd(I8042_CMD_SEND_TO_P2); +// i8042_write_data(I8042_CMD_RESET_DEV); + +// for (i = 0; i < 2; i++) { +// if (i8042_read_data() == 0xfc) { +// printk("[i8042]PS/2 Port1 Device reset failed!\n"); +// } +// } +// if (i8042_get_status(I8042_STAT_OUTBUF)) { +// devext->p2_dev_type = i8042_read_data(); +// if (devext->p2_dev_type == 0x00) { +// printk("[i8042]Found PS/2 device 2.Type: Mouse\n"); +// i8042_send_cmd(I8042_CMD_SEND_TO_P2); +// i8042_write_data(0xf4); +// if (i8042_read_data() != 0xfa) { +// printk("[i8042]PS/2 Port2 Device: mouse enable failed!\n"); +// } +// } else { +// printk( +// "[i8042]Found PS/2 device 2.Type: %#0X\n", +// devext->p2_dev_type); +// } +// } else { // AT键盘没有设备类型的响应 +// devext->p2_dev_type = 0xff; +// printk("[i8042]Found PS/2 device 2.Type: AT Keyboard\n"); +// } +// } +// return SUCCUESS; +// } + +// static status_t i8042_exit(driver_t *drv_obj) { +// device_t *devobj, *next; +// // device_extension_t *ext; +// list_for_each_owner_safe (devobj, next, &drv_obj->device_list, list) { +// device_delete(devobj); +// } +// string_del(&drv_obj->name); +// return SUCCUESS; +// } + +// static __init void i8042_driver_entry(void) { +// if (driver_create(i8042_driver, DRV_NAME) < 0) { +// printk(COLOR_RED "[driver] %s driver create failed!\n", __func__); +// } +// } + +// driver_initcall(i8042_driver_entry); \ No newline at end of file diff --git a/src/arch/x86/drivers/input/8042/Makefile b/src/arch/x86/drivers/input/8042/Makefile new file mode 100644 index 0000000..24062da --- /dev/null +++ b/src/arch/x86/drivers/input/8042/Makefile @@ -0,0 +1,3 @@ +SRC += 8042.c +SRC += keyboard.c +SRC += mouse.c \ No newline at end of file diff --git a/src/arch/x86/drivers/keyboard.c b/src/arch/x86/drivers/input/8042/keyboard.c similarity index 100% rename from src/arch/x86/drivers/keyboard.c rename to src/arch/x86/drivers/input/8042/keyboard.c diff --git a/src/arch/x86/drivers/mouse.c b/src/arch/x86/drivers/input/8042/mouse.c similarity index 100% rename from src/arch/x86/drivers/mouse.c rename to src/arch/x86/drivers/input/8042/mouse.c diff --git a/src/arch/x86/drivers/input/Makefile b/src/arch/x86/drivers/input/Makefile new file mode 100644 index 0000000..ac6c8ad --- /dev/null +++ b/src/arch/x86/drivers/input/Makefile @@ -0,0 +1 @@ +SRC += 8042/ \ No newline at end of file From 0b55f33f64022e91ecf012f1c8ef04997749bc9f Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 29 Sep 2025 15:04:37 +0800 Subject: [PATCH 142/158] =?UTF-8?q?object:=20=E6=96=B0=E5=A2=9Edelete=5Fob?= =?UTF-8?q?ject?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/objects/object.h | 11 +++++++---- src/objects/objects.c | 19 ++++++++++++++++--- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/include/objects/object.h b/src/include/objects/object.h index 5679c2c..066818a 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -12,6 +12,7 @@ typedef enum ObjectResult { OBJECT_OK, OBJECT_ERROR_MEMORY, + OBJECT_ERROR_DELETE_DIRECTORY, OBJECT_ERROR_INVALID_OPERATION, OBJECT_ERROR_CANNOT_FIND, OBJECT_ERROR_ILLEGAL_ARGUMENT, @@ -156,10 +157,12 @@ ObjectResult add_object(Object *parent, Object *child); // 通过路径打开对象,对于符号链接会自动解析 ObjectResult open_oringinal_object_by_path(char *path, Object **out_object); ObjectResult open_object_by_path(char *path, Object **object); -Object *create_object(Object *parent, string_t name, ObjectAttr attr); -Object *create_object_directory(Object *parent, string_t name, ObjectAttr attr); -void object_close(Object *object); -void show_object_tree(); +Object *create_object(Object *parent, string_t *name, ObjectAttr attr); +ObjectResult delete_object(Object *object); +Object *create_object_directory( + Object *parent, string_t *name, ObjectAttr attr); +void object_close(Object *object); +void show_object_tree(); #define append_object(parent, child) \ dyn_array_append((parent)->value.directory.children, Object *, (child)); diff --git a/src/objects/objects.c b/src/objects/objects.c index a7342d6..4cb3988 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -142,11 +142,11 @@ ObjectResult add_object(Object *parent, Object *child) { return OBJECT_OK; } -Object *create_object(Object *parent, string_t name, ObjectAttr attr) { +Object *create_object(Object *parent, string_t *name, ObjectAttr attr) { Object *object = kmalloc(sizeof(Object)); if (object == NULL) { return NULL; } - object->name = name; + object->name = *name; object->attr = kmalloc_from_template(attr); object->attr->object = object; object->parent = parent; @@ -161,8 +161,21 @@ Object *create_object(Object *parent, string_t name, ObjectAttr attr) { return object; } +ObjectResult delete_object(Object *object) { + if (object == NULL || object == &root_object) { + return OBJECT_ERROR_INVALID_OPERATION; + } + if (object->attr->type == OBJECT_TYPE_DIRECTORY) { + return OBJECT_ERROR_DELETE_DIRECTORY; + } + list_del(&object->list); + kfree(object->attr); + kfree(object); + return OBJECT_OK; +} + Object *create_object_directory( - Object *parent, string_t name, ObjectAttr attr) { + Object *parent, string_t *name, ObjectAttr attr) { Object *object = create_object(parent, name, attr); if (object == NULL) { return NULL; } object->attr->type = OBJECT_TYPE_DIRECTORY; From fd69252a47e118db27c6784e0f7eecb6f57db097 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 2 Oct 2025 00:59:50 +0800 Subject: [PATCH 143/158] =?UTF-8?q?thread:=20=E4=BF=AE=E5=A4=8Dthread=5Fun?= =?UTF-8?q?block=E9=87=8D=E5=A4=8D=E6=B7=BB=E5=8A=A0=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E5=88=B0thread=5Fready=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/thread.c | 49 +++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/kernel/thread.c b/src/kernel/thread.c index e23766a..83e2597 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -6,15 +6,15 @@ * @date 2021-02 * */ -#include "kernel/driver_interface.h" -#include "kernel/spinlock.h" -#include +#include #include +#include #include #include #include #include #include +#include #include #include #include @@ -24,7 +24,7 @@ uint32_t preempt_count = 0; // 预防抢占计数 -struct task_s *current_task, *dead_task = NULL; +struct task_s *current_task, *dead_task = NULL, *prev; struct task_s *main_thread; list_t thread_ready; @@ -118,7 +118,7 @@ void init_thread( pthread->priority = priority; pthread->kstack = (uint32_t *)((uint32_t)stack_page + PAGE_SIZE); - pthread->ticks = timer_get_schedule_tick(priority); + // pthread->ticks = timer_get_schedule_tick(priority); pthread->elapsed_ticks = 0; pthread->pgdir = NULL; pthread->stack_magic = 0x10000000; @@ -172,7 +172,6 @@ struct task_s *thread_start( void thread_exit(void) { struct task_s *cur = get_current_thread(); - cur->status = TASK_DIED; if (cur->parent != NULL) { struct task_s *parent = cur->parent; @@ -193,7 +192,12 @@ void thread_exit(void) { spin_unlock_irqrestore(&thread_all_lock, flags); flags = spin_lock_irqsave(&thread_ready_lock); - if (list_in_list(&cur->general_tag)) list_del(&cur->general_tag); + if (list_in_list(&cur->general_tag)) { + printk("d"); + // list_del(&cur->general_tag); + } + + cur->status = TASK_DIED; // 切换线程 struct task_s *next; @@ -216,6 +220,7 @@ void thread_exit(void) { // 激活页表并跳转 process_activate(next); current_task = next; + prev = cur; switch_to((int *)cur, (int *)next); } @@ -268,19 +273,8 @@ void thread_unblock(struct task_s *pthread) { return; } - if (pthread->status != TASK_READY) { - pthread->status = TASK_READY; - spin_unlock(&pthread->status_lock); - - spin_lock(&thread_ready_lock); - if (list_in_list(&pthread->general_tag)) { - list_del(&pthread->general_tag); - } - list_add_after(&pthread->general_tag, &thread_ready); - spin_unlock_irqrestore(&thread_ready_lock, flags); - } else { - spin_unlock_irqrestore(&pthread->status_lock, flags); - } + if (pthread->status != TASK_READY) pthread->status = TASK_READY; + spin_unlock_irqrestore(&pthread->status_lock, flags); } /** @@ -328,7 +322,8 @@ void schedule(void) { return; } - old_status = save_and_disable_interrupt(); + old_status = spin_try_lock_irqsave(&thread_ready_lock); + if (old_status == 0) return; // 1. 判断当前线程是否需要加入到thread_ready if (cur->status == TASK_RUNNING) { @@ -353,10 +348,20 @@ void schedule(void) { if (!list_empty(&thread_ready)) { next = list_first_owner(&thread_ready, struct task_s, general_tag); list_del(&next->general_tag); - } else next = task_idle; + if (next == cur) { + printk("?"); + printk("?"); + } + } else { + next = task_idle; + if (list_in_list(&task_idle->general_tag)) + list_del(&task_idle->general_tag); + } // 4. 改变状态并加入到thread_ready if (next->status == TASK_READY) next->status = TASK_RUNNING; + spin_unlock(&thread_ready_lock); + prev = cur; // 5. 切换线程 // 激活页表并跳转 process_activate(next); From d315aee103a5a0ddbc37b5ca1d06c6b088b092d6 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 6 Oct 2025 02:17:47 +0800 Subject: [PATCH 144/158] =?UTF-8?q?kernel&driver:=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E7=BB=93=E6=9E=84=EF=BC=8C=E7=AE=80=E5=8C=96=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E6=A1=86=E6=9E=B6=EF=BC=8C=E5=87=8F=E5=B0=91=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 - src/arch/x86/drivers/8042.c | 198 ------------- src/arch/x86/drivers/Makefile | 18 +- src/arch/x86/drivers/acpi.c | 2 +- src/arch/x86/drivers/bus/isa/dma.c | 13 +- src/arch/x86/drivers/bus/isa/isa.c | 120 +++----- src/arch/x86/drivers/bus/pci/pci.c | 200 ++++++------- src/arch/x86/drivers/cmos.c | 65 ++--- src/arch/x86/drivers/disk/ata/ata_driver.c | 6 +- src/arch/x86/drivers/disk/ata/dma.c | 4 +- src/arch/x86/drivers/disk/ata/ide.c | 106 +++---- .../x86/drivers/disk/ata/ide_controller.c | 105 +++---- .../x86/drivers/disk/ata/include/ata_driver.h | 6 +- src/arch/x86/drivers/disk/ata/include/ide.h | 16 +- .../drivers/disk/ata/include/ide_controller.h | 16 +- .../x86/drivers/framebuffer/vesa_display.c | 51 ++-- src/arch/x86/drivers/input/8042/8042.c | 20 -- src/arch/x86/drivers/interrupt/8259a.c | 119 +++----- src/arch/x86/drivers/interrupt/apic.c | 239 +++++++--------- src/arch/x86/drivers/msr.c | 32 +-- .../x86/drivers/network/rtl8139/rtl8139.c | 139 +++++---- .../x86/drivers/network/rtl8139/rtl8139.h | 15 +- src/arch/x86/drivers/serial.c | 102 +++---- src/arch/x86/drivers/sound/Makefile | 3 +- src/arch/x86/drivers/sound/sb16/sb16.c | 203 +++++++------- src/arch/x86/drivers/sound/sb16/sb16.h | 3 + src/arch/x86/drivers/sound/sound.c | 0 src/arch/x86/drivers/timer/pit.c | 246 ++++------------ src/arch/x86/drivers/usb/Makefile | 2 +- src/arch/x86/drivers/usb/hcd/Makefile | 2 + src/arch/x86/drivers/usb/hcd/hcd.c | 12 + src/arch/x86/drivers/usb/hcd/hcd.h | 8 + src/arch/x86/drivers/usb/hcd/uhci/Makefile | 3 + .../drivers/usb/{hci => hcd}/uhci/packet.c | 18 +- .../drivers/usb/{hci => hcd}/uhci/skeleton.c | 0 .../x86/drivers/usb/{hci => hcd/uhci}/uhci.c | 182 ++++++------ src/arch/x86/drivers/usb/hci/Makefile | 2 - src/arch/x86/drivers/usb/hci/hci.c | 0 src/arch/x86/drivers/usb/hci/uhci/Makefile | 2 - src/arch/x86/include/drivers/8259a.h | 8 +- src/arch/x86/include/drivers/apic.h | 9 +- src/arch/x86/include/drivers/bus/isa/dma.h | 6 +- src/arch/x86/include/drivers/bus/pci/pci.h | 9 +- src/arch/x86/include/drivers/cmos.h | 8 +- src/arch/x86/include/drivers/pit.h | 29 +- src/arch/x86/include/drivers/serial.h | 8 +- src/arch/x86/include/drivers/usb/uhci.h | 15 +- src/arch/x86/include/drivers/vesa_display.h | 6 +- src/arch/x86/include/kernel/descriptor.h | 1 - src/arch/x86/kernel/descriptor.c | 25 +- src/arch/x86/kernel/platform.c | 90 +++--- src/driver/Makefile | 3 +- src/driver/bus_dm.c | 38 +-- src/driver/framebuffer/console_backend.c | 9 +- src/driver/framebuffer/framebuffer_dm.c | 106 ++++--- src/driver/input/input_dm.c | 99 +++++-- src/driver/interrupt/Makefile | 1 + src/driver/interrupt/interrupt_dm.c | 191 +++++++++++++ src/driver/interrupt_dm.c | 178 ------------ src/driver/network/buffer.c | 6 + src/driver/network/conn.c | 9 +- src/driver/network/mii.c | 13 +- src/driver/network/network.c | 5 +- src/driver/network/network_dm.c | 120 +++++--- src/driver/network/protocols/ipv4/acd.c | 13 +- src/driver/network/protocols/ipv4/dhcp.c | 16 +- src/driver/network/protocols/tcp.c | 20 +- src/driver/serial/serial_dm.c | 77 +++-- src/driver/sound/pcm.c | 101 ++----- src/driver/sound/sound_dm.c | 75 +++-- src/driver/storage/disk/mbr.c | 2 +- src/driver/storage/storage_dm.c | 139 +++++---- src/driver/storage/storage_io.c | 14 +- src/driver/storage/volume.c | 4 +- src/driver/time_dm.c | 55 +++- src/driver/timer/timer.c | 24 +- src/driver/timer/timer_dm.c | 66 +++-- src/driver/usb/Makefile | 3 - src/driver/usb/usb-core/hcd.c | 67 ----- src/driver/usb/usb-core/usb.c | 100 ------- src/driver/usb/usb_dm.c | 101 ------- src/driver/usb/usb_driver.c | 9 - src/drivers/bus/Makefile | 3 +- src/drivers/bus/hcd.c | 79 ++++++ src/drivers/bus/usb.c | 155 ++++++----- src/drivers/usb/Makefile | 3 +- .../usb-core => drivers/usb/core}/Makefile | 1 - .../usb/usb-core => drivers/usb/core}/func.c | 42 +-- .../usb/usb-core => drivers/usb/core}/hub.c | 34 +-- .../usb/usb-core => drivers/usb/core}/urb.c | 4 +- src/drivers/usb/core/usb.c | 125 +++++++++ src/drivers/usb/hid/hid.c | 16 +- src/drivers/usb/hid/keyboard.c | 75 ++--- src/drivers/usb/hid/mouse.c | 80 +++--- src/fs/fat/dir.c | 10 - src/fs/fat/entry.c | 6 +- src/fs/fat/fat.c | 2 +- src/fs/fs.c | 8 +- src/include/driver/bus_dm.h | 21 +- src/include/driver/framebuffer/fb_dm.h | 26 +- src/include/driver/input/input_dm.h | 14 +- .../driver/{ => interrupt}/interrupt_dm.h | 19 +- src/include/driver/network/buffer.h | 1 + src/include/driver/network/conn.h | 18 +- .../driver/network/ethernet/ethernet.h | 8 +- src/include/driver/network/network_dm.h | 38 +-- .../driver/network/protocols/ipv4/dhcp.h | 10 +- src/include/driver/network/protocols/tcp.h | 4 +- src/include/driver/serial/serial_dm.h | 14 +- src/include/driver/sound/pcm.h | 11 +- src/include/driver/sound/sound_dm.h | 26 +- src/include/driver/storage/storage_dm.h | 29 +- src/include/driver/time_dm.h | 19 +- src/include/driver/{ => timer}/timer_dm.h | 36 +-- src/include/driver/usb/usb_dm.h | 41 --- src/include/drivers/bus/usb.h | 18 -- src/include/{driver => drivers/bus}/usb/hcd.h | 24 +- src/include/drivers/bus/usb/usb.h | 33 +++ .../{driver => drivers/bus}/usb/usb_driver.h | 3 +- .../usb => drivers/usb/core}/descriptors.h | 0 .../{driver/usb => drivers/usb/core}/func.h | 89 +++--- .../{driver/usb => drivers/usb/core}/hub.h | 6 +- .../{driver/usb => drivers/usb/core}/urb.h | 2 +- .../{driver/usb => drivers/usb/core}/usb.h | 11 +- src/include/drivers/usb/hid.h | 2 +- src/include/drivers/usb/keyboard.h | 9 +- src/include/drivers/usb/mouse.h | 9 +- src/include/fs/fs.h | 4 +- src/include/kernel/app.h | 22 +- src/include/kernel/bus_driver.h | 64 ++--- src/include/kernel/device.h | 145 ++++++---- src/include/kernel/device_driver.h | 46 +-- src/include/kernel/device_manager.h | 24 +- src/include/kernel/driver.h | 100 +++---- src/include/kernel/driver_interface.h | 45 ++- src/include/kernel/driver_manager.h | 41 --- src/include/kernel/dynamic_device_manager.h | 2 +- src/include/kernel/platform.h | 11 +- src/include/objects/attr.h | 37 +++ src/include/objects/mount.h | 2 +- src/include/objects/object.h | 50 +--- src/include/objects/types.h | 2 +- src/include/string.h | 2 +- src/kernel/driver/Makefile | 5 +- src/kernel/driver/bus_driver.c | 167 +++-------- src/kernel/driver/device.c | 195 +++++++------ src/kernel/driver/device_driver.c | 83 +----- src/kernel/driver/device_manager.c | 62 +++-- src/kernel/driver/dma.c | 6 +- src/kernel/driver/driver.c | 263 ++++++++---------- src/kernel/driver/driver_dependency.c | 55 ---- src/kernel/driver/driver_interface.c | 63 ++++- src/kernel/driver/driver_manager.c | 32 --- src/kernel/driver/dynamic_device_manager.c | 37 --- src/kernel/main.c | 42 +-- src/kernel/memtest.c | 6 +- src/kernel/periodic_task.c | 2 +- src/kernel/softirq.c | 6 +- src/kernel/thread.c | 15 +- src/objects/types.c | 9 +- tools/grub/install_grub.py | 1 + 161 files changed, 3085 insertions(+), 3902 deletions(-) delete mode 100644 src/arch/x86/drivers/8042.c delete mode 100644 src/arch/x86/drivers/sound/sound.c create mode 100644 src/arch/x86/drivers/usb/hcd/Makefile create mode 100644 src/arch/x86/drivers/usb/hcd/hcd.c create mode 100644 src/arch/x86/drivers/usb/hcd/hcd.h create mode 100644 src/arch/x86/drivers/usb/hcd/uhci/Makefile rename src/arch/x86/drivers/usb/{hci => hcd}/uhci/packet.c (97%) rename src/arch/x86/drivers/usb/{hci => hcd}/uhci/skeleton.c (100%) rename src/arch/x86/drivers/usb/{hci => hcd/uhci}/uhci.c (72%) delete mode 100644 src/arch/x86/drivers/usb/hci/Makefile delete mode 100644 src/arch/x86/drivers/usb/hci/hci.c delete mode 100644 src/arch/x86/drivers/usb/hci/uhci/Makefile create mode 100644 src/driver/interrupt/Makefile create mode 100644 src/driver/interrupt/interrupt_dm.c delete mode 100644 src/driver/interrupt_dm.c delete mode 100644 src/driver/usb/Makefile delete mode 100644 src/driver/usb/usb-core/hcd.c delete mode 100644 src/driver/usb/usb-core/usb.c delete mode 100644 src/driver/usb/usb_dm.c delete mode 100644 src/driver/usb/usb_driver.c create mode 100644 src/drivers/bus/hcd.c rename src/{driver/usb/usb-core => drivers/usb/core}/Makefile (80%) rename src/{driver/usb/usb-core => drivers/usb/core}/func.c (87%) rename src/{driver/usb/usb-core => drivers/usb/core}/hub.c (61%) rename src/{driver/usb/usb-core => drivers/usb/core}/urb.c (90%) create mode 100644 src/drivers/usb/core/usb.c rename src/include/driver/{ => interrupt}/interrupt_dm.h (66%) rename src/include/driver/{ => timer}/timer_dm.h (68%) delete mode 100644 src/include/driver/usb/usb_dm.h delete mode 100644 src/include/drivers/bus/usb.h rename src/include/{driver => drivers/bus}/usb/hcd.h (75%) create mode 100644 src/include/drivers/bus/usb/usb.h rename src/include/{driver => drivers/bus}/usb/usb_driver.h (88%) rename src/include/{driver/usb => drivers/usb/core}/descriptors.h (100%) rename src/include/{driver/usb => drivers/usb/core}/func.h (50%) rename src/include/{driver/usb => drivers/usb/core}/hub.h (88%) rename src/include/{driver/usb => drivers/usb/core}/urb.h (93%) rename src/include/{driver/usb => drivers/usb/core}/usb.h (94%) delete mode 100644 src/include/kernel/driver_manager.h create mode 100644 src/include/objects/attr.h delete mode 100644 src/kernel/driver/driver_dependency.c delete mode 100644 src/kernel/driver/driver_manager.c delete mode 100644 src/kernel/driver/dynamic_device_manager.c diff --git a/.gitignore b/.gitignore index 593ecd2..816bc26 100644 --- a/.gitignore +++ b/.gitignore @@ -66,7 +66,6 @@ __pycache__/ /disk/ tools/bin/ tools/imagetool/target/ -core fixdep *.img *.log diff --git a/src/arch/x86/drivers/8042.c b/src/arch/x86/drivers/8042.c deleted file mode 100644 index f5e3a82..0000000 --- a/src/arch/x86/drivers/8042.c +++ /dev/null @@ -1,198 +0,0 @@ -/** - * @file 8042.c - * @author Ryan Wang (ryan1202@foxmail.com) - * @brief 8042控制器的驱动 - * @version 0.1 - * @date 2021-06 - */ -#include -#include -#include -#include -#include -#include - - -static status_t i8042_enter(driver_t *drv_obj); -static status_t i8042_exit(driver_t *drv_obj); - -#define DRV_NAME "General PS/2 Driver" -#define DEV_NAME "ps2controller" - -typedef struct { - bool is_dual_channel; - bool is_p1_avail, is_p2_avail; - - uint8_t p1_dev_type, p2_dev_type; -} device_extension_t; - -driver_func_t i8042_driver = { - .driver_enter = i8042_enter, - .driver_exit = i8042_exit, - .driver_open = NULL, - .driver_close = NULL, - .driver_read = NULL, - .driver_write = NULL, - .driver_devctl = NULL, -}; - -int i8042_get_status(uint8_t type) { - int data = io_in8(I8042_PORT_STAT); - return data & type; -} - -void i8042_wait_ctr_send_ready(void) { - for (;;) { - if ((io_in8(I8042_PORT_STAT) & I8042_STAT_INBUF) == - 0) { // 输入缓存区为空 - return; - } - } -} - -void i8042_send_cmd(int command) { - io_out8(I8042_PORT_CMD, command); - i8042_wait_ctr_send_ready(); -} - -int i8042_read_data(void) { - return io_in8(I8042_PORT_DATA); -} - -void i8042_write_data(int data) { - io_out8(I8042_PORT_DATA, data); -} - -static status_t i8042_enter(driver_t *drv_obj) { - device_t *devobj; - device_extension_t *devext; - - device_create( - drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_MANAGER, &devobj); - devext = devobj->device_extension; - - // 1.禁用设备 - i8042_send_cmd(I8042_CMD_DISABLE_P1); // 禁用第一个PS/2端口 - i8042_send_cmd(I8042_CMD_DISABLE_P2); // 禁用第二个PS/2端口(如果有) - - // 2.配置控制器 - i8042_send_cmd(I8042_CMD_WRITE); - i8042_write_data( - I8042_CFG_TRANS1 | I8042_CFG_SYS_FLAG | I8042_CFG_INT2 | - I8042_CFG_INT1); - - // 3.控制器自检 - i8042_send_cmd(I8042_CMD_TEST_CTL); - if (i8042_read_data() != 0x55) { - printk("[i8042]PS/2 Controller Self test failed!\n"); - device_delete(devobj); - return FAILED; - } - - // 4.检测是否为双通道 - i8042_send_cmd(I8042_CMD_ENABLE_P2); - devext->is_dual_channel = (i8042_read_data() & I8042_CFG_CLK2) == 0; - if (devext->is_dual_channel) { // 存在第二个通道则禁用第二个通道 - i8042_send_cmd(I8042_CMD_DISABLE_P2); - - i8042_send_cmd(I8042_CMD_READ); - uint8_t tmp = i8042_read_data(); - - i8042_send_cmd(I8042_CMD_WRITE); - i8042_write_data(tmp & ~I8042_CFG_INT2 | I8042_CFG_CLK2); - } - - // 5.接口测试 - i8042_send_cmd(I8042_CMD_TEST_P1); - if (i8042_read_data() != 0x00) { - printk("[i8042]PS/2 Port 1 test failed!\n"); - devext->is_p1_avail = false; - } else { - devext->is_p1_avail = true; - } - if (devext->is_dual_channel) { - i8042_send_cmd(I8042_CMD_TEST_P1); - if (i8042_read_data() != 0x00) { - printk("[i8042]PS/2 Port 2 test failed!\n"); - devext->is_p2_avail = false; - } else { - devext->is_p2_avail = true; - } - } - - int i = 0; - if (devext->is_p1_avail) { - // 6.启用端口 - i8042_send_cmd(I8042_CMD_ENABLE_P1); - // 7.重置设备 - i8042_write_data(I8042_CMD_RESET_DEV); - - for (i = 0; i < 2; i++) { - if (i8042_read_data() == 0xfc) { - printk("[i8042]PS/2 Port1 Device reset failed!\n"); - } - } - if (i8042_get_status(I8042_STAT_OUTBUF)) { - devext->p1_dev_type = i8042_read_data(); - } else { // AT键盘没有设备类型的响应 - devext->p2_dev_type = 0xff; - printk("[i8042]Found PS/2 device 1.Type: AT Keyboard\n"); - } - } - if (devext->is_p2_avail) { - // 6.启用端口 - i8042_send_cmd(I8042_CMD_ENABLE_P2); - - i8042_send_cmd(I8042_CMD_READ); - uint8_t tmp = i8042_read_data(); - - i8042_send_cmd(I8042_CMD_WRITE); - i8042_write_data(tmp | I8042_CFG_INT2); - // 7.重置设备 - i8042_send_cmd(I8042_CMD_SEND_TO_P2); - i8042_write_data(I8042_CMD_RESET_DEV); - - for (i = 0; i < 2; i++) { - if (i8042_read_data() == 0xfc) { - printk("[i8042]PS/2 Port1 Device reset failed!\n"); - } - } - if (i8042_get_status(I8042_STAT_OUTBUF)) { - devext->p2_dev_type = i8042_read_data(); - if (devext->p2_dev_type == 0x00) { - printk("[i8042]Found PS/2 device 2.Type: Mouse\n"); - i8042_send_cmd(I8042_CMD_SEND_TO_P2); - i8042_write_data(0xf4); - if (i8042_read_data() != 0xfa) { - printk("[i8042]PS/2 Port2 Device: mouse enable failed!\n"); - } - } else { - printk( - "[i8042]Found PS/2 device 2.Type: %#0X\n", - devext->p2_dev_type); - } - } else { // AT键盘没有设备类型的响应 - devext->p2_dev_type = 0xff; - printk("[i8042]Found PS/2 device 2.Type: AT Keyboard\n"); - } - } - return SUCCUESS; -} - -static status_t i8042_exit(driver_t *drv_obj) { - device_t *devobj, *next; - // device_extension_t *ext; - list_for_each_owner_safe (devobj, next, &drv_obj->device_list, list) { - device_delete(devobj); - } - string_del(&drv_obj->name); - return SUCCUESS; -} - -static __init void i8042_driver_entry(void) { - if (driver_create(i8042_driver, DRV_NAME) < 0) { - printk(COLOR_RED "[driver] %s driver create failed!\n", __func__); - } -} - -driver_initcall(i8042_driver_entry); \ No newline at end of file diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index 28b0f80..d2081a4 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -1,21 +1,15 @@ -#SRC += 8042.c -SRC += 8259a.c #SRC += acpi.c -SRC += apic.c -SRC += cpufreq.c -SRC += disk.c -#SRC += keyboard.c -#SRC += mouse.c +#SRC += cpufreq.c SRC += msr.c -SRC += pit.c SRC += serial.c -SRC += smbios.c -SRC += vesa_display.c +#SRC += smbios.c SRC += cmos.c -SRC += network/ +SRC += network/ SRC += sound/ SRC += usb/ SRC += bus/ SRC += disk/ SRC += interrupt/ -SRC += timer/ \ No newline at end of file +SRC += timer/ +SRC += framebuffer/ +#SRC += 8042/ \ No newline at end of file diff --git a/src/arch/x86/drivers/acpi.c b/src/arch/x86/drivers/acpi.c index f47d6db..3ede1e6 100644 --- a/src/arch/x86/drivers/acpi.c +++ b/src/arch/x86/drivers/acpi.c @@ -5,7 +5,7 @@ * @version 0.1 * @date 2021-06 */ -#include +#include #include #include #include diff --git a/src/arch/x86/drivers/bus/isa/dma.c b/src/arch/x86/drivers/bus/isa/dma.c index da93370..f87c0cc 100644 --- a/src/arch/x86/drivers/bus/isa/dma.c +++ b/src/arch/x86/drivers/bus/isa/dma.c @@ -5,18 +5,19 @@ * @version 0.1 * @date 2021-7 */ -#include "kernel/driver.h" -#include "math.h" #include #include #include +#include #include #include #include +#include #include #include #include + DmaOps isa_dma_ops = { .dma_alloc = dma_alloc_region, .dma_free = dma_free_region, @@ -24,7 +25,7 @@ DmaOps isa_dma_ops = { #define DMA_MEM_BASE_ADDR 0x800000 -Device *dma_channels[8]; // 使用DMA通道的设备 +LogicalDevice *dma_channels[8]; // 使用DMA通道的设备 struct mmap dma_mem_mmap; spinlock_t dma_spin_lock; @@ -61,7 +62,7 @@ DriverResult dma_free_region(Dma *dma, void *ptr, uint32_t size) { for (int i = 0; i < cnt; i++) { mmap_set(&dma_mem_mmap, idx + i, 0); } - return DRIVER_RESULT_OK; + return DRIVER_OK; } uint32_t get_dma_count(int channel) { @@ -90,7 +91,7 @@ uint32_t dma_pointer(int channel, uint32_t size) { else return size - result; } -int dma_channel_use(Device *device, int *possible_ch, int len) { +int dma_channel_use(LogicalDevice *device, int *possible_ch, int len) { for (int i = 0; i < len; i++) { if (dma_channels[possible_ch[i]] == NULL) { dma_channels[possible_ch[i]] = device; @@ -100,7 +101,7 @@ int dma_channel_use(Device *device, int *possible_ch, int len) { return -1; } -void dma_channel_unuse(Device *device, uint8_t channel) { +void dma_channel_unuse(LogicalDevice *device, uint8_t channel) { if (channel < 8) { if (dma_channels[channel] == device) dma_channels[channel] = NULL; } diff --git a/src/arch/x86/drivers/bus/isa/isa.c b/src/arch/x86/drivers/bus/isa/isa.c index cdc9215..aabe7d6 100644 --- a/src/arch/x86/drivers/bus/isa/isa.c +++ b/src/arch/x86/drivers/bus/isa/isa.c @@ -1,5 +1,4 @@ #include "kernel/initcall.h" -#include "objects/object.h" #include #include #include @@ -7,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -18,30 +16,9 @@ DriverResult isa_driver_init(Driver *driver); DriverResult isa_probe(BusDriver *bus_driver, Bus *bus); DriverResult isa_init_bus(BusDriver *bus_driver); -DeviceDriverOps isa_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, -}; -DeviceOps isa_device_ops = { - .init = NULL, - .start = NULL, - .stop = NULL, - .destroy = NULL, - .status = NULL, -}; -BusDriverOps isa_bus_driver_ops = { - .register_bus_hook = NULL, - .unregister_bus_hook = NULL, - .init = isa_init_bus, -}; BusOps isa_bus_ops = { - .register_device_hook = NULL, - .unregister_device_hook = NULL, - .scan_bus = NULL, - .probe_device = isa_probe, -}; -BusControllerDeviceOps isa_controller_ops = { - .probe = NULL, + .scan_bus = NULL, + .probe_device = isa_probe, }; DriverDependency isa_dependencies[] = { @@ -52,56 +29,24 @@ DriverDependency isa_dependencies[] = { }, }; Driver isa_driver = { - .short_name = STRING_INIT("IsaDriver"), - .dependency_count = sizeof(isa_dependencies) / sizeof(DriverDependency), - .dependencies = isa_dependencies, - .init = isa_driver_init, -}; -DeviceDriver isa_device_driver = { - .name = STRING_INIT("ISA Device Driver"), - .type = DEVICE_TYPE_BUS_CONTROLLER, - .state = DRIVER_STATE_UNREGISTERED, - .private_data_size = 0, - .ops = &isa_driver_ops, + .short_name = STRING_INIT("IsaDriver"), }; -Device isa_device = { - .name = STRING_INIT("ISA Controller"), - .state = DEVICE_STATE_UNREGISTERED, - .bus = &platform_bus, - .private_data_size = 0, - .ops = &isa_device_ops, -}; -BusDriver isa_bus_driver = { - .name = STRING_INIT("ISA"), - .driver_type = DRIVER_TYPE_BUS_DRIVER, - .bus_type = BUS_TYPE_ISA, - .state = DRIVER_STATE_UNREGISTERED, - .private_data_size = 0, - .ops = &isa_bus_driver_ops, -}; -BusControllerDevice isa_bus_controller_device = { - .short_name = STRING_INIT("ISA"), - .device = &isa_device, - .bus_driver = &isa_bus_driver, - .bus_controller_ops = &isa_controller_ops, -}; -Bus isa_bus = { - .bus_num = 0, - .bus_driver = &isa_bus_driver, - .controller_device = &isa_device, - .ops = &isa_bus_ops, +DeviceDriver isa_device_driver; +BusDriver isa_bus_driver = { + .name = STRING_INIT("ISA"), }; +Bus *isa_bus; DriverResult isa_register_device_driver( DeviceDriver *device_driver, IsaOps *ops) { IsaDeviceDriver *isa_device_driver = kmalloc(sizeof(IsaDeviceDriver)); - if (isa_device_driver == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } + if (isa_device_driver == NULL) { return DRIVER_ERROR_OUT_OF_MEMORY; } isa_device_driver->device_driver = device_driver; isa_device_driver->ops = ops; list_add_tail(&isa_device_driver->list, &isa_driver_lh); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult isa_probe(BusDriver *bus_driver, Bus *bus) { @@ -111,30 +56,39 @@ DriverResult isa_probe(BusDriver *bus_driver, Bus *bus) { isa_device_driver->bus = bus; isa_device_driver->ops->probe(isa_device_driver); } - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult isa_init_bus(BusDriver *bus_driver) { - isa_bus_driver.bus_count = 1; +static void __init isa_initcall(void) { + DriverResult result; + ObjectAttr attr = driver_object_attr; + + result = register_driver(&isa_driver); + if (result != DRIVER_OK) goto failed_register_driver; - ObjectAttr attr = device_object_attr; - register_bus(&isa_bus_driver, &isa_device, &isa_bus, &attr); - return DRIVER_RESULT_OK; -} + result = register_device_driver(&isa_driver, &isa_device_driver); + if (result != DRIVER_OK) goto failed_register_device_driver; -DriverResult isa_driver_init(Driver *driver) { - ObjectAttr attr = device_object_attr; - DRIVER_RESULT_PASS(register_bus_controller_device( - &isa_device_driver, &isa_bus_driver, &isa_device, - &isa_bus_controller_device, &attr)); - return DRIVER_RESULT_OK; -} + result = + register_bus_driver(&isa_driver, BUS_TYPE_ISA, &isa_bus_driver, &attr); + if (result != DRIVER_OK) goto failed_resgister_bus_driver; -static void __init isa_initcall(void) { - register_driver(&isa_driver); - register_device_driver(&isa_driver, &isa_device_driver); - ObjectAttr attr = driver_object_attr; - register_bus_driver(&isa_driver, &isa_bus_driver, &attr); + result = create_bus(&isa_bus, &isa_bus_driver, &isa_bus_ops); + if (result != DRIVER_OK) goto failed_create_bus; + + return; + +failed_create_bus: + unregister_bus_driver(&isa_bus_driver); + +failed_resgister_bus_driver: + unregister_device_driver(&isa_device_driver); + +failed_register_device_driver: + unregister_driver(&isa_driver); + +failed_register_driver: + return; } driver_initcall(isa_initcall); diff --git a/src/arch/x86/drivers/bus/pci/pci.c b/src/arch/x86/drivers/bus/pci/pci.c index 7d86401..323c9d6 100644 --- a/src/arch/x86/drivers/bus/pci/pci.c +++ b/src/arch/x86/drivers/bus/pci/pci.c @@ -5,8 +5,6 @@ * @version 0.1 * @date 2020-07 */ -#include "kernel/list.h" -#include "objects/object.h" #include #include #include @@ -19,9 +17,10 @@ #include #include #include +#include #include #include -#include +#include #include #include #include @@ -30,36 +29,20 @@ LIST_HEAD(pci_driver_lh); PciDevice pci_devices[PCI_MAX_DEVICE]; -DriverResult pci_driver_init(Driver *driver); -DriverResult pci_device_init(Device *device); +DriverResult pci_device_init(void *device); DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus); DriverResult pci_init_bus(BusDriver *bus_driver); DriverResult pci_probe(BusDriver *bus_driver, Bus *bus); -DeviceDriverOps pci_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, -}; DeviceOps pci_device_ops = { .init = pci_device_init, .start = NULL, .stop = NULL, .destroy = NULL, - .status = NULL, -}; -BusDriverOps pci_bus_driver_ops = { - .register_bus_hook = NULL, - .unregister_bus_hook = NULL, - .init = pci_init_bus, }; BusOps pci_bus_ops = { - .register_device_hook = NULL, - .unregister_device_hook = NULL, - .scan_bus = pci_scan_bus, - .probe_device = pci_probe, -}; -BusControllerDeviceOps pci_controller_ops = { - .probe = NULL, + .scan_bus = pci_scan_bus, + .probe_device = pci_probe, }; DriverDependency pci_dependencies[] = { @@ -70,38 +53,11 @@ DriverDependency pci_dependencies[] = { }, }; Driver pci_driver = { - .short_name = STRING_INIT("PciDriver"), - .dependency_count = sizeof(pci_dependencies) / sizeof(DriverDependency), - .dependencies = pci_dependencies, - .init = pci_driver_init, -}; -DeviceDriver pci_device_driver = { - .name = STRING_INIT("PCI Device Driver"), - .type = DEVICE_TYPE_BUS_CONTROLLER, - .state = DRIVER_STATE_UNREGISTERED, - .private_data_size = 0, - .ops = &pci_driver_ops, -}; -Device pci_device = { - .name = STRING_INIT("PCI Controller"), - .state = DEVICE_STATE_UNREGISTERED, - .bus = &platform_bus, - .private_data_size = 0, - .ops = &pci_device_ops, -}; -BusDriver pci_bus_driver = { - .name = STRING_INIT("PCI"), - .driver_type = DRIVER_TYPE_BUS_DRIVER, - .bus_type = BUS_TYPE_PCI, - .state = DRIVER_STATE_UNREGISTERED, - .private_data_size = 0, - .ops = &pci_bus_driver_ops, + .short_name = STRING_INIT("PciDriver"), }; -BusControllerDevice pci_bus_controller_device = { - .short_name = STRING_INIT("PCI"), - .device = &pci_device, - .bus_driver = &pci_bus_driver, - .bus_controller_ops = &pci_controller_ops, +DeviceDriver pci_device_driver; +BusDriver pci_bus_driver = { + .name = STRING_INIT("PCI"), }; DEF_PCI_RW(8) @@ -209,21 +165,21 @@ uint32_t pci_device_get_io_addr(PciDevice *pci_device) { DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus) { int i, j; PciDevice *pci_device; - print_driver_info( - pci_driver, "device id\tvendor id\theader " - "type\tclasscode\tsubclass\tprogif\trevision id\n"); + print_info( + "PCI", "device id\tvendor id\theader " + "type\tclasscode\tsubclass\tprogif\trevision id\n"); for (i = 0; i < PCI_MAX_DEV; i++) { for (j = 0; j < PCI_MAX_FUNC; j++) { DriverResult result = pci_scan_device(bus, bus->bus_num, i, j, &pci_device); - if (result == DRIVER_RESULT_NOT_EXIST) { + if (result == DRIVER_ERROR_NOT_EXIST) { continue; - } else if (result == DRIVER_RESULT_NULL_POINTER) { + } else if (result == DRIVER_ERROR_NULL_POINTER) { print_error_with_position( "pci_probe_bus: pci device(%d:%d:%d) alloc failed!\n", bus->bus_num, i, j); continue; - } else if (result == DRIVER_RESULT_UNSUPPORT_DEVICE) { + } else if (result == DRIVER_ERROR_UNSUPPORT_DEVICE) { print_error_with_position( "pci_probe_bus: pci device(%d:%d:%d) unsupport! Header " "Type:%d\n", @@ -233,8 +189,8 @@ DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus) { bus_driver->device_count++; pci_device->status = PCI_DEVICE_STATUS_UNUSED; - print_driver_info( - pci_driver, + print_info( + "PCI", "%#06x\t\t%#06x\t\t%#04x\t\t%#04x\t\t%#04x\t\t%#04x\t%#04x\n", pci_device->device_id, pci_device->vendor_id, pci_device->header_type, pci_device->classcode, @@ -246,40 +202,14 @@ DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus) { } if (pci_device->header_type == 1) { // 为PCI-to-PCI桥 - bus_driver->bus_count = - MAX(bus_driver->bus_count, - pci_device->pci2pci_bridge.subordinate_bus_number); - - Bus *new_bus = kmalloc(sizeof(Bus)); - new_bus->ops = &pci_bus_ops; - new_bus->primary_bus = bus; - new_bus->bus_num = - pci_device->pci2pci_bridge.secondary_bus_number; - new_bus->subordinate_bus_num = - pci_device->pci2pci_bridge.subordinate_bus_number; - - ObjectAttr attr = device_object_attr; - register_bus( - bus_driver, bus->controller_device, new_bus, &attr); + Bus *new_bus; + + DRV_RESULT_PRINT_CALL( + create_bus(&new_bus, &pci_bus_driver, &pci_bus_ops)); } } } - return DRIVER_RESULT_OK; -} - -DriverResult pci_init_bus(BusDriver *bus_driver) { - pci_bus_driver.bus_count = 1; // 默认只有一个主总线 - - Bus *bus = kmalloc(sizeof(Bus)); - bus->ops = &pci_bus_ops; - bus->bus_num = 0; - bus->subordinate_bus_num = 0; - bus->primary_bus = NULL; - ObjectAttr attr = device_object_attr; - register_bus(&pci_bus_driver, &pci_device, bus, &attr); - // printk("device id\tvendor id\theader " - // "type\tclasscode\tsubclass\tprogif\trevision id\n"); - return DRIVER_RESULT_OK; + return DRIVER_OK; } PciDevice *pci_alloc_device(void) { @@ -336,7 +266,7 @@ DriverResult pci_scan_device( uint32_t value = pci_read32(bus_num, device_num, function_num, 0); uint16_t vendorID = value & 0xffff; uint16_t deviceID = value >> 16; - if (vendorID == 0xffff) { return DRIVER_RESULT_NOT_EXIST; } + if (vendorID == 0xffff) { return DRIVER_ERROR_NOT_EXIST; } value = pci_read32(bus_num, device_num, function_num, 0x0c); uint8_t bist = value >> 24; @@ -350,7 +280,7 @@ DriverResult pci_scan_device( uint8_t revisionID = value & 0xff; PciDevice *pci_device = pci_alloc_device(); - if (pci_device == NULL) { return DRIVER_RESULT_NULL_POINTER; } + if (pci_device == NULL) { return DRIVER_ERROR_NULL_POINTER; } *out_pci_device = pci_device; pci_device->device = NULL; fill_pci_device_info( @@ -486,7 +416,7 @@ DriverResult pci_scan_device( } else { print_error_with_position( "unsupport PCI Header Type: %d\n", header_type); - return DRIVER_RESULT_UNSUPPORT_DEVICE; + return DRIVER_ERROR_UNSUPPORT_DEVICE; } pci_device->irqline = value & 0xff; pci_device->irqpin = value >> 8; @@ -521,7 +451,7 @@ DriverResult pci_scan_device( } } - return DRIVER_RESULT_OK; + return DRIVER_OK; } bool pci_match_driver(PciDriver *pci_driver, PciDriver *new_pci_driver) { @@ -580,7 +510,7 @@ DriverResult pci_register_driver(Driver *driver, PciDriver *new_pci_driver) { list_for_each_owner (old_pci_driver, &pci_driver_lh, pci_driver_list) { if (new_pci_driver->find_type == old_pci_driver->find_type) { if (pci_match_driver(old_pci_driver, new_pci_driver)) { - return DRIVER_RESULT_DEVICE_DRIVER_CONFLICT; + return DRIVER_ERROR_CONFLICT; } break; } else if ( @@ -602,54 +532,86 @@ DriverResult pci_register_driver(Driver *driver, PciDriver *new_pci_driver) { old_pci_driver->class_subclass.classcode && new_pci_driver->class_subclass.subclass == old_pci_driver->class_subclass.subclass) { - return DRIVER_RESULT_DEVICE_DRIVER_CONFLICT; + return DRIVER_ERROR_CONFLICT; } } } list_add_tail(&new_pci_driver->pci_driver_list, &pci_driver_lh); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult pci_device_init(Device *device) { +DriverResult pci_device_init(void *device) { int i; for (i = 0; i < PCI_MAX_DEVICE; i++) { pci_devices[i].status = PCI_DEVICE_STATUS_INVALID; } - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult pci_probe(BusDriver *bus_driver, Bus *bus) { - PciDriver *pci_driver; + ObjectAttr attr = device_object_attr; + PciDriver *pci_driver, *select; + PhysicalDevice *device; + DriverResult result; for (int i = 0; i < PCI_MAX_DEVICE; i++) { if (pci_devices[i].status == PCI_DEVICE_STATUS_UNUSED) { + if (pci_devices[i].device == NULL) { + result = create_physical_device(&device, bus, &attr); + if (result != DRIVER_OK) continue; + pci_devices[i].device = device; + device->bus_ext = &pci_devices[i]; + } + + select = NULL; list_for_each_owner (pci_driver, &pci_driver_lh, pci_driver_list) { if (pci_match_device(pci_driver, &pci_devices[i])) { - pci_devices[i].status = PCI_DEVICE_STATUS_USING; - pci_devices[i].pci_driver = pci_driver; - pci_devices[i].bus = bus; - pci_driver->pci_device = &pci_devices[i]; - pci_driver->ops->probe(&pci_devices[i]); + select = pci_driver; } } + if (select != NULL) { + pci_devices[i].status = PCI_DEVICE_STATUS_USING; + pci_devices[i].pci_driver = select; + pci_devices[i].bus = bus; + select->pci_device = &pci_devices[i]; + + select->ops->probe(&pci_devices[i], device); + } } } - return DRIVER_RESULT_OK; -} - -DriverResult pci_driver_init(Driver *driver) { - ObjectAttr attr = device_object_attr; - DRIVER_RESULT_PASS(register_bus_controller_device( - &pci_device_driver, &pci_bus_driver, &pci_device, - &pci_bus_controller_device, &attr)); - return DRIVER_RESULT_OK; + return DRIVER_OK; } static __init void pci_initcall(void) { - register_driver(&pci_driver); - register_device_driver(&pci_driver, &pci_device_driver); + DriverResult result; + + result = register_driver(&pci_driver); + if (result != DRIVER_OK) goto failed_register_driver; + + result = register_device_driver(&pci_driver, &pci_device_driver); + if (result != DRIVER_OK) goto failed_register_device_driver; + ObjectAttr attr = driver_object_attr; - register_bus_driver(&pci_driver, &pci_bus_driver, &attr); + result = + register_bus_driver(&pci_driver, BUS_TYPE_PCI, &pci_bus_driver, &attr); + if (result != DRIVER_OK) goto failed_register_bus_driver; + + Bus *bus; + result = create_bus(&bus, &pci_bus_driver, &pci_bus_ops); + if (result != DRIVER_OK) goto failed_create_bus; + + return; +failed_create_bus: + unregister_bus_driver(&pci_bus_driver); + +failed_register_bus_driver: + unregister_device_driver(&pci_device_driver); + +failed_register_device_driver: + unregister_driver(&pci_driver); + +failed_register_driver: + return; } driver_initcall(pci_initcall); diff --git a/src/arch/x86/drivers/cmos.c b/src/arch/x86/drivers/cmos.c index d9f5079..dbbd405 100644 --- a/src/arch/x86/drivers/cmos.c +++ b/src/arch/x86/drivers/cmos.c @@ -1,60 +1,61 @@ -#include "kernel/driver.h" #include #include #include #include +#include +#include extern Driver core_driver; DriverResult rtc_get_time(TimeDevice *time_device, TimeType type, Time *time); -DeviceDriverOps rtc_device_driver_ops = { - +DeviceOps cmos_device_ops = { + .init = NULL, + .start = NULL, + .stop = NULL, + .destroy = NULL, }; DeviceOps rtc_device_ops = { .init = NULL, .start = NULL, .stop = NULL, .destroy = NULL, - .status = NULL, }; -TimeDeviceOps rtc_time_device_ops = { +TimeOps rtc_time_device_ops = { .get_time = rtc_get_time, .set_time = NULL, }; -DeviceDriver rtc_device_driver = { - .name = STRING_INIT("RTC"), - .type = DEVICE_TYPE_TIME, - .priority = DRIVER_PRIORITY_BASIC, - .ops = &rtc_device_driver_ops, - .private_data_size = 0, -}; -Device rtc_device = { - .name = STRING_INIT("RTC"), - .device_driver = &rtc_device_driver, - .ops = &rtc_device_ops, - .private_data_size = 0, -}; -TimeDevice rtc_time_device = { - .device = &rtc_device, - .type = TIME_TYPE_LOCAL, - .ops = &rtc_time_device_ops}; - -void register_cmos(void) { - register_device_driver(&core_driver, &rtc_device_driver); - register_time_device(&rtc_device_driver, &rtc_device, &rtc_time_device); +DeviceDriver cmos_device_driver; +PhysicalDevice *cmos_device; +TimeDevice *rtc_time_device; + +DriverResult register_cmos(void) { + register_device_driver(&core_driver, &cmos_device_driver); + + ObjectAttr attr = driver_object_attr; + DRIVER_RESULT_PASS( + create_physical_device(&cmos_device, platform_bus, &attr)); + register_physical_device(cmos_device, &cmos_device_ops); + + DRIVER_RESULT_PASS(create_time_device( + &rtc_time_device, &rtc_time_device_ops, &rtc_device_ops, cmos_device, + &cmos_device_driver)); + + rtc_time_device->type = TIME_TYPE_LOCAL; + + return DRIVER_OK; } -int rtc_guess_year(int year) { +static inline int rtc_guess_year(int year) { return 2000 + year; } -bool rtc_is_updating(void) { +static inline bool rtc_is_updating(void) { return (CMOS_READ(CMOS_STATUS_A) & 0x80); } -bool rtc_is_bcd(void) { +static inline bool rtc_is_bcd(void) { return !(CMOS_READ(CMOS_STATUS_B) & 0x04); } @@ -84,9 +85,9 @@ DriverResult rtc_get_time(TimeDevice *time_device, TimeType type, Time *time) { time->time.minute = minute; time->time.second = second; - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult rtc_set_time(Device *device, TimeType type, Time *time) { - return DRIVER_RESULT_OK; +DriverResult rtc_set_time(TimeDevice *device, TimeType type, Time *time) { + return DRIVER_OK; } diff --git a/src/arch/x86/drivers/disk/ata/ata_driver.c b/src/arch/x86/drivers/disk/ata/ata_driver.c index 3d8281a..94925e8 100644 --- a/src/arch/x86/drivers/disk/ata/ata_driver.c +++ b/src/arch/x86/drivers/disk/ata/ata_driver.c @@ -11,7 +11,6 @@ #include #include "include/ata_driver.h" -#include "include/ide.h" #include "include/ide_controller.h" DriverDependency ata_dependencies[] = { @@ -23,15 +22,12 @@ DriverDependency ata_dependencies[] = { }; Driver ata_driver = { - .short_name = STRING_INIT("AtaDriver"), - .dependency_count = sizeof(ata_dependencies) / sizeof(DriverDependency), - .dependencies = ata_dependencies, + .short_name = STRING_INIT("AtaDriver"), }; static __init void ata_driver_initcall(void) { register_driver(&ata_driver); register_device_driver(&ata_driver, &ide_controller_device_driver); - register_device_driver(&ata_driver, &ide_device_driver); pci_register_driver(&ata_driver, &ide_pci_driver); } diff --git a/src/arch/x86/drivers/disk/ata/dma.c b/src/arch/x86/drivers/disk/ata/dma.c index 6f3c005..f50c886 100644 --- a/src/arch/x86/drivers/disk/ata/dma.c +++ b/src/arch/x86/drivers/disk/ata/dma.c @@ -59,7 +59,7 @@ DriverResult ata_bmdma_map_buffer(AtaDma *ata_dma, void *ptr, uint32_t size) { // 申请一个小的临时缓冲区处理未对齐的部分 int size = 32 - (addr & 0x1f); void *tmp_buf = kmalloc(size); - if (tmp_buf == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } + if (tmp_buf == NULL) { return DRIVER_ERROR_OUT_OF_MEMORY; } memcpy(tmp_buf, ptr, size); DmaSegment *seg = kmalloc(sizeof(DmaSegment)); @@ -71,7 +71,7 @@ DriverResult ata_bmdma_map_buffer(AtaDma *ata_dma, void *ptr, uint32_t size) { } dma_split_mem(&ata_dma->segment_lh, ptr, size, ata_dma->max_segment_size); - return DRIVER_RESULT_OK; + return DRIVER_OK; } void ata_bmdma_unmap_buffer(AtaDma *ata_dma, void *ptr, uint32_t size) { diff --git a/src/arch/x86/drivers/disk/ata/ide.c b/src/arch/x86/drivers/disk/ata/ide.c index 5f16a82..1d75c13 100644 --- a/src/arch/x86/drivers/disk/ata/ide.c +++ b/src/arch/x86/drivers/disk/ata/ide.c @@ -1,12 +1,13 @@ #include -#include +#include #include #include -#include +#include #include #include #include #include +#include #include #include #include @@ -23,9 +24,8 @@ #include "include/dma.h" #include "include/ide.h" #include "include/ide_controller.h" -#include "kernel/list.h" -DriverResult ide_device_init(Device *device); +DriverResult ide_device_init(void *device); DriverResult ide_device_read_sectors( StorageDevice *storage_device, StorageRequest *request); @@ -38,49 +38,28 @@ StorageDeviceOps ide_storage_device_ops = { .submit_write_request = ide_device_write_sectors, .is_busy = ide_device_is_busy, }; -DeviceDriverOps ide_device_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, -}; DeviceOps ide_device_ops = { .init = ide_device_init, .start = NULL, .stop = NULL, .destroy = NULL, - .status = NULL, -}; - -DeviceDriver ide_device_driver = { - .name = STRING_INIT("IDE Driver"), - .type = DEVICE_TYPE_STORAGE, - .priority = DRIVER_PRIORITY_BASIC, - .state = DRIVER_STATE_UNREGISTERED, - .ops = &ide_device_driver_ops, }; -Device ide_device_template = { - .name = STRING_INIT("IDE Harddisk"), - .state = DEVICE_STATE_UNREGISTERED, - .device_driver = &ide_device_driver, - .ops = &ide_device_ops, - .private_data_size = sizeof(IdeDevice), -}; -StorageDevice storage_device_template = { - .block_size = SECTOR_SIZE, - .max_block_per_request = 256, - .max_segment = IDE_MAX_PRDT_COUNT, - .type = STORAGE_DEVICE_TYPE_HARDDISK, - .ops = &ide_storage_device_ops, -}; +DeviceDriver ide_device_driver; void ide_handle_interrupt(IdeChannel *channel) { - int status = io_in_byte(channel->io_base + ATA_REG_ALTSTATUS); - if (BIN_IS_EN(status, ATA_STATUS_ERR)) { + int status = io_in_byte(channel->bmide + IDE_REG_BM_STATUS); + if (!(status & IDE_BMSTATUS_INT)) return; + io_out_byte(channel->bmide + IDE_REG_BM_STATUS, IDE_BMSTATUS_INT); + + status = io_in_byte(channel->io_base + ATA_REG_STATUS); + if (status & ATA_STATUS_ERR) { print_error("IDE", "IDE device error!"); ide_print_error(channel); } IdeDevice *ide_device = channel->ide_devices[channel->selected_device]; + if (ide_device == NULL) { return; } int flags = spin_lock_irqsave(&ide_device->request_lock); StorageRequest *request = ide_device->current_request; @@ -101,20 +80,15 @@ void ide_handle_interrupt(IdeChannel *channel) { storage_finish_request(request); } -void ide_channel0_handler(Device *device) { - IdeChannel *ide_channel = device->child_private_data[0]; - - ide_handle_interrupt(ide_channel); -} -void ide_channel1_handler(Device *device) { - IdeChannel *ide_channel = device->child_private_data[1]; +void ide_irq_handler(void *channel) { + IdeChannel *ide_channel = channel; ide_handle_interrupt(ide_channel); } void ide_sync(IdeChannel *channel) { // 保证先前的命令执行,而不是在缓存中 - io_in_byte(channel->io_base + ATA_REG_ALTSTATUS); + io_in_byte(channel->control_base + ATA_REG_ALTSTATUS); } void ide_pause(IdeChannel *channel) { @@ -125,12 +99,11 @@ void ide_pause(IdeChannel *channel) { void ide_device_probe(IdeChannel *channel) { int i, status, err = 0; AtaDeviceType type = ATA_DEVICE_TYPE_ATA; - ObjectAttr attr = device_object_attr; timer_init(&channel->timer); channel->device_count = 0; - Device *device[2] = {NULL, NULL}; + StorageDevice *device[2] = {NULL, NULL}; for (i = 0; i < 2; i++) { // 1.选择设备 ide_select_device(channel, i); @@ -179,16 +152,18 @@ void ide_device_probe(IdeChannel *channel) { sizeof(AtaIdentifyInfo) / 2); // 6.注册设备 - device[i] = kmalloc_from_template(ide_device_template); - device[i]->bus = &platform_bus; // TODO: BUS - StorageDevice *storage_device = - kmalloc_from_template(storage_device_template); - - register_storage_device( - &ide_device_driver, device[i], storage_device, &attr); - - IdeDevice *ide_device = device[i]->private_data; - ide_device->device = device[i]; + create_storage_device( + &device[i], &ide_storage_device_ops, &ide_device_ops, + channel->physical_device, &ide_device_driver); + + IdeDevice *ide_device = kmalloc(sizeof(IdeDevice)); + device[i]->device->private_data = ide_device; + device[i]->block_size = SECTOR_SIZE; + device[i]->max_block_per_request = 256; + device[i]->max_segment = IDE_MAX_PRDT_COUNT; + device[i]->type = STORAGE_DEVICE_TYPE_HARDDISK; + + ide_device->device = device[i]->device; ide_device->channel = channel; ide_device->type = type; ide_device->info = identify; @@ -201,9 +176,9 @@ void ide_device_probe(IdeChannel *channel) { channel->device_count++; } if (channel->device_count) { - uint8_t data = io_in_byte(channel->io_base + ATA_REG_CONTROL); + uint8_t data = io_in_byte(channel->control_base + ATA_REG_CONTROL); io_out_byte( - channel->io_base + ATA_REG_CONTROL, + channel->control_base + ATA_REG_CONTROL, BIN_DIS(data, ATA_CONTROL_NIEN)); channel->dma = kmalloc(sizeof(AtaDma)); @@ -214,15 +189,18 @@ void ide_device_probe(IdeChannel *channel) { channel->dma->max_segment_size = 65536; list_init(&channel->dma->segment_lh); - interrupt_enable_irq(channel->irq->irq); + enable_device_irq(channel->irq); for (i = 0; i < 2; i++) { - if (device[i] != NULL) { init_and_start(device[i]); } + if (device[i] != NULL) { + init_and_start_logical_device(device[i]->device); + } } } } -DriverResult ide_device_init(Device *device) { +DriverResult ide_device_init(void *_device) { + LogicalDevice *device = _device; IdeDevice *ide_device = device->private_data; AtaIdentifyInfo *identify = ide_device->info; @@ -239,10 +217,10 @@ DriverResult ide_device_init(Device *device) { ide_device->cmdset[ATA_CMDSET_READ] = ATA_CMD_READ_PIO; ide_device->cmdset[ATA_CMDSET_WRITE] = ATA_CMD_WRITE_PIO; } else { - return DRIVER_RESULT_UNSUPPORT_FEATURE; + return DRIVER_ERROR_UNSUPPORT_FEATURE; } - return DRIVER_RESULT_OK; + return DRIVER_OK; } void ide_set_sector_lba28(IdeChannel *channel, uint32_t lba0, uint8_t count) { @@ -344,7 +322,7 @@ DriverResult ide_device_read_sectors( BIN_EN(data, IDE_BMCMD_START_STOP_BM)); } spin_unlock_irqrestore(&ide_device->request_lock, flags); - return DRIVER_RESULT_OK; + return DRIVER_OK; } /** @@ -402,12 +380,12 @@ DriverResult ide_device_write_sectors( BIN_EN(data, IDE_BMCMD_START_STOP_BM)); } spin_unlock_irqrestore(&ide_device->request_lock, flags); - return DRIVER_RESULT_OK; + return DRIVER_OK; } bool ide_device_is_busy(StorageDevice *storage_device) { - Device *device = storage_device->device; - IdeDevice *ide_device = device->private_data; + LogicalDevice *device = storage_device->device; + IdeDevice *ide_device = device->private_data; int flags = spin_lock_irqsave(&ide_device->request_lock); bool result = ide_device->current_request != NULL; diff --git a/src/arch/x86/drivers/disk/ata/ide_controller.c b/src/arch/x86/drivers/disk/ata/ide_controller.c index 1feaea5..7c1c0c7 100644 --- a/src/arch/x86/drivers/disk/ata/ide_controller.c +++ b/src/arch/x86/drivers/disk/ata/ide_controller.c @@ -1,6 +1,9 @@ +#include "include/ide_controller.h" +#include "include/ata_driver.h" +#include "include/ide.h" #include #include -#include +#include #include #include #include @@ -9,43 +12,21 @@ #include #include #include +#include #include #include -#include "include/ata_driver.h" -#include "include/ide.h" -#include "include/ide_controller.h" -#include "objects/object.h" +DriverResult ide_controller_probe( + PciDevice *pci_device, PhysicalDevice *physical_device); +DriverResult ide_controller_init(void *device); -DriverResult ide_controller_probe(PciDevice *pci_device); -DriverResult ide_controller_init(Device *device); - -DeviceDriverOps ide_controller_device_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, -}; -DeviceDriver ide_controller_device_driver = { - .name = STRING_INIT("IDE Controller Device Driver"), - .type = DEVICE_TYPE_BUS_CONTROLLER, - .priority = DRIVER_PRIORITY_BASIC, - .state = DRIVER_STATE_UNREGISTERED, - .ops = &ide_controller_device_driver_ops, -}; +DeviceDriver ide_controller_device_driver; DeviceOps ide_controller_device_ops = { .init = ide_controller_init, .start = NULL, .stop = NULL, .destroy = NULL, - .status = NULL, -}; -Device ide_controller_device_templete = { - .name = STRING_INIT("IDE Controller"), - .state = DEVICE_STATE_UNREGISTERED, - .device_driver = &ide_controller_device_driver, - .ops = &ide_controller_device_ops, - .max_child_device = 2, - .private_data_size = sizeof(IdeControllerInfo), }; PciDriverOps ide_pci_driver_ops = { @@ -75,27 +56,31 @@ void ide_detect_channel_mode( } } -DriverResult ide_controller_probe(PciDevice *pci_device) { - Device *device = kmalloc_from_template(ide_controller_device_templete); - ObjectAttr attr = device_object_attr; - register_device( - &ide_controller_device_driver, NULL, pci_device->bus, device, &attr); +DriverResult ide_controller_probe( + PciDevice *pci_device, PhysicalDevice *physical_device) { + IdeControllerInfo *info = kmalloc(sizeof(IdeControllerInfo)); - IdeControllerInfo *info = device->private_data; - info->pci_device = pci_device; - info->dma_support = pci_device->prog_if >> 7; - info->bus_master_base = pci_device->common.bar[4].base_addr; + register_physical_device(physical_device, &ide_controller_device_ops); - return DRIVER_RESULT_OK; + physical_device->private_data = info; + info->pci_device = pci_device; + info->dma_support = pci_device->prog_if >> 7; + info->bus_master_base = pci_device->common.bar[4].base_addr; + + return DRIVER_OK; } -void ide_controller_setup_legacy_mode(IdeChannel *channel) { +void ide_controller_setup_legacy_mode( + PhysicalDevice *physical_device, IdeChannel *channel) { channel->io_base = (channel->channel_num ? ATA_SECONDARY_PORT : ATA_PRIMARY_PORT); channel->control_base = (channel->channel_num ? ATA_SECONDARY_CONTROL_PORT : ATA_PRIMARY_CONTROL_PORT); - channel->irq->irq = (channel->channel_num ? IDE_IRQ1 : IDE_IRQ0); + register_device_irq( + &channel->irq, physical_device, channel, + (channel->channel_num ? IDE_IRQ1 : IDE_IRQ0), ide_irq_handler, + IRQ_MODE_SHARED); } void ide_controller_setup_pci_mode(PciDevice *pci_device, IdeChannel *channel) { @@ -103,30 +88,26 @@ void ide_controller_setup_pci_mode(PciDevice *pci_device, IdeChannel *channel) { pci_device->common.bar[channel->channel_num * 2].base_addr; channel->control_base = pci_device->common.bar[channel->channel_num * 2 + 1].base_addr; - channel->irq->irq = pci_device->irqline; + register_device_irq( + &channel->irq, pci_device->device, channel, pci_device->irqline, + ide_irq_handler, IRQ_MODE_SHARED); } -DriverResult ide_controller_init(Device *device) { - IdeControllerInfo *info = device->private_data; +DriverResult ide_controller_init(void *_device) { + PhysicalDevice *device = _device; + IdeControllerInfo *info = device->private_data; for (int i = 0; i < 2; i++) { - register_child_device(device, sizeof(IdeChannel)); - - IdeChannel *channel = device->child_private_data[i]; + IdeChannel *channel = &info->channels[i]; - channel->channel_num = i; + channel->physical_device = device; + channel->channel_num = i; + channel->selected_device = 0; // 检查是否支持PCI Native模式 ide_detect_channel_mode(channel, info->pci_device, i); - DeviceIrq *irq = kmalloc(sizeof(DeviceIrq)); - irq->device = device; - irq->handler = - (channel->channel_num == 0 ? ide_channel0_handler - : ide_channel1_handler); - channel->irq = irq; - if (channel->mode == IDE_COMPATITY_MODE) { - ide_controller_setup_legacy_mode(channel); + ide_controller_setup_legacy_mode(device, channel); } else { ide_controller_setup_pci_mode(info->pci_device, channel); } @@ -138,13 +119,12 @@ DriverResult ide_controller_init(Device *device) { } // 禁用并注册IRQ - io_out_byte(channel->io_base + ATA_REG_CONTROL, ATA_CONTROL_NIEN); - register_device_irq(irq); + io_out_byte(channel->control_base + ATA_REG_CONTROL, ATA_CONTROL_NIEN); ide_device_probe(channel); } - return DRIVER_RESULT_OK; + return DRIVER_OK; } void ide_print_error(IdeChannel *channel) { @@ -177,15 +157,15 @@ void ide_print_error(IdeChannel *channel) { } void ide_reset_drive(IdeChannel *channel) { - uint8_t data = io_in_byte(channel->io_base + ATA_REG_CONTROL); - io_out_byte(channel->io_base + ATA_REG_CONTROL, BIN_EN(data, BIT(2))); + uint8_t data = io_in_byte(channel->control_base + ATA_REG_CONTROL); + io_out_byte(channel->control_base + ATA_REG_CONTROL, BIN_EN(data, BIT(2))); // 等待重置 int i; for (i = 0; i < 50; i++) { io_in_byte(channel->io_base + ATA_REG_STATUS); } - io_out_byte(channel->io_base + ATA_REG_CONTROL, data); + io_out_byte(channel->control_base + ATA_REG_CONTROL, data); channel->selected_device = 0; } @@ -208,7 +188,8 @@ void ide_polling(IdeChannel *channel) { // 等待400ns for (int i = 0; i < 4; i++) { - io_in_byte(channel->io_base + ATA_REG_ALTSTATUS); // 读一次需要100ns + io_in_byte( + channel->control_base + ATA_REG_ALTSTATUS); // 读一次需要100ns } int status; diff --git a/src/arch/x86/drivers/disk/ata/include/ata_driver.h b/src/arch/x86/drivers/disk/ata/include/ata_driver.h index cb20364..a96c817 100644 --- a/src/arch/x86/drivers/disk/ata/include/ata_driver.h +++ b/src/arch/x86/drivers/disk/ata/include/ata_driver.h @@ -53,9 +53,9 @@ typedef enum AtaDeviceType { #define ATA_REG_LBA4 0x04 #define ATA_REG_LBA5 0x05 -#define ATA_REG_CONTROL 0x02 -#define ATA_REG_ALTSTATUS 0x02 -#define ATA_REG_DEVADDRESS 0x03 +#define ATA_REG_CONTROL 0x00 +#define ATA_REG_ALTSTATUS 0x00 +#define ATA_REG_DEVADDRESS 0x01 #define ATA_PRIMARY 0x00 #define ATA_SECONDARY 0x01 diff --git a/src/arch/x86/drivers/disk/ata/include/ide.h b/src/arch/x86/drivers/disk/ata/include/ide.h index 7800be9..25bf4c4 100644 --- a/src/arch/x86/drivers/disk/ata/include/ide.h +++ b/src/arch/x86/drivers/disk/ata/include/ide.h @@ -3,11 +3,11 @@ #include "ata.h" #include "ata_driver.h" -#include "driver/storage/storage_io_queue.h" #include "ide_controller.h" -#include "kernel/device.h" -#include "kernel/spinlock.h" -#include "stdint.h" +#include +#include +#include +#include #define IDE_IRQ0 14 #define IDE_IRQ1 15 @@ -16,11 +16,12 @@ typedef struct IdeOps { void (*set_sector)( - struct Device *device, uint32_t lba0, uint32_t lba1, uint32_t count); + struct PhysicalDevice *device, uint32_t lba0, uint32_t lba1, + uint32_t count); } IdeOps; typedef struct IdeDevice { - Device *device; + LogicalDevice *device; IdeChannel *channel; AtaIdentifyInfo *info; AtaDeviceType type; @@ -38,8 +39,7 @@ typedef struct IdeDevice { extern struct DeviceDriver ide_device_driver; -void ide_channel0_handler(struct Device *device); -void ide_channel1_handler(struct Device *device); +void ide_irq_handler(void *channel); void ide_device_probe(IdeChannel *channel); #endif \ No newline at end of file diff --git a/src/arch/x86/drivers/disk/ata/include/ide_controller.h b/src/arch/x86/drivers/disk/ata/include/ide_controller.h index 88a2c0a..317ea8d 100644 --- a/src/arch/x86/drivers/disk/ata/include/ide_controller.h +++ b/src/arch/x86/drivers/disk/ata/include/ide_controller.h @@ -1,12 +1,12 @@ #ifndef _ATA_IDE_CONTROLL_H #define _ATA_IDE_CONTROLL_H -#include "bits.h" -#include "driver/timer_dm.h" -#include "drivers/bus/pci/pci.h" -#include "kernel/driver_interface.h" -#include "kernel/spinlock.h" -#include "stdint.h" +#include "kernel/device.h" +#include +#include +#include +#include +#include #define IDE_CONTROLLER_CLASSCODE 0x01 #define IDE_CONTROLLER_SUBCLASS 0x01 @@ -34,6 +34,8 @@ typedef struct IdeChannelInfo { IDE_COMPATITY_MODE, IDE_NATIVE_MODE, } mode; + PhysicalDevice *physical_device; + DeviceIrq *irq; uint16_t io_base; uint16_t control_base; @@ -54,6 +56,8 @@ typedef struct IdeControllerInfo { PciDevice *pci_device; uint32_t bus_master_base; + + IdeChannel channels[2]; } IdeControllerInfo; extern struct DeviceDriver ide_controller_device_driver; diff --git a/src/arch/x86/drivers/framebuffer/vesa_display.c b/src/arch/x86/drivers/framebuffer/vesa_display.c index e30ae72..7bd00c7 100644 --- a/src/arch/x86/drivers/framebuffer/vesa_display.c +++ b/src/arch/x86/drivers/framebuffer/vesa_display.c @@ -12,52 +12,35 @@ extern Driver core_driver; struct VesaDisplayInfo vesa_display_info; -DriverResult vesa_display_device_init(Device *device); -DriverResult vesa_display_device_start(Device *device); +DriverResult vesa_display_device_init(void *device); +DriverResult vesa_display_device_start(void *device); -DeviceDriverOps vesa_display_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, -}; DeviceOps vesa_display_device_ops = { .init = vesa_display_device_init, .start = vesa_display_device_start, .stop = NULL, .destroy = NULL, - .status = NULL, }; -DeviceDriver vesa_display_device_driver = { - .name = STRING_INIT("VESA Display Device Driver"), - .type = DEVICE_TYPE_FRAMEBUFFER, - .priority = DRIVER_PRIORITY_BASIC, - .state = DRIVER_STATE_UNREGISTERED, - .ops = &vesa_display_driver_ops, -}; -Device vesa_display_device = { - .name = STRING_INIT("Vesa Display"), - .bus = &platform_bus, - .device_driver = &vesa_display_device_driver, - .ops = &vesa_display_device_ops, - .private_data_size = 0, -}; -FrameBufferDevice vesa_display_fb_device = { - .device = &vesa_display_device, -}; +DeviceDriver vesa_display_device_driver; -void register_vesa_display(void) { +DriverResult register_vesa_display(void) { + FrameBufferDevice *fb_device; register_device_driver(&core_driver, &vesa_display_device_driver); - ObjectAttr attr = device_object_attr; - register_framebuffer_device( - &vesa_display_device_driver, &vesa_display_device, - &vesa_display_fb_device, &attr); + + DriverResult result = create_framebuffer_device( + &fb_device, &vesa_display_device_ops, platform_device, + &vesa_display_device_driver); + if (result != DRIVER_OK) { return result; } + + return DRIVER_OK; } #define SEG_ADDR2LINEAR_ADDR(addr) \ ((unsigned int *)(((unsigned int)(addr) >> 12) & 0xffff0) + \ ((unsigned int)(addr) & 0xffff)) -DriverResult vesa_display_device_init(Device *device) { +DriverResult vesa_display_device_init(void *device) { vesa_display_info.vbe_mode_info->OemStringPtr = SEG_ADDR2LINEAR_ADDR(vesa_display_info.vbe_mode_info->OemStringPtr); vesa_display_info.vbe_mode_info->VideoModePtr = @@ -68,17 +51,17 @@ DriverResult vesa_display_device_init(Device *device) { SEG_ADDR2LINEAR_ADDR(vesa_display_info.vbe_mode_info->OemProduceRevPtr); vesa_display_info.vbe_mode_info->OemProductNamePtr = SEG_ADDR2LINEAR_ADDR( vesa_display_info.vbe_mode_info->OemProductNamePtr); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult vesa_display_device_start(Device *device) { +DriverResult vesa_display_device_start(void *device) { vesa_display_info.vram = (uint8_t *)VRAM_VIR_ADDR; - FrameBufferDevice *fb_device = device->dm_ext; + FrameBufferDevice *fb_device = ((LogicalDevice *)device)->dm_ext; fb_device->mode_info.width = vesa_display_info.width; fb_device->mode_info.height = vesa_display_info.height; fb_device->mode_info.bits_per_pixel = vesa_display_info.BitsPerPixel; fb_device->mode_info.bytes_per_pixel = vesa_display_info.BitsPerPixel / 8; fb_device->framebuffer_address = vesa_display_info.vram; - return DRIVER_RESULT_OK; + return DRIVER_OK; } diff --git a/src/arch/x86/drivers/input/8042/8042.c b/src/arch/x86/drivers/input/8042/8042.c index e343fa8..dd93dc5 100644 --- a/src/arch/x86/drivers/input/8042/8042.c +++ b/src/arch/x86/drivers/input/8042/8042.c @@ -12,29 +12,9 @@ #include #include -// static status_t i8042_enter(driver_t *drv_obj); -// static status_t i8042_exit(driver_t *drv_obj); - #define DRV_NAME "General PS/2 Driver" #define DEV_NAME "ps2controller" -// typedef struct { -// bool is_dual_channel; -// bool is_p1_avail, is_p2_avail; - -// uint8_t p1_dev_type, p2_dev_type; -// } device_extension_t; - -// driver_func_t i8042_driver = { -// .driver_enter = i8042_enter, -// .driver_exit = i8042_exit, -// .driver_open = NULL, -// .driver_close = NULL, -// .driver_read = NULL, -// .driver_write = NULL, -// .driver_devctl = NULL, -// }; - int i8042_get_status(uint8_t type) { int data = io_in8(I8042_PORT_STAT); return data & type; diff --git a/src/arch/x86/drivers/interrupt/8259a.c b/src/arch/x86/drivers/interrupt/8259a.c index d19c798..26d3903 100644 --- a/src/arch/x86/drivers/interrupt/8259a.c +++ b/src/arch/x86/drivers/interrupt/8259a.c @@ -6,23 +6,22 @@ * @date 2022-07-31 * */ +#include +#include #include #include #include -#include - -// --------new-------- -#include -#include #include #include #include #include +#include #include +#include #include #include -DriverResult pic_init(Device *device); +DriverResult i8259a_init(void *device); int pic_redirect_irq(InterruptDevice *device, int irq); DriverResult pic_enable_irq(InterruptDevice *device, int irq); DriverResult pic_disable_irq(InterruptDevice *device, int irq); @@ -30,16 +29,17 @@ void pic_eoi(InterruptDevice *device, int irq); extern Driver core_driver; -DeviceDriverOps pic_device_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, +DeviceOps i8259a_device_ops = { + .init = i8259a_init, + .start = NULL, + .stop = NULL, + .destroy = NULL, }; DeviceOps pic_device_ops = { - .init = pic_init, + .init = NULL, .start = NULL, .stop = NULL, .destroy = NULL, - .status = NULL, }; InterruptDeviceOps pic_interrupt_ops = { .enable_irq = pic_enable_irq, @@ -48,31 +48,31 @@ InterruptDeviceOps pic_interrupt_ops = { .redirect_irq = pic_redirect_irq, }; -DeviceDriver pic_device_driver = { - .name = STRING_INIT("PIC Driver"), - .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, - .priority = DRIVER_PRIORITY_BASIC, - .state = DRIVER_STATE_UNREGISTERED, - .ops = &pic_device_driver_ops, +DeviceDriver pic_device_driver; +PhysicalDevice *i8259a_device; +InterruptDevice *pic_device; +InterruptDevice pic_interrupt_device = { + .ops = &pic_interrupt_ops, + .priority = 0, }; -Device pic_device = { - .name = STRING_INIT("8259a"), - .device_driver = &pic_device_driver, +DriverResult register_pic(void) { + ObjectAttr attr = device_object_attr; - .ops = &pic_device_ops, + if (use_apic) return DRIVER_OK; - .private_data_size = 0, -}; -InterruptDevice pic_interrupt_device = { - .interrupt_ops = &pic_interrupt_ops, - .priority = 0, -}; + DRIVER_RESULT_PASS( + register_device_driver(&core_driver, &pic_device_driver)); -void register_pic(void) { - register_device_driver(&core_driver, &pic_device_driver); - register_interrupt_device( - &pic_device_driver, &pic_device, &pic_interrupt_device); + DRIVER_RESULT_PASS( + create_physical_device(&i8259a_device, platform_bus, &attr)); + + DRIVER_RESULT_PASS(create_interrupt_device( + &pic_device, &pic_device_ops, i8259a_device, &pic_device_driver, + &pic_interrupt_ops, 0)); + + register_physical_device(i8259a_device, &i8259a_device_ops); + return DRIVER_OK; } void mask_8259a(void) { @@ -80,12 +80,12 @@ void mask_8259a(void) { io_out_byte(PIC1_IMR, 0xff); } -DriverResult pic_init(Device *device) { +DriverResult i8259a_init(void *device) { io_out_byte(PIC0_IMR, 0xff); // 屏蔽主PIC的所有中断 io_out_byte(PIC1_IMR, 0xff); // 屏蔽从PIC的所有中断 - io_out_byte(PIC0_ICW1, 0x11); // 级联,边沿触发 - io_out_byte(PIC0_ICW2, 0x20); // 起始中断向量号位0x20(0x00~0x1f为内部中断) + io_out_byte(PIC0_ICW1, 0x11); // 级联,边沿触发 + io_out_byte(PIC0_ICW2, 0x20); // 起始中断向量号位0x20(0x00~0x1f为内部中断) io_out_byte(PIC0_ICW3, 1 << 2); // IRQ2用于连接从PIC // 全嵌套模式,非缓冲模式,手动结束中断,x86处理器 io_out_byte(PIC0_ICW4, 0x01); @@ -98,7 +98,7 @@ DriverResult pic_init(Device *device) { io_out_byte(PIC0_IMR, 0xfb); // 开启IRQ2(从PIC)中断 io_out_byte(PIC1_IMR, 0xff); // 屏蔽从PIC的所有中断 - return DRIVER_RESULT_OK; + return DRIVER_OK; } int pic_redirect_irq(InterruptDevice *device, int irq) { @@ -114,7 +114,7 @@ DriverResult pic_enable_irq(InterruptDevice *device, int irq) { data = io_in8(PIC1_IMR); io_out8(PIC1_IMR, BIN_DIS(data, BIT(irq % 8))); } - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult pic_disable_irq(InterruptDevice *device, int irq) { @@ -126,55 +126,10 @@ DriverResult pic_disable_irq(InterruptDevice *device, int irq) { data = io_in8(PIC1_IMR); io_out8(PIC1_IMR, BIN_EN(data, BIT(irq % 8))); } - return DRIVER_RESULT_OK; + return DRIVER_OK; } void pic_eoi(InterruptDevice *device, int irq) { if (irq >= 8) { io_out8(PIC1_OCW1, PIC_EOI); } io_out8(PIC0_OCW1, PIC_EOI); } - -// --------old-------- - -// void init_8259a(void) { -// io_out8(PIC0_IMR, 0xff); // 屏蔽主PIC的所有中断 -// io_out8(PIC1_IMR, 0xff); // 屏蔽从PIC的所有中断 - -// io_out8(PIC0_ICW1, 0x11); // 级联,边沿触发 -// io_out8(PIC0_ICW2, 0x20); // 起始中断向量号位0x20(0x00~0x1f为内部中断) -// io_out8(PIC0_ICW3, 1 << 2); // IRQ2用于连接从PIC -// io_out8(PIC0_ICW4, 0x01); // 全嵌套模式,非缓冲模式,手动结束中断,x86处理器 - -// io_out8(PIC1_ICW1, 0x11); // 级联,边沿触发 -// io_out8(PIC1_ICW2, 0x28); // 起始中断向量号位0x28 -// io_out8(PIC1_ICW3, 0x02); // 连接到主PIC的IRQ2 -// io_out8(PIC1_ICW4, 0x01); // 全嵌套模式,非缓冲模式,手动结束中断,x86处理器 - -// io_out8(PIC0_IMR, 0xfb); // 开启IRQ2(从PIC)中断 -// io_out8(PIC1_IMR, 0xff); // 屏蔽从PIC的所有中断 - -// use_apic = 0; - -// return; -// } - -// void mask_8259a(void) { -// io_out8(PIC0_IMR, 0xff); -// io_out8(PIC1_IMR, 0xff); -// } - -// void pic_enable_irq(int irq) { -// uint8_t data; -// if (irq < 8) { -// data = io_in8(PIC0_IMR); -// io_out8(PIC0_IMR, data & ~(1 << irq)); -// } else { -// data = io_in8(PIC1_IMR); -// io_out8(PIC1_IMR, data & ~(1 << (irq % 8))); -// } -// } - -// void pic_eoi(int irq) { -// if (irq >= 8) { io_out8(PIC1_OCW1, PIC_EOI); } -// io_out8(PIC0_OCW1, PIC_EOI); -// } diff --git a/src/arch/x86/drivers/interrupt/apic.c b/src/arch/x86/drivers/interrupt/apic.c index 9e5d953..079d18a 100644 --- a/src/arch/x86/drivers/interrupt/apic.c +++ b/src/arch/x86/drivers/interrupt/apic.c @@ -2,11 +2,12 @@ * @file apic.c * @author Ryan Wang (ryan1202@foxmail.com) * @brief APIC驱动(参考xv6) - * @version 0.1 Alpha - * @date 2021-06 + * @version 0.1 + * @date 2025-09 */ #include -#include +#include +#include #include #include #include @@ -15,47 +16,34 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include +#include #include #include -void apic_timer_handler(void); - -char use_apic; - -volatile struct ioapic { - uint32_t reg; - uint32_t pad[3]; - uint32_t data; -}; - -// --------new--------- -#include -#include -#include -#include -#include - -DriverResult apic_init(Device *device); -DriverResult apic_start(Device *device); -DriverResult apic_stop(Device *device); +DriverResult apic_init(void *device); +DriverResult apic_start(void *device); +DriverResult apic_stop(void *device); DriverResult apic_driver_init(struct DeviceDriver *driver); int apic_redirect_irq(InterruptDevice *device, int irq); DriverResult apic_enable_irq(InterruptDevice *device, int irq); DriverResult apic_disable_irq(InterruptDevice *device, int irq); -DriverResult apic_timer_init(Device *device); -DriverResult apic_timer_start(Device *device); -DriverResult apic_timer_stop(Device *device); +DriverResult apic_timer_init(void *device); +DriverResult apic_timer_start(void *device); +DriverResult apic_timer_stop(void *device); void apic_eoi(InterruptDevice *device, int irq); TimerResult apic_timer_set_frequency( TimerDevice *timer_device, uint32_t frequency); -void apic_timer_irq_handler(Device *device); +void apic_timer_irq_handler(void *device); extern Driver core_driver; @@ -72,9 +60,18 @@ typedef struct ApicInfo { uint8_t max_lvt_entry; uint32_t *lapic_mmio; struct ioapic *ioapic; + DeviceIrq *device_irq; } ApicInfo; ApicInfo apic_info; +volatile struct ioapic { + uint32_t reg; + uint32_t pad[3]; + uint32_t data; +}; + +bool use_apic; + uint32_t lapic_write(int index, int value) { apic_info.lapic_mmio[index / 4] = value; return apic_info.lapic_mmio[APIC_ID / 4]; @@ -84,84 +81,38 @@ uint32_t lapic_read(int index) { return apic_info.lapic_mmio[index / 4]; } -DeviceDriverOps apic_device_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, -}; DeviceOps apic_device_ops = { .init = apic_init, .start = apic_start, .stop = apic_stop, .destroy = NULL, - .status = NULL, -}; -InterruptDeviceOps apic_interrupt_ops = { - .enable_irq = apic_enable_irq, - .disable_irq = apic_disable_irq, - .eoi = apic_eoi, - .redirect_irq = apic_redirect_irq, }; - -DeviceDriverOps apic_timer_device_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, +DeviceOps apic_interrupt_device_ops = { + .init = NULL, + .start = NULL, + .stop = NULL, + .destroy = NULL, }; DeviceOps apic_timer_device_ops = { .init = apic_timer_init, .start = apic_timer_start, .stop = apic_timer_stop, .destroy = NULL, - .status = NULL, +}; +InterruptDeviceOps apic_interrupt_ops = { + .enable_irq = apic_enable_irq, + .disable_irq = apic_disable_irq, + .eoi = apic_eoi, + .redirect_irq = apic_redirect_irq, }; TimerOps apic_timer_ops = { .set_frequency = apic_timer_set_frequency, }; -DeviceDriver apic_device_driver = { - .name = STRING_INIT("APIC"), - .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, - .priority = DRIVER_PRIORITY_BASIC, - .state = DRIVER_STATE_UNREGISTERED, - .ops = &apic_device_driver_ops, -}; -Device apic_device = { - .name = STRING_INIT("APIC"), - .device_driver = &apic_device_driver, - .ops = &apic_device_ops, - .private_data_size = 0, -}; -InterruptDevice apic_interrupt_device = { - .interrupt_ops = &apic_interrupt_ops, - .priority = 1, -}; - -DeviceDriver apic_timer_device_driver = { - .name = STRING_INIT("APIC Timer"), - .type = DEVICE_TYPE_TIMER, - .priority = DRIVER_PRIORITY_BASIC, - .state = DRIVER_STATE_UNREGISTERED, - .ops = &apic_timer_device_driver_ops, -}; -DeviceIrq apic_timer_irq = { - .device = &apic_timer_device, - .irq = 2, - .handler = apic_timer_irq_handler, -}; -Device apic_timer_device = { - .name = STRING_INIT("APIC Timer"), - .device_driver = &apic_timer_device_driver, - .ops = &apic_timer_device_ops, - .irq = &apic_timer_irq, - .private_data_size = 0, -}; -TimerDevice apic_timer_timer_device = { - .current_frequency = 0, - .min_frequency = 0, - .max_frequency = 0, - .source_frequency = 0, - .priority = 2, - .timer_ops = &apic_timer_ops, -}; +DeviceDriver apic_device_driver; +PhysicalDevice *apic_device; +InterruptDevice *apic_interrupt_device; +TimerDevice *apic_timer_device; uint32_t io_apic_read(uint32_t reg) { apic_info.ioapic->reg = reg; @@ -173,13 +124,23 @@ void io_apic_write(uint32_t reg, uint32_t data) { apic_info.ioapic->data = data; } -void register_apic(void) { +DriverResult register_apic(void) { register_device_driver(&core_driver, &apic_device_driver); - register_device_driver(&core_driver, &apic_timer_device_driver); - register_interrupt_device( - &apic_device_driver, &apic_device, &apic_interrupt_device); - register_timer_device( - &apic_device_driver, &apic_timer_device, &apic_timer_timer_device); + + apic_driver_init(&apic_device_driver); + if (!use_apic) return DRIVER_ERROR_NOT_EXIST; + + ObjectAttr attr = device_object_attr; + DRIVER_RESULT_PASS( + create_physical_device(&apic_device, platform_bus, &attr)); + register_physical_device(apic_device, &apic_device_ops); + + DRIVER_RESULT_PASS(create_interrupt_device( + &apic_interrupt_device, &apic_interrupt_device_ops, apic_device, + &apic_device_driver, &apic_interrupt_ops, 1)); + return create_timer_device( + &apic_timer_device, &apic_timer_ops, &apic_timer_device_ops, + apic_device, &apic_device_driver); } void x2apic_init(struct DeviceDriver *driver) { @@ -193,10 +154,10 @@ void x2apic_init(struct DeviceDriver *driver) { uint32_t tmp; DRV_RESULT_PRINT_CALL( - driver_remap_memory, &core_driver, apic_info.apic_base, 0x3ff, &tmp); + driver_remap_memory(&core_driver, apic_info.apic_base, 0x3ff, &tmp)); apic_info.lapic_mmio = (uint32_t *)tmp; DRV_RESULT_PRINT_CALL( - driver_remap_memory, &core_driver, 0xfec00000, 0xfff00, &tmp); + driver_remap_memory(&core_driver, 0xfec00000, 0xfff00, &tmp)); apic_info.ioapic = (struct ioapic *)tmp; read_msr(X2APIC_ID_MSR, &apic_info.apic_id, &apic_info.apic_id_high); @@ -208,12 +169,11 @@ void xapic_init(struct DeviceDriver *driver) { apic_info.apic_type = APIC_TYPE_XAPIC; apic_info.apic_base = 0xfee00000; - DRV_RESULT_PRINT_CALL( - driver_remap_memory, &core_driver, apic_info.apic_base, 0x3ff, - (uint32_t *)&apic_info.lapic_mmio); - DRV_RESULT_PRINT_CALL( - driver_remap_memory, &core_driver, 0xfec00000, 0xfff00, - (uint32_t *)&apic_info.ioapic); + DRV_RESULT_PRINT_CALL(driver_remap_memory( + &core_driver, apic_info.apic_base, 0x3ff, + (uint32_t *)&apic_info.lapic_mmio)); + DRV_RESULT_PRINT_CALL(driver_remap_memory( + &core_driver, 0xfec00000, 0xfff00, (uint32_t *)&apic_info.ioapic)); apic_info.apic_id = lapic_read(APIC_ID) >> 24; apic_info.version = (lapic_read(APIC_Ver) & 0xff); @@ -225,6 +185,7 @@ DriverResult apic_driver_init(struct DeviceDriver *driver) { * 所有文档都说要先屏蔽8259a的中断,直到我无数次触发#DF才知道为什么... * 防止apic完成初始化前触发中断无法正确处理导致异常 */ + use_apic = true; if (cpu_check_feature(CPUID_FEAT_X2APIC)) { mask_8259a(); x2apic_init(driver); @@ -232,9 +193,10 @@ DriverResult apic_driver_init(struct DeviceDriver *driver) { mask_8259a(); xapic_init(driver); } else { - return DRIVER_RESULT_NOT_EXIST; + use_apic = false; + return DRIVER_ERROR_NOT_EXIST; } - return DRIVER_RESULT_OK; + return DRIVER_OK; } void enable_apic_with_msr(void) { @@ -277,8 +239,8 @@ void disable_apic(void) { } } -DriverResult apic_init(Device *device) { - apic_driver_init(&apic_device_driver); +DriverResult apic_init(void *device) { + DRIVER_RESULT_PASS(apic_driver_init(&apic_device_driver)); lapic_write(APIC_LVT_LINT0, BIT(16)); lapic_write(APIC_LVT_LINT1, BIT(16)); @@ -301,19 +263,19 @@ DriverResult apic_init(Device *device) { if (i == timeout) { print_error_with_position("APIC init timeout\n"); - return DRIVER_RESULT_TIMEOUT; + return DRIVER_ERROR_TIMEOUT; } lapic_write(APIC_TPR, 0); for (int i = 0; i < apic_info.max_lvt_entry; i++) { - apic_disable_irq(device->dm_ext, 0x20 + i); + apic_disable_irq(apic_interrupt_device, 0x20 + i); } - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult apic_timer_calibrate(Device *device) { - const int ms = 10; +DriverResult apic_timer_calibrate(LogicalDevice *device) { + const int ms = 100; Timer timer; timer_init(&timer); @@ -322,51 +284,57 @@ DriverResult apic_timer_calibrate(Device *device) { lapic_write(APIC_TIMER_ICT, 0xffffffff); - enable_interrupt(); delay_ms(&timer, ms); - disable_interrupt(); lapic_write(APIC_LVT_TIMER, BIN_EN(data, BIT(16))); - uint32_t apic_timer_count = lapic_read(APIC_TIMER_CCT); - uint32_t freq = (0xffffffff - apic_timer_count) / ms * 1000; - apic_timer_timer_device.source_frequency = freq; - apic_timer_timer_device.min_frequency = DIV_ROUND_UP(freq, 0xffffffff); - apic_timer_timer_device.max_frequency = freq; - return DRIVER_RESULT_OK; + uint32_t apic_timer_count = lapic_read(APIC_TIMER_CCT); + uint32_t delta = (0xffffffff - apic_timer_count); + uint32_t freq = delta * (1000 / ms); + apic_timer_device->source_frequency = freq; + apic_timer_device->min_frequency = DIV_ROUND_UP(freq, 0xffffffff); + apic_timer_device->max_frequency = freq; + apic_timer_device->current_frequency = 0; + apic_timer_device->priority = 2; + return DRIVER_OK; } -DriverResult apic_timer_init(Device *device) { +DriverResult apic_timer_init(void *device) { lapic_write(APIC_TIMER_DCR, APIC_TIMER_DCR_DIVIDE_BY_1); lapic_write( APIC_LVT_TIMER, APIC_LVT_TIMER_MODE_PERIODIC | (0x20 + LAPIC_TIMER_IRQ)); + apic_timer_calibrate(device); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult apic_start(Device *device) { +DriverResult apic_start(void *device) { enable_apic(); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult apic_timer_start(Device *device) { - register_device_irq(apic_timer_device.irq); - interrupt_enable_irq(apic_timer_device.irq->irq); +DriverResult apic_timer_start(void *device) { + register_device_irq( + &apic_info.device_irq, apic_device, device, LAPIC_TIMER_IRQ, + apic_timer_irq_handler, IRQ_MODE_EXCLUSIVE); + enable_device_irq(apic_info.device_irq); uint32_t data = lapic_read(APIC_LVT_TIMER); lapic_write(APIC_LVT_TIMER, BIN_DIS(data, BIT(16))); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult apic_stop(Device *device) { +DriverResult apic_stop(void *device) { disable_apic(); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult apic_timer_stop(Device *device) { +DriverResult apic_timer_stop(void *device) { uint32_t data = lapic_read(APIC_LVT_TIMER); lapic_write(APIC_LVT_TIMER, BIN_EN(data, BIT(16))); - return DRIVER_RESULT_OK; + unregister_device_irq(apic_info.device_irq); + apic_info.device_irq = NULL; + return DRIVER_OK; } int apic_redirect_irq(InterruptDevice *device, int irq) { @@ -381,13 +349,13 @@ int apic_redirect_irq(InterruptDevice *device, int irq) { DriverResult apic_enable_irq(InterruptDevice *device, int irq) { io_apic_write(IOAPIC_TBL + irq * 2, BIN_DIS(0x20 + irq, BIT(16))); io_apic_write(IOAPIC_TBL + irq * 2 + 1, 0); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult apic_disable_irq(InterruptDevice *device, int irq) { io_apic_write(IOAPIC_TBL + irq * 2, BIN_EN(0x20 + irq, BIT(16))); io_apic_write(IOAPIC_TBL + irq * 2 + 1, 0); - return DRIVER_RESULT_OK; + return DRIVER_OK; } void apic_eoi(InterruptDevice *device, int irq) { @@ -396,11 +364,12 @@ void apic_eoi(InterruptDevice *device, int irq) { TimerResult apic_timer_set_frequency( TimerDevice *timer_device, uint32_t frequency) { - uint32_t divisor = apic_timer_timer_device.source_frequency / frequency; + uint32_t divisor = + DIV_ROUND_UP(apic_timer_device->source_frequency, frequency); lapic_write(APIC_TIMER_ICT, divisor); return TIMER_RESULT_OK; } -void apic_timer_irq_handler(Device *device) { +void apic_timer_irq_handler(void *device) { timer_irq_handler(device); } diff --git a/src/arch/x86/drivers/msr.c b/src/arch/x86/drivers/msr.c index 13af639..b0c7113 100644 --- a/src/arch/x86/drivers/msr.c +++ b/src/arch/x86/drivers/msr.c @@ -7,28 +7,16 @@ */ #include -// char cpuHasMSR(void) -// { -// uint32_t a, d; // eax, edx -// cpuid(1, &a, &d); -// return d & 0x20; -// } - -void cpu_RDMSR(uint32_t msr, uint32_t *lo, uint32_t *hi) -{ - uint32_t l, h; - __asm__ __volatile__("rdmsr \n\t" - : "=a"(l), "=d"(h) - : "c"(msr) - : "memory"); - *lo = l; - *hi = h; +void cpu_RDMSR(uint32_t msr, uint32_t *lo, uint32_t *hi) { + uint32_t l, h; + __asm__ __volatile__("rdmsr \n\t" : "=a"(l), "=d"(h) : "c"(msr) : "memory"); + *lo = l; + *hi = h; } -void cpu_WRMSR(uint32_t msr, uint32_t lo, uint32_t hi) -{ - __asm__ __volatile__("wrmsr \n\t" - : - : "a"(lo), "d"(hi), "c"(msr) - : "memory"); +void cpu_WRMSR(uint32_t msr, uint32_t lo, uint32_t hi) { + __asm__ __volatile__("wrmsr \n\t" + : + : "a"(lo), "d"(hi), "c"(msr) + : "memory"); } \ No newline at end of file diff --git a/src/arch/x86/drivers/network/rtl8139/rtl8139.c b/src/arch/x86/drivers/network/rtl8139/rtl8139.c index 8e71e8f..544a254 100644 --- a/src/arch/x86/drivers/network/rtl8139/rtl8139.c +++ b/src/arch/x86/drivers/network/rtl8139/rtl8139.c @@ -1,13 +1,13 @@ #include "rtl8139.h" #include -#include +#include #include #include #include #include #include #include -#include +#include #include #include #include @@ -28,70 +28,44 @@ #include #include -DriverResult rtl8139_init(Device *device); -DriverResult rtl8139_start(Device *device); -DriverResult rtl8139_pci_probe(PciDevice *pci_device); +DriverResult rtl8139_init(void *device); +DriverResult rtl8139_start(void *device); +DriverResult rtl8139_pci_probe( + PciDevice *pci_device, PhysicalDevice *physical_device); TransferResult rtl8139_send(NetworkDevice *device, void *buf, int length); -DeviceDriverOps rtl8139_device_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, -}; PciDriverOps rtl8139_pci_driver_ops = { .probe = rtl8139_pci_probe, }; -DeviceOps rtl8139_device_ops = { +DeviceOps rtl8139_physical_device_ops = { + .init = NULL, + .start = NULL, + .destroy = NULL, + .stop = NULL, +}; +DeviceOps rtl8139_logical_device_ops = { .init = rtl8139_init, .start = rtl8139_start, .destroy = NULL, - .status = NULL, .stop = NULL, }; -NetworkDeviceOps rtl8139_net_device_ops = { +NetworkOps rtl8139_net_device_ops = { .send = rtl8139_send, }; -DriverDependency rtl8139_dependencies[] = { - { - .in_type = DRIVER_DEPENDENCY_TYPE_BUS, - .dependency_in_bus = {BUS_TYPE_PCI, 0}, - .out_bus = NULL, - }, -}; -Driver rtl8139_driver = { - .short_name = STRING_INIT("HorizonRtl8139Driver"), - .dependency_count = sizeof(rtl8139_dependencies) / sizeof(DriverDependency), - .dependencies = rtl8139_dependencies, -}; -DeviceDriver rtl8139_device_driver = { - .name = STRING_INIT("RTL8139"), - .type = DEVICE_TYPE_ETHERNET, - .priority = DRIVER_PRIORITY_BASIC, - .ops = &rtl8139_device_driver_ops, -}; -PciDriver rtl8139_pci_driver = { - .driver = &rtl8139_driver, - .device_driver = &rtl8139_device_driver, - .find_type = FIND_BY_VENDORID_DEVICEID, - .vendor_device = {RTL8139_VENDOR_ID, RTL8139_DEVICE_ID}, - .ops = &rtl8139_pci_driver_ops, -}; -const Device rtl8139_device_template = { - .name = STRING_INIT("RTL8139"), - .device_driver = &rtl8139_device_driver, - .ops = &rtl8139_device_ops, - .private_data_size = sizeof(Rtl8139Device), -}; -const NetworkDevice rtl8139_network_device_template = { - .head_size = 0, - .tail_size = 0, - .type = NETWORK_TYPE_ETHERNET, - .ops = &rtl8139_net_device_ops, - .mtu = ETH_MTU, +Driver rtl8139_driver; +DeviceDriver rtl8139_device_driver; +PciDriver rtl8139_pci_driver = { + .driver = &rtl8139_driver, + .device_driver = &rtl8139_device_driver, + .find_type = FIND_BY_VENDORID_DEVICEID, + .vendor_device = {RTL8139_VENDOR_ID, RTL8139_DEVICE_ID}, + .ops = &rtl8139_pci_driver_ops, }; +NetworkDeviceCapabilities rtl8139_caps = {}; -void rtl8139_handler(Device *device) { - Rtl8139Device *rtl_device = device->private_data; +void rtl8139_handler(void *_device) { + Rtl8139Device *rtl_device = _device; spin_lock(&rtl_device->lock); int status = io_in_word(rtl_device->io_base + REG_ISR); @@ -124,11 +98,11 @@ void rtl8139_handler(Device *device) { _status |= IMR_FOVW; } if (status & IMR_PUN_LINKCHG) { - print_device_info(device, "Link Changed"); + print_warning("RTL8139", "Link Changed"); _status |= IMR_PUN_LINKCHG; } if (status & IMR_LEN_CHG) { - print_device_info(device, "Length Changed"); + print_warning("RTL8139", "Length Changed"); _status |= IMR_LEN_CHG; } if (status & IMR_TIMEOUT) { @@ -233,7 +207,8 @@ TransferResult rtl8139_send(NetworkDevice *device, void *buf, int length) { return TRANSFER_OK; } -DriverResult rtl8139_init(Device *device) { +DriverResult rtl8139_init(void *_device) { + LogicalDevice *device = _device; Rtl8139Device *rtl_device = device->private_data; rtl_device->io_base = rtl_device->pci_device->common.bar[0].base_addr; rtl_device->io_len = rtl_device->pci_device->common.bar[0].length; @@ -246,7 +221,10 @@ DriverResult rtl8139_init(Device *device) { timer_init(&rtl_device->timer); SPINLOCK_INIT(rtl_device->lock); - return DRIVER_RESULT_OK; + NetworkDevice *net = device->dm_ext; + net->mtu = ETH_MTU; + + return DRIVER_OK; } void rtl8139_reset(Rtl8139Device *device) { @@ -259,7 +237,8 @@ void rtl8139_reset(Rtl8139Device *device) { } } -DriverResult rtl8139_start(Device *device) { +DriverResult rtl8139_start(void *_device) { + LogicalDevice *device = _device; Rtl8139Device *rtl_device = device->private_data; pci_enable_bus_mastering(rtl_device->pci_device); @@ -285,8 +264,8 @@ DriverResult rtl8139_start(Device *device) { } NetworkDevice *net_device = device->dm_ext; eth_set_mac_address(net_device->ethernet, mac_addr); - print_device_info( - device, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac_addr[0], + print_info( + "RTL8139", "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); net_init_mii(&rtl_device->mii); @@ -327,22 +306,21 @@ DriverResult rtl8139_start(Device *device) { IMR_ROK | IMR_RER | IMR_TOK | IMR_TER | IMR_RXOVW | IMR_PUN_LINKCHG | IMR_FOVW | IMR_LEN_CHG | IMR_TIMEOUT | IMR_SERR); - device->irq = kmalloc(sizeof(DeviceIrq)); - device->irq->device = device; - device->irq->irq = rtl_device->pci_device->irqline; - device->irq->handler = rtl8139_handler; + register_device_irq( + &rtl_device->irq, device->physical_device, rtl_device, + rtl_device->pci_device->irqline, rtl8139_handler, IRQ_MODE_SHARED); rtl_device->net_rx.handler = rtl8139_net_rx_handler; rtl_device->net_rx.data = rtl_device; network_softirq_register(&rtl_device->net_rx); - register_device_irq(device->irq); - interrupt_enable_irq(rtl_device->pci_device->irqline); + enable_device_irq(rtl_device->irq); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult rtl8139_pci_probe(PciDevice *pci_device) { +DriverResult rtl8139_pci_probe( + PciDevice *pci_device, PhysicalDevice *physical_device) { uint32_t io_base = pci_device->common.bar[0].base_addr; uint32_t data = io_in_dword(io_base + RTL8139_TCR); Rtl8139Chipset chipset = RTL_UNKNOWN; @@ -354,21 +332,28 @@ DriverResult rtl8139_pci_probe(PciDevice *pci_device) { break; } } - if (chipset == RTL_UNKNOWN) { return DRIVER_RESULT_UNSUPPORT_DEVICE; } - - Device *device = kmalloc_from_template(rtl8139_device_template); - NetworkDevice *network_device = - kmalloc_from_template(rtl8139_network_device_template); - ObjectAttr attr = device_object_attr; - device->bus = pci_device->bus; - register_network_device( - &rtl8139_device_driver, device, network_device, &attr); + if (chipset == RTL_UNKNOWN) { return DRIVER_ERROR_UNSUPPORT_DEVICE; } - Rtl8139Device *rtl_device = device->private_data; + Rtl8139Device *rtl_device = kmalloc(sizeof(Rtl8139Device)); rtl_device->pci_device = pci_device; rtl_device->chipset = chipset; - return DRIVER_RESULT_OK; + DriverResult result; + NetworkDevice *network_device; + result = create_network_device( + &network_device, NETWORK_TYPE_ETHERNET, rtl8139_caps, + &rtl8139_net_device_ops, &rtl8139_logical_device_ops, physical_device, + &rtl8139_device_driver); + if (result != DRIVER_OK) { + kfree(rtl_device); + return result; + } + register_physical_device(physical_device, &rtl8139_physical_device_ops); + + rtl_device->net_device = network_device; + network_device->device->private_data = rtl_device; + + return DRIVER_OK; } static __init void rtl8139_initcall(void) { diff --git a/src/arch/x86/drivers/network/rtl8139/rtl8139.h b/src/arch/x86/drivers/network/rtl8139/rtl8139.h index ced4bcb..8e9b813 100644 --- a/src/arch/x86/drivers/network/rtl8139/rtl8139.h +++ b/src/arch/x86/drivers/network/rtl8139/rtl8139.h @@ -1,14 +1,14 @@ #ifndef _RTL8139_H #define _RTL8139_H -#include "driver/network/mii.h" -#include "driver/network/network.h" -#include "driver/network/network_dm.h" -#include "driver/timer_dm.h" -#include "drivers/bus/pci/pci.h" -#include "kernel/softirq.h" -#include "kernel/spinlock.h" +#include "kernel/driver_interface.h" #include +#include +#include +#include +#include +#include +#include #include #define RTL8139_VENDOR_ID 0x10ec @@ -138,6 +138,7 @@ typedef struct Rtl8139Device { Mii mii; spinlock_t lock; NetRxHandler net_rx; + DeviceIrq *irq; void *rx_buffer; size_t rx_buffer_phy; diff --git a/src/arch/x86/drivers/serial.c b/src/arch/x86/drivers/serial.c index dc3561b..4732b9f 100644 --- a/src/arch/x86/drivers/serial.c +++ b/src/arch/x86/drivers/serial.c @@ -1,7 +1,6 @@ -#include "drivers/serial.h" -#include "driver/interrupt_dm.h" -#include "driver/serial/serial_dm.h" -#include "string.h" +#include +#include +#include #include #include #include @@ -11,11 +10,12 @@ #include #include #include +#include extern Driver core_driver; -DriverResult serial_init(Device *device); -DriverResult serial_start(Device *device); +DriverResult serial_init(void *device); +DriverResult serial_start(void *device); DriverResult serial_self_test(SerialDevice *serial_device); void serial_set_baud_rate( SerialDevice *serial_device, SerialBaudRate baud_rate); @@ -26,30 +26,19 @@ void serial_set_recv_mode( void serial_console_backend_put_string( void *context, const char *string, int length); -DeviceDriverOps serial_device_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, -}; DeviceOps serial_device_ops = { .init = serial_init, .start = serial_start, .stop = NULL, .destroy = NULL, - .status = NULL, }; -SerialDeviceOps serial_serial_device_ops = { +SerialOps serial_serial_ops = { .self_test = serial_self_test, .set_baud_rate = serial_set_baud_rate, .set_recv_mode = serial_set_recv_mode, }; -DeviceDriver serial_device_driver = { - .name = STRING_INIT("Serial"), - .type = DEVICE_TYPE_SERIAL, - .priority = DRIVER_PRIORITY_BASIC, - .ops = &serial_device_driver_ops, - .state = DRIVER_STATE_UNREGISTERED, -}; +DeviceDriver serial_device_driver; const uint16_t serial_ports[] = { SERIAL_COM1_BASE, @@ -80,11 +69,12 @@ void serial_console_backend_put_string( } } -void serial_irq_handler(Device *device) { - SerialDevice *serial_device = device->dm_ext; - Serial *serial = device->private_data; - uint16_t base_port = serial->base_port; - uint8_t status = +void serial_irq_handler(void *arg) { + LogicalDevice *device = arg; + SerialDevice *serial_device = device->dm_ext; + Serial *serial = device->private_data; + uint16_t base_port = serial->base_port; + uint8_t status = io_in_byte(base_port + SERIAL_UART_REG_INTERRUPT_IDENTIFICATION); // 判断中断类型 @@ -140,12 +130,12 @@ DriverResult serial_self_test(SerialDevice *serial_device) { // 测试发送和接收 io_out_byte(base_port + SERIAL_UART_REG_DATA, 0x5A); if (io_in_byte(base_port + SERIAL_UART_REG_DATA) != 0x5A) - return DRIVER_RESULT_OTHER_ERROR; + return DRIVER_ERROR_OTHER; io_out_byte(base_port + SERIAL_UART_REG_MODEM_CONTROL, 0x0F); io_out_byte(base_port + SERIAL_UART_REG_INTERRUPT_ENABLE, val); - return DRIVER_RESULT_OK; + return DRIVER_OK; } void serial_set_baud_rate( @@ -194,9 +184,10 @@ void serial_set_recv_mode( } } -DriverResult serial_init(Device *device) { - Serial *serial = device->private_data; - uint16_t base_port = serial->base_port; +DriverResult serial_init(void *_device) { + LogicalDevice *device = _device; + Serial *serial = device->private_data; + uint16_t base_port = serial->base_port; // 禁用中断 io_out_byte(base_port + SERIAL_UART_REG_INTERRUPT_ENABLE, 0x00); @@ -207,55 +198,50 @@ DriverResult serial_init(Device *device) { // 设置 RTS 和 DSR io_out_byte(base_port + SERIAL_UART_REG_MODEM_CONTROL, 0x0B); - DeviceIrq *irq = kmalloc(sizeof(DeviceIrq)); - irq->device = device; - irq->irq = serial->irq; - irq->handler = serial_irq_handler; - device->irq = irq; - register_device_irq(irq); + register_device_irq( + &serial->irq, device->physical_device, serial->device, serial->irq_num, + serial_irq_handler, IRQ_MODE_SHARED); serial->console_backend.init = NULL; serial->console_backend.put_string = serial_console_backend_put_string; - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult serial_start(Device *device) { - Serial *serial = device->private_data; - uint16_t base_port = serial->base_port; +DriverResult serial_start(void *_device) { + LogicalDevice *device = _device; + Serial *serial = device->private_data; + uint16_t base_port = serial->base_port; // 启用接收中断 io_out_byte(base_port + SERIAL_UART_REG_INTERRUPT_ENABLE, 0x01); - interrupt_enable_irq(serial->irq); + enable_device_irq(serial->irq); console_register_backend(&serial->console_backend, serial); - return DRIVER_RESULT_OK; + return DRIVER_OK; } void register_serial() { - serial_device_driver.ops = &serial_device_driver_ops; register_device_driver(&core_driver, &serial_device_driver); + DriverResult result; + SerialDevice *serial_device; + LogicalDevice *logical_device; for (int i = 0; i < sizeof(serial_ports) / sizeof(serial_ports[0]); i++) { if (serial_probe(serial_ports[i])) { - SerialDevice *serial_device = kmalloc(sizeof(SerialDevice)); - Device *device = kmalloc(sizeof(Device)); - serial_device->device = device; - serial_device->ops = &serial_serial_device_ops; - device->name = name; - device->state = DEVICE_STATE_UNREGISTERED; - device->private_data_size = sizeof(Serial); - device->ops = &serial_device_ops; - device->max_child_device = 0; - - register_serial_device( - &serial_device_driver, device, &platform_bus, serial_device); - - Serial *serial = device->private_data; + result = create_serial_device( + &serial_device, &serial_serial_ops, &serial_device_ops, + platform_device, &serial_device_driver); + if (result != DRIVER_OK) continue; + + logical_device = serial_device->device; + Serial *serial = kmalloc(sizeof(Serial)); serial->base_port = serial_ports[i]; - serial->irq = serial_irqs[i]; - serial->device = device; + serial->irq_num = serial_irqs[i]; + serial->device = serial_device->device; + + logical_device->private_data = serial; } } } \ No newline at end of file diff --git a/src/arch/x86/drivers/sound/Makefile b/src/arch/x86/drivers/sound/Makefile index 71ee2c7..bc8b128 100644 --- a/src/arch/x86/drivers/sound/Makefile +++ b/src/arch/x86/drivers/sound/Makefile @@ -1,2 +1 @@ -SRC += sb16/ -SRC += sound.c \ No newline at end of file +SRC += sb16/ \ No newline at end of file diff --git a/src/arch/x86/drivers/sound/sb16/sb16.c b/src/arch/x86/drivers/sound/sb16/sb16.c index e6edaf4..caa6006 100644 --- a/src/arch/x86/drivers/sound/sb16/sb16.c +++ b/src/arch/x86/drivers/sound/sb16/sb16.c @@ -1,10 +1,9 @@ #include "sb16.h" -#include "driver/interrupt_dm.h" -#include "objects/object.h" #include +#include #include #include -#include +#include #include #include #include @@ -18,10 +17,14 @@ #include #include #include +#include #include #include -DriverResult sb16_init(struct Device *dev); +DriverResult sb16_init(void *_device); +DriverResult sb16_start(void *_device); +DriverResult sb16_stop(void *_device); +DriverResult sb16_destroy(void *_device); DriverResult sb16_probe(IsaDeviceDriver *isa_device_driver); DriverResult sb16_pcm_set_default_params(PcmStream *stream); @@ -40,21 +43,22 @@ DriverResult sb16_record_prepare( DriverResult sb16_record_trigger(PcmStream *stream, PcmTrigger trigger); size_t sb16_record_position(PcmStream *stream); -DeviceDriverOps sb16_device_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, -}; DeviceOps sb16_device_ops = { - .init = sb16_init, + .init = NULL, .start = NULL, .destroy = NULL, - .status = NULL, .stop = NULL, }; +DeviceOps sb16_logical_device_ops = { + .init = sb16_init, + .start = sb16_start, + .destroy = sb16_destroy, + .stop = sb16_stop, +}; IsaOps sb16_isa_ops = { .probe = sb16_probe, }; -SoundDeviceOps sb16_sound_device_ops = { +SoundOps sb16_sound_device_ops = { .set_volume = NULL, }; PcmOps sb16_pcm_ops = { @@ -82,42 +86,14 @@ PcmStreamOps sb16_pcm_record_ops = { .set_channel = sb16_pcm_set_channel, }; -DriverDependency sb_dependencies[] = { - { - .in_type = DRIVER_DEPENDENCY_TYPE_BUS, - .dependency_in_bus = {BUS_TYPE_ISA, 0}, - .out_bus = NULL, - }, -}; - -Driver sb_driver = { - .short_name = STRING_INIT("HorizonSoundBlasterDriver"), - .dependency_count = sizeof(sb_dependencies) / sizeof(DriverDependency), - .dependencies = sb_dependencies, -}; -DeviceDriver sb16_device_driver = { - .name = STRING_INIT("SoundBlaster16"), - .type = DEVICE_TYPE_SOUND, - .priority = DRIVER_PRIORITY_BASIC, - .ops = &sb16_device_driver_ops, -}; -const Device sb16_device_template = { - .name = STRING_INIT("sb16"), - .device_driver = &sb16_device_driver, - .ops = &sb16_device_ops, - .private_data_size = 0, -}; +Driver sb_driver; +DeviceDriver sb16_device_driver; const SoundDeviceCapabilities sb16_capabilities = { .record = 1, .play = 1, .set_volume = 1, .set_sample_rate = 1, }; -const SoundDevice sb16_sound_device_template = { - .capabilities = sb16_capabilities, - .ops = &sb16_sound_device_ops, - .type = SOUND_TYPE_PCM, -}; static const int sb16_possible_ports[] = {0x220, 0x240, 0x260, 0x280}; static const int sb16_possible_dmas[] = {5, 6, 7}; @@ -126,9 +102,9 @@ uint32_t data_len[DMA_MAX]; DriverResult sb16_write(Sb16Ports *ports, uint8_t value); -void sb16_irq_handler(Device *device) { - SoundDevice *sound_device = device->dm_ext; - Sb16Info *info = sound_device->private_data; +void sb16_irq_handler(void *arg) { + SoundDevice *sound_device = arg; + Sb16Info *info = sound_device->device->private_data; PcmDevice *pcm = sound_device->pcm; PcmStream *current_stream = pcm->current_stream; @@ -150,30 +126,30 @@ DriverResult sb16_reset(Sb16Ports *ports) { delay_ms(&timer, 1); for (int i = 0; i < 100000; i++) { if (io_in8(ports->read_status) & 0x80) { - if (io_in8(ports->read) == 0xaa) { return DRIVER_RESULT_OK; } + if (io_in8(ports->read) == 0xaa) { return DRIVER_OK; } } } - return DRIVER_RESULT_NOT_EXIST; + return DRIVER_ERROR_NOT_EXIST; } DriverResult sb16_write(Sb16Ports *ports, uint8_t value) { for (int i = 0; i < 100000; i++) { if ((io_in8(ports->write) & 0x80) == 0) { io_out8(ports->write, value); - return DRIVER_RESULT_OK; + return DRIVER_OK; } } - return DRIVER_RESULT_TIMEOUT; + return DRIVER_ERROR_TIMEOUT; } DriverResult sb16_read(Sb16Ports *ports, uint8_t *value) { for (int i = 0; i < 100000; i++) { if (io_in8(ports->iack16) & 0x80) { *value = io_in8(ports->read); - return DRIVER_RESULT_OK; + return DRIVER_OK; } } - return DRIVER_RESULT_TIMEOUT; + return DRIVER_ERROR_TIMEOUT; } DriverResult sb16_get_version( @@ -183,7 +159,7 @@ DriverResult sb16_get_version( DRIVER_RESULT_PASS(sb16_read(ports, major_version)); DRIVER_RESULT_PASS(sb16_read(ports, minor_version)); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sb16_check(int port, Sb16Info **info) { @@ -199,33 +175,43 @@ DriverResult sb16_check(int port, Sb16Info **info) { uint8_t major, minor; DRIVER_RESULT_PASS(sb16_reset(&ports)); DRIVER_RESULT_PASS(sb16_get_version(&ports, &major, &minor)); - print_driver_info( - sb_driver, "SB16 DSP found. version:%d.%d\n", major, minor); + print_info("SB16", "DSP found. version:%d.%d\n", major, minor); *info = kmalloc(sizeof(Sb16Info)); (*info)->ports = ports; (*info)->major_ver = major; (*info)->minor_ver = minor; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sb16_probe(IsaDeviceDriver *isa_device_driver) { + DriverResult result = DRIVER_ERROR_NOT_EXIST; + ObjectAttr attr = device_object_attr; + PhysicalDevice *phy; + SoundDevice *snd; + for (int i = 0; i < sizeof(sb16_possible_ports) / sizeof(int); i++) { Sb16Info *info = NULL; - if (sb16_check(sb16_possible_ports[i], &info) == DRIVER_RESULT_OK) { - Device *sb16_device = kmalloc_from_template(sb16_device_template); - SoundDevice *sb16_sound_device = - kmalloc_from_template(sb16_sound_device_template); - ObjectAttr attr = device_object_attr; - sb16_device->bus = isa_device_driver->bus; - sb16_device->private_data = info; - DRIVER_RESULT_PASS(register_sound_device( - &sb16_device_driver, sb16_device, sb16_sound_device, &attr)); - - PcmDevice *pcm = sound_register_pcm( - sb16_sound_device, &sb16_pcm_ops, 128 * 1024); - if (pcm == NULL) return DRIVER_RESULT_OUT_OF_MEMORY; + if (sb16_check(sb16_possible_ports[i], &info) == DRIVER_OK) { + result = + create_physical_device(&phy, isa_device_driver->bus, &attr); + if (result != DRIVER_OK) continue; + + result = create_sound_device( + &snd, SOUND_TYPE_PCM, sb16_capabilities, &sb16_sound_device_ops, + &sb16_logical_device_ops, phy, &sb16_device_driver); + if (result != DRIVER_OK) { + delete_physical_device(phy); + continue; + } + PcmDevice *pcm = sound_register_pcm(snd, &sb16_pcm_ops, 128 * 1024); + if (pcm == NULL) { + delete_sound_device(snd); + delete_physical_device(phy); + result = DRIVER_ERROR_OUT_OF_MEMORY; + continue; + } DRIVER_RESULT_PASS(pcm_register_stream( pcm, &pcm->play_stream, &sb16_pcm_play_ops, @@ -234,35 +220,61 @@ DriverResult sb16_probe(IsaDeviceDriver *isa_device_driver) { pcm, &pcm->record_stream, &sb16_pcm_record_ops, &info->stream_info[1])); DRIVER_RESULT_PASS(pcm_register_dma(pcm, NULL, NULL, &isa_dma_ops)); + + register_physical_device(phy, &sb16_device_ops); } } - return DRIVER_RESULT_OK; + return result; } -DriverResult sb16_init(struct Device *dev) { - Sb16Info *info = (Sb16Info *)dev->private_data; - DeviceIrq *irq = kmalloc(sizeof(DeviceIrq)); +DriverResult sb16_init(void *_device) { + LogicalDevice *device = _device; + Sb16Info *info = (Sb16Info *)device->private_data; + // io_out8(info->ports.mixer, 0x80 /* 设置IRQ */); // io_out8(info->ports.mixer_data, 0x02 /* IRQ5 */); - irq->irq = 5; - irq->device = dev; - irq->handler = sb16_irq_handler; - dev->irq = irq; - register_device_irq(dev->irq); - interrupt_enable_irq(irq->irq); + register_device_irq( + &info->irq, device->physical_device, device->dm_ext, 5, + sb16_irq_handler, IRQ_MODE_SHARED); spinlock_init(&info->lock); memset(data_len, 0, sizeof(data_len)); - return DRIVER_RESULT_OK; + return DRIVER_OK; +} + +DriverResult sb16_start(void *_device) { + LogicalDevice *device = _device; + Sb16Info *info = (Sb16Info *)device->private_data; + enable_device_irq(info->irq); + return DRIVER_OK; +} + +DriverResult sb16_stop(void *_device) { + LogicalDevice *device = _device; + Sb16Info *info = (Sb16Info *)device->private_data; + disable_device_irq(info->irq); + return DRIVER_OK; +} + +DriverResult sb16_destroy(void *_device) { + LogicalDevice *device = _device; + Sb16Info *info = (Sb16Info *)device->private_data; + if (info->irq != NULL) { + unregister_device_irq(info->irq); + info->irq = NULL; + } + int result = kfree(info); + if (result < 0) return DRIVER_ERROR_MEMORY_FREE; + return DRIVER_OK; } DriverResult sb16_set_sample_rate(Sb16Info *info, uint16_t sample_rate) { sb16_write(&info->ports, CMD_SET_OUTPUT_SAMPLE_RATE); sb16_write(&info->ports, (uint8_t)(sample_rate >> 8)); sb16_write(&info->ports, (uint8_t)sample_rate); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sb16_set_time_constant(Sb16Info *info, uint16_t sample_rate) { @@ -270,7 +282,7 @@ DriverResult sb16_set_time_constant(Sb16Info *info, uint16_t sample_rate) { sb16_write(&info->ports, CMD_SET_TIME_CONSTANT); sb16_write(&info->ports, (uint8_t)(time_constant >> 8)); sb16_write(&info->ports, (uint8_t)time_constant); - return DRIVER_RESULT_OK; + return DRIVER_OK; } void sb16_setup_dma( @@ -292,7 +304,7 @@ DriverResult sb16_set_volume(Sb16Info *info, int volume) { sb16_write(&info->ports, (uint8_t)(volume >> 8)); sb16_write(&info->ports, (uint8_t)volume); spin_unlock_irqrestore(&info->lock, flags); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sb16_pcm_set_default_params(PcmStream *stream) { @@ -307,7 +319,7 @@ DriverResult sb16_pcm_set_default_params(PcmStream *stream) { stream->frame_per_period = stream->period_bytes / stream->frame_bytes; stream->start_threshold = 4 * 1024; stream->stop_threshold = 1 * 1024; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sb16_pcm_set_data_type(PcmStream *stream, PcmDataType type) { @@ -317,13 +329,13 @@ DriverResult sb16_pcm_set_data_type(PcmStream *stream, PcmDataType type) { } else if (type == PCM_S16LE) { info->data_type |= BIT(SIGNED_BIT); } - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sb16_pcm_set_mode(PcmStream *stream, PcmMode mode) { if (mode == PCM_MODE_INTERLEAVED) stream->hw_mode = mode; - else return DRIVER_RESULT_UNSUPPORT_FEATURE; - return DRIVER_RESULT_OK; + else return DRIVER_ERROR_UNSUPPORT_FEATURE; + return DRIVER_OK; } DriverResult sb16_pcm_set_channel(PcmStream *stream, uint8_t channel) { @@ -333,11 +345,12 @@ DriverResult sb16_pcm_set_channel(PcmStream *stream, uint8_t channel) { } else if (channel == 2) { info->data_type |= BIT(STEREO_BIT); } - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sb16_pcm_set_sample_rate(PcmDevice *pcm, uint32_t sample_rate) { - return sb16_set_sample_rate(pcm->sound_device->private_data, sample_rate); + return sb16_set_sample_rate( + pcm->sound_device->device->private_data, sample_rate); } DriverResult sb16_play_open(SoundDevice *sound_device, PcmStream *stream) { @@ -346,7 +359,7 @@ DriverResult sb16_play_open(SoundDevice *sound_device, PcmStream *stream) { sound_device->device, (int *)sb16_possible_dmas, sizeof(sb16_possible_dmas) / sizeof(int)); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sb16_play_prepare(PcmStream *stream, void *addr, size_t size) { @@ -369,7 +382,7 @@ DriverResult sb16_play_prepare(PcmStream *stream, void *addr, size_t size) { sb16_write(&info->ports, CMD_STOP_PLAY16); spin_unlock_irqrestore(&info->lock, flags); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sb16_play_trigger(PcmStream *stream, PcmTrigger trigger) { @@ -384,9 +397,9 @@ DriverResult sb16_play_trigger(PcmStream *stream, PcmTrigger trigger) { sb16_write(&info->ports, CMD_STOP_PLAY16); break; case PCM_TRIGGER_NONE: - return DRIVER_RESULT_OTHER_ERROR; + return DRIVER_ERROR_OTHER; } - return DRIVER_RESULT_OK; + return DRIVER_OK; } size_t sb16_play_position(PcmStream *stream) { @@ -400,7 +413,7 @@ DriverResult sb16_record_open(SoundDevice *sound_device, PcmStream *stream) { sound_device->device, (int *)sb16_possible_dmas, sizeof(sb16_possible_dmas) / sizeof(int)); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sb16_record_prepare(PcmStream *stream, void *addr, size_t size) { @@ -423,7 +436,7 @@ DriverResult sb16_record_prepare(PcmStream *stream, void *addr, size_t size) { sb16_write(&info->ports, CMD_STOP_PLAY16); spin_unlock_irqrestore(&info->lock, flags); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sb16_record_trigger(PcmStream *stream, PcmTrigger trigger) { @@ -438,9 +451,9 @@ DriverResult sb16_record_trigger(PcmStream *stream, PcmTrigger trigger) { sb16_write(&info->ports, CMD_STOP_PLAY16); break; case PCM_TRIGGER_NONE: - return DRIVER_RESULT_OTHER_ERROR; + return DRIVER_ERROR_OTHER; } - return DRIVER_RESULT_OK; + return DRIVER_OK; } static void __init sb16_driver_entry(void) { diff --git a/src/arch/x86/drivers/sound/sb16/sb16.h b/src/arch/x86/drivers/sound/sb16/sb16.h index 64406e4..e452ba1 100644 --- a/src/arch/x86/drivers/sound/sb16/sb16.h +++ b/src/arch/x86/drivers/sound/sb16/sb16.h @@ -1,6 +1,7 @@ #ifndef _SB16_H #define _SB16_H +#include "kernel/driver_interface.h" #include "kernel/spinlock.h" #include "stdint.h" @@ -54,6 +55,8 @@ typedef struct Sb16Info { uint8_t dma_channel; spinlock_t lock; + DeviceIrq *irq; + struct Sb16StreamInfo { uint8_t data_type; } stream_info[2]; diff --git a/src/arch/x86/drivers/sound/sound.c b/src/arch/x86/drivers/sound/sound.c deleted file mode 100644 index e69de29..0000000 diff --git a/src/arch/x86/drivers/timer/pit.c b/src/arch/x86/drivers/timer/pit.c index 9539675..072b83e 100644 --- a/src/arch/x86/drivers/timer/pit.c +++ b/src/arch/x86/drivers/timer/pit.c @@ -4,89 +4,84 @@ * @brief PIT(Programmable Interval Timer)驱动 * @date 2022-07-31 */ -#include +#include +#include #include #include #include #include #include +#include #include #include +#include #include #include -#include - -// ---------new--------- -#include -#include -#include #include +#include #include #include +#include #define PIT_MAX_FREQUENCY 1193180 -DriverResult pit_init(Device *device); +DriverResult pit_init(void *device); TimerResult pit_set_frequency(TimerDevice *timer_device, uint32_t frequency); -DriverResult pit_start(Device *device); -DriverResult pit_stop(Device *device); -void pit_irq_handler(Device *device); +DriverResult pit_start(void *device); +DriverResult pit_stop(void *device); +void pit_irq_handler(void *device); extern Driver core_driver; -DeviceDriverOps pit_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, +DeviceOps i8254_device_ops = { + .init = NULL, + .destroy = NULL, + .start = NULL, + .stop = NULL, }; DeviceOps pit_device_ops = { .init = pit_init, .destroy = NULL, .start = pit_start, .stop = pit_stop, - .status = NULL, }; TimerOps pit_timer_ops = { + .one_shot = NULL, .set_frequency = pit_set_frequency, }; -DeviceIrq pit_irq = { - .device = &pit_device, - .irq = PIC_PIT_IRQ, - .handler = pit_irq_handler, -}; -DeviceDriver pit_device_driver = { - .name = STRING_INIT("PIT"), - .type = DEVICE_TYPE_TIMER, - .priority = DRIVER_PRIORITY_BASIC, - .state = DRIVER_STATE_UNREGISTERED, - .ops = &pit_driver_ops, -}; -Device pit_device = { - .name = STRING_INIT("PIT"), - .device_driver = &pit_device_driver, - .ops = &pit_device_ops, - .irq = &pit_irq, - .private_data_size = 0, -}; -TimerDevice pit_timer_device = { - .current_frequency = 0, - .min_frequency = PIT_MAX_FREQUENCY / (uint16_t)-1, - .max_frequency = PIT_MAX_FREQUENCY / 1, - .source_frequency = PIT_MAX_FREQUENCY, - .priority = 1, - - .timer_ops = &pit_timer_ops, -}; +DeviceDriver pit_device_driver; +PhysicalDevice *i8254_device; +TimerDevice *pit_timer_device; +DeviceIrq *pit_device_irq; -void register_pit() { +DriverResult register_pit() { register_device_driver(&core_driver, &pit_device_driver); - register_timer_device(&pit_device_driver, &pit_device, &pit_timer_device); + + ObjectAttr attr = device_object_attr; + DRIVER_RESULT_PASS( + create_physical_device(&i8254_device, platform_bus, &attr)); + + DRIVER_RESULT_PASS(create_timer_device( + &pit_timer_device, &pit_timer_ops, &pit_device_ops, i8254_device, + &pit_device_driver)); + + register_physical_device(i8254_device, &i8254_device_ops); + return DRIVER_OK; } -DriverResult pit_init(Device *device) { +DriverResult pit_init(void *device) { io_out_byte(PIT_CTRL, 0x34); - register_device_irq(pit_device.irq); - return DRIVER_RESULT_OK; + + pit_timer_device->current_frequency = 0; + pit_timer_device->min_frequency = PIT_MAX_FREQUENCY / (uint16_t)-1; + pit_timer_device->max_frequency = PIT_MAX_FREQUENCY / 1; + pit_timer_device->source_frequency = PIT_MAX_FREQUENCY; + pit_timer_device->priority = 1; + + return register_device_irq( + &pit_device_irq, i8254_device, pit_timer_device->device, PIC_PIT_IRQ, + pit_irq_handler, IRQ_MODE_EXCLUSIVE); } TimerResult pit_set_frequency(TimerDevice *timer_device, uint32_t frequency) { @@ -96,157 +91,16 @@ TimerResult pit_set_frequency(TimerDevice *timer_device, uint32_t frequency) { return TIMER_RESULT_OK; } -DriverResult pit_start(Device *device) { - DRV_RESULT_DELIVER_CALL(interrupt_enable_irq, device->irq->irq); - return DRIVER_RESULT_OK; +DriverResult pit_start(void *device) { + DRIVER_RESULT_PASS(enable_device_irq(pit_device_irq)); + return DRIVER_OK; } -DriverResult pit_stop(Device *device) { - DRV_RESULT_DELIVER_CALL(interrupt_disable_irq, device->irq->irq); - return DRIVER_RESULT_OK; +DriverResult pit_stop(void *device) { + DRIVER_RESULT_PASS(disable_device_irq(pit_device_irq)); + return DRIVER_OK; } -void pit_irq_handler(Device *device) { +void pit_irq_handler(void *device) { timer_irq_handler(device); } - -// ---------old--------- -// struct timerctl timerctl; - -// void init_timer(void) { -// int i; -// io_out8(PIT_CTRL, 0x34); -// io_out8(PIT_CNT0, 0x9c); -// io_out8(PIT_CNT0, 0x2e); - -// timerctl.count = 0; -// timerctl.next = 0xffffffff; // 没有定时器 -// timerctl.using = 0; -// for (i = 0; i <= MAX_TIMER; i++) { -// timerctl.timers0[i].flags = TIMER_FREE; // 释放所有计时器 -// } - -// if (use_apic) { -// put_irq_handler(APIC_PIT_IRQ, timer_handler); -// irq_enable(APIC_PIT_IRQ); -// } else { -// put_irq_handler(PIC_PIT_IRQ, timer_handler); -// irq_enable(PIC_PIT_IRQ); -// } -// return; -// } - -void timer_handler(int irq) { - // int i; - // struct timer *timer; - // timerctl.count++; - // if (use_apic) { - // struct task_s *cur_thread = get_current_thread(); - // cur_thread->elapsed_ticks++; - - // if (cur_thread->ticks == 0) { - // schedule(); - // } else { - // cur_thread->ticks--; - // } - // } - // if (timerctl.next > timerctl.count) { return; } - // timer = timerctl.timers[0]; - // for (i = 0; i < timerctl.using; i++) { - // if (timer->timeout > timerctl.count) { break; } - // timer->flags = TIMER_UNUSED; - // fifo_put(timer->fifo, timer->data); - // timer = timer->next; - // } - // timerctl.using -= i; - // timerctl.timers[0] = timer; - // if (timerctl.using > 0) { - // timerctl.next = timerctl.timers[0]->timeout; - // } else { - // timerctl.next = 0xffffffff; - // } - return; -} - -// struct timer *timer_alloc(void) { -// int i; -// for (i = 0; i < MAX_TIMER; i++) { -// if (timerctl.timers0[i].flags == 0) { -// timerctl.timers0[i].flags = TIMER_UNUSED; -// return &timerctl.timers0[i]; -// } -// } -// return 0; -// } - -// void timer_free(struct timer *timer) { -// if (timer->flags == TIMER_USING) { timerctl.using --; } -// timer->flags = TIMER_FREE; -// return; -// } - -// void timer_init(struct timer *timer, struct fifo *fifo, int data) { -// timer->fifo = fifo; -// timer->data = data; -// return; -// } - -// void timer_settime(struct timer *timer, unsigned int timeout) { -// int e; -// struct timer *t, *s; -// timer->timeout = timeout + timerctl.count; -// timer->flags = TIMER_USING; -// e = io_load_eflags(); -// io_cli(); -// timerctl.using ++; -// if (timerctl.using == 1) { -// timerctl.timers[0] = timer; -// timer->next = 0; -// timerctl.next = timer->timeout; -// io_store_eflags(e); -// return; -// } -// t = timerctl.timers[0]; -// if (timer->timeout <= t->timeout) { -// timerctl.timers[0] = timer; -// timer->next = t; -// timerctl.next = timer->timeout; -// io_store_eflags(e); -// return; -// } -// for (;;) { -// s = t; -// t = t->next; -// if (t == 0) { break; } -// if (timer->timeout <= t->timeout) { -// s->next = timer; -// timer->next = t; -// io_store_eflags(e); -// return; -// } -// } -// s->next = timer; -// timer->next = 0; -// io_store_eflags(e); -// return; -// } - -// /** -// * @brief 等待 -// * -// * @param time 时间(单位:10毫秒) -// */ -// void delay(int time) { -// struct timer *timer; -// struct fifo fifo; -// char buf[1]; -// timer = timer_alloc(); -// fifo_init(&fifo, 1, (int *)buf); -// timer_init(timer, &fifo, 0); -// timer_settime(timer, time); -// while (!fifo_status(&fifo)) -// ; -// fifo_get(&fifo); -// timer_free(timer); -// return; -// } diff --git a/src/arch/x86/drivers/usb/Makefile b/src/arch/x86/drivers/usb/Makefile index cacfec5..978216b 100644 --- a/src/arch/x86/drivers/usb/Makefile +++ b/src/arch/x86/drivers/usb/Makefile @@ -1 +1 @@ -SRC += hci/ \ No newline at end of file +SRC += hcd/ \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/hcd/Makefile b/src/arch/x86/drivers/usb/hcd/Makefile new file mode 100644 index 0000000..e027c57 --- /dev/null +++ b/src/arch/x86/drivers/usb/hcd/Makefile @@ -0,0 +1,2 @@ +SRC += hcd.c +SRC += uhci/ \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/hcd/hcd.c b/src/arch/x86/drivers/usb/hcd/hcd.c new file mode 100644 index 0000000..ad424b3 --- /dev/null +++ b/src/arch/x86/drivers/usb/hcd/hcd.c @@ -0,0 +1,12 @@ +#include +#include +#include + +Driver x86_usb_hcd_driver; + +static __init void usb_hcd_entry(void) { + register_driver(&x86_usb_hcd_driver); + return; +} + +driver_initcall(usb_hcd_entry); \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/hcd/hcd.h b/src/arch/x86/drivers/usb/hcd/hcd.h new file mode 100644 index 0000000..66ff01f --- /dev/null +++ b/src/arch/x86/drivers/usb/hcd/hcd.h @@ -0,0 +1,8 @@ +#ifndef _X86_HCD_H +#define _X86_HCD_H + +#include + +extern Driver x86_usb_hcd_driver; + +#endif \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/hcd/uhci/Makefile b/src/arch/x86/drivers/usb/hcd/uhci/Makefile new file mode 100644 index 0000000..eee8698 --- /dev/null +++ b/src/arch/x86/drivers/usb/hcd/uhci/Makefile @@ -0,0 +1,3 @@ +SRC += packet.c +SRC += skeleton.c +SRC += uhci.c \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/hci/uhci/packet.c b/src/arch/x86/drivers/usb/hcd/uhci/packet.c similarity index 97% rename from src/arch/x86/drivers/usb/hci/uhci/packet.c rename to src/arch/x86/drivers/usb/hcd/uhci/packet.c index cfa55ec..6c2f8ff 100644 --- a/src/arch/x86/drivers/usb/hci/uhci/packet.c +++ b/src/arch/x86/drivers/usb/hcd/uhci/packet.c @@ -1,18 +1,18 @@ -#include "driver/timer_dm.h" -#include "driver/usb/usb_dm.h" -#include "kernel/barrier.h" -#include "kernel/list.h" -#include "math.h" #include -#include -#include -#include +#include +#include +#include #include +#include +#include #include +#include #include #include +#include #include #include +#include #include #include @@ -25,7 +25,7 @@ void uhci_add_interrupt_transfer( struct UsbRequestBlock *urb); void uhci_interrupt_transfer(UsbHcd *hcd, UsbEndpoint *ep); -UsbHcdOps uhci_ops = { +UsbHcdOps uhci_hcd_ops = { .create_pipeline = uhci_create_pipeline, .ctrl_transfer_in = uhci_ctrl_transfer_in, .ctrl_transfer_out = uhci_ctrl_transfer_out, diff --git a/src/arch/x86/drivers/usb/hci/uhci/skeleton.c b/src/arch/x86/drivers/usb/hcd/uhci/skeleton.c similarity index 100% rename from src/arch/x86/drivers/usb/hci/uhci/skeleton.c rename to src/arch/x86/drivers/usb/hcd/uhci/skeleton.c diff --git a/src/arch/x86/drivers/usb/hci/uhci.c b/src/arch/x86/drivers/usb/hcd/uhci/uhci.c similarity index 72% rename from src/arch/x86/drivers/usb/hci/uhci.c rename to src/arch/x86/drivers/usb/hcd/uhci/uhci.c index 3b12024..0d5e677 100644 --- a/src/arch/x86/drivers/usb/hci/uhci.c +++ b/src/arch/x86/drivers/usb/hcd/uhci/uhci.c @@ -8,20 +8,17 @@ * 目前仅仅只是初始化了UHCI而已,其他涉及USB协议的东西都还没做 * */ -#include "driver/timer_dm.h" -#include "driver/usb/descriptors.h" -#include "kernel/driver_interface.h" -#include "kernel/list.h" -#include "kernel/softirq.h" -#include "kernel/thread.h" +#include "../hcd.h" #include -#include -#include -#include -#include +#include +#include #include -#include +#include +#include #include +#include +#include +#include #include #include #include @@ -29,11 +26,16 @@ #include #include #include +#include #include #include +#include #include #include #include +#include +#include +#include #include #include @@ -45,7 +47,7 @@ #define DEV_NAME "UHCI" #define DEV_FULL_NAME "Universal Host Controller Interface(UHCI)" -extern UsbHcdOps uhci_ops; +extern UsbHcdOps uhci_hcd_ops; uint32_t uhci_get_hub_status(UsbHub *hub); uint32_t uhci_get_port_status(UsbHub *hub, uint8_t port); @@ -54,24 +56,26 @@ UsbSetupStatus uhci_clear_port_feature( UsbSetupStatus uhci_set_port_feature( UsbHub *hub, uint8_t port, uint16_t feature); void uhci_register(Driver *driver); -DriverResult uhci_init(Device *device); -DriverResult uhci_start(Device *device); -DriverResult uhci_pci_probe(PciDevice *pci_device); -void uhci_port_reset(Uhci *uhci, int port); -void uhci_port_init(UsbHub *hub, UsbHcd *hcd, int port); - -DeviceDriverOps uhci_device_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, -}; +DriverResult uhci_init(void *_device); +DriverResult uhci_start(void *_device); +DriverResult uhci_pci_probe( + PciDevice *pci_device, PhysicalDevice *physical_device); +void uhci_port_reset(Uhci *uhci, int port); +void uhci_port_init(UsbHub *hub, UsbHcd *hcd, int port); + PciDriverOps uhci_pci_driver_ops = { .probe = uhci_pci_probe, }; +DeviceOps uhci_logical_device_ops = { + .init = NULL, + .start = NULL, + .destroy = NULL, + .stop = NULL, +}; DeviceOps uhci_device_ops = { .init = uhci_init, .start = uhci_start, .destroy = NULL, - .status = NULL, .stop = NULL, }; UsbHubOps uhci_root_hub_ops = { @@ -82,31 +86,17 @@ UsbHubOps uhci_root_hub_ops = { .get_port_status = uhci_get_port_status, }; -DeviceDriver uhci_device_driver = { - .name = STRING_INIT("uhci"), - .type = DEVICE_TYPE_BUS_CONTROLLER, - .priority = DRIVER_PRIORITY_BASIC, - .ops = &uhci_device_driver_ops, -}; -PciDriver uhci_pci_driver = { - .driver = &usb_driver, - .device_driver = &uhci_device_driver, - .find_type = FIND_BY_CLASSCODE_SUBCLASS_PROGIF, - .class_subclass_progif = {UHCI_CLASSID, UHCI_SUBCLASSID, UHCI_PROGIF}, - .ops = &uhci_pci_driver_ops, -}; -const Device uhci_device_template = { - .name = STRING_INIT("UHCI Controller"), - .device_driver = &uhci_device_driver, - .ops = &uhci_device_ops, - .private_data_size = sizeof(Uhci), -}; -HciInit uhci_hci_init = { - .init = uhci_register, +DeviceDriver uhci_device_driver; +PciDriver uhci_pci_driver = { + .driver = &usb_driver, + .device_driver = &uhci_device_driver, + .find_type = FIND_BY_CLASSCODE_SUBCLASS_PROGIF, + .class_subclass_progif = {UHCI_CLASSID, UHCI_SUBCLASSID, UHCI_PROGIF}, + .ops = &uhci_pci_driver_ops, }; -void uhci_handler(Device *device) { - Uhci *uhci = device->private_data; +void uhci_handler(void *arg) { + Uhci *uhci = arg; UhciQh *qhs = uhci->skel->qh, *qh; // 清除UHCI状态寄存器 @@ -283,8 +273,8 @@ void uhci_port_reset(Uhci *uhci, int port) { } void uhci_port_init(UsbHub *hub, UsbHcd *hcd, int port) { - Uhci *devext = (Uhci *)hcd->device->private_data; - uint32_t io_port = devext->io_base + UHCI_PORTSC1 + port * 2; + Uhci *uhci = (Uhci *)hcd->device->private_data; + uint32_t io_port = uhci->io_base + UHCI_PORTSC1 + port * 2; UsbHcdPort *hcd_port = &hcd->ports[port]; // 获取端口信息 @@ -296,20 +286,10 @@ void uhci_port_init(UsbHub *hub, UsbHcd *hcd, int port) { ? USB_SPEED_LOW : USB_SPEED_FULL; printk("[UHCI]port %d connected.\n", port); - UsbDevice *usb_device = usb_create_device(hcd, hub, speed, 0); - - uhci_port_reset(devext, port); - - UsbEndpoint *ep0 = kmalloc(sizeof(UsbEndpoint)); - struct UsbEndpointDescriptor *endpoint_desc = - kmalloc(sizeof(struct UsbEndpointDescriptor)); - endpoint_desc->bLength = sizeof(struct UsbEndpointDescriptor); - endpoint_desc->bDescriptorType = USB_DESC_TYPE_ENDPOINT; - endpoint_desc->bEndpointAddress = USB_EP_OUT << 7 | 0; // ep0 out - endpoint_desc->bmAttributes = USB_EP_CONTROL; - endpoint_desc->wMaxPacketSize = HOST2LE_WORD(64); - endpoint_desc->bInterval = 0; - usb_init_device(hcd, ep0, endpoint_desc, usb_device); + + uhci_port_reset(uhci, port); + + usb_probe_device(hcd, hub, speed); } // 输出端口信息 @@ -318,7 +298,6 @@ void uhci_port_init(UsbHub *hub, UsbHcd *hcd, int port) { hcd_port->enable = BIN_IS_EN(port_status, UHCI_PORT_SC_ENABLE); hcd_port->suspend = BIN_IS_EN(port_status, UHCI_PORT_SC_SUSPEND); - printk("[UHCI]port %d reset. status: %04x\n", port, port_status); printk( "[UHCI]suspend: %d, enable: %d, connected: %d,", hcd_port->suspend, hcd_port->enable, hcd_port->connected); @@ -328,8 +307,9 @@ void uhci_port_init(UsbHub *hub, UsbHcd *hcd, int port) { : "FullSpeed"); } -DriverResult uhci_init(Device *device) { - Uhci *uhci = device->private_data; +DriverResult uhci_init(void *_device) { + PhysicalDevice *device = _device; + Uhci *uhci = device->private_data; timer_init(&uhci->timer); uhci_reset(uhci); @@ -337,7 +317,7 @@ DriverResult uhci_init(Device *device) { intr |= UHCI_INTR_SPI | UHCI_INTR_IOC | UHCI_INTR_RESUME | UHCI_INTR_CRC; io_out_word(uhci->io_base + UHCI_REG_USBINTR, intr); - return DRIVER_RESULT_OK; + return DRIVER_OK; } void uhci_probe_thread(void *arg) { @@ -345,6 +325,7 @@ void uhci_probe_thread(void *arg) { UsbHub *hub = kmalloc(sizeof(UsbHub)); hub->usb_device = NULL; + hub->hcd = uhci->hcd; hub->ops = &uhci_root_hub_ops; struct UsbHubDescriptor *desc = kmalloc(sizeof(struct UsbHubDescriptor)); @@ -353,8 +334,8 @@ void uhci_probe_thread(void *arg) { desc->bDescriptorType = USB_DESC_TYPE_HUB; desc->bNbrPorts = uhci->port_cnt; desc->wHubCharacteristics = HOST2LE_WORD(0x0009); // 无电源开关,单独供电 - desc->bPwrOn2PwrGood = 0; - desc->bHubContrCurrent = 0; + desc->bPwrOn2PwrGood = 0; + desc->bHubContrCurrent = 0; memset(&desc->DeviceRemovable, 0xff, 8); // 都是可移除的 memset(&desc->PortPwrCtrlMask, 0xff, 8); // 都是电源控制的 @@ -363,17 +344,17 @@ void uhci_probe_thread(void *arg) { } } -void uhci_probe(Device *device) { +void uhci_probe(Uhci *uhci) { // 通过独立线程初始化,避免usb初始化长时间的等待导致系统阻塞 thread_start( - "UHCI Probe", THREAD_DEFAULT_PRIO, uhci_probe_thread, - device->private_data, NULL); + "UHCI Probe", THREAD_DEFAULT_PRIO, uhci_probe_thread, uhci, NULL); } -DriverResult uhci_start(Device *device) { - Uhci *uhci = device->private_data; - uhci->fl.frames_vir = (uint32_t *)kernel_alloc_pages(1); - uhci->fl.frames_phy = (uint32_t *)vir2phy((uint32_t)uhci->fl.frames_vir); +DriverResult uhci_start(void *_device) { + PhysicalDevice *device = _device; + Uhci *uhci = device->private_data; + uhci->fl.frames_vir = (uint32_t *)kernel_alloc_pages(1); + uhci->fl.frames_phy = (uint32_t *)vir2phy((uint32_t)uhci->fl.frames_vir); uhci_skel_init(uhci); pci_device_write16(uhci->device, UHCI_PCI_REG_LEGSUP, 0x2000); @@ -385,24 +366,22 @@ DriverResult uhci_start(Device *device) { uint16_t cmd = io_in_word(uhci->io_base + UHCI_REG_CMD); io_out_word(uhci->io_base + UHCI_REG_CMD, cmd | UHCI_CMD_RUN); - uhci_probe(device); + uhci_probe(uhci); + + register_device_irq( + &uhci->irq, device, uhci, uhci->device->irqline, uhci_handler, + IRQ_MODE_SHARED); - device->irq = kmalloc(sizeof(DeviceIrq)); - device->irq->device = device; - device->irq->irq = uhci->device->irqline; - device->irq->handler = uhci_handler; - register_device_irq(device->irq); - interrupt_enable_irq(device->irq->irq); + enable_device_irq(uhci->irq); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult uhci_pci_probe(PciDevice *pci_device) { +DriverResult uhci_pci_probe( + PciDevice *pci_device, PhysicalDevice *physical_device) { uint32_t io_base = pci_device->common.bar[4].base_addr & 0xfffffff0; - if (io_base == 0) { return DRIVER_RESULT_UNSUPPORT_DEVICE; } + if (io_base == 0) { return DRIVER_ERROR_UNSUPPORT_DEVICE; } - Device *device = kmalloc_from_template(uhci_device_template); - device->bus = pci_device->bus; uint8_t port_cnt = (pci_device->common.bar[4].length - UHCI_PORTSC1) / 2; uint16_t status; @@ -414,26 +393,33 @@ DriverResult uhci_pci_probe(PciDevice *pci_device) { } } - UsbHcd *hcd = usb_hcd_register( - &uhci_device_driver, device, DEV_NAME, sizeof(DEV_NAME), port_cnt, - &uhci_ops); + DriverResult result; - Uhci *uhci = device->private_data; + Uhci *uhci = kmalloc(sizeof(Uhci)); uhci->device = pci_device; uhci->io_base = io_base; uhci->port_cnt = port_cnt; - uhci->hcd = hcd; - return DRIVER_RESULT_OK; -} + result = usb_create_hcd( + &uhci->hcd, port_cnt, &uhci_hcd_ops, &uhci_logical_device_ops, + physical_device, &uhci_device_driver); + if (result != DRIVER_OK) { + kfree(uhci); + return result; + } + + LogicalDevice *logical_device = uhci->hcd->device; + logical_device->private_data = uhci; + physical_device->private_data = uhci; + + register_physical_device(physical_device, &uhci_device_ops); -void uhci_register(Driver *driver) { - register_device_driver(driver, &uhci_device_driver); - pci_register_driver(driver, &uhci_pci_driver); + return DRIVER_OK; } static __init void uhci_driver_entry(void) { - list_add_tail(&uhci_hci_init.list, &hci_lh); + register_device_driver(&x86_usb_hcd_driver, &uhci_device_driver); + pci_register_driver(&x86_usb_hcd_driver, &uhci_pci_driver); } driver_initcall(uhci_driver_entry); \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/hci/Makefile b/src/arch/x86/drivers/usb/hci/Makefile deleted file mode 100644 index 01d0702..0000000 --- a/src/arch/x86/drivers/usb/hci/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -SRC += uhci/ -SRC += uhci.c \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/hci/hci.c b/src/arch/x86/drivers/usb/hci/hci.c deleted file mode 100644 index e69de29..0000000 diff --git a/src/arch/x86/drivers/usb/hci/uhci/Makefile b/src/arch/x86/drivers/usb/hci/uhci/Makefile deleted file mode 100644 index 85f66dc..0000000 --- a/src/arch/x86/drivers/usb/hci/uhci/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -SRC += packet.c -SRC += skeleton.c \ No newline at end of file diff --git a/src/arch/x86/include/drivers/8259a.h b/src/arch/x86/include/drivers/8259a.h index d2f9a59..45a5418 100644 --- a/src/arch/x86/include/drivers/8259a.h +++ b/src/arch/x86/include/drivers/8259a.h @@ -1,6 +1,8 @@ #ifndef _8259A_H #define _8259A_H +#include + #define PIC0_ICW1 0x20 #define PIC0_OCW1 0x20 #define PIC0_IMR 0x21 @@ -16,9 +18,9 @@ #define PIC_EOI 0x20 -extern struct Device pic_device; +extern struct PhysicalDevice *i8259a_device; -void mask_8259a(void); -void register_pic(void); +void mask_8259a(void); +DriverResult register_pic(void); #endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/apic.h b/src/arch/x86/include/drivers/apic.h index 99cbaf3..1ecc925 100644 --- a/src/arch/x86/include/drivers/apic.h +++ b/src/arch/x86/include/drivers/apic.h @@ -1,7 +1,8 @@ #ifndef APIC_H #define APIC_H -#include "kernel/driver.h" +#include +#include #define APIC_ID 0x20 #define APIC_Ver 0x30 @@ -90,8 +91,10 @@ #define LAPIC_TIMER_IRQ 0 -extern struct Device apic_timer_device; +extern struct PhysicalDevice *apic_device; +extern struct TimerDevice *apic_timer_device; +extern bool use_apic; -void register_apic(void); +DriverResult register_apic(void); #endif diff --git a/src/arch/x86/include/drivers/bus/isa/dma.h b/src/arch/x86/include/drivers/bus/isa/dma.h index c578252..323e883 100644 --- a/src/arch/x86/include/drivers/bus/isa/dma.h +++ b/src/arch/x86/include/drivers/bus/isa/dma.h @@ -1,6 +1,7 @@ #ifndef _ISA_DMA_H #define _ISA_DMA_H +#include "kernel/device.h" #include "stdint.h" #define DMA0 0x00 @@ -76,9 +77,8 @@ void dma_init(); void *dma_alloc_region(Dma *dma, uint32_t size); DriverResult dma_free_region(Dma *dma, void *ptr, uint32_t size); -struct Device; -int dma_channel_use(struct Device *device, int *possible_ch, int len); -void dma_channel_unuse(struct Device *device, uint8_t channel); +int dma_channel_use(struct LogicalDevice *device, int *possible_ch, int len); +void dma_channel_unuse(struct LogicalDevice *device, uint8_t channel); int dma_lock(); void dma_unlock(int flags); diff --git a/src/arch/x86/include/drivers/bus/pci/pci.h b/src/arch/x86/include/drivers/bus/pci/pci.h index ceff410..9688b51 100644 --- a/src/arch/x86/include/drivers/bus/pci/pci.h +++ b/src/arch/x86/include/drivers/bus/pci/pci.h @@ -1,6 +1,7 @@ #ifndef _PCI_H #define _PCI_H +#include "kernel/device.h" #include "kernel/driver_interface.h" #include "stdint.h" @@ -95,8 +96,8 @@ typedef struct PciDeviceBar { } PciDeviceBar; typedef struct PciDevice { - Bus *bus; - Device *device; + Bus *bus; + PhysicalDevice *device; struct PciDriver *pci_driver; @@ -183,8 +184,8 @@ typedef struct PciDevice { } PciDevice; typedef struct PciDriverOps { - - DriverResult (*probe)(struct PciDevice *pci_device); + DriverResult (*probe)( + struct PciDevice *pci_device, PhysicalDevice *physical_device); } PciDriverOps; typedef struct PciDriver { diff --git a/src/arch/x86/include/drivers/cmos.h b/src/arch/x86/include/drivers/cmos.h index e6d8b1a..6ef4407 100644 --- a/src/arch/x86/include/drivers/cmos.h +++ b/src/arch/x86/include/drivers/cmos.h @@ -1,6 +1,9 @@ #ifndef _CMOS_H #define _CMOS_H +#include +#include +#include #include #define CMOS_REGS 0x70 @@ -29,8 +32,9 @@ #define BCD2BIN(bcd) ((bcd >> 4) * 10 + (bcd & 0x0f)) #define BIN2BCD(bin) (((bin / 10) << 4) + (bin % 10)) -extern struct Device rtc_device; +extern PhysicalDevice *cmos_device; +extern TimeDevice *rtc_time_device; -void register_cmos(void); +DriverResult register_cmos(void); #endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/pit.h b/src/arch/x86/include/drivers/pit.h index b199335..751c0d6 100644 --- a/src/arch/x86/include/drivers/pit.h +++ b/src/arch/x86/include/drivers/pit.h @@ -1,6 +1,7 @@ #ifndef _PIT_H #define _PIT_H +#include "kernel/driver.h" #define PIT_CTRL 0x43 #define PIT_CNT0 0x40 @@ -13,30 +14,8 @@ #define TIMER_UNUSED 1 #define TIMER_USING 2 -struct timer { - struct timer *next; - unsigned int timeout, flags; - struct fifo *fifo; - int data; -}; - -struct timerctl { - unsigned int count, next, using; - struct timer *timers[MAX_TIMER]; - struct timer timers0[MAX_TIMER]; -}; - -// extern struct timerctl timerctl; - -// void init_timer(void); -// void timer_handler(int irq); -// struct timer *timer_alloc(void); -// void timer_free(struct timer *timer); -// void timer_init(struct timer *timer, struct fifo *fifo, int data); -// void timer_settime(struct timer *timer, unsigned int timeout); -// void delay(int time); - -void register_pit(); -extern struct Device pit_device; +DriverResult register_pit(); +extern struct PhysicalDevice *i8254_device; +extern struct TimerDevice *pit_timer_device; #endif \ No newline at end of file diff --git a/src/arch/x86/include/drivers/serial.h b/src/arch/x86/include/drivers/serial.h index 80ba866..4447bc2 100644 --- a/src/arch/x86/include/drivers/serial.h +++ b/src/arch/x86/include/drivers/serial.h @@ -1,6 +1,7 @@ #ifndef _SERIAL_H #define _SERIAL_H +#include "kernel/driver_interface.h" #include #include #include @@ -42,9 +43,10 @@ #define SERIAL_TEST_MAGIC_2 0xAA typedef struct { - Device *device; - uint16_t base_port; - uint8_t irq; + LogicalDevice *device; + uint16_t base_port; + uint8_t irq_num; + DeviceIrq *irq; ConsoleBackend console_backend; } Serial; diff --git a/src/arch/x86/include/drivers/usb/uhci.h b/src/arch/x86/include/drivers/usb/uhci.h index 8427a89..2fd8faf 100644 --- a/src/arch/x86/include/drivers/usb/uhci.h +++ b/src/arch/x86/include/drivers/usb/uhci.h @@ -1,14 +1,15 @@ #ifndef _UHCI_H #define _UHCI_H -#include "driver/usb/urb.h" -#include "kernel/list.h" #include -#include -#include -#include -#include +#include #include +#include +#include +#include +#include +#include +#include #include #define FRAMELIST_SIZE 1024 @@ -160,6 +161,8 @@ typedef struct { UhciSkel *skel; UsbHcd *hcd; + + DeviceIrq *irq; } Uhci; typedef enum UhciSkelType { diff --git a/src/arch/x86/include/drivers/vesa_display.h b/src/arch/x86/include/drivers/vesa_display.h index 0b12c3b..41d336e 100644 --- a/src/arch/x86/include/drivers/vesa_display.h +++ b/src/arch/x86/include/drivers/vesa_display.h @@ -1,6 +1,7 @@ #ifndef _VESA_DISPLAY_H #define _VESA_DISPLAY_H +#include "kernel/driver.h" struct VbeModeInfoBlock { unsigned char VbeSignature[4]; unsigned short VbeVersion; @@ -38,7 +39,8 @@ struct VesaDisplayInfo { struct VbeControlInfoBlock *vbe_conrtol_info; }; -extern struct Device vesa_display_device; -void register_vesa_display(void); +extern struct LogicalDevice vesa_display_device; + +DriverResult register_vesa_display(void); #endif \ No newline at end of file diff --git a/src/arch/x86/include/kernel/descriptor.h b/src/arch/x86/include/kernel/descriptor.h index 84606eb..4d06c14 100644 --- a/src/arch/x86/include/kernel/descriptor.h +++ b/src/arch/x86/include/kernel/descriptor.h @@ -74,6 +74,5 @@ void set_segment_descriptor( struct segment_descriptor *sd, unsigned int limit, int base, int ar); void set_gate_descriptor( struct gate_descriptor *gd, int offset, int selector, int ar); -void irq_enable(int irq); #endif \ No newline at end of file diff --git a/src/arch/x86/kernel/descriptor.c b/src/arch/x86/kernel/descriptor.c index c8cd5c6..4062cdd 100644 --- a/src/arch/x86/kernel/descriptor.c +++ b/src/arch/x86/kernel/descriptor.c @@ -5,18 +5,18 @@ * @version 1.2 * @date 2022-07-31 */ -#include "kernel/driver_interface.h" -#include "kernel/thread.h" -#include +#include #include #include #include #include #include #include +#include #include #include #include +#include #include #include @@ -332,7 +332,9 @@ void exception_handler( } else { printk(COLOR_RED " TI: selector in gdt.\n"); } - printk(COLOR_RED " Selector: idx %d\n", (error_code & 0xfff8) >> 3); + printk( + COLOR_RED " Selector: idx %d\n" COLOR_RESET, + (error_code & 0xfff8) >> 3); } io_hlt(); @@ -348,11 +350,7 @@ void irq_return(void) { } void do_irq(int irq) { - // if (use_apic) { - // apic_eoi(); - // } else { - // pic_eoi(irq); - // } + disable_interrupt(); hardirq_enter(); device_irq_handler(irq); irq_table[irq](irq); @@ -373,12 +371,3 @@ void default_irq_handler(int irq) { // pic_eoi(irq); // } } - -void irq_enable(int irq) { - // if (use_apic) { - // apic_enable_irq(irq); - // } else { - // pic_enable_irq(irq); - // } - interrupt_enable_irq(irq); -} diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index 9defca7..57f6b58 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -1,7 +1,7 @@ -#include "driver/serial/serial_dm.h" -#include "stdint.h" #include -#include +#include +#include +#include #include #include #include @@ -21,6 +21,7 @@ #include #include #include +#include #include BusDriverOps platform_ops = { @@ -28,24 +29,24 @@ BusDriverOps platform_ops = { .unregister_bus_hook = NULL, }; BusOps platform_bus_ops = { - .register_device_hook = NULL, - .unregister_device_hook = NULL, + .scan_bus = NULL, + .probe_device = NULL, +}; +DeviceOps platform_device_ops = { + .init = NULL, + .start = NULL, + .stop = NULL, + .destroy = NULL, }; Driver platform_driver; BusDriver platform_bus_driver = { - .driver_type = DRIVER_TYPE_BUS_DRIVER, - .bus_type = BUS_TYPE_PLATFORM, - .name = STRING_INIT("Platform"), - .state = DRIVER_STATE_UNREGISTERED, - .private_data_size = 0, - .ops = &platform_ops, -}; -Bus platform_bus = { - .controller_device = NULL, - .bus_driver = &platform_bus_driver, - .ops = &platform_bus_ops, + .name = STRING_INIT("Platform"), }; +Bus *platform_bus; + +DeviceDriver platform_device_driver; +PhysicalDevice *platform_device; // 完成一些平台必要的准备工作 void platform_early_init() { @@ -53,30 +54,39 @@ void platform_early_init() { init_descriptor(); } -void platform_init() { +DriverResult platform_init() { + DriverResult result; + // 因为platform_bus是虚拟的,所以不需要注册device ObjectAttr attr = driver_object_attr; - list_init(&platform_driver.sub_driver_lh); - register_bus_driver(&platform_driver, &platform_bus_driver, &attr); - platform_bus.object = platform_bus_driver.object; - list_init(&platform_bus_driver.bus_lh); - list_add_tail(&platform_bus.bus_list, &platform_bus_driver.bus_lh); - list_init(&platform_bus.device_lh); + register_driver(&platform_driver); + register_bus_driver( + &platform_driver, BUS_TYPE_PLATFORM, &platform_bus_driver, &attr); + register_device_driver(&platform_driver, &platform_device_driver); + + result = create_bus(&platform_bus, &platform_bus_driver, &platform_bus_ops); + if (result != DRIVER_OK) { return result; } + + result = create_physical_device(&platform_device, platform_bus, &attr); + if (result != DRIVER_OK) { return result; } + register_physical_device(platform_device, &platform_device_ops); read_features(); bios_emu_init(); register_serial(); - register_vesa_display(); - register_pic(); - register_apic(); - register_pit(); - register_cmos(); + result = register_vesa_display(); + result = register_apic(); + result = register_pic(); + result = register_pit(); + result = register_cmos(); dma_init(); if (cpu_check_feature(CPUID_FEAT_TSC)) rand_seed((uint32_t)read_tsc()); + + return DRIVER_OK; } void serial_receive(uint8_t data) { @@ -84,18 +94,28 @@ void serial_receive(uint8_t data) { } void platform_start_devices() { + init_and_start_physical_device(i8254_device); + init_and_start_physical_device(cmos_device); + Object *serial_object; - init_and_start(&vesa_display_device); + framebuffer_start_all(); init_console(); interrupt_dm_start(); // 启动由interrupt_dm选择的中断控制器 - open_object_by_path("\\Device\\Serial0", &serial_object); - serial_device_open(serial_object, SERIAL_BAUD_115200, serial_receive); + ObjectResult result; + result = open_object_by_path("\\Device\\Serial0", &serial_object); + if (result == OBJECT_OK) { + serial_device_open(serial_object, SERIAL_BAUD_115200, serial_receive); + } print_features(); - DRV_RESULT_PRINT_CALL(init_and_start, &pit_device); - DRV_RESULT_PRINT_CALL(init_and_start, &apic_timer_device); - DRV_RESULT_PRINT_CALL(init_and_start, &rtc_device); + DRV_RESULT_PRINT_CALL( + init_and_start_logical_device(pit_timer_device->device)); + if (use_apic) + DRV_RESULT_PRINT_CALL( + init_and_start_logical_device(apic_timer_device->device)); + DRV_RESULT_PRINT_CALL( + init_and_start_logical_device(rtc_time_device->device)); - platform_bus_driver.subdriver.state = SUBDRIVER_STATE_READY; + // platform_bus_driver.subdriver.state = SUBDRIVER_STATE_READY; } \ No newline at end of file diff --git a/src/driver/Makefile b/src/driver/Makefile index e9a42a6..6fc8baa 100644 --- a/src/driver/Makefile +++ b/src/driver/Makefile @@ -2,10 +2,9 @@ SRC += storage/ SRC += sound/ SRC += timer/ SRC += network/ -SRC += usb/ SRC += input/ SRC += serial/ SRC += framebuffer/ -SRC += interrupt_dm.c +SRC += interrupt/ SRC += bus_dm.c SRC += time_dm.c \ No newline at end of file diff --git a/src/driver/bus_dm.c b/src/driver/bus_dm.c index 55a3e7e..edca79f 100644 --- a/src/driver/bus_dm.c +++ b/src/driver/bus_dm.c @@ -1,41 +1,23 @@ -#include "objects/object.h" #include #include #include #include #include #include - -DriverResult bus_controller_start(DeviceManager *manager, Device *device); +#include DeviceManagerOps bus_controller_dm_ops = { .dm_load = NULL, .dm_unload = NULL, -}; - -typedef struct BusControllerDeviceManager { -} BusControllerDeviceManager; - -BusControllerDeviceManager bus_controller_dm_ext; - -struct DeviceManager bus_controller_device_manager = { - .type = DEVICE_TYPE_BUS_CONTROLLER, - .ops = &bus_controller_dm_ops, - - .private_data = &bus_controller_dm_ext, + .init_device_hook = NULL, + .start_device_hook = NULL, + .stop_device_hook = NULL, + .destroy_device_hook = NULL, }; -DriverResult register_bus_controller_device( - DeviceDriver *device_driver, BusDriver *bus_driver, Device *device, - BusControllerDevice *bus_controller_device, ObjectAttr *attr) { - - device->device_driver = device_driver; - bus_controller_device->device = device; - bus_controller_device->bus_driver = bus_driver; - - DRV_RESULT_DELIVER_CALL( - register_device, device_driver, &bus_controller_device->short_name, - device->bus, device, attr); - return DRIVER_RESULT_OK; -} +DeviceManager bus_controller_dm = { + .type = DEVICE_TYPE_BUS_CONTROLLER, + .ops = &bus_controller_dm_ops, + .private_data = NULL, +}; diff --git a/src/driver/framebuffer/console_backend.c b/src/driver/framebuffer/console_backend.c index e31d5e7..cd99832 100644 --- a/src/driver/framebuffer/console_backend.c +++ b/src/driver/framebuffer/console_backend.c @@ -1,12 +1,11 @@ -#include "driver/framebuffer/console_backend.h" -#include "kernel/driver_interface.h" -#include "kernel/periodic_task.h" -#include "kernel/spinlock.h" +#include #include #include #include #include #include +#include +#include #include #include #include @@ -273,6 +272,6 @@ void fb_console_backend_put_string( } } } - if (list_empty(&thread_all)) { fb_console_backend_update(backend); } spin_unlock(&backend->lock); + if (list_empty(&thread_all)) { fb_console_backend_update(backend); } } diff --git a/src/driver/framebuffer/framebuffer_dm.c b/src/driver/framebuffer/framebuffer_dm.c index cdaaa0f..f9e3dd5 100644 --- a/src/driver/framebuffer/framebuffer_dm.c +++ b/src/driver/framebuffer/framebuffer_dm.c @@ -1,4 +1,3 @@ -#include "objects/object.h" #include #include #include @@ -6,17 +5,20 @@ #include #include #include +#include +#include #include #include -DriverResult framebuffer_device_start(DeviceManager *manager, Device *device); +DriverResult framebuffer_device_start( + DeviceManager *manager, LogicalDevice *device); DeviceManagerOps framebuffer_dm_ops = { .dm_load = NULL, .dm_unload = NULL, .init_device_hook = NULL, - .start_device_hook = framebuffer_device_start, + .start_device_hook = NULL, .stop_device_hook = NULL, .destroy_device_hook = NULL, }; @@ -34,57 +36,87 @@ struct DeviceManager framebuffer_dm = { DriverResult framebuffer_dm_load(DeviceManager *manager) { FrameBufferDeviceManager *framebuffer_manager = manager->private_data; framebuffer_manager->main_display_device = NULL; + framebuffer_dm_ext.new_fb_device_num = 0; + framebuffer_manager->fb_device_count = 0; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult framebuffer_dm_unload(DeviceManager *manager) { FrameBufferDeviceManager *framebuffer_manager = manager->private_data; framebuffer_manager->main_display_device = NULL; - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult register_framebuffer_device( - DeviceDriver *device_driver, Device *device, FrameBufferDevice *fb_device, - ObjectAttr *attr) { - device->dm_ext = fb_device; - if (device->dm_ext == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } - fb_device->device = device; +DriverResult create_framebuffer_device( + FrameBufferDevice **fb_device, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver) { + DriverResult result; + LogicalDevice *logical_device = NULL; + + result = create_logical_device( + &logical_device, physical_device, device_driver, ops, + DEVICE_TYPE_FRAMEBUFFER); + if (result != DRIVER_OK) return result; + + *fb_device = kmalloc(sizeof(FrameBufferDevice)); + if (*fb_device == NULL) { + delete_logical_device(logical_device); + return DRIVER_ERROR_OUT_OF_MEMORY; + } + FrameBufferDevice *fb = *fb_device; + logical_device->dm_ext = fb; + fb->device = logical_device; string_t name; + char _name[] = "FrameBuffer"; string_new_with_number( - &name, "FrameBuffer", 5, framebuffer_dm_ext.fb_device_count++); - - DRV_RESULT_DELIVER_CALL( - register_device, device_driver, &name, device->bus, device, attr); + &name, _name, sizeof(_name) - 1, framebuffer_dm_ext.new_fb_device_num); + framebuffer_dm_ext.new_fb_device_num++; + framebuffer_dm_ext.fb_device_count++; + + Object *obj = create_object(&device_object, &name, device_object_attr); + if (obj == NULL) { + kfree(fb); + delete_logical_device(logical_device); + return DRIVER_ERROR_OBJECT; + } + obj->value.device.kind = DEVICE_KIND_LOGICAL; + obj->value.device.logical = logical_device; + logical_device->object = obj; - list_init(&fb_device->fb_list_lh); - list_add_tail(&device->dm_list, &framebuffer_dm.device_lh); + list_init(&fb->fb_list_lh); - ConsoleBackend *backend = &fb_device->console_backend.backend; + ConsoleBackend *backend = &fb->console_backend.backend; backend->init = fb_console_backend_init; backend->put_string = fb_console_backend_put_string; - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult unregister_framebuffer_device( - DeviceDriver *device_driver, Device *device, - FrameBufferDevice *framebuffer_device) { +DriverResult delete_framebuffer_device(FrameBufferDevice *framebuffer_device) { + framebuffer_dm_ext.fb_device_count--; + + LogicalDevice *logical_device = framebuffer_device->device; + list_del(&framebuffer_device->fb_list_lh); - return DRIVER_RESULT_OK; + delete_logical_device(logical_device); + int result = kfree(framebuffer_device); + if (result < 0) return DRIVER_ERROR_MEMORY_FREE; + return DRIVER_OK; } -DriverResult framebuffer_device_start(DeviceManager *manager, Device *device) { +DriverResult framebuffer_device_start( + DeviceManager *manager, LogicalDevice *device) { FrameBufferDevice *fb_device = (FrameBufferDevice *)device->dm_ext; + init_and_start_logical_device(device); + if (framebuffer_dm_ext.main_display_device == NULL) { framebuffer_dm_ext.main_display_device = device; } - if (fb_device->framebuffer_address == NULL) { - return DRIVER_RESULT_OTHER_ERROR; - } + if (fb_device->framebuffer_address == NULL) { return DRIVER_ERROR_OTHER; } if (fb_device->mode_info.bits_per_pixel == 8) { fb_device->framebuffer_ops = &fb_ops_8; } else if (fb_device->mode_info.bits_per_pixel == 16) { @@ -94,28 +126,36 @@ DriverResult framebuffer_device_start(DeviceManager *manager, Device *device) { } else if (fb_device->mode_info.bits_per_pixel == 32) { fb_device->framebuffer_ops = &fb_ops_32; } else { - return DRIVER_RESULT_UNSUPPORT_FEATURE; + return DRIVER_ERROR_UNSUPPORT_FEATURE; } console_register_backend(&fb_device->console_backend.backend, fb_device); - return DRIVER_RESULT_OK; + return DRIVER_OK; +} + +DriverResult framebuffer_start_all() { + LogicalDevice *device; + list_for_each_owner (device, &framebuffer_dm.device_lh, dm_list) { + framebuffer_device_start(&framebuffer_dm, device); + } + return DRIVER_OK; } DriverResult framebuffer_get_device( int in_index, FrameBufferDevice **out_device) { - Device *device; + LogicalDevice *device; if (in_index == 0) { *out_device = framebuffer_dm_ext.main_display_device->dm_ext; - return DRIVER_RESULT_OK; + return DRIVER_OK; } int i = 0; list_for_each_owner (device, &framebuffer_dm.device_lh, dm_list) { if (device == framebuffer_dm_ext.main_display_device) { continue; } if (i == in_index) { *out_device = device->dm_ext; - return DRIVER_RESULT_OK; + return DRIVER_OK; } i++; } - return DRIVER_RESULT_NOT_EXIST; + return DRIVER_ERROR_NOT_EXIST; } diff --git a/src/driver/input/input_dm.c b/src/driver/input/input_dm.c index e64fef6..fd44d4a 100644 --- a/src/driver/input/input_dm.c +++ b/src/driver/input/input_dm.c @@ -1,4 +1,5 @@ #include "kernel/driver.h" +#include "kernel/spinlock.h" #include "string.h" #include #include @@ -7,10 +8,12 @@ #include #include #include +#include string_t input_object = STRING_INIT("Input"); DriverResult input_dm_load(DeviceManager *manager); +DriverResult input_dm_unload(DeviceManager *manager); DeviceManagerOps input_dm_ops = { .dm_load = input_dm_load, @@ -24,9 +27,11 @@ DeviceManager input_dm = { }; DriverResult input_dm_load(DeviceManager *manager) { - ObjectAttr attr = base_obj_sys_attr; - create_object_directory(&device_object, input_object, attr); - memset(input_dm_ext.device_count, 0, sizeof(input_dm_ext.device_count)); + for (int i = 0; i < INPUT_TYPE_MAX; i++) { + input_dm_ext.new_device_num[i] = 0; + input_dm_ext.device_count[i] = 0; + spinlock_init(&input_dm_ext.lock[i]); + } input_dm_ext.key_events = kmalloc(sizeof(KeyEvent) * INPUT_EVENT_QUEUE_SIZE); @@ -36,28 +41,86 @@ DriverResult input_dm_load(DeviceManager *manager) { kmalloc(sizeof(PointerEvent) * INPUT_EVENT_QUEUE_SIZE); input_dm_ext.pointer_event_w = 0; input_dm_ext.pointer_event_r = 0; - return DRIVER_RESULT_OK; + return DRIVER_OK; +} + +DriverResult input_dm_unload(DeviceManager *manager) { + kfree(input_dm_ext.key_events); + kfree(input_dm_ext.pointer_events); + return DRIVER_OK; } -DriverResult register_input_device( - DeviceDriver *device_driver, Device *device, Bus *bus, - InputDevice *input_device) { - device->dm_ext = input_device; - input_device->device = device; +DriverResult create_input_device( + InputDevice **input_device, InputDeviceType type, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver) { + DriverResult result; + LogicalDevice *logical_device = NULL; + + result = create_logical_device( + &logical_device, physical_device, device_driver, ops, + DEVICE_TYPE_INPUT); + if (result != DRIVER_OK) return result; + + *input_device = kmalloc(sizeof(InputDevice)); + if (*input_device == NULL) { + delete_logical_device(logical_device); + return DRIVER_ERROR_OUT_OF_MEMORY; + } + InputDevice *in = *input_device; + logical_device->dm_ext = in; + in->device = logical_device; + in->type = type; - int id = input_dm_ext.device_count[input_device->type]++; + char name1[] = "Keyboard"; + char name2[] = "Mouse"; + char name3[] = "Input"; + char *_name; + uint8_t len; string_t name; - if (input_device->type == INPUT_TYPE_KEYBOARD) { - string_new_with_number(&name, "Keyboard", 8, id); - } else if (input_device->type == INPUT_TYPE_MOUSE) { - string_new_with_number(&name, "Mouse", 5, id); + uint8_t num; + if (type == INPUT_TYPE_KEYBOARD) { + _name = name1; + len = sizeof(name1) - 1; + } else if (type == INPUT_TYPE_MOUSE) { + _name = name2; + len = sizeof(name2) - 1; } else { - string_new_with_number(&name, "Input", 5, id); + _name = name3; + len = sizeof(name3) - 1; } - ObjectAttr attr = device_object_attr; - register_device(device_driver, &name, bus, device, &attr); + spin_lock(&input_dm_ext.lock[type]); + num = input_dm_ext.new_device_num[type]++; + input_dm_ext.device_count[type]++; + spin_unlock(&input_dm_ext.lock[type]); + string_new_with_number(&name, _name, len, num); + + Object *obj = create_object(&device_object, &name, device_object_attr); + if (obj == NULL) { + kfree(in); + delete_logical_device(logical_device); + return DRIVER_ERROR_OBJECT; + } + obj->value.device.kind = DEVICE_KIND_LOGICAL; + obj->value.device.logical = logical_device; + logical_device->object = obj; + + if (result != DRIVER_OK) return result; + return DRIVER_OK; +} + +DriverResult delete_input_device(InputDevice *input_device) { + InputDeviceType type = input_device->type; + spin_lock(&input_dm_ext.lock[type]); + if (input_dm_ext.device_count[type] > 0) input_dm_ext.device_count[type]--; + spin_unlock(&input_dm_ext.lock[type]); + + LogicalDevice *logical_device = input_device->device; - return DRIVER_RESULT_OK; + list_del(&logical_device->dm_list); + delete_logical_device(logical_device); + int result = kfree(input_device); + if (result < 0) return DRIVER_ERROR_MEMORY_FREE; + return DRIVER_OK; } KeyEvent *new_key_event() { diff --git a/src/driver/interrupt/Makefile b/src/driver/interrupt/Makefile new file mode 100644 index 0000000..d3c6cf2 --- /dev/null +++ b/src/driver/interrupt/Makefile @@ -0,0 +1 @@ +SRC += interrupt_dm.c \ No newline at end of file diff --git a/src/driver/interrupt/interrupt_dm.c b/src/driver/interrupt/interrupt_dm.c new file mode 100644 index 0000000..1f097b3 --- /dev/null +++ b/src/driver/interrupt/interrupt_dm.c @@ -0,0 +1,191 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DriverResult interrupt_start(DeviceManager *manager, PhysicalDevice *device); + +DeviceManagerOps interrupt_dm_ops = { + .dm_load = NULL, + .dm_unload = NULL, + + .init_device_hook = NULL, + .start_device_hook = NULL, + .stop_device_hook = NULL, + .destroy_device_hook = NULL, +}; + +typedef struct InterruptDeviceManager { + InterruptDevice *current_device; +} InterruptDeviceManager; + +InterruptDeviceManager interrupt_dm_ext; + +struct DeviceManager interrupt_dm = { + .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, + + .ops = &interrupt_dm_ops, + + .private_data = &interrupt_dm_ext, +}; + +DriverResult interrupt_dm_load(DeviceManager *manager) { + interrupt_dm_ext.current_device = NULL; + + return DRIVER_OK; +} + +/** + * @brief 检查是否提供了必要的接口 + */ +DriverResult check_intterupt_ops(InterruptDeviceOps *int_ops) { + if (!int_ops->disable_irq) { + print_error("Interrupt", "no disable_irq operation\n"); + return DRIVER_ERROR_INCOMPLETABLE_OPS; + } + if (!int_ops->enable_irq) { + print_error("Interrupt", "no enable_irq operation\n"); + return DRIVER_ERROR_INCOMPLETABLE_OPS; + } + if (!int_ops->eoi) { + print_error("Interrupt", "no eoi operation\n"); + return DRIVER_ERROR_INCOMPLETABLE_OPS; + } + if (!int_ops->redirect_irq) { + print_error("Interrupt", "no redirect_irq operation\n"); + return DRIVER_ERROR_INCOMPLETABLE_OPS; + } + return DRIVER_OK; +} + +DriverResult create_interrupt_device( + InterruptDevice **interrupt_device, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver, + InterruptDeviceOps *int_ops, int priority) { + DriverResult result; + LogicalDevice *logical_device = NULL; + + DRIVER_RESULT_PASS(check_intterupt_ops(int_ops)); + + result = create_logical_device( + &logical_device, physical_device, device_driver, ops, + DEVICE_TYPE_INTERRUPT_CONTROLLER); + if (result != DRIVER_OK) return result; + + *interrupt_device = kmalloc(sizeof(InterruptDevice)); + if (*interrupt_device == NULL) { + delete_logical_device(logical_device); + return DRIVER_ERROR_OUT_OF_MEMORY; + } + InterruptDevice *int_device = *interrupt_device; + logical_device->dm_ext = int_device; + int_device->device = logical_device; + int_device->ops = int_ops; + int_device->priority = priority; + + InterruptDevice *current_device = interrupt_dm_ext.current_device; + if (current_device) { + if (int_device->priority > current_device->priority) { + if (current_device->device->state == DEVICE_STATE_ACTIVE) { + DEV_OPS_CALL(current_device->device, stop); + } + interrupt_dm_ext.current_device = int_device; + } + } else { + interrupt_dm_ext.current_device = int_device; + } + + return DRIVER_OK; +} + +DriverResult delete_interrupt_device(InterruptDevice *interrupt_device) { + InterruptDeviceManager *manager = &interrupt_dm_ext; + + LogicalDevice *cur; + LogicalDevice *device = interrupt_device->device; + + // 如果是正在使用的设备 + InterruptDevice *new_interrupt_device = NULL; + if (manager->current_device == interrupt_device) { + // 寻找替代的设备 + list_for_each_owner (cur, &interrupt_dm.device_lh, dm_list) { + if (cur != device) { + if (new_interrupt_device == NULL) { + new_interrupt_device = cur->dm_ext; + } else { + InterruptDevice *cur_interrupt_device = cur->dm_ext; + if (cur_interrupt_device->priority > + new_interrupt_device->priority) { + new_interrupt_device = cur_interrupt_device; + } + } + } + } + if (new_interrupt_device == NULL) return DRIVER_ERROR_BUSY; + } + if (device->ops->stop && device->state == DEVICE_STATE_ACTIVE) + DRIVER_RESULT_PASS(device->ops->stop(device)); + + LogicalDevice *new_device = new_interrupt_device->device; + + // 恢复运行状态 + if (device->state == DEVICE_STATE_UNINIT) { + init_and_start_logical_device(new_device); + } else if (device->state == DEVICE_STATE_READY) { + start_logical_device(new_device); + } + new_device->state = DEVICE_STATE_ACTIVE; + manager->current_device = new_interrupt_device; + + list_del(&device->dm_list); + DRIVER_RESULT_PASS(delete_logical_device(device)); + int result = kfree(interrupt_device); + if (result < 0) return DRIVER_ERROR_MEMORY_FREE; + + return DRIVER_OK; +} + +DriverResult interrupt_dm_start() { + if (interrupt_dm_ext.current_device) { + LogicalDevice *device = interrupt_dm_ext.current_device->device; + if (device->physical_device->state != DEVICE_STATE_READY) { + DRIVER_RESULT_PASS( + init_and_start_physical_device(device->physical_device)); + } + init_and_start_logical_device(device); + return DRIVER_OK; + } + return DRIVER_ERROR_NOT_EXIST; +} + +uint32_t interrupt_redirect_irq(int irq) { + InterruptDevice *interrupt_device = interrupt_dm_ext.current_device; + + return interrupt_device->ops->redirect_irq(interrupt_device, irq); +} + +DriverResult interrupt_enable_irq(int irq) { + InterruptDevice *interrupt_device = interrupt_dm_ext.current_device; + + return interrupt_device->ops->enable_irq(interrupt_device, irq); +} + +DriverResult interrupt_disable_irq(int irq) { + InterruptDevice *interrupt_device = interrupt_dm_ext.current_device; + + return interrupt_device->ops->disable_irq(interrupt_device, irq); +} + +void interrupt_eoi(int irq) { + InterruptDevice *interrupt_device = interrupt_dm_ext.current_device; + + interrupt_device->ops->eoi(interrupt_device, irq); +} diff --git a/src/driver/interrupt_dm.c b/src/driver/interrupt_dm.c deleted file mode 100644 index 1e3fa19..0000000 --- a/src/driver/interrupt_dm.c +++ /dev/null @@ -1,178 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DriverResult interrupt_start(DeviceManager *manager, Device *device); - -DeviceManagerOps interrupt_dm_ops = { - .dm_load = NULL, - .dm_unload = NULL, -}; - -typedef struct InterruptDeviceManager { - InterruptDevice *current_device; -} InterruptDeviceManager; - -InterruptDeviceManager interrupt_dm_ext; - -struct DeviceManager interrupt_dm = { - .type = DEVICE_TYPE_INTERRUPT_CONTROLLER, - - .ops = &interrupt_dm_ops, - - .private_data = &interrupt_dm_ext, -}; - -/** - * @brief 检查是否提供了必要的接口 - */ -DriverResult check_intterupt_ops(InterruptDevice *interrupt_device) { - if (!interrupt_device->interrupt_ops) { - print_error_with_position( - "%s has no operations\n", interrupt_device->device->name.text); - return DRIVER_RESULT_NO_OPS; - } - if (!interrupt_device->interrupt_ops->disable_irq) { - print_error_with_position( - "%s has no disable_irq operation\n", - interrupt_device->device->name.text); - return DRIVER_RESULT_INCOMPLETABLE_OPS; - } - if (!interrupt_device->interrupt_ops->enable_irq) { - print_error_with_position( - "%s has no enable_irq operation\n", - interrupt_device->device->name.text); - return DRIVER_RESULT_INCOMPLETABLE_OPS; - } - if (!interrupt_device->interrupt_ops->eoi) { - print_error_with_position( - "%s has no eoi operation\n", interrupt_device->device->name.text); - return DRIVER_RESULT_INCOMPLETABLE_OPS; - } - if (!interrupt_device->interrupt_ops->redirect_irq) { - print_error_with_position( - "%s has no redirect_irq operation\n", - interrupt_device->device->name.text); - return DRIVER_RESULT_INCOMPLETABLE_OPS; - } - return DRIVER_RESULT_OK; -} - -DriverResult register_interrupt_device( - DeviceDriver *device_driver, Device *device, - InterruptDevice *interrupt_device) { - interrupt_device->device = device; - DRV_RESULT_DELIVER_CALL(check_intterupt_ops, interrupt_device); - - list_add_tail(&device->dm_list, &interrupt_dm.device_lh); - - InterruptDeviceManager *manager = interrupt_dm.private_data; - if (manager->current_device) { - if (interrupt_device->priority > manager->current_device->priority) { - if (manager->current_device->device->state == DEVICE_STATE_ACTIVE) { - DEV_OPS_CALL( - manager->current_device->device, stop, - manager->current_device->device); - } - manager->current_device = interrupt_device; - } - } else { - manager->current_device = interrupt_device; - } - - return DRIVER_RESULT_OK; -} - -DriverResult unregister_interrupt_device( - DeviceDriver *device_driver, Device *device, - InterruptDevice *interrupt_device) { - - InterruptDeviceManager *manager = interrupt_dm.private_data; - Device *cur; - - DEV_OPS_CALL(device, stop, device); - // 如果是正在使用的设备 - if (manager->current_device == interrupt_device) { - // 寻找替代的设备 - InterruptDevice *new_interrupt_device; - list_for_each_owner (cur, &interrupt_dm.device_lh, device_list) { - if (cur != device) { - if (new_interrupt_device == NULL) { - new_interrupt_device = cur->dm_ext; - } else { - InterruptDevice *cur_interrupt_device = - (InterruptDevice *)cur->dm_ext; - if (cur_interrupt_device->priority > - new_interrupt_device->priority) { - new_interrupt_device = cur_interrupt_device; - } - } - } - } - if (new_interrupt_device != NULL) { - Device *new_device = new_interrupt_device->device; - DeviceDriver *new_device_driver = new_device->device_driver; - DRV_RESULT_DELIVER_CALL( - register_interrupt_device, new_device_driver, new_device, - new_interrupt_device); - // 恢复运行状态 - if (device->state == DEVICE_STATE_ACTIVE) { - DEV_OPS_CALL(new_device, init, new_device); - DEV_OPS_CALL(new_device, start, new_device); - } else if (device->state == DEVICE_STATE_READY) { - DEV_OPS_CALL(new_device, init, new_device); - } - manager->current_device = new_interrupt_device; - } - } - DEV_OPS_CALL(device, destroy, device); - - DRV_RESULT_DELIVER_CALL(unregister_device, device_driver, device); - list_del(&device->dm_list); - - return DRIVER_RESULT_OK; -} - -DriverResult interrupt_dm_start() { - if (interrupt_dm_ext.current_device) { - Device *device = interrupt_dm_ext.current_device->device; - DRV_RESULT_DELIVER_CALL(init_device, device); - DEV_OPS_CALL(device, start, device); - } - return DRIVER_RESULT_OK; -} - -uint32_t interrupt_redirect_irq(int irq) { - InterruptDeviceManager *manager = interrupt_dm.private_data; - InterruptDevice *interrupt_device = manager->current_device; - return interrupt_device->interrupt_ops->redirect_irq(interrupt_device, irq); -} - -DriverResult interrupt_enable_irq(int irq) { - InterruptDeviceManager *manager = interrupt_dm.private_data; - InterruptDevice *interrupt_device = manager->current_device; - DRV_RESULT_DELIVER_CALL( - interrupt_device->interrupt_ops->enable_irq, interrupt_device, irq); - return DRIVER_RESULT_OK; -} - -DriverResult interrupt_disable_irq(int irq) { - InterruptDeviceManager *manager = interrupt_dm.private_data; - InterruptDevice *interrupt_device = manager->current_device; - DRV_RESULT_DELIVER_CALL( - interrupt_device->interrupt_ops->disable_irq, interrupt_device, irq); - return DRIVER_RESULT_OK; -} - -void interrupt_eoi(int irq) { - InterruptDeviceManager *manager = interrupt_dm.private_data; - InterruptDevice *interrupt_device = manager->current_device; - interrupt_device->interrupt_ops->eoi(interrupt_device, irq); -} diff --git a/src/driver/network/buffer.c b/src/driver/network/buffer.c index 02685b1..1242769 100644 --- a/src/driver/network/buffer.c +++ b/src/driver/network/buffer.c @@ -16,6 +16,12 @@ NetBuffer *net_buffer_create(uint16_t size) { return buffer; } +void net_buffer_delete(NetBuffer *buffer) { + if (buffer == NULL) return; + if (buffer->ptr) kfree(buffer->ptr); + kfree(buffer); +} + void net_buffer_init( NetBuffer *buffer, uint16_t size, uint16_t head, uint16_t tail) { buffer->size = size; diff --git a/src/driver/network/conn.c b/src/driver/network/conn.c index b2b090e..f9e6a61 100644 --- a/src/driver/network/conn.c +++ b/src/driver/network/conn.c @@ -17,7 +17,7 @@ NetworkConnection *net_create_conn(Object *object) { if (conn == NULL) { return NULL; } conn->object = object; conn->handle = object_handle_create(object); - conn->net_device = object->value.device->dm_ext; + conn->net_device = object->value.device.logical->dm_ext; conn->state = CONN_STATE_INIT; conn->thread = get_current_thread(); @@ -34,13 +34,6 @@ NetworkConnection *net_create_conn(Object *object) { } void net_destroy_conn(NetworkConnection *conn) { - // NetProtocol *protocol = conn->protocols; - // while (protocol != NULL) { - // NetProtocol *next = protocol->next; - // protocol->ops.destroy(conn, protocol->context); - // kfree(protocol); - // protocol = next; - // } object_handle_delete(conn->handle); kfree(conn); } diff --git a/src/driver/network/mii.c b/src/driver/network/mii.c index 5754f1d..cd19f57 100644 --- a/src/driver/network/mii.c +++ b/src/driver/network/mii.c @@ -26,14 +26,15 @@ MiiMediaType mii_check_media_type(uint32_t negotiation) { * */ DriverResult net_init_mii(Mii *mii) { - bool linked = mii_is_linked(mii); + bool linked = mii_is_linked(mii); + char *device_name = mii->net_dev->device->object->name.text; if (!linked) { - print_device_info(mii->net_dev->device, "MII: No link detected"); + print_info("MII", "device %s No link detected\n", device_name); mii->net_dev->state = NET_STATE_NO_CARRIER; - return DRIVER_RESULT_OK; + return DRIVER_OK; } - print_device_info(mii->net_dev->device, "MII: Link detected\n"); + print_info("MII", "device %s Link detecteds\n", device_name); mii->net_dev->state = NET_STATE_RUNNING; uint32_t anar = mii->mdio_read(mii, MII_REG_ANAR); // 本地能力 @@ -41,7 +42,7 @@ DriverResult net_init_mii(Mii *mii) { uint32_t support = anar & anlpar; // 计算双方都支持的特性 MiiMediaType media_type = mii_check_media_type(support); - print_device_info(mii->net_dev->device, "MII: Media type: "); + print_info("MII", "device %s Media type: ", device_name); int speed = (media_type >> 1) & 0b111; int duplex = media_type & 1; if (speed == 0) printk("10Mbps "); @@ -51,5 +52,5 @@ DriverResult net_init_mii(Mii *mii) { printk("\n"); mii->full_duplex = duplex; - return DRIVER_RESULT_OK; + return DRIVER_OK; } \ No newline at end of file diff --git a/src/driver/network/network.c b/src/driver/network/network.c index 2ac91f0..a0bbeec 100644 --- a/src/driver/network/network.c +++ b/src/driver/network/network.c @@ -2,6 +2,7 @@ #include "driver/network/buffer.h" #include "driver/network/conn.h" #include "driver/network/protocols/protocols.h" +#include "kernel/device.h" #include "kernel/list.h" #include #include @@ -24,7 +25,7 @@ bool net_queue_is_blocked(NetworkQueue *queue, int blocker) { TransferResult network_transfer( struct Object *object, struct ObjectHandle *obj_handle, TransferDirection direction, uint8_t *buf, size_t size) { - Device *device = object->value.device; + LogicalDevice *device = object->value.device.logical; NetworkDevice *net_device = device->dm_ext; if (net_device->ops->send == NULL) { return TRANSFER_ERROR_NOT_SUPPORTED; } if (net_queue_is_blocked(&net_device->tx_queue, NQ_BLOCKER_DRIVER)) { @@ -35,7 +36,7 @@ TransferResult network_transfer( DriverResult network_softirq_register(NetRxHandler *handler) { list_add_tail(&handler->list, &net_rx_lh); - return DRIVER_RESULT_OK; + return DRIVER_OK; } void network_softirq_handler(void) { diff --git a/src/driver/network/network_dm.c b/src/driver/network/network_dm.c index 7e87223..33f3953 100644 --- a/src/driver/network/network_dm.c +++ b/src/driver/network/network_dm.c @@ -1,19 +1,19 @@ -#include "driver/network/buffer.h" -#include "driver/network/conn.h" -#include "driver/network/ethernet/ethernet.h" -#include "driver/network/network.h" -#include "driver/timer_dm.h" -#include "kernel/softirq.h" -#include "objects/transfer.h" +#include +#include +#include #include +#include #include +#include #include #include #include #include #include #include +#include #include +#include DriverResult network_dm_load(DeviceManager *manager); DriverResult network_dm_unload(DeviceManager *manager); @@ -34,55 +34,103 @@ DriverResult network_dm_load(DeviceManager *manager) { manager->private_data = kmalloc(sizeof(NetworkDeviceManager)); softirq_register_handler(SOFTIRQ_NETWORK, network_softirq_handler); neighbour_init(); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult network_dm_unload(DeviceManager *manager) { kfree(manager->private_data); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult register_network_device( - DeviceDriver *driver, Device *device, NetworkDevice *network_device, - ObjectAttr *attr) { - device->dm_ext = network_device; - network_device->device = device; - network_device->private_data = device->private_data; - network_device->state = NET_STATE_INITED; - network_device->tx_queue.blocker = 0; - list_add_tail(&device->dm_list, &network_dm.device_lh); +DriverResult create_network_device( + NetworkDevice **network_device, NetworkDeviceType type, + NetworkDeviceCapabilities caps, NetworkOps *net_ops, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver) { + DriverResult result; + LogicalDevice *logical_device = NULL; + result = create_logical_device( + &logical_device, physical_device, device_driver, ops, + DEVICE_TYPE_ETHERNET); + if (result != DRIVER_OK) return result; + + *network_device = kmalloc(sizeof(NetworkDevice)); + if (*network_device == NULL) { + delete_logical_device(logical_device); + return DRIVER_ERROR_OUT_OF_MEMORY; + } + + NetworkDevice *net = *network_device; + logical_device->dm_ext = net; + net->type = type; + net->capabilities = caps; + net->ops = net_ops; + net->state = NET_STATE_INITED; + net->device = logical_device; + net->tx_queue.blocker = 0; + + char _name[] = "Network"; string_t name; - string_new_with_number(&name, "Network", 7, network_dm_ext.device_count++); - DRIVER_RESULT_PASS(register_device( - device->device_driver, &name, device->bus, device, attr)); + string_new_with_number( + &name, _name, sizeof(_name) - 1, network_dm_ext.device_count); + network_dm_ext.new_device_num++; + network_dm_ext.device_count++; - device->object->out.type = TRANSFER_TYPE_STREAM; - device->object->out.stream = network_transfer; + Object *obj = create_object(&device_object, &name, device_object_attr); + if (obj == NULL) { + kfree(net); + delete_logical_device(logical_device); + return DRIVER_ERROR_OBJECT; + } + obj->value.device.kind = DEVICE_KIND_LOGICAL; + obj->value.device.logical = logical_device; + obj->in.type = TRANSFER_TYPE_NONE; + obj->out.type = TRANSFER_TYPE_STREAM; + obj->out.stream = network_transfer; + logical_device->object = obj; - switch (network_device->type) { + switch (type) { case NETWORK_TYPE_ETHERNET: { - EthernetDevice *eth_device = kmalloc(sizeof(EthernetDevice)); - network_device->ethernet = eth_device; - eth_device->acd_state = ACD_STATE_NONE; - eth_device->arp_conn = net_create_conn(device->object); - conn_buffer(eth_device->arp_conn) = net_buffer_create(128); - net_buffer_init(conn_buffer(eth_device->arp_conn), 128, 0, 0); - timer_init(ð_device->timer); - eth_register(eth_device->arp_conn); + EthernetDevice *eth = kmalloc(sizeof(EthernetDevice)); + net->ethernet = eth; + eth->acd_state = ACD_STATE_NONE; + eth->arp_conn = net_create_conn(obj); + + conn_buffer(eth->arp_conn) = net_buffer_create(128); + + net_buffer_init(conn_buffer(eth->arp_conn), 128, 0, 0); + timer_init(ð->timer); + eth_register(eth->arp_conn); break; } default: break; } - return DRIVER_RESULT_OK; + return DRIVER_OK; +} + +DriverResult delete_network_device(NetworkDevice *network_device) { + network_dm_ext.device_count--; + LogicalDevice *logical_device = network_device->device; + + logical_device->object->out.type = TRANSFER_TYPE_NONE; + logical_device->object->out.stream = NULL; + if (network_device->type == NETWORK_TYPE_ETHERNET) { + net_buffer_delete(conn_buffer(network_device->ethernet->arp_conn)); + kfree(network_device->ethernet); + } + + delete_logical_device(logical_device); + int result = kfree(network_device); + if (result < 0) return DRIVER_ERROR_MEMORY_FREE; + return DRIVER_OK; } NetworkDevice *network_get_device(Object *object) { - if (object->attr->type != OBJECT_TYPE_DEVICE) return NULL; - Device *device = object->value.device; - if (device->device_driver->type != DEVICE_TYPE_SOUND) return NULL; + // if (object->attr->type != OBJECT_TYPE_DEVICE) return NULL; + LogicalDevice *device = object->value.device.logical; + // if (device->device_driver->type != DEVICE_TYPE_SOUND) return NULL; return device->dm_ext; } diff --git a/src/driver/network/protocols/ipv4/acd.c b/src/driver/network/protocols/ipv4/acd.c index 0f75249..4da6a98 100644 --- a/src/driver/network/protocols/ipv4/acd.c +++ b/src/driver/network/protocols/ipv4/acd.c @@ -5,15 +5,14 @@ * References: * - RFC5227: IPv4 Address Conflict Detection */ -#include "driver/network/ethernet/ethernet.h" -#include "driver/network/neighbour.h" -#include "driver/network/network_dm.h" -#include "driver/network/protocols/ipv4/ipv4.h" -#include "driver/network/protocols/protocols.h" -#include "driver/timer_dm.h" +#include +#include +#include #include #include -#include +#include +#include +#include void acd_timer_callback(void *arg) { NetworkDevice *device = arg; diff --git a/src/driver/network/protocols/ipv4/dhcp.c b/src/driver/network/protocols/ipv4/dhcp.c index a773756..3e9e4ad 100644 --- a/src/driver/network/protocols/ipv4/dhcp.c +++ b/src/driver/network/protocols/ipv4/dhcp.c @@ -7,22 +7,20 @@ * RFC 2131: Dynamic Host Configuration Protocol * RFC 1533: DHCP Options and BOOTP Vendor Extensions */ -#include "bits.h" -#include "driver/network/buffer.h" -#include "driver/network/ethernet/ethernet.h" -#include "driver/network/neighbour.h" -#include "driver/network/protocols/ipv4/acd.h" -#include "driver/timer_dm.h" -#include "kernel/driver_interface.h" -#include "kernel/thread.h" -#include "objects/transfer.h" +#include +#include #include +#include +#include #include #include #include #include #include +#include +#include #include +#include #include #include #include diff --git a/src/driver/network/protocols/tcp.c b/src/driver/network/protocols/tcp.c index bd6cc09..32c14ab 100644 --- a/src/driver/network/protocols/tcp.c +++ b/src/driver/network/protocols/tcp.c @@ -8,22 +8,22 @@ * RFC6298: Computing TCP's Retransmission Timer * */ -#include "bits.h" -#include "driver/network/buffer.h" -#include "driver/network/network_dm.h" -#include "driver/network/protocols/protocols.h" -#include "driver/timer_dm.h" -#include "kernel/console.h" -#include "kernel/memory.h" -#include "kernel/spinlock.h" -#include "kernel/thread.h" -#include "math.h" +#include +#include #include +#include #include #include +#include #include +#include #include +#include #include +#include +#include +#include +#include #include #include #include diff --git a/src/driver/serial/serial_dm.c b/src/driver/serial/serial_dm.c index 6311c81..fbe0de5 100644 --- a/src/driver/serial/serial_dm.c +++ b/src/driver/serial/serial_dm.c @@ -1,13 +1,13 @@ -#include "kernel/driver.h" -#include "string.h" #include #include #include #include #include +#include #include #include #include +#include string_t serial_object = STRING_INIT("Serial"); @@ -25,33 +25,70 @@ DeviceManager serial_dm = { }; DriverResult serial_dm_load(DeviceManager *manager) { - serial_dm_ext.device_count = 0; - return DRIVER_RESULT_OK; + serial_dm_ext.new_device_num = 0; + serial_dm_ext.device_count = 0; + return DRIVER_OK; } -DriverResult register_serial_device( - DeviceDriver *device_driver, Device *device, Bus *bus, - SerialDevice *serial_device) { - device->dm_ext = serial_device; - device->device_driver = device_driver; - serial_device->device = device; +DriverResult create_serial_device( + SerialDevice **serial_device, SerialOps *serial_ops, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver) { + LogicalDevice *logical_device = NULL; - int id = serial_dm_ext.device_count++; + DRIVER_RESULT_PASS(create_logical_device( + &logical_device, physical_device, device_driver, ops, + DEVICE_TYPE_SERIAL)); + + *serial_device = kmalloc(sizeof(SerialDevice)); + if (*serial_device == NULL) { + delete_logical_device(logical_device); + return DRIVER_ERROR_OUT_OF_MEMORY; + } + SerialDevice *serial = *serial_device; + logical_device->dm_ext = serial; + serial->device = logical_device; + serial->ops = serial_ops; + + char _name[] = "Serial"; string_t name; - string_new_with_number(&name, "Serial", 6, id); - ObjectAttr attr = device_object_attr; - register_device(device_driver, &name, bus, device, &attr); + string_new_with_number( + &name, _name, sizeof(_name) - 1, serial_dm_ext.new_device_num); + serial_dm_ext.new_device_num++; + serial_dm_ext.device_count++; + + logical_device->object = + create_object(&device_object, &name, device_object_attr); + if (logical_device->object == NULL) { + kfree(serial); + delete_logical_device(logical_device); + return DRIVER_ERROR_OBJECT; + } + + Object *obj = logical_device->object; + obj->value.device.kind = DEVICE_KIND_LOGICAL; + obj->value.device.logical = logical_device; + + return DRIVER_OK; +} + +DriverResult delete_serial_device(SerialDevice *serial_device) { + serial_dm_ext.device_count--; + + LogicalDevice *logical_device = serial_device->device; - return DRIVER_RESULT_OK; + delete_logical_device(logical_device); + int result = kfree(serial_device); + if (result < 0) return DRIVER_ERROR_MEMORY_FREE; + return DRIVER_OK; } DriverResult serial_device_open( Object *serial_object, SerialBaudRate baud_rate, void (*receive)(uint8_t data)) { - Device *device = serial_object->value.device; - SerialDevice *serial_device = device->dm_ext; + LogicalDevice *device = serial_object->value.device.logical; + SerialDevice *serial_device = device->dm_ext; - DRIVER_RESULT_PASS(init_device(device)); + DRIVER_RESULT_PASS(init_logical_device(device)); serial_device->ops->set_baud_rate(serial_device, baud_rate); serial_device->ops->set_recv_mode( @@ -60,7 +97,7 @@ DriverResult serial_device_open( serial_device->receive = receive; - DRIVER_RESULT_PASS(start_device(device)); + DRIVER_RESULT_PASS(start_logical_device(device)); - return DRIVER_RESULT_OK; + return DRIVER_OK; } diff --git a/src/driver/sound/pcm.c b/src/driver/sound/pcm.c index 9bb8f75..7e64a23 100644 --- a/src/driver/sound/pcm.c +++ b/src/driver/sound/pcm.c @@ -40,7 +40,7 @@ PcmDevice *sound_register_pcm( DriverResult pcm_register_stream( PcmDevice *pcm, PcmStream **stream, PcmStreamOps *ops, void *private_data) { *stream = kmalloc(sizeof(PcmStream)); - if (*stream == NULL) return DRIVER_RESULT_OUT_OF_MEMORY; + if (*stream == NULL) return DRIVER_ERROR_OUT_OF_MEMORY; PcmStream *s = *stream; s->pcm = pcm; @@ -57,18 +57,18 @@ DriverResult pcm_register_stream( spinlock_init(&s->lock); wait_queue_init(&s->wq); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult pcm_register_dma( PcmDevice *pcm, void *dma, void *param, DmaOps *ops) { Dma *_dma = kmalloc(sizeof(Dma)); - if (_dma == NULL) return DRIVER_RESULT_OUT_OF_MEMORY; + if (_dma == NULL) return DRIVER_ERROR_OUT_OF_MEMORY; _dma->dma = dma; _dma->param = param; _dma->ops = ops; pcm->dma = _dma; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sound_pcm_alloc(PcmStream *stream) { @@ -77,25 +77,25 @@ DriverResult sound_pcm_alloc(PcmStream *stream) { stream->device_ptr_base = stream->host_ptr_base = 0; stream->device_period_ptr = stream->host_period_ptr = 0; stream->host_ptr = 0; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult pcm_set_data_type(PcmStream *stream, PcmDataType data_type) { DRIVER_RESULT_PASS(stream->ops->set_data_type(stream, data_type)); stream->data_type = data_type; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult pcm_set_channel(PcmStream *stream, uint8_t channel) { DRIVER_RESULT_PASS(stream->ops->set_channel(stream, channel)); stream->channel = channel; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult pcm_set_sample_rate(PcmDevice *pcm, uint32_t sample_rate) { DRIVER_RESULT_PASS(pcm->ops->set_sample_rate(pcm, sample_rate)); pcm->sample_rate = sample_rate; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sound_pcm_open( @@ -105,7 +105,7 @@ DriverResult sound_pcm_open( PcmStream *cur_stream; if (sound_device->type != SOUND_TYPE_PCM) - return DRIVER_RESULT_UNSUPPORT_FEATURE; + return DRIVER_ERROR_UNSUPPORT_FEATURE; PcmDevice *pcm = sound_device->pcm; if (mode == SOUND_DEVICE_MODE_PLAY) { @@ -115,7 +115,7 @@ DriverResult sound_pcm_open( pcm->record_stream->ops->open(sound_device, pcm->record_stream); cur_stream = pcm->record_stream; } else { - return DRIVER_RESULT_UNSUPPORT_FEATURE; + return DRIVER_ERROR_UNSUPPORT_FEATURE; } cur_stream->ops->set_default_params(cur_stream); @@ -125,14 +125,14 @@ DriverResult sound_pcm_open( object->in.stream = sound_pcm_transfer; object->out.type = TRANSFER_TYPE_STREAM; object->out.stream = sound_pcm_transfer; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sound_pcm_set_frame_count(PcmStream *stream, size_t count) { stream->frame_per_period = count; stream->frame_bytes = stream->channel * stream->pcm->data_bytes; stream->period_bytes = stream->frame_per_period * stream->frame_bytes; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sound_pcm_set_mode(PcmStream *stream, PcmMode mode) { @@ -194,7 +194,7 @@ void pcm_noninterleaved2interleaved( DriverResult sound_pcm_copy_interleaved( PcmStream *stream, uint8_t *dst, uint8_t *src, uint32_t frame_count) { if (frame_count > stream->frame_per_period) - return DRIVER_RESULT_EXCEED_MAX_SIZE; + return DRIVER_ERROR_EXCEED_MAX_SIZE; if (stream->hw_mode == PCM_MODE_INTERLEAVED) { // 模式相同,直接复制 memcpy(dst, src, frame_count * stream->frame_bytes); @@ -203,7 +203,7 @@ DriverResult sound_pcm_copy_interleaved( // 输入为交织模式,输出为非交织模式 pcm_interleaved2noninterleaved(stream, src, dst, frame_count); } - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sound_pcm_copy_noninterleaved( @@ -216,7 +216,7 @@ DriverResult sound_pcm_copy_noninterleaved( // 输入为非交织模式,输出为交织模式 pcm_noninterleaved2interleaved(stream, src, dst, frame_count); } - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult pcm_transfer( @@ -287,9 +287,9 @@ DriverResult pcm_transfer( stream->host_period_ptr = stream->host_ptr_base + position; } spin_unlock_irqrestore(&stream->lock, flags); - if (done < frame_count) { return DRIVER_RESULT_BUSY; }; + if (done < frame_count) { return DRIVER_ERROR_BUSY; }; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sound_pcm_read( @@ -302,69 +302,6 @@ DriverResult sound_pcm_write( PcmStream *stream, uint8_t *buf, uint32_t frame_count) { return pcm_transfer( stream, buf, stream->pcm->buf, frame_count, TRANSFER_OUT); - // PcmDevice *pcm = stream->pcm; - // uint32_t count; - // uint8_t *dst, *src = buf; - - // int flags = spin_lock_irqsave(&stream->lock); - // int left_space = sound_pcm_left_space(stream); - - // size_t writed = 0; - // size_t size, left_size = frame_count * stream->frame_bytes; - // while (left_size > 0) { - // while (left_space == 0) { - // thread_set_status(TASK_INTERRUPTIBLE); - // wait_queue_add(&stream->wq); - // spin_unlock_irqrestore(&stream->lock, flags); - - // thread_wait(); - - // spin_lock_irqsave(&stream->lock); - // left_space = sound_pcm_left_space(stream); - // } - // dst = pcm->buf + stream->host_ptr; - // size = MIN(left_space, left_size); - // size = MIN(size, pcm->buffer_bytes - stream->host_ptr); - // spin_unlock_irqrestore(&stream->lock, flags); - - // count = size / stream->frame_bytes; - // if (stream->user_mode == PCM_MODE_INTERLEAVED) { - // sound_pcm_copy_interleaved(stream, dst, src, count); - // } else { - // sound_pcm_copy_noninterleaved(stream, dst, src, count); - // } - // src += size; - // left_space -= size; - // left_size -= size; - // writed += count; - - // flags = spin_lock_irqsave(&stream->lock); - // stream->host_ptr += size; - - // if (stream->host_ptr >= pcm->buffer_bytes) { - // stream->host_ptr -= pcm->buffer_bytes; - // stream->host_ptr_base += pcm->buffer_bytes; - // if (stream->host_ptr_base > pcm->boundary) { - // stream->host_ptr_base = 0; - // } - // } - // } - // if (writed > 0) { - // if ((pcm->status == PCM_STATUS_PREPARED || - // pcm->status == PCM_STATUS_PAUSED)) { - // if (sound_pcm_left_space(stream) >= stream->start_threshold) { - // stream->ops->trigger(stream, PCM_TRIGGER_START); - // pcm->status = PCM_STATUS_RUNNING; - // } - // } - // int position = stream->host_ptr; - // position -= position % stream->period_bytes; - // stream->host_period_ptr = stream->host_ptr_base + position; - // } - // spin_unlock_irqrestore(&stream->lock, flags); - // if (writed < frame_count) { return DRIVER_RESULT_BUSY; }; - - // return DRIVER_RESULT_OK; } DriverResult sound_pcm_prepare(PcmStream *stream) { @@ -376,7 +313,7 @@ DriverResult sound_pcm_prepare(PcmStream *stream) { DRIVER_RESULT_PASS( stream->ops->prepare(stream, pcm->buf, pcm->buffer_bytes)); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult sound_pcm_done(PcmStream *stream) { @@ -413,7 +350,7 @@ DriverResult sound_pcm_done(PcmStream *stream) { wait_queue_wakeup(&stream->wq); spin_unlock_irqrestore(&stream->lock, flags); - return DRIVER_RESULT_OK; + return DRIVER_OK; } TransferResult sound_pcm_transfer( diff --git a/src/driver/sound/sound_dm.c b/src/driver/sound/sound_dm.c index 7a0e043..ff81d3a 100644 --- a/src/driver/sound/sound_dm.c +++ b/src/driver/sound/sound_dm.c @@ -23,36 +23,77 @@ DeviceManager sound_dm = { }; DriverResult sound_dm_load(DeviceManager *manager) { - manager->private_data = kmalloc(sizeof(SoundDeviceManager)); - return DRIVER_RESULT_OK; + manager->private_data = kmalloc(sizeof(SoundDeviceManager)); + sound_dm_ext.new_device_num = 0; + sound_dm_ext.device_count = 0; + return DRIVER_OK; } DriverResult sound_dm_unload(DeviceManager *manager) { kfree(manager->private_data); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult register_sound_device( - DeviceDriver *driver, Device *device, SoundDevice *sound_device, - ObjectAttr *attr) { - device->dm_ext = sound_device; - sound_device->device = device; - sound_device->private_data = device->private_data; +DriverResult create_sound_device( + SoundDevice **sound_device, SoundDeviceType type, + SoundDeviceCapabilities caps, SoundOps *sound_ops, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver) { + DriverResult result; + LogicalDevice *logical_device = NULL; - list_add_tail(&device->dm_list, &sound_dm.device_lh); + result = create_logical_device( + &logical_device, physical_device, device_driver, ops, + DEVICE_TYPE_SOUND); + if (result != DRIVER_OK) return result; + *sound_device = kmalloc(sizeof(SoundDevice)); + if (*sound_device == NULL) { + delete_logical_device(logical_device); + return DRIVER_ERROR_OUT_OF_MEMORY; + } + SoundDevice *snd; + logical_device->dm_ext = *sound_device; + snd = *sound_device; + snd->device = logical_device; + snd->type = type; + snd->ops = sound_ops; + snd->capabilities = caps; + + char _name[] = "Sound"; string_t name; - string_new_with_number(&name, "Sound", 5, sound_dm_ext.device_count++); - DRIVER_RESULT_PASS(register_device( - device->device_driver, &name, device->bus, device, attr)); + string_new_with_number( + &name, _name, sizeof(_name) - 1, sound_dm_ext.new_device_num); + sound_dm_ext.new_device_num++; + sound_dm_ext.device_count++; + + Object *obj = create_object(&device_object, &name, device_object_attr); + if (obj == NULL) { + kfree(snd); + delete_logical_device(logical_device); + return DRIVER_ERROR_OBJECT; + } + obj->value.device.kind = DEVICE_KIND_LOGICAL; + obj->value.device.logical = logical_device; + logical_device->object = obj; + + return DRIVER_OK; +} + +DriverResult delete_sound_device(SoundDevice *sound_device) { + sound_dm_ext.device_count--; + LogicalDevice *logical_device = sound_device->device; - return DRIVER_RESULT_OK; + list_del(&logical_device->dm_list); + delete_logical_device(logical_device); + int result = kfree(sound_device); + if (result < 0) return DRIVER_ERROR_MEMORY_FREE; + return DRIVER_OK; } SoundDevice *sound_get_device(Object *object) { - if (object->attr->type != OBJECT_TYPE_DEVICE) return NULL; - Device *device = object->value.device; - if (device->device_driver->type != DEVICE_TYPE_SOUND) return NULL; + // if (object->attr->type != OBJECT_TYPE_DEVICE) return NULL; + LogicalDevice *device = object->value.device.logical; + // if (device->type != DEVICE_TYPE_SOUND) return NULL; return device->dm_ext; } diff --git a/src/driver/storage/disk/mbr.c b/src/driver/storage/disk/mbr.c index d620825..eb73821 100644 --- a/src/driver/storage/disk/mbr.c +++ b/src/driver/storage/disk/mbr.c @@ -29,7 +29,7 @@ void parse_mbr_partition_table(StorageDevice *storage_device) { string_new_with_number(&name, "Partition", 9, partition_count); ObjectAttr attr = device_object_attr; attr.type = OBJECT_TYPE_PARTITION; - Object *object = create_object(storage_device->object, name, attr); + Object *object = create_object(storage_device->object, &name, attr); Partition *partition = kmalloc(sizeof(Partition)); partition->storage_object = storage_device->device->object; diff --git a/src/driver/storage/storage_dm.c b/src/driver/storage/storage_dm.c index 646c261..2e30976 100644 --- a/src/driver/storage/storage_dm.c +++ b/src/driver/storage/storage_dm.c @@ -1,5 +1,6 @@ #include "kernel/spinlock.h" #include "kernel/wait_queue.h" +#include "objects/attr.h" #include #include #include @@ -22,76 +23,114 @@ #include extern void storage_periodic_task(void *arg); -DriverResult start_storage_device(DeviceManager *manager, Device *device); +DriverResult start_storage_device( + DeviceManager *manager, LogicalDevice *device); DeviceManagerOps storage_dm_ops = { - .dm_load = NULL, - .dm_unload = NULL, - .start_device_hook = start_storage_device, - .stop_device_hook = NULL, + .dm_load = NULL, + .dm_unload = NULL, + + .init_device_hook = NULL, + .start_device_hook = start_storage_device, + .stop_device_hook = NULL, + .destroy_device_hook = NULL, }; typedef struct StorageDeviceManager { + uint8_t new_device_num; uint8_t device_count; } StorageDeviceManager; StorageDeviceManager storage_dm_ext; - struct DeviceManager storage_dm = { - .type = DEVICE_TYPE_STORAGE, - - .ops = &storage_dm_ops, - + .type = DEVICE_TYPE_STORAGE, + .ops = &storage_dm_ops, .private_data = &storage_dm_ext, }; -DriverResult register_storage_device( - DeviceDriver *device_driver, Device *device, StorageDevice *storage_device, - ObjectAttr *attr) { - storage_device->device = device; +DriverResult create_storage_device( + StorageDevice **storage_device, StorageDeviceOps *storage_ops, + DeviceOps *ops, PhysicalDevice *physical_device, + DeviceDriver *device_driver) { + DriverResult result; + LogicalDevice *logical_device = NULL; + + result = create_logical_device( + &logical_device, physical_device, device_driver, ops, + DEVICE_TYPE_STORAGE); + if (result != DRIVER_OK) return result; + + *storage_device = kmalloc(sizeof(StorageDevice)); + if (*storage_device == NULL) { + delete_logical_device(logical_device); + return DRIVER_ERROR_OUT_OF_MEMORY; + } - device->dm_ext = storage_device; - spinlock_init(&storage_device->queue_lock); - list_init(&storage_device->io_queue_lh); - wait_queue_init(&storage_device->wq); + StorageDevice *storage = *storage_device; + logical_device->dm_ext = storage; + storage->device = logical_device; + storage->ops = storage_ops; + spinlock_init(&storage->queue_lock); + list_init(&storage->io_queue_lh); + wait_queue_init(&storage->wq); + + char _name[] = "Storage"; string_t name; - string_new_with_number(&name, "Storage", 7, storage_dm_ext.device_count++); - DRV_RESULT_DELIVER_CALL( - register_device, device_driver, &name, device->bus, device, attr); - list_add_tail(&device->dm_list, &storage_dm.device_lh); - - device->object->in.type = TRANSFER_TYPE_BLOCK; - device->object->in.block = storage_transfer; - device->object->in.block_async = storage_transfer_async; - device->object->in.is_transfer_done = storage_is_transfer_done; - device->object->out.type = TRANSFER_TYPE_BLOCK; - device->object->out.block = storage_transfer; - device->object->out.block_async = storage_transfer_async; - device->object->out.is_transfer_done = storage_is_transfer_done; - - storage_device->periodic_task.func = storage_periodic_task; - storage_device->periodic_task.arg = storage_device; - storage_device->name = name; - periodic_task_add(&storage_device->periodic_task); - - attr->type = OBJECT_TYPE_DIRECTORY; - storage_device->object = - create_object_directory(&device_object, name, *attr); - - return DRIVER_RESULT_OK; + string_new_with_number( + &name, _name, sizeof(_name) - 1, storage_dm_ext.new_device_num); + storage_dm_ext.new_device_num++; + storage_dm_ext.device_count++; + + Object *obj = create_object(&device_object, &name, device_object_attr); + logical_device->object = obj; + if (logical_device->object == NULL) { + kfree(storage); + delete_logical_device(logical_device); + return DRIVER_ERROR_OBJECT; + } + + obj->in.type = TRANSFER_TYPE_BLOCK; + obj->in.block = storage_transfer; + obj->in.block_async = storage_transfer_async; + obj->in.is_transfer_done = storage_is_transfer_done; + obj->out.type = TRANSFER_TYPE_BLOCK; + obj->out.block = storage_transfer; + obj->out.block_async = storage_transfer_async; + obj->out.is_transfer_done = storage_is_transfer_done; + obj->value.device.kind = DEVICE_KIND_LOGICAL; + obj->value.device.logical = logical_device; + + storage->periodic_task.func = storage_periodic_task; + storage->periodic_task.arg = storage; + storage->name = name; + periodic_task_add(&storage->periodic_task); + + ObjectAttr attr = base_obj_sys_attr; + attr.type = OBJECT_TYPE_DIRECTORY; + storage->object = create_object_directory(&device_object, &name, attr); + + return DRIVER_OK; } -DriverResult unregister_storage_device( - DeviceDriver *device_driver, Device *device, - StorageDevice *storage_device) { +DriverResult delete_storage_device(StorageDevice *storage_device) { + // TODO: delete_object_directory + // TODO: periodic_task_remove - DRV_RESULT_DELIVER_CALL(unregister_device, device_driver, device); - list_del(&device->device_list); - return DRIVER_RESULT_OK; + list_del(&storage_device->device->dm_list); + delete_logical_device(storage_device->device); + int result; + if (storage_device->device->state == DEVICE_STATE_ACTIVE) { + result = kfree(storage_device->superblock); + if (result < 0) return DRIVER_ERROR_MEMORY_FREE; + } + result = kfree(storage_device); + if (result < 0) return DRIVER_ERROR_MEMORY_FREE; + return DRIVER_OK; } -DriverResult start_storage_device(DeviceManager *manager, Device *device) { +DriverResult start_storage_device( + DeviceManager *manager, LogicalDevice *device) { StorageDevice *storage_device = device->dm_ext; storage_device->superblock = kmalloc(2 * SECTOR_SIZE); @@ -107,5 +146,5 @@ DriverResult start_storage_device(DeviceManager *manager, Device *device) { storage_device->block_cache_lh.next = NULL; storage_device->block_cache_lh.prev = NULL; } - return DRIVER_RESULT_OK; + return DRIVER_OK; } diff --git a/src/driver/storage/storage_io.c b/src/driver/storage/storage_io.c index 581f578..12733ec 100644 --- a/src/driver/storage/storage_io.c +++ b/src/driver/storage/storage_io.c @@ -45,7 +45,7 @@ DriverResult storage_generate_request( // 创建新的请求 request = kmalloc(sizeof(StorageRequest)); if (request == NULL && first_request != NULL) { - return DRIVER_RESULT_OUT_OF_MEMORY; + return DRIVER_ERROR_OUT_OF_MEMORY; } // 设置新请求的参数 @@ -69,7 +69,7 @@ DriverResult storage_generate_request( if (first_request == NULL) { first_request = request; } } MRET(last_request) = request; - return DRIVER_RESULT_OK; + return DRIVER_OK; } TransferResult storage_transfer_async( @@ -78,7 +78,7 @@ TransferResult storage_transfer_async( while (object->attr->type == OBJECT_TYPE_SYM_LINK) { object = object->value.sym_link; } - Device *device = object->value.device; + LogicalDevice *device = object->value.device.logical; storage_generate_request( device->dm_ext, (direction == TRANSFER_IN) ? 0 : 1, buf, position, count, (StorageRequest **)handle); @@ -92,7 +92,7 @@ TransferResult storage_transfer( while (object->attr->type == OBJECT_TYPE_SYM_LINK) { object = object->value.sym_link; } - Device *device = object->value.device; + LogicalDevice *device = object->value.device.logical; StorageRequest *request; StorageDevice *storage_device = device->dm_ext; @@ -103,7 +103,7 @@ TransferResult storage_transfer( DriverResult result = storage_generate_request( storage_device, (direction == TRANSFER_IN) ? 0 : 1, buf, position, count, &request); - if (result != DRIVER_RESULT_OK) { + if (result != DRIVER_OK) { wait_queue_del(&storage_device->wq); return TRANSFER_ERROR_FAILED; } @@ -123,9 +123,9 @@ TransferResult storage_is_transfer_done( if (object->attr->type != OBJECT_TYPE_DEVICE) { return TRANSFER_ERROR_INVALID_PARAMETER; } - Device *device = object->value.device; + LogicalDevice *device = object->value.device.logical; - if (device->device_driver->type != DEVICE_TYPE_STORAGE) { + if (device->type != DEVICE_TYPE_STORAGE) { return TRANSFER_ERROR_INVALID_PARAMETER; } StorageDevice *storage_device = device->dm_ext; diff --git a/src/driver/storage/volume.c b/src/driver/storage/volume.c index 1eab179..2e65659 100644 --- a/src/driver/storage/volume.c +++ b/src/driver/storage/volume.c @@ -13,7 +13,7 @@ void probe_volume(Partition *partition) { Object *object = partition->storage_object; StorageDevice *storage_device = - partition->storage_object->value.device->dm_ext; + partition->storage_object->value.device.logical->dm_ext; string_t prefix = storage_device->name; partition->superblock = kmalloc(2 * SECTOR_SIZE); @@ -34,7 +34,7 @@ void probe_volume(Partition *partition) { partition->index); ObjectAttr attr = device_object_attr; Object *root_object = - create_object_directory(&volumes_object, name, attr); + create_object_directory(&volumes_object, &name, attr); partition->object->fs_info = fs_info; object_mount(partition->object, root_object); diff --git a/src/driver/time_dm.c b/src/driver/time_dm.c index a6da36c..31338ed 100644 --- a/src/driver/time_dm.c +++ b/src/driver/time_dm.c @@ -1,8 +1,9 @@ -#include "kernel/list.h" +#include "kernel/device.h" #include #include #include #include +#include #include DriverResult timer_dm_load(DeviceManager *manager); @@ -11,6 +12,11 @@ DriverResult timer_dm_unload(DeviceManager *manager); DeviceManagerOps time_dm_ops = { .dm_load = NULL, .dm_unload = NULL, + + .init_device_hook = NULL, + .start_device_hook = NULL, + .stop_device_hook = NULL, + .destroy_device_hook = NULL, }; TimeDeviceManager time_dm_ext; @@ -20,17 +26,46 @@ DeviceManager time_dm = { .private_data = &time_dm_ext, }; -DriverResult register_time_device( - DeviceDriver *driver, Device *device, TimeDevice *time_device) { - device->dm_ext = time_device; - time_device->device = device; +DriverResult create_time_device( + TimeDevice **time_device, TimeOps *time_ops, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver) { + DriverResult result; + LogicalDevice *logical_device = NULL; - list_add_tail(&device->dm_list, &time_dm.device_lh); + result = create_logical_device( + &logical_device, physical_device, device_driver, ops, DEVICE_TYPE_TIME); + if (result != DRIVER_OK) return result; - if (time_dm_ext.time_devices[time_device->type] == NULL) { - time_dm_ext.time_devices[time_device->type] = time_device; + *time_device = kmalloc(sizeof(TimeDevice)); + if (*time_device == NULL) { + delete_logical_device(logical_device); + return DRIVER_ERROR_OUT_OF_MEMORY; } - return DRIVER_RESULT_OK; + + TimeDevice *time = *time_device; + logical_device->dm_ext = time; + time->device = logical_device; + time->ops = time_ops; + return DRIVER_OK; +} + +DriverResult time_device_start(LogicalDevice *device) { + TimeDevice *time = (TimeDevice *)device->dm_ext; + + if (time_dm_ext.time_devices[time->device->type] == NULL) { + time_dm_ext.time_devices[time->device->type] = time; + } + return DRIVER_OK; +} + +DriverResult delete_time_device(TimeDevice *time_device) { + int result = 0; + + list_del(&time_device->device->dm_list); + DRIVER_RESULT_PASS(delete_logical_device(time_device->device)); + result = kfree(time_device); + if (result < 0) return DRIVER_ERROR_MEMORY_FREE; + return DRIVER_OK; } DriverResult get_current_time(TimeType type, Time *time) { @@ -38,5 +73,5 @@ DriverResult get_current_time(TimeType type, Time *time) { if (time_device != NULL) { return time_device->ops->get_time(time_device, type, time); } - return DRIVER_RESULT_UNSUPPORT_FEATURE; + return DRIVER_ERROR_UNSUPPORT_FEATURE; } diff --git a/src/driver/timer/timer.c b/src/driver/timer/timer.c index 3064139..e833bd7 100644 --- a/src/driver/timer/timer.c +++ b/src/driver/timer/timer.c @@ -1,8 +1,8 @@ -#include "kernel/driver_interface.h" #include "kernel/func.h" -#include "kernel/list.h" -#include +#include #include +#include +#include #include #include #include @@ -12,21 +12,21 @@ extern TimerDeviceManager timer_dm_ext; DriverResult timer_init(Timer *timer) { timer->timer_device = timer_dm_ext.scheduler_timer->dm_ext; timer->timeout = 0; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult timer_set_timeout(Timer *timer, uint32_t count) { - if (timer->timer_device == NULL) return DRIVER_RESULT_NOT_EXIST; + if (timer->timer_device == NULL) return DRIVER_ERROR_NOT_EXIST; uint32_t counter = timer->timer_device->counter; timer->timeout = counter + count; timer->will_wrap = (timer->timeout > counter) ? false : true; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult timer_callback_enable(Timer *timer) { if (timer == NULL || timer->timer_device == NULL) - return DRIVER_RESULT_NOT_EXIST; + return DRIVER_ERROR_NOT_EXIST; // 在插入时排序 if (!list_empty(&timer->timer_device->timer_callback_lh)) { Timer *last_timer = list_last_owner( @@ -38,17 +38,17 @@ DriverResult timer_callback_enable(Timer *timer) { } else { list_add_tail(&timer->list, &timer->timer_device->timer_callback_lh); } - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult timer_callback_cancel(Timer *timer) { if (timer == NULL || timer->timer_device == NULL) - return DRIVER_RESULT_NOT_EXIST; + return DRIVER_ERROR_NOT_EXIST; if (list_in_list(&timer->list)) list_del(&timer->list); - else return DRIVER_RESULT_OTHER_ERROR; + else return DRIVER_ERROR_OTHER; - return DRIVER_RESULT_OK; + return DRIVER_OK; } uint32_t timer_count_ms(Timer *timer, uint32_t ms) { @@ -67,7 +67,7 @@ void delay_ms(Timer *timer, uint32_t ms) { uint32_t status = load_interrupt_status(); enable_interrupt(); while (!timer_is_timeout(timer)) - ; + io_hlt(); store_interrupt_status(status); } diff --git a/src/driver/timer/timer_dm.c b/src/driver/timer/timer_dm.c index a68c664..34bf4f6 100644 --- a/src/driver/timer/timer_dm.c +++ b/src/driver/timer/timer_dm.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -13,7 +13,7 @@ const int default_frequencies[] = {100, 250, 1000}; DriverResult timer_dm_load(DeviceManager *manager); DriverResult timer_dm_unload(DeviceManager *manager); -DriverResult timer_device_init(DeviceManager *manager, Device *device); +DriverResult timer_device_init(DeviceManager *manager, LogicalDevice *device); DeviceManagerOps timer_dm_ops = { .dm_load = timer_dm_load, @@ -36,20 +36,19 @@ struct DeviceManager timer_dm = { }; DriverResult timer_dm_load(DeviceManager *manager) { - TimerDeviceManager *timer_manager = manager->private_data; - timer_manager->scheduler_timer = NULL; + timer_dm_ext.scheduler_timer = NULL; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult timer_dm_unload(DeviceManager *manager) { TimerDeviceManager *timer_manager = manager->private_data; timer_manager->scheduler_timer = NULL; - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult timer_device_init(DeviceManager *manager, Device *device) { +DriverResult timer_device_init(DeviceManager *manager, LogicalDevice *device) { TimerDevice *timer_device = (TimerDevice *)device->dm_ext; const int count = @@ -65,7 +64,7 @@ DriverResult timer_device_init(DeviceManager *manager, Device *device) { freq = default_frequencies[i]; } } - DRV_RESULT_DELIVER_CALL(timer_set_frequency, device, freq); + DRIVER_RESULT_PASS(timer_set_frequency(device, freq)); TimerDeviceManager *timer_manager = manager->private_data; if (timer_manager->scheduler_timer == NULL) { @@ -77,7 +76,7 @@ DriverResult timer_device_init(DeviceManager *manager, Device *device) { timer_manager->scheduler_timer = device; } } - return DRIVER_RESULT_OK; + return DRIVER_OK; } int timer_get_schedule_tick(int priority) { @@ -88,7 +87,7 @@ int timer_get_schedule_tick(int priority) { return ticks; } -DriverResult timer_set_frequency(Device *device, uint32_t frequency) { +DriverResult timer_set_frequency(LogicalDevice *device, uint32_t frequency) { TimerDevice *timer_device = (TimerDevice *)device->dm_ext; TimerResult result = @@ -96,11 +95,11 @@ DriverResult timer_set_frequency(Device *device, uint32_t frequency) { timer_device->current_frequency = frequency; timer_device->counter = 0; - if (result != TIMER_RESULT_OK) { return DRIVER_RESULT_OTHER_ERROR; } - return DRIVER_RESULT_OK; + if (result != TIMER_RESULT_OK) { return DRIVER_ERROR_OTHER; } + return DRIVER_OK; } -void timer_irq_handler(Device *device) { +void timer_irq_handler(LogicalDevice *device) { TimerDevice *timer_device = (TimerDevice *)device->dm_ext; timer_device->counter++; @@ -129,20 +128,33 @@ void timer_irq_handler(Device *device) { } } -DriverResult register_timer_device( - DeviceDriver *device_driver, Device *device, TimerDevice *timer_device) { - - device->dm_ext = timer_device; - timer_device->device = device; +DriverResult create_timer_device( + TimerDevice **timer_device, TimerOps *timer_ops, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver) { + DriverResult result; + LogicalDevice *logical_device = NULL; + + result = create_logical_device( + &logical_device, physical_device, device_driver, ops, + DEVICE_TYPE_TIMER); + if (result != DRIVER_OK) return result; + + *timer_device = kmalloc(sizeof(TimerDevice)); + if (*timer_device == NULL) { + delete_logical_device(logical_device); + return DRIVER_ERROR_OUT_OF_MEMORY; + } + TimerDevice *timer = *timer_device; + logical_device->dm_ext = timer; + timer->device = logical_device; + timer->timer_ops = timer_ops; - list_init(&timer_device->timer_callback_lh); - list_add_tail(&device->dm_list, &timer_dm.device_lh); + list_init(&timer->timer_callback_lh); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult unregister_timer_device( - DeviceDriver *device_driver, Device *device, TimerDevice *timer_device) { +DriverResult delete_timer_device(TimerDevice *timer_device) { Timer *timer, *next; list_for_each_owner_safe ( timer, next, &timer_device->timer_callback_lh, list) { @@ -151,7 +163,9 @@ DriverResult unregister_timer_device( list_del(&timer->list); } - DRV_RESULT_DELIVER_CALL(unregister_device, device_driver, device); - list_del(&device->device_list); - return DRIVER_RESULT_OK; + DRIVER_RESULT_PASS(delete_logical_device(timer_device->device)); + int result = kfree(timer_device); + if (result < 0) return DRIVER_ERROR_MEMORY_FREE; + + return DRIVER_OK; } diff --git a/src/driver/usb/Makefile b/src/driver/usb/Makefile deleted file mode 100644 index c986b7f..0000000 --- a/src/driver/usb/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -SRC += usb_dm.c -SRC += usb_driver.c -SRC += usb-core/ \ No newline at end of file diff --git a/src/driver/usb/usb-core/hcd.c b/src/driver/usb/usb-core/hcd.c deleted file mode 100644 index 85820d7..0000000 --- a/src/driver/usb/usb-core/hcd.c +++ /dev/null @@ -1,67 +0,0 @@ -#include "driver/bus_dm.h" -#include "driver/usb/usb_dm.h" -#include "kernel/bus_driver.h" -#include "kernel/device_driver.h" -#include "kernel/spinlock.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -LIST_HEAD(hcd_list); - -extern BusOps usb_bus_ops; - -UsbHcd *usb_hcd_register( - DeviceDriver *device_driver, Device *device, char *name, int name_len, - uint32_t port_cnt, UsbHcdOps *ops) { - BusControllerDevice *bus_controller_device = - kmalloc(sizeof(BusControllerDevice)); - string_new(&bus_controller_device->short_name, name, name_len); - bus_controller_device->bus_controller_ops = NULL; - - ObjectAttr attr = driver_object_attr; - register_bus_controller_device( - device_driver, &usb_bus_driver, device, bus_controller_device, &attr); - - uint8_t bus_num; - spin_lock(&usb_dm_ext.hcd_count_lock); - bus_num = usb_dm_ext.hcd_count++; - spin_unlock(&usb_dm_ext.hcd_count_lock); - - char bus_name[4]; - char *next = itoa(bus_name, bus_num, 10); - *next = '\0'; - Bus *bus = kmalloc(sizeof(Bus)); - bus->bus_num = bus_num; - bus->ops = &usb_bus_ops; - string_new(&bus->name, bus_name, next - bus_name); - register_bus(&usb_bus_driver, device, bus, &attr); - - UsbHcd *hcd = kmalloc(sizeof(UsbHcd)); - if (hcd == NULL) return NULL; - - list_add_tail(&hcd->list, &hcd_list); - hcd->bus_ctrlr_device = bus_controller_device; - hcd->device = bus_controller_device->device; - hcd->device_count = 0; - hcd->bus = bus; - hcd->ops = ops; - string_new(&hcd->name, name, name_len); - - hcd->ports = kmalloc(sizeof(UsbHcdPort) * port_cnt); - for (int i = 0; i < port_cnt; i++) { - hcd->ports[i].port = i; - hcd->ports[i].hcd = hcd; - hcd->ports[i].connected = 0; - } - - return hcd; -} \ No newline at end of file diff --git a/src/driver/usb/usb-core/usb.c b/src/driver/usb/usb-core/usb.c deleted file mode 100644 index 3271c6c..0000000 --- a/src/driver/usb/usb-core/usb.c +++ /dev/null @@ -1,100 +0,0 @@ -#include "kernel/device.h" -#include "kernel/list.h" -#include "objects/object.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -UsbDevice *usb_create_device( - UsbHcd *hcd, UsbHub *hub, UsbDeviceSpeed speed, uint8_t address) { - Device *device = kmalloc(sizeof(Device)); - device->private_data_size = 0; - device->ops = NULL; - device->state = DEVICE_STATE_UNREGISTERED; - device->bus = hcd->bus; - - UsbDevice *usb_device = (UsbDevice *)kmalloc(sizeof(UsbDevice)); - list_init(&usb_device->ep_lh); - list_init(&usb_device->interface_lh); - usb_device->desc = kmalloc(sizeof(struct UsbDeviceDescriptor)); - usb_device->speed = speed; - usb_device->address = address; - usb_device->state = USB_STATE_UNINITED; - usb_device->device = device; - usb_device->hcd = hcd; - usb_device->hub = hub; - - return usb_device; -} - -int usb_destroy_device(UsbDevice *device) { - return kfree(device); -} - -UsbControlRequest *usb_create_request( - uint8_t direction, uint8_t type, uint8_t recipient, uint8_t request_id, - uint8_t value_hi, uint8_t value_lo, uint16_t index, uint16_t length) { - UsbControlRequest *request = - (UsbControlRequest *)kmalloc(sizeof(UsbControlRequest)); - request->bmRequestType = direction << 7 | type << 5 | recipient; - request->bRequest = request_id; - request->wValue = HOST2LE_WORD(value_hi << 8 | value_lo); - request->wIndex = HOST2LE_WORD(index); - request->wLength = HOST2LE_WORD(length); - return request; -} - -void usb_init_endpoint( - UsbDevice *usb_device, UsbEndpoint *ep, - struct UsbEndpointDescriptor *desc) { - ep->desc = desc; - - ep->pipe = usb_device->hcd->ops->create_pipeline(usb_device, ep); -} - -int usb_init_device( - UsbHcd *hcd, UsbEndpoint *ep0, struct UsbEndpointDescriptor *ep_desc, - UsbDevice *usb_device) { - usb_init_endpoint(usb_device, ep0, ep_desc); - usb_device->ep0 = ep0; - - struct UsbDeviceDescriptor *desc = - usb_get_device_descriptor(hcd, usb_device, ep0); - // usb_show_device_descriptor(hcd, device, ep0, desc); - hcd->device_count++; - usb_set_address(hcd, usb_device, ep0, hcd->device_count); - - Timer timer; - timer_init(&timer); - delay_ms(&timer, 2); - - usb_device->address = hcd->device_count; - usb_get_config_descriptor(hcd, usb_device, ep0); - - usb_set_config(hcd, usb_device, ep0, 1); - - ObjectAttr attr = device_object_attr; - register_usb_device( - hcd->device->device_driver, usb_device->device, usb_device, &attr); - - if (desc->bDeviceClass == USB_CLASS_HUB) { - UsbHub *hub = kmalloc(sizeof(UsbHub)); - hub->usb_device = usb_device; - hub->ops = &usb_hub_ops; - hub->hcd = hcd; - - hub->desc = usb_get_hub_descriptor(hub); - // usb_show_hub_descriptor(desc); - - usb_init_hub(hcd, hub, ep0, usb_device); - } - return 0; -} \ No newline at end of file diff --git a/src/driver/usb/usb_dm.c b/src/driver/usb/usb_dm.c deleted file mode 100644 index 8066a47..0000000 --- a/src/driver/usb/usb_dm.c +++ /dev/null @@ -1,101 +0,0 @@ -#include "kernel/bus_driver.h" -#include "kernel/spinlock.h" -#include "objects/transfer.h" -#include "string.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -list_t usb_driver_lh[USB_INTERFACE_TYPE_MAX]; - -void usb_dm_probe(DeviceManager *dm); -DriverResult usb_dm_load(DeviceManager *manager); -// DriverResult usb_dm_unload(DeviceManager *manager); -UsbDeviceManager usb_dm_ext; - -DynamicDeviceEvents usb_dm_events = { - .probe = usb_dm_probe, - .remove = NULL, -}; -DeviceManagerOps usb_dm_ops = { - .dm_load = usb_dm_load, - .dm_unload = NULL, -}; - -// UsbDeviceManager usb_dm_ext; -DeviceManager usb_dm = { - .type = DEVICE_TYPE_USB, - .ops = &usb_dm_ops, - .private_data = &usb_dm_ext, -}; - -DriverResult usb_dm_load(DeviceManager *manager) { - spinlock_init(&usb_dm_ext.hcd_count_lock); - usb_dm_ext.hcd_count = 0; - for (int i = 0; i < USB_INTERFACE_TYPE_MAX; i++) { - list_init(&usb_driver_lh[i]); - } - register_dynamic_device_manager(&usb_dm_events, manager); - softirq_register_handler(SOFTIRQ_USB, usb_softirq_handler); - return DRIVER_RESULT_OK; -} - -void usb_dm_probe(DeviceManager *dm) { - UsbDriver *usb_driver; - Device *device; - UsbInterface *interface; - list_for_each_owner (device, &dm->device_lh, dm_list) { - UsbDevice *usb_device = (UsbDevice *)device->dm_ext; - if (usb_device->state == USB_STATE_INITED) { - list_for_each_owner (interface, &usb_device->interface_lh, list) { - if (interface->usb_driver != NULL) { continue; } - uint8_t interface_type = - usb_interface_map[interface->desc->bInterfaceClass]; - list_for_each_owner ( - usb_driver, &usb_driver_lh[interface_type], list) { - if (usb_driver->probe != NULL) { - usb_driver->probe(usb_device, interface); - } - } - } - } - } -} - -DriverResult register_usb_device( - DeviceDriver *driver, Device *device, UsbDevice *usb_device, - ObjectAttr *attr) { - device->dm_ext = usb_device; - usb_device->state = USB_STATE_INITED; - usb_device->device = device; - usb_device->device->ops = &usb_device_ops; - list_add_tail(&device->dm_list, &usb_dm.device_lh); - - char _name[4]; - char *next = itoa(_name, device->bus->bus_num, 10); - *next = '\0'; - - string_t name; - string_new(&name, _name, next - _name); - DRIVER_RESULT_PASS( - register_device(driver, NULL, device->bus, device, attr)); - - // 不可直接传输数据 - device->object->in.type = TRANSFER_TYPE_NONE; - device->object->out.type = TRANSFER_TYPE_NONE; - - return DRIVER_RESULT_OK; -} diff --git a/src/driver/usb/usb_driver.c b/src/driver/usb/usb_driver.c deleted file mode 100644 index c1463d7..0000000 --- a/src/driver/usb/usb_driver.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#include - -DriverResult register_usb_driver(UsbDriver *usb_driver) { - list_add_tail( - &usb_driver->list, &usb_driver_lh[usb_driver->interface_type]); - return DRIVER_RESULT_OK; -} \ No newline at end of file diff --git a/src/drivers/bus/Makefile b/src/drivers/bus/Makefile index 347720f..f374ace 100644 --- a/src/drivers/bus/Makefile +++ b/src/drivers/bus/Makefile @@ -1 +1,2 @@ -SRC += usb.c \ No newline at end of file +SRC += usb.c +SRC += hcd.c \ No newline at end of file diff --git a/src/drivers/bus/hcd.c b/src/drivers/bus/hcd.c new file mode 100644 index 0000000..0a07ba0 --- /dev/null +++ b/src/drivers/bus/hcd.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LIST_HEAD(hcd_list); + +extern BusOps usb_bus_ops; + +DriverResult usb_create_hcd( + DEF_MRET(UsbHcd *, hcd), uint32_t port_cnt, UsbHcdOps *hcd_ops, + DeviceOps *ops, PhysicalDevice *physical_device, + DeviceDriver *device_driver) { + DriverResult ret = DRIVER_OK; + + if (usb_bus_driver.state != DRIVER_STATE_REGISTERED) + return DRIVER_ERROR_WAITING; + + LogicalDevice *logical_device = NULL; + DRIVER_RESULT_PASS(create_logical_device( + &logical_device, physical_device, device_driver, ops, + DEVICE_TYPE_BUS_CONTROLLER)); + + UsbHcd *hcd = kmalloc(sizeof(UsbHcd)); + if (hcd == NULL) { + ret = DRIVER_ERROR_OUT_OF_MEMORY; + goto failed_create_hcd; + } + MRET(hcd) = hcd; + hcd->device = logical_device; + hcd->ops = hcd_ops; + hcd->new_device_num = 0; + hcd->device_count = 0; + hcd->device = logical_device; + logical_device->dm_ext = hcd; + spinlock_init(&hcd->lock); + + ret = create_bus(&hcd->bus, &usb_bus_driver, &usb_bus_ops); + if (ret != DRIVER_OK) goto failed_create_bus; + + hcd->ports = kmalloc(sizeof(UsbHcdPort) * port_cnt); + if (hcd->ports == NULL) { + ret = DRIVER_ERROR_OUT_OF_MEMORY; + goto failed_create_ports; + } + for (int i = 0; i < port_cnt; i++) { + hcd->ports[i].port = i; + hcd->ports[i].hcd = hcd; + hcd->ports[i].connected = 0; + } + + list_add_tail(&hcd->list, &hcd_list); + list_add_tail(&hcd->bus->bus_check_list, &bus_lh); + list_init(&hcd->usb_device_lh); + + return DRIVER_OK; +failed_create_ports: + delete_bus(hcd->bus); + +failed_create_bus: + kfree(hcd); + +failed_create_hcd: + delete_logical_device(logical_device); + + return ret; +} diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c index df9af5f..72aa6b3 100644 --- a/src/drivers/bus/usb.c +++ b/src/drivers/bus/usb.c @@ -1,92 +1,109 @@ -#include "drivers/bus/usb.h" #include "kernel/device.h" -#include "kernel/device_driver.h" -#include "kernel/driver.h" -#include "kernel/list.h" -#include "objects/object.h" +#include "kernel/spinlock.h" #include +#include +#include +#include #include #include #include #include +#include #include +#include -LIST_HEAD(hci_lh); +#define LH_INIT(type) [type] = LIST_HEAD_INIT(usb_driver_lh[type]) -BusDriverOps usb_bus_driver_ops = { - .register_bus_hook = NULL, - .unregister_bus_hook = NULL, - .init = NULL, -}; -DeviceDriverOps usb_device_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, +DriverResult usb_probe(BusDriver *bus_driver, Bus *bus); + +list_t usb_driver_lh[USB_INTERFACE_TYPE_MAX] = { + LH_INIT(USB_INTERFACE_TYPE_HID), + LH_INIT(USB_INTERFACE_TYPE_MASS_STORAGE), + LH_INIT(USB_INTERFACE_TYPE_HUB), + LH_INIT(USB_INTERFACE_TYPE_CDC_DATA), + LH_INIT(USB_INTERFACE_TYPE_SMART_CARD), + LH_INIT(USB_INTERFACE_TYPE_CONTENT_SECURITY), + LH_INIT(USB_INTERFACE_TYPE_VIDEO), + LH_INIT(USB_INTERFACE_TYPE_PERSONAL_HEALTHCARE), + LH_INIT(USB_INTERFACE_TYPE_AUDIO_VIDEO), + LH_INIT(USB_INTERFACE_TYPE_BILLBOARD), + LH_INIT(USB_INTERFACE_TYPE_TYPE_C_BRIDGE), + LH_INIT(USB_INTERFACE_TYPE_BULK_DISPLAY_PROTOCOL), + LH_INIT(USB_INTERFACE_TYPE_MTCP), + LH_INIT(USB_INTERFACE_TYPE_I3C), + LH_INIT(USB_INTERFACE_TYPE_DIAGNOSTIC), + LH_INIT(USB_INTERFACE_TYPE_WIRELESS_CONTROLLER), + LH_INIT(USB_INTERFACE_TYPE_MISCELLANEOUS), + LH_INIT(USB_INTERFACE_TYPE_APPLICATION_SPECIFIC), + LH_INIT(USB_INTERFACE_TYPE_VENDOR_SPECIFIC), }; + BusOps usb_bus_ops = { - .register_device_hook = NULL, - .unregister_device_hook = NULL, - .scan_bus = NULL, - .probe_device = NULL, -}; -DeviceOps usb_device_ops = { - .init = NULL, - .start = NULL, - .stop = NULL, - .destroy = NULL, - .status = NULL, + .scan_bus = NULL, + .probe_device = usb_probe, }; -DriverDependency usb_dependencies[] = { - { - .in_type = DRIVER_DEPENDENCY_TYPE_BUS, - .dependency_in_bus = {BUS_TYPE_PCI, 0}, - .out_bus = NULL, - }, -}; Driver usb_driver = { - .short_name = STRING_INIT("UsbDriver"), - .dependency_count = sizeof(usb_dependencies) / sizeof(DriverDependency), - .dependencies = usb_dependencies, - .init = NULL, + .short_name = STRING_INIT("UsbDriver"), }; BusDriver usb_bus_driver = { - .name = STRING_INIT("USB"), - .driver_type = DRIVER_TYPE_BUS_DRIVER, - .bus_type = BUS_TYPE_USB, - .state = DRIVER_STATE_UNREGISTERED, - .private_data_size = 0, - .ops = &usb_bus_driver_ops, -}; -DeviceDriver usb_device_driver = { - .name = STRING_INIT("USB Device Driver"), - .type = DEVICE_TYPE_BUS_CONTROLLER, - .state = DRIVER_STATE_UNREGISTERED, - .private_data_size = 0, - .ops = &usb_device_driver_ops, -}; -Device usb_device = { - .name = STRING_INIT("System USB Controller"), - .state = DEVICE_STATE_UNREGISTERED, - .bus = &platform_bus, - .private_data_size = 0, - .ops = &usb_device_ops, -}; -BusControllerDevice usb_bus_controller_device = { - .short_name = STRING_INIT("USB Bus Controller"), - .device = &usb_device, - .bus_driver = &usb_bus_driver, - .bus_controller_ops = NULL, + .name = STRING_INIT("USB"), }; +DriverResult usb_probe(BusDriver *bus_driver, Bus *bus) { + UsbDriver *usb_driver; + PhysicalDevice *device; + UsbInterface *interface; + list_for_each_owner (device, &bus->device_lh, bus_list) { + UsbDevice *usb_device = device->bus_ext; + if (usb_device->state == USB_STATE_INITED) { + list_for_each_owner (interface, &usb_device->interface_lh, list) { + if (interface->usb_driver != NULL) { continue; } + uint8_t interface_type = + usb_interface_map[interface->desc->bInterfaceClass]; + list_for_each_owner ( + usb_driver, &usb_driver_lh[interface_type], list) { + if (usb_driver->probe != NULL) { + usb_driver->probe(usb_device, interface); + } + } + } + } + } + + return DRIVER_OK; +} + +DriverResult register_usb_driver(UsbDriver *usb_driver) { + list_add_tail( + &usb_driver->list, &usb_driver_lh[usb_driver->interface_type]); + return DRIVER_OK; +} + +DriverResult unregister_usb_driver(UsbDriver *usb_driver) { + list_del(&usb_driver->list); + return DRIVER_OK; +} + static __init void usb_bus_driver_entry(void) { - ObjectAttr attr = device_object_attr; - register_driver(&usb_driver); - register_bus_driver(&usb_driver, &usb_bus_driver, &attr); + DriverResult result; - HciInit *hci_init; - list_for_each_owner (hci_init, &hci_lh, list) { - if (hci_init->init) hci_init->init(&usb_driver); - } + result = register_driver(&usb_driver); + if (result != DRIVER_OK) goto failed_register_driver; + + ObjectAttr attr = driver_object_attr; + result = + register_bus_driver(&usb_driver, BUS_TYPE_USB, &usb_bus_driver, &attr); + if (result != DRIVER_OK) goto failed_register_bus_driver; + + softirq_register_handler(SOFTIRQ_USB, usb_softirq_handler); + + return; +failed_register_bus_driver: + unregister_driver(&usb_driver); + +failed_register_driver: + return; } driver_initcall(usb_bus_driver_entry); diff --git a/src/drivers/usb/Makefile b/src/drivers/usb/Makefile index c1fbaa7..bf1da59 100644 --- a/src/drivers/usb/Makefile +++ b/src/drivers/usb/Makefile @@ -1 +1,2 @@ -SRC += hid/ \ No newline at end of file +SRC += hid/ +SRC += core/ \ No newline at end of file diff --git a/src/driver/usb/usb-core/Makefile b/src/drivers/usb/core/Makefile similarity index 80% rename from src/driver/usb/usb-core/Makefile rename to src/drivers/usb/core/Makefile index ecedd10..96f2352 100644 --- a/src/driver/usb/usb-core/Makefile +++ b/src/drivers/usb/core/Makefile @@ -1,5 +1,4 @@ SRC += func.c SRC += hub.c SRC += usb.c -SRC += hcd.c SRC += urb.c \ No newline at end of file diff --git a/src/driver/usb/usb-core/func.c b/src/drivers/usb/core/func.c similarity index 87% rename from src/driver/usb/usb-core/func.c rename to src/drivers/usb/core/func.c index 7aa91bc..888af30 100644 --- a/src/driver/usb/usb-core/func.c +++ b/src/drivers/usb/core/func.c @@ -1,8 +1,8 @@ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include @@ -11,8 +11,7 @@ void *usb_get_descriptor( UsbHcd *hcd, UsbDevice *device, uint8_t type, uint8_t recipient, - uint8_t index, UsbEndpoint *ep, uint8_t value_hi, uint8_t value_lo, - uint16_t desc_size) { + uint8_t index, uint8_t value_hi, uint8_t value_lo, uint16_t desc_size) { void *desc = kmalloc(desc_size); UsbControlRequest usb_req = USB_BUILD_REQUEST( @@ -25,8 +24,7 @@ void *usb_get_descriptor( void *usb_set_descriptor( UsbHcd *hcd, UsbDevice *device, uint8_t type, uint8_t recipient, - uint8_t index, UsbEndpoint *ep, uint8_t value_hi, uint8_t value_lo, - uint16_t desc_size) { + uint8_t index, uint8_t value_hi, uint8_t value_lo, uint16_t desc_size) { void *desc = kmalloc(desc_size); UsbControlRequest usb_req = USB_BUILD_REQUEST( @@ -38,7 +36,7 @@ void *usb_set_descriptor( } struct UsbConfigDescriptor *usb_get_config_descriptor( - UsbHcd *hcd, UsbDevice *usb_device, UsbEndpoint *ep) { + UsbHcd *hcd, UsbDevice *usb_device) { struct UsbConfigDescriptor *desc = kmalloc(sizeof(struct UsbConfigDescriptor)); @@ -91,7 +89,7 @@ struct UsbConfigDescriptor *usb_get_config_descriptor( return desc; } -uint8_t usb_get_config(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { +uint8_t usb_get_config(UsbHcd *hcd, UsbDevice *device) { uint8_t config; UsbControlRequest usb_req = USB_BUILD_REQUEST( @@ -102,8 +100,7 @@ uint8_t usb_get_config(UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep) { return config; } -UsbSetupStatus usb_set_config( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint8_t config) { +UsbSetupStatus usb_set_config(UsbHcd *hcd, UsbDevice *device, uint8_t config) { UsbControlRequest usb_req = USB_BUILD_REQUEST( USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, @@ -151,7 +148,7 @@ uint32_t usb_get_port_status(UsbHub *hub, uint8_t port) { } struct UsbStringDescriptor *usb_get_string_descriptor( - UsbHcd *hcd, UsbDevice *device, uint8_t index, UsbEndpoint *ep) { + UsbHcd *hcd, UsbDevice *device, uint8_t index) { uint8_t buffer[2]; UsbControlRequest usb_req = USB_BUILD_REQUEST( @@ -169,13 +166,17 @@ struct UsbStringDescriptor *usb_get_string_descriptor( } UsbSetupStatus usb_set_address( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, uint32_t address) { + UsbHcd *hcd, UsbDevice *device, uint32_t address) { UsbControlRequest req = USB_BUILD_REQUEST( USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_STANDARD, USB_REQ_RECIPIENT_DEVICE, USB_REQ_SET_ADDRESS, address >> 8, address & 0xff, 0, 0); - return hcd->ops->ctrl_transfer_out(hcd, device, NULL, 0, &req); + UsbSetupStatus status = + hcd->ops->ctrl_transfer_out(hcd, device, NULL, 0, &req); + + if (status == USB_SETUP_SUCCESS) device->address = address; + return status; } UsbSetupStatus usb_clear_port_feature( @@ -203,8 +204,7 @@ UsbSetupStatus usb_set_port_feature( } void usb_show_device_descriptor( - UsbHcd *hcd, UsbDevice *device, UsbEndpoint *ep, - struct UsbDeviceDescriptor *desc) { + UsbHcd *hcd, UsbDevice *device, struct UsbDeviceDescriptor *desc) { printk("\nUSB Device Descriptor:\n"); printk("Length: %d\n", desc->bLength); printk("DescriptorType: %d\n", desc->bDescriptorType); @@ -223,7 +223,7 @@ void usb_show_device_descriptor( printk("Manufacturer: "); struct UsbStringDescriptor *str1 = - usb_get_string_descriptor(hcd, device, desc->iManufacturer, ep); + usb_get_string_descriptor(hcd, device, desc->iManufacturer); for (int i = 0; i < (str1->bLength - 2) / 2; i++) { printk("%c", str1->wData[i]); } @@ -231,7 +231,7 @@ void usb_show_device_descriptor( printk("Product: "); struct UsbStringDescriptor *str2 = - usb_get_string_descriptor(hcd, device, desc->iProduct, ep); + usb_get_string_descriptor(hcd, device, desc->iProduct); for (int i = 0; i < (str2->bLength - 2) / 2; i++) { printk("%c", str2->wData[i]); } @@ -239,7 +239,7 @@ void usb_show_device_descriptor( printk("Serial Number: "); struct UsbStringDescriptor *str3 = - usb_get_string_descriptor(hcd, device, desc->iSerialNumber, ep); + usb_get_string_descriptor(hcd, device, desc->iSerialNumber); for (int i = 0; i < (str3->bLength - 2) / 2; i++) { printk("%c", str3->wData[i]); } diff --git a/src/driver/usb/usb-core/hub.c b/src/drivers/usb/core/hub.c similarity index 61% rename from src/driver/usb/usb-core/hub.c rename to src/drivers/usb/core/hub.c index 1e8b0f7..16b6a7a 100644 --- a/src/driver/usb/usb-core/hub.c +++ b/src/drivers/usb/core/hub.c @@ -1,12 +1,13 @@ +#include "kernel/console.h" #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include #include +#include +#include +#include +#include #include #include @@ -18,8 +19,7 @@ UsbHubOps usb_hub_ops = { .get_port_status = usb_get_port_status, }; -void usb_init_hub( - UsbHcd *hcd, UsbHub *hub, UsbEndpoint *ep0, UsbDevice *usb_device) { +void usb_init_hub(UsbHcd *hcd, UsbHub *hub, UsbDevice *usb_device) { Timer timer; timer_init(&timer); @@ -27,8 +27,6 @@ void usb_init_hub( int i; UsbSetupStatus status2; - UsbEndpoint *endpoints = - kmalloc(sizeof(UsbEndpoint) * hub->desc->bNbrPorts); uint32_t port_status[hub->desc->bNbrPorts]; for (i = 0; i < hub->desc->bNbrPorts; i++) { @@ -48,7 +46,9 @@ void usb_init_hub( if (status2 == USB_SETUP_CRC_TIMEOUT_ERR) continue; } } + printk("%d ", timer_get_counter()); delay_ms(&timer, 200); + printk("%d ", timer_get_counter()); for (i = 0; i < hub->desc->bNbrPorts; i++) { status = port_status[i]; @@ -57,16 +57,8 @@ void usb_init_hub( BIN_IS_EN(status, USB_PORT_STAT_LOW_SPEED) ? USB_SPEED_LOW : BIN_IS_EN(status, USB_PORT_STAT_HIGH_SPEED) ? USB_SPEED_HIGH : USB_SPEED_FULL; - UsbDevice *dev = usb_create_device(hcd, hub, speed, 0); - struct UsbEndpointDescriptor *endpoint_desc = - kmalloc(sizeof(struct UsbEndpointDescriptor)); - endpoint_desc->bLength = sizeof(struct UsbEndpointDescriptor); - endpoint_desc->bDescriptorType = USB_DESC_TYPE_ENDPOINT; - endpoint_desc->bEndpointAddress = USB_EP_OUT << 7 | 0; // ep0 out - endpoint_desc->bmAttributes = USB_EP_CONTROL; - endpoint_desc->wMaxPacketSize = HOST2LE_WORD(64); - endpoint_desc->bInterval = 0; - usb_init_device(hcd, &endpoints[i], endpoint_desc, dev); + + usb_probe_device(hcd, hub, speed); } } delay_ms(&timer, 100); diff --git a/src/driver/usb/usb-core/urb.c b/src/drivers/usb/core/urb.c similarity index 90% rename from src/driver/usb/usb-core/urb.c rename to src/drivers/usb/core/urb.c index 4380892..33596a0 100644 --- a/src/driver/usb/usb-core/urb.c +++ b/src/drivers/usb/core/urb.c @@ -1,5 +1,5 @@ -#include "driver/usb/usb.h" -#include +#include "drivers/usb/core/usb.h" +#include #include #include diff --git a/src/drivers/usb/core/usb.c b/src/drivers/usb/core/usb.c new file mode 100644 index 0000000..eff68d5 --- /dev/null +++ b/src/drivers/usb/core/usb.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DeviceOps usb_device_ops = { + .init = NULL, + .start = NULL, + .stop = NULL, + .destroy = NULL, +}; + +struct UsbEndpointDescriptor ep0_desc = { + .bLength = sizeof(struct UsbEndpointDescriptor), + .bDescriptorType = USB_DESC_TYPE_ENDPOINT, + .bEndpointAddress = USB_EP_OUT << 7 | 0, // ep0 out + .bmAttributes = USB_EP_CONTROL, + .wMaxPacketSize = HOST2LE_WORD(64), + .bInterval = 0, +}; + +UsbDevice *usb_create_device( + UsbHcd *hcd, UsbHub *hub, UsbDeviceSpeed speed, uint8_t address) { + ObjectAttr attr = device_object_attr; + DriverResult result; + PhysicalDevice *physical_device; + + result = create_physical_device(&physical_device, hcd->bus, &attr); + if (result != DRIVER_OK) return NULL; + + UsbDevice *usb_device = (UsbDevice *)kmalloc(sizeof(UsbDevice)); + list_init(&usb_device->ep_lh); + list_init(&usb_device->interface_lh); + usb_device->desc = kmalloc(sizeof(struct UsbDeviceDescriptor)); + usb_device->speed = speed; + usb_device->address = address; + usb_device->state = USB_STATE_UNINITED; + usb_device->device = physical_device; + usb_device->hcd = hcd; + usb_device->hub = hub; + physical_device->bus_ext = usb_device; + + usb_device->ep0 = kmalloc(sizeof(UsbEndpoint)); + usb_init_endpoint(usb_device, usb_device->ep0, &ep0_desc); + + register_physical_device(physical_device, &usb_device_ops); + + return usb_device; +} + +int usb_destroy_device(UsbDevice *device) { + return kfree(device); +} + +UsbControlRequest *usb_create_request( + uint8_t direction, uint8_t type, uint8_t recipient, uint8_t request_id, + uint8_t value_hi, uint8_t value_lo, uint16_t index, uint16_t length) { + UsbControlRequest *request = + (UsbControlRequest *)kmalloc(sizeof(UsbControlRequest)); + request->bmRequestType = direction << 7 | type << 5 | recipient; + request->bRequest = request_id; + request->wValue = HOST2LE_WORD(value_hi << 8 | value_lo); + request->wIndex = HOST2LE_WORD(index); + request->wLength = HOST2LE_WORD(length); + return request; +} + +void usb_init_endpoint( + UsbDevice *usb_device, UsbEndpoint *ep, + struct UsbEndpointDescriptor *desc) { + ep->desc = desc; + + ep->pipe = usb_device->hcd->ops->create_pipeline(usb_device, ep); +} + +int usb_probe_device(UsbHcd *hcd, UsbHub *hub, UsbDeviceSpeed speed) { + UsbDevice *usb_device = usb_create_device(hcd, hub, speed, 0); + + struct UsbDeviceDescriptor *desc = + usb_get_device_descriptor(hcd, usb_device); + // usb_show_device_descriptor(hcd, device, desc); + + uint8_t address; + spin_lock(&hcd->lock); + hcd->new_device_num++; + hcd->device_count++; + address = hcd->new_device_num; + spin_unlock(&hcd->lock); + usb_set_address(hcd, usb_device, address); + + Timer timer; + timer_init(&timer); + delay_ms(&timer, 2); + + usb_device->address = address; + usb_get_config_descriptor(hcd, usb_device); + + usb_set_config(hcd, usb_device, 1); + + if (desc->bDeviceClass == USB_CLASS_HUB) { + UsbHub *new_hub = kmalloc(sizeof(UsbHub)); + new_hub->usb_device = usb_device; + new_hub->ops = &usb_hub_ops; + new_hub->hcd = hcd; + + new_hub->desc = usb_get_hub_descriptor(new_hub); + // usb_show_hub_descriptor(desc); + + usb_init_hub(hcd, new_hub, usb_device); + } + + usb_device->state = USB_STATE_INITED; + return 0; +} \ No newline at end of file diff --git a/src/drivers/usb/hid/hid.c b/src/drivers/usb/hid/hid.c index 41b4705..ee12be0 100644 --- a/src/drivers/usb/hid/hid.c +++ b/src/drivers/usb/hid/hid.c @@ -1,12 +1,11 @@ -#include "drivers/usb/hid.h" -#include "driver/usb/usb.h" -#include "driver/usb/usb_driver.h" -#include "string.h" +#include +#include #include #include #include #include #include +#include DriverResult usb_hid_probe(UsbDevice *device, UsbInterface *interface); @@ -19,10 +18,7 @@ DriverDependency usb_hid_dependencies[] = { }; Driver usb_hid_driver = { - .short_name = STRING_INIT("HID"), - .dependency_count = sizeof(usb_hid_dependencies) / sizeof(DriverDependency), - .dependencies = usb_hid_dependencies, - .init = NULL, + .short_name = STRING_INIT("HID"), }; UsbDriver usb_hid_usb_driver = { .driver = &usb_hid_driver, @@ -35,7 +31,7 @@ DriverResult usb_hid_probe(UsbDevice *usb_device, UsbInterface *interface) { switch (interface->desc->bInterfaceSubClass) { case USB_HID_SUBCLASS_NO: // printk("HID Interface Found\n"); - return DRIVER_RESULT_UNSUPPORT_DEVICE; + return DRIVER_ERROR_UNSUPPORT_DEVICE; case USB_HID_SUBCLASS_BOOT: // printk("HID Boot Interface Found\n"); break; @@ -64,7 +60,7 @@ DriverResult usb_hid_probe(UsbDevice *usb_device, UsbInterface *interface) { interface->desc->bInterfaceProtocol); break; } - return DRIVER_RESULT_OK; + return DRIVER_OK; } static __init void usb_hid_driver_entry(void) { diff --git a/src/drivers/usb/hid/keyboard.c b/src/drivers/usb/hid/keyboard.c index 703d97d..760da0f 100644 --- a/src/drivers/usb/hid/keyboard.c +++ b/src/drivers/usb/hid/keyboard.c @@ -1,46 +1,35 @@ -#include "driver/usb/descriptors.h" -#include "driver/usb/usb_dm.h" -#include "kernel/dynamic_device_manager.h" -#include "kernel/list.h" #include -#include +#include +#include +#include #include #include #include #include #include #include +#include #include +#include #include #include #include DeviceDriver usb_hid_keyboard_device_driver; -DriverResult usb_hid_keyboard_init(Device *device); -DriverResult usb_hid_keyboard_start(Device *device); +DriverResult usb_hid_keyboard_init(void *_device); +DriverResult usb_hid_keyboard_start(void *_device); -DeviceDriverOps usb_hid_keyboard_device_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, -}; DeviceOps usb_hid_keyboard_device_ops = { .init = usb_hid_keyboard_init, .start = usb_hid_keyboard_start, .destroy = NULL, - .status = NULL, .stop = NULL, }; -DeviceDriver usb_hid_keyboard_device_driver = { - .name = STRING_INIT("USB HID Keyboard Driver"), - .priority = DRIVER_PRIORITY_GENERAL, - .type = DEVICE_TYPE_USB, - .private_data_size = 0, - .ops = &usb_hid_keyboard_device_driver_ops, -}; -InputDevice usb_hid_keyboard_input_device = { - .type = INPUT_TYPE_KEYBOARD, +DeviceDriver usb_hid_keyboard_device_driver; +InputDevice usb_hid_keyboard_input_device = { + .type = INPUT_TYPE_KEYBOARD, }; void usb_hid_keyboard_handler(UsbRequestBlock *urb) { @@ -113,7 +102,8 @@ void usb_hid_keyboard_handler(UsbRequestBlock *urb) { } } -DriverResult usb_hid_keyboard_init(Device *device) { +DriverResult usb_hid_keyboard_init(void *_device) { + LogicalDevice *device = _device; UsbHidKeyboard *keyboard = device->private_data; struct UsbInterfaceDescriptor *interface = keyboard->interface->desc; @@ -134,46 +124,39 @@ DriverResult usb_hid_keyboard_init(Device *device) { break; } } - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult usb_hid_keyboard_start(Device *device) { +DriverResult usb_hid_keyboard_start(void *_device) { + LogicalDevice *device = _device; UsbHidKeyboard *keyboard = device->private_data; UsbEndpoint *ep = keyboard->urb->ep; ep->data_toggle = 1; keyboard->usb_device->hcd->ops->add_interrupt_transfer( keyboard->usb_device->hcd, keyboard->usb_device, ep, keyboard->urb); - // UsbControlRequest req = USB_BUILD_REQUEST( - // USB_REQ_HOST_TO_DEVICE, USB_REQ_TYPE_CLASS, USB_REQ_RECIPIENT_INTERFACE, - // 0x0b, 0x00, 0x00, keyboard->interface->desc->bInterfaceNumber, 0); - // uint8_t data = 0; - // keyboard->usb_device->hcd->ops->ctrl_transfer_out( - // keyboard->usb_device->hcd, keyboard->usb_device, &data, 0, &req); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult usb_hid_keyboard_probe( UsbDevice *usb_device, UsbInterface *interface) { - Device *device = kmalloc(sizeof(Device)); - device->private_data_size = sizeof(UsbHidKeyboard); - string_new(&device->name, "USB HID Keyboard", 14); - device->device_driver = &usb_hid_keyboard_device_driver; - device->ops = &usb_hid_keyboard_device_ops; - device->state = DEVICE_STATE_UNREGISTERED; + PhysicalDevice *physical_device = usb_device->device; + interface->usb_driver = &usb_hid_usb_driver; - register_input_device( - &usb_hid_keyboard_device_driver, device, usb_device->device->bus, - &usb_hid_keyboard_input_device); + InputDevice *input_device; + DRIVER_RESULT_PASS(create_input_device( + &input_device, INPUT_TYPE_KEYBOARD, &usb_hid_keyboard_device_ops, + physical_device, &usb_hid_keyboard_device_driver)); - UsbHidKeyboard *keyboard = device->private_data; - keyboard->device = device; - keyboard->usb_device = usb_device; - keyboard->interface = interface; + UsbHidKeyboard *keyboard = kmalloc(sizeof(UsbHidKeyboard)); + keyboard->device = input_device; + keyboard->usb_device = usb_device; + keyboard->interface = interface; + input_device->device->private_data = keyboard; - list_add_tail(&device->new_device_list, &new_device_lh); + usb_device->state = USB_STATE_ACTIVE; - return DRIVER_RESULT_OK; + return DRIVER_OK; } static __init void usb_hid_keyboard_initcall() { diff --git a/src/drivers/usb/hid/mouse.c b/src/drivers/usb/hid/mouse.c index 60752e0..1fb66ca 100644 --- a/src/drivers/usb/hid/mouse.c +++ b/src/drivers/usb/hid/mouse.c @@ -1,45 +1,33 @@ -#include "driver/input/input_dm.h" -#include "driver/usb/descriptors.h" -#include "driver/usb/usb_dm.h" -#include "kernel/dynamic_device_manager.h" -#include "kernel/list.h" -#include +#include +#include +#include #include #include #include #include #include #include +#include #include +#include #include #include DeviceDriver usb_hid_mouse_device_driver; -DriverResult usb_hid_mouse_init(Device *device); -DriverResult usb_hid_mouse_start(Device *device); +DriverResult usb_hid_mouse_init(void *_device); +DriverResult usb_hid_mouse_start(void *_device); -DeviceDriverOps usb_hid_mouse_device_driver_ops = { - .device_driver_init = NULL, - .device_driver_uninit = NULL, -}; DeviceOps usb_hid_mouse_device_ops = { .init = usb_hid_mouse_init, .start = usb_hid_mouse_start, .destroy = NULL, - .status = NULL, .stop = NULL, }; -DeviceDriver usb_hid_mouse_device_driver = { - .name = STRING_INIT("USB HID Mouse Driver"), - .priority = DRIVER_PRIORITY_GENERAL, - .type = DEVICE_TYPE_USB, - .private_data_size = 0, - .ops = &usb_hid_mouse_device_driver_ops, -}; -InputDevice usb_hid_mouse_input_device = { - .type = INPUT_TYPE_MOUSE, +DeviceDriver usb_hid_mouse_device_driver; +InputDevice usb_hid_mouse_input_device = { + .type = INPUT_TYPE_MOUSE, }; void usb_hid_mouse_handler(UsbRequestBlock *urb) { @@ -73,7 +61,8 @@ void usb_hid_mouse_handler(UsbRequestBlock *urb) { } } -DriverResult usb_hid_mouse_init(Device *device) { +DriverResult usb_hid_mouse_init(void *_device) { + LogicalDevice *device = _device; UsbHidMouse *mouse = device->private_data; struct UsbInterfaceDescriptor *interface = mouse->interface->desc; @@ -83,6 +72,10 @@ DriverResult usb_hid_mouse_init(Device *device) { if ((ep->desc->bmAttributes & 0x03) == USB_EP_INTERRUPT && (ep->desc->bEndpointAddress >> 7) == USB_EP_IN) { // 找到中断输入端点 + printk( + "Mouse Interrupt IN Endpoint Found: 0x%02x\n", + ep->desc->bEndpointAddress); + int size = ep->desc->wMaxPacketSize & 0x7ff; mouse->buffer = kmalloc(size); mouse->urb = usb_create_urb( @@ -90,40 +83,39 @@ DriverResult usb_hid_mouse_init(Device *device) { break; } } - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult usb_hid_mouse_start(Device *device) { - UsbHidMouse *mouse = device->private_data; - UsbEndpoint *ep = mouse->urb->ep; - ep->data_toggle = 1; +DriverResult usb_hid_mouse_start(void *_device) { + LogicalDevice *device = _device; + UsbHidMouse *mouse = device->private_data; + UsbEndpoint *ep = mouse->urb->ep; + ep->data_toggle = 1; mouse->usb_device->hcd->ops->add_interrupt_transfer( mouse->usb_device->hcd, mouse->usb_device, ep, mouse->urb); - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult usb_hid_mouse_probe( UsbDevice *usb_device, UsbInterface *interface) { - Device *device = kmalloc(sizeof(Device)); - device->private_data_size = sizeof(UsbHidMouse); - string_new(&device->name, "UsbHidMouse", 12); - device->device_driver = &usb_hid_mouse_device_driver; - device->ops = &usb_hid_mouse_device_ops; - device->state = DEVICE_STATE_UNREGISTERED; + PhysicalDevice *physical_device = usb_device->device; + interface->usb_driver = &usb_hid_usb_driver; - register_input_device( - &usb_hid_mouse_device_driver, device, usb_device->device->bus, - &usb_hid_mouse_input_device); + InputDevice *input_device; + DRIVER_RESULT_PASS(create_input_device( + &input_device, INPUT_TYPE_MOUSE, &usb_hid_mouse_device_ops, + physical_device, &usb_hid_mouse_device_driver)); - UsbHidMouse *mouse = device->private_data; - mouse->device = device; - mouse->usb_device = usb_device; - mouse->interface = interface; + UsbHidMouse *mouse = kmalloc(sizeof(UsbHidMouse)); + mouse->device = input_device; + mouse->usb_device = usb_device; + mouse->interface = interface; + input_device->device->private_data = mouse; - list_add_tail(&device->new_device_list, &new_device_lh); + usb_device->state = USB_STATE_ACTIVE; - return DRIVER_RESULT_OK; + return DRIVER_OK; } static __init void usb_hid_mouse_initcall() { diff --git a/src/fs/fat/dir.c b/src/fs/fat/dir.c index 06fcbe0..c68139d 100644 --- a/src/fs/fat/dir.c +++ b/src/fs/fat/dir.c @@ -190,11 +190,6 @@ FsResult fat32_dir_lookup( MRET(location).first_cluster = short_dir->first_cluster_high << 16 | short_dir->first_cluster_low; MRET(short_dir) = *short_dir; - // MRET(entry) = generate_dir_entry( - // fat_info, parent_entry, short_dir, name, - // short_dir->attr & ATTR_DIRECTORY, iter.last_cluster, - // iter.last_entry_index, iter.longname_cluster, - // iter.longname_entry_index); return FS_OK; } } @@ -233,11 +228,6 @@ FsResult fat_dir_lookup( MRET(location).first_cluster = short_dir->first_cluster_high << 16 | short_dir->first_cluster_low; MRET(short_dir) = *short_dir; - // MRET(entry) = generate_dir_entry( - // fat_info, parent_entry, short_dir, name, - // short_dir->attr & ATTR_DIRECTORY, iter.last_cluster, - // iter.last_entry_index, iter.longname_cluster, - // iter.longname_entry_index); return FS_OK; } } diff --git a/src/fs/fat/entry.c b/src/fs/fat/entry.c index 654bfe9..21243a2 100644 --- a/src/fs/fat/entry.c +++ b/src/fs/fat/entry.c @@ -187,14 +187,14 @@ PUBLIC FatDirEntry *generate_dir_entry( if (is_directory) { FsResult result = fs_obj_create_dir( - parent_entry->object, fat_info->fs_info, entry->name, &object, + parent_entry->object, fat_info->fs_info, &entry->name, &object, _attr); if (result != FS_OK) { return NULL; } object->value.directory.data = entry; entry_cache_init(fat_info, entry, fat_info->bytes_per_cluster); } else { FsResult result = fs_obj_create_file( - parent_entry->object, fat_info->fs_info, entry->name, &object, + parent_entry->object, fat_info->fs_info, &entry->name, &object, _attr); if (result != FS_OK) { return NULL; } object->value.file.data = entry; @@ -216,7 +216,7 @@ PUBLIC FsResult fat_create_entry( Time time; DriverResult result = get_current_time(TIME_TYPE_LOCAL, &time); - if (result != DRIVER_RESULT_OK) { return FS_ERROR_OTHER; } + if (result != DRIVER_OK) { return FS_ERROR_OTHER; } TimeFull full_time = time.time; uint16_t cur_time = FAT_TIME(full_time.hour, full_time.minute, full_time.second); diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c index 84b4e24..7a3b3fe 100644 --- a/src/fs/fat/fat.c +++ b/src/fs/fat/fat.c @@ -177,7 +177,7 @@ FsResult fat_mount(FileSystemInfo *fs_info, Object *root_object) { root_object->fs_info->file_ops = fat_file_ops; root_object->fs_info->dir_ops = fat_dir_ops; fat_info->storage_device = - fs_info->partition->storage_object->value.device->dm_ext; + fs_info->partition->storage_object->value.device.logical->dm_ext; return FS_OK; } diff --git a/src/fs/fs.c b/src/fs/fs.c index 2d31c68..d66f207 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c @@ -1,11 +1,11 @@ -#include "objects/transfer.h" -#include "stdint.h" #include #include #include #include #include #include +#include +#include LIST_HEAD(fs_list_head); @@ -45,7 +45,7 @@ TransferResult fs_obj_write( } FsResult fs_obj_create_file( - Object *parent, FileSystemInfo *info, string_t name, Object **object, + Object *parent, FileSystemInfo *info, string_t *name, Object **object, ObjectAttr *attr) { *object = create_object(parent, name, *attr); Object *out = *object; @@ -62,7 +62,7 @@ FsResult fs_obj_create_file( } FsResult fs_obj_create_dir( - Object *parent, FileSystemInfo *info, string_t name, Object **object, + Object *parent, FileSystemInfo *info, string_t *name, Object **object, ObjectAttr *attr) { *object = create_object_directory(parent, name, *attr); Object *out = *object; diff --git a/src/include/driver/bus_dm.h b/src/include/driver/bus_dm.h index e0fc86a..c1b6b57 100644 --- a/src/include/driver/bus_dm.h +++ b/src/include/driver/bus_dm.h @@ -1,24 +1,7 @@ #ifndef _BUS_DM_H #define _BUS_DM_H -#include "kernel/bus_driver.h" -#include "kernel/device.h" -#include "objects/object.h" -#include "string.h" - -typedef struct BusControllerDeviceOps { - void (*probe)(Device *device); -} BusControllerDeviceOps; - -typedef struct BusControllerDevice { - string_t short_name; - Device *device; - BusDriver *bus_driver; - BusControllerDeviceOps *bus_controller_ops; -} BusControllerDevice; - -DriverResult register_bus_controller_device( - DeviceDriver *device_driver, BusDriver *bus_driver, Device *device, - BusControllerDevice *bus_controller_device, ObjectAttr *attr); +#include +extern DeviceManager bus_controller_dm; #endif \ No newline at end of file diff --git a/src/include/driver/framebuffer/fb_dm.h b/src/include/driver/framebuffer/fb_dm.h index feaa8d1..b95a154 100644 --- a/src/include/driver/framebuffer/fb_dm.h +++ b/src/include/driver/framebuffer/fb_dm.h @@ -1,14 +1,13 @@ #ifndef _FRAMEBUFFER_DM_H #define _FRAMEBUFFER_DM_H -#include "kernel/device.h" -#include "kernel/device_driver.h" -#include "kernel/list.h" -#include "objects/object.h" -#include "stdint.h" #include #include #include +#include +#include +#include +#include typedef struct FrameBufferModeInfo { uint16_t width; @@ -20,7 +19,7 @@ typedef struct FrameBufferModeInfo { typedef struct FrameBufferDevice { list_t fb_list_lh; - Device *device; + LogicalDevice *device; FrameBufferModeInfo mode_info; uint8_t *framebuffer_address; @@ -30,17 +29,18 @@ typedef struct FrameBufferDevice { } FrameBufferDevice; typedef struct FrameBufferDeviceManager { - Device *main_display_device; - uint8_t fb_device_count; + LogicalDevice *main_display_device; + uint8_t new_fb_device_num; + uint8_t fb_device_count; } FrameBufferDeviceManager; extern struct DeviceManager framebuffer_dm; -DriverResult register_framebuffer_device( - DeviceDriver *device_driver, Device *device, FrameBufferDevice *fb_device, - ObjectAttr *attr); -DriverResult unregister_framebuffer_devce( - DeviceDriver *device_driver, Device *device, FrameBufferDevice *fb_device); +DriverResult create_framebuffer_device( + FrameBufferDevice **fb_device, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver); +DriverResult delete_framebuffer_device(FrameBufferDevice *framebuffer_device); +DriverResult framebuffer_start_all(); DriverResult framebuffer_get_device( int in_index, FrameBufferDevice **out_device); #endif \ No newline at end of file diff --git a/src/include/driver/input/input_dm.h b/src/include/driver/input/input_dm.h index 7b974c5..00a5422 100644 --- a/src/include/driver/input/input_dm.h +++ b/src/include/driver/input/input_dm.h @@ -1,6 +1,7 @@ #ifndef _INPUT_DM_H #define _INPUT_DM_H +#include "kernel/spinlock.h" #include #include #include @@ -21,7 +22,7 @@ typedef enum { } InputDeviceType; typedef struct InputDevice { - Device *device; + LogicalDevice *device; InputDeviceType type; } InputDevice; @@ -42,7 +43,9 @@ typedef struct PointerEvent { } PointerEvent; typedef struct InputDeviceManager { - int device_count[INPUT_TYPE_MAX]; + int new_device_num[INPUT_TYPE_MAX]; + int device_count[INPUT_TYPE_MAX]; + spinlock_t lock[INPUT_TYPE_MAX]; int key_event_w, key_event_r; KeyEvent *key_events; @@ -51,9 +54,10 @@ typedef struct InputDeviceManager { PointerEvent *pointer_events; } InputDeviceManager; -DriverResult register_input_device( - DeviceDriver *device_driver, Device *device, Bus *bus, - InputDevice *input_device); +DriverResult create_input_device( + InputDevice **input_device, InputDeviceType type, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver); +DriverResult delete_input_device(InputDevice *input_device); extern DeviceManager input_dm; diff --git a/src/include/driver/interrupt_dm.h b/src/include/driver/interrupt/interrupt_dm.h similarity index 66% rename from src/include/driver/interrupt_dm.h rename to src/include/driver/interrupt/interrupt_dm.h index a6a8279..fe82421 100644 --- a/src/include/driver/interrupt_dm.h +++ b/src/include/driver/interrupt/interrupt_dm.h @@ -1,10 +1,10 @@ #ifndef _INTERRUPT_DM_H #define _INTERRUPT_DM_H -#include "kernel/device.h" -#include "kernel/device_driver.h" -#include "kernel/device_manager.h" -#include "kernel/driver.h" +#include +#include +#include +#include #include struct InterruptDevice; @@ -17,14 +17,15 @@ typedef struct InterruptDeviceOps { } InterruptDeviceOps; typedef struct InterruptDevice { - Device *device; - InterruptDeviceOps *interrupt_ops; + LogicalDevice *device; + InterruptDeviceOps *ops; uint8_t priority; } InterruptDevice; -DriverResult register_interrupt_device( - DeviceDriver *device_driver, Device *device, - InterruptDevice *interrupt_device); +DriverResult create_interrupt_device( + InterruptDevice **interrupt_device, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver, + InterruptDeviceOps *int_ops, int priority); extern struct DeviceManager interrupt_dm; diff --git a/src/include/driver/network/buffer.h b/src/include/driver/network/buffer.h index 414372d..0878753 100644 --- a/src/include/driver/network/buffer.h +++ b/src/include/driver/network/buffer.h @@ -22,6 +22,7 @@ typedef struct NetBuffer { } NetBuffer; NetBuffer *net_buffer_create(uint16_t size); +void net_buffer_delete(NetBuffer *buffer); void net_buffer_init( NetBuffer *buffer, uint16_t size, uint16_t head, uint16_t tail); diff --git a/src/include/driver/network/conn.h b/src/include/driver/network/conn.h index 3600ed9..faeca59 100644 --- a/src/include/driver/network/conn.h +++ b/src/include/driver/network/conn.h @@ -1,15 +1,15 @@ #ifndef _NET_CONN_H #define _NET_CONN_H -#include "buffer.h" -#include "driver/network/ethernet/ethernet.h" -#include "driver/network/network_dm.h" -#include "driver/network/protocols/ipv4/ipv4.h" -#include "kernel/list.h" -#include "kernel/spinlock.h" -#include "kernel/thread.h" -#include "objects/handle.h" -#include "objects/object.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #define NET_CONN_MAX_PROTOCOLS 8 diff --git a/src/include/driver/network/ethernet/ethernet.h b/src/include/driver/network/ethernet/ethernet.h index 484a9e5..9f7ed39 100644 --- a/src/include/driver/network/ethernet/ethernet.h +++ b/src/include/driver/network/ethernet/ethernet.h @@ -1,10 +1,10 @@ #ifndef _NETWORK_ETHERNET_H #define _NETWORK_ETHERNET_H -#include "driver/network/buffer.h" -#include "driver/network/network_dm.h" -#include "driver/network/protocols/protocols.h" -#include "driver/timer_dm.h" +#include +#include +#include +#include #include #define ETH_MAX_FRAME_SIZE 1792 diff --git a/src/include/driver/network/network_dm.h b/src/include/driver/network/network_dm.h index 4f5b6aa..84c5563 100644 --- a/src/include/driver/network/network_dm.h +++ b/src/include/driver/network/network_dm.h @@ -1,13 +1,14 @@ #ifndef _NETWORK_DM_H #define _NETWORK_DM_H -#include "kernel/device.h" -#include "kernel/device_driver.h" -#include "kernel/device_manager.h" -#include "kernel/driver.h" -#include "net_queue.h" -#include "objects/transfer.h" -#include "protocols/protocols.h" +#include +#include +#include +#include +#include +#include +#include +#include #include #define NETWORK_SEND(device, conn) \ @@ -17,7 +18,7 @@ struct NetworkDevice; typedef struct NetworkDeviceOps { TransferResult (*send)(struct NetworkDevice *device, void *buf, int length); -} NetworkDeviceOps; +} NetworkOps; typedef struct NetworkDeviceCapabilities { } NetworkDeviceCapabilities; @@ -34,20 +35,16 @@ typedef enum NetworkDeviceState { } NetworkDeviceState; typedef struct NetworkDevice { - Device *device; + LogicalDevice *device; + NetworkDeviceType type; NetworkDeviceCapabilities capabilities; - NetworkDeviceOps *ops; + NetworkOps *ops; - uint16_t head_size; - uint16_t tail_size; - int mtu; + int mtu; NetworkDeviceState state; NetworkQueue tx_queue; - void *private_data; - - NetworkDeviceType type; union { struct EthernetDevice *ethernet; }; @@ -63,14 +60,17 @@ typedef struct NetworkDevice { } NetworkDevice; typedef struct NetworkDeviceManager { + int new_device_num; int device_count; } NetworkDeviceManager; extern DeviceManager network_dm; -DriverResult register_network_device( - DeviceDriver *driver, Device *device, NetworkDevice *network_device, - ObjectAttr *attr); +DriverResult create_network_device( + NetworkDevice **network_device, NetworkDeviceType type, + NetworkDeviceCapabilities caps, NetworkOps *net_ops, DeviceOps *ops, + PhysicalDevice *device, DeviceDriver *device_driver); +DriverResult delete_network_device(NetworkDevice *network_device); NetworkDevice *network_get_device(Object *object); diff --git a/src/include/driver/network/protocols/ipv4/dhcp.h b/src/include/driver/network/protocols/ipv4/dhcp.h index 0a44333..ceff68a 100644 --- a/src/include/driver/network/protocols/ipv4/dhcp.h +++ b/src/include/driver/network/protocols/ipv4/dhcp.h @@ -1,11 +1,11 @@ #ifndef _DHCP_H #define _DHCP_H -#include "driver/network/conn.h" -#include "driver/network/network_dm.h" -#include "driver/timer_dm.h" -#include "math.h" -#include "stdint.h" +#include +#include +#include +#include +#include #define DHCP_OP_BOOTREQUEST 1 #define DHCP_OP_BOOTREPLY 2 diff --git a/src/include/driver/network/protocols/tcp.h b/src/include/driver/network/protocols/tcp.h index a7cdb30..e344f1e 100644 --- a/src/include/driver/network/protocols/tcp.h +++ b/src/include/driver/network/protocols/tcp.h @@ -1,8 +1,8 @@ #ifndef _TCP_H #define _TCP_H -#include "driver/network/conn.h" -#include +#include +#include #include #define TCP_FLAG_FIN 0x01 diff --git a/src/include/driver/serial/serial_dm.h b/src/include/driver/serial/serial_dm.h index 6a4d2dc..c57efac 100644 --- a/src/include/driver/serial/serial_dm.h +++ b/src/include/driver/serial/serial_dm.h @@ -28,24 +28,26 @@ typedef struct SerialDeviceOps { struct SerialDevice *serial, SerialBaudRate baud_rate); void (*set_recv_mode)( struct SerialDevice *serial, SerialReceiveMode recv_mode); -} SerialDeviceOps; +} SerialOps; typedef struct SerialDevice { - Device *device; - SerialDeviceOps *ops; + LogicalDevice *device; + SerialOps *ops; void (*receive)(uint8_t data); } SerialDevice; typedef struct SerialDeviceManager { + int new_device_num; int device_count; } SerialDeviceManager; extern DeviceManager serial_dm; -DriverResult register_serial_device( - DeviceDriver *device_driver, Device *device, Bus *bus, - SerialDevice *serial_device); +DriverResult create_serial_device( + SerialDevice **serial_device, SerialOps *serial_ops, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver); +DriverResult delete_serial_device(SerialDevice *serial_device); DriverResult serial_device_open( Object *serial_object, SerialBaudRate baud_rate, void (*receive)(uint8_t data)); diff --git a/src/include/driver/sound/pcm.h b/src/include/driver/sound/pcm.h index d792a6c..f206cf1 100644 --- a/src/include/driver/sound/pcm.h +++ b/src/include/driver/sound/pcm.h @@ -1,12 +1,13 @@ #ifndef _PCM_H #define _PCM_H -#include "kernel/device.h" -#include "kernel/dma.h" -#include "kernel/driver.h" -#include "kernel/spinlock.h" -#include "kernel/wait_queue.h" +#include +#include +#include +#include +#include #include +#include #include #define PCM_STATUS_FREE 0 diff --git a/src/include/driver/sound/sound_dm.h b/src/include/driver/sound/sound_dm.h index c3f7f1c..a7a8c61 100644 --- a/src/include/driver/sound/sound_dm.h +++ b/src/include/driver/sound/sound_dm.h @@ -1,10 +1,11 @@ #ifndef _SOUND_DM_H #define _SOUND_DM_H -#include "kernel/device.h" -#include "kernel/device_driver.h" -#include "kernel/device_manager.h" -#include "kernel/driver.h" +#include +#include +#include +#include +#include #include #define SOUND_DEVICE_MODE_PLAY 0 @@ -13,7 +14,7 @@ struct SoundDevice; typedef struct SoundDeviceOps { DriverResult (*set_volume)(struct SoundDevice *device, int volume); -} SoundDeviceOps; +} SoundOps; typedef struct SoundDeviceCapabilities { uint32_t record : 1; @@ -28,11 +29,9 @@ typedef enum SoundDeviceType { } SoundDeviceType; typedef struct SoundDevice { - Device *device; + LogicalDevice *device; SoundDeviceCapabilities capabilities; - SoundDeviceOps *ops; - - void *private_data; + SoundOps *ops; SoundDeviceType type; @@ -42,14 +41,17 @@ typedef struct SoundDevice { } SoundDevice; typedef struct SoundDeviceManager { + int new_device_num; int device_count; } SoundDeviceManager; extern DeviceManager sound_dm; -DriverResult register_sound_device( - DeviceDriver *driver, Device *device, SoundDevice *sound_device, - ObjectAttr *attr); +DriverResult create_sound_device( + SoundDevice **sound_device, SoundDeviceType type, + SoundDeviceCapabilities caps, SoundOps *sound_ops, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver); +DriverResult delete_sound_device(SoundDevice *sound_device); SoundDevice *sound_get_device(Object *object); diff --git a/src/include/driver/storage/storage_dm.h b/src/include/driver/storage/storage_dm.h index 25700c0..e75830b 100644 --- a/src/include/driver/storage/storage_dm.h +++ b/src/include/driver/storage/storage_dm.h @@ -1,15 +1,17 @@ #ifndef _STORAGE_DM_H #define _STORAGE_DM_H -#include "kernel/device_manager.h" -#include "kernel/driver.h" -#include "kernel/list.h" -#include "kernel/periodic_task.h" -#include "kernel/spinlock.h" -#include "kernel/wait_queue.h" -#include "objects/object.h" -#include "string.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include typedef enum StorageDeviceType { STORAGE_DEVICE_TYPE_UNKNOWN, @@ -30,7 +32,7 @@ typedef struct StorageDeviceOps { struct Object; typedef struct StorageDevice { - Device *device; + LogicalDevice *device; StorageDeviceType type; StorageDeviceOps *ops; @@ -63,11 +65,12 @@ typedef struct StorageDeviceDriver { extern DeviceManager storage_dm; -DriverResult register_storage_device( - struct DeviceDriver *device_driver, Device *device, - StorageDevice *storage_device, ObjectAttr *attr); +DriverResult create_storage_device( + StorageDevice **storage_device, StorageDeviceOps *storage_ops, + DeviceOps *ops, PhysicalDevice *physical_device, + DeviceDriver *device_driver); DriverResult unregister_storage_device( - struct DeviceDriver *device_driver, Device *device, + struct DeviceDriver *device_driver, PhysicalDevice *device, StorageDevice *storage_device); #endif \ No newline at end of file diff --git a/src/include/driver/time_dm.h b/src/include/driver/time_dm.h index e72152c..bcf3983 100644 --- a/src/include/driver/time_dm.h +++ b/src/include/driver/time_dm.h @@ -1,8 +1,9 @@ #ifndef _TIME_DM_H #define _TIME_DM_H -#include "kernel/device_driver.h" -#include "kernel/device_manager.h" +#include +#include +#include typedef enum TimeType { TIME_TYPE_UNIX_TIMESTAMP, // Unix时间戳 @@ -26,17 +27,17 @@ typedef union Time { } Time; struct TimeDevice; -typedef struct TimeDeviceOps { +typedef struct TimeOps { DriverResult (*get_time)( struct TimeDevice *device, TimeType type, Time *time); DriverResult (*set_time)( struct TimeDevice *device, TimeType type, Time *time); -} TimeDeviceOps; +} TimeOps; typedef struct TimeDevice { - Device *device; + LogicalDevice *device; TimeType type; - TimeDeviceOps *ops; + TimeOps *ops; } TimeDevice; typedef struct TimeDeviceManager { @@ -45,8 +46,10 @@ typedef struct TimeDeviceManager { extern DeviceManager time_dm; -DriverResult register_time_device( - DeviceDriver *driver, Device *device, TimeDevice *time_device); +DriverResult create_time_device( + TimeDevice **time_device, TimeOps *time_ops, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver); +DriverResult delete_time_device(TimeDevice *time_device); DriverResult get_current_time(TimeType type, Time *time); diff --git a/src/include/driver/timer_dm.h b/src/include/driver/timer/timer_dm.h similarity index 68% rename from src/include/driver/timer_dm.h rename to src/include/driver/timer/timer_dm.h index 339786f..c3acca6 100644 --- a/src/include/driver/timer_dm.h +++ b/src/include/driver/timer/timer_dm.h @@ -1,16 +1,17 @@ #ifndef _TIMER_DM_H #define _TIMER_DM_H -#include "kernel/device.h" -#include "kernel/device_driver.h" -#include "kernel/list.h" -#include "result.h" -#include "stdint.h" +#include +#include +#include +#include +#include typedef enum TimerResult { TIMER_RESULT_OK = 0, TIMER_RESULT_FREQ_TOO_LARGE, TIMER_RESULT_FREQ_TOO_SMALL, + TIMER_RESULT_UNSUPPORT, TIMER_RESULT_OTHER_ERROR, } TimerResult; @@ -30,12 +31,12 @@ typedef struct TimerOps { typedef struct TimerDevice { list_t timer_callback_lh; - Device *device; - uint32_t current_frequency; - uint32_t min_frequency; - uint32_t max_frequency; - uint32_t source_frequency; - uint32_t priority; + LogicalDevice *device; + uint32_t current_frequency; + uint32_t min_frequency; + uint32_t max_frequency; + uint32_t source_frequency; + uint32_t priority; uint32_t counter; @@ -57,18 +58,21 @@ typedef struct Timer { } Timer; typedef struct TimerDeviceManager { - Device *scheduler_timer; + LogicalDevice *scheduler_timer; } TimerDeviceManager; extern struct DeviceManager timer_dm; -DriverResult register_timer_device( - DeviceDriver *device_driver, Device *device, TimerDevice *timer_device); +DriverResult create_timer_device( + TimerDevice **timer_device, TimerOps *timer_ops, DeviceOps *ops, + PhysicalDevice *physical_device, DeviceDriver *device_driver); +DriverResult delete_timer_device(TimerDevice *timer_device); + DriverResult timer_init(Timer *timer); -void timer_irq_handler(Device *device); +void timer_irq_handler(LogicalDevice *device); uint32_t timer_count_ms(Timer *timer, uint32_t ms); int timer_get_schedule_tick(int priority); -DriverResult timer_set_frequency(Device *device, uint32_t frequency); +DriverResult timer_set_frequency(LogicalDevice *device, uint32_t frequency); void delay_ms(Timer *timer, uint32_t ms); void delay_ms_async(Timer *timer, uint32_t ms); bool timer_is_timeout(Timer *timer); diff --git a/src/include/driver/usb/usb_dm.h b/src/include/driver/usb/usb_dm.h deleted file mode 100644 index 159e53b..0000000 --- a/src/include/driver/usb/usb_dm.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _USB_DM_H -#define _USB_DM_H - -#include -#include -#include -#include -#include - -typedef struct UsbDevice { - list_t list; - uint8_t address; - - list_t ep_lh; - list_t interface_lh; - - UsbDeviceState state; - UsbHcd *hcd; - Device *device; - struct UsbHub *hub; - - struct UsbDeviceDescriptor *desc; - UsbDeviceSpeed speed; - struct UsbEndpoint *ep0; - - void *private_data; -} UsbDevice; - -typedef struct { - uint8_t hcd_count; - spinlock_t hcd_count_lock; -} UsbDeviceManager; - -extern UsbDeviceManager usb_dm_ext; -extern DeviceManager usb_dm; - -DriverResult register_usb_device( - DeviceDriver *driver, Device *device, UsbDevice *usb_device, - ObjectAttr *attr); - -#endif \ No newline at end of file diff --git a/src/include/drivers/bus/usb.h b/src/include/drivers/bus/usb.h deleted file mode 100644 index 1ccc02a..0000000 --- a/src/include/drivers/bus/usb.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _BUS_USB_H -#define _BUS_USB_H - -#include -#include -#include - -extern BusDriver usb_bus_driver; -extern Driver usb_driver; -extern list_t hci_lh; -extern DeviceOps usb_device_ops; - -typedef struct HciInit { - list_t list; - void (*init)(Driver *driver); -} HciInit; - -#endif \ No newline at end of file diff --git a/src/include/driver/usb/hcd.h b/src/include/drivers/bus/usb/hcd.h similarity index 75% rename from src/include/driver/usb/hcd.h rename to src/include/drivers/bus/usb/hcd.h index 20d2c8a..6b99904 100644 --- a/src/include/driver/usb/hcd.h +++ b/src/include/drivers/bus/usb/hcd.h @@ -1,13 +1,12 @@ #ifndef HCD_H #define HCD_H -#include "driver/bus_dm.h" #include #include #include #include +#include #include -#include struct UsbDevice; struct UsbRequestBlock; @@ -44,19 +43,20 @@ typedef struct UsbHcd { UsbHcdOps *ops; - string_t name; + // BusControllerDevice *bus_ctrlr_device; + LogicalDevice *device; + Bus *bus; - BusControllerDevice *bus_ctrlr_device; - Device *device; - Bus *bus; + uint8_t new_device_num; + uint8_t device_count; + spinlock_t lock; - uint8_t device_count; - - list_t usb_devices; + list_t usb_device_lh; } UsbHcd; -UsbHcd *usb_hcd_register( - DeviceDriver *device_driver, Device *device, char *name, int name_len, - uint32_t port_cnt, UsbHcdOps *ops); +DriverResult usb_create_hcd( + DEF_MRET(UsbHcd *, hcd), uint32_t port_cnt, UsbHcdOps *hcd_ops, + DeviceOps *ops, PhysicalDevice *physical_device, + DeviceDriver *device_driver); #endif // HCD_H \ No newline at end of file diff --git a/src/include/drivers/bus/usb/usb.h b/src/include/drivers/bus/usb/usb.h new file mode 100644 index 0000000..874b3d1 --- /dev/null +++ b/src/include/drivers/bus/usb/usb.h @@ -0,0 +1,33 @@ +#ifndef _BUS_USB_H +#define _BUS_USB_H + +#include +#include +#include +#include +#include + +typedef struct UsbDevice { + list_t list; + uint8_t address; + + list_t ep_lh; + list_t interface_lh; + + UsbDeviceState state; + UsbHcd *hcd; + PhysicalDevice *device; + struct UsbHub *hub; + + struct UsbDeviceDescriptor *desc; + UsbDeviceSpeed speed; + struct UsbEndpoint *ep0; + + void *private_data; +} UsbDevice; + +extern BusDriver usb_bus_driver; +extern Driver usb_driver; +extern DeviceOps usb_device_ops; + +#endif \ No newline at end of file diff --git a/src/include/driver/usb/usb_driver.h b/src/include/drivers/bus/usb/usb_driver.h similarity index 88% rename from src/include/driver/usb/usb_driver.h rename to src/include/drivers/bus/usb/usb_driver.h index 0b2e6bc..4a3524f 100644 --- a/src/include/driver/usb/usb_driver.h +++ b/src/include/drivers/bus/usb/usb_driver.h @@ -1,8 +1,7 @@ #ifndef _USB_DEVICE_DRIVER_H #define _USB_DEVICE_DRIVER_H -#include -#include +#include #include typedef struct UsbDriver { diff --git a/src/include/driver/usb/descriptors.h b/src/include/drivers/usb/core/descriptors.h similarity index 100% rename from src/include/driver/usb/descriptors.h rename to src/include/drivers/usb/core/descriptors.h diff --git a/src/include/driver/usb/func.h b/src/include/drivers/usb/core/func.h similarity index 50% rename from src/include/driver/usb/func.h rename to src/include/drivers/usb/core/func.h index 9d275a6..f5ef0f4 100644 --- a/src/include/driver/usb/func.h +++ b/src/include/drivers/usb/core/func.h @@ -1,71 +1,69 @@ #ifndef _USB_FUNC_H #define _USB_FUNC_H -#include -#include +#include +#include #define REQ_GET_PORT_STATUS_SIZE 4 void *usb_get_descriptor( UsbHcd *hcd, struct UsbDevice *device, uint8_t type, uint8_t recipient, - uint8_t index, UsbEndpoint *ep, uint8_t value_hi, uint8_t value_lo, - uint16_t desc_size); -#define usb_get_standard_descriptor( \ - hcd, device, recipient, index, ep, value_hi, value_lo, desc_size) \ - usb_get_descriptor( \ - hcd, device, USB_REQ_TYPE_STANDARD, recipient, index, ep, value_hi, \ + uint8_t index, uint8_t value_hi, uint8_t value_lo, uint16_t desc_size); +#define usb_get_standard_descriptor( \ + hcd, device, recipient, index, value_hi, value_lo, desc_size) \ + usb_get_descriptor( \ + hcd, device, USB_REQ_TYPE_STANDARD, recipient, index, value_hi, \ value_lo, desc_size) -#define usb_get_class_descriptor( \ - hcd, device, recipient, index, ep, value_hi, value_lo, desc_size) \ - usb_get_descriptor( \ - hcd, device, USB_REQ_TYPE_CLASS, recipient, index, ep, value_hi, \ - value_lo, desc_size) -#define usb_get_vendor_descriptor( \ - hcd, device, recipient, index, ep, value_hi, value_lo, desc_size) \ - usb_get_descriptor( \ - hcd, device, USB_REQ_TYPE_VENDOR, recipient, index, ep, value_hi, \ +#define usb_get_class_descriptor( \ + hcd, device, recipient, index, value_hi, value_lo, desc_size) \ + usb_get_descriptor( \ + hcd, device, USB_REQ_TYPE_CLASS, recipient, index, value_hi, value_lo, \ + desc_size) +#define usb_get_vendor_descriptor( \ + hcd, device, recipient, index, value_hi, value_lo, desc_size) \ + usb_get_descriptor( \ + hcd, device, USB_REQ_TYPE_VENDOR, recipient, index, value_hi, \ value_lo, desc_size) -#define usb_get_device_descriptor(hcd, device, ep) \ - usb_get_standard_descriptor( \ - hcd, device, USB_REQ_RECIPIENT_DEVICE, 0, ep, USB_DESC_TYPE_DEVICE, 0, \ +#define usb_get_device_descriptor(hcd, device) \ + usb_get_standard_descriptor( \ + hcd, device, USB_REQ_RECIPIENT_DEVICE, 0, USB_DESC_TYPE_DEVICE, 0, \ sizeof(struct UsbDeviceDescriptor)) -#define usb_get_interface_descriptor(hcd, device, ep) \ - usb_get_standard_descriptor( \ - hcd, device, USB_REQ_RECIPIENT_DEVICE, 0, ep, USB_DESC_TYPE_INTERFACE, \ - 0, sizeof(struct UsbInterfaceDescriptor)) +#define usb_get_interface_descriptor(hcd, device) \ + usb_get_standard_descriptor( \ + hcd, device, USB_REQ_RECIPIENT_DEVICE, 0, USB_DESC_TYPE_INTERFACE, 0, \ + sizeof(struct UsbInterfaceDescriptor)) void *usb_set_descriptor( UsbHcd *hcd, struct UsbDevice *device, uint8_t type, uint8_t recipient, - uint8_t index, UsbEndpoint *ep, uint8_t value_hi, uint8_t value_lo, - uint16_t desc_size); -#define usb_set_standard_descriptor( \ - hcd, device, recipient, index, ep, value_hi, value_lo, desc_size) \ - usb_set_descriptor( \ - hcd, device, USB_REQ_TYPE_STANDARD, recipient, index, ep, value_hi, \ - value_lo, desc_size) -#define usb_set_class_descriptor( \ - hcd, device, recipient, index, ep, value_hi, value_lo, desc_size) \ - usb_set_descriptor( \ - hcd, device, USB_REQ_TYPE_CLASS, recipient, index, ep, value_hi, \ + uint8_t index, uint8_t value_hi, uint8_t value_lo, uint16_t desc_size); +#define usb_set_standard_descriptor( \ + hcd, device, recipient, index, value_hi, value_lo, desc_size) \ + usb_set_descriptor( \ + hcd, device, USB_REQ_TYPE_STANDARD, recipient, index, value_hi, \ value_lo, desc_size) -#define usb_set_vendor_descriptor( \ - hcd, device, recipient, index, ep, value_hi, value_lo, desc_size) \ - usb_set_descriptor( \ - hcd, device, USB_REQ_TYPE_VENDOR, recipient, index, ep, value_hi, \ +#define usb_set_class_descriptor( \ + hcd, device, recipient, index, value_hi, value_lo, desc_size) \ + usb_set_descriptor( \ + hcd, device, USB_REQ_TYPE_CLASS, recipient, index, value_hi, value_lo, \ + desc_size) +#define usb_set_vendor_descriptor( \ + hcd, device, recipient, index, value_hi, value_lo, desc_size) \ + usb_set_descriptor( \ + hcd, device, USB_REQ_TYPE_VENDOR, recipient, index, value_hi, \ value_lo, desc_size) struct UsbConfigDescriptor *usb_get_config_descriptor( - UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep); + UsbHcd *hcd, struct UsbDevice *device); -uint8_t usb_get_config(UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep); +uint8_t usb_get_config(UsbHcd *hcd, struct UsbDevice *device); UsbSetupStatus usb_set_config( - UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep, uint8_t config); + UsbHcd *hcd, struct UsbDevice *device, uint8_t config); struct UsbHubDescriptor *usb_get_hub_descriptor(UsbHub *hub); UsbSetupStatus usb_set_address( - UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep, uint32_t address); + UsbHcd *hcd, struct UsbDevice *device, uint32_t address); UsbSetupStatus usb_clear_port_feature( UsbHub *hub, uint8_t port, uint16_t feature); @@ -76,11 +74,10 @@ uint32_t usb_get_hub_status(UsbHub *hub); uint32_t usb_get_port_status(UsbHub *hub, uint8_t port); struct UsbStringDescriptor *usb_get_string_descriptor( - UsbHcd *hcd, struct UsbDevice *device, uint8_t index, UsbEndpoint *ep); + UsbHcd *hcd, struct UsbDevice *device, uint8_t index); void usb_show_device_descriptor( - UsbHcd *hcd, struct UsbDevice *device, UsbEndpoint *ep, - struct UsbDeviceDescriptor *desc); + UsbHcd *hcd, struct UsbDevice *device, struct UsbDeviceDescriptor *desc); void usb_show_hub_descriptor(struct UsbHubDescriptor *desc); #endif \ No newline at end of file diff --git a/src/include/driver/usb/hub.h b/src/include/drivers/usb/core/hub.h similarity index 88% rename from src/include/driver/usb/hub.h rename to src/include/drivers/usb/core/hub.h index 89dbbbe..9caca7d 100644 --- a/src/include/driver/usb/hub.h +++ b/src/include/drivers/usb/core/hub.h @@ -1,8 +1,7 @@ #ifndef _USB_HUB_H #define _USB_HUB_H -#include -#include +#include #include #define HUB_FEAT_C_LOCAL_POWER 0 @@ -45,7 +44,6 @@ typedef struct UsbHubOps { extern UsbHubOps usb_hub_ops; -void usb_init_hub( - UsbHcd *hcd, UsbHub *hub, UsbEndpoint *ep0, struct UsbDevice *usb_device); +void usb_init_hub(UsbHcd *hcd, UsbHub *hub, struct UsbDevice *usb_device); #endif \ No newline at end of file diff --git a/src/include/driver/usb/urb.h b/src/include/drivers/usb/core/urb.h similarity index 93% rename from src/include/driver/usb/urb.h rename to src/include/drivers/usb/core/urb.h index 9528fb9..a243148 100644 --- a/src/include/driver/usb/urb.h +++ b/src/include/drivers/usb/core/urb.h @@ -1,7 +1,7 @@ #ifndef _USB_URB_H #define _USB_URB_H -#include +#include #include typedef struct UsbRequestBlock { diff --git a/src/include/driver/usb/usb.h b/src/include/drivers/usb/core/usb.h similarity index 94% rename from src/include/driver/usb/usb.h rename to src/include/drivers/usb/core/usb.h index 2fc7bf1..87a7052 100644 --- a/src/include/driver/usb/usb.h +++ b/src/include/drivers/usb/core/usb.h @@ -1,9 +1,9 @@ #ifndef _USB_H #define _USB_H -#include "driver/usb/descriptors.h" #include -#include +#include +#include #include #include #include @@ -62,8 +62,7 @@ .bmRequestType = direction << 7 | type << 5 | recipient, \ .bRequest = request_id, \ .wValue = HOST2LE_WORD(value_hi << 8 | value_lo), \ - .wIndex = HOST2LE_WORD(index), \ - .wLength = HOST2LE_WORD(length), \ + .wIndex = HOST2LE_WORD(index), .wLength = HOST2LE_WORD(length), \ } typedef enum UsbInterfaceType { @@ -206,8 +205,6 @@ void usb_init_endpoint( struct UsbDevice *usb_device, UsbEndpoint *ep, struct UsbEndpointDescriptor *desc); -int usb_init_device( - UsbHcd *hcd, UsbEndpoint *ep0, struct UsbEndpointDescriptor *ep_desc, - struct UsbDevice *usb_device); +int usb_probe_device(UsbHcd *hcd, struct UsbHub *hub, UsbDeviceSpeed speed); #endif \ No newline at end of file diff --git a/src/include/drivers/usb/hid.h b/src/include/drivers/usb/hid.h index 1621bd6..8a07464 100644 --- a/src/include/drivers/usb/hid.h +++ b/src/include/drivers/usb/hid.h @@ -1,7 +1,7 @@ #ifndef _USB_HID_H #define _USB_HID_H -#include +#include #include extern Driver usb_hid_driver; diff --git a/src/include/drivers/usb/keyboard.h b/src/include/drivers/usb/keyboard.h index d6620dd..756ed97 100644 --- a/src/include/drivers/usb/keyboard.h +++ b/src/include/drivers/usb/keyboard.h @@ -1,9 +1,10 @@ #ifndef _USB_HID_KEYBOARD_H #define _USB_HID_KEYBOARD_H -#include "driver/usb/usb.h" -#include "driver/usb/usb_dm.h" -#include +#include +#include +#include +#include #include #include #include @@ -15,7 +16,7 @@ typedef struct { } __attribute__((packed)) UsbHidKeyboardReport; typedef struct { - Device *device; + InputDevice *device; UsbDevice *usb_device; UsbInterface *interface; UsbRequestBlock *urb; diff --git a/src/include/drivers/usb/mouse.h b/src/include/drivers/usb/mouse.h index 3b0ff73..a5c3766 100644 --- a/src/include/drivers/usb/mouse.h +++ b/src/include/drivers/usb/mouse.h @@ -1,9 +1,10 @@ #ifndef _USB_HID_MOUSE_H #define _USB_HID_MOUSE_H -#include "driver/usb/usb.h" -#include "driver/usb/usb_dm.h" -#include +#include +#include +#include +#include #include #include #include @@ -15,7 +16,7 @@ typedef struct { } __attribute__((packed)) UsbHidMouseReport; typedef struct { - Device *device; + InputDevice *device; UsbDevice *usb_device; UsbInterface *interface; UsbRequestBlock *urb; diff --git a/src/include/fs/fs.h b/src/include/fs/fs.h index f58c177..1cad5e0 100644 --- a/src/include/fs/fs.h +++ b/src/include/fs/fs.h @@ -104,10 +104,10 @@ void register_fs(FileSystem *fs); void unregister_fs(FileSystem *fs); FsResult fs_obj_create_file( - Object *parent, FileSystemInfo *info, string_t name, Object **object, + Object *parent, FileSystemInfo *info, string_t *name, Object **object, ObjectAttr *attr); FsResult fs_obj_create_dir( - Object *parent, FileSystemInfo *info, string_t name, Object **object, + Object *parent, FileSystemInfo *info, string_t *name, Object **object, ObjectAttr *attr); #endif \ No newline at end of file diff --git a/src/include/kernel/app.h b/src/include/kernel/app.h index a9743f7..f0a5f74 100644 --- a/src/include/kernel/app.h +++ b/src/include/kernel/app.h @@ -5,11 +5,11 @@ #include struct prog_segment { - unsigned int offset; // 程序段在文件中的偏移 - unsigned int vaddr; // 程序段的虚拟地址 - unsigned int filesz; // 程序段在文件中的大小 - unsigned int memsz; // 程序段在内存中的大小 - list_t list; + unsigned int offset; // 程序段在文件中的偏移 + unsigned int vaddr; // 程序段的虚拟地址 + unsigned int filesz; // 程序段在文件中的大小 + unsigned int memsz; // 程序段在内存中的大小 + list_t list; }; /** @@ -18,12 +18,12 @@ struct prog_segment { * 记录了一个程序(*.elf)的相关信息 */ struct program_struct { - struct index_node *inode; - string_t name; // 程序名 - string_t filename; // 程序的源文件名 - string_t path; // 源文件路径 - unsigned int phnum; - list_t seg_head; + // struct index_node *inode; + string_t name; // 程序名 + string_t filename; // 程序的源文件名 + string_t path; // 源文件路径 + unsigned int phnum; + list_t seg_head; }; void run_app(char *path); diff --git a/src/include/kernel/bus_driver.h b/src/include/kernel/bus_driver.h index f2a1f9a..18d539f 100644 --- a/src/include/kernel/bus_driver.h +++ b/src/include/kernel/bus_driver.h @@ -1,20 +1,13 @@ #ifndef _BUS_DRIVER_H #define _BUS_DRIVER_H -#include "kernel/device_driver.h" -#include "kernel/driver.h" -#include "kernel/driver_manager.h" -#include "kernel/list.h" -#include "objects/object.h" -#include "string.h" +#include +#include +#include +#include +#include #include - -#define BUS_OPS_CALL(bus, func, ...) \ - { \ - if ((bus)->ops->func != NULL) { \ - DRV_RESULT_DELIVER_CALL((bus)->ops->func, __VA_ARGS__) \ - } \ - } +#include struct BusDriver; @@ -35,63 +28,50 @@ typedef struct BusDriverOps { } BusDriverOps; typedef struct BusOps { - DriverResult (*register_device_hook)(struct Device *device); - DriverResult (*unregister_device_hook)(struct Device *device); - DriverResult (*scan_bus)(struct BusDriver *bus_driver, struct Bus *bus); DriverResult (*probe_device)(struct BusDriver *bus_driver, struct Bus *bus); } BusOps; typedef struct BusDriver { - // 继承SubDriver特征 - SubDriver subdriver; - - list_t dm_list; list_t bus_lh; string_t name; - DriverType driver_type; BusType bus_type; DriverState state; Object *object; - uint32_t bus_count; - uint32_t device_count; + uint16_t new_bus_num; + uint16_t bus_count; - BusDriverOps *ops; - - void *private_data; - uint32_t private_data_size; + uint16_t new_device_num; + uint16_t device_count; } BusDriver; typedef struct Bus { - list_t device_lh; - list_t bus_list; - BusDriver *bus_driver; - Device *controller_device; + list_t device_lh; + list_t bus_list; + list_t bus_check_list; + list_t new_bus_list; + BusDriver *bus_driver; + struct Bus *primary_bus; string_t name; Object *object; - uint32_t last_device_num; uint32_t bus_num; uint32_t subordinate_bus_num; BusOps *ops; } Bus; -extern struct BusDriver *bus_drivers[BUS_TYPE_MAX]; -extern struct DriverManager bus_driver_manager; +extern struct BusDriver *bus_drivers[BUS_TYPE_MAX]; +DriverResult init_bus_manager(); DriverResult register_bus_driver( - Driver *driver, BusDriver *bus_driver, ObjectAttr *attr); -DriverResult unregister_bus_driver(Driver *driver, BusType type); -DriverResult register_bus( - BusDriver *bus_driver, Device *bus_controller_device, Bus *bus, - ObjectAttr *attr); -DriverResult unregister_bus(Bus *bus); -DriverResult bus_register_device(Device *device, Bus *bus, ObjectAttr *attr); -DriverResult bus_unregister_device(Device *device); + Driver *driver, BusType type, BusDriver *bus_driver, ObjectAttr *attr); +DriverResult unregister_bus_driver(BusDriver *bus_driver); +DriverResult create_bus(Bus **bus, BusDriver *bus_driver, BusOps *ops); +DriverResult delete_bus(Bus *bus); #endif \ No newline at end of file diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index e608e42..d170185 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -1,23 +1,21 @@ #ifndef _DEVICE_H #define _DEVICE_H -#include "kernel/driver.h" -#include "kernel/driver_interface.h" -#include "kernel/list.h" -#include "objects/object.h" -#include "objects/permission.h" -#include "stdint.h" -#include "string.h" -#include "types.h" +#include +#include +#include +#include +#include +#include #define device_print_error(device, str, ...) \ print_error(device->name.text, str, ##__VA_ARGS__) // 调用后自动传递错误 -#define DEV_OPS_CALL(dm, func, ...) \ - { \ - if ((dm)->ops->func != NULL) { \ - DRV_RESULT_DELIVER_CALL((dm)->ops->func, __VA_ARGS__) \ - } \ +#define DEV_OPS_CALL(dm, func) \ + { \ + if ((dm)->ops->func != NULL) { \ + DRIVER_RESULT_PASS((dm)->ops->func(dm)) \ + } \ } typedef enum { @@ -31,63 +29,71 @@ typedef enum { DEVICE_TYPE_BUS_CONTROLLER, DEVICE_TYPE_ETHERNET, DEVICE_TYPE_TIME, // 时间设备(如:Unix时间戳/UTC时间) - DEVICE_TYPE_USB, DEVICE_TYPE_SERIAL, DEVICE_TYPE_MAX, } DeviceType; -struct Device; - typedef struct DeviceOps { - DriverResult (*init)(struct Device *dev); // 初始化设备 - DriverResult (*start)(struct Device *dev); // 启动设备 - DriverResult (*stop)(struct Device *dev); // 停止设备 - DriverResult (*destroy)(struct Device *dev); // 销毁设备 - DriverResult (*status)(struct Device *dev); // 查询设备状态 + DriverResult (*init)(void *device); // 初始化设备 + DriverResult (*start)(void *device); // 启动设备 + DriverResult (*stop)(void *device); // 停止设备 + DriverResult (*destroy)(void *device); // 销毁设备 } DeviceOps; typedef enum { - DEVICE_STATE_UNREGISTERED, // 设备未注册 - DEVICE_STATE_REGISTERED, // 设备已注册 - DEVICE_STATE_READY, // 设备准备就绪 - DEVICE_STATE_ACTIVE, // 设备正在运行 - DEVICE_STATE_ERROR, // 设备错误 + DEVICE_STATE_UNINIT, // 设备未初始化 + DEVICE_STATE_READY, // 设备准备就绪 + DEVICE_STATE_ACTIVE, // 设备正在运行 + DEVICE_STATE_ERROR, // 设备错误 } DeviceState; -typedef struct ChildDevice { - bool is_using; - uint32_t id; - struct Device *parent; - void *private_data; -} ChildDevice; +typedef enum DeviceKind { + DEVICE_KIND_PHYSICAL, + DEVICE_KIND_LOGICAL, +} DeviceKind; + +typedef struct LogicalDevice { + DeviceKind kind; + DeviceState state; + list_t new_device_list; + + list_t logical_device_list; + list_t dm_list; + list_t device_list; + + DeviceType type; + DeviceOps *ops; + + struct PhysicalDevice *physical_device; + struct Object *object; + void *dm_ext; // 设备管理器所需的扩展信息 + + void *private_data; +} LogicalDevice; struct Bus; struct Object; struct DeviceDriver; -typedef struct Device { - list_t bus_list; - list_t device_list; - list_t dm_list; - list_t new_device_list; - string_t name; - DeviceState state; - struct DeviceDriver *device_driver; +typedef struct PhysicalDevice { + DeviceKind kind; + DeviceState state; + list_t new_device_list; + + list_t bus_list; + list_t logical_device_lh; + list_t irq_lh; + + int num; struct Bus *bus; struct Object *object; - DeviceIrq *irq; DeviceOps *ops; - uint32_t max_child_device; - ChildDevice *child_devices; - void **child_private_data; - - void *private_data; - uint32_t private_data_size; - void *dm_ext; // 设备管理器所需的扩展信息 -} Device; + void *private_data; + void *bus_ext; +} PhysicalDevice; static const Permission device_sys_permission = { .subject_id = SUBJECT_ID_SYSTEM, @@ -108,7 +114,7 @@ static const Permission device_admin_permission = { static const ObjectAttr device_object_attr = { .type = OBJECT_TYPE_DEVICE, - .size = sizeof(Device), + .size = sizeof(PhysicalDevice), .is_mounted = false, .owner_id = SUBJECT_ID_SYSTEM, .all_user_permission = device_all_user_permission, @@ -117,15 +123,34 @@ static const ObjectAttr device_object_attr = { .admin_permission = device_admin_permission, }; -DriverResult register_device( - struct DeviceDriver *device_driver, string_t *name, struct Bus *bus, - Device *device, ObjectAttr *attr); -DriverResult unregister_device( - struct DeviceDriver *device_driver, Device *device); -DriverResult unregister_child_device(ChildDevice *child_device); -DriverResult register_child_device(Device *device, int private_data_size); -DriverResult init_device(Device *device); -DriverResult start_device(Device *device); -DriverResult init_and_start(Device *device); +DriverResult create_physical_device( + PhysicalDevice **physical_device, struct Bus *bus, ObjectAttr *attr); +void register_physical_device(PhysicalDevice *physical_device, DeviceOps *ops); +DriverResult delete_physical_device(PhysicalDevice *physical_device); +DriverResult create_logical_device( + LogicalDevice **logical_device, PhysicalDevice *physical_device, + struct DeviceDriver *device_driver, DeviceOps *ops, DeviceType type); +DriverResult delete_logical_device(LogicalDevice *logical_device); +DriverResult init_physical_device(PhysicalDevice *device); +DriverResult start_physical_device(PhysicalDevice *device); +DriverResult init_logical_device(LogicalDevice *device); +DriverResult start_logical_device(LogicalDevice *device); + +#define init_and_start_physical_device(device) \ + ({ \ + DriverResult result = init_physical_device(device); \ + if (result == DRIVER_OK) result = start_physical_device(device); \ + result; \ + }) + +#define init_and_start_logical_device(device) \ + ({ \ + DriverResult result = init_logical_device(device); \ + if (result == DRIVER_OK) result = start_logical_device(device); \ + result; \ + }) + +extern list_t new_physical_device_lh; +extern list_t new_logical_device_lh; #endif \ No newline at end of file diff --git a/src/include/kernel/device_driver.h b/src/include/kernel/device_driver.h index a994f0f..407933f 100644 --- a/src/include/kernel/device_driver.h +++ b/src/include/kernel/device_driver.h @@ -1,19 +1,9 @@ #ifndef _DEVICE_DRIVER_H #define _DEVICE_DRIVER_H -#include "kernel/device.h" -#include "kernel/driver.h" -#include "kernel/list.h" -#include "stdint.h" -#include "string.h" - -// 调用后自动传递错误 -#define DRV_OPS_CALL(dm, func, ...) \ - { \ - if ((dm)->ops->func != NULL) { \ - DRV_RESULT_DELIVER_CALL((dm)->ops->func, __VA_ARGS__) \ - } \ - } +#include +#include +#include typedef enum { DRIVER_PRIORITY_BASIC, // 基础驱动 @@ -22,39 +12,15 @@ typedef enum { DRIVER_PRIORITY_EXCLUSIVE, // 专属驱动 } DriverPriority; -struct DeviceDriver; - -typedef struct DeviceDriverOps { - DriverResult (*device_driver_init)(struct DeviceDriver *driver); - DriverResult (*device_driver_uninit)(struct DeviceDriver *driver); -} DeviceDriverOps; - struct Bus; struct Object; typedef struct DeviceDriver { - // 继承SubDriver特征 - SubDriver subdriver; - - list_t bus_list; - list_t device_lh; - string_t name; - DeviceType type; - DriverPriority priority; - DriverState state; - - struct Object *object; - - DeviceDriverOps *ops; - - void *private_data; - uint32_t private_data_size; + list_t device_driver_list; + list_t device_lh; } DeviceDriver; -extern struct DriverManager device_driver_manager; - DriverResult register_device_driver( Driver *driver, DeviceDriver *device_driver); -DriverResult unregister_device_driver( - Driver *driver, DeviceDriver *device_driver); +DriverResult unregister_device_driver(DeviceDriver *device_driver); #endif \ No newline at end of file diff --git a/src/include/kernel/device_manager.h b/src/include/kernel/device_manager.h index 489ebf9..0ddbeb7 100644 --- a/src/include/kernel/device_manager.h +++ b/src/include/kernel/device_manager.h @@ -1,16 +1,9 @@ #ifndef _DEVICE_MANAGER_H #define _DEVICE_MANAGER_H -#include "kernel/device.h" -#include "kernel/driver.h" -#include "kernel/list.h" - -#define DEVM_OPS_CALL(dm, func, ...) \ - { \ - if ((dm)->ops->func != NULL) { \ - DRV_RESULT_DELIVER_CALL((dm)->ops->func, __VA_ARGS__) \ - } \ - } +#include +#include +#include struct DeviceManager; @@ -19,13 +12,13 @@ typedef struct DeviceMangerOps { DriverResult (*dm_unload)(struct DeviceManager *manager); DriverResult (*init_device_hook)( - struct DeviceManager *manager, Device *device); + struct DeviceManager *manager, LogicalDevice *device); DriverResult (*start_device_hook)( - struct DeviceManager *manager, Device *device); + struct DeviceManager *manager, LogicalDevice *device); DriverResult (*stop_device_hook)( - struct DeviceManager *manager, Device *device); + struct DeviceManager *manager, LogicalDevice *device); DriverResult (*destroy_device_hook)( - struct DeviceManager *manager, Device *device); + struct DeviceManager *manager, LogicalDevice *device); } DeviceManagerOps; typedef struct DeviceManager { @@ -41,7 +34,6 @@ typedef struct DeviceManager { extern DeviceManager *device_managers[DEVICE_TYPE_MAX]; -DriverResult register_device_manager(DeviceManager *manager); -DriverResult unregister_device_manager(DeviceManager *manager); +DriverResult init_device_managers(); #endif \ No newline at end of file diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index bb99bfe..1f5f9e5 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -35,29 +35,31 @@ static const ObjectAttr driver_object_attr = { }; typedef enum DriverResult { - DRIVER_RESULT_OK, - DRIVER_RESULT_TIMEOUT, - DRIVER_RESULT_ALREADY_EXIST, - DRIVER_RESULT_NOT_EXIST, - DRIVER_RESULT_DEVICE_DRIVER_CONFLICT, - DRIVER_RESULT_NO_OPS, - DRIVER_RESULT_INCOMPLETABLE_OPS, - DRIVER_RESULT_NO_VALID_CHILD_DEVICE, - DRIVER_RESULT_INVALID_IRQ_NUMBER, - DRIVER_RESULT_OUT_OF_MEMORY, - DRIVER_RESULT_NULL_POINTER, - DRIVER_RESULT_UNSUPPORT_DEVICE, - DRIVER_RESULT_UNSUPPORT_FEATURE, - DRIVER_RESULT_BUSY, - DRIVER_RESULT_EXCEED_MAX_SIZE, - DRIVER_RESULT_INVALID_TYPE, - DRIVER_RESULT_OTHER_ERROR, + DRIVER_OK, + DRIVER_ERROR_TIMEOUT, + DRIVER_ERROR_ALREADY_EXIST, + DRIVER_ERROR_NOT_EXIST, + DRIVER_ERROR_CONFLICT, + DRIVER_ERROR_NO_OPS, + DRIVER_ERROR_INCOMPLETABLE_OPS, + DRIVER_ERROR_INVALID_IRQ_NUMBER, + DRIVER_ERROR_OUT_OF_MEMORY, + DRIVER_ERROR_OBJECT, + DRIVER_ERROR_NULL_POINTER, + DRIVER_ERROR_UNSUPPORT_DEVICE, + DRIVER_ERROR_UNSUPPORT_FEATURE, + DRIVER_ERROR_BUSY, + DRIVER_ERROR_WAITING, + DRIVER_ERROR_EXCEED_MAX_SIZE, + DRIVER_ERROR_INVALID_TYPE, + DRIVER_ERROR_MEMORY_FREE, + DRIVER_ERROR_OTHER, } DriverResult; -#define DRIVER_RESULT_PASS(func) \ - { \ - DriverResult result = func; \ - if (result != DRIVER_RESULT_OK) { return result; } \ +#define DRIVER_RESULT_PASS(func) \ + { \ + DriverResult result = func; \ + if (result != DRIVER_OK) { return result; } \ } typedef enum { @@ -68,68 +70,38 @@ typedef enum { typedef enum { DRIVER_STATE_UNREGISTERED, // 驱动未注册 - DRIVER_STATE_UNINITED, // 驱动未初始化 - DRIVER_STATE_ACTIVE, // 驱动正在运行 + DRIVER_STATE_REGISTERED, // 驱动已注册 } DriverState; -typedef enum { - SUBDRIVER_STATE_UNREGISTERED, // 子驱动未注册 - SUBDRIVER_STATE_UNREADY, // 子驱动未准备好 - SUBDRIVER_STATE_READY, // 子驱动准备好 -} SubDriverState; - // 描述驱动程序的结构,管理着一个驱动下的所有类型的抽象驱动 typedef struct Driver { string_t short_name; - list_t driver_list; - list_t sub_driver_lh; + list_t device_driver_lh; list_t remapped_memory_lh; DriverState state; - - int dependency_count; - struct DriverDependency *dependencies; - - DriverResult (*init)(struct Driver *driver); } Driver; -struct DriverDenpendency; -typedef struct SubDriver { - list_t list; - list_t sub_driver_list; - Driver *driver; - DriverType type; - SubDriverState state; - - WaitQueue wq; -} SubDriver; - -extern list_t startup_dm_lh; - DriverResult register_driver(Driver *driver); DriverResult unregister_driver(Driver *driver); -DriverResult register_sub_driver( - Driver *driver, SubDriver *sub_driver, DriverType type); -DriverResult unregister_sub_driver(Driver *driver, SubDriver *sub_driver); -DriverResult driver_init(Driver *driver); DriverResult driver_start_all(void); void add_driver_objects(void); void print_driver_result( DriverResult result, char *file, int line, char *func_with_args); +extern list_t new_bus_lh; +extern list_t bus_lh; +extern list_t device_lh; +extern spinlock_t device_list_lock; extern struct Object driver_object; -#define DRV_PRINT_RESULT(result, func, ...) \ - print_driver_result(result, __FILE__, __LINE__, #func "(" #__VA_ARGS__ ")"); -#define DRV_RESULT_DELIVER_CALL(func, ...) \ - RESULT_DELIVER_CALL( \ - DriverResult, DRIVER_RESULT_OK, func, \ - { DRV_PRINT_RESULT(result, func, ...); }, __VA_ARGS__) +#define DRV_PRINT_RESULT(result, func) \ + print_driver_result(result, __FILE__, __LINE__, #func); -#define DRV_RESULT_PRINT_CALL(func, ...) \ - { \ - DriverResult result = func(__VA_ARGS__); \ - DRV_PRINT_RESULT(result, func, __VA_ARGS__); \ +#define DRV_RESULT_PRINT_CALL(func) \ + { \ + DriverResult result = func; \ + if (result != DRIVER_OK) DRV_PRINT_RESULT(result, func); \ } #endif \ No newline at end of file diff --git a/src/include/kernel/driver_interface.h b/src/include/kernel/driver_interface.h index f1c1550..b447b89 100644 --- a/src/include/kernel/driver_interface.h +++ b/src/include/kernel/driver_interface.h @@ -1,9 +1,13 @@ #ifndef _DRIVER_INTERFACE_H #define _DRIVER_INTERFACE_H +#include +#include +#include + #ifdef ARCH_X86 -#include "kernel/func.h" +#include #define io_in_byte(port) io_in8(port) #define io_in_word(port) io_in16(port) @@ -43,22 +47,28 @@ printk(COLOR_RED "[" source "]" str COLOR_RESET, ##__VA_ARGS__) #define print_warning(source, str, ...) \ printk(COLOR_BYELLOW "[%s]" str COLOR_RESET, source, ##__VA_ARGS__) -#define print_device_info(device, str, ...) \ - printk("[%s]" str COLOR_RESET, device->name.text, ##__VA_ARGS__) -#define print_driver_info(driver, str, ...) \ - printk("[%s]" str COLOR_RESET, driver.short_name.text, ##__VA_ARGS__) - -#include "kernel/list.h" -struct Device; -typedef void (*DeviceIrqHandler)(struct Device *device); +#define print_info(source, str, ...) \ + printk(COLOR_RESET "[%s]" str, source, ##__VA_ARGS__) + +struct PhysicalDevice; +typedef void (*DeviceIrqHandler)(void *device); + +typedef enum { + IRQ_MODE_SHARED, + IRQ_MODE_EXCLUSIVE, +} IrqMode; + typedef struct DeviceIrq { - list_t list; - int irq; - struct Device *device; - DeviceIrqHandler handler; + list_t list; + list_t irq_list; + int irq; + IrqMode mode; + + void *arg; + DeviceIrqHandler handler; + struct PhysicalDevice *physical_device; } DeviceIrq; -#include "stdint.h" typedef struct DriverRemappedMemory { list_t list; uint32_t vir_start; @@ -67,8 +77,13 @@ typedef struct DriverRemappedMemory { } DriverRemappedMemory; struct Driver; -enum DriverResult register_device_irq(DeviceIrq *dev_irq); +enum DriverResult register_device_irq( + DEF_MRET(DeviceIrq *, device_irq), struct PhysicalDevice *physical_device, + void *arg, int irq, DeviceIrqHandler irq_handler, IrqMode mode); enum DriverResult unregister_device_irq(DeviceIrq *dev_irq); +enum DriverResult enable_device_irq(DeviceIrq *dev_irq); +enum DriverResult disable_device_irq(DeviceIrq *dev_irq); + void device_irq_handler(int irq); enum DriverResult driver_remap_memory( struct Driver *in_driver, uint32_t in_physical_address, uint32_t in_size, diff --git a/src/include/kernel/driver_manager.h b/src/include/kernel/driver_manager.h deleted file mode 100644 index 07e8fa2..0000000 --- a/src/include/kernel/driver_manager.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _DRIVER_MANAGER_H -#define _DRIVER_MANAGER_H - -#include "kernel/device_driver.h" -#include "kernel/driver.h" -#include "kernel/list.h" -#include "result.h" - -// 调用后自动传递错误 -#define DM_OPS_CALL(dm, func, ...) \ - { \ - if ((dm)->ops->func != NULL) { \ - DRV_RESULT_DELIVER_CALL((dm)->ops->func, __VA_ARGS__) \ - } \ - } - -struct DriverManager; - -typedef struct DriverManagerOps { - DriverResult (*dm_load_hook)(struct DriverManager *driver_manager); - DriverResult (*register_device_driver_hook)( - struct DriverManager *driver_manager, struct DeviceDriver *driver); - DriverResult (*unregister_device_driver_hook)( - struct DriverManager *driver_manager, struct DeviceDriver *driver); - DriverResult (*dm_unload_hook)(struct DriverManager *driver_manager); -} DriverManagerOps; - -typedef struct DriverManager { - list_t dm_lh; - DriverType type; - DriverManagerOps *ops; - - void *private_data; -} DriverManager; - -extern DriverManager *driver_managers[DRIVER_TYPE_MAX]; - -DriverResult register_driver_manager(DriverManager *driver_manager); -DriverResult unregister_driver_manager(DriverManager *driver_manager); - -#endif \ No newline at end of file diff --git a/src/include/kernel/dynamic_device_manager.h b/src/include/kernel/dynamic_device_manager.h index 2fa4251..e44c38b 100644 --- a/src/include/kernel/dynamic_device_manager.h +++ b/src/include/kernel/dynamic_device_manager.h @@ -14,7 +14,7 @@ typedef struct DynamicDeviceEvents { typedef struct DynamicDevice { list_t list; - Device *device; + PhysicalDevice *device; } DynamicDevice; typedef struct DynamicDeviceManager { diff --git a/src/include/kernel/platform.h b/src/include/kernel/platform.h index 1d5e956..cb43806 100644 --- a/src/include/kernel/platform.h +++ b/src/include/kernel/platform.h @@ -1,9 +1,12 @@ #ifndef _PLATFORM_H -extern struct Bus platform_bus; +#include -void platform_early_init(); -void platform_init(); -void platform_start_devices(); +extern struct Bus *platform_bus; +extern struct PhysicalDevice *platform_device; + +void platform_early_init(); +DriverResult platform_init(); +void platform_start_devices(); #endif \ No newline at end of file diff --git a/src/include/objects/attr.h b/src/include/objects/attr.h new file mode 100644 index 0000000..b93ab95 --- /dev/null +++ b/src/include/objects/attr.h @@ -0,0 +1,37 @@ +#ifndef _OBJECT_ATTR_H +#define _OBJECT_ATTR_H + +#include +#include + +typedef enum ObjectType { + OBJECT_TYPE_TYPE, // 表示该对象用于表示一种对象类型 + OBJECT_TYPE_DIRECTORY, // 表示该对象是一个目录 + OBJECT_TYPE_DRIVER, // 表示该对象是一个驱动程序 + OBJECT_TYPE_DEVICE, // 表示该对象是一个设备 + OBJECT_TYPE_FILE, // 表示该对象是一个文件 + OBJECT_TYPE_VALUE, // 表示该对象是一个值 + OBJECT_TYPE_SYM_LINK, // 表示该对象是一个符号链接 + OBJECT_TYPE_PARTITION, // 表示该对象是一个分区 + OBJECT_TYPE_VOLUME, // 表示该对象是一个卷 + OBJECT_TYPE_BUILTIN_MAX, // 表示对象系统内建类型数量的最大值 +} ObjectType; + +typedef struct ObjectAttr { + ObjectType type; + size_t size; + + bool is_mounted; + size_t owner_id; + Permission all_user_permission; + Permission owner_permission; + Permission system_permission; + Permission admin_permission; + + list_t permission_lh; + + struct Object *object; + void *fs_location; +} ObjectAttr; + +#endif \ No newline at end of file diff --git a/src/include/objects/mount.h b/src/include/objects/mount.h index 16e0277..a2aef06 100644 --- a/src/include/objects/mount.h +++ b/src/include/objects/mount.h @@ -1,7 +1,7 @@ #ifndef _MOUNT_H #define _MOUNT_H -#include "objects/object.h" +#include ObjectResult object_mount(Object *origin, Object *dest); diff --git a/src/include/objects/object.h b/src/include/objects/object.h index 066818a..d729058 100644 --- a/src/include/objects/object.h +++ b/src/include/objects/object.h @@ -1,13 +1,13 @@ #ifndef _OBJECT_H #define _OBJECT_H -#include "dyn_array.h" -#include "kernel/list.h" -#include "objects/permission.h" -#include "objects/transfer.h" -#include "stdint.h" -#include "string.h" +#include +#include +#include +#include +#include #include +#include typedef enum ObjectResult { OBJECT_OK, @@ -33,36 +33,6 @@ typedef enum ObjectResult { #define OBJECT_DIR_SIZE_MEDIUM 16 #define OBJECT_DIR_SIZE_LARGE 32 -typedef enum ObjectType { - OBJECT_TYPE_TYPE, // 表示该对象用于表示一种对象类型 - OBJECT_TYPE_DIRECTORY, // 表示该对象是一个目录 - OBJECT_TYPE_DRIVER, // 表示该对象是一个驱动程序 - OBJECT_TYPE_DEVICE, // 表示该对象是一个设备 - OBJECT_TYPE_FILE, // 表示该对象是一个文件 - OBJECT_TYPE_VALUE, // 表示该对象是一个值 - OBJECT_TYPE_SYM_LINK, // 表示该对象是一个符号链接 - OBJECT_TYPE_PARTITION, // 表示该对象是一个分区 - OBJECT_TYPE_VOLUME, // 表示该对象是一个卷 - OBJECT_TYPE_BUILTIN_MAX, // 表示对象系统内建类型数量的最大值 -} ObjectType; - -typedef struct ObjectAttr { - ObjectType type; - size_t size; - - bool is_mounted; - size_t owner_id; - Permission all_user_permission; - Permission owner_permission; - Permission system_permission; - Permission admin_permission; - - list_t permission_lh; - - struct Object *object; - void *fs_location; -} ObjectAttr; - struct Partition; typedef struct Object { list_t list; @@ -87,7 +57,13 @@ typedef struct Object { void *fs_iterator; } directory; struct Driver *driver; - struct Device *device; + struct { + DeviceKind kind; + union { + struct PhysicalDevice *physical; + struct LogicalDevice *logical; + }; + } device; struct { void *data; size_t size; diff --git a/src/include/objects/types.h b/src/include/objects/types.h index 1b6e633..e9f8737 100644 --- a/src/include/objects/types.h +++ b/src/include/objects/types.h @@ -4,6 +4,6 @@ #include "object.h" ObjectResult init_builtin_types(); -Object *create_object_type(string_t name); +Object *create_object_type(string_t *name); #endif \ No newline at end of file diff --git a/src/include/string.h b/src/include/string.h index 0c71543..e7c280f 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -12,7 +12,7 @@ #define STRING_MAX_LEN 256 #define STRING_INIT(str) \ - {.text = str "\0", .length = sizeof(str), .max_length = sizeof(str)} + { .text = str "\0", .length = sizeof(str), .max_length = sizeof(str) } typedef struct _string { unsigned int length; diff --git a/src/kernel/driver/Makefile b/src/kernel/driver/Makefile index d13ac0c..f0ac1b7 100644 --- a/src/kernel/driver/Makefile +++ b/src/kernel/driver/Makefile @@ -3,8 +3,5 @@ SRC += device_driver.c SRC += device_manager.c SRC += device.c SRC += dma.c -SRC += driver_dependency.c SRC += driver_interface.c -SRC += driver_manager.c -SRC += driver.c -SRC += dynamic_device_manager.c \ No newline at end of file +SRC += driver.c \ No newline at end of file diff --git a/src/kernel/driver/bus_driver.c b/src/kernel/driver/bus_driver.c index 345cd84..3d77cc8 100644 --- a/src/kernel/driver/bus_driver.c +++ b/src/kernel/driver/bus_driver.c @@ -1,179 +1,100 @@ -#include "kernel/driver_interface.h" -#include "objects/object.h" -#include "string.h" #include #include #include -#include #include #include #include #include +#include +#include BusDriver *bus_drivers[BUS_TYPE_MAX]; WaitQueue bus_wqm[BUS_TYPE_MAX]; -DriverResult bus_driver_manager_load(DriverManager *driver_manager); -DriverResult bus_driver_manager_unload(DriverManager *driver_manager); -DriverResult driver_load(BusDriver *driver); -DriverResult driver_unload(BusDriver *driver); - -DriverManagerOps bus_driver_ops = { - .dm_load_hook = bus_driver_manager_load, - .dm_unload_hook = bus_driver_manager_unload, - .register_device_driver_hook = NULL, - .unregister_device_driver_hook = NULL, -}; - -typedef struct BusDriverManagerExt { -} BusDriverMangerExt; - -BusDriverMangerExt bus_driver_manager_ext; - -struct DriverManager bus_driver_manager = { - .type = DRIVER_TYPE_BUS_DRIVER, - - .ops = &bus_driver_ops, - - .private_data = &bus_driver_manager_ext, -}; - -DriverResult bus_driver_manager_load(DriverManager *driver_manager) { +DriverResult init_bus_manager() { for (int i = 0; i < BUS_TYPE_MAX; i++) { wait_queue_init(&bus_wqm[i]); } - return DRIVER_RESULT_OK; -} - -DriverResult bus_driver_manager_unload(DriverManager *driver_manager) { - - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult register_bus_driver( - Driver *driver, BusDriver *bus_driver, ObjectAttr *attr) { - - DriverManager *manager = driver_managers[DRIVER_TYPE_BUS_DRIVER]; - if (manager == NULL) return DRIVER_RESULT_NOT_EXIST; + Driver *driver, BusType type, BusDriver *bus_driver, ObjectAttr *attr) { + BusDriver *_bus_driver = bus_drivers[type]; + if (_bus_driver != NULL) return DRIVER_ERROR_ALREADY_EXIST; - BusDriver *_bus_driver = bus_drivers[bus_driver->bus_type]; - if (_bus_driver != NULL) return DRIVER_RESULT_ALREADY_EXIST; - - bus_driver->private_data = kmalloc(bus_driver->private_data_size); - bus_driver->state = DRIVER_STATE_UNINITED; + bus_driver->state = DRIVER_STATE_REGISTERED; list_init(&bus_driver->bus_lh); - DRV_RESULT_DELIVER_CALL( - register_sub_driver, driver, &bus_driver->subdriver, - DRIVER_TYPE_BUS_DRIVER); + bus_drivers[type] = bus_driver; - bus_drivers[bus_driver->bus_type] = bus_driver; + bus_driver->bus_type = type; + bus_driver->new_bus_num = 0; + bus_driver->bus_count = 0; + bus_driver->new_device_num = 0; + bus_driver->device_count = 0; bus_driver->object = - create_object_directory(&bus_object, bus_driver->name, *attr); + create_object_directory(&bus_object, &bus_driver->name, *attr); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult unregister_bus_driver(Driver *driver, BusType type) { - - DriverManager *manager = driver_managers[DRIVER_TYPE_BUS_DRIVER]; - if (manager == NULL) return DRIVER_RESULT_NOT_EXIST; - - BusDriver *bus_driver = bus_drivers[type]; - if (bus_driver == NULL) return DRIVER_RESULT_NOT_EXIST; +DriverResult unregister_bus_driver(BusDriver *bus_driver) { + delete_object(bus_driver->object); - // TODO: delete_object(&bus_driver->object); - - bus_drivers[bus_driver->driver_type] = NULL; + bus_drivers[bus_driver->bus_type] = NULL; Bus *cur, *next; list_for_each_owner_safe (cur, next, &bus_driver->bus_lh, bus_list) { - unregister_bus(cur); + delete_bus(cur); } - DRV_RESULT_DELIVER_CALL( - unregister_sub_driver, driver, &bus_driver->subdriver); - - bus_driver->state = DRIVER_STATE_UNREGISTERED; - if (bus_driver->private_data != NULL) kfree(bus_driver->private_data); - - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult register_bus( - BusDriver *bus_driver, Device *bus_controller_device, Bus *bus, - ObjectAttr *attr) { - if (bus_driver == NULL) return DRIVER_RESULT_NOT_EXIST; +DriverResult create_bus(Bus **bus, BusDriver *bus_driver, BusOps *ops) { + *bus = kmalloc(sizeof(Bus)); + if (*bus == NULL) return DRIVER_ERROR_OUT_OF_MEMORY; + Bus *b = *bus; - Bus *primary_bus = bus->primary_bus; - Bus *tmp_bus = bus; + Bus *primary_bus = b->primary_bus; + Bus *tmp_bus = b; while (primary_bus != NULL) { primary_bus->subordinate_bus_num = MAX(primary_bus->subordinate_bus_num, tmp_bus->subordinate_bus_num); tmp_bus = primary_bus; primary_bus = primary_bus->primary_bus; } + char _name[6] = {0}; // bus_count为uint16_t类型,最大65535,5位数 + itoa(_name, bus_driver->new_bus_num++, 10); + bus_driver->bus_count++; + string_new(&b->name, _name, sizeof(_name)); - string_new_with_number(&bus->name, "", 0, bus->bus_num); - bus->bus_driver = bus_driver; - bus->controller_device = bus_controller_device; - list_init(&bus->device_lh); - list_add_tail(&bus->bus_list, &bus_driver->bus_lh); + b->bus_driver = bus_driver; + b->ops = ops; + list_init(&b->device_lh); + list_add_tail(&b->bus_list, &bus_driver->bus_lh); - bus->object = create_object_directory(bus_driver->object, bus->name, *attr); + b->object = create_object_directory( + bus_driver->object, &b->name, base_obj_sys_attr); - BUS_OPS_CALL(bus_driver, register_bus_hook, bus); + list_add_tail(&b->new_bus_list, &new_bus_lh); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult unregister_bus(Bus *bus) { - BusDriver *bus_driver = bus->bus_driver; - if (bus_driver == NULL) return DRIVER_RESULT_NOT_EXIST; - - // TODO: delete_object(&bus->object); +DriverResult delete_bus(Bus *bus) { + delete_object(bus->object); // 取消注册bus下的所有device_driver - Device *cur, *next; + PhysicalDevice *cur, *next; list_for_each_owner_safe (cur, next, &bus->device_lh, bus_list) { - bus_unregister_device(cur); + delete_physical_device(cur); } - BUS_OPS_CALL(bus_driver, unregister_bus_hook, bus); list_del(&bus->bus_list); bus->bus_driver = NULL; - return DRIVER_RESULT_OK; -} - -DriverResult bus_register_device(Device *device, Bus *bus, ObjectAttr *attr) { - BusDriver *bus_driver = bus->bus_driver; - if (bus_driver == NULL) return DRIVER_RESULT_NOT_EXIST; - - device->bus = bus; - list_add_tail(&device->bus_list, &bus->device_lh); - BUS_OPS_CALL(bus, register_device_hook, device); - - // TODO: 名字冲突 - string_t name; - string_new_with_number(&name, "_", 1, bus->last_device_num++); - attr->type = OBJECT_TYPE_DEVICE; - device->object = create_object(bus->object, name, *attr); - device->object->value.device = device; - - return DRIVER_RESULT_OK; -} - -DriverResult bus_unregister_device(Device *device) { - Bus *bus = device->bus; - if (bus == NULL) return DRIVER_RESULT_NOT_EXIST; - - BUS_OPS_CALL(bus, unregister_device_hook, device); - list_del(&device->bus_list); - device->bus = NULL; - - // TODO: delete_object(&device_driver->object); - - return DRIVER_RESULT_OK; + return DRIVER_OK; } diff --git a/src/kernel/driver/device.c b/src/kernel/driver/device.c index fe46d0d..8c295a5 100644 --- a/src/kernel/driver/device.c +++ b/src/kernel/driver/device.c @@ -1,4 +1,3 @@ -#include "kernel/console.h" #include #include #include @@ -10,109 +9,137 @@ #include #include -/** - * @brief 注册设备 - * - * @param device_driver - * @param name 无空格的设备名,如未提供则不会被添加到对象树中 - * @param bus - * @param device - * @return DriverResult - */ -DriverResult register_device( - DeviceDriver *device_driver, string_t *name, Bus *bus, Device *device, - ObjectAttr *attr) { - if (device->ops == NULL) { - printk(COLOR_RED "Error: Device %s has no ops!\n", device->name.text); - return DRIVER_RESULT_NO_OPS; - } +DriverResult create_physical_device( + PhysicalDevice **physical_device, Bus *bus, ObjectAttr *attr) { + BusDriver *bus_driver = bus->bus_driver; - device->state = DEVICE_STATE_REGISTERED; + *physical_device = kmalloc(sizeof(PhysicalDevice)); + if (*physical_device == NULL) return DRIVER_ERROR_OUT_OF_MEMORY; + PhysicalDevice *phy = *physical_device; - device->child_devices = - kmalloc(device->max_child_device * sizeof(ChildDevice)); - device->child_private_data = - kmalloc(device->max_child_device * sizeof(void *)); - for (int i = 0; i < device->max_child_device; i++) { - device->child_devices[i].id = i; - device->child_devices[i].is_using = false; - device->child_devices[i].parent = device; - } + phy->kind = DEVICE_KIND_PHYSICAL; + phy->bus = bus; + phy->ops = NULL; + phy->state = DEVICE_STATE_UNINIT; + list_add_tail(&phy->bus_list, &bus->device_lh); + list_init(&phy->logical_device_lh); - if (device->private_data_size != 0) { - device->private_data = kmalloc(device->private_data_size); - } - list_add_tail(&device->device_list, &device_driver->device_lh); + phy->private_data = NULL; + phy->bus_ext = NULL; - bus_register_device(device, bus, attr); + char _name[6] = {0}; // device_count为uint16_t类型,最大65535,5位数 + itoa(_name, bus_driver->new_device_num++, 10); + bus_driver->device_count++; - if (name != NULL && name->text != NULL && name->length != 0) { - attr->type = OBJECT_TYPE_SYM_LINK; - Object *object = create_object(&device_object, *name, *attr); - object->value.sym_link = device->object; - } + string_t name; + string_new(&name, _name, sizeof(_name)); + attr->type = OBJECT_TYPE_DEVICE; + phy->object = create_object(bus->object, &name, *attr); + phy->object->value.device.kind = DEVICE_KIND_PHYSICAL; + phy->object->value.device.physical = phy; - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult unregister_device(DeviceDriver *device_driver, Device *device) { - device->state = DEVICE_STATE_REGISTERED; - bus_unregister_device(device); - list_del(&device->device_list); - return DRIVER_RESULT_OK; +void register_physical_device(PhysicalDevice *physical_device, DeviceOps *ops) { + physical_device->ops = ops; } -DriverResult register_child_device(Device *device, int private_data_size) { - ChildDevice *new = NULL; - for (int i = 0; i < device->max_child_device; i++) { - new = &device->child_devices[i]; - if (!new->is_using) { break; } +DriverResult delete_physical_device(PhysicalDevice *physical_device) { + BusDriver *bus_driver = physical_device->bus->bus_driver; + DriverResult ret = DRIVER_OK; + + if (!list_empty(&physical_device->logical_device_lh)) { + return DRIVER_ERROR_BUSY; + } + if (physical_device->object) { + ObjectResult result = delete_object(physical_device->object); + if (result != OBJECT_OK) ret = DRIVER_ERROR_OBJECT; } - if (new == NULL) { return DRIVER_RESULT_NO_VALID_CHILD_DEVICE; } - new->is_using = true; - new->private_data = kmalloc(private_data_size); - device->child_private_data[new->id] = new->private_data; - return DRIVER_RESULT_OK; + list_del(&physical_device->bus_list); + int result = kfree(physical_device); + if (result < 0) ret = DRIVER_ERROR_MEMORY_FREE; + + bus_driver->device_count--; + return ret; } -DriverResult unregister_child_device(ChildDevice *child_device) { - Device *device = child_device->parent; - child_device->is_using = false; - kfree(child_device->private_data); - device->child_private_data[child_device->id] = NULL; - return DRIVER_RESULT_OK; +DriverResult create_logical_device( + LogicalDevice **logical_device, PhysicalDevice *physical_device, + DeviceDriver *device_driver, DeviceOps *ops, DeviceType type) { + *logical_device = kmalloc(sizeof(LogicalDevice)); + if (logical_device == NULL) return DRIVER_ERROR_OUT_OF_MEMORY; + LogicalDevice *logi = *logical_device; + + logi->kind = DEVICE_KIND_LOGICAL; + logi->state = DEVICE_STATE_UNINIT; + logi->ops = ops; + logi->type = type; + logi->physical_device = physical_device; + list_add_tail( + &logi->logical_device_list, &physical_device->logical_device_lh); + + if (device_managers[type] != NULL) { + DeviceManager *manager = device_managers[type]; + list_add_tail(&logi->dm_list, &manager->device_lh); + } + + return DRIVER_OK; } -DriverResult init_device(Device *device) { - DeviceManager *manager = device_managers[device->device_driver->type]; - if (device->ops->init != NULL) { - DriverResult result = device->ops->init(device); - if (result != DRIVER_RESULT_OK) { - if (result != DRIVER_RESULT_NOT_EXIST) { - DRV_PRINT_RESULT(result, device->ops->init, device); - return result; - } else { - return DRIVER_RESULT_OK; - } - } +DriverResult delete_logical_device(LogicalDevice *logical_device) { + DeviceOps *ops = logical_device->ops; + DeviceState state = logical_device->state; + DriverResult ret = DRIVER_OK; + + if (ops->stop && state == DEVICE_STATE_ACTIVE) + DRIVER_RESULT_PASS(ops->stop(logical_device)); + if (ops->destroy && state != DEVICE_STATE_UNINIT) + DRIVER_RESULT_PASS(ops->destroy(logical_device)); + + if (logical_device->object != NULL) { + ObjectResult result = delete_object(logical_device->object); + if (result != OBJECT_OK) ret = DRIVER_ERROR_OBJECT; } - DEVM_OPS_CALL(manager, init_device_hook, manager, device); + + int result = 0; + if (!list_empty(&logical_device->dm_list)) + list_del(&logical_device->dm_list); + + list_del(&logical_device->logical_device_list); + result = kfree(logical_device); + if (result < 0) ret = DRIVER_ERROR_MEMORY_FREE; + + return ret; +} + +DriverResult init_physical_device(PhysicalDevice *device) { + DEV_OPS_CALL(device, init); device->state = DEVICE_STATE_READY; - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult start_device(Device *device) { - DeviceManager *manager = device_managers[device->device_driver->type]; - DEV_OPS_CALL(device, start, device); - DEVM_OPS_CALL(manager, start_device_hook, manager, device); - device->device_driver->subdriver.state = SUBDRIVER_STATE_READY; - device->state = DEVICE_STATE_ACTIVE; - return DRIVER_RESULT_OK; +DriverResult start_physical_device(PhysicalDevice *device) { + DEV_OPS_CALL(device, start); + device->state = DEVICE_STATE_ACTIVE; + return DRIVER_OK; +} + +DriverResult init_logical_device(LogicalDevice *device) { + DeviceManager *manager = device_managers[device->type]; + DEV_OPS_CALL(device, init); + if (manager->ops->init_device_hook != NULL) + manager->ops->init_device_hook(manager, device); + device->state = DEVICE_STATE_READY; + return DRIVER_OK; } -DriverResult init_and_start(Device *device) { - DRV_RESULT_DELIVER_CALL(init_device, device); - DRV_RESULT_DELIVER_CALL(start_device, device); - return DRIVER_RESULT_OK; +DriverResult start_logical_device(LogicalDevice *device) { + DeviceManager *manager = device_managers[device->type]; + DEV_OPS_CALL(device, start); + if (manager->ops->start_device_hook != NULL) + manager->ops->start_device_hook(manager, device); + device->state = DEVICE_STATE_ACTIVE; + return DRIVER_OK; } diff --git a/src/kernel/driver/device_driver.c b/src/kernel/driver/device_driver.c index 0f7f873..937f425 100644 --- a/src/kernel/driver/device_driver.c +++ b/src/kernel/driver/device_driver.c @@ -2,92 +2,23 @@ #include #include #include -#include #include #include -DriverResult device_driver_manager_load(DriverManager *driver_manager); -DriverResult device_driver_manager_unload(DriverManager *driver_manager); DriverResult driver_load(DeviceDriver *driver); DriverResult driver_unload(DeviceDriver *driver); -DriverManagerOps device_driver_ops = { - .dm_load_hook = device_driver_manager_load, - .dm_unload_hook = device_driver_manager_unload, - .register_device_driver_hook = NULL, - .unregister_device_driver_hook = NULL, -}; - -typedef struct DeviceDriverManagerExt { - -} DeviceDriverMangerExt; - -DeviceDriverMangerExt device_driver_manager_ext; - -struct DriverManager device_driver_manager = { - .type = DRIVER_TYPE_DEVICE_DRIVER, - - .ops = &device_driver_ops, - - .private_data = &device_driver_manager_ext, -}; - -DriverResult device_driver_manager_load(DriverManager *driver_manager) { - for (int i = 0; i < DEVICE_TYPE_MAX; i++) { - DeviceManager *device_manager = device_managers[i]; - if (device_manager != NULL) { - DEVM_OPS_CALL(device_manager, dm_load, device_manager); - } - } - - return DRIVER_RESULT_OK; -} - -DriverResult device_driver_manager_unload(DriverManager *driver_manager) { - for (int i = 0; i < DEVICE_TYPE_MAX; i++) { - DeviceManager *device_manager = device_managers[i]; - if (device_manager != NULL) { - DEVM_OPS_CALL(device_manager, dm_unload, device_manager); - } - } - - return DRIVER_RESULT_OK; -} - DriverResult register_device_driver( Driver *driver, DeviceDriver *device_driver) { - - DriverManager *manager = driver_managers[DRIVER_TYPE_DEVICE_DRIVER]; - if (manager == NULL) return DRIVER_RESULT_NOT_EXIST; - list_init(&device_driver->device_lh); - device_driver->private_data = kmalloc(device_driver->private_data_size); - device_driver->state = DRIVER_STATE_UNINITED; - - DM_OPS_CALL(manager, register_device_driver_hook, manager, device_driver); - - DRV_RESULT_DELIVER_CALL( - register_sub_driver, driver, &device_driver->subdriver, - DRIVER_TYPE_DEVICE_DRIVER); - - device_driver->state = DRIVER_STATE_ACTIVE; - - return DRIVER_RESULT_OK; + list_add_tail( + &device_driver->device_driver_list, &driver->device_driver_lh); + return DRIVER_OK; } -DriverResult unregister_device_driver( - Driver *driver, DeviceDriver *device_driver) { - - DriverManager *manager = driver_managers[device_driver->type]; - if (manager == NULL) return DRIVER_RESULT_NOT_EXIST; - - DRV_RESULT_DELIVER_CALL( - unregister_sub_driver, driver, &device_driver->subdriver); - - DM_OPS_CALL(manager, unregister_device_driver_hook, manager, device_driver); - - device_driver->state = DRIVER_STATE_UNREGISTERED; - if (device_driver->private_data != NULL) kfree(device_driver->private_data); +DriverResult unregister_device_driver(DeviceDriver *device_driver) { + if (!list_empty(&device_driver->device_lh)) return DRIVER_ERROR_BUSY; + list_del(&device_driver->device_driver_list); - return DRIVER_RESULT_OK; + return DRIVER_OK; } diff --git a/src/kernel/driver/device_manager.c b/src/kernel/driver/device_manager.c index a015de0..c377902 100644 --- a/src/kernel/driver/device_manager.c +++ b/src/kernel/driver/device_manager.c @@ -1,40 +1,42 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include -#include #include #include -DeviceManager *device_managers[DEVICE_TYPE_MAX]; +DeviceManager *device_managers[DEVICE_TYPE_MAX] = { + [DEVICE_TYPE_INTERRUPT_CONTROLLER] = &interrupt_dm, + [DEVICE_TYPE_TIMER] = &timer_dm, + [DEVICE_TYPE_TIME] = &time_dm, + [DEVICE_TYPE_FRAMEBUFFER] = &framebuffer_dm, + [DEVICE_TYPE_STORAGE] = &storage_dm, + [DEVICE_TYPE_INPUT] = &input_dm, + [DEVICE_TYPE_SOUND] = &sound_dm, + [DEVICE_TYPE_ETHERNET] = &network_dm, + [DEVICE_TYPE_SERIAL] = &serial_dm, + [DEVICE_TYPE_BUS_CONTROLLER] = &bus_controller_dm, +}; -DriverResult register_device_manager(DeviceManager *manager) { - DeviceManager *old_manager = device_managers[manager->type]; - if (old_manager != NULL) { - DRV_RESULT_DELIVER_CALL(unregister_device_manager, old_manager); +DriverResult init_device_managers() { + DeviceManager *device_manager; + for (int i = 0; i < DEVICE_TYPE_MAX; i++) { + device_manager = device_managers[i]; + if (device_manager == NULL) continue; + list_init(&device_manager->device_lh); + if (device_manager->ops->dm_load != NULL) + DRIVER_RESULT_PASS(device_manager->ops->dm_load(device_manager)); } - - list_init(&manager->device_lh); - device_managers[manager->type] = manager; - list_add_tail(&manager->dm_list, &device_driver_manager.dm_lh); - if (manager->ops->dm_load != NULL) { - DRV_RESULT_DELIVER_CALL(manager->ops->dm_load, manager); - } - return DRIVER_RESULT_OK; -} - -DriverResult unregister_device_manager(DeviceManager *manager) { - // 关闭所有设备 - Device *cur; - list_for_each_owner (cur, &manager->device_lh, device_list) { - if (cur->state != DEVICE_STATE_UNREGISTERED) { - DEV_OPS_CALL(cur, destroy, cur); - } - } - DEVM_OPS_CALL(manager, dm_unload, manager); - // 从链表中删除 - list_del(&manager->dm_list); - - device_managers[manager->type] = NULL; - return DRIVER_RESULT_OK; + return DRIVER_OK; } diff --git a/src/kernel/driver/dma.c b/src/kernel/driver/dma.c index a6d57d3..70b5717 100644 --- a/src/kernel/driver/dma.c +++ b/src/kernel/driver/dma.c @@ -33,7 +33,7 @@ DriverResult dma_split_mem( } else { // 创建新的请求 seg = kmalloc(sizeof(DmaSegment)); - if (seg == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } + if (seg == NULL) { return DRIVER_ERROR_OUT_OF_MEMORY; } // 设置新请求的参数 seg->vaddr = seg_start_vaddr; @@ -50,7 +50,7 @@ DriverResult dma_split_mem( } if (seg_size > 0) { seg = kmalloc(sizeof(DmaSegment)); - if (seg == NULL) { return DRIVER_RESULT_OUT_OF_MEMORY; } + if (seg == NULL) { return DRIVER_ERROR_OUT_OF_MEMORY; } // 设置新请求的参数 seg->vaddr = seg_start_vaddr; @@ -58,5 +58,5 @@ DriverResult dma_split_mem( seg->size = seg_size; list_add_tail(&seg->list, lh); } - return DRIVER_RESULT_OK; + return DRIVER_OK; } \ No newline at end of file diff --git a/src/kernel/driver/driver.c b/src/kernel/driver/driver.c index da464dd..0c63751 100644 --- a/src/kernel/driver/driver.c +++ b/src/kernel/driver/driver.c @@ -5,196 +5,179 @@ * @version 0.3 * @date 2022-07-20 */ +#include "kernel/periodic_task.h" #include #include #include #include +#include +#include #include #include #include #include #include #include +#include #include #include #include -#include - -LIST_HEAD(driver_list_head); - -// --------new-------- -#include -#include -#include #include -LIST_HEAD(driver_lh); +LIST_HEAD(new_bus_lh); +LIST_HEAD(bus_lh); +LIST_HEAD(device_lh); +SPINLOCK(device_list_lock); Driver core_driver = { .short_name = STRING_INIT("CoreDriver"), - .init = NULL, - .state = DRIVER_STATE_UNINITED, + .state = DRIVER_STATE_UNREGISTERED, }; void print_driver_result( DriverResult result, char *file, int line, char *func_with_args) { - if (result == DRIVER_RESULT_OK) return; + if (result == DRIVER_OK) return; printk("[At file %s line%d: %s]", file, line, func_with_args); switch (result) { - RESULT_CASE_PRINT(DRIVER_RESULT_OK) - RESULT_CASE_PRINT(DRIVER_RESULT_TIMEOUT) - RESULT_CASE_PRINT(DRIVER_RESULT_DEVICE_DRIVER_CONFLICT) - RESULT_CASE_PRINT(DRIVER_RESULT_NO_OPS) - RESULT_CASE_PRINT(DRIVER_RESULT_INCOMPLETABLE_OPS) - RESULT_CASE_PRINT(DRIVER_RESULT_NO_VALID_CHILD_DEVICE) - RESULT_CASE_PRINT(DRIVER_RESULT_INVALID_IRQ_NUMBER) - RESULT_CASE_PRINT(DRIVER_RESULT_OUT_OF_MEMORY) - RESULT_CASE_PRINT(DRIVER_RESULT_ALREADY_EXIST) - RESULT_CASE_PRINT(DRIVER_RESULT_NOT_EXIST) - RESULT_CASE_PRINT(DRIVER_RESULT_NULL_POINTER) - RESULT_CASE_PRINT(DRIVER_RESULT_UNSUPPORT_DEVICE) - RESULT_CASE_PRINT(DRIVER_RESULT_UNSUPPORT_FEATURE) - RESULT_CASE_PRINT(DRIVER_RESULT_INVALID_TYPE) - RESULT_CASE_PRINT(DRIVER_RESULT_BUSY) - RESULT_CASE_PRINT(DRIVER_RESULT_EXCEED_MAX_SIZE) - RESULT_CASE_PRINT(DRIVER_RESULT_OTHER_ERROR) + RESULT_CASE_PRINT(DRIVER_OK) + RESULT_CASE_PRINT(DRIVER_ERROR_TIMEOUT) + RESULT_CASE_PRINT(DRIVER_ERROR_CONFLICT) + RESULT_CASE_PRINT(DRIVER_ERROR_NO_OPS) + RESULT_CASE_PRINT(DRIVER_ERROR_OBJECT) + RESULT_CASE_PRINT(DRIVER_ERROR_INCOMPLETABLE_OPS) + RESULT_CASE_PRINT(DRIVER_ERROR_INVALID_IRQ_NUMBER) + RESULT_CASE_PRINT(DRIVER_ERROR_OUT_OF_MEMORY) + RESULT_CASE_PRINT(DRIVER_ERROR_ALREADY_EXIST) + RESULT_CASE_PRINT(DRIVER_ERROR_NOT_EXIST) + RESULT_CASE_PRINT(DRIVER_ERROR_NULL_POINTER) + RESULT_CASE_PRINT(DRIVER_ERROR_UNSUPPORT_DEVICE) + RESULT_CASE_PRINT(DRIVER_ERROR_UNSUPPORT_FEATURE) + RESULT_CASE_PRINT(DRIVER_ERROR_INVALID_TYPE) + RESULT_CASE_PRINT(DRIVER_ERROR_WAITING) + RESULT_CASE_PRINT(DRIVER_ERROR_MEMORY_FREE) + RESULT_CASE_PRINT(DRIVER_ERROR_BUSY) + RESULT_CASE_PRINT(DRIVER_ERROR_EXCEED_MAX_SIZE) + RESULT_CASE_PRINT(DRIVER_ERROR_OTHER) } } DriverResult register_driver(Driver *driver) { - - driver->state = DRIVER_STATE_UNINITED; - list_init(&driver->sub_driver_lh); + driver->state = DRIVER_STATE_REGISTERED; + list_init(&driver->device_driver_lh); list_init(&driver->remapped_memory_lh); - list_add_tail(&driver->driver_list, &driver_lh); - Object *object = - create_object(&driver_object, driver->short_name, driver_object_attr); - object->value.driver = driver; - return DRIVER_RESULT_OK; + return DRIVER_OK; } DriverResult unregister_driver(Driver *driver) { - list_del(&driver->driver_list); - return DRIVER_RESULT_OK; + return DRIVER_OK; } -DriverResult register_sub_driver( - Driver *driver, SubDriver *sub_driver, DriverType type) { - sub_driver->driver = driver; - sub_driver->state = SUBDRIVER_STATE_UNREADY; - sub_driver->type = type; - - wait_queue_init(&sub_driver->wq); - list_add(&sub_driver->sub_driver_list, &driver->sub_driver_lh); - - return DRIVER_RESULT_OK; -} - -DriverResult unregister_sub_driver(Driver *driver, SubDriver *sub_driver) { - list_del(&sub_driver->sub_driver_list); - - return DRIVER_RESULT_OK; -} - -DriverResult driver_init(Driver *driver) { - DriverResult result; - if (driver->init != NULL) { - result = driver->init(driver); - if (result != DRIVER_RESULT_OK) { - driver->state = DRIVER_STATE_UNREGISTERED; - unregister_driver(driver); - print_error_with_position( - "driver_init: driver %s init failed!\n", - driver->short_name.text); - return result; +void device_detect(void *arg) { + Bus *bus, *next; + PhysicalDevice *phy, *phy_next; + LogicalDevice *logi; + list_for_each_owner_safe (bus, next, &bus_lh, bus_check_list) { + if (bus->ops->probe_device != NULL) + bus->ops->probe_device(bus->bus_driver, bus); + list_for_each_owner_safe (phy, phy_next, &bus->device_lh, bus_list) { + if (phy->state != DEVICE_STATE_UNINIT) continue; + spin_lock(&device_list_lock); + list_add_tail(&phy->new_device_list, &device_lh); + spin_unlock(&device_list_lock); } } - driver->state = DRIVER_STATE_ACTIVE; - return DRIVER_RESULT_OK; -} - -void sub_driver_start_thread(void *arg) { - SubDriver *sub_driver = arg; - if (sub_driver->type == DRIVER_TYPE_DEVICE_DRIVER) { - DeviceDriver *device_driver = - container_of(sub_driver, DeviceDriver, subdriver); - Device *device; - list_for_each_owner (device, &device_driver->device_lh, device_list) { - if (device->ops->init != NULL) { device->ops->init(device); } - if (device->ops->start != NULL) { device->ops->start(device); } + while (!list_empty(&device_lh)) { + spin_lock(&device_list_lock); + phy = list_first_owner_or_null( + &device_lh, PhysicalDevice, new_device_list); + spin_unlock(&device_list_lock); + if (phy == NULL) { + schedule(); + continue; + } + if (phy->ops == NULL) { // 没有绑定驱动 + spin_lock(&device_list_lock); + list_del(&phy->new_device_list); + spin_unlock(&device_list_lock); + continue; } - sub_driver->state = SUBDRIVER_STATE_READY; - } else if (sub_driver->type == DRIVER_TYPE_BUS_DRIVER) { - BusDriver *bus_driver = container_of(sub_driver, BusDriver, subdriver); - if (bus_driver->ops->init != NULL) { - bus_driver->ops->init(bus_driver); + if (phy->state == DEVICE_STATE_UNINIT) init_physical_device(phy); + if (phy->state == DEVICE_STATE_READY) start_physical_device(phy); + list_for_each_owner ( + logi, &phy->logical_device_lh, logical_device_list) { + if (logi->state == DEVICE_STATE_UNINIT) init_logical_device(logi); + if (logi->state == DEVICE_STATE_READY) start_logical_device(logi); } + spin_lock(&device_list_lock); + list_del(&phy->new_device_list); + spin_unlock(&device_list_lock); + } +} - Bus *bus; - sub_driver->state = SUBDRIVER_STATE_READY; - wait_queue_wakeup_all(&bus_driver->subdriver.wq); - list_for_each_owner (bus, &bus_driver->bus_lh, bus_list) { - // 先等待Bus Controller Device就绪 - while (bus->controller_device->device_driver->subdriver.state != - SUBDRIVER_STATE_READY) { +void start_devices(void *arg) { + Bus *bus, *next; + PhysicalDevice *phy, *phy_next; + LogicalDevice *logi; + while (!(list_empty(&new_bus_lh) && list_empty(&device_lh))) { + list_for_each_owner_safe (bus, next, &new_bus_lh, new_bus_list) { + if (bus->ops->scan_bus != NULL) + bus->ops->scan_bus(bus->bus_driver, bus); + if (bus->ops->probe_device != NULL) + bus->ops->probe_device(bus->bus_driver, bus); + list_for_each_owner_safe ( + phy, phy_next, &bus->device_lh, bus_list) { + if (phy->state != DEVICE_STATE_UNINIT) continue; + spin_lock(&device_list_lock); + list_add_tail(&phy->new_device_list, &device_lh); + spin_unlock(&device_list_lock); + } + list_del(&bus->new_bus_list); + } + while (!list_empty(&device_lh)) { + spin_lock(&device_list_lock); + phy = list_first_owner_or_null( + &device_lh, PhysicalDevice, new_device_list); + spin_unlock(&device_list_lock); + if (phy == NULL) { schedule(); + continue; } - if (bus->ops->scan_bus != NULL) { - bus->ops->scan_bus(bus_driver, bus); + if (phy->ops == NULL) { // 没有绑定驱动 + spin_lock(&device_list_lock); + list_del(&phy->new_device_list); + spin_unlock(&device_list_lock); + continue; } - if (bus->ops->probe_device != NULL) { - bus->ops->probe_device(bus_driver, bus); + if (phy->state == DEVICE_STATE_UNINIT) init_physical_device(phy); + if (phy->state == DEVICE_STATE_READY) start_physical_device(phy); + list_for_each_owner ( + logi, &phy->logical_device_lh, logical_device_list) { + if (logi->state == DEVICE_STATE_UNINIT) + init_logical_device(logi); + if (logi->state == DEVICE_STATE_READY) + start_logical_device(logi); } + spin_lock(&device_list_lock); + list_del(&phy->new_device_list); + spin_unlock(&device_list_lock); } } } -void driver_start_thread(void *arg) { - Driver *driver = arg; - check_dependency(driver); - driver_init(driver); - - struct task_s *cur = get_current_thread(); - - SubDriver *sub_driver; - list_for_each_owner (sub_driver, &driver->sub_driver_lh, sub_driver_list) { - int old_status = save_and_disable_interrupt(); - - char *name; - if (sub_driver->type == DRIVER_TYPE_DEVICE_DRIVER) { - DeviceDriver *dd = - container_of(sub_driver, DeviceDriver, subdriver); - name = dd->name.text; - } else if (sub_driver->type == DRIVER_TYPE_BUS_DRIVER) { - BusDriver *bd = container_of(sub_driver, BusDriver, subdriver); - name = bd->name.text; - } else name = "sub_driver_start_thread"; - thread_start( - name, THREAD_DEFAULT_PRIO, sub_driver_start_thread, sub_driver, - cur); - store_interrupt_status(old_status); - } - - thread_wait_children(cur); -} +PeriodicTask driver_periodic_task = { + .func = device_detect, + .arg = NULL, +}; DriverResult driver_start_all(void) { - Driver *driver; - - struct task_s *cur = get_current_thread(); - - list_for_each_owner (driver, &driver_lh, driver_list) { - if (driver->state == DRIVER_STATE_UNINITED) { - int old_status = save_and_disable_interrupt(); - - thread_start( - driver->short_name.text, THREAD_DEFAULT_PRIO, - driver_start_thread, driver, cur); - store_interrupt_status(old_status); - } + thread_start( + "Start Devices", THREAD_DEFAULT_PRIO, start_devices, NULL, NULL); + while (!(list_empty(&new_bus_lh) && list_empty(&device_lh))) { + schedule(); } - thread_wait_children(cur); - return DRIVER_RESULT_OK; + periodic_task_add(&driver_periodic_task); + + return DRIVER_OK; } diff --git a/src/kernel/driver/driver_dependency.c b/src/kernel/driver/driver_dependency.c deleted file mode 100644 index 44a6705..0000000 --- a/src/kernel/driver/driver_dependency.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "kernel/driver_interface.h" -#include "kernel/spinlock.h" -#include -#include -#include -#include -#include -#include -#include - -DriverResult check_dependency(Driver *driver) { - int count = driver->dependency_count; - DriverDependency *deps = driver->dependencies; - - for (int i = 0; i < count; i++) { - if (deps[i].in_type == DRIVER_DEPENDENCY_TYPE_BUS) { - if (deps[i].dependency_in_bus.type > BUS_TYPE_MAX) { - return DRIVER_RESULT_NOT_EXIST; - } - - Bus *bus; - BusDriver *bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; - - disable_preempt(); // 禁用中断防止执行过程中被调度打断导致在进入等待循环前被“唤醒” - while (bus_driver == NULL || - bus_driver->subdriver.state != SUBDRIVER_STATE_READY) { - // 总线驱动还没准备好则等待 - thread_set_status(TASK_INTERRUPTIBLE); - wait_queue_add(&bus_driver->subdriver.wq); - - enable_preempt(); - thread_wait(); - disable_preempt(); - - bus_driver = bus_drivers[deps[i].dependency_in_bus.type]; - } - enable_preempt(); - - int j = 0; - list_for_each_owner (bus, &bus_driver->bus_lh, bus_list) { - if (j == deps[i].dependency_in_bus.bus_num) { - deps[i].out_bus = bus; - break; - } - j++; - } - } else if (deps[i].in_type == DRIVER_DEPENDENCY_TYPE_DEVICE) { - if (deps[i].in_device_type > DEVICE_TYPE_MAX) { - return DRIVER_RESULT_NOT_EXIST; - } - // TODO: device依赖 - } - } - return DRIVER_RESULT_OK; -} \ No newline at end of file diff --git a/src/kernel/driver/driver_interface.c b/src/kernel/driver/driver_interface.c index 31860c0..8c3c5df 100644 --- a/src/kernel/driver/driver_interface.c +++ b/src/kernel/driver/driver_interface.c @@ -1,10 +1,12 @@ -#include +#include #include #include #include #include #include #include +#include +#include #include list_t device_irq_lists[16] = { @@ -18,26 +20,61 @@ list_t device_irq_lists[16] = { LIST_HEAD_INIT(device_irq_lists[14]), LIST_HEAD_INIT(device_irq_lists[15]), }; -DriverResult register_device_irq(DeviceIrq *dev_irq) { - if (dev_irq->irq > 16) { - print_error_with_position("invalid irq number:%d\n", dev_irq->irq); - return DRIVER_RESULT_INVALID_IRQ_NUMBER; +DriverResult register_device_irq( + DEF_MRET(DeviceIrq *, device_irq), PhysicalDevice *physical_device, + void *arg, int irq, DeviceIrqHandler irq_handler, IrqMode mode) { + if (irq > 16) { + print_error( + "DeviceIrq", "invalid irq number:%d, device %s\n", irq, + physical_device->object->name.text); + return DRIVER_ERROR_INVALID_IRQ_NUMBER; } - dev_irq->irq = interrupt_redirect_irq(dev_irq->irq); - list_add_tail(&dev_irq->list, &device_irq_lists[dev_irq->irq]); - return DRIVER_RESULT_OK; + + DeviceIrq *device_irq = + list_first_owner_or_null(&device_irq_lists[irq], DeviceIrq, irq_list); + if (device_irq != NULL && mode == IRQ_MODE_EXCLUSIVE) { + print_error( + "DeviceIrq", + "Conflict irq number:%d, registered device %s, new device %s\n", + irq, device_irq->physical_device->object->name.text, + physical_device->object->name.text); + return DRIVER_ERROR_CONFLICT; + } + + device_irq = kmalloc(sizeof(DeviceIrq)); + if (device_irq == NULL) return DRIVER_ERROR_OUT_OF_MEMORY; + device_irq->arg = arg; + device_irq->physical_device = physical_device; + device_irq->handler = irq_handler; + device_irq->irq = interrupt_redirect_irq(irq); + + MRET(device_irq) = device_irq; + return DRIVER_OK; } DriverResult unregister_device_irq(DeviceIrq *dev_irq) { list_del(&dev_irq->list); - return DRIVER_RESULT_OK; + list_del(&dev_irq->irq_list); + int result = kfree(dev_irq); + if (result < 0) return DRIVER_ERROR_MEMORY_FREE; + return DRIVER_OK; +} + +DriverResult enable_device_irq(DeviceIrq *dev_irq) { + list_add_tail(&dev_irq->list, &device_irq_lists[dev_irq->irq]); + return interrupt_enable_irq(dev_irq->irq); +} + +DriverResult disable_device_irq(DeviceIrq *dev_irq) { + list_del(&dev_irq->list); + return interrupt_disable_irq(dev_irq->irq); } void device_irq_handler(int irq) { DeviceIrq *cur; if (list_empty(&device_irq_lists[irq])) return; list_for_each_owner (cur, &device_irq_lists[irq], list) { - cur->handler(cur->device); + cur->handler(cur->arg); } } @@ -55,7 +92,7 @@ DriverResult driver_remap_memory( list_for_each_owner (cur, &in_driver->remapped_memory_lh, list) { if (cur->phy_start < start && cur->phy_start + cur->size > end) { virtual_address = cur->vir_start; - return DRIVER_RESULT_OK; + return DRIVER_OK; } } @@ -65,7 +102,7 @@ DriverResult driver_remap_memory( printk( "Driver Interface: remap memory:0x%08x(size: %d) failed\n", in_physical_address, in_size); - return DRIVER_RESULT_OTHER_ERROR; + return DRIVER_ERROR_OTHER; } if (virtual_address == 0) { virtual_address = tmp; } @@ -76,5 +113,5 @@ DriverResult driver_remap_memory( remapped_memory->phy_start = start; list_add_tail(&remapped_memory->list, &in_driver->remapped_memory_lh); *out_virtual_address = virtual_address; - return DRIVER_RESULT_OK; + return DRIVER_OK; } diff --git a/src/kernel/driver/driver_manager.c b/src/kernel/driver/driver_manager.c deleted file mode 100644 index 5292c26..0000000 --- a/src/kernel/driver/driver_manager.c +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -#include -#include -#include - -DriverManager *driver_managers[DRIVER_TYPE_MAX]; - -DriverResult register_driver_manager(DriverManager *driver_manager) { - - DriverManager *old_manager = driver_managers[driver_manager->type]; - if (old_manager != NULL) { - DRV_RESULT_DELIVER_CALL(unregister_driver_manager, old_manager); - } - - list_init(&driver_manager->dm_lh); - driver_managers[driver_manager->type] = driver_manager; - - DM_OPS_CALL(driver_manager, dm_load_hook, driver_manager); - return DRIVER_RESULT_OK; -} - -DriverResult unregister_driver_manager(DriverManager *driver_manager) { - DriverManager *old_manager = driver_managers[driver_manager->type]; - - if (old_manager == NULL) return DRIVER_RESULT_NOT_EXIST; - DM_OPS_CALL(old_manager, dm_unload_hook, old_manager); - - driver_managers[driver_manager->type] = NULL; - - return DRIVER_RESULT_OK; -} diff --git a/src/kernel/driver/dynamic_device_manager.c b/src/kernel/driver/dynamic_device_manager.c deleted file mode 100644 index c084f3e..0000000 --- a/src/kernel/driver/dynamic_device_manager.c +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -LIST_HEAD(dynamic_device_manager_lh); -LIST_HEAD(new_device_lh); - -DriverResult register_dynamic_device_manager( - DynamicDeviceEvents *events, DeviceManager *device_manager) { - DynamicDeviceManager *ddm = kmalloc(sizeof(DynamicDeviceManager)); - ddm->device_manager = device_manager; - ddm->events = events; - list_init(&ddm->dynamic_device_lh); - list_add_tail(&ddm->list, &dynamic_device_manager_lh); - - return DRIVER_RESULT_OK; -} - -void dynamic_device_manager(void *arg) { - DynamicDeviceManager *ddm; - Device *device, *next; - while (true) { - list_for_each_owner (ddm, &dynamic_device_manager_lh, list) { - ddm->events->probe(ddm->device_manager); - } - list_for_each_owner_safe ( - device, next, &new_device_lh, new_device_list) { - list_del(&device->new_device_list); - init_and_start(device); - } - schedule(); - } -} diff --git a/src/kernel/main.c b/src/kernel/main.c index 550e480..1c1a175 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -4,28 +4,20 @@ * @brief 内核主程序 * @date 2020-03 */ -#include "driver/input/input_dm.h" -#include "driver/network/network_dm.h" +#include "driver/timer/timer_dm.h" +#include "objects/transfer.h" #include #include #include -#include -#include #include #include #include #include #include #include -#include #include #include -#include -#include #include -#include -#include -#include #include #include #include @@ -35,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -114,27 +105,14 @@ void network_timer_init(void); int main() { platform_early_init(); - init_memory(); - uint8_t *zero = 0; + init_memory(); init_object_tree(); - - register_driver_manager(&device_driver_manager); - register_driver_manager(&bus_driver_manager); - register_device_manager(&interrupt_dm); - register_device_manager(&timer_dm); - register_device_manager(&time_dm); - register_device_manager(&framebuffer_dm); - register_device_manager(&sound_dm); - register_device_manager(&storage_dm); - register_device_manager(&network_dm); - register_device_manager(&usb_dm); - register_device_manager(&input_dm); - register_device_manager(&serial_dm); + init_device_managers(); + init_bus_manager(); register_driver(&core_driver); - driver_init(&core_driver); platform_init(); platform_start_devices(); @@ -157,7 +135,7 @@ int main() { Object *net; ObjectResult result = open_object_by_path("\\Device\\Network0", &net); if (result == OBJECT_OK) { - dhcp_start(net->value.device->dm_ext); + dhcp_start(net->value.device.logical->dm_ext); // uint8_t dst_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // uint8_t dst_ip[] = {10, 0, 2, 2}; // uint8_t udp_data[] = "Hello, World!"; @@ -181,10 +159,10 @@ int main() { } // bios_emu_env.regs.ax = 0x4f02; - // bios_emu_env.regs.bx = 0x4192; // 1920x1080x32bit模式 - // BiosEmuExceptions exception = emu_interrupt(0x10); // 调用BIOS 0x10中断 - // FrameBufferDevice *fb_device; - // framebuffer_get_device(0, &fb_device); + // bios_emu_env.regs.bx = 0x4192; // + // 1920x1080x32bit模式 BiosEmuExceptions exception = + // emu_interrupt(0x10); // 调用BIOS 0x10中断 FrameBufferDevice + // *fb_device; framebuffer_get_device(0, &fb_device); // fb_device->mode_info.width = 1920; // fb_device->mode_info.height = 1080; // init_console(); // 重置控制台配置 diff --git a/src/kernel/memtest.c b/src/kernel/memtest.c index b638607..f0dcacf 100644 --- a/src/kernel/memtest.c +++ b/src/kernel/memtest.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -34,8 +34,8 @@ uint32_t rdtsc() { } uint32_t get_counter() { - Device *device = timer_dm_ext.scheduler_timer; - TimerDevice *td = device->dm_ext; + LogicalDevice *device = timer_dm_ext.scheduler_timer; + TimerDevice *td = device->dm_ext; return td->counter; } // 初始化性能统计 diff --git a/src/kernel/periodic_task.c b/src/kernel/periodic_task.c index 2f9e652..db39350 100644 --- a/src/kernel/periodic_task.c +++ b/src/kernel/periodic_task.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/src/kernel/softirq.c b/src/kernel/softirq.c index 972deb1..74aea6f 100644 --- a/src/kernel/softirq.c +++ b/src/kernel/softirq.c @@ -24,12 +24,12 @@ void do_softirq(void) { } DriverResult softirq_register_handler(SoftirqType type, void (*handler)(void)) { - if (type == SOFTIRQ_MAX) { return DRIVER_RESULT_INVALID_TYPE; } + if (type == SOFTIRQ_MAX) { return DRIVER_ERROR_INVALID_TYPE; } if (softirq_handlers[type].handler != NULL) { - return DRIVER_RESULT_DEVICE_DRIVER_CONFLICT; + return DRIVER_ERROR_CONFLICT; } softirq_handlers[type].handler = handler; - return DRIVER_RESULT_OK; + return DRIVER_OK; } diff --git a/src/kernel/thread.c b/src/kernel/thread.c index 83e2597..b705f50 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -118,7 +118,7 @@ void init_thread( pthread->priority = priority; pthread->kstack = (uint32_t *)((uint32_t)stack_page + PAGE_SIZE); - // pthread->ticks = timer_get_schedule_tick(priority); + pthread->ticks = timer_get_schedule_tick(priority); pthread->elapsed_ticks = 0; pthread->pgdir = NULL; pthread->stack_magic = 0x10000000; @@ -192,10 +192,7 @@ void thread_exit(void) { spin_unlock_irqrestore(&thread_all_lock, flags); flags = spin_lock_irqsave(&thread_ready_lock); - if (list_in_list(&cur->general_tag)) { - printk("d"); - // list_del(&cur->general_tag); - } + if (list_in_list(&cur->general_tag)) { list_del(&cur->general_tag); } cur->status = TASK_DIED; @@ -255,7 +252,6 @@ void thread_wait() { struct task_s *cur_thread = get_current_thread(); while (cur_thread->status == TASK_INTERRUPTIBLE) { - // while (list_in_list(&cur_thread->wait_queue_tag)) { schedule(); } } @@ -347,11 +343,11 @@ void schedule(void) { struct task_s *next; if (!list_empty(&thread_ready)) { next = list_first_owner(&thread_ready, struct task_s, general_tag); - list_del(&next->general_tag); if (next == cur) { - printk("?"); - printk("?"); + printk("[Thread Error] Same Task!\n"); + __asm__("nop" ::); } + list_del(&next->general_tag); } else { next = task_idle; if (list_in_list(&task_idle->general_tag)) @@ -360,6 +356,7 @@ void schedule(void) { // 4. 改变状态并加入到thread_ready if (next->status == TASK_READY) next->status = TASK_RUNNING; spin_unlock(&thread_ready_lock); + // printk("%s,%d\n", next->name, timer_get_counter()); prev = cur; // 5. 切换线程 diff --git a/src/objects/types.c b/src/objects/types.c index 717d09a..dc358ab 100644 --- a/src/objects/types.c +++ b/src/objects/types.c @@ -5,11 +5,8 @@ static int type_number = OBJECT_TYPE_BUILTIN_MAX; -#define DEFINE_OBJECT_TYPE(type_name) \ - { \ - .name = STRING_INIT(#type_name), \ - .value.type = OBJECT_TYPE_##type_name, \ - } +#define DEFINE_OBJECT_TYPE(type_name) \ + { .name = STRING_INIT(#type_name), .value.type = OBJECT_TYPE_##type_name, } Object object_builtin_types[OBJECT_TYPE_BUILTIN_MAX] = { DEFINE_OBJECT_TYPE(TYPE), DEFINE_OBJECT_TYPE(DIRECTORY), @@ -37,7 +34,7 @@ ObjectResult init_builtin_types() { return OBJECT_OK; } -Object *create_object_type(string_t name) { +Object *create_object_type(string_t *name) { Object *object = create_object(&object_type_directory, name, base_obj_sys_attr); if (object == NULL) { return NULL; } diff --git a/tools/grub/install_grub.py b/tools/grub/install_grub.py index 54ed343..cd1dc73 100644 --- a/tools/grub/install_grub.py +++ b/tools/grub/install_grub.py @@ -141,6 +141,7 @@ def get_brew_prefix(): if args.grub_mkimage != None: grub_mkimage_path = args.grub_mkimage else: + grub_dir_path = args.grub_dir if args.grub_mkimage != None: grub_mkimage_path = args.grub_mkimage From 0adcd075c822e8619e3ce293f847a3fa703ccb97 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 6 Oct 2025 14:12:45 +0800 Subject: [PATCH 145/158] =?UTF-8?q?driver:=20=E5=88=A0=E9=99=A4dynamic=5Fd?= =?UTF-8?q?evice=5Fmanager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/drivers/usb/hid/keyboard.c | 1 - src/drivers/usb/hid/mouse.c | 1 - src/include/kernel/dynamic_device_manager.h | 34 --------------------- src/kernel/main.c | 5 --- 4 files changed, 41 deletions(-) delete mode 100644 src/include/kernel/dynamic_device_manager.h diff --git a/src/drivers/usb/hid/keyboard.c b/src/drivers/usb/hid/keyboard.c index 760da0f..ca8185d 100644 --- a/src/drivers/usb/hid/keyboard.c +++ b/src/drivers/usb/hid/keyboard.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/src/drivers/usb/hid/mouse.c b/src/drivers/usb/hid/mouse.c index 1fb66ca..9e3e8fe 100644 --- a/src/drivers/usb/hid/mouse.c +++ b/src/drivers/usb/hid/mouse.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff --git a/src/include/kernel/dynamic_device_manager.h b/src/include/kernel/dynamic_device_manager.h deleted file mode 100644 index e44c38b..0000000 --- a/src/include/kernel/dynamic_device_manager.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _DYNAMIC_DM_H -#define _DYNAMIC_DM_H - -#include -#include -#include - -struct DynamicDevice; -typedef struct DynamicDeviceEvents { - void (*probe)(DeviceManager *ddm); - void (*remove)(struct DynamicDevice *device); -} DynamicDeviceEvents; - -typedef struct DynamicDevice { - list_t list; - - PhysicalDevice *device; -} DynamicDevice; - -typedef struct DynamicDeviceManager { - list_t list; - list_t dynamic_device_lh; - - DeviceManager *device_manager; - DynamicDeviceEvents *events; -} DynamicDeviceManager; - -extern list_t new_device_lh; - -DriverResult register_dynamic_device_manager( - DynamicDeviceEvents *events, DeviceManager *device_manager); -void dynamic_device_manager(void *arg); - -#endif \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index 1c1a175..e5371bf 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -128,10 +127,6 @@ int main() { do_initcalls(); driver_start_all(); - thread_start( - "Dynamic Device Manager", THREAD_DEFAULT_PRIO, dynamic_device_manager, - NULL, NULL); - Object *net; ObjectResult result = open_object_by_path("\\Device\\Network0", &net); if (result == OBJECT_OK) { From 45da73a18f0924b56bbfc3a617104828b8ce948a Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 6 Oct 2025 21:09:02 +0800 Subject: [PATCH 146/158] =?UTF-8?q?driver:=20=E9=87=8D=E6=96=B0=E6=A2=B3?= =?UTF-8?q?=E7=90=86=E9=A9=B1=E5=8A=A8=E7=9B=B8=E5=85=B3=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E4=B9=8B=E9=97=B4=E7=9A=84=E5=85=B3=E7=B3=BB=E5=B9=B6=E7=AE=80?= =?UTF-8?q?=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/bus/pci/pci.c | 1 - src/arch/x86/kernel/platform.c | 4 ---- src/driver/framebuffer/framebuffer_dm.c | 4 ++-- src/driver/input/input_dm.c | 2 +- src/driver/interrupt/interrupt_dm.c | 4 ++-- src/driver/network/network_dm.c | 4 ++-- src/driver/sound/sound_dm.c | 2 +- src/driver/storage/storage_dm.c | 2 +- src/driver/time_dm.c | 2 +- src/drivers/bus/hcd.c | 2 +- src/drivers/bus/usb.c | 2 +- src/include/kernel/bus_driver.h | 17 ++++----------- src/include/kernel/device.h | 28 ++++++++++++------------- src/include/kernel/driver.h | 4 ++-- src/kernel/driver/bus_driver.c | 25 +++++++++++----------- src/kernel/driver/device.c | 21 +++++++++---------- src/kernel/driver/device_manager.c | 2 +- src/kernel/driver/driver.c | 26 +++++++++++------------ 18 files changed, 69 insertions(+), 83 deletions(-) diff --git a/src/arch/x86/drivers/bus/pci/pci.c b/src/arch/x86/drivers/bus/pci/pci.c index 323c9d6..04dd934 100644 --- a/src/arch/x86/drivers/bus/pci/pci.c +++ b/src/arch/x86/drivers/bus/pci/pci.c @@ -187,7 +187,6 @@ DriverResult pci_scan_bus(BusDriver *bus_driver, Bus *bus) { continue; } - bus_driver->device_count++; pci_device->status = PCI_DEVICE_STATUS_UNUSED; print_info( "PCI", diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index 57f6b58..fdb9477 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -24,10 +24,6 @@ #include #include -BusDriverOps platform_ops = { - .register_bus_hook = NULL, - .unregister_bus_hook = NULL, -}; BusOps platform_bus_ops = { .scan_bus = NULL, .probe_device = NULL, diff --git a/src/driver/framebuffer/framebuffer_dm.c b/src/driver/framebuffer/framebuffer_dm.c index f9e3dd5..6ffa5ba 100644 --- a/src/driver/framebuffer/framebuffer_dm.c +++ b/src/driver/framebuffer/framebuffer_dm.c @@ -135,7 +135,7 @@ DriverResult framebuffer_device_start( DriverResult framebuffer_start_all() { LogicalDevice *device; - list_for_each_owner (device, &framebuffer_dm.device_lh, dm_list) { + list_for_each_owner (device, &framebuffer_dm.device_lh, dm_device_list) { framebuffer_device_start(&framebuffer_dm, device); } return DRIVER_OK; @@ -149,7 +149,7 @@ DriverResult framebuffer_get_device( return DRIVER_OK; } int i = 0; - list_for_each_owner (device, &framebuffer_dm.device_lh, dm_list) { + list_for_each_owner (device, &framebuffer_dm.device_lh, dm_device_list) { if (device == framebuffer_dm_ext.main_display_device) { continue; } if (i == in_index) { *out_device = device->dm_ext; diff --git a/src/driver/input/input_dm.c b/src/driver/input/input_dm.c index fd44d4a..5603d1f 100644 --- a/src/driver/input/input_dm.c +++ b/src/driver/input/input_dm.c @@ -116,7 +116,7 @@ DriverResult delete_input_device(InputDevice *input_device) { LogicalDevice *logical_device = input_device->device; - list_del(&logical_device->dm_list); + list_del(&logical_device->dm_device_list); delete_logical_device(logical_device); int result = kfree(input_device); if (result < 0) return DRIVER_ERROR_MEMORY_FREE; diff --git a/src/driver/interrupt/interrupt_dm.c b/src/driver/interrupt/interrupt_dm.c index 1f097b3..aaf8a58 100644 --- a/src/driver/interrupt/interrupt_dm.c +++ b/src/driver/interrupt/interrupt_dm.c @@ -116,7 +116,7 @@ DriverResult delete_interrupt_device(InterruptDevice *interrupt_device) { InterruptDevice *new_interrupt_device = NULL; if (manager->current_device == interrupt_device) { // 寻找替代的设备 - list_for_each_owner (cur, &interrupt_dm.device_lh, dm_list) { + list_for_each_owner (cur, &interrupt_dm.device_lh, dm_device_list) { if (cur != device) { if (new_interrupt_device == NULL) { new_interrupt_device = cur->dm_ext; @@ -145,7 +145,7 @@ DriverResult delete_interrupt_device(InterruptDevice *interrupt_device) { new_device->state = DEVICE_STATE_ACTIVE; manager->current_device = new_interrupt_device; - list_del(&device->dm_list); + list_del(&device->dm_device_list); DRIVER_RESULT_PASS(delete_logical_device(device)); int result = kfree(interrupt_device); if (result < 0) return DRIVER_ERROR_MEMORY_FREE; diff --git a/src/driver/network/network_dm.c b/src/driver/network/network_dm.c index 33f3953..45448d8 100644 --- a/src/driver/network/network_dm.c +++ b/src/driver/network/network_dm.c @@ -25,7 +25,7 @@ DeviceManagerOps network_dm_ops = { NetworkDeviceManager network_dm_ext; DeviceManager network_dm = { - .type = DEVICE_TYPE_ETHERNET, + .type = DEVICE_TYPE_INTERNET, .ops = &network_dm_ops, .private_data = &network_dm_ext, }; @@ -51,7 +51,7 @@ DriverResult create_network_device( result = create_logical_device( &logical_device, physical_device, device_driver, ops, - DEVICE_TYPE_ETHERNET); + DEVICE_TYPE_INTERNET); if (result != DRIVER_OK) return result; *network_device = kmalloc(sizeof(NetworkDevice)); diff --git a/src/driver/sound/sound_dm.c b/src/driver/sound/sound_dm.c index ff81d3a..bfd32d2 100644 --- a/src/driver/sound/sound_dm.c +++ b/src/driver/sound/sound_dm.c @@ -83,7 +83,7 @@ DriverResult delete_sound_device(SoundDevice *sound_device) { sound_dm_ext.device_count--; LogicalDevice *logical_device = sound_device->device; - list_del(&logical_device->dm_list); + list_del(&logical_device->dm_device_list); delete_logical_device(logical_device); int result = kfree(sound_device); if (result < 0) return DRIVER_ERROR_MEMORY_FREE; diff --git a/src/driver/storage/storage_dm.c b/src/driver/storage/storage_dm.c index 2e30976..c5b5dda 100644 --- a/src/driver/storage/storage_dm.c +++ b/src/driver/storage/storage_dm.c @@ -117,7 +117,7 @@ DriverResult delete_storage_device(StorageDevice *storage_device) { // TODO: delete_object_directory // TODO: periodic_task_remove - list_del(&storage_device->device->dm_list); + list_del(&storage_device->device->dm_device_list); delete_logical_device(storage_device->device); int result; if (storage_device->device->state == DEVICE_STATE_ACTIVE) { diff --git a/src/driver/time_dm.c b/src/driver/time_dm.c index 31338ed..3b744bb 100644 --- a/src/driver/time_dm.c +++ b/src/driver/time_dm.c @@ -61,7 +61,7 @@ DriverResult time_device_start(LogicalDevice *device) { DriverResult delete_time_device(TimeDevice *time_device) { int result = 0; - list_del(&time_device->device->dm_list); + list_del(&time_device->device->dm_device_list); DRIVER_RESULT_PASS(delete_logical_device(time_device->device)); result = kfree(time_device); if (result < 0) return DRIVER_ERROR_MEMORY_FREE; diff --git a/src/drivers/bus/hcd.c b/src/drivers/bus/hcd.c index 0a07ba0..70720be 100644 --- a/src/drivers/bus/hcd.c +++ b/src/drivers/bus/hcd.c @@ -62,7 +62,7 @@ DriverResult usb_create_hcd( } list_add_tail(&hcd->list, &hcd_list); - list_add_tail(&hcd->bus->bus_check_list, &bus_lh); + list_add_tail(&hcd->bus->bus_check_list, &bus_check_lh); list_init(&hcd->usb_device_lh); return DRIVER_OK; diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c index 72aa6b3..1d6c783 100644 --- a/src/drivers/bus/usb.c +++ b/src/drivers/bus/usb.c @@ -54,7 +54,7 @@ DriverResult usb_probe(BusDriver *bus_driver, Bus *bus) { UsbDriver *usb_driver; PhysicalDevice *device; UsbInterface *interface; - list_for_each_owner (device, &bus->device_lh, bus_list) { + list_for_each_owner (device, &bus->device_lh, device_list) { UsbDevice *usb_device = device->bus_ext; if (usb_device->state == USB_STATE_INITED) { list_for_each_owner (interface, &usb_device->interface_lh, list) { diff --git a/src/include/kernel/bus_driver.h b/src/include/kernel/bus_driver.h index 18d539f..b192b80 100644 --- a/src/include/kernel/bus_driver.h +++ b/src/include/kernel/bus_driver.h @@ -19,14 +19,6 @@ typedef enum BusType { BUS_TYPE_MAX, } BusType; -struct Bus; -typedef struct BusDriverOps { - DriverResult (*register_bus_hook)(struct Bus *bus); - DriverResult (*unregister_bus_hook)(struct Bus *bus); - - DriverResult (*init)(struct BusDriver *bus_driver); -} BusDriverOps; - typedef struct BusOps { DriverResult (*scan_bus)(struct BusDriver *bus_driver, struct Bus *bus); DriverResult (*probe_device)(struct BusDriver *bus_driver, struct Bus *bus); @@ -42,9 +34,6 @@ typedef struct BusDriver { uint16_t new_bus_num; uint16_t bus_count; - - uint16_t new_device_num; - uint16_t device_count; } BusDriver; typedef struct Bus { @@ -56,12 +45,14 @@ typedef struct Bus { struct Bus *primary_bus; - string_t name; - Object *object; + Object *object; uint32_t bus_num; uint32_t subordinate_bus_num; + int new_device_num; + int device_count; + BusOps *ops; } Bus; diff --git a/src/include/kernel/device.h b/src/include/kernel/device.h index d170185..bc5e197 100644 --- a/src/include/kernel/device.h +++ b/src/include/kernel/device.h @@ -19,17 +19,17 @@ } typedef enum { - DEVICE_TYPE_UNKNOWN = 0, - DEVICE_TYPE_INTERRUPT_CONTROLLER, - DEVICE_TYPE_TIMER, // 定时器设备 - DEVICE_TYPE_FRAMEBUFFER, - DEVICE_TYPE_STORAGE, - DEVICE_TYPE_INPUT, - DEVICE_TYPE_SOUND, - DEVICE_TYPE_BUS_CONTROLLER, - DEVICE_TYPE_ETHERNET, - DEVICE_TYPE_TIME, // 时间设备(如:Unix时间戳/UTC时间) - DEVICE_TYPE_SERIAL, + DEVICE_TYPE_UNKNOWN = 0, // 未知设备类型 + DEVICE_TYPE_INTERRUPT_CONTROLLER, // 中断控制器 + DEVICE_TYPE_TIMER, // 定时器设备 + DEVICE_TYPE_FRAMEBUFFER, // 通过显示缓冲区直接控制的屏幕 + DEVICE_TYPE_STORAGE, // 存储设备(如硬盘) + DEVICE_TYPE_INPUT, // 输入设备(如键盘鼠标) + DEVICE_TYPE_SOUND, // 声音设备(声卡) + DEVICE_TYPE_BUS_CONTROLLER, // 总线控制器(如usb控制器XHCI/EHCI/OHCI/UHCI) + DEVICE_TYPE_INTERNET, // 网络设备(网卡) + DEVICE_TYPE_TIME, // 时间设备(如:Unix时间戳/UTC时间) + DEVICE_TYPE_SERIAL, // 串口设备 DEVICE_TYPE_MAX, } DeviceType; @@ -58,8 +58,8 @@ typedef struct LogicalDevice { list_t new_device_list; list_t logical_device_list; - list_t dm_list; - list_t device_list; + list_t dm_device_list; + list_t device_driver_device_list; DeviceType type; DeviceOps *ops; @@ -79,7 +79,7 @@ typedef struct PhysicalDevice { DeviceState state; list_t new_device_list; - list_t bus_list; + list_t device_list; list_t logical_device_lh; list_t irq_lh; diff --git a/src/include/kernel/driver.h b/src/include/kernel/driver.h index 1f5f9e5..feb0198 100644 --- a/src/include/kernel/driver.h +++ b/src/include/kernel/driver.h @@ -90,8 +90,8 @@ void print_driver_result( DriverResult result, char *file, int line, char *func_with_args); extern list_t new_bus_lh; -extern list_t bus_lh; -extern list_t device_lh; +extern list_t bus_check_lh; +extern list_t new_device_lh; extern spinlock_t device_list_lock; extern struct Object driver_object; diff --git a/src/kernel/driver/bus_driver.c b/src/kernel/driver/bus_driver.c index 3d77cc8..c974492 100644 --- a/src/kernel/driver/bus_driver.c +++ b/src/kernel/driver/bus_driver.c @@ -28,11 +28,9 @@ DriverResult register_bus_driver( bus_drivers[type] = bus_driver; - bus_driver->bus_type = type; - bus_driver->new_bus_num = 0; - bus_driver->bus_count = 0; - bus_driver->new_device_num = 0; - bus_driver->device_count = 0; + bus_driver->bus_type = type; + bus_driver->new_bus_num = 0; + bus_driver->bus_count = 0; bus_driver->object = create_object_directory(&bus_object, &bus_driver->name, *attr); @@ -66,18 +64,21 @@ DriverResult create_bus(Bus **bus, BusDriver *bus_driver, BusOps *ops) { tmp_bus = primary_bus; primary_bus = primary_bus->primary_bus; } - char _name[6] = {0}; // bus_count为uint16_t类型,最大65535,5位数 + char _name[6] = {0}; // bus_count为uint16_t类型,最大65535,5位数 + string_t name; itoa(_name, bus_driver->new_bus_num++, 10); bus_driver->bus_count++; - string_new(&b->name, _name, sizeof(_name)); + string_new(&name, _name, sizeof(_name)); - b->bus_driver = bus_driver; - b->ops = ops; + b->bus_driver = bus_driver; + b->ops = ops; + b->new_device_num = 0; + b->device_count = 0; list_init(&b->device_lh); list_add_tail(&b->bus_list, &bus_driver->bus_lh); - b->object = create_object_directory( - bus_driver->object, &b->name, base_obj_sys_attr); + b->object = + create_object_directory(bus_driver->object, &name, base_obj_sys_attr); list_add_tail(&b->new_bus_list, &new_bus_lh); @@ -89,7 +90,7 @@ DriverResult delete_bus(Bus *bus) { // 取消注册bus下的所有device_driver PhysicalDevice *cur, *next; - list_for_each_owner_safe (cur, next, &bus->device_lh, bus_list) { + list_for_each_owner_safe (cur, next, &bus->device_lh, device_list) { delete_physical_device(cur); } diff --git a/src/kernel/driver/device.c b/src/kernel/driver/device.c index 8c295a5..138d25e 100644 --- a/src/kernel/driver/device.c +++ b/src/kernel/driver/device.c @@ -11,7 +11,6 @@ DriverResult create_physical_device( PhysicalDevice **physical_device, Bus *bus, ObjectAttr *attr) { - BusDriver *bus_driver = bus->bus_driver; *physical_device = kmalloc(sizeof(PhysicalDevice)); if (*physical_device == NULL) return DRIVER_ERROR_OUT_OF_MEMORY; @@ -21,15 +20,15 @@ DriverResult create_physical_device( phy->bus = bus; phy->ops = NULL; phy->state = DEVICE_STATE_UNINIT; - list_add_tail(&phy->bus_list, &bus->device_lh); + list_add_tail(&phy->device_list, &bus->device_lh); list_init(&phy->logical_device_lh); phy->private_data = NULL; phy->bus_ext = NULL; char _name[6] = {0}; // device_count为uint16_t类型,最大65535,5位数 - itoa(_name, bus_driver->new_device_num++, 10); - bus_driver->device_count++; + itoa(_name, bus->new_device_num++, 10); + bus->device_count++; string_t name; string_new(&name, _name, sizeof(_name)); @@ -46,8 +45,8 @@ void register_physical_device(PhysicalDevice *physical_device, DeviceOps *ops) { } DriverResult delete_physical_device(PhysicalDevice *physical_device) { - BusDriver *bus_driver = physical_device->bus->bus_driver; - DriverResult ret = DRIVER_OK; + Bus *bus = physical_device->bus; + DriverResult ret = DRIVER_OK; if (!list_empty(&physical_device->logical_device_lh)) { return DRIVER_ERROR_BUSY; @@ -57,11 +56,11 @@ DriverResult delete_physical_device(PhysicalDevice *physical_device) { if (result != OBJECT_OK) ret = DRIVER_ERROR_OBJECT; } - list_del(&physical_device->bus_list); + list_del(&physical_device->device_list); int result = kfree(physical_device); if (result < 0) ret = DRIVER_ERROR_MEMORY_FREE; - bus_driver->device_count--; + bus->device_count--; return ret; } @@ -82,7 +81,7 @@ DriverResult create_logical_device( if (device_managers[type] != NULL) { DeviceManager *manager = device_managers[type]; - list_add_tail(&logi->dm_list, &manager->device_lh); + list_add_tail(&logi->dm_device_list, &manager->device_lh); } return DRIVER_OK; @@ -104,8 +103,8 @@ DriverResult delete_logical_device(LogicalDevice *logical_device) { } int result = 0; - if (!list_empty(&logical_device->dm_list)) - list_del(&logical_device->dm_list); + if (!list_empty(&logical_device->dm_device_list)) + list_del(&logical_device->dm_device_list); list_del(&logical_device->logical_device_list); result = kfree(logical_device); diff --git a/src/kernel/driver/device_manager.c b/src/kernel/driver/device_manager.c index c377902..4f7772f 100644 --- a/src/kernel/driver/device_manager.c +++ b/src/kernel/driver/device_manager.c @@ -24,7 +24,7 @@ DeviceManager *device_managers[DEVICE_TYPE_MAX] = { [DEVICE_TYPE_STORAGE] = &storage_dm, [DEVICE_TYPE_INPUT] = &input_dm, [DEVICE_TYPE_SOUND] = &sound_dm, - [DEVICE_TYPE_ETHERNET] = &network_dm, + [DEVICE_TYPE_INTERNET] = &network_dm, [DEVICE_TYPE_SERIAL] = &serial_dm, [DEVICE_TYPE_BUS_CONTROLLER] = &bus_controller_dm, }; diff --git a/src/kernel/driver/driver.c b/src/kernel/driver/driver.c index 0c63751..192ce42 100644 --- a/src/kernel/driver/driver.c +++ b/src/kernel/driver/driver.c @@ -25,8 +25,8 @@ #include LIST_HEAD(new_bus_lh); -LIST_HEAD(bus_lh); -LIST_HEAD(device_lh); +LIST_HEAD(bus_check_lh); +LIST_HEAD(new_device_lh); SPINLOCK(device_list_lock); Driver core_driver = { @@ -77,20 +77,20 @@ void device_detect(void *arg) { Bus *bus, *next; PhysicalDevice *phy, *phy_next; LogicalDevice *logi; - list_for_each_owner_safe (bus, next, &bus_lh, bus_check_list) { + list_for_each_owner_safe (bus, next, &bus_check_lh, bus_check_list) { if (bus->ops->probe_device != NULL) bus->ops->probe_device(bus->bus_driver, bus); - list_for_each_owner_safe (phy, phy_next, &bus->device_lh, bus_list) { + list_for_each_owner_safe (phy, phy_next, &bus->device_lh, device_list) { if (phy->state != DEVICE_STATE_UNINIT) continue; spin_lock(&device_list_lock); - list_add_tail(&phy->new_device_list, &device_lh); + list_add_tail(&phy->new_device_list, &new_device_lh); spin_unlock(&device_list_lock); } } - while (!list_empty(&device_lh)) { + while (!list_empty(&new_device_lh)) { spin_lock(&device_list_lock); phy = list_first_owner_or_null( - &device_lh, PhysicalDevice, new_device_list); + &new_device_lh, PhysicalDevice, new_device_list); spin_unlock(&device_list_lock); if (phy == NULL) { schedule(); @@ -119,25 +119,25 @@ void start_devices(void *arg) { Bus *bus, *next; PhysicalDevice *phy, *phy_next; LogicalDevice *logi; - while (!(list_empty(&new_bus_lh) && list_empty(&device_lh))) { + while (!(list_empty(&new_bus_lh) && list_empty(&new_device_lh))) { list_for_each_owner_safe (bus, next, &new_bus_lh, new_bus_list) { if (bus->ops->scan_bus != NULL) bus->ops->scan_bus(bus->bus_driver, bus); if (bus->ops->probe_device != NULL) bus->ops->probe_device(bus->bus_driver, bus); list_for_each_owner_safe ( - phy, phy_next, &bus->device_lh, bus_list) { + phy, phy_next, &bus->device_lh, device_list) { if (phy->state != DEVICE_STATE_UNINIT) continue; spin_lock(&device_list_lock); - list_add_tail(&phy->new_device_list, &device_lh); + list_add_tail(&phy->new_device_list, &new_device_lh); spin_unlock(&device_list_lock); } list_del(&bus->new_bus_list); } - while (!list_empty(&device_lh)) { + while (!list_empty(&new_device_lh)) { spin_lock(&device_list_lock); phy = list_first_owner_or_null( - &device_lh, PhysicalDevice, new_device_list); + &new_device_lh, PhysicalDevice, new_device_list); spin_unlock(&device_list_lock); if (phy == NULL) { schedule(); @@ -173,7 +173,7 @@ PeriodicTask driver_periodic_task = { DriverResult driver_start_all(void) { thread_start( "Start Devices", THREAD_DEFAULT_PRIO, start_devices, NULL, NULL); - while (!(list_empty(&new_bus_lh) && list_empty(&device_lh))) { + while (!(list_empty(&new_bus_lh) && list_empty(&new_device_lh))) { schedule(); } From 4da525e690b0e060aa5ae0df5469d8ece0a51e16 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 6 Oct 2025 21:42:20 +0800 Subject: [PATCH 147/158] =?UTF-8?q?doc:=20=E6=96=B0=E5=A2=9E=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8=E6=A1=86=E6=9E=B6=E7=9A=84=E8=AF=B4=E6=98=8E=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/driver framework.md | 469 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 469 insertions(+) create mode 100644 doc/driver framework.md diff --git a/doc/driver framework.md b/doc/driver framework.md new file mode 100644 index 0000000..308a640 --- /dev/null +++ b/doc/driver framework.md @@ -0,0 +1,469 @@ +# 关系图 + +## 总览 + +所有驱动框架下驱动及设备相关结构之间的关系如下(以APIC为例): + +```mermaid +graph TD + A[Kernel]-->B[DriverManager] + A-->C[DeviceManager] + + B-->D[Driver0] + C-->E[InterruptDeviceManager] + C-->F[TimerDeviceManager] + + D-->BD0[BusDriver0] + D-->DD1[DeviceDriver1] + + BD0-.->B0[Bus0] + + B0-.->PD1 + + DD1-.->PD1["PhysicalDevice1(e.g. APIC)"] + PD1-.->D1["LogicalDevice1(e.g. APIC)"] + PD1-.->D2["LogiicalDevice2(e.g.APIC Timer)"] + + E-.->InterruptDevice-->D1 + F-.->TimerDevice-->D2 + +``` + +通过`Object`系统可访问的`PhysicalDevice`和`LogicalDevice`的关系如下: + +```mermaid +graph LR + A["\Bus"]-->|\|PCI-.->|\|B[0]-.->|\|C[0] + + Device0-->Bus0-->B + PhysicalDevice1-->C + + PhysicalDevice1-.->LogicalDevice1 + + D["\Device"]-->|\|Storage0 + LogicalDevice1-->Storage0 + + +``` + +总线-设备的包含关系如下: + +```mermaid +graph TD + A[ISA Controller] + B[PCI Controller] + A-->C[ISA Bus0] + B-->D[PCI Bus0] + + C-->I[SB16] + + D-->E[USB HCI] + E-->F[USB Bus0] + + F-->G[Mouse] + F-->H[Keyboard] +``` + +## 链表 + + + +```mermaid +graph LR + A[BusDriver]-->|bus_lh|B[Bus] + B-->|bus_list|A +``` + + + +```mermaid +graph LR + A[PhysicalDevice]-->|logical_device_lh|B[LogicalDevice]; + B-.->|logical_device_list|A + subgraph SA[PhysicalDevice] + A1[PhysicalDevice]-.->|bus_list|AA1[Bus] + AA1-->|device_lh|A1 + A1-->|irq_lh|AA4[DeviceIrq] + AA4-.->|device_list|A1 + end + subgraph SB[LogicalDevice] + B0[LogicalDevice] + B0-.->|dm_device_list|BB2[XxDeviceManager] + BB2-->|device_list|B0 + B0-.->|device_driver_device_list|BB3[DeviceDriver] + BB3-->|device_list|B0 + end +``` + +# 结构体 + +## Driver + +`Driver`结构描述一个驱动集合,类似于Windows中用户直接下载的驱动 + +```c +typedef struct Driver { + string_t short_name; + list_t device_driver_lh; + list_t remapped_memory_lh; + + DriverState state; +} Driver; +``` + +- `short_name`: 暂时无用 +- `device_driver_lh`: 链表,存储`Driver`下注册的所有`DeviceDriver` +- `remapped_memory_lh`: 链表,存储`Driver`下所有驱动程序重映射的内存,方便检查是否重复映射同一片内存和在销毁时释放 + +## BusDriver + +## BusType + +```c +typedef enum BusType { + BUS_TYPE_PLATFORM, + BUS_TYPE_PCI, + BUS_TYPE_ISA, + BUS_TYPE_USB, + BUS_TYPE_MAX, +} BusType; +``` + +目前支持4种Bus类型, + +- `BUS_TYPE_PLATFORM`: 所有通过固定配置发现的设备都挂到`platform_bus`下,如`pic`/`pit`这类设备 +- `BUS_TYPE_PCI`: PCI总线,没什么好说的。在x86中,PCI控制器通过特定IO端口直接访问,所以挂在`platform_bus`下 +- `BUS_TYPE_ISA`: ISA总线,目前已有驱动的只有一个`Sound Blaster 16`设备属于ISA总线 +- `BUS_TYPE_USB`: USB总线,需要注意的是USB主机控制器接口(Host Controller Interface, HCI)不属于USB总线,因为控制器自身是一个独立的设备挂在其他总线下,如`XHCI`(USB3.x)/`EHCI`(USB2.0)/`UHCI`(USB1.x)/`OHCI`(USB1.x)这些HCI在PC中都是通过PCI总线发现的,所以属于PCI总线 + +### BusDriver + +```c +typedef struct BusDriver { + list_t bus_lh; + string_t name; + BusType bus_type; + DriverState state; + + Object *object; + + uint16_t new_bus_num; + uint16_t bus_count; +} BusDriver; +``` + +- `bus_lh`: 链表,保存这一类型总线下的所有具体的`Bus` +- `name`: 仅用于寻址,如果为`"PCI"`则可直接通过`\Bus\PCI\x\y`寻址到总线下的`PhysicalDevice` +- `bus_type`: 总线类型 +- `state`: 驱动状态,主要用于总线下设备驱动注册时先检查总线驱动是否初始化完成 +- `object`: 可被寻址的结构,`name`为`"PCI"`时则对应路径`\Bus\PCI` +- `new_bus_num`: 用于分配新创建的`Bus`的编号,对应路径`\Bus\PCI\x\y`中的`x` +- `bus_count`: 统计`Bus`的数量 + +### Bus + +```c +typedef struct Bus { + list_t device_lh; + list_t bus_list; + list_t bus_check_list; + list_t new_bus_list; + BusDriver *bus_driver; + + struct Bus *primary_bus; + + Object *object; + + uint32_t bus_num; + uint32_t subordinate_bus_num; + + int new_device_num; + int device_count; + + BusOps *ops; +} Bus; +``` + +- `device_lh`: 链表,保存总线下所有设备 +- `bus_list`: 连接到`BusDriver`中的`bus_lh` +- `bus_check_list`: 连接到`driver.c`中的`bus_check_lh`,用于启动后持续检测总线设备连接情况,目前仅USB使用 +- `new_bus_list`: 由`register_bus_driver`添加到`driver.c`的`new_bus_lh`中,用于启动时遍历所有总线并初始化 +- `bus_driver`: 对应的`BusDriver` +- `primary_bus`: 父总线,如果没有则为`NULL` +- `object`: `bus`对应的`Object`,对应路径`\Bus\PCI\x\y`中的`x` `Object` +- `bus_num`: `bus`的编号,在`create_bus`时分配,对应路径`\Bus\PCI\x\y`中的`x`的数值 +- `subordinate_bus_num`: 子`Bus`的起始编号 +- `new_device_num`: 用于分配总线下新设备的编号,对应路径`\Bus\PCI\x\y`中的`y` +- `device_count`: 统计总线下设备的总数 +- `ops`: 每个`Bus`的操作接口 + +### BusOps + +```c +typedef struct BusOps { + DriverResult (*scan_bus)(struct BusDriver *bus_driver, struct Bus *bus); + DriverResult (*probe_device)(struct BusDriver *bus_driver, struct Bus *bus); +} BusOps; +``` + +- `scan_bus`: 扫描总线下存在的设备 +- `probe_device`: 探测总线下所有的设备,并为其匹配驱动 + +## DeviceDriver + +### DeviceDriver + +```c +typedef struct DeviceDriver { + list_t device_driver_list; + list_t device_lh; +} DeviceDriver; +``` + +- `device_driver_list`: 连接到`Driver`的`device_driver_lh` +- `device_lh`: 链表,保存该`DeviceDriver`驱动的所有设备 + +## Device + +### DeviceKind + +```c +typedef enum DeviceKind { + DEVICE_KIND_PHYSICAL, + DEVICE_KIND_LOGICAL, +} DeviceKind; +``` + +用于区分`PhysicalDevice`和`LogicalDevice`类型 + +### DeviceState + +```c +typedef enum { + DEVICE_STATE_UNINIT, // 设备未初始化 + DEVICE_STATE_READY, // 设备准备就绪 + DEVICE_STATE_ACTIVE, // 设备正在运行 + DEVICE_STATE_ERROR, // 设备错误 +} DeviceState; +``` + +### DeviceOps + +```c +typedef struct DeviceOps { + DriverResult (*init)(void *device); // 初始化设备 + DriverResult (*start)(void *device); // 启动设备 + DriverResult (*stop)(void *device); // 停止设备 + DriverResult (*destroy)(void *device); // 销毁设备 +} DeviceOps; +``` + +`PhysicalDevice`和`LogicalDevice`通用,所以使用`void *`类型 + +### PhysicalDevice + +```c +typedef struct PhysicalDevice { + DeviceKind kind; + DeviceState state; + list_t new_device_list; + + list_t bus_list; + list_t logical_device_lh; + list_t irq_lh; + + int num; + + struct Bus *bus; + + struct Object *object; + + DeviceOps *ops; + + void *private_data; + void *bus_ext; +} PhysicalDevice; +``` + +`PhysicalDevice`一般对应真实存在的设备(或芯片),一般在总线探测设备时直接创建,设备驱动需要使用`register_physical_device`才不会在初始化设备时忽略这个设备。如果不是由总线发现时则需要驱动自行调用`create_physical_device`创建 + +- `kind`: 标识设备种类(`PhysicalDevice`/`LogicalDevice`),与`LogicalDevice`头部保持一致,所以可以先假设类型再判断 +- `state`: 标识设备状态,其余同上 +- `new_device_list`: 连接到`new_device_lh`,其余同上 +- `bus_list`: 连接到`Bus`的`device_lh` +- `logical_device_lh`: 链表,保存`PhysicalDevice`对应的所有`LogicalDevice` +- `irq_lh`: 暂未使用,计划用于删除`PhysicalDevice`时注销该设备所有已注册的`DeviceIrq` +- `num`: 该设备在总线下的设备编号,对应路径`\Bus\PCI\x\y`中的`y`的数值 +- `bus`: 该设备所在的`Bus` +- `object`: 对应路径`\Bus\PCI\x\y`指向的`Object` +- `ops`: 设备通用的操作接口,由具体的设备驱动通过`register_physical_device`设置 +- `private_data`: 驱动自行保存的信息 +- `bus_ext`: 由总线保存的总线相关信息 + +### DeviceType + +```c +typedef enum { + DEVICE_TYPE_UNKNOWN = 0, // 未知设备类型 + DEVICE_TYPE_INTERRUPT_CONTROLLER, // 中断控制器 + DEVICE_TYPE_TIMER, // 定时器设备 + DEVICE_TYPE_FRAMEBUFFER, // 通过显示缓冲区直接控制的屏幕 + DEVICE_TYPE_STORAGE, // 存储设备(如硬盘) + DEVICE_TYPE_INPUT, // 输入设备(如键盘鼠标) + DEVICE_TYPE_SOUND, // 声音设备(声卡) + DEVICE_TYPE_BUS_CONTROLLER, // 总线控制器(如usb控制器XHCI/EHCI/OHCI/UHCI) + DEVICE_TYPE_INTERNET, // 网络设备(网卡) + DEVICE_TYPE_TIME, // 时间设备(如:Unix时间戳/UTC时间) + DEVICE_TYPE_SERIAL, // 串口设备 + DEVICE_TYPE_MAX, +} DeviceType; +``` + +只在`LogicalDevice`中使用,用于标识`LogicalDevice`对应的设备的功能 + +需要注意的是USB设备不单独作为类型在`DeviceType中`,USB设备根据其具体的功能选择`DeviceType` + +### LogicalDevice + +```c +typedef struct LogicalDevice { + DeviceKind kind; + DeviceState state; + list_t new_device_list; + + list_t logical_device_list; + list_t dm_device_list; + list_t device_driver_device_list; + + DeviceType type; + DeviceOps *ops; + + struct PhysicalDevice *physical_device; + struct Object *object; + void *dm_ext; // 设备管理器所需的扩展信息 + + void *private_data; +} LogicalDevice; +``` + +`LogicalDevice`根据具体的功能来划分,一个`PhysicalDevice`可以创建多个`LogicalDevice`,一般通过对应`DeviceManager`的接口隐式创建,如果是未知设备类型需要手动调用`create_logical_device`创建 + +- `kind`: 同上 +- `state`: 同上 +- `new_device_list`: 同上 +- `logical_device_list`: 连接到`PhysicalDevice`的`logical_device_lh` +- `dm_device_list`: 连接到`DeviceManager`的`device_lh` +- `device_driver_device_list`: 连接到`DeviceDriver`的`device_lh` +- `type`: 标识设备类型 +- `ops`: 同`PhysicalDevice`,一般由对应的`DeviceManager`设置,如果是未知类型则需要自行设置 + +# 指南 + +## 基本结构 + +*注意:为了尽可能展示各种接口等用法,这里把很多东西拼在了一起,请根据需要选择需要用到的部分* + +```c +DriverResult example_pci_probe(PciDevice *pci_device, PhysicalDevice *physical_device); +DriverResult example_device_start(void *_device); +DriverResult example_device_init(void *_device); + +// 定义全局变量 +// 操作接口 +PciDriverOps example_pci_driver_ops = { + .probe = example_pci_probe, +}; +BusOps example_bus_ops = { + .scan_bus = NULL, + .probe_device = NULL, +} +DeviceOps example_physical_device_ops = { + .init = NULL, + .start = example_device_start, + .stop = NULL, + .destroy = NULL, +}; +DeviceOps example_logical_device_ops = { + .init = example_device_init, + .start = NULL, + .stop = NULL, + .destroy = NULL, +}; + +Driver example_driver; // 驱动 +BusDriver example_bus_driver = { // 总线驱动 + .name = STRING_INIT("Example"), // 总线名称 +}; +// 定义PCI设备驱动信息 +PciDriver example_pci_driver = { + .driver = &example_driver, + .device_driver = &example_device_driver, + .find_type = FIND_BY_VENDORID_DEVICEID, + .vendor_device = {EXAMPLE_VENDOR_ID, EXAMPLE_DEVICE_ID}, + .ops = &example_pci_driver_ops, +}; +DeviceDriver example_device_driver; // 设备驱动 +// 如果确认只有一个的话,Bus、PhysicalDevice、LogicalDevice等结构可以定义为全局指针变量 +Bus *bus; +// PhysicalDevice *physical_device; +// LogicalDevice *logical_device; +DeviceIrq *irq; + +void example_irq_handler(void *_device) { + PhysicalDevice *device = _device; + + if (!have_interrupt()) return; // 检查中断是否来自该设备 +} + +DriverResult example_device_start(void *_device) { + PhysicalDevice *physical_device = _device; + + register_device_irq(&irq, physical_device, physical_device /* arg */, EXAMPLE_IRQ, example_irq_handler, IRQ_MODE_SHARED); // 注册共享IRQ中断 + + enable_device_irq(&irq); // 启用IRQ + + return DRIVER_OK; +} + +DriverResult example_device_init(void *_device) { + DriverResult result; + result = create_bus(&bus, &example_bus_driver, &example_bus_ops); + + return result; +} + +DriverResult example_pci_probe(PciDevice *pci_device, PhysicalDevice *physical_device) { + DriverResult result; + XxxDevice *xxx_device; + result = create_xxx_device(&xxx_device, &example_logical_device_ops, physical_device); + if (result != DRIVER_OK) return result; + + register_physical_device(physical_device, &example_physical_device_ops); + physical_device = physical_device; + + return DRIVER_OK; +} + +// register_driver和register_bus_driver尽量在initcall阶段完成注册 +static __init void example_entry(void) { + register_driver(&example_driver); + register_bus_driver(&example_driver, &example_bus_driver); + // 如果有pci设备等总线设备的话也要在initcall阶段注册 + pci_register_driver(&example_driver, &example_pci_driver); +} + +driver_initcall(example_entry) // 链接的时候写入到.initcall段 +``` + + + + + +## 其他 + +`XxDevice`:基础的分配等工作由`xx_dm`完成,设备参数信息填写则是由驱动在init阶段自行完成 + +`DeviceIrq`: 由驱动自行决定传入参数 + +`LogicalDevice`: `private_data`由驱动自行申请内存并填入,`create_logical_device`和`delete_logical_device`不负责管理`private_data` + From 08954b34bfc4b46926f1d837ad2db9400af63f29 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 7 Oct 2025 15:02:04 +0800 Subject: [PATCH 148/158] =?UTF-8?q?thread:=20=E4=BF=AE=E5=A4=8Dthread=5Fun?= =?UTF-8?q?block=E9=94=99=E8=AF=AF=E4=BF=AE=E6=94=B9=E6=AD=A3=E5=9C=A8?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E7=9A=84=E7=BA=BF=E7=A8=8B=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/thread.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/kernel/thread.c b/src/kernel/thread.c index b705f50..46a0233 100644 --- a/src/kernel/thread.c +++ b/src/kernel/thread.c @@ -269,7 +269,11 @@ void thread_unblock(struct task_s *pthread) { return; } - if (pthread->status != TASK_READY) pthread->status = TASK_READY; + if (pthread != current_task) { + if (pthread->status != TASK_READY) { pthread->status = TASK_READY; } + } else { + pthread->status = TASK_RUNNING; + } spin_unlock_irqrestore(&pthread->status_lock, flags); } @@ -356,7 +360,6 @@ void schedule(void) { // 4. 改变状态并加入到thread_ready if (next->status == TASK_READY) next->status = TASK_RUNNING; spin_unlock(&thread_ready_lock); - // printk("%s,%d\n", next->name, timer_get_counter()); prev = cur; // 5. 切换线程 From dffe6def7442431f46d249a9dc21c328f567c2b4 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 7 Oct 2025 15:02:53 +0800 Subject: [PATCH 149/158] =?UTF-8?q?sb16:=20=E4=BF=AE=E5=A4=8D=E7=A7=81?= =?UTF-8?q?=E6=9C=89=E6=95=B0=E6=8D=AE=E7=9A=84=E5=86=85=E5=AD=98=E5=88=86?= =?UTF-8?q?=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/sound/sb16/sb16.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/arch/x86/drivers/sound/sb16/sb16.c b/src/arch/x86/drivers/sound/sb16/sb16.c index caa6006..a2a300e 100644 --- a/src/arch/x86/drivers/sound/sb16/sb16.c +++ b/src/arch/x86/drivers/sound/sb16/sb16.c @@ -229,7 +229,8 @@ DriverResult sb16_probe(IsaDeviceDriver *isa_device_driver) { DriverResult sb16_init(void *_device) { LogicalDevice *device = _device; - Sb16Info *info = (Sb16Info *)device->private_data; + Sb16Info *info = kmalloc(sizeof(Sb16Info)); + device->private_data = info; // io_out8(info->ports.mixer, 0x80 /* 设置IRQ */); // io_out8(info->ports.mixer_data, 0x02 /* IRQ5 */); From d8e1193fd09ea0e92a9dc42b22bc6b54bc483755 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 9 Oct 2025 23:47:07 +0800 Subject: [PATCH 150/158] =?UTF-8?q?driver:=20enable=5Fdevice=5Firq?= =?UTF-8?q?=E5=92=8Cdisable=5Fdevice=5Firq=E5=8A=A0=E5=85=A5=E6=A3=80?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/driver/driver_interface.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/kernel/driver/driver_interface.c b/src/kernel/driver/driver_interface.c index 8c3c5df..559c7a7 100644 --- a/src/kernel/driver/driver_interface.c +++ b/src/kernel/driver/driver_interface.c @@ -61,13 +61,19 @@ DriverResult unregister_device_irq(DeviceIrq *dev_irq) { } DriverResult enable_device_irq(DeviceIrq *dev_irq) { - list_add_tail(&dev_irq->list, &device_irq_lists[dev_irq->irq]); - return interrupt_enable_irq(dev_irq->irq); + bool empty = list_empty(&device_irq_lists[dev_irq->irq]); + if (!list_in_list(&dev_irq->list)) + list_add_tail(&dev_irq->list, &device_irq_lists[dev_irq->irq]); + if (empty) { return interrupt_enable_irq(dev_irq->irq); } + return DRIVER_OK; } DriverResult disable_device_irq(DeviceIrq *dev_irq) { - list_del(&dev_irq->list); - return interrupt_disable_irq(dev_irq->irq); + if (list_in_list(&dev_irq->list)) list_del(&dev_irq->list); + if (list_empty(&device_irq_lists[dev_irq->irq])) { + return interrupt_disable_irq(dev_irq->irq); + } + return DRIVER_OK; } void device_irq_handler(int irq) { From 837dab216d7b1019267e5b90388161507758441f Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Thu, 9 Oct 2025 23:49:27 +0800 Subject: [PATCH 151/158] =?UTF-8?q?input:=20=E5=9F=BA=E4=BA=8EUSB=20HID=20?= =?UTF-8?q?Usage=20Table=E7=9A=84=E5=AE=9A=E4=B9=89key=20event=E7=9A=84?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6id?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/input/input_dm.c | 40 ++- src/drivers/usb/hid/keyboard.c | 40 +-- src/drivers/usb/hid/mouse.c | 36 ++- src/include/driver/input/input_dm.h | 18 +- src/include/driver/input/key_events.h | 373 ++++++++++++++++++++++++++ 5 files changed, 442 insertions(+), 65 deletions(-) create mode 100644 src/include/driver/input/key_events.h diff --git a/src/driver/input/input_dm.c b/src/driver/input/input_dm.c index 5603d1f..2ea5489 100644 --- a/src/driver/input/input_dm.c +++ b/src/driver/input/input_dm.c @@ -1,3 +1,4 @@ +#include "kernel/console.h" #include "kernel/driver.h" #include "kernel/spinlock.h" #include "string.h" @@ -35,12 +36,14 @@ DriverResult input_dm_load(DeviceManager *manager) { input_dm_ext.key_events = kmalloc(sizeof(KeyEvent) * INPUT_EVENT_QUEUE_SIZE); - input_dm_ext.key_event_w = 0; - input_dm_ext.key_event_r = 0; + input_dm_ext.key_event_w = 0; + input_dm_ext.key_event_r = 0; + input_dm_ext.key_event_full = false; input_dm_ext.pointer_events = kmalloc(sizeof(PointerEvent) * INPUT_EVENT_QUEUE_SIZE); - input_dm_ext.pointer_event_w = 0; - input_dm_ext.pointer_event_r = 0; + input_dm_ext.pointer_event_w = 0; + input_dm_ext.pointer_event_r = 0; + input_dm_ext.pointer_event_full = false; return DRIVER_OK; } @@ -123,27 +126,44 @@ DriverResult delete_input_device(InputDevice *input_device) { return DRIVER_OK; } -KeyEvent *new_key_event() { - if (input_dm_ext.key_event_w == input_dm_ext.key_event_r) { +void new_key_event(uint16_t keycode, uint8_t pressed, uint8_t page) { + if (input_dm_ext.key_event_full) { // 队列满,丢弃最旧的事件 input_dm_ext.key_event_r = (input_dm_ext.key_event_r + 1) % INPUT_EVENT_QUEUE_SIZE; + // 分配新的事件后仍然是满的,所以不更新full标志 } KeyEvent *event = &input_dm_ext.key_events[input_dm_ext.key_event_w]; + event->keycode = keycode; + event->pressed = pressed; + event->page = page; input_dm_ext.key_event_w = (input_dm_ext.key_event_w + 1) % INPUT_EVENT_QUEUE_SIZE; - return event; + + // 如果更新前w在前r在后,更新后相等说明队列满 + if (input_dm_ext.key_event_w == input_dm_ext.key_event_r) { + input_dm_ext.key_event_full = true; + } + return; } -PointerEvent *new_pointer_event() { - if (input_dm_ext.pointer_event_w == input_dm_ext.pointer_event_r) { +void new_pointer_event(int16_t dx, int16_t dy, enum PointerEventType type) { + if (input_dm_ext.pointer_event_full) { // 队列满,丢弃最旧的事件 input_dm_ext.pointer_event_r = (input_dm_ext.pointer_event_r + 1) % INPUT_EVENT_QUEUE_SIZE; + // 分配新的事件后仍然是满的,所以不更新full标志 } PointerEvent *event = &input_dm_ext.pointer_events[input_dm_ext.pointer_event_w]; + event->dx = dx; + event->dy = dy; + event->type = type; input_dm_ext.pointer_event_w = (input_dm_ext.pointer_event_w + 1) % INPUT_EVENT_QUEUE_SIZE; - return event; + + if (input_dm_ext.pointer_event_w == input_dm_ext.pointer_event_r) { + input_dm_ext.pointer_event_full = true; + } + return; } diff --git a/src/drivers/usb/hid/keyboard.c b/src/drivers/usb/hid/keyboard.c index ca8185d..5c37611 100644 --- a/src/drivers/usb/hid/keyboard.c +++ b/src/drivers/usb/hid/keyboard.c @@ -36,26 +36,15 @@ void usb_hid_keyboard_handler(UsbRequestBlock *urb) { UsbHidKeyboard *keyboard = urb->context; UsbDevice *usb_device = keyboard->usb_device; if (urb->status == USB_STATUS_ACK) { - printk( - "Keyboard Report: Keycode: M:0x%02x 0x%02x 0x%02x 0x%02x 0x%02x " - "0x%02x " - "0x%02x\n", - report->modifier_keys, report->keycodes[0], report->keycodes[1], - report->keycodes[2], report->keycodes[3], report->keycodes[4], - report->keycodes[5]); if (report->modifier_keys != keyboard->last_keys[0]) { for (int i = 0; i < 8; i++) { uint8_t mask = 1 << i; if ((report->modifier_keys & mask) | (keyboard->last_keys[0] & mask)) { - KeyEvent *event = new_key_event(); - event->page = 0; - event->keycode = INPUT_KEY_EVENT_MODIFIER_BASE + i; - if (keyboard->last_keys[0] & mask) { - event->pressed = 0; - } else { - event->pressed = 1; - } + new_key_event( + INPUT_KEY_EVENT_MODIFIER_BASE + i, + keyboard->last_keys[0] & mask ? 0 : 1, + INPUT_KEY_PAGE_KEYBOARD_KEYPAD); } } } @@ -77,18 +66,15 @@ void usb_hid_keyboard_handler(UsbRequestBlock *urb) { if (found1 && found2) break; } if (!found1) { - KeyEvent *event = new_key_event(); - event->page = 0; - event->keycode = - INPUT_KEY_EVENT_KEYBOARD_BASE + report->keycodes[i]; - event->pressed = 1; + new_key_event( + INPUT_KEY_EVENT_KEYBOARD_BASE + report->keycodes[i], 1, + INPUT_KEY_PAGE_KEYBOARD_KEYPAD); } if (!found2) { - KeyEvent *event = new_key_event(); - event->page = 0; - event->keycode = INPUT_KEY_EVENT_KEYBOARD_BASE + - keyboard->last_keys[i + 1]; - event->pressed = 0; + new_key_event( + INPUT_KEY_EVENT_KEYBOARD_BASE + + keyboard->last_keys[i + 1], + 0, INPUT_KEY_PAGE_KEYBOARD_KEYPAD); } } } @@ -112,10 +98,6 @@ DriverResult usb_hid_keyboard_init(void *_device) { if ((ep->desc->bmAttributes & 0x03) == USB_EP_INTERRUPT && (ep->desc->bEndpointAddress >> 7) == USB_EP_IN) { // 找到中断输入端点 - printk( - "Keyboard Interrupt IN Endpoint Found: 0x%02x\n", - ep->desc->bEndpointAddress); - int size = ep->desc->wMaxPacketSize & 0x7ff; keyboard->buffer = kmalloc(size); keyboard->urb = usb_create_urb( diff --git a/src/drivers/usb/hid/mouse.c b/src/drivers/usb/hid/mouse.c index 9e3e8fe..0342509 100644 --- a/src/drivers/usb/hid/mouse.c +++ b/src/drivers/usb/hid/mouse.c @@ -1,3 +1,4 @@ +#include "driver/input/key_events.h" #include #include #include @@ -34,24 +35,23 @@ void usb_hid_mouse_handler(UsbRequestBlock *urb) { UsbHidMouse *mouse = urb->context; UsbDevice *usb_device = mouse->usb_device; if (urb->status == USB_STATUS_ACK) { - printk( - "Mouse Report: Buttons: 0x%02x, X: %d, Y: %d\n", report->buttons, - report->x, report->y); if (report->x != 0 || report->y != 0) { - PointerEvent *event = new_pointer_event(); - if (event) { - event->type = POINTER_TYPE_MOVE; - event->dx = report->x; - event->dy = report->y; - } + new_pointer_event(report->x, report->y, POINTER_TYPE_MOVE); } - if ((report->buttons & 7) != (mouse->last_buttons & 7)) { - KeyEvent *event = new_key_event(); - if (event) { - event->keycode = report->buttons + INPUT_KEY_EVENT_MOUSE_BASE; - event->pressed = 1; - event->page = 0; - } + if ((report->buttons ^ mouse->last_buttons) & 0x01) { // 左键变化 + new_key_event( + INPUT_KEY_EVENT_MOUSE_BASE + KEY_MOUSE_LEFT, + report->buttons & 0x01, INPUT_KEY_PAGE_KEYBOARD_KEYPAD); + } + if ((report->buttons ^ mouse->last_buttons) & 0x02) { // 右键变化 + new_key_event( + INPUT_KEY_EVENT_MOUSE_BASE + KEY_MOUSE_RIGHT, + (report->buttons >> 1) & 0x01, INPUT_KEY_PAGE_KEYBOARD_KEYPAD); + } + if ((report->buttons ^ mouse->last_buttons) & 0x04) { // 中键变化 + new_key_event( + INPUT_KEY_EVENT_MOUSE_BASE + KEY_MOUSE_MIDDLE, + (report->buttons >> 2) & 0x01, INPUT_KEY_PAGE_KEYBOARD_KEYPAD); } urb->ep->data_toggle ^= 1; usb_device->hcd->ops->interrupt_transfer(usb_device->hcd, urb->ep); @@ -71,10 +71,6 @@ DriverResult usb_hid_mouse_init(void *_device) { if ((ep->desc->bmAttributes & 0x03) == USB_EP_INTERRUPT && (ep->desc->bEndpointAddress >> 7) == USB_EP_IN) { // 找到中断输入端点 - printk( - "Mouse Interrupt IN Endpoint Found: 0x%02x\n", - ep->desc->bEndpointAddress); - int size = ep->desc->wMaxPacketSize & 0x7ff; mouse->buffer = kmalloc(size); mouse->urb = usb_create_urb( diff --git a/src/include/driver/input/input_dm.h b/src/include/driver/input/input_dm.h index 00a5422..523af29 100644 --- a/src/include/driver/input/input_dm.h +++ b/src/include/driver/input/input_dm.h @@ -14,6 +14,10 @@ #define INPUT_KEY_EVENT_MODIFIER_BASE 8 #define INPUT_KEY_EVENT_KEYBOARD_BASE 16 +#define INPUT_KEY_PAGE_KEYBOARD_KEYPAD 0x07 +#define INPUT_KEY_PAGE_CONSUMER 0x0c +#define INPUT_KEY_PAGE_GENERAL_DESKTOP 0x01 + typedef enum { INPUT_TYPE_UNKNOWN, INPUT_TYPE_KEYBOARD, @@ -27,15 +31,15 @@ typedef struct InputDevice { } InputDevice; typedef struct KeyEvent { - uint8_t keycode; - uint8_t pressed; // 1: pressed, 0: released - uint8_t page; + uint16_t keycode; + uint8_t pressed; // 1: pressed, 0: released + uint8_t page; } KeyEvent; typedef struct PointerEvent { int16_t dx; int16_t dy; - enum { + enum PointerEventType { POINTER_TYPE_MOVE, POINTER_TYPE_SCROLL, POINTER_TYPE_PRESSURE, @@ -48,9 +52,11 @@ typedef struct InputDeviceManager { spinlock_t lock[INPUT_TYPE_MAX]; int key_event_w, key_event_r; + bool key_event_full; KeyEvent *key_events; int pointer_event_w, pointer_event_r; + bool pointer_event_full; PointerEvent *pointer_events; } InputDeviceManager; @@ -61,7 +67,7 @@ DriverResult delete_input_device(InputDevice *input_device); extern DeviceManager input_dm; -KeyEvent *new_key_event(); -PointerEvent *new_pointer_event(); +void new_key_event(uint16_t keycode, uint8_t pressed, uint8_t page); +void new_pointer_event(int16_t dx, int16_t dy, enum PointerEventType type); #endif \ No newline at end of file diff --git a/src/include/driver/input/key_events.h b/src/include/driver/input/key_events.h new file mode 100644 index 0000000..465bd97 --- /dev/null +++ b/src/include/driver/input/key_events.h @@ -0,0 +1,373 @@ +#ifndef _INPUT_KEY_EVENTS_H +#define _INPUT_KEY_EVENTS_H + +/** + * @brief 除标准鼠标按键外使用HID Usage Tables定义的按键码 + * References: + * https://www.usb.org/sites/default/files/hut1_6.pdf + */ + +// 鼠标按键 +#define KEY_MOUSE_LEFT 0x01 +#define KEY_MOUSE_RIGHT 0x02 +#define KEY_MOUSE_MIDDLE 0x03 + +// General Desktop Page +// ... +#define KEY_GDP_SYSTEM_POWER_DOWN 0x81 +#define KEY_GDP_SYSTEM_SLEEP 0x82 +#define KEY_GDP_SYSTEM_WAKEUP 0x83 +#define KEY_GDP_SYSTEM_CONTEXT_MENU 0x84 +#define KEY_GDP_SYSTEM_MAIN_MENU 0x85 +#define KEY_GDP_SYSTEM_APP_MENU 0x86 +#define KEY_GDP_SYSTEM_MENU_HELP 0x87 +#define KEY_GDP_SYSTEM_MENU_EXIT 0x88 +#define KEY_GDP_SYSTEM_MENU_SELECT 0x89 +// ... +#define KEY_GDP_SYSTEM_COLD_RESTART 0x8E +#define KEY_GDP_SYSTEM_WARM_RESTART 0x8F +// ... + +// Keyboard/Keypad Page +#define KEY_A 0x04 +#define KEY_B 0x05 +#define KEY_C 0x06 +#define KEY_D 0x07 +#define KEY_E 0x08 +#define KEY_F 0x09 +#define KEY_G 0x0A +#define KEY_H 0x0B +#define KEY_I 0x0C +#define KEY_J 0x0D +#define KEY_K 0x0E +#define KEY_L 0x0F +#define KEY_M 0x10 +#define KEY_N 0x11 +#define KEY_O 0x12 +#define KEY_P 0x13 +#define KEY_Q 0x14 +#define KEY_R 0x15 +#define KEY_S 0x16 +#define KEY_T 0x17 +#define KEY_U 0x18 +#define KEY_V 0x19 +#define KEY_W 0x1A +#define KEY_X 0x1B +#define KEY_Y 0x1C +#define KEY_Z 0x1D +#define KEY_1 0x1E +#define KEY_2 0x1F +#define KEY_3 0x20 +#define KEY_4 0x21 +#define KEY_5 0x22 +#define KEY_6 0x23 +#define KEY_7 0x24 +#define KEY_8 0x25 +#define KEY_9 0x26 +#define KEY_0 0x27 +#define KEY_ENTER 0x28 +#define KEY_ESC 0x29 +#define KEY_BACKSPACE 0x2A +#define KEY_TAB 0x2B +#define KEY_SPACE 0x2C +#define KEY_MINUS 0x2D // '-' +#define KEY_EQUAL 0x2E // '=' +#define KEY_LEFTBRACE 0x2F // '[' +#define KEY_RIGHTBRACE 0x30 // ']' +#define KEY_BACKSLASH 0x31 // '\' +#define KEY_SEMICOLON 0x33 // ';' +#define KEY_APOSTROPHE 0x34 // '\'' +#define KEY_GRAVE 0x35 // '`' +#define KEY_COMMA 0x36 // ',' +#define KEY_DOT 0x37 // '.' +#define KEY_SLASH 0x38 // '/' +#define KEY_CAPSLOCK 0x39 +#define KEY_F1 0x3A +#define KEY_F2 0x3B +#define KEY_F3 0x3C +#define KEY_F4 0x3D +#define KEY_F5 0x3E +#define KEY_F6 0x3F +#define KEY_F7 0x40 +#define KEY_F8 0x41 +#define KEY_F9 0x42 +#define KEY_F10 0x43 +#define KEY_F11 0x44 +#define KEY_F12 0x45 +#define KEY_PRINTSCREEN 0x46 +#define KEY_SCROLLLOCK 0x47 +#define KEY_PAUSE 0x48 +#define KEY_INSERT 0x49 +#define KEY_HOME 0x4A +#define KEY_PAGEUP 0x4B +#define KEY_DELETE 0x4C +#define KEY_END 0x4D +#define KEY_PAGEDOWN 0x4E +#define KEY_RIGHT 0x4F +#define KEY_LEFT 0x50 +#define KEY_DOWN 0x51 +#define KEY_UP 0x52 +#define KEY_NUMLOCK 0x53 +#define KEY_KEYPAD_SLASH 0x54 // '/' +#define KEY_KEYPAD_ASTERISK 0x55 // '*' +#define KEY_KEYPAD_MINUS 0x56 // '-' +#define KEY_KEYPAD_PLUS 0x57 // '+' +#define KEY_KEYPAD_ENTER 0x58 +#define KEY_KEYPAD_1 0x59 +#define KEY_KEYPAD_2 0x5A +#define KEY_KEYPAD_3 0x5B +#define KEY_KEYPAD_4 0x5C +#define KEY_KEYPAD_5 0x5D +#define KEY_KEYPAD_6 0x5E +#define KEY_KEYPAD_7 0x5F +#define KEY_KEYPAD_8 0x60 +#define KEY_KEYPAD_9 0x61 +#define KEY_KEYPAD_0 0x62 +#define KEY_KEYPAD_DOT 0x63 +#define KEY_NON_US_64 0x64 // "<>" or "\|" +#define KEY_APPLICATION 0x65 +#define KEY_POWER 0x66 +#define KEY_KEYPAD_EQUAL 0x67 // '=' +#define KEY_F13 0x68 +#define KEY_F14 0x69 +#define KEY_F15 0x6A +#define KEY_F16 0x6B +#define KEY_F17 0x6C +#define KEY_F18 0x6D +#define KEY_F19 0x6E +#define KEY_F20 0x6F +#define KEY_F21 0x70 +#define KEY_F22 0x71 +#define KEY_F23 0x72 +#define KEY_F24 0x73 +#define KEY_EXECUTE 0x74 +#define KEY_HELP 0x75 +#define KEY_MENU 0x76 +#define KEY_SELECT 0x77 +#define KEY_STOP 0x78 +#define KEY_AGAIN 0x79 +#define KEY_UNDO 0x7A +#define KEY_CUT 0x7B +#define KEY_COPY 0x7C +#define KEY_PASTE 0x7D +#define KEY_FIND 0x7E +#define KEY_MUTE 0x7F +#define KEY_VOLUMEUP 0x80 +#define KEY_VOLUMEDOWN 0x81 +#define KEY_LOCKING_CAPSLOCK 0x82 +#define KEY_LOCKING_NUMLOCK 0x83 +#define KEY_LOCKING_SCROLLLOCK 0x84 +#define KEY_KEYPAD_COMMA 0x85 +#define KEY_KEYPAD_EQUAL_SIGN 0x86 +#define KEY_INTERNATIONAL1 0x87 +#define KEY_INTERNATIONAL2 0x88 +#define KEY_INTERNATIONAL3 0x89 +#define KEY_INTERNATIONAL4 0x8A +#define KEY_INTERNATIONAL5 0x8B +#define KEY_INTERNATIONAL6 0x8C +#define KEY_INTERNATIONAL7 0x8D +#define KEY_INTERNATIONAL8 0x8E +#define KEY_INTERNATIONAL9 0x8F +#define KEY_LANG1 0x90 // "Hangul/English" +#define KEY_LANG2 0x91 // "Hanja" +#define KEY_LANG3 0x92 // "Katakana" +#define KEY_LANG4 0x93 // "Hiragana" +#define KEY_LANG5 0x94 // "Zenkaku/Hankaku" +#define KEY_LANG6 0x95 // "Reserved" +#define KEY_LANG7 0x96 // "Reserved" +#define KEY_LANG8 0x97 // "Reserved" +#define KEY_LANG9 0x98 // "Reserved" +#define KEY_ALTERASE 0x99 +#define KEY_SYSREQ 0x9A +#define KEY_CANCEL 0x9B +#define KEY_CLEAR 0x9C +#define KEY_PRIOR 0x9D +#define KEY_RETURN 0x9E +#define KEY_SEPARATOR 0x9F +#define KEY_OUT 0xA0 +#define KEY_OPER 0xA1 +#define KEY_CLEARAGAIN 0xA2 +#define KEY_CRSEL 0xA3 +#define KEY_EXSEL 0xA4 + +#define KEY_KEYPAD_00 0xB0 +#define KEY_KEYPAD_000 0xB1 +#define KEY_KEYPAD_THOUSANDS_SEPARATOR 0xB2 +#define KEY_KEYPAD_DECIMAL_SEPARATOR 0xB3 +#define KEY_KEYPAD_CURRENCY_UNIT 0xB4 +#define KEY_KEYPAD_CURRENCY_SUBUNIT 0xB5 +#define KEY_KEYPAD_LEFT_PARENTHESIS 0xB6 // '(' +#define KEY_KEYPAD_RIGHT_PARENTHESIS 0xB7 // ')' +#define KEY_KEYPAD_LEFT_BRACE 0xB8 // '{' +#define KEY_KEYPAD_RIGHT_BRACE 0xB9 // '}' +#define KEY_KEYPAD_TAB 0xBA +#define KEY_KEYPAD_BACKSPACE 0xBB +#define KEY_KEYPAD_A 0xBC +#define KEY_KEYPAD_B 0xBD +#define KEY_KEYPAD_C 0xBE +#define KEY_KEYPAD_D 0xBF +#define KEY_KEYPAD_E 0xC0 +#define KEY_KEYPAD_F 0xC1 +#define KEY_KEYPAD_XOR 0xC2 // '^' +#define KEY_KEYPAD_CARET 0xC3 // '^' +#define KEY_KEYPAD_PERCENT 0xC4 // '%' +#define KEY_KEYPAD_LESS_THAN 0xC5 // '<' +#define KEY_KEYPAD_GREATER_THAN 0xC6 +#define KEY_KEYPAD_AMPERSAND 0xC7 // '&' +#define KEY_KEYPAD_AMPERSAND_AMPERSAND 0xC8 // "&&" +#define KEY_KEYPAD_PIPE 0xC9 // '|' +#define KEY_KEYPAD_PIPE_PIPE 0xCA // "||" +#define KEY_KEYPAD_COLON 0xCB // ':' +#define KEY_KEYPAD_HASH 0xCC // '#' +#define KEY_KEYPAD_SPACE 0xCD +#define KEY_KEYPAD_AT 0xCE // '@' +#define KEY_KEYPAD_EXCLAMATION 0xCF // '!' +#define KEY_KEYPAD_MEMORY_STORE 0xD0 +#define KEY_KEYPAD_MEMORY_RECALL 0xD1 +#define KEY_KEYPAD_MEMORY_CLEAR 0xD2 +#define KEY_KEYPAD_MEMORY_ADD 0xD3 +#define KEY_KEYPAD_MEMORY_SUBTRACT 0xD4 +#define KEY_KEYPAD_MEMORY_MULTIPLY 0xD5 +#define KEY_KEYPAD_MEMORY_DIVIDE 0xD6 +#define KEY_KEYPAD_PLUS_MINUS 0xD7 // '±' +#define KEY_KEYPAD_CLEAR 0xD8 +#define KEY_KEYPAD_CLEAR_ENTRY 0xD9 +#define KEY_KEYPAD_BINARY 0xDA +#define KEY_KEYPAD_OCTAL 0xDB +#define KEY_KEYPAD_DECIMAL 0xDC +#define KEY_KEYPAD_HEXADECIMAL 0xDD + +#define KEY_LEFTCTRL 0xE0 +#define KEY_LEFTSHIFT 0xE1 +#define KEY_LEFTALT 0xE2 +#define KEY_LEFTGUI 0xE3 +#define KEY_RIGHTCTRL 0xE4 +#define KEY_RIGHTSHIFT 0xE5 +#define KEY_RIGHTALT 0xE6 +#define KEY_RIGHTGUI 0xE7 + +// Consumer Page (0x0C) +#define KEY_CP_CONSUMER_CONTROL 0x01 +#define KEY_CP_NUMERIC_KEYPAD 0x02 +#define KEY_CP_PROGRAMMABLE_BUTTONS 0x03 +#define KEY_CP_MICROPHONE 0x04 +#define KEY_CP_HEADPHONE 0x05 +#define KEY_CP_GRAPHICS_EQUALIZER 0x06 +#define KEY_CP_PLUS10 0x20 +#define KEY_CP_PLUS100 0x21 +#define KEY_CP_AM_PM 0x22 +#define KEY_CP_POWER 0x30 +#define KEY_CP_RESET 0x31 +#define KEY_CP_SLEEP 0x32 +#define KEY_CP_SLEEP_AFTER 0x33 +#define KEY_CP_SLEEP_MODE 0x34 +#define KEY_CP_ILLUMINATION 0x35 +#define KEY_CP_FUNCTION_BUTTONS 0x36 +#define KEY_CP_MENU 0x40 +#define KEY_CP_MENU_PICK 0x41 +#define KEY_CP_MENU_UP 0x42 +#define KEY_CP_MENU_DOWN 0x43 +#define KEY_CP_MENU_LEFT 0x44 +#define KEY_CP_MENU_RIGHT 0x45 +#define KEY_CP_MENU_ESCAPE 0x46 +#define KEY_CP_MENU_VALUE_INCREASE 0x47 +#define KEY_CP_MENU_VALUE_DECREASE 0x48 +#define KEY_CP_DATA_ON_SCREEN 0x60 +#define KEY_CP_CLOSED_CAPTION 0x61 +#define KEY_CP_CLOSED_CAPTION_SELECT 0x62 +#define KEY_CP_VCR_TV 0x63 +#define KEY_CP_BROADCAST_MODE 0x64 +#define KEY_CP_SNAPSHOT 0x65 +#define KEY_CP_STILL 0x66 +#define KEY_CP_PIC_IN_PIC_TOGGLE 0x67 +#define KEY_CP_PIC_IN_PIC_SWAP 0x68 +#define KEY_CP_RED_MENU 0x69 +#define KEY_CP_GREEN_MENU 0x6A +#define KEY_CP_BLUE_MENU 0x6B +#define KEY_CP_YELLOW_MENU 0x6C +#define KEY_CP_ASPECT 0x6D +#define KEY_CP_3D_MODE_SELECT 0x6E +#define KEY_CP_DISPLAY_BRIGHTNESS_INCREMENT 0x6F +#define KEY_CP_DISPLAY_BRIGHTNESS_DECREMENT 0x70 +#define KEY_CP_DISPLAY_BRIGHTNESS 0x71 +#define KEY_CP_DISPLAY_BACKLIGHT_TOGGLE 0x72 +#define KEY_CP_DISPLAY_SET_BRIGHTNESS_TO_MINIMUM 0x73 +#define KEY_CP_DISPLAY_SET_BRIGHTNESS_TO_MAXIMUM 0x74 +#define KEY_CP_DISPLAY_AUTOBRIGHTNESS_MODE 0x75 +// ... +#define KEY_CP_KEYBOARD_BRIGHTNESS_INCREMENT 0x7F +#define KEY_CP_KEYBOARD_BRIGHTNESS_DECREMENT 0x80 +#define KEY_CP_KEYBOARD_BACKLIGHT_SET_LEVEL 0x81 +#define KEY_CP_KEYBOARD_BACKLIGHT_OOC 0x82 +#define KEY_CP_KEYBOARD_BACKLIGHT_SET_MINIMUM 0x83 +#define KEY_CP_KEYBOARD_BACKLIGHT_SET_MAXIMUM 0x84 +#define KEY_CP_KEYBOARD_BACKLIGHT_AUTO 0x85 +// ... +#define KEY_CP_PLAY 0xB0 +#define KEY_CP_PAUSE 0xB1 +#define KEY_CP_RECORD 0xB2 +#define KEY_CP_FAST_FORWARD 0xB3 +#define KEY_CP_REWIND 0xB4 +#define KEY_CP_NEXT_TRACK 0xB5 +#define KEY_CP_PREVIOUS_TRACK 0xB6 +#define KEY_CP_STOP 0xB7 +#define KEY_CP_EJECT 0xB8 +#define KEY_CP_RANDOM_PLAY 0xB9 +#define KEY_CP_SELECT_DISC 0xBA +#define KEY_CP_ENTER_DISC 0xBB +#define KEY_CP_REPEAT 0xBC +#define KEY_CP_TRACKING 0xBD +#define KEY_CP_TRACK_NORMAL 0xBE +#define KEY_CP_SLOW_TRACKING 0xBF +#define KEY_CP_FRAME_FORWARD 0xC0 +#define KEY_CP_FRAME_BACK 0xC1 +#define KEY_CP_MARK 0xC2 +#define KEY_CP_CLEAR_MARK 0xC3 +#define KEY_CP_REPEAT_FROM_MARK 0xC4 +#define KEY_CP_RETURN_TO_MARK 0xC5 +#define KEY_CP_SEARCH_MARK_FORWARD 0xC6 +#define KEY_CP_SEARCH_MARK_BACKWARDS 0xC7 +#define KEY_CP_COUNTER_RESET 0xC8 +#define KEY_CP_SHOW_COUNTER 0xC9 +#define KEY_CP_TRACKING_INCREMENT 0xCA +#define KEY_CP_TRACKING_DECREMENT 0xCB +#define KEY_CP_STOP_EJECT 0xCC +#define KEY_CP_PLAY_PAUSE 0xCD +#define KEY_CP_PLAY_SKIP 0xCE +#define KEY_CP_VOICE_COMMAND 0xCF +// ... +#define KEY_CP_VOLUME 0xE0 +#define KEY_CP_BALANCE 0xE1 +#define KEY_CP_MUTE 0xE2 +#define KEY_CP_BASS 0xE3 +#define KEY_CP_TREBLE 0xE4 +#define KEY_CP_BASS_BOOST 0xE5 +#define KEY_CP_SURROUND_MODE 0xE6 +#define KEY_CP_LOUDNESS 0xE7 +#define KEY_CP_MPX 0xE8 +#define KEY_CP_VOLUME_INCREMENT 0xE9 +#define KEY_CP_VOLUME_DECREMENT 0xEA +// ... +#define KEY_CP_AL_CONSUMER_CONTROL_CONFIGURATION 0x183 +// ... +#define KEY_CP_AL_EMAIL_READER 0x18A +// ... +#define KEY_CP_AL_CALC 0x192 +// ... +#define KEY_CP_AL_INTERNET_BROWSER 0x196 +// ... +#define KEY_CP_AL_FILE_BROWSER 0x1B4 +// ... +#define KEY_CP_AL_RESEARCH_SEARCH_BROWSER 0x1C6 +// ... +#define KEY_CP_AC_HOME 0x223 +#define KEY_CP_AC_BACK 0x224 +#define KEY_CP_AC_FORWARD 0x225 +#define KEY_CP_AC_STOP 0x226 +#define KEY_CP_AC_REFRESH 0x227 +#define KEY_CP_AC_PREVIOUS_LINK 0x228 +#define KEY_CP_AC_NEXT_LINK 0x229 +#define KEY_CP_AC_BOOKMARKS 0x22A +// ... + +#endif \ No newline at end of file From 78040b2cd402b3c4eab1ed2f82be3013b96c125a Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 10 Oct 2025 01:29:13 +0800 Subject: [PATCH 152/158] =?UTF-8?q?apic:=20=E9=BB=98=E8=AE=A4=E7=A6=81?= =?UTF-8?q?=E7=94=A8apic=20timer=EF=BC=8C=E7=94=B1=E4=BA=8E=E5=9C=A8?= =?UTF-8?q?=E8=99=9A=E6=8B=9F=E6=9C=BA=E4=B8=AD=E9=A2=91=E7=8E=87=E8=BF=87?= =?UTF-8?q?=E4=BA=8E=E4=B8=8D=E7=A8=B3=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/kernel/platform.c | 6 +++--- src/driver/timer/timer_dm.c | 2 ++ src/drivers/usb/core/hub.c | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/arch/x86/kernel/platform.c b/src/arch/x86/kernel/platform.c index fdb9477..6b6ca7e 100644 --- a/src/arch/x86/kernel/platform.c +++ b/src/arch/x86/kernel/platform.c @@ -107,9 +107,9 @@ void platform_start_devices() { print_features(); DRV_RESULT_PRINT_CALL( init_and_start_logical_device(pit_timer_device->device)); - if (use_apic) - DRV_RESULT_PRINT_CALL( - init_and_start_logical_device(apic_timer_device->device)); + // if (use_apic) + // DRV_RESULT_PRINT_CALL( + // init_and_start_logical_device(apic_timer_device->device)); DRV_RESULT_PRINT_CALL( init_and_start_logical_device(rtc_time_device->device)); diff --git a/src/driver/timer/timer_dm.c b/src/driver/timer/timer_dm.c index 34bf4f6..4c06e89 100644 --- a/src/driver/timer/timer_dm.c +++ b/src/driver/timer/timer_dm.c @@ -1,3 +1,4 @@ +#include "kernel/console.h" #include #include #include @@ -120,6 +121,7 @@ void timer_irq_handler(LogicalDevice *device) { cur_thread->elapsed_ticks++; if (cur_thread->ticks == 0) { + // printk("need resched\n"); cur_thread->flags.need_resched = 1; } else { cur_thread->ticks--; diff --git a/src/drivers/usb/core/hub.c b/src/drivers/usb/core/hub.c index 16b6a7a..6155bc8 100644 --- a/src/drivers/usb/core/hub.c +++ b/src/drivers/usb/core/hub.c @@ -1,4 +1,5 @@ #include "kernel/console.h" +#include "kernel/thread.h" #include #include #include @@ -46,9 +47,8 @@ void usb_init_hub(UsbHcd *hcd, UsbHub *hub, UsbDevice *usb_device) { if (status2 == USB_SETUP_CRC_TIMEOUT_ERR) continue; } } - printk("%d ", timer_get_counter()); + delay_ms(&timer, 200); - printk("%d ", timer_get_counter()); for (i = 0; i < hub->desc->bNbrPorts; i++) { status = port_status[i]; From 62843236f85a2337c2d3d6ead6323b6abd47d748 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 10 Oct 2025 01:31:41 +0800 Subject: [PATCH 153/158] =?UTF-8?q?driver&8042:=20=E9=87=8D=E6=9E=84ps/2?= =?UTF-8?q?=E9=94=AE=E9=BC=A0=E9=A9=B1=E5=8A=A8=EF=BC=9B=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=9C=A8=E7=A6=81=E7=94=A8USB=20Legacy=20Sup?= =?UTF-8?q?port=E5=90=8E=E5=86=8D=E5=88=9D=E5=A7=8B=E5=8C=96PS/2=E8=AE=BE?= =?UTF-8?q?=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/arch/x86/drivers/Makefile | 2 +- src/arch/x86/drivers/input/8042/8042.c | 404 +++++++++++------- src/arch/x86/drivers/input/8042/keyboard.c | 459 +++++++++++++++------ src/arch/x86/drivers/input/8042/mouse.c | 175 +++++--- src/arch/x86/drivers/usb/hcd/uhci/uhci.c | 10 +- src/arch/x86/include/drivers/8042.h | 39 +- src/kernel/driver/driver.c | 12 +- src/kernel/main.c | 18 - src/todo.md | 1 - 9 files changed, 767 insertions(+), 353 deletions(-) delete mode 100644 src/todo.md diff --git a/src/arch/x86/drivers/Makefile b/src/arch/x86/drivers/Makefile index d2081a4..24c98e1 100644 --- a/src/arch/x86/drivers/Makefile +++ b/src/arch/x86/drivers/Makefile @@ -12,4 +12,4 @@ SRC += disk/ SRC += interrupt/ SRC += timer/ SRC += framebuffer/ -#SRC += 8042/ \ No newline at end of file +SRC += input/ \ No newline at end of file diff --git a/src/arch/x86/drivers/input/8042/8042.c b/src/arch/x86/drivers/input/8042/8042.c index dd93dc5..93f94c1 100644 --- a/src/arch/x86/drivers/input/8042/8042.c +++ b/src/arch/x86/drivers/input/8042/8042.c @@ -7,171 +7,289 @@ */ #include #include +#include +#include #include +#include #include #include +#include +#include +#include #include -#define DRV_NAME "General PS/2 Driver" -#define DEV_NAME "ps2controller" +extern Driver core_driver; + +bool usb_legacy_support_disabled = true; + +DriverResult i8042_init(void *_device); +DriverResult i8042_start(void *_device); +DriverResult i8042_destroy(void *_device); + +DeviceOps i8042_device_ops = { + .init = i8042_init, + .start = i8042_start, + .stop = NULL, + .destroy = i8042_destroy, +}; + +DeviceDriver i8042_device_driver; +PhysicalDevice *i8042_device; + +void i8042_irq_handler(void *arg) { + do { + i8042_read_data(); + } while (i8042_get_status(I8042_STAT_OUTBUF)); +} int i8042_get_status(uint8_t type) { - int data = io_in8(I8042_PORT_STAT); + int data = io_in_byte(I8042_PORT_STAT); return data & type; } void i8042_wait_ctr_send_ready(void) { for (;;) { - if ((io_in8(I8042_PORT_STAT) & I8042_STAT_INBUF) == + if ((io_in_byte(I8042_PORT_STAT) & I8042_STAT_INBUF) == 0) { // 输入缓存区为空 return; } } } -void i8042_send_cmd(int command) { - io_out8(I8042_PORT_CMD, command); +void i8042_send_cmd(uint8_t command) { + io_out_byte(I8042_PORT_CMD, command); i8042_wait_ctr_send_ready(); } -int i8042_read_data(void) { - return io_in8(I8042_PORT_DATA); +uint8_t i8042_read_data(void) { + return io_in_byte(I8042_PORT_DATA); +} + +void i8042_write_data(uint8_t data) { + io_out_byte(I8042_PORT_DATA, data); } -void i8042_write_data(int data) { - io_out8(I8042_PORT_DATA, data); +void i8042_disable_interrupt(int port) { + I8042Device *i8042 = i8042_device->private_data; + uint8_t cfg; + disable_device_irq(i8042->irq[port]); + i8042_send_cmd(I8042_CMD_READ); + cfg = i8042_read_data(); + if (port == 0) { + cfg &= ~I8042_CFG_INT1; + } else if (port == 1) { + cfg &= ~I8042_CFG_INT2; + } + i8042_send_cmd(I8042_CMD_WRITE); + i8042_write_data(cfg); +} + +void i8042_enable_interrupt(int port) { + I8042Device *i8042 = i8042_device->private_data; + uint8_t cfg; + disable_device_irq(i8042->irq[port]); + i8042_send_cmd(I8042_CMD_READ); + cfg = i8042_read_data(); + if (port == 0) { + cfg |= I8042_CFG_INT1; + } else if (port == 1) { + cfg |= I8042_CFG_INT2; + } + i8042_send_cmd(I8042_CMD_WRITE); + i8042_write_data(cfg); + enable_device_irq(i8042->irq[port]); +} + +void i8042_clear_buffer(void) { + while (i8042_get_status(I8042_STAT_OUTBUF)) { + io_in_byte(I8042_PORT_DATA); + } +} + +DriverResult i8042_init(void *_device) { + if (!usb_legacy_support_disabled) return DRIVER_ERROR_WAITING; + + PhysicalDevice *device = (PhysicalDevice *)_device; + I8042Device *i8042 = device->private_data; + + // 1.禁用设备 + i8042_send_cmd(I8042_CMD_DISABLE_P1); // 禁用第一个PS/2端口 + i8042_send_cmd(I8042_CMD_DISABLE_P2); // 禁用第二个PS/2端口(如果有) + + // 2.配置控制器 + i8042_send_cmd(I8042_CMD_WRITE); + i8042_write_data( + I8042_CFG_TRANS1 | I8042_CFG_SYS_FLAG | I8042_CFG_INT2 | + I8042_CFG_INT1); + + // 3.控制器自检 + i8042_send_cmd(I8042_CMD_TEST_CTL); + if (i8042_read_data() != 0x55) { return DRIVER_ERROR_OTHER; } + + // 4.检测是否为双通道 + i8042_send_cmd(I8042_CMD_ENABLE_P2); + i8042->is_dual_channel = (i8042_read_data() & I8042_CFG_CLK2) == 0; + if (i8042->is_dual_channel) { // 存在第二个通道则禁用第二个通道 + i8042_send_cmd(I8042_CMD_DISABLE_P2); + + i8042_send_cmd(I8042_CMD_READ); + uint8_t tmp = i8042_read_data(); + + i8042_send_cmd(I8042_CMD_WRITE); + i8042_write_data((tmp & ~I8042_CFG_INT2) | I8042_CFG_CLK2); + } + + // 5.接口测试 + i8042_send_cmd(I8042_CMD_TEST_P1); + if (i8042_read_data() != 0x00) { + printk("[i8042]PS/2 Port 1 test failed!\n"); + i8042->is_p1_avail = false; + } else { + i8042->is_p1_avail = true; + register_device_irq( + &i8042->irq[0], i8042_device, NULL, ps2_irqs[0], i8042_irq_handler, + IRQ_MODE_SHARED); + } + if (i8042->is_dual_channel) { + i8042_send_cmd(I8042_CMD_TEST_P2); + if (i8042_read_data() != 0x00) { + printk("[i8042]PS/2 Port 2 test failed!\n"); + i8042->is_p2_avail = false; + } else { + i8042->is_p2_avail = true; + register_device_irq( + &i8042->irq[1], i8042_device, NULL, ps2_irqs[1], + i8042_irq_handler, IRQ_MODE_SHARED); + } + } + + return DRIVER_OK; +} + +DriverResult i8042_start(void *_device) { + PhysicalDevice *physical_device = (PhysicalDevice *)_device; + I8042Device *i8042 = physical_device->private_data; + if (i8042->is_p1_avail) { + // 6.启用端口 + i8042_send_cmd(I8042_CMD_ENABLE_P1); + // 7.重置设备 + i8042_write_data(I8042_CMD_RESET_DEV); + + while (!i8042_get_status(I8042_STAT_OUTBUF)) + ; + if (i8042_read_data() != 0xfa) { + printk("[i8042]PS/2 Port1 Device reset failed!\n"); + i8042->is_p1_avail = false; + goto enable2; + } + while (!i8042_get_status(I8042_STAT_OUTBUF)) + ; + if (i8042_read_data() != 0xaa) { + printk("[i8042]PS/2 Port1 Device self-test failed!\n"); + i8042->is_p1_avail = false; + goto enable2; + } + + if (i8042_get_status(I8042_STAT_OUTBUF)) { + i8042->p1_dev_type = i8042_read_data(); + + if (i8042->p1_dev_type == 0xfc) { + printk("[i8042]PS/2 Port1 Device enable failed!\n"); + i8042->is_p1_avail = false; + goto enable2; + } + } else { // AT键盘没有设备类型的响应 + i8042->p1_dev_type = 0xff; + } + } +enable2: + if (i8042->is_p2_avail) { + // 6.启用端口 + i8042_send_cmd(I8042_CMD_ENABLE_P2); + + // 7.重置设备 + i8042_send_cmd(I8042_CMD_SEND_TO_P2); + i8042_write_data(I8042_CMD_RESET_DEV); + + while (!i8042_get_status(I8042_STAT_OUTBUF)) + ; + if (i8042_read_data() != 0xfa) { + printk("[i8042]PS/2 Port2 Device reset failed!\n"); + i8042->is_p2_avail = false; + goto next; + } + + while (!i8042_get_status(I8042_STAT_OUTBUF)) + ; + if (i8042_read_data() != 0xaa) { + printk("[i8042]PS/2 Port2 Device self-test failed!\n"); + i8042->is_p2_avail = false; + goto next; + } + + if (i8042_get_status(I8042_STAT_OUTBUF)) { + i8042->p2_dev_type = i8042_read_data(); + if (i8042->p2_dev_type != 0xfa) { + printk("[i8042]PS/2 Port2 Device enable failed!\n"); + i8042->is_p2_avail = false; + goto next; + } + } else { // AT键盘没有设备类型的响应 + i8042->p2_dev_type = 0xff; + } + } +next: + + int available[2] = {i8042->is_p1_avail, i8042->is_p2_avail}; + int types[2] = {i8042->p1_dev_type, i8042->p2_dev_type}; + for (int i = 0; i < 2; i++) { + if (!available[i]) { + printk("[i8042]PS/2 Port %d is not available.\n", i + 1); + continue; + } + + printk("[i8042]PS/2 Port %d is available.Type: ", i + 1); + switch (types[i]) { + case 0x00: + printk("Standard PS/2 Mouse"); + ps2_mouse_register(physical_device, i); + break; + case 0x03: + printk("Mouse with scroll wheel"); + break; + case 0xff: { + printk("AT Keyboard"); + ps2_keyboard_register(physical_device, i); + break; + } + default: + printk("Unknown Device (0x%x)", types[i]); + break; + } + printk("\n"); + + i8042_enable_interrupt(i); + enable_device_irq(i8042->irq[i]); + } + + return DRIVER_OK; +} + +DriverResult i8042_destroy(void *_device) { + PhysicalDevice *device = (PhysicalDevice *)_device; + kfree(device->private_data); + return DRIVER_OK; +} + +static __init void i8042_driver_entry(void) { + register_device_driver(&core_driver, &i8042_device_driver); + + ObjectAttr attr = device_object_attr; + create_physical_device(&i8042_device, platform_bus, &attr); + register_physical_device(i8042_device, &i8042_device_ops); + + I8042Device *i8042 = kmalloc(sizeof(I8042Device)); + i8042_device->private_data = i8042; } -// static status_t i8042_enter(driver_t *drv_obj) { -// device_t *devobj; -// device_extension_t *devext; - -// device_create( -// drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_MANAGER, &devobj); -// devext = devobj->device_extension; - -// // 1.禁用设备 -// i8042_send_cmd(I8042_CMD_DISABLE_P1); // 禁用第一个PS/2端口 -// i8042_send_cmd(I8042_CMD_DISABLE_P2); // 禁用第二个PS/2端口(如果有) - -// // 2.配置控制器 -// i8042_send_cmd(I8042_CMD_WRITE); -// i8042_write_data( -// I8042_CFG_TRANS1 | I8042_CFG_SYS_FLAG | I8042_CFG_INT2 | -// I8042_CFG_INT1); - -// // 3.控制器自检 -// i8042_send_cmd(I8042_CMD_TEST_CTL); -// if (i8042_read_data() != 0x55) { -// printk("[i8042]PS/2 Controller Self test failed!\n"); -// device_delete(devobj); -// return FAILED; -// } - -// // 4.检测是否为双通道 -// i8042_send_cmd(I8042_CMD_ENABLE_P2); -// devext->is_dual_channel = (i8042_read_data() & I8042_CFG_CLK2) == 0; -// if (devext->is_dual_channel) { // 存在第二个通道则禁用第二个通道 -// i8042_send_cmd(I8042_CMD_DISABLE_P2); - -// i8042_send_cmd(I8042_CMD_READ); -// uint8_t tmp = i8042_read_data(); - -// i8042_send_cmd(I8042_CMD_WRITE); -// i8042_write_data(tmp & ~I8042_CFG_INT2 | I8042_CFG_CLK2); -// } - -// // 5.接口测试 -// i8042_send_cmd(I8042_CMD_TEST_P1); -// if (i8042_read_data() != 0x00) { -// printk("[i8042]PS/2 Port 1 test failed!\n"); -// devext->is_p1_avail = false; -// } else { -// devext->is_p1_avail = true; -// } -// if (devext->is_dual_channel) { -// i8042_send_cmd(I8042_CMD_TEST_P1); -// if (i8042_read_data() != 0x00) { -// printk("[i8042]PS/2 Port 2 test failed!\n"); -// devext->is_p2_avail = false; -// } else { -// devext->is_p2_avail = true; -// } -// } - -// int i = 0; -// if (devext->is_p1_avail) { -// // 6.启用端口 -// i8042_send_cmd(I8042_CMD_ENABLE_P1); -// // 7.重置设备 -// i8042_write_data(I8042_CMD_RESET_DEV); - -// for (i = 0; i < 2; i++) { -// if (i8042_read_data() == 0xfc) { -// printk("[i8042]PS/2 Port1 Device reset failed!\n"); -// } -// } -// if (i8042_get_status(I8042_STAT_OUTBUF)) { -// devext->p1_dev_type = i8042_read_data(); -// } else { // AT键盘没有设备类型的响应 -// devext->p2_dev_type = 0xff; -// printk("[i8042]Found PS/2 device 1.Type: AT Keyboard\n"); -// } -// } -// if (devext->is_p2_avail) { -// // 6.启用端口 -// i8042_send_cmd(I8042_CMD_ENABLE_P2); - -// i8042_send_cmd(I8042_CMD_READ); -// uint8_t tmp = i8042_read_data(); - -// i8042_send_cmd(I8042_CMD_WRITE); -// i8042_write_data(tmp | I8042_CFG_INT2); -// // 7.重置设备 -// i8042_send_cmd(I8042_CMD_SEND_TO_P2); -// i8042_write_data(I8042_CMD_RESET_DEV); - -// for (i = 0; i < 2; i++) { -// if (i8042_read_data() == 0xfc) { -// printk("[i8042]PS/2 Port1 Device reset failed!\n"); -// } -// } -// if (i8042_get_status(I8042_STAT_OUTBUF)) { -// devext->p2_dev_type = i8042_read_data(); -// if (devext->p2_dev_type == 0x00) { -// printk("[i8042]Found PS/2 device 2.Type: Mouse\n"); -// i8042_send_cmd(I8042_CMD_SEND_TO_P2); -// i8042_write_data(0xf4); -// if (i8042_read_data() != 0xfa) { -// printk("[i8042]PS/2 Port2 Device: mouse enable failed!\n"); -// } -// } else { -// printk( -// "[i8042]Found PS/2 device 2.Type: %#0X\n", -// devext->p2_dev_type); -// } -// } else { // AT键盘没有设备类型的响应 -// devext->p2_dev_type = 0xff; -// printk("[i8042]Found PS/2 device 2.Type: AT Keyboard\n"); -// } -// } -// return SUCCUESS; -// } - -// static status_t i8042_exit(driver_t *drv_obj) { -// device_t *devobj, *next; -// // device_extension_t *ext; -// list_for_each_owner_safe (devobj, next, &drv_obj->device_list, list) { -// device_delete(devobj); -// } -// string_del(&drv_obj->name); -// return SUCCUESS; -// } - -// static __init void i8042_driver_entry(void) { -// if (driver_create(i8042_driver, DRV_NAME) < 0) { -// printk(COLOR_RED "[driver] %s driver create failed!\n", __func__); -// } -// } - -// driver_initcall(i8042_driver_entry); \ No newline at end of file +driver_initcall(i8042_driver_entry); \ No newline at end of file diff --git a/src/arch/x86/drivers/input/8042/keyboard.c b/src/arch/x86/drivers/input/8042/keyboard.c index d395e47..0295526 100644 --- a/src/arch/x86/drivers/input/8042/keyboard.c +++ b/src/arch/x86/drivers/input/8042/keyboard.c @@ -5,6 +5,10 @@ * @version 0.1 * @date 2021-06 */ +#include "driver/input/input_dm.h" +#include "kernel/device.h" +#include "kernel/driver_interface.h" +#include #include #include #include @@ -15,167 +19,364 @@ #include #include #include +#include + +DriverResult ps2_keyboard_start(void *_device); + +DeviceOps ps2_keyboard_device_ops = { + .init = NULL, + .start = ps2_keyboard_start, + .stop = NULL, + .destroy = NULL, +}; + +#define SCANCODE_1_MAX 0xd8 +#define SCANCODE_2_MAX 0x83 // clang-format off -static char scan_codes1[95] = +static uint8_t scancodes1_usage_id[108] = { 0, - 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', - 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', - 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', - 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, + KEY_ESC, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, + KEY_TAB, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_ENTER, + KEY_LEFTCTRL, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, + KEY_LEFTSHIFT, KEY_BACKSLASH, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA, KEY_DOT, KEY_SLASH, KEY_RIGHTSHIFT, + KEY_KEYPAD_ASTERISK, KEY_LEFTALT, KEY_SPACE, KEY_CAPSLOCK, + KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_NUMLOCK, KEY_SCROLLLOCK, + KEY_KEYPAD_7, KEY_KEYPAD_8, KEY_KEYPAD_9, KEY_KEYPAD_MINUS, + KEY_KEYPAD_4, KEY_KEYPAD_5, KEY_KEYPAD_6, KEY_KEYPAD_PLUS, + KEY_KEYPAD_1, KEY_KEYPAD_2, KEY_KEYPAD_3, + KEY_KEYPAD_0, KEY_KEYPAD_DOT, 0, 0, 0, + KEY_F11, KEY_F12, 0, 0, 0, 0 }; -static char scan_codes1_shift[95] = -{ - 0, - 0, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b', - 0, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', - 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '\"', '~', - 0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0, + +// 从0xE0,0x10开始, 使用最高8位区分Page(0: Keyboard/Keypad Page, 1: Consumer Page, 2: General Desktop Page) +static uint16_t scancodes1_ext_usage_id[0x5e] = { + [0x00] = 0x1000 | KEY_CP_PREVIOUS_TRACK,[0x09] = 0x1000 | KEY_CP_NEXT_TRACK, + [0x12] = 0x1000 | KEY_CP_PLAY_PAUSE, [0x14] = 0x1000 | KEY_CP_STOP_EJECT, + + [0x0c] = KEY_KEYPAD_ENTER, [0x25] = KEY_KEYPAD_SLASH, + [0x11] = 0x1000 | KEY_CP_AL_CALC, [0x22] = 0x1000 | KEY_CP_AL_INTERNET_BROWSER, + + [0x10] = KEY_CP_MUTE, [0x1e] = KEY_CP_VOLUME_DECREMENT, [0x20] = KEY_CP_VOLUME_INCREMENT, + + [0x42] = KEY_INSERT, [0x37] = KEY_HOME, [0x39] = KEY_PAGEUP, + [0x43] = KEY_DELETE, [0x3f] = KEY_END, [0x41] = KEY_PAGEDOWN, + + [0x38] = KEY_UP, + [0x3b] = KEY_LEFT, [0x3d] = KEY_RIGHT, [0x40] = KEY_DOWN, + + + [0x0d] = KEY_RIGHTCTRL, [0x28] = KEY_RIGHTALT, + [0x4b] = KEY_LEFTGUI, [0x4c] = KEY_RIGHTGUI, + [0x4d] = KEY_APPLICATION, + [0x4e] = 0x2000 | KEY_GDP_SYSTEM_POWER_DOWN, + [0x4f] = 0x2000 | KEY_GDP_SYSTEM_SLEEP, [0x53] = 0x2000 | KEY_GDP_SYSTEM_WAKEUP, + [0x55] = 0x1000 | KEY_CP_AL_RESEARCH_SEARCH_BROWSER, + [0x56] = 0x1000 | KEY_CP_AC_BOOKMARKS, + [0x57] = 0x1000 | KEY_CP_AC_REFRESH, [0x58] = 0x1000 | KEY_CP_AC_STOP, + [0x59] = 0x1000 | KEY_CP_AC_FORWARD, [0x5a] = 0x1000 | KEY_CP_AC_BACK, + [0x5b] = 0x1000 | KEY_CP_AL_FILE_BROWSER, [0x5c] = 0x1000 | KEY_CP_AL_EMAIL_READER, + [0x5d] = 0x1000 | KEY_CP_AL_CONSUMER_CONTROL_CONFIGURATION, }; -static char scan_codes2[0x5d+1] = +// printscreen insert +static uint8_t scancodes2_usage_id[0x84] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '`', 0, 0, 0, 0, - 0, 0, 'q', '1', 0, 0, 0, 'z', 's', 'a', 'w', '2', 0, 0, 'c', 'x', 'd', 'e', '4', - '3', 0, 0, ' ', 'v', 'f', 't', 'r', '5', 0, 0, 'n', 'b', 'h', 'g', 'y', '6', 0, 0, - 0, 'm', 'j', 'u', '7', '8', 0, 0, ',', 'k', 'i', 'o', '0', '9', 0, 0, '.', '/', 'l', - ';', 'p', '-', 0, 0, 0, '\'', 0, '[', '=', 0, 0, 0, 0, 0, ']', 0, '\\' + 0, KEY_F9, 0, + KEY_F5, KEY_F3, KEY_F1, KEY_F2, KEY_F12, 0, + KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_GRAVE, 0, 0, + KEY_LEFTALT, KEY_LEFTSHIFT, 0, + KEY_LEFTCTRL, KEY_Q, KEY_1, 0, 0, 0, + KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, 0, 0, + KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, 0, 0, + KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, 0, 0, + KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, 0, 0, 0, + KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, 0, 0, + KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, 0, 0, + KEY_DOT, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, 0, 0, 0, + + KEY_APOSTROPHE, 0, + KEY_LEFTBRACE, KEY_EQUAL, 0, 0, + KEY_CAPSLOCK, KEY_RIGHTSHIFT, KEY_ENTER, KEY_RIGHTBRACE, 0, + KEY_BACKSLASH, 0, 0, 0, 0, 0, 0, 0, 0, + KEY_BACKSPACE, 0, 0, + KEY_KEYPAD_1, 0, + KEY_KEYPAD_4, KEY_KEYPAD_7, 0, 0, 0, + KEY_KEYPAD_0, KEY_KEYPAD_DOT, + KEY_KEYPAD_2, KEY_KEYPAD_5, KEY_KEYPAD_6, KEY_KEYPAD_8, + KEY_ESC, KEY_NUMLOCK, KEY_F11, KEY_KEYPAD_PLUS, + KEY_KEYPAD_3, KEY_KEYPAD_MINUS, KEY_KEYPAD_ASTERISK, KEY_KEYPAD_9, KEY_SCROLLLOCK, 0,0,0,0, + KEY_F7, }; -static char scan_codes2_shift[0x5d+1] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '~', 0, 0, 0, 0, - 0, 0, 'Q', '!', 0, 0, 0, 'Z', 'S', 'A', 'W', '@', 0, 0, 'C', 'X', 'D', 'E', '$', - '$', 0, 0, 0, 'V', 'F', 'T', 'R', '%', 0, 0, 'N', 'B', 'H', 'G', 'Y', '^', 0, 0, - 0, 'M', 'J', 'U', '&', '*', 0, 0, '<', 'K', 'I', 'O', 'P', '(', 0, 0, '>', '?', 'L', - ':', 'P', '_', 0, 0, 0, '\"', 0, '{', '+', 0, 0, 0, 0, 0, '}', 0, '|' + +static uint16_t scancodes2_ext_usage_id[0x6e] = { + [0x05] = 0x1000 | KEY_CP_PREVIOUS_TRACK, [0x3d] = 0x1000 | KEY_CP_NEXT_TRACK, + + [0x2a] = 0x1000 | KEY_CP_AC_HOME, + [0x08] = 0x1000 | KEY_CP_AC_BOOKMARKS, + [0x10] = 0x1000 | KEY_CP_AC_REFRESH, + [0x28] = 0x1000 | KEY_CP_AC_BACK, [0x20] = 0x1000 | KEY_CP_AC_FORWARD, + + [0x0f] = KEY_LEFTGUI, [0x17] = KEY_RIGHTGUI, + [0x01] = KEY_RIGHTALT, [0x04] = KEY_RIGHTCTRL, + [0x4a] = KEY_ENTER, [0x3a] = KEY_KEYPAD_SLASH, + + [0x11] = 0x1000 | KEY_CP_VOLUME_DECREMENT, + [0x13] = 0x1000 | KEY_CP_MUTE, + + [0x22] = 0x1000 | KEY_CP_VOLUME_INCREMENT, + [0x24] = 0x1000 | KEY_CP_PLAY_PAUSE, + [0x2b] = 0x1000 | KEY_CP_STOP, + + [0x00] = 0x1000 | KEY_CP_AL_RESEARCH_SEARCH_BROWSER, + [0x30] = 0x1000 | KEY_CP_AL_FILE_BROWSER, [0x38] = 0x1000 | KEY_CP_AL_EMAIL_READER, + [0x40] = 0x1000 | KEY_CP_AL_CONSUMER_CONTROL_CONFIGURATION, + + [0x27] = 0x2000 | KEY_GDP_SYSTEM_POWER_DOWN, + [0x2f] = 0x2000 | KEY_GDP_SYSTEM_SLEEP, [0x4e] = 0x2000 | KEY_GDP_SYSTEM_WAKEUP, + + + [0x60] = KEY_INSERT, [0x5c] = KEY_HOME, [0x6d] = KEY_PAGEUP, + [0x61] = KEY_DELETE, [0x59] = KEY_END, [0x6a] = KEY_PAGEDOWN, + [0x65] = KEY_UP, + [0x5b] = KEY_LEFT, [0x62] = KEY_DOWN, [0x64] = KEY_RIGHT, + }; // clang-format on -#define KEYBOARD_IRQ 1 +#define KEYBOARD_CAPSLOCK 0x04 +#define KEYBOARD_NUMLOCK 0x02 +#define KEYBOARD_SCROLLLOCK 0x01 +typedef struct { + int port; + uint8_t scancode_num; -#define DRV_NAME "General PS/2 Driver(Keyboard)" -#define DEV_NAME "PS/2 Keyboard" + uint8_t *scancode; + uint8_t scancode_max; + uint16_t *scancode_ext; -typedef struct { - int num_lock, caps_lock, scroll_lock; // 键盘锁 - int left_ctrl, right_ctrl; - int left_shift, right_shift; - int left_alt, right_alt; - int keybuf[512]; - struct fifo keyfifo; -} device_extension_t; - -void keyboard_handler(device_t *devobj, int irq); -static status_t keyboard_enter(driver_t *drv_obj); -static status_t keyboard_exit(driver_t *drv_obj); -char scancode_analysis(device_extension_t *devext, int keycode); -void keyboard_setleds(device_extension_t *devext); - -driver_func_t keyboard_driver = {.driver_enter = keyboard_enter, - .driver_exit = keyboard_exit, - .driver_open = NULL, - .driver_close = NULL, - .driver_read = NULL, - .driver_write = NULL, - .driver_devctl = NULL}; - -static status_t keyboard_enter(driver_t *drv_obj) { - device_t *devobj; - device_extension_t *devext; - - device_create(drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_KEYBOARD, &devobj); - devext = devobj->device_extension; - - fifo_init(&devext->keyfifo, 512, devext->keybuf); - - devext->left_ctrl = 0; - devext->left_shift = 0; - devext->left_alt = 0; - devext->right_ctrl = 0; - devext->right_shift = 0; - devext->right_alt = 0; - - devext->num_lock = 1; - devext->caps_lock = 0; - devext->scroll_lock = 0; - - keyboard_setleds(devext); - - device_register_irq(devobj, KEYBOARD_IRQ, keyboard_handler); - return SUCCUESS; -} + uint8_t extended_mode; // 0: none, 1: 0xe0, 2: 0xe1 + uint8_t release; // scancode 2专用,0: none, 1: 0xf0 + + uint8_t locks; +} Ps2Keyboard; -static status_t keyboard_exit(driver_t *drv_obj) { - device_t *devobj, *next; - // device_extension_t *ext; - list_for_each_owner_safe (devobj, next, &drv_obj->device_list, list) {} - string_del(&drv_obj->name); - return SUCCUESS; +void scancode_handle(Ps2Keyboard *kbd, uint8_t keycode); +void keyboard_setleds(Ps2Keyboard *kbd); + +void keyboard_irq_handler(void *arg) { + Ps2Keyboard *kbd = (Ps2Keyboard *)arg; + uint16_t data; + data = i8042_read_data(); + scancode_handle(kbd, data); } -void keyboard_handler(device_t *devobj, int irq) { - device_extension_t *devext = (device_extension_t *)devobj->device_extension; - uint8_t data = i8042_read_data(); - fifo_put(&devext->keyfifo, data); +uint16_t scancode_handle_ext_1(Ps2Keyboard *kbd, uint8_t keycode) { + uint16_t data = kbd->scancode_ext[(keycode & 0x7f) - 0x10]; + if (kbd->scancode_num == 1) { + // print screen pressed: 0xE0 0x2A 0xE0 0x37 + // print screen released: 0xE0 0xB7 0xE0 0xAA + + // 0xE0字节会被scancode_handle设备为扩展码自动跳过,通过第二个字节判断是pressed还是released, + // 第四个字节判断是否为print screen + if (keycode == 0x2a) { + kbd->release = false; + return 0; + } else if (keycode == 0xb7) { + kbd->release = true; + return 0; + } + if (keycode == 0x37 || keycode == 0xaa) { return KEY_PRINTSCREEN; } + } else if (kbd->scancode_num == 2) { + // print screen pressed: 0xE0 0x12 0xE0 0x7C + // print screen released: 0xE0 0xF0 0x7C 0xE0 0xF0 0x12 + + // 由于需要判断结束字节,需要结合release状态(是否遇到过0xF0)判断 + if (kbd->release == false && keycode == 0x7C) { + return KEY_PRINTSCREEN; + } + if (kbd->release == true && keycode == 0x12) { return KEY_PRINTSCREEN; } + } + return data; } -char scancode_analysis(device_extension_t *devext, int keycode) { - char data = '\0'; - if (keycode <= 0x35 && keycode != 0x2a && keycode != 0x1d) { - if (devext->left_shift == 0 && devext->right_shift == 0) { - data = scan_codes1[keycode]; - } else { - data = scan_codes1_shift[keycode]; +uint16_t scancode_handle_ext_2(Ps2Keyboard *kbd, uint8_t keycode) { + // pause只有pressed + if (kbd->scancode_num == 1) { + // pause pressed: 0xe1 0x1d 0x45 0xe1 0x9d 0xc5 + // scancode 1 + // 0xe1开头的扩展按键只有pause,最后一个字节没有冲突直接通过最后一个字节判断 + if (keycode == 0xc5) { + kbd->release = false; + return KEY_PAUSE; + } + } else if (kbd->scancode_num == 2) { + // pause pressed: 0xe1 0x14 0x77 0xe1 0xf0 0x14 0xf0 0x77 + + // 0xf0字节会被scancode_handle设备为释放码,所以需要通过最后一个字节判断 + // 又由于序列中包含两个0x77,而前一个0x77前面没有0xf0,所以要结合release状态(是否遇到过0xf0)判断 + if (keycode == 0x77 && kbd->release == true) { + kbd->release = false; + return KEY_PAUSE; } } - if (keycode == 0x39) { - data = ' '; - } else if (keycode == 0x1d) { - devext->left_ctrl = 1 - devext->left_ctrl; - } else if (keycode == 0x2a) { - devext->left_shift = 1 - devext->left_shift; - } else if (keycode == 0x36) { - devext->right_shift = 1 - devext->right_shift; - } else if (keycode == 0x38) { - devext->left_alt = 1 - devext->left_alt; - } else if (keycode == 0x3a) { - devext->caps_lock = 1 - devext->caps_lock; - keyboard_setleds(devext); - } else if (keycode == 0x45) { - devext->num_lock = 1 - devext->num_lock; - keyboard_setleds(devext); - } else if (keycode == 0x46) { - devext->scroll_lock = 1 - devext->scroll_lock; - keyboard_setleds(devext); + return 0; +} + +void scancode_handle(Ps2Keyboard *kbd, uint8_t keycode) { + bool press = true; + uint16_t data = kbd->scancode[keycode]; + if (keycode == 0xe0) { + kbd->extended_mode = 1; + return; + } else if (keycode == 0xe1) { + kbd->extended_mode = 2; + return; + } else if (kbd->scancode_num == 2 && keycode == 0xf0) { + kbd->release = 1; + return; + } else if (keycode > kbd->scancode_max) { + return; + } else { + if (kbd->scancode_num == 1 && data & 0x80) press = false; } - if (data == 0) { /* code */ + if (kbd->extended_mode == 1) { + data = scancode_handle_ext_1(kbd, keycode); + if (data == 0) return; // 还没处理完 + } else if (kbd->extended_mode == 2) { + data = scancode_handle_ext_2(kbd, keycode); + if (data == 0) return; // 还没处理完 } - return data; -} -void keyboard_setleds(device_extension_t *devext) { - uint8_t kb_read; + press = (kbd->release == 1) ? false : press; + uint8_t old_locks = kbd->locks; + if (data == KEY_CAPSLOCK) { kbd->locks ^= KEYBOARD_CAPSLOCK; } + if (data == KEY_NUMLOCK) { kbd->locks ^= KEYBOARD_NUMLOCK; } + if (data == KEY_SCROLLLOCK) { kbd->locks ^= KEYBOARD_SCROLLLOCK; } + if (old_locks != kbd->locks) { keyboard_setleds(kbd); } + if (data != 0) { + uint8_t tmp = data >> 12; + if (tmp == 0) { + new_key_event( + INPUT_KEY_EVENT_KEYBOARD_BASE + data & 0xfff, press, + INPUT_KEY_PAGE_KEYBOARD_KEYPAD); + } else if (tmp == 1) { + new_key_event(data & 0xfff, press, INPUT_KEY_PAGE_CONSUMER); + } else if (tmp == 2) { + new_key_event(data & 0xfff, press, INPUT_KEY_PAGE_GENERAL_DESKTOP); + } + } + if (kbd->extended_mode) kbd->extended_mode = 0; + if (kbd->release) kbd->release = 0; +} +void keyboard_setleds(Ps2Keyboard *kbd) { + i8042_wait_ctr_send_ready(); + i8042_write_data(I8042_KBD_CMD_SET_LEDS); + i8042_wait_ctr_send_ready(); + io_in_byte(I8042_PORT_DATA); i8042_wait_ctr_send_ready(); - i8042_write_data(0xed); - do { - kb_read = (uint8_t)io_in8(I8042_PORT_DATA); - } while ((kb_read != 0xfa)); + i8042_write_data(kbd->locks & 0x07); i8042_wait_ctr_send_ready(); - i8042_write_data(devext->caps_lock << 2 | devext->num_lock << 1 | devext->scroll_lock); - do { - kb_read = (uint8_t)io_in8(I8042_PORT_DATA); - } while ((kb_read != 0xfa)); + io_in_byte(I8042_PORT_DATA); } -static __init void keyboard_driver_entry(void) { - if (driver_create(keyboard_driver, DRV_NAME) < 0) { - printk(COLOR_RED "[driver] %s driver create failed!\n", __func__); +DriverResult ps2_keyboard_start(void *_device) { + LogicalDevice *device = _device; + Ps2Keyboard *kbd = device->private_data; + + i8042_disable_interrupt(kbd->port); + // 获取scancode集 + i8042_wait_ctr_send_ready(); + i8042_write_data(I8042_KBD_CMD_GET_SET_SCANCODE_SET); + i8042_wait_ctr_send_ready(); + if (i8042_read_data() != 0xfa) { + printk( + "[i8042]PS/2 Port%d Device get scancode set failed!\n", + kbd->port + 1); + return DRIVER_ERROR_OTHER; } + i8042_wait_ctr_send_ready(); + i8042_write_data(0); + i8042_wait_ctr_send_ready(); + if (i8042_read_data() != 0xfa) { + printk( + "[i8042]PS/2 Port%d Device get scancode set failed!\n", + kbd->port + 1); + return DRIVER_ERROR_OTHER; + } + int num = i8042_read_data(); + if (num == 0x43) { + kbd->scancode = scancodes1_usage_id; + kbd->scancode_max = SCANCODE_1_MAX; + kbd->scancode_ext = scancodes1_ext_usage_id; + kbd->scancode_num = 1; + } else if (num == 0x41) { + kbd->scancode = scancodes2_usage_id; + kbd->scancode_max = SCANCODE_2_MAX; + kbd->scancode_ext = scancodes2_ext_usage_id; + kbd->scancode_num = 2; + } else { + i8042_wait_ctr_send_ready(); + i8042_write_data(I8042_KBD_CMD_GET_SET_SCANCODE_SET); + i8042_wait_ctr_send_ready(); + if (i8042_read_data() != 0xfa) { + printk( + "[i8042]PS/2 Port%d Device set scancode set failed!\n", + kbd->port + 1); + return DRIVER_ERROR_OTHER; + } + i8042_wait_ctr_send_ready(); + i8042_write_data(1); + i8042_wait_ctr_send_ready(); + if (i8042_read_data() != 0xfa) { + printk( + "[i8042]PS/2 Port%d Device set scancode set failed!\n", + kbd->port + 1); + return DRIVER_ERROR_OTHER; + } + kbd->scancode = scancodes1_usage_id; + kbd->scancode_max = SCANCODE_1_MAX; + kbd->scancode_ext = scancodes1_ext_usage_id; + kbd->scancode_num = 1; + } + kbd->release = 0; + kbd->extended_mode = 0; + // 关闭编码转换 + i8042_wait_ctr_send_ready(); + i8042_send_cmd(I8042_CMD_READ); + i8042_wait_ctr_send_ready(); + uint8_t cfg = i8042_read_data(); + cfg &= ~I8042_CFG_TRANS1; + i8042_send_cmd(I8042_CMD_WRITE); + i8042_wait_ctr_send_ready(); + i8042_write_data(cfg); + + I8042Device *i8042 = i8042_device->private_data; + // 手动修改irq的处理函数和参数 + i8042->irq[kbd->port]->handler = keyboard_irq_handler; + i8042->irq[kbd->port]->arg = kbd; + + i8042_wait_ctr_send_ready(); + i8042_write_data(I8042_KBD_CMD_ENABLE_SCANNING); + i8042_read_data(); + + i8042_enable_interrupt(kbd->port); + + return DRIVER_OK; } -driver_initcall(keyboard_driver_entry); \ No newline at end of file +void ps2_keyboard_register(PhysicalDevice *physical_device, int port) { + InputDevice *in; + create_input_device( + &in, INPUT_TYPE_KEYBOARD, &ps2_keyboard_device_ops, physical_device, + &i8042_device_driver); + Ps2Keyboard *kbd = kmalloc(sizeof(Ps2Keyboard)); + kbd->port = port; + in->device->private_data = kbd; + kbd->locks = 0; +} \ No newline at end of file diff --git a/src/arch/x86/drivers/input/8042/mouse.c b/src/arch/x86/drivers/input/8042/mouse.c index 9b6d231..54d869a 100644 --- a/src/arch/x86/drivers/input/8042/mouse.c +++ b/src/arch/x86/drivers/input/8042/mouse.c @@ -5,6 +5,9 @@ * @version 0.1 * @date 2021-06 */ +#include "driver/input/key_events.h" +#include "kernel/device.h" +#include #include #include #include @@ -13,72 +16,138 @@ #include #include #include -#include +#include -struct fifo mouse_fifo; - -static status_t mouse_enter(driver_t *drv_obj); -static status_t mouse_exit(driver_t *drv_obj); +#define MOUSE_Y_OVERFLOW 0x80 +#define MOUSE_X_OVERFLOW 0x40 +#define MOUSE_Y_SIGN 0x20 +#define MOUSE_X_SIGN 0x10 +#define MOUSE_MIDDLE_BTN 0x04 +#define MOUSE_RIGHT_BTN 0x02 +#define MOUSE_LEFT_BTN 0x01 -#define MOUSE_IRQ 12 - -driver_func_t mouse_driver = { - .driver_enter = mouse_enter, - .driver_exit = mouse_exit, - .driver_open = NULL, - .driver_close = NULL, - .driver_read = NULL, - .driver_write = NULL, - .driver_devctl = NULL, -}; +struct fifo mouse_fifo; -#define DRV_NAME "General PS/2 Driver(Mouse)" -#define DEV_NAME "mouse" +DriverResult ps2_mouse_start(void *_device); typedef struct { - int x, y; - int old_x, old_y; - int lbtn, mbtn, rbtn; // 左键 中键 右键 -} device_extension_t; - -void mouse_handler(device_t *devobj, int irq) { - device_extension_t *devext = (device_extension_t *)devobj->device_extension; - uint8_t data = i8042_read_data(); -} + int port; -static status_t mouse_enter(driver_t *drv_obj) { - device_t *devobj; - device_extension_t *devext; + int state; - device_create(drv_obj, sizeof(device_extension_t), DEV_NAME, DEV_MOUSE, &devobj); - devext = devobj->device_extension; + int byte0, x, y; - devext->x = 0; - devext->y = 0; - devext->old_x = 0; - devext->old_y = 0; - devext->lbtn = 0; - devext->mbtn = 0; - devext->rbtn = 0; + // 记录左中右键状态来决定是否发送事件 + int btn; +} Ps2Mouse; - device_register_irq(devobj, MOUSE_IRQ, mouse_handler); - return SUCCUESS; -} +DeviceOps ps2_mouse_device_ops = { + .init = NULL, + .start = ps2_mouse_start, + .stop = NULL, + .destroy = NULL, +}; -static status_t mouse_exit(driver_t *drv_obj) { - device_t *devobj, *next; - // device_extension_t *ext; - list_for_each_owner_safe (devobj, next, &drv_obj->device_list, list) { - device_delete(devobj); +void mouse_handler(void *arg) { + Ps2Mouse *mouse = (Ps2Mouse *)arg; + uint8_t data = i8042_read_data(); + switch (mouse->state) { + case 0: + if ((data & 0x08) != 0x08) { return; } + mouse->byte0 = data; + mouse->state = 1; + break; + case 1: + mouse->x = data; + mouse->state = 2; + break; + case 2: + mouse->y = data; + mouse->state = 0; + break; + default: + mouse->state = 0; + return; + } + if (mouse->state == 1) { // 原先是0 + bool old_left = !!(mouse->btn & MOUSE_LEFT_BTN); + bool old_mid = !!(mouse->btn & MOUSE_MIDDLE_BTN); + bool old_right = !!(mouse->btn & MOUSE_RIGHT_BTN); + bool left = !!(data & MOUSE_LEFT_BTN); + bool mid = !!(data & MOUSE_MIDDLE_BTN); + bool right = !!(data & MOUSE_RIGHT_BTN); + if (mouse->btn != + (data & (MOUSE_LEFT_BTN | MOUSE_MIDDLE_BTN | MOUSE_RIGHT_BTN))) { + // 按键状态变化 + if (left ^ old_left) { + // 左键状态变化 + new_key_event( + INPUT_KEY_EVENT_MOUSE_BASE + KEY_MOUSE_LEFT, left, + INPUT_KEY_PAGE_KEYBOARD_KEYPAD); + } + if (mid ^ old_mid) { + // 中键状态变化 + new_key_event( + INPUT_KEY_EVENT_MOUSE_BASE + KEY_MOUSE_MIDDLE, mid, + INPUT_KEY_PAGE_KEYBOARD_KEYPAD); + } + if (right ^ old_right) { + // 右键状态变化 + new_key_event( + INPUT_KEY_EVENT_MOUSE_BASE + KEY_MOUSE_RIGHT, right, + INPUT_KEY_PAGE_KEYBOARD_KEYPAD); + } + mouse->btn = + data & (MOUSE_LEFT_BTN | MOUSE_MIDDLE_BTN | MOUSE_RIGHT_BTN); + } + } + if (mouse->state == 0) { + if (mouse->x != 0 || mouse->y != 0) { + int16_t dx = (mouse->byte0 & MOUSE_X_SIGN) + ? (0xff00 | (uint16_t)mouse->x) + : (uint16_t)mouse->x; + int16_t dy = (mouse->byte0 & MOUSE_Y_SIGN) + ? (0xff00 | (uint16_t)mouse->y) + : (uint16_t)mouse->y; + new_pointer_event(dx, -dy, POINTER_TYPE_MOVE); + } + mouse->byte0 = mouse->x = mouse->y = 0; } - string_del(&drv_obj->name); - return SUCCUESS; } -static __init void mouse_driver_entry(void) { - if (driver_create(mouse_driver, DRV_NAME) < 0) { - printk(COLOR_RED "[driver] %s driver create failed!\n", __func__); +DriverResult ps2_mouse_start(void *_device) { + LogicalDevice *logical_device = (LogicalDevice *)_device; + Ps2Mouse *mouse = (Ps2Mouse *)logical_device->private_data; + + i8042_disable_interrupt(mouse->port); + + i8042_wait_ctr_send_ready(); + i8042_send_cmd(I8042_CMD_SEND_TO_P2); + i8042_wait_ctr_send_ready(); + i8042_write_data(I8042_KBD_CMD_ENABLE_SCANNING); + i8042_wait_ctr_send_ready(); + if (i8042_read_data() != 0xfa) { + printk("[i8042]PS/2 Port2 Device enable failed!\n"); + return DRIVER_ERROR_OTHER; } + + // 手动修改irq的处理函数和参数 + I8042Device *i8042 = i8042_device->private_data; + i8042->irq[mouse->port]->handler = mouse_handler; + i8042->irq[mouse->port]->arg = mouse; + + mouse->state = 0; + i8042_enable_interrupt(mouse->port); + + return DRIVER_OK; } -driver_initcall(mouse_driver_entry); \ No newline at end of file +void ps2_mouse_register(PhysicalDevice *physical_device, int port) { + InputDevice *in; + create_input_device( + &in, INPUT_TYPE_MOUSE, &ps2_mouse_device_ops, physical_device, + &i8042_device_driver); + Ps2Mouse *mouse = kmalloc(sizeof(Ps2Mouse)); + mouse->port = port; + in->device->private_data = mouse; +} \ No newline at end of file diff --git a/src/arch/x86/drivers/usb/hcd/uhci/uhci.c b/src/arch/x86/drivers/usb/hcd/uhci/uhci.c index 0d5e677..daf9c74 100644 --- a/src/arch/x86/drivers/usb/hcd/uhci/uhci.c +++ b/src/arch/x86/drivers/usb/hcd/uhci/uhci.c @@ -39,6 +39,8 @@ #include #include +extern bool usb_legacy_support_disabled; + #define UHCI_CLASSID 0x0c #define UHCI_SUBCLASSID 0x03 #define UHCI_PROGIF 0x00 @@ -334,8 +336,8 @@ void uhci_probe_thread(void *arg) { desc->bDescriptorType = USB_DESC_TYPE_HUB; desc->bNbrPorts = uhci->port_cnt; desc->wHubCharacteristics = HOST2LE_WORD(0x0009); // 无电源开关,单独供电 - desc->bPwrOn2PwrGood = 0; - desc->bHubContrCurrent = 0; + desc->bPwrOn2PwrGood = 0; + desc->bHubContrCurrent = 0; memset(&desc->DeviceRemovable, 0xff, 8); // 都是可移除的 memset(&desc->PortPwrCtrlMask, 0xff, 8); // 都是电源控制的 @@ -360,6 +362,8 @@ DriverResult uhci_start(void *_device) { pci_device_write16(uhci->device, UHCI_PCI_REG_LEGSUP, 0x2000); pci_enable_bus_mastering(uhci->device); + usb_legacy_support_disabled = true; + io_out_word(uhci->io_base + UHCI_FRNUM, 0); io_out_dword(uhci->io_base + UHCI_FRBASEADD, (uint32_t)uhci->fl.frames_phy); @@ -408,6 +412,8 @@ DriverResult uhci_pci_probe( return result; } + usb_legacy_support_disabled = false; // 发现USB控制器,让8042驱动等待 + LogicalDevice *logical_device = uhci->hcd->device; logical_device->private_data = uhci; physical_device->private_data = uhci; diff --git a/src/arch/x86/include/drivers/8042.h b/src/arch/x86/include/drivers/8042.h index 6ecd6a0..fae8522 100644 --- a/src/arch/x86/include/drivers/8042.h +++ b/src/arch/x86/include/drivers/8042.h @@ -1,6 +1,8 @@ #ifndef _8042_H #define _8042_H +#include +#include #include #define I8042_PORT_DATA 0x60 @@ -22,6 +24,12 @@ #define I8042_CMD_SEND_TO_P2 0xd4 #define I8042_CMD_RESET_DEV 0xff +#define I8042_KBD_CMD_SET_LEDS 0xed +#define I8042_KBD_CMD_GET_SET_SCANCODE_SET 0xf0 +#define I8042_KBD_CMD_IDENTIFY 0xf2 +#define I8042_KBD_CMD_ENABLE_SCANNING 0xf4 +#define I8042_KBD_CMD_DISABLE_SCANNING 0xf5 + // 配置 #define I8042_CFG_INT1 0x01 #define I8042_CFG_INT2 0x02 @@ -38,10 +46,31 @@ #define I8042_STAT_TIMEOUT_ERR 0x40 #define I8042_STAT_PARITY_ERR 0x80 -int i8042_get_status(uint8_t type); // 获取控制器状态 -void i8042_wait_ctr_send_ready(void); // 等待输入缓存区为空 -void i8042_send_cmd(int command); // 发送控制字节 -int i8042_read_data(void); // 读取数据 -void i8042_write_data(int data); // 写数据 +typedef struct { + uint8_t is_dual_channel; + uint8_t is_p1_avail; + uint8_t is_p2_avail; + uint8_t p1_dev_type; + uint8_t p2_dev_type; + + DeviceIrq *irq[2]; +} I8042Device; + +extern DeviceDriver i8042_device_driver; +extern PhysicalDevice *i8042_device; + +static const int ps2_irqs[2] = {1, 12}; + +int i8042_get_status(uint8_t type); // 获取控制器状态 +void i8042_wait_ctr_send_ready(void); // 等待输入缓存区为空 +void i8042_send_cmd(uint8_t command); // 发送控制字节 +uint8_t i8042_read_data(void); // 读取数据 +void i8042_write_data(uint8_t data); // 写数据 +void i8042_disable_interrupt(int port); +void i8042_enable_interrupt(int port); +void i8042_clear_buffer(void); // 清空缓冲区 + +void ps2_keyboard_register(PhysicalDevice *physical_device, int port); +void ps2_mouse_register(PhysicalDevice *physical_device, int port); #endif \ No newline at end of file diff --git a/src/kernel/driver/driver.c b/src/kernel/driver/driver.c index 192ce42..f6374ee 100644 --- a/src/kernel/driver/driver.c +++ b/src/kernel/driver/driver.c @@ -149,7 +149,17 @@ void start_devices(void *arg) { spin_unlock(&device_list_lock); continue; } - if (phy->state == DEVICE_STATE_UNINIT) init_physical_device(phy); + if (phy->state == DEVICE_STATE_UNINIT) { + DriverResult result = init_physical_device(phy); + if (result == DRIVER_ERROR_WAITING) { + // 设备初始化需要等待,跳过 + spin_lock(&device_list_lock); + list_del(&phy->new_device_list); + list_add_tail(&phy->new_device_list, &new_device_lh); + spin_unlock(&device_list_lock); + continue; + } + } if (phy->state == DEVICE_STATE_READY) start_physical_device(phy); list_for_each_owner ( logi, &phy->logical_device_lh, logical_device_list) { diff --git a/src/kernel/main.c b/src/kernel/main.c index e5371bf..a777f68 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -169,24 +169,6 @@ int main() { // thread_start("play", 100, thread_play, NULL, NULL); - // const string_t name = STRING_INIT("A folder"); - // obj_rmdir(object, name); - - // void *handle = NULL; - // Object *object; - // ObjectResult result = - // open_object_by_ascii_path("\\Device\\Storage0\\Partition0", - // &object); - // if (result != OBJECT_OK) { - // } - - // bool is_done; - // do { - // TRANSFER_IN_IS_DONE(object)(object, &handle, &is_done); - // } while (!is_done); - - // show_object_tree(); - console_start(); thread_exit(); diff --git a/src/todo.md b/src/todo.md deleted file mode 100644 index 65072c3..0000000 --- a/src/todo.md +++ /dev/null @@ -1 +0,0 @@ - - [ ] 驱动生命周期新增AfterInitialized,在所有驱动初始化完成后运行 \ No newline at end of file From 428bfea5fb56c010bd6a938c0afd6afcca6bed7a Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Fri, 10 Oct 2025 01:32:48 +0800 Subject: [PATCH 154/158] =?UTF-8?q?framebuffer:=20=E5=8E=BB=E6=8E=89consol?= =?UTF-8?q?e=5Fbackend=E8=B6=85=E5=87=BA=E6=9C=80=E5=A4=A7=E8=A1=8C?= =?UTF-8?q?=E6=95=B0=E6=97=B6=E8=A7=A3=E9=94=81=E5=86=8D=E5=8A=A0=E9=94=81?= =?UTF-8?q?=E7=9A=84=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driver/framebuffer/console_backend.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/driver/framebuffer/console_backend.c b/src/driver/framebuffer/console_backend.c index cd99832..46868b3 100644 --- a/src/driver/framebuffer/console_backend.c +++ b/src/driver/framebuffer/console_backend.c @@ -266,9 +266,7 @@ void fb_console_backend_put_string( backend->x = 0; if (backend->y >= backend->height) { // 超过最大行数,滚屏 - spin_unlock(&backend->lock); fb_console_backend_scroll(backend, 1); - spin_lock(&backend->lock); } } } From cd6dbe6d95c226ce38ff68949f8a0721d207348c Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Mon, 13 Oct 2025 01:03:26 +0800 Subject: [PATCH 155/158] =?UTF-8?q?script:=20=E9=87=8D=E5=86=99=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + CMakeLists.txt | 35 -- Makefile | 10 +- config.toml | 26 ++ include/ctype.h | 48 +-- src/CMakeLists.txt | 55 --- src/arch/x86/bios_emu/config.toml | 2 + src/arch/x86/bios_emu/ops/config.toml | 12 + src/arch/x86/boot/config.toml | 1 + src/arch/x86/config.toml | 1 + src/arch/x86/drivers/bus/config.toml | 1 + src/arch/x86/drivers/bus/isa/config.toml | 1 + src/arch/x86/drivers/bus/pci/config.toml | 1 + src/arch/x86/drivers/config.toml | 12 + src/arch/x86/drivers/disk/ata/ata.c | 0 src/arch/x86/drivers/disk/ata/config.toml | 1 + src/arch/x86/drivers/disk/config.toml | 1 + src/arch/x86/drivers/framebuffer/config.toml | 1 + src/arch/x86/drivers/input/8042/config.toml | 1 + src/arch/x86/drivers/input/config.toml | 1 + src/arch/x86/drivers/interrupt/config.toml | 1 + src/arch/x86/drivers/network/config.toml | 1 + .../x86/drivers/network/rtl8139/config.toml | 1 + src/arch/x86/drivers/sound/config.toml | 1 + src/arch/x86/drivers/sound/sb16/config.toml | 1 + src/arch/x86/drivers/timer/config.toml | 1 + src/arch/x86/drivers/usb/config.toml | 1 + src/arch/x86/drivers/usb/hcd/config.toml | 2 + src/arch/x86/drivers/usb/hcd/uhci/config.toml | 1 + src/arch/x86/kernel.lds | 4 + src/arch/x86/kernel/config.toml | 2 + src/arch/x86/multiboot2/config.toml | 2 + src/config.toml | 15 + src/driver/config.toml | 11 + src/driver/framebuffer/config.toml | 1 + src/driver/input/config.toml | 1 + src/driver/interrupt/config.toml | 1 + src/driver/network/config.toml | 2 + src/driver/network/ethernet/config.toml | 1 + src/driver/network/protocols/config.toml | 2 + src/driver/network/protocols/ipv4/config.toml | 1 + src/driver/serial/config.toml | 1 + src/driver/sound/config.toml | 1 + src/driver/storage/config.toml | 2 + src/driver/storage/disk/config.toml | 1 + src/driver/timer/config.toml | 1 + src/drivers/bus/Makefile | 3 +- src/drivers/bus/config.toml | 1 + src/drivers/bus/usb/Makefile | 2 + src/drivers/bus/usb/config.toml | 1 + src/drivers/bus/{ => usb}/hcd.c | 0 src/drivers/bus/{ => usb}/usb.c | 0 src/drivers/config.toml | 1 + src/drivers/usb/config.toml | 1 + src/drivers/usb/core/config.toml | 1 + src/drivers/usb/hid/config.toml | 1 + src/fs/config.toml | 2 + src/fs/fat/config.toml | 1 + src/include/ctype.h | 38 +- src/include/driver/framebuffer/fb.h | 5 - src/include/stdarg.h | 14 +- src/kernel/config.toml | 28 ++ src/kernel/elf.c | 64 +-- src/lib/config.toml | 10 + src/lib/dyn_array.c | 4 +- src/lib/vsprintf.c | 248 +++++------ src/objects/config.toml | 1 + tools/Makefile | 17 +- tools/configurator/.vscode/launch.json | 45 ++ tools/configurator/Cargo.lock | 398 ++++++++++++++++++ tools/configurator/Cargo.toml | 11 + tools/configurator/src/compile_commands.rs | 101 +++++ tools/configurator/src/config.rs | 191 +++++++++ tools/configurator/src/dependency.rs | 128 ++++++ tools/configurator/src/main.rs | 102 +++++ tools/configurator/src/parse.rs | 351 +++++++++++++++ 76 files changed, 1725 insertions(+), 315 deletions(-) delete mode 100644 CMakeLists.txt create mode 100644 config.toml delete mode 100644 src/CMakeLists.txt create mode 100644 src/arch/x86/bios_emu/config.toml create mode 100644 src/arch/x86/bios_emu/ops/config.toml create mode 100644 src/arch/x86/boot/config.toml create mode 100644 src/arch/x86/config.toml create mode 100644 src/arch/x86/drivers/bus/config.toml create mode 100644 src/arch/x86/drivers/bus/isa/config.toml create mode 100644 src/arch/x86/drivers/bus/pci/config.toml create mode 100644 src/arch/x86/drivers/config.toml delete mode 100644 src/arch/x86/drivers/disk/ata/ata.c create mode 100644 src/arch/x86/drivers/disk/ata/config.toml create mode 100644 src/arch/x86/drivers/disk/config.toml create mode 100644 src/arch/x86/drivers/framebuffer/config.toml create mode 100644 src/arch/x86/drivers/input/8042/config.toml create mode 100644 src/arch/x86/drivers/input/config.toml create mode 100644 src/arch/x86/drivers/interrupt/config.toml create mode 100644 src/arch/x86/drivers/network/config.toml create mode 100644 src/arch/x86/drivers/network/rtl8139/config.toml create mode 100644 src/arch/x86/drivers/sound/config.toml create mode 100644 src/arch/x86/drivers/sound/sb16/config.toml create mode 100644 src/arch/x86/drivers/timer/config.toml create mode 100644 src/arch/x86/drivers/usb/config.toml create mode 100644 src/arch/x86/drivers/usb/hcd/config.toml create mode 100644 src/arch/x86/drivers/usb/hcd/uhci/config.toml create mode 100644 src/arch/x86/kernel/config.toml create mode 100644 src/arch/x86/multiboot2/config.toml create mode 100644 src/config.toml create mode 100644 src/driver/config.toml create mode 100644 src/driver/framebuffer/config.toml create mode 100644 src/driver/input/config.toml create mode 100644 src/driver/interrupt/config.toml create mode 100644 src/driver/network/config.toml create mode 100644 src/driver/network/ethernet/config.toml create mode 100644 src/driver/network/protocols/config.toml create mode 100644 src/driver/network/protocols/ipv4/config.toml create mode 100644 src/driver/serial/config.toml create mode 100644 src/driver/sound/config.toml create mode 100644 src/driver/storage/config.toml create mode 100644 src/driver/storage/disk/config.toml create mode 100644 src/driver/timer/config.toml create mode 100644 src/drivers/bus/config.toml create mode 100644 src/drivers/bus/usb/Makefile create mode 100644 src/drivers/bus/usb/config.toml rename src/drivers/bus/{ => usb}/hcd.c (100%) rename src/drivers/bus/{ => usb}/usb.c (100%) create mode 100644 src/drivers/config.toml create mode 100644 src/drivers/usb/config.toml create mode 100644 src/drivers/usb/core/config.toml create mode 100644 src/drivers/usb/hid/config.toml create mode 100644 src/fs/config.toml create mode 100644 src/fs/fat/config.toml create mode 100644 src/kernel/config.toml create mode 100644 src/lib/config.toml create mode 100644 src/objects/config.toml create mode 100644 tools/configurator/.vscode/launch.json create mode 100644 tools/configurator/Cargo.lock create mode 100644 tools/configurator/Cargo.toml create mode 100644 tools/configurator/src/compile_commands.rs create mode 100644 tools/configurator/src/config.rs create mode 100644 tools/configurator/src/dependency.rs create mode 100644 tools/configurator/src/main.rs create mode 100644 tools/configurator/src/parse.rs diff --git a/.gitignore b/.gitignore index 816bc26..6fa8ef0 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,4 @@ fixdep *.dat *.idx dump.pcap +target/ diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 1a904af..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -cmake_minimum_required(VERSION 3.24) -project(HorizonOS C ASM) - -set(CMAKE_C_STANDARD 11) -enable_language(ASM) - -# 内核 -add_subdirectory(src) - -# 库 -#add_subdirectory(libs) - -# 工具 (Rust) -add_custom_target(tools - COMMAND cargo build --manifest-path ${CMAKE_SOURCE_DIR}/tools/imagetool/Cargo.toml --release - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tools/imagetool -) - -# 应用 -#add_subdirectory(apps) - -# qemu run -add_custom_target(run - COMMAND ${CMAKE_COMMAND} -E echo "Running QEMU..." - # 后续可以写具体 qemu 命令 - COMMAND "qemu-system-x86_64" -no-reboot -monitor stdio -m 1024 - -hda ${CMAKE_SOURCE_DIR}/hd0.img - -usb - -device usb-mouse - -device rtl8139,netdev=nc1 - -netdev user,id=nc1,hostfwd=tcp::5555-:80 - -object filter-dump,id=f1,netdev=nc1,file=dump.pcap - -readconfig ${CMAKE_SOURCE_DIR}/qemu-linux.cfg - -boot c -) diff --git a/Makefile b/Makefile index 5ea9845..da7612e 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,8 @@ FS_DIR = $(KERNEL_DIR)/fs LIB_DIR = $(KERNEL_SRC)/lib DISK_DIR = disk +KERNEL_OUTPUT_DIR = $(KERNEL_SRC)/build + LOADER_OFF = 2 LOADER_CNTS = 8 @@ -48,9 +50,10 @@ KERNEL_CNTS = 600 BOOT_BIN = $(BOOT_DIR)/boot.bin LOADER_BIN = $(BOOT_DIR)/loader.bin -KERNEL_ELF = $(KERNEL_SRC)/kernel.elf +KERNEL_ELF = $(KERNEL_OUTPUT_DIR)/kernel.elf IMAGETOOL = $(TOOL_SRC)/bin/imagetool +CONFIGURATOR = $(TOOL_SRC)/bin/configurator INSTALL_GRUB_SCRIPT = $(TOOL_SRC)/grub/install_grub.py @@ -71,9 +74,10 @@ hd: tool app: $(MAKE) -s -C $(APP_SRC) -kernel: +kernel: tool $(MAKE) -s -C $(BOOT_DIR) - $(MAKE) -s -C $(KERNEL_SRC) + $(CONFIGURATOR) --work-dir . --out-dir $(KERNEL_OUTPUT_DIR) + $(MAKE) -s -C $(KERNEL_OUTPUT_DIR) $(IMAGETOOL) $(HD_IMG) copy $(KERNEL_ELF) /p0/kernel.elf tool: diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..4fc9d89 --- /dev/null +++ b/config.toml @@ -0,0 +1,26 @@ +arch = "x86" + +[tools] +cc = "x86_64-elf-gcc" +as = "nasm" +ld = "x86_64-elf-ld" +cflags = [ + "-march=i486", + "-std=gnu11", + "-nostdinc", + "-nostdlib", + "-O0", + "-m32", + "-ffreestanding", + "-fno-pie", + "-fno-stack-protector", + "-fno-strict-aliasing", + "-fno-builtin", + "-Wall", + "-Wunused", +] +asflags = ["-g", "-f", "elf32"] +ldflags = ["-m", "elf_i386", "-nostdlib"] + +[debug] +level = "all" diff --git a/include/ctype.h b/include/ctype.h index 7acf55d..da3f51f 100644 --- a/include/ctype.h +++ b/include/ctype.h @@ -1,34 +1,34 @@ #ifndef _CTYPE_H #define _CTYPE_H -#define _U 0x01 /* upper */ -#define _L 0x02 /* lower */ -#define _D 0x04 /* digit */ -#define _C 0x08 /* cntrl */ -#define _P 0x10 /* punct */ -#define _S 0x20 /* white space (space/lf/tab) */ -#define _X 0x40 /* hex digit */ -#define _SP 0x80 /* hard space (0x20) */ +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ +#define _SP 0x80 /* hard space (0x20) */ extern unsigned char _ctype[]; -extern char _ctmp; +extern char _ctmp; -#define isalnum(c) ((_ctype+1)[c]&(_U|_L|_D)) -#define isalpha(c) ((_ctype+1)[c]&(_U|_L)) -#define iscntrl(c) ((_ctype+1)[c]&(_C)) -#define isdigit(c) ((_ctype+1)[c]&(_D)) -#define isgraph(c) ((_ctype+1)[c]&(_P|_U|_L|_D)) -#define islower(c) ((_ctype+1)[c]&(_L)) -#define isprint(c) ((_ctype+1)[c]&(_P|_U|_L|_D|_SP)) -#define ispunct(c) ((_ctype+1)[c]&(_P)) -#define isspace(c) ((_ctype+1)[c]&(_S)) -#define isupper(c) ((_ctype+1)[c]&(_U)) -#define isxdigit(c) ((_ctype+1)[c]&(_D|_X)) +#define isalnum(c) ((_ctype + 1)[(int)(c)] & (_U | _L | _D)) +#define isalpha(c) ((_ctype + 1)[(int)(c)] & (_U | _L)) +#define iscntrl(c) ((_ctype + 1)[(int)(c)] & (_C)) +#define isdigit(c) ((_ctype + 1)[(int)(c)] & (_D)) +#define isgraph(c) ((_ctype + 1)[(int)(c)] & (_P | _U | _L | _D)) +#define islower(c) ((_ctype + 1)[(int)(c)] & (_L)) +#define isprint(c) ((_ctype + 1)[(int)(c)] & (_P | _U | _L | _D | _SP)) +#define ispunct(c) ((_ctype + 1)[(int)(c)] & (_P)) +#define isspace(c) ((_ctype + 1)[(int)(c)] & (_S)) +#define isupper(c) ((_ctype + 1)[(int)(c)] & (_U)) +#define isxdigit(c) ((_ctype + 1)[(int)(c)] & (_D | _X)) -#define isascii(c) (((unsigned) c)<=0x7f) -#define toascii(c) (((unsigned) c)&0x7f) +#define isascii(c) (((unsigned)c) <= 0x7f) +#define toascii(c) (((unsigned)c) & 0x7f) -#define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp-('A'-'a'):_ctmp) -#define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp-('a'-'A'):_ctmp) +#define tolower(c) (_ctmp = c, isupper(_ctmp) ? _ctmp - ('A' - 'a') : _ctmp) +#define toupper(c) (_ctmp = c, islower(_ctmp) ? _ctmp - ('a' - 'A') : _ctmp) #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 174765e..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -cmake_minimum_required(VERSION 3.24) -project(HorizonOSKernel C ASM) - -# 开启 ASM 支持 -enable_language(ASM) - -# include 目录 -include_directories( - ${CMAKE_SOURCE_DIR}/src/include - ${CMAKE_SOURCE_DIR}/src/arch/x86/include -) - -# 汇编文件列表 -file(GLOB_RECURSE ASM_SRCS - arch/x86/boot/*.asm - arch/x86/kernel/*.asm -) - -# C 文件列表 -file(GLOB_RECURSE C_SRCS - arch/x86/**/*.c - fs/**/*.c - driver/**/*.c - kernel/*.c - lib/**/*.c - objects/**/*.c -) -list(REMOVE_ITEM C_SRCS - "${CMAKE_SOURCE_DIR}/src/arch/x86/drivers/network/rtl8139.c" - "${CMAKE_SOURCE_DIR}/src/arch/x86/drivers/usb/**.c" -) - - -# 输出内核 ELF -add_executable(kernel.elf ${C_SRCS} ${ASM_SRCS}) - -if(APPLE) - set(CMAKE_LINKER x86_64-elf-ld) -else() - set(CMAKE_LINKER ld) -endif() -set(CMAKE_EXE_LINKER_FLAGS "-m elf_i386 -g -no-pie -T ${CMAKE_SOURCE_DIR}/src/arch/x86/kernel.lds") - - -set_source_files_properties(${ASM_SRCS} PROPERTIES COMPILE_FLAGS "-g -f elf") - -# 链接器脚本 -set_target_properties(kernel.elf PROPERTIES LINK_FLAGS "-T ${CMAKE_SOURCE_DIR}/src/arch/x86/kernel.lds") - -# 编译选项 -target_compile_options(kernel.elf PRIVATE - -march=i486 -fno-builtin -Wall -Wunused -m32 -std=gnu11 - -fno-stack-protector -nostdinc -nostdlib -O0 -DARCH_X86=32 - -DKERNEL_NAME=\"horizon\" -DKERNEL_VERSION=\"0.0.1\" -) diff --git a/src/arch/x86/bios_emu/config.toml b/src/arch/x86/bios_emu/config.toml new file mode 100644 index 0000000..cb40055 --- /dev/null +++ b/src/arch/x86/bios_emu/config.toml @@ -0,0 +1,2 @@ +dir = ["ops/"] +c = ["bios_emu.c", "decode.c", "mod_rm.c", "operations.c", "segment.c"] diff --git a/src/arch/x86/bios_emu/ops/config.toml b/src/arch/x86/bios_emu/ops/config.toml new file mode 100644 index 0000000..0976020 --- /dev/null +++ b/src/arch/x86/bios_emu/ops/config.toml @@ -0,0 +1,12 @@ +c = [ + "alu.c", + "bt.c", + "call.c", + "conditions.c", + "int.c", + "jmp.c", + "mov.c", + "segment.c", + "stack.c", + "xchg.c", +] diff --git a/src/arch/x86/boot/config.toml b/src/arch/x86/boot/config.toml new file mode 100644 index 0000000..ebf3ef0 --- /dev/null +++ b/src/arch/x86/boot/config.toml @@ -0,0 +1 @@ +asm = ["boot.asm", "loader.asm"] diff --git a/src/arch/x86/config.toml b/src/arch/x86/config.toml new file mode 100644 index 0000000..f609394 --- /dev/null +++ b/src/arch/x86/config.toml @@ -0,0 +1 @@ +dir = ["multiboot2/", "bios_emu/", "drivers/", "kernel/"] diff --git a/src/arch/x86/drivers/bus/config.toml b/src/arch/x86/drivers/bus/config.toml new file mode 100644 index 0000000..8d07c67 --- /dev/null +++ b/src/arch/x86/drivers/bus/config.toml @@ -0,0 +1 @@ +dir = ["isa/", "pci/"] diff --git a/src/arch/x86/drivers/bus/isa/config.toml b/src/arch/x86/drivers/bus/isa/config.toml new file mode 100644 index 0000000..160f80d --- /dev/null +++ b/src/arch/x86/drivers/bus/isa/config.toml @@ -0,0 +1 @@ +c = ["dma.c", "isa.c"] diff --git a/src/arch/x86/drivers/bus/pci/config.toml b/src/arch/x86/drivers/bus/pci/config.toml new file mode 100644 index 0000000..b90a931 --- /dev/null +++ b/src/arch/x86/drivers/bus/pci/config.toml @@ -0,0 +1 @@ +c = ["pci.c"] diff --git a/src/arch/x86/drivers/config.toml b/src/arch/x86/drivers/config.toml new file mode 100644 index 0000000..25805d8 --- /dev/null +++ b/src/arch/x86/drivers/config.toml @@ -0,0 +1,12 @@ +dir = [ + "bus/", + "disk/", + "framebuffer/", + "input/", + "interrupt/", + "network/", + "sound/", + "timer/", + "usb/", +] +c = ["cmos.c", "msr.c", "serial.c"] diff --git a/src/arch/x86/drivers/disk/ata/ata.c b/src/arch/x86/drivers/disk/ata/ata.c deleted file mode 100644 index e69de29..0000000 diff --git a/src/arch/x86/drivers/disk/ata/config.toml b/src/arch/x86/drivers/disk/ata/config.toml new file mode 100644 index 0000000..705a9cc --- /dev/null +++ b/src/arch/x86/drivers/disk/ata/config.toml @@ -0,0 +1 @@ +c = ["ata_driver.c", "dma.c", "ide_controller.c", "ide.c"] diff --git a/src/arch/x86/drivers/disk/config.toml b/src/arch/x86/drivers/disk/config.toml new file mode 100644 index 0000000..62b46df --- /dev/null +++ b/src/arch/x86/drivers/disk/config.toml @@ -0,0 +1 @@ +dir = ["ata/"] diff --git a/src/arch/x86/drivers/framebuffer/config.toml b/src/arch/x86/drivers/framebuffer/config.toml new file mode 100644 index 0000000..f0d20c3 --- /dev/null +++ b/src/arch/x86/drivers/framebuffer/config.toml @@ -0,0 +1 @@ +c = ["vesa_display.c"] diff --git a/src/arch/x86/drivers/input/8042/config.toml b/src/arch/x86/drivers/input/8042/config.toml new file mode 100644 index 0000000..701acd0 --- /dev/null +++ b/src/arch/x86/drivers/input/8042/config.toml @@ -0,0 +1 @@ +c = ["8042.c", "keyboard.c", "mouse.c"] diff --git a/src/arch/x86/drivers/input/config.toml b/src/arch/x86/drivers/input/config.toml new file mode 100644 index 0000000..76ef4f5 --- /dev/null +++ b/src/arch/x86/drivers/input/config.toml @@ -0,0 +1 @@ +dir = ["8042/"] diff --git a/src/arch/x86/drivers/interrupt/config.toml b/src/arch/x86/drivers/interrupt/config.toml new file mode 100644 index 0000000..f84b2c8 --- /dev/null +++ b/src/arch/x86/drivers/interrupt/config.toml @@ -0,0 +1 @@ +c = ["8259a.c", "apic.c"] diff --git a/src/arch/x86/drivers/network/config.toml b/src/arch/x86/drivers/network/config.toml new file mode 100644 index 0000000..ee2eec7 --- /dev/null +++ b/src/arch/x86/drivers/network/config.toml @@ -0,0 +1 @@ +dir = ["rtl8139/"] diff --git a/src/arch/x86/drivers/network/rtl8139/config.toml b/src/arch/x86/drivers/network/rtl8139/config.toml new file mode 100644 index 0000000..f532cef --- /dev/null +++ b/src/arch/x86/drivers/network/rtl8139/config.toml @@ -0,0 +1 @@ +c = ["rtl8139.c"] diff --git a/src/arch/x86/drivers/sound/config.toml b/src/arch/x86/drivers/sound/config.toml new file mode 100644 index 0000000..0ce69d9 --- /dev/null +++ b/src/arch/x86/drivers/sound/config.toml @@ -0,0 +1 @@ +dir = ["sb16/"] diff --git a/src/arch/x86/drivers/sound/sb16/config.toml b/src/arch/x86/drivers/sound/sb16/config.toml new file mode 100644 index 0000000..4c4ea29 --- /dev/null +++ b/src/arch/x86/drivers/sound/sb16/config.toml @@ -0,0 +1 @@ +c = ["sb16.c"] diff --git a/src/arch/x86/drivers/timer/config.toml b/src/arch/x86/drivers/timer/config.toml new file mode 100644 index 0000000..6a7b406 --- /dev/null +++ b/src/arch/x86/drivers/timer/config.toml @@ -0,0 +1 @@ +c = ["pit.c"] diff --git a/src/arch/x86/drivers/usb/config.toml b/src/arch/x86/drivers/usb/config.toml new file mode 100644 index 0000000..24cb422 --- /dev/null +++ b/src/arch/x86/drivers/usb/config.toml @@ -0,0 +1 @@ +dir = ["hcd/"] diff --git a/src/arch/x86/drivers/usb/hcd/config.toml b/src/arch/x86/drivers/usb/hcd/config.toml new file mode 100644 index 0000000..9e30df0 --- /dev/null +++ b/src/arch/x86/drivers/usb/hcd/config.toml @@ -0,0 +1,2 @@ +dir = ["uhci/"] +c = ["hcd.c"] diff --git a/src/arch/x86/drivers/usb/hcd/uhci/config.toml b/src/arch/x86/drivers/usb/hcd/uhci/config.toml new file mode 100644 index 0000000..4d5c41a --- /dev/null +++ b/src/arch/x86/drivers/usb/hcd/uhci/config.toml @@ -0,0 +1 @@ +c = ["packet.c", "skeleton.c", "uhci.c"] diff --git a/src/arch/x86/kernel.lds b/src/arch/x86/kernel.lds index c48d3b5..e3dd9d7 100644 --- a/src/arch/x86/kernel.lds +++ b/src/arch/x86/kernel.lds @@ -16,6 +16,10 @@ SECTIONS { */ . = 0x00100000; + .multiboot2_header ALIGN(8) : { + KEEP(*(.multiboot2_header)) + } : text + /* code segment */ .text : { . = ALIGN(4); /* 4 bytes align */ diff --git a/src/arch/x86/kernel/config.toml b/src/arch/x86/kernel/config.toml new file mode 100644 index 0000000..d440512 --- /dev/null +++ b/src/arch/x86/kernel/config.toml @@ -0,0 +1,2 @@ +c = ["descriptor.c", "feature.c", "page.c", "platform.c"] +asm = ["func.asm", "start.asm"] diff --git a/src/arch/x86/multiboot2/config.toml b/src/arch/x86/multiboot2/config.toml new file mode 100644 index 0000000..fecbc06 --- /dev/null +++ b/src/arch/x86/multiboot2/config.toml @@ -0,0 +1,2 @@ +c = ["multiboot2.c"] +asm = ["multiboot2.asm"] diff --git a/src/config.toml b/src/config.toml new file mode 100644 index 0000000..561fa3d --- /dev/null +++ b/src/config.toml @@ -0,0 +1,15 @@ +dir = ["driver/", "drivers/", "fs/", "kernel/", "lib/", "objects/"] +includes = ["include/", "../include/"] +output = "kernel.elf" + +[arch.x86] +dir = ["arch/x86"] +lds = "arch/x86/kernel.lds" +includes = ["arch/x86/include"] +macro = { ARCH_X86 = "32" } + +[arch.x86_64] +dir = ["arch/x86"] +lds = "arch/x86/kernel.lds" +includes = ["arch/x86/include"] +macro = { ARCH_X86 = "64" } diff --git a/src/driver/config.toml b/src/driver/config.toml new file mode 100644 index 0000000..e9bfe6c --- /dev/null +++ b/src/driver/config.toml @@ -0,0 +1,11 @@ +dir = [ + "framebuffer/", + "input/", + "interrupt/", + "network/", + "serial/", + "sound/", + "storage/", + "timer/", +] +c = ["bus_dm.c", "time_dm.c"] diff --git a/src/driver/framebuffer/config.toml b/src/driver/framebuffer/config.toml new file mode 100644 index 0000000..8ae3d15 --- /dev/null +++ b/src/driver/framebuffer/config.toml @@ -0,0 +1 @@ +c = ["console_backend.c", "framebuffer_dm.c", "framebuffer.c"] diff --git a/src/driver/input/config.toml b/src/driver/input/config.toml new file mode 100644 index 0000000..87ad3d6 --- /dev/null +++ b/src/driver/input/config.toml @@ -0,0 +1 @@ +c = ["input_dm.c"] diff --git a/src/driver/interrupt/config.toml b/src/driver/interrupt/config.toml new file mode 100644 index 0000000..fd95a49 --- /dev/null +++ b/src/driver/interrupt/config.toml @@ -0,0 +1 @@ +c = ["interrupt_dm.c"] diff --git a/src/driver/network/config.toml b/src/driver/network/config.toml new file mode 100644 index 0000000..2824976 --- /dev/null +++ b/src/driver/network/config.toml @@ -0,0 +1,2 @@ +dir = ["ethernet/", "protocols/"] +c = ["buffer.c", "conn.c", "mii.c", "neighbour.c", "network_dm.c", "network.c"] diff --git a/src/driver/network/ethernet/config.toml b/src/driver/network/ethernet/config.toml new file mode 100644 index 0000000..280b667 --- /dev/null +++ b/src/driver/network/ethernet/config.toml @@ -0,0 +1 @@ +c = ["ethernet.c"] diff --git a/src/driver/network/protocols/config.toml b/src/driver/network/protocols/config.toml new file mode 100644 index 0000000..f619b0e --- /dev/null +++ b/src/driver/network/protocols/config.toml @@ -0,0 +1,2 @@ +dir = ["ipv4/"] +c = ["tcp.c", "udp.c"] diff --git a/src/driver/network/protocols/ipv4/config.toml b/src/driver/network/protocols/ipv4/config.toml new file mode 100644 index 0000000..2382354 --- /dev/null +++ b/src/driver/network/protocols/ipv4/config.toml @@ -0,0 +1 @@ +c = ["acd.c", "arp.c", "dhcp.c", "icmp.c", "ipv4.c"] diff --git a/src/driver/serial/config.toml b/src/driver/serial/config.toml new file mode 100644 index 0000000..341ca48 --- /dev/null +++ b/src/driver/serial/config.toml @@ -0,0 +1 @@ +c = ["serial_dm.c"] diff --git a/src/driver/sound/config.toml b/src/driver/sound/config.toml new file mode 100644 index 0000000..ba9d00e --- /dev/null +++ b/src/driver/sound/config.toml @@ -0,0 +1 @@ +c = ["pcm.c", "sound_dm.c"] diff --git a/src/driver/storage/config.toml b/src/driver/storage/config.toml new file mode 100644 index 0000000..b9158a0 --- /dev/null +++ b/src/driver/storage/config.toml @@ -0,0 +1,2 @@ +dir = ["disk/"] +c = ["storage_dm.c", "storage_io_queue.c", "storage_io.c", "volume.c"] diff --git a/src/driver/storage/disk/config.toml b/src/driver/storage/disk/config.toml new file mode 100644 index 0000000..376e353 --- /dev/null +++ b/src/driver/storage/disk/config.toml @@ -0,0 +1 @@ +c = ["disk.c", "mbr.c"] diff --git a/src/driver/timer/config.toml b/src/driver/timer/config.toml new file mode 100644 index 0000000..1c2fc4c --- /dev/null +++ b/src/driver/timer/config.toml @@ -0,0 +1 @@ +c = ["timer_dm.c", "timer.c"] diff --git a/src/drivers/bus/Makefile b/src/drivers/bus/Makefile index f374ace..3a34463 100644 --- a/src/drivers/bus/Makefile +++ b/src/drivers/bus/Makefile @@ -1,2 +1 @@ -SRC += usb.c -SRC += hcd.c \ No newline at end of file +SRC += usb/ \ No newline at end of file diff --git a/src/drivers/bus/config.toml b/src/drivers/bus/config.toml new file mode 100644 index 0000000..21c43fe --- /dev/null +++ b/src/drivers/bus/config.toml @@ -0,0 +1 @@ +dir = ["usb/"] diff --git a/src/drivers/bus/usb/Makefile b/src/drivers/bus/usb/Makefile new file mode 100644 index 0000000..9547e5f --- /dev/null +++ b/src/drivers/bus/usb/Makefile @@ -0,0 +1,2 @@ +SRC += hcd.c +SRC += usb.c \ No newline at end of file diff --git a/src/drivers/bus/usb/config.toml b/src/drivers/bus/usb/config.toml new file mode 100644 index 0000000..5a38118 --- /dev/null +++ b/src/drivers/bus/usb/config.toml @@ -0,0 +1 @@ +c = ["hcd.c", "usb.c"] diff --git a/src/drivers/bus/hcd.c b/src/drivers/bus/usb/hcd.c similarity index 100% rename from src/drivers/bus/hcd.c rename to src/drivers/bus/usb/hcd.c diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb/usb.c similarity index 100% rename from src/drivers/bus/usb.c rename to src/drivers/bus/usb/usb.c diff --git a/src/drivers/config.toml b/src/drivers/config.toml new file mode 100644 index 0000000..7442c33 --- /dev/null +++ b/src/drivers/config.toml @@ -0,0 +1 @@ +dir = ["bus/", "usb/"] diff --git a/src/drivers/usb/config.toml b/src/drivers/usb/config.toml new file mode 100644 index 0000000..1571f7c --- /dev/null +++ b/src/drivers/usb/config.toml @@ -0,0 +1 @@ +dir = ["core/", "hid/"] diff --git a/src/drivers/usb/core/config.toml b/src/drivers/usb/core/config.toml new file mode 100644 index 0000000..985a26e --- /dev/null +++ b/src/drivers/usb/core/config.toml @@ -0,0 +1 @@ +c = ["func.c", "hub.c", "urb.c", "usb.c"] diff --git a/src/drivers/usb/hid/config.toml b/src/drivers/usb/hid/config.toml new file mode 100644 index 0000000..76102a6 --- /dev/null +++ b/src/drivers/usb/hid/config.toml @@ -0,0 +1 @@ +c = ["hid.c", "keyboard.c", "mouse.c"] diff --git a/src/fs/config.toml b/src/fs/config.toml new file mode 100644 index 0000000..e211fa6 --- /dev/null +++ b/src/fs/config.toml @@ -0,0 +1,2 @@ +dir = ["fat/"] +c = ["fs.c"] diff --git a/src/fs/fat/config.toml b/src/fs/fat/config.toml new file mode 100644 index 0000000..370b264 --- /dev/null +++ b/src/fs/fat/config.toml @@ -0,0 +1 @@ +c = ["attr.c", "cluster.c", "dir.c", "entry.c", "fat.c", "name.c"] diff --git a/src/include/ctype.h b/src/include/ctype.h index 09037f7..da3f51f 100644 --- a/src/include/ctype.h +++ b/src/include/ctype.h @@ -1,29 +1,29 @@ #ifndef _CTYPE_H #define _CTYPE_H -#define _U 0x01 /* upper */ -#define _L 0x02 /* lower */ -#define _D 0x04 /* digit */ -#define _C 0x08 /* cntrl */ -#define _P 0x10 /* punct */ -#define _S 0x20 /* white space (space/lf/tab) */ -#define _X 0x40 /* hex digit */ +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ #define _SP 0x80 /* hard space (0x20) */ extern unsigned char _ctype[]; -extern char _ctmp; +extern char _ctmp; -#define isalnum(c) ((_ctype + 1)[c] & (_U | _L | _D)) -#define isalpha(c) ((_ctype + 1)[c] & (_U | _L)) -#define iscntrl(c) ((_ctype + 1)[c] & (_C)) -#define isdigit(c) ((_ctype + 1)[c] & (_D)) -#define isgraph(c) ((_ctype + 1)[c] & (_P | _U | _L | _D)) -#define islower(c) ((_ctype + 1)[c] & (_L)) -#define isprint(c) ((_ctype + 1)[c] & (_P | _U | _L | _D | _SP)) -#define ispunct(c) ((_ctype + 1)[c] & (_P)) -#define isspace(c) ((_ctype + 1)[c] & (_S)) -#define isupper(c) ((_ctype + 1)[c] & (_U)) -#define isxdigit(c) ((_ctype + 1)[c] & (_D | _X)) +#define isalnum(c) ((_ctype + 1)[(int)(c)] & (_U | _L | _D)) +#define isalpha(c) ((_ctype + 1)[(int)(c)] & (_U | _L)) +#define iscntrl(c) ((_ctype + 1)[(int)(c)] & (_C)) +#define isdigit(c) ((_ctype + 1)[(int)(c)] & (_D)) +#define isgraph(c) ((_ctype + 1)[(int)(c)] & (_P | _U | _L | _D)) +#define islower(c) ((_ctype + 1)[(int)(c)] & (_L)) +#define isprint(c) ((_ctype + 1)[(int)(c)] & (_P | _U | _L | _D | _SP)) +#define ispunct(c) ((_ctype + 1)[(int)(c)] & (_P)) +#define isspace(c) ((_ctype + 1)[(int)(c)] & (_S)) +#define isupper(c) ((_ctype + 1)[(int)(c)] & (_U)) +#define isxdigit(c) ((_ctype + 1)[(int)(c)] & (_D | _X)) #define isascii(c) (((unsigned)c) <= 0x7f) #define toascii(c) (((unsigned)c) & 0x7f) diff --git a/src/include/driver/framebuffer/fb.h b/src/include/driver/framebuffer/fb.h index 6c5c65b..5fb2e50 100644 --- a/src/include/driver/framebuffer/fb.h +++ b/src/include/driver/framebuffer/fb.h @@ -10,11 +10,6 @@ typedef struct FramebufferOps { struct FrameBufferDevice; struct FrameBufferModeInfo; -void inline write_pixel( - struct FrameBufferDevice *fb_device, int x, int y, uint32_t color); -void inline write_pixel_rgb( - struct FrameBufferDevice *fb_device, int x, int y, uint8_t r, uint8_t g, - uint8_t b); void draw_rect( struct FrameBufferDevice *fb_device, int x, int y, int width, int height, int color); diff --git a/src/include/stdarg.h b/src/include/stdarg.h index 18e8025..5ce0974 100644 --- a/src/include/stdarg.h +++ b/src/include/stdarg.h @@ -1,15 +1,13 @@ #ifndef _LIB_STDARG_H #define _LIB_STDARG_H -#define _AUPBND 1 -#define _ADNBND 1 -#define _Bnd(X, bnd) (sizeof(X) + (bnd) & ~(bnd)) +#define _AUPBND 1 +#define _ADNBND 1 +#define _Bnd(X, bnd) (sizeof(X) + ((bnd) & ~(bnd))) typedef char *va_list; -#define va_arg(ap, T) \ - (*(T *)(((ap) += _Bnd(T, _AUPBND)) - _Bnd(T, _ADNBND))) -#define va_end(ap) (void)0 -#define va_start(ap, A) \ - (void)((ap) = (char *)&(A) + _Bnd(A, _AUPBND)) +#define va_arg(ap, T) (*(T *)(((ap) += _Bnd(T, _AUPBND)) - _Bnd(T, _ADNBND))) +#define va_end(ap) (void)0 +#define va_start(ap, A) (void)((ap) = (char *)&(A) + _Bnd(A, _AUPBND)) #endif diff --git a/src/kernel/config.toml b/src/kernel/config.toml new file mode 100644 index 0000000..9e6db61 --- /dev/null +++ b/src/kernel/config.toml @@ -0,0 +1,28 @@ +c = [ + "driver/bus_driver.c", + "driver/device_driver.c", + "driver/device_manager.c", + "driver/device.c", + "driver/dma.c", + "driver/driver_interface.c", + "driver/driver.c", + "app.c", + "block_cache.c", + "condvar.c", + "console.c", + "elf.c", + "fifo.c", + "font-default.c", + "initcall.c", + "main.c", + "memory.c", + "memtest.c", + "periodic_task.c", + "process.c", + "rwlock.c", + "softirq.c", + "sync.c", + "syscall.c", + "thread.c", + "wait_queue.c", +] diff --git a/src/kernel/elf.c b/src/kernel/elf.c index c0cc38b..5b82947 100644 --- a/src/kernel/elf.c +++ b/src/kernel/elf.c @@ -17,38 +17,38 @@ * @param prog * @return unsigned int* */ -unsigned int *elf_load(struct program_struct *prog) { - struct elf32_header header; - // seek(prog->inode, 0, 0); - // read(prog->inode, (uint8_t *)&header, sizeof(struct elf32_header)); +// unsigned int *elf_load(struct program_struct *prog) { +// struct elf32_header header; +// seek(prog->inode, 0, 0); +// read(prog->inode, (uint8_t *)&header, sizeof(struct elf32_header)); - if (memcmp(header.e_ident, "\177ELF\1\1\1", 7) || - header.e_type != ELF32_ET_EXEC || header.e_machine != ELF32_EM_386 || - header.e_version != 1 || header.e_phnum > 1024 || - header.e_phentsize != sizeof(struct elf32_program_header)) { - printk("Error:unsupported executable file!\n"); - return NULL; - } +// if (memcmp(header.e_ident, "\177ELF\1\1\1", 7) || +// header.e_type != ELF32_ET_EXEC || header.e_machine != ELF32_EM_386 || +// header.e_version != 1 || header.e_phnum > 1024 || +// header.e_phentsize != sizeof(struct elf32_program_header)) { +// printk("Error:unsupported executable file!\n"); +// return NULL; +// } - struct elf32_program_header pheader; - Elf32_Off prog_header_off = header.e_phoff; - Elf32_Half prog_header_size = header.e_phentsize; +// struct elf32_program_header pheader; +// Elf32_Off prog_header_off = header.e_phoff; +// Elf32_Half prog_header_size = header.e_phentsize; - unsigned long i; - prog->phnum = header.e_phnum; - for (i = 0; i < header.e_phnum; i++) { - memset(&pheader, 0, prog_header_size); - // seek(prog->inode, prog_header_off, 0); - // read(prog->inode, (uint8_t *)&pheader, prog_header_size); - if (pheader.p_type == PT_LOAD) { - struct prog_segment *progseg = kmalloc(sizeof(struct prog_segment)); - progseg->vaddr = pheader.p_vaddr; - progseg->filesz = pheader.p_filesz; - progseg->memsz = pheader.p_memsz; - progseg->offset = pheader.p_offset; - list_add_tail(&progseg->list, &prog->seg_head); - } - prog_header_off += prog_header_size; - } - return (unsigned int *)header.e_entry; -} \ No newline at end of file +// unsigned long i; +// prog->phnum = header.e_phnum; +// for (i = 0; i < header.e_phnum; i++) { +// memset(&pheader, 0, prog_header_size); +// seek(prog->inode, prog_header_off, 0); +// read(prog->inode, (uint8_t *)&pheader, prog_header_size); +// if (pheader.p_type == PT_LOAD) { +// struct prog_segment *progseg = kmalloc(sizeof(struct prog_segment)); +// progseg->vaddr = pheader.p_vaddr; +// progseg->filesz = pheader.p_filesz; +// progseg->memsz = pheader.p_memsz; +// progseg->offset = pheader.p_offset; +// list_add_tail(&progseg->list, &prog->seg_head); +// } +// prog_header_off += prog_header_size; +// } +// return (unsigned int *)header.e_entry; +// } \ No newline at end of file diff --git a/src/lib/config.toml b/src/lib/config.toml new file mode 100644 index 0000000..69c8b88 --- /dev/null +++ b/src/lib/config.toml @@ -0,0 +1,10 @@ +c = [ + "ctype.c", + "dyn_array.c", + "math.c", + "random.c", + "string.c", + "vsprintf.c", + "hash/fnv.c", + "hash/md5.c", +] diff --git a/src/lib/dyn_array.c b/src/lib/dyn_array.c index af0ac53..9188aae 100644 --- a/src/lib/dyn_array.c +++ b/src/lib/dyn_array.c @@ -85,8 +85,8 @@ void *dyn_array_next_ptr( DynArray *dyn_array, struct DynArrayBlock **block, int *block_index, int *block_offset) { - struct DynArrayBlock *current_block = *block; - int offset = *block_offset; + // struct DynArrayBlock *current_block = *block; + int offset = *block_offset; if (offset + 1 < dyn_array->block_size) { (*block_offset)++; diff --git a/src/lib/vsprintf.c b/src/lib/vsprintf.c index 686cf4d..4682759 100644 --- a/src/lib/vsprintf.c +++ b/src/lib/vsprintf.c @@ -5,13 +5,12 @@ * copyright: (C) 2018-2020 by Book OS developers. All rights reserved. */ -#include -#include #include +#include +#include -unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) -{ - unsigned long result = 0,value; +unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) { + unsigned long result = 0, value; if (!base) { base = 10; @@ -24,130 +23,138 @@ unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) } } } - while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) - ? toupper(*cp) : *cp)-'A'+10) < base) { - result = result*base + value; + while (isxdigit(*cp) && + (value = isdigit(*cp) ? *cp - '0' + : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + + 10) < base) { + result = result * base + value; cp++; } - if (endp) - *endp = (char *)cp; + if (endp) *endp = (char *)cp; return result; } /* we use this so that we can do without the ctype library */ -#define is_digit(c) ((c) >= '0' && (c) <= '9') +#define is_digit(c) ((c) >= '0' && (c) <= '9') -static int skip_atoi(const char **s) -{ - int i=0; +static int skip_atoi(const char **s) { + int i = 0; while (is_digit(**s)) - i = i*10 + *((*s)++) - '0'; + i = i * 10 + *((*s)++) - '0'; return i; } -#define ZEROPAD 1 /* pad with zero */ -#define SIGN 2 /* unsigned/signed long */ -#define PLUS 4 /* show plus */ -#define SPACE 8 /* space if plus */ -#define LEFT 16 /* left justified */ -#define SPECIAL 32 /* 0x */ -#define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */ +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */ -#define do_div(n,base) ({ \ -int __res; \ -__asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \ -__res; }) +#define do_div(n, base) \ + ({ \ + int __res; \ + __asm__("divl %4" : "=a"(n), "=d"(__res) : "0"(n), "1"(0), "r"(base)); \ + __res; \ + }) -static char * number(char * str, int num, int base, int size, int precision - ,int type) -{ - char c,sign,tmp[36]; - const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - int i; +static char *number( + char *str, int num, int base, int size, int precision, int type) { + char c, sign, tmp[36]; + const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; - if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz"; - if (type&LEFT) type &= ~ZEROPAD; - if (base<2 || base>36) - return 0; - c = (type & ZEROPAD) ? '0' : ' ' ; - if (type&SIGN && num<0) { - sign='-'; - num = -num; - } else - sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0); + if (type & SMALL) digits = "0123456789abcdefghijklmnopqrstuvwxyz"; + if (type & LEFT) type &= ~ZEROPAD; + if (base < 2 || base > 36) return 0; + c = (type & ZEROPAD) ? '0' : ' '; + if (type & SIGN && num < 0) { + sign = '-'; + num = -num; + } else sign = (type & PLUS) ? '+' : ((type & SPACE) ? ' ' : 0); if (sign) size--; - if (type&SPECIAL) - if (base==16) size -= 2; - else if (base==8) size--; - i=0; - if (num==0) - tmp[i++]='0'; - else while (num!=0) - tmp[i++]=digits[do_div(num,base)]; - if (i>precision) precision=i; + if (type & SPECIAL) { + if (base == 16) size -= 2; + else if (base == 8) size--; + } + i = 0; + if (num == 0) tmp[i++] = '0'; + else + while (num != 0) + tmp[i++] = digits[do_div(num, base)]; + if (i > precision) precision = i; size -= precision; - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) + if (!(type & (ZEROPAD + LEFT))) + while (size-- > 0) *str++ = ' '; - if (sign) - *str++ = sign; - if (type&SPECIAL) - if (base==8) + if (sign) *str++ = sign; + if (type & SPECIAL) { + if (base == 8) { *str++ = '0'; - else if (base==16) { + } else if (base == 16) { *str++ = '0'; *str++ = digits[33]; } - if (!(type&LEFT)) - while(size-->0) + } + if (!(type & LEFT)) + while (size-- > 0) *str++ = c; - while(i0) + while (i-- > 0) *str++ = tmp[i]; - while(size-->0) + while (size-- > 0) *str++ = ' '; return str; } -int vsprintf(char *buf, const char *fmt, va_list args) -{ - int len; - int i; - char * str; +int vsprintf(char *buf, const char *fmt, va_list args) { + int len; + int i; + char *str; char *s; - int *ip; + int *ip; - int flags; /* flags to number() */ + int flags; /* flags to number() */ - int field_width; /* width of output field */ - int precision; /* min. # of digits for integers; max - number of chars for from string */ - int qualifier; /* 'h', 'l', or 'L' for integer fields */ + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + // int qualifier; /* 'h', 'l', or 'L' for integer fields */ - for (str=buf ; *fmt ; ++fmt) { + for (str = buf; *fmt; ++fmt) { if (*fmt != '%') { *str++ = *fmt; continue; } - + /* process flags */ flags = 0; - repeat: - ++fmt; /* this also skips first '%' */ - switch (*fmt) { - case '-': flags |= LEFT; goto repeat; - case '+': flags |= PLUS; goto repeat; - case ' ': flags |= SPACE; goto repeat; - case '#': flags |= SPECIAL; goto repeat; - case '0': flags |= ZEROPAD; goto repeat; - } - + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': + flags |= LEFT; + goto repeat; + case '+': + flags |= PLUS; + goto repeat; + case ' ': + flags |= SPACE; + goto repeat; + case '#': + flags |= SPECIAL; + goto repeat; + case '0': + flags |= ZEROPAD; + goto repeat; + } + /* get field width */ field_width = -1; - if (is_digit(*fmt)) - field_width = skip_atoi(&fmt); + if (is_digit(*fmt)) field_width = skip_atoi(&fmt); else if (*fmt == '*') { /* it's the next argument */ field_width = va_arg(args, int); @@ -160,21 +167,19 @@ int vsprintf(char *buf, const char *fmt, va_list args) /* get the precision */ precision = -1; if (*fmt == '.') { - ++fmt; - if (is_digit(*fmt)) - precision = skip_atoi(&fmt); + ++fmt; + if (is_digit(*fmt)) precision = skip_atoi(&fmt); else if (*fmt == '*') { /* it's the next argument */ precision = va_arg(args, int); } - if (precision < 0) - precision = 0; + if (precision < 0) precision = 0; } /* get the conversion qualifier */ - qualifier = -1; + // qualifier = -1; if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { - qualifier = *fmt; + // qualifier = *fmt; ++fmt; } @@ -183,20 +188,17 @@ int vsprintf(char *buf, const char *fmt, va_list args) if (!(flags & LEFT)) while (--field_width > 0) *str++ = ' '; - *str++ = (unsigned char) va_arg(args, int); + *str++ = (unsigned char)va_arg(args, int); while (--field_width > 0) *str++ = ' '; break; case 's': s = va_arg(args, char *); - if (!s) - s = ""; + if (!s) s = ""; len = strlen(s); - if (precision < 0) - precision = len; - else if (len > precision) - len = precision; + if (precision < 0) precision = len; + else if (len > precision) len = precision; if (!(flags & LEFT)) while (len < field_width--) @@ -208,8 +210,9 @@ int vsprintf(char *buf, const char *fmt, va_list args) break; case 'o': - str = number(str, va_arg(args, unsigned long), 8, - field_width, precision, flags); + str = number( + str, va_arg(args, unsigned long), 8, field_width, precision, + flags); break; case 'p': @@ -217,53 +220,50 @@ int vsprintf(char *buf, const char *fmt, va_list args) field_width = 8; flags |= ZEROPAD; } - str = number(str, - (unsigned long) va_arg(args, void *), 16, - field_width, precision, flags); + str = number( + str, (unsigned long)va_arg(args, void *), 16, field_width, + precision, flags); break; case 'x': flags |= SMALL; case 'X': - str = number(str, va_arg(args, unsigned long), 16, - field_width, precision, flags); + str = number( + str, va_arg(args, unsigned long), 16, field_width, precision, + flags); break; case 'd': case 'i': flags |= SIGN; case 'u': - str = number(str, va_arg(args, unsigned long), 10, - field_width, precision, flags); + str = number( + str, va_arg(args, unsigned long), 10, field_width, precision, + flags); break; case 'n': - ip = va_arg(args, int *); + ip = va_arg(args, int *); *ip = (str - buf); break; default: - if (*fmt != '%') - *str++ = '%'; - if (*fmt) - *str++ = *fmt; - else - --fmt; + if (*fmt != '%') *str++ = '%'; + if (*fmt) *str++ = *fmt; + else --fmt; break; } } *str = '\0'; - return str-buf; + return str - buf; } -int sprintf(char * buf, const char *fmt, ...) -{ +int sprintf(char *buf, const char *fmt, ...) { va_list args; - int i; + int i; va_start(args, fmt); - i=vsprintf(buf,fmt,args); + i = vsprintf(buf, fmt, args); va_end(args); return i; } - diff --git a/src/objects/config.toml b/src/objects/config.toml new file mode 100644 index 0000000..51d0210 --- /dev/null +++ b/src/objects/config.toml @@ -0,0 +1 @@ +c = ["handle.c", "mount.c", "objects.c", "ops.c", "permission.c", "types.c"] diff --git a/tools/Makefile b/tools/Makefile index a0e463a..5bc7c8e 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -5,19 +5,24 @@ RM = rm OUTPUT_DIR = bin/ IMAGETOOL_DIR = imagetool +CONFIGURATOR_DIR = configurator .PHONY: all -all: bin imgtool - -bin: - $(MKDIR) $(OUTPUT_DIR) +all: bin imgtool config imgtool: cargo build --release --manifest-path $(IMAGETOOL_DIR)/Cargo.toml cp $(IMAGETOOL_DIR)/target/release/imagetool $(OUTPUT_DIR) - cargo clean --manifest-path imagetool/Cargo.toml + +config: + cargo build --release --manifest-path $(CONFIGURATOR_DIR)/Cargo.toml + cp $(CONFIGURATOR_DIR)/target/release/configurator $(OUTPUT_DIR) + +bin: + $(MKDIR) $(OUTPUT_DIR) clean: - cargo clean --manifest-path imagetool/Cargo.toml + cargo clean --manifest-path $(IMAGETOOL_DIR)/Cargo.toml + cargo clean --manifest-path $(CONFIGURATOR_DIR)/Cargo.toml $(RM) -rf $(OUTPUT_DIR) \ No newline at end of file diff --git a/tools/configurator/.vscode/launch.json b/tools/configurator/.vscode/launch.json new file mode 100644 index 0000000..502e60e --- /dev/null +++ b/tools/configurator/.vscode/launch.json @@ -0,0 +1,45 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'configurator'", + "cargo": { + "args": [ + "build", + "--bin=configurator", + "--package=configurator" + ], + "filter": { + "name": "configurator", + "kind": "bin" + } + }, + "args": ["--work-dir", "../../", "--out-dir", "../../build/"], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'configurator'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=configurator", + "--package=configurator" + ], + "filter": { + "name": "configurator", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/tools/configurator/Cargo.lock b/tools/configurator/Cargo.lock new file mode 100644 index 0000000..0cac545 --- /dev/null +++ b/tools/configurator/Cargo.lock @@ -0,0 +1,398 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "clap" +version = "4.5.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "configurator" +version = "0.1.0" +dependencies = [ + "clap", + "path-clean", + "serde", + "serde_json", + "toml", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indexmap" +version = "2.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "path-clean" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_spanned" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +dependencies = [ + "serde_core", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "toml" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" diff --git a/tools/configurator/Cargo.toml b/tools/configurator/Cargo.toml new file mode 100644 index 0000000..e2c2807 --- /dev/null +++ b/tools/configurator/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "configurator" +version = "0.1.0" +edition = "2024" + +[dependencies] +clap = { version = "4.5.48", features = ["derive"] } +path-clean = "1.0.1" +serde = { version = "1.0.228", features = ["derive"] } +serde_json = "1.0.145" +toml = "0.9.8" diff --git a/tools/configurator/src/compile_commands.rs b/tools/configurator/src/compile_commands.rs new file mode 100644 index 0000000..4b79b4c --- /dev/null +++ b/tools/configurator/src/compile_commands.rs @@ -0,0 +1,101 @@ +use std::{io, path::PathBuf}; +use serde::{Serialize, Deserialize}; +use crate::config::CompilerConfig; +use path_clean::PathClean; + +#[derive(Debug, Serialize, Deserialize)] +pub struct CompileCommand<'a> { + pub arguments: Vec, + directory: &'a str, + file: String, + output: String, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(bound(deserialize = "'de: 'a"))] +pub struct CompileCommands<'a> { + pub commands: Vec>, +} + +impl<'a> CompileCommand<'a> { + pub fn new_c(config: &'a CompilerConfig, directory: &'a str, output: &PathBuf, file: &PathBuf) -> Self { + let mut arguments = Vec::new(); + arguments.push(config.executable.to_string_lossy().to_string()); + arguments.extend(config.flags.iter().map(|s| s.to_string())); + + // name: 输出目标文件名(保持相对名,例如 foo.o) + let name = file.with_extension("c.o").file_name().unwrap() + .to_string_lossy().to_string(); + + // output: 将 output 目录与 name 组合,然后把结果转换为绝对路径。 + let output_path = output.join(name); + let output = output_path.to_string_lossy().to_string(); + + // file: 将 file 转为绝对路径字符串 + let file = file.canonicalize() + .unwrap_or_else(|_| file.clean()) + .to_string_lossy().to_string(); + + arguments.push("-c".to_string()); + arguments.push(file.clone()); + arguments.push("-o".to_string()); + arguments.push(output.clone()); + + CompileCommand { + arguments, + directory, + file, + output, + } + } + + pub fn new_asm(config: &'a CompilerConfig, directory: &'a str, output: &PathBuf, file: &PathBuf) -> Self { + let mut arguments = Vec::new(); + arguments.push(config.executable.to_string_lossy().to_string()); + arguments.extend(config.flags.iter().map(|s| s.to_string())); + + // name: 输出目标文件名(保持相对名,例如 foo.o) + let name = file.with_extension("asm.o").file_name().unwrap() + .to_string_lossy().to_string(); + + // output: 将 output 目录与 name 组合,然后把结果转换为绝对路径。 + let output_path = output.join(name); + let output = output_path.to_string_lossy().to_string(); + + // file: 将 file 转为绝对路径字符串 + let file = file.canonicalize() + .unwrap_or_else(|_| file.clean()) + .to_string_lossy().to_string(); + + arguments.push(file.clone()); + arguments.push("-o".to_string()); + arguments.push(output.clone()); + + CompileCommand { + arguments, + directory, + file, + output, + } + } +} + +impl<'a> CompileCommands<'a> { + pub fn new() -> Self { + CompileCommands { commands: Vec::new() } + } + + pub fn add_command(&mut self, command: CompileCommand<'a>) { + self.commands.push(command); + } + + pub fn extend(&mut self, other: CompileCommands<'a>) { + self.commands.extend(other.commands); + } + + pub fn to_json(&self, out_file: &PathBuf) -> io::Result<()> { + let json = serde_json::to_string_pretty(&self.commands)?; + std::fs::write(out_file, json)?; + Ok(()) + } +} \ No newline at end of file diff --git a/tools/configurator/src/config.rs b/tools/configurator/src/config.rs new file mode 100644 index 0000000..aea7057 --- /dev/null +++ b/tools/configurator/src/config.rs @@ -0,0 +1,191 @@ +use std::{ + env, + error::Error, + path::{Path, PathBuf}, +}; + +use toml::Value; + +#[derive(Debug)] +pub struct CompilerConfig { + pub executable: PathBuf, + pub flags: Vec, +} + +#[derive(Debug)] +pub struct Tools { + pub cc: CompilerConfig, + pub assembler: CompilerConfig, + pub linker: CompilerConfig, +} + +#[derive(Debug)] +pub struct Config { + pub arch: String, + dir: PathBuf, + pub tools: Tools, +} + +impl Tools { + fn new( + cc_executable: PathBuf, + cc_flags: Vec, + assembler_executable: PathBuf, + assembler_flags: Vec, + linker_executable: PathBuf, + linker_flags: Vec, + ) -> Self { + Tools { + cc: CompilerConfig { + executable: cc_executable, + flags: cc_flags, + }, + assembler: CompilerConfig { + executable: assembler_executable, + flags: assembler_flags, + }, + linker: CompilerConfig { + executable: linker_executable, + flags: linker_flags, + }, + } + } +} + +/// 在工作目录下或 PATH 中查找可执行文件,返回第一个存在的绝对或相对路径 +fn find_executable(work_dir: &Path, name: &str) -> Option { + let name_path = Path::new(name); + + // 如果给定的是包含路径分隔符的相对或绝对路径,先按此解释 + if name_path.is_absolute() + || name.contains(std::path::MAIN_SEPARATOR) + || name.contains('/') + || name.contains('\\') + { + let cand = if name_path.is_absolute() { + name_path.to_path_buf() + } else { + work_dir.join(name_path) + }; + if cand.exists() && cand.is_file() { + return Some(cand); + } + return None; + } + + // 优先检查 work_dir/name + let cand = work_dir.join(name); + if cand.exists() && cand.is_file() { + return Some(cand); + } + + // 在 PATH 中查找 + if let Some(paths) = env::var_os("PATH") { + for p in env::split_paths(&paths) { + let cand = p.join(name); + if cand.exists() && cand.is_file() { + return Some(cand); + } + // On Windows, consider PATHEXT - but keep it simple for now + } + } + + None +} + +impl Config { + pub fn from(work_dir: PathBuf, config: Value) -> Result> { + let arch = config + .get("arch") + .and_then(Value::as_str) + .ok_or("Missing or invalid 'arch' field")? + .to_string(); + + let tools_table = config + .get("tools") + .and_then(Value::as_table) + .ok_or("Missing or invalid 'tools' field")?; + + let tools; + + let mut cc = String::from("gcc"); + let mut as_ = String::from("nasm"); + let mut ld = String::from("ld"); + let mut cflags = Vec::new(); + let mut asflags = Vec::new(); + let mut ldflags = Vec::new(); + for (name, tool_config) in tools_table { + match name.as_str() { + "cc" => { + cc = tool_config + .as_str() + .ok_or("Invalid 'cc' field")? + .to_string() + } + "as" => { + as_ = tool_config + .as_str() + .ok_or("Invalid 'as' field")? + .to_string() + } + "ld" => { + ld = tool_config + .as_str() + .ok_or("Invalid 'ld' field")? + .to_string() + } + "cflags" => { + cflags = tool_config + .as_array() + .ok_or("Invalid 'cflags' field")? + .iter() + .filter_map(Value::as_str) + .map(String::from) + .collect(); + continue; + } + "asflags" => { + asflags = tool_config + .as_array() + .ok_or("Invalid 'asflags' field")? + .iter() + .filter_map(Value::as_str) + .map(String::from) + .collect(); + } + "ldflags" => { + // 解析链接器标志 + ldflags = tool_config + .as_array() + .ok_or("Invalid 'ldflags' field")? + .iter() + .filter_map(Value::as_str) + .map(String::from) + .collect(); + } + _ => {} + }; + } + // 将可执行文件名解析为实际路径,优先在工作目录查找,然后在 PATH 中查找 + let cc_path = find_executable(&work_dir, &cc).ok_or(format!("C 编译器未找到: {}", cc))?; + let as_path = find_executable(&work_dir, &as_).ok_or(format!("汇编器未找到: {}", as_))?; + let ld_path = find_executable(&work_dir, &ld).ok_or(format!("链接器未找到: {}", ld))?; + + tools = Tools::new(cc_path, cflags, as_path, asflags, ld_path, ldflags); + + let debug_level = config + .get("debug") + .and_then(|x| x.get("level").and_then(Value::as_str)); + if let Some(debug_level) = debug_level { + match debug_level { + _ => {} + } + } + + Ok(Config { + arch: arch, + dir: work_dir, + tools, + }) + } +} diff --git a/tools/configurator/src/dependency.rs b/tools/configurator/src/dependency.rs new file mode 100644 index 0000000..f35300e --- /dev/null +++ b/tools/configurator/src/dependency.rs @@ -0,0 +1,128 @@ +use std::path::PathBuf; + +use std::process::Command; + +use crate::config::{CompilerConfig, Config}; +use std::fs::OpenOptions; +use std::io::Write; + +pub fn do_cc_dependency<'a>(compiler: &'a CompilerConfig, file: &PathBuf, out_dir: &PathBuf) { + let file_name = file.file_name().unwrap().to_str().unwrap(); + let out_cmd_file = out_dir.join(format!("{}.o.cmd", file_name)); + let out_file = out_dir.join(format!("{}.o", file_name)); + let mut command = Command::new(compiler.executable.as_os_str()); + command.args(&compiler.flags); + command.args(["-M", "-MF"]); + command.arg(&out_cmd_file); + command.arg("-MT"); + command.arg(&out_file); + command.arg(file); + + let status = command.status().expect("无法执行编译器以生成依赖文件"); + if !status.success() { + eprintln!("错误: 编译器生成依赖文件失败,状态码: {}", status); + std::process::exit(1); + } + + let mut cmd_file = OpenOptions::new() + .append(true) + .open(&out_cmd_file) + .expect(&format!("无法打开{}", out_cmd_file.display())); + + writeln!(cmd_file, "\t@echo CC $@").unwrap(); + writeln!( + cmd_file, + "\t@{} {} -c $< -o $@", + compiler.executable.display(), + compiler.flags.join(" ") + ) + .unwrap(); +} + +pub fn do_asm_dependency<'a>(assembler: &'a CompilerConfig, file: &PathBuf, out_dir: &PathBuf) { + let file_name = file.file_name().unwrap().to_str().unwrap(); + let out_cmd_file = out_dir.join(format!("{}.o.cmd", file_name)); + let out_file = out_dir.join(format!("{}.o", file_name)); + + let mut cmd_file = OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(&out_cmd_file) + .expect(&format!("无法打开{}", out_cmd_file.display())); + + // 禁用所有默认的后缀规则,防止 make 使用内置规则编译 + writeln!(cmd_file, ".SUFFIXES:\n").unwrap(); + + writeln!(cmd_file, "{}: {}", out_file.display(), file.display()).unwrap(); + + writeln!(cmd_file, "\t@echo AS $@").unwrap(); + writeln!( + cmd_file, + "\t@{} {} $< -o $@", + assembler.executable.display(), + assembler.flags.join(" ") + ) + .unwrap(); +} + +pub fn do_dir_dependency<'a>( + config: &Config, + out_dir: &PathBuf, + files: Vec, + dirs: &Vec, +) { + let out_cmd_file = out_dir.join("built-in.o.cmd"); + + let mut cmd_file = OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(&out_cmd_file) + .expect("无法打开目录依赖文件以追加目录"); + + writeln!(cmd_file, "# 由 {} 自动生成", env!("CARGO_PKG_NAME")).unwrap(); + + // 禁用所有默认的后缀规则,防止 make 使用内置规则编译 + writeln!(cmd_file, ".SUFFIXES:\n").unwrap(); + + write!(cmd_file, "{}: ", out_dir.join("built-in.o").display()).unwrap(); + for file in &files { + write!( + cmd_file, + " {}.o", + out_dir.join(file.file_name().unwrap()).display() + ) + .unwrap(); + } + for dir in dirs { + write!(cmd_file, " {}", dir.join("built-in.o").display()).unwrap(); + } + + write!(cmd_file, "\n").unwrap(); + writeln!(cmd_file, "\t@echo LD $@").unwrap(); + writeln!( + cmd_file, + "\t@{} {} -r $^ -o $@", + config.tools.linker.executable.display(), + config.tools.linker.flags.join(" ") + ) + .unwrap(); + for file in &files { + writeln!( + cmd_file, + "-include {}.o.cmd", + out_dir.join(file.file_name().unwrap()).display() + ) + .unwrap(); + } + + for dir in dirs { + writeln!( + cmd_file, + "-include {}", + dir.join("built-in.o.cmd").display() + ) + .unwrap(); + } +} diff --git a/tools/configurator/src/main.rs b/tools/configurator/src/main.rs new file mode 100644 index 0000000..2a6ab8a --- /dev/null +++ b/tools/configurator/src/main.rs @@ -0,0 +1,102 @@ +use std::{fs, path::PathBuf, process::Command}; +use clap::Parser; + +mod parse; +mod config; +mod compile_commands; +mod dependency; +use config::Config; +use toml::{self, Value}; + +use crate::parse::parse_config; + +/// 配置工具命令行参数 +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// 工作目录(工作目录路径) + #[arg(short = 'w', long = "work-dir", value_name = "PATH")] + work_dir: PathBuf, + + /// 输出目录(生成文件将写入此目录) + #[arg(short = 'o', long = "out-dir", value_name = "PATH")] + out_dir: PathBuf, + + #[arg(short = 'f', long = "force-update")] + force_update: bool, + + #[arg(long = "compile-commands")] + compile_commands: bool, +} + +fn main() { + let args = Args::parse(); + + if !args.out_dir.exists() || !args.out_dir.is_dir() { + if let Err(e) = std::fs::create_dir_all(&args.out_dir) { + eprintln!( + "错误: 无法创建输出目录 {}: {}", + args.out_dir.display(), + e + ); + std::process::exit(4); + } else { + println!("已创建输出目录: {}", args.out_dir.display()); + } + } + + println!("工作目录: {}", args.work_dir.canonicalize().unwrap().display()); + println!("输出目录: {}", args.out_dir.canonicalize().unwrap().display()); + + // 验证工作目录存在且为目录 + if !args.work_dir.exists() { + eprintln!("错误: 工作目录不存在: {}", args.work_dir.display()); + std::process::exit(2); + } + if !args.work_dir.is_dir() { + eprintln!("错误: 工作目录不是一个目录: {}", args.work_dir.display()); + std::process::exit(3); + } + + // 如果输出目录不存在则尝试创建 + if !args.out_dir.exists() { + if let Err(e) = std::fs::create_dir_all(&args.out_dir) { + eprintln!( + "错误: 无法创建输出目录 {}: {}", + args.out_dir.display(), + e + ); + std::process::exit(4); + } else { + println!("已创建输出目录: {}", args.out_dir.display()); + } + } else if !args.out_dir.is_dir() { + eprintln!("错误: 输出目录路径存在但不是目录: {}", args.out_dir.display()); + std::process::exit(5); + } + + let config_file = args.work_dir.join("config.toml"); + if !config_file.exists() || !config_file.is_file() { + eprintln!("错误: 配置文件不存在或不是文件: {}", config_file.display()); + std::process::exit(6); + } + let config_file = fs::read_to_string(config_file.as_path()).expect("无法读取配置文件"); + let config: Value = toml::from_str(&config_file).expect("无法解析配置文件"); + let mut config = Config::from(args.work_dir.clone(), config).expect("无法加载配置"); + + let out_dir = args.out_dir.canonicalize().unwrap(); + let work_dir = args.work_dir.canonicalize().unwrap(); + let work_dir = work_dir.join("src/"); + + let directory = work_dir.to_string_lossy().to_string(); + + let compile_commands = parse_config(&mut config, work_dir, out_dir, &directory, args.force_update); + + if args.compile_commands { + let out_file = args.work_dir.join("compile_commands.json"); + compile_commands + .to_json(&out_file) + .expect(&format!("无法写入 {}", out_file.display())); + println!("已生成 {}", out_file.display()); + } +} \ No newline at end of file diff --git a/tools/configurator/src/parse.rs b/tools/configurator/src/parse.rs new file mode 100644 index 0000000..8f7e566 --- /dev/null +++ b/tools/configurator/src/parse.rs @@ -0,0 +1,351 @@ +use crate::{ + compile_commands::{CompileCommand, CompileCommands}, + config::Config, + dependency, +}; +use serde::de; +use std::{ + fs::{self, File}, + io::Read, + path::PathBuf, + process::Command, +}; +use toml::Value; + +fn parse_string_array(config_toml: &Value, key: &str) -> Option> { + config_toml.get(key).and_then(|v| { + Some( + v.as_array()? + .iter() + .filter_map(|v| v.as_str()) + .map(String::from) + .collect::>(), + ) + }) +} + +fn parse_includes(work_dir: &PathBuf, config: &mut Config, config_toml: &Value) { + let includes = parse_string_array(config_toml, "includes"); + if let Some(includes) = includes { + config.tools.cc.flags.extend( + includes + .iter() + .map(|s| format!("-I{}{}", work_dir.display(), s)), + ); + config.tools.assembler.flags.extend( + includes + .iter() + .map(|s| format!("-I{}{}", work_dir.display(), s)), + ); + } +} + +fn parse_macros(config: &mut Config, config_toml: &Value) { + let macros = config_toml.get("macro").and_then(|v| { + Some( + v.as_table()? + .iter() + .filter_map(|(k, v)| { + let v = v.as_str()?; + Some((k, v)) + }) + .collect::>(), + ) + }); + if let Some(macros) = macros { + config + .tools + .cc + .flags + .extend(macros.iter().map(|(k, v)| format!("-D{}={}", k, v))); + config + .tools + .assembler + .flags + .extend(macros.iter().map(|(k, v)| format!("-D{}={}", k, v))); + } +} + +pub fn parse_arch_config( + config: &mut Config, + work_dir: &PathBuf, + config_toml: &Value, +) -> (Vec, String) { + let archs = config_toml.get("arch").and_then(|v| v.as_table()).unwrap(); + + let arch = archs.get(&config.arch).unwrap_or_else(|| { + eprintln!("错误: 配置文件中未找到目标架构的配置: {}", config.arch); + std::process::exit(1); + }); + + let dirs = parse_string_array(arch, "dir").unwrap_or_else(|| { + eprintln!("错误: 配置文件中目标架构缺少 'dir' 字段或格式不正确"); + std::process::exit(1); + }); + + let lds = arch.get("lds").and_then(Value::as_str).unwrap().to_string(); + + parse_includes(work_dir, config, arch); + parse_macros(config, arch); + + (dirs, lds) +} + +pub fn parse_config<'a>( + config: &'a mut Config, + work_dir: PathBuf, + out_dir: PathBuf, + directory: &'a str, + force_update: bool, +) -> CompileCommands<'a> { + let mut compile_commands = CompileCommands::new(); + let config_file_path = work_dir.join("config.toml"); + let content = fs::read_to_string(&config_file_path).expect("src: 无法读取 config.toml"); + let config_toml: Value = toml::from_str(&content).expect("src: 无法解析 config.toml"); + + let (mut dirs, lds) = parse_arch_config(config, &work_dir, &config_toml); + dirs.extend(parse_string_array(&config_toml, "dir").unwrap_or(Vec::new())); + let mut real_dirs = Vec::new(); + + let output = config_toml.get("output").and_then(|v| v.as_str()).unwrap(); + parse_includes(&work_dir, config, &config_toml); + parse_macros(config, &config_toml); + + for dir in &dirs { + let cur_work_dir = work_dir.join(&dir); + let cur_out_dir = out_dir.join(&dir); + + if !cur_out_dir.exists() || !cur_out_dir.is_dir() { + if let Err(e) = fs::create_dir_all(&cur_out_dir) { + eprintln!( + "错误: 无法创建子目录输出目录 {}: {}", + cur_out_dir.display(), + e + ); + std::process::exit(9); + } + } + + let mut force_update = force_update; + let source = cur_work_dir.join("config.toml"); + let target = cur_out_dir.join("built-in.o.cmd"); + if !source.exists() { + eprintln!( + "错误: 目录 {} 中缺少 config.toml 文件", + cur_work_dir.display() + ); + std::process::exit(7); + } + if target.exists() { + let source_meta = fs::metadata(&source).expect("无法获取源文件元数据"); + let target_meta = fs::metadata(&target).expect("无法获取目标文件元数据"); + if source_meta.modified().unwrap() > target_meta.modified().unwrap() { + force_update = true; + } + } else { + force_update = true; + } + + compile_commands.extend(parse_dir_config( + &cur_work_dir, + &cur_out_dir, + directory, + config, + force_update, + )); + + if force_update { + // 配置文件有更新,清除子目录的中间文件强制make重新生成 + let pattern = format!("{}/**/*.o", cur_out_dir.display()); + Command::new("rm") + .arg("-f") + .arg(pattern) + .status() + .expect("无法清除中间文件"); + + real_dirs.push(cur_out_dir); + } + } + + let files = Vec::new(); + dependency::do_dir_dependency(config, &out_dir, files, &real_dirs); + + let file_path = out_dir.join("Makefile"); + if !file_path.exists() { + let mut makefile = File::create(&file_path).expect("无法创建 Makefile"); + use std::io::Write; + writeln!(makefile, ".SUFFIXES:\n").unwrap(); + writeln!(makefile, ".PHONY: {}\n", output).unwrap(); + writeln!( + makefile, + "{}: {}", + output, + out_dir.join("built-in.o").display() + ) + .unwrap(); + writeln!(makefile, "\t@echo LD $@").unwrap(); + writeln!( + makefile, + "\t@{} {} -T {} -o $@ $^", + config.tools.linker.executable.display(), + config.tools.linker.flags.join(" "), + work_dir.join(lds).display() + ) + .unwrap(); + + writeln!(makefile, "-include built-in.o.cmd").unwrap(); + writeln!(makefile, "\nclean:\n\trm -r ./**/*.o").unwrap(); + } + + compile_commands +} + +pub fn parse_dir_config<'a>( + work_dir: &PathBuf, + out_dir: &PathBuf, + directory: &'a str, + config: &'a Config, + force_update: bool, +) -> CompileCommands<'a> { + let config_file_path = work_dir.join("config.toml"); + let mut config_file = File::open(&config_file_path).expect(&format!( + "错误: 目录 {} 中缺少 config.toml 文件", + work_dir.display() + )); + let mut content = String::new(); + config_file + .read_to_string(&mut content) + .expect(&format!("无法读取 {}", &config_file_path.display())); + let config_toml: Value = + toml::from_str(&content).expect(&format!("无法解析 {}", &config_file_path.display())); + let mut compile_commands = CompileCommands::new(); + + let dirs = parse_string_array(&config_toml, "dir").unwrap_or(Vec::new()); + let mut real_dirs = Vec::new(); + let mut files = Vec::new(); + + let asm_files = config_toml.get("asm").and_then(|v| { + Some( + v.as_array()? + .iter() + .filter_map(|v| v.as_str()) + .collect::>(), + ) + }); + if let Some(asm_files) = asm_files { + for asm_file in asm_files { + let asm_file_path = work_dir.join(asm_file); + if !asm_file_path.exists() || !asm_file_path.is_file() { + eprintln!( + "错误: ASM 源文件不存在或不是文件: {}", + asm_file_path.display() + ); + std::process::exit(7); + } + compile_commands.add_command(CompileCommand::new_asm( + &config.tools.assembler, + directory, + &out_dir, + &asm_file_path, + )); + + files.push(asm_file_path.clone()); + if force_update { + dependency::do_asm_dependency(&config.tools.assembler, &asm_file_path, &out_dir); + } + } + } + + let c_files = config_toml.get("c").and_then(|v| { + Some( + v.as_array()? + .iter() + .filter_map(|v| v.as_str()) + .collect::>(), + ) + }); + if let Some(c_files) = c_files { + for c_file in c_files { + let c_file_path = work_dir.join(c_file); + if !c_file_path.exists() || !c_file_path.is_file() { + eprintln!("错误: C 源文件不存在或不是文件: {}", c_file_path.display()); + std::process::exit(7); + } + compile_commands.add_command(CompileCommand::new_c( + &config.tools.cc, + directory, + &out_dir, + &c_file_path, + )); + + files.push(c_file_path.clone()); + if force_update { + dependency::do_cc_dependency(&config.tools.cc, &c_file_path, &out_dir); + } + } + } + + for dir in &dirs { + let sub_dir = work_dir.join(&dir); + if !sub_dir.exists() || !sub_dir.is_dir() { + eprintln!("错误: 子目录不存在或不是目录: {}", sub_dir.display()); + std::process::exit(8); + } + let sub_out_dir = out_dir.join(&dir); + if !sub_out_dir.exists() { + if let Err(e) = fs::create_dir_all(&sub_out_dir) { + eprintln!( + "错误: 无法创建子目录输出目录 {}: {}", + sub_out_dir.display(), + e + ); + std::process::exit(9); + } + } else if !sub_out_dir.is_dir() { + eprintln!( + "错误: 子目录输出目录路径存在但不是目录: {}", + sub_out_dir.display() + ); + std::process::exit(10); + } + + let mut force_update = force_update; + let source = sub_dir.join("config.toml"); + let target = sub_out_dir.join("built-in.o.cmd"); + if !source.exists() { + eprintln!("错误: 目录 {} 中缺少 config.toml 文件", sub_dir.display()); + std::process::exit(7); + } + if target.exists() { + let source_meta = fs::metadata(&source).expect("无法获取源文件元数据"); + let target_meta = fs::metadata(&target).expect("无法获取目标文件元数据"); + if source_meta.modified().unwrap() > target_meta.modified().unwrap() { + force_update = true; + } + } else { + force_update = true; + } + + let sub_compile_commands = + parse_dir_config(&sub_dir, &sub_out_dir, directory, config, force_update); + compile_commands.extend(sub_compile_commands); + + if force_update { + // 配置文件有更新,清除子目录的中间文件强制make重新生成 + let pattern = format!("{}/**/*.o", sub_out_dir.display()); + Command::new("rm") + .arg("-f") + .arg(pattern) + .status() + .expect("无法清除中间文件"); + + real_dirs.push(sub_out_dir); + } + } + + if !files.is_empty() || !real_dirs.is_empty() { + dependency::do_dir_dependency(config, &out_dir, files, &real_dirs); + } + + compile_commands +} From dfdc1e7725d9e69c5ca10229878ed9f5deb065dc Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Wed, 15 Oct 2025 00:45:46 +0800 Subject: [PATCH 156/158] =?UTF-8?q?script:=20configurator:=20=E7=AE=80?= =?UTF-8?q?=E5=8C=96=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/configurator/.vscode/launch.json | 2 +- tools/configurator/.vscode/settings.json | 9 + tools/configurator/Cargo.lock | 12 +- tools/configurator/src/compile_commands.rs | 4 +- tools/configurator/src/config.rs | 8 +- tools/configurator/src/dependency.rs | 23 +- tools/configurator/src/main.rs | 7 +- tools/configurator/src/parse.rs | 338 ++++++++++----------- 8 files changed, 203 insertions(+), 200 deletions(-) create mode 100644 tools/configurator/.vscode/settings.json diff --git a/tools/configurator/.vscode/launch.json b/tools/configurator/.vscode/launch.json index 502e60e..883a18f 100644 --- a/tools/configurator/.vscode/launch.json +++ b/tools/configurator/.vscode/launch.json @@ -19,7 +19,7 @@ "kind": "bin" } }, - "args": ["--work-dir", "../../", "--out-dir", "../../build/"], + "args": ["--work-dir", "../../", "--out-dir", "../../src/build/"], "cwd": "${workspaceFolder}" }, { diff --git a/tools/configurator/.vscode/settings.json b/tools/configurator/.vscode/settings.json new file mode 100644 index 0000000..9184f3f --- /dev/null +++ b/tools/configurator/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "rust-analyzer.checkOnSave": true, + "rust-analyzer.cargo.autoreload": true, + "rust-analyzer.procMacro.enable": true, + "rust-analyzer.trace.server": "verbose", + "rust-analyzer.linkedProjects": [ + "./Cargo.toml" + ] +} \ No newline at end of file diff --git a/tools/configurator/Cargo.lock b/tools/configurator/Cargo.lock index 0cac545..f3fdad8 100644 --- a/tools/configurator/Cargo.lock +++ b/tools/configurator/Cargo.lock @@ -54,9 +54,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.48" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" +checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f" dependencies = [ "clap_builder", "clap_derive", @@ -64,9 +64,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.48" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" +checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730" dependencies = [ "anstream", "anstyle", @@ -76,9 +76,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.47" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", diff --git a/tools/configurator/src/compile_commands.rs b/tools/configurator/src/compile_commands.rs index 4b79b4c..c155304 100644 --- a/tools/configurator/src/compile_commands.rs +++ b/tools/configurator/src/compile_commands.rs @@ -18,7 +18,7 @@ pub struct CompileCommands<'a> { } impl<'a> CompileCommand<'a> { - pub fn new_c(config: &'a CompilerConfig, directory: &'a str, output: &PathBuf, file: &PathBuf) -> Self { + pub fn new_c(config: &CompilerConfig, directory: &'a str, output: &PathBuf, file: &PathBuf) -> Self { let mut arguments = Vec::new(); arguments.push(config.executable.to_string_lossy().to_string()); arguments.extend(config.flags.iter().map(|s| s.to_string())); @@ -49,7 +49,7 @@ impl<'a> CompileCommand<'a> { } } - pub fn new_asm(config: &'a CompilerConfig, directory: &'a str, output: &PathBuf, file: &PathBuf) -> Self { + pub fn new_asm(config: &CompilerConfig, directory: &'a str, output: &PathBuf, file: &PathBuf) -> Self { let mut arguments = Vec::new(); arguments.push(config.executable.to_string_lossy().to_string()); arguments.extend(config.flags.iter().map(|s| s.to_string())); diff --git a/tools/configurator/src/config.rs b/tools/configurator/src/config.rs index aea7057..e26a4fb 100644 --- a/tools/configurator/src/config.rs +++ b/tools/configurator/src/config.rs @@ -6,23 +6,22 @@ use std::{ use toml::Value; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct CompilerConfig { pub executable: PathBuf, pub flags: Vec, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Tools { pub cc: CompilerConfig, pub assembler: CompilerConfig, pub linker: CompilerConfig, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Config { pub arch: String, - dir: PathBuf, pub tools: Tools, } @@ -184,7 +183,6 @@ impl Config { Ok(Config { arch: arch, - dir: work_dir, tools, }) } diff --git a/tools/configurator/src/dependency.rs b/tools/configurator/src/dependency.rs index f35300e..985642d 100644 --- a/tools/configurator/src/dependency.rs +++ b/tools/configurator/src/dependency.rs @@ -100,14 +100,21 @@ pub fn do_dir_dependency<'a>( } write!(cmd_file, "\n").unwrap(); - writeln!(cmd_file, "\t@echo LD $@").unwrap(); - writeln!( - cmd_file, - "\t@{} {} -r $^ -o $@", - config.tools.linker.executable.display(), - config.tools.linker.flags.join(" ") - ) - .unwrap(); + if files.is_empty() && dirs.is_empty() { + // 没有输入文件时,不调用链接器以避免 "no input files" 错误,改为创建一个空占位文件 + writeln!(cmd_file, "\t@echo TOUCH $@").unwrap(); + writeln!(cmd_file, "\t@mkdir -p $(dir $@) 2>/dev/null || true").unwrap(); + writeln!(cmd_file, "\t@touch $@").unwrap(); + } else { + writeln!(cmd_file, "\t@echo LD $@").unwrap(); + writeln!( + cmd_file, + "\t@{} {} -r $^ -o $@", + config.tools.linker.executable.display(), + config.tools.linker.flags.join(" ") + ) + .unwrap(); + } for file in &files { writeln!( cmd_file, diff --git a/tools/configurator/src/main.rs b/tools/configurator/src/main.rs index 2a6ab8a..6c1c453 100644 --- a/tools/configurator/src/main.rs +++ b/tools/configurator/src/main.rs @@ -1,4 +1,4 @@ -use std::{fs, path::PathBuf, process::Command}; +use std::{borrow::Cow, fs, path::PathBuf}; use clap::Parser; mod parse; @@ -82,7 +82,7 @@ fn main() { } let config_file = fs::read_to_string(config_file.as_path()).expect("无法读取配置文件"); let config: Value = toml::from_str(&config_file).expect("无法解析配置文件"); - let mut config = Config::from(args.work_dir.clone(), config).expect("无法加载配置"); + let config = Config::from(args.work_dir.clone(), config).expect("无法加载配置"); let out_dir = args.out_dir.canonicalize().unwrap(); let work_dir = args.work_dir.canonicalize().unwrap(); @@ -90,7 +90,8 @@ fn main() { let directory = work_dir.to_string_lossy().to_string(); - let compile_commands = parse_config(&mut config, work_dir, out_dir, &directory, args.force_update); + let config = Cow::Owned(config); + let compile_commands = parse_config(config, work_dir, out_dir, &directory, args.force_update); if args.compile_commands { let out_file = args.work_dir.join("compile_commands.json"); diff --git a/tools/configurator/src/parse.rs b/tools/configurator/src/parse.rs index 8f7e566..db83c1f 100644 --- a/tools/configurator/src/parse.rs +++ b/tools/configurator/src/parse.rs @@ -3,15 +3,90 @@ use crate::{ config::Config, dependency, }; -use serde::de; use std::{ + borrow::Cow, fs::{self, File}, - io::Read, - path::PathBuf, - process::Command, + io::{self, Read}, + path::PathBuf }; use toml::Value; +struct DirectoryContext<'a> { + config: Cow<'a, Config>, + work_dir: PathBuf, + out_dir: PathBuf, + force_update: bool, + toml: Option, +} + +impl<'a> DirectoryContext<'a> { + fn new(config: Cow<'a, Config>, work_dir: PathBuf, out_dir: PathBuf, force_update: bool) -> Self { + DirectoryContext { + config, + work_dir, + out_dir, + force_update, + toml: None, + } + } + + fn check_dir_update(&mut self) -> io::Result<()> { + let config_file_path = self.work_dir.join("config.toml"); + let target_file_path = self.out_dir.join("built-in.o.cmd"); + + let source_meta = match File::open(config_file_path) { + Ok(mut file) => { + self.toml = Some({ + let mut buf = String::new(); + file.read_to_string(&mut buf)?; + toml::from_str(&buf).map_err(|e| { + io::Error::new( + io::ErrorKind::InvalidData, + format!("无法解析 config.toml: {}", e), + ) + })? + }); + file.metadata()? + } + Err(e) => return Err(e), + }; + let target_meta = match fs::metadata(&target_file_path) { + Ok(metadata) => metadata, + Err(_) => { + self.force_update = true; + return Ok(()); + } + }; + if source_meta.modified()? > target_meta.modified()? { + self.force_update = true; + } + Ok(()) + } + + fn enter_subdir(&'_ self, subdir: &str) -> DirectoryContext<'_> { + let new_work_dir = self.work_dir.join(subdir); + let new_out_dir = self.out_dir.join(subdir); + + if !new_out_dir.exists() || !new_out_dir.is_dir() { + if let Err(e) = fs::create_dir_all(&new_out_dir) { + eprintln!( + "错误: 无法创建子目录输出目录 {}: {}", + new_out_dir.display(), + e + ); + std::process::exit(9); + } + } + DirectoryContext { + config: Cow::Borrowed(&self.config), + work_dir: new_work_dir, + out_dir: new_out_dir, + force_update: self.force_update, + toml: None, + } + } +} + fn parse_string_array(config_toml: &Value, key: &str) -> Option> { config_toml.get(key).and_then(|v| { Some( @@ -91,136 +166,90 @@ pub fn parse_arch_config( (dirs, lds) } -pub fn parse_config<'a>( - config: &'a mut Config, +pub fn parse_config<'a, 'b>( + config: Cow<'a, Config>, work_dir: PathBuf, out_dir: PathBuf, - directory: &'a str, + directory: &'b str, force_update: bool, -) -> CompileCommands<'a> { +) -> CompileCommands<'b> { let mut compile_commands = CompileCommands::new(); - let config_file_path = work_dir.join("config.toml"); - let content = fs::read_to_string(&config_file_path).expect("src: 无法读取 config.toml"); - let config_toml: Value = toml::from_str(&content).expect("src: 无法解析 config.toml"); - - let (mut dirs, lds) = parse_arch_config(config, &work_dir, &config_toml); - dirs.extend(parse_string_array(&config_toml, "dir").unwrap_or(Vec::new())); + let mut ctx = DirectoryContext::new(config, work_dir, out_dir, force_update); let mut real_dirs = Vec::new(); - let output = config_toml.get("output").and_then(|v| v.as_str()).unwrap(); - parse_includes(&work_dir, config, &config_toml); - parse_macros(config, &config_toml); + ctx.check_dir_update().expect("检查目录更新失败!"); + if ctx.force_update { + real_dirs.push(ctx.out_dir.clone()); + } + + let dirs = { + let config_toml = ctx.toml.as_ref().expect("未获取到config.toml!"); + let (dirs, lds, output) = { + let config = ctx.config.to_mut(); + let (mut dirs, lds) = + parse_arch_config(config, &ctx.work_dir, &config_toml); + dirs.extend(parse_string_array(&config_toml, "dir").unwrap_or(Vec::new())); + + let output = config_toml.get("output").and_then(|v| v.as_str()).unwrap(); + parse_includes(&ctx.work_dir, config, &config_toml); + parse_macros(config, &config_toml); + + (dirs, lds, output) + }; + + let file_path = ctx.out_dir.join("Makefile"); + if !file_path.exists() { + let mut makefile = File::create(&file_path).expect("无法创建 Makefile"); + use std::io::Write; + writeln!(makefile, ".SUFFIXES:\n").unwrap(); + writeln!(makefile, ".PHONY: {}\n", output).unwrap(); + writeln!( + makefile, + "{}: {}", + output, + ctx.out_dir.join("built-in.o").display() + ) + .unwrap(); + writeln!(makefile, "\t@echo LD $@").unwrap(); + writeln!( + makefile, + "\t@{} {} -T {} -o $@ $^", + ctx.config.tools.linker.executable.display(), + ctx.config.tools.linker.flags.join(" "), + ctx.work_dir.join(lds).display() + ) + .unwrap(); + + writeln!(makefile, "-include built-in.o.cmd").unwrap(); + writeln!(makefile, "\nclean:\n\trm -r ./**/*.o").unwrap(); + } + dirs + }; for dir in &dirs { - let cur_work_dir = work_dir.join(&dir); - let cur_out_dir = out_dir.join(&dir); + let mut new_ctx = ctx.enter_subdir(dir); - if !cur_out_dir.exists() || !cur_out_dir.is_dir() { - if let Err(e) = fs::create_dir_all(&cur_out_dir) { - eprintln!( - "错误: 无法创建子目录输出目录 {}: {}", - cur_out_dir.display(), - e - ); - std::process::exit(9); - } - } + new_ctx.check_dir_update().expect("检查目录更新失败!"); - let mut force_update = force_update; - let source = cur_work_dir.join("config.toml"); - let target = cur_out_dir.join("built-in.o.cmd"); - if !source.exists() { - eprintln!( - "错误: 目录 {} 中缺少 config.toml 文件", - cur_work_dir.display() - ); - std::process::exit(7); - } - if target.exists() { - let source_meta = fs::metadata(&source).expect("无法获取源文件元数据"); - let target_meta = fs::metadata(&target).expect("无法获取目标文件元数据"); - if source_meta.modified().unwrap() > target_meta.modified().unwrap() { - force_update = true; - } - } else { - force_update = true; + if new_ctx.force_update { + real_dirs.push(new_ctx.out_dir.clone()); } - compile_commands.extend(parse_dir_config( - &cur_work_dir, - &cur_out_dir, - directory, - config, - force_update, - )); - - if force_update { - // 配置文件有更新,清除子目录的中间文件强制make重新生成 - let pattern = format!("{}/**/*.o", cur_out_dir.display()); - Command::new("rm") - .arg("-f") - .arg(pattern) - .status() - .expect("无法清除中间文件"); - - real_dirs.push(cur_out_dir); - } + compile_commands.extend(parse_dir_config(new_ctx, directory)); } let files = Vec::new(); - dependency::do_dir_dependency(config, &out_dir, files, &real_dirs); - - let file_path = out_dir.join("Makefile"); - if !file_path.exists() { - let mut makefile = File::create(&file_path).expect("无法创建 Makefile"); - use std::io::Write; - writeln!(makefile, ".SUFFIXES:\n").unwrap(); - writeln!(makefile, ".PHONY: {}\n", output).unwrap(); - writeln!( - makefile, - "{}: {}", - output, - out_dir.join("built-in.o").display() - ) - .unwrap(); - writeln!(makefile, "\t@echo LD $@").unwrap(); - writeln!( - makefile, - "\t@{} {} -T {} -o $@ $^", - config.tools.linker.executable.display(), - config.tools.linker.flags.join(" "), - work_dir.join(lds).display() - ) - .unwrap(); - - writeln!(makefile, "-include built-in.o.cmd").unwrap(); - writeln!(makefile, "\nclean:\n\trm -r ./**/*.o").unwrap(); - } + dependency::do_dir_dependency(&ctx.config, &ctx.out_dir, files, &real_dirs); compile_commands } -pub fn parse_dir_config<'a>( - work_dir: &PathBuf, - out_dir: &PathBuf, - directory: &'a str, - config: &'a Config, - force_update: bool, -) -> CompileCommands<'a> { - let config_file_path = work_dir.join("config.toml"); - let mut config_file = File::open(&config_file_path).expect(&format!( - "错误: 目录 {} 中缺少 config.toml 文件", - work_dir.display() - )); - let mut content = String::new(); - config_file - .read_to_string(&mut content) - .expect(&format!("无法读取 {}", &config_file_path.display())); - let config_toml: Value = - toml::from_str(&content).expect(&format!("无法解析 {}", &config_file_path.display())); +// 因为ctx所有权传递给了这个函数,在函数结束时会被释放,所以CompileCommands需要和ctx使用不同的生命周期标记 +fn parse_dir_config<'a, 'b>(ctx: DirectoryContext<'a>, directory: &'b str) -> CompileCommands<'b> { let mut compile_commands = CompileCommands::new(); - let dirs = parse_string_array(&config_toml, "dir").unwrap_or(Vec::new()); + let config_toml = ctx.toml.as_ref().expect("未获取到config.toml!"); + let dirs = parse_string_array(config_toml, "dir").unwrap_or(Vec::new()); let mut real_dirs = Vec::new(); let mut files = Vec::new(); @@ -234,7 +263,7 @@ pub fn parse_dir_config<'a>( }); if let Some(asm_files) = asm_files { for asm_file in asm_files { - let asm_file_path = work_dir.join(asm_file); + let asm_file_path = ctx.work_dir.join(asm_file); if !asm_file_path.exists() || !asm_file_path.is_file() { eprintln!( "错误: ASM 源文件不存在或不是文件: {}", @@ -243,15 +272,19 @@ pub fn parse_dir_config<'a>( std::process::exit(7); } compile_commands.add_command(CompileCommand::new_asm( - &config.tools.assembler, + &ctx.config.tools.assembler, directory, - &out_dir, + &ctx.out_dir, &asm_file_path, )); files.push(asm_file_path.clone()); - if force_update { - dependency::do_asm_dependency(&config.tools.assembler, &asm_file_path, &out_dir); + if ctx.force_update { + dependency::do_asm_dependency( + &ctx.config.tools.assembler, + &asm_file_path, + &ctx.out_dir, + ); } } } @@ -266,85 +299,40 @@ pub fn parse_dir_config<'a>( }); if let Some(c_files) = c_files { for c_file in c_files { - let c_file_path = work_dir.join(c_file); + let c_file_path = ctx.work_dir.join(c_file); if !c_file_path.exists() || !c_file_path.is_file() { eprintln!("错误: C 源文件不存在或不是文件: {}", c_file_path.display()); std::process::exit(7); } compile_commands.add_command(CompileCommand::new_c( - &config.tools.cc, + &ctx.config.tools.cc, directory, - &out_dir, + &ctx.out_dir, &c_file_path, )); files.push(c_file_path.clone()); - if force_update { - dependency::do_cc_dependency(&config.tools.cc, &c_file_path, &out_dir); + if ctx.force_update { + dependency::do_cc_dependency(&ctx.config.tools.cc, &c_file_path, &ctx.out_dir); } } } for dir in &dirs { - let sub_dir = work_dir.join(&dir); - if !sub_dir.exists() || !sub_dir.is_dir() { - eprintln!("错误: 子目录不存在或不是目录: {}", sub_dir.display()); - std::process::exit(8); - } - let sub_out_dir = out_dir.join(&dir); - if !sub_out_dir.exists() { - if let Err(e) = fs::create_dir_all(&sub_out_dir) { - eprintln!( - "错误: 无法创建子目录输出目录 {}: {}", - sub_out_dir.display(), - e - ); - std::process::exit(9); - } - } else if !sub_out_dir.is_dir() { - eprintln!( - "错误: 子目录输出目录路径存在但不是目录: {}", - sub_out_dir.display() - ); - std::process::exit(10); - } + let mut new_ctx = ctx.enter_subdir(dir); - let mut force_update = force_update; - let source = sub_dir.join("config.toml"); - let target = sub_out_dir.join("built-in.o.cmd"); - if !source.exists() { - eprintln!("错误: 目录 {} 中缺少 config.toml 文件", sub_dir.display()); - std::process::exit(7); - } - if target.exists() { - let source_meta = fs::metadata(&source).expect("无法获取源文件元数据"); - let target_meta = fs::metadata(&target).expect("无法获取目标文件元数据"); - if source_meta.modified().unwrap() > target_meta.modified().unwrap() { - force_update = true; - } - } else { - force_update = true; + new_ctx.check_dir_update().expect("检查目录更新失败!"); + + if ctx.force_update { + real_dirs.push(new_ctx.out_dir.clone()); } - let sub_compile_commands = - parse_dir_config(&sub_dir, &sub_out_dir, directory, config, force_update); + let sub_compile_commands = parse_dir_config(new_ctx, directory); compile_commands.extend(sub_compile_commands); - - if force_update { - // 配置文件有更新,清除子目录的中间文件强制make重新生成 - let pattern = format!("{}/**/*.o", sub_out_dir.display()); - Command::new("rm") - .arg("-f") - .arg(pattern) - .status() - .expect("无法清除中间文件"); - - real_dirs.push(sub_out_dir); - } } if !files.is_empty() || !real_dirs.is_empty() { - dependency::do_dir_dependency(config, &out_dir, files, &real_dirs); + dependency::do_dir_dependency(&ctx.config, &ctx.out_dir, files, &real_dirs); } compile_commands From c5d9744261e57bda76f7000be71a069671028ce1 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Sun, 19 Oct 2025 01:27:58 +0800 Subject: [PATCH 157/158] =?UTF-8?q?script:=20configurator:=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20=E6=94=AF=E6=8C=81=E5=B0=86rust=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E4=BD=9C=E4=B8=BA=E9=9D=99=E6=80=81=E5=BA=93=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E5=88=B0=E5=86=85=E6=A0=B8;=20kernel:=20=E8=AF=95=E9=AA=8C?= =?UTF-8?q?=E6=80=A7=E5=8A=A0=E5=85=A5rust=E7=A8=8B=E5=BA=8F=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/launch.json | 2 +- config.toml | 5 + src/Cargo.template.toml | 13 ++ src/arch/x86/i686-none.json | 33 +++ src/kernel/config.toml | 3 + src/kernel/memory.c | 6 + src/kernel/memory/mod.rs | 9 + src/kernel/memory/page.rs | 66 ++++++ tools/configurator/src/config.rs | 83 ++++++- tools/configurator/src/dependency.rs | 66 +++++- tools/configurator/src/main.rs | 12 +- tools/configurator/src/parse.rs | 86 ++++++- tools/configurator/src/rustc_target.rs | 311 +++++++++++++++++++++++++ 13 files changed, 672 insertions(+), 23 deletions(-) create mode 100644 src/Cargo.template.toml create mode 100644 src/arch/x86/i686-none.json create mode 100644 src/kernel/memory/mod.rs create mode 100644 src/kernel/memory/page.rs create mode 100644 tools/configurator/src/rustc_target.rs diff --git a/.vscode/launch.json b/.vscode/launch.json index ac4d65d..fb7854e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,7 +9,7 @@ "type": "cppdbg", "request": "launch", "miDebuggerServerAddress": "127.0.0.1:1234", - "program": "${workspaceFolder}/src/kernel.elf", + "program": "${workspaceFolder}/src/build/kernel.elf", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", diff --git a/config.toml b/config.toml index 4fc9d89..e0d50a8 100644 --- a/config.toml +++ b/config.toml @@ -11,6 +11,7 @@ cflags = [ "-nostdlib", "-O0", "-m32", + "-g", "-ffreestanding", "-fno-pie", "-fno-stack-protector", @@ -21,6 +22,10 @@ cflags = [ ] asflags = ["-g", "-f", "elf32"] ldflags = ["-m", "elf_i386", "-nostdlib"] +rust_target = "src/arch/x86/i686-none.json" +rustflags = ["-C", "relocation-model=static", "--emit", "obj"] [debug] level = "all" +cflags = ["-O0", "-g"] +asflags = ["-g"] diff --git a/src/Cargo.template.toml b/src/Cargo.template.toml new file mode 100644 index 0000000..4d8852d --- /dev/null +++ b/src/Cargo.template.toml @@ -0,0 +1,13 @@ +[package] +name = "kernel" +version = "0.0.0" +edition = "2021" + +[lib] +crate-type = ["staticlib"] + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" diff --git a/src/arch/x86/i686-none.json b/src/arch/x86/i686-none.json new file mode 100644 index 0000000..1355057 --- /dev/null +++ b/src/arch/x86/i686-none.json @@ -0,0 +1,33 @@ +{ + "arch": "x86", + "code-model": "kernel", + "cpu": "i686", + "crt-objects-fallback": "false", + "data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128", + "disable-redzone": true, + "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float", + "linker": "rust-lld", + "linker-flavor": "gnu-lld", + "llvm-target": "i686-unknown-none-elf", + "max-atomic-width": 32, + "metadata": { + "description": "Freestanding/bare-metal x86 softfloat", + "host_tools": false, + "std": false, + "tier": 2 + }, + "panic-strategy": "abort", + "plt-by-default": false, + "position-independent-executables": true, + "relro-level": "full", + "rustc-abi": "x86-softfloat", + "stack-probes": { + "kind": "inline" + }, + "static-position-independent-executables": true, + "supported-sanitizers": [ + "kcfi", + "kernel-address" + ], + "target-pointer-width": 32 +} \ No newline at end of file diff --git a/src/kernel/config.toml b/src/kernel/config.toml index 9e6db61..2190e13 100644 --- a/src/kernel/config.toml +++ b/src/kernel/config.toml @@ -26,3 +26,6 @@ c = [ "thread.c", "wait_queue.c", ] +rust = [ + "memory/mod.rs", +] diff --git a/src/kernel/memory.c b/src/kernel/memory.c index 1929448..ae052d0 100644 --- a/src/kernel/memory.c +++ b/src/kernel/memory.c @@ -28,6 +28,9 @@ uint32_t memory_total_size; const int memory_block_size[MEMORY_FREE_LIST_COUNT] = {32, 64, 128, 256, 512, 1024, 2048}; +extern void new_vir(void); +extern void new_phy(void); + void init_memory(void) { uint16_t ards_nr = *((uint16_t *)ards_nr_addr); // ards 结构数 ards = (struct ards *)ards_addr; // ards 地址 @@ -70,6 +73,9 @@ void init_memory(void) { memory_manage->free_blocks[i].size = 0; // 大小是页的数量 memory_manage->free_blocks[i].flags = 0; } + + new_phy(); + new_vir(); } int get_memory_size(void) { diff --git a/src/kernel/memory/mod.rs b/src/kernel/memory/mod.rs new file mode 100644 index 0000000..657c2a3 --- /dev/null +++ b/src/kernel/memory/mod.rs @@ -0,0 +1,9 @@ +#![no_std] + +mod page; + +extern "C" { + fn kmalloc(size: u32) -> *mut core::ffi::c_void; + fn new_vir(); + fn new_phy(); +} diff --git a/src/kernel/memory/page.rs b/src/kernel/memory/page.rs new file mode 100644 index 0000000..b8ab423 --- /dev/null +++ b/src/kernel/memory/page.rs @@ -0,0 +1,66 @@ +#![no_std] + +use core::iter::Iterator; +use core::marker::Copy; +use core::option::Option; +use core::option::Option::{None, Some}; + +#[repr(C)] +pub struct MemoryBitmap { + pub bitmap: *mut u8, + pub size_in_bytes: usize, +} + +#[export_name = "virtual_memory_bitmap"] +pub static mut VIRTUAL_MEMORY_BITMAP: MemoryBitmap = MemoryBitmap { + bitmap: core::ptr::null_mut(), + size_in_bytes: 0, +}; + +#[export_name = "physical_memory_bitmap"] +pub static mut PHYSICAL_MEMORY_BITMAP: MemoryBitmap = MemoryBitmap { + bitmap: core::ptr::null_mut(), + size_in_bytes: 0, +}; + +impl MemoryBitmap { + #[no_mangle] + pub unsafe fn new_vir(addr: *mut u8, size_in_bytes: usize) { + VIRTUAL_MEMORY_BITMAP = MemoryBitmap { + bitmap: addr, + size_in_bytes, + }; + } + #[no_mangle] + pub unsafe fn new_phy(addr: *mut u8, size_in_bytes: usize) { + PHYSICAL_MEMORY_BITMAP = MemoryBitmap { + bitmap: addr, + size_in_bytes, + }; + } + + unsafe fn read(&self, index: usize) -> T { + *(self.bitmap.add(index) as *const T) + } + + unsafe fn reverse(&mut self, index: usize, bit: u8) { + *(self.bitmap.add(index) as *mut u32) ^= 1 << bit; + } + + pub fn alloc_single(&mut self) -> Option { + let mut dword; + + for i in (0..(self.size_in_bytes)).step_by(4) { + dword = unsafe { self.read::(i) }; + let bit = dword.leading_zeros(); + if bit != 32 { + dword |= 1 << (31 - bit); + unsafe { + self.reverse(i, bit as u8); + } + return Some(i * 32 + (31 - bit) as usize); + } + } + None + } +} diff --git a/tools/configurator/src/config.rs b/tools/configurator/src/config.rs index e26a4fb..c8c47aa 100644 --- a/tools/configurator/src/config.rs +++ b/tools/configurator/src/config.rs @@ -6,6 +6,8 @@ use std::{ use toml::Value; +use crate::rustc_target::RustConfig; + #[derive(Debug, Clone)] pub struct CompilerConfig { pub executable: PathBuf, @@ -17,12 +19,20 @@ pub struct Tools { pub cc: CompilerConfig, pub assembler: CompilerConfig, pub linker: CompilerConfig, + pub rustc: RustConfig, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum DebugLevel { + Release, + Debug, } #[derive(Debug, Clone)] pub struct Config { pub arch: String, pub tools: Tools, + pub debug_level: DebugLevel, } impl Tools { @@ -33,6 +43,7 @@ impl Tools { assembler_flags: Vec, linker_executable: PathBuf, linker_flags: Vec, + rust_config: RustConfig, ) -> Self { Tools { cc: CompilerConfig { @@ -47,6 +58,7 @@ impl Tools { executable: linker_executable, flags: linker_flags, }, + rustc: rust_config, } } } @@ -113,6 +125,8 @@ impl Config { let mut cflags = Vec::new(); let mut asflags = Vec::new(); let mut ldflags = Vec::new(); + let mut rust_flags = Vec::new(); + let mut rust_target = String::new(); for (name, tool_config) in tools_table { match name.as_str() { "cc" => { @@ -162,6 +176,22 @@ impl Config { .map(String::from) .collect(); } + "rust_flags" => { + // 解析 Rust 编译器标志 + rust_flags = tool_config + .as_array() + .ok_or("Invalid 'rust_flags' field")? + .iter() + .filter_map(Value::as_str) + .map(String::from) + .collect(); + } + "rust_target" => { + rust_target = tool_config + .as_str() + .ok_or("Invalid 'rust_target' field")? + .to_string(); + } _ => {} }; } @@ -170,20 +200,63 @@ impl Config { let as_path = find_executable(&work_dir, &as_).ok_or(format!("汇编器未找到: {}", as_))?; let ld_path = find_executable(&work_dir, &ld).ok_or(format!("链接器未找到: {}", ld))?; - tools = Tools::new(cc_path, cflags, as_path, asflags, ld_path, ldflags); + let rust_config = RustConfig::new(rust_target, rust_flags, &work_dir); - let debug_level = config + let debug_table = config .get("debug") - .and_then(|x| x.get("level").and_then(Value::as_str)); - if let Some(debug_level) = debug_level { + .and_then(Value::as_table) + .ok_or("Missing or invalid 'debug' field")?; + let debug_level = debug_table + .get("level") + .and_then(Value::as_str); + let debug_level = if let Some(debug_level) = debug_level { match debug_level { - _ => {} + "release" => DebugLevel::Release, + "debug" => DebugLevel::Debug, + _ => DebugLevel::Debug, + } + } else { + DebugLevel::Debug + }; + + if debug_level != DebugLevel::Release { + for (name, value) in debug_table { + match name.as_str() { + "cflags" => { + cflags.extend(value + .as_array() + .ok_or("Invalid 'cflags' field")? + .iter() + .filter_map(Value::as_str) + .map(String::from)); + } + "asflags" => { + asflags.extend(value + .as_array() + .ok_or("Invalid 'asflags' field")? + .iter() + .filter_map(Value::as_str) + .map(String::from)); + } + "ldflags" => { + ldflags.extend(value + .as_array() + .ok_or("Invalid 'ldflags' field")? + .iter() + .filter_map(Value::as_str) + .map(String::from)); + } + _ => {} + } } } + tools = Tools::new(cc_path, cflags, as_path, asflags, ld_path, ldflags, rust_config); + Ok(Config { arch: arch, tools, + debug_level }) } } diff --git a/tools/configurator/src/dependency.rs b/tools/configurator/src/dependency.rs index 985642d..76f2a29 100644 --- a/tools/configurator/src/dependency.rs +++ b/tools/configurator/src/dependency.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use std::process::Command; use crate::config::{CompilerConfig, Config}; +use crate::rustc_target::{RustConfig, RustcTargetType}; use std::fs::OpenOptions; use std::io::Write; @@ -66,10 +67,52 @@ pub fn do_asm_dependency<'a>(assembler: &'a CompilerConfig, file: &PathBuf, out_ .unwrap(); } +pub fn do_rust_dependency<'a>( + rustc: &'a RustConfig, + file: &PathBuf, + out_dir: &PathBuf, + target_name: &str, + is_release: bool, +) { + let out_cmd_file = out_dir.join("rlib.a.cmd"); + let out_file = out_dir.join("rlib.a"); + + let mut cmd_file = OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(&out_cmd_file) + .expect(&format!("无法打开{}", out_cmd_file.display())); + + // 禁用所有默认的后缀规则,防止 make 使用内置规则编译 + writeln!(cmd_file, ".SUFFIXES:\n").unwrap(); + + writeln!(cmd_file, "{}: {}", out_file.display(), file.display()).unwrap(); + + writeln!(cmd_file, "\t@echo RUSTC $@").unwrap(); + writeln!( + cmd_file, + "\t@rustup run {}", + match rustc.target_type { + RustcTargetType::Builtin => { "cargo rustc" }, + RustcTargetType::Custom => { "nightly cargo rustc" }, + }, + ) + .unwrap(); + + writeln!(cmd_file, "\t@echo COPY $@").unwrap(); + if is_release { + writeln!(cmd_file, "\t@cp ./rustc_target/{}/release/lib*.a $@", target_name).unwrap(); + } else { + writeln!(cmd_file, "\t@cp ./rustc_target/{}/debug/lib*.a $@", target_name).unwrap(); + } +} + pub fn do_dir_dependency<'a>( config: &Config, out_dir: &PathBuf, files: Vec, + libs: Vec, dirs: &Vec, ) { let out_cmd_file = out_dir.join("built-in.o.cmd"); @@ -90,13 +133,21 @@ pub fn do_dir_dependency<'a>( for file in &files { write!( cmd_file, - " {}.o", + "\\\n {}.o", out_dir.join(file.file_name().unwrap()).display() ) .unwrap(); } + for lib in &libs { + write!( + cmd_file, + "\\\n {}", + out_dir.join(lib.file_name().unwrap()).display() + ) + .unwrap(); + } for dir in dirs { - write!(cmd_file, " {}", dir.join("built-in.o").display()).unwrap(); + write!(cmd_file, "\\\n {}", dir.join("built-in.o").display()).unwrap(); } write!(cmd_file, "\n").unwrap(); @@ -109,7 +160,7 @@ pub fn do_dir_dependency<'a>( writeln!(cmd_file, "\t@echo LD $@").unwrap(); writeln!( cmd_file, - "\t@{} {} -r $^ -o $@", + "\t@{} {} --whole-archive -r $^ -o $@", config.tools.linker.executable.display(), config.tools.linker.flags.join(" ") ) @@ -123,7 +174,14 @@ pub fn do_dir_dependency<'a>( ) .unwrap(); } - + for lib in &libs { + writeln!( + cmd_file, + "-include {}.cmd", + out_dir.join(lib.file_name().unwrap()).display() + ) + .unwrap(); + } for dir in dirs { writeln!( cmd_file, diff --git a/tools/configurator/src/main.rs b/tools/configurator/src/main.rs index 6c1c453..755dbee 100644 --- a/tools/configurator/src/main.rs +++ b/tools/configurator/src/main.rs @@ -5,6 +5,7 @@ mod parse; mod config; mod compile_commands; mod dependency; +mod rustc_target; use config::Config; use toml::{self, Value}; @@ -80,6 +81,7 @@ fn main() { eprintln!("错误: 配置文件不存在或不是文件: {}", config_file.display()); std::process::exit(6); } + let config_metadata = fs::metadata(config_file.as_path()).expect("无法获取metadata"); let config_file = fs::read_to_string(config_file.as_path()).expect("无法读取配置文件"); let config: Value = toml::from_str(&config_file).expect("无法解析配置文件"); let config = Config::from(args.work_dir.clone(), config).expect("无法加载配置"); @@ -90,8 +92,16 @@ fn main() { let directory = work_dir.to_string_lossy().to_string(); + let mut force_update = args.force_update; + let target_metadata = fs::metadata(out_dir.as_path().join("built-in.o.cmd")); + if let Ok(target_metadata) = target_metadata { + if config_metadata.modified().unwrap() > target_metadata.modified().unwrap() { + force_update = true; + } + } + let config = Cow::Owned(config); - let compile_commands = parse_config(config, work_dir, out_dir, &directory, args.force_update); + let compile_commands = parse_config(config, work_dir, out_dir, &directory, force_update); if args.compile_commands { let out_file = args.work_dir.join("compile_commands.json"); diff --git a/tools/configurator/src/parse.rs b/tools/configurator/src/parse.rs index db83c1f..23166d1 100644 --- a/tools/configurator/src/parse.rs +++ b/tools/configurator/src/parse.rs @@ -7,7 +7,7 @@ use std::{ borrow::Cow, fs::{self, File}, io::{self, Read}, - path::PathBuf + path::PathBuf, }; use toml::Value; @@ -20,7 +20,12 @@ struct DirectoryContext<'a> { } impl<'a> DirectoryContext<'a> { - fn new(config: Cow<'a, Config>, work_dir: PathBuf, out_dir: PathBuf, force_update: bool) -> Self { + fn new( + config: Cow<'a, Config>, + work_dir: PathBuf, + out_dir: PathBuf, + force_update: bool, + ) -> Self { DirectoryContext { config, work_dir, @@ -179,15 +184,19 @@ pub fn parse_config<'a, 'b>( ctx.check_dir_update().expect("检查目录更新失败!"); if ctx.force_update { - real_dirs.push(ctx.out_dir.clone()); + ctx.config.tools.rustc.set_force_update(true); + } + + let cargo_toml = ctx.work_dir.join("Cargo.template.toml"); + if cargo_toml.exists() && cargo_toml.is_file() { + ctx.config.to_mut().tools.rustc.use_cargo_toml(cargo_toml, &ctx.work_dir, &ctx.out_dir); } let dirs = { let config_toml = ctx.toml.as_ref().expect("未获取到config.toml!"); let (dirs, lds, output) = { let config = ctx.config.to_mut(); - let (mut dirs, lds) = - parse_arch_config(config, &ctx.work_dir, &config_toml); + let (mut dirs, lds) = parse_arch_config(config, &ctx.work_dir, &config_toml); dirs.extend(parse_string_array(&config_toml, "dir").unwrap_or(Vec::new())); let output = config_toml.get("output").and_then(|v| v.as_str()).unwrap(); @@ -198,7 +207,7 @@ pub fn parse_config<'a, 'b>( }; let file_path = ctx.out_dir.join("Makefile"); - if !file_path.exists() { + if !file_path.exists() || force_update { let mut makefile = File::create(&file_path).expect("无法创建 Makefile"); use std::io::Write; writeln!(makefile, ".SUFFIXES:\n").unwrap(); @@ -213,7 +222,7 @@ pub fn parse_config<'a, 'b>( writeln!(makefile, "\t@echo LD $@").unwrap(); writeln!( makefile, - "\t@{} {} -T {} -o $@ $^", + "\t@{} {} -T {} --gc-sections -o $@ $^", ctx.config.tools.linker.executable.display(), ctx.config.tools.linker.flags.join(" "), ctx.work_dir.join(lds).display() @@ -221,7 +230,7 @@ pub fn parse_config<'a, 'b>( .unwrap(); writeln!(makefile, "-include built-in.o.cmd").unwrap(); - writeln!(makefile, "\nclean:\n\trm -r ./**/*.o").unwrap(); + writeln!(makefile, "\nclean:\n\t@echo RM *.o\n\t@find . -type f \\( -name '*.o' -o -name '*.a' \\) -print -delete").unwrap(); } dirs }; @@ -239,13 +248,25 @@ pub fn parse_config<'a, 'b>( } let files = Vec::new(); - dependency::do_dir_dependency(&ctx.config, &ctx.out_dir, files, &real_dirs); + let mut libs = Vec::new(); + if let Some(file) = + ctx.config + .tools + .rustc + .write_configs(&ctx.work_dir, &ctx.out_dir, ctx.config.debug_level) + { + libs.push(file); + } + + if ctx.force_update{ + dependency::do_dir_dependency(&ctx.config, &ctx.out_dir, files, libs, &real_dirs); + } compile_commands } // 因为ctx所有权传递给了这个函数,在函数结束时会被释放,所以CompileCommands需要和ctx使用不同的生命周期标记 -fn parse_dir_config<'a, 'b>(ctx: DirectoryContext<'a>, directory: &'b str) -> CompileCommands<'b> { +fn parse_dir_config<'a, 'b>(mut ctx: DirectoryContext<'a>, directory: &'b str) -> CompileCommands<'b> { let mut compile_commands = CompileCommands::new(); let config_toml = ctx.toml.as_ref().expect("未获取到config.toml!"); @@ -318,6 +339,37 @@ fn parse_dir_config<'a, 'b>(ctx: DirectoryContext<'a>, directory: &'b str) -> Co } } + let cargo_toml = ctx.work_dir.join("Cargo.template.toml"); + if cargo_toml.exists() && cargo_toml.is_file() { + ctx.config.to_mut().tools.rustc.use_cargo_toml(cargo_toml, &ctx.work_dir, &ctx.out_dir); + } + + let rust_files = config_toml.get("rust").and_then(|v| { + Some( + v.as_array()? + .iter() + .filter_map(|v| v.as_str()) + .collect::>(), + ) + }); + if let Some(ref rust_files) = rust_files { + for rust_file in rust_files { + let rust_file_path = ctx.work_dir.join(rust_file); + if !rust_file_path.exists() || !rust_file_path.is_file() { + eprintln!( + "错误: Rust 源文件不存在或不是文件: {}", + rust_file_path.display() + ); + std::process::exit(7); + } + + ctx.config.tools.rustc.add_file(&rust_file_path); + if ctx.force_update { + ctx.config.tools.rustc.set_force_update(true); + } + } + } + for dir in &dirs { let mut new_ctx = ctx.enter_subdir(dir); @@ -331,8 +383,18 @@ fn parse_dir_config<'a, 'b>(ctx: DirectoryContext<'a>, directory: &'b str) -> Co compile_commands.extend(sub_compile_commands); } - if !files.is_empty() || !real_dirs.is_empty() { - dependency::do_dir_dependency(&ctx.config, &ctx.out_dir, files, &real_dirs); + let mut libs = Vec::new(); + if let Some(file) = + ctx.config + .tools + .rustc + .write_configs(&ctx.work_dir, &ctx.out_dir, ctx.config.debug_level) + { + libs.push(file); + } + + if ctx.force_update && (!files.is_empty() || !real_dirs.is_empty()) { + dependency::do_dir_dependency(&ctx.config, &ctx.out_dir, files, libs, &real_dirs); } compile_commands diff --git a/tools/configurator/src/rustc_target.rs b/tools/configurator/src/rustc_target.rs new file mode 100644 index 0000000..57a50ce --- /dev/null +++ b/tools/configurator/src/rustc_target.rs @@ -0,0 +1,311 @@ +use std::cell::RefCell; +use std::collections::HashMap; +use std::fs::{self, File}; +use std::io::Write; +use std::path::PathBuf; +use std::sync::Arc; + +use crate::config::DebugLevel; +use crate::dependency; + +#[derive(Debug, Clone, Copy)] +pub enum RustcTargetType { + Builtin, + Custom, +} + +#[derive(Debug, Clone)] +pub struct RustConfig { + pub target: String, + pub target_type: RustcTargetType, + pub cargo_toml: RefCell>, + rust_flags: Vec, + modules: Arc>, + force_update: Arc>, +} + +#[derive(Debug, Clone, Copy)] +enum ModuleType { + Exist, // 存在 mod.rs 的目录 + NotExist, +} + +#[derive(Debug)] +struct ModuleNode { + module_type: ModuleType, + children: HashMap, +} + +impl ModuleNode { + fn new(module_type: ModuleType) -> Self { + ModuleNode { + module_type, + children: HashMap::new(), + } + } + + fn add_child(&mut self, name: &str, module_type: ModuleType) -> &mut ModuleNode { + let entry = self.children.entry(name.to_string()); + entry.or_insert_with(|| ModuleNode::new(module_type)) + } +} + +#[derive(Debug)] +pub struct RustModules { + root: ModuleNode, +} + +impl RustModules { + pub fn new() -> Self { + RustModules { + root: ModuleNode::new(ModuleType::Exist), + } + } + + pub fn add_path(&mut self, cargo_toml: &PathBuf, path: &PathBuf) { + if !cargo_toml.exists() || !cargo_toml.is_file() { + panic!("Cargo.template.toml不存在!"); + } + let path = path.strip_prefix( + cargo_toml.parent().unwrap()).expect("路径不在Cargo.template.toml目录下"); + let components = path.components().map(|v| v.as_os_str().to_string_lossy().to_string()); + + let mut entry = &mut self.root; + let mut path = cargo_toml.parent().unwrap().to_path_buf(); + for component in components { + let tmp_path = path.join(&component); + let mod_rs = tmp_path.join("mod.rs"); + let module_type = if mod_rs.exists() { + ModuleType::Exist + } else { + ModuleType::NotExist + }; + entry = entry.add_child(&component, module_type); + path = tmp_path; + if let ModuleType::Exist = module_type { + break; + } + } + } +} + +impl RustConfig { + pub fn new(target: String, rust_flags: Vec, work_dir: &PathBuf) -> Self { + if target.ends_with(".json") { + let work_dir = work_dir.canonicalize().unwrap(); + let target = work_dir.join(target).to_string_lossy().to_string(); + RustConfig { + target, + target_type: RustcTargetType::Custom, + rust_flags, + modules: Arc::new(RefCell::new(RustModules::new())), + force_update: Arc::new(RefCell::new(false)), + cargo_toml: RefCell::new(None), + } + } else { + RustConfig { + target, + target_type: RustcTargetType::Builtin, + rust_flags, + modules: Arc::new(RefCell::new(RustModules::new())), + force_update: Arc::new(RefCell::new(false)), + cargo_toml: RefCell::new(None), + } + } + } + + pub fn use_cargo_toml(&mut self, cargo_toml: PathBuf, work_dir: &PathBuf, out_dir: &PathBuf) { + self.write_cargo_configs(&cargo_toml, work_dir, out_dir); + if self.cargo_toml.borrow().is_some() { + self.cargo_toml = RefCell::new(Some(cargo_toml)); + } else { + self.cargo_toml.borrow_mut().replace(cargo_toml); + } + } + + fn write_module_declaration( + &self, + file: &mut File, + node: &ModuleNode, + indent_level: usize, + ) -> std::io::Result<()> { + let indent = " ".repeat(indent_level); + + for (name, node) in node.children.iter().clone() { + match node.module_type { + ModuleType::NotExist => { + writeln!(file, "{}pub mod {} {{", indent, name)?; + self.write_module_declaration(file, node, indent_level + 1)?; + writeln!(file, "{}}}", indent)?; + } + ModuleType::Exist => { + writeln!(file, "{}pub mod {};", indent, name)?; + } + } + } + Ok(()) + } + + fn write_root_file(&self, work_dir: &PathBuf) -> std::io::Result<()> { + let root_file_path = work_dir.canonicalize()?.join("lib.rs"); + let mut file = std::fs::File::create(&root_file_path)?; + + writeln!(file, "// Auto-generated root file for this crate")?; + writeln!(file, "// Target: {}", self.target)?; + writeln!(file, "#![no_std]")?; + writeln!(file, "#![no_main]")?; + writeln!(file, "\nuse core::panic::PanicInfo;\n")?; + writeln!(file, "\n#[panic_handler]")?; + writeln!(file, "fn panic(_info: &PanicInfo) -> ! {{")?; + writeln!(file, " loop {{}}")?; + writeln!(file, "}}\n")?; + + let modules = self.modules.borrow(); + self.write_module_declaration(&mut file, &modules.root, 0)?; + + Ok(()) + } + + fn write_cargo_config(&self, out_dir: &PathBuf) -> std::io::Result<()> { + let cargo_config_path = out_dir.join(".cargo"); + if !cargo_config_path.exists() { + fs::create_dir_all(&cargo_config_path)?; + } + let config_toml_path = cargo_config_path.canonicalize()?.join("config.toml"); + let mut file = fs::File::create(&config_toml_path)?; + + writeln!(file, "# Auto-generated Cargo config file")?; + writeln!(file, "[build]")?; + writeln!(file, "target = \"{}\"", self.target)?; + writeln!( + file, + "target-dir = \"{}\"", + out_dir.join("rustc_target/").display() + )?; + write!(file, "rustflags = [")?; + for flag in self.rust_flags.iter() { + write!(file, "\"{}\",", flag)?; + } + writeln!(file, "]")?; + + if let RustcTargetType::Custom = self.target_type { + writeln!(file, "\n[unstable]")?; + writeln!(file, "build-std = [\"core\", \"compiler_builtins\"]")?; + } + + Ok(()) + } + + fn write_cargo_toml(&self, cargo_toml: &PathBuf, work_dir: &PathBuf, out_dir: &PathBuf) -> std::io::Result<()> { + let cargo_toml_path = out_dir.join("Cargo.template.toml"); + let cargo_toml = fs::read_to_string(cargo_toml)?; + + let mut lines: Vec = cargo_toml.lines().map(|s| s.to_string()).collect(); + + let mut lib_index: Option = None; + for (i, line) in lines.iter().enumerate() { + if line.trim_start().starts_with("[lib]") { + lib_index = Some(i); + break; + } + } + + if let Some(idx) = lib_index { + // 找到下一个以 '[' 开头的 section 行位置(如果没有则使用文件末尾) + let mut next_idx = lines.len(); + for (j, line) in lines.iter().enumerate().skip(idx + 1) { + if line.trim_start().starts_with('[') { + next_idx = j; + break; + } + } + + // 在 [lib] 和下一个 section 之间检查是否已有 path 字段 + for line in &lines[idx + 1..next_idx] { + if let Some(eq_pos) = line.find('=') { + let key = line[..eq_pos].trim(); + if key == "path" { + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + "Cargo.template.toml 中 [lib] 已包含 path 字段", + )); + } + } else if line.trim_start().starts_with("path") { + // 保守检查,处理没有等号的异常格式 + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + "Cargo.template.toml 中 [lib] 已包含 path 字段", + )); + } + } + + // 在该 section 的末尾插入 path 字段(即在 next_idx 处插入) + lines.insert(next_idx, format!("path = \"{}\"", work_dir.join("lib.rs").display())); + } else { + // 如果没有 [lib] 节,则追加一个新的 [lib] 节并写入 path + if !cargo_toml.ends_with('\n') { + lines.push(String::new()); + } + lines.push("[lib]".to_string()); + lines.push("path = \"./lib.rs\"".to_string()); + } + + let new_contents = lines.join("\n"); + let cargo_toml_path = out_dir.join("Cargo.toml"); + fs::write(cargo_toml_path, new_contents)?; + + Ok(()) + } + + pub fn add_file(&self, file_path: &PathBuf) { + let mut modules = self.modules.borrow_mut(); + match self.cargo_toml.borrow().as_ref() { + Some(cargo_toml) => {modules.add_path(cargo_toml, file_path);}, + None => {panic!("使用了rust文件但没有定义Cargo.template.toml!");}, + } + } + + pub fn set_force_update(&self, value: bool) { + let mut force_update = self.force_update.borrow_mut(); + *force_update = value; + } + + fn need_update(&self) -> bool { + *self.force_update.borrow() + } + + fn is_empty(&self) -> bool { + let modules = self.modules.borrow(); + modules.root.children.is_empty() + } + + fn write_cargo_configs(&self, cargo_toml: &PathBuf, work_dir: &PathBuf, out_dir: &PathBuf) { + if self.need_update() { + self.write_cargo_toml(cargo_toml, work_dir, out_dir) + .expect("写入Cargo.template.toml失败"); + self.write_cargo_config(out_dir) + .expect("写入cargo config失败"); + } + } + + pub fn write_configs(&self, work_dir: &PathBuf, out_dir: &PathBuf, debug_level: DebugLevel) -> Option { + let cargo_toml = work_dir.join("Cargo.template.toml"); + if cargo_toml.exists() && cargo_toml.is_file() { + if self.need_update() { + self.write_root_file(work_dir) + .expect("写入lib.rs失败"); + + let target_name = self.target.split(".").next().unwrap().rsplit('/').next().unwrap(); + dependency::do_rust_dependency( + &self, + &work_dir.join("lib.rs"), + &out_dir, + &target_name, + debug_level == DebugLevel::Release, + ); + return Some(out_dir.join("rlib.a")); + } + } + None + } +} From b86124d101bd9b0642e61cbd56faa3a913666bc7 Mon Sep 17 00:00:00 2001 From: Ryan1202 Date: Tue, 13 Jan 2026 22:33:06 +0800 Subject: [PATCH 158/158] update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6fa8ef0..b0cdc76 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ fixdep *.idx dump.pcap target/ +.stfolder/