From 916cc9cbca0a5977831ee75b756009463973fd84 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 11 Jun 2025 00:00:00 +0000 Subject: [PATCH 01/79] Hack for getting the .img working, not using dtb in favor of hardcoded values --- kernel/hw/elfvirt.h | 3 +++ kernel/hw/hw.h | 3 +++ kernel/linker.ld | 2 +- kernel/memory/kalloc.c | 18 +++++++++++++++--- kernel/memory/mmu.c | 5 +++++ run | 2 +- 6 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 kernel/hw/elfvirt.h create mode 100644 kernel/hw/hw.h diff --git a/kernel/hw/elfvirt.h b/kernel/hw/elfvirt.h new file mode 100644 index 00000000..0c3fe9f2 --- /dev/null +++ b/kernel/hw/elfvirt.h @@ -0,0 +1,3 @@ +#pragma once + +#define USE_DTB \ No newline at end of file diff --git a/kernel/hw/hw.h b/kernel/hw/hw.h new file mode 100644 index 00000000..7eae3f72 --- /dev/null +++ b/kernel/hw/hw.h @@ -0,0 +1,3 @@ +#pragma once + +// #include "elfvirt.h" \ No newline at end of file diff --git a/kernel/linker.ld b/kernel/linker.ld index db674661..78f5fce2 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -1,7 +1,7 @@ ENTRY(_start) SECTIONS { - . = 0x41000000; + . = 0x40080000; kernel_start = .; .boot . : { boot.o(.text) } .text : { diff --git a/kernel/memory/kalloc.c b/kernel/memory/kalloc.c index 164ea766..7f470506 100644 --- a/kernel/memory/kalloc.c +++ b/kernel/memory/kalloc.c @@ -2,7 +2,10 @@ #include "types.h" #include "exceptions/exception_handler.h" #include "console/kio.h" +#include "hw/hw.h" +#ifdef USE_DTB #include "dtb.h" +#endif #include "console/serial/uart.h" #include "memory/memory_access.h" #include "std/string.h" @@ -118,6 +121,8 @@ uint64_t mem_get_kmem_end(){ return (uint64_t)&kcode_end; } +#ifdef USE_DTB + int handle_mem_node(const char *propname, const void *prop, uint32_t len, dtb_match_t *match) { if (strcmp(propname, "reg") == 0 && len >= 16) { uint32_t *p = (uint32_t *)prop; @@ -141,17 +146,24 @@ int get_memory_region(uint64_t *out_base, uint64_t *out_size) { } return 0; } +#endif void calc_ram(){ +#ifdef USE_DTB if (get_memory_region(&total_ram_start, &total_ram_size)) { calculated_ram_end = total_ram_start + total_ram_size; calculated_ram_start = ((uint64_t)&kfull_end) + 0x1; calculated_ram_start = ((calculated_ram_start) & ~((1ULL << 21) - 1)); calculated_ram_end = ((calculated_ram_end) & ~((1ULL << 21) - 1)); - - calculated_ram_size = calculated_ram_end - calculated_ram_start; - kprintf("Device has %x memory starting at %x. %x for user starting at %x ",total_ram_size, total_ram_start, calculated_ram_size, calculated_ram_start); } +#else + total_ram_start = 0x40000000; + total_ram_size = 0x20000000; + calculated_ram_end = 0x60000000; + calculated_ram_start = 0x43600000; +#endif + calculated_ram_size = calculated_ram_end - calculated_ram_start; + kprintf("Device has %x memory starting at %x. %x for user starting at %x ending at %x ",total_ram_size, total_ram_start, calculated_ram_size, calculated_ram_start, calculated_ram_end); } #define calcvar(var)\ diff --git a/kernel/memory/mmu.c b/kernel/memory/mmu.c index 99d15bf7..b68a8d6e 100644 --- a/kernel/memory/mmu.c +++ b/kernel/memory/mmu.c @@ -3,7 +3,10 @@ #include "memory/kalloc.h" #include "console/kio.h" #include "exceptions/irq.h" +#include "hw/hw.h" +#ifdef USE_DTB #include "dtb.h" +#endif #include "pci.h" #include "filesystem/disk.h" #include "memory/page_allocator.h" @@ -189,11 +192,13 @@ void mmu_init() { for (uint64_t addr = get_shared_start(); addr <= get_shared_end(); addr += GRANULE_4KB) mmu_map_4kb(addr, addr, MAIR_IDX_NORMAL, 2); +#ifdef USE_DTB uint64_t dstart; uint64_t dsize; dtb_addresses(&dstart,&dsize); for (uint64_t addr = dstart; addr <= dstart + dsize; addr += GRANULE_4KB) mmu_map_4kb(addr, addr, MAIR_IDX_NORMAL, 1); +#endif uint64_t mair = (MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE * 8)) | (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL * 8)); asm volatile ("msr mair_el1, %0" :: "r"(mair)); diff --git a/run b/run index c1c67916..90723f09 100755 --- a/run +++ b/run @@ -11,7 +11,7 @@ qemu-system-aarch64 \ -M virt \ -cpu cortex-a72 \ -m 512M \ --kernel kernel.elf \ +-kernel kernel.img \ -device virtio-gpu-pci \ -display sdl \ -serial mon:stdio \ From e44bfb3c85b1ba8d833d3e0f72032a1072612d97 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 23 Jun 2025 00:00:00 +0000 Subject: [PATCH 02/79] Half ported UART for rpi --- kernel/boot.S | 27 ++++++++++++++++++--------- kernel/console/serial/uart.h | 2 +- kernel/linker.ld | 12 ++++++++++-- run | 11 +---------- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/kernel/boot.S b/kernel/boot.S index ae1e7d65..582b3f83 100644 --- a/kernel/boot.S +++ b/kernel/boot.S @@ -1,11 +1,20 @@ .global _start +.org 0x80000 _start: - ldr x1, =stack_top - mov sp, x1 - mov x29, xzr - mov x30, xzr - mrs x0, CPACR_EL1 - orr x0, x0, #(3 << 20) - msr CPACR_EL1, x0 - bl kernel_main - b . \ No newline at end of file + ldr x5, =stack_top + mov sp, x5 + + // clear bss + ldr x5, =__bss_start + ldr w6, =__bss_size +1: cbz w6, 2f + str xzr, [x5], #8 + sub w6, w6, #1 + cbnz w6, 1b + + // jump to C code, should not return +2: bl kernel_main + // for failsafe, halt this core +halt: + wfe + b halt \ No newline at end of file diff --git a/kernel/console/serial/uart.h b/kernel/console/serial/uart.h index 9bb386d3..07acd8df 100644 --- a/kernel/console/serial/uart.h +++ b/kernel/console/serial/uart.h @@ -6,7 +6,7 @@ extern "C" { #include "types.h" -#define UART0_BASE 0x09000000 +#define UART0_BASE 0xFE201000 uint64_t get_uart_base(); void enable_uart(); diff --git a/kernel/linker.ld b/kernel/linker.ld index db674661..28e6f300 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -1,14 +1,22 @@ ENTRY(_start) SECTIONS { - . = 0x41000000; + . = 0x80000; kernel_start = .; .boot . : { boot.o(.text) } .text : { *(EXCLUDE_FILE(shared/*.o) .text .text.[!p]*) } .data : { *(.data) } - .bss : { *(.bss COMMON) } + __bss_start = .; + .bss : + { + bss = .; + *(.bss) + } + . = ALIGN(4096); /* align to page size */ + __bss_end = .; + __bss_size = __bss_end - __bss_start; .vectors : { KEEP(*(.vectors)) } . = ALIGN(16); diff --git a/run b/run index 8a380ef2..f662dbd0 100755 --- a/run +++ b/run @@ -16,17 +16,8 @@ if echo "$XHCI_CAPABILITIES" | grep -q "msi "; then fi qemu-system-aarch64 \ --M virt \ --cpu cortex-a72 \ --m 512M \ +-M raspi4b \ -kernel kernel.elf \ --device virtio-gpu-pci \ --display sdl \ --device virtio-net-pci \ -serial mon:stdio \ --drive file=disk.img,if=none,format=raw,id=hd0 \ --device virtio-blk-pci,drive=hd0 \ --device qemu-xhci,${MSI_CAPABILITIES}id=usb \ --device usb-kbd,bus=usb.0 \ -d guest_errors \ $ARGS From afc3d89bf724b2093817a683c8465498273ccfbc Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 03/79] Halt other cores --- kernel/boot.S | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/kernel/boot.S b/kernel/boot.S index 582b3f83..5e2746d1 100644 --- a/kernel/boot.S +++ b/kernel/boot.S @@ -1,19 +1,27 @@ .global _start .org 0x80000 _start: + //Halt other cores + mrs x0, mpidr_el1 + and x0, x0, #3 + cbz x0, 1f + 0: wfe + b 0b + 1: + ldr x5, =stack_top mov sp, x5 // clear bss ldr x5, =__bss_start ldr w6, =__bss_size -1: cbz w6, 2f +2: cbz w6, 3f str xzr, [x5], #8 sub w6, w6, #1 - cbnz w6, 1b + cbnz w6, 2b // jump to C code, should not return -2: bl kernel_main +3: bl kernel_main // for failsafe, halt this core halt: wfe From 25ba8b2490f787809fa024ee8acf6965e86411c1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 04/79] Basic RPI header without DTB --- kernel/hw/hw.h | 3 ++- kernel/hw/rpi.h | 6 ++++++ kernel/memory/kalloc.c | 5 +++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 kernel/hw/rpi.h diff --git a/kernel/hw/hw.h b/kernel/hw/hw.h index 7eae3f72..df6b7df8 100644 --- a/kernel/hw/hw.h +++ b/kernel/hw/hw.h @@ -1,3 +1,4 @@ #pragma once -// #include "elfvirt.h" \ No newline at end of file +// #include "elfvirt.h" +#include "rpi.h" \ No newline at end of file diff --git a/kernel/hw/rpi.h b/kernel/hw/rpi.h new file mode 100644 index 00000000..28ff3aaa --- /dev/null +++ b/kernel/hw/rpi.h @@ -0,0 +1,6 @@ +#pragma once + +#define RAM_START 0x40000000 +#define RAM_SIZE 0x20000000 +#define CRAM_END 0x60000000 +#define CRAM_START 0x43600000 \ No newline at end of file diff --git a/kernel/memory/kalloc.c b/kernel/memory/kalloc.c index 7f470506..19ff8968 100644 --- a/kernel/memory/kalloc.c +++ b/kernel/memory/kalloc.c @@ -156,6 +156,11 @@ void calc_ram(){ calculated_ram_start = ((calculated_ram_start) & ~((1ULL << 21) - 1)); calculated_ram_end = ((calculated_ram_end) & ~((1ULL << 21) - 1)); } +#elif defined (RAM_ADDRESSES) + total_ram_start = RAM_START; + total_ram_size = RAM_SIZE; + calculated_ram_end = CRAM_END; + calculated_ram_start = CRAM_START; #else total_ram_start = 0x40000000; total_ram_size = 0x20000000; From d2126cb5a3db68293ad9bcfac5903d17b8f9fc1e Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 05/79] Drop EL3 to EL1, disable PCI --- kernel/boot.S | 72 +++++++++++++++++++++++++++++++++++++------------ kernel/hw/hw.h | 2 ++ kernel/hw/rpi.h | 4 ++- kernel/kernel.c | 3 +++ kernel/pci.c | 5 ++++ 5 files changed, 68 insertions(+), 18 deletions(-) diff --git a/kernel/boot.S b/kernel/boot.S index 5e2746d1..f1cd530b 100644 --- a/kernel/boot.S +++ b/kernel/boot.S @@ -1,28 +1,66 @@ .global _start +.section .text .org 0x80000 _start: - //Halt other cores mrs x0, mpidr_el1 and x0, x0, #3 - cbz x0, 1f - 0: wfe - b 0b - 1: + cbz x0, drop_el3 +half: + wfe + b half + +drop_el3: + + msr sctlr_el2, xzr + mrs x0, hcr_el2 + orr x0, x0, #(1<<19) + msr hcr_el2, x0 + + mrs x0, scr_el3 + orr x0, x0, #(1<<10) + orr x0, x0, #(1<<0) + msr scr_el3, x0 + + mov x0, #0b01001//DAIF 0000 + msr spsr_el3, x0 + + adr x0, el2_entry + msr elr_el3, x0 + eret + +el2_entry: + + mov x0, #3 << 20 + msr cpacr_el1, x0 - ldr x5, =stack_top - mov sp, x5 + ldr x0, =0x30C00800 + msr sctlr_el1, x0 - // clear bss + mrs x0, hcr_el2 + orr x0, x0, #(1<<31) + msr hcr_el2, x0 + + mov x0, 0x1C5 + msr spsr_el2, x0 + + adr x0, el1_non_secure + msr elr_el2, x0 + + eret + +el1_non_secure: ldr x5, =__bss_start - ldr w6, =__bss_size -2: cbz w6, 3f + ldr x6, =__bss_end +clear_bss: + cmp x5, x6 + b.ge stack_setup str xzr, [x5], #8 - sub w6, w6, #1 - cbnz w6, 2b + b clear_bss + +stack_setup: + ldr x0, =stack_top + mov sp, x0 + + bl kernel_main - // jump to C code, should not return -3: bl kernel_main - // for failsafe, halt this core -halt: - wfe b halt \ No newline at end of file diff --git a/kernel/hw/hw.h b/kernel/hw/hw.h index df6b7df8..182d2665 100644 --- a/kernel/hw/hw.h +++ b/kernel/hw/hw.h @@ -1,4 +1,6 @@ #pragma once +#define USE_PCI + // #include "elfvirt.h" #include "rpi.h" \ No newline at end of file diff --git a/kernel/hw/rpi.h b/kernel/hw/rpi.h index 28ff3aaa..fbd7d2e9 100644 --- a/kernel/hw/rpi.h +++ b/kernel/hw/rpi.h @@ -3,4 +3,6 @@ #define RAM_START 0x40000000 #define RAM_SIZE 0x20000000 #define CRAM_END 0x60000000 -#define CRAM_START 0x43600000 \ No newline at end of file +#define CRAM_START 0x43600000 + +#undef USE_PCI \ No newline at end of file diff --git a/kernel/kernel.c b/kernel/kernel.c index 10a8b8dd..be9a86cc 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -42,6 +42,9 @@ void kernel_main() { kprintf("Interrupts initialized"); enable_interrupt(); + + kprintf("Initializing GPU"); + gpu_init(screen_size); kprintf("GPU initialized"); diff --git a/kernel/pci.c b/kernel/pci.c index 7fede964..850f628a 100644 --- a/kernel/pci.c +++ b/kernel/pci.c @@ -7,6 +7,7 @@ #include "exceptions/irq.h" #include "memory/mmu.h" #include "memory/memory_access.h" +#include "hw/hw.h" #define PCI_BUS_MAX 256 #define PCI_SLOT_MAX 32 @@ -203,6 +204,10 @@ uint64_t pci_setup_bar(uint64_t pci_addr, uint32_t bar_index, uint64_t *mmio_sta uint64_t find_pci_device(uint32_t vendor_id, uint32_t device_id) { +#ifndef USE_PCI + return 0; +#endif + if (NINIT) find_pci(); From 04656c606977c252bc5a8bf56ccff70f553ae780 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 06/79] Starting to set up xhci alternatives --- kernel/console/serial/uart.h | 7 ++++++- kernel/hw/rpi.h | 5 ++++- kernel/input/xhci.c | 7 +++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/kernel/console/serial/uart.h b/kernel/console/serial/uart.h index 07acd8df..97ea6e7a 100644 --- a/kernel/console/serial/uart.h +++ b/kernel/console/serial/uart.h @@ -5,8 +5,13 @@ extern "C" { #endif #include "types.h" +#include "hw/hw.h" -#define UART0_BASE 0xFE201000 +#ifdef UART_RPI_BASE +#define UART_BASE UART_RPI_BASE +#else +#define UART0_BASE 0x9000000 +#endif uint64_t get_uart_base(); void enable_uart(); diff --git a/kernel/hw/rpi.h b/kernel/hw/rpi.h index fbd7d2e9..cc36ccf7 100644 --- a/kernel/hw/rpi.h +++ b/kernel/hw/rpi.h @@ -5,4 +5,7 @@ #define CRAM_END 0x60000000 #define CRAM_START 0x43600000 -#undef USE_PCI \ No newline at end of file +#undef USE_PCI + +#define XHCI_BASE 0xFE9C0000 +#define UART_RPI_BASE 0xFE201000 \ No newline at end of file diff --git a/kernel/input/xhci.c b/kernel/input/xhci.c index e98bfa4f..75d41e46 100644 --- a/kernel/input/xhci.c +++ b/kernel/input/xhci.c @@ -8,6 +8,7 @@ #include "xhci_bridge.h" #include "std/string.h" #include "std/memfunctions.h" +#include "hw/hw.h" static xhci_device global_device; @@ -113,6 +114,7 @@ uint8_t xhci_init_interrupts(uint64_t pci_addr){ bool xhci_init(xhci_device *xhci, uint64_t pci_addr) { kprintfv("[xHCI] init"); +#ifdef USE_PCI if (!(read16(pci_addr + 0x06) & (1 << 4))){ kprintfv("[xHCI] Wrong capabilities list"); return false; @@ -141,6 +143,7 @@ bool xhci_init(xhci_device *xhci, uint64_t pci_addr) { pci_enable_device(pci_addr); kprintfv("[xHCI] BARs set up @ %x (%x)",xhci->mmio,xhci->mmio_size); +#endif xhci->cap = (xhci_cap_regs*)(uintptr_t)xhci->mmio; kprintfv("[xHCI] caplength %x",xhci->cap->caplength); @@ -692,7 +695,11 @@ bool xhci_setup_device(uint16_t port){ } bool xhci_input_init() { + #ifdef XHCI_BASE + uint64_t addr = XHCI_BASE; + #else uint64_t addr = find_pci_device(0x1B36, 0xD); + #endif if (!addr){ kprintf_raw("[PCI] xHCI device not found"); return false; From 806fab54fe9bbd32dd34afcd50c29aed461ee8c3 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 07/79] UART base fix --- kernel/console/serial/uart.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/console/serial/uart.h b/kernel/console/serial/uart.h index 97ea6e7a..788dab70 100644 --- a/kernel/console/serial/uart.h +++ b/kernel/console/serial/uart.h @@ -8,7 +8,7 @@ extern "C" { #include "hw/hw.h" #ifdef UART_RPI_BASE -#define UART_BASE UART_RPI_BASE +#define UART0_BASE UART_RPI_BASE #else #define UART0_BASE 0x9000000 #endif From 993dd2775672ef7610d8db81c2672d71416dfcf6 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 08/79] Hardware detection (limited to rpi only. If we wanna support non-rpi devices such as the old virtio board, we want the old boot.S back --- kernel/console/serial/uart.h | 6 ------ kernel/hw/elfvirt.h | 3 --- kernel/hw/hw.c | 32 ++++++++++++++++++++++++++++++++ kernel/hw/hw.h | 17 ++++++++++++++--- kernel/hw/rpi.h | 11 ----------- kernel/input/xhci.c | 11 ++++++----- kernel/kernel.c | 3 +++ kernel/memory/kalloc.c | 34 ++++++++++++---------------------- kernel/memory/mmu.c | 16 +++++++--------- 9 files changed, 74 insertions(+), 59 deletions(-) delete mode 100644 kernel/hw/elfvirt.h create mode 100644 kernel/hw/hw.c delete mode 100644 kernel/hw/rpi.h diff --git a/kernel/console/serial/uart.h b/kernel/console/serial/uart.h index 788dab70..cb01c8e1 100644 --- a/kernel/console/serial/uart.h +++ b/kernel/console/serial/uart.h @@ -7,12 +7,6 @@ extern "C" { #include "types.h" #include "hw/hw.h" -#ifdef UART_RPI_BASE -#define UART0_BASE UART_RPI_BASE -#else -#define UART0_BASE 0x9000000 -#endif - uint64_t get_uart_base(); void enable_uart(); void uart_puts(const char *s); diff --git a/kernel/hw/elfvirt.h b/kernel/hw/elfvirt.h deleted file mode 100644 index 0c3fe9f2..00000000 --- a/kernel/hw/elfvirt.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#define USE_DTB \ No newline at end of file diff --git a/kernel/hw/hw.c b/kernel/hw/hw.c new file mode 100644 index 00000000..0ec00c23 --- /dev/null +++ b/kernel/hw/hw.c @@ -0,0 +1,32 @@ +#include "hw.h" + +uint8_t USE_DTB = 0; +uint8_t USE_PCI = 0; +uintptr_t RAM_START = 0; +uintptr_t RAM_SIZE = 0; +uintptr_t CRAM_START = 0; +uintptr_t CRAM_END = 0; +uintptr_t UART0_BASE = 0; +uintptr_t XHCI_BASE = 0; + +void detect_hardware(){ + uint32_t reg; + asm volatile ("mrs %x0, midr_el1" : "=r" (reg)); + //We can detect if we're running on 0x400.... to know if we're in virt. And 41 vs 40 to know if we're in img or elf + uint32_t raspi = (reg >> 4) & 0xFFF; + switch (raspi) { + case 0xC07: + case 0xD03: UART0_BASE = 0x3F201000; break; + case 0xD08: UART0_BASE = 0xFE201000; break;; + default: UART0_BASE = 0x20201000; break; + } + //Virt: UART0_BASE = 0x9000000 + + RAM_START = 0x40000000; + RAM_SIZE = 0x20000000; + CRAM_END = 0x60000000; + CRAM_START = 0x43600000; + XHCI_BASE = 0xFE9C0000; + USE_PCI = 0; + USE_DTB = 0; +} \ No newline at end of file diff --git a/kernel/hw/hw.h b/kernel/hw/hw.h index 182d2665..c7c1ef00 100644 --- a/kernel/hw/hw.h +++ b/kernel/hw/hw.h @@ -1,6 +1,17 @@ #pragma once -#define USE_PCI - // #include "elfvirt.h" -#include "rpi.h" \ No newline at end of file +#include "types.h" + +extern uint8_t USE_DTB; +extern uint8_t USE_PCI; + +extern uintptr_t RAM_START; +extern uintptr_t RAM_SIZE; +extern uintptr_t CRAM_START; +extern uintptr_t CRAM_END; + +extern uintptr_t UART0_BASE; +extern uintptr_t XHCI_BASE; + +void detect_hardware(); \ No newline at end of file diff --git a/kernel/hw/rpi.h b/kernel/hw/rpi.h deleted file mode 100644 index cc36ccf7..00000000 --- a/kernel/hw/rpi.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#define RAM_START 0x40000000 -#define RAM_SIZE 0x20000000 -#define CRAM_END 0x60000000 -#define CRAM_START 0x43600000 - -#undef USE_PCI - -#define XHCI_BASE 0xFE9C0000 -#define UART_RPI_BASE 0xFE201000 \ No newline at end of file diff --git a/kernel/input/xhci.c b/kernel/input/xhci.c index 526d7a42..5b39af5c 100644 --- a/kernel/input/xhci.c +++ b/kernel/input/xhci.c @@ -677,11 +677,12 @@ bool xhci_setup_device(uint16_t port){ } bool xhci_input_init() { - #ifdef XHCI_BASE - uint64_t addr = XHCI_BASE; - #else - uint64_t addr = find_pci_device(0x1B36, 0xD); - #endif + uint64_t addr; + if (XHCI_BASE){ + addr = XHCI_BASE; + } else if (USE_PCI) { + addr = find_pci_device(0x1B36, 0xD); + } if (!addr){ kprintf_raw("[PCI] xHCI device not found"); return false; diff --git a/kernel/kernel.c b/kernel/kernel.c index bf2f7203..a1df3abe 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,6 +1,7 @@ #include "console/kio.h" #include "console/serial/uart.h" #include "graph/graphics.h" +#include "hw/hw.h" #include "pci.h" #include "kstring.h" #include "console/kconsole/kconsole.h" @@ -19,6 +20,8 @@ #include "networking/network.h" void kernel_main() { + + detect_hardware(); mmu_alloc(); // mmu_enable_verbose(); diff --git a/kernel/memory/kalloc.c b/kernel/memory/kalloc.c index c1cab01f..fd392e63 100644 --- a/kernel/memory/kalloc.c +++ b/kernel/memory/kalloc.c @@ -3,9 +3,7 @@ #include "exceptions/exception_handler.h" #include "console/kio.h" #include "hw/hw.h" -#ifdef USE_DTB #include "dtb.h" -#endif #include "console/serial/uart.h" #include "memory/memory_access.h" #include "std/string.h" @@ -124,8 +122,6 @@ uint64_t mem_get_kmem_end(){ return (uint64_t)&kcode_end; } -#ifdef USE_DTB - int handle_mem_node(const char *propname, const void *prop, uint32_t len, dtb_match_t *match) { if (strcmp(propname, "reg") == 0 && len >= 16) { uint32_t *p = (uint32_t *)prop; @@ -149,27 +145,21 @@ int get_memory_region(uint64_t *out_base, uint64_t *out_size) { } return 0; } -#endif void calc_ram(){ -#ifdef USE_DTB - if (get_memory_region(&total_ram_start, &total_ram_size)) { - calculated_ram_end = total_ram_start + total_ram_size; - calculated_ram_start = ((uint64_t)&kfull_end) + 0x1; - calculated_ram_start = ((calculated_ram_start) & ~((1ULL << 21) - 1)); - calculated_ram_end = ((calculated_ram_end) & ~((1ULL << 21) - 1)); + if (USE_DTB){ + if (get_memory_region(&total_ram_start, &total_ram_size)) { + calculated_ram_end = total_ram_start + total_ram_size; + calculated_ram_start = ((uint64_t)&kfull_end) + 0x1; + calculated_ram_start = ((calculated_ram_start) & ~((1ULL << 21) - 1)); + calculated_ram_end = ((calculated_ram_end) & ~((1ULL << 21) - 1)); + } + } else { + total_ram_start = RAM_START; + total_ram_size = RAM_SIZE; + calculated_ram_end = CRAM_END; + calculated_ram_start = CRAM_START; } -#elif defined (RAM_ADDRESSES) - total_ram_start = RAM_START; - total_ram_size = RAM_SIZE; - calculated_ram_end = CRAM_END; - calculated_ram_start = CRAM_START; -#else - total_ram_start = 0x40000000; - total_ram_size = 0x20000000; - calculated_ram_end = 0x60000000; - calculated_ram_start = 0x43600000; -#endif calculated_ram_size = calculated_ram_end - calculated_ram_start; kprintf("Device has %x memory starting at %x. %x for user starting at %x ending at %x ",total_ram_size, total_ram_start, calculated_ram_size, calculated_ram_start, calculated_ram_end); } diff --git a/kernel/memory/mmu.c b/kernel/memory/mmu.c index 0ec69eed..041a7ede 100644 --- a/kernel/memory/mmu.c +++ b/kernel/memory/mmu.c @@ -4,9 +4,7 @@ #include "console/kio.h" #include "exceptions/irq.h" #include "hw/hw.h" -#ifdef USE_DTB #include "dtb.h" -#endif #include "pci.h" #include "filesystem/disk.h" #include "memory/page_allocator.h" @@ -191,13 +189,13 @@ void mmu_init() { for (uint64_t addr = get_shared_start(); addr <= get_shared_end(); addr += GRANULE_4KB) mmu_map_4kb(addr, addr, MAIR_IDX_NORMAL, 2); -#ifdef USE_DTB - uint64_t dstart; - uint64_t dsize; - dtb_addresses(&dstart,&dsize); - for (uint64_t addr = dstart; addr <= dstart + dsize; addr += GRANULE_4KB) - mmu_map_4kb(addr, addr, MAIR_IDX_NORMAL, 1); -#endif + if (USE_DTB){ + uint64_t dstart; + uint64_t dsize; + dtb_addresses(&dstart,&dsize); + for (uint64_t addr = dstart; addr <= dstart + dsize; addr += GRANULE_4KB) + mmu_map_4kb(addr, addr, MAIR_IDX_NORMAL, 1); + } uint64_t mair = (MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE * 8)) | (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL * 8)); asm volatile ("msr mair_el1, %0" :: "r"(mair)); From 55529759e338bb813489aab89a9173aa50cbe326 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 09/79] Run both rpi and virtio --- Makefile | 22 +++++++++++++---- kernel/Makefile | 3 ++- kernel/boot.S | 54 +++++++++++++++++++++++++++++++++++------- kernel/hw/hw.c | 32 +++++++++++++++---------- kernel/hw/hw.h | 5 +++- kernel/kernel.c | 2 ++ kernel/linker.ld | 2 +- kernel/memory/kalloc.c | 4 +--- kernel/memory/mmu.c | 7 +++--- kernel/pci.c | 3 +-- run_rpi | 17 +++++++++++++ run => run_virtio | 14 ++++++++--- rundebug => rundebug_r | 2 +- rundebug_v | 10 ++++++++ 14 files changed, 136 insertions(+), 41 deletions(-) create mode 100755 run_rpi rename run => run_virtio (60%) rename rundebug => rundebug_r (73%) create mode 100755 rundebug_v diff --git a/Makefile b/Makefile index 5e688684..7a0ee00c 100644 --- a/Makefile +++ b/Makefile @@ -11,15 +11,27 @@ user: $(MAKE) -C user kernel: - $(MAKE) -C kernel + $(MAKE) -C kernel LOAD_ADDR=$(LOAD_ADDR) clean: $(MAKE) -C shared clean $(MAKE) -C kernel clean $(MAKE) -C user clean -run: all - ./run +rpi: + $(MAKE) LOAD_ADDR=0x80000 all -debug: all - ./rundebug \ No newline at end of file +virtio: + $(MAKE) LOAD_ADDR=0x41000000 all + +debugrpi: + $(MAKE) rpi + ./rundebug_r + +debugvirtio: + $(MAKE) virtio + ./rundebug_v + +run: + $(MAKE) rpi + ./run_rpi \ No newline at end of file diff --git a/kernel/Makefile b/kernel/Makefile index 5471cb91..0530334a 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -4,7 +4,8 @@ LD = $(ARCH)-ld OBJCOPY = $(ARCH)-objcopy CFLAGS = -g -O0 -nostdlib -ffreestanding -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -Wall -Wextra -mcpu=cortex-a72 -I. -I../shared -I../user -LDFLAGS = -T $(shell ls *.ld) + +LDFLAGS = -T $(shell ls *.ld) --defsym=LOAD_ADDR=$(LOAD_ADDR) C_SRC = $(shell find . -name '*.c') ASM_SRC = $(shell find . -name '*.S') diff --git a/kernel/boot.S b/kernel/boot.S index f1cd530b..4da69d4b 100644 --- a/kernel/boot.S +++ b/kernel/boot.S @@ -1,16 +1,50 @@ .global _start .section .text -.org 0x80000 _start: mrs x0, mpidr_el1 and x0, x0, #3 - cbz x0, drop_el3 + cbz x0, check_hw half: wfe b half -drop_el3: +check_hw: + adr x0, . + + movz x1, #0x4100, lsl #16 + and x2, x0, #0xFFF00000 + cmp x2, x1 + b.eq virt + + movz x1, #0x4000, lsl #16 + and x2, x0, #0xFFF00000 + cmp x2, x1 + b.eq virt + + mov x1, #0x80000 + and x2, x0, #0xFFFFF000 + cmp x2, x1 + b.eq rpi + + mov x1, #0x100000 + and x2, x0, #0xFFFFF000 + cmp x2, x1 + b.eq rpi + + b .//Halt if none + +virt: + mov w0, #1 + adrp x1, BOARD_TYPE + strb w0, [x1, #:lo12:BOARD_TYPE] + b stack_setup +rpi: + mov w0, #2 + adrp x1, BOARD_TYPE + strb w0, [x1, #:lo12:BOARD_TYPE] + b drop_el3 +drop_el3: msr sctlr_el2, xzr mrs x0, hcr_el2 orr x0, x0, #(1<<19) @@ -29,7 +63,6 @@ drop_el3: eret el2_entry: - mov x0, #3 << 20 msr cpacr_el1, x0 @@ -58,9 +91,14 @@ clear_bss: b clear_bss stack_setup: - ldr x0, =stack_top - mov sp, x0 - + ldr x1, =stack_top + mov sp, x1 + + mov x29, xzr + mov x30, xzr + mrs x1, CPACR_EL1 + orr x1, x1, #(3 << 20) + msr CPACR_EL1, x1 bl kernel_main - b halt \ No newline at end of file + b . \ No newline at end of file diff --git a/kernel/hw/hw.c b/kernel/hw/hw.c index 0ec00c23..50021a77 100644 --- a/kernel/hw/hw.c +++ b/kernel/hw/hw.c @@ -1,5 +1,7 @@ #include "hw.h" +#include "console/kio.h" +uint8_t BOARD_TYPE; uint8_t USE_DTB = 0; uint8_t USE_PCI = 0; uintptr_t RAM_START = 0; @@ -10,23 +12,29 @@ uintptr_t UART0_BASE = 0; uintptr_t XHCI_BASE = 0; void detect_hardware(){ - uint32_t reg; - asm volatile ("mrs %x0, midr_el1" : "=r" (reg)); - //We can detect if we're running on 0x400.... to know if we're in virt. And 41 vs 40 to know if we're in img or elf - uint32_t raspi = (reg >> 4) & 0xFFF; - switch (raspi) { - case 0xC07: - case 0xD03: UART0_BASE = 0x3F201000; break; - case 0xD08: UART0_BASE = 0xFE201000; break;; - default: UART0_BASE = 0x20201000; break; + if (BOARD_TYPE == 1){ + UART0_BASE = 0x9000000; + } else { + uint32_t reg; + asm volatile ("mrs %x0, midr_el1" : "=r" (reg)); + //We can detect if we're running on 0x400.... to know if we're in virt. And 41 vs 40 to know if we're in img or elf + uint32_t raspi = (reg >> 4) & 0xFFF; + switch (raspi) { + case 0xC07: + case 0xD03: UART0_BASE = 0x3F201000; break; + case 0xD08: UART0_BASE = 0xFE201000; break;; + default: UART0_BASE = 0x20201000; break; + } } - //Virt: UART0_BASE = 0x9000000 RAM_START = 0x40000000; RAM_SIZE = 0x20000000; CRAM_END = 0x60000000; CRAM_START = 0x43600000; XHCI_BASE = 0xFE9C0000; - USE_PCI = 0; - USE_DTB = 0; + USE_PCI = BOARD_TYPE == 1; +} + +void print_hardware(){ + kprintf("Board type %i",BOARD_TYPE); } \ No newline at end of file diff --git a/kernel/hw/hw.h b/kernel/hw/hw.h index c7c1ef00..cceebb11 100644 --- a/kernel/hw/hw.h +++ b/kernel/hw/hw.h @@ -3,6 +3,8 @@ // #include "elfvirt.h" #include "types.h" +extern uint8_t BOARD_TYPE; + extern uint8_t USE_DTB; extern uint8_t USE_PCI; @@ -14,4 +16,5 @@ extern uintptr_t CRAM_END; extern uintptr_t UART0_BASE; extern uintptr_t XHCI_BASE; -void detect_hardware(); \ No newline at end of file +void detect_hardware(); +void print_hardware(); \ No newline at end of file diff --git a/kernel/kernel.c b/kernel/kernel.c index a1df3abe..4632d658 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -32,6 +32,8 @@ void kernel_main() { set_exception_vectors(); kprintf("Exception vectors set"); + print_hardware(); + page_allocator_init(); // page_alloc_enable_verbose(); kprintf("Initializing kernel..."); diff --git a/kernel/linker.ld b/kernel/linker.ld index 28e6f300..543b8d78 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -1,7 +1,7 @@ ENTRY(_start) SECTIONS { - . = 0x80000; + . = LOAD_ADDR; kernel_start = .; .boot . : { boot.o(.text) } .text : { diff --git a/kernel/memory/kalloc.c b/kernel/memory/kalloc.c index fd392e63..ce2b37cb 100644 --- a/kernel/memory/kalloc.c +++ b/kernel/memory/kalloc.c @@ -147,13 +147,11 @@ int get_memory_region(uint64_t *out_base, uint64_t *out_size) { } void calc_ram(){ - if (USE_DTB){ - if (get_memory_region(&total_ram_start, &total_ram_size)) { + if (get_memory_region(&total_ram_start, &total_ram_size)) { calculated_ram_end = total_ram_start + total_ram_size; calculated_ram_start = ((uint64_t)&kfull_end) + 0x1; calculated_ram_start = ((calculated_ram_start) & ~((1ULL << 21) - 1)); calculated_ram_end = ((calculated_ram_end) & ~((1ULL << 21) - 1)); - } } else { total_ram_start = RAM_START; total_ram_size = RAM_SIZE; diff --git a/kernel/memory/mmu.c b/kernel/memory/mmu.c index 041a7ede..f8b0db8e 100644 --- a/kernel/memory/mmu.c +++ b/kernel/memory/mmu.c @@ -189,10 +189,9 @@ void mmu_init() { for (uint64_t addr = get_shared_start(); addr <= get_shared_end(); addr += GRANULE_4KB) mmu_map_4kb(addr, addr, MAIR_IDX_NORMAL, 2); - if (USE_DTB){ - uint64_t dstart; - uint64_t dsize; - dtb_addresses(&dstart,&dsize); + uint64_t dstart; + uint64_t dsize; + if (dtb_addresses(&dstart,&dsize)){ for (uint64_t addr = dstart; addr <= dstart + dsize; addr += GRANULE_4KB) mmu_map_4kb(addr, addr, MAIR_IDX_NORMAL, 1); } diff --git a/kernel/pci.c b/kernel/pci.c index 249b01b9..b2e0ba19 100644 --- a/kernel/pci.c +++ b/kernel/pci.c @@ -214,9 +214,8 @@ uint64_t pci_setup_bar(uint64_t pci_addr, uint32_t bar_index, uint64_t *mmio_sta uint64_t find_pci_device(uint32_t vendor_id, uint32_t device_id) { -#ifndef USE_PCI + if (!USE_PCI) return 0; -#endif if (NINIT) find_pci(); diff --git a/run_rpi b/run_rpi new file mode 100755 index 00000000..f7b95ad7 --- /dev/null +++ b/run_rpi @@ -0,0 +1,17 @@ +#/!bin/sh + +echo "Running raspi emulator" + +ARGS="" +if [ "$1" = "debug" ]; then + ARGS="-monitor unix:/tmp/qemu-monitor-socket,server,nowait -s -S" +fi + +qemu-system-aarch64 \ +-M raspi4b \ +-kernel kernel.elf \ +-display sdl \ +-netdev vmnet-bridged,id=net0,ifname=en0 \ +-serial mon:stdio \ +-d guest_errors \ +$ARGS diff --git a/run b/run_virtio similarity index 60% rename from run rename to run_virtio index 3c7de014..65803e2e 100755 --- a/run +++ b/run_virtio @@ -1,6 +1,6 @@ #/!bin/sh -echo "Running emulator" +echo "Running virtio emulator" ARGS="" if [ "$1" = "debug" ]; then @@ -16,10 +16,18 @@ if echo "$XHCI_CAPABILITIES" | grep -q "msi "; then fi qemu-system-aarch64 \ --M raspi4b \ +-M virt \ +-cpu cortex-a72 \ +-m 512M \ -kernel kernel.elf \ +-device virtio-gpu-pci \ -display sdl \ -netdev vmnet-bridged,id=net0,ifname=en0 \ +-device virtio-net-pci,netdev=net0 \ -serial mon:stdio \ +-drive file=disk.img,if=none,format=raw,id=hd0 \ +-device virtio-blk-pci,drive=hd0 \ +-device qemu-xhci,${MSI_CAPABILITIES}id=usb \ +-device usb-kbd,bus=usb.0 \ -d guest_errors \ -$ARGS +$ARGS \ No newline at end of file diff --git a/rundebug b/rundebug_r similarity index 73% rename from rundebug rename to rundebug_r index 1b4a8888..c4b910e6 100755 --- a/rundebug +++ b/rundebug_r @@ -4,7 +4,7 @@ ARGS="$@" osascript < Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 10/79] Cleaner syntax for run and debug --- Makefile | 22 ++++++++++------------ rundebug | 18 ++++++++++++++++++ rundebug_r | 10 ---------- rundebug_v | 10 ---------- 4 files changed, 28 insertions(+), 32 deletions(-) create mode 100755 rundebug delete mode 100755 rundebug_r delete mode 100755 rundebug_v diff --git a/Makefile b/Makefile index 7a0ee00c..dbb8a070 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ -.PHONY: all kernel user shared clean +MODE ?= rpi + +.PHONY: all kernel user shared clean rpi virtio debugrpi debugvirtio run debug all: shared user kernel @echo "Build complete." @@ -18,20 +20,16 @@ clean: $(MAKE) -C kernel clean $(MAKE) -C user clean -rpi: +rpi: $(MAKE) LOAD_ADDR=0x80000 all -virtio: +virtio: $(MAKE) LOAD_ADDR=0x41000000 all -debugrpi: - $(MAKE) rpi - ./rundebug_r - -debugvirtio: - $(MAKE) virtio - ./rundebug_v +debug: + $(MAKE) $(MODE) + ./rundebug MODE=$(MODE) $(ARGS) run: - $(MAKE) rpi - ./run_rpi \ No newline at end of file + $(MAKE) $(MODE) + ./run_$(MODE) \ No newline at end of file diff --git a/rundebug b/rundebug new file mode 100755 index 00000000..c06603f9 --- /dev/null +++ b/rundebug @@ -0,0 +1,18 @@ +#!/bin/bash + +MODE="rpi" +ARGS=() + +for arg in "$@"; do + case $arg in + MODE=*) MODE="${arg#MODE=}" ;; + *) ARGS+=("$arg") ;; + esac +done + +osascript < Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 11/79] bss fix --- kernel/boot.S | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/kernel/boot.S b/kernel/boot.S index 4da69d4b..940ce31f 100644 --- a/kernel/boot.S +++ b/kernel/boot.S @@ -3,11 +3,20 @@ _start: mrs x0, mpidr_el1 and x0, x0, #3 - cbz x0, check_hw + cbz x0, setup_vars half: wfe b half +setup_vars: + ldr x5, =__bss_start + ldr x6, =__bss_end +clear_bss: + cmp x5, x6 + b.ge check_hw + str xzr, [x5], #8 + b clear_bss + check_hw: adr x0, . @@ -82,14 +91,6 @@ el2_entry: eret el1_non_secure: - ldr x5, =__bss_start - ldr x6, =__bss_end -clear_bss: - cmp x5, x6 - b.ge stack_setup - str xzr, [x5], #8 - b clear_bss - stack_setup: ldr x1, =stack_top mov sp, x1 From 159387d5b002462083e85e0c77ecef30711da361 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 25 Jun 2025 00:00:00 +0000 Subject: [PATCH 12/79] VideoCore GPU --- kernel/graph/drivers/videocore/videocore.cpp | 175 ++++++++++++++++++ kernel/graph/drivers/videocore/videocore.hpp | 38 ++++ .../drivers/virtio_gpu_pci/virtio_gpu_pci.cpp | 2 + kernel/graph/graphics.cpp | 6 +- kernel/hw/hw.c | 9 +- kernel/hw/hw.h | 2 + kernel/mailbox/mailbox.c | 15 ++ kernel/mailbox/mailbox.h | 21 +++ kernel/memory/kalloc.c | 8 +- 9 files changed, 268 insertions(+), 8 deletions(-) create mode 100644 kernel/graph/drivers/videocore/videocore.cpp create mode 100644 kernel/graph/drivers/videocore/videocore.hpp create mode 100644 kernel/mailbox/mailbox.c create mode 100644 kernel/mailbox/mailbox.h diff --git a/kernel/graph/drivers/videocore/videocore.cpp b/kernel/graph/drivers/videocore/videocore.cpp new file mode 100644 index 00000000..96b54950 --- /dev/null +++ b/kernel/graph/drivers/videocore/videocore.cpp @@ -0,0 +1,175 @@ +#include "videocore.hpp" +#include "fw/fw_cfg.h" +#include "memory/kalloc.h" +#include "console/kio.h" +#include "graph/font8x8_bridge.h" +#include "ui/draw/draw.h" +#include "memory/memory_access.h" +#include "std/std.hpp" +#include "std/memfunctions.h" +#include "mailbox/mailbox.h" +#include "math/math.h" + +#define RGB_FORMAT_XRGB8888 ((uint32_t)('X') | ((uint32_t)('R') << 8) | ((uint32_t)('2') << 16) | ((uint32_t)('4') << 24)) + +VideoCoreGPUDriver* VideoCoreGPUDriver::try_init(gpu_size preferred_screen_size){ + VideoCoreGPUDriver* driver = new VideoCoreGPUDriver(); + if (driver->init(preferred_screen_size)) + return driver; + delete driver; + return nullptr; +} + +volatile uint32_t rmbox[36] __attribute__((aligned(16))) = { + 25 * 4,// Buf size + 0,// Request. Code 0 + 0x00048003, 8, 0, 640, 480,// Physical size + 0x00048004, 8, 0, 0, 0,// Virtual size + 0x00048005, 4, 0, 32,// Depth + 0x00040008, 4, 0, 0,//Pitch + 0x00048006, 4, 0, 0, //BGR + 0,// End +};//TODO: Screen resolution seems fixed at 640x480 (on QEMU at least). Setting it to anything else hangs the system + +volatile uint32_t fb_mbox[36] __attribute__((aligned(16))) = { + 32, 0, + 0x00040001, 8, 0, 16, 0, + 0 +}; + +bool VideoCoreGPUDriver::init(gpu_size preferred_screen_size){ + kprintf("Initializing VideoCore GPU"); + if (mailbox_call(rmbox, 8)) { + uint32_t phys_w = rmbox[5]; + uint32_t phys_h = rmbox[6]; + uint32_t virt_w = rmbox[10]; + uint32_t virt_h = rmbox[11]; + uint32_t depth = rmbox[15]; + stride = rmbox[19]; + + bpp = depth/8; + + screen_size = (gpu_size){phys_w,phys_h}; + kprintf("Size %ix%i (%ix%i) (%ix%i) | %i (%i)",phys_w,phys_h,virt_w,virt_h,screen_size.width,screen_size.height,depth, stride); + + fb_set_stride(bpp * screen_size.width); + fb_set_bounds(screen_size.width,screen_size.height); + if (!mailbox_call(fb_mbox, 8)){ + kprintf("Error"); + return false; + } + framebuffer = fb_mbox[5]; + back_framebuffer = talloc(screen_size.width * screen_size.height * bpp); + kprintf("Framebuffer allocated to %x. BPP %i. Stride %i",framebuffer, bpp, stride/bpp); + kprintf("Done"); + return true; + } + return false; +} + +void VideoCoreGPUDriver::flush(){ + if (full_redraw) { + memcpy((void*)framebuffer, (void*)back_framebuffer, screen_size.width * screen_size.height * bpp); + dirty_count = 0; + full_redraw = false; + return; + } + + volatile uint32_t* fb = (volatile uint32_t*)framebuffer; + volatile uint32_t* bfb = (volatile uint32_t*)back_framebuffer; + + for (uint32_t i = 0; i < dirty_count; i++) { + gpu_rect r = dirty_rects[i]; + + for (uint32_t y = 0; y < r.size.height; y++) { + uint32_t dest_y = r.point.y + y; + if (dest_y >= screen_size.height) break; + + uint32_t* dst = (uint32_t*)&fb[dest_y * (stride / 4) + r.point.x]; + uint32_t* src = (uint32_t*)&bfb[dest_y * (stride / 4) + r.point.x]; + + uint32_t copy_width = r.size.width; + if (r.point.x + copy_width > screen_size.width) + copy_width = screen_size.width - r.point.x; + + memcpy(dst, src, copy_width * sizeof(uint32_t)); + } + } + + full_redraw = false; + dirty_count = 0; +} + +void VideoCoreGPUDriver::clear(color color){ + fb_clear((uint32_t*)back_framebuffer, screen_size.width, screen_size.height, color); + mark_dirty(0,0,screen_size.width,screen_size.height); +} + +void VideoCoreGPUDriver::draw_pixel(uint32_t x, uint32_t y, color color){ + fb_draw_pixel((uint32_t*)back_framebuffer, x, y, color); + mark_dirty(x,y,1,1); +} + +void VideoCoreGPUDriver::fill_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color){ + fb_fill_rect((uint32_t*)back_framebuffer, x, y, width, height, color); + mark_dirty(x,y,width,height); +} + +void VideoCoreGPUDriver::draw_line(uint32_t x0, uint32_t y0, uint32_t x1,uint32_t y1, color color){ + gpu_rect rect = fb_draw_line((uint32_t*)framebuffer, x0, y0, x1, y1, color); + mark_dirty(rect.point.x,rect.point.y,rect.size.width,rect.size.height); +} + +void VideoCoreGPUDriver::draw_char(uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color){ + fb_draw_char((uint32_t*)back_framebuffer, x, y, c, scale, color); + mark_dirty(x,y,8*scale,8*scale); +} + +gpu_size VideoCoreGPUDriver::get_screen_size(){ + return screen_size; +} + +void VideoCoreGPUDriver::draw_string(string s, uint32_t x, uint32_t y, uint32_t scale, uint32_t color){ + gpu_size drawn_string = fb_draw_string((uint32_t*)back_framebuffer, s, x, y, scale, color); + mark_dirty(x,y,drawn_string.width,drawn_string.height); +} + +uint32_t VideoCoreGPUDriver::get_char_size(uint32_t scale){ + return fb_get_char_size(max(1,scale-1));//TODO: Screen resolution seems fixed at 640x480 (on QEMU at least). So we make the font smaller +} + +int VideoCoreGPUDriver::try_merge(gpu_rect* a, gpu_rect* b) { + uint32_t ax2 = a->point.x + a->size.width; + uint32_t ay2 = a->point.y + a->size.height; + uint32_t bx2 = b->point.x + b->size.width; + uint32_t by2 = b->point.y + b->size.height; + + if (a->point.x > bx2 || b->point.x > ax2 || a->point.y > by2 || b->point.y > ay2) + return 0; + + uint32_t min_x = a->point.x < b->point.x ? a->point.x : b->point.x; + uint32_t min_y = a->point.y < b->point.y ? a->point.y : b->point.y; + uint32_t max_x = ax2 > bx2 ? ax2 : bx2; + uint32_t max_y = ay2 > by2 ? ay2 : by2; + + a->point.x = min_x; + a->point.y = min_y; + a->size.width = max_x - min_x; + a->size.height = max_y - min_y; + + return 1; +} + +void VideoCoreGPUDriver::mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { + gpu_rect new_rect = { x, y, w, h }; + + for (uint32_t i = 0; i < dirty_count; i++) { + if (try_merge(&dirty_rects[i], &new_rect)) + return; + } + + if (dirty_count < MAX_DIRTY_RECTS_VCG) + dirty_rects[dirty_count++] = new_rect; + else + full_redraw = true; +} \ No newline at end of file diff --git a/kernel/graph/drivers/videocore/videocore.hpp b/kernel/graph/drivers/videocore/videocore.hpp new file mode 100644 index 00000000..9d5b2835 --- /dev/null +++ b/kernel/graph/drivers/videocore/videocore.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "../gpu_driver.hpp" + +#define MAX_DIRTY_RECTS_VCG 64 + +class VideoCoreGPUDriver : public GPUDriver { +public: + static VideoCoreGPUDriver* try_init(gpu_size preferred_screen_size); + VideoCoreGPUDriver(){} + bool init(gpu_size preferred_screen_size) override; + + void flush() override; + + void clear(color color) override; + void draw_pixel(uint32_t x, uint32_t y, color color) override; + void fill_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color) override; + void draw_line(uint32_t x0, uint32_t y0, uint32_t x1,uint32_t y1, color color) override; + void draw_char(uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color) override; + gpu_size get_screen_size() override; + void draw_string(string s, uint32_t x, uint32_t y, uint32_t scale, uint32_t color) override; + uint32_t get_char_size(uint32_t scale) override; + ~VideoCoreGPUDriver() = default; + +private: + gpu_size screen_size; + uintptr_t framebuffer; + uintptr_t back_framebuffer; + uint64_t framebuffer_size; + + gpu_rect dirty_rects[MAX_DIRTY_RECTS_VCG]; + uint32_t dirty_count = 0; + bool full_redraw = false; + int try_merge(gpu_rect* a, gpu_rect* b); + void mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h); + uint8_t bpp; + uint32_t stride; +}; \ No newline at end of file diff --git a/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp b/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp index 90478c47..cae12f35 100644 --- a/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp +++ b/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp @@ -54,6 +54,8 @@ bool VirtioGPUDriver::init(gpu_size preferred_screen_size){ } fb_set_stride(screen_size.width * BPP); + + kprintf("Stride %i",screen_size.width * BPP); framebuffer_size = screen_size.width * screen_size.height * BPP; framebuffer_size = (framebuffer_size); diff --git a/kernel/graph/graphics.cpp b/kernel/graph/graphics.cpp index c0ca916c..5a0f0677 100644 --- a/kernel/graph/graphics.cpp +++ b/kernel/graph/graphics.cpp @@ -3,8 +3,10 @@ #include "drivers/virtio_gpu_pci/virtio_gpu_pci.hpp" #include "drivers/ramfb_driver/ramfb.hpp" +#include "drivers/videocore/videocore.hpp" #include "std/std.hpp" +#include "hw/hw.h" static gpu_size screen_size; static bool _gpu_ready; @@ -16,10 +18,12 @@ void gpu_init(gpu_size preferred_screen_size){ gpu_driver = vgd; } else if (RamFBGPUDriver *rfb = RamFBGPUDriver::try_init(preferred_screen_size)){ gpu_driver = rfb; + } else if (BOARD_TYPE == 2){ + gpu_driver = VideoCoreGPUDriver::try_init(preferred_screen_size); } screen_size = preferred_screen_size; _gpu_ready = true; - kprintf("Selected and initialized GPU %x", (uintptr_t)gpu_driver); + kprintf("Selected and initialized GPU %x.", (uintptr_t)gpu_driver); } bool gpu_ready(){ diff --git a/kernel/hw/hw.c b/kernel/hw/hw.c index 50021a77..3edfc805 100644 --- a/kernel/hw/hw.c +++ b/kernel/hw/hw.c @@ -10,10 +10,12 @@ uintptr_t CRAM_START = 0; uintptr_t CRAM_END = 0; uintptr_t UART0_BASE = 0; uintptr_t XHCI_BASE = 0; +uintptr_t MMIO_BASE = 0; void detect_hardware(){ if (BOARD_TYPE == 1){ UART0_BASE = 0x9000000; + MMIO_BASE = 0x10010000; } else { uint32_t reg; asm volatile ("mrs %x0, midr_el1" : "=r" (reg)); @@ -21,10 +23,11 @@ void detect_hardware(){ uint32_t raspi = (reg >> 4) & 0xFFF; switch (raspi) { case 0xC07: - case 0xD03: UART0_BASE = 0x3F201000; break; - case 0xD08: UART0_BASE = 0xFE201000; break;; - default: UART0_BASE = 0x20201000; break; + case 0xD03: MMIO_BASE = 0x3F000000; break; + case 0xD08: MMIO_BASE = 0xFE000000; break;; + default: MMIO_BASE = 0x20000000; break; } + UART0_BASE = MMIO_BASE + 0x201000; } RAM_START = 0x40000000; diff --git a/kernel/hw/hw.h b/kernel/hw/hw.h index cceebb11..55e84871 100644 --- a/kernel/hw/hw.h +++ b/kernel/hw/hw.h @@ -16,5 +16,7 @@ extern uintptr_t CRAM_END; extern uintptr_t UART0_BASE; extern uintptr_t XHCI_BASE; +extern uintptr_t MMIO_BASE; + void detect_hardware(); void print_hardware(); \ No newline at end of file diff --git a/kernel/mailbox/mailbox.c b/kernel/mailbox/mailbox.c new file mode 100644 index 00000000..ac52f2e1 --- /dev/null +++ b/kernel/mailbox/mailbox.c @@ -0,0 +1,15 @@ +#include "mailbox.h" + +int mailbox_call(volatile uint32_t* mbox, uint8_t channel) { + uint32_t addr = ((uint32_t)(uintptr_t)mbox) & ~0xF; + + while (MBOX_STATUS & MBOX_FULL); + MBOX_WRITE = addr | (channel & 0xF); + + while (1) { + while (MBOX_STATUS & MBOX_EMPTY); + uint32_t resp = MBOX_READ; + if ((resp & 0xF) == channel && (resp & ~0xF) == addr) + return mbox[1] == 0x80000000; + } +} \ No newline at end of file diff --git a/kernel/mailbox/mailbox.h b/kernel/mailbox/mailbox.h new file mode 100644 index 00000000..bd28d6c7 --- /dev/null +++ b/kernel/mailbox/mailbox.h @@ -0,0 +1,21 @@ +#pragma once + +#include "types.h" +#include "hw/hw.h" + +#define MAILBOX_BASE (MMIO_BASE + 0xB880) + +#define MBOX_READ (*(volatile uint32_t*)(MAILBOX_BASE + 0x00)) +#define MBOX_STATUS (*(volatile uint32_t*)(MAILBOX_BASE + 0x18)) +#define MBOX_WRITE (*(volatile uint32_t*)(MAILBOX_BASE + 0x20)) + +#define MBOX_FULL 0x80000000 +#define MBOX_EMPTY 0x40000000 + +#ifdef __cplusplus +extern "C" { +#endif +int mailbox_call(volatile uint32_t* mbox, uint8_t channel); +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/kernel/memory/kalloc.c b/kernel/memory/kalloc.c index ce2b37cb..dcd25eed 100644 --- a/kernel/memory/kalloc.c +++ b/kernel/memory/kalloc.c @@ -17,12 +17,12 @@ static uint64_t calculated_ram_end = 0; FreeBlock* temp_free_list = 0; -#define PCI_MMIO_BASE 0x10010000 -#define PCI_MMIO_LIMIT 0x1FFFFFFF +#define PCI_MMIO_LIMIT MMIO_BASE + 0xFFFFFFF -static uint64_t next_mmio_base = PCI_MMIO_BASE; +static uint64_t next_mmio_base; uint64_t alloc_mmio_region(uint64_t size) { + if (next_mmio_base == 0) next_mmio_base = MMIO_BASE; size = (size + 0xFFF) & ~0xFFF; if (next_mmio_base + size > PCI_MMIO_LIMIT){ panic_with_info("MMIO alloc overflow",next_mmio_base+size); @@ -34,7 +34,7 @@ uint64_t alloc_mmio_region(uint64_t size) { } bool is_mmio_allocated(uint64_t addr){ - return addr > PCI_MMIO_BASE && addr < next_mmio_base; + return addr > MMIO_BASE && addr < next_mmio_base; } extern uint64_t kernel_start; From ee9a8c106d6f2922c9724f6e0355556e61320523 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 25 Jun 2025 00:00:00 +0000 Subject: [PATCH 13/79] MMU mapping and page allocation for fb --- kernel/graph/drivers/videocore/videocore.cpp | 8 ++++++-- kernel/graph/drivers/videocore/videocore.hpp | 2 ++ kernel/memory/mmu.h | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/kernel/graph/drivers/videocore/videocore.cpp b/kernel/graph/drivers/videocore/videocore.cpp index 96b54950..83b9fe55 100644 --- a/kernel/graph/drivers/videocore/videocore.cpp +++ b/kernel/graph/drivers/videocore/videocore.cpp @@ -9,6 +9,7 @@ #include "std/memfunctions.h" #include "mailbox/mailbox.h" #include "math/math.h" +#include "memory/mmu.h" #define RGB_FORMAT_XRGB8888 ((uint32_t)('X') | ((uint32_t)('R') << 8) | ((uint32_t)('2') << 16) | ((uint32_t)('4') << 24)) @@ -59,9 +60,12 @@ bool VideoCoreGPUDriver::init(gpu_size preferred_screen_size){ return false; } framebuffer = fb_mbox[5]; - back_framebuffer = talloc(screen_size.width * screen_size.height * bpp); + size_t fb_size = fb_mbox[6]; + page = alloc_page(0x1000, true, true, false); + back_framebuffer = (uintptr_t)allocate_in_page(page, fb_size, ALIGN_16B, true, true); kprintf("Framebuffer allocated to %x. BPP %i. Stride %i",framebuffer, bpp, stride/bpp); - kprintf("Done"); + for (size_t i = framebuffer; i < framebuffer + fb_size; i += GRANULE_4KB) + register_device_memory(i,i); return true; } return false; diff --git a/kernel/graph/drivers/videocore/videocore.hpp b/kernel/graph/drivers/videocore/videocore.hpp index 9d5b2835..e19b8f33 100644 --- a/kernel/graph/drivers/videocore/videocore.hpp +++ b/kernel/graph/drivers/videocore/videocore.hpp @@ -28,6 +28,8 @@ class VideoCoreGPUDriver : public GPUDriver { uintptr_t back_framebuffer; uint64_t framebuffer_size; + void* page; + gpu_rect dirty_rects[MAX_DIRTY_RECTS_VCG]; uint32_t dirty_count = 0; bool full_redraw = false; diff --git a/kernel/memory/mmu.h b/kernel/memory/mmu.h index 7361bc9b..38ebcae5 100644 --- a/kernel/memory/mmu.h +++ b/kernel/memory/mmu.h @@ -7,9 +7,15 @@ void mmu_alloc(); void mmu_init(); +#ifdef __cplusplus +extern "C" { +#endif void register_device_memory(uint64_t va, uint64_t pa); void register_device_memory_2mb(uint64_t va, uint64_t pa); void register_proc_memory(uint64_t va, uint64_t pa, bool kernel); +#ifdef __cplusplus +} +#endif void debug_mmu_address(uint64_t va); void mmu_enable_verbose(); From 9f6bf00f975e868bdd2352a097901d47c8198822 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 25 Jun 2025 00:00:00 +0000 Subject: [PATCH 14/79] Moved RAM for RPI --- kernel/hw/hw.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/kernel/hw/hw.c b/kernel/hw/hw.c index 3edfc805..0bb46cc6 100644 --- a/kernel/hw/hw.c +++ b/kernel/hw/hw.c @@ -16,26 +16,26 @@ void detect_hardware(){ if (BOARD_TYPE == 1){ UART0_BASE = 0x9000000; MMIO_BASE = 0x10010000; + CRAM_END = 0x60000000; + RAM_START = 0x40000000; + CRAM_START = 0x43600000; + USE_PCI = 1; } else { uint32_t reg; asm volatile ("mrs %x0, midr_el1" : "=r" (reg)); //We can detect if we're running on 0x400.... to know if we're in virt. And 41 vs 40 to know if we're in img or elf uint32_t raspi = (reg >> 4) & 0xFFF; switch (raspi) { - case 0xC07: - case 0xD03: MMIO_BASE = 0x3F000000; break; case 0xD08: MMIO_BASE = 0xFE000000; break;; - default: MMIO_BASE = 0x20000000; break; + default: MMIO_BASE = 0x3F000000; break; } UART0_BASE = MMIO_BASE + 0x201000; + RAM_START = 0x10000000; + CRAM_END = (MMIO_BASE - 0x10000000) & 0xF0000000; + RAM_START = 0x10000000; + CRAM_START = 0x13600000; + XHCI_BASE = 0xFE9C0000; } - - RAM_START = 0x40000000; - RAM_SIZE = 0x20000000; - CRAM_END = 0x60000000; - CRAM_START = 0x43600000; - XHCI_BASE = 0xFE9C0000; - USE_PCI = BOARD_TYPE == 1; } void print_hardware(){ From 4ca847c5c147b0985df0f370a2b0f1fb43a5ef5a Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 25 Jun 2025 00:00:00 +0000 Subject: [PATCH 15/79] Interrupts in the RPI4b --- kernel/exceptions/irq.h | 4 +--- kernel/hw/hw.c | 11 ++++++++++- kernel/hw/hw.h | 3 +++ kernel/memory/mmu.c | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/kernel/exceptions/irq.h b/kernel/exceptions/irq.h index 67eeb7f7..a8fae41e 100644 --- a/kernel/exceptions/irq.h +++ b/kernel/exceptions/irq.h @@ -1,9 +1,7 @@ #pragma once #include "types.h" - -#define GICD_BASE 0x08000000 -#define GICC_BASE 0x08010000 +#include "hw/hw.h" void irq_init(); void irq_el1_handler(); diff --git a/kernel/hw/hw.c b/kernel/hw/hw.c index 0bb46cc6..ee848320 100644 --- a/kernel/hw/hw.c +++ b/kernel/hw/hw.c @@ -11,6 +11,8 @@ uintptr_t CRAM_END = 0; uintptr_t UART0_BASE = 0; uintptr_t XHCI_BASE = 0; uintptr_t MMIO_BASE = 0; +uintptr_t GICD_BASE = 0; +uintptr_t GICC_BASE = 0; void detect_hardware(){ if (BOARD_TYPE == 1){ @@ -20,13 +22,20 @@ void detect_hardware(){ RAM_START = 0x40000000; CRAM_START = 0x43600000; USE_PCI = 1; + GICD_BASE = 0x08000000; + GICC_BASE = 0x08010000; + } else { uint32_t reg; asm volatile ("mrs %x0, midr_el1" : "=r" (reg)); //We can detect if we're running on 0x400.... to know if we're in virt. And 41 vs 40 to know if we're in img or elf uint32_t raspi = (reg >> 4) & 0xFFF; switch (raspi) { - case 0xD08: MMIO_BASE = 0xFE000000; break;; + case 0xD08: + MMIO_BASE = 0xFE000000; + GICD_BASE = 0xff841000; + GICC_BASE = 0xff842000; + break;; default: MMIO_BASE = 0x3F000000; break; } UART0_BASE = MMIO_BASE + 0x201000; diff --git a/kernel/hw/hw.h b/kernel/hw/hw.h index 55e84871..dee8dd91 100644 --- a/kernel/hw/hw.h +++ b/kernel/hw/hw.h @@ -18,5 +18,8 @@ extern uintptr_t XHCI_BASE; extern uintptr_t MMIO_BASE; +extern uintptr_t GICD_BASE; +extern uintptr_t GICC_BASE; + void detect_hardware(); void print_hardware(); \ No newline at end of file diff --git a/kernel/memory/mmu.c b/kernel/memory/mmu.c index f8b0db8e..8d44eacd 100644 --- a/kernel/memory/mmu.c +++ b/kernel/memory/mmu.c @@ -183,7 +183,7 @@ void mmu_init() { for (uint64_t addr = get_uart_base(); addr <= get_uart_base(); addr += GRANULE_4KB) mmu_map_4kb(addr, addr, MAIR_IDX_DEVICE, 1); - for (uint64_t addr = GICD_BASE; addr <= GICD_BASE + 0x20040; addr += GRANULE_4KB) + for (uint64_t addr = GICD_BASE; addr <= GICC_BASE + 0x1000; addr += GRANULE_4KB) mmu_map_4kb(addr, addr, MAIR_IDX_DEVICE, 1); for (uint64_t addr = get_shared_start(); addr <= get_shared_end(); addr += GRANULE_4KB) From 41fd7d2587f72d992816ecee8ac06b6039fa5854 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 25 Jun 2025 00:00:00 +0000 Subject: [PATCH 16/79] Fixed virtio xhci --- kernel/input/xhci.c | 56 ++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/kernel/input/xhci.c b/kernel/input/xhci.c index 5b39af5c..d2e678e0 100644 --- a/kernel/input/xhci.c +++ b/kernel/input/xhci.c @@ -96,37 +96,37 @@ void make_ring_link(trb* ring, bool cycle){ bool xhci_init(xhci_device *xhci, uint64_t pci_addr) { kprintfv("[xHCI] init"); -#ifdef USE_PCI - if (!(read16(pci_addr + 0x06) & (1 << 4))){ - kprintfv("[xHCI] Wrong capabilities list"); - return false; - } - - pci_enable_device(pci_addr); - - if (!pci_setup_bar(pci_addr, 0, &xhci->mmio, &xhci->mmio_size)){ - kprintfv("[xHCI] BARs not set up"); - return false; - } - - pci_register(xhci->mmio, xhci->mmio_size); - - uint8_t interrupts_ok = pci_setup_interrupts(pci_addr, XHCI_IRQ, 1); - switch(interrupts_ok){ - case 0: - kprintf_raw("[xHCI] Failed to setup interrupts"); + if (USE_PCI){ + if (!(read16(pci_addr + 0x06) & (1 << 4))){ + kprintfv("[xHCI] Wrong capabilities list"); return false; - case 1: - kprintf_raw("[xHCI] Interrupts setup with MSI-X %i",XHCI_IRQ); - break; - default: - kprintf_raw("[xHCI] Interrupts setup with MSI %i",XHCI_IRQ); - break; + } + + pci_enable_device(pci_addr); + + if (!pci_setup_bar(pci_addr, 0, &xhci->mmio, &xhci->mmio_size)){ + kprintfv("[xHCI] BARs not set up"); + return false; + } + + pci_register(xhci->mmio, xhci->mmio_size); + + uint8_t interrupts_ok = pci_setup_interrupts(pci_addr, XHCI_IRQ, 1); + switch(interrupts_ok){ + case 0: + kprintf_raw("[xHCI] Failed to setup interrupts"); + return false; + case 1: + kprintf_raw("[xHCI] Interrupts setup with MSI-X %i",XHCI_IRQ); + break; + default: + kprintf_raw("[xHCI] Interrupts setup with MSI %i",XHCI_IRQ); + break; + } + + kprintfv("[xHCI] BARs set up @ %x (%x)",xhci->mmio,xhci->mmio_size); } - kprintfv("[xHCI] BARs set up @ %x (%x)",xhci->mmio,xhci->mmio_size); -#endif - xhci->cap = (xhci_cap_regs*)(uintptr_t)xhci->mmio; kprintfv("[xHCI] caplength %x",xhci->cap->caplength); uint64_t op_base = xhci->mmio + xhci->cap->caplength; From 196d331c085a9a8e4b20aac0c5a1ca7b3f3da576 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 25 Jun 2025 00:00:00 +0000 Subject: [PATCH 17/79] Removing unused comment --- kernel/kernel.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/kernel.c b/kernel/kernel.c index 4632d658..fa1a9b96 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -78,8 +78,6 @@ void kernel_main() { kprintf("Starting processes"); - // translate_enable_verbose(); - launch_net_process(); init_bootprocess(); From 2b13978518a5367286dc677878fa5fbcb7dd16d1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 25 Jun 2025 00:00:00 +0000 Subject: [PATCH 18/79] Fallback if no disk --- kernel/kernel_processes/windows/desktop.cpp | 22 +++++++++++---------- user/default_process.c | 5 ----- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/kernel/kernel_processes/windows/desktop.cpp b/kernel/kernel_processes/windows/desktop.cpp index 11150a2b..5507fc51 100644 --- a/kernel/kernel_processes/windows/desktop.cpp +++ b/kernel/kernel_processes/windows/desktop.cpp @@ -28,16 +28,18 @@ uint16_t Desktop::find_extension(char *path){ Desktop::Desktop() { entries = Array(9); string_list *list = list_directory_contents("/redos/user/"); - char* reader = (char*)list->array; - for (uint32_t i = 0; i < list->count; i++){ - char *file = reader; - string fullpath = string_format("/redos/user/%s",(uintptr_t)file); - string name = string_ca_max(file,find_extension(file)); - string ext = string_l(file + find_extension(file)); - if (strcmp(ext.data,".elf") == 0) - add_entry(name.data, ext.data, fullpath.data); - while (*reader) reader++; - reader++; + if (list){ + char* reader = (char*)list->array; + for (uint32_t i = 0; i < list->count; i++){ + char *file = reader; + string fullpath = string_format("/redos/user/%s",(uintptr_t)file); + string name = string_ca_max(file,find_extension(file)); + string ext = string_l(file + find_extension(file)); + if (strcmp(ext.data,".elf") == 0) + add_entry(name.data, ext.data, fullpath.data); + while (*reader) reader++; + reader++; + } } single_label = new Label(); diff --git a/user/default_process.c b/user/default_process.c index 84dae5e0..4d9d644e 100644 --- a/user/default_process.c +++ b/user/default_process.c @@ -4,11 +4,6 @@ #include "input_keycodes.h" #include "std/string.h" -void var_test(char* s, ...){ - va_list args; - va_start(args, s); -} - void proc_func() { uint64_t j = 0; gpu_size* size = gpu_screen_size(); From 30eb951032e38688854df6acc0a5afac84afcc90 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 25 Jun 2025 00:00:00 +0000 Subject: [PATCH 19/79] Passing disk for rpi --- run_rpi | 1 + 1 file changed, 1 insertion(+) diff --git a/run_rpi b/run_rpi index f7b95ad7..aa39ca32 100755 --- a/run_rpi +++ b/run_rpi @@ -11,6 +11,7 @@ qemu-system-aarch64 \ -M raspi4b \ -kernel kernel.elf \ -display sdl \ +-drive file=disk.img,if=none,format=raw,id=hd0 \ -netdev vmnet-bridged,id=net0,ifname=en0 \ -serial mon:stdio \ -d guest_errors \ From 363c011672eb9c52eebf8c2f536da66e3246f3ca Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 25 Jun 2025 00:00:00 +0000 Subject: [PATCH 20/79] Fix for process crashing due to overlapping with stack --- kernel/kernel_processes/kprocess_loader.c | 2 +- kernel/memory/page_allocator.c | 2 +- kernel/process/loading/elf_file.c | 2 +- kernel/process/loading/process_loader.c | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/kernel_processes/kprocess_loader.c b/kernel/kernel_processes/kprocess_loader.c index 1868acad..47f57577 100644 --- a/kernel/kernel_processes/kprocess_loader.c +++ b/kernel/kernel_processes/kprocess_loader.c @@ -30,7 +30,7 @@ process_t *create_kernel_process(const char *name, void (*func)()){ proc->sp = proc->stack; proc->pc = (uintptr_t)func; - kprintf_raw("Kernel process allocated with address at %x, stack at %x, heap at %x",proc->pc, proc->sp, proc->heap); + kprintf_raw("Kernel process %s allocated with address at %x, stack at %x, heap at %x", (uintptr_t)name, proc->pc, proc->sp, proc->heap); proc->spsr = 0x205; proc->state = READY; diff --git a/kernel/memory/page_allocator.c b/kernel/memory/page_allocator.c index 6a60103e..f2fb8963 100644 --- a/kernel/memory/page_allocator.c +++ b/kernel/memory/page_allocator.c @@ -72,7 +72,7 @@ void* alloc_page(uint64_t size, bool kernel, bool device, bool full) { uintptr_t first_address = 0; for (uint64_t j = 0; j < page_count; j++){ - mem_bitmap[i] |= (1ULL << bit + j); + mem_bitmap[i] |= (1 << (bit + j)); uint64_t page_index = (i * 64) + (bit + j); uintptr_t address = page_index * PAGE_SIZE; if (!first_address) first_address = address; diff --git a/kernel/process/loading/elf_file.c b/kernel/process/loading/elf_file.c index 6da1204f..60b85c55 100644 --- a/kernel/process/loading/elf_file.c +++ b/kernel/process/loading/elf_file.c @@ -46,7 +46,7 @@ process_t* load_elf_file(const char *name, void* file){ elf_program_header* first_program_header = (elf_program_header*)((uint8_t *)file + header->program_header_offset); kprintf("program takes up %x, begins at %x, and is %b, %b",first_program_header->p_filez, first_program_header->p_offset, first_program_header->segment_type, first_program_header->flags); kprintf("SECTION %x - %i * %i",header->section_header_offset, header->section_entry_size,header->section_num_entries); - kprintf("First instruction %x", (uint64_t)*((uint8_t *)file + 0x1000)); + kprintf("First instruction %x", *(uint64_t*)(file + header->program_entry_offset)); return create_process(name, (void*)(file + first_program_header->p_offset), first_program_header->p_filez, header->program_entry_offset); } \ No newline at end of file diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index d1e3c9b3..7f8b42d6 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -259,7 +259,8 @@ process_t* create_process(char *name, void *content, uint64_t content_size, uint name_process(proc, name); - uint8_t* dest = (uint8_t*)alloc_page(content_size, false, false, false); + //TODO: keep track of code size so we can free up allocated code pages + uint8_t* dest = (uint8_t*)alloc_page(content_size, false, false, true); if (!dest) return 0; for (uint64_t i = 0; i < content_size; i++){ From 8a20f4ec5ab78c186523a7247922911a1303de60 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 26 Jun 2025 00:00:00 +0000 Subject: [PATCH 21/79] Init an SD card. No RW yet --- kernel/filesystem/{disk.c => disk.cpp} | 9 +- kernel/filesystem/exfat.h | 8 +- kernel/filesystem/sdhci.cpp | 266 +++++++++++++++++++++++++ kernel/filesystem/sdhci.hpp | 41 ++++ kernel/filesystem/virtio_blk_pci.h | 8 +- kernel/hw/hw.c | 23 ++- kernel/hw/hw.h | 14 +- run_rpi | 2 +- 8 files changed, 365 insertions(+), 6 deletions(-) rename kernel/filesystem/{disk.c => disk.cpp} (83%) create mode 100644 kernel/filesystem/sdhci.cpp create mode 100644 kernel/filesystem/sdhci.hpp diff --git a/kernel/filesystem/disk.c b/kernel/filesystem/disk.cpp similarity index 83% rename from kernel/filesystem/disk.c rename to kernel/filesystem/disk.cpp index 7fe50076..1ab8a13e 100644 --- a/kernel/filesystem/disk.c +++ b/kernel/filesystem/disk.cpp @@ -1,6 +1,8 @@ #include "disk.h" #include "exfat.h" #include "virtio_blk_pci.h" +#include "sdhci.hpp" +#include "hw/hw.h" static bool disk_enable_verbose; @@ -17,8 +19,13 @@ void disk_verbose(){ }\ }) +SDHCI sdhci_driver; + bool find_disk(){ - return vblk_find_disk(); + if (BOARD_TYPE == 2) + return sdhci_driver.init(); + else + return vblk_find_disk(); } bool disk_init(){ diff --git a/kernel/filesystem/exfat.h b/kernel/filesystem/exfat.h index 9f124374..8e2d9393 100644 --- a/kernel/filesystem/exfat.h +++ b/kernel/filesystem/exfat.h @@ -1,8 +1,14 @@ #include "types.h" #include "std/string.h" +#ifdef __cplusplus +extern "C" { +#endif bool ef_init(); void ef_read_dump(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint32_t root_index); void* ef_read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index); void* ef_read_file(const char *path); -string_list* ef_list_contents(const char *path); \ No newline at end of file +string_list* ef_list_contents(const char *path); +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/kernel/filesystem/sdhci.cpp b/kernel/filesystem/sdhci.cpp new file mode 100644 index 00000000..79605682 --- /dev/null +++ b/kernel/filesystem/sdhci.cpp @@ -0,0 +1,266 @@ +#include "sdhci.hpp" +#include "console/kio.h" +#include "hw/hw.h" +#include "mailbox/mailbox.h" +#include "syscalls/syscalls.h" + +#define CMD_INDEX(x) ((x) << 8) +#define RESP_TYPE(x) (x) +#define CRC_ENABLE (1 << 3) +#define IDX_ENABLE (1 << 4) +#define IS_DATA (1 << 5) + +#define SEND_CID (CMD_INDEX(2) | RESP_TYPE(1) | CRC_ENABLE) +#define IF_COND (CMD_INDEX(8) | RESP_TYPE(2) | CRC_ENABLE | IDX_ENABLE) +#define RCA (CMD_INDEX(3) | RESP_TYPE(2) | CRC_ENABLE) +#define APP (CMD_INDEX(55) | RESP_TYPE(2) | CRC_ENABLE | IDX_ENABLE) +#define OCR (CMD_INDEX(41) | RESP_TYPE(2)) + +bool SDHCI::wait(uint32_t *reg, uint32_t expected_value, bool match, uint32_t timeout){ + bool condition; + do { + delay(140); + timeout--; + if (timeout == 0){ + kprintf("Command timed out. Final value %x vs %x on %x",*reg,expected_value, (uintptr_t)reg); + return false; + } + condition = *reg & expected_value; + } while (match ^ condition); + + kprintf("Finished with %i",timeout); + return true; +} + +uint32_t SDHCI::clock_divider(uint32_t target_rate) { + uint32_t target_div = 1; + + if (target_rate <= clock_rate) { + target_div = clock_rate / target_rate; + + if (clock_rate % target_rate) { + target_div = 0; + } + } + + int div = -1; + for (int fb = 31; fb >= 0; fb--) { + uint32_t bt = (1 << fb); + + if (target_div & bt) { + div = fb; + target_div &= ~(bt); + + if (target_div) { + div++; + } + + break; + } + } + + if (div == -1) + div = 31; + + if (div >= 32) + div = 31; + + if (div != 0) + div = (1 << (div - 1)); + + if (div >= 0x400) + div = 0x3FF; + + uint32_t freq = div & 0xff; + uint32_t hi = (div >> 8) & 0x3; + uint32_t ret = (freq << 8) | (hi << 6) | (0 << 5); + + return ret; +} + +bool SDHCI::switch_clock_rate(uint32_t target_rate) { + uint32_t div = clock_divider(target_rate); + + wait(®s->status,0b11, false); + + kprintf("Clock divider %i",div); + + regs->ctrl1 &= ~(1 << 2); + + delay(3); + + regs->ctrl1 = (regs->ctrl1 | div) & ~0xFFE0; + + delay(3); + + regs->ctrl1 |= (1 << 2); + + delay(3); + + return true; +} + +volatile uint32_t mbox[8] __attribute__((aligned(16))) = { + 32, + 0, + 0x00030002, 8, 0, 1, 0,//Request clock rate for 1 (EMMC) + 0 +}; + +bool SDHCI::setup_clock(){ + regs->ctrl2 = 0; + + if (!mailbox_call(mbox,8)) return false; + + clock_rate = mbox[6]; + + regs->ctrl1 |= 1; + regs->ctrl1 |= clock_divider(400000); + regs->ctrl1 &= ~(0xf << 16); + regs->ctrl1 |= (11 << 16); + regs->ctrl1 |= (1 << 2); + + wait(®s->ctrl1, (1 << 1)); + + delay(30); + + regs->ctrl1 |= 4; + + delay(30); + + return true; +} + +void SDHCI::dump(){ + kprintf("SD HCI Register dump\n*-*-*"); + for (size_t i = 0; i <= 0xFC; i+= 4){ + uint32_t value = *(uint32_t*)(SDHCI_BASE + i); + if (value) + kprintf("[%x] %x",i,value); + } + kprintf("*-*-*"); +} + +bool SDHCI::init() { + if (!SDHCI_BASE) return false; + regs = (sdhci_regs*)SDHCI_BASE; + + regs->ctrl1 |= (1 << 24);//Reset + wait(®s->ctrl1,(1 << 24), false); + + if (RPI_BOARD == 4){ + regs->ctrl0 |= 0x0F << 8;//VDD1 bus power + delay(3); + } + + kprintf("[SDHCI] Controller reset"); + + setup_clock(); + + kprintf("[SDHCI] Controller ready"); + + regs->interrupt = 0; + regs->irpt_en = 0xFFFFFFFF; + regs->irpt_mask = 0xFFFFFFFF; + + delay(203); + + if (!issue_command(0, 0)){ + kprintf("[SDHCI error] Failed setting to idle"); + return false; + } + kprintf("[SDHCI] Idle"); + + switch_clock_rate(25000000); + + bool v2_card = 0; + if (!issue_command(IF_COND, 0)){ + if (!(regs->interrupt & 0x10000)){ + kprintf("Error in IFCOND"); + return false; + } + kprintf("[SDHCI error] Timeout on IFCOND. Defaulting to V1"); + } else { + if ((regs->resp0 & 0xFF) != 0xAA) { + kprintf("[SDHCI error] IFCOND pattern mismatch"); + return false; + } + v2_card = true; + } + + kprintf("[SDHCI] V2 = %i",v2_card); + + if (!true) {//usable_card + return false; + } + + while (true){ + if (!issue_app_command(OCR, 0xFF8000 | (v2_card << 30))){ + kprintf("[SDHCI error] Get OCR Failed"); + return false; + } + if (regs->resp0 & (1 << 31)) break; + else delay(500); + } + + kprintf("[SDHCI] OCR %x",regs->resp0); + + delay(1000); + + if (!issue_command(SEND_CID, 0)){ + kprintf("[SDHCI error] Failed requesting card id"); + return false; + } + kprintf("[SDHCI] Card ID: %x.%x.%x.%x",regs->resp0, regs->resp1,regs->resp2,regs->resp3); + if (!issue_command(RCA, 0)){ + kprintf("[SDHCI error] Failed to send relative address"); + return false; + } + + kprintf("[SDHCI] RCA %x",(regs->resp0 >> 16) & 0xFFFF); + + // if (!select_card()) { + // return false; + // } + + if (!true) {//set_scr + return false; + } + + return true; +} + +bool SDHCI::issue_app_command(uint32_t cmd, uint32_t arg, uint32_t flags) { + if (issue_command(APP, 0, 1 << 3)) + return issue_command(cmd, arg); + + return false; +} + +bool SDHCI::issue_command(uint32_t cmd, uint32_t arg, uint32_t flags) { + + if (!wait(®s->status, 0b11, false)) { + kprintf("[SDHCI] Timeout waiting for CMD/DAT inhibit"); + return false; + } + + regs->interrupt = 0xFFFFFFFF; + + regs->blksize_count = 0; + regs->arg1 = arg; + regs->cmd_transfmode = (cmd << 16) | flags; + + kprintf("[SDHCI] Sent command %b.",(cmd << 16) | flags); + + if (!wait(®s->interrupt,0x8001)) { + kprintf("[SDHCI warning] Issue command timeout"); + return false; + } + + kprintf("[SDHCI] Command finished %x",regs->interrupt); + + if (regs->interrupt & 0x8000) return false;//Error + if (!(regs->interrupt & 0x0001)) return false;//No finish + + return true; +} \ No newline at end of file diff --git a/kernel/filesystem/sdhci.hpp b/kernel/filesystem/sdhci.hpp new file mode 100644 index 00000000..b559139a --- /dev/null +++ b/kernel/filesystem/sdhci.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "types.h" + +typedef struct sdhci_regs { + uint32_t arg2; + uint32_t blksize_count; + uint32_t arg1; + uint32_t cmd_transfmode; + uint32_t resp0; + uint32_t resp1; + uint32_t resp2; + uint32_t resp3; + uint32_t data; + uint32_t status; + uint32_t ctrl0; + uint32_t ctrl1; + uint32_t interrupt; + uint32_t irpt_mask; + uint32_t irpt_en; + uint32_t ctrl2; + uint32_t __reserved[0x2F]; + uint32_t slotisr_ver; +} sdhci_regs; + +class SDHCI { +public: + bool init(); + void write(void *buffer, uint32_t sector, uint32_t count); + void read(void *buffer, uint32_t sector, uint32_t count); +private: + sdhci_regs* regs; + bool issue_command(uint32_t cmd_index, uint32_t arg, uint32_t flags = 0); + bool issue_app_command(uint32_t cmd, uint32_t arg, uint32_t flags = 0); + bool setup_clock(); + uint32_t clock_divider(uint32_t target_rate); + bool switch_clock_rate(uint32_t target_rate); + void dump(); + bool wait(uint32_t *reg, uint32_t expected_value, bool match = true, uint32_t timeout = 2000); + uint32_t clock_rate; +}; \ No newline at end of file diff --git a/kernel/filesystem/virtio_blk_pci.h b/kernel/filesystem/virtio_blk_pci.h index 91333df4..a8df3970 100644 --- a/kernel/filesystem/virtio_blk_pci.h +++ b/kernel/filesystem/virtio_blk_pci.h @@ -2,7 +2,13 @@ #include "types.h" +#ifdef __cplusplus +extern "C" { +#endif bool vblk_find_disk(); void vblk_disk_verbose(); void vblk_write(const void *buffer, uint32_t sector, uint32_t count); -void vblk_read(void *buffer, uint32_t sector, uint32_t count); \ No newline at end of file +void vblk_read(void *buffer, uint32_t sector, uint32_t count); +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/kernel/hw/hw.c b/kernel/hw/hw.c index ee848320..9234e1b6 100644 --- a/kernel/hw/hw.c +++ b/kernel/hw/hw.c @@ -13,6 +13,9 @@ uintptr_t XHCI_BASE = 0; uintptr_t MMIO_BASE = 0; uintptr_t GICD_BASE = 0; uintptr_t GICC_BASE = 0; +uintptr_t SDHCI_BASE = 0; + +uint8_t RPI_BOARD; void detect_hardware(){ if (BOARD_TYPE == 1){ @@ -35,18 +38,36 @@ void detect_hardware(){ MMIO_BASE = 0xFE000000; GICD_BASE = 0xff841000; GICC_BASE = 0xff842000; + RPI_BOARD = 4; break;; default: MMIO_BASE = 0x3F000000; break; } UART0_BASE = MMIO_BASE + 0x201000; + SDHCI_BASE = MMIO_BASE + 0x300000; + XHCI_BASE = MMIO_BASE + 0x9C0000; RAM_START = 0x10000000; CRAM_END = (MMIO_BASE - 0x10000000) & 0xF0000000; RAM_START = 0x10000000; CRAM_START = 0x13600000; - XHCI_BASE = 0xFE9C0000; } } void print_hardware(){ kprintf("Board type %i",BOARD_TYPE); +} + +void delay(uint32_t ms) { + uint64_t freq; + asm volatile ("mrs %0, cntfrq_el0" : "=r"(freq)); + + uint64_t ticks; + asm volatile ("mrs %0, cntpct_el0" : "=r"(ticks)); + + uint64_t target = ticks + (freq / 1000) * ms; + + while (1) { + uint64_t now; + asm volatile ("mrs %0, cntpct_el0" : "=r"(now)); + if (now >= target) break; + } } \ No newline at end of file diff --git a/kernel/hw/hw.h b/kernel/hw/hw.h index dee8dd91..d2f01e68 100644 --- a/kernel/hw/hw.h +++ b/kernel/hw/hw.h @@ -21,5 +21,17 @@ extern uintptr_t MMIO_BASE; extern uintptr_t GICD_BASE; extern uintptr_t GICC_BASE; +extern uintptr_t SDHCI_BASE; + +extern uint8_t RPI_BOARD; + void detect_hardware(); -void print_hardware(); \ No newline at end of file +void print_hardware(); + +#ifdef __cplusplus +extern "C" { +#endif +void delay(uint32_t count); +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/run_rpi b/run_rpi index aa39ca32..d3bcbc09 100755 --- a/run_rpi +++ b/run_rpi @@ -11,7 +11,7 @@ qemu-system-aarch64 \ -M raspi4b \ -kernel kernel.elf \ -display sdl \ --drive file=disk.img,if=none,format=raw,id=hd0 \ +-device sd-card,drive=sd -drive id=sd,format=raw,file=disk.img,if=none \ -netdev vmnet-bridged,id=net0,ifname=en0 \ -serial mon:stdio \ -d guest_errors \ From 001e0e4cc2637ba9d25666939b1792e685fb76e7 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 26 Jun 2025 00:00:00 +0000 Subject: [PATCH 22/79] Fixed MMU issue --- kernel/hw/hw.c | 2 +- kernel/memory/page_allocator.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/hw/hw.c b/kernel/hw/hw.c index 9234e1b6..038a10d2 100644 --- a/kernel/hw/hw.c +++ b/kernel/hw/hw.c @@ -39,7 +39,7 @@ void detect_hardware(){ GICD_BASE = 0xff841000; GICC_BASE = 0xff842000; RPI_BOARD = 4; - break;; + break; default: MMIO_BASE = 0x3F000000; break; } UART0_BASE = MMIO_BASE + 0x201000; diff --git a/kernel/memory/page_allocator.c b/kernel/memory/page_allocator.c index f2fb8963..be8d3325 100644 --- a/kernel/memory/page_allocator.c +++ b/kernel/memory/page_allocator.c @@ -72,7 +72,7 @@ void* alloc_page(uint64_t size, bool kernel, bool device, bool full) { uintptr_t first_address = 0; for (uint64_t j = 0; j < page_count; j++){ - mem_bitmap[i] |= (1 << (bit + j)); + mem_bitmap[i] |= (1ULL << (bit + j)); uint64_t page_index = (i * 64) + (bit + j); uintptr_t address = page_index * PAGE_SIZE; if (!first_address) first_address = address; From 963cc3a5b117241d2f3eaa100bb80f8efb721798 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 26 Jun 2025 00:00:00 +0000 Subject: [PATCH 23/79] SDHCI read --- kernel/filesystem/disk.cpp | 5 ++- kernel/filesystem/exfat.c | 4 +-- kernel/filesystem/sdhci.cpp | 72 ++++++++++++++++++++++++++++--------- kernel/filesystem/sdhci.hpp | 3 +- 4 files changed, 63 insertions(+), 21 deletions(-) diff --git a/kernel/filesystem/disk.cpp b/kernel/filesystem/disk.cpp index 1ab8a13e..c6e5476f 100644 --- a/kernel/filesystem/disk.cpp +++ b/kernel/filesystem/disk.cpp @@ -37,7 +37,10 @@ void disk_write(const void *buffer, uint32_t sector, uint32_t count){ } void disk_read(void *buffer, uint32_t sector, uint32_t count){ - vblk_read(buffer, sector, count); + if (BOARD_TYPE == 2) + sdhci_driver.read(buffer, sector, count); + else + vblk_read(buffer, sector, count); } void* read_file(const char *path){ diff --git a/kernel/filesystem/exfat.c b/kernel/filesystem/exfat.c index f9e39267..838458a2 100644 --- a/kernel/filesystem/exfat.c +++ b/kernel/filesystem/exfat.c @@ -200,8 +200,8 @@ void ef_read_FAT(uint32_t location, uint32_t size, uint8_t count){ disk_read((void*)fat, location, size); kprintf("FAT: %x (%x)",location*512,size * count * 512); uint32_t total_entries = (size * count * 512) / 4; - for (uint32_t i = 0; i < total_entries; i++) - if (fat[i] != 0) kprintf("[%i] = %x", i, fat[i]); + // for (uint32_t i = 0; i < total_entries; i++) + // if (fat[i] != 0) kprintf("[%i] = %x", i, fat[i]); } bool ef_init(){ diff --git a/kernel/filesystem/sdhci.cpp b/kernel/filesystem/sdhci.cpp index 79605682..430bf93d 100644 --- a/kernel/filesystem/sdhci.cpp +++ b/kernel/filesystem/sdhci.cpp @@ -3,6 +3,8 @@ #include "hw/hw.h" #include "mailbox/mailbox.h" #include "syscalls/syscalls.h" +#include "memory/mmu.h" +#include "std/memfunctions.h" #define CMD_INDEX(x) ((x) << 8) #define RESP_TYPE(x) (x) @@ -14,15 +16,19 @@ #define IF_COND (CMD_INDEX(8) | RESP_TYPE(2) | CRC_ENABLE | IDX_ENABLE) #define RCA (CMD_INDEX(3) | RESP_TYPE(2) | CRC_ENABLE) #define APP (CMD_INDEX(55) | RESP_TYPE(2) | CRC_ENABLE | IDX_ENABLE) +#define SELECT_CARD (CMD_INDEX(7) | RESP_TYPE(3) | CRC_ENABLE | IDX_ENABLE) #define OCR (CMD_INDEX(41) | RESP_TYPE(2)) +#define READ_ONE (CMD_INDEX(17) | RESP_TYPE(2) | CRC_ENABLE | IS_DATA) +#define READ_MULTIPLE (CMD_INDEX(18) | RESP_TYPE(2) | CRC_ENABLE | IS_DATA) +#define STOP_TRANSMISSION (CMD_INDEX(12) | RESP_TYPE(2) | CRC_ENABLE) bool SDHCI::wait(uint32_t *reg, uint32_t expected_value, bool match, uint32_t timeout){ bool condition; do { - delay(140); + delay(1); timeout--; if (timeout == 0){ - kprintf("Command timed out. Final value %x vs %x on %x",*reg,expected_value, (uintptr_t)reg); + kprintf("Command timed out"); return false; } condition = *reg & expected_value; @@ -81,7 +87,7 @@ uint32_t SDHCI::clock_divider(uint32_t target_rate) { bool SDHCI::switch_clock_rate(uint32_t target_rate) { uint32_t div = clock_divider(target_rate); - wait(®s->status,0b11, false); + if (!wait(®s->status,0b11, false)) return false; kprintf("Clock divider %i",div); @@ -120,7 +126,7 @@ bool SDHCI::setup_clock(){ regs->ctrl1 |= (11 << 16); regs->ctrl1 |= (1 << 2); - wait(®s->ctrl1, (1 << 1)); + if (!wait(®s->ctrl1, (1 << 1))) return false; delay(30); @@ -143,10 +149,13 @@ void SDHCI::dump(){ bool SDHCI::init() { if (!SDHCI_BASE) return false; + + register_device_memory(SDHCI_BASE, SDHCI_BASE); + regs = (sdhci_regs*)SDHCI_BASE; regs->ctrl1 |= (1 << 24);//Reset - wait(®s->ctrl1,(1 << 24), false); + if (!wait(®s->ctrl1,(1 << 24), false)) return false; if (RPI_BOARD == 4){ regs->ctrl0 |= 0x0F << 8;//VDD1 bus power @@ -190,10 +199,6 @@ bool SDHCI::init() { kprintf("[SDHCI] V2 = %i",v2_card); - if (!true) {//usable_card - return false; - } - while (true){ if (!issue_app_command(OCR, 0xFF8000 | (v2_card << 30))){ kprintf("[SDHCI error] Get OCR Failed"); @@ -217,13 +222,11 @@ bool SDHCI::init() { return false; } - kprintf("[SDHCI] RCA %x",(regs->resp0 >> 16) & 0xFFFF); + rca = (regs->resp0 >> 16) & 0xFFFF; + kprintf("[SDHCI] RCA %x",rca); - // if (!select_card()) { - // return false; - // } - - if (!true) {//set_scr + if (!issue_command(SELECT_CARD, rca << 16)){ + kprintf("[SDHCI error] Failed to select card"); return false; } @@ -246,7 +249,6 @@ bool SDHCI::issue_command(uint32_t cmd, uint32_t arg, uint32_t flags) { regs->interrupt = 0xFFFFFFFF; - regs->blksize_count = 0; regs->arg1 = arg; regs->cmd_transfmode = (cmd << 16) | flags; @@ -263,4 +265,40 @@ bool SDHCI::issue_command(uint32_t cmd, uint32_t arg, uint32_t flags) { if (!(regs->interrupt & 0x0001)) return false;//No finish return true; -} \ No newline at end of file +} + +bool SDHCI::read(void *buffer, uint32_t sector, uint32_t count){ + bool multiple = count > 1; + regs->blksize_count = (count << 16) | 512; + uint32_t command = multiple ? READ_MULTIPLE : READ_ONE; + uint32_t flags = multiple ? 0b110110 : 0b010000; + kprintf("Direction %b",(flags >> 4) & 1); + for (int i = 5; i >= 0; i--){ + if (issue_command(command, sector, flags)) break; + if (i == 0) { kprintf("[SDHCI read timeout]"); return false; } + delay(500); + } + + uint32_t* dest = (uint32_t*)buffer; + for (uint32_t i = 0; i < count; i++) { + if (!wait(®s->interrupt,(1 << 5) | 0x8000)){ + kprintf("Read operation timed out on block %i",i); + return false; + } + for (int j = 0; j < 128; j++) + dest[(i * 128) + j] = regs->data; + regs->interrupt = (1 << 5); + } + + wait(®s->interrupt, 1 << 1); + regs->interrupt = (1 << 1); + + kprintf("Finished reading"); + + if (multiple) + issue_command(STOP_TRANSMISSION, 0, 0); + + return true; +} + +//Write CMD (24 block, 25 multiple) \ No newline at end of file diff --git a/kernel/filesystem/sdhci.hpp b/kernel/filesystem/sdhci.hpp index b559139a..d5640563 100644 --- a/kernel/filesystem/sdhci.hpp +++ b/kernel/filesystem/sdhci.hpp @@ -27,7 +27,7 @@ class SDHCI { public: bool init(); void write(void *buffer, uint32_t sector, uint32_t count); - void read(void *buffer, uint32_t sector, uint32_t count); + bool read(void *buffer, uint32_t sector, uint32_t count); private: sdhci_regs* regs; bool issue_command(uint32_t cmd_index, uint32_t arg, uint32_t flags = 0); @@ -38,4 +38,5 @@ class SDHCI { void dump(); bool wait(uint32_t *reg, uint32_t expected_value, bool match = true, uint32_t timeout = 2000); uint32_t clock_rate; + uint32_t rca; }; \ No newline at end of file From f293ef678d0862cfc18dc910507a8ae878381835 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 27 Jun 2025 00:00:00 +0000 Subject: [PATCH 24/79] Fixed typo in blk --- kernel/filesystem/virtio_blk_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/filesystem/virtio_blk_pci.c b/kernel/filesystem/virtio_blk_pci.c index 88e0aab4..9df79f8c 100644 --- a/kernel/filesystem/virtio_blk_pci.c +++ b/kernel/filesystem/virtio_blk_pci.c @@ -40,7 +40,7 @@ void vblk_disk_verbose(){ #define kprintfv(fmt, ...) \ ({ \ - if (mmu_verbose){\ + if (blk_disk_enable_verbose){\ uint64_t _args[] = { __VA_ARGS__ }; \ kprintf_args_raw((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ }\ From 42c0cd2fb868ef2ad28d9a99ce04de1a0acccb61 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 27 Jun 2025 00:00:00 +0000 Subject: [PATCH 25/79] Disk read fix --- kernel/filesystem/disk.cpp | 5 ++- kernel/filesystem/sdhci.cpp | 86 +++++++++++++++++++++---------------- kernel/filesystem/sdhci.hpp | 3 +- 3 files changed, 55 insertions(+), 39 deletions(-) diff --git a/kernel/filesystem/disk.cpp b/kernel/filesystem/disk.cpp index c6e5476f..03a3d2d2 100644 --- a/kernel/filesystem/disk.cpp +++ b/kernel/filesystem/disk.cpp @@ -5,10 +5,14 @@ #include "hw/hw.h" static bool disk_enable_verbose; +SDHCI sdhci_driver; void disk_verbose(){ disk_enable_verbose = true; vblk_disk_verbose(); + if (BOARD_TYPE == 2){ + sdhci_driver.enable_verbose(); + } } #define kprintfv(fmt, ...) \ @@ -19,7 +23,6 @@ void disk_verbose(){ }\ }) -SDHCI sdhci_driver; bool find_disk(){ if (BOARD_TYPE == 2) diff --git a/kernel/filesystem/sdhci.cpp b/kernel/filesystem/sdhci.cpp index 430bf93d..99588ad5 100644 --- a/kernel/filesystem/sdhci.cpp +++ b/kernel/filesystem/sdhci.cpp @@ -21,6 +21,19 @@ #define READ_ONE (CMD_INDEX(17) | RESP_TYPE(2) | CRC_ENABLE | IS_DATA) #define READ_MULTIPLE (CMD_INDEX(18) | RESP_TYPE(2) | CRC_ENABLE | IS_DATA) #define STOP_TRANSMISSION (CMD_INDEX(12) | RESP_TYPE(2) | CRC_ENABLE) +#define SET_BLOCKLEN (CMD_INDEX(16) | RESP_TYPE(2) | CRC_ENABLE) + +#define kprintfv(fmt, ...) \ + ({ \ + if (verbose){\ + uint64_t _args[] = { __VA_ARGS__ }; \ + kprintf_args_raw((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ + }\ + }) + +void SDHCI::enable_verbose(){ + verbose = true; +} bool SDHCI::wait(uint32_t *reg, uint32_t expected_value, bool match, uint32_t timeout){ bool condition; @@ -28,13 +41,12 @@ bool SDHCI::wait(uint32_t *reg, uint32_t expected_value, bool match, uint32_t ti delay(1); timeout--; if (timeout == 0){ - kprintf("Command timed out"); + kprintf("[SDHCI] Command timed out"); return false; } condition = *reg & expected_value; } while (match ^ condition); - kprintf("Finished with %i",timeout); return true; } @@ -89,8 +101,6 @@ bool SDHCI::switch_clock_rate(uint32_t target_rate) { if (!wait(®s->status,0b11, false)) return false; - kprintf("Clock divider %i",div); - regs->ctrl1 &= ~(1 << 2); delay(3); @@ -137,16 +147,6 @@ bool SDHCI::setup_clock(){ return true; } -void SDHCI::dump(){ - kprintf("SD HCI Register dump\n*-*-*"); - for (size_t i = 0; i <= 0xFC; i+= 4){ - uint32_t value = *(uint32_t*)(SDHCI_BASE + i); - if (value) - kprintf("[%x] %x",i,value); - } - kprintf("*-*-*"); -} - bool SDHCI::init() { if (!SDHCI_BASE) return false; @@ -162,7 +162,7 @@ bool SDHCI::init() { delay(3); } - kprintf("[SDHCI] Controller reset"); + kprintfv("[SDHCI] Controller reset"); setup_clock(); @@ -178,17 +178,17 @@ bool SDHCI::init() { kprintf("[SDHCI error] Failed setting to idle"); return false; } - kprintf("[SDHCI] Idle"); + kprintfv("[SDHCI] Idle"); switch_clock_rate(25000000); bool v2_card = 0; if (!issue_command(IF_COND, 0)){ if (!(regs->interrupt & 0x10000)){ - kprintf("Error in IFCOND"); + kprintf("[SDHCI error] IFCOND error"); return false; } - kprintf("[SDHCI error] Timeout on IFCOND. Defaulting to V1"); + kprintfv("[SDHCI] Timeout on IFCOND. Defaulting to V1"); } else { if ((regs->resp0 & 0xFF) != 0xAA) { kprintf("[SDHCI error] IFCOND pattern mismatch"); @@ -197,7 +197,7 @@ bool SDHCI::init() { v2_card = true; } - kprintf("[SDHCI] V2 = %i",v2_card); + kprintfv("[SDHCI] V2 = %i",v2_card); while (true){ if (!issue_app_command(OCR, 0xFF8000 | (v2_card << 30))){ @@ -208,7 +208,7 @@ bool SDHCI::init() { else delay(500); } - kprintf("[SDHCI] OCR %x",regs->resp0); + kprintfv("[SDHCI] OCR %x",regs->resp0); delay(1000); @@ -223,13 +223,18 @@ bool SDHCI::init() { } rca = (regs->resp0 >> 16) & 0xFFFF; - kprintf("[SDHCI] RCA %x",rca); + kprintfv("[SDHCI] RCA %x",rca); if (!issue_command(SELECT_CARD, rca << 16)){ kprintf("[SDHCI error] Failed to select card"); return false; } + if (!issue_command(SET_BLOCKLEN, 512)){ + kprintf("[SDHCI error] Failed to set block length"); + return false; + } + return true; } @@ -243,7 +248,7 @@ bool SDHCI::issue_app_command(uint32_t cmd, uint32_t arg, uint32_t flags) { bool SDHCI::issue_command(uint32_t cmd, uint32_t arg, uint32_t flags) { if (!wait(®s->status, 0b11, false)) { - kprintf("[SDHCI] Timeout waiting for CMD/DAT inhibit"); + kprintf("[SDHCI error] Timeout waiting for CMD/DAT inhibit"); return false; } @@ -252,14 +257,14 @@ bool SDHCI::issue_command(uint32_t cmd, uint32_t arg, uint32_t flags) { regs->arg1 = arg; regs->cmd_transfmode = (cmd << 16) | flags; - kprintf("[SDHCI] Sent command %b.",(cmd << 16) | flags); + kprintfv("[SDHCI] Sent command %b.",(cmd << 16) | flags); if (!wait(®s->interrupt,0x8001)) { kprintf("[SDHCI warning] Issue command timeout"); return false; } - kprintf("[SDHCI] Command finished %x",regs->interrupt); + kprintfv("[SDHCI] Command finished %x",regs->interrupt); if (regs->interrupt & 0x8000) return false;//Error if (!(regs->interrupt & 0x0001)) return false;//No finish @@ -272,33 +277,40 @@ bool SDHCI::read(void *buffer, uint32_t sector, uint32_t count){ regs->blksize_count = (count << 16) | 512; uint32_t command = multiple ? READ_MULTIPLE : READ_ONE; uint32_t flags = multiple ? 0b110110 : 0b010000; - kprintf("Direction %b",(flags >> 4) & 1); for (int i = 5; i >= 0; i--){ - if (issue_command(command, sector, flags)) break; - if (i == 0) { kprintf("[SDHCI read timeout]"); return false; } + //TODO: Byte addressing works here, instead of block addressing. Not sure that's normal or if it's card-specific + if (issue_command(command, sector * 512, flags)) break; + if (i == 0) { kprintf("[SDHCI error] read request timeout"); return false; } delay(500); } uint32_t* dest = (uint32_t*)buffer; for (uint32_t i = 0; i < count; i++) { if (!wait(®s->interrupt,(1 << 5) | 0x8000)){ - kprintf("Read operation timed out on block %i",i); + kprintf("[SDHCI error] Read operation timed out on block %i",i); + memset(buffer,0,count * 128); return false; } + + regs->interrupt = 0xFFFFFFFF; + for (int j = 0; j < 128; j++) dest[(i * 128) + j] = regs->data; - regs->interrupt = (1 << 5); + + if (regs->interrupt & (1 << 1)) + break; } - - wait(®s->interrupt, 1 << 1); - regs->interrupt = (1 << 1); - - kprintf("Finished reading"); - if (multiple) - issue_command(STOP_TRANSMISSION, 0, 0); + if (multiple) { + if (!wait(®s->interrupt, (1 << 1))) { + kprintf("[SDHCI error] Timed out waiting for DATA_DONE"); + return false; + } + regs->interrupt = 0xFFFFFFFF; + } return true; } -//Write CMD (24 block, 25 multiple) \ No newline at end of file +//TODO: Write (CMD24 block, CMD25 multiple). Read can be generalized. +//TODO: DMA \ No newline at end of file diff --git a/kernel/filesystem/sdhci.hpp b/kernel/filesystem/sdhci.hpp index d5640563..10a82218 100644 --- a/kernel/filesystem/sdhci.hpp +++ b/kernel/filesystem/sdhci.hpp @@ -28,6 +28,7 @@ class SDHCI { bool init(); void write(void *buffer, uint32_t sector, uint32_t count); bool read(void *buffer, uint32_t sector, uint32_t count); + void enable_verbose(); private: sdhci_regs* regs; bool issue_command(uint32_t cmd_index, uint32_t arg, uint32_t flags = 0); @@ -35,8 +36,8 @@ class SDHCI { bool setup_clock(); uint32_t clock_divider(uint32_t target_rate); bool switch_clock_rate(uint32_t target_rate); - void dump(); bool wait(uint32_t *reg, uint32_t expected_value, bool match = true, uint32_t timeout = 2000); uint32_t clock_rate; uint32_t rca; + bool verbose; }; \ No newline at end of file From 88e7567fa1f9caabcf5cfe89b3271f2a5105615f Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 27 Jun 2025 00:00:00 +0000 Subject: [PATCH 26/79] Wait/delay in async.h --- kernel/async.c | 33 +++++++++++++++++++++++++++++++++ kernel/async.h | 12 ++++++++++++ kernel/filesystem/sdhci.cpp | 30 ++++++++---------------------- kernel/filesystem/sdhci.hpp | 1 - kernel/hw/hw.c | 16 ---------------- kernel/hw/hw.h | 10 +--------- 6 files changed, 54 insertions(+), 48 deletions(-) create mode 100644 kernel/async.c create mode 100644 kernel/async.h diff --git a/kernel/async.c b/kernel/async.c new file mode 100644 index 00000000..0cd27ce0 --- /dev/null +++ b/kernel/async.c @@ -0,0 +1,33 @@ +#include "async.h" +#include "console/kio.h" + +void delay(uint32_t ms) { + uint64_t freq; + asm volatile ("mrs %0, cntfrq_el0" : "=r"(freq)); + + uint64_t ticks; + asm volatile ("mrs %0, cntpct_el0" : "=r"(ticks)); + + uint64_t target = ticks + (freq / 1000) * ms; + + while (1) { + uint64_t now; + asm volatile ("mrs %0, cntpct_el0" : "=r"(now)); + if (now >= target) break; + } +} + +bool wait(uint32_t *reg, uint32_t expected_value, bool match, uint32_t timeout){ + bool condition; + do { + delay(1); + timeout--; + if (timeout == 0){ + kprintf("Wait timed out"); + return false; + } + condition = (*reg & expected_value) != 0; + } while ((match > 0) ^ condition); + + return true; +} \ No newline at end of file diff --git a/kernel/async.h b/kernel/async.h new file mode 100644 index 00000000..8eaab384 --- /dev/null +++ b/kernel/async.h @@ -0,0 +1,12 @@ +#pragma once + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif +void delay(uint32_t count); +bool wait(uint32_t *reg, uint32_t expected_value, bool match, uint32_t timeout); +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/kernel/filesystem/sdhci.cpp b/kernel/filesystem/sdhci.cpp index 99588ad5..a4aa34d0 100644 --- a/kernel/filesystem/sdhci.cpp +++ b/kernel/filesystem/sdhci.cpp @@ -5,6 +5,7 @@ #include "syscalls/syscalls.h" #include "memory/mmu.h" #include "std/memfunctions.h" +#include "async.h" #define CMD_INDEX(x) ((x) << 8) #define RESP_TYPE(x) (x) @@ -35,21 +36,6 @@ void SDHCI::enable_verbose(){ verbose = true; } -bool SDHCI::wait(uint32_t *reg, uint32_t expected_value, bool match, uint32_t timeout){ - bool condition; - do { - delay(1); - timeout--; - if (timeout == 0){ - kprintf("[SDHCI] Command timed out"); - return false; - } - condition = *reg & expected_value; - } while (match ^ condition); - - return true; -} - uint32_t SDHCI::clock_divider(uint32_t target_rate) { uint32_t target_div = 1; @@ -99,7 +85,7 @@ uint32_t SDHCI::clock_divider(uint32_t target_rate) { bool SDHCI::switch_clock_rate(uint32_t target_rate) { uint32_t div = clock_divider(target_rate); - if (!wait(®s->status,0b11, false)) return false; + if (!wait(®s->status,0b11, false, 2000)) return false; regs->ctrl1 &= ~(1 << 2); @@ -136,7 +122,7 @@ bool SDHCI::setup_clock(){ regs->ctrl1 |= (11 << 16); regs->ctrl1 |= (1 << 2); - if (!wait(®s->ctrl1, (1 << 1))) return false; + if (!wait(®s->ctrl1, (1 << 1), true, 2000)) return false; delay(30); @@ -155,7 +141,7 @@ bool SDHCI::init() { regs = (sdhci_regs*)SDHCI_BASE; regs->ctrl1 |= (1 << 24);//Reset - if (!wait(®s->ctrl1,(1 << 24), false)) return false; + if (!wait(®s->ctrl1,(1 << 24), false, 2000)) return false; if (RPI_BOARD == 4){ regs->ctrl0 |= 0x0F << 8;//VDD1 bus power @@ -247,7 +233,7 @@ bool SDHCI::issue_app_command(uint32_t cmd, uint32_t arg, uint32_t flags) { bool SDHCI::issue_command(uint32_t cmd, uint32_t arg, uint32_t flags) { - if (!wait(®s->status, 0b11, false)) { + if (!wait(®s->status, 0b11, false, 2000)) { kprintf("[SDHCI error] Timeout waiting for CMD/DAT inhibit"); return false; } @@ -259,7 +245,7 @@ bool SDHCI::issue_command(uint32_t cmd, uint32_t arg, uint32_t flags) { kprintfv("[SDHCI] Sent command %b.",(cmd << 16) | flags); - if (!wait(®s->interrupt,0x8001)) { + if (!wait(®s->interrupt,0x8001, true, 2000)) { kprintf("[SDHCI warning] Issue command timeout"); return false; } @@ -286,7 +272,7 @@ bool SDHCI::read(void *buffer, uint32_t sector, uint32_t count){ uint32_t* dest = (uint32_t*)buffer; for (uint32_t i = 0; i < count; i++) { - if (!wait(®s->interrupt,(1 << 5) | 0x8000)){ + if (!wait(®s->interrupt,(1 << 5) | 0x8000, true, 2000)){ kprintf("[SDHCI error] Read operation timed out on block %i",i); memset(buffer,0,count * 128); return false; @@ -302,7 +288,7 @@ bool SDHCI::read(void *buffer, uint32_t sector, uint32_t count){ } if (multiple) { - if (!wait(®s->interrupt, (1 << 1))) { + if (!wait(®s->interrupt, (1 << 1), true, 2000)) { kprintf("[SDHCI error] Timed out waiting for DATA_DONE"); return false; } diff --git a/kernel/filesystem/sdhci.hpp b/kernel/filesystem/sdhci.hpp index 10a82218..c2ba2037 100644 --- a/kernel/filesystem/sdhci.hpp +++ b/kernel/filesystem/sdhci.hpp @@ -36,7 +36,6 @@ class SDHCI { bool setup_clock(); uint32_t clock_divider(uint32_t target_rate); bool switch_clock_rate(uint32_t target_rate); - bool wait(uint32_t *reg, uint32_t expected_value, bool match = true, uint32_t timeout = 2000); uint32_t clock_rate; uint32_t rca; bool verbose; diff --git a/kernel/hw/hw.c b/kernel/hw/hw.c index 038a10d2..d28418da 100644 --- a/kernel/hw/hw.c +++ b/kernel/hw/hw.c @@ -54,20 +54,4 @@ void detect_hardware(){ void print_hardware(){ kprintf("Board type %i",BOARD_TYPE); -} - -void delay(uint32_t ms) { - uint64_t freq; - asm volatile ("mrs %0, cntfrq_el0" : "=r"(freq)); - - uint64_t ticks; - asm volatile ("mrs %0, cntpct_el0" : "=r"(ticks)); - - uint64_t target = ticks + (freq / 1000) * ms; - - while (1) { - uint64_t now; - asm volatile ("mrs %0, cntpct_el0" : "=r"(now)); - if (now >= target) break; - } } \ No newline at end of file diff --git a/kernel/hw/hw.h b/kernel/hw/hw.h index d2f01e68..767cbe1c 100644 --- a/kernel/hw/hw.h +++ b/kernel/hw/hw.h @@ -26,12 +26,4 @@ extern uintptr_t SDHCI_BASE; extern uint8_t RPI_BOARD; void detect_hardware(); -void print_hardware(); - -#ifdef __cplusplus -extern "C" { -#endif -void delay(uint32_t count); -#ifdef __cplusplus -} -#endif \ No newline at end of file +void print_hardware(); \ No newline at end of file From 597f8f33cfbfd18ae5913c5b8293066e91dceb40 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 28 Jun 2025 00:00:00 +0000 Subject: [PATCH 27/79] Adapted to run script fixes from main --- run_rpi | 18 ++++++++++++++++-- run_virtio | 45 +++++++++++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/run_rpi b/run_rpi index d3bcbc09..c3eeaa7b 100755 --- a/run_rpi +++ b/run_rpi @@ -7,12 +7,26 @@ if [ "$1" = "debug" ]; then ARGS="-monitor unix:/tmp/qemu-monitor-socket,server,nowait -s -S" fi -qemu-system-aarch64 \ +OS_TYPE="$(uname)" + +if [[ "$OS_TYPE" == "Darwin" ]]; then + NETARG="vmnet-bridged,id=net0,ifname=en0" + PRIVILEGE="sudo" +elif [[ "$OS_TYPE" == "Linux" ]]; then + NETARG="user,id=net0" + PRIVILEGE="" +else + echo "Unknown OS: $OS_TYPE" >&2 + exit 1 +fi + +$PRIVILEGE qemu-system-aarch64 \ -M raspi4b \ -kernel kernel.elf \ -display sdl \ -device sd-card,drive=sd -drive id=sd,format=raw,file=disk.img,if=none \ --netdev vmnet-bridged,id=net0,ifname=en0 \ +-netdev $NETARG \ -serial mon:stdio \ +-device usb-kbd \ -d guest_errors \ $ARGS diff --git a/run_virtio b/run_virtio index 65803e2e..3e1101f1 100755 --- a/run_virtio +++ b/run_virtio @@ -15,19 +15,32 @@ if echo "$XHCI_CAPABILITIES" | grep -q "msi "; then MSI_CAPABILITIES="msi=on,msix=off," fi -qemu-system-aarch64 \ --M virt \ --cpu cortex-a72 \ --m 512M \ --kernel kernel.elf \ --device virtio-gpu-pci \ --display sdl \ --netdev vmnet-bridged,id=net0,ifname=en0 \ --device virtio-net-pci,netdev=net0 \ --serial mon:stdio \ --drive file=disk.img,if=none,format=raw,id=hd0 \ --device virtio-blk-pci,drive=hd0 \ --device qemu-xhci,${MSI_CAPABILITIES}id=usb \ --device usb-kbd,bus=usb.0 \ --d guest_errors \ -$ARGS \ No newline at end of file +OS_TYPE="$(uname)" + +if [[ "$OS_TYPE" == "Darwin" ]]; then + NETARG="vmnet-bridged,id=net0,ifname=en0" + PRIVILEGE="sudo" +elif [[ "$OS_TYPE" == "Linux" ]]; then + NETARG="user,id=net0" + PRIVILEGE="" +else + echo "Unknown OS: $OS_TYPE" >&2 + exit 1 +fi + +$PRIVILEGE qemu-system-aarch64 \ + -M virt \ + -cpu cortex-a72 \ + -m 512M \ + -kernel kernel.elf \ + -device virtio-gpu-pci \ + -display sdl \ + -netdev $NETARG \ + -device virtio-net-pci,netdev=net0 \ + -serial mon:stdio \ + -drive file=disk.img,if=none,format=raw,id=hd0 \ + -device virtio-blk-pci,drive=hd0 \ + -device qemu-xhci,${MSI_CAPABILITIES}id=usb \ + -device usb-kbd,bus=usb.0 \ + -d guest_errors \ + $ARGS \ No newline at end of file From 5a20dba8ab5f1dc51617a9b5b91d37d11c372e64 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 28 Jun 2025 00:00:00 +0000 Subject: [PATCH 28/79] Async value fix --- kernel/async.c | 2 +- kernel/filesystem/sdhci.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/async.c b/kernel/async.c index 0cd27ce0..61473e45 100644 --- a/kernel/async.c +++ b/kernel/async.c @@ -26,7 +26,7 @@ bool wait(uint32_t *reg, uint32_t expected_value, bool match, uint32_t timeout){ kprintf("Wait timed out"); return false; } - condition = (*reg & expected_value) != 0; + condition = (*reg & expected_value) == expected_value; } while ((match > 0) ^ condition); return true; diff --git a/kernel/filesystem/sdhci.cpp b/kernel/filesystem/sdhci.cpp index a4aa34d0..c19432ef 100644 --- a/kernel/filesystem/sdhci.cpp +++ b/kernel/filesystem/sdhci.cpp @@ -245,8 +245,8 @@ bool SDHCI::issue_command(uint32_t cmd, uint32_t arg, uint32_t flags) { kprintfv("[SDHCI] Sent command %b.",(cmd << 16) | flags); - if (!wait(®s->interrupt,0x8001, true, 2000)) { - kprintf("[SDHCI warning] Issue command timeout"); + if (!wait(®s->interrupt,0x1, true, 2000)) { + kprintf("[SDHCI warning] Issue command timeout %x",regs->interrupt); return false; } @@ -272,8 +272,8 @@ bool SDHCI::read(void *buffer, uint32_t sector, uint32_t count){ uint32_t* dest = (uint32_t*)buffer; for (uint32_t i = 0; i < count; i++) { - if (!wait(®s->interrupt,(1 << 5) | 0x8000, true, 2000)){ - kprintf("[SDHCI error] Read operation timed out on block %i",i); + if (!wait(®s->interrupt,(1 << 5), true, 2000)){ + kprintf("[SDHCI error] Read operation timed out on block %i %x",i,regs->interrupt); memset(buffer,0,count * 128); return false; } From 34114a332a1a544ae90e24bc5b747b86c15ba7ed Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 28 Jun 2025 00:00:00 +0000 Subject: [PATCH 29/79] DWC2 port reset --- kernel/input/dwc2.c | 75 +++++++++++++++++++++++++++++++++++++++++++++ kernel/input/dwc2.h | 3 ++ 2 files changed, 78 insertions(+) create mode 100644 kernel/input/dwc2.c create mode 100644 kernel/input/dwc2.h diff --git a/kernel/input/dwc2.c b/kernel/input/dwc2.c new file mode 100644 index 00000000..5359238f --- /dev/null +++ b/kernel/input/dwc2.c @@ -0,0 +1,75 @@ +#include "dwc2.h" +#include "async.h" +#include "console/kio.h" + +#define DWC2_BASE 0xFE980000 + +typedef struct { + uint32_t gotgctl; + uint32_t gotgint; + uint32_t gahbcfg; + uint32_t gusbcfg; + uint32_t grstctl; + uint32_t gintsts; + uint32_t gintmsk; + uint32_t grxstsr; + uint32_t grxstsp; + uint32_t grxfsiz; + uint32_t gnptxfsiz; + uint32_t gnptxsts; +} dwc2_regs; + +typedef struct { + uint32_t hstcfg; + uint32_t frminterval; + uint32_t frmnum; + uint32_t rsvd; + uint32_t ptx_fifo; + uint32_t allchan_int; + uint32_t allchan_int_mask; + uint32_t frmlst_base; + uint32_t rsvd2[8]; + uint32_t port; +} dwc2_host; + +bool dwc2_init() { + + dwc2_regs *dwc2 = (dwc2_regs*)DWC2_BASE; + dwc2_host *host = (dwc2_host*)(DWC2_BASE + 0x400); + + *(uint32_t*)(DWC2_BASE + 0xE00) = 0;//Power reset + + dwc2->grstctl |= 1; + if (!wait(&dwc2->grstctl, 1, false, 2000)){ + kprintf("[DWC2] Failed to reset"); + return false; + } + + dwc2->gusbcfg &= ~(1 << 30);//Device mode disable + dwc2->gusbcfg |= (1 << 29);//Host mode enable + + delay(200); + + dwc2->gintmsk = 0xffffffff; + + host->port |= (1 << 12); + + if (!wait(&host->port, 1, true, 2000)){ + kprintf("[DWC2] No device connected %x",host->port); + return false; + } + + delay(100); + + host->port &= ~0b101110; + host->port |= (1 << 8); + + delay(50); + + host->port &= ~0b101110; + host->port &= ~(1 << 8); + + kprintf("Port reset %x",host->port); + + return true; +} \ No newline at end of file diff --git a/kernel/input/dwc2.h b/kernel/input/dwc2.h new file mode 100644 index 00000000..425c6f56 --- /dev/null +++ b/kernel/input/dwc2.h @@ -0,0 +1,3 @@ +#include "types.h" + +bool dwc2_init(); \ No newline at end of file From 0ac9de9eb04465c22280ba74da81a954919814e6 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 28 Jun 2025 00:00:00 +0000 Subject: [PATCH 30/79] Wait for port clear --- kernel/input/dwc2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/input/dwc2.c b/kernel/input/dwc2.c index 5359238f..574a270f 100644 --- a/kernel/input/dwc2.c +++ b/kernel/input/dwc2.c @@ -69,6 +69,8 @@ bool dwc2_init() { host->port &= ~0b101110; host->port &= ~(1 << 8); + wait(&host->port, (1 << 8), false, 2000); + kprintf("Port reset %x",host->port); return true; From 614800f268e82b6b25866c78e3fc21c8a7c46e17 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sun, 29 Jun 2025 00:00:00 +0000 Subject: [PATCH 31/79] DWC2 cpp driver with device recognition (not working yet) --- kernel/console/kconsole/kconsole.cpp | 1 - kernel/input/dwc2.c | 77 ------- kernel/input/dwc2.cpp | 198 ++++++++++++++++++ kernel/input/dwc2.h | 3 - kernel/input/dwc2.hpp | 56 +++++ .../{input_dispatch.c => input_dispatch.cpp} | 10 + kernel/input/input_dispatch.h | 2 + kernel/kernel.c | 8 +- shared/std/string.h | 10 +- 9 files changed, 278 insertions(+), 87 deletions(-) delete mode 100644 kernel/input/dwc2.c create mode 100644 kernel/input/dwc2.cpp delete mode 100644 kernel/input/dwc2.h create mode 100644 kernel/input/dwc2.hpp rename kernel/input/{input_dispatch.c => input_dispatch.cpp} (93%) diff --git a/kernel/console/kconsole/kconsole.cpp b/kernel/console/kconsole/kconsole.cpp index 5690e221..948ddf4c 100644 --- a/kernel/console/kconsole/kconsole.cpp +++ b/kernel/console/kconsole/kconsole.cpp @@ -22,7 +22,6 @@ bool KernelConsole::check_ready(){ void KernelConsole::resize() { gpu_size screen = gpu_get_screen_size(); - uart_puthex(screen.width); columns = screen.width / char_width; rows = screen.height / char_height; diff --git a/kernel/input/dwc2.c b/kernel/input/dwc2.c deleted file mode 100644 index 574a270f..00000000 --- a/kernel/input/dwc2.c +++ /dev/null @@ -1,77 +0,0 @@ -#include "dwc2.h" -#include "async.h" -#include "console/kio.h" - -#define DWC2_BASE 0xFE980000 - -typedef struct { - uint32_t gotgctl; - uint32_t gotgint; - uint32_t gahbcfg; - uint32_t gusbcfg; - uint32_t grstctl; - uint32_t gintsts; - uint32_t gintmsk; - uint32_t grxstsr; - uint32_t grxstsp; - uint32_t grxfsiz; - uint32_t gnptxfsiz; - uint32_t gnptxsts; -} dwc2_regs; - -typedef struct { - uint32_t hstcfg; - uint32_t frminterval; - uint32_t frmnum; - uint32_t rsvd; - uint32_t ptx_fifo; - uint32_t allchan_int; - uint32_t allchan_int_mask; - uint32_t frmlst_base; - uint32_t rsvd2[8]; - uint32_t port; -} dwc2_host; - -bool dwc2_init() { - - dwc2_regs *dwc2 = (dwc2_regs*)DWC2_BASE; - dwc2_host *host = (dwc2_host*)(DWC2_BASE + 0x400); - - *(uint32_t*)(DWC2_BASE + 0xE00) = 0;//Power reset - - dwc2->grstctl |= 1; - if (!wait(&dwc2->grstctl, 1, false, 2000)){ - kprintf("[DWC2] Failed to reset"); - return false; - } - - dwc2->gusbcfg &= ~(1 << 30);//Device mode disable - dwc2->gusbcfg |= (1 << 29);//Host mode enable - - delay(200); - - dwc2->gintmsk = 0xffffffff; - - host->port |= (1 << 12); - - if (!wait(&host->port, 1, true, 2000)){ - kprintf("[DWC2] No device connected %x",host->port); - return false; - } - - delay(100); - - host->port &= ~0b101110; - host->port |= (1 << 8); - - delay(50); - - host->port &= ~0b101110; - host->port &= ~(1 << 8); - - wait(&host->port, (1 << 8), false, 2000); - - kprintf("Port reset %x",host->port); - - return true; -} \ No newline at end of file diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp new file mode 100644 index 00000000..8b554d48 --- /dev/null +++ b/kernel/input/dwc2.cpp @@ -0,0 +1,198 @@ +#include "dwc2.hpp" +#include "async.h" +#include "console/kio.h" +#include "memory/page_allocator.h" +#include "xhci_types.h"//TODO: split into xhci and USB types +#include "std/string.h" + +#define DWC2_BASE 0xFE980000 + +dwc2_host_channel* DWC2Driver::get_channel(uint16_t channel){ + return (dwc2_host_channel *)(DWC2_BASE + 0x500 + (channel * 0x20)); +} + +void DWC2Driver::assign_channel(dwc2_host_channel* channel, uint8_t device, uint8_t endpoint, uint8_t ep_type){ + channel->cchar = (device << 22) | (endpoint << 11) | (ep_type << 18); +} + +uint16_t DWC2Driver::packet_size(uint16_t speed){ + switch (speed) { + case 2: return 8;//Low + case 1: + case 3: return 64;//High & full + case 4: + case 5: + default: return 512;//Super & Super Plus & Default + } +} + +bool DWC2Driver::init() { + + dwc2 = (dwc2_regs*)DWC2_BASE; + host = (dwc2_host*)(DWC2_BASE + 0x400); + + *(uint32_t*)(DWC2_BASE + 0xE00) = 0;//Power reset + + dwc2->grstctl |= 1; + if (!wait(&dwc2->grstctl, 1, false, 2000)){ + kprintf("[DWC2] Failed to reset"); + return false; + } + + dwc2->gusbcfg &= ~(1 << 30);//Device mode disable + dwc2->gusbcfg |= (1 << 29);//Host mode enable + + delay(200); + + dwc2->gahbcfg |= (1 << 5);//DMA + + dwc2->gintmsk = 0xffffffff; + + host->port |= (1 << 12); + + if (!wait(&host->port, 1, true, 2000)){ + kprintf("[DWC2] No device connected %x",host->port); + return false; + } + + delay(100); + + host->port &= ~0b101110; + host->port |= (1 << 8); + + delay(50); + + host->port &= ~0b101110; + host->port &= ~(1 << 8); + + wait(&host->port, (1 << 8), false, 2000); + + kprintf("Port reset %x",host->port); + + port_speed = (host->port >> 17) & 0x3; + kprintf("Port speed %i",port_speed); + + dwc2_host_channel *channel = get_channel(0); + + assign_channel(channel, 0, 0, 0); + + mem_page = alloc_page(0x1000, true, true, false); + usb_device_descriptor* descriptor = (usb_device_descriptor*)allocate_in_page(mem_page, sizeof(usb_device_descriptor), ALIGN_64B, true, true); + + if (!request_descriptor(false, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ + kprintf_raw("[DWC2 error] failed to get device descriptor"); + return false; + } + + usb_string_language_descriptor* lang_desc = (usb_string_language_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_language_descriptor), ALIGN_64B, true, true); + + bool use_lang_desc = true; + + if (!request_descriptor(false, USB_STRING_DESCRIPTOR, 0, 0, lang_desc)){ + kprintf_raw("[DWC2 warning] failed to get language descriptor"); + use_lang_desc = false; + } + + kprintf("[DWC2] Vendor %x",descriptor->idVendor); + kprintf("[DWC2] Product %x",descriptor->idProduct); + kprintf("[DWC2] USB version %x",descriptor->bcdUSB); + kprintf("[DWC2] EP0 Max Packet Size: %x", descriptor->bMaxPacketSize0); + kprintf("[DWC2] Configurations: %x", descriptor->bNumConfigurations); + if (use_lang_desc){ + //TODO: we want to maintain the strings so we can have USB device information, and rework it to silece the alignment warning + uint16_t langid = lang_desc->lang_ids[0]; + usb_string_descriptor* prod_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); + if (request_descriptor(false, USB_STRING_DESCRIPTOR, descriptor->iProduct, langid, prod_name)){ + char name[128]; + if (utf16tochar(prod_name->unicode_string, name, sizeof(name))) { + kprintf("[DWC2 device] Product name: %s", (uint64_t)name); + } + } + usb_string_descriptor* man_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); + if (request_descriptor(false, USB_STRING_DESCRIPTOR, descriptor->iManufacturer, langid, man_name)){ + char name[128]; + if (utf16tochar(man_name->unicode_string, name, sizeof(name))) { + kprintf("[DWC2 device] Manufacturer name: %s", (uint64_t)name); + } + } + usb_string_descriptor* ser_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); + if (request_descriptor(false, USB_STRING_DESCRIPTOR, descriptor->iSerialNumber, langid, ser_name)){ + char name[128]; + if (utf16tochar(ser_name->unicode_string, name, sizeof(name))) { + kprintf("[DWC2 device] Serial: %s", (uint64_t)name); + } + } + } + + return true; +} + +bool DWC2Driver::make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, sizedptr data){ + channel->dma = data.ptr; + uint16_t max_size = packet_size(port_speed); + uint32_t pkt_count = (data.size + max_size - 1)/max_size; + channel->xfer_size = (pkt_count << 19) | (pid << 29) | data.size; + + channel->cchar &= ~0x7FF; + channel->cchar |= max_size; + + channel->intmask = 0xFFFFFFFF; + + delay(10); + + channel->cchar &= ~(1 << 15); + channel->cchar |= ((in ? 1 : 0) << 15); + + channel->cchar &= ~(1 << 30); + channel->cchar &= ~(1 << 31); + channel->cchar |= (1 << 31); + + if (!wait(&channel->interrupt, 1, true, 2000)){ + kprintf("[DWC2 error] Transfer timed out."); + return false; + } + + return true; +} + +bool DWC2Driver::request_sized_descriptor(bool interface, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor){ + dwc2_host_channel *channel = get_channel(0); + + usb_setup_packet packet = { + .bmRequestType = 0x80 | interface, + .bRequest = 6, + .wValue = (type << 8) | descriptor_index, + .wIndex = wIndex, + .wLength = descriptor_size + }; + + if (!make_transfer(channel, false, 0x3, (sizedptr){(uintptr_t)&packet, sizeof(uintptr_t)})){ + kprintf("[DWC2 error] Descriptor transfer failed setup stage"); + return false; + } + + if (!make_transfer(channel, true, 0x2, (sizedptr){(uintptr_t)out_descriptor, descriptor_size})){ + kprintf("[DWC2 error] Descriptor transfer failed data stage"); + return false; + } + + if (!make_transfer(channel, false, 0x2, (sizedptr){0, 0})){ + kprintf("[DWC2 error] Descriptor transfer failed status stage"); + return false; + } + + return true; +} + +bool DWC2Driver::request_descriptor(bool interface, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor){ + if (!request_sized_descriptor(interface, type, index, wIndex, sizeof(usb_descriptor_header), out_descriptor)){ + kprintf_raw("[DWC2 error] Failed to get descriptor header. Size %i", sizeof(usb_descriptor_header)); + return false; + } + usb_descriptor_header* descriptor = (usb_descriptor_header*)out_descriptor; + if (descriptor->bLength == 0){ + kprintf_raw("[DWC2 error] wrong descriptor size %i. Size %x",descriptor->bLength, (uintptr_t)out_descriptor); + return false; + } + return request_sized_descriptor(interface, type, index, wIndex, descriptor->bLength, out_descriptor); +} \ No newline at end of file diff --git a/kernel/input/dwc2.h b/kernel/input/dwc2.h deleted file mode 100644 index 425c6f56..00000000 --- a/kernel/input/dwc2.h +++ /dev/null @@ -1,3 +0,0 @@ -#include "types.h" - -bool dwc2_init(); \ No newline at end of file diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp new file mode 100644 index 00000000..0f4e7bf3 --- /dev/null +++ b/kernel/input/dwc2.hpp @@ -0,0 +1,56 @@ +#include "types.h" + +typedef struct { + uint32_t gotgctl; + uint32_t gotgint; + uint32_t gahbcfg; + uint32_t gusbcfg; + uint32_t grstctl; + uint32_t gintsts; + uint32_t gintmsk; + uint32_t grxstsr; + uint32_t grxstsp; + uint32_t grxfsiz; + uint32_t gnptxfsiz; + uint32_t gnptxsts; +} dwc2_regs; + +typedef struct { + uint32_t hstcfg; + uint32_t frminterval; + uint32_t frmnum; + uint32_t rsvd; + uint32_t ptx_fifo; + uint32_t allchan_int; + uint32_t allchan_int_mask; + uint32_t frmlst_base; + uint32_t rsvd2[8]; + uint32_t port; +} dwc2_host; + +typedef struct { + uint32_t cchar; + uint32_t splt; + uint32_t interrupt; + uint32_t intmask; + uint32_t xfer_size; + uint32_t dma; + uint32_t reserved[2]; + uint32_t buf; +} dwc2_host_channel; + +class DWC2Driver { +public: + bool init(); + bool request_descriptor(bool interface, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor); + bool request_sized_descriptor(bool interface, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor); + uint16_t packet_size(uint16_t speed); +private: + dwc2_host_channel* get_channel(uint16_t channel); + void assign_channel(dwc2_host_channel* channel, uint8_t device, uint8_t endpoint, uint8_t ep_type); + bool make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, sizedptr data); + void *mem_page; + uint16_t port_speed; + dwc2_regs *dwc2; + dwc2_host *host; +}; \ No newline at end of file diff --git a/kernel/input/input_dispatch.c b/kernel/input/input_dispatch.cpp similarity index 93% rename from kernel/input/input_dispatch.c rename to kernel/input/input_dispatch.cpp index 850b5296..14530f54 100644 --- a/kernel/input/input_dispatch.c +++ b/kernel/input/input_dispatch.cpp @@ -1,6 +1,8 @@ #include "input_dispatch.h" #include "process/process.h" #include "process/scheduler.h" +#include "dwc2.hpp" +#include "hw/hw.h" process_t* focused_proc; @@ -101,4 +103,12 @@ bool sys_shortcut_triggered(uint16_t pid, uint16_t sid){ return true; } return false; +} + +DWC2Driver dwc_driver; + +bool input_init(){ + if (BOARD_TYPE == 2){ + return dwc_driver.init(); + } else return xhci_input_init(); } \ No newline at end of file diff --git a/kernel/input/input_dispatch.h b/kernel/input/input_dispatch.h index ef8e27b9..fcb3c46b 100644 --- a/kernel/input/input_dispatch.h +++ b/kernel/input/input_dispatch.h @@ -24,6 +24,8 @@ bool sys_shortcut_triggered(uint16_t pid, uint16_t sid); bool is_new_keypress(keypress* current, keypress* previous); +bool input_init(); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/kernel/kernel.c b/kernel/kernel.c index fa1a9b96..4aa271b9 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -12,8 +12,7 @@ #include "process/scheduler.h" #include "filesystem/disk.h" #include "kernel_processes/boot/bootprocess.h" -#include "input/xhci_bridge.h" -#include "input/xhci.h" +#include "input/input_dispatch.h" #include "kernel_processes/monitor/monitor_processes.h" #include "networking/processes/net_proc.h" #include "memory/page_allocator.h" @@ -61,9 +60,8 @@ void kernel_main() { panic("Disk initialization failure"); // xhci_enable_verbose(); - if (!xhci_input_init()){ - panic("Input initialization failure"); - } + if (!input_init()) + panic("Input initialization error"); if (!network_init()) panic("Network initialization failure"); diff --git a/shared/std/string.h b/shared/std/string.h index bb61cfc2..ce654200 100644 --- a/shared/std/string.h +++ b/shared/std/string.h @@ -3,6 +3,10 @@ #include "types.h" #include "args.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { char *data; uint32_t length; @@ -32,4 +36,8 @@ int strindex(const char *a, const char *b); uint64_t parse_hex_u64(char* str, size_t size); -bool utf16tochar(const uint16_t* str_in, char* out_str, size_t max_len); \ No newline at end of file +bool utf16tochar(const uint16_t* str_in, char* out_str, size_t max_len); + +#ifdef __cplusplus +} +#endif \ No newline at end of file From fdcf3a7417607f14955d466650fc7ed79b638883 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sun, 29 Jun 2025 00:00:00 +0000 Subject: [PATCH 32/79] Device configuration (not working yet due to qemu automatically adding a hub) --- kernel/input/dwc2.cpp | 130 +++++++++++++++++++++++++++++++++++--- kernel/input/dwc2.hpp | 5 +- kernel/input/xhci_types.h | 1 - 3 files changed, 123 insertions(+), 13 deletions(-) diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index 8b554d48..405f4745 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -79,7 +79,7 @@ bool DWC2Driver::init() { mem_page = alloc_page(0x1000, true, true, false); usb_device_descriptor* descriptor = (usb_device_descriptor*)allocate_in_page(mem_page, sizeof(usb_device_descriptor), ALIGN_64B, true, true); - if (!request_descriptor(false, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ + if (!request_descriptor(0x80, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ kprintf_raw("[DWC2 error] failed to get device descriptor"); return false; } @@ -88,7 +88,7 @@ bool DWC2Driver::init() { bool use_lang_desc = true; - if (!request_descriptor(false, USB_STRING_DESCRIPTOR, 0, 0, lang_desc)){ + if (!request_descriptor(0x80, USB_STRING_DESCRIPTOR, 0, 0, lang_desc)){ kprintf_raw("[DWC2 warning] failed to get language descriptor"); use_lang_desc = false; } @@ -102,21 +102,21 @@ bool DWC2Driver::init() { //TODO: we want to maintain the strings so we can have USB device information, and rework it to silece the alignment warning uint16_t langid = lang_desc->lang_ids[0]; usb_string_descriptor* prod_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (request_descriptor(false, USB_STRING_DESCRIPTOR, descriptor->iProduct, langid, prod_name)){ + if (request_descriptor(0x80, USB_STRING_DESCRIPTOR, descriptor->iProduct, langid, prod_name)){ char name[128]; if (utf16tochar(prod_name->unicode_string, name, sizeof(name))) { kprintf("[DWC2 device] Product name: %s", (uint64_t)name); } } usb_string_descriptor* man_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (request_descriptor(false, USB_STRING_DESCRIPTOR, descriptor->iManufacturer, langid, man_name)){ + if (request_descriptor(0x80, USB_STRING_DESCRIPTOR, descriptor->iManufacturer, langid, man_name)){ char name[128]; if (utf16tochar(man_name->unicode_string, name, sizeof(name))) { kprintf("[DWC2 device] Manufacturer name: %s", (uint64_t)name); } } usb_string_descriptor* ser_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (request_descriptor(false, USB_STRING_DESCRIPTOR, descriptor->iSerialNumber, langid, ser_name)){ + if (request_descriptor(0x80, USB_STRING_DESCRIPTOR, descriptor->iSerialNumber, langid, ser_name)){ char name[128]; if (utf16tochar(ser_name->unicode_string, name, sizeof(name))) { kprintf("[DWC2 device] Serial: %s", (uint64_t)name); @@ -124,6 +124,8 @@ bool DWC2Driver::init() { } } + get_configuration(); + return true; } @@ -155,11 +157,11 @@ bool DWC2Driver::make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, return true; } -bool DWC2Driver::request_sized_descriptor(bool interface, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor){ +bool DWC2Driver::request_sized_descriptor(uint8_t rType, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor){ dwc2_host_channel *channel = get_channel(0); usb_setup_packet packet = { - .bmRequestType = 0x80 | interface, + .bmRequestType = rType, .bRequest = 6, .wValue = (type << 8) | descriptor_index, .wIndex = wIndex, @@ -184,8 +186,8 @@ bool DWC2Driver::request_sized_descriptor(bool interface, uint8_t type, uint16_t return true; } -bool DWC2Driver::request_descriptor(bool interface, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor){ - if (!request_sized_descriptor(interface, type, index, wIndex, sizeof(usb_descriptor_header), out_descriptor)){ +bool DWC2Driver::request_descriptor(uint8_t rType, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor){ + if (!request_sized_descriptor(rType, type, index, wIndex, sizeof(usb_descriptor_header), out_descriptor)){ kprintf_raw("[DWC2 error] Failed to get descriptor header. Size %i", sizeof(usb_descriptor_header)); return false; } @@ -194,5 +196,113 @@ bool DWC2Driver::request_descriptor(bool interface, uint8_t type, uint16_t index kprintf_raw("[DWC2 error] wrong descriptor size %i. Size %x",descriptor->bLength, (uintptr_t)out_descriptor); return false; } - return request_sized_descriptor(interface, type, index, wIndex, descriptor->bLength, out_descriptor); + return request_sized_descriptor(rType, type, index, wIndex, descriptor->bLength, out_descriptor); +} + +bool DWC2Driver::get_configuration(){ + + uint16_t ep_num = 0; + + usb_configuration_descriptor* config = (usb_configuration_descriptor*)allocate_in_page(mem_page, sizeof(usb_configuration_descriptor), ALIGN_64B, true, true); + if (!request_sized_descriptor(0x80, USB_CONFIGURATION_DESCRIPTOR, 0, 0, 8, config)){ + kprintf("[DWC2 error] could not get config descriptor header"); + return false; + } + + if (!request_sized_descriptor(0x80, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->header.bLength, config)){ + kprintf("[DWC2 error] could not get full config descriptor"); + return false; + } + + if (!request_sized_descriptor(0x80, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->wTotalLength, config)){ + kprintf("[DWC2 error] could not get full config descriptor"); + return false; + } + + uint16_t total_length = config->wTotalLength - config->header.bLength; + + kprintf("[DWC2] Config length %i (%i - %i)",total_length,config->wTotalLength,config->header.bLength); + + uint16_t interface_index = 0; + + bool need_new_endpoint = true; + + uint8_t* report_descriptor; + uint16_t report_length; + + for (uint16_t i = 0; i < total_length;){ + usb_descriptor_header* header = (usb_descriptor_header*)&config->data[i]; + if (header->bLength == 0){ + kprintf("Failed to get descriptor. Header size 0"); + return false; + } + if (need_new_endpoint){ + need_new_endpoint = false; + // device_endpoint = (xhci_usb_device_endpoint*)allocate_in_page(xhci_mem_page, sizeof(xhci_usb_device_endpoint), ALIGN_64B, true, true); + } + switch (header->bDescriptorType) + { + case 0x4: { //Interface + usb_interface_descriptor *interface = (usb_interface_descriptor *)&config->data[i]; + if (interface->bInterfaceClass == 0x9){ + kprintf("USB Hub detected %i", interface->bNumEndpoints); + + } else if (interface->bInterfaceClass != 0x3){ + kprintf("[DWC2 implementation error] non-hid devices not supported yet %x",interface->bInterfaceClass); + return false; + } + kprintf("[DWC2] interface protocol %x",interface->bInterfaceProtocol); + switch (interface->bInterfaceProtocol) + { + case 0x1: + // device_endpoint->type = KEYBOARD; + break; + + default: + break; + } + interface_index++; + } + break; + case 0x21: { //HID + usb_hid_descriptor *hid = (usb_hid_descriptor *)&config->data[i]; + for (uint8_t j = 0; j < hid->bNumDescriptors; j++){ + if (hid->descriptors[j].bDescriptorType == 0x22){//REPORT HID + report_length = hid->descriptors[j].wDescriptorLength; + report_descriptor = (uint8_t*)allocate_in_page(mem_page, report_length, ALIGN_64B, true, true); + request_descriptor(0x81, 0x22, 0, interface_index-1, report_descriptor); + kprintf("[DWC2] retrieved report descriptor of length %i at %x", report_length, (uintptr_t)report_descriptor); + } + } + } + break; + case 0x5: {//Endpoint + + usb_endpoint_descriptor *endpoint = (usb_endpoint_descriptor*)&config->data[i]; + kprintf("[DWC2] endpoint address %x",endpoint->bEndpointAddress); + uint8_t ep_address = endpoint->bEndpointAddress; + uint8_t ep_dir = (ep_address & 0x80) ? 1 : 0; // 1 IN, 0 OUT + uint8_t ep_num = ((ep_address & 0x0F) * 2) + ep_dir; + + uint8_t ep_type = endpoint->bmAttributes & 0x03; // 0 = Control, 1 = Iso, 2 = Bulk, 3 = Interrupt + kprintf("[DWC2] endpoint %i info. Direction %i type %i",ep_num, ep_dir, ep_type); + + // device_endpoint->poll_endpoint = ep_num; + // device_endpoint->poll_packetSize = endpoint->wMaxPacketSize; + + // if (!issue_command((uintptr_t)ctx, 0, (device->slot_id << 24) | (TRB_TYPE_CONFIG_EP << 10))){ + // kprintf_raw("[xHCI] Failed to configure endpoint %i",ep_num); + // return false; + // } + + need_new_endpoint = true; + } + break; + default: kprintf("Unknown type %x", header->bDescriptorType); + } + i += header->bLength; + } + + return true; + } \ No newline at end of file diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index 0f4e7bf3..de81edec 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -42,9 +42,10 @@ typedef struct { class DWC2Driver { public: bool init(); - bool request_descriptor(bool interface, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor); - bool request_sized_descriptor(bool interface, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor); + bool request_descriptor(uint8_t rType, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor); + bool request_sized_descriptor(uint8_t rType, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor); uint16_t packet_size(uint16_t speed); + bool get_configuration(); private: dwc2_host_channel* get_channel(uint16_t channel); void assign_channel(dwc2_host_channel* channel, uint8_t device, uint8_t endpoint, uint8_t ep_type); diff --git a/kernel/input/xhci_types.h b/kernel/input/xhci_types.h index 5151afe5..34484fac 100644 --- a/kernel/input/xhci_types.h +++ b/kernel/input/xhci_types.h @@ -354,7 +354,6 @@ typedef struct { uint32_t transfer_index; trb* transfer_ring; uint32_t slot_id; - uint8_t interface_protocol;//TODO: support multiple xhci_input_context* ctx; } xhci_usb_device; From 6ebafc6532e0f0532610cd1a127a5c79fbaa1411 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sun, 29 Jun 2025 00:00:00 +0000 Subject: [PATCH 33/79] Hub setup of keyboard --- kernel/input/dwc2.cpp | 134 ++++++++++++++++++++++++++++-------------- kernel/input/dwc2.hpp | 10 +++- 2 files changed, 98 insertions(+), 46 deletions(-) diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index 405f4745..bba9ee90 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -55,31 +55,32 @@ bool DWC2Driver::init() { return false; } - delay(100); - - host->port &= ~0b101110; - host->port |= (1 << 8); - - delay(50); - - host->port &= ~0b101110; - host->port &= ~(1 << 8); - - wait(&host->port, (1 << 8), false, 2000); + if (!port_reset(&host->port)){ + kprintf("[DWC2] failed port reset %b",host->port); + return false; + } kprintf("Port reset %x",host->port); port_speed = (host->port >> 17) & 0x3; kprintf("Port speed %i",port_speed); - dwc2_host_channel *channel = get_channel(0); - assign_channel(channel, 0, 0, 0); + dwc2_host_channel *channel = get_channel(next_channel++); + assign_channel(channel, 0, 0, 0); mem_page = alloc_page(0x1000, true, true, false); + + setup_device(channel); + + return true; +} + +bool DWC2Driver::setup_device(dwc2_host_channel *channel){ + usb_device_descriptor* descriptor = (usb_device_descriptor*)allocate_in_page(mem_page, sizeof(usb_device_descriptor), ALIGN_64B, true, true); - if (!request_descriptor(0x80, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ + if (!request_descriptor(channel, 0x80, 6, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ kprintf_raw("[DWC2 error] failed to get device descriptor"); return false; } @@ -88,7 +89,7 @@ bool DWC2Driver::init() { bool use_lang_desc = true; - if (!request_descriptor(0x80, USB_STRING_DESCRIPTOR, 0, 0, lang_desc)){ + if (!request_descriptor(channel, 0x80, 6, USB_STRING_DESCRIPTOR, 0, 0, lang_desc)){ kprintf_raw("[DWC2 warning] failed to get language descriptor"); use_lang_desc = false; } @@ -102,21 +103,21 @@ bool DWC2Driver::init() { //TODO: we want to maintain the strings so we can have USB device information, and rework it to silece the alignment warning uint16_t langid = lang_desc->lang_ids[0]; usb_string_descriptor* prod_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (request_descriptor(0x80, USB_STRING_DESCRIPTOR, descriptor->iProduct, langid, prod_name)){ + if (request_descriptor(channel, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iProduct, langid, prod_name)){ char name[128]; if (utf16tochar(prod_name->unicode_string, name, sizeof(name))) { kprintf("[DWC2 device] Product name: %s", (uint64_t)name); } } usb_string_descriptor* man_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (request_descriptor(0x80, USB_STRING_DESCRIPTOR, descriptor->iManufacturer, langid, man_name)){ + if (request_descriptor(channel, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iManufacturer, langid, man_name)){ char name[128]; if (utf16tochar(man_name->unicode_string, name, sizeof(name))) { kprintf("[DWC2 device] Manufacturer name: %s", (uint64_t)name); } } usb_string_descriptor* ser_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (request_descriptor(0x80, USB_STRING_DESCRIPTOR, descriptor->iSerialNumber, langid, ser_name)){ + if (request_descriptor(channel, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iSerialNumber, langid, ser_name)){ char name[128]; if (utf16tochar(ser_name->unicode_string, name, sizeof(name))) { kprintf("[DWC2 device] Serial: %s", (uint64_t)name); @@ -124,11 +125,23 @@ bool DWC2Driver::init() { } } - get_configuration(); + get_configuration(channel); return true; } +bool DWC2Driver::port_reset(uint32_t *port){ + *port &= ~0b101110; + *port |= (1 << 8); + + delay(50); + + *port &= ~0b101110; + *port &= ~(1 << 8); + + return wait(port, (1 << 8), false, 2000); +} + bool DWC2Driver::make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, sizedptr data){ channel->dma = data.ptr; uint16_t max_size = packet_size(port_speed); @@ -157,28 +170,31 @@ bool DWC2Driver::make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, return true; } -bool DWC2Driver::request_sized_descriptor(uint8_t rType, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor){ - dwc2_host_channel *channel = get_channel(0); +bool DWC2Driver::request_sized_descriptor(dwc2_host_channel *channel, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor){ usb_setup_packet packet = { .bmRequestType = rType, - .bRequest = 6, + .bRequest = request, .wValue = (type << 8) | descriptor_index, .wIndex = wIndex, .wLength = descriptor_size }; - if (!make_transfer(channel, false, 0x3, (sizedptr){(uintptr_t)&packet, sizeof(uintptr_t)})){ + // kprintf("RT: %x R: %x V: %x I: %x L: %x",packet.bmRequestType,packet.bRequest,packet.wValue,packet.wIndex,packet.wLength); + + if (!make_transfer(channel, descriptor_size == 0, 0x3, (sizedptr){(uintptr_t)&packet, sizeof(uintptr_t)})){ kprintf("[DWC2 error] Descriptor transfer failed setup stage"); return false; } - if (!make_transfer(channel, true, 0x2, (sizedptr){(uintptr_t)out_descriptor, descriptor_size})){ - kprintf("[DWC2 error] Descriptor transfer failed data stage"); - return false; + if (descriptor_size > 0){ + if (!make_transfer(channel, true, 0x2, (sizedptr){(uintptr_t)out_descriptor, descriptor_size})){ + kprintf("[DWC2 error] Descriptor transfer failed data stage"); + return false; + } } - if (!make_transfer(channel, false, 0x2, (sizedptr){0, 0})){ + if (!make_transfer(channel, descriptor_size == 0, 0x2, (sizedptr){0, 0})){ kprintf("[DWC2 error] Descriptor transfer failed status stage"); return false; } @@ -186,8 +202,8 @@ bool DWC2Driver::request_sized_descriptor(uint8_t rType, uint8_t type, uint16_t return true; } -bool DWC2Driver::request_descriptor(uint8_t rType, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor){ - if (!request_sized_descriptor(rType, type, index, wIndex, sizeof(usb_descriptor_header), out_descriptor)){ +bool DWC2Driver::request_descriptor(dwc2_host_channel *channel, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor){ + if (!request_sized_descriptor(channel, rType, request, type, index, wIndex, sizeof(usb_descriptor_header), out_descriptor)){ kprintf_raw("[DWC2 error] Failed to get descriptor header. Size %i", sizeof(usb_descriptor_header)); return false; } @@ -196,25 +212,25 @@ bool DWC2Driver::request_descriptor(uint8_t rType, uint8_t type, uint16_t index, kprintf_raw("[DWC2 error] wrong descriptor size %i. Size %x",descriptor->bLength, (uintptr_t)out_descriptor); return false; } - return request_sized_descriptor(rType, type, index, wIndex, descriptor->bLength, out_descriptor); + return request_sized_descriptor(channel, rType, request, type, index, wIndex, descriptor->bLength, out_descriptor); } -bool DWC2Driver::get_configuration(){ +bool DWC2Driver::get_configuration(dwc2_host_channel *channel){ uint16_t ep_num = 0; usb_configuration_descriptor* config = (usb_configuration_descriptor*)allocate_in_page(mem_page, sizeof(usb_configuration_descriptor), ALIGN_64B, true, true); - if (!request_sized_descriptor(0x80, USB_CONFIGURATION_DESCRIPTOR, 0, 0, 8, config)){ + if (!request_sized_descriptor(channel, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, 8, config)){ kprintf("[DWC2 error] could not get config descriptor header"); return false; } - if (!request_sized_descriptor(0x80, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->header.bLength, config)){ + if (!request_sized_descriptor(channel, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->header.bLength, config)){ kprintf("[DWC2 error] could not get full config descriptor"); return false; } - if (!request_sized_descriptor(0x80, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->wTotalLength, config)){ + if (!request_sized_descriptor(channel, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->wTotalLength, config)){ kprintf("[DWC2 error] could not get full config descriptor"); return false; } @@ -246,7 +262,8 @@ bool DWC2Driver::get_configuration(){ usb_interface_descriptor *interface = (usb_interface_descriptor *)&config->data[i]; if (interface->bInterfaceClass == 0x9){ kprintf("USB Hub detected %i", interface->bNumEndpoints); - + hub_enumerate(channel); + return true; } else if (interface->bInterfaceClass != 0x3){ kprintf("[DWC2 implementation error] non-hid devices not supported yet %x",interface->bInterfaceClass); return false; @@ -270,7 +287,7 @@ bool DWC2Driver::get_configuration(){ if (hid->descriptors[j].bDescriptorType == 0x22){//REPORT HID report_length = hid->descriptors[j].wDescriptorLength; report_descriptor = (uint8_t*)allocate_in_page(mem_page, report_length, ALIGN_64B, true, true); - request_descriptor(0x81, 0x22, 0, interface_index-1, report_descriptor); + request_descriptor(channel, 0x81, 6, 0x22, 0, interface_index-1, report_descriptor); kprintf("[DWC2] retrieved report descriptor of length %i at %x", report_length, (uintptr_t)report_descriptor); } } @@ -287,13 +304,14 @@ bool DWC2Driver::get_configuration(){ uint8_t ep_type = endpoint->bmAttributes & 0x03; // 0 = Control, 1 = Iso, 2 = Bulk, 3 = Interrupt kprintf("[DWC2] endpoint %i info. Direction %i type %i",ep_num, ep_dir, ep_type); - // device_endpoint->poll_endpoint = ep_num; - // device_endpoint->poll_packetSize = endpoint->wMaxPacketSize; - - // if (!issue_command((uintptr_t)ctx, 0, (device->slot_id << 24) | (TRB_TYPE_CONFIG_EP << 10))){ - // kprintf_raw("[xHCI] Failed to configure endpoint %i",ep_num); - // return false; - // } + //Configure endpoint + uint16_t new_channel = next_channel++; + uint16_t address = ((uintptr_t)channel - DWC2_BASE - 0x500)/0x20; + uint16_t port = ((channel->splt >> 1) & 0xF) << 1; + request_sized_descriptor(channel, 0x0, 0x5, 0, new_channel, port, 0, 0);//Address device + dwc2_host_channel *ep_channel = get_channel(new_channel); + assign_channel(ep_channel, address, 0, 0); + ep_channel->splt = (1 << 31 /*split enable*/) | (address << 7) | port; need_new_endpoint = true; } @@ -305,4 +323,34 @@ bool DWC2Driver::get_configuration(){ return true; +} + +void DWC2Driver::hub_enumerate(dwc2_host_channel *channel){ + //TODO: actually support multiple devices + uint8_t port = 1; + uint32_t port_status; + uint16_t address = ((uintptr_t)channel - DWC2_BASE - 0x500)/0x20; + request_sized_descriptor(channel, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); + kprintf("Port %i status %b",port, port_status); + if (port_status & 1){ + request_sized_descriptor(channel, 0x23, 3, 0, 4, port, 0, 0);//Port Reset + delay(50); + request_sized_descriptor(channel, 0x23, 1, 0, 4, port, 0, 0);//Port Reset Clear + delay(10); + request_sized_descriptor(channel, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); + kprintf("Port 1 status %b",port_status); + if (!(port_status & 0b11)){ + kprintf("Port not enabled or device not connected"); + return; + } + uint16_t new_channel = next_channel++; + kprintf("Address device %i",new_channel); + request_sized_descriptor(channel, 0x0, 0x5, 0, new_channel, port, 0, 0);//Address device + request_sized_descriptor(channel, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); + kprintf("Port 1 status %b",port_status); + dwc2_host_channel *dev_channel = get_channel(new_channel); + assign_channel(dev_channel, address, 0, 0); + dev_channel->splt = (1 << 31) | (address << 7) | (port << 1); + setup_device(dev_channel); + } } \ No newline at end of file diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index de81edec..70522b72 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -42,10 +42,13 @@ typedef struct { class DWC2Driver { public: bool init(); - bool request_descriptor(uint8_t rType, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor); - bool request_sized_descriptor(uint8_t rType, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor); + bool request_descriptor(dwc2_host_channel *channel, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor); + bool request_sized_descriptor(dwc2_host_channel *channel, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor); uint16_t packet_size(uint16_t speed); - bool get_configuration(); + bool get_configuration(dwc2_host_channel *channel); + void hub_enumerate(dwc2_host_channel *channel); + bool port_reset(uint32_t *port); + bool setup_device(dwc2_host_channel *channel); private: dwc2_host_channel* get_channel(uint16_t channel); void assign_channel(dwc2_host_channel* channel, uint8_t device, uint8_t endpoint, uint8_t ep_type); @@ -54,4 +57,5 @@ class DWC2Driver { uint16_t port_speed; dwc2_regs *dwc2; dwc2_host *host; + uint16_t next_channel; }; \ No newline at end of file From c11ba3ea9cd88e18fc1e50b7fa231fa888ccfd90 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 30 Jun 2025 00:00:00 +0000 Subject: [PATCH 34/79] More correct device addressing, still no input --- kernel/input/dwc2.cpp | 80 ++++++++++++++++++++++++++++++++----------- kernel/input/dwc2.hpp | 7 ++-- 2 files changed, 65 insertions(+), 22 deletions(-) diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index bba9ee90..bc897731 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -65,7 +65,6 @@ bool DWC2Driver::init() { port_speed = (host->port >> 17) & 0x3; kprintf("Port speed %i",port_speed); - dwc2_host_channel *channel = get_channel(next_channel++); assign_channel(channel, 0, 0, 0); @@ -76,8 +75,20 @@ bool DWC2Driver::init() { return true; } +uint8_t DWC2Driver::address_device(dwc2_host_channel *channel){ + request_sized_descriptor(channel, 0x0, 0x5, 0, ++next_address, 0, 0, 0); + return next_address; +} + bool DWC2Driver::setup_device(dwc2_host_channel *channel){ + uint8_t chan_num = ((uintptr_t)channel - DWC2_BASE - 0x500)/0x20; + uint8_t address = (channel->cchar >> 22) & 0xFFFF; + + kprintf("Speaking to device %i on channel %i",address, chan_num); + if (channel->splt) + kprintf("Using split from original device %i:%i", (channel->splt >> 7) & 0xFFFF, (channel->splt) & 0x7F); + usb_device_descriptor* descriptor = (usb_device_descriptor*)allocate_in_page(mem_page, sizeof(usb_device_descriptor), ALIGN_64B, true, true); if (!request_descriptor(channel, 0x80, 6, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ @@ -85,6 +96,15 @@ bool DWC2Driver::setup_device(dwc2_host_channel *channel){ return false; } + uint16_t addr = address_device(channel); + + channel->cchar &= ~(0x7F << 22); + channel->cchar |= (addr << 22); + + address = (channel->cchar >> 22) & 0xFFFF; + + kprintf("Changed address of device to %i on channel %i",address, chan_num); + usb_string_language_descriptor* lang_desc = (usb_string_language_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_language_descriptor), ALIGN_64B, true, true); bool use_lang_desc = true; @@ -153,8 +173,6 @@ bool DWC2Driver::make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, channel->intmask = 0xFFFFFFFF; - delay(10); - channel->cchar &= ~(1 << 15); channel->cchar |= ((in ? 1 : 0) << 15); @@ -182,7 +200,7 @@ bool DWC2Driver::request_sized_descriptor(dwc2_host_channel *channel, uint8_t rT // kprintf("RT: %x R: %x V: %x I: %x L: %x",packet.bmRequestType,packet.bRequest,packet.wValue,packet.wIndex,packet.wLength); - if (!make_transfer(channel, descriptor_size == 0, 0x3, (sizedptr){(uintptr_t)&packet, sizeof(uintptr_t)})){ + if (!make_transfer(channel, false, 0x3, (sizedptr){(uintptr_t)&packet, sizeof(uintptr_t)})){ kprintf("[DWC2 error] Descriptor transfer failed setup stage"); return false; } @@ -209,7 +227,7 @@ bool DWC2Driver::request_descriptor(dwc2_host_channel *channel, uint8_t rType, u } usb_descriptor_header* descriptor = (usb_descriptor_header*)out_descriptor; if (descriptor->bLength == 0){ - kprintf_raw("[DWC2 error] wrong descriptor size %i. Size %x",descriptor->bLength, (uintptr_t)out_descriptor); + kprintf_raw("[DWC2 error] wrong descriptor size %i",descriptor->bLength); return false; } return request_sized_descriptor(channel, rType, request, type, index, wIndex, descriptor->bLength, out_descriptor); @@ -217,6 +235,9 @@ bool DWC2Driver::request_descriptor(dwc2_host_channel *channel, uint8_t rType, u bool DWC2Driver::get_configuration(dwc2_host_channel *channel){ + uint8_t chan_num = ((uintptr_t)channel - DWC2_BASE - 0x500)/0x20; + uint8_t address = (channel->cchar >> 22) & 0xFFFF; + uint16_t ep_num = 0; usb_configuration_descriptor* config = (usb_configuration_descriptor*)allocate_in_page(mem_page, sizeof(usb_configuration_descriptor), ALIGN_64B, true, true); @@ -262,7 +283,7 @@ bool DWC2Driver::get_configuration(dwc2_host_channel *channel){ usb_interface_descriptor *interface = (usb_interface_descriptor *)&config->data[i]; if (interface->bInterfaceClass == 0x9){ kprintf("USB Hub detected %i", interface->bNumEndpoints); - hub_enumerate(channel); + hub_enumerate(channel, address); return true; } else if (interface->bInterfaceClass != 0x3){ kprintf("[DWC2 implementation error] non-hid devices not supported yet %x",interface->bInterfaceClass); @@ -305,15 +326,34 @@ bool DWC2Driver::get_configuration(dwc2_host_channel *channel){ kprintf("[DWC2] endpoint %i info. Direction %i type %i",ep_num, ep_dir, ep_type); //Configure endpoint - uint16_t new_channel = next_channel++; - uint16_t address = ((uintptr_t)channel - DWC2_BASE - 0x500)/0x20; - uint16_t port = ((channel->splt >> 1) & 0xF) << 1; - request_sized_descriptor(channel, 0x0, 0x5, 0, new_channel, port, 0, 0);//Address device - dwc2_host_channel *ep_channel = get_channel(new_channel); - assign_channel(ep_channel, address, 0, 0); - ep_channel->splt = (1 << 31 /*split enable*/) | (address << 7) | port; + dwc2_host_channel *ep_channel = get_channel(next_channel++); + assign_channel(ep_channel, address, ep_num, ep_type); + if (channel->splt) + ep_channel->splt = channel->splt; + + TEMP_input_buffer = allocate_in_page(mem_page, 0x1000, ALIGN_64B, true, true); + + ep_channel->dma = (uintptr_t)TEMP_input_buffer; // Aligned memory to receive the report + uint16_t pckt_size = endpoint->wMaxPacketSize; + ep_channel->xfer_size = (1 << 19) | (0x1 << 29) | pckt_size; + + ep_channel->intmask = 0xFFFFFFFF; + ep_channel->cchar &= ~0x7FF; + ep_channel->cchar |= pckt_size; + ep_channel->cchar &= ~(1 << 30); + ep_channel->cchar |= (1 << 15); + ep_channel->cchar |= (1 << 31); + + kprintf("EP transfer requested %b. Packet size %i",ep_channel->cchar,endpoint->wMaxPacketSize); need_new_endpoint = true; + + if (!wait(&ep_channel->interrupt, 1, true, 20000)){ + kprintf("Did not receive a keystroke"); + return false; + } + + kprintf("Keystroke received"); } break; default: kprintf("Unknown type %x", header->bDescriptorType); @@ -325,11 +365,10 @@ bool DWC2Driver::get_configuration(dwc2_host_channel *channel){ } -void DWC2Driver::hub_enumerate(dwc2_host_channel *channel){ +void DWC2Driver::hub_enumerate(dwc2_host_channel *channel, uint16_t address){ //TODO: actually support multiple devices uint8_t port = 1; uint32_t port_status; - uint16_t address = ((uintptr_t)channel - DWC2_BASE - 0x500)/0x20; request_sized_descriptor(channel, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); kprintf("Port %i status %b",port, port_status); if (port_status & 1){ @@ -337,20 +376,21 @@ void DWC2Driver::hub_enumerate(dwc2_host_channel *channel){ delay(50); request_sized_descriptor(channel, 0x23, 1, 0, 4, port, 0, 0);//Port Reset Clear delay(10); + channel->splt = (1 << 31) | (1 << 16) | (address << 7) | (port << 0); request_sized_descriptor(channel, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); + channel->splt = 0; kprintf("Port 1 status %b",port_status); if (!(port_status & 0b11)){ kprintf("Port not enabled or device not connected"); return; } uint16_t new_channel = next_channel++; - kprintf("Address device %i",new_channel); - request_sized_descriptor(channel, 0x0, 0x5, 0, new_channel, port, 0, 0);//Address device request_sized_descriptor(channel, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); kprintf("Port 1 status %b",port_status); dwc2_host_channel *dev_channel = get_channel(new_channel); - assign_channel(dev_channel, address, 0, 0); - dev_channel->splt = (1 << 31) | (address << 7) | (port << 1); - setup_device(dev_channel); + dev_channel->splt = (1 << 31) | (3 << 14) | (address << 7) | (port << 0); + assign_channel(dev_channel, 0, 0, 0); + if (address == 1) + setup_device(dev_channel); } } \ No newline at end of file diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index 70522b72..785004a4 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -46,16 +46,19 @@ class DWC2Driver { bool request_sized_descriptor(dwc2_host_channel *channel, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor); uint16_t packet_size(uint16_t speed); bool get_configuration(dwc2_host_channel *channel); - void hub_enumerate(dwc2_host_channel *channel); + void hub_enumerate(dwc2_host_channel *channel, uint16_t address); bool port_reset(uint32_t *port); bool setup_device(dwc2_host_channel *channel); + uint8_t address_device(dwc2_host_channel *channel); private: dwc2_host_channel* get_channel(uint16_t channel); void assign_channel(dwc2_host_channel* channel, uint8_t device, uint8_t endpoint, uint8_t ep_type); bool make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, sizedptr data); void *mem_page; uint16_t port_speed; + void *TEMP_input_buffer; dwc2_regs *dwc2; dwc2_host *host; - uint16_t next_channel; + uint8_t next_channel; + uint8_t next_address; }; \ No newline at end of file From d939857a60358f248a6b7ba2c93cd7a75865ccf9 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 30 Jun 2025 00:00:00 +0000 Subject: [PATCH 35/79] DWC2 input --- kernel/graph/drivers/videocore/videocore.cpp | 1 + kernel/input/dwc2.cpp | 70 ++++++++++++++------ 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/kernel/graph/drivers/videocore/videocore.cpp b/kernel/graph/drivers/videocore/videocore.cpp index 83b9fe55..559d7423 100644 --- a/kernel/graph/drivers/videocore/videocore.cpp +++ b/kernel/graph/drivers/videocore/videocore.cpp @@ -64,6 +64,7 @@ bool VideoCoreGPUDriver::init(gpu_size preferred_screen_size){ page = alloc_page(0x1000, true, true, false); back_framebuffer = (uintptr_t)allocate_in_page(page, fb_size, ALIGN_16B, true, true); kprintf("Framebuffer allocated to %x. BPP %i. Stride %i",framebuffer, bpp, stride/bpp); + //TODO: Mark the fb memory as used in the page allocator manually for (size_t i = framebuffer; i < framebuffer + fb_size; i += GRANULE_4KB) register_device_memory(i,i); return true; diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index bc897731..e103d57a 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -87,7 +87,7 @@ bool DWC2Driver::setup_device(dwc2_host_channel *channel){ kprintf("Speaking to device %i on channel %i",address, chan_num); if (channel->splt) - kprintf("Using split from original device %i:%i", (channel->splt >> 7) & 0xFFFF, (channel->splt) & 0x7F); + kprintf("Using split from original device %i:%i", (channel->splt >> 7) & 0x7F, (channel->splt) & 0x7F); usb_device_descriptor* descriptor = (usb_device_descriptor*)allocate_in_page(mem_page, sizeof(usb_device_descriptor), ALIGN_64B, true, true); @@ -172,6 +172,7 @@ bool DWC2Driver::make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, channel->cchar |= max_size; channel->intmask = 0xFFFFFFFF; + channel->interrupt = 0; channel->cchar &= ~(1 << 15); channel->cchar |= ((in ? 1 : 0) << 15); @@ -198,6 +199,8 @@ bool DWC2Driver::request_sized_descriptor(dwc2_host_channel *channel, uint8_t rT .wLength = descriptor_size }; + bool is_in = (rType & 0x80) != 0; + // kprintf("RT: %x R: %x V: %x I: %x L: %x",packet.bmRequestType,packet.bRequest,packet.wValue,packet.wIndex,packet.wLength); if (!make_transfer(channel, false, 0x3, (sizedptr){(uintptr_t)&packet, sizeof(uintptr_t)})){ @@ -206,13 +209,13 @@ bool DWC2Driver::request_sized_descriptor(dwc2_host_channel *channel, uint8_t rT } if (descriptor_size > 0){ - if (!make_transfer(channel, true, 0x2, (sizedptr){(uintptr_t)out_descriptor, descriptor_size})){ + if (!make_transfer(channel, is_in, 0x2, (sizedptr){(uintptr_t)out_descriptor, descriptor_size})){ kprintf("[DWC2 error] Descriptor transfer failed data stage"); return false; } } - if (!make_transfer(channel, descriptor_size == 0, 0x2, (sizedptr){0, 0})){ + if (!make_transfer(channel, !is_in, 0x2, (sizedptr){0, 0})){ kprintf("[DWC2 error] Descriptor transfer failed status stage"); return false; } @@ -317,34 +320,63 @@ bool DWC2Driver::get_configuration(dwc2_host_channel *channel){ case 0x5: {//Endpoint usb_endpoint_descriptor *endpoint = (usb_endpoint_descriptor*)&config->data[i]; - kprintf("[DWC2] endpoint address %x",endpoint->bEndpointAddress); + kprintf("[DWC2] endpoint address %x. Device address %i",endpoint->bEndpointAddress,address); uint8_t ep_address = endpoint->bEndpointAddress; - uint8_t ep_dir = (ep_address & 0x80) ? 1 : 0; // 1 IN, 0 OUT - uint8_t ep_num = ((ep_address & 0x0F) * 2) + ep_dir; + uint8_t ep_num = ep_address & 0x0F; + uint8_t ep_dir = (ep_address & 0x80) >> 7; uint8_t ep_type = endpoint->bmAttributes & 0x03; // 0 = Control, 1 = Iso, 2 = Bulk, 3 = Interrupt + kprintf("[DWC2] endpoint %i info. Direction %i type %i",ep_num, ep_dir, ep_type); //Configure endpoint + request_sized_descriptor(channel, 0x00, 0x09, 0, config->bConfigurationValue, 0, 0, 0); + + uint8_t conf; + request_sized_descriptor(channel, 0x80, 0x08, 0, 0, 0, 1, &conf); + + if (!conf){ + kprintf("Failed to set configuration for device"); + return false; + } + dwc2_host_channel *ep_channel = get_channel(next_channel++); assign_channel(ep_channel, address, ep_num, ep_type); if (channel->splt) ep_channel->splt = channel->splt; - - TEMP_input_buffer = allocate_in_page(mem_page, 0x1000, ALIGN_64B, true, true); + + TEMP_input_buffer = allocate_in_page(mem_page, 8, ALIGN_64B, true, true); ep_channel->dma = (uintptr_t)TEMP_input_buffer; // Aligned memory to receive the report - uint16_t pckt_size = endpoint->wMaxPacketSize; - ep_channel->xfer_size = (1 << 19) | (0x1 << 29) | pckt_size; + // uint8_t pckt_size = endpoint->wMaxPacketSize; ep_channel->intmask = 0xFFFFFFFF; + + ep_channel->xfer_size = (1 << 19) | (0x3 << 29) | endpoint->wMaxPacketSize; + ep_channel->cchar &= ~0x7FF; - ep_channel->cchar |= pckt_size; + ep_channel->cchar |= endpoint->wMaxPacketSize; + + ep_channel->intmask = 0xFFFFFFFF; + + ep_channel->cchar &= ~(1 << 15); + ep_channel->cchar |= (ep_dir << 15); + ep_channel->cchar &= ~(1 << 30); - ep_channel->cchar |= (1 << 15); - ep_channel->cchar |= (1 << 31); + ep_channel->cchar &= ~(1 << 31); + ep_channel->cchar |= (1 << 17); + + uint8_t mc = endpoint->bInterval & 0x3; + ep_channel->cchar &= ~(0b11 << 20); + ep_channel->cchar |= (mc << 20); + + // ep_channel->cchar |= (1 << 19); + + delay(1000); + + ep_channel->cchar |= (1 << 31); + - kprintf("EP transfer requested %b. Packet size %i",ep_channel->cchar,endpoint->wMaxPacketSize); need_new_endpoint = true; @@ -370,26 +402,20 @@ void DWC2Driver::hub_enumerate(dwc2_host_channel *channel, uint16_t address){ uint8_t port = 1; uint32_t port_status; request_sized_descriptor(channel, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); - kprintf("Port %i status %b",port, port_status); if (port_status & 1){ + kprintf("Port %i status %b",port, port_status); request_sized_descriptor(channel, 0x23, 3, 0, 4, port, 0, 0);//Port Reset delay(50); request_sized_descriptor(channel, 0x23, 1, 0, 4, port, 0, 0);//Port Reset Clear delay(10); - channel->splt = (1 << 31) | (1 << 16) | (address << 7) | (port << 0); request_sized_descriptor(channel, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); - channel->splt = 0; - kprintf("Port 1 status %b",port_status); if (!(port_status & 0b11)){ kprintf("Port not enabled or device not connected"); return; } uint16_t new_channel = next_channel++; - request_sized_descriptor(channel, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); - kprintf("Port 1 status %b",port_status); dwc2_host_channel *dev_channel = get_channel(new_channel); - dev_channel->splt = (1 << 31) | (3 << 14) | (address << 7) | (port << 0); - assign_channel(dev_channel, 0, 0, 0); + dev_channel->splt = (1 << 31) | (1 << 16) | (address << 7) | (port << 0); if (address == 1) setup_device(dev_channel); } From a65a48322e54d4fb1f33454fa4f84b2f05878832 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 30 Jun 2025 00:00:00 +0000 Subject: [PATCH 36/79] Hacked together input system --- kernel/async.c | 4 +- kernel/input/dwc2.cpp | 97 +++++++++++++-------- kernel/input/dwc2.hpp | 5 ++ kernel/input/input_dispatch.cpp | 6 +- kernel/kernel.c | 2 +- kernel/kernel_processes/windows/desktop.cpp | 1 + 6 files changed, 71 insertions(+), 44 deletions(-) diff --git a/kernel/async.c b/kernel/async.c index 61473e45..37ab9aa9 100644 --- a/kernel/async.c +++ b/kernel/async.c @@ -22,10 +22,8 @@ bool wait(uint32_t *reg, uint32_t expected_value, bool match, uint32_t timeout){ do { delay(1); timeout--; - if (timeout == 0){ - kprintf("Wait timed out"); + if (timeout == 0) return false; - } condition = (*reg & expected_value) == expected_value; } while ((match > 0) ^ condition); diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index e103d57a..c7904b91 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -4,6 +4,8 @@ #include "memory/page_allocator.h" #include "xhci_types.h"//TODO: split into xhci and USB types #include "std/string.h" +#include "memory/mmu.h" +#include "input_dispatch.h" #define DWC2_BASE 0xFE980000 @@ -72,6 +74,8 @@ bool DWC2Driver::init() { setup_device(channel); + register_device_memory(DWC2_BASE, DWC2_BASE); + return true; } @@ -340,61 +344,78 @@ bool DWC2Driver::get_configuration(dwc2_host_channel *channel){ return false; } - dwc2_host_channel *ep_channel = get_channel(next_channel++); - assign_channel(ep_channel, address, ep_num, ep_type); + endpoint_channel = get_channel(next_channel++); + assign_channel(endpoint_channel, address, ep_num, ep_type); if (channel->splt) - ep_channel->splt = channel->splt; - - TEMP_input_buffer = allocate_in_page(mem_page, 8, ALIGN_64B, true, true); - - ep_channel->dma = (uintptr_t)TEMP_input_buffer; // Aligned memory to receive the report - // uint8_t pckt_size = endpoint->wMaxPacketSize; - - ep_channel->intmask = 0xFFFFFFFF; + endpoint_channel->splt = channel->splt; - ep_channel->xfer_size = (1 << 19) | (0x3 << 29) | endpoint->wMaxPacketSize; + endpoint_channel->cchar &= ~(1 << 15); + endpoint_channel->cchar |= (ep_dir << 15); - ep_channel->cchar &= ~0x7FF; - ep_channel->cchar |= endpoint->wMaxPacketSize; + endpoint_channel->cchar &= ~0x7FF; + endpoint_channel->cchar |= endpoint->wMaxPacketSize; - ep_channel->intmask = 0xFFFFFFFF; + endpoint_channel->xfer_size = (1 << 19) | (0x3 << 29) | endpoint->wMaxPacketSize; - ep_channel->cchar &= ~(1 << 15); - ep_channel->cchar |= (ep_dir << 15); - - ep_channel->cchar &= ~(1 << 30); - ep_channel->cchar &= ~(1 << 31); - ep_channel->cchar |= (1 << 17); - uint8_t mc = endpoint->bInterval & 0x3; - ep_channel->cchar &= ~(0b11 << 20); - ep_channel->cchar |= (mc << 20); + endpoint_channel->cchar &= ~(0b11 << 20); + endpoint_channel->cchar |= (mc << 20); + + TEMP_input_buffer = allocate_in_page(mem_page, 8, ALIGN_64B, true, true); - // ep_channel->cchar |= (1 << 19); + need_new_endpoint = true; + } + break; + default: { kprintf("Unknown type %x", header->bDescriptorType); return false; } + } + i += header->bLength; + } - delay(1000); + return true; + +} - ep_channel->cchar |= (1 << 31); +bool DWC2Driver::poll_interrupt_in(){ + if (endpoint_channel->cchar & 1) + return false; + endpoint_channel->dma = (uintptr_t)TEMP_input_buffer; + endpoint_channel->xfer_size = (1 << 19) | (0x3 << 29) | 8; - need_new_endpoint = true; + endpoint_channel->intmask = 0xFFFFFFFF; - if (!wait(&ep_channel->interrupt, 1, true, 20000)){ - kprintf("Did not receive a keystroke"); - return false; - } + endpoint_channel->interrupt = 0xFFFFFFFF; + + endpoint_channel->cchar &= ~(1 << 30); + endpoint_channel->cchar &= ~(1 << 31); - kprintf("Keystroke received"); - } - break; - default: kprintf("Unknown type %x", header->bDescriptorType); - } - i += header->bLength; + endpoint_channel->cchar |= (1 << 31); + + if (!wait(&endpoint_channel->interrupt, 1, true, 10)){ + return false; } - return true; + endpoint_channel->interrupt = 0xFFFFFFFF; + endpoint_channel->cchar &= ~(1 << 31); + + keypress kp; + keypress *rkp = (keypress*)TEMP_input_buffer; + if (is_new_keypress(rkp, &last_keypress) || repeated_keypresses > 3){ + if (is_new_keypress(rkp, &last_keypress)) + repeated_keypresses = 0; + kp.modifier = rkp->modifier; + for (int i = 0; i < 6; i++){ + kp.keys[i] = rkp->keys[i]; + } + last_keypress = kp; + register_keypress(kp); + return true; + } else + repeated_keypresses++; + + return false; } void DWC2Driver::hub_enumerate(dwc2_host_channel *channel, uint16_t address){ diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index 785004a4..b37ded42 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -1,4 +1,5 @@ #include "types.h" +#include "keypress.h" typedef struct { uint32_t gotgctl; @@ -50,6 +51,7 @@ class DWC2Driver { bool port_reset(uint32_t *port); bool setup_device(dwc2_host_channel *channel); uint8_t address_device(dwc2_host_channel *channel); + bool poll_interrupt_in(); private: dwc2_host_channel* get_channel(uint16_t channel); void assign_channel(dwc2_host_channel* channel, uint8_t device, uint8_t endpoint, uint8_t ep_type); @@ -61,4 +63,7 @@ class DWC2Driver { dwc2_host *host; uint8_t next_channel; uint8_t next_address; + dwc2_host_channel *endpoint_channel; + keypress last_keypress; + int repeated_keypresses = 0; }; \ No newline at end of file diff --git a/kernel/input/input_dispatch.cpp b/kernel/input/input_dispatch.cpp index 14530f54..38d9b8cd 100644 --- a/kernel/input/input_dispatch.cpp +++ b/kernel/input/input_dispatch.cpp @@ -18,6 +18,8 @@ uint16_t shortcut_count = 0; bool secure_mode = false; +DWC2Driver dwc_driver; + void register_keypress(keypress kp) { if (!secure_mode){ @@ -85,6 +87,8 @@ bool is_new_keypress(keypress* current, keypress* previous) { } bool sys_read_input(int pid, keypress *out){ + if (BOARD_TYPE == 2) + dwc_driver.poll_interrupt_in(); process_t *process = get_proc_by_pid(pid); if (process->input_buffer.read_index == process->input_buffer.write_index) return false; @@ -105,8 +109,6 @@ bool sys_shortcut_triggered(uint16_t pid, uint16_t sid){ return false; } -DWC2Driver dwc_driver; - bool input_init(){ if (BOARD_TYPE == 2){ return dwc_driver.init(); diff --git a/kernel/kernel.c b/kernel/kernel.c index 4aa271b9..c7f7d056 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -70,7 +70,7 @@ void kernel_main() { kprintf("MMU Mapped"); if (!disk_init()) - panic("Disk read failure"); + panic("Disk read failure"); kprintf("Kernel initialization finished"); diff --git a/kernel/kernel_processes/windows/desktop.cpp b/kernel/kernel_processes/windows/desktop.cpp index 5507fc51..121e9ac4 100644 --- a/kernel/kernel_processes/windows/desktop.cpp +++ b/kernel/kernel_processes/windows/desktop.cpp @@ -57,6 +57,7 @@ void Desktop::draw_desktop(){ keypress kp; gpu_point old_selected = selected; while (sys_read_input_current(&kp)){ + //TODO: there's a crash when moving in the desktop with no processes loaded. Memcpy for (int i = 0; i < 6; i++){ char key = kp.keys[i]; if (key == KEY_ENTER){ From 1988e881c5e5ee7792a2c09d791c73d0e7a2505c Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 30 Jun 2025 00:00:00 +0000 Subject: [PATCH 37/79] Moved configuration endpoint to own function --- kernel/input/dwc2.cpp | 91 +++++++++++++++++++++++-------------------- kernel/input/dwc2.hpp | 2 + 2 files changed, 50 insertions(+), 43 deletions(-) diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index c7904b91..801e50fd 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -86,10 +86,9 @@ uint8_t DWC2Driver::address_device(dwc2_host_channel *channel){ bool DWC2Driver::setup_device(dwc2_host_channel *channel){ - uint8_t chan_num = ((uintptr_t)channel - DWC2_BASE - 0x500)/0x20; uint8_t address = (channel->cchar >> 22) & 0xFFFF; - kprintf("Speaking to device %i on channel %i",address, chan_num); + kprintf("Speaking to device %i",address); if (channel->splt) kprintf("Using split from original device %i:%i", (channel->splt >> 7) & 0x7F, (channel->splt) & 0x7F); @@ -107,7 +106,7 @@ bool DWC2Driver::setup_device(dwc2_host_channel *channel){ address = (channel->cchar >> 22) & 0xFFFF; - kprintf("Changed address of device to %i on channel %i",address, chan_num); + kprintf("Changed address of device to %i",address); usb_string_language_descriptor* lang_desc = (usb_string_language_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_language_descriptor), ALIGN_64B, true, true); @@ -240,9 +239,52 @@ bool DWC2Driver::request_descriptor(dwc2_host_channel *channel, uint8_t rType, u return request_sized_descriptor(channel, rType, request, type, index, wIndex, descriptor->bLength, out_descriptor); } +bool DWC2Driver::configure_endpoint(dwc2_host_channel *channel, usb_endpoint_descriptor *endpoint, uint8_t configuration_value){ + uint8_t ep_address = endpoint->bEndpointAddress; + uint8_t ep_num = ep_address & 0x0F; + uint8_t ep_dir = (ep_address & 0x80) >> 7; + + uint8_t address = (channel->cchar >> 22) & 0xFFFF; + + uint8_t ep_type = endpoint->bmAttributes & 0x03; // 0 = Control, 1 = Iso, 2 = Bulk, 3 = Interrupt + + kprintf("[DWC2] endpoint %i info. Direction %i type %i",ep_num, ep_dir, ep_type); + + //Configure endpoint + request_sized_descriptor(channel, 0x00, 0x09, 0, configuration_value, 0, 0, 0); + + uint8_t conf; + request_sized_descriptor(channel, 0x80, 0x08, 0, 0, 0, 1, &conf); + + if (!conf){ + kprintf("Failed to set configuration for device"); + return false; + } + + endpoint_channel = get_channel(next_channel++); + assign_channel(endpoint_channel, address, ep_num, ep_type); + if (channel->splt) + endpoint_channel->splt = channel->splt; + + endpoint_channel->cchar &= ~(1 << 15); + endpoint_channel->cchar |= (ep_dir << 15); + + endpoint_channel->cchar &= ~0x7FF; + endpoint_channel->cchar |= endpoint->wMaxPacketSize; + + endpoint_channel->xfer_size = (1 << 19) | (0x3 << 29) | endpoint->wMaxPacketSize; + + uint8_t mc = endpoint->bInterval & 0x3; + endpoint_channel->cchar &= ~(0b11 << 20); + endpoint_channel->cchar |= (mc << 20); + + TEMP_input_buffer = allocate_in_page(mem_page, 8, ALIGN_64B, true, true); + + return true; +} + bool DWC2Driver::get_configuration(dwc2_host_channel *channel){ - uint8_t chan_num = ((uintptr_t)channel - DWC2_BASE - 0x500)/0x20; uint8_t address = (channel->cchar >> 22) & 0xFFFF; uint16_t ep_num = 0; @@ -322,46 +364,9 @@ bool DWC2Driver::get_configuration(dwc2_host_channel *channel){ } break; case 0x5: {//Endpoint - usb_endpoint_descriptor *endpoint = (usb_endpoint_descriptor*)&config->data[i]; - kprintf("[DWC2] endpoint address %x. Device address %i",endpoint->bEndpointAddress,address); - uint8_t ep_address = endpoint->bEndpointAddress; - uint8_t ep_num = ep_address & 0x0F; - uint8_t ep_dir = (ep_address & 0x80) >> 7; - - uint8_t ep_type = endpoint->bmAttributes & 0x03; // 0 = Control, 1 = Iso, 2 = Bulk, 3 = Interrupt - - kprintf("[DWC2] endpoint %i info. Direction %i type %i",ep_num, ep_dir, ep_type); - - //Configure endpoint - request_sized_descriptor(channel, 0x00, 0x09, 0, config->bConfigurationValue, 0, 0, 0); - - uint8_t conf; - request_sized_descriptor(channel, 0x80, 0x08, 0, 0, 0, 1, &conf); - - if (!conf){ - kprintf("Failed to set configuration for device"); - return false; - } - - endpoint_channel = get_channel(next_channel++); - assign_channel(endpoint_channel, address, ep_num, ep_type); - if (channel->splt) - endpoint_channel->splt = channel->splt; - - endpoint_channel->cchar &= ~(1 << 15); - endpoint_channel->cchar |= (ep_dir << 15); - - endpoint_channel->cchar &= ~0x7FF; - endpoint_channel->cchar |= endpoint->wMaxPacketSize; - - endpoint_channel->xfer_size = (1 << 19) | (0x3 << 29) | endpoint->wMaxPacketSize; - - uint8_t mc = endpoint->bInterval & 0x3; - endpoint_channel->cchar &= ~(0b11 << 20); - endpoint_channel->cchar |= (mc << 20); - - TEMP_input_buffer = allocate_in_page(mem_page, 8, ALIGN_64B, true, true); + + if (!configure_endpoint(channel, endpoint, config->bConfigurationValue)) return false; need_new_endpoint = true; } diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index b37ded42..02c45ae5 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -1,5 +1,6 @@ #include "types.h" #include "keypress.h" +#include "xhci_types.h" typedef struct { uint32_t gotgctl; @@ -52,6 +53,7 @@ class DWC2Driver { bool setup_device(dwc2_host_channel *channel); uint8_t address_device(dwc2_host_channel *channel); bool poll_interrupt_in(); + bool configure_endpoint(dwc2_host_channel *channel, usb_endpoint_descriptor *endpoint, uint8_t configuration_value); private: dwc2_host_channel* get_channel(uint16_t channel); void assign_channel(dwc2_host_channel* channel, uint8_t device, uint8_t endpoint, uint8_t ep_type); From 9a4d3d9945850984a9b37b565185eb4f2d00754b Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 30 Jun 2025 00:00:00 +0000 Subject: [PATCH 38/79] Introduced a channel map to setup_device --- kernel/input/dwc2.cpp | 44 ++++++++++++++++++++++++++----------------- kernel/input/dwc2.hpp | 8 ++++++-- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index 801e50fd..fd3e721b 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -13,8 +13,16 @@ dwc2_host_channel* DWC2Driver::get_channel(uint16_t channel){ return (dwc2_host_channel *)(DWC2_BASE + 0x500 + (channel * 0x20)); } -void DWC2Driver::assign_channel(dwc2_host_channel* channel, uint8_t device, uint8_t endpoint, uint8_t ep_type){ +uint8_t DWC2Driver::assign_channel(uint8_t device, uint8_t endpoint, uint8_t ep_type){ + uint8_t new_chan = ++next_channel; + dwc2_host_channel *channel = get_channel(new_chan); channel->cchar = (device << 22) | (endpoint << 11) | (ep_type << 18); + channel_map[device << 8 | endpoint] = new_chan; + return new_chan; +} + +dwc2_host_channel* DWC2Driver::get_channel(uint8_t device, uint8_t endpoint){ + return get_channel(channel_map[device << 8 | endpoint]); } uint16_t DWC2Driver::packet_size(uint16_t speed){ @@ -62,17 +70,16 @@ bool DWC2Driver::init() { return false; } + channel_map = IndexMap(64); + kprintf("Port reset %x",host->port); port_speed = (host->port >> 17) & 0x3; kprintf("Port speed %i",port_speed); - dwc2_host_channel *channel = get_channel(next_channel++); - - assign_channel(channel, 0, 0, 0); mem_page = alloc_page(0x1000, true, true, false); - setup_device(channel); + setup_device(); register_device_memory(DWC2_BASE, DWC2_BASE); @@ -80,11 +87,15 @@ bool DWC2Driver::init() { } uint8_t DWC2Driver::address_device(dwc2_host_channel *channel){ - request_sized_descriptor(channel, 0x0, 0x5, 0, ++next_address, 0, 0, 0); + uint8_t new_address = ++next_address; + request_sized_descriptor(get_channel(0), 0x0, 0x5, 0, new_address, 0, 0, 0); + channel_map[new_address << 16] = assign_channel(new_address, 0, 0); return next_address; } -bool DWC2Driver::setup_device(dwc2_host_channel *channel){ +bool DWC2Driver::setup_device(){ + + dwc2_host_channel *channel = get_channel(0); uint8_t address = (channel->cchar >> 22) & 0xFFFF; @@ -99,12 +110,14 @@ bool DWC2Driver::setup_device(dwc2_host_channel *channel){ return false; } - uint16_t addr = address_device(channel); + address = address_device(channel); - channel->cchar &= ~(0x7F << 22); - channel->cchar |= (addr << 22); + channel->splt = 0; - address = (channel->cchar >> 22) & 0xFFFF; + channel = get_channel(channel_map[address << 16]); + + channel->cchar &= ~(0x7F << 22); + channel->cchar |= (address << 22); kprintf("Changed address of device to %i",address); @@ -261,8 +274,7 @@ bool DWC2Driver::configure_endpoint(dwc2_host_channel *channel, usb_endpoint_des return false; } - endpoint_channel = get_channel(next_channel++); - assign_channel(endpoint_channel, address, ep_num, ep_type); + endpoint_channel = get_channel(assign_channel(address, ep_num, ep_type)); if (channel->splt) endpoint_channel->splt = channel->splt; @@ -439,10 +451,8 @@ void DWC2Driver::hub_enumerate(dwc2_host_channel *channel, uint16_t address){ kprintf("Port not enabled or device not connected"); return; } - uint16_t new_channel = next_channel++; - dwc2_host_channel *dev_channel = get_channel(new_channel); + dwc2_host_channel *dev_channel = get_channel(0); dev_channel->splt = (1 << 31) | (1 << 16) | (address << 7) | (port << 0); - if (address == 1) - setup_device(dev_channel); + setup_device(); } } \ No newline at end of file diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index 02c45ae5..728e0523 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -1,6 +1,7 @@ #include "types.h" #include "keypress.h" #include "xhci_types.h" +#include "std/indexmap.hpp" typedef struct { uint32_t gotgctl; @@ -50,14 +51,16 @@ class DWC2Driver { bool get_configuration(dwc2_host_channel *channel); void hub_enumerate(dwc2_host_channel *channel, uint16_t address); bool port_reset(uint32_t *port); - bool setup_device(dwc2_host_channel *channel); + bool setup_device(); uint8_t address_device(dwc2_host_channel *channel); bool poll_interrupt_in(); bool configure_endpoint(dwc2_host_channel *channel, usb_endpoint_descriptor *endpoint, uint8_t configuration_value); + // bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value); private: dwc2_host_channel* get_channel(uint16_t channel); - void assign_channel(dwc2_host_channel* channel, uint8_t device, uint8_t endpoint, uint8_t ep_type); + uint8_t assign_channel(uint8_t device, uint8_t endpoint, uint8_t ep_type); bool make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, sizedptr data); + dwc2_host_channel* get_channel(uint8_t device, uint8_t endpoint); void *mem_page; uint16_t port_speed; void *TEMP_input_buffer; @@ -68,4 +71,5 @@ class DWC2Driver { dwc2_host_channel *endpoint_channel; keypress last_keypress; int repeated_keypresses = 0; + IndexMap channel_map; }; \ No newline at end of file From a211f6fed0ac8a3466f6217c703ce78453462f60 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 30 Jun 2025 00:00:00 +0000 Subject: [PATCH 39/79] Get configuration uses address --- kernel/input/dwc2.cpp | 17 +++++++++-------- kernel/input/dwc2.hpp | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index fd3e721b..dfccc2fa 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -89,8 +89,8 @@ bool DWC2Driver::init() { uint8_t DWC2Driver::address_device(dwc2_host_channel *channel){ uint8_t new_address = ++next_address; request_sized_descriptor(get_channel(0), 0x0, 0x5, 0, new_address, 0, 0, 0); - channel_map[new_address << 16] = assign_channel(new_address, 0, 0); - return next_address; + channel_map[new_address << 8] = assign_channel(new_address, 0, 0); + return new_address; } bool DWC2Driver::setup_device(){ @@ -114,12 +114,12 @@ bool DWC2Driver::setup_device(){ channel->splt = 0; - channel = get_channel(channel_map[address << 16]); + channel = get_channel(channel_map[address << 8]); channel->cchar &= ~(0x7F << 22); channel->cchar |= (address << 22); - kprintf("Changed address of device to %i",address); + kprintf("Changed address of device to %i %x",address,(uintptr_t)channel); usb_string_language_descriptor* lang_desc = (usb_string_language_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_language_descriptor), ALIGN_64B, true, true); @@ -161,7 +161,7 @@ bool DWC2Driver::setup_device(){ } } - get_configuration(channel); + get_configuration(address); return true; } @@ -295,10 +295,11 @@ bool DWC2Driver::configure_endpoint(dwc2_host_channel *channel, usb_endpoint_des return true; } -bool DWC2Driver::get_configuration(dwc2_host_channel *channel){ - - uint8_t address = (channel->cchar >> 22) & 0xFFFF; +bool DWC2Driver::get_configuration(uint8_t address){ + dwc2_host_channel *channel = get_channel(channel_map[address << 8]); + + kprintf("Getting configuration for device %i %x",address, (uintptr_t)channel); uint16_t ep_num = 0; usb_configuration_descriptor* config = (usb_configuration_descriptor*)allocate_in_page(mem_page, sizeof(usb_configuration_descriptor), ALIGN_64B, true, true); diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index 728e0523..48b6656e 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -48,7 +48,7 @@ class DWC2Driver { bool request_descriptor(dwc2_host_channel *channel, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor); bool request_sized_descriptor(dwc2_host_channel *channel, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor); uint16_t packet_size(uint16_t speed); - bool get_configuration(dwc2_host_channel *channel); + bool get_configuration(uint8_t address); void hub_enumerate(dwc2_host_channel *channel, uint16_t address); bool port_reset(uint32_t *port); bool setup_device(); From 57076b5bd5e6dbc41df913c459ad387e7f5f355a Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 30 Jun 2025 00:00:00 +0000 Subject: [PATCH 40/79] Address device and configure endpoint removed channel dependency --- kernel/input/dwc2.cpp | 13 +++++++------ kernel/input/dwc2.hpp | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index dfccc2fa..c22accc0 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -86,7 +86,7 @@ bool DWC2Driver::init() { return true; } -uint8_t DWC2Driver::address_device(dwc2_host_channel *channel){ +uint8_t DWC2Driver::address_device(){ uint8_t new_address = ++next_address; request_sized_descriptor(get_channel(0), 0x0, 0x5, 0, new_address, 0, 0, 0); channel_map[new_address << 8] = assign_channel(new_address, 0, 0); @@ -110,7 +110,7 @@ bool DWC2Driver::setup_device(){ return false; } - address = address_device(channel); + address = address_device(); channel->splt = 0; @@ -252,13 +252,14 @@ bool DWC2Driver::request_descriptor(dwc2_host_channel *channel, uint8_t rType, u return request_sized_descriptor(channel, rType, request, type, index, wIndex, descriptor->bLength, out_descriptor); } -bool DWC2Driver::configure_endpoint(dwc2_host_channel *channel, usb_endpoint_descriptor *endpoint, uint8_t configuration_value){ +bool DWC2Driver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value){ + + dwc2_host_channel *channel = get_channel(channel_map[address << 8]); + uint8_t ep_address = endpoint->bEndpointAddress; uint8_t ep_num = ep_address & 0x0F; uint8_t ep_dir = (ep_address & 0x80) >> 7; - uint8_t address = (channel->cchar >> 22) & 0xFFFF; - uint8_t ep_type = endpoint->bmAttributes & 0x03; // 0 = Control, 1 = Iso, 2 = Bulk, 3 = Interrupt kprintf("[DWC2] endpoint %i info. Direction %i type %i",ep_num, ep_dir, ep_type); @@ -379,7 +380,7 @@ bool DWC2Driver::get_configuration(uint8_t address){ case 0x5: {//Endpoint usb_endpoint_descriptor *endpoint = (usb_endpoint_descriptor*)&config->data[i]; - if (!configure_endpoint(channel, endpoint, config->bConfigurationValue)) return false; + if (!configure_endpoint(address, endpoint, config->bConfigurationValue)) return false; need_new_endpoint = true; } diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index 48b6656e..76fdbda4 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -52,9 +52,9 @@ class DWC2Driver { void hub_enumerate(dwc2_host_channel *channel, uint16_t address); bool port_reset(uint32_t *port); bool setup_device(); - uint8_t address_device(dwc2_host_channel *channel); + uint8_t address_device(); bool poll_interrupt_in(); - bool configure_endpoint(dwc2_host_channel *channel, usb_endpoint_descriptor *endpoint, uint8_t configuration_value); + bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value); // bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value); private: dwc2_host_channel* get_channel(uint16_t channel); From 701065ec86216449452884341078de6f75b8bdda Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 30 Jun 2025 00:00:00 +0000 Subject: [PATCH 41/79] Hub uses only address --- kernel/input/dwc2.cpp | 5 +++-- kernel/input/dwc2.hpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index c22accc0..8e43dcee 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -346,7 +346,7 @@ bool DWC2Driver::get_configuration(uint8_t address){ usb_interface_descriptor *interface = (usb_interface_descriptor *)&config->data[i]; if (interface->bInterfaceClass == 0x9){ kprintf("USB Hub detected %i", interface->bNumEndpoints); - hub_enumerate(channel, address); + hub_enumerate(address); return true; } else if (interface->bInterfaceClass != 0x3){ kprintf("[DWC2 implementation error] non-hid devices not supported yet %x",interface->bInterfaceClass); @@ -437,7 +437,8 @@ bool DWC2Driver::poll_interrupt_in(){ return false; } -void DWC2Driver::hub_enumerate(dwc2_host_channel *channel, uint16_t address){ +void DWC2Driver::hub_enumerate(uint8_t address){ + dwc2_host_channel *channel = get_channel(channel_map[address << 8]); //TODO: actually support multiple devices uint8_t port = 1; uint32_t port_status; diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index 76fdbda4..1564f88d 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -49,7 +49,7 @@ class DWC2Driver { bool request_sized_descriptor(dwc2_host_channel *channel, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor); uint16_t packet_size(uint16_t speed); bool get_configuration(uint8_t address); - void hub_enumerate(dwc2_host_channel *channel, uint16_t address); + void hub_enumerate(uint8_t address); bool port_reset(uint32_t *port); bool setup_device(); uint8_t address_device(); From dce81e29abfb333245b1f95cb9262ea96e960198 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 30 Jun 2025 00:00:00 +0000 Subject: [PATCH 42/79] Request descriptors with just address and endpoint --- kernel/input/dwc2.cpp | 41 +++++++++++++++++++++-------------------- kernel/input/dwc2.hpp | 4 ++-- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index 8e43dcee..2297aa4d 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -88,7 +88,7 @@ bool DWC2Driver::init() { uint8_t DWC2Driver::address_device(){ uint8_t new_address = ++next_address; - request_sized_descriptor(get_channel(0), 0x0, 0x5, 0, new_address, 0, 0, 0); + request_sized_descriptor(0, 0, 0x0, 0x5, 0, new_address, 0, 0, 0); channel_map[new_address << 8] = assign_channel(new_address, 0, 0); return new_address; } @@ -105,7 +105,7 @@ bool DWC2Driver::setup_device(){ usb_device_descriptor* descriptor = (usb_device_descriptor*)allocate_in_page(mem_page, sizeof(usb_device_descriptor), ALIGN_64B, true, true); - if (!request_descriptor(channel, 0x80, 6, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ + if (!request_descriptor(address, 0, 0x80, 6, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ kprintf_raw("[DWC2 error] failed to get device descriptor"); return false; } @@ -125,7 +125,7 @@ bool DWC2Driver::setup_device(){ bool use_lang_desc = true; - if (!request_descriptor(channel, 0x80, 6, USB_STRING_DESCRIPTOR, 0, 0, lang_desc)){ + if (!request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, 0, 0, lang_desc)){ kprintf_raw("[DWC2 warning] failed to get language descriptor"); use_lang_desc = false; } @@ -139,21 +139,21 @@ bool DWC2Driver::setup_device(){ //TODO: we want to maintain the strings so we can have USB device information, and rework it to silece the alignment warning uint16_t langid = lang_desc->lang_ids[0]; usb_string_descriptor* prod_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (request_descriptor(channel, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iProduct, langid, prod_name)){ + if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iProduct, langid, prod_name)){ char name[128]; if (utf16tochar(prod_name->unicode_string, name, sizeof(name))) { kprintf("[DWC2 device] Product name: %s", (uint64_t)name); } } usb_string_descriptor* man_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (request_descriptor(channel, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iManufacturer, langid, man_name)){ + if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iManufacturer, langid, man_name)){ char name[128]; if (utf16tochar(man_name->unicode_string, name, sizeof(name))) { kprintf("[DWC2 device] Manufacturer name: %s", (uint64_t)name); } } usb_string_descriptor* ser_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (request_descriptor(channel, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iSerialNumber, langid, ser_name)){ + if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iSerialNumber, langid, ser_name)){ char name[128]; if (utf16tochar(ser_name->unicode_string, name, sizeof(name))) { kprintf("[DWC2 device] Serial: %s", (uint64_t)name); @@ -205,7 +205,7 @@ bool DWC2Driver::make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, return true; } -bool DWC2Driver::request_sized_descriptor(dwc2_host_channel *channel, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor){ +bool DWC2Driver::request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor){ usb_setup_packet packet = { .bmRequestType = rType, @@ -217,6 +217,7 @@ bool DWC2Driver::request_sized_descriptor(dwc2_host_channel *channel, uint8_t rT bool is_in = (rType & 0x80) != 0; + dwc2_host_channel *channel = address == 0 ? get_channel(0) : get_channel(channel_map[address << 8 | endpoint]); // kprintf("RT: %x R: %x V: %x I: %x L: %x",packet.bmRequestType,packet.bRequest,packet.wValue,packet.wIndex,packet.wLength); if (!make_transfer(channel, false, 0x3, (sizedptr){(uintptr_t)&packet, sizeof(uintptr_t)})){ @@ -239,8 +240,8 @@ bool DWC2Driver::request_sized_descriptor(dwc2_host_channel *channel, uint8_t rT return true; } -bool DWC2Driver::request_descriptor(dwc2_host_channel *channel, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor){ - if (!request_sized_descriptor(channel, rType, request, type, index, wIndex, sizeof(usb_descriptor_header), out_descriptor)){ +bool DWC2Driver::request_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor){ + if (!request_sized_descriptor(address, endpoint, rType, request, type, index, wIndex, sizeof(usb_descriptor_header), out_descriptor)){ kprintf_raw("[DWC2 error] Failed to get descriptor header. Size %i", sizeof(usb_descriptor_header)); return false; } @@ -249,7 +250,7 @@ bool DWC2Driver::request_descriptor(dwc2_host_channel *channel, uint8_t rType, u kprintf_raw("[DWC2 error] wrong descriptor size %i",descriptor->bLength); return false; } - return request_sized_descriptor(channel, rType, request, type, index, wIndex, descriptor->bLength, out_descriptor); + return request_sized_descriptor(address, endpoint, rType, request, type, index, wIndex, descriptor->bLength, out_descriptor); } bool DWC2Driver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value){ @@ -265,10 +266,10 @@ bool DWC2Driver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *en kprintf("[DWC2] endpoint %i info. Direction %i type %i",ep_num, ep_dir, ep_type); //Configure endpoint - request_sized_descriptor(channel, 0x00, 0x09, 0, configuration_value, 0, 0, 0); + request_sized_descriptor(address, 0, 0x00, 0x09, 0, configuration_value, 0, 0, 0); uint8_t conf; - request_sized_descriptor(channel, 0x80, 0x08, 0, 0, 0, 1, &conf); + request_sized_descriptor(address, 0, 0x80, 0x08, 0, 0, 0, 1, &conf); if (!conf){ kprintf("Failed to set configuration for device"); @@ -304,17 +305,17 @@ bool DWC2Driver::get_configuration(uint8_t address){ uint16_t ep_num = 0; usb_configuration_descriptor* config = (usb_configuration_descriptor*)allocate_in_page(mem_page, sizeof(usb_configuration_descriptor), ALIGN_64B, true, true); - if (!request_sized_descriptor(channel, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, 8, config)){ + if (!request_sized_descriptor(address, 0, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, 8, config)){ kprintf("[DWC2 error] could not get config descriptor header"); return false; } - if (!request_sized_descriptor(channel, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->header.bLength, config)){ + if (!request_sized_descriptor(address, 0, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->header.bLength, config)){ kprintf("[DWC2 error] could not get full config descriptor"); return false; } - if (!request_sized_descriptor(channel, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->wTotalLength, config)){ + if (!request_sized_descriptor(address, 0, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->wTotalLength, config)){ kprintf("[DWC2 error] could not get full config descriptor"); return false; } @@ -371,7 +372,7 @@ bool DWC2Driver::get_configuration(uint8_t address){ if (hid->descriptors[j].bDescriptorType == 0x22){//REPORT HID report_length = hid->descriptors[j].wDescriptorLength; report_descriptor = (uint8_t*)allocate_in_page(mem_page, report_length, ALIGN_64B, true, true); - request_descriptor(channel, 0x81, 6, 0x22, 0, interface_index-1, report_descriptor); + request_descriptor(address, 0, 0x81, 6, 0x22, 0, interface_index-1, report_descriptor); kprintf("[DWC2] retrieved report descriptor of length %i at %x", report_length, (uintptr_t)report_descriptor); } } @@ -442,14 +443,14 @@ void DWC2Driver::hub_enumerate(uint8_t address){ //TODO: actually support multiple devices uint8_t port = 1; uint32_t port_status; - request_sized_descriptor(channel, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); + request_sized_descriptor(address, 0, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); if (port_status & 1){ kprintf("Port %i status %b",port, port_status); - request_sized_descriptor(channel, 0x23, 3, 0, 4, port, 0, 0);//Port Reset + request_sized_descriptor(address, 0, 0x23, 3, 0, 4, port, 0, 0);//Port Reset delay(50); - request_sized_descriptor(channel, 0x23, 1, 0, 4, port, 0, 0);//Port Reset Clear + request_sized_descriptor(address, 0, 0x23, 1, 0, 4, port, 0, 0);//Port Reset Clear delay(10); - request_sized_descriptor(channel, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); + request_sized_descriptor(address, 0, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); if (!(port_status & 0b11)){ kprintf("Port not enabled or device not connected"); return; diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index 1564f88d..a9a8b862 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -45,8 +45,8 @@ typedef struct { class DWC2Driver { public: bool init(); - bool request_descriptor(dwc2_host_channel *channel, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor); - bool request_sized_descriptor(dwc2_host_channel *channel, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor); + bool request_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor); + bool request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor); uint16_t packet_size(uint16_t speed); bool get_configuration(uint8_t address); void hub_enumerate(uint8_t address); From b4801490c2a822371019286b444bf193175ca056 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 30 Jun 2025 00:00:00 +0000 Subject: [PATCH 43/79] Created USB driver with common functionality --- kernel/input/dwc2.cpp | 258 ++------------------------------ kernel/input/dwc2.hpp | 21 +-- kernel/input/input_dispatch.cpp | 8 +- kernel/input/usb.cpp | 213 ++++++++++++++++++++++++++ kernel/input/usb.hpp | 25 ++++ 5 files changed, 265 insertions(+), 260 deletions(-) create mode 100644 kernel/input/usb.cpp create mode 100644 kernel/input/usb.hpp diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index 2297aa4d..12b76496 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -2,7 +2,6 @@ #include "async.h" #include "console/kio.h" #include "memory/page_allocator.h" -#include "xhci_types.h"//TODO: split into xhci and USB types #include "std/string.h" #include "memory/mmu.h" #include "input_dispatch.h" @@ -21,21 +20,6 @@ uint8_t DWC2Driver::assign_channel(uint8_t device, uint8_t endpoint, uint8_t ep_ return new_chan; } -dwc2_host_channel* DWC2Driver::get_channel(uint8_t device, uint8_t endpoint){ - return get_channel(channel_map[device << 8 | endpoint]); -} - -uint16_t DWC2Driver::packet_size(uint16_t speed){ - switch (speed) { - case 2: return 8;//Low - case 1: - case 3: return 64;//High & full - case 4: - case 5: - default: return 512;//Super & Super Plus & Default - } -} - bool DWC2Driver::init() { dwc2 = (dwc2_regs*)DWC2_BASE; @@ -52,12 +36,12 @@ bool DWC2Driver::init() { dwc2->gusbcfg &= ~(1 << 30);//Device mode disable dwc2->gusbcfg |= (1 << 29);//Host mode enable - delay(200); - dwc2->gahbcfg |= (1 << 5);//DMA dwc2->gintmsk = 0xffffffff; + //Device setup0 + host->port |= (1 << 12); if (!wait(&host->port, 1, true, 2000)){ @@ -70,7 +54,7 @@ bool DWC2Driver::init() { return false; } - channel_map = IndexMap(64); + channel_map = IndexMap(UINT16_MAX); kprintf("Port reset %x",host->port); @@ -90,94 +74,10 @@ uint8_t DWC2Driver::address_device(){ uint8_t new_address = ++next_address; request_sized_descriptor(0, 0, 0x0, 0x5, 0, new_address, 0, 0, 0); channel_map[new_address << 8] = assign_channel(new_address, 0, 0); + get_channel(0)->splt = 0; return new_address; } -bool DWC2Driver::setup_device(){ - - dwc2_host_channel *channel = get_channel(0); - - uint8_t address = (channel->cchar >> 22) & 0xFFFF; - - kprintf("Speaking to device %i",address); - if (channel->splt) - kprintf("Using split from original device %i:%i", (channel->splt >> 7) & 0x7F, (channel->splt) & 0x7F); - - usb_device_descriptor* descriptor = (usb_device_descriptor*)allocate_in_page(mem_page, sizeof(usb_device_descriptor), ALIGN_64B, true, true); - - if (!request_descriptor(address, 0, 0x80, 6, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ - kprintf_raw("[DWC2 error] failed to get device descriptor"); - return false; - } - - address = address_device(); - - channel->splt = 0; - - channel = get_channel(channel_map[address << 8]); - - channel->cchar &= ~(0x7F << 22); - channel->cchar |= (address << 22); - - kprintf("Changed address of device to %i %x",address,(uintptr_t)channel); - - usb_string_language_descriptor* lang_desc = (usb_string_language_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_language_descriptor), ALIGN_64B, true, true); - - bool use_lang_desc = true; - - if (!request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, 0, 0, lang_desc)){ - kprintf_raw("[DWC2 warning] failed to get language descriptor"); - use_lang_desc = false; - } - - kprintf("[DWC2] Vendor %x",descriptor->idVendor); - kprintf("[DWC2] Product %x",descriptor->idProduct); - kprintf("[DWC2] USB version %x",descriptor->bcdUSB); - kprintf("[DWC2] EP0 Max Packet Size: %x", descriptor->bMaxPacketSize0); - kprintf("[DWC2] Configurations: %x", descriptor->bNumConfigurations); - if (use_lang_desc){ - //TODO: we want to maintain the strings so we can have USB device information, and rework it to silece the alignment warning - uint16_t langid = lang_desc->lang_ids[0]; - usb_string_descriptor* prod_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iProduct, langid, prod_name)){ - char name[128]; - if (utf16tochar(prod_name->unicode_string, name, sizeof(name))) { - kprintf("[DWC2 device] Product name: %s", (uint64_t)name); - } - } - usb_string_descriptor* man_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iManufacturer, langid, man_name)){ - char name[128]; - if (utf16tochar(man_name->unicode_string, name, sizeof(name))) { - kprintf("[DWC2 device] Manufacturer name: %s", (uint64_t)name); - } - } - usb_string_descriptor* ser_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iSerialNumber, langid, ser_name)){ - char name[128]; - if (utf16tochar(ser_name->unicode_string, name, sizeof(name))) { - kprintf("[DWC2 device] Serial: %s", (uint64_t)name); - } - } - } - - get_configuration(address); - - return true; -} - -bool DWC2Driver::port_reset(uint32_t *port){ - *port &= ~0b101110; - *port |= (1 << 8); - - delay(50); - - *port &= ~0b101110; - *port &= ~(1 << 8); - - return wait(port, (1 << 8), false, 2000); -} - bool DWC2Driver::make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, sizedptr data){ channel->dma = data.ptr; uint16_t max_size = packet_size(port_speed); @@ -240,42 +140,28 @@ bool DWC2Driver::request_sized_descriptor(uint8_t address, uint8_t endpoint, uin return true; } -bool DWC2Driver::request_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor){ - if (!request_sized_descriptor(address, endpoint, rType, request, type, index, wIndex, sizeof(usb_descriptor_header), out_descriptor)){ - kprintf_raw("[DWC2 error] Failed to get descriptor header. Size %i", sizeof(usb_descriptor_header)); - return false; - } - usb_descriptor_header* descriptor = (usb_descriptor_header*)out_descriptor; - if (descriptor->bLength == 0){ - kprintf_raw("[DWC2 error] wrong descriptor size %i",descriptor->bLength); - return false; - } - return request_sized_descriptor(address, endpoint, rType, request, type, index, wIndex, descriptor->bLength, out_descriptor); -} - bool DWC2Driver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value){ - dwc2_host_channel *channel = get_channel(channel_map[address << 8]); - uint8_t ep_address = endpoint->bEndpointAddress; uint8_t ep_num = ep_address & 0x0F; uint8_t ep_dir = (ep_address & 0x80) >> 7; - + uint8_t ep_type = endpoint->bmAttributes & 0x03; // 0 = Control, 1 = Iso, 2 = Bulk, 3 = Interrupt - + kprintf("[DWC2] endpoint %i info. Direction %i type %i",ep_num, ep_dir, ep_type); - + //Configure endpoint request_sized_descriptor(address, 0, 0x00, 0x09, 0, configuration_value, 0, 0, 0); - + uint8_t conf; request_sized_descriptor(address, 0, 0x80, 0x08, 0, 0, 0, 1, &conf); - + if (!conf){ kprintf("Failed to set configuration for device"); return false; } - + + dwc2_host_channel *channel = get_channel(channel_map[address << 8]); endpoint_channel = get_channel(assign_channel(address, ep_num, ep_type)); if (channel->splt) endpoint_channel->splt = channel->splt; @@ -297,104 +183,6 @@ bool DWC2Driver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *en return true; } -bool DWC2Driver::get_configuration(uint8_t address){ - - dwc2_host_channel *channel = get_channel(channel_map[address << 8]); - - kprintf("Getting configuration for device %i %x",address, (uintptr_t)channel); - uint16_t ep_num = 0; - - usb_configuration_descriptor* config = (usb_configuration_descriptor*)allocate_in_page(mem_page, sizeof(usb_configuration_descriptor), ALIGN_64B, true, true); - if (!request_sized_descriptor(address, 0, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, 8, config)){ - kprintf("[DWC2 error] could not get config descriptor header"); - return false; - } - - if (!request_sized_descriptor(address, 0, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->header.bLength, config)){ - kprintf("[DWC2 error] could not get full config descriptor"); - return false; - } - - if (!request_sized_descriptor(address, 0, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->wTotalLength, config)){ - kprintf("[DWC2 error] could not get full config descriptor"); - return false; - } - - uint16_t total_length = config->wTotalLength - config->header.bLength; - - kprintf("[DWC2] Config length %i (%i - %i)",total_length,config->wTotalLength,config->header.bLength); - - uint16_t interface_index = 0; - - bool need_new_endpoint = true; - - uint8_t* report_descriptor; - uint16_t report_length; - - for (uint16_t i = 0; i < total_length;){ - usb_descriptor_header* header = (usb_descriptor_header*)&config->data[i]; - if (header->bLength == 0){ - kprintf("Failed to get descriptor. Header size 0"); - return false; - } - if (need_new_endpoint){ - need_new_endpoint = false; - // device_endpoint = (xhci_usb_device_endpoint*)allocate_in_page(xhci_mem_page, sizeof(xhci_usb_device_endpoint), ALIGN_64B, true, true); - } - switch (header->bDescriptorType) - { - case 0x4: { //Interface - usb_interface_descriptor *interface = (usb_interface_descriptor *)&config->data[i]; - if (interface->bInterfaceClass == 0x9){ - kprintf("USB Hub detected %i", interface->bNumEndpoints); - hub_enumerate(address); - return true; - } else if (interface->bInterfaceClass != 0x3){ - kprintf("[DWC2 implementation error] non-hid devices not supported yet %x",interface->bInterfaceClass); - return false; - } - kprintf("[DWC2] interface protocol %x",interface->bInterfaceProtocol); - switch (interface->bInterfaceProtocol) - { - case 0x1: - // device_endpoint->type = KEYBOARD; - break; - - default: - break; - } - interface_index++; - } - break; - case 0x21: { //HID - usb_hid_descriptor *hid = (usb_hid_descriptor *)&config->data[i]; - for (uint8_t j = 0; j < hid->bNumDescriptors; j++){ - if (hid->descriptors[j].bDescriptorType == 0x22){//REPORT HID - report_length = hid->descriptors[j].wDescriptorLength; - report_descriptor = (uint8_t*)allocate_in_page(mem_page, report_length, ALIGN_64B, true, true); - request_descriptor(address, 0, 0x81, 6, 0x22, 0, interface_index-1, report_descriptor); - kprintf("[DWC2] retrieved report descriptor of length %i at %x", report_length, (uintptr_t)report_descriptor); - } - } - } - break; - case 0x5: {//Endpoint - usb_endpoint_descriptor *endpoint = (usb_endpoint_descriptor*)&config->data[i]; - - if (!configure_endpoint(address, endpoint, config->bConfigurationValue)) return false; - - need_new_endpoint = true; - } - break; - default: { kprintf("Unknown type %x", header->bDescriptorType); return false; } - } - i += header->bLength; - } - - return true; - -} - bool DWC2Driver::poll_interrupt_in(){ if (endpoint_channel->cchar & 1) return false; @@ -438,25 +226,7 @@ bool DWC2Driver::poll_interrupt_in(){ return false; } -void DWC2Driver::hub_enumerate(uint8_t address){ - dwc2_host_channel *channel = get_channel(channel_map[address << 8]); - //TODO: actually support multiple devices - uint8_t port = 1; - uint32_t port_status; - request_sized_descriptor(address, 0, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); - if (port_status & 1){ - kprintf("Port %i status %b",port, port_status); - request_sized_descriptor(address, 0, 0x23, 3, 0, 4, port, 0, 0);//Port Reset - delay(50); - request_sized_descriptor(address, 0, 0x23, 1, 0, 4, port, 0, 0);//Port Reset Clear - delay(10); - request_sized_descriptor(address, 0, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); - if (!(port_status & 0b11)){ - kprintf("Port not enabled or device not connected"); - return; - } - dwc2_host_channel *dev_channel = get_channel(0); - dev_channel->splt = (1 << 31) | (1 << 16) | (address << 7) | (port << 0); - setup_device(); - } +void DWC2Driver::handle_hub_routing(uint8_t hub, uint8_t port){ + dwc2_host_channel *dev_channel = get_channel(0); + dev_channel->splt = (1 << 31) | (1 << 16) | (hub << 7) | (port << 0); } \ No newline at end of file diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index a9a8b862..5a1d6661 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -1,6 +1,6 @@ -#include "types.h" -#include "keypress.h" -#include "xhci_types.h" +#pragma once + +#include "usb.hpp" #include "std/indexmap.hpp" typedef struct { @@ -42,26 +42,21 @@ typedef struct { uint32_t buf; } dwc2_host_channel; -class DWC2Driver { +class DWC2Driver: public USBDriver { public: + DWC2Driver() = default; bool init(); bool request_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor); bool request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor); - uint16_t packet_size(uint16_t speed); - bool get_configuration(uint8_t address); - void hub_enumerate(uint8_t address); - bool port_reset(uint32_t *port); - bool setup_device(); uint8_t address_device(); bool poll_interrupt_in(); bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value); - // bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value); + void handle_hub_routing(uint8_t hub, uint8_t port); + ~DWC2Driver() = default; private: dwc2_host_channel* get_channel(uint16_t channel); uint8_t assign_channel(uint8_t device, uint8_t endpoint, uint8_t ep_type); bool make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, sizedptr data); - dwc2_host_channel* get_channel(uint8_t device, uint8_t endpoint); - void *mem_page; uint16_t port_speed; void *TEMP_input_buffer; dwc2_regs *dwc2; @@ -71,5 +66,5 @@ class DWC2Driver { dwc2_host_channel *endpoint_channel; keypress last_keypress; int repeated_keypresses = 0; - IndexMap channel_map; + IndexMap channel_map; }; \ No newline at end of file diff --git a/kernel/input/input_dispatch.cpp b/kernel/input/input_dispatch.cpp index 38d9b8cd..ed6e786a 100644 --- a/kernel/input/input_dispatch.cpp +++ b/kernel/input/input_dispatch.cpp @@ -3,6 +3,7 @@ #include "process/scheduler.h" #include "dwc2.hpp" #include "hw/hw.h" +#include "std/std.hpp" process_t* focused_proc; @@ -18,7 +19,7 @@ uint16_t shortcut_count = 0; bool secure_mode = false; -DWC2Driver dwc_driver; +DWC2Driver *dwc_driver; void register_keypress(keypress kp) { @@ -88,7 +89,7 @@ bool is_new_keypress(keypress* current, keypress* previous) { bool sys_read_input(int pid, keypress *out){ if (BOARD_TYPE == 2) - dwc_driver.poll_interrupt_in(); + dwc_driver->poll_interrupt_in(); process_t *process = get_proc_by_pid(pid); if (process->input_buffer.read_index == process->input_buffer.write_index) return false; @@ -111,6 +112,7 @@ bool sys_shortcut_triggered(uint16_t pid, uint16_t sid){ bool input_init(){ if (BOARD_TYPE == 2){ - return dwc_driver.init(); + dwc_driver = new DWC2Driver();//TODO: QEMU Only + return dwc_driver->init(); } else return xhci_input_init(); } \ No newline at end of file diff --git a/kernel/input/usb.cpp b/kernel/input/usb.cpp new file mode 100644 index 00000000..5d4033ba --- /dev/null +++ b/kernel/input/usb.cpp @@ -0,0 +1,213 @@ +#include "usb.hpp" +#include "console/kio.h" +#include "async.h" +#include "std/string.h" +#include "memory/page_allocator.h" + +uint16_t USBDriver::packet_size(uint16_t speed){ + switch (speed) { + case 2: return 8;//Low + case 1: + case 3: return 64;//High & full + case 4: + case 5: + default: return 512;//Super & Super Plus & Default + } +} + +bool USBDriver::port_reset(uint32_t *port){ + *port &= ~0b101110; + *port |= (1 << 8); + + delay(50); + + *port &= ~0b101110; + *port &= ~(1 << 8); + + return wait(port, (1 << 8), false, 2000); +} + +bool USBDriver::setup_device(){ + + usb_device_descriptor* descriptor = (usb_device_descriptor*)allocate_in_page(mem_page, sizeof(usb_device_descriptor), ALIGN_64B, true, true); + + if (!request_descriptor(0, 0, 0x80, 6, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ + kprintf_raw("[USB error] failed to get device descriptor"); + return false; + } + + uint8_t address = address_device(); + + usb_string_language_descriptor* lang_desc = (usb_string_language_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_language_descriptor), ALIGN_64B, true, true); + + bool use_lang_desc = true; + + if (!request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, 0, 0, lang_desc)){ + kprintf_raw("[USB warning] failed to get language descriptor"); + use_lang_desc = false; + } + + kprintf("[USB] Vendor %x",descriptor->idVendor); + kprintf("[USB] Product %x",descriptor->idProduct); + kprintf("[USB] USB version %x",descriptor->bcdUSB); + kprintf("[USB] EP0 Max Packet Size: %x", descriptor->bMaxPacketSize0); + kprintf("[USB] Configurations: %x", descriptor->bNumConfigurations); + if (use_lang_desc){ + //TODO: we want to maintain the strings so we can have USB device information, and rework it to silece the alignment warning + uint16_t langid = lang_desc->lang_ids[0]; + usb_string_descriptor* prod_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); + if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iProduct, langid, prod_name)){ + char name[128]; + if (utf16tochar(prod_name->unicode_string, name, sizeof(name))) { + kprintf("[USB device] Product name: %s", (uint64_t)name); + } + } + usb_string_descriptor* man_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); + if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iManufacturer, langid, man_name)){ + char name[128]; + if (utf16tochar(man_name->unicode_string, name, sizeof(name))) { + kprintf("[USB device] Manufacturer name: %s", (uint64_t)name); + } + } + usb_string_descriptor* ser_name = (usb_string_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); + if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iSerialNumber, langid, ser_name)){ + char name[128]; + if (utf16tochar(ser_name->unicode_string, name, sizeof(name))) { + kprintf("[USB device] Serial: %s", (uint64_t)name); + } + } + } + + get_configuration(address); + + return true; +} + +bool USBDriver::get_configuration(uint8_t address){ + + uint16_t ep_num = 0; + + usb_configuration_descriptor* config = (usb_configuration_descriptor*)allocate_in_page(mem_page, sizeof(usb_configuration_descriptor), ALIGN_64B, true, true); + if (!request_sized_descriptor(address, 0, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, 8, config)){ + kprintf("[USB error] could not get config descriptor header"); + return false; + } + + if (!request_sized_descriptor(address, 0, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->header.bLength, config)){ + kprintf("[USB error] could not get full config descriptor"); + return false; + } + + if (!request_sized_descriptor(address, 0, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->wTotalLength, config)){ + kprintf("[USB error] could not get full config descriptor"); + return false; + } + + uint16_t total_length = config->wTotalLength - config->header.bLength; + + kprintf("[USB] Config length %i (%i - %i)",total_length,config->wTotalLength,config->header.bLength); + + uint16_t interface_index = 0; + + bool need_new_endpoint = true; + + uint8_t* report_descriptor; + uint16_t report_length; + + for (uint16_t i = 0; i < total_length;){ + usb_descriptor_header* header = (usb_descriptor_header*)&config->data[i]; + if (header->bLength == 0){ + kprintf("[USB] Failed to get descriptor. Header size 0"); + return false; + } + if (need_new_endpoint){ + need_new_endpoint = false; + // device_endpoint = (xhci_usb_device_endpoint*)allocate_in_page(xhci_mem_page, sizeof(xhci_usb_device_endpoint), ALIGN_64B, true, true); + } + switch (header->bDescriptorType) + { + case 0x4: { //Interface + usb_interface_descriptor *interface = (usb_interface_descriptor *)&config->data[i]; + if (interface->bInterfaceClass == 0x9){ + kprintf("[USB] Hub detected %i", interface->bNumEndpoints); + hub_enumerate(address); + return true; + } else if (interface->bInterfaceClass != 0x3){ + kprintf("[USB implementation error] non-hid devices not supported yet %x",interface->bInterfaceClass); + return false; + } + kprintf("[USB] interface protocol %x",interface->bInterfaceProtocol); + switch (interface->bInterfaceProtocol) + { + case 0x1: + // device_endpoint->type = KEYBOARD; + break; + + default: + break; + } + interface_index++; + } + break; + case 0x21: { //HID + usb_hid_descriptor *hid = (usb_hid_descriptor *)&config->data[i]; + for (uint8_t j = 0; j < hid->bNumDescriptors; j++){ + if (hid->descriptors[j].bDescriptorType == 0x22){//REPORT HID + report_length = hid->descriptors[j].wDescriptorLength; + report_descriptor = (uint8_t*)allocate_in_page(mem_page, report_length, ALIGN_64B, true, true); + request_descriptor(address, 0, 0x81, 6, 0x22, 0, interface_index-1, report_descriptor); + kprintf("[USB] retrieved report descriptor of length %i at %x", report_length, (uintptr_t)report_descriptor); + } + } + } + break; + case 0x5: {//Endpoint + usb_endpoint_descriptor *endpoint = (usb_endpoint_descriptor*)&config->data[i]; + + if (!configure_endpoint(address, endpoint, config->bConfigurationValue)) return false; + + need_new_endpoint = true; + } + break; + default: { kprintf("[USB error] Unknown type %x", header->bDescriptorType); return false; } + } + i += header->bLength; + } + + return true; + +} + +bool USBDriver::request_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor){ + if (!request_sized_descriptor(address, endpoint, rType, request, type, index, wIndex, sizeof(usb_descriptor_header), out_descriptor)){ + kprintf_raw("[USB error] Failed to get descriptor header. Size %i", sizeof(usb_descriptor_header)); + return false; + } + usb_descriptor_header* descriptor = (usb_descriptor_header*)out_descriptor; + if (descriptor->bLength == 0){ + kprintf_raw("[USB error] wrong descriptor size %i",descriptor->bLength); + return false; + } + return request_sized_descriptor(address, endpoint, rType, request, type, index, wIndex, descriptor->bLength, out_descriptor); +} + +void USBDriver::hub_enumerate(uint8_t address){ + //TODO: actually support multiple devices + uint8_t port = 1; + uint32_t port_status; + request_sized_descriptor(address, 0, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); + if (port_status & 1){ + kprintf("Port %i status %b",port, port_status); + request_sized_descriptor(address, 0, 0x23, 3, 0, 4, port, 0, 0);//Port Reset + delay(50); + request_sized_descriptor(address, 0, 0x23, 1, 0, 4, port, 0, 0);//Port Reset Clear + delay(10); + request_sized_descriptor(address, 0, 0xA3, 0, 0, 0, port, sizeof(uint32_t), (void*)&port_status); + if (!(port_status & 0b11)){ + kprintf("Port not enabled or device not connected"); + return; + } + handle_hub_routing(address,port); + setup_device(); + } +} \ No newline at end of file diff --git a/kernel/input/usb.hpp b/kernel/input/usb.hpp new file mode 100644 index 00000000..d333451c --- /dev/null +++ b/kernel/input/usb.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "types.h" +#include "keypress.h" +#include "xhci_types.h" + +class USBDriver { +public: + USBDriver() = default; + virtual bool init() = 0; + bool request_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor); + virtual bool request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor) = 0; + uint16_t packet_size(uint16_t speed); + bool get_configuration(uint8_t address); + void hub_enumerate(uint8_t address); + bool port_reset(uint32_t *port); + bool setup_device(); + virtual uint8_t address_device() = 0; + bool poll_interrupt_in(); + virtual bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value) = 0; + virtual void handle_hub_routing(uint8_t hub, uint8_t port) = 0; + ~USBDriver() = default; +protected: + void *mem_page; +}; \ No newline at end of file From 409299d626679068f680cd9fbae15df0fbb62e65 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 1 Jul 2025 00:00:00 +0000 Subject: [PATCH 44/79] Renamed the XHCI device classes to USB --- .../input/{xHCIDevice.cpp => USBDevice.cpp} | 18 ++++++------ .../input/{xHCIDevice.hpp => USBDevice.hpp} | 10 +++---- .../{xHCIKeyboard.cpp => USBKeyboard.cpp} | 9 ++++-- .../{xHCIKeyboard.hpp => USBKeyboard.hpp} | 6 ++-- kernel/input/USBManager.cpp | 29 +++++++++++++++++++ .../input/{xHCIManager.hpp => USBManager.hpp} | 10 +++---- kernel/input/xHCIManager.cpp | 29 ------------------- kernel/input/xhci_bridge.cpp | 8 ++--- 8 files changed, 61 insertions(+), 58 deletions(-) rename kernel/input/{xHCIDevice.cpp => USBDevice.cpp} (54%) rename kernel/input/{xHCIDevice.hpp => USBDevice.hpp} (66%) rename kernel/input/{xHCIKeyboard.cpp => USBKeyboard.cpp} (92%) rename kernel/input/{xHCIKeyboard.hpp => USBKeyboard.hpp} (59%) create mode 100644 kernel/input/USBManager.cpp rename kernel/input/{xHCIManager.hpp => USBManager.hpp} (70%) delete mode 100644 kernel/input/xHCIManager.cpp diff --git a/kernel/input/xHCIDevice.cpp b/kernel/input/USBDevice.cpp similarity index 54% rename from kernel/input/xHCIDevice.cpp rename to kernel/input/USBDevice.cpp index 05c6c981..02262028 100644 --- a/kernel/input/xHCIDevice.cpp +++ b/kernel/input/USBDevice.cpp @@ -1,26 +1,26 @@ -#include "xHCIDevice.hpp" -#include "xHCIKeyboard.hpp" +#include "USBDevice.hpp" +#include "USBKeyboard.hpp" -xHCIDevice::xHCIDevice(uint32_t capacity, xhci_usb_device *dev) : device(dev) { - endpoints = IndexMap(capacity); +USBDevice::USBDevice(uint32_t capacity, xhci_usb_device *dev) : device(dev) { + endpoints = IndexMap(capacity); }; -void xHCIDevice::request_data(uint8_t endpoint_id){ +void USBDevice::request_data(uint8_t endpoint_id){ if (endpoint_id >= endpoints.max_size()) return;//TODO: check if it exists endpoints[endpoint_id]->request_data(); } -void xHCIDevice::process_data(uint8_t endpoint_id){ +void USBDevice::process_data(uint8_t endpoint_id){ if (endpoint_id >= endpoints.max_size()) return;//TODO: check if it exists endpoints[endpoint_id]->process_data(); } -void xHCIDevice::register_endpoint(xhci_usb_device_endpoint *endpoint){ +void USBDevice::register_endpoint(xhci_usb_device_endpoint *endpoint){ if (endpoint->poll_endpoint >= endpoints.max_size()) return; - xHCIEndpoint *newendpoint; + USBEndpoint *newendpoint; switch (endpoint->type){ case KEYBOARD: - newendpoint = new xHCIKeyboard(device->slot_id, endpoint); + newendpoint = new USBKeyboard(device->slot_id, endpoint); break; default: return; } diff --git a/kernel/input/xHCIDevice.hpp b/kernel/input/USBDevice.hpp similarity index 66% rename from kernel/input/xHCIDevice.hpp rename to kernel/input/USBDevice.hpp index 4415e120..3255740e 100644 --- a/kernel/input/xHCIDevice.hpp +++ b/kernel/input/USBDevice.hpp @@ -3,9 +3,9 @@ #include "xhci_types.h" #include "std/std.hpp" -class xHCIEndpoint { +class USBEndpoint { public: - xHCIEndpoint(xhci_usb_device_endpoint *ep): endpoint(ep) {} + USBEndpoint(xhci_usb_device_endpoint *ep): endpoint(ep) {} virtual void request_data() {}; virtual void process_data() {}; @@ -13,15 +13,15 @@ class xHCIEndpoint { xhci_usb_device_endpoint *endpoint; }; -class xHCIDevice { +class USBDevice { public: - xHCIDevice(uint32_t capacity, xhci_usb_device *dev); + USBDevice(uint32_t capacity, xhci_usb_device *dev); void request_data(uint8_t endpoint_id); void process_data(uint8_t endpoint_id); void register_endpoint(xhci_usb_device_endpoint *endpoint); - IndexMap endpoints; + IndexMap endpoints; xhci_usb_device *device; }; \ No newline at end of file diff --git a/kernel/input/xHCIKeyboard.cpp b/kernel/input/USBKeyboard.cpp similarity index 92% rename from kernel/input/xHCIKeyboard.cpp rename to kernel/input/USBKeyboard.cpp index f79e79b9..dff2934b 100644 --- a/kernel/input/xHCIKeyboard.cpp +++ b/kernel/input/USBKeyboard.cpp @@ -1,10 +1,13 @@ -#include "xHCIKeyboard.hpp" +#include "USBKeyboard.hpp" #include "xhci.h" #include "input_dispatch.h" #include "console/kio.h" #include "memory/page_allocator.h" -void xHCIKeyboard::request_data(){ +//Input buffer +//Packet size +//Endpoint identifier +void USBKeyboard::request_data(){ requesting = true; latest_ring = &endpoint->endpoint_transfer_ring[endpoint->endpoint_transfer_index++]; @@ -26,7 +29,7 @@ void xHCIKeyboard::request_data(){ ring_doorbell(slot_id, endpoint->poll_endpoint); } -void xHCIKeyboard::process_data(){ +void USBKeyboard::process_data(){ if (!requesting){ return; } diff --git a/kernel/input/xHCIKeyboard.hpp b/kernel/input/USBKeyboard.hpp similarity index 59% rename from kernel/input/xHCIKeyboard.hpp rename to kernel/input/USBKeyboard.hpp index d4cf9083..dda8d3e8 100644 --- a/kernel/input/xHCIKeyboard.hpp +++ b/kernel/input/USBKeyboard.hpp @@ -1,12 +1,12 @@ #pragma once #include "types.h" -#include "xHCIDevice.hpp" +#include "USBDevice.hpp" #include "keypress.h" -class xHCIKeyboard: public xHCIEndpoint { +class USBKeyboard: public USBEndpoint { public: - xHCIKeyboard(uint8_t new_slot_id, xhci_usb_device_endpoint *endpoint) : xHCIEndpoint(endpoint), slot_id(new_slot_id) {} + USBKeyboard(uint8_t new_slot_id, xhci_usb_device_endpoint *endpoint) : USBEndpoint(endpoint), slot_id(new_slot_id) {} void request_data() override; void process_data() override; private: diff --git a/kernel/input/USBManager.cpp b/kernel/input/USBManager.cpp new file mode 100644 index 00000000..0dacd5e9 --- /dev/null +++ b/kernel/input/USBManager.cpp @@ -0,0 +1,29 @@ +#include "USBManager.hpp" +#include "USBKeyboard.hpp" +#include "console/kio.h" + +USBManager::USBManager(uint32_t capacity){ + devices = IndexMap(capacity); +}; + +void USBManager::register_device(uint8_t slot_id, xhci_usb_device *device){ + if (slot_id >= devices.max_size()) return; + USBDevice *newdevice = new USBDevice(8,device); + if (!newdevice) return; + devices.add(slot_id,newdevice); +} + +void USBManager::register_endpoint(uint8_t slot_id, xhci_usb_device_endpoint *endpoint){ + if (slot_id >= devices.max_size()) return; + devices[slot_id]->register_endpoint(endpoint); +} + +void USBManager::request_data(uint8_t slot_id, uint8_t endpoint_id){ + if (slot_id >= devices.max_size()) return;//TODO: check if it exists + devices[slot_id]->request_data(endpoint_id); +} + +void USBManager::process_data(uint8_t slot_id, uint8_t endpoint_id){ + if (slot_id >= devices.max_size()) return;//TODO: check if it exists + devices[slot_id]->process_data(endpoint_id); +} diff --git a/kernel/input/xHCIManager.hpp b/kernel/input/USBManager.hpp similarity index 70% rename from kernel/input/xHCIManager.hpp rename to kernel/input/USBManager.hpp index 6f600282..8732e8c8 100644 --- a/kernel/input/xHCIManager.hpp +++ b/kernel/input/USBManager.hpp @@ -2,13 +2,13 @@ #include "types.h" #include "xhci_types.h" #include "std/std.hpp" -#include "xHCIDevice.hpp" +#include "USBDevice.hpp" -class xHCIManager { +class USBManager { public: - xHCIManager(uint32_t capacity); - IndexMap devices; - xHCIDevice *default_device; + USBManager(uint32_t capacity); + IndexMap devices; + USBDevice *default_device; void register_device(uint8_t slot_id, xhci_usb_device *device); void register_endpoint(uint8_t slot_id, xhci_usb_device_endpoint *endpoint); diff --git a/kernel/input/xHCIManager.cpp b/kernel/input/xHCIManager.cpp deleted file mode 100644 index 6c7b3e69..00000000 --- a/kernel/input/xHCIManager.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "xHCIManager.hpp" -#include "xHCIKeyboard.hpp" -#include "console/kio.h" - -xHCIManager::xHCIManager(uint32_t capacity){ - devices = IndexMap(capacity); -}; - -void xHCIManager::register_device(uint8_t slot_id, xhci_usb_device *device){ - if (slot_id >= devices.max_size()) return; - xHCIDevice *newdevice = new xHCIDevice(8,device); - if (!newdevice) return; - devices.add(slot_id,newdevice); -} - -void xHCIManager::register_endpoint(uint8_t slot_id, xhci_usb_device_endpoint *endpoint){ - if (slot_id >= devices.max_size()) return; - devices[slot_id]->register_endpoint(endpoint); -} - -void xHCIManager::request_data(uint8_t slot_id, uint8_t endpoint_id){ - if (slot_id >= devices.max_size()) return;//TODO: check if it exists - devices[slot_id]->request_data(endpoint_id); -} - -void xHCIManager::process_data(uint8_t slot_id, uint8_t endpoint_id){ - if (slot_id >= devices.max_size()) return;//TODO: check if it exists - devices[slot_id]->process_data(endpoint_id); -} diff --git a/kernel/input/xhci_bridge.cpp b/kernel/input/xhci_bridge.cpp index 4d192d84..4129d54e 100644 --- a/kernel/input/xhci_bridge.cpp +++ b/kernel/input/xhci_bridge.cpp @@ -2,10 +2,10 @@ #include "memory/kalloc.h" #include "input_dispatch.h" #include "memory/page_allocator.h" -#include "xHCIManager.hpp" -#include "xHCIKeyboard.hpp" +#include "USBManager.hpp" +#include "USBKeyboard.hpp" -xHCIManager *xhci_manager; +USBManager *xhci_manager; void xhci_bridge_request_data(uint8_t slot_id, uint8_t endpoint_id) { xhci_manager->request_data(slot_id,endpoint_id); @@ -16,7 +16,7 @@ void xhci_process_input(uint8_t slot_id, uint8_t endpoint_id){ } void xhci_initialize_manager(uint32_t capacity){ - xhci_manager = new xHCIManager(capacity); + xhci_manager = new USBManager(capacity); } void xhci_configure_device(uint8_t slot_id, xhci_usb_device *device){ From 2c0ca7183ebc6aa92dd62630a40a809e084ef338 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 1 Jul 2025 00:00:00 +0000 Subject: [PATCH 45/79] Made network optional --- kernel/kernel.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kernel/kernel.c b/kernel/kernel.c index c7f7d056..b5cc82ec 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -63,8 +63,7 @@ void kernel_main() { if (!input_init()) panic("Input initialization error"); - if (!network_init()) - panic("Network initialization failure"); + bool network_available = network_init(); mmu_init(); kprintf("MMU Mapped"); @@ -76,7 +75,7 @@ void kernel_main() { kprintf("Starting processes"); - launch_net_process(); + if (network_available) launch_net_process(); init_bootprocess(); From 4fa9286a28652b003299b3f3902f517c6ff36145 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 1 Jul 2025 00:00:00 +0000 Subject: [PATCH 46/79] DWC full integration with USBDevices. XHCI is beyond broken --- kernel/input/USBDevice.cpp | 35 +++++++++++++++++-------- kernel/input/USBDevice.hpp | 25 +++++++++++------- kernel/input/USBKeyboard.cpp | 46 ++++++++++++++------------------- kernel/input/USBKeyboard.hpp | 10 ++++--- kernel/input/USBManager.cpp | 36 +++++++++++++++++++------- kernel/input/USBManager.hpp | 12 +++++---- kernel/input/dwc2.cpp | 37 ++++++++++---------------- kernel/input/dwc2.hpp | 17 +++++------- kernel/input/input_dispatch.cpp | 3 +-- kernel/input/usb.cpp | 14 +++++++--- kernel/input/usb.hpp | 8 ++++-- kernel/input/xhci.c | 37 +++++++++++++------------- kernel/input/xhci_bridge.cpp | 15 ++++++----- kernel/input/xhci_bridge.h | 4 +-- 14 files changed, 165 insertions(+), 134 deletions(-) diff --git a/kernel/input/USBDevice.cpp b/kernel/input/USBDevice.cpp index 02262028..0a65e9ca 100644 --- a/kernel/input/USBDevice.cpp +++ b/kernel/input/USBDevice.cpp @@ -1,30 +1,43 @@ #include "USBDevice.hpp" #include "USBKeyboard.hpp" +#include "xhci_types.h" +#include "console/kio.h" -USBDevice::USBDevice(uint32_t capacity, xhci_usb_device *dev) : device(dev) { +USBDevice::USBDevice(uint32_t capacity, uint8_t address) : address(address) { endpoints = IndexMap(capacity); }; -void USBDevice::request_data(uint8_t endpoint_id){ +void USBDevice::request_data(uint8_t endpoint_id, USBDriver *driver){ if (endpoint_id >= endpoints.max_size()) return;//TODO: check if it exists - endpoints[endpoint_id]->request_data(); + USBEndpoint *ep = endpoints[endpoint_id]; + if (ep) + ep->request_data(driver); } -void USBDevice::process_data(uint8_t endpoint_id){ +void USBDevice::process_data(uint8_t endpoint_id, USBDriver *driver){ if (endpoint_id >= endpoints.max_size()) return;//TODO: check if it exists - endpoints[endpoint_id]->process_data(); + USBEndpoint *ep = endpoints[endpoint_id]; + if (ep) + ep->process_data(driver); } -void USBDevice::register_endpoint(xhci_usb_device_endpoint *endpoint){ - if (endpoint->poll_endpoint >= endpoints.max_size()) return; +void USBDevice::register_endpoint(uint8_t endpoint, xhci_device_types type, uint16_t packet_size){ + if (endpoint >= endpoints.max_size()) return; USBEndpoint *newendpoint; - switch (endpoint->type){ + switch (type){ case KEYBOARD: - newendpoint = new USBKeyboard(device->slot_id, endpoint); + newendpoint = new USBKeyboard(address, endpoint, packet_size); break; default: return; } if (!newendpoint) return; - endpoints.add(endpoint->poll_endpoint,newendpoint); - request_data(endpoint->poll_endpoint); + endpoints.add(endpoint,newendpoint); +} + +void USBDevice::poll_inputs(USBDriver *driver){ + for (uint8_t i = 0; i < endpoints.max_size(); i++){ + USBEndpoint *ep = endpoints[i]; + if (ep && ep->type == KEYBOARD) + ep->request_data(driver); + } } \ No newline at end of file diff --git a/kernel/input/USBDevice.hpp b/kernel/input/USBDevice.hpp index 3255740e..a3e4a4e2 100644 --- a/kernel/input/USBDevice.hpp +++ b/kernel/input/USBDevice.hpp @@ -2,26 +2,33 @@ #include "types.h" #include "xhci_types.h" #include "std/std.hpp" +#include "console/kio.h" + +class USBDriver; class USBEndpoint { public: - USBEndpoint(xhci_usb_device_endpoint *ep): endpoint(ep) {} - virtual void request_data() {}; + USBEndpoint(uint8_t endpoint, xhci_device_types type, uint16_t packet_size): endpoint(endpoint), type(type), packet_size(packet_size) { } + virtual void request_data(USBDriver *driver) = 0; - virtual void process_data() {}; + virtual void process_data(USBDriver *driver) = 0; - xhci_usb_device_endpoint *endpoint; + uint8_t endpoint; + xhci_device_types type; + uint16_t packet_size; }; class USBDevice { public: - USBDevice(uint32_t capacity, xhci_usb_device *dev); - void request_data(uint8_t endpoint_id); + USBDevice(uint32_t capacity, uint8_t address); + void request_data(uint8_t endpoint_id, USBDriver *driver); + + void process_data(uint8_t endpoint_id, USBDriver *driver); - void process_data(uint8_t endpoint_id); + void register_endpoint(uint8_t endpoint, xhci_device_types type, uint16_t packet_size); - void register_endpoint(xhci_usb_device_endpoint *endpoint); + void poll_inputs(USBDriver *driver); IndexMap endpoints; - xhci_usb_device *device; + uint8_t address; }; \ No newline at end of file diff --git a/kernel/input/USBKeyboard.cpp b/kernel/input/USBKeyboard.cpp index dff2934b..a5b95e4e 100644 --- a/kernel/input/USBKeyboard.cpp +++ b/kernel/input/USBKeyboard.cpp @@ -3,42 +3,37 @@ #include "input_dispatch.h" #include "console/kio.h" #include "memory/page_allocator.h" +#include "usb.hpp" -//Input buffer -//Packet size -//Endpoint identifier -void USBKeyboard::request_data(){ +void USBKeyboard::request_data(USBDriver *driver){ requesting = true; - latest_ring = &endpoint->endpoint_transfer_ring[endpoint->endpoint_transfer_index++]; - - if (endpoint->input_buffer == 0x0){ - uint64_t buffer_addr = (uint64_t)alloc_page(endpoint->poll_packetSize, true, true, true); - endpoint->input_buffer = (uint8_t*)buffer_addr; + + if (buffer == 0){ + buffer = alloc_page(packet_size, true, true, true); } - latest_ring->parameter = (uintptr_t)endpoint->input_buffer; - latest_ring->status = endpoint->poll_packetSize; - latest_ring->control = (TRB_TYPE_NORMAL << 10) | (1 << 5) | endpoint->endpoint_transfer_cycle_bit; - - if (endpoint->endpoint_transfer_index == MAX_TRB_AMOUNT - 1){ - make_ring_link_control(endpoint->endpoint_transfer_ring, endpoint->endpoint_transfer_cycle_bit); - endpoint->endpoint_transfer_cycle_bit = !endpoint->endpoint_transfer_cycle_bit; - endpoint->endpoint_transfer_index = 0; + if (driver->poll(slot_id, endpoint, buffer, packet_size) && !driver->use_interrupts){ + process_keypress((keypress*)buffer); } - - ring_doorbell(slot_id, endpoint->poll_endpoint); } -void USBKeyboard::process_data(){ +void USBKeyboard::process_data(USBDriver *driver){ if (!requesting){ return; } - keypress kp; - if (!xhci_await_response((uintptr_t)latest_ring,TRB_TYPE_TRANSFER)) - xhci_sync_events();//TODO: we're just consuming the event without even looking to see if it's the right one, this is wrong, seriously, IRQ await would fix this + // if (!xhci_await_response((uintptr_t)latest_ring,TRB_TYPE_TRANSFER)) + // xhci_sync_events();//TODO: we're just consuming the event without even looking to see if it's the right one, this is wrong, seriously, IRQ await would fix this + + // keypress *rkp = (keypress*)endpoint->input_buffer; + // process_keypress(rkp); + + // request_data(); - keypress *rkp = (keypress*)endpoint->input_buffer; +} + +void USBKeyboard::process_keypress(keypress *rkp){ + keypress kp; if (is_new_keypress(rkp, &last_keypress) || repeated_keypresses > 3){ if (is_new_keypress(rkp, &last_keypress)) repeated_keypresses = 0; @@ -52,7 +47,4 @@ void USBKeyboard::process_data(){ register_keypress(kp); } else repeated_keypresses++; - - request_data(); - } \ No newline at end of file diff --git a/kernel/input/USBKeyboard.hpp b/kernel/input/USBKeyboard.hpp index dda8d3e8..1d0b7883 100644 --- a/kernel/input/USBKeyboard.hpp +++ b/kernel/input/USBKeyboard.hpp @@ -3,13 +3,15 @@ #include "types.h" #include "USBDevice.hpp" #include "keypress.h" +#include "xhci_types.h" class USBKeyboard: public USBEndpoint { public: - USBKeyboard(uint8_t new_slot_id, xhci_usb_device_endpoint *endpoint) : USBEndpoint(endpoint), slot_id(new_slot_id) {} - void request_data() override; - void process_data() override; + USBKeyboard(uint8_t new_slot_id, uint8_t endpoint, uint16_t packet_size) : USBEndpoint(endpoint, KEYBOARD, packet_size), slot_id(new_slot_id) {} + void request_data(USBDriver *driver) override; + void process_data(USBDriver *driver) override; private: + void process_keypress(keypress *rkp); trb* latest_ring; bool requesting = false; uint8_t slot_id; @@ -17,4 +19,6 @@ class USBKeyboard: public USBEndpoint { keypress last_keypress; int repeated_keypresses = 0; + + void* buffer; }; \ No newline at end of file diff --git a/kernel/input/USBManager.cpp b/kernel/input/USBManager.cpp index 0dacd5e9..3efd8f75 100644 --- a/kernel/input/USBManager.cpp +++ b/kernel/input/USBManager.cpp @@ -1,4 +1,5 @@ #include "USBManager.hpp" +#include "USBDevice.hpp" #include "USBKeyboard.hpp" #include "console/kio.h" @@ -6,24 +7,39 @@ USBManager::USBManager(uint32_t capacity){ devices = IndexMap(capacity); }; -void USBManager::register_device(uint8_t slot_id, xhci_usb_device *device){ - if (slot_id >= devices.max_size()) return; - USBDevice *newdevice = new USBDevice(8,device); +void USBManager::register_device(uint8_t address){ + if (address >= devices.max_size()) return; + USBDevice *newdevice = new USBDevice(8,address); if (!newdevice) return; - devices.add(slot_id,newdevice); + devices.add(address,newdevice); } -void USBManager::register_endpoint(uint8_t slot_id, xhci_usb_device_endpoint *endpoint){ +void USBManager::register_endpoint(uint8_t slot_id, uint8_t endpoint, xhci_device_types type, uint16_t packet_size){ if (slot_id >= devices.max_size()) return; - devices[slot_id]->register_endpoint(endpoint); + USBDevice *dev = devices[slot_id]; + if (dev) + dev->register_endpoint(endpoint, type, packet_size); } -void USBManager::request_data(uint8_t slot_id, uint8_t endpoint_id){ +void USBManager::request_data(uint8_t slot_id, uint8_t endpoint_id, USBDriver *driver){ if (slot_id >= devices.max_size()) return;//TODO: check if it exists - devices[slot_id]->request_data(endpoint_id); + USBDevice *dev = devices[slot_id]; + if (dev) + dev->request_data(endpoint_id, driver); } -void USBManager::process_data(uint8_t slot_id, uint8_t endpoint_id){ +void USBManager::process_data(uint8_t slot_id, uint8_t endpoint_id, USBDriver *driver){ if (slot_id >= devices.max_size()) return;//TODO: check if it exists - devices[slot_id]->process_data(endpoint_id); + USBDevice *dev = devices[slot_id]; + if (dev) + dev->process_data(endpoint_id, driver); } + +void USBManager::poll_inputs(USBDriver *driver){ + for (uint8_t i = 0; i < devices.max_size(); i++){ + USBDevice *device = devices[i]; + if (device){ + device->poll_inputs(driver); + } + } +} \ No newline at end of file diff --git a/kernel/input/USBManager.hpp b/kernel/input/USBManager.hpp index 8732e8c8..efcb9830 100644 --- a/kernel/input/USBManager.hpp +++ b/kernel/input/USBManager.hpp @@ -4,14 +4,16 @@ #include "std/std.hpp" #include "USBDevice.hpp" +class USBDriver; + class USBManager { public: USBManager(uint32_t capacity); IndexMap devices; - USBDevice *default_device; - void register_device(uint8_t slot_id, xhci_usb_device *device); - void register_endpoint(uint8_t slot_id, xhci_usb_device_endpoint *endpoint); - void request_data(uint8_t slot_id, uint8_t endpoint_id); - void process_data(uint8_t slot_id, uint8_t endpoint_id); + void register_device(uint8_t address); + void register_endpoint(uint8_t slot_id, uint8_t endpoint, xhci_device_types type, uint16_t packet_size); + void request_data(uint8_t slot_id, uint8_t endpoint_id, USBDriver *driver); + void process_data(uint8_t slot_id, uint8_t endpoint_id, USBDriver *driver); + void poll_inputs(USBDriver *driver); }; \ No newline at end of file diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index 12b76496..e1a67f5d 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -4,7 +4,6 @@ #include "memory/page_allocator.h" #include "std/string.h" #include "memory/mmu.h" -#include "input_dispatch.h" #define DWC2_BASE 0xFE980000 @@ -22,6 +21,8 @@ uint8_t DWC2Driver::assign_channel(uint8_t device, uint8_t endpoint, uint8_t ep_ bool DWC2Driver::init() { + use_interrupts = false; + dwc2 = (dwc2_regs*)DWC2_BASE; host = (dwc2_host*)(DWC2_BASE + 0x400); @@ -54,7 +55,8 @@ bool DWC2Driver::init() { return false; } - channel_map = IndexMap(UINT16_MAX); + channel_map = IndexMap(127); + usb_manager = new USBManager(127); kprintf("Port reset %x",host->port); @@ -140,7 +142,7 @@ bool DWC2Driver::request_sized_descriptor(uint8_t address, uint8_t endpoint, uin return true; } -bool DWC2Driver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value){ +bool DWC2Driver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value, xhci_device_types type){ uint8_t ep_address = endpoint->bEndpointAddress; uint8_t ep_num = ep_address & 0x0F; @@ -178,18 +180,21 @@ bool DWC2Driver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *en endpoint_channel->cchar &= ~(0b11 << 20); endpoint_channel->cchar |= (mc << 20); - TEMP_input_buffer = allocate_in_page(mem_page, 8, ALIGN_64B, true, true); + usb_manager->register_endpoint(address, ep_num, type, endpoint->wMaxPacketSize); return true; } -bool DWC2Driver::poll_interrupt_in(){ +bool DWC2Driver::poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t size){ + dwc2_host_channel *endpoint_channel = get_channel(channel_map[(address << 8) | endpoint]); if (endpoint_channel->cchar & 1) return false; - endpoint_channel->dma = (uintptr_t)TEMP_input_buffer; + endpoint_channel->dma = (uintptr_t)out_buf; - endpoint_channel->xfer_size = (1 << 19) | (0x3 << 29) | 8; + uint16_t max_size = endpoint_channel->cchar & 0x7FF; + uint32_t pkt_count = (size + max_size - 1)/max_size; + endpoint_channel->xfer_size = (pkt_count << 19) | (0x3 << 29) | size; endpoint_channel->intmask = 0xFFFFFFFF; @@ -207,23 +212,7 @@ bool DWC2Driver::poll_interrupt_in(){ endpoint_channel->interrupt = 0xFFFFFFFF; endpoint_channel->cchar &= ~(1 << 31); - keypress kp; - - keypress *rkp = (keypress*)TEMP_input_buffer; - if (is_new_keypress(rkp, &last_keypress) || repeated_keypresses > 3){ - if (is_new_keypress(rkp, &last_keypress)) - repeated_keypresses = 0; - kp.modifier = rkp->modifier; - for (int i = 0; i < 6; i++){ - kp.keys[i] = rkp->keys[i]; - } - last_keypress = kp; - register_keypress(kp); - return true; - } else - repeated_keypresses++; - - return false; + return true; } void DWC2Driver::handle_hub_routing(uint8_t hub, uint8_t port){ diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index 5a1d6661..69d65922 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -2,6 +2,7 @@ #include "usb.hpp" #include "std/indexmap.hpp" +#include "xhci_types.h" typedef struct { uint32_t gotgctl; @@ -45,26 +46,22 @@ typedef struct { class DWC2Driver: public USBDriver { public: DWC2Driver() = default; - bool init(); - bool request_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor); - bool request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor); - uint8_t address_device(); - bool poll_interrupt_in(); - bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value); - void handle_hub_routing(uint8_t hub, uint8_t port); + bool init() override; + bool request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor) override; + uint8_t address_device() override; + bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value, xhci_device_types type) override; + void handle_hub_routing(uint8_t hub, uint8_t port) override; + bool poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t size) override; ~DWC2Driver() = default; private: dwc2_host_channel* get_channel(uint16_t channel); uint8_t assign_channel(uint8_t device, uint8_t endpoint, uint8_t ep_type); bool make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, sizedptr data); uint16_t port_speed; - void *TEMP_input_buffer; dwc2_regs *dwc2; dwc2_host *host; uint8_t next_channel; uint8_t next_address; dwc2_host_channel *endpoint_channel; - keypress last_keypress; - int repeated_keypresses = 0; IndexMap channel_map; }; \ No newline at end of file diff --git a/kernel/input/input_dispatch.cpp b/kernel/input/input_dispatch.cpp index ed6e786a..d5dbe4d8 100644 --- a/kernel/input/input_dispatch.cpp +++ b/kernel/input/input_dispatch.cpp @@ -22,7 +22,6 @@ bool secure_mode = false; DWC2Driver *dwc_driver; void register_keypress(keypress kp) { - if (!secure_mode){ for (int i = 0; i < shortcut_count; i++){ if (shortcuts[i].pid != -1 && !is_new_keypress(&shortcuts[i].kp, &kp)){ @@ -89,7 +88,7 @@ bool is_new_keypress(keypress* current, keypress* previous) { bool sys_read_input(int pid, keypress *out){ if (BOARD_TYPE == 2) - dwc_driver->poll_interrupt_in(); + dwc_driver->poll_inputs(); process_t *process = get_proc_by_pid(pid); if (process->input_buffer.read_index == process->input_buffer.write_index) return false; diff --git a/kernel/input/usb.cpp b/kernel/input/usb.cpp index 5d4033ba..e8d9e206 100644 --- a/kernel/input/usb.cpp +++ b/kernel/input/usb.cpp @@ -3,6 +3,7 @@ #include "async.h" #include "std/string.h" #include "memory/page_allocator.h" +#include "xhci_types.h" uint16_t USBDriver::packet_size(uint16_t speed){ switch (speed) { @@ -87,6 +88,8 @@ bool USBDriver::get_configuration(uint8_t address){ uint16_t ep_num = 0; + usb_manager->register_device(address); + usb_configuration_descriptor* config = (usb_configuration_descriptor*)allocate_in_page(mem_page, sizeof(usb_configuration_descriptor), ALIGN_64B, true, true); if (!request_sized_descriptor(address, 0, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, 8, config)){ kprintf("[USB error] could not get config descriptor header"); @@ -114,6 +117,8 @@ bool USBDriver::get_configuration(uint8_t address){ uint8_t* report_descriptor; uint16_t report_length; + xhci_device_types dev_type; + for (uint16_t i = 0; i < total_length;){ usb_descriptor_header* header = (usb_descriptor_header*)&config->data[i]; if (header->bLength == 0){ @@ -122,7 +127,6 @@ bool USBDriver::get_configuration(uint8_t address){ } if (need_new_endpoint){ need_new_endpoint = false; - // device_endpoint = (xhci_usb_device_endpoint*)allocate_in_page(xhci_mem_page, sizeof(xhci_usb_device_endpoint), ALIGN_64B, true, true); } switch (header->bDescriptorType) { @@ -140,7 +144,7 @@ bool USBDriver::get_configuration(uint8_t address){ switch (interface->bInterfaceProtocol) { case 0x1: - // device_endpoint->type = KEYBOARD; + dev_type = KEYBOARD; break; default: @@ -164,7 +168,7 @@ bool USBDriver::get_configuration(uint8_t address){ case 0x5: {//Endpoint usb_endpoint_descriptor *endpoint = (usb_endpoint_descriptor*)&config->data[i]; - if (!configure_endpoint(address, endpoint, config->bConfigurationValue)) return false; + if (!configure_endpoint(address, endpoint, config->bConfigurationValue, dev_type)) return false; need_new_endpoint = true; } @@ -210,4 +214,8 @@ void USBDriver::hub_enumerate(uint8_t address){ handle_hub_routing(address,port); setup_device(); } +} + +void USBDriver::poll_inputs(){ + usb_manager->poll_inputs(this); } \ No newline at end of file diff --git a/kernel/input/usb.hpp b/kernel/input/usb.hpp index d333451c..fed5fd57 100644 --- a/kernel/input/usb.hpp +++ b/kernel/input/usb.hpp @@ -3,6 +3,7 @@ #include "types.h" #include "keypress.h" #include "xhci_types.h" +#include "USBManager.hpp" class USBDriver { public: @@ -16,10 +17,13 @@ class USBDriver { bool port_reset(uint32_t *port); bool setup_device(); virtual uint8_t address_device() = 0; - bool poll_interrupt_in(); - virtual bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value) = 0; + virtual bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value, xhci_device_types type) = 0; virtual void handle_hub_routing(uint8_t hub, uint8_t port) = 0; + virtual bool poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t size) = 0; ~USBDriver() = default; + void poll_inputs(); + bool use_interrupts; protected: void *mem_page; + USBManager *usb_manager; }; \ No newline at end of file diff --git a/kernel/input/xhci.c b/kernel/input/xhci.c index d2e678e0..898713ea 100644 --- a/kernel/input/xhci.c +++ b/kernel/input/xhci.c @@ -9,6 +9,7 @@ #include "std/string.h" #include "std/memfunctions.h" #include "hw/hw.h" +#include "xhci_types.h" static xhci_device global_device; @@ -446,9 +447,9 @@ bool xhci_get_configuration(usb_configuration_descriptor *config, xhci_usb_devic bool need_new_endpoint = true; - xhci_usb_device_endpoint *device_endpoint; + xhci_device_types dev_type; - xhci_configure_device(device->slot_id, device); + xhci_configure_device(device->slot_id); for (uint16_t i = 0; i < total_length;){ usb_descriptor_header* header = (usb_descriptor_header*)&config->data[i]; @@ -458,7 +459,6 @@ bool xhci_get_configuration(usb_configuration_descriptor *config, xhci_usb_devic } if (need_new_endpoint){ need_new_endpoint = false; - device_endpoint = (xhci_usb_device_endpoint*)allocate_in_page(xhci_mem_page, sizeof(xhci_usb_device_endpoint), ALIGN_64B, true, true); } switch (header->bDescriptorType) { @@ -472,7 +472,7 @@ bool xhci_get_configuration(usb_configuration_descriptor *config, xhci_usb_devic switch (interface->bInterfaceProtocol) { case 0x1: - device_endpoint->type = KEYBOARD; + dev_type = KEYBOARD; break; default: @@ -484,10 +484,10 @@ bool xhci_get_configuration(usb_configuration_descriptor *config, xhci_usb_devic usb_hid_descriptor *hid = (usb_hid_descriptor *)&config->data[i]; for (uint8_t j = 0; j < hid->bNumDescriptors; j++){ if (hid->descriptors[j].bDescriptorType == 0x22){//REPORT HID - device_endpoint->report_length = hid->descriptors[j].wDescriptorLength; - device_endpoint->report_descriptor = (uint8_t*)allocate_in_page(xhci_mem_page, device_endpoint->report_length, ALIGN_64B, true, true); - xhci_request_descriptor(device, true, 0x22, 0, interface_index-1, device_endpoint->report_descriptor); - kprintfv("[xHCI] retrieved report descriptor of length %i at %x", device_endpoint->report_length, (uintptr_t)device_endpoint->report_descriptor); + // device_endpoint->report_length = hid->descriptors[j].wDescriptorLength; + // device_endpoint->report_descriptor = (uint8_t*)allocate_in_page(xhci_mem_page, device_endpoint->report_length, ALIGN_64B, true, true); + // xhci_request_descriptor(device, true, 0x22, 0, interface_index-1, device_endpoint->report_descriptor); + // kprintfv("[xHCI] retrieved report descriptor of length %i at %x", device_endpoint->report_length, (uintptr_t)device_endpoint->report_descriptor); } } break; @@ -513,26 +513,25 @@ bool xhci_get_configuration(usb_configuration_descriptor *config, xhci_usb_devic ctx->device_context.endpoints[ep_num-1].endpoint_f4.max_esit_payload_lo = endpoint->wMaxPacketSize; ctx->device_context.endpoints[ep_num-1].endpoint_f1.error_count = 3; - device_endpoint->endpoint_transfer_ring = (trb*)allocate_in_page(xhci_mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); - device_endpoint->endpoint_transfer_cycle_bit = 1; - make_ring_link(device_endpoint->endpoint_transfer_ring, device_endpoint->endpoint_transfer_cycle_bit); - ctx->device_context.endpoints[ep_num-1].endpoint_f23.dcs = device_endpoint->endpoint_transfer_cycle_bit; - ctx->device_context.endpoints[ep_num-1].endpoint_f23.ring_ptr = ((uintptr_t)device_endpoint->endpoint_transfer_ring) >> 4; - ctx->device_context.endpoints[ep_num-1].endpoint_f4.average_trb_length = 8; + // device_endpoint->endpoint_transfer_ring = (trb*)allocate_in_page(xhci_mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); + // device_endpoint->endpoint_transfer_cycle_bit = 1; + // make_ring_link(device_endpoint->endpoint_transfer_ring, device_endpoint->endpoint_transfer_cycle_bit); + // ctx->device_context.endpoints[ep_num-1].endpoint_f23.dcs = device_endpoint->endpoint_transfer_cycle_bit; + // ctx->device_context.endpoints[ep_num-1].endpoint_f23.ring_ptr = ((uintptr_t)device_endpoint->endpoint_transfer_ring) >> 4; + // ctx->device_context.endpoints[ep_num-1].endpoint_f4.average_trb_length = endpoint->wMaxPacketSize; - device_endpoint->poll_endpoint = ep_num; - device_endpoint->poll_packetSize = endpoint->wMaxPacketSize; + // device_endpoint->poll_packetSize = endpoint->wMaxPacketSize; if (!issue_command((uintptr_t)ctx, 0, (device->slot_id << 24) | (TRB_TYPE_CONFIG_EP << 10))){ kprintf_raw("[xHCI] Failed to configure endpoint %i",ep_num); return false; } - kprintf_raw("[xHCI] Storing configuration for endpoint %i -> %i (%x)",ep_num,device_endpoint->poll_endpoint, (uintptr_t)device_endpoint); + // kprintf_raw("[xHCI] Storing configuration for endpoint %i -> %i (%x)",ep_num,device_endpoint->poll_endpoint, (uintptr_t)device_endpoint); - xhci_configure_endpoint(device->slot_id, device_endpoint); + xhci_configure_endpoint(device->slot_id, ep_num, dev_type, endpoint->wMaxPacketSize); - kprintf_raw("[xHCI] Returned from configuration for endpoint %i -> %i (%x)",ep_num,device_endpoint->poll_endpoint, (uintptr_t)device_endpoint); + // kprintf_raw("[xHCI] Returned from configuration for endpoint %i -> %i (%x)",ep_num,device_endpoint->poll_endpoint, (uintptr_t)device_endpoint); need_new_endpoint = true; diff --git a/kernel/input/xhci_bridge.cpp b/kernel/input/xhci_bridge.cpp index 4129d54e..a14a93e2 100644 --- a/kernel/input/xhci_bridge.cpp +++ b/kernel/input/xhci_bridge.cpp @@ -4,25 +4,26 @@ #include "memory/page_allocator.h" #include "USBManager.hpp" #include "USBKeyboard.hpp" +#include "xhci_types.h" USBManager *xhci_manager; void xhci_bridge_request_data(uint8_t slot_id, uint8_t endpoint_id) { - xhci_manager->request_data(slot_id,endpoint_id); + // xhci_manager->request_data(slot_id,endpoint_id); } void xhci_process_input(uint8_t slot_id, uint8_t endpoint_id){ - xhci_manager->process_data(slot_id,endpoint_id); + // xhci_manager->process_data(slot_id,endpoint_id); } void xhci_initialize_manager(uint32_t capacity){ - xhci_manager = new USBManager(capacity); + // xhci_manager = new USBManager(capacity); } -void xhci_configure_device(uint8_t slot_id, xhci_usb_device *device){ - xhci_manager->register_device(slot_id,device); +void xhci_configure_device(uint8_t slot_id){ + // xhci_manager->register_device(slot_id); } -void xhci_configure_endpoint(uint8_t slot_id, xhci_usb_device_endpoint *endpoint){ - xhci_manager->register_endpoint(slot_id,endpoint); +void xhci_configure_endpoint(uint8_t slot_id, uint8_t endpoint, xhci_device_types type, uint16_t packet_size){ + // xhci_manager->register_endpoint(slot_id, endpoint, type, packet_size); } \ No newline at end of file diff --git a/kernel/input/xhci_bridge.h b/kernel/input/xhci_bridge.h index dabb7f08..920be5f6 100644 --- a/kernel/input/xhci_bridge.h +++ b/kernel/input/xhci_bridge.h @@ -13,8 +13,8 @@ void xhci_bridge_request_data(uint8_t slot_id, uint8_t endpoint_id); void xhci_process_input(uint8_t slot_id, uint8_t endpoint_id); void xhci_initialize_manager(uint32_t capacity); -void xhci_configure_device(uint8_t slot_id, xhci_usb_device *device); -void xhci_configure_endpoint(uint8_t slot_id, xhci_usb_device_endpoint *endpoint); +void xhci_configure_device(uint8_t slot_id); +void xhci_configure_endpoint(uint8_t slot_id, uint8_t endpoint, xhci_device_types type, uint16_t packet_size); #ifdef __cplusplus } From 8076277388eee7987030787395ad6789da7bba78 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 1 Jul 2025 00:00:00 +0000 Subject: [PATCH 47/79] Port of XHCI to USB/C++ driver (configure endpoint error 19) --- kernel/exceptions/irq.c | 4 +- kernel/input/USBKeyboard.cpp | 1 - kernel/input/dwc2.cpp | 22 +- kernel/input/dwc2.hpp | 6 +- kernel/input/input_dispatch.cpp | 20 +- kernel/input/input_dispatch.h | 5 +- kernel/input/usb.cpp | 24 +- kernel/input/usb.hpp | 9 +- kernel/input/xhci.c | 732 -------------------------------- kernel/input/xhci.cpp | 511 ++++++++++++++++++++++ kernel/input/xhci.h | 21 - kernel/input/xhci.hpp | 53 +++ kernel/input/xhci_bridge.cpp | 29 -- kernel/input/xhci_bridge.h | 21 - 14 files changed, 616 insertions(+), 842 deletions(-) delete mode 100644 kernel/input/xhci.c create mode 100644 kernel/input/xhci.cpp delete mode 100644 kernel/input/xhci.h create mode 100644 kernel/input/xhci.hpp delete mode 100644 kernel/input/xhci_bridge.cpp delete mode 100644 kernel/input/xhci_bridge.h diff --git a/kernel/exceptions/irq.c b/kernel/exceptions/irq.c index 08d3d56c..a1c0ea74 100644 --- a/kernel/exceptions/irq.c +++ b/kernel/exceptions/irq.c @@ -2,9 +2,9 @@ #include "console/kio.h" #include "memory/memory_access.h" #include "process/scheduler.h" +#include "input/input_dispatch.h" #include "input/xhci_types.h" #include "pci.h" -#include "input/xhci.h" #include "console/serial/uart.h" #include "networking/network.h" @@ -71,7 +71,7 @@ void irq_el1_handler() { write32(GICC_BASE + 0x10, irq); switch_proc(INTERRUPT); } else if (irq == MSI_OFFSET + XHCI_IRQ){ - xhci_handle_interrupt(); + handle_input_interrupt(); write32(GICC_BASE + 0x10, irq); process_restore(); } else if (irq == SLEEP_TIMER){ diff --git a/kernel/input/USBKeyboard.cpp b/kernel/input/USBKeyboard.cpp index a5b95e4e..0a9d0fcc 100644 --- a/kernel/input/USBKeyboard.cpp +++ b/kernel/input/USBKeyboard.cpp @@ -1,5 +1,4 @@ #include "USBKeyboard.hpp" -#include "xhci.h" #include "input_dispatch.h" #include "console/kio.h" #include "memory/page_allocator.h" diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index e1a67f5d..5da780f6 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -19,6 +19,18 @@ uint8_t DWC2Driver::assign_channel(uint8_t device, uint8_t endpoint, uint8_t ep_ return new_chan; } +bool DWC2Driver::port_reset(uint32_t *port){ + *port &= ~0b101110; + *port |= (1 << 8); + + delay(50); + + *port &= ~0b101110; + *port &= ~(1 << 8); + + return wait(port, (1 << 8), false, 2000); +} + bool DWC2Driver::init() { use_interrupts = false; @@ -55,7 +67,7 @@ bool DWC2Driver::init() { return false; } - channel_map = IndexMap(127); + channel_map = IndexMap(127 * 5); usb_manager = new USBManager(127); kprintf("Port reset %x",host->port); @@ -65,14 +77,14 @@ bool DWC2Driver::init() { mem_page = alloc_page(0x1000, true, true, false); - setup_device(); + setup_device(0,0); register_device_memory(DWC2_BASE, DWC2_BASE); return true; } -uint8_t DWC2Driver::address_device(){ +uint8_t DWC2Driver::address_device(uint8_t address){ uint8_t new_address = ++next_address; request_sized_descriptor(0, 0, 0x0, 0x5, 0, new_address, 0, 0, 0); channel_map[new_address << 8] = assign_channel(new_address, 0, 0); @@ -218,4 +230,6 @@ bool DWC2Driver::poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t void DWC2Driver::handle_hub_routing(uint8_t hub, uint8_t port){ dwc2_host_channel *dev_channel = get_channel(0); dev_channel->splt = (1 << 31) | (1 << 16) | (hub << 7) | (port << 0); -} \ No newline at end of file +} + +void DWC2Driver::handle_interrupt(){} \ No newline at end of file diff --git a/kernel/input/dwc2.hpp b/kernel/input/dwc2.hpp index 69d65922..adabfe50 100644 --- a/kernel/input/dwc2.hpp +++ b/kernel/input/dwc2.hpp @@ -48,15 +48,17 @@ class DWC2Driver: public USBDriver { DWC2Driver() = default; bool init() override; bool request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor) override; - uint8_t address_device() override; + uint8_t address_device(uint8_t address) override; bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value, xhci_device_types type) override; void handle_hub_routing(uint8_t hub, uint8_t port) override; bool poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t size) override; + void handle_interrupt() override; ~DWC2Driver() = default; -private: + private: dwc2_host_channel* get_channel(uint16_t channel); uint8_t assign_channel(uint8_t device, uint8_t endpoint, uint8_t ep_type); bool make_transfer(dwc2_host_channel *channel, bool in, uint8_t pid, sizedptr data); + bool port_reset(uint32_t *port); uint16_t port_speed; dwc2_regs *dwc2; dwc2_host *host; diff --git a/kernel/input/input_dispatch.cpp b/kernel/input/input_dispatch.cpp index d5dbe4d8..7f3993ec 100644 --- a/kernel/input/input_dispatch.cpp +++ b/kernel/input/input_dispatch.cpp @@ -2,6 +2,7 @@ #include "process/process.h" #include "process/scheduler.h" #include "dwc2.hpp" +#include "xhci.hpp" #include "hw/hw.h" #include "std/std.hpp" @@ -19,7 +20,7 @@ uint16_t shortcut_count = 0; bool secure_mode = false; -DWC2Driver *dwc_driver; +USBDriver *input_driver; void register_keypress(keypress kp) { if (!secure_mode){ @@ -88,7 +89,7 @@ bool is_new_keypress(keypress* current, keypress* previous) { bool sys_read_input(int pid, keypress *out){ if (BOARD_TYPE == 2) - dwc_driver->poll_inputs(); + input_driver->poll_inputs(); process_t *process = get_proc_by_pid(pid); if (process->input_buffer.read_index == process->input_buffer.write_index) return false; @@ -105,13 +106,20 @@ bool sys_shortcut_triggered(uint16_t pid, uint16_t sid){ if (shortcuts[sid].pid == pid && shortcuts[sid].triggered){ shortcuts[sid].triggered = false; return true; - } + } return false; } bool input_init(){ if (BOARD_TYPE == 2){ - dwc_driver = new DWC2Driver();//TODO: QEMU Only - return dwc_driver->init(); - } else return xhci_input_init(); + input_driver = new DWC2Driver();//TODO: QEMU & 3 Only + return input_driver->init(); + } else { + input_driver = new XHCIDriver(); + return input_driver->init(); + } +} + +void handle_input_interrupt(){ + if (input_driver->use_interrupts) input_driver->handle_interrupt(); } \ No newline at end of file diff --git a/kernel/input/input_dispatch.h b/kernel/input/input_dispatch.h index fcb3c46b..9976c6ff 100644 --- a/kernel/input/input_dispatch.h +++ b/kernel/input/input_dispatch.h @@ -1,11 +1,12 @@ #pragma once -#include "xhci_bridge.h" #include "input_keycodes.h" +#include "keypress.h" #ifdef __cplusplus extern "C" { #endif + void register_keypress(keypress kp); uint16_t sys_subscribe_shortcut(uint16_t pid, keypress kp); uint16_t sys_subscribe_shortcut_current(keypress kp); @@ -26,6 +27,8 @@ bool is_new_keypress(keypress* current, keypress* previous); bool input_init(); +void handle_input_interrupt(); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/kernel/input/usb.cpp b/kernel/input/usb.cpp index e8d9e206..deb9c035 100644 --- a/kernel/input/usb.cpp +++ b/kernel/input/usb.cpp @@ -16,28 +16,16 @@ uint16_t USBDriver::packet_size(uint16_t speed){ } } -bool USBDriver::port_reset(uint32_t *port){ - *port &= ~0b101110; - *port |= (1 << 8); - - delay(50); - - *port &= ~0b101110; - *port &= ~(1 << 8); - - return wait(port, (1 << 8), false, 2000); -} - -bool USBDriver::setup_device(){ +bool USBDriver::setup_device(uint8_t address, uint16_t port){ + address = address_device(address); usb_device_descriptor* descriptor = (usb_device_descriptor*)allocate_in_page(mem_page, sizeof(usb_device_descriptor), ALIGN_64B, true, true); - if (!request_descriptor(0, 0, 0x80, 6, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ + if (!request_descriptor(address, 0, 0x80, 6, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ kprintf_raw("[USB error] failed to get device descriptor"); return false; } - uint8_t address = address_device(); usb_string_language_descriptor* lang_desc = (usb_string_language_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_language_descriptor), ALIGN_64B, true, true); @@ -79,9 +67,7 @@ bool USBDriver::setup_device(){ } } - get_configuration(address); - - return true; + return get_configuration(address); } bool USBDriver::get_configuration(uint8_t address){ @@ -212,7 +198,7 @@ void USBDriver::hub_enumerate(uint8_t address){ return; } handle_hub_routing(address,port); - setup_device(); + setup_device(0,1); } } diff --git a/kernel/input/usb.hpp b/kernel/input/usb.hpp index fed5fd57..7fbf1c4b 100644 --- a/kernel/input/usb.hpp +++ b/kernel/input/usb.hpp @@ -14,16 +14,17 @@ class USBDriver { uint16_t packet_size(uint16_t speed); bool get_configuration(uint8_t address); void hub_enumerate(uint8_t address); - bool port_reset(uint32_t *port); - bool setup_device(); - virtual uint8_t address_device() = 0; + virtual bool setup_device(uint8_t address, uint16_t port); + virtual uint8_t address_device(uint8_t address) = 0; virtual bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value, xhci_device_types type) = 0; virtual void handle_hub_routing(uint8_t hub, uint8_t port) = 0; virtual bool poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t size) = 0; - ~USBDriver() = default; void poll_inputs(); + virtual void handle_interrupt() = 0; bool use_interrupts; + ~USBDriver() = default; protected: void *mem_page; USBManager *usb_manager; + bool verbose = false; }; \ No newline at end of file diff --git a/kernel/input/xhci.c b/kernel/input/xhci.c deleted file mode 100644 index 898713ea..00000000 --- a/kernel/input/xhci.c +++ /dev/null @@ -1,732 +0,0 @@ -#include "xhci.h" -#include "console/kio.h" -#include "console/serial/uart.h" -#include "pci.h" -#include "memory/kalloc.h" -#include "memory/memory_access.h" -#include "memory/page_allocator.h" -#include "xhci_bridge.h" -#include "std/string.h" -#include "std/memfunctions.h" -#include "hw/hw.h" -#include "xhci_types.h" - -static xhci_device global_device; - -static bool xhci_verbose = false; - -void xhci_enable_verbose(){ - xhci_verbose = true; -} - -uint64_t awaited_addr; -uint32_t awaited_type; -#define AWAIT(addr, action, type) \ - ({ \ - awaited_addr = (uintptr_t)(addr); \ - awaited_type = (type); \ - action; \ - xhci_await_response((uintptr_t)(addr), (type)); \ - }) - -#define kprintfv(fmt, ...) \ - ({ \ - if (xhci_verbose){\ - uint64_t _args[] = { __VA_ARGS__ }; \ - kprintf_args_raw((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ - }\ - }) - -static void* xhci_mem_page; - -bool xhci_check_fatal_error() { - uint32_t sts = global_device.op->usbsts; - if (sts & (XHCI_USBSTS_HSE | XHCI_USBSTS_CE)) { - kprintf_raw("[xHCI ERROR] Fatal condition: USBSTS = %x", sts); - return true; - } - return false; -} - -bool enable_xhci_events(){ - kprintfv("[xHCI] Allocating ERST"); - global_device.interrupter = (xhci_interrupter*)(uintptr_t)(global_device.rt_base + 0x20); - - uint64_t event_ring = (uintptr_t)allocate_in_page(xhci_mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); - uint64_t erst_addr = (uintptr_t)allocate_in_page(xhci_mem_page, MAX_ERST_AMOUNT * sizeof(erst_entry), ALIGN_64B, true, true); - erst_entry* erst = (erst_entry*)erst_addr; - - erst->ring_base = event_ring; - erst->ring_size = MAX_TRB_AMOUNT; - erst->reserved = 0; - kprintfv("[xHCI] ERST ring_base: %x", event_ring); - kprintfv("[xHCI] ERST ring_size: %x", erst[0].ring_size); - global_device.event_ring = (trb*)event_ring; - - kprintfv("[xHCI] Interrupter register @ %x", global_device.rt_base + 0x20); - - global_device.interrupter->erstsz = 1; - kprintfv("[xHCI] ERSTSZ set to: %x", global_device.interrupter->erstsz); - - global_device.interrupter->erdp = event_ring; - global_device.interrupter->erstba = erst_addr; - kprintfv("[xHCI] ERSTBA set to: %x", global_device.interrupter->erstba); - - kprintfv("[xHCI] ERDP set to: %x", global_device.interrupter->erdp); - - global_device.interrupter->iman |= 1 << 1;//Enable interrupt - - global_device.op->usbsts = 1 << 3;//Enable interrupts - global_device.interrupter->iman |= 1;//Clear pending interrupts - - return !xhci_check_fatal_error(); -} - -void make_ring_link_control(trb* ring, bool cycle){ - ring[MAX_TRB_AMOUNT-1].control = - (TRB_TYPE_LINK << 10) - | (1 << 1) // Toggle Cycle - | cycle; -} - -void make_ring_link(trb* ring, bool cycle){ - ring[MAX_TRB_AMOUNT-1].parameter = (uintptr_t)ring; - ring[MAX_TRB_AMOUNT-1].status = 0; - make_ring_link_control(ring, cycle); -} - -bool xhci_init(xhci_device *xhci, uint64_t pci_addr) { - kprintfv("[xHCI] init"); - if (USE_PCI){ - if (!(read16(pci_addr + 0x06) & (1 << 4))){ - kprintfv("[xHCI] Wrong capabilities list"); - return false; - } - - pci_enable_device(pci_addr); - - if (!pci_setup_bar(pci_addr, 0, &xhci->mmio, &xhci->mmio_size)){ - kprintfv("[xHCI] BARs not set up"); - return false; - } - - pci_register(xhci->mmio, xhci->mmio_size); - - uint8_t interrupts_ok = pci_setup_interrupts(pci_addr, XHCI_IRQ, 1); - switch(interrupts_ok){ - case 0: - kprintf_raw("[xHCI] Failed to setup interrupts"); - return false; - case 1: - kprintf_raw("[xHCI] Interrupts setup with MSI-X %i",XHCI_IRQ); - break; - default: - kprintf_raw("[xHCI] Interrupts setup with MSI %i",XHCI_IRQ); - break; - } - - kprintfv("[xHCI] BARs set up @ %x (%x)",xhci->mmio,xhci->mmio_size); - } - - xhci->cap = (xhci_cap_regs*)(uintptr_t)xhci->mmio; - kprintfv("[xHCI] caplength %x",xhci->cap->caplength); - uint64_t op_base = xhci->mmio + xhci->cap->caplength; - xhci->op = (xhci_op_regs*)(uintptr_t)op_base; - xhci->ports = (xhci_port_regs*)((uintptr_t)op_base + 0x400); - xhci->db_base = xhci->mmio + (xhci->cap->dboff & ~0x1F); - xhci->rt_base = xhci->mmio + (xhci->cap->rtsoff & ~0x1F); - - kprintfv("[xHCI] Resetting controller"); - xhci->op->usbcmd &= ~1; - while (xhci->op->usbcmd & 1); - kprintfv("[xHCI] Clear complete"); - - xhci->op->usbcmd |= (1 << 1); - while (xhci->op->usbcmd & 1); - kprintfv("[xHCI] Reset complete"); - - while (xhci->op->usbsts & (1 << 11)); - kprintfv("[xHCI] Device ready"); - - if (xhci->op->usbcmd != 0){ - kprintf_raw("[xHCI Error] wrong usbcmd %x",xhci->op->usbcmd); - return false; - } else { - kprintfv("[xHCI] Correct usbcmd value"); - } - - if (xhci->op->dnctrl != 0){ - kprintf_raw("[xHCI Error] wrong dnctrl %x",xhci->op->dnctrl); - return false; - } else { - kprintfv("[xHCI] Correct dnctrl value"); - } - - if (xhci->op->crcr != 0){ - kprintf_raw("[xHCI Error] wrong crcr %x",xhci->op->crcr); - return false; - } else { - kprintfv("[xHCI] Correct crcr value"); - } - - if (xhci->op->dcbaap != 0){ - kprintf_raw("[xHCI Error] wrong dcbaap %x",xhci->op->dcbaap); - return false; - } else { - kprintfv("[xHCI] Correct dcbaap value"); - } - - if (xhci->op->config != 0){ - kprintf_raw("[xHCI Error] wrong config %x",xhci->op->config); - return false; - } else { - kprintfv("[xHCI] Correct config value"); - } - - xhci->command_cycle_bit = 1; - xhci->event_cycle_bit = 1; - - xhci->max_device_slots = xhci->cap->hcsparams1 & 0xFF; - xhci->max_ports = (xhci->cap->hcsparams1 >> 24) & 0xFF; - - xhci_initialize_manager(xhci->max_device_slots); - - uint16_t erst_max = ((xhci->cap->hcsparams2 >> 4) & 0xF); - - kprintfv("[xHCI] ERST Max: 2^%i",erst_max); - - xhci->op->dnctrl = 0xFFFF;//Enable device notifications - - xhci->op->config = xhci->max_device_slots; - kprintfv("[xHCI] %i device slots", xhci->max_device_slots); - - xhci_mem_page = alloc_page(0x1000, true, true, false); - - uintptr_t dcbaap_addr = (uintptr_t)allocate_in_page(xhci_mem_page, (xhci->max_device_slots + 1) * sizeof(uintptr_t), ALIGN_64B, true, true); - - xhci->op->dcbaap = dcbaap_addr; - - xhci->op->pagesize = 0b1;//4KB page size - - uint32_t scratchpad_count = ((xhci->cap->hcsparams2 >> 27) & 0x1F); - - xhci->dcbaa = (uint64_t *)dcbaap_addr; - - uint64_t* scratchpad_array = (uint64_t*)allocate_in_page(xhci_mem_page, (scratchpad_count == 0 ? 1 : scratchpad_count) * sizeof(uintptr_t), ALIGN_64B, true, true); - for (uint32_t i = 0; i < scratchpad_count; i++) - scratchpad_array[i] = (uint64_t)allocate_in_page(xhci_mem_page, 0x1000, ALIGN_64B, true, true); - xhci->dcbaa[0] = (uint64_t)scratchpad_array; - - kprintfv("[xHCI] dcbaap assigned at %x with %i scratchpads",dcbaap_addr,scratchpad_count); - - uint64_t command_ring = (uintptr_t)allocate_in_page(xhci_mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); - - xhci->cmd_ring = (trb*)command_ring; - xhci->cmd_index = 0; - xhci->op->crcr = command_ring | xhci->command_cycle_bit; - - make_ring_link(xhci->cmd_ring, xhci->command_cycle_bit); - - kprintfv("[xHCI] command ring allocated at %x. crcr now %x",command_ring, xhci->op->crcr); - - if (!enable_xhci_events()) - return false; - - kprintfv("[xHCI] event configuration finished"); - - xhci->op->usbcmd |= (1 << 2);//Interrupt enable - xhci->op->usbcmd |= 1;//Run - while ((xhci->op->usbsts & 0x1)); - - kprintfv("[xHCI] Init complete with usbcmd %x, usbsts %x",xhci->op->usbcmd, xhci->op->usbsts); - - return !xhci_check_fatal_error(); -} - - -void ring_doorbell(uint32_t slot, uint32_t endpoint) { - volatile uint32_t* db = (uint32_t*)(uintptr_t)(global_device.db_base + (slot << 2)); - kprintfv("[xHCI] Ringing doorbell at %x with value %x", global_device.db_base + (slot << 2),endpoint); - *db = endpoint; -} - -bool xhci_await_response(uint64_t command, uint32_t type){ - while (true){ - if (xhci_check_fatal_error()){ - kprintf_raw("[xHCI error] USBSTS value %x",global_device.op->usbsts); - awaited_type = 0; - return false; - } - for (; global_device.event_index < MAX_TRB_AMOUNT; global_device.event_index++){ - trb* ev = &global_device.event_ring[global_device.event_index]; - if (!((ev->control & 1) == global_device.event_cycle_bit)) //TODO: implement a timeout - break; - // kprintf_raw("[xHCI] A response at %i of type %x as a response to %x",global_device.event_index, (ev->control & TRB_TYPE_MASK) >> 10, ev->parameter); - if (global_device.event_index == MAX_TRB_AMOUNT - 1){ - global_device.event_index = 0; - global_device.event_cycle_bit = !global_device.event_cycle_bit; - } - if ((ev->control & TRB_TYPE_MASK) >> 10 == type && (command == 0 || ev->parameter == (command & 0xFFFFFFFFFFFFFFFF))){ - uint8_t completion_code = (ev->control >> 24) & 0xFF; - global_device.interrupter->erdp = (uintptr_t)ev | (1 << 3);//Inform of latest processed event - global_device.interrupter->iman |= 1;//Clear interrupts - global_device.op->usbsts |= 1 << 3;//Clear interrupts - awaited_type = 0; - return completion_code == 1; - } - } - awaited_type = 0; - return false; - } -} - -void xhci_sync_events(){ - for (; global_device.event_index < MAX_TRB_AMOUNT; global_device.event_index++){ - trb* ev = &global_device.event_ring[global_device.event_index]; - if (!((ev->control & 1) == global_device.event_cycle_bit)){ - global_device.interrupter->erdp = (uintptr_t)ev | (1 << 3); - global_device.interrupter->iman |= 1; - global_device.op->usbsts |= 1 << 3; - return; - } - global_device.interrupter->erdp = (uintptr_t)ev | (1 << 3); - global_device.interrupter->iman |= 1; - global_device.op->usbsts |= 1 << 3; - } -} - -bool issue_command(uint64_t param, uint32_t status, uint32_t control){ - trb* cmd = &global_device.cmd_ring[global_device.cmd_index++]; - cmd->parameter = param; - cmd->status = status; - cmd->control = control | global_device.command_cycle_bit; - - uint64_t cmd_addr = (uintptr_t)cmd; - kprintfv("[xHCI] issuing command with control: %x", cmd->control); - if (global_device.cmd_index == MAX_TRB_AMOUNT - 1){ - make_ring_link_control(global_device.cmd_ring, global_device.command_cycle_bit); - global_device.command_cycle_bit = !global_device.command_cycle_bit; - global_device.cmd_index = 0; - } - return AWAIT(cmd_addr, {ring_doorbell(0, 0);}, TRB_TYPE_COMMAND_COMPLETION); -} - -uint16_t packet_size(uint16_t port_speed){ - switch (port_speed) { - case 2: return 8;//Low - case 1: - case 3: return 64;//High & full - case 4: - case 5: - default: return 512;//Super & Super Plus & Default - } -} - -bool reset_port(uint16_t port){ - - xhci_port_regs* port_info = &global_device.ports[port]; - - if (port_info->portsc.pp == 0){ - port_info->portsc.pp = 1; - - //Read back after delay to ensure - // if (port_info->portsc.pp == 0){ - // kprintf_raw("[xHCI error] failed to power on port %i",port); - // return false; - // } - } - - port_info->portsc.csc = 1; - port_info->portsc.pec = 1; - port_info->portsc.prc = 1; - - //TODO: if usb3 - //portsc.wpr = 1; - //else - - return AWAIT(0, { - port_info->portsc.pr = 1; - },TRB_TYPE_PORT_STATUS_CHANGE); -} - -bool xhci_request_sized_descriptor(xhci_usb_device *device, bool interface, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor){ - usb_setup_packet packet = { - .bmRequestType = 0x80 | interface, - .bRequest = 6, - .wValue = (type << 8) | descriptor_index, - .wIndex = wIndex, - .wLength = descriptor_size - }; - - trb* setup_trb = &device->transfer_ring[device->transfer_index++]; - memcpy(&setup_trb->parameter, &packet, sizeof(packet)); - setup_trb->status = sizeof(usb_setup_packet); - //bit 4 = chain. Bit 16 direction (3 = IN, 2 = OUT, 0 = NO DATA) - setup_trb->control = (3 << 16) | (TRB_TYPE_SETUP_STAGE << 10) | (1 << 6) | (1 << 4) | device->transfer_cycle_bit; - - trb* data = &device->transfer_ring[device->transfer_index++]; - data->parameter = (uintptr_t)out_descriptor; - data->status = packet.wLength; - //bit 16 = direction - data->control = (1 << 16) | (TRB_TYPE_DATA_STAGE << 10) | (0 << 4) | device->transfer_cycle_bit; - - trb* status_trb = &device->transfer_ring[device->transfer_index++]; - status_trb->parameter = 0; - status_trb->status = 0; - //bit 5 = interrupt-on-completion - status_trb->control = (TRB_TYPE_STATUS_STAGE << 10) | (1 << 5) | device->transfer_cycle_bit; - - if (device->transfer_index == MAX_TRB_AMOUNT - 1){ - make_ring_link_control(device->transfer_ring, device->transfer_cycle_bit); - device->transfer_cycle_bit = !device->transfer_cycle_bit; - device->transfer_index = 0; - } - - return AWAIT((uintptr_t)status_trb, {ring_doorbell(device->slot_id, 1);}, TRB_TYPE_TRANSFER); -} - -bool clear_halt(xhci_usb_device *device, uint16_t endpoint_num){ - kprintfv("Clearing halt"); - usb_setup_packet packet = { - .bmRequestType = 0x2, - .bRequest = 1, - .wValue = 0, - .wIndex = endpoint_num, - .wLength = 0 - }; - - trb* setup_trb = &device->transfer_ring[device->transfer_index++]; - memcpy(&setup_trb->parameter, &packet, sizeof(packet)); - setup_trb->status = sizeof(usb_setup_packet); - //Bit 16 direction (3 = IN, 2 = OUT, 0 = NO DATA) - setup_trb->control = (0 << 16) | (TRB_TYPE_SETUP_STAGE << 10) | (1 << 6) | device->transfer_cycle_bit; - - trb* status_trb = &device->transfer_ring[device->transfer_index++]; - status_trb->parameter = 0; - status_trb->status = 0; - //bit 16 = direction. 1 = handshake. bit 5 = interrupt-on-completion - status_trb->control = (1 << 16) | (TRB_TYPE_STATUS_STAGE << 10) | (1 << 5) | device->transfer_cycle_bit; - - if (device->transfer_index == MAX_TRB_AMOUNT - 1){ - make_ring_link_control(device->transfer_ring, device->transfer_cycle_bit); - device->transfer_cycle_bit = !device->transfer_cycle_bit; - device->transfer_index = 0; - } - - if (!AWAIT((uintptr_t)status_trb, {ring_doorbell(device->slot_id, 1);},TRB_TYPE_TRANSFER)){ - kprintf_raw("[xHCI error] could not clear stall"); - return false; - } - - return true; -} - -bool xhci_request_descriptor(xhci_usb_device *device, bool interface, uint8_t type, uint16_t index, uint16_t wIndex, void *out_descriptor){ - if (!xhci_request_sized_descriptor(device, interface, type, index, wIndex, sizeof(usb_descriptor_header), out_descriptor)){ - kprintf_raw("[xHCI error] Failed to get descriptor header. Size %i", sizeof(usb_descriptor_header)); - return false; - } - usb_descriptor_header* descriptor = (usb_descriptor_header*)out_descriptor; - if (descriptor->bLength == 0){ - kprintf_raw("[xHCI error] wrong descriptor size %i",descriptor->bLength); - return false; - } - return xhci_request_sized_descriptor(device, interface, type, index, wIndex, descriptor->bLength, out_descriptor); -} - -uint8_t get_ep_type(usb_endpoint_descriptor* descriptor) { - return (descriptor->bEndpointAddress & 0x80 ? 1 << 2 : 0) | (descriptor->bmAttributes & 0x3); -} - -bool xhci_get_configuration(usb_configuration_descriptor *config, xhci_usb_device *device){ - uint16_t total_length = config->wTotalLength - config->header.bLength; - - kprintfv("[xHCI] Config length %i (%i - %i)",total_length,config->wTotalLength,config->header.bLength); - - uint16_t interface_index = 0; - - bool need_new_endpoint = true; - - xhci_device_types dev_type; - - xhci_configure_device(device->slot_id); - - for (uint16_t i = 0; i < total_length;){ - usb_descriptor_header* header = (usb_descriptor_header*)&config->data[i]; - if (header->bLength == 0){ - kprintf_raw("Failed to get descriptor. Header size 0"); - return false; - } - if (need_new_endpoint){ - need_new_endpoint = false; - } - switch (header->bDescriptorType) - { - case 0x4: //Interface - usb_interface_descriptor *interface = (usb_interface_descriptor *)&config->data[i]; - if (interface->bInterfaceClass != 0x3){ - kprintf_raw("[xHCI implementation error] non-hid devices not supported yet"); - return false; - } - kprintfv("[xHCI] interface protocol %x",interface->bInterfaceProtocol); - switch (interface->bInterfaceProtocol) - { - case 0x1: - dev_type = KEYBOARD; - break; - - default: - break; - } - interface_index++; - break; - case 0x21://HID - usb_hid_descriptor *hid = (usb_hid_descriptor *)&config->data[i]; - for (uint8_t j = 0; j < hid->bNumDescriptors; j++){ - if (hid->descriptors[j].bDescriptorType == 0x22){//REPORT HID - // device_endpoint->report_length = hid->descriptors[j].wDescriptorLength; - // device_endpoint->report_descriptor = (uint8_t*)allocate_in_page(xhci_mem_page, device_endpoint->report_length, ALIGN_64B, true, true); - // xhci_request_descriptor(device, true, 0x22, 0, interface_index-1, device_endpoint->report_descriptor); - // kprintfv("[xHCI] retrieved report descriptor of length %i at %x", device_endpoint->report_length, (uintptr_t)device_endpoint->report_descriptor); - } - } - break; - case 0x5: //Endpoint - usb_endpoint_descriptor *endpoint = (usb_endpoint_descriptor*)&config->data[i]; - kprintfv("[xHCI] endpoint address %x",endpoint->bEndpointAddress); - uint8_t ep_address = endpoint->bEndpointAddress; - uint8_t ep_dir = (ep_address & 0x80) ? 1 : 0; // 1 IN, 0 OUT - uint8_t ep_num = ((ep_address & 0x0F) * 2) + ep_dir; - - uint8_t ep_type = endpoint->bmAttributes & 0x03; // 0 = Control, 1 = Iso, 2 = Bulk, 3 = Interrupt - kprintf_raw("[xHCI] endpoint %i info. Direction %i type %i",ep_num, ep_dir, ep_type); - - xhci_input_context* ctx = device->ctx; - - ctx->control_context.add_flags = (1 << 0) | (1 << ep_num); - ctx->device_context.slot_f0.context_entries = 2; // 2 entries: EP0 + EP1 - ctx->device_context.endpoints[ep_num-1].endpoint_f0.interval = endpoint->bInterval; - - ctx->device_context.endpoints[ep_num-1].endpoint_f0.endpoint_state = 0; - ctx->device_context.endpoints[ep_num-1].endpoint_f1.endpoint_type = get_ep_type(endpoint); - ctx->device_context.endpoints[ep_num-1].endpoint_f1.max_packet_size = endpoint->wMaxPacketSize; - ctx->device_context.endpoints[ep_num-1].endpoint_f4.max_esit_payload_lo = endpoint->wMaxPacketSize; - ctx->device_context.endpoints[ep_num-1].endpoint_f1.error_count = 3; - - // device_endpoint->endpoint_transfer_ring = (trb*)allocate_in_page(xhci_mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); - // device_endpoint->endpoint_transfer_cycle_bit = 1; - // make_ring_link(device_endpoint->endpoint_transfer_ring, device_endpoint->endpoint_transfer_cycle_bit); - // ctx->device_context.endpoints[ep_num-1].endpoint_f23.dcs = device_endpoint->endpoint_transfer_cycle_bit; - // ctx->device_context.endpoints[ep_num-1].endpoint_f23.ring_ptr = ((uintptr_t)device_endpoint->endpoint_transfer_ring) >> 4; - // ctx->device_context.endpoints[ep_num-1].endpoint_f4.average_trb_length = endpoint->wMaxPacketSize; - - // device_endpoint->poll_packetSize = endpoint->wMaxPacketSize; - - if (!issue_command((uintptr_t)ctx, 0, (device->slot_id << 24) | (TRB_TYPE_CONFIG_EP << 10))){ - kprintf_raw("[xHCI] Failed to configure endpoint %i",ep_num); - return false; - } - - // kprintf_raw("[xHCI] Storing configuration for endpoint %i -> %i (%x)",ep_num,device_endpoint->poll_endpoint, (uintptr_t)device_endpoint); - - xhci_configure_endpoint(device->slot_id, ep_num, dev_type, endpoint->wMaxPacketSize); - - // kprintf_raw("[xHCI] Returned from configuration for endpoint %i -> %i (%x)",ep_num,device_endpoint->poll_endpoint, (uintptr_t)device_endpoint); - - need_new_endpoint = true; - - break; - } - i += header->bLength; - } - - xhci_sync_events();//TODO: This is hacky af, we should have await use irqs entirely and we won't need to await anything anymore - - return true; - -} - -bool xhci_setup_device(uint16_t port){ - - kprintfv("[xHCI] detecting and activating the default device at %i port. Resetting port...",port); - reset_port(port); - kprintfv("[xHCI] Port speed %i", (uint32_t)global_device.ports[port].portsc.port_speed); - - if (!issue_command(0,0,TRB_TYPE_ENABLE_SLOT << 10)){ - kprintf_raw("[xHCI error] failed enable slot command"); - return false; - } - - xhci_usb_device *device = (xhci_usb_device*)allocate_in_page(xhci_mem_page, sizeof(xhci_usb_device), ALIGN_64B, true, true); - - device->slot_id = (global_device.event_ring[0].status >> 24) & 0xFF; - kprintfv("[xHCI] Slot id %x", device->slot_id); - - if (device->slot_id == 0){ - kprintf_raw("[xHCI error]: Wrong slot id 0"); - return false; - } - - device->transfer_cycle_bit = 1; - - xhci_input_context *ctx = (xhci_input_context*)allocate_in_page(xhci_mem_page, sizeof(xhci_input_context), ALIGN_64B, true, true); - device->ctx = ctx; - void* output_ctx = (void*)allocate_in_page(xhci_mem_page, 0x1000, ALIGN_64B, true, true); - kprintfv("[xHCI] Allocating output for context at %x", (uintptr_t)output_ctx); - - ctx->control_context.add_flags = 0b11; - - ctx->device_context.slot_f0.speed = global_device.ports[port].portsc.port_speed; - ctx->device_context.slot_f0.context_entries = 1; - ctx->device_context.slot_f1.root_hub_port_num = port + 1; - - ctx->device_context.endpoints[0].endpoint_f0.endpoint_state = 0;//Disabled - ctx->device_context.endpoints[0].endpoint_f1.endpoint_type = 4;//Type = control - ctx->device_context.endpoints[0].endpoint_f0.interval = 0; - ctx->device_context.endpoints[0].endpoint_f1.error_count = 3;//3 errors allowed - ctx->device_context.endpoints[0].endpoint_f1.max_packet_size = packet_size(ctx->device_context.slot_f0.speed);//Packet size. Guessed from port speed - - device->transfer_ring = (trb*)allocate_in_page(xhci_mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); - kprintfv("Transfer ring at %x",(uintptr_t)device->transfer_ring); - make_ring_link(device->transfer_ring, device->transfer_cycle_bit); - - ctx->device_context.endpoints[0].endpoint_f23.dcs = device->transfer_cycle_bit; - ctx->device_context.endpoints[0].endpoint_f23.ring_ptr = ((uintptr_t)device->transfer_ring) >> 4; - ctx->device_context.endpoints[0].endpoint_f4.average_trb_length = 8; - - ((uint64_t*)(uintptr_t)global_device.op->dcbaap)[device->slot_id] = (uintptr_t)output_ctx; - if (!issue_command((uintptr_t)device->ctx, 0, (device->slot_id << 24) | (TRB_TYPE_ADDRESS_DEV << 10))){ - kprintf_raw("[xHCI error] failed addressing device at slot %x",device->slot_id); - return false; - } - - xhci_device_context* context = (xhci_device_context*)(uintptr_t)(global_device.dcbaa[device->slot_id]); - - kprintfv("[xHCI] ADDRESS_DEVICE command issued. Received package size %i",context->endpoints[0].endpoint_f1.max_packet_size); - - usb_device_descriptor* descriptor = (usb_device_descriptor*)allocate_in_page(xhci_mem_page, sizeof(usb_device_descriptor), ALIGN_64B, true, true); - - if (!xhci_request_descriptor(device, false, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ - kprintf_raw("[xHCI error] failed to get device descriptor"); - return false; - } - - usb_string_language_descriptor* lang_desc = (usb_string_language_descriptor*)allocate_in_page(xhci_mem_page, sizeof(usb_string_language_descriptor), ALIGN_64B, true, true); - - bool use_lang_desc = true; - - if (!xhci_request_descriptor(device, false, USB_STRING_DESCRIPTOR, 0, 0, lang_desc)){ - kprintf_raw("[xHCI warning] failed to get language descriptor"); - use_lang_desc = false; - } - - kprintfv("[xHCI] Vendor %x",descriptor->idVendor); - kprintfv("[xHCI] Product %x",descriptor->idProduct); - kprintfv("[xHCI] USB version %x",descriptor->bcdUSB); - kprintfv("[xHCI] EP0 Max Packet Size: %x", descriptor->bMaxPacketSize0); - kprintfv("[xHCI] Configurations: %x", descriptor->bNumConfigurations); - if (use_lang_desc){ - //TODO: we want to maintain the strings so we can have USB device information, and rework it to silece the alignment warning - uint16_t langid = lang_desc->lang_ids[0]; - usb_string_descriptor* prod_name = (usb_string_descriptor*)allocate_in_page(xhci_mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (xhci_request_descriptor(device, false, USB_STRING_DESCRIPTOR, descriptor->iProduct, langid, prod_name)){ - char name[128]; - if (utf16tochar(prod_name->unicode_string, name, sizeof(name))) { - kprintfv("[xHCI device] Product name: %s", (uint64_t)name); - } - } - usb_string_descriptor* man_name = (usb_string_descriptor*)allocate_in_page(xhci_mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (xhci_request_descriptor(device, false, USB_STRING_DESCRIPTOR, descriptor->iManufacturer, langid, man_name)){ - char name[128]; - if (utf16tochar(man_name->unicode_string, name, sizeof(name))) { - kprintfv("[xHCI device] Manufacturer name: %s", (uint64_t)name); - } - } - usb_string_descriptor* ser_name = (usb_string_descriptor*)allocate_in_page(xhci_mem_page, sizeof(usb_string_descriptor), ALIGN_64B, true, true); - if (xhci_request_descriptor(device, false, USB_STRING_DESCRIPTOR, descriptor->iSerialNumber, langid, ser_name)){ - char name[128]; - if (utf16tochar(ser_name->unicode_string, name, sizeof(name))) { - kprintfv("[xHCI device] Serial: %s", (uint64_t)name); - } - } - } - - usb_configuration_descriptor* config = (usb_configuration_descriptor*)allocate_in_page(xhci_mem_page, sizeof(usb_configuration_descriptor), ALIGN_64B, true, true); - if (!xhci_request_sized_descriptor(device, false, USB_CONFIGURATION_DESCRIPTOR, 0, 0, 8, config)){ - kprintf_raw("[xHCI error] could not get config descriptor header"); - return false; - } - - if (!xhci_request_sized_descriptor(device, false, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->header.bLength, config)){ - kprintf_raw("[xHCI error] could not get full config descriptor"); - return false; - } - - if (!xhci_request_sized_descriptor(device, false, USB_CONFIGURATION_DESCRIPTOR, 0, 0, config->wTotalLength, config)){ - kprintf_raw("[xHCI error] could not get full config descriptor"); - return false; - } - - if (!xhci_get_configuration(config, device)){ - kprintf_raw("[xHCI error] failed to parse device configuration"); - return false; - } - - return true; -} - -bool xhci_input_init() { - uint64_t addr; - if (XHCI_BASE){ - addr = XHCI_BASE; - } else if (USE_PCI) { - addr = find_pci_device(0x1B36, 0xD); - } - if (!addr){ - kprintf_raw("[PCI] xHCI device not found"); - return false; - } - - if (!xhci_init(&global_device, addr)){ - kprintf_raw("xHCI device initialization failed"); - return false; - } - - kprintfv("[xHCI] device initialized"); - - //TODO: we don't need this anymore, it's enough to handle port status changes - - for (uint16_t i = 0; i < global_device.max_ports; i++) - if (global_device.ports[i].portsc.ccs && global_device.ports[i].portsc.csc){ - if (!xhci_setup_device(i)){ - kprintf_raw("Failed to configure device at port %i",i); - return false; - } - break; - } - - return true; -} - -void xhci_handle_interrupt(){ - trb* ev = &global_device.event_ring[global_device.event_index]; - kprintfv("[xHCI] Interrupt with next event id %x. Awaited is %x", (ev->control & TRB_TYPE_MASK) >> 10, awaited_type); - uint32_t type = (ev->control & TRB_TYPE_MASK) >> 10; - uint64_t addr = ev->parameter; - if (type == awaited_type && (awaited_addr == 0 || (awaited_addr & 0xFFFFFFFFFFFFFFFF) == addr)) return;// Compatibility between our polling and interrupt, we'll need to get rid of this - kprintfv("[xHCI] Unhandled interrupt"); - switch (type){ - case TRB_TYPE_TRANSFER: - uint8_t slot_id = (ev->control & TRB_SLOT_MASK) >> 24; - uint8_t endpoint_id = (ev->control & TRB_ENDPOINT_MASK) >> 16; - kprintfv("Received input from slot %i endpoint %i",slot_id, endpoint_id); - xhci_process_input(slot_id, endpoint_id); - break; - case TRB_TYPE_PORT_STATUS_CHANGE: - kprintf_raw("[xHCI] Port status change. Ignored for now"); - global_device.interrupter->erdp = (uintptr_t)ev | (1 << 3);//Inform of latest processed event - global_device.interrupter->iman |= 1;//Clear interrupts - global_device.op->usbsts |= 1 << 3;//Clear interrupts - break; - } -} \ No newline at end of file diff --git a/kernel/input/xhci.cpp b/kernel/input/xhci.cpp new file mode 100644 index 00000000..ebfce0d5 --- /dev/null +++ b/kernel/input/xhci.cpp @@ -0,0 +1,511 @@ +#include "xhci.hpp" +#include "USBManager.hpp" +#include "async.h" +#include "usb.hpp" +#include "pci.h" +#include "xhci_types.h" +#include "hw/hw.h" +#include "memory/memory_access.h" +#include "std/memfunctions.h" + +uint64_t awaited_addr; +uint32_t awaited_type; +#define AWAIT(addr, action, type) \ + ({ \ + awaited_addr = (uintptr_t)(addr); \ + awaited_type = (type); \ + action; \ + await_response((uintptr_t)(addr), (type)); \ + }) + +#define kprintfv(fmt, ...) \ + ({ \ + if (verbose){\ + uint64_t _args[] = { __VA_ARGS__ }; \ + kprintf_args_raw((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ + }\ + }) + +bool XHCIDriver::check_fatal_error() { + uint32_t sts = op->usbsts; + if (sts & (XHCI_USBSTS_HSE | XHCI_USBSTS_CE)) { + kprintf_raw("[xHCI ERROR] Fatal condition: USBSTS = %x", sts); + return true; + } + return false; +} + +#define CHECK_XHCI_FIELD(field) (op->field != 0 ? (kprintf_raw("[xHCI Error] wrong " #field " %x", op->field), false) : (kprintfv("[xHCI] Correct " #field " value"), true)) + +bool XHCIDriver::init(){ + uint64_t addr, mmio, mmio_size; + if (XHCI_BASE){ + addr = XHCI_BASE; + mmio = addr; + } else if (USE_PCI) { + addr = find_pci_device(0x1B36, 0xD); + } + if (!addr){ + kprintf_raw("[PCI] xHCI device not found"); + return false; + } + + kprintfv("[xHCI] init"); + if (USE_PCI){ + if (!(*(uint16_t*)(addr + 0x06) & (1 << 4))){ + kprintfv("[xHCI] Wrong capabilities list"); + return false; + } + + pci_enable_device(addr); + + if (!pci_setup_bar(addr, 0, &mmio, &mmio_size)){ + kprintfv("[xHCI] BARs not set up"); + return false; + } + + pci_register(mmio, mmio_size); + + uint8_t interrupts_ok = pci_setup_interrupts(addr, XHCI_IRQ, 1); + switch(interrupts_ok){ + case 0: + kprintf_raw("[xHCI] Failed to setup interrupts"); + return false; + case 1: + kprintf_raw("[xHCI] Interrupts setup with MSI-X %i",XHCI_IRQ); + break; + default: + kprintf_raw("[xHCI] Interrupts setup with MSI %i",XHCI_IRQ); + break; + } + + kprintfv("[xHCI] BARs set up @ %x (%x)",mmio,mmio_size); + } + + cap = (xhci_cap_regs*)(uintptr_t)mmio; + kprintfv("[xHCI] caplength %x",cap->caplength); + uint64_t op_base = mmio + cap->caplength; + op = (xhci_op_regs*)(uintptr_t)op_base; + ports = (xhci_port_regs*)((uintptr_t)op_base + 0x400); + db_base = mmio + (cap->dboff & ~0x1F); + rt_base = mmio + (cap->rtsoff & ~0x1F); + + kprintfv("[xHCI] Resetting controller"); + op->usbcmd &= ~1; + while (op->usbcmd & 1); + kprintfv("[xHCI] Clear complete"); + + op->usbcmd |= (1 << 1); + while (op->usbcmd & 1); + kprintfv("[xHCI] Reset complete"); + + while (op->usbsts & (1 << 11)); + kprintfv("[xHCI] Device ready"); + + if (!CHECK_XHCI_FIELD(usbcmd)) return false; + if (!CHECK_XHCI_FIELD(dnctrl)) return false; + if (!CHECK_XHCI_FIELD(crcr)) return false; + if (!CHECK_XHCI_FIELD(dcbaap)) return false; + if (!CHECK_XHCI_FIELD(config)) return false; + + command_ring.cycle_bit = 1; + + max_device_slots = cap->hcsparams1 & 0xFF; + max_ports = (cap->hcsparams1 >> 24) & 0xFF; + + usb_manager = new USBManager(max_device_slots); + + uint16_t erst_max = ((cap->hcsparams2 >> 4) & 0xF); + + kprintfv("[xHCI] ERST Max: 2^%i",erst_max); + + op->dnctrl = 0xFFFF;//Enable device notifications + + op->config = max_device_slots; + kprintfv("[xHCI] %i device slots", max_device_slots); + + mem_page = alloc_page(0x1000, true, true, false); + + uintptr_t dcbaap_addr = (uintptr_t)allocate_in_page(mem_page, (max_device_slots + 1) * sizeof(uintptr_t), ALIGN_64B, true, true); + + op->dcbaap = dcbaap_addr; + + op->pagesize = 0b1;//4KB page size + + uint32_t scratchpad_count = ((cap->hcsparams2 >> 27) & 0x1F); + + dcbaap = dcbaap_addr; + + uint64_t* scratchpad_array = (uint64_t*)allocate_in_page(mem_page, (scratchpad_count == 0 ? 1 : scratchpad_count) * sizeof(uintptr_t), ALIGN_64B, true, true); + for (uint32_t i = 0; i < scratchpad_count; i++) + scratchpad_array[i] = (uint64_t)allocate_in_page(mem_page, 0x1000, ALIGN_64B, true, true); + ((uint64_t*)dcbaap)[0] = (uint64_t)scratchpad_array; + + kprintfv("[xHCI] dcbaap assigned at %x with %i scratchpads",dcbaap_addr,scratchpad_count); + + command_ring.ring = (trb*)allocate_in_page(mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); + + op->crcr = (uintptr_t)command_ring.ring | command_ring.cycle_bit; + + make_ring_link(command_ring.ring, command_ring.cycle_bit); + + kprintfv("[xHCI] command ring allocated at %x. crcr now %x",(uintptr_t)command_ring.ring, op->crcr); + + if (!enable_events()) + return false; + + kprintfv("[xHCI] event configuration finished"); + + op->usbcmd |= (1 << 2);//Interrupt enable + op->usbcmd |= 1;//Run + while ((op->usbsts & 0x1)); + + endpoint_map = IndexMap(255 * 5); + context_map = IndexMap(255 * 5); + + kprintfv("[xHCI] Init complete with usbcmd %x, usbsts %x",op->usbcmd, op->usbsts); + + if (check_fatal_error()) return false; + + for (uint16_t i = 0; i < max_ports; i++) + if (ports[i].portsc.ccs && ports[i].portsc.csc){ + if (!port_reset(i)){ + kprintf("[xHCI] Failed to reset port %i",i); + return false; + } + if (!setup_device(0,i)){ + kprintf_raw("[xHCI] Failed to configure device at port %i",i); + return false; + } + break; + } + + return true; + +} + +bool XHCIDriver::port_reset(uint16_t port){ + + xhci_port_regs* port_info = &ports[port]; + + if (port_info->portsc.pp == 0){ + port_info->portsc.pp = 1; + + //Read back after delay to ensure + // if (port_info->portsc.pp == 0){ + // kprintf_raw("[xHCI error] failed to power on port %i",port); + // return false; + // } + } + + port_info->portsc.csc = 1; + port_info->portsc.pec = 1; + port_info->portsc.prc = 1; + + //TODO: if usb3 + //portsc.wpr = 1; + //else + + return AWAIT(0, { + port_info->portsc.pr = 1; + },TRB_TYPE_PORT_STATUS_CHANGE); +} + +bool XHCIDriver::enable_events(){ + kprintfv("[xHCI] Allocating ERST"); + interrupter = (xhci_interrupter*)(rt_base + 0x20); + + uint64_t ev_ring = (uintptr_t)allocate_in_page(mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); + uint64_t erst_addr = (uintptr_t)allocate_in_page(mem_page, MAX_ERST_AMOUNT * sizeof(erst_entry), ALIGN_64B, true, true); + erst_entry* erst = (erst_entry*)erst_addr; + + erst->ring_base = ev_ring; + erst->ring_size = MAX_TRB_AMOUNT; + + kprintfv("[xHCI] ERST ring_base: %x", ev_ring); + kprintfv("[xHCI] ERST ring_size: %x", erst[0].ring_size); + event_ring.ring = (trb*)ev_ring; + event_ring.cycle_bit = 1; + + kprintfv("[xHCI] Interrupter register @ %x", rt_base + 0x20); + + interrupter->erstsz = 1; + kprintfv("[xHCI] ERSTSZ set to: %x", interrupter->erstsz); + + interrupter->erdp = ev_ring; + interrupter->erstba = erst_addr; + kprintfv("[xHCI] ERSTBA set to: %x", interrupter->erstba); + + kprintfv("[xHCI] ERDP set to: %x", interrupter->erdp); + + interrupter->iman |= 1 << 1;//Enable interrupt + + op->usbsts = 1 << 3;//Enable interrupts + interrupter->iman |= 1;//Clear pending interrupts + + use_interrupts = true; + + return !check_fatal_error(); +} + +void XHCIDriver::make_ring_link_control(trb* ring, bool cycle){ + ring[MAX_TRB_AMOUNT-1].control = + (TRB_TYPE_LINK << 10) + | (1 << 1) // Toggle Cycle + | cycle; +} + +void XHCIDriver::make_ring_link(trb* ring, bool cycle){ + ring[MAX_TRB_AMOUNT-1].parameter = (uintptr_t)ring; + ring[MAX_TRB_AMOUNT-1].status = 0; + make_ring_link_control(ring, cycle); +} + +void XHCIDriver::ring_doorbell(uint32_t slot, uint32_t endpoint) { + volatile uint32_t* db = (uint32_t*)(uintptr_t)(db_base + (slot << 2)); + kprintfv("[xHCI] Ringing doorbell at %x with value %x", db_base + (slot << 2),endpoint); + *db = endpoint; +} + +bool XHCIDriver::await_response(uint64_t command, uint32_t type){ + while (1){ + if (check_fatal_error()){ + kprintf_raw("[xHCI error] USBSTS value %x",op->usbsts); + awaited_type = 0; + return false; + } + for (; event_ring.index < MAX_TRB_AMOUNT; event_ring.index++){ + trb* ev = &event_ring.ring[event_ring.index]; + if (!wait(&ev->control, event_ring.cycle_bit, true, 2000)){ + awaited_type = 0; + return false; + } + // kprintf_raw("[xHCI] A response at %i of type %x as a response to %x",event_ring.index, (ev->control & TRB_TYPE_MASK) >> 10, ev->parameter); + // kprintf_raw("[xHCI] %x vs %x = %i and %x vs %x = %i", (ev->control & TRB_TYPE_MASK) >> 10, type, (ev->control & TRB_TYPE_MASK) >> 10 == type, ev->parameter, command, command == 0 || ev->parameter == command); + if (event_ring.index == MAX_TRB_AMOUNT - 1){ + event_ring.index = 0; + event_ring.cycle_bit = !event_ring.cycle_bit; + } + if ((((ev->control & TRB_TYPE_MASK) >> 10) == type) && (command == 0 || ev->parameter == command)){ + uint8_t completion_code = (ev->status >> 24) & 0xFF; + if (completion_code != 1) + kprintf("[xHCI] status error %i", completion_code); + interrupter->erdp = (uintptr_t)ev | (1 << 3);//Inform of latest processed event + interrupter->iman |= 1;//Clear interrupts + op->usbsts |= 1 << 3;//Clear interrupts + awaited_type = 0; + return completion_code == 1; + } + } + } + awaited_type = 0; + return false; +} + +bool XHCIDriver::issue_command(uint64_t param, uint32_t status, uint32_t control){ + trb* cmd = &command_ring.ring[command_ring.index++]; + cmd->parameter = param; + cmd->status = status; + cmd->control = control | command_ring.cycle_bit; + + uint64_t cmd_addr = (uintptr_t)cmd; + kprintfv("[xHCI] issuing command with control: %x", cmd->control); + if (command_ring.index == MAX_TRB_AMOUNT - 1){ + make_ring_link_control(command_ring.ring, command_ring.cycle_bit); + command_ring.cycle_bit = !command_ring.cycle_bit; + command_ring.index = 0; + } + return AWAIT(cmd_addr, {ring_doorbell(0, 0);}, TRB_TYPE_COMMAND_COMPLETION); +} + +bool XHCIDriver::setup_device(uint8_t address, uint16_t port){ + + if (!issue_command(0,0,TRB_TYPE_ENABLE_SLOT << 10)){ + kprintf_raw("[xHCI error] failed enable slot command"); + return false; + } + + address = (event_ring.ring[event_ring.index].status >> 24) & 0xFF; + kprintfv("[xHCI] Slot id %x", address); + + if (address == 0){ + kprintf_raw("[xHCI error]: Wrong slot id 0"); + return false; + } + + xhci_ring *transfer_ring = &endpoint_map[address << 8]; + + transfer_ring->cycle_bit = 1; + + xhci_input_context *ctx = (xhci_input_context*)allocate_in_page(mem_page, sizeof(xhci_input_context), ALIGN_64B, true, true); + kprintf("[xHCI] Allocating input context at %x", (uintptr_t)ctx); + context_map[address << 8] = ctx; + void* output_ctx = (void*)allocate_in_page(mem_page, 0x1000, ALIGN_64B, true, true); + kprintfv("[xHCI] Allocating output for context at %x", (uintptr_t)output_ctx); + + ctx->control_context.add_flags = 0b11; + + ctx->device_context.slot_f0.speed = ports[port].portsc.port_speed; + ctx->device_context.slot_f0.context_entries = 1; + ctx->device_context.slot_f1.root_hub_port_num = port + 1; + + ctx->device_context.endpoints[0].endpoint_f0.endpoint_state = 0;//Disabled + ctx->device_context.endpoints[0].endpoint_f1.endpoint_type = 4;//Type = control + ctx->device_context.endpoints[0].endpoint_f0.interval = 0; + ctx->device_context.endpoints[0].endpoint_f1.error_count = 3; + ctx->device_context.endpoints[0].endpoint_f1.max_packet_size = packet_size(ctx->device_context.slot_f0.speed);//Packet size. Guessed from port speed + + transfer_ring->ring = (trb*)allocate_in_page(mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); + kprintfv("Transfer ring at %x %i",(uintptr_t)transfer_ring->ring, address << 8); + make_ring_link(transfer_ring->ring, transfer_ring->cycle_bit); + + ctx->device_context.endpoints[0].endpoint_f23.dcs = transfer_ring->cycle_bit; + ctx->device_context.endpoints[0].endpoint_f23.ring_ptr = ((uintptr_t)transfer_ring->ring) >> 4; + ctx->device_context.endpoints[0].endpoint_f4.average_trb_length = sizeof(trb); + + USBDriver::setup_device(address, port); +} + +bool XHCIDriver::request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor){ + usb_setup_packet packet = { + .bmRequestType = rType, + .bRequest = request, + .wValue = (type << 8) | descriptor_index, + .wIndex = wIndex, + .wLength = descriptor_size + }; + + bool is_in = (rType & 0x80) != 0; + + xhci_ring *transfer_ring = &endpoint_map[address << 8 | endpoint]; + + trb* setup_trb = &transfer_ring->ring[transfer_ring->index++]; + memcpy(&setup_trb->parameter, &packet, sizeof(packet)); + setup_trb->status = sizeof(usb_setup_packet); + //bit 4 = chain. Bit 16 direction (3 = IN, 2 = OUT, 0 = NO DATA) + setup_trb->control = (3 << 16) | (TRB_TYPE_SETUP_STAGE << 10) | (1 << 6) | (1 << 4) | transfer_ring->cycle_bit; + + trb* data = &transfer_ring->ring[transfer_ring->index++]; + data->parameter = (uintptr_t)out_descriptor; + data->status = packet.wLength; + //bit 16 = direction + data->control = (1 << 16) | (TRB_TYPE_DATA_STAGE << 10) | (0 << 4) | transfer_ring->cycle_bit; + + trb* status_trb = &transfer_ring->ring[transfer_ring->index++]; + status_trb->parameter = 0; + status_trb->status = 0; + //bit 5 = interrupt-on-completion + status_trb->control = (TRB_TYPE_STATUS_STAGE << 10) | (1 << 5) | transfer_ring->cycle_bit; + + if (transfer_ring->index == MAX_TRB_AMOUNT - 1){ + make_ring_link_control(transfer_ring->ring, transfer_ring->cycle_bit); + transfer_ring->cycle_bit = !transfer_ring->cycle_bit; + transfer_ring->index = 0; + } + + return AWAIT((uintptr_t)status_trb, {ring_doorbell(address, 1);}, TRB_TYPE_TRANSFER); +} + +uint8_t XHCIDriver::address_device(uint8_t address){ + xhci_input_context* ctx = context_map[address << 8]; + kprintf("Addressing device %i with context %x", address, (uintptr_t)ctx); + if (!issue_command((uintptr_t)ctx, 0, (address << 24) | (TRB_TYPE_ADDRESS_DEV << 10))){ + kprintf_raw("[xHCI error] failed addressing device at slot %x",address); + return 0; + } + kprintf("Succeeded Addressing device %i with context %x", address, (uintptr_t)ctx); + return address; +} + +uint8_t XHCIDriver::get_ep_type(usb_endpoint_descriptor* descriptor) { + return (descriptor->bEndpointAddress & 0x80 ? 1 << 2 : 0) | (descriptor->bmAttributes & 0x3); +} + +bool XHCIDriver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value, xhci_device_types type){ + kprintfv("[xHCI] endpoint address %x",endpoint->bEndpointAddress); + uint8_t ep_address = endpoint->bEndpointAddress; + uint8_t ep_dir = (ep_address & 0x80) ? 1 : 0; // 1 IN, 0 OUT + uint8_t ep_num = ((ep_address & 0x0F) * 2) + ep_dir; + + uint8_t ep_type = endpoint->bmAttributes & 0x03; // 0 = Control, 1 = Iso, 2 = Bulk, 3 = Interrupt + kprintf_raw("[xHCI] endpoint %i info. Direction %i type %i",ep_num, ep_dir, ep_type); + + xhci_input_context* ctx = context_map[address << 8]; + + kprintf("XHCI ADD FLAGS %i",ctx->device_context.endpoints[0].endpoint_f1.max_packet_size); + + ctx->control_context.add_flags = (1 << 0) | (1 << ep_num); + ctx->device_context.slot_f0.context_entries = 2; //2 entries: EP0 + EP1 + ctx->device_context.endpoints[ep_num-1].endpoint_f0.interval = endpoint->bInterval; + + ctx->device_context.endpoints[ep_num-1].endpoint_f0.endpoint_state = 0; + ctx->device_context.endpoints[ep_num-1].endpoint_f1.endpoint_type = get_ep_type(endpoint); + ctx->device_context.endpoints[ep_num-1].endpoint_f1.max_packet_size = endpoint->wMaxPacketSize; + ctx->device_context.endpoints[ep_num-1].endpoint_f4.max_esit_payload_lo = endpoint->wMaxPacketSize; + ctx->device_context.endpoints[ep_num-1].endpoint_f1.error_count = 3; + + xhci_ring *ep_ring = &endpoint_map[address << 8 | ep_num]; + + ep_ring->ring = (trb*)allocate_in_page(mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); + ep_ring->cycle_bit = 1; + make_ring_link(ep_ring->ring, ep_ring->cycle_bit); + ctx->device_context.endpoints[ep_num-1].endpoint_f23.dcs = ep_ring->cycle_bit; + ctx->device_context.endpoints[ep_num-1].endpoint_f23.ring_ptr = ((uintptr_t)ep_ring->ring) >> 4; + ctx->device_context.endpoints[ep_num-1].endpoint_f4.average_trb_length = 8; + + kprintf("Passing in context %x",(uintptr_t)ctx); + + if (!issue_command((uintptr_t)ctx, 0, (address << 24) | (TRB_TYPE_CONFIG_EP << 10))){ + kprintf_raw("[xHCI] Failed to configure endpoint %i for address %i",ep_num,address); + return false; + } + + usb_manager->register_endpoint(address, ep_num, type, endpoint->wMaxPacketSize); + + return true; +} + +void XHCIDriver::handle_hub_routing(uint8_t hub, uint8_t port){ + //TODO: hubs +} + +bool XHCIDriver::poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t size){ + xhci_ring *ep_ring = &endpoint_map[address << 8 | endpoint]; + + trb* ev = &ep_ring->ring[ep_ring->index]; + + ev->parameter = (uintptr_t)out_buf; + ev->status = size; + ev->control = (TRB_TYPE_NORMAL << 10) | (1 << 5) | ep_ring->cycle_bit; + + if (ep_ring->index == MAX_TRB_AMOUNT - 1){ + make_ring_link_control(ep_ring->ring, ep_ring->cycle_bit); + ep_ring->cycle_bit = !ep_ring->cycle_bit; + ep_ring->index = 0; + } +} + +void XHCIDriver::handle_interrupt(){ + trb* ev = &event_ring.ring[event_ring.index]; + kprintfv("[xHCI] Interrupt with next event id %x. Awaited is %x", (ev->control & TRB_TYPE_MASK) >> 10, awaited_type); + uint32_t type = (ev->control & TRB_TYPE_MASK) >> 10; + uint64_t addr = ev->parameter; + if (type == awaited_type && (awaited_addr == 0 || (awaited_addr & 0xFFFFFFFFFFFFFFFF) == addr)) return;// Compatibility between our polling and interrupt, we'll need to get rid of this + kprintfv("[xHCI] Unhandled interrupt"); + switch (type){ + case TRB_TYPE_TRANSFER: { + uint8_t slot_id = (ev->control & TRB_SLOT_MASK) >> 24; + uint8_t endpoint_id = (ev->control & TRB_ENDPOINT_MASK) >> 16; + kprintfv("Received input from slot %i endpoint %i",slot_id, endpoint_id); + usb_manager->process_data(slot_id,endpoint_id, this); + break; + } + case TRB_TYPE_PORT_STATUS_CHANGE: { + kprintf_raw("[xHCI] Port status change. Ignored for now"); + interrupter->erdp = (uintptr_t)ev | (1 << 3);//Inform of latest processed event + interrupter->iman |= 1;//Clear interrupts + op->usbsts |= 1 << 3;//Clear interrupts + break; + } + } +} \ No newline at end of file diff --git a/kernel/input/xhci.h b/kernel/input/xhci.h deleted file mode 100644 index 2b796c5f..00000000 --- a/kernel/input/xhci.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif -#include "types.h" -#include "xhci_types.h" - -void xhci_enable_verbose(); -bool xhci_input_init(); - -void make_ring_link_control(trb* ring, bool cycle); -void ring_doorbell(uint32_t slot, uint32_t endpoint); -bool xhci_await_response(uint64_t command, uint32_t type); - -void xhci_sync_events(); -void xhci_handle_interrupt(); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/kernel/input/xhci.hpp b/kernel/input/xhci.hpp new file mode 100644 index 00000000..23458533 --- /dev/null +++ b/kernel/input/xhci.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include "usb.hpp" +#include "xhci_types.h" + +typedef struct xhci_ring { + trb* ring; + uint8_t cycle_bit; + uint32_t index; +} xhci_ring; + +class XHCIDriver : public USBDriver { +public: + XHCIDriver() = default; + bool init() override; + bool request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor) override; + uint8_t address_device(uint8_t address) override; + bool configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value, xhci_device_types type) override; + void handle_hub_routing(uint8_t hub, uint8_t port) override; + bool poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t size) override; + bool setup_device(uint8_t address, uint16_t port) override; + void handle_interrupt() override; + ~XHCIDriver() = default; +private: + bool check_fatal_error(); + bool enable_events(); + + bool port_reset(uint16_t port); + + bool issue_command(uint64_t param, uint32_t status, uint32_t control); + void ring_doorbell(uint32_t slot, uint32_t endpoint); + bool await_response(uint64_t command, uint32_t type); + uint8_t get_ep_type(usb_endpoint_descriptor* descriptor); + + void make_ring_link_control(trb* ring, bool cycle); + void make_ring_link(trb* ring, bool cycle); + + xhci_cap_regs* cap; + xhci_op_regs* op; + xhci_port_regs* ports; + xhci_interrupter* interrupter; + uintptr_t db_base; + uintptr_t rt_base; + uintptr_t dcbaap; + uint16_t max_device_slots; + uint16_t max_ports; + + xhci_ring command_ring; + xhci_ring event_ring; + + IndexMap endpoint_map; + IndexMap context_map; +}; \ No newline at end of file diff --git a/kernel/input/xhci_bridge.cpp b/kernel/input/xhci_bridge.cpp deleted file mode 100644 index a14a93e2..00000000 --- a/kernel/input/xhci_bridge.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "xhci_bridge.h" -#include "memory/kalloc.h" -#include "input_dispatch.h" -#include "memory/page_allocator.h" -#include "USBManager.hpp" -#include "USBKeyboard.hpp" -#include "xhci_types.h" - -USBManager *xhci_manager; - -void xhci_bridge_request_data(uint8_t slot_id, uint8_t endpoint_id) { - // xhci_manager->request_data(slot_id,endpoint_id); -} - -void xhci_process_input(uint8_t slot_id, uint8_t endpoint_id){ - // xhci_manager->process_data(slot_id,endpoint_id); -} - -void xhci_initialize_manager(uint32_t capacity){ - // xhci_manager = new USBManager(capacity); -} - -void xhci_configure_device(uint8_t slot_id){ - // xhci_manager->register_device(slot_id); -} - -void xhci_configure_endpoint(uint8_t slot_id, uint8_t endpoint, xhci_device_types type, uint16_t packet_size){ - // xhci_manager->register_endpoint(slot_id, endpoint, type, packet_size); -} \ No newline at end of file diff --git a/kernel/input/xhci_bridge.h b/kernel/input/xhci_bridge.h deleted file mode 100644 index 920be5f6..00000000 --- a/kernel/input/xhci_bridge.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "xhci.h" -#include "xhci_types.h" - -#include "keypress.h" - -void xhci_bridge_request_data(uint8_t slot_id, uint8_t endpoint_id); -void xhci_process_input(uint8_t slot_id, uint8_t endpoint_id); - -void xhci_initialize_manager(uint32_t capacity); -void xhci_configure_device(uint8_t slot_id); -void xhci_configure_endpoint(uint8_t slot_id, uint8_t endpoint, xhci_device_types type, uint16_t packet_size); - -#ifdef __cplusplus -} -#endif \ No newline at end of file From 2032d5f74c6befd533c3beb2df2d009e66ae3df1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 1 Jul 2025 00:00:00 +0000 Subject: [PATCH 48/79] Minor fixes --- kernel/input/usb.cpp | 16 ++++++++-------- kernel/input/xhci.cpp | 17 +++++++++-------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/kernel/input/usb.cpp b/kernel/input/usb.cpp index deb9c035..b28d900a 100644 --- a/kernel/input/usb.cpp +++ b/kernel/input/usb.cpp @@ -36,11 +36,11 @@ bool USBDriver::setup_device(uint8_t address, uint16_t port){ use_lang_desc = false; } - kprintf("[USB] Vendor %x",descriptor->idVendor); - kprintf("[USB] Product %x",descriptor->idProduct); - kprintf("[USB] USB version %x",descriptor->bcdUSB); - kprintf("[USB] EP0 Max Packet Size: %x", descriptor->bMaxPacketSize0); - kprintf("[USB] Configurations: %x", descriptor->bNumConfigurations); + kprintf("[USB device] Vendor %x",descriptor->idVendor); + kprintf("[USB device] Product %x",descriptor->idProduct); + kprintf("[USB device] USB version %x",descriptor->bcdUSB); + kprintf("[USB device] EP0 Max Packet Size: %x", descriptor->bMaxPacketSize0); + kprintf("[USB device] Configurations: %x", descriptor->bNumConfigurations); if (use_lang_desc){ //TODO: we want to maintain the strings so we can have USB device information, and rework it to silece the alignment warning uint16_t langid = lang_desc->lang_ids[0]; @@ -137,8 +137,8 @@ bool USBDriver::get_configuration(uint8_t address){ break; } interface_index++; + break; } - break; case 0x21: { //HID usb_hid_descriptor *hid = (usb_hid_descriptor *)&config->data[i]; for (uint8_t j = 0; j < hid->bNumDescriptors; j++){ @@ -149,16 +149,16 @@ bool USBDriver::get_configuration(uint8_t address){ kprintf("[USB] retrieved report descriptor of length %i at %x", report_length, (uintptr_t)report_descriptor); } } + break; } - break; case 0x5: {//Endpoint usb_endpoint_descriptor *endpoint = (usb_endpoint_descriptor*)&config->data[i]; if (!configure_endpoint(address, endpoint, config->bConfigurationValue, dev_type)) return false; need_new_endpoint = true; + break; } - break; default: { kprintf("[USB error] Unknown type %x", header->bDescriptorType); return false; } } i += header->bLength; diff --git a/kernel/input/xhci.cpp b/kernel/input/xhci.cpp index ebfce0d5..76e1baa9 100644 --- a/kernel/input/xhci.cpp +++ b/kernel/input/xhci.cpp @@ -177,7 +177,6 @@ bool XHCIDriver::init(){ kprintf_raw("[xHCI] Failed to configure device at port %i",i); return false; } - break; } return true; @@ -289,7 +288,7 @@ bool XHCIDriver::await_response(uint64_t command, uint32_t type){ if ((((ev->control & TRB_TYPE_MASK) >> 10) == type) && (command == 0 || ev->parameter == command)){ uint8_t completion_code = (ev->status >> 24) & 0xFF; if (completion_code != 1) - kprintf("[xHCI] status error %i", completion_code); + kprintf("[xHCI error] wrong status %i on command type %x", completion_code, ((ev->control & TRB_TYPE_MASK) >> 10) ); interrupter->erdp = (uintptr_t)ev | (1 << 3);//Inform of latest processed event interrupter->iman |= 1;//Clear interrupts op->usbsts |= 1 << 3;//Clear interrupts @@ -413,7 +412,9 @@ uint8_t XHCIDriver::address_device(uint8_t address){ kprintf_raw("[xHCI error] failed addressing device at slot %x",address); return 0; } - kprintf("Succeeded Addressing device %i with context %x", address, (uintptr_t)ctx); + xhci_device_context* context = (xhci_device_context*)((uint64_t*)dcbaap)[address]; + + kprintf("[xHCI] ADDRESS_DEVICE command issued. Received package size %i",context->endpoints[0].endpoint_f1.max_packet_size); return address; } @@ -432,8 +433,7 @@ bool XHCIDriver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *en xhci_input_context* ctx = context_map[address << 8]; - kprintf("XHCI ADD FLAGS %i",ctx->device_context.endpoints[0].endpoint_f1.max_packet_size); - + ctx->control_context.add_flags = (1 << 0) | (1 << ep_num); ctx->device_context.slot_f0.context_entries = 2; //2 entries: EP0 + EP1 ctx->device_context.endpoints[ep_num-1].endpoint_f0.interval = endpoint->bInterval; @@ -443,9 +443,10 @@ bool XHCIDriver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *en ctx->device_context.endpoints[ep_num-1].endpoint_f1.max_packet_size = endpoint->wMaxPacketSize; ctx->device_context.endpoints[ep_num-1].endpoint_f4.max_esit_payload_lo = endpoint->wMaxPacketSize; ctx->device_context.endpoints[ep_num-1].endpoint_f1.error_count = 3; - + xhci_ring *ep_ring = &endpoint_map[address << 8 | ep_num]; - + + kprintf("XHCI ADD FLAGS %i",ctx->device_context.endpoints[0].endpoint_f1.max_packet_size); ep_ring->ring = (trb*)allocate_in_page(mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); ep_ring->cycle_bit = 1; make_ring_link(ep_ring->ring, ep_ring->cycle_bit); @@ -457,7 +458,7 @@ bool XHCIDriver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *en if (!issue_command((uintptr_t)ctx, 0, (address << 24) | (TRB_TYPE_CONFIG_EP << 10))){ kprintf_raw("[xHCI] Failed to configure endpoint %i for address %i",ep_num,address); - return false; + // return false; } usb_manager->register_endpoint(address, ep_num, type, endpoint->wMaxPacketSize); From 25158fe1f6dd0799eb3268c4e5b4c30d849a6d50 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 1 Jul 2025 00:00:00 +0000 Subject: [PATCH 49/79] fix crash --- kernel/input/xhci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/input/xhci.cpp b/kernel/input/xhci.cpp index 76e1baa9..c4dcb0cf 100644 --- a/kernel/input/xhci.cpp +++ b/kernel/input/xhci.cpp @@ -362,7 +362,7 @@ bool XHCIDriver::setup_device(uint8_t address, uint16_t port){ ctx->device_context.endpoints[0].endpoint_f23.ring_ptr = ((uintptr_t)transfer_ring->ring) >> 4; ctx->device_context.endpoints[0].endpoint_f4.average_trb_length = sizeof(trb); - USBDriver::setup_device(address, port); + return USBDriver::setup_device(address, port); } bool XHCIDriver::request_sized_descriptor(uint8_t address, uint8_t endpoint, uint8_t rType, uint8_t request, uint8_t type, uint16_t descriptor_index, uint16_t wIndex, uint16_t descriptor_size, void *out_descriptor){ From e0c012677984d3ec03d4c3983246218eb38cebe3 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 1 Jul 2025 00:00:00 +0000 Subject: [PATCH 50/79] Alignment and proper slot address detection --- kernel/input/usb.hpp | 2 +- kernel/input/xhci.cpp | 18 +++++++++--------- kernel/input/xhci.hpp | 2 ++ kernel/input/xhci_types.h | 28 ++++++++++++++-------------- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/kernel/input/usb.hpp b/kernel/input/usb.hpp index 7fbf1c4b..105d376a 100644 --- a/kernel/input/usb.hpp +++ b/kernel/input/usb.hpp @@ -26,5 +26,5 @@ class USBDriver { protected: void *mem_page; USBManager *usb_manager; - bool verbose = false; + bool verbose = true; }; \ No newline at end of file diff --git a/kernel/input/xhci.cpp b/kernel/input/xhci.cpp index c4dcb0cf..ccd9eeb4 100644 --- a/kernel/input/xhci.cpp +++ b/kernel/input/xhci.cpp @@ -274,22 +274,22 @@ bool XHCIDriver::await_response(uint64_t command, uint32_t type){ return false; } for (; event_ring.index < MAX_TRB_AMOUNT; event_ring.index++){ - trb* ev = &event_ring.ring[event_ring.index]; - if (!wait(&ev->control, event_ring.cycle_bit, true, 2000)){ + last_event = &event_ring.ring[event_ring.index]; + if (!wait(&last_event->control, event_ring.cycle_bit, true, 2000)){ awaited_type = 0; return false; } - // kprintf_raw("[xHCI] A response at %i of type %x as a response to %x",event_ring.index, (ev->control & TRB_TYPE_MASK) >> 10, ev->parameter); + // kprintf_raw("[xHCI] A response at %i of type %x as a response to %x",event_ring.index, (last_event->control & TRB_TYPE_MASK) >> 10, last_event->parameter); // kprintf_raw("[xHCI] %x vs %x = %i and %x vs %x = %i", (ev->control & TRB_TYPE_MASK) >> 10, type, (ev->control & TRB_TYPE_MASK) >> 10 == type, ev->parameter, command, command == 0 || ev->parameter == command); if (event_ring.index == MAX_TRB_AMOUNT - 1){ event_ring.index = 0; event_ring.cycle_bit = !event_ring.cycle_bit; } - if ((((ev->control & TRB_TYPE_MASK) >> 10) == type) && (command == 0 || ev->parameter == command)){ - uint8_t completion_code = (ev->status >> 24) & 0xFF; + if ((((last_event->control & TRB_TYPE_MASK) >> 10) == type) && (command == 0 || last_event->parameter == command)){ + uint8_t completion_code = (last_event->status >> 24) & 0xFF; if (completion_code != 1) - kprintf("[xHCI error] wrong status %i on command type %x", completion_code, ((ev->control & TRB_TYPE_MASK) >> 10) ); - interrupter->erdp = (uintptr_t)ev | (1 << 3);//Inform of latest processed event + kprintf("[xHCI error] wrong status %i on command type %x", completion_code, ((last_event->control & TRB_TYPE_MASK) >> 10) ); + interrupter->erdp = (uintptr_t)last_event | (1 << 3);//Inform of latest processed event interrupter->iman |= 1;//Clear interrupts op->usbsts |= 1 << 3;//Clear interrupts awaited_type = 0; @@ -324,7 +324,7 @@ bool XHCIDriver::setup_device(uint8_t address, uint16_t port){ return false; } - address = (event_ring.ring[event_ring.index].status >> 24) & 0xFF; + address = (last_event->control >> 24) & 0xFF; kprintfv("[xHCI] Slot id %x", address); if (address == 0){ @@ -414,7 +414,7 @@ uint8_t XHCIDriver::address_device(uint8_t address){ } xhci_device_context* context = (xhci_device_context*)((uint64_t*)dcbaap)[address]; - kprintf("[xHCI] ADDRESS_DEVICE command issued. Received package size %i",context->endpoints[0].endpoint_f1.max_packet_size); + kprintf("[xHCI] ADDRESS_DEVICE command issued. Received packet size %i",context->endpoints[0].endpoint_f1.max_packet_size); return address; } diff --git a/kernel/input/xhci.hpp b/kernel/input/xhci.hpp index 23458533..10f4c77a 100644 --- a/kernel/input/xhci.hpp +++ b/kernel/input/xhci.hpp @@ -47,6 +47,8 @@ class XHCIDriver : public USBDriver { xhci_ring command_ring; xhci_ring event_ring; + + trb* last_event; IndexMap endpoint_map; IndexMap context_map; diff --git a/kernel/input/xhci_types.h b/kernel/input/xhci_types.h index 34484fac..e153d33f 100644 --- a/kernel/input/xhci_types.h +++ b/kernel/input/xhci_types.h @@ -42,7 +42,7 @@ typedef struct { uint32_t control; }__attribute__((packed)) trb; -typedef struct { +typedef struct __attribute__((packed)){ uint8_t caplength; uint8_t reserved; uint16_t hciversion; @@ -53,9 +53,9 @@ typedef struct { uint32_t dboff; uint32_t rtsoff; uint32_t hccparams2; -}__attribute__((packed)) xhci_cap_regs; +} xhci_cap_regs; -typedef struct { +typedef struct __attribute__((packed)){ uint32_t usbcmd; uint32_t usbsts; uint32_t pagesize; @@ -65,7 +65,7 @@ typedef struct { uint32_t reserved1[4]; uint64_t dcbaap; uint32_t config; -}__attribute__((packed)) xhci_op_regs; +} xhci_op_regs; typedef union { struct { @@ -97,21 +97,21 @@ typedef union { uint32_t value; } portstatuscontrol; -typedef struct { +typedef struct __attribute__((packed)){ portstatuscontrol portsc; uint32_t portpmsc; uint32_t portli; uint32_t rsvd; -}__attribute__((packed, aligned(4))) xhci_port_regs; +} xhci_port_regs; -typedef struct { +typedef struct __attribute__((packed)){ uint32_t iman; uint32_t imod; uint32_t erstsz; uint32_t reserved; uint64_t erstba; uint64_t erdp; -}__attribute__((packed)) xhci_interrupter; +} xhci_interrupter; typedef struct { uint64_t mmio; @@ -134,17 +134,17 @@ typedef struct { uint16_t max_ports; } xhci_device; -typedef struct { +typedef struct __attribute__((packed)){ uint64_t ring_base; uint32_t ring_size; uint32_t reserved; -}__attribute__((packed)) erst_entry; +} erst_entry; -typedef struct { +typedef struct __attribute__((packed)) { uint32_t drop_flags; uint32_t add_flags; uint64_t reserved[3]; -}__attribute__((packed)) xhci_input_control_context; +} xhci_input_control_context; typedef union { @@ -241,7 +241,7 @@ typedef union uint32_t value; } endpoint_field4; -typedef struct { +typedef struct __attribute__((packed)) { slot_field0 slot_f0; slot_field1 slot_f1; slot_field2 slot_f2; @@ -256,7 +256,7 @@ typedef struct { } endpoints[31]; } xhci_device_context; -typedef struct { +typedef struct __attribute__((packed)) { xhci_input_control_context control_context; xhci_device_context device_context; } xhci_input_context; From 70fcf569825ffd678571eac47ee9c3f65a1631a1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 1 Jul 2025 00:00:00 +0000 Subject: [PATCH 51/79] Reverted alignment due to crash --- kernel/input/xhci_types.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/kernel/input/xhci_types.h b/kernel/input/xhci_types.h index e153d33f..34484fac 100644 --- a/kernel/input/xhci_types.h +++ b/kernel/input/xhci_types.h @@ -42,7 +42,7 @@ typedef struct { uint32_t control; }__attribute__((packed)) trb; -typedef struct __attribute__((packed)){ +typedef struct { uint8_t caplength; uint8_t reserved; uint16_t hciversion; @@ -53,9 +53,9 @@ typedef struct __attribute__((packed)){ uint32_t dboff; uint32_t rtsoff; uint32_t hccparams2; -} xhci_cap_regs; +}__attribute__((packed)) xhci_cap_regs; -typedef struct __attribute__((packed)){ +typedef struct { uint32_t usbcmd; uint32_t usbsts; uint32_t pagesize; @@ -65,7 +65,7 @@ typedef struct __attribute__((packed)){ uint32_t reserved1[4]; uint64_t dcbaap; uint32_t config; -} xhci_op_regs; +}__attribute__((packed)) xhci_op_regs; typedef union { struct { @@ -97,21 +97,21 @@ typedef union { uint32_t value; } portstatuscontrol; -typedef struct __attribute__((packed)){ +typedef struct { portstatuscontrol portsc; uint32_t portpmsc; uint32_t portli; uint32_t rsvd; -} xhci_port_regs; +}__attribute__((packed, aligned(4))) xhci_port_regs; -typedef struct __attribute__((packed)){ +typedef struct { uint32_t iman; uint32_t imod; uint32_t erstsz; uint32_t reserved; uint64_t erstba; uint64_t erdp; -} xhci_interrupter; +}__attribute__((packed)) xhci_interrupter; typedef struct { uint64_t mmio; @@ -134,17 +134,17 @@ typedef struct { uint16_t max_ports; } xhci_device; -typedef struct __attribute__((packed)){ +typedef struct { uint64_t ring_base; uint32_t ring_size; uint32_t reserved; -} erst_entry; +}__attribute__((packed)) erst_entry; -typedef struct __attribute__((packed)) { +typedef struct { uint32_t drop_flags; uint32_t add_flags; uint64_t reserved[3]; -} xhci_input_control_context; +}__attribute__((packed)) xhci_input_control_context; typedef union { @@ -241,7 +241,7 @@ typedef union uint32_t value; } endpoint_field4; -typedef struct __attribute__((packed)) { +typedef struct { slot_field0 slot_f0; slot_field1 slot_f1; slot_field2 slot_f2; @@ -256,7 +256,7 @@ typedef struct __attribute__((packed)) { } endpoints[31]; } xhci_device_context; -typedef struct __attribute__((packed)) { +typedef struct { xhci_input_control_context control_context; xhci_device_context device_context; } xhci_input_context; From a9f6c55f141ab8dd1cd9a87165e5609460cd65a1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 2 Jul 2025 00:00:00 +0000 Subject: [PATCH 52/79] DCBAAP fix --- kernel/input/usb.hpp | 2 +- kernel/input/xhci.cpp | 29 ++++++++++++++++++++++++----- kernel/input/xhci.hpp | 4 +++- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/kernel/input/usb.hpp b/kernel/input/usb.hpp index 105d376a..7fbf1c4b 100644 --- a/kernel/input/usb.hpp +++ b/kernel/input/usb.hpp @@ -26,5 +26,5 @@ class USBDriver { protected: void *mem_page; USBManager *usb_manager; - bool verbose = true; + bool verbose = false; }; \ No newline at end of file diff --git a/kernel/input/xhci.cpp b/kernel/input/xhci.cpp index ccd9eeb4..44b040f8 100644 --- a/kernel/input/xhci.cpp +++ b/kernel/input/xhci.cpp @@ -134,12 +134,12 @@ bool XHCIDriver::init(){ uint32_t scratchpad_count = ((cap->hcsparams2 >> 27) & 0x1F); - dcbaap = dcbaap_addr; + dcbaap = (uintptr_t*)dcbaap_addr; uint64_t* scratchpad_array = (uint64_t*)allocate_in_page(mem_page, (scratchpad_count == 0 ? 1 : scratchpad_count) * sizeof(uintptr_t), ALIGN_64B, true, true); for (uint32_t i = 0; i < scratchpad_count; i++) scratchpad_array[i] = (uint64_t)allocate_in_page(mem_page, 0x1000, ALIGN_64B, true, true); - ((uint64_t*)dcbaap)[0] = (uint64_t)scratchpad_array; + dcbaap[0] = (uint64_t)scratchpad_array; kprintfv("[xHCI] dcbaap assigned at %x with %i scratchpads",dcbaap_addr,scratchpad_count); @@ -362,6 +362,8 @@ bool XHCIDriver::setup_device(uint8_t address, uint16_t port){ ctx->device_context.endpoints[0].endpoint_f23.ring_ptr = ((uintptr_t)transfer_ring->ring) >> 4; ctx->device_context.endpoints[0].endpoint_f4.average_trb_length = sizeof(trb); + dcbaap[address] = (uintptr_t)output_ctx; + return USBDriver::setup_device(address, port); } @@ -412,9 +414,9 @@ uint8_t XHCIDriver::address_device(uint8_t address){ kprintf_raw("[xHCI error] failed addressing device at slot %x",address); return 0; } - xhci_device_context* context = (xhci_device_context*)((uint64_t*)dcbaap)[address]; + xhci_device_context* context = (xhci_device_context*)dcbaap[address]; - kprintf("[xHCI] ADDRESS_DEVICE command issued. Received packet size %i",context->endpoints[0].endpoint_f1.max_packet_size); + kprintf("[xHCI] ADDRESS_DEVICE %i command issued. DCBAAP %x Received packet size %i",address, (uintptr_t)dcbaap, context->endpoints[0].endpoint_f1.max_packet_size); return address; } @@ -458,14 +460,31 @@ bool XHCIDriver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *en if (!issue_command((uintptr_t)ctx, 0, (address << 24) | (TRB_TYPE_CONFIG_EP << 10))){ kprintf_raw("[xHCI] Failed to configure endpoint %i for address %i",ep_num,address); - // return false; + return false; } usb_manager->register_endpoint(address, ep_num, type, endpoint->wMaxPacketSize); + sync_events(); + return true; } +void XHCIDriver::sync_events(){ + for (; event_ring.index < MAX_TRB_AMOUNT; event_ring.index++){ + trb* ev = &event_ring.ring[event_ring.index]; + if (!((ev->control & 1) == event_ring.cycle_bit)){ + interrupter->erdp = (uintptr_t)ev | (1 << 3); + interrupter->iman |= 1; + op->usbsts |= 1 << 3; + return; + } + interrupter->erdp = (uintptr_t)ev | (1 << 3); + interrupter->iman |= 1; + op->usbsts |= 1 << 3; + } +} + void XHCIDriver::handle_hub_routing(uint8_t hub, uint8_t port){ //TODO: hubs } diff --git a/kernel/input/xhci.hpp b/kernel/input/xhci.hpp index 10f4c77a..d2acec4e 100644 --- a/kernel/input/xhci.hpp +++ b/kernel/input/xhci.hpp @@ -35,13 +35,15 @@ class XHCIDriver : public USBDriver { void make_ring_link_control(trb* ring, bool cycle); void make_ring_link(trb* ring, bool cycle); + void sync_events(); + xhci_cap_regs* cap; xhci_op_regs* op; xhci_port_regs* ports; xhci_interrupter* interrupter; uintptr_t db_base; uintptr_t rt_base; - uintptr_t dcbaap; + uintptr_t* dcbaap; uint16_t max_device_slots; uint16_t max_ports; From 2a4dea7e2fd657d64abe6a85f825075e884160d1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 2 Jul 2025 00:00:00 +0000 Subject: [PATCH 53/79] Restored XHCI interrupts --- kernel/input/USBKeyboard.cpp | 19 +++++------ kernel/input/xhci.cpp | 63 +++++++++++++++++------------------- kernel/input/xhci.hpp | 2 -- 3 files changed, 39 insertions(+), 45 deletions(-) diff --git a/kernel/input/USBKeyboard.cpp b/kernel/input/USBKeyboard.cpp index 0a9d0fcc..a37d5760 100644 --- a/kernel/input/USBKeyboard.cpp +++ b/kernel/input/USBKeyboard.cpp @@ -10,9 +10,15 @@ void USBKeyboard::request_data(USBDriver *driver){ if (buffer == 0){ buffer = alloc_page(packet_size, true, true, true); } - - if (driver->poll(slot_id, endpoint, buffer, packet_size) && !driver->use_interrupts){ + + if (!driver->poll(slot_id, endpoint, buffer, packet_size)){ + + return; + } + + if (!driver->use_interrupts){ process_keypress((keypress*)buffer); + return; } } @@ -21,14 +27,9 @@ void USBKeyboard::process_data(USBDriver *driver){ return; } - // if (!xhci_await_response((uintptr_t)latest_ring,TRB_TYPE_TRANSFER)) - // xhci_sync_events();//TODO: we're just consuming the event without even looking to see if it's the right one, this is wrong, seriously, IRQ await would fix this - - // keypress *rkp = (keypress*)endpoint->input_buffer; - // process_keypress(rkp); - - // request_data(); + process_keypress((keypress*)buffer); + request_data(driver); } void USBKeyboard::process_keypress(keypress *rkp){ diff --git a/kernel/input/xhci.cpp b/kernel/input/xhci.cpp index 44b040f8..a86d25d4 100644 --- a/kernel/input/xhci.cpp +++ b/kernel/input/xhci.cpp @@ -14,8 +14,10 @@ uint32_t awaited_type; ({ \ awaited_addr = (uintptr_t)(addr); \ awaited_type = (type); \ + interrupter->iman &= ~1; \ action; \ await_response((uintptr_t)(addr), (type)); \ + interrupter->iman |= 1; \ }) #define kprintfv(fmt, ...) \ @@ -289,10 +291,11 @@ bool XHCIDriver::await_response(uint64_t command, uint32_t type){ uint8_t completion_code = (last_event->status >> 24) & 0xFF; if (completion_code != 1) kprintf("[xHCI error] wrong status %i on command type %x", completion_code, ((last_event->control & TRB_TYPE_MASK) >> 10) ); - interrupter->erdp = (uintptr_t)last_event | (1 << 3);//Inform of latest processed event + interrupter->erdp = (uintptr_t)&event_ring.ring[event_ring.index+1] | (1 << 3);//Inform of latest processed event interrupter->iman |= 1;//Clear interrupts op->usbsts |= 1 << 3;//Clear interrupts awaited_type = 0; + event_ring.index++; return completion_code == 1; } } @@ -308,7 +311,7 @@ bool XHCIDriver::issue_command(uint64_t param, uint32_t status, uint32_t control cmd->control = control | command_ring.cycle_bit; uint64_t cmd_addr = (uintptr_t)cmd; - kprintfv("[xHCI] issuing command with control: %x", cmd->control); + kprintfv("[xHCI] issuing command with control: %x from %x", cmd->control, cmd_addr); if (command_ring.index == MAX_TRB_AMOUNT - 1){ make_ring_link_control(command_ring.ring, command_ring.cycle_bit); command_ring.cycle_bit = !command_ring.cycle_bit; @@ -337,7 +340,7 @@ bool XHCIDriver::setup_device(uint8_t address, uint16_t port){ transfer_ring->cycle_bit = 1; xhci_input_context *ctx = (xhci_input_context*)allocate_in_page(mem_page, sizeof(xhci_input_context), ALIGN_64B, true, true); - kprintf("[xHCI] Allocating input context at %x", (uintptr_t)ctx); + kprintfv("[xHCI] Allocating input context at %x", (uintptr_t)ctx); context_map[address << 8] = ctx; void* output_ctx = (void*)allocate_in_page(mem_page, 0x1000, ALIGN_64B, true, true); kprintfv("[xHCI] Allocating output for context at %x", (uintptr_t)output_ctx); @@ -409,14 +412,14 @@ bool XHCIDriver::request_sized_descriptor(uint8_t address, uint8_t endpoint, uin uint8_t XHCIDriver::address_device(uint8_t address){ xhci_input_context* ctx = context_map[address << 8]; - kprintf("Addressing device %i with context %x", address, (uintptr_t)ctx); + kprintfv("Addressing device %i with context %x", address, (uintptr_t)ctx); if (!issue_command((uintptr_t)ctx, 0, (address << 24) | (TRB_TYPE_ADDRESS_DEV << 10))){ kprintf_raw("[xHCI error] failed addressing device at slot %x",address); return 0; } xhci_device_context* context = (xhci_device_context*)dcbaap[address]; - kprintf("[xHCI] ADDRESS_DEVICE %i command issued. DCBAAP %x Received packet size %i",address, (uintptr_t)dcbaap, context->endpoints[0].endpoint_f1.max_packet_size); + kprintfv("[xHCI] ADDRESS_DEVICE %i command issued. dcbaap %x Received packet size %i",address, (uintptr_t)dcbaap, context->endpoints[0].endpoint_f1.max_packet_size); return address; } @@ -448,7 +451,6 @@ bool XHCIDriver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *en xhci_ring *ep_ring = &endpoint_map[address << 8 | ep_num]; - kprintf("XHCI ADD FLAGS %i",ctx->device_context.endpoints[0].endpoint_f1.max_packet_size); ep_ring->ring = (trb*)allocate_in_page(mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); ep_ring->cycle_bit = 1; make_ring_link(ep_ring->ring, ep_ring->cycle_bit); @@ -456,35 +458,17 @@ bool XHCIDriver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *en ctx->device_context.endpoints[ep_num-1].endpoint_f23.ring_ptr = ((uintptr_t)ep_ring->ring) >> 4; ctx->device_context.endpoints[ep_num-1].endpoint_f4.average_trb_length = 8; - kprintf("Passing in context %x",(uintptr_t)ctx); - if (!issue_command((uintptr_t)ctx, 0, (address << 24) | (TRB_TYPE_CONFIG_EP << 10))){ kprintf_raw("[xHCI] Failed to configure endpoint %i for address %i",ep_num,address); return false; } usb_manager->register_endpoint(address, ep_num, type, endpoint->wMaxPacketSize); - - sync_events(); - + usb_manager->request_data(address, ep_num, this); + return true; } -void XHCIDriver::sync_events(){ - for (; event_ring.index < MAX_TRB_AMOUNT; event_ring.index++){ - trb* ev = &event_ring.ring[event_ring.index]; - if (!((ev->control & 1) == event_ring.cycle_bit)){ - interrupter->erdp = (uintptr_t)ev | (1 << 3); - interrupter->iman |= 1; - op->usbsts |= 1 << 3; - return; - } - interrupter->erdp = (uintptr_t)ev | (1 << 3); - interrupter->iman |= 1; - op->usbsts |= 1 << 3; - } -} - void XHCIDriver::handle_hub_routing(uint8_t hub, uint8_t port){ //TODO: hubs } @@ -492,7 +476,7 @@ void XHCIDriver::handle_hub_routing(uint8_t hub, uint8_t port){ bool XHCIDriver::poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t size){ xhci_ring *ep_ring = &endpoint_map[address << 8 | endpoint]; - trb* ev = &ep_ring->ring[ep_ring->index]; + trb* ev = &ep_ring->ring[ep_ring->index++]; ev->parameter = (uintptr_t)out_buf; ev->status = size; @@ -503,29 +487,40 @@ bool XHCIDriver::poll(uint8_t address, uint8_t endpoint, void *out_buf, uint16_t ep_ring->cycle_bit = !ep_ring->cycle_bit; ep_ring->index = 0; } + + ring_doorbell(address, endpoint); + + return true; } void XHCIDriver::handle_interrupt(){ trb* ev = &event_ring.ring[event_ring.index]; - kprintfv("[xHCI] Interrupt with next event id %x. Awaited is %x", (ev->control & TRB_TYPE_MASK) >> 10, awaited_type); + if (!((ev->control & 1) == event_ring.cycle_bit)) return; uint32_t type = (ev->control & TRB_TYPE_MASK) >> 10; uint64_t addr = ev->parameter; - if (type == awaited_type && (awaited_addr == 0 || (awaited_addr & 0xFFFFFFFFFFFFFFFF) == addr)) return;// Compatibility between our polling and interrupt, we'll need to get rid of this - kprintfv("[xHCI] Unhandled interrupt"); + if (type == awaited_type && (awaited_addr == 0 || (awaited_addr & 0xFFFFFFFFFFFFFFFF) == addr)) + return; + kprintfv("[xHCI] >>> Unhandled interrupt %i %x",event_ring.index,type); switch (type){ case TRB_TYPE_TRANSFER: { uint8_t slot_id = (ev->control & TRB_SLOT_MASK) >> 24; uint8_t endpoint_id = (ev->control & TRB_ENDPOINT_MASK) >> 16; kprintfv("Received input from slot %i endpoint %i",slot_id, endpoint_id); + usb_manager->process_data(slot_id,endpoint_id, this); break; } case TRB_TYPE_PORT_STATUS_CHANGE: { - kprintf_raw("[xHCI] Port status change. Ignored for now"); - interrupter->erdp = (uintptr_t)ev | (1 << 3);//Inform of latest processed event - interrupter->iman |= 1;//Clear interrupts - op->usbsts |= 1 << 3;//Clear interrupts + kprintfv("[xHCI] Port status change. Ignored for now"); break; } } + event_ring.index++; + if (event_ring.index == MAX_TRB_AMOUNT - 1){ + event_ring.index = 0; + event_ring.cycle_bit = !event_ring.cycle_bit; + } + interrupter->erdp = (uintptr_t)&event_ring.ring[event_ring.index] | (1 << 3);//Inform of latest processed event + interrupter->iman |= 1;//Clear interrupts + op->usbsts |= 1 << 3;//Clear interrupts } \ No newline at end of file diff --git a/kernel/input/xhci.hpp b/kernel/input/xhci.hpp index d2acec4e..234bb97a 100644 --- a/kernel/input/xhci.hpp +++ b/kernel/input/xhci.hpp @@ -35,8 +35,6 @@ class XHCIDriver : public USBDriver { void make_ring_link_control(trb* ring, bool cycle); void make_ring_link(trb* ring, bool cycle); - void sync_events(); - xhci_cap_regs* cap; xhci_op_regs* op; xhci_port_regs* ports; From 3b6b0b72f162eb77b01732808779885b1ce58e0c Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 2 Jul 2025 00:00:00 +0000 Subject: [PATCH 54/79] (Speedrun) moved ExFAT to cpp --- kernel/filesystem/disk.cpp | 13 +- kernel/filesystem/disk.h | 4 +- kernel/filesystem/{exfat.c => exfat.cpp} | 158 +++++------------------ kernel/filesystem/exfat.h | 14 -- kernel/filesystem/exfat.hpp | 99 ++++++++++++++ 5 files changed, 142 insertions(+), 146 deletions(-) rename kernel/filesystem/{exfat.c => exfat.cpp} (51%) delete mode 100644 kernel/filesystem/exfat.h create mode 100644 kernel/filesystem/exfat.hpp diff --git a/kernel/filesystem/disk.cpp b/kernel/filesystem/disk.cpp index 03a3d2d2..01e8b6ea 100644 --- a/kernel/filesystem/disk.cpp +++ b/kernel/filesystem/disk.cpp @@ -1,11 +1,12 @@ #include "disk.h" -#include "exfat.h" +#include "exfat.hpp" #include "virtio_blk_pci.h" #include "sdhci.hpp" #include "hw/hw.h" static bool disk_enable_verbose; SDHCI sdhci_driver; +ExFATFS fs_driver; void disk_verbose(){ disk_enable_verbose = true; @@ -32,7 +33,7 @@ bool find_disk(){ } bool disk_init(){ - return ef_init(); + return fs_driver.init(); } void disk_write(const void *buffer, uint32_t sector, uint32_t count){ @@ -46,10 +47,10 @@ void disk_read(void *buffer, uint32_t sector, uint32_t count){ vblk_read(buffer, sector, count); } -void* read_file(const char *path){ - return ef_read_file(path); +void* read_file(char *path){ + return fs_driver.read_file(path); } -string_list* list_directory_contents(const char *path){ - return ef_list_contents(path); +string_list* list_directory_contents(char *path){ + return fs_driver.list_contents(path); } \ No newline at end of file diff --git a/kernel/filesystem/disk.h b/kernel/filesystem/disk.h index bff6a946..8d4de64e 100644 --- a/kernel/filesystem/disk.h +++ b/kernel/filesystem/disk.h @@ -14,8 +14,8 @@ bool disk_init(); void disk_write(const void *buffer, uint32_t sector, uint32_t count); void disk_read(void *buffer, uint32_t sector, uint32_t count); -void* read_file(const char *path); -string_list* list_directory_contents(const char *path); +void* read_file(char *path); +string_list* list_directory_contents(char *path); #ifdef __cplusplus } diff --git a/kernel/filesystem/exfat.c b/kernel/filesystem/exfat.cpp similarity index 51% rename from kernel/filesystem/exfat.c rename to kernel/filesystem/exfat.cpp index 838458a2..6e8fe309 100644 --- a/kernel/filesystem/exfat.c +++ b/kernel/filesystem/exfat.cpp @@ -1,85 +1,18 @@ -#include "exfat.h" +#include "exfat.hpp" #include "disk.h" #include "memory/page_allocator.h" #include "console/kio.h" #include "std/string.h" #include "std/memfunctions.h" -void *fs_page; - -typedef struct exfat_mbs { - uint8_t jumpboot[3];//3 - char fsname[8];//8 - uint8_t mustbezero[53]; - uint64_t partition_offset; - uint64_t volume_length; - uint32_t fat_offset; - uint32_t fat_length; - uint32_t cluster_heap_offset; - uint32_t cluster_count; - uint32_t first_cluster_of_root_directory; - uint32_t volume_serial_number; - uint16_t fs_revision; - uint16_t volume_flags; - uint8_t bytes_per_sector_shift; - uint8_t sectors_per_cluster_shift; - uint8_t number_of_fats; - uint8_t drive_select; - uint8_t percent_in_use; - uint8_t rsvd[7]; - char bootcode[390]; - uint16_t bootsignature; -}__attribute__((packed)) exfat_mbs; - -typedef struct file_entry { - uint8_t entry_type; - uint8_t entry_count; - uint16_t checksum; - struct { - uint16_t read_only: 1; - uint16_t hidden: 1; - uint16_t system: 1; - uint16_t rsvd: 1; - uint16_t directory: 1; - uint16_t archive: 1; - uint16_t rsvd2: 10; - } flags; - - uint16_t rsvd; - uint32_t create_timestamp; - uint32_t last_modified; - uint32_t last_accessed; - uint8_t create10msincrement; - uint8_t lastmod10msincrement; - uint8_t createutcoffset; - uint8_t lastmodutcoffset; - uint8_t lastaccutcoffset; - - uint8_t rsvd2[7]; -}__attribute__((packed)) file_entry; - -typedef struct fileinfo_entry { - uint8_t entry_type; - uint8_t flags; - uint8_t rsvd; - uint8_t name_length; - uint16_t name_hash; - uint16_t rsvd2; - uint64_t valid_filesize; - uint32_t rsvd3; - uint32_t first_cluster; - uint64_t filesize; -}__attribute__((packed)) fileinfo_entry; - -typedef struct filename_entry { - uint8_t entry_type; - uint8_t flags; - uint16_t name[15]; -}__attribute__((packed)) filename_entry; - -exfat_mbs* mbs; - -void* ef_read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint32_t root_index){ +char* ExFATFS::advance_path(char *path){ + while (*path != '/' && *path != '\0') + path++; + path++; + return path; +} + +void* ExFATFS::read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint32_t root_index){ uint32_t count = cluster_count * cluster_size; uint32_t lba = cluster_start + ((root_index - 2) * cluster_size); @@ -93,18 +26,9 @@ void* ef_read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint32_t cl return buffer; } -const char* advance_path(const char *path){ - while (*path != '/' && *path != '\0') - path++; - path++; - return path; -} - -typedef void* (*ef_entry_handler)(file_entry*, fileinfo_entry*, filename_entry*, const char *seek); - -void* ef_walk_directory(uint32_t cluster_count, uint32_t root_index, const char *seek, ef_entry_handler handler) { +void* ExFATFS::walk_directory(uint32_t cluster_count, uint32_t root_index, char *seek, ef_entry_handler handler) { uint32_t cluster_size = 1 << mbs->sectors_per_cluster_shift; - char *buffer = (char*)ef_read_cluster(mbs->cluster_heap_offset, cluster_size, cluster_count, root_index); + char *buffer = (char*)read_cluster(mbs->cluster_heap_offset, cluster_size, cluster_count, root_index); file_entry *entry = 0; fileinfo_entry *entry1 = 0; filename_entry *entry2 = 0; @@ -120,7 +44,7 @@ void* ef_walk_directory(uint32_t cluster_count, uint32_t root_index, const char } else if (c == 0xC1) { entry2 = (filename_entry *)&buffer[i]; if (entry && entry1 && entry2) { - void *result = handler(entry, entry1, entry2, seek); + void *result = handler(this,entry, entry1, entry2, seek); if (result) return result; } @@ -131,9 +55,9 @@ void* ef_walk_directory(uint32_t cluster_count, uint32_t root_index, const char return 0; } -void* ef_list_directory(uint32_t cluster_count, uint32_t root_index) { +void* ExFATFS::list_directory(uint32_t cluster_count, uint32_t root_index) { uint32_t cluster_size = 1 << mbs->sectors_per_cluster_shift; - char *buffer = (char*)ef_read_cluster(mbs->cluster_heap_offset, cluster_size, cluster_count, root_index); + char *buffer = (char*)read_cluster(mbs->cluster_heap_offset, cluster_size, cluster_count, root_index); file_entry *entry = 0; fileinfo_entry *entry1 = 0; filename_entry *entry2 = 0; @@ -170,9 +94,9 @@ void* ef_list_directory(uint32_t cluster_count, uint32_t root_index) { return list_buffer; } -void* ef_read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index){ +void* ExFATFS::read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index){ - char *buffer = (char*)ef_read_cluster(cluster_start, cluster_size, cluster_count, root_index); + char *buffer = (char*)read_cluster(cluster_start, cluster_size, cluster_count, root_index); void *file = allocate_in_page(fs_page, file_size, ALIGN_64B, true, true); @@ -181,21 +105,7 @@ void* ef_read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t return file; } -void ef_read_dump(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint32_t root_index){ - - char *buffer = (char*)ef_read_cluster(cluster_start, cluster_size, cluster_count, root_index); - - for (uint64_t i = 0; i < cluster_size * cluster_count * 512; i++){ - // if (i % 8 == 0){ puts("\n["); puthex(i/8); puts("]: "); } - char c = buffer[i]; - if (c >= 0x20 && c <= 0x7E) putc(c); - // else puthex(c); - } - // puts("Done printing"); - putc('\n'); -} - -void ef_read_FAT(uint32_t location, uint32_t size, uint8_t count){ +void ExFATFS::read_FAT(uint32_t location, uint32_t size, uint8_t count){ uint32_t* fat = (uint32_t*)allocate_in_page(fs_page, size * count * 512, ALIGN_64B, true, true); disk_read((void*)fat, location, size); kprintf("FAT: %x (%x)",location*512,size * count * 512); @@ -204,7 +114,7 @@ void ef_read_FAT(uint32_t location, uint32_t size, uint8_t count){ // if (fat[i] != 0) kprintf("[%i] = %x", i, fat[i]); } -bool ef_init(){ +bool ExFATFS::init(){ fs_page = alloc_page(0x1000, true, true, false); mbs = (exfat_mbs*)allocate_in_page(fs_page, 512, ALIGN_64B, true, true); @@ -233,11 +143,11 @@ bool ef_init(){ kprintf("EXFAT Volume uses %i cluster size", 1 << mbs->bytes_per_sector_shift); kprintf("Cluster at %x (%x * %x of size %x each)",mbs->fat_offset + mbs->fat_length * mbs->number_of_fats, mbs->cluster_heap_offset,mbs->cluster_count, 1 << mbs->sectors_per_cluster_shift); - ef_read_FAT(mbs->fat_offset, mbs->fat_length, mbs->number_of_fats); + read_FAT(mbs->fat_offset, mbs->fat_length, mbs->number_of_fats); return true; } -static void* read_entry_handler(file_entry *entry, fileinfo_entry *info, filename_entry *name, const char *seek) { +void* ExFATFS::read_entry_handler(ExFATFS *instance, file_entry *entry, fileinfo_entry *info, filename_entry *name, char *seek) { char filename[15]; utf16tochar(name->name, filename, 15); @@ -245,48 +155,48 @@ static void* read_entry_handler(file_entry *entry, fileinfo_entry *info, filenam return 0; uint32_t filecluster = info->first_cluster; - uint32_t bps = 1 << mbs->bytes_per_sector_shift; - uint32_t spc = 1 << mbs->sectors_per_cluster_shift; + uint32_t bps = 1 << instance->mbs->bytes_per_sector_shift; + uint32_t spc = 1 << instance->mbs->sectors_per_cluster_shift; uint32_t bpc = bps * spc; uint32_t count = (info->filesize + bpc - 1) / bpc; return entry->flags.directory - ? ef_walk_directory(count, filecluster, advance_path(seek), read_entry_handler) - : ef_read_full_file(mbs->cluster_heap_offset, 1 << mbs->sectors_per_cluster_shift, count, info->filesize, filecluster); + ? instance->walk_directory(count, filecluster, instance->advance_path(seek), read_entry_handler) + : instance->read_full_file(instance->mbs->cluster_heap_offset, 1 << instance->mbs->sectors_per_cluster_shift, count, info->filesize, filecluster); } -void* ef_read_file(const char *path){ +void* ExFATFS::read_file(char *path){ path = advance_path(path); - return ef_walk_directory(1, mbs->first_cluster_of_root_directory, path, read_entry_handler); + return walk_directory(1, mbs->first_cluster_of_root_directory, path, read_entry_handler); } -static void* list_entries_handler(file_entry *entry, fileinfo_entry *info, filename_entry *name, const char *seek) { +void* ExFATFS::list_entries_handler(ExFATFS *instance, file_entry *entry, fileinfo_entry *info, filename_entry *name, char *seek) { char filename[15]; utf16tochar(name->name, filename, 15); if (strstart(seek, filename) != 0) return 0; - bool is_last = *advance_path(seek) == '\0'; + bool is_last = *instance->advance_path(seek) == '\0'; uint32_t filecluster = info->first_cluster; - uint32_t bps = 1 << mbs->bytes_per_sector_shift; - uint32_t spc = 1 << mbs->sectors_per_cluster_shift; + uint32_t bps = 1 << instance->mbs->bytes_per_sector_shift; + uint32_t spc = 1 << instance->mbs->sectors_per_cluster_shift; uint32_t bpc = bps * spc; uint32_t count = (info->filesize + bpc - 1) / bpc; kprintf("Now handling %s. Last %i",(uintptr_t)seek, is_last); if (is_last) - return ef_list_directory(count, filecluster); + return instance->list_directory(count, filecluster); if (entry->flags.directory) - return ef_walk_directory(count, filecluster, advance_path(seek), list_entries_handler); + return instance->walk_directory(count, filecluster, instance->advance_path(seek), list_entries_handler); return 0; } -string_list* ef_list_contents(const char *path){ +string_list* ExFATFS::list_contents(char *path){ path = advance_path(path); - return (string_list*)ef_walk_directory(1, mbs->first_cluster_of_root_directory, path, list_entries_handler); + return (string_list*)walk_directory(1, mbs->first_cluster_of_root_directory, path, list_entries_handler); } \ No newline at end of file diff --git a/kernel/filesystem/exfat.h b/kernel/filesystem/exfat.h deleted file mode 100644 index 8e2d9393..00000000 --- a/kernel/filesystem/exfat.h +++ /dev/null @@ -1,14 +0,0 @@ -#include "types.h" -#include "std/string.h" - -#ifdef __cplusplus -extern "C" { -#endif -bool ef_init(); -void ef_read_dump(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint32_t root_index); -void* ef_read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index); -void* ef_read_file(const char *path); -string_list* ef_list_contents(const char *path); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/kernel/filesystem/exfat.hpp b/kernel/filesystem/exfat.hpp new file mode 100644 index 00000000..b044bf39 --- /dev/null +++ b/kernel/filesystem/exfat.hpp @@ -0,0 +1,99 @@ +#pragma once + +#include "types.h" +#include "std/string.h" + +typedef struct exfat_mbs { + uint8_t jumpboot[3];//3 + char fsname[8];//8 + uint8_t mustbezero[53]; + uint64_t partition_offset; + uint64_t volume_length; + uint32_t fat_offset; + uint32_t fat_length; + uint32_t cluster_heap_offset; + uint32_t cluster_count; + uint32_t first_cluster_of_root_directory; + uint32_t volume_serial_number; + uint16_t fs_revision; + uint16_t volume_flags; + uint8_t bytes_per_sector_shift; + uint8_t sectors_per_cluster_shift; + uint8_t number_of_fats; + uint8_t drive_select; + uint8_t percent_in_use; + uint8_t rsvd[7]; + char bootcode[390]; + uint16_t bootsignature; +}__attribute__((packed)) exfat_mbs; + +typedef struct file_entry { + uint8_t entry_type; + uint8_t entry_count; + uint16_t checksum; + struct { + uint16_t read_only: 1; + uint16_t hidden: 1; + uint16_t system: 1; + uint16_t rsvd: 1; + uint16_t directory: 1; + uint16_t archive: 1; + uint16_t rsvd2: 10; + } flags; + + uint16_t rsvd; + uint32_t create_timestamp; + uint32_t last_modified; + uint32_t last_accessed; + uint8_t create10msincrement; + uint8_t lastmod10msincrement; + uint8_t createutcoffset; + uint8_t lastmodutcoffset; + uint8_t lastaccutcoffset; + + uint8_t rsvd2[7]; +}__attribute__((packed)) file_entry; + +typedef struct fileinfo_entry { + uint8_t entry_type; + uint8_t flags; + uint8_t rsvd; + uint8_t name_length; + uint16_t name_hash; + uint16_t rsvd2; + uint64_t valid_filesize; + uint32_t rsvd3; + uint32_t first_cluster; + uint64_t filesize; +}__attribute__((packed)) fileinfo_entry; + +typedef struct filename_entry { + uint8_t entry_type; + uint8_t flags; + uint16_t name[15]; +}__attribute__((packed)) filename_entry; + +class ExFATFS; + +typedef void* (*ef_entry_handler)(ExFATFS *instance, file_entry*, fileinfo_entry*, filename_entry*, char *seek); + +class ExFATFS { +public: + bool init(); + void* read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index); + void* read_file(char *path); + string_list* list_contents(char *path); + +protected: + void read_FAT(uint32_t location, uint32_t size, uint8_t count); + void* list_directory(uint32_t cluster_count, uint32_t root_index); + void* walk_directory(uint32_t cluster_count, uint32_t root_index, char *seek, ef_entry_handler handler); + void* read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint32_t root_index); + char* advance_path(char *path); + + exfat_mbs* mbs; + void *fs_page; + + static void* read_entry_handler(ExFATFS *instance, file_entry *entry, fileinfo_entry *info, filename_entry *name, char *seek); + static void* list_entries_handler(ExFATFS *instance, file_entry *entry, fileinfo_entry *info, filename_entry *name, char *seek); +}; \ No newline at end of file From 641abbce10a63ca05089e4b8c470b0f7c420d244 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 3 Jul 2025 00:00:00 +0000 Subject: [PATCH 55/79] Switched filesystem to fat32 (no large names yet) --- createfs | 69 ++----- kernel/filesystem/disk.cpp | 3 +- kernel/filesystem/exfat.cpp | 6 +- kernel/filesystem/fat32.cpp | 193 ++++++++++++++++++++ kernel/filesystem/fat32.hpp | 103 +++++++++++ kernel/kernel_processes/boot/login_screen.c | 2 +- kernel/kernel_processes/windows/desktop.cpp | 11 +- kernel/kstring.c | 2 +- kernel/memory/kalloc.c | 4 +- kernel/networking/processes/net_proc.c | 2 +- kernel/process/loading/elf_file.c | 5 + shared/std/string.c | 80 +++++--- shared/std/string.h | 25 +-- 13 files changed, 407 insertions(+), 98 deletions(-) create mode 100644 kernel/filesystem/fat32.cpp create mode 100644 kernel/filesystem/fat32.hpp diff --git a/createfs b/createfs index 34953033..9a4a6f6f 100755 --- a/createfs +++ b/createfs @@ -1,62 +1,29 @@ #!/bin/bash -IMG="disk.img" FOLDER="fs" -SIZE_MB=64 -VOLUME_NAME="REDOS" +VOLUME_LABEL="REDACTED OS" +IMAGE=disk.img -[ -f "$IMG" ] && rm "$IMG" -[ -f "$IMG.dmg" ] && rm "$IMG.dmg" - -function need_executable() { - - EXECUTABLE="$1" - - RECOMMENDED_PACKAGE="$2" - - if ! command -v "$EXECUTABLE" >/dev/null 2>&1; then - echo "Error: this script needs the '$EXECUTABLE' executable, please install it" >&2 - if [ -n "$RECOMMENDED_PACKAGE" ]; then - echo "The recommended package to install for this program is: '$RECOMMENDED_PACKAGE'" >&2 - fi - exit 1 - fi - -} - -OS_TYPE="$(uname)" - -if [[ "$OS_TYPE" == "Darwin" ]]; then - echo "Running on macOS" - need_executable hdiutil - - DEV_INFO=$(hdiutil create -size ${SIZE_MB}m -fs "ExFAT" -layout NONE -volname "$VOLUME_NAME" "$IMG" -attach) - MOUNTPOINT=$(echo "$DEV_INFO" | awk '/\/Volumes\// {print $NF}') - DEVICE=$(echo "$DEV_INFO" | awk '/\/dev\/disk/ {print $1; exit}') - - cp -R "$FOLDER/" "$MOUNTPOINT/" +if ! command -v "mcopy" >/dev/null 2>&1; then + echo "Error: this script depends on mtools. Please install it" >&2 + exit 1 +fi - #.fseventsd is not getting deleted i think - find "$MOUNTPOINT/" -type f \( -name '.DS_Store' -o -name '.fseventsd' -o -name '._*' \) -delete - echo "$MOUNTPOINT" - echo "DEV: $DEVICE" +if [[ "$OSTYPE" == "darwin"* ]]; then + SIZE_KB=$(du -sk "$FOLDER" | cut -f1) +else + SIZE_KB=$(du -s -B1 "$FOLDER" | awk '{print int($1/1024)}') +fi - hdiutil detach "$DEVICE" - mv "$IMG.dmg" "$IMG" +SIZE_MB=$(( (SIZE_KB * 12 / 10 + 1023) / 1024 )) -elif [[ "$OS_TYPE" == "Linux" ]]; then - echo "Running on Linux" +if ((SIZE_MB < 64)); then + SIZE_MB=64 +fi - need_executable dd - need_executable mkfs.exfat "exfatprogs" +dd if=/dev/zero of=$IMAGE bs=1M count=$SIZE_MB - # 1. Create an empty image file - dd if=/dev/zero of="$IMG" bs=1M count="$SIZE_MB" +mkfs.fat -F 32 -n "$VOLUME_LABEL" $IMAGE - # 2. Format it as ExFAT - mkfs.exfat -n "$VOLUME_NAME" "$IMG" -else - echo "Unknown OS: $OS_TYPE" >&2 - exit 1 -fi +mcopy -i $IMAGE -s "$FOLDER"/* :: \ No newline at end of file diff --git a/kernel/filesystem/disk.cpp b/kernel/filesystem/disk.cpp index 01e8b6ea..39ba9067 100644 --- a/kernel/filesystem/disk.cpp +++ b/kernel/filesystem/disk.cpp @@ -1,12 +1,13 @@ #include "disk.h" #include "exfat.hpp" +#include "fat32.hpp" #include "virtio_blk_pci.h" #include "sdhci.hpp" #include "hw/hw.h" static bool disk_enable_verbose; SDHCI sdhci_driver; -ExFATFS fs_driver; +FAT32FS fs_driver; void disk_verbose(){ disk_enable_verbose = true; diff --git a/kernel/filesystem/exfat.cpp b/kernel/filesystem/exfat.cpp index 6e8fe309..d9c8f7ea 100644 --- a/kernel/filesystem/exfat.cpp +++ b/kernel/filesystem/exfat.cpp @@ -125,7 +125,7 @@ bool ExFATFS::init(){ kprintf("[exfat] Wrong boot signature %x",mbs->bootsignature); return false; } - if (strcmp("EXFAT ", mbs->fsname) != 0){ + if (strcmp("EXFAT ", mbs->fsname, false) != 0){ kprintf("[exfat error] Wrong filesystem type %s",(uintptr_t)mbs->fsname); return false; } @@ -151,7 +151,7 @@ void* ExFATFS::read_entry_handler(ExFATFS *instance, file_entry *entry, fileinfo char filename[15]; utf16tochar(name->name, filename, 15); - if (strstart(seek, filename) != 0) + if (strstart(seek, filename, false) != 0) return 0; uint32_t filecluster = info->first_cluster; @@ -175,7 +175,7 @@ void* ExFATFS::list_entries_handler(ExFATFS *instance, file_entry *entry, filein char filename[15]; utf16tochar(name->name, filename, 15); - if (strstart(seek, filename) != 0) + if (strstart(seek, filename, false) != 0) return 0; bool is_last = *instance->advance_path(seek) == '\0'; diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp new file mode 100644 index 00000000..271eab45 --- /dev/null +++ b/kernel/filesystem/fat32.cpp @@ -0,0 +1,193 @@ +#include "fat32.hpp" +#include "disk.h" +#include "memory/page_allocator.h" +#include "console/kio.h" +#include "std/string.h" +#include "std/memfunctions.h" +#include "math/math.h" + +char* FAT32FS::advance_path(char *path){ + while (*path != '/' && *path != '\0') + path++; + path++; + return path; +} + +void* FAT32FS::read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint32_t root_index){ + uint32_t count = cluster_count * cluster_size; + + uint32_t lba = cluster_start + ((root_index - 2) * cluster_size); + + kprintf("Reading cluster(s) %i-%i, starting from %i (LBA %i) Address %x", root_index, root_index+cluster_count, cluster_start, lba, lba * 512); + + void* buffer = (char*)allocate_in_page(fs_page, cluster_count * cluster_size * 512, ALIGN_64B, true, true); + + if (count > 0) + disk_read(buffer, lba, count); + + return buffer; +} + +void* FAT32FS::walk_directory(uint32_t cluster_count, uint32_t root_index, char *seek, f32_entry_handler handler) { + uint32_t cluster_size = mbs->sectors_per_cluster; + char *buffer = (char*)read_cluster(data_start_sector, cluster_size, cluster_count, root_index); + f32file_entry *entry = 0; + + for (uint64_t i = 0; i < cluster_size * 512; i++) { + char c = buffer[i]; + entry = (f32file_entry *)&buffer[i]; + void *result = handler(this, entry, seek); + if (result) + return result; + i+= sizeof(f32file_entry) - 1; + } + + return 0; +} + +void* FAT32FS::list_directory(uint32_t cluster_count, uint32_t root_index) { + uint32_t cluster_size = mbs->sectors_per_cluster; + char *buffer = (char*)read_cluster(data_start_sector, cluster_size, cluster_count, root_index); + f32file_entry *entry = 0; + void *list_buffer = (char*)allocate_in_page(fs_page, 0x1000 * cluster_count, ALIGN_64B, true, true); + uint32_t len = 0; + uint32_t count = 0; + + char *write_ptr = (char*)list_buffer + 4; + + for (uint64_t i = 0; i < cluster_size * 512; i++) { + char c = buffer[i]; + entry = (f32file_entry *)&buffer[i]; + count++; + + bool ext_found = false; + for (int j = 0; j < 11 && entry->filename[j]; j++){ + if (entry->filename[j] != ' ') + *write_ptr++ = entry->filename[j]; + else if (!ext_found){ + *write_ptr++ = '.'; + ext_found = true; + } + } + *write_ptr++ = '\0'; + i += sizeof(f32file_entry) - 1; + } + + *(uint32_t*)list_buffer = count; + + return list_buffer; +} + +void* FAT32FS::read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index){ + + char *buffer = (char*)read_cluster(cluster_start, cluster_size, cluster_count, root_index); + + void *file = allocate_in_page(fs_page, file_size, ALIGN_64B, true, true); + + memcpy(file, (void*)buffer, file_size); + + return file; +} + +void FAT32FS::read_FAT(uint32_t location, uint32_t size, uint8_t count){ + // kprintf("FAT: %x (%x)",location*512,size * count * 512); + uint32_t* fat = (uint32_t*)allocate_in_page(fs_page, size * count * 512, ALIGN_64B, true, true); + disk_read((void*)fat, location, size); + uint32_t total_entries = (size * count * 512) / 4; + // for (uint32_t i = 0; i < total_entries; i++) + // if (fat[i] != 0) kprintf("[%i] = %x", i, fat[i]); +} + +bool FAT32FS::init(){ + fs_page = alloc_page(0x1000, true, true, false); + + mbs = (fat32_mbs*)allocate_in_page(fs_page, 512, ALIGN_64B, true, true); + + disk_read((void*)mbs, 0, 1); + + if (mbs->boot_signature != 0xAA55){ + kprintf("[fat32] Wrong boot signature %x",mbs->boot_signature); + return false; + } + if (mbs->signature != 0x29 && mbs->signature != 0x28){ + kprintf("[fat32 error] Wrong signature %x",mbs->signature); + return false; + } + + cluster_count = (mbs->num_sectors == 0 ? mbs->large_num_sectors : mbs->num_sectors)/mbs->sectors_per_cluster; + data_start_sector = mbs->reserved_sectors + (mbs->sectors_per_fat * mbs->number_of_fats); + + if (mbs->first_cluster_of_root_directory > cluster_count){ + kprintf("[fat32 error] root directory cluster not found"); + return false; + } + + kprintf("FAT32 Volume uses %i cluster size", mbs->bytes_per_sector); + kprintf("Data start at %x",data_start_sector*512); + + read_FAT(mbs->reserved_sectors, mbs->sectors_per_fat, mbs->number_of_fats); + + return true; +} + +void* FAT32FS::read_entry_handler(FAT32FS *instance, f32file_entry *entry, char *seek) { + char filename[11]; + if (entry->flags.volume_id) return 0; + int j = 0; + bool ext_found = false; + for (int i = 0; i < 11 && entry->filename[i]; i++){ + if (entry->filename[i] != ' ') + filename[j++] = entry->filename[i]; + else if (!ext_found){ + filename[j++] = '.'; + ext_found = true; + } + } + filename[j++] = '\0'; + bool is_last = *instance->advance_path(seek) == '\0'; + if (!is_last && strstart(seek, filename, true) == 0) return 0; + if (is_last && strcmp(seek, filename, true) != 0) return 0; + + uint32_t filecluster = (entry->hi_first_cluster << 16) | entry->lo_first_cluster; + uint32_t bps = instance->mbs->bytes_per_sector; + uint32_t spc = instance->mbs->sectors_per_cluster; + uint32_t bpc = bps * spc; + uint32_t count = max(1,(entry->filesize + bpc - 1) / bpc); + + return entry->flags.directory + ? instance->walk_directory(count, filecluster, instance->advance_path(seek), read_entry_handler) + : instance->read_full_file(instance->data_start_sector, instance->mbs->sectors_per_cluster, count, entry->filesize, filecluster); +} + +void* FAT32FS::read_file(char *path){ + path = advance_path(path); + + return walk_directory(1, mbs->first_cluster_of_root_directory, path, read_entry_handler); +} + +void* FAT32FS::list_entries_handler(FAT32FS *instance, f32file_entry *entry, char *seek) { + + if (entry->flags.volume_id) return 0; + if (strstart(seek, entry->filename, true) == 0) return 0; + + bool is_last = *instance->advance_path(seek) == '\0'; + + uint32_t filecluster = (entry->hi_first_cluster << 16) | entry->lo_first_cluster; + + uint32_t bps = instance->mbs->bytes_per_sector; + uint32_t spc = instance->mbs->sectors_per_cluster; + uint32_t bpc = bps * spc; + uint32_t count = max(1,(entry->filesize + bpc - 1) / bpc); + + // kprintf("Now handling %s. Last %i",(uintptr_t)seek, is_last); + + if (is_last) return instance->list_directory(count, filecluster); + if (entry->flags.directory) return instance->walk_directory(count, filecluster, instance->advance_path(seek), list_entries_handler); + return 0; +} + +string_list* FAT32FS::list_contents(char *path){ + path = advance_path(path); + + return (string_list*)walk_directory(1, mbs->first_cluster_of_root_directory, path, list_entries_handler); +} \ No newline at end of file diff --git a/kernel/filesystem/fat32.hpp b/kernel/filesystem/fat32.hpp new file mode 100644 index 00000000..dbbfede3 --- /dev/null +++ b/kernel/filesystem/fat32.hpp @@ -0,0 +1,103 @@ +#pragma once + +#include "types.h" +#include "std/string.h" + +typedef struct fat32_mbs { + uint8_t jumpboot[3];//3 + char fsname[8];//8 + uint16_t bytes_per_sector; + uint8_t sectors_per_cluster; + uint16_t reserved_sectors; + uint8_t number_of_fats; + uint16_t root_directory_entries; + uint16_t num_sectors;//Could be 0, in which case it's stored in large_num_sectors + uint8_t media_descriptor_type; + uint16_t num_sectors_fat;//Used only in 12/16 + uint16_t num_sectors_track; + uint16_t num_heads; + uint32_t num_hidden_sectors; + uint32_t large_num_sectors; + + uint32_t sectors_per_fat; + uint16_t flags; + uint16_t fat_version;//high major low minor + uint32_t first_cluster_of_root_directory; + uint16_t fsinfo_sector; + uint16_t backup_boot_sector; + uint8_t reserved[12]; + uint8_t drive_number; + uint8_t reserved_flags; + uint8_t signature;//0x28 or 0x29 + uint32_t volume_id; + char volume_label[11]; + char system_identifier[8]; + uint8_t boot_code[420]; + uint16_t boot_signature; +}__attribute__((packed)) fat32_mbs; + +typedef struct f32file_entry { + char filename[11]; + struct { + uint8_t read_only: 1; + uint8_t hidden: 1; + uint8_t system: 1; + uint8_t volume_id: 1; + uint8_t directory: 1; + uint8_t archive: 1; + uint8_t long_filename: 1; + } flags; + + uint8_t rsvd;//Can be used for case sensitivity + + uint8_t create10msincrement; + uint16_t create_timestamp;//Multiply seconds by 2 + uint16_t create_date; + uint16_t last_accessed_date; + uint16_t hi_first_cluster; + uint16_t last_modified_time; + uint16_t last_modified_date; + uint16_t lo_first_cluster; + uint32_t filesize; + +}__attribute__((packed)) f32file_entry; + +// typedef struct f32longname { +// uint8_t entry_type; +// uint8_t flags; +// uint8_t rsvd; +// uint8_t name_length; +// uint16_t name_hash; +// uint16_t rsvd2; +// uint64_t valid_filesize; +// uint32_t rsvd3; +// uint32_t first_cluster; +// uint64_t filesize; +// }__attribute__((packed)) f32longname; + +class FAT32FS; + +typedef void* (*f32_entry_handler)(FAT32FS *instance, f32file_entry*, char *seek); + +class FAT32FS { +public: + bool init(); + void* read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index); + void* read_file(char *path); + string_list* list_contents(char *path); + +protected: + void read_FAT(uint32_t location, uint32_t size, uint8_t count); + void* list_directory(uint32_t cluster_count, uint32_t root_index); + void* walk_directory(uint32_t cluster_count, uint32_t root_index, char *seek, f32_entry_handler handler); + void* read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint32_t root_index); + char* advance_path(char *path); + + fat32_mbs* mbs; + void *fs_page; + uint32_t cluster_count; + uint32_t data_start_sector; + + static void* read_entry_handler(FAT32FS *instance, f32file_entry *entry, char *seek); + static void* list_entries_handler(FAT32FS *instance, f32file_entry *entry, char *seek); +}; \ No newline at end of file diff --git a/kernel/kernel_processes/boot/login_screen.c b/kernel/kernel_processes/boot/login_screen.c index d08315b8..45f842eb 100644 --- a/kernel/kernel_processes/boot/login_screen.c +++ b/kernel/kernel_processes/boot/login_screen.c @@ -69,7 +69,7 @@ void login_screen(){ char key = kp.keys[i]; if (hid_keycode_to_char[(uint8_t)key]){ if (key == KEY_ENTER){ - if (strcmp(buf,default_pwd) == 0){ + if (strcmp(buf,default_pwd, false) == 0){ free(s.data,s.mem_length); free(title.data,title.mem_length); free(subtitle.data,subtitle.mem_length); diff --git a/kernel/kernel_processes/windows/desktop.cpp b/kernel/kernel_processes/windows/desktop.cpp index 121e9ac4..85884f3b 100644 --- a/kernel/kernel_processes/windows/desktop.cpp +++ b/kernel/kernel_processes/windows/desktop.cpp @@ -35,8 +35,10 @@ Desktop::Desktop() { string fullpath = string_format("/redos/user/%s",(uintptr_t)file); string name = string_ca_max(file,find_extension(file)); string ext = string_l(file + find_extension(file)); - if (strcmp(ext.data,".elf") == 0) + if (strcmp(ext.data,".elf", true) == 0){ + kprintf("Extension %s matches .elf", (uintptr_t)ext.data); add_entry(name.data, ext.data, fullpath.data); + } while (*reader) reader++; reader++; } @@ -115,12 +117,17 @@ void Desktop::activate_current(){ uint32_t index = (selected.y * MAX_COLS) + selected.x; if (index < entries.size()){ - if (strcmp(".elf",entries[index].ext) != 0){ + if (strcmp(".elf",entries[index].ext, true) != 0){ kprintf("Wrong executable format. Must be .elf"); return; } + kprintf("File path %s",(uintptr_t)entries[index].path); void *file = read_file(entries[index].path); active_proc = load_elf_file(entries[index].name, file); + if (!active_proc){ + kprintf("Failed to read ELF file"); + return; + } process_active = true; sys_set_focus(active_proc->id); } diff --git a/kernel/kstring.c b/kernel/kstring.c index aca1461b..3cfe197b 100644 --- a/kernel/kstring.c +++ b/kernel/kstring.c @@ -100,7 +100,7 @@ kstring kstring_from_bin(uint64_t value) { } bool kstring_equals(kstring a, kstring b) { - return strcmp(a.data,b.data) == 0; + return strcmp(a.data,b.data, false) == 0; } kstring kstring_format_args(const char *fmt, const uint64_t *args, uint32_t arg_count) { diff --git a/kernel/memory/kalloc.c b/kernel/memory/kalloc.c index dcd25eed..3fd18caa 100644 --- a/kernel/memory/kalloc.c +++ b/kernel/memory/kalloc.c @@ -123,14 +123,14 @@ uint64_t mem_get_kmem_end(){ } int handle_mem_node(const char *propname, const void *prop, uint32_t len, dtb_match_t *match) { - if (strcmp(propname, "reg") == 0 && len >= 16) { + if (strcmp(propname, "reg", false) == 0 && len >= 16) { uint32_t *p = (uint32_t *)prop; match->reg_base = ((uint64_t)__builtin_bswap32(p[0]) << 32) | __builtin_bswap32(p[1]); match->reg_size = ((uint64_t)__builtin_bswap32(p[2]) << 32) | __builtin_bswap32(p[3]); return 1; } - if (strcmp(propname, "device_type") == 0 && strcmp(prop,"memory") == 0){ + if (strcmp(propname, "device_type", false) == 0 && strcmp(prop,"memory", false) == 0){ match->found = true; } return 0; diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 38e1ac94..84b7bfdc 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -45,7 +45,7 @@ bool find_server(){ unbind_port(7777); - return strcmp(content, "world") == 0; + return strcmp(content, "world", false) == 0; } void test_network(){ diff --git a/kernel/process/loading/elf_file.c b/kernel/process/loading/elf_file.c index 60b85c55..2d46d350 100644 --- a/kernel/process/loading/elf_file.c +++ b/kernel/process/loading/elf_file.c @@ -39,6 +39,11 @@ typedef struct elf_program_header { process_t* load_elf_file(const char *name, void* file){ elf_header *header = (elf_header*)file; + if (header->magic[0] != 0x7f){ + kprintf("Failed to read header file"); + return 0; + } + kprintf("ELF FILE VERSION %x HEADER VERSION %x (%x)",header->elf_version,header->header_version,header->header_size); kprintf("FILE %i for %x",header->type, header->instruction_set); kprintf("ENTRY %x - %i",header->program_entry_offset); diff --git a/shared/std/string.c b/shared/std/string.c index 4f6c6892..a36cc437 100644 --- a/shared/std/string.c +++ b/shared/std/string.c @@ -3,7 +3,7 @@ #include "memory/memory_access.h" #include "std/memfunctions.h" -static uint32_t compute_length(const char *s, uint32_t max_length) { +static uint32_t compute_length( char *s, uint32_t max_length) { uint32_t len = 0; while ((max_length == 0 || len < max_length) && s[len] != '\0') { len++; @@ -11,7 +11,7 @@ static uint32_t compute_length(const char *s, uint32_t max_length) { return len; } -string string_l(const char *literal) { +string string_l( char *literal) { uint32_t len = compute_length(literal, 0); char *buf = (char*)malloc(len+1); for (uint32_t i = 0; i < len; i++) @@ -27,7 +27,7 @@ string string_repeat(char symbol, uint32_t amount){ return (string){ .data = buf, .length = amount, .mem_length = amount+1 }; } -string string_tail(const char *array, uint32_t max_length){ +string string_tail( char *array, uint32_t max_length){ uint32_t len = compute_length(array, 0); int offset = len-max_length; if (offset < 0) @@ -40,7 +40,7 @@ string string_tail(const char *array, uint32_t max_length){ return (string){ .data = buf, .length = adjusted_len }; } -string string_ca_max(const char *array, uint32_t max_length) { +string string_ca_max( char *array, uint32_t max_length) { uint32_t len = compute_length(array, max_length); char *buf = (char*)malloc(len + 1); for (uint32_t i = 0; i < len; i++) @@ -49,7 +49,7 @@ string string_ca_max(const char *array, uint32_t max_length) { return (string){ .data = buf, .length = len }; } -string string_c(const char c){ +string string_c( char c){ char *buf = (char*)malloc(2); buf[0] = c; buf[1] = 0; @@ -106,17 +106,17 @@ string string_from_bin(uint64_t value) { } bool string_equals(string a, string b) { - return strcmp(a.data,b.data) == 0; + return strcmp(a.data,b.data, false) == 0; } -string string_format(const char *fmt, ...) { +string string_format( char *fmt, ...) { va_list args; va_start(args, fmt); string_format_va(fmt, args); va_end(args); } -string string_format_va(const char *fmt, va_list args){ +string string_format_va( char *fmt, va_list args){ char *buf = (char*)malloc(256); uint32_t len = 0; uint32_t arg_index = 0; @@ -136,7 +136,7 @@ string string_format_va(const char *fmt, va_list args){ uint64_t val = va_arg(args, uint64_t); buf[len++] = (char)val; } else if (fmt[i] == 's') { - const char *str = (const char *)va_arg(args, uintptr_t); + char *str = ( char *)va_arg(args, uintptr_t); for (uint32_t j = 0; str[j] && len < 255; j++) buf[len++] = str[j]; } else if (fmt[i] == 'i') { uint64_t val = va_arg(args, long int); @@ -200,23 +200,47 @@ string string_format_va(const char *fmt, va_list args){ return (string){ .data = buf, .length = len, .mem_length = 256 }; } -int strcmp(const char *a, const char *b) { +char tolower(char c){ + if (c >= 'A' && c <= 'Z') return c + 'a' - 'A'; + return c; +} + +int strcmp(char *a, char *b, bool case_insensitive) { while (*a && *b) { - if (*a != *b) return (unsigned char)*a - (unsigned char)*b; + char ca = *a; + char cb = *b; + + if (case_insensitive) { + ca = tolower((unsigned char)ca); + cb = tolower((unsigned char)cb); + } + + if (ca != cb) return ca - cb; + a++; b++; } - return (unsigned char)*a - (unsigned char)*b; + if (case_insensitive) return tolower(*a) - tolower(*b); + return *a - *b; } -int strstart(const char *a, const char *b) { +int strstart(char *a, char *b, bool case_insensitive) { + int index = 0; while (*a && *b) { - if (*a != *b) return (unsigned char)*a - (unsigned char)*b; - a++; b++; + char ca = *a; + char cb = *b; + + if (case_insensitive) { + ca = tolower(ca); + cb = tolower(cb); + } + + if (ca != cb) return index; + a++; b++; index++; } return 0; } -int strindex(const char *a, const char *b) { +int strindex( char *a, char *b) { for (int i = 0; a[i]; i++) { int j = 0; while (b[j] && a[i + j] == b[j]) j++; @@ -225,12 +249,20 @@ int strindex(const char *a, const char *b) { return -1; } -int strend(const char *a, const char *b) { +int strend(char *a, char *b, bool case_insensitive) { while (*a && *b) { - if (*a == *b) { - const char *pa = a, *pb = b; - while (*pa == *pb) { - if (!*pa) return 0; + char ca = case_insensitive ? tolower((unsigned char)*a) : *a; + char cb = case_insensitive ? tolower((unsigned char)*b) : *b; + + if (ca == cb) { + char *pa = a, *pb = b; + while (1) { + char cpa = case_insensitive ? tolower((unsigned char)*pa) : *pa; + char cpb = case_insensitive ? tolower((unsigned char)*pb) : *pb; + + if (!cpa) return 0; + if (cpa != cpb) break; + pa++; pb++; } } @@ -239,9 +271,9 @@ int strend(const char *a, const char *b) { return 1; } -bool strcont(const char *a, const char *b) { +bool strcont( char *a, char *b) { while (*a) { - const char *p = a, *q = b; + char *p = a, *q = b; while (*p && *q && *p == *q) { p++; q++; } @@ -251,7 +283,7 @@ bool strcont(const char *a, const char *b) { return 0; } -bool utf16tochar(const uint16_t* str_in, char* out_str, size_t max_len) { +bool utf16tochar( uint16_t* str_in, char* out_str, size_t max_len) { size_t out_i = 0; while (str_in[out_i] != 0 && out_i + 1 < max_len) { uint16_t wc = str_in[out_i]; diff --git a/shared/std/string.h b/shared/std/string.h index ce654200..165c83c2 100644 --- a/shared/std/string.h +++ b/shared/std/string.h @@ -18,25 +18,26 @@ typedef struct string_list { char array[]; } string_list; -string string_l(const char *literal); -string string_ca_max(const char *array, uint32_t max_length); -string string_c(const char c); +string string_l( char *literal); +string string_ca_max( char *array, uint32_t max_length); +string string_c( char c); string string_from_hex(uint64_t value); bool string_equals(string a, string b); -string string_format(const char *fmt, ...); -string string_format_va(const char *fmt, va_list args); -string string_tail(const char *array, uint32_t max_length); +string string_format( char *fmt, ...); +string string_format_va( char *fmt, va_list args); +string string_tail( char *array, uint32_t max_length); string string_repeat(char symbol, uint32_t amount); -int strcmp(const char *a, const char *b); -bool strcont(const char *a, const char *b); -int strstart(const char *a, const char *b); -int strend(const char *a, const char *b); -int strindex(const char *a, const char *b); +char tolower(char c); +int strcmp( char *a, char *b, bool case_insensitive); +bool strcont( char *a, char *b); +int strstart(char *a, char *b, bool case_insensitive); +int strend( char *a, char *b, bool case_insensitive); +int strindex( char *a, char *b); uint64_t parse_hex_u64(char* str, size_t size); -bool utf16tochar(const uint16_t* str_in, char* out_str, size_t max_len); +bool utf16tochar( uint16_t* str_in, char* out_str, size_t max_len); #ifdef __cplusplus } From 3539c1c65d74658b92a490acec71e0217980a580 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 3 Jul 2025 00:00:00 +0000 Subject: [PATCH 56/79] Long filenames (jfc) --- kernel/filesystem/fat32.cpp | 101 ++++++++++++++++++++++++++---------- kernel/filesystem/fat32.hpp | 31 +++++------ 2 files changed, 89 insertions(+), 43 deletions(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index 271eab45..84f08d35 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -28,18 +28,63 @@ void* FAT32FS::read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint3 return buffer; } +void FAT32FS::parse_longnames(f32longname entries[], uint16_t count, char* out){ + uint16_t total = (5+6+2)*count; + uint16_t filename[total]; + uint16_t f = 0; + for (int i = count-1; i >= 0; i--){ + for (int j = 0; j < 5; j++) + filename[f++] = entries[i].name1[j]; + for (int j = 0; j < 6; j++) + filename[f++] = entries[i].name2[j]; + for (int j = 0; j < 2; j++) + filename[f++] = entries[i].name3[j]; + } + filename[f++] = '\0'; + utf16tochar(filename, out, total); +} + +void FAT32FS::parse_shortnames(f32file_entry* entry, char* out){ + int j = 0; + bool ext_found = false; + for (int i = 0; i < 11 && entry->filename[i]; i++){ + if (entry->filename[i] != ' ') + out[j++] = entry->filename[i]; + else if (!ext_found){ + out[j++] = '.'; + ext_found = true; + } + } + out[j++] = '\0'; +} + void* FAT32FS::walk_directory(uint32_t cluster_count, uint32_t root_index, char *seek, f32_entry_handler handler) { uint32_t cluster_size = mbs->sectors_per_cluster; char *buffer = (char*)read_cluster(data_start_sector, cluster_size, cluster_count, root_index); f32file_entry *entry = 0; for (uint64_t i = 0; i < cluster_size * 512; i++) { - char c = buffer[i]; + bool long_name = buffer[i + 0xB] == 0xF; + char filename[255]; + if (long_name){ + uint8_t order; + f32longname *first_longname = (f32longname*)&buffer[i]; + uint16_t count; + do { + f32longname *longname = (f32longname*)&buffer[i]; + i += sizeof(f32longname); + count++; + } while (buffer[i + 0xB] == 0xF); + parse_longnames(first_longname, count, filename); + } entry = (f32file_entry *)&buffer[i]; - void *result = handler(this, entry, seek); + if (!long_name){ + parse_shortnames(entry, filename); + } + i+= sizeof(f32file_entry) - 1; + void *result = handler(this, entry, filename, seek); if (result) return result; - i+= sizeof(f32file_entry) - 1; } return 0; @@ -57,17 +102,28 @@ void* FAT32FS::list_directory(uint32_t cluster_count, uint32_t root_index) { for (uint64_t i = 0; i < cluster_size * 512; i++) { char c = buffer[i]; - entry = (f32file_entry *)&buffer[i]; count++; - - bool ext_found = false; - for (int j = 0; j < 11 && entry->filename[j]; j++){ - if (entry->filename[j] != ' ') - *write_ptr++ = entry->filename[j]; - else if (!ext_found){ - *write_ptr++ = '.'; - ext_found = true; - } + bool long_name = buffer[i + 0xB] == 0xF; + char filename[255]; + if (long_name){ + uint8_t order; + f32longname *first_longname = (f32longname*)&buffer[i]; + uint16_t count; + do { + f32longname *longname = (f32longname*)&buffer[i]; + i += sizeof(f32longname); + count++; + } while (buffer[i + 0xB] == 0xF); + parse_longnames(first_longname, count, filename); + } + entry = (f32file_entry *)&buffer[i]; + if (!long_name){ + parse_shortnames(entry, filename); + } + char *f = filename; + while (*f) { + *write_ptr++ = *f; + f++; } *write_ptr++ = '\0'; i += sizeof(f32file_entry) - 1; @@ -130,20 +186,9 @@ bool FAT32FS::init(){ return true; } -void* FAT32FS::read_entry_handler(FAT32FS *instance, f32file_entry *entry, char *seek) { - char filename[11]; +void* FAT32FS::read_entry_handler(FAT32FS *instance, f32file_entry *entry, char *filename, char *seek) { if (entry->flags.volume_id) return 0; - int j = 0; - bool ext_found = false; - for (int i = 0; i < 11 && entry->filename[i]; i++){ - if (entry->filename[i] != ' ') - filename[j++] = entry->filename[i]; - else if (!ext_found){ - filename[j++] = '.'; - ext_found = true; - } - } - filename[j++] = '\0'; + bool is_last = *instance->advance_path(seek) == '\0'; if (!is_last && strstart(seek, filename, true) == 0) return 0; if (is_last && strcmp(seek, filename, true) != 0) return 0; @@ -165,10 +210,10 @@ void* FAT32FS::read_file(char *path){ return walk_directory(1, mbs->first_cluster_of_root_directory, path, read_entry_handler); } -void* FAT32FS::list_entries_handler(FAT32FS *instance, f32file_entry *entry, char *seek) { +void* FAT32FS::list_entries_handler(FAT32FS *instance, f32file_entry *entry, char *filename, char *seek) { if (entry->flags.volume_id) return 0; - if (strstart(seek, entry->filename, true) == 0) return 0; + if (strstart(seek, filename, true) == 0) return 0; bool is_last = *instance->advance_path(seek) == '\0'; diff --git a/kernel/filesystem/fat32.hpp b/kernel/filesystem/fat32.hpp index dbbfede3..d7650f0f 100644 --- a/kernel/filesystem/fat32.hpp +++ b/kernel/filesystem/fat32.hpp @@ -62,22 +62,20 @@ typedef struct f32file_entry { }__attribute__((packed)) f32file_entry; -// typedef struct f32longname { -// uint8_t entry_type; -// uint8_t flags; -// uint8_t rsvd; -// uint8_t name_length; -// uint16_t name_hash; -// uint16_t rsvd2; -// uint64_t valid_filesize; -// uint32_t rsvd3; -// uint32_t first_cluster; -// uint64_t filesize; -// }__attribute__((packed)) f32longname; +typedef struct f32longname { + uint8_t order; + uint16_t name1[5]; + uint8_t attribute; + uint8_t long_type; + uint8_t checksum; + uint16_t name2[6]; + uint16_t rsvd2; + uint16_t name3[2]; +}__attribute__((packed)) f32longname; class FAT32FS; -typedef void* (*f32_entry_handler)(FAT32FS *instance, f32file_entry*, char *seek); +typedef void* (*f32_entry_handler)(FAT32FS *instance, f32file_entry*, char *filename, char *seek); class FAT32FS { public: @@ -98,6 +96,9 @@ class FAT32FS { uint32_t cluster_count; uint32_t data_start_sector; - static void* read_entry_handler(FAT32FS *instance, f32file_entry *entry, char *seek); - static void* list_entries_handler(FAT32FS *instance, f32file_entry *entry, char *seek); + static void* read_entry_handler(FAT32FS *instance, f32file_entry *entry, char *filename, char *seek); + static void* list_entries_handler(FAT32FS *instance, f32file_entry *entry, char *filename, char *seek); + + void parse_longnames(f32longname entries[], uint16_t count, char* out); + void parse_shortnames(f32file_entry* entry, char* out); }; \ No newline at end of file From 0129912e42dbd88ed422fb70872f29d0b7ab4614 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 4 Jul 2025 00:00:00 +0000 Subject: [PATCH 57/79] Ignoring fx --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b40b9743..24a9643d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ libshared.a *.a dump.dtb +fs From 21a9c3b86bebde3d0d75b6aef0c31cc7b7e76bc1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 4 Jul 2025 00:00:00 +0000 Subject: [PATCH 58/79] Making image a power of 2 for SD card support --- createfs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/createfs b/createfs index 9a4a6f6f..bb5878f2 100755 --- a/createfs +++ b/createfs @@ -16,8 +16,19 @@ else SIZE_KB=$(du -s -B1 "$FOLDER" | awk '{print int($1/1024)}') fi +power_of_two() { + local n=$1 + local p=1 + while (( p < n )); do + (( p *= 2 )) + done + echo $p +} + SIZE_MB=$(( (SIZE_KB * 12 / 10 + 1023) / 1024 )) +SIZE_MB=$(power_of_two "$SIZE_MB") + if ((SIZE_MB < 64)); then SIZE_MB=64 fi From 2fd3ce70b049b827eb151859d2645b5159dd6a9b Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 4 Jul 2025 00:00:00 +0000 Subject: [PATCH 59/79] Parsing multiple clusters as if they were one --- kernel/filesystem/fat32.cpp | 41 ++++++++++++++++++++++++------------- kernel/filesystem/fat32.hpp | 7 +++++-- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index 84f08d35..2b9c6802 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -14,7 +14,6 @@ char* FAT32FS::advance_path(char *path){ } void* FAT32FS::read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint32_t root_index){ - uint32_t count = cluster_count * cluster_size; uint32_t lba = cluster_start + ((root_index - 2) * cluster_size); @@ -22,8 +21,15 @@ void* FAT32FS::read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint3 void* buffer = (char*)allocate_in_page(fs_page, cluster_count * cluster_size * 512, ALIGN_64B, true, true); - if (count > 0) - disk_read(buffer, lba, count); + if (cluster_count > 0){ + uint32_t next_index = root_index; + for (int i = 0; i < cluster_count; i++){ + kprintf("Cluster %i = %x (%x)",i,next_index,(cluster_start + ((next_index - 2) * cluster_size)) * 512); + disk_read(buffer + (i * cluster_size * 512), cluster_start + ((next_index - 2) * cluster_size), cluster_size); + next_index = fat[next_index]; + // if (next_index >= 0x0FFFFFF8) return buffer; + } + } return buffer; } @@ -71,7 +77,6 @@ void* FAT32FS::walk_directory(uint32_t cluster_count, uint32_t root_index, char f32longname *first_longname = (f32longname*)&buffer[i]; uint16_t count; do { - f32longname *longname = (f32longname*)&buffer[i]; i += sizeof(f32longname); count++; } while (buffer[i + 0xB] == 0xF); @@ -110,7 +115,6 @@ void* FAT32FS::list_directory(uint32_t cluster_count, uint32_t root_index) { f32longname *first_longname = (f32longname*)&buffer[i]; uint16_t count; do { - f32longname *longname = (f32longname*)&buffer[i]; i += sizeof(f32longname); count++; } while (buffer[i + 0xB] == 0xF); @@ -146,12 +150,19 @@ void* FAT32FS::read_full_file(uint32_t cluster_start, uint32_t cluster_size, uin } void FAT32FS::read_FAT(uint32_t location, uint32_t size, uint8_t count){ - // kprintf("FAT: %x (%x)",location*512,size * count * 512); - uint32_t* fat = (uint32_t*)allocate_in_page(fs_page, size * count * 512, ALIGN_64B, true, true); + fat = (uint32_t*)allocate_in_page(fs_page, size * count * 512, ALIGN_64B, true, true); disk_read((void*)fat, location, size); - uint32_t total_entries = (size * count * 512) / 4; - // for (uint32_t i = 0; i < total_entries; i++) - // if (fat[i] != 0) kprintf("[%i] = %x", i, fat[i]); + total_fat_entries = (size * count * 512) / 4; +} + +uint32_t FAT32FS::count_FAT(uint32_t first){ + uint32_t entry = fat[first]; + int count = 1; + while (entry < 0x0FFFFFF8){ + entry = fat[entry]; + count++; + } + return count; } bool FAT32FS::init(){ @@ -197,7 +208,7 @@ void* FAT32FS::read_entry_handler(FAT32FS *instance, f32file_entry *entry, char uint32_t bps = instance->mbs->bytes_per_sector; uint32_t spc = instance->mbs->sectors_per_cluster; uint32_t bpc = bps * spc; - uint32_t count = max(1,(entry->filesize + bpc - 1) / bpc); + uint32_t count = entry->filesize > 0 ? ((entry->filesize + bpc - 1) / bpc) : instance->count_FAT(filecluster); return entry->flags.directory ? instance->walk_directory(count, filecluster, instance->advance_path(seek), read_entry_handler) @@ -222,9 +233,9 @@ void* FAT32FS::list_entries_handler(FAT32FS *instance, f32file_entry *entry, cha uint32_t bps = instance->mbs->bytes_per_sector; uint32_t spc = instance->mbs->sectors_per_cluster; uint32_t bpc = bps * spc; - uint32_t count = max(1,(entry->filesize + bpc - 1) / bpc); + uint32_t count = instance->count_FAT(filecluster); - // kprintf("Now handling %s. Last %i",(uintptr_t)seek, is_last); + kprintf("Final count %i", count); if (is_last) return instance->list_directory(count, filecluster); if (entry->flags.directory) return instance->walk_directory(count, filecluster, instance->advance_path(seek), list_entries_handler); @@ -234,5 +245,7 @@ void* FAT32FS::list_entries_handler(FAT32FS *instance, f32file_entry *entry, cha string_list* FAT32FS::list_contents(char *path){ path = advance_path(path); - return (string_list*)walk_directory(1, mbs->first_cluster_of_root_directory, path, list_entries_handler); + uint32_t count = count_FAT(mbs->first_cluster_of_root_directory); + kprintf("Total clusters of root directory %i",count); + return (string_list*)walk_directory(count, mbs->first_cluster_of_root_directory, path, list_entries_handler); } \ No newline at end of file diff --git a/kernel/filesystem/fat32.hpp b/kernel/filesystem/fat32.hpp index d7650f0f..d3dcf048 100644 --- a/kernel/filesystem/fat32.hpp +++ b/kernel/filesystem/fat32.hpp @@ -80,12 +80,13 @@ typedef void* (*f32_entry_handler)(FAT32FS *instance, f32file_entry*, char *file class FAT32FS { public: bool init(); - void* read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index); void* read_file(char *path); string_list* list_contents(char *path); - + protected: + void* read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index); void read_FAT(uint32_t location, uint32_t size, uint8_t count); + uint32_t count_FAT(uint32_t first); void* list_directory(uint32_t cluster_count, uint32_t root_index); void* walk_directory(uint32_t cluster_count, uint32_t root_index, char *seek, f32_entry_handler handler); void* read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint32_t root_index); @@ -95,6 +96,8 @@ class FAT32FS { void *fs_page; uint32_t cluster_count; uint32_t data_start_sector; + uint32_t* fat; + uint32_t total_fat_entries; static void* read_entry_handler(FAT32FS *instance, f32file_entry *entry, char *filename, char *seek); static void* list_entries_handler(FAT32FS *instance, f32file_entry *entry, char *filename, char *seek); From d6dfd17b97bd1203014c450aa9ee87e12430058d Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 4 Jul 2025 00:00:00 +0000 Subject: [PATCH 60/79] Read all clusters and fixed most bugs, but crashes sometimes (probably memory corruption --- kernel/filesystem/fat32.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index 2b9c6802..b5014c95 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -27,7 +27,7 @@ void* FAT32FS::read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint3 kprintf("Cluster %i = %x (%x)",i,next_index,(cluster_start + ((next_index - 2) * cluster_size)) * 512); disk_read(buffer + (i * cluster_size * 512), cluster_start + ((next_index - 2) * cluster_size), cluster_size); next_index = fat[next_index]; - // if (next_index >= 0x0FFFFFF8) return buffer; + if (next_index >= 0x0FFFFFF8) return buffer; } } @@ -35,19 +35,23 @@ void* FAT32FS::read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint3 } void FAT32FS::parse_longnames(f32longname entries[], uint16_t count, char* out){ - uint16_t total = (5+6+2)*count; + if (count == 0) return; + uint16_t total = ((5+6+2)*count) + 1; uint16_t filename[total]; uint16_t f = 0; for (int i = count-1; i >= 0; i--){ - for (int j = 0; j < 5; j++) + for (int j = 0; j < 5; j++){ filename[f++] = entries[i].name1[j]; - for (int j = 0; j < 6; j++) + } + for (int j = 0; j < 6; j++){ filename[f++] = entries[i].name2[j]; - for (int j = 0; j < 2; j++) + } + for (int j = 0; j < 2; j++){ filename[f++] = entries[i].name3[j]; + } } filename[f++] = '\0'; - utf16tochar(filename, out, total); + utf16tochar(filename, out, f); } void FAT32FS::parse_shortnames(f32file_entry* entry, char* out){ @@ -69,13 +73,13 @@ void* FAT32FS::walk_directory(uint32_t cluster_count, uint32_t root_index, char char *buffer = (char*)read_cluster(data_start_sector, cluster_size, cluster_count, root_index); f32file_entry *entry = 0; - for (uint64_t i = 0; i < cluster_size * 512; i++) { + for (uint64_t i = 0; i < cluster_count * cluster_size * 512; i++) { bool long_name = buffer[i + 0xB] == 0xF; char filename[255]; if (long_name){ uint8_t order; f32longname *first_longname = (f32longname*)&buffer[i]; - uint16_t count; + uint16_t count = 0; do { i += sizeof(f32longname); count++; @@ -105,7 +109,7 @@ void* FAT32FS::list_directory(uint32_t cluster_count, uint32_t root_index) { char *write_ptr = (char*)list_buffer + 4; - for (uint64_t i = 0; i < cluster_size * 512; i++) { + for (uint64_t i = 0; i < cluster_count * cluster_size * 512; i++) { char c = buffer[i]; count++; bool long_name = buffer[i + 0xB] == 0xF; @@ -113,7 +117,7 @@ void* FAT32FS::list_directory(uint32_t cluster_count, uint32_t root_index) { if (long_name){ uint8_t order; f32longname *first_longname = (f32longname*)&buffer[i]; - uint16_t count; + uint16_t count = 0; do { i += sizeof(f32longname); count++; From 89348cb0fcf0993bba780e7dd3ee214d4ed69109 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 4 Jul 2025 00:00:00 +0000 Subject: [PATCH 61/79] Read file fix --- kernel/filesystem/fat32.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index b5014c95..cc38f9b0 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -38,6 +38,7 @@ void FAT32FS::parse_longnames(f32longname entries[], uint16_t count, char* out){ if (count == 0) return; uint16_t total = ((5+6+2)*count) + 1; uint16_t filename[total]; + memset(filename, 0, sizeof(filename)); uint16_t f = 0; for (int i = count-1; i >= 0; i--){ for (int j = 0; j < 5; j++){ @@ -222,7 +223,8 @@ void* FAT32FS::read_entry_handler(FAT32FS *instance, f32file_entry *entry, char void* FAT32FS::read_file(char *path){ path = advance_path(path); - return walk_directory(1, mbs->first_cluster_of_root_directory, path, read_entry_handler); + uint32_t count = count_FAT(mbs->first_cluster_of_root_directory); + return walk_directory(count, mbs->first_cluster_of_root_directory, path, read_entry_handler); } void* FAT32FS::list_entries_handler(FAT32FS *instance, f32file_entry *entry, char *filename, char *seek) { From ddefae721924b247041039ddd9a45a8ff00c139f Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 4 Jul 2025 00:00:00 +0000 Subject: [PATCH 62/79] Fixing unaligned access (amazing work as always microsoft) --- kernel/filesystem/fat32.cpp | 25 ++++++++++++++++++------- kernel/filesystem/fat32.hpp | 1 + shared/std/string.c | 9 ++++----- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index cc38f9b0..4b982339 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -41,14 +41,15 @@ void FAT32FS::parse_longnames(f32longname entries[], uint16_t count, char* out){ memset(filename, 0, sizeof(filename)); uint16_t f = 0; for (int i = count-1; i >= 0; i--){ + uint8_t* buffer = (uint8_t*)&entries[i]; for (int j = 0; j < 5; j++){ - filename[f++] = entries[i].name1[j]; + filename[f++] = (buffer[1+(j*2)] << 8) | buffer[1+(j*2) + 1]; } for (int j = 0; j < 6; j++){ - filename[f++] = entries[i].name2[j]; + filename[f++] = (buffer[14+(j*2)] << 8) | buffer[1+(j*2) + 1]; } for (int j = 0; j < 2; j++){ - filename[f++] = entries[i].name3[j]; + filename[f++] = (buffer[18+(j*2)] << 8) | buffer[1+(j*2) + 1]; } } filename[f++] = '\0'; @@ -170,6 +171,12 @@ uint32_t FAT32FS::count_FAT(uint32_t first){ return count; } +uint16_t read_unaligned16(const uint8_t *p) { + return (uint16_t)p[0] | ((uint16_t)p[1] << 8); +} + +#define MBS_NUM_SECTORS read_unaligned16(mbs8 + 0x13) + bool FAT32FS::init(){ fs_page = alloc_page(0x1000, true, true, false); @@ -186,7 +193,9 @@ bool FAT32FS::init(){ return false; } - cluster_count = (mbs->num_sectors == 0 ? mbs->large_num_sectors : mbs->num_sectors)/mbs->sectors_per_cluster; + uint8_t *mbs8 = (uint8_t*)mbs; + + cluster_count = (MBS_NUM_SECTORS == 0 ? mbs->large_num_sectors : MBS_NUM_SECTORS)/mbs->sectors_per_cluster; data_start_sector = mbs->reserved_sectors + (mbs->sectors_per_fat * mbs->number_of_fats); if (mbs->first_cluster_of_root_directory > cluster_count){ @@ -194,7 +203,9 @@ bool FAT32FS::init(){ return false; } - kprintf("FAT32 Volume uses %i cluster size", mbs->bytes_per_sector); + bytes_per_sector = read_unaligned16(mbs8 + 0xB); + + kprintf("FAT32 Volume uses %i cluster size", bytes_per_sector); kprintf("Data start at %x",data_start_sector*512); read_FAT(mbs->reserved_sectors, mbs->sectors_per_fat, mbs->number_of_fats); @@ -210,7 +221,7 @@ void* FAT32FS::read_entry_handler(FAT32FS *instance, f32file_entry *entry, char if (is_last && strcmp(seek, filename, true) != 0) return 0; uint32_t filecluster = (entry->hi_first_cluster << 16) | entry->lo_first_cluster; - uint32_t bps = instance->mbs->bytes_per_sector; + uint32_t bps = instance->bytes_per_sector; uint32_t spc = instance->mbs->sectors_per_cluster; uint32_t bpc = bps * spc; uint32_t count = entry->filesize > 0 ? ((entry->filesize + bpc - 1) / bpc) : instance->count_FAT(filecluster); @@ -236,7 +247,7 @@ void* FAT32FS::list_entries_handler(FAT32FS *instance, f32file_entry *entry, cha uint32_t filecluster = (entry->hi_first_cluster << 16) | entry->lo_first_cluster; - uint32_t bps = instance->mbs->bytes_per_sector; + uint32_t bps = instance->bytes_per_sector; uint32_t spc = instance->mbs->sectors_per_cluster; uint32_t bpc = bps * spc; uint32_t count = instance->count_FAT(filecluster); diff --git a/kernel/filesystem/fat32.hpp b/kernel/filesystem/fat32.hpp index d3dcf048..b7a2177d 100644 --- a/kernel/filesystem/fat32.hpp +++ b/kernel/filesystem/fat32.hpp @@ -98,6 +98,7 @@ class FAT32FS { uint32_t data_start_sector; uint32_t* fat; uint32_t total_fat_entries; + uint16_t bytes_per_sector; static void* read_entry_handler(FAT32FS *instance, f32file_entry *entry, char *filename, char *seek); static void* list_entries_handler(FAT32FS *instance, f32file_entry *entry, char *filename, char *seek); diff --git a/shared/std/string.c b/shared/std/string.c index a36cc437..b0ee1623 100644 --- a/shared/std/string.c +++ b/shared/std/string.c @@ -285,12 +285,11 @@ bool strcont( char *a, char *b) { bool utf16tochar( uint16_t* str_in, char* out_str, size_t max_len) { size_t out_i = 0; - while (str_in[out_i] != 0 && out_i + 1 < max_len) { - uint16_t wc = str_in[out_i]; - out_str[out_i] = (wc <= 0x7F) ? (char)wc : '?'; - out_i++; + for (int i = 0; i < max_len && str_in[i]; i++){ + uint16_t wc = str_in[i]; + out_str[out_i++] = (wc <= 0x7F) ? (char)(wc & 0xFF) : '?'; } - out_str[out_i] = '\0'; + out_str[out_i++] = '\0'; return true; } From 253d527853dc363829e9ba30d3ead317c76d5cae Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 4 Jul 2025 00:00:00 +0000 Subject: [PATCH 63/79] 0 and E5 (unused/deleted) support --- kernel/filesystem/fat32.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index 4b982339..0d4cf265 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -75,7 +75,12 @@ void* FAT32FS::walk_directory(uint32_t cluster_count, uint32_t root_index, char char *buffer = (char*)read_cluster(data_start_sector, cluster_size, cluster_count, root_index); f32file_entry *entry = 0; - for (uint64_t i = 0; i < cluster_count * cluster_size * 512; i++) { + for (uint64_t i = 0; i < cluster_count * cluster_size * 512;) { + if (buffer[i] == 0) return 0; + if (buffer[i] == 0xE5){ + i += sizeof(f32file_entry); + continue; + } bool long_name = buffer[i + 0xB] == 0xF; char filename[255]; if (long_name){ @@ -92,10 +97,10 @@ void* FAT32FS::walk_directory(uint32_t cluster_count, uint32_t root_index, char if (!long_name){ parse_shortnames(entry, filename); } - i+= sizeof(f32file_entry) - 1; void *result = handler(this, entry, filename, seek); if (result) return result; + i += sizeof(f32file_entry); } return 0; @@ -111,7 +116,12 @@ void* FAT32FS::list_directory(uint32_t cluster_count, uint32_t root_index) { char *write_ptr = (char*)list_buffer + 4; - for (uint64_t i = 0; i < cluster_count * cluster_size * 512; i++) { + for (uint64_t i = 0; i < cluster_count * cluster_size * 512;) { + if (buffer[i] == 0) break; + if (buffer[i] == 0xE5){ + i += sizeof(f32file_entry); + continue; + } char c = buffer[i]; count++; bool long_name = buffer[i + 0xB] == 0xF; @@ -136,7 +146,7 @@ void* FAT32FS::list_directory(uint32_t cluster_count, uint32_t root_index) { f++; } *write_ptr++ = '\0'; - i += sizeof(f32file_entry) - 1; + i += sizeof(f32file_entry); } *(uint32_t*)list_buffer = count; From 065c0b9df6de4f9d2695b761fb42f4e86ff36273 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 4 Jul 2025 00:00:00 +0000 Subject: [PATCH 64/79] Fixed occasional long filename crash --- kernel/filesystem/fat32.cpp | 27 +++++++++++++++++---------- kernel/filesystem/fat32.hpp | 2 ++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index 0d4cf265..b51264c3 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -6,6 +6,14 @@ #include "std/memfunctions.h" #include "math/math.h" +#define kprintfv(fmt, ...) \ + ({ \ + if (verbose){\ + uint64_t _args[] = { __VA_ARGS__ }; \ + kprintf_args((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ + }\ + }) + char* FAT32FS::advance_path(char *path){ while (*path != '/' && *path != '\0') path++; @@ -17,14 +25,14 @@ void* FAT32FS::read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint3 uint32_t lba = cluster_start + ((root_index - 2) * cluster_size); - kprintf("Reading cluster(s) %i-%i, starting from %i (LBA %i) Address %x", root_index, root_index+cluster_count, cluster_start, lba, lba * 512); + kprintfv("Reading cluster(s) %i-%i, starting from %i (LBA %i) Address %x", root_index, root_index+cluster_count, cluster_start, lba, lba * 512); void* buffer = (char*)allocate_in_page(fs_page, cluster_count * cluster_size * 512, ALIGN_64B, true, true); if (cluster_count > 0){ uint32_t next_index = root_index; for (int i = 0; i < cluster_count; i++){ - kprintf("Cluster %i = %x (%x)",i,next_index,(cluster_start + ((next_index - 2) * cluster_size)) * 512); + kprintfv("Cluster %i = %x (%x)",i,next_index,(cluster_start + ((next_index - 2) * cluster_size)) * 512); disk_read(buffer + (i * cluster_size * 512), cluster_start + ((next_index - 2) * cluster_size), cluster_size); next_index = fat[next_index]; if (next_index >= 0x0FFFFFF8) return buffer; @@ -37,11 +45,10 @@ void* FAT32FS::read_cluster(uint32_t cluster_start, uint32_t cluster_size, uint3 void FAT32FS::parse_longnames(f32longname entries[], uint16_t count, char* out){ if (count == 0) return; uint16_t total = ((5+6+2)*count) + 1; - uint16_t filename[total]; - memset(filename, 0, sizeof(filename)); + uint16_t *filename = (uint16_t*)allocate_in_page(fs_page, total*2, ALIGN_64B, true, true); uint16_t f = 0; for (int i = count-1; i >= 0; i--){ - uint8_t* buffer = (uint8_t*)&entries[i]; + uint8_t *buffer = (uint8_t*)&entries[i]; for (int j = 0; j < 5; j++){ filename[f++] = (buffer[1+(j*2)] << 8) | buffer[1+(j*2) + 1]; } @@ -54,6 +61,7 @@ void FAT32FS::parse_longnames(f32longname entries[], uint16_t count, char* out){ } filename[f++] = '\0'; utf16tochar(filename, out, f); + free_from_page(filename, total*2); } void FAT32FS::parse_shortnames(f32file_entry* entry, char* out){ @@ -82,7 +90,7 @@ void* FAT32FS::walk_directory(uint32_t cluster_count, uint32_t root_index, char continue; } bool long_name = buffer[i + 0xB] == 0xF; - char filename[255]; + char *filename = (char*)allocate_in_page(fs_page, 255, ALIGN_64B, true, true); if (long_name){ uint8_t order; f32longname *first_longname = (f32longname*)&buffer[i]; @@ -98,6 +106,7 @@ void* FAT32FS::walk_directory(uint32_t cluster_count, uint32_t root_index, char parse_shortnames(entry, filename); } void *result = handler(this, entry, filename, seek); + free_from_page(filename, 255); if (result) return result; i += sizeof(f32file_entry); @@ -125,7 +134,7 @@ void* FAT32FS::list_directory(uint32_t cluster_count, uint32_t root_index) { char c = buffer[i]; count++; bool long_name = buffer[i + 0xB] == 0xF; - char filename[255]; + char *filename = (char*)allocate_in_page(fs_page, 255, ALIGN_64B, true, true); if (long_name){ uint8_t order; f32longname *first_longname = (f32longname*)&buffer[i]; @@ -146,6 +155,7 @@ void* FAT32FS::list_directory(uint32_t cluster_count, uint32_t root_index) { f++; } *write_ptr++ = '\0'; + free_from_page(filename, 255); i += sizeof(f32file_entry); } @@ -262,8 +272,6 @@ void* FAT32FS::list_entries_handler(FAT32FS *instance, f32file_entry *entry, cha uint32_t bpc = bps * spc; uint32_t count = instance->count_FAT(filecluster); - kprintf("Final count %i", count); - if (is_last) return instance->list_directory(count, filecluster); if (entry->flags.directory) return instance->walk_directory(count, filecluster, instance->advance_path(seek), list_entries_handler); return 0; @@ -273,6 +281,5 @@ string_list* FAT32FS::list_contents(char *path){ path = advance_path(path); uint32_t count = count_FAT(mbs->first_cluster_of_root_directory); - kprintf("Total clusters of root directory %i",count); return (string_list*)walk_directory(count, mbs->first_cluster_of_root_directory, path, list_entries_handler); } \ No newline at end of file diff --git a/kernel/filesystem/fat32.hpp b/kernel/filesystem/fat32.hpp index b7a2177d..b142535e 100644 --- a/kernel/filesystem/fat32.hpp +++ b/kernel/filesystem/fat32.hpp @@ -105,4 +105,6 @@ class FAT32FS { void parse_longnames(f32longname entries[], uint16_t count, char* out); void parse_shortnames(f32file_entry* entry, char* out); + + bool verbose = false; }; \ No newline at end of file From 3eda8249e10525632d96db254c6b7558a9c24771 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 5 Jul 2025 00:00:00 +0000 Subject: [PATCH 65/79] Default to virtio for qemu --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index dbb8a070..842d5e13 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -MODE ?= rpi +MODE ?= virtio .PHONY: all kernel user shared clean rpi virtio debugrpi debugvirtio run debug From 6a7335a084e5e3f1dc5c2bdb8049254370e52aca Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 7 Jul 2025 00:00:00 +0000 Subject: [PATCH 66/79] (hypothetical) rpi5 support --- kernel/console/serial/uart.c | 7 +++++++ kernel/filesystem/sdhci.cpp | 2 +- kernel/gpio.c | 14 ++++++++++++++ kernel/gpio.h | 6 ++++++ kernel/hw/hw.c | 32 +++++++++++++++++++++----------- kernel/hw/hw.h | 4 ++++ 6 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 kernel/gpio.c create mode 100644 kernel/gpio.h diff --git a/kernel/console/serial/uart.c b/kernel/console/serial/uart.c index 3173a7b0..1427062d 100644 --- a/kernel/console/serial/uart.c +++ b/kernel/console/serial/uart.c @@ -1,6 +1,8 @@ #include "console/serial/uart.h" #include "memory/memory_access.h" #include "exceptions/irq.h" +#include "gpio.h" +#include "hw/hw.h" #define UART0_DR (UART0_BASE + 0x00) #define UART0_FR (UART0_BASE + 0x18) @@ -16,6 +18,11 @@ uint64_t get_uart_base(){ void enable_uart() { write32(UART0_CR, 0x0); + if (BOARD_TYPE == 2){ + enable_gpio_pin(14); + enable_gpio_pin(15); + } + write32(UART0_IBRD, 1); write32(UART0_FBRD, 40); diff --git a/kernel/filesystem/sdhci.cpp b/kernel/filesystem/sdhci.cpp index c19432ef..917196ca 100644 --- a/kernel/filesystem/sdhci.cpp +++ b/kernel/filesystem/sdhci.cpp @@ -143,7 +143,7 @@ bool SDHCI::init() { regs->ctrl1 |= (1 << 24);//Reset if (!wait(®s->ctrl1,(1 << 24), false, 2000)) return false; - if (RPI_BOARD == 4){ + if (RPI_BOARD >= 4){ regs->ctrl0 |= 0x0F << 8;//VDD1 bus power delay(3); } diff --git a/kernel/gpio.c b/kernel/gpio.c new file mode 100644 index 00000000..b8ae7656 --- /dev/null +++ b/kernel/gpio.c @@ -0,0 +1,14 @@ +#include "gpio.h" +#include "hw/hw.h" +#include "async.h" +#include "memory/memory_access.h" + +void reset_gpio(){ + write32(GPIO_BASE + GPIO_PIN_BASE + 0x94, 0x0); + delay(150); +} + +void enable_gpio_pin(uint8_t pin){ + uint32_t v = read32(GPIO_BASE + GPIO_PIN_BASE + 0x98); + write32(GPIO_BASE + GPIO_PIN_BASE + 0x98, v | (1 << pin)); +} \ No newline at end of file diff --git a/kernel/gpio.h b/kernel/gpio.h new file mode 100644 index 00000000..8b50b0a0 --- /dev/null +++ b/kernel/gpio.h @@ -0,0 +1,6 @@ +#pragma once + +#include "types.h" + +void reset_gpio(); +void enable_gpio_pin(uint8_t pin); \ No newline at end of file diff --git a/kernel/hw/hw.c b/kernel/hw/hw.c index d28418da..0067a6b6 100644 --- a/kernel/hw/hw.c +++ b/kernel/hw/hw.c @@ -1,5 +1,6 @@ #include "hw.h" #include "console/kio.h" +#include "gpio.h" uint8_t BOARD_TYPE; uint8_t USE_DTB = 0; @@ -16,6 +17,8 @@ uintptr_t GICC_BASE = 0; uintptr_t SDHCI_BASE = 0; uint8_t RPI_BOARD; +uint8_t GPIO_BASE; +uint8_t GPIO_PIN_BASE; void detect_hardware(){ if (BOARD_TYPE == 1){ @@ -31,24 +34,31 @@ void detect_hardware(){ } else { uint32_t reg; asm volatile ("mrs %x0, midr_el1" : "=r" (reg)); - //We can detect if we're running on 0x400.... to know if we're in virt. And 41 vs 40 to know if we're in img or elf uint32_t raspi = (reg >> 4) & 0xFFF; switch (raspi) { - case 0xD08: + case 0xD08: //4B. Cortex A72 MMIO_BASE = 0xFE000000; - GICD_BASE = 0xff841000; - GICC_BASE = 0xff842000; RPI_BOARD = 4; + GPIO_PIN_BASE = 0x50; + break; + case 0xD0B: //5. Cortex A76 + MMIO_BASE = 0x107C000000UL; + RPI_BOARD = 5; + GPIO_PIN_BASE = 0x50; break; default: MMIO_BASE = 0x3F000000; break; } - UART0_BASE = MMIO_BASE + 0x201000; - SDHCI_BASE = MMIO_BASE + 0x300000; - XHCI_BASE = MMIO_BASE + 0x9C0000; - RAM_START = 0x10000000; - CRAM_END = (MMIO_BASE - 0x10000000) & 0xF0000000; - RAM_START = 0x10000000; - CRAM_START = 0x13600000; + GPIO_BASE = MMIO_BASE + 0x200000; + GICD_BASE = MMIO_BASE + 0x1841000; + GICC_BASE = MMIO_BASE + 0x1842000; + UART0_BASE = MMIO_BASE + 0x201000; + SDHCI_BASE = MMIO_BASE + 0x300000; + XHCI_BASE = MMIO_BASE + 0x9C0000; + RAM_START = 0x10000000; + CRAM_END = (MMIO_BASE - 0x10000000) & 0xF0000000; + RAM_START = 0x10000000; + CRAM_START = 0x13600000; + reset_gpio(); } } diff --git a/kernel/hw/hw.h b/kernel/hw/hw.h index 767cbe1c..7633c348 100644 --- a/kernel/hw/hw.h +++ b/kernel/hw/hw.h @@ -23,6 +23,10 @@ extern uintptr_t GICC_BASE; extern uintptr_t SDHCI_BASE; +extern uint8_t GPIO_BASE; + +extern uint8_t GPIO_PIN_BASE; + extern uint8_t RPI_BOARD; void detect_hardware(); From 2ca1a4bf289c6e755c4b19e22fbea8f60ca2d691 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 7 Jul 2025 00:00:00 +0000 Subject: [PATCH 67/79] Check EL level before switching --- kernel/boot.S | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kernel/boot.S b/kernel/boot.S index 940ce31f..cc4b195d 100644 --- a/kernel/boot.S +++ b/kernel/boot.S @@ -54,6 +54,11 @@ rpi: b drop_el3 drop_el3: + mrs x0, CurrentEL + lsr x0, x0, #2 + cmp x0, #3 + b.ne el2_entry + msr sctlr_el2, xzr mrs x0, hcr_el2 orr x0, x0, #(1<<19) @@ -72,6 +77,11 @@ drop_el3: eret el2_entry: + mrs x0, CurrentEL + lsr x0, x0, #2 + cmp x0, #2 + b.ne el1_non_secure + mov x0, #3 << 20 msr cpacr_el1, x0 From 6ae0e95dbc0476440232a4a941458d1992b8dae0 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 7 Jul 2025 00:00:00 +0000 Subject: [PATCH 68/79] rpi runs the .img by default --- kernel/kernel.c | 2 +- run_rpi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/kernel.c b/kernel/kernel.c index b5cc82ec..e06eb58b 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -25,7 +25,7 @@ void kernel_main() { mmu_alloc(); // mmu_enable_verbose(); enable_uart(); - kprintf("UART output enabled"); + kprintf_l("UART output enabled"); // enable_talloc_verbose(); set_exception_vectors(); diff --git a/run_rpi b/run_rpi index c3eeaa7b..3b6c756e 100755 --- a/run_rpi +++ b/run_rpi @@ -22,7 +22,7 @@ fi $PRIVILEGE qemu-system-aarch64 \ -M raspi4b \ --kernel kernel.elf \ +-kernel kernel.img \ -display sdl \ -device sd-card,drive=sd -drive id=sd,format=raw,file=disk.img,if=none \ -netdev $NETARG \ From fbc2f58866ddc03a5e4d5a2488824931c0d06ac9 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 7 Jul 2025 00:00:00 +0000 Subject: [PATCH 69/79] Changed names of boards to raspi and virt --- Makefile | 8 ++++---- run_rpi => run_raspi | 0 run_virtio => run_virt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename run_rpi => run_raspi (100%) rename run_virtio => run_virt (96%) diff --git a/Makefile b/Makefile index 842d5e13..084366e5 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -MODE ?= virtio +MODE ?= virt -.PHONY: all kernel user shared clean rpi virtio debugrpi debugvirtio run debug +.PHONY: all kernel user shared clean raspi virt run debug all: shared user kernel @echo "Build complete." @@ -20,10 +20,10 @@ clean: $(MAKE) -C kernel clean $(MAKE) -C user clean -rpi: +raspi: $(MAKE) LOAD_ADDR=0x80000 all -virtio: +virt: $(MAKE) LOAD_ADDR=0x41000000 all debug: diff --git a/run_rpi b/run_raspi similarity index 100% rename from run_rpi rename to run_raspi diff --git a/run_virtio b/run_virt similarity index 96% rename from run_virtio rename to run_virt index 3e1101f1..25663d9f 100755 --- a/run_virtio +++ b/run_virt @@ -1,6 +1,6 @@ #/!bin/sh -echo "Running virtio emulator" +echo "Running virt emulator" ARGS="" if [ "$1" = "debug" ]; then From e8f82fca2db5a5e59965773296432a71628b1c03 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 7 Jul 2025 00:00:00 +0000 Subject: [PATCH 70/79] Updated github action --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 53b1ccea..a0c5d73c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,7 +44,7 @@ jobs: - name: Build run: | mkdir -pv fs/redos/user - make all + make run MODE=virt - name: Upload artifacts uses: actions/upload-artifact@v4 From 3c37dd612f3156766768606a15d85bdeb4769d16 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 8 Jul 2025 00:00:00 +0000 Subject: [PATCH 71/79] Unified the mark_dirty functions under draw.c NOTE: bug with draw_pixel, mark_dirty must be called from outside the function --- kernel/graph/drivers/ramfb_driver/ramfb.cpp | 43 +----------- kernel/graph/drivers/ramfb_driver/ramfb.hpp | 7 -- kernel/graph/drivers/videocore/videocore.cpp | 47 +------------ kernel/graph/drivers/videocore/videocore.hpp | 8 --- .../drivers/virtio_gpu_pci/virtio_gpu_pci.cpp | 60 +---------------- .../drivers/virtio_gpu_pci/virtio_gpu_pci.hpp | 8 --- shared/ui/draw/draw.c | 67 ++++++++++++++++++- shared/ui/draw/draw.h | 13 +++- 8 files changed, 83 insertions(+), 170 deletions(-) diff --git a/kernel/graph/drivers/ramfb_driver/ramfb.cpp b/kernel/graph/drivers/ramfb_driver/ramfb.cpp index dec71dbb..ad133dc0 100644 --- a/kernel/graph/drivers/ramfb_driver/ramfb.cpp +++ b/kernel/graph/drivers/ramfb_driver/ramfb.cpp @@ -98,8 +98,7 @@ void RamFBGPUDriver::flush(){ } void RamFBGPUDriver::clear(color color){ - fb_clear((uint32_t*)back_framebuffer, screen_size.width, screen_size.height, color); - mark_dirty(0,0,screen_size.width,screen_size.height); + fb_clear((uint32_t*)back_framebuffer, color); } void RamFBGPUDriver::draw_pixel(uint32_t x, uint32_t y, color color){ @@ -109,17 +108,14 @@ void RamFBGPUDriver::draw_pixel(uint32_t x, uint32_t y, color color){ void RamFBGPUDriver::fill_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color){ fb_fill_rect((uint32_t*)back_framebuffer, x, y, width, height, color); - mark_dirty(x,y,width,height); } void RamFBGPUDriver::draw_line(uint32_t x0, uint32_t y0, uint32_t x1,uint32_t y1, color color){ gpu_rect rect = fb_draw_line((uint32_t*)framebuffer, x0, y0, x1, y1, color); - mark_dirty(rect.point.x,rect.point.y,rect.size.width,rect.size.height); } void RamFBGPUDriver::draw_char(uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color){ fb_draw_char((uint32_t*)back_framebuffer, x, y, c, scale, color); - mark_dirty(x,y,8*scale,8*scale); } gpu_size RamFBGPUDriver::get_screen_size(){ @@ -128,45 +124,8 @@ gpu_size RamFBGPUDriver::get_screen_size(){ void RamFBGPUDriver::draw_string(string s, uint32_t x, uint32_t y, uint32_t scale, uint32_t color){ gpu_size drawn_string = fb_draw_string((uint32_t*)back_framebuffer, s, x, y, scale, color); - mark_dirty(x,y,drawn_string.width,drawn_string.height); } uint32_t RamFBGPUDriver::get_char_size(uint32_t scale){ return fb_get_char_size(scale); -} - -int RamFBGPUDriver::try_merge(gpu_rect* a, gpu_rect* b) { - uint32_t ax2 = a->point.x + a->size.width; - uint32_t ay2 = a->point.y + a->size.height; - uint32_t bx2 = b->point.x + b->size.width; - uint32_t by2 = b->point.y + b->size.height; - - if (a->point.x > bx2 || b->point.x > ax2 || a->point.y > by2 || b->point.y > ay2) - return 0; - - uint32_t min_x = a->point.x < b->point.x ? a->point.x : b->point.x; - uint32_t min_y = a->point.y < b->point.y ? a->point.y : b->point.y; - uint32_t max_x = ax2 > bx2 ? ax2 : bx2; - uint32_t max_y = ay2 > by2 ? ay2 : by2; - - a->point.x = min_x; - a->point.y = min_y; - a->size.width = max_x - min_x; - a->size.height = max_y - min_y; - - return 1; -} - -void RamFBGPUDriver::mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { - gpu_rect new_rect = { x, y, w, h }; - - for (uint32_t i = 0; i < dirty_count; i++) { - if (try_merge(&dirty_rects[i], &new_rect)) - return; - } - - if (dirty_count < MAX_DIRTY_RECTS_RFB) - dirty_rects[dirty_count++] = new_rect; - else - full_redraw = true; } \ No newline at end of file diff --git a/kernel/graph/drivers/ramfb_driver/ramfb.hpp b/kernel/graph/drivers/ramfb_driver/ramfb.hpp index c0344b65..5d8352d6 100644 --- a/kernel/graph/drivers/ramfb_driver/ramfb.hpp +++ b/kernel/graph/drivers/ramfb_driver/ramfb.hpp @@ -2,8 +2,6 @@ #include "../gpu_driver.hpp" -#define MAX_DIRTY_RECTS_RFB 64 - class RamFBGPUDriver : public GPUDriver { public: static RamFBGPUDriver* try_init(gpu_size preferred_screen_size); @@ -28,10 +26,5 @@ class RamFBGPUDriver : public GPUDriver { uintptr_t back_framebuffer; uint64_t framebuffer_size; gpu_size screen_size; - gpu_rect dirty_rects[MAX_DIRTY_RECTS_RFB]; - uint32_t dirty_count = 0; - bool full_redraw = false; - int try_merge(gpu_rect* a, gpu_rect* b); - void mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h); uint32_t stride; }; \ No newline at end of file diff --git a/kernel/graph/drivers/videocore/videocore.cpp b/kernel/graph/drivers/videocore/videocore.cpp index 559d7423..44c83cc2 100644 --- a/kernel/graph/drivers/videocore/videocore.cpp +++ b/kernel/graph/drivers/videocore/videocore.cpp @@ -106,8 +106,7 @@ void VideoCoreGPUDriver::flush(){ } void VideoCoreGPUDriver::clear(color color){ - fb_clear((uint32_t*)back_framebuffer, screen_size.width, screen_size.height, color); - mark_dirty(0,0,screen_size.width,screen_size.height); + fb_clear((uint32_t*)back_framebuffer, color); } void VideoCoreGPUDriver::draw_pixel(uint32_t x, uint32_t y, color color){ @@ -117,17 +116,14 @@ void VideoCoreGPUDriver::draw_pixel(uint32_t x, uint32_t y, color color){ void VideoCoreGPUDriver::fill_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color){ fb_fill_rect((uint32_t*)back_framebuffer, x, y, width, height, color); - mark_dirty(x,y,width,height); } void VideoCoreGPUDriver::draw_line(uint32_t x0, uint32_t y0, uint32_t x1,uint32_t y1, color color){ - gpu_rect rect = fb_draw_line((uint32_t*)framebuffer, x0, y0, x1, y1, color); - mark_dirty(rect.point.x,rect.point.y,rect.size.width,rect.size.height); + fb_draw_line((uint32_t*)back_framebuffer, x0, y0, x1, y1, color); } void VideoCoreGPUDriver::draw_char(uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color){ fb_draw_char((uint32_t*)back_framebuffer, x, y, c, scale, color); - mark_dirty(x,y,8*scale,8*scale); } gpu_size VideoCoreGPUDriver::get_screen_size(){ @@ -135,46 +131,9 @@ gpu_size VideoCoreGPUDriver::get_screen_size(){ } void VideoCoreGPUDriver::draw_string(string s, uint32_t x, uint32_t y, uint32_t scale, uint32_t color){ - gpu_size drawn_string = fb_draw_string((uint32_t*)back_framebuffer, s, x, y, scale, color); - mark_dirty(x,y,drawn_string.width,drawn_string.height); + fb_draw_string((uint32_t*)back_framebuffer, s, x, y, scale, color); } uint32_t VideoCoreGPUDriver::get_char_size(uint32_t scale){ return fb_get_char_size(max(1,scale-1));//TODO: Screen resolution seems fixed at 640x480 (on QEMU at least). So we make the font smaller -} - -int VideoCoreGPUDriver::try_merge(gpu_rect* a, gpu_rect* b) { - uint32_t ax2 = a->point.x + a->size.width; - uint32_t ay2 = a->point.y + a->size.height; - uint32_t bx2 = b->point.x + b->size.width; - uint32_t by2 = b->point.y + b->size.height; - - if (a->point.x > bx2 || b->point.x > ax2 || a->point.y > by2 || b->point.y > ay2) - return 0; - - uint32_t min_x = a->point.x < b->point.x ? a->point.x : b->point.x; - uint32_t min_y = a->point.y < b->point.y ? a->point.y : b->point.y; - uint32_t max_x = ax2 > bx2 ? ax2 : bx2; - uint32_t max_y = ay2 > by2 ? ay2 : by2; - - a->point.x = min_x; - a->point.y = min_y; - a->size.width = max_x - min_x; - a->size.height = max_y - min_y; - - return 1; -} - -void VideoCoreGPUDriver::mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { - gpu_rect new_rect = { x, y, w, h }; - - for (uint32_t i = 0; i < dirty_count; i++) { - if (try_merge(&dirty_rects[i], &new_rect)) - return; - } - - if (dirty_count < MAX_DIRTY_RECTS_VCG) - dirty_rects[dirty_count++] = new_rect; - else - full_redraw = true; } \ No newline at end of file diff --git a/kernel/graph/drivers/videocore/videocore.hpp b/kernel/graph/drivers/videocore/videocore.hpp index e19b8f33..3a703551 100644 --- a/kernel/graph/drivers/videocore/videocore.hpp +++ b/kernel/graph/drivers/videocore/videocore.hpp @@ -2,8 +2,6 @@ #include "../gpu_driver.hpp" -#define MAX_DIRTY_RECTS_VCG 64 - class VideoCoreGPUDriver : public GPUDriver { public: static VideoCoreGPUDriver* try_init(gpu_size preferred_screen_size); @@ -26,15 +24,9 @@ class VideoCoreGPUDriver : public GPUDriver { gpu_size screen_size; uintptr_t framebuffer; uintptr_t back_framebuffer; - uint64_t framebuffer_size; void* page; - gpu_rect dirty_rects[MAX_DIRTY_RECTS_VCG]; - uint32_t dirty_count = 0; - bool full_redraw = false; - int try_merge(gpu_rect* a, gpu_rect* b); - void mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h); uint8_t bpp; uint32_t stride; }; \ No newline at end of file diff --git a/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp b/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp index 2e414485..f9c440e7 100644 --- a/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp +++ b/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp @@ -387,58 +387,8 @@ void VirtioGPUDriver::flush() { return; } -int VirtioGPUDriver::try_merge(gpu_rect* a, gpu_rect* b) { - uint32_t ax2 = a->point.x + a->size.width; - uint32_t ay2 = a->point.y + a->size.height; - uint32_t bx2 = b->point.x + b->size.width; - uint32_t by2 = b->point.y + b->size.height; - - if (a->point.x > bx2 || b->point.x > ax2 || a->point.y > by2 || b->point.y > ay2) - return 0; - - uint32_t min_x = a->point.x < b->point.x ? a->point.x : b->point.x; - uint32_t min_y = a->point.y < b->point.y ? a->point.y : b->point.y; - uint32_t max_x = ax2 > bx2 ? ax2 : bx2; - uint32_t max_y = ay2 > by2 ? ay2 : by2; - - a->point.x = min_x; - a->point.y = min_y; - a->size.width = max_x - min_x; - a->size.height = max_y - min_y; - - return 1; -} - -void VirtioGPUDriver::mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { - if (x >= screen_size.width || y >= screen_size.height) - return; - - if (x + w > screen_size.width) - w = screen_size.width - x; - - if (y + h > screen_size.height) - h = screen_size.height - y; - - if (w == 0 || h == 0) - return; - - gpu_rect new_rect = { x, y, w, h }; - - for (uint32_t i = 0; i < dirty_count; i++) { - if (try_merge(&dirty_rects[i], &new_rect)) - return; - } - - if (dirty_count < MAX_DIRTY_RECTS_VGP) - dirty_rects[dirty_count++] = new_rect; - else - full_redraw = true; -} - - void VirtioGPUDriver::clear(uint32_t color) { - fb_clear((uint32_t*)framebuffer, screen_size.width, screen_size.height, color); - mark_dirty(0,0,screen_size.width,screen_size.height); + fb_clear((uint32_t*)framebuffer, color); } void VirtioGPUDriver::draw_pixel(uint32_t x, uint32_t y, color color){ @@ -448,22 +398,18 @@ void VirtioGPUDriver::draw_pixel(uint32_t x, uint32_t y, color color){ void VirtioGPUDriver::fill_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color){ fb_fill_rect((uint32_t*)framebuffer, x, y, width, height, color); - mark_dirty(x,y,width,height); } void VirtioGPUDriver::draw_line(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, color color){ - gpu_rect rect = fb_draw_line((uint32_t*)framebuffer, x0, y0, x1, y1, color); - mark_dirty(rect.point.x,rect.point.y,rect.size.width,rect.size.height); + fb_draw_line((uint32_t*)framebuffer, x0, y0, x1, y1, color); } void VirtioGPUDriver::draw_char(uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color){ fb_draw_char((uint32_t*)framebuffer, x, y, c, scale, color); - mark_dirty(x,y,8*scale,8*scale); } void VirtioGPUDriver::draw_string(string s, uint32_t x, uint32_t y, uint32_t scale, uint32_t color){ - gpu_size drawn_string = fb_draw_string((uint32_t*)framebuffer, s, x, y, scale, color); - mark_dirty(x,y,drawn_string.width,drawn_string.height); + fb_draw_string((uint32_t*)framebuffer, s, x, y, scale, color); } uint32_t VirtioGPUDriver::get_char_size(uint32_t scale){ diff --git a/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.hpp b/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.hpp index a97992aa..47341c89 100644 --- a/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.hpp +++ b/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.hpp @@ -3,8 +3,6 @@ #include "virtio/virtio_pci.h" #include "../gpu_driver.hpp" -#define MAX_DIRTY_RECTS_VGP 64 - class VirtioGPUDriver : public GPUDriver { public: static VirtioGPUDriver* try_init(gpu_size preferred_screen_size); @@ -35,12 +33,6 @@ class VirtioGPUDriver : public GPUDriver { bool set_scanout(); bool transfer_to_host(gpu_rect rect); - gpu_rect dirty_rects[MAX_DIRTY_RECTS_VGP]; - uint32_t dirty_count = 0; - bool full_redraw = false; - int try_merge(gpu_rect* a, gpu_rect* b); - void mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h); - bool scanout_found; uint64_t scanout_id; }; \ No newline at end of file diff --git a/shared/ui/draw/draw.c b/shared/ui/draw/draw.c index 6b7c0d7a..eb0680b2 100644 --- a/shared/ui/draw/draw.c +++ b/shared/ui/draw/draw.c @@ -7,15 +7,70 @@ uint32_t stride = 0; uint32_t max_width, max_height; -void fb_clear(uint32_t* fb, uint32_t width, uint32_t height, uint32_t color) { - for (uint32_t i = 0; i < width * height; i++) { +gpu_rect dirty_rects[MAX_DIRTY_RECTS]; +uint32_t dirty_count = 0; +bool full_redraw = false; + +int try_merge(gpu_rect* a, gpu_rect* b) { + uint32_t ax2 = a->point.x + a->size.width; + uint32_t ay2 = a->point.y + a->size.height; + uint32_t bx2 = b->point.x + b->size.width; + uint32_t by2 = b->point.y + b->size.height; + + if (a->point.x > bx2 || b->point.x > ax2 || a->point.y > by2 || b->point.y > ay2) + return false; + + uint32_t min_x = a->point.x < b->point.x ? a->point.x : b->point.x; + uint32_t min_y = a->point.y < b->point.y ? a->point.y : b->point.y; + uint32_t max_x = ax2 > bx2 ? ax2 : bx2; + uint32_t max_y = ay2 > by2 ? ay2 : by2; + + a->point.x = min_x; + a->point.y = min_y; + a->size.width = max_x - min_x; + a->size.height = max_y - min_y; + + return true; +} + +void mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { + if (full_redraw) return; + + if (x >= max_width || y >= max_height) + return; + + if (x + w > max_width) + w = max_width - x; + + if (y + h > max_height) + h = max_height - y; + + if (w == 0 || h == 0) + return; + + gpu_rect new_rect = { x, y, w, h }; + + for (uint32_t i = 0; i < dirty_count; i++) + if (try_merge(&dirty_rects[i], &new_rect)) + return; + + if (dirty_count < MAX_DIRTY_RECTS) + dirty_rects[dirty_count++] = new_rect; + else + full_redraw = true; +} + +void fb_clear(uint32_t* fb, uint32_t color) { + for (uint32_t i = 0; i < max_width * max_height; i++) { fb[i] = color; } + full_redraw = true; } void fb_draw_pixel(uint32_t* fb, uint32_t x, uint32_t y, color color){ - if (x > max_width || y > max_height) return; + if (x >= max_width || y >= max_height) return; fb[y * (stride / 4) + x] = color; + //TODO: for some reason, calling mark_dirty from here crashes. Calling it from just outside this function does not. Something to do with merge. Need to investigate. } void fb_fill_rect(uint32_t* fb, uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color){ @@ -24,6 +79,7 @@ void fb_fill_rect(uint32_t* fb, uint32_t x, uint32_t y, uint32_t width, uint32_t fb_draw_pixel(fb, x + dx, y + dy, color); } } + mark_dirty(x,y,width,height); } gpu_rect fb_draw_line(uint32_t* fb, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, color color){ @@ -46,6 +102,8 @@ gpu_rect fb_draw_line(uint32_t* fb, uint32_t x0, uint32_t y0, uint32_t x1, uint3 int max_x = (x0 > x1) ? x0 : x1; int max_y = (y0 > y1) ? y0 : y1; + mark_dirty(min_x,min_y,max_x - min_x + 1,max_y - min_y + 1); + return (gpu_rect) { {min_x, min_y}, {max_x - min_x + 1, max_y - min_y + 1}}; } @@ -59,6 +117,7 @@ void fb_draw_char(uint32_t* fb, uint32_t x, uint32_t y, char c, uint32_t scale, } } } + mark_dirty(x,y,8*scale,8*scale); } gpu_size fb_draw_string(uint32_t* fb, string s, uint32_t x0, uint32_t y0, uint32_t scale, uint32_t color){ @@ -87,6 +146,8 @@ gpu_size fb_draw_string(uint32_t* fb, string s, uint32_t x0, uint32_t y0, uint32 if (xRowSize > xSize) xSize = xRowSize; + mark_dirty(x0,y0,xSize,ySize); + return (gpu_size){xSize,ySize}; } diff --git a/shared/ui/draw/draw.h b/shared/ui/draw/draw.h index 94f295e7..0b949c8a 100644 --- a/shared/ui/draw/draw.h +++ b/shared/ui/draw/draw.h @@ -6,7 +6,12 @@ extern "C" { #include "ui/graphic_types.h" #include "std/string.h" -void fb_clear(uint32_t* fb, uint32_t width, uint32_t height, uint32_t color); +int try_merge(gpu_rect* a, gpu_rect* b); +void mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h); + +//TODO: to make this a more robust drawing library available without syscall, unify dirty_rects, fb pointer, stride and size into a context structure + +void fb_clear(uint32_t* fb, uint32_t color); void fb_draw_pixel(uint32_t* fb, uint32_t x, uint32_t y, color color); void fb_fill_rect(uint32_t* fb, uint32_t x, uint32_t y, uint32_t width, uint32_t height, color color); gpu_rect fb_draw_line(uint32_t* fb, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, color color); @@ -17,6 +22,12 @@ uint32_t fb_get_char_size(uint32_t scale); void fb_set_stride(uint32_t new_stride); void fb_set_bounds(uint32_t width, uint32_t height); +#define MAX_DIRTY_RECTS 64 + +extern gpu_rect dirty_rects[MAX_DIRTY_RECTS]; +extern uint32_t dirty_count; +extern bool full_redraw; + #ifdef __cplusplus } #endif \ No newline at end of file From 988c69f57179eaf56945c74cd21ff4707effc98c Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 8 Jul 2025 00:00:00 +0000 Subject: [PATCH 72/79] Added mtools to build script --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a0c5d73c..a432636a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,6 +33,7 @@ jobs: run: | brew update brew install make + brew install mtools - name: Install Toolchain run: | From 22ef1902a939a012eec71dc787df3077839b5661 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 8 Jul 2025 00:00:00 +0000 Subject: [PATCH 73/79] dosfstools --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a432636a..36036254 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,6 +34,7 @@ jobs: brew update brew install make brew install mtools + brew install dosfstools - name: Install Toolchain run: | From 11c5b29933eb139e77582f117e2432d378ba7529 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 8 Jul 2025 00:00:00 +0000 Subject: [PATCH 74/79] unexpected missing dependencies --- .github/workflows/build.yml | 2 ++ createfs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 36036254..d6c62689 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,6 +32,8 @@ jobs: if: matrix.config.os == 'macos' run: | brew update + brew install qemu + brew install aarch64-elf-gcc brew install make brew install mtools brew install dosfstools diff --git a/createfs b/createfs index bb5878f2..5fb68023 100755 --- a/createfs +++ b/createfs @@ -9,6 +9,11 @@ if ! command -v "mcopy" >/dev/null 2>&1; then exit 1 fi +if ! command -v "mkfs.fat" >/dev/null 2>&1; then + echo "Error: this script depends on dosfstools. Please install it" >&2 + exit 1 +fi + if [[ "$OSTYPE" == "darwin"* ]]; then SIZE_KB=$(du -sk "$FOLDER" | cut -f1) From e8923c14aa7e9090a6f10ad265767a6bb9436b3f Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 8 Jul 2025 00:00:00 +0000 Subject: [PATCH 75/79] Switching to linux --- .github/workflows/build.yml | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d6c62689..08118389 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,25 +18,21 @@ jobs: fail-fast: false matrix: config: - - name: MacOS (Arm64) - os: macos - os-version: 15 - toolchain_arch: darwin-arm64 + - name: Linux (x64) + os: ubuntu + os-version: 22.04 + toolchain_arch: x86_64 steps: - uses: actions/checkout@v4 with: fetch-depth: '0' - - name: Install MacOS Dependencies - if: matrix.config.os == 'macos' + - name: Install Linux Dependencies + if: matrix.config.os == 'ubuntu' run: | - brew update - brew install qemu - brew install aarch64-elf-gcc - brew install make - brew install mtools - brew install dosfstools + sudo apt-get update + sudo apt-get install -y qemu-system-x86 qemu-utils make mtools dosfstools wget xz-utils - name: Install Toolchain run: | @@ -61,4 +57,4 @@ jobs: run debug createfs - fs/redos/user/*.elf + fs/redos/user/*.elf \ No newline at end of file From 1e91e80689e4655434d706cc93dface7f44635ff Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 8 Jul 2025 00:00:00 +0000 Subject: [PATCH 76/79] wrong qemu --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 08118389..29e0f0b8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,7 +32,7 @@ jobs: if: matrix.config.os == 'ubuntu' run: | sudo apt-get update - sudo apt-get install -y qemu-system-x86 qemu-utils make mtools dosfstools wget xz-utils + sudo apt-get install -y qemu-system-aarch64 qemu-utils make mtools dosfstools wget xz-utils - name: Install Toolchain run: | From 94626135b8e904de8b5bf646397f4d0409d0caea Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 8 Jul 2025 00:00:00 +0000 Subject: [PATCH 77/79] Compile-only command --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 29e0f0b8..c5caf613 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,7 +44,7 @@ jobs: - name: Build run: | mkdir -pv fs/redos/user - make run MODE=virt + make all LOAD_ADDR=0x41000000 - name: Upload artifacts uses: actions/upload-artifact@v4 From 49a7cadfa5882498acf071fb01754cc3ff9b688a Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 8 Jul 2025 00:00:00 +0000 Subject: [PATCH 78/79] run_virt --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c5caf613..c5dc8240 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,7 +54,7 @@ jobs: kernel.elf kernel.img disk.img - run + run_virt debug createfs fs/redos/user/*.elf \ No newline at end of file From e19ce1beafd7bd3fc25ae77c2804b27564852c65 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 8 Jul 2025 00:00:00 +0000 Subject: [PATCH 79/79] PR format and todo fixes --- kernel/Makefile | 2 +- kernel/filesystem/virtio_blk_pci.h | 1 + kernel/graph/graphics.cpp | 2 +- kernel/input/usb.cpp | 1 - kernel/kernel.c | 16 ++++++++-------- kernel/memory/mmu.c | 2 +- shared/Makefile | 2 +- user/Makefile | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 0530334a..cf9780d7 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -3,7 +3,7 @@ CC = $(ARCH)-gcc LD = $(ARCH)-ld OBJCOPY = $(ARCH)-objcopy -CFLAGS = -g -O0 -nostdlib -ffreestanding -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -Wall -Wextra -mcpu=cortex-a72 -I. -I../shared -I../user +CFLAGS = -g -O0 -std=c17 -nostdlib -ffreestanding -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -Wall -Wextra -mcpu=cortex-a72 -I. -I../shared -I../user LDFLAGS = -T $(shell ls *.ld) --defsym=LOAD_ADDR=$(LOAD_ADDR) diff --git a/kernel/filesystem/virtio_blk_pci.h b/kernel/filesystem/virtio_blk_pci.h index a8df3970..d67c17d5 100644 --- a/kernel/filesystem/virtio_blk_pci.h +++ b/kernel/filesystem/virtio_blk_pci.h @@ -5,6 +5,7 @@ #ifdef __cplusplus extern "C" { #endif +//TODO port to c++ bool vblk_find_disk(); void vblk_disk_verbose(); void vblk_write(const void *buffer, uint32_t sector, uint32_t count); diff --git a/kernel/graph/graphics.cpp b/kernel/graph/graphics.cpp index 5a0f0677..c59fa1ac 100644 --- a/kernel/graph/graphics.cpp +++ b/kernel/graph/graphics.cpp @@ -23,7 +23,7 @@ void gpu_init(gpu_size preferred_screen_size){ } screen_size = preferred_screen_size; _gpu_ready = true; - kprintf("Selected and initialized GPU %x.", (uintptr_t)gpu_driver); + kprintf("Selected and initialized GPU %x", (uintptr_t)gpu_driver); } bool gpu_ready(){ diff --git a/kernel/input/usb.cpp b/kernel/input/usb.cpp index b28d900a..1c7d658f 100644 --- a/kernel/input/usb.cpp +++ b/kernel/input/usb.cpp @@ -26,7 +26,6 @@ bool USBDriver::setup_device(uint8_t address, uint16_t port){ return false; } - usb_string_language_descriptor* lang_desc = (usb_string_language_descriptor*)allocate_in_page(mem_page, sizeof(usb_string_language_descriptor), ALIGN_64B, true, true); bool use_lang_desc = true; diff --git a/kernel/kernel.c b/kernel/kernel.c index e06eb58b..189e4ac1 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -29,17 +29,17 @@ void kernel_main() { // enable_talloc_verbose(); set_exception_vectors(); - kprintf("Exception vectors set"); + kprintf_l("Exception vectors set"); print_hardware(); page_allocator_init(); // page_alloc_enable_verbose(); - kprintf("Initializing kernel..."); + kprintf_l("Initializing kernel..."); init_main_process(); - kprintf("Preparing for draw"); + kprintf_l("Preparing for draw"); gpu_size screen_size = {1080,720}; irq_init(); @@ -47,7 +47,7 @@ void kernel_main() { enable_interrupt(); - kprintf("Initializing GPU"); + kprintf_l("Initializing GPU"); gpu_init(screen_size); @@ -66,20 +66,20 @@ void kernel_main() { bool network_available = network_init(); mmu_init(); - kprintf("MMU Mapped"); + kprintf_l("MMU Mapped"); if (!disk_init()) panic("Disk read failure"); - kprintf("Kernel initialization finished"); + kprintf_l("Kernel initialization finished"); - kprintf("Starting processes"); + kprintf_l("Starting processes"); if (network_available) launch_net_process(); init_bootprocess(); - kprintf("Starting scheduler"); + kprintf_l("Starting scheduler"); disable_interrupt(); start_scheduler(); diff --git a/kernel/memory/mmu.c b/kernel/memory/mmu.c index 8d44eacd..046beb27 100644 --- a/kernel/memory/mmu.c +++ b/kernel/memory/mmu.c @@ -174,7 +174,7 @@ void mmu_alloc(){ } void mmu_init() { - + //TODO: Move these hardcoded mappings to their own file uint64_t kstart = mem_get_kmem_start(); uint64_t kend = mem_get_kmem_end(); for (uint64_t addr = kstart; addr <= kend; addr += GRANULE_2MB) diff --git a/shared/Makefile b/shared/Makefile index 7f3ebf38..fb7390db 100644 --- a/shared/Makefile +++ b/shared/Makefile @@ -3,7 +3,7 @@ CC = $(ARCH)-gcc AR = $(ARCH)-ar OBJCOPY = $(ARCH)-objcopy -CFLAGS = -g -O0 -nostdlib -nolibc -ffreestanding -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -Wall -Wextra -mcpu=cortex-a72 -I. -I../kernel -Wno-unused-parameter +CFLAGS = -g -O0 -std=c17 -nostdlib -nolibc -ffreestanding -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -Wall -Wextra -mcpu=cortex-a72 -I. -I../kernel -Wno-unused-parameter C_SRC = $(shell find . -name '*.c') CPP_SRC = $(shell find . -name '*.cpp') diff --git a/user/Makefile b/user/Makefile index 48042a7d..fb6b8328 100644 --- a/user/Makefile +++ b/user/Makefile @@ -3,7 +3,7 @@ CC = $(ARCH)-gcc LD = $(ARCH)-ld OBJCOPY = $(ARCH)-objcopy -CFLAGS = -g -O0 -nostdlib -ffreestanding -Wall -Wextra -mcpu=cortex-a72 -I. -I../shared -Wno-unused-parameter +CFLAGS = -g -O0 -std=c17 -nostdlib -ffreestanding -Wall -Wextra -mcpu=cortex-a72 -I. -I../shared -Wno-unused-parameter LDFLAGS = -T $(shell ls *.ld) C_SRC = $(shell find . -name '*.c')