From 8844a7888ea94a11939b1c92915162f2e5acd378 Mon Sep 17 00:00:00 2001 From: cpplover0 Date: Mon, 30 Mar 2026 18:21:18 +0300 Subject: trying to get xhci working on vbox --- GNUmakefile | 2 +- kernel/src/arch/x86_64/assembly.hpp | 20 + kernel/src/arch/x86_64/drivers/pci.cpp | 3 +- kernel/src/arch/x86_64/drivers/tsc.cpp | 7 + kernel/src/arch/x86_64/panic.cpp | 12 +- kernel/src/arch/x86_64/x86_64.cpp | 2 + kernel/src/drivers/xhci.cpp | 1666 ++++++++++++++++++++++++++++++++ kernel/src/drivers/xhci.hpp | 707 ++++++++++++++ kernel/src/generic/devfs.cpp | 205 ++++ kernel/src/generic/devfs.hpp | 29 +- kernel/src/generic/evdev.cpp | 1 + kernel/src/generic/mp.cpp | 4 +- kernel/src/generic/tmpfs.cpp | 3 +- kernel/src/generic/vfs.hpp | 22 +- kernel/src/main.cpp | 3 + kernel/src/utils/align.hpp | 4 +- kernel/src/utils/ringbuffer.hpp | 4 - limine.conf | 3 +- 18 files changed, 2666 insertions(+), 31 deletions(-) create mode 100644 kernel/src/drivers/xhci.cpp create mode 100644 kernel/src/drivers/xhci.hpp diff --git a/GNUmakefile b/GNUmakefile index 7748f12..edd3160 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -5,7 +5,7 @@ ARCH := x86_64 # Default user QEMU flags. These are appended to the QEMU command calls. -QEMUFLAGS := -m 256M -d int -serial stdio +QEMUFLAGS := -m 256M -d int -serial stdio -device qemu-xhci -device usb-kbd override IMAGE_NAME := orange-$(ARCH) diff --git a/kernel/src/arch/x86_64/assembly.hpp b/kernel/src/arch/x86_64/assembly.hpp index e030e84..c1659fd 100644 --- a/kernel/src/arch/x86_64/assembly.hpp +++ b/kernel/src/arch/x86_64/assembly.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include namespace assembly { inline static std::uint64_t rdmsr(std::uint32_t msr) { @@ -28,4 +29,23 @@ namespace assembly { __asm__ volatile ("rdtsc" : "=a"(lo), "=d"(hi)); return ((uint64_t)hi << 32) | lo; } + + inline static bool is_qemu() { + uint32_t a,b,c,d; + + cpuid(0x40000000, 0, &a, &b, &c, &d); + + char hypervisorSignature[13]; + ((uint32_t *)hypervisorSignature)[0] = b; + ((uint32_t *)hypervisorSignature)[1] = c; + ((uint32_t *)hypervisorSignature)[2] = d; + hypervisorSignature[12] = '\0'; + + if (klibc::memcmp(hypervisorSignature, (void*)"TCGTCGTCGTCG", 12) == 0 || klibc::memcmp(hypervisorSignature, (void*)"KVMKVMKVM\0\0\0", 12) == 0) { + return true; + } + + return false; + } + }; \ No newline at end of file diff --git a/kernel/src/arch/x86_64/drivers/pci.cpp b/kernel/src/arch/x86_64/drivers/pci.cpp index 88d5f36..db259f8 100644 --- a/kernel/src/arch/x86_64/drivers/pci.cpp +++ b/kernel/src/arch/x86_64/drivers/pci.cpp @@ -2,6 +2,7 @@ #include pci_driver_t pci_drivers[256]; +int last_pci_drv = 0; pci_t __pci_load(std::uint8_t bus, std::uint8_t num, std::uint8_t function) { pci_t pciData; @@ -19,6 +20,7 @@ void x86_64::pci::reg(void (*pcidrv)(pci_t, std::uint8_t, std::uint8_t, std::uin pci_drivers[i]._class = _class; pci_drivers[i].subclass = subclass; pci_drivers[i].pcidrv = pcidrv; + return; } } } @@ -27,7 +29,6 @@ void __pci_launch(pci_t pci, std::uint8_t bus, std::uint8_t device, std::uint8_t for (std::uint16_t i = 0; i < 256; i++) { if (pci_drivers[i].used && pci_drivers[i]._class == pci._class && pci_drivers[i].subclass == pci.subclass) { pci_drivers[i].pcidrv(pci, bus, device, function); - return; } } } diff --git a/kernel/src/arch/x86_64/drivers/tsc.cpp b/kernel/src/arch/x86_64/drivers/tsc.cpp index 4203d76..f381173 100644 --- a/kernel/src/arch/x86_64/drivers/tsc.cpp +++ b/kernel/src/arch/x86_64/drivers/tsc.cpp @@ -14,10 +14,17 @@ static inline uint64_t rdtsc() { return ((uint64_t)hi << 32) | lo; } +bool is_disabled_tsc = false; + void drivers::tsc::init() { + if(is_disabled_tsc == true) + return; + if(time::timer == nullptr) { log("tsc", "can't initialize without timer !"); + is_disabled_tsc = true; + return; } uint64_t tsc_start, tsc_end; diff --git a/kernel/src/arch/x86_64/panic.cpp b/kernel/src/arch/x86_64/panic.cpp index df923df..ba59a38 100644 --- a/kernel/src/arch/x86_64/panic.cpp +++ b/kernel/src/arch/x86_64/panic.cpp @@ -18,14 +18,14 @@ void print_regs(x86_64::idt::int_frame_t* ctx) { ctx->rsp, cr2, ctx->cr3, ctx->vec, ctx->err_code, ctx->cs,ctx->ss); klibc::printf("\n\r Stacktrace\n\r\n\r"); - stackframe_t* rbp = (stackframe_t*)ctx->rbp; + //stackframe_t* rbp = (stackframe_t*)ctx->rbp; klibc::printf("[0] - 0x%016llX (current rip)\n\r",ctx->rip); - for (int i = 1; i < 5 && rbp; ++i) { - std::uint64_t ret_addr = rbp->rip; - klibc::printf("[%d] - 0x%016llX\n\r", i, ret_addr); - rbp = (stackframe_t*)rbp->rbp; - } + // for (int i = 1; i < 5 && rbp; ++i) { + // std::uint64_t ret_addr = rbp->rip; + // klibc::printf("[%d] - 0x%016llX\n\r", i, ret_addr); + // rbp = (stackframe_t*)rbp->rbp; + // } } diff --git a/kernel/src/arch/x86_64/x86_64.cpp b/kernel/src/arch/x86_64/x86_64.cpp index 1389351..7653346 100644 --- a/kernel/src/arch/x86_64/x86_64.cpp +++ b/kernel/src/arch/x86_64/x86_64.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace arch { [[gnu::weak]] void disable_interrupts() { @@ -74,6 +75,7 @@ namespace arch { drivers::hpet::init(); drivers::tsc::init(); drivers::pvclock::bsp_init(); + assert(time::timer != nullptr, "can't init orange without timer !"); x86_64::gdt::init(); x86_64::idt::init(); x86_64::lapic::init(1500); diff --git a/kernel/src/drivers/xhci.cpp b/kernel/src/drivers/xhci.cpp new file mode 100644 index 0000000..696e2bc --- /dev/null +++ b/kernel/src/drivers/xhci.cpp @@ -0,0 +1,1666 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__x86_64__) +#include +#include +#endif + +xhci_device_t* xhci_list; + +void __xhci_put_new_device(xhci_device_t* dev) { + if(!dev) { + return; + } + + if(!xhci_list) { + xhci_list = dev; + } else { + dev->next = xhci_list; + xhci_list = dev; + } + +} + +void __xhci_doorbell(xhci_device_t* dev,uint32_t value) { + arch::memory_barrier(); + *dev->doorbell = value; + arch::memory_barrier(); +} + +void __xhci_doorbell_id(xhci_device_t* dev,uint32_t idx,uint32_t val) { + arch::memory_barrier(); + dev->doorbell[idx] = val; + arch::memory_barrier(); +} + +void __xhci_reset(xhci_device_t* dev) { + + time::timer->sleep(50*1000); // wait some time + + dev->op->usbcmd |= (1 << 1); + uint16_t timeout = XHCI_RESET_TIMEOUT; + while(dev->op->usbsts & (1 << 11)) { + if(!timeout) { + log("xhci","Can't reset XHCI Controller, ignoring"); + break; + } + time::timer->sleep(5 * 1000); + timeout = timeout - 1; + } + + time::timer->sleep(5000); + +} + +void __xhci_enable(xhci_device_t* dev) { + time::timer->sleep(50*1000); + dev->op->usbcmd |= (1 << 0) | (1 << 2); + uint16_t timeout = XHCI_RESET_TIMEOUT; + while(dev->op->usbsts & (1 << 0)) { + if(!timeout) { + log("xhci","Can't start XHCI Controller, crying"); + break; + } + time::timer->sleep(5 * 1000); + timeout = timeout - 1; + } + + time::timer->sleep(5000); + +} + +void __xhci_reset_intr(xhci_device_t* dev, uint16_t intr) { + + if(intr > dev->cap->hcsparams1.maxintrs) { + log("xhci","Intr is higher than maxintrs! Skipping"); + return; + } + + dev->op->usbsts = (1 << 3); + dev->runtime->int_regs[intr].iman |= (1 << 0); +} + +void __xhci_punch_intr(xhci_device_t* dev,uint16_t intr) { + dev->runtime->int_regs[intr].erdp.event_busy = 1; +} + +void __xhci_update_stepfather(xhci_device_t* dev,xhci_event_ring_ctx_t* grandpa) { + (void)dev; + grandpa->father->erdp_val = grandpa->table[0].base + (grandpa->queue * sizeof(xhci_trb_t)); +} + +xhci_trb_t* __xhci_move_father(xhci_device_t* dev,xhci_event_ring_ctx_t* ctx) { + (void)dev; + xhci_trb_t* trb = &ctx->trb[ctx->queue++]; + if(ctx->queue == ctx->trb_limit) { + ctx->cycle = !ctx->cycle; + ctx->queue = 0; + } + return trb; +} + +xhci_event_ring_ctx_t* __xhci_create_event_ring(xhci_device_t* dev,uint16_t trb_size,volatile IR_t* stepfather,uint16_t sons) { + xhci_event_ring_ctx_t* ring_info = new xhci_event_ring_ctx_t; + ring_info->cycle = 1; + ring_info->queue = 0; + ring_info->father = stepfather; // :pensive: + ring_info->trb_limit = trb_size; + ring_info->trb = 0; + + uint64_t new_table = pmm::buddy::alloc(ALIGNPAGEUP(sons * sizeof(xhci_erst_t))).phys; + void* virt_table = (void*)(new_table + etc::hhdm()); + + ring_info->table = (xhci_erst_t*)virt_table; + + uint64_t phys_trb = pmm::buddy::alloc(16 * PAGE_SIZE).phys; + ring_info->table[0].base = phys_trb; + ring_info->table[0].size = trb_size; + + ring_info->trb = (xhci_trb_t*)(phys_trb + etc::hhdm()); + + stepfather->erstsz = sons; + __xhci_update_stepfather(dev,ring_info); + stepfather->erstba = new_table; + + return ring_info; + +} + +xhci_trb_t get_trb(xhci_event_ring_ctx_t* father,uint16_t idx) { + return father->trb[idx]; +} + +int __xhci_event_receive(xhci_device_t* dev,xhci_event_ring_ctx_t* father,xhci_trb_t** out) { // it will return trb virtual addresses + int len = 0; + arch::memory_barrier(); + while(get_trb(father,father->queue).info_s.cycle == father->cycle) + out[len++] = __xhci_move_father(dev,father); + __xhci_punch_intr(dev,0); + __xhci_update_stepfather(dev,father); + arch::memory_barrier(); + return len; +} + +xhci_command_ring_ctx_t* __xhci_create_command_ring(xhci_device_t* dev,uint16_t trb_size) { + (void)dev; + xhci_command_ring_ctx_t* ring_info = new xhci_command_ring_ctx_t; + ring_info->cycle = 1; + ring_info->queue = 0; + ring_info->trb_limit = trb_size; + + uint64_t phys_trb = pmm::buddy::alloc(ALIGNPAGEUP(trb_size * sizeof(xhci_trb_t))).phys; + + ring_info->phys = phys_trb; + + ring_info->trb = (xhci_trb_t*)(phys_trb + etc::hhdm()); + ring_info->trb[trb_size - 1].base = phys_trb; + ring_info->trb[trb_size - 1].info = (6 << 10) | (1 << 1) | (1 << 0); + return ring_info; +} + + +void __xhci_command_ring_queue(xhci_device_t* dev,xhci_command_ring_ctx_t* ctx,xhci_trb_t* trb) { + (void)dev; + trb->info |= ctx->cycle; + klibc::memcpy(&ctx->trb[ctx->queue],trb,sizeof(xhci_trb_t)); + if(++ctx->queue == ctx->trb_limit - 1) { + ctx->queue = 0; + ctx->trb[ctx->trb_limit - 1].info = (6 << 10) | (1 << 1) | (ctx->cycle << 0); + ctx->cycle = !ctx->cycle; + } + arch::memory_barrier(); +} + +void __xhci_setup_run(xhci_device_t* dev) { + volatile IR_t* head = (volatile IR_t*)&dev->runtime->int_regs[0]; + head->iman |= (1 << 1); + + dev->event_ring = __xhci_create_event_ring(dev,256,head,1); + + __xhci_reset_intr(dev,0); +} + +void __xhci_fill_dcbaa(xhci_device_t* dev) { + + uint64_t phys_dcbaa = pmm::buddy::alloc(ALIGNPAGEUP(8*dev->cap->hcsparams1.maxslots)).phys; + + uint64_t* dcbaa = (uint64_t*)(phys_dcbaa + etc::hhdm()); + + if(dev->calculated_scratchpad_count) { + + uint64_t phys_list = pmm::buddy::alloc(ALIGNPAGEUP(8*dev->calculated_scratchpad_count)).phys; + + uint64_t* list = (uint64_t*)(phys_list + etc::hhdm()); + for(uint16_t i = 0;i < dev->calculated_scratchpad_count;i++) { + uint64_t hi = pmm::freelist::alloc_4k(); + list[i] = hi; + } + dcbaa[0] = phys_list; + } + + dev->dcbaa = (uint64_t*)dcbaa; + dev->op->dcbaap = phys_dcbaa; + time::timer->sleep(5000); +} + +void __xhci_setup_op(xhci_device_t* dev) { + __xhci_fill_dcbaa(dev); + dev->com_ring = __xhci_create_command_ring(dev,128); // i dont think what command ring will be fat + dev->op->crcr = dev->com_ring->phys | dev->com_ring->cycle; + dev->op->config = dev->cap->hcsparams1.maxslots; + dev->op->dnctrl = 0xFFFF; +} + +volatile uint32_t* __xhci_portsc(xhci_device_t* dev,uint32_t portnum) { + return ((volatile uint32_t*)(dev->xhci_virt_base + 0x400 + dev->cap->caplength + (0x10 * portnum))); +} + +const char* trb_type_to_str(int type) { + switch(type) { + case TRB_COMMANDCOMPLETIONEVENT_TYPE: + return "TRB_COMMAND_COMPLETION_EVENT"; + case TRB_TRANSFEREVENT_TYPE: + return "TRB_TRANSFER_EVENT"; + default: + return "Unknown"; + } +} + +xhci_trb_t __xhci_event_wait(xhci_device_t* dev,int type) { + xhci_event_ring_ctx_t* father = dev->event_ring; + xhci_trb_t* buffer[1024]; + int timeout = 100; + while(1) { + arch::memory_barrier(); + int count = 0; + klibc::memset(buffer,0,sizeof(xhci_trb_t*) * 1024); + if(get_trb(father,father->queue).info_s.cycle == father->cycle) + count = __xhci_event_receive(dev,father,buffer); + + if(count) { + xhci_trb_t* current = 0; + for(int i = 0;i < count;i++) { + current = buffer[i]; + if(current->info_s.type == type) { + return *current; + } else { + log("xhci","Wait for wrong type %d",current->info_s.type); + } + } + } + + if(--timeout == 0) { + xhci_trb_t t; + t.base = 0xDEAD; + t.ret_code = 0; + return t; + } + + arch::memory_barrier(); + time::timer->sleep(5000); + + } +} + +void __xhci_clear_event(xhci_device_t* dev) { + xhci_trb_t* buffer[1024]; + if(get_trb(dev->event_ring,dev->event_ring->queue).info_s.cycle == dev->event_ring->cycle) + __xhci_event_receive(dev,dev->event_ring,buffer); +} + + +xhci_port_ring_ctx_t* __xhci_setup_port_ring(uint16_t trb_count,uint16_t slot) { + xhci_port_ring_ctx_t* ring_info = new xhci_port_ring_ctx_t; + ring_info->cycle = 1; + ring_info->queue = 0; + ring_info->slot = slot; + ring_info->trb_limit = trb_count; + + uint64_t phys_trb = pmm::buddy::alloc(16 * 4096).phys; + ring_info->trb = (xhci_trb_t*)(phys_trb + etc::hhdm()); + + ring_info->phys = phys_trb; + ring_info->trb[trb_count - 1].base = phys_trb; + ring_info->trb[trb_count - 1].info = (6 << 10) | (1 << 1) | (1 << 0); + return ring_info; +} + +// its same as command ring +void __xhci_port_ring_queue(xhci_port_ring_ctx_t* ctx,xhci_trb_t* trb) { + trb->info |= ctx->cycle; + klibc::memcpy(&ctx->trb[ctx->queue],trb,sizeof(xhci_trb_t)); + if(++ctx->queue == ctx->trb_limit - 1) { + ctx->queue = 0; + ctx->trb[ctx->trb_limit - 1].info = (6 << 10) | (1 << 1) | (ctx->cycle << 0); + ctx->cycle = !ctx->cycle; + } +} + +void __xhci_create_dcbaa(xhci_device_t* dev,uint32_t slotid,uint64_t addr) { + dev->dcbaa[slotid] = addr; +} + +xhci_usb_device_t* usbdevs = 0; + +xhci_usb_device_t* __xhci_alloc_dev(uint32_t portnum,uint32_t slotid) { + xhci_usb_device_t* dev = new xhci_usb_device_t; + dev->next = 0; + dev->portnum = portnum; + dev->slotid = slotid; + dev->transfer_ring = __xhci_setup_port_ring(256,slotid); + dev->phys_input_ctx = pmm::freelist::alloc_4k(); + if(!usbdevs) { + usbdevs = dev; + } else { + dev->next = usbdevs; + usbdevs = dev; + } + return dev; +} + +int __xhci_enable_slot(xhci_device_t* dev, int portnum) { + xhci_trb_t trb; + + klibc::memset(&trb,0,sizeof(xhci_trb_t)); + + trb.info_s.intoncompletion = 1; + trb.info_s.type = TRB_ENABLESLOTCOMMAND_TYPE; + + __xhci_clear_event(dev); + + __xhci_command_ring_queue(dev,dev->com_ring,&trb); + __xhci_doorbell(dev,0); + time::timer->sleep(25000); + + xhci_trb_t ret = __xhci_event_wait(dev,TRB_COMMANDCOMPLETIONEVENT_TYPE); + + if(ret.base == 0xDEAD) { + log("xhci","Timeout for port %d in slot enabling",portnum); + return 0; + } + + xhci_slot_trb_t* slot_ret = (xhci_slot_trb_t*)&ret; + + if(ret.ret_code != 1) + log("xhci","Can't allocate slot for port %d (ret %d)",portnum,ret.ret_code); + + return slot_ret->info_s.slotid; + +} + +int __xhci_set_addr(xhci_device_t* dev,uint64_t addr,uint32_t id,char bsr) { + (void)bsr; + xhci_set_addr_trb_t trb; + klibc::memset(&trb,0,sizeof(trb)); + trb.base = addr; + trb.info_s.bsr = 0; + trb.info_s.type = TRB_ADDRESSDEVICECOMMAND_TYPE; + trb.info_s.slotid = id; + __xhci_clear_event(dev); + + time::timer->sleep(5000); + + __xhci_clear_event(dev); + + __xhci_command_ring_queue(dev,dev->com_ring,(xhci_trb_t*)&trb); + __xhci_doorbell(dev,0); + time::timer->sleep(5000); + + xhci_trb_t ret = __xhci_event_wait(dev,TRB_COMMANDCOMPLETIONEVENT_TYPE); + + if(ret.ret_code != 1 && ret.ret_code != 0) + log("xhci","Can't set XHCI port address (ret %d)",ret.ret_code); + + return ret.ret_code; + +} + +xhci_trb_t __xhci_send_usb_request_packet(xhci_device_t* dev,xhci_usb_device_t* usbdev,xhci_usb_command_t usbcommand,void* out,uint64_t len) { + + uint64_t phys_status_buf = pmm::freelist::alloc_4k(); + uint64_t phys_desc_buf = pmm::freelist::alloc_4k(); + + void* desc_buf = (void*)(phys_desc_buf + etc::hhdm()); + + klibc::memset(out,0,len); + + xhci_setupstage_trb_t setup; + xhci_datastage_trb_t data; + xhci_eventdata_trb_t event0; + xhci_statusstage_trb_t status; + xhci_eventdata_trb_t event1; + + klibc::memset(&setup,0,sizeof(xhci_trb_t)); + klibc::memset(&data,0, sizeof(xhci_trb_t)); + klibc::memset(&event0,0,sizeof(xhci_trb_t)); + klibc::memset(&status,0,sizeof(xhci_trb_t)); + klibc::memset(&event1,0,sizeof(xhci_trb_t)); + + klibc::memcpy(&setup.command,&usbcommand,sizeof(xhci_usb_command_t)); + + setup.type = TRB_SETUPSTAGE_TYPE; + setup.trt = 3; + setup.imdata = 1; + setup.len = 8; + + data.type = TRB_DATASTAGE_TYPE; + data.data = phys_desc_buf; + data.len = len; + data.chain = 1; + data.direction = 1; + + event0.type = TRB_EVENTDATA_TYPE; + event0.base = phys_status_buf; + event0.chain = 0; + event0.intoncomp = 1; + + status.type = TRB_STATUSSTAGE_TYPE; + status.chain = 1; + + event1.type = TRB_EVENTDATA_TYPE; + event1.intoncomp = 1; + + __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&setup); + __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&data); + __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&event0); + __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&status); + __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&event1); + + + arch::memory_barrier(); + + __xhci_clear_event(dev); + + __xhci_doorbell_id(dev,usbdev->slotid,1); + time::timer->sleep(5000); + + xhci_trb_t ret = __xhci_event_wait(dev,TRB_TRANSFEREVENT_TYPE); + + if(ret.base == 0xDEAD) { + ret.ret_code = 0; + log("xhci", "timeout !"); + return ret; + } + + if(ret.ret_code != 1) { + log("xhci","Failed to request xhci device, idx: %p, val: %p, type: %p, len: %p, request: %d ret_code %d",usbcommand.index,usbcommand.value,usbcommand.type,usbcommand.len,usbcommand.request,ret.ret_code); + ret.ret_code = 0; + return ret; + } + + time::timer->sleep(5000); + + klibc::memcpy(out,desc_buf,len); + + pmm::freelist::free(phys_desc_buf); + pmm::freelist::free(phys_status_buf); + + return ret; + +} + +xhci_trb_t __xhci_send_usb_packet(xhci_device_t* dev,xhci_usb_device_t* usbdev,xhci_usb_command_t com) { + + xhci_setupstage_trb_t setup; + xhci_statusstage_trb_t status; + + klibc::memset(&setup,0,sizeof(xhci_setupstage_trb_t)); + klibc::memset(&status,0,sizeof(xhci_statusstage_trb_t)); + + klibc::memcpy(&setup.command,&com,sizeof(xhci_usb_command_t)); + + setup.imdata = 1; + setup.len = 8; + setup.type = TRB_SETUPSTAGE_TYPE; + + status.direction = 1; + status.intoncomp = 1; + status.type = TRB_STATUSSTAGE_TYPE; + + __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&setup); + __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&status); + + __xhci_clear_event(dev); + + __xhci_doorbell_id(dev,usbdev->slotid,1); + time::timer->sleep(5000); + + xhci_trb_t ret = __xhci_event_wait(dev,TRB_TRANSFEREVENT_TYPE); + + return ret; + +} + +int __xhci_get_usb_descriptor(xhci_device_t* dev,xhci_usb_device_t* usbdev,void* out,uint64_t len) { + xhci_usb_command_t usbcommand; + usbcommand.type = 0x80; + usbcommand.request = 6; + usbcommand.value = 1 << 8; + usbcommand.index = 0; + usbcommand.len = len; + + xhci_trb_t ret = __xhci_send_usb_request_packet(dev,usbdev,usbcommand,out,len); + if(ret.ret_code != 1) { + log("xhci", "failed to get usb descriptior ret code is %d\r\n",ret.ret_code); + return 0; + } + + return 1; + +} + +uint16_t __xhci_get_speed(xhci_device_t* dev,uint32_t portsc) { + (void)dev; + uint8_t extracted_speed = (portsc & 0x3C00) >> 10; + switch (extracted_speed) { + case XHCI_USB_SPEED_LOW_SPEED: + return 8; + + case XHCI_USB_SPEED_FULL_SPEED: + return 64; + + case XHCI_USB_SPEED_HIGH_SPEED: + return 64; + + case XHCI_USB_SPEED_SUPER_SPEED: + return 512; + + case XHCI_USB_SPEED_SUPER_SPEED_PLUS: + return 512; + + default: + return 0; + } +} + +int __xhci_reset_dev(xhci_device_t* dev, uint32_t portnum) { + volatile uint32_t* portsc = (volatile uint32_t*)__xhci_portsc(dev, portnum); + uint32_t load_portsc = *portsc; + + if (!(load_portsc & (1 << 9))) { + *portsc = (load_portsc & 0x0E0003E0) | (1 << 9); + time::timer->sleep(5000); + if (!(*portsc & (1 << 9))) return 0; + } + + if (dev->usb3ports[portnum]) { + + uint32_t val = *portsc & 0x0E0003E0; + *portsc = val | (1 << 31); + } else { + + uint32_t val = *portsc & 0x0E0003E0; + *portsc = val | (1 << 4); + } + + uint16_t timeout = 50; + if (dev->usb3ports[portnum]) { + + while (!(*portsc & (1 << 19))) { + if (timeout-- == 0) { + log("xhci", "Can't reset USB 3.0 device on port %d", portnum); + return 0; + } + time::timer->sleep(5000); + } + + *portsc = (*portsc & 0x0E0003E0) | (1 << 19); + } else { + while (*portsc & (1 << 4)) { + if (timeout-- == 0) { + log("xhci", "Can't reset USB 2.0 device on port %d", portnum); + return 0; + } + time::timer->sleep(5000); + } + } + + time::timer->sleep(50000); + return 1; +} + + +void __xhci_unicode_to_ascii(uint16_t* src,char* dest) { + uint16_t src_ptr = 0; + uint16_t dest_ptr = 0; + + uint16_t* ptr = (uint16_t*)src; + while(ptr[src_ptr]) { + + if(ptr[src_ptr] < 128) + dest[dest_ptr++] = ptr[src_ptr++]; + else + dest[dest_ptr++] = '?'; + } + dest[dest_ptr] = '\0'; +} + +int __xhci_read_usb_string(xhci_device_t* dev,xhci_usb_device_t* usbdev,xhci_string_descriptor_t* out,uint8_t index,uint8_t lang) { + xhci_usb_command_t usbcommand; + usbcommand.type = 0x80; + usbcommand.request = 6; + usbcommand.value = (3 << 8) | index; + usbcommand.index = lang; + usbcommand.len = sizeof(xhci_usb_descriptor_header); + + xhci_trb_t ret = __xhci_send_usb_request_packet(dev,usbdev,usbcommand,out,usbcommand.len); + if(ret.ret_code != 1) + return 0; + + usbcommand.len = out->head.len; + + if(usbcommand.len < 8) { + return 1; + } + + ret = __xhci_send_usb_request_packet(dev,usbdev,usbcommand,out,usbcommand.len); + if(ret.ret_code != 1) + return 0; + + return 1; + +} + + + +int __xhci_read_usb_lang_string(xhci_device_t* dev,xhci_usb_device_t* usbdev,xhci_lang_descriptor_t* out) { + xhci_usb_command_t usbcommand; + usbcommand.type = 0x80; + usbcommand.request = 6; + usbcommand.value = (3 << 8); + usbcommand.index = 0; + usbcommand.len = sizeof(xhci_usb_descriptor_header); + + xhci_trb_t ret = __xhci_send_usb_request_packet(dev,usbdev,usbcommand,out,usbcommand.len); + if(ret.ret_code != 1) + return 0; + + usbcommand.len = out->head.len; + + ret = __xhci_send_usb_request_packet(dev,usbdev,usbcommand,out,usbcommand.len); + if(ret.ret_code != 1) + return 0; + + return 1; + +} + +int __xhci_print_device_info(xhci_device_t* dev,xhci_usb_device_t* usb_dev,char* product0,char* manufacter0) { + xhci_lang_descriptor_t lang; + + int status = __xhci_read_usb_lang_string(dev,usb_dev,&lang); + + if(!status) + return 0; + + uint16_t lang0 = lang.lang[0]; + + xhci_string_descriptor_t product; + xhci_string_descriptor_t manufacter; + + klibc::memset(&product,0,sizeof(product)); + klibc::memset(&manufacter,0,sizeof(manufacter)); + + status = __xhci_read_usb_string(dev,usb_dev,&product,usb_dev->desc->product1,lang0); + + if(!status) + return 0; + + status = __xhci_read_usb_string(dev,usb_dev,&manufacter,usb_dev->desc->manufacter,lang0); + + if(!status) + return 0; + + klibc::memset(product0,0,256); + klibc::memset(manufacter0,0,256); + + __xhci_unicode_to_ascii(product.str,product0); + __xhci_unicode_to_ascii(manufacter.str,manufacter0); + + return 1; + +} + +void __xhci_setup_config(xhci_device_t* dev,xhci_usb_device_t* usbdev,uint16_t value) { + xhci_usb_command_t command; + command.type = 0; + command.index = 0; + command.len = 0; + command.request = 9; + command.value = value; + + int ret = __xhci_send_usb_packet(dev,usbdev,command).ret_code; + + if(ret != 1) + log("xhci","Can't set configuration on port %d with val %d (ret %d)",usbdev->portnum,value,ret); +} + +void __xhci_get_config_descriptor(xhci_device_t* dev,xhci_usb_device_t* usbdev, xhci_config_descriptor_t* out) { + xhci_usb_command_t com; + com.type = 0x80; + com.value = 2 << 8; + com.index = 0; + com.len = sizeof(xhci_usb_descriptor_header); + com.request = 6; + + __xhci_send_usb_request_packet(dev,usbdev,com,out,sizeof(xhci_usb_descriptor_header)); + com.len = out->head.len; + __xhci_send_usb_request_packet(dev,usbdev,com,out,out->head.len); + com.len = out->len; + __xhci_send_usb_request_packet(dev,usbdev,com,out,out->len); + +} + +void __xhci_get_hid_report(xhci_device_t* dev,xhci_usb_device_t* usbdev,uint8_t idx,uint8_t internum,void* data,uint32_t len) { + xhci_usb_command_t cmd; + cmd.index = internum; + cmd.request = 6; + cmd.type = 0x81; + cmd.len = len; + cmd.value = (0x22 << 8) | idx; + __xhci_send_usb_request_packet(dev,usbdev,cmd,data,len); +} + +void __xhci_set_boot_protocol(xhci_device_t* dev, xhci_usb_device_t* usbdev, int internum) { + xhci_usb_command_t cmd; + cmd.index = internum; + cmd.request = 0x0B; + cmd.type = 0x21; + cmd.len = 0; + cmd.value = 0; + + char data[4096]; + __xhci_send_usb_request_packet(dev,usbdev,cmd,data,0); +} + +int __xhci_ep_to_type(xhci_endpoint_descriptor_t* desc) { + uint8_t direction = (desc->endpointaddr & 0x80) ? 1 : 0; + uint8_t type = desc->attributes & 3; + + switch (type) { + case 1: + return direction == 1 ? XHCI_ENDPOINTTYPE_ISOCHRONOUS_IN : XHCI_ENDPOINTTYPE_ISOCHRONOUS_OUT; + + case 2: + return direction == 1 ? XHCI_ENDPOINTTYPE_BULK_IN : XHCI_ENDPOINTTYPE_BULK_OUT; + + case 3: + return direction == 1 ? XHCI_ENDPOINTTYPE_INTERRUPT_IN : XHCI_ENDPOINTTYPE_INTERRUPT_OUT; + } + + return 0; // without it i will got UB +} + +void __xhci_ask_for_help_hid(xhci_device_t* dev,xhci_usb_device_t* usbdev) { + + for(int i = 0;i < 30;i++) { + + if(!usbdev->doorbell_values[i]) + continue; + + xhci_port_ring_ctx_t* transfer_ring = usbdev->ep_ctx[i]; + xhci_normal_trb_t trb; + klibc::memset(&trb,0,sizeof(xhci_normal_trb_t)); + trb.info_s.type = 1; + trb.info_s.ioc = 1; + trb.base = (uint64_t)usbdev->phys_buffers[i]; + trb.trbtransferlen = usbdev->buffers_need_size[i]; + + __xhci_port_ring_queue(transfer_ring,(xhci_trb_t*)&trb); + __xhci_doorbell_id(dev,usbdev->slotid,usbdev->doorbell_values[i]); + } + +} + +const char* __xhci_usb_type_to_str(int type) { + switch(type) { + case USB_TYPE_KEYBOARD: + return "USB Keyboard"; + case USB_TYPE_MOUSE: + return "USB Mouse"; + default: + return "Unsupported"; + }; +} + +int log2(unsigned int x) { + int result = -1; + while (x) { + x >>= 1; + result++; + } + return result; +} + +bool usb_device_self_test(xhci_device_t* dev, xhci_usb_device_t* usbdev) { + xhci_normal_trb_t trb = {}; + trb.info_s.type = 8; + trb.info_s.ioc = 1; + + __xhci_clear_event(dev); + + __xhci_port_ring_queue(usbdev->transfer_ring,(xhci_trb_t*)&trb); + + arch::memory_barrier(); + + __xhci_doorbell_id(dev,usbdev->slotid,1); + time::timer->sleep(5000); + + xhci_trb_t ret1 = __xhci_event_wait(dev,TRB_TRANSFEREVENT_TYPE); + + if(ret1.base == 0xDEAD) { + log("xhci", "xhci usb device self test timeouted"); + return false; + } + + if(ret1.ret_code != 1) { + log("xhci", "xhci usb device self test is not ok (%d)",ret1.ret_code); + return false; + } + + log("xhci", "xhci usb device self test is ok"); + return true; +} + +void __xhci_init_dev(xhci_device_t* dev,int portnum) { + + volatile uint32_t* portsc = __xhci_portsc(dev,portnum); + uint32_t load_portsc = *portsc; + + if(!(load_portsc & 1)) + return; + + int status = __xhci_reset_dev(dev,portnum); + if(!status) + return; + + int id = __xhci_enable_slot(dev,portnum); + xhci_usb_device_t* usb_dev = __xhci_alloc_dev(portnum,id); + //String::memset(usb_dev,0,sizeof(xhci_usb_device_t)); + + klibc::memset(usb_dev->doorbell_values,0,30); + + usb_dev->interface = 0; + + uint64_t addr = pmm::freelist::alloc_4k(); + __xhci_create_dcbaa(dev,usb_dev->slotid,addr); + + uint32_t* hccparams = (uint32_t*)(&dev->cap->hccparams1); + char context_size = ((hccparams1_t*)hccparams)->contextsize; + + + if(!context_size) + dev->dcbaa[id] += 64; + else + dev->dcbaa[id] += 128; + + if(!context_size) + usb_dev->_is64byte = 0; + else + usb_dev->_is64byte = 1; + + usb_dev->dev = dev; + + load_portsc = *portsc; // load it again + + uint16_t speed = __xhci_get_speed(dev,load_portsc); + + const char* speed_to_str[7] = { + "(0 MB/s - USB ?)", + "(12 MB/s - USB 2.0)", + "(1.5 Mb/s - USB 2.0)", + "(480 Mb/s - USB 2.0)", + "(5 Gb/s - USB3.0)", + "(10 Gb/s - USB 3.1)" + }; + + assert((addr % 64) == 0, "addr is not aligned (kernel bug)"); + assert((usb_dev->transfer_ring->phys % 16) == 0, "sfaf"); + + if(!context_size) { + xhci_input_ctx_t* input_ctx = (xhci_input_ctx_t*)(addr + etc::hhdm()); + + klibc::memset(input_ctx,0,4096); + input_ctx->input_ctx.A = (1 << 0) | (1 << 1); + input_ctx->slot.contextentries = 1; + input_ctx->slot.speed = (load_portsc & 0x3C00) >> 10; + input_ctx->slot.porthubnum = portnum + 1; + input_ctx->ep0.endpointtype = 4; + input_ctx->ep0.cerr = 3; + input_ctx->ep0.maxpacketsize = speed; + input_ctx->ep0.base = usb_dev->transfer_ring->phys | usb_dev->transfer_ring->cycle; + input_ctx->ep0.averagetrblen = 0x8; + usb_dev->input_ctx = (xhci_input_ctx_t*)input_ctx; + + } else { + xhci_input_ctx64_t* input_ctx = (xhci_input_ctx64_t*)(addr + etc::hhdm()); + + klibc::memset(input_ctx,0,4096); + input_ctx->input_ctx.A = (1 << 0) | (1 << 1); + input_ctx->slot.contextentries = 1; + input_ctx->slot.speed = (load_portsc & 0x3C00) >> 10; + input_ctx->slot.porthubnum = portnum + 1; + input_ctx->ep0.endpointtype = 4; + input_ctx->ep0.cerr = 3; + input_ctx->ep0.maxpacketsize = speed; + input_ctx->ep0.base = usb_dev->transfer_ring->phys | usb_dev->transfer_ring->cycle; + input_ctx->ep0.averagetrblen = 8; + + usb_dev->input_ctx = (xhci_input_ctx_t*)input_ctx; + + } + + int status_addr = __xhci_set_addr(dev,addr,id,0); + + if(status_addr == 0) { + log("xhci","zero ret from xhci_set_addr (broken xhci ?)"); + } else if(status_addr != 1) + return; + + // bool self_test = usb_device_self_test(dev, usb_dev); + // if(self_test == false) + // return; + + xhci_usb_descriptor_t* descriptor = (xhci_usb_descriptor_t*)klibc::malloc(4096); + int status2 = __xhci_get_usb_descriptor(dev,usb_dev,(void*)descriptor,8); + + if(!status2) + return; + + ((xhci_input_ctx_t*)(dev->dcbaa[id] + etc::hhdm()))->ep0.maxpacketsize = descriptor->maxpacketsize; + + status2 = __xhci_get_usb_descriptor(dev,usb_dev,(void*)descriptor,descriptor->head.len); + if(!status2) + return; + usb_dev->desc = descriptor; + + usb_dev->type = 0; + + if(!speed) { + log("xhci","Broken USB Device/Firmware, can't continue work. skipping"); + return; + } + + char product[1024]; + char manufacter[1024]; + + klibc::memset(product,0,1024); + klibc::memset(manufacter,0,1024); + + int status4 = __xhci_print_device_info(dev,usb_dev,product,manufacter); + if(!status4) + return; + + xhci_config_descriptor_t* cfg = (xhci_config_descriptor_t*)klibc::malloc(4096); + usb_dev->config = cfg; + + __xhci_get_config_descriptor(dev,usb_dev,cfg); + + __xhci_setup_config(dev,usb_dev,cfg->configval); + + if(!context_size) { + usb_dev->input_ctx->input_ctx.A = (1 << 0); + } else { + xhci_input_ctx64_t* input = (xhci_input_ctx64_t*)(addr + etc::hhdm()); + input->input_ctx.A = (1 << 0); + } + + uint16_t i = 0; + while(i < (cfg->len - cfg->head.len)) { + xhci_usb_descriptor_header* current = (xhci_usb_descriptor_header*)(&cfg->data[i]); + //INFO("Found descriptor with type %d (0x%p) and len %d (i %d)!",current->type,current->type,current->len,i); + + xhci_interface_t* inter = new xhci_interface_t; + inter->type = current->type; + inter->data = current; + klibc::memset(inter,0,sizeof(xhci_interface_t)); + if(!usb_dev->interface) + usb_dev->interface = inter; + else { + inter->next = usb_dev->interface; + usb_dev->interface = inter; + } + + switch(current->type) { + + case 0x04: { + xhci_interface_descriptor_t* interface = (xhci_interface_descriptor_t*)current; + //INFO("interface interclass %d, interface intersubclass %d, protocol %d",interface->interclass,interface->intersubclass,interface->protocol); + if(interface->interclass == 3 && interface->intersubclass == 1 && !usb_dev->type) { + switch(interface->protocol) { + case 2: { + usb_dev->type = USB_TYPE_MOUSE; + break; + } + + case 1: { + usb_dev->type = USB_TYPE_KEYBOARD; + break; + } + } + } + break; + } + + case 0x21: { + xhci_hid_descriptor_t* hid = (xhci_hid_descriptor_t*)current; + for(int i = 0; i < hid->numdesc;i++) { + xhci_hid_sub_desc* desc = &hid->desc[i]; + if(desc->desctype == 0x22) { + + xhci_interface_t* need_interface = usb_dev->interface; + while(need_interface) { + if(need_interface->type == 0x04) + break; + need_interface = need_interface->next; + } + + if(!need_interface) + continue; + + need_interface->buffer = klibc::malloc(desc->desclen + 1); + klibc::memset(need_interface->buffer,0,desc->desclen + 1); + need_interface->len = desc->desclen; + + xhci_interface_descriptor_t* interface = (xhci_interface_descriptor_t*)need_interface; + + __xhci_set_boot_protocol(dev,usb_dev,interface->num); + __xhci_get_hid_report(dev,usb_dev,0,interface->num,need_interface->buffer,need_interface->len); + + } + } + break; + } + // __xhci_setup_port_ring(256,slotid); + case 0x05: { + xhci_endpoint_descriptor_t* ep = (xhci_endpoint_descriptor_t*)current; + + int idx = ((ep->endpointaddr >> 7) & 1) + ((ep->endpointaddr & 0x0F) << 1); + usb_dev->main_ep = idx; + idx -= 2; + usb_dev->ep_ctx[idx] = __xhci_setup_port_ring(256,usb_dev->slotid); + + usb_dev->buffers_need_size[idx] = ep->maxpacketsize; + + usb_dev->phys_buffers[idx] = pmm::freelist::alloc_4k(); + usb_dev->buffers[idx] = (uint8_t*)(usb_dev->phys_buffers[idx] + etc::hhdm()); + usb_dev->doorbell_values[idx] = idx + 2; + + if(!context_size) { + xhci_input_ctx_t* input = (xhci_input_ctx_t*)(addr + etc::hhdm()); + xhci_endpoint_ctx_t* ep1 = &input->ep[idx]; + klibc::memset(ep1,0,sizeof(xhci_endpoint_ctx_t)); + usb_dev->input_ctx->input_ctx.A |= (1 << (idx + 2)); + + input->slot.contextentries += 2; + ep1->state = 0; + ep1->endpointtype = __xhci_ep_to_type(ep); + ep1->maxpacketsize = ep->maxpacketsize; + ep1->some_shit_with_long_name_lo = ep->maxpacketsize; + ep1->cerr = 3; + ep1->maxburstsize = 0; + ep1->averagetrblen = ep->maxpacketsize; + ep1->base = usb_dev->ep_ctx[idx]->phys | usb_dev->ep_ctx[idx]->cycle; + uint8_t port_speed = (load_portsc & 0x3C00) >> 10; + uint8_t interval = ep->interval; + uint8_t epty = ep1->endpointtype; + + /* thanks n00byedge for tips */ + + if(port_speed == XHCI_USB_SPEED_HIGH_SPEED || port_speed == XHCI_USB_SPEED_SUPER_SPEED || port_speed == XHCI_USB_SPEED_SUPER_SPEED_PLUS) + ep1->interval = interval - 1; + else if(port_speed == XHCI_USB_SPEED_FULL_SPEED && (epty == XHCI_ENDPOINTTYPE_ISOCHRONOUS_IN || epty == XHCI_ENDPOINTTYPE_ISOCHRONOUS_OUT)) + ep1->interval = interval + 2; + else if((port_speed == XHCI_USB_SPEED_FULL_SPEED || port_speed == XHCI_USB_SPEED_LOW_SPEED) && (epty == XHCI_ENDPOINTTYPE_INTERRUPT_IN || epty == XHCI_ENDPOINTTYPE_INTERRUPT_OUT)) { + ep1->interval = log2(interval) + 4; + } + + + } else { + xhci_input_ctx64_t* input = (xhci_input_ctx64_t*)(addr + etc::hhdm()); + xhci_endpoint_ctx_t* ep1 = (xhci_endpoint_ctx_t*)(&input->ep[idx]); + klibc::memset(ep1,0,sizeof(xhci_endpoint_ctx_t)); + + input->slot.contextentries += 2; + input->input_ctx.A |= (1 << (idx + 2)); + ep1->state = 0; + ep1->endpointtype = __xhci_ep_to_type(ep); + ep1->maxpacketsize = ep->maxpacketsize; + ep1->some_shit_with_long_name_lo = ep->maxpacketsize; + ep1->cerr = 3; + ep1->maxburstsize = 0; + ep1->averagetrblen = ep->maxpacketsize; + ep1->base = (uint64_t)usb_dev->ep_ctx[idx]->phys | usb_dev->ep_ctx[idx]->cycle; + uint8_t port_speed = (load_portsc & 0x3C00) >> 10; + uint8_t interval = ep->interval; + uint8_t epty = ep1->endpointtype; + + if(port_speed == XHCI_USB_SPEED_HIGH_SPEED || port_speed == XHCI_USB_SPEED_SUPER_SPEED || port_speed == XHCI_USB_SPEED_SUPER_SPEED_PLUS) + ep1->interval = interval - 1; + else if(port_speed == XHCI_USB_SPEED_FULL_SPEED && (epty == XHCI_ENDPOINTTYPE_ISOCHRONOUS_IN || epty == XHCI_ENDPOINTTYPE_ISOCHRONOUS_OUT)) + ep1->interval = interval + 2; + else if((port_speed == XHCI_USB_SPEED_FULL_SPEED || port_speed == XHCI_USB_SPEED_LOW_SPEED) && (epty == XHCI_ENDPOINTTYPE_INTERRUPT_IN || epty == XHCI_ENDPOINTTYPE_INTERRUPT_OUT)) { + ep1->interval = log2(interval) + 4; + } + } + + break; + } + } + + i += current->len; + } + + xhci_configure_endpoints_trb_t ep_trb; + klibc::memset(&ep_trb,0,sizeof(xhci_trb_t)); + + ep_trb.info_s.type = 12; + ep_trb.base = addr; + ep_trb.info_s.slot = usb_dev->slotid; + + __xhci_clear_event(dev); + + __xhci_command_ring_queue(dev,dev->com_ring,(xhci_trb_t*)&ep_trb); + __xhci_doorbell(dev,0); + time::timer->sleep(5000); + + xhci_trb_t ret = __xhci_event_wait(dev,TRB_COMMANDCOMPLETIONEVENT_TYPE); + + if(ret.ret_code > 1) { + log("xhci","Can't configure endpoints for port %d (ret %d base %p), context_size: %d, given addr %p",portnum,ret.ret_code,ret.base,usb_dev->_is64byte,ep_trb.base); + return; + } else if(ret.ret_code == 0) { + log("xhci","Endpoint configure TRB ret_code is 0 (it shouldn't)"); + } + + __xhci_ask_for_help_hid(dev,usb_dev); + + time::timer->sleep(1000); + + log("xhci","Found USB%s Device %s (%d, %d, %d) %s %s on port %d and slot %d",dev->usb3ports[portnum] == 1 ? "3.0" : "2.0",((load_portsc & 0x3C00) >> 10) < 7 ? speed_to_str[(load_portsc & 0x3C00) >> 10] : "Broken (0 MB/S - USB ?)",(load_portsc & 0x3C00) >> 10,speed,descriptor->maxpacketsize,manufacter,product,portnum,usb_dev->slotid); + + char buffer[2048]; + klibc::memset(buffer,0,2048); + klibc::__printfbuf(buffer,2048,"%s %s",manufacter, product); + + usb_dev->evdev_num = evdev::create(buffer,usb_dev->type == USB_TYPE_KEYBOARD ? EVDEV_TYPE_KEYBOARD : EVDEV_TYPE_MOUSE); + +} + +void __xhci_init_ports(xhci_device_t* dev) { + for(std::uint32_t i = 0;i < dev->max_ports;i++) { + __xhci_init_dev(dev,i); + } +} + +void __xhci_iterate_usb_ports(xhci_device_t* dev) { + + volatile uint32_t* cap = (volatile uint32_t*)(dev->xhci_virt_base + dev->cap->hccparams1.xECP * 4); + + xhci_ext_cap_t load_cap; + load_cap.full = *cap; + //INFO("0x%p",cap); + while(1) { + //INFO("Found cap with id %d",load_cap.id); + + if(load_cap.id == 2) { + + xhci_usb_cap_t usb_cap; + + usb_cap.firsthalf = cap[0]; + usb_cap.name = cap[1]; + usb_cap.thirdhalf = cap[2]; + usb_cap.fourhalf = cap[3]; + + if(usb_cap.major == 3) { + for(uint8_t i = usb_cap.portoffset - 1;i <= (usb_cap.portoffset - 1) + usb_cap.portcount - 1;i++) { + dev->usb3ports[i] = 1; + //log("xhci","Found USB 3.0 Port %d !",i); + } + } else { + for(uint8_t i = usb_cap.portoffset - 1;i <= (usb_cap.portoffset - 1) + usb_cap.portcount - 1;i++) { + dev->usb3ports[i] = 0; + //log("xhci","Found USB 2.0 Port %d !",i); + } + } + + } else if(load_cap.id == 1) { + + log("xhci","disabling xhci hand off"); + *((volatile uint32_t*)((uint64_t)cap + 4)) &= ~((1 << 0) | (1 << 13) | (1 << 4) | (1 << 14) | (1 << 15)); + *cap |= (1 << 24); + + time::timer->sleep(500 * 1000); + + } + + + + if(!load_cap.nextcap) + break; + + + cap = (uint32_t*)((uint64_t)cap + (load_cap.nextcap * 4)); + load_cap.full = *cap; + + } +} + +xhci_hid_driver_t* hid_drv = 0; + +void xhci_hid_register(void (*func)(xhci_usb_device_t* usbdev,xhci_done_trb_t* trb),int type) { + xhci_hid_driver_t* drv = new xhci_hid_driver_t; + drv->func = func; + drv->type = type; + + if(!hid_drv) + hid_drv = drv; + else { + drv->next = hid_drv; + hid_drv = drv; + } +} + +void __xhci_process_fetch(xhci_device_t* dev) { + xhci_event_ring_ctx_t* father = dev->event_ring; + xhci_trb_t* buffer[1024]; + + while(1) { + //Paging::EnableKernel(); + int count = 0; + klibc::memset(buffer,0,sizeof(xhci_trb_t*) * 1024); + if(get_trb(father,father->queue).info_s.cycle == father->cycle) + count = __xhci_event_receive(dev,father,buffer); + + if(!count) { + process::yield(); + } + + if(count) { + xhci_trb_t* current = 0; + for(int i = 0;i < count;i++) { + current = buffer[i]; + switch(current->info_s.type) { + case TRB_TRANSFEREVENT_TYPE: { + xhci_usb_device_t* usbdev = usbdevs; + xhci_done_trb_t* trb = (xhci_done_trb_t*)current; + while(usbdev) { + if(usbdev->dev == dev) { + if(usbdev->slotid == trb->info_s.slot) { + xhci_hid_driver_t* drv = hid_drv; + while(drv) { + if((std::uint32_t)drv->type == usbdev->type) + drv->func(usbdev,trb); + drv = drv->next; + } + __xhci_ask_for_help_hid(dev,usbdev); + } + } + usbdev = usbdev->next; + } + break; + } + default: { + log("xhci","xhci unsupported trb: %d",current->info_s.type); + } + } + } + } + + } +} + +void xhci_device(std::uint64_t addr) { + + xhci_device_t* dev = (xhci_device_t*)klibc::malloc(4096); + klibc::memset(dev,0,4096); + + dev->xhci_phys_base = addr; + dev->xhci_virt_base = addr + etc::hhdm(); + paging::map_range(gobject::kernel_root,addr,addr + etc::hhdm(), PAGE_SIZE,PAGING_RW | PAGING_PRESENT | PAGING_NC); // map page + + dev->cap = (xhci_cap_regs_t*)dev->xhci_virt_base; + dev->op = (xhci_op_regs_t*)(dev->xhci_virt_base + dev->cap->caplength); + dev->runtime = (xhci_runtime_regs_t*)(dev->xhci_virt_base + dev->cap->rtsoff); + dev->doorbell = (uint32_t*)(dev->xhci_virt_base + dev->cap->dboff); + + uint32_t hcsparams1 = *(uint32_t*)(&dev->cap->hcsparams1); + + dev->max_ports = ((volatile hcsparams1_t*)&hcsparams1)->maxports; + //std::uint32_t max_slots = ((volatile hcsparams1_t*)&hcsparams1)->maxslots; + + paging::map_range(gobject::kernel_root,addr,addr + etc::hhdm(), PAGE_SIZE * 16,PAGING_RW | PAGING_PRESENT | PAGING_NC); // map full + + __xhci_put_new_device(dev); + if(dev->op->usbcmd & XHCI_USBCMD_RS) { // wtf how does it running + uint16_t timeout = XHCI_RESET_TIMEOUT; + //INFO("XHCI is already running, stopping it."); + dev->op->usbcmd &= ~(XHCI_USBCMD_RS); + time::timer->sleep(20 * 1000); + while(!(dev->op->usbsts & (1 << 0))) { + if(!timeout) { + log("xhci", "cant reset xhci device :("); + return; + } + time::timer->sleep(20 * 1000); + timeout = timeout - 1; + } + } + + uint16_t hci_version = ((*(volatile std::uint32_t*)dev->cap) >> 16) & 0xFFFF; + + uint8_t major = (hci_version >> 8) & 0xFF; + uint8_t minor = hci_version & 0xFF; + + log("xhci", "hciversion: %d.%d (0x%04x)", major, minor, hci_version); + + //DEBUG("Resetting XHCI device"); + __xhci_reset(dev); + + dev->calculated_scratchpad_count = (uint16_t)((dev->cap->hcsparams2.max_scratchpad_hi << 5) | dev->cap->hcsparams2.max_scratchpad_lo); + + //INFO("Configuring XHCI OPER"); + __xhci_setup_op(dev); + //INFO("Configuring XHCI Runtime"); + __xhci_setup_run(dev); + //INFO("Starting XHCI Device"); + __xhci_enable(dev); + //INFO("Iterating USB Ports"); + __xhci_iterate_usb_ports(dev); + //INFO("Configuring XHCI Ports"); + + log("xhci", "iterating ports"); + __xhci_init_ports(dev); + + // int pid = fork(); + // if(pid == 0) + // __xhci_process_fetch(dev); + + process::kthread((void (*)(void*))__xhci_process_fetch,(void*)dev); + log("xhci", "xhci initializied"); +} + +#if defined(__x86_64__) +void __xhci_pci_device(pci_t pci_dev,uint8_t a, uint8_t b,uint8_t c) { + if(pci_dev.progIF != 0x30) { + //INFO("Current USB device with progIF 0x%p is not XHCI !",pci_dev.progIF); + return; + } + + uint32_t usb3_ports = x86_64::pci::pci_read_config32(a,b,c,0xDC); + x86_64::pci::pci_write_config32(a,b,c,0xD8,usb3_ports); + + auto usb2_ports = x86_64::pci::pci_read_config32(a,b,c,0xD4); + x86_64::pci::pci_write_config32(a,b,c,0xD0,usb2_ports); + + uint64_t addr = pci_dev.bar0 & ~4; // clear upper 2 bits + addr |= ((uint64_t)pci_dev.bar1 << 32); + + std::uint32_t cmd = x86_64::pci::pci_read_config32(a,b,c,0x4); + log("xhci_pci", "bus mastering %d, memory access %d",(cmd & (1 << 2)) ? 1 : 0, (cmd & (1 << 1)) ? 1 : 0); + cmd |= 1 << 2; + cmd |= 1 << 1; + x86_64::pci::pci_write_config32(a,b,c,0x4,cmd); + + xhci_device(addr); +} +#endif + +char hid_to_ps2_layout[0x48]; + +int input0_fd = 0; +int mouse_fd = 0; + +void hid_layout_init() { + hid_to_ps2_layout[0x04] = 0x1E; + hid_to_ps2_layout[0x05] = 0x30; + hid_to_ps2_layout[0x06] = 0x2E; + hid_to_ps2_layout[0x07] = 0x20; + hid_to_ps2_layout[0x08] = 0x12; + hid_to_ps2_layout[0x09] = 0x21; + hid_to_ps2_layout[0x0A] = 0x22; + hid_to_ps2_layout[0x0B] = 0x23; + hid_to_ps2_layout[0x0C] = 0x17; + hid_to_ps2_layout[0x0D] = 0x24; + hid_to_ps2_layout[0x0E] = 0x25; + hid_to_ps2_layout[0x0F] = 0x26; + hid_to_ps2_layout[0x10] = 0x32; + hid_to_ps2_layout[0x11] = 0x31; + hid_to_ps2_layout[0x12] = 0x18; + hid_to_ps2_layout[0x13] = 0x19; + hid_to_ps2_layout[0x14] = 0x10; + hid_to_ps2_layout[0x15] = 0x13; + hid_to_ps2_layout[0x16] = 0x1F; + hid_to_ps2_layout[0x17] = 0x14; + hid_to_ps2_layout[0x18] = 0x16; + hid_to_ps2_layout[0x19] = 0x2F; + hid_to_ps2_layout[0x1A] = 0x11; + hid_to_ps2_layout[0x1B] = 0x2D; + hid_to_ps2_layout[0x1C] = 0x15; + hid_to_ps2_layout[0x1D] = 0x2C; + hid_to_ps2_layout[0x1E] = 0x02; + hid_to_ps2_layout[0x1F] = 0x03; + hid_to_ps2_layout[0x20] = 0x04; + hid_to_ps2_layout[0x21] = 0x05; + hid_to_ps2_layout[0x22] = 0x06; + hid_to_ps2_layout[0x23] = 0x07; + hid_to_ps2_layout[0x24] = 0x08; + hid_to_ps2_layout[0x25] = 0x09; + hid_to_ps2_layout[0x26] = 0x0A; + hid_to_ps2_layout[0x27] = 0x0B; + hid_to_ps2_layout[0x28] = 0x1C; + hid_to_ps2_layout[0x29] = 0x01; + hid_to_ps2_layout[0x2A] = 0x0E; + hid_to_ps2_layout[0x2B] = 0x0F; + hid_to_ps2_layout[0x2C] = 0x39; + hid_to_ps2_layout[0x2D] = 0x0C; + hid_to_ps2_layout[0x2E] = 0x0D; + hid_to_ps2_layout[0x2F] = 0x1A; + hid_to_ps2_layout[0x30] = 0x1B; + hid_to_ps2_layout[0x31] = 0x2B; + hid_to_ps2_layout[0x32] = 0x2B; + hid_to_ps2_layout[0x33] = 0x27; + hid_to_ps2_layout[0x34] = 0x28; + hid_to_ps2_layout[0x35] = 0x29; + hid_to_ps2_layout[0x36] = 0x33; + hid_to_ps2_layout[0x37] = 0x34; + hid_to_ps2_layout[0x38] = 0x35; + hid_to_ps2_layout[0x39] = 0x3A; + hid_to_ps2_layout[0x3B] = 0x3C; + hid_to_ps2_layout[0x3C] = 0x3D; + hid_to_ps2_layout[0x3D] = 0x3E; + hid_to_ps2_layout[0x3E] = 0x3F; + hid_to_ps2_layout[0x3F] = 0x40; + hid_to_ps2_layout[0x40] = 0x41; + hid_to_ps2_layout[0x41] = 0x42; + hid_to_ps2_layout[0x42] = 0x43; + hid_to_ps2_layout[0x43] = 0x44; + hid_to_ps2_layout[0x44] = 0x57; + hid_to_ps2_layout[0x45] = 0x58; + hid_to_ps2_layout[0x46] = 0x00; + hid_to_ps2_layout[0x47] = 0x46; +} + +void input_send(int num, uint8_t key) { + + std::uint64_t current_nano = time::timer->current_nano(); + + input_event ev; + ev.time.tv_sec = current_nano / 1000000000; + ev.time.tv_usec = (current_nano & 1000000000) / 1000; + ev.type = 1; + ev.code = key & ~(1 << 7); + ev.value = (key & (1 << 7)) ? 0 : 1; + evdev::submit(num,ev); +} + +uint8_t hid_mods_to_ps2[8] = { + 0x1D, + 0x2A, + 0x38, + 0x5B, + 0x1D, + 0x36, + 0x38, + 0x5C +}; + +void __usbkeyboard_handler(xhci_usb_device_t* usbdev, xhci_done_trb_t* trb) { + uint8_t* data = usbdev->buffers[trb->info_s.ep_id - 2]; + uint8_t mods = data[0]; + uint8_t prev_mods = usbdev->add_buffer[0]; + + for (int i = 0; i < 8; i++) { + uint8_t mask = 1 << i; + if ((mods & mask) && !(prev_mods & mask)) { + if (i >= 4) input_send(usbdev->evdev_num, 0xE0); + input_send(usbdev->evdev_num, hid_mods_to_ps2[i]); + } else if (!(mods & mask) && (prev_mods & mask)) { + if (i >= 4) input_send(usbdev->evdev_num, 0xE0); + input_send(usbdev->evdev_num, hid_mods_to_ps2[i] | 0x80); + } + } + + for (int i = 2; i < 8; i++) { + int isPressed = 0; + for (int j = 2; j < 8; j++) { + if (usbdev->add_buffer[j] == data[i]) { + isPressed = 1; + break; + } + } + if (!isPressed && data[i] != 0) { + if (data[i] < 0x47) { + input_send(usbdev->evdev_num, hid_to_ps2_layout[data[i]]); + } else if(data[i] == 0x4F) { + input_send(usbdev->evdev_num, 0xE0); + input_send(usbdev->evdev_num, 0x4D); + } else if(data[i] == 0x50) { + input_send(usbdev->evdev_num, 0xE0); + input_send(usbdev->evdev_num, 0x4B); + } else if(data[i] == 0x51) { + input_send(usbdev->evdev_num, 0xE0); + input_send(usbdev->evdev_num, 0x50); + } else if(data[i] == 0x52) { + input_send(usbdev->evdev_num, 0xE0); + input_send(usbdev->evdev_num, 0x48); + } + } + } + + for (int i = 2; i < 8; i++) { + int isStillPressed = 0; + for (int j = 2; j < 8; j++) { + if (usbdev->add_buffer[i] == data[j]) { + isStillPressed = 1; + break; + } + } + if (!isStillPressed && usbdev->add_buffer[i] != 0) { + input_send(usbdev->evdev_num, hid_to_ps2_layout[usbdev->add_buffer[i]] | 0x80); + } else if(usbdev->add_buffer[i] == 0x4F) { + input_send(usbdev->evdev_num, 0xE0 | 0x80); + input_send(usbdev->evdev_num, 0x4D | 0x80); + } else if(usbdev->add_buffer[i] == 0x50) { + input_send(usbdev->evdev_num, 0xE0 | 0x80); + input_send(usbdev->evdev_num, 0x4B | 0x80); + } else if(usbdev->add_buffer[i] == 0x51) { + input_send(usbdev->evdev_num, 0xE0 | 0x80); + input_send(usbdev->evdev_num, 0x50 | 0x80); + } else if(usbdev->add_buffer[i] == 0x52) { + input_send(usbdev->evdev_num, 0xE0 | 0x80); + input_send(usbdev->evdev_num, 0x48 | 0x80); + } + } + + klibc::memcpy(usbdev->add_buffer, data, 8); +} + + +#define MOUSE_LB (1 << 0) +#define MOUSE_RB (1 << 1) +#define MOUSE_MB (1 << 2) +#define MOUSE_B4 (1 << 3) +#define MOUSE_B5 (1 << 4) + +/* +input0_fd = open("/dev/masterps2keyboard",O_RDWR); + mouse_fd = open("/dev/mastermouse",O_RDWR); +*/ + +#define REL_X 0x00 +#define REL_Y 0x01 +#define REL_Z 0x02 +#define REL_RX 0x03 +#define REL_RY 0x04 +#define REL_RZ 0x05 +#define REL_HWHEEL 0x06 +#define REL_DIAL 0x07 +#define REL_WHEEL 0x08 +#define REL_MISC 0x09 + +void __usbmouse_handler(xhci_usb_device_t* usbdev, xhci_done_trb_t* trb) { + uint8_t* data = usbdev->buffers[trb->info_s.ep_id - 2]; + + mouse_packet_t packet; + + packet.buttons = 0; + + packet.buttons |= (data[0] & (1 << 0)) ? MOUSE_LB : 0; + packet.buttons |= (data[0] & (1 << 1)) ? MOUSE_RB : 0; + packet.buttons |= (data[0] & (1 << 2)) ? MOUSE_MB : 0; + + packet.x = data[1]; + packet.y = -data[2]; + packet.z = 0; // todo: figure out how to get mouse scroll wheel data + + std::uint64_t current_nano = time::timer->current_nano(); + input_event ev; + ev.time.tv_sec = current_nano / 1000000000; + ev.time.tv_usec = (current_nano & 1000000000) / 1000; + if(packet.x) { + ev.code = REL_X; + ev.type = 2; + ev.value = (packet.x & 0x80) ? (packet.x | 0xFFFFFF00) : packet.x; + evdev::submit(usbdev->evdev_num,ev); + } + + if(packet.y) { + ev.code = REL_Y; + ev.type = 2; + ev.value = (packet.y & 0x80) ? (packet.y | 0xFFFFFF00) : packet.y; + evdev::submit(usbdev->evdev_num,ev); + } + + if(packet.z) { + ev.code = REL_Z; + ev.type = 2; + ev.value = (packet.z & 0x80) ? (packet.z | 0xFFFFFF00) : packet.z; + evdev::submit(usbdev->evdev_num,ev); + } + + if((packet.buttons & MOUSE_LB) && !(usbdev->last_pack.buttons & MOUSE_LB)) { + ev.code = 272; + ev.type = 1; + ev.value = 1; + evdev::submit(usbdev->evdev_num,ev); + } else if(!(packet.buttons & MOUSE_LB) && (usbdev->last_pack.buttons & MOUSE_LB)) { + ev.code = 272; + ev.type = 1; + ev.value = 0; + evdev::submit(usbdev->evdev_num,ev); + } + + if((packet.buttons & MOUSE_RB) && !(usbdev->last_pack.buttons & MOUSE_RB)) { + ev.code = 273; + ev.type = 1; + ev.value = 1; + evdev::submit(usbdev->evdev_num,ev); + } else if(!(packet.buttons & MOUSE_RB) && (usbdev->last_pack.buttons & MOUSE_RB)) { + ev.code = 273; + ev.type = 1; + ev.value = 0; + evdev::submit(usbdev->evdev_num,ev); + } + + if((packet.buttons & MOUSE_MB) && !(usbdev->last_pack.buttons & MOUSE_MB)) { + ev.code = 274; + ev.type = 1; + ev.value = 1; + evdev::submit(usbdev->evdev_num,ev); + } else if(!(packet.buttons & MOUSE_MB) && (usbdev->last_pack.buttons & MOUSE_MB)) { + ev.code = 274; + ev.type = 1; + ev.value = 0; + evdev::submit(usbdev->evdev_num,ev); + } + + usbdev->last_pack = packet; + + time::timer->sleep(1000); // actually hid wants this only after 1 ms + +} + +int xhci_init() { + + xhci_hid_register(__usbkeyboard_handler,USB_TYPE_KEYBOARD); + xhci_hid_register(__usbmouse_handler,USB_TYPE_MOUSE); + + hid_layout_init(); + +#if defined(__x86_64__) + x86_64::pci::reg(__xhci_pci_device,0x0C,0x03); +#endif + return 0; +} \ No newline at end of file diff --git a/kernel/src/drivers/xhci.hpp b/kernel/src/drivers/xhci.hpp new file mode 100644 index 0000000..c76a3c9 --- /dev/null +++ b/kernel/src/drivers/xhci.hpp @@ -0,0 +1,707 @@ +#include + +#pragma once + +#define XHCI_RESET_TIMEOUT 1000 + +typedef struct { + unsigned char buttons; + unsigned char x; + unsigned char y; + unsigned char z; +} __attribute__((packed)) mouse_packet_t; + +typedef struct { + uint32_t maxslots : 8; + uint32_t maxintrs : 11; + uint32_t reserved1 : 5; + uint32_t maxports : 8; +} __attribute__((packed)) hcsparams1_t; + +typedef struct { + uint32_t ist : 4; + uint32_t erstmax : 4; + uint32_t reserved1 : 13; + uint32_t max_scratchpad_hi : 5; + uint32_t spr : 1; + uint32_t max_scratchpad_lo : 5; +} __attribute__((packed)) hcsparams2_t; + +typedef struct { + uint32_t _64bitcap : 1; + uint32_t bnc : 1; + uint32_t contextsize : 1; + uint32_t portpowercontrol : 1; + uint32_t portindicator : 1; + uint32_t lhrc : 1; + uint32_t ltc : 1; + uint32_t nss : 1; + uint32_t pae : 1; + uint32_t spc : 1; + uint32_t sec : 1; + uint32_t cfc : 1; + uint32_t max_psa_size : 4; + uint32_t xECP : 16; +} __attribute__((packed)) hccparams1_t; + +typedef struct { + uint8_t caplength; + uint8_t reserved; + uint16_t hciversion; + hcsparams1_t hcsparams1; + hcsparams2_t hcsparams2; + uint32_t hcsparams3; + hccparams1_t hccparams1; + uint32_t dboff; + uint32_t rtsoff; + uint32_t hccparms2; +} xhci_cap_regs_t; + +typedef struct { + uint32_t usbcmd; + uint32_t usbsts; + uint32_t pagesize; + uint32_t reserved1[2]; + uint32_t dnctrl; + uint64_t crcr; + uint32_t reserved2[4]; + uint64_t dcbaap; + uint32_t config; +} xhci_op_regs_t; + +#define XHCI_USBCMD_RS (1 << 0) +#define XHCI_USBCMD_HOSTCONTROLLERREST (1 << 1) +#define XHCI_USB_SPEED_FULL_SPEED 1 +#define XHCI_USB_SPEED_LOW_SPEED 2 +#define XHCI_USB_SPEED_HIGH_SPEED 3 +#define XHCI_USB_SPEED_SUPER_SPEED 4 +#define XHCI_USB_SPEED_SUPER_SPEED_PLUS 5 + +typedef struct { + uint32_t portsc; + uint32_t portpmsc; + uint32_t portli; +} xhci_port_regs_t; + +typedef struct { + uint64_t erst_segment : 3; + uint64_t event_busy : 1; + uint64_t event_ring_pointer : 60; +} xhci_erdp_t; + +typedef struct { + uint32_t iman; + uint32_t imod; + uint32_t erstsz; + uint32_t reserved0; + uint64_t erstba; + union { + xhci_erdp_t erdp; + uint64_t erdp_val; + }; +} IR_t; + +typedef struct { + uint32_t mfindex; + uint32_t reserved1[7]; + IR_t int_regs[1024]; +} xhci_runtime_regs_t; + +typedef struct { + uint64_t base; + uint32_t size; + uint32_t reserved0; +} xhci_erst_t; + +typedef struct { + uint32_t cycle : 1; + uint32_t nexttrb : 1; + uint32_t interruptonshort : 1; + uint32_t nosnoop : 1; + uint32_t chain : 1; + uint32_t intoncompletion : 1; + uint32_t immediate : 1; + uint32_t reserved1 : 2; + uint32_t blockeventint : 1; + uint32_t type : 6; + uint32_t reserved2 : 16; +} xhci_trb_info_t; + +typedef struct { + uint64_t base; + union { + struct { + uint32_t reserved0 : 24; + uint32_t ret_code : 8; + }; + uint32_t status; + }; + union { + xhci_trb_info_t info_s; + uint32_t info; + }; +} xhci_trb_t; + +typedef struct { + uint32_t cycle : 1; + uint32_t reserved1 : 9; + uint32_t type : 6; + uint32_t vfid : 8; + uint32_t slotid : 8; +} xhci_slot_info_trb_t; + +typedef struct { + uint64_t base; + uint32_t CCP : 24; + uint32_t ret_code : 8; + union { + xhci_slot_info_trb_t info_s; + uint32_t info; + }; +} xhci_slot_trb_t; + +typedef struct { + uint32_t cycle : 1; + uint32_t reserved0 : 8; + uint32_t bsr : 1; + uint32_t type : 6; + uint8_t reserved1; + uint8_t slotid; +} xhci_set_addr_info_trb_t; + +typedef struct { + uint64_t base; + uint32_t status; + union { + xhci_set_addr_info_trb_t info_s; + uint32_t info; + }; +} xhci_set_addr_trb_t; + +typedef struct { + uint8_t cycle; + uint16_t trb_limit; + uint64_t queue; + uint64_t phys; + xhci_trb_t* trb; +} xhci_command_ring_ctx_t; + +typedef struct { + uint16_t trb_limit; + uint64_t queue; + uint8_t cycle; + volatile IR_t* father; + xhci_trb_t* trb; + xhci_erst_t* table; +} xhci_event_ring_ctx_t; + +typedef struct { + uint16_t trb_limit; + uint64_t queue; + uint8_t cycle; + uint32_t slot; + uint64_t phys; + xhci_trb_t* trb; +} xhci_port_ring_ctx_t; + +typedef struct { + uint32_t D; + uint32_t A; + uint32_t reserved0[5]; + uint8_t configvalue; + uint8_t interfacenum; + uint8_t altsetting; + uint8_t reserved1; +} __attribute__((packed)) xhci_input_control_ctx_t; + +typedef struct { + uint32_t D; + uint32_t A; + uint32_t reserved0[5]; + uint8_t configvalue; + uint8_t interfacenum; + uint8_t altsetting; + uint8_t reserved1; + uint32_t align[8]; +} __attribute__((packed)) xhci_input_control_ctx64_t; + +typedef struct { + uint32_t routestring : 20; + uint8_t speed : 4; + uint8_t reserved0 : 1; + uint8_t multitt : 1; + uint8_t hub : 1; + uint8_t contextentries : 5; + uint16_t maxexitlat; + uint8_t porthubnum; + uint8_t numofports; + uint8_t parenthubslot; + uint8_t parentportnum; + uint8_t thinktime : 2; + uint8_t reserved1 : 4; + uint16_t irtarget : 10; + uint8_t address; + uint32_t reserved2 : 19; + uint8_t slotstate : 5; + uint32_t reserved3[4]; +} __attribute__((packed)) xhci_slot_ctx_t; + +typedef struct { + uint32_t routestring : 20; + uint8_t speed : 4; + uint8_t reserved0 : 1; + uint8_t multitt : 1; + uint8_t hub : 1; + uint8_t contextentries : 5; + uint16_t maxexitlat; + uint8_t porthubnum; + uint8_t numofports; + uint8_t parenthubslot; + uint8_t parentportnum; + uint8_t thinktime : 2; + uint8_t reserved1 : 4; + uint16_t irtarget : 10; + uint8_t address; + uint32_t reserved2 : 19; + uint8_t slotstate : 5; + uint32_t reserved3[4]; + uint32_t align[8]; +} __attribute__((packed)) xhci_slot_ctx64_t; + +typedef struct { + uint32_t state : 3; + uint32_t reserved0 : 5; + uint32_t mult : 2; + uint32_t maxprimarystreams : 5; + uint32_t linear : 1; + uint32_t interval : 8; + uint32_t some_shit_with_long_name : 8; + uint32_t reserved1 : 1; + uint32_t cerr : 2; + uint32_t endpointtype : 3; + uint32_t reserved2 : 1; + uint32_t hid : 1; + uint32_t maxburstsize : 8; + uint32_t maxpacketsize : 16; + uint64_t base; + uint16_t averagetrblen; + uint16_t some_shit_with_long_name_lo; + uint32_t align[3]; +} __attribute__((packed)) xhci_endpoint_ctx_t; + +typedef struct { + uint32_t state : 3; + uint32_t reserved0 : 5; + uint32_t mult : 2; + uint32_t maxprimarystreams : 5; + uint32_t linear : 1; + uint32_t interval : 8; + uint32_t some_shit_with_long_name : 8; + uint32_t reserved1 : 1; + uint32_t cerr : 2; + uint32_t endpointtype : 3; + uint32_t reserved2 : 1; + uint32_t hid : 1; + uint32_t maxburstsize : 8; + uint32_t maxpacketsize : 16; + uint64_t base; + uint16_t averagetrblen; + uint16_t some_shit_with_long_name_lo; + uint32_t align[11]; +} __attribute__((packed)) xhci_endpoint_ctx64_t; + +typedef struct { + xhci_input_control_ctx_t input_ctx; + xhci_slot_ctx_t slot; + xhci_endpoint_ctx_t ep0; + xhci_endpoint_ctx_t ep[30]; +} __attribute__((packed)) xhci_input_ctx_t; + +typedef struct { + xhci_input_control_ctx64_t input_ctx; + xhci_slot_ctx64_t slot; + xhci_endpoint_ctx64_t ep0; + xhci_endpoint_ctx64_t ep[30]; +} __attribute__((packed)) xhci_input_ctx64_t; + +typedef struct { + uint8_t len; + uint8_t type; +} xhci_usb_descriptor_header; + +typedef struct { + xhci_usb_descriptor_header head; + uint16_t usb; + uint8_t deviceclass; + uint8_t devicesubclass; + uint8_t protocol; + uint8_t maxpacketsize; + uint16_t vendor; + uint16_t product0; + uint16_t device; + uint8_t manufacter; + uint8_t product1; + uint8_t serialnum; + uint8_t numconfigs; +} xhci_usb_descriptor_t; + +typedef struct { + xhci_usb_descriptor_header head; + uint16_t lang[128]; +} xhci_lang_descriptor_t; + +typedef struct { + xhci_usb_descriptor_header head; + uint16_t str[128]; +} xhci_string_descriptor_t; + +typedef struct { + xhci_usb_descriptor_header head; + uint16_t len; + uint8_t numinterfaces; + uint8_t configval; + uint8_t config; + uint8_t attributes; + uint8_t maxpower; + uint8_t data[1024]; +} xhci_config_descriptor_t; + +typedef struct { + uint8_t desctype; + uint8_t desclen; +} xhci_hid_sub_desc; + +typedef struct { + xhci_usb_descriptor_header head; + uint16_t hid; + uint8_t country; + uint8_t numdesc; + xhci_hid_sub_desc desc[1024]; +} xhci_hid_descriptor_t; + +typedef struct { + xhci_usb_descriptor_header head; + uint8_t endpointaddr; + uint8_t attributes; + uint16_t maxpacketsize; + uint8_t interval; +} xhci_endpoint_descriptor_t; + +typedef struct { + xhci_usb_descriptor_header head; + uint8_t num; + uint8_t altsetting; + uint8_t numendpoints; + uint8_t interclass; + uint8_t intersubclass; + uint8_t protocol; + uint8_t interface; +} xhci_interface_descriptor_t; + +typedef struct { + uint32_t cycle : 1; + uint32_t reserved0 : 8; + uint32_t deconfigure : 1; + uint32_t type : 6; + uint32_t reserved1 : 8; + uint32_t slot : 8; +} xhci_configure_endpoints_info_trb_t; + +typedef struct { + uint64_t base; + uint32_t status; + union { + xhci_configure_endpoints_info_trb_t info_s; + uint32_t info; + }; +} xhci_configure_endpoints_trb_t; + +typedef struct xhci_device { + uint64_t xhci_phys_base; + uint64_t xhci_virt_base; + uint64_t* dcbaa; + uint16_t calculated_scratchpad_count; + volatile xhci_cap_regs_t* cap; + volatile xhci_op_regs_t* op; + volatile xhci_port_regs_t* port; + volatile xhci_runtime_regs_t* runtime; + volatile uint32_t* doorbell; + xhci_command_ring_ctx_t* com_ring; + xhci_event_ring_ctx_t* event_ring; + + uint32_t max_ports; + + uint8_t usb3ports[64]; + + struct xhci_device* next; +} __attribute__((packed)) xhci_device_t; + +typedef struct { + uint32_t type : 6; // TRB_TYPE = 0b100000 (32) + uint32_t reserved : 26; + uint32_t cycle : 1; +} __attribute__((packed)) xhci_noop_trb_t; + +typedef struct xhci_interface { + uint8_t type; + void* data; + + uint64_t len; + void* buffer; + + xhci_interface* next; +} xhci_interface_t; + +#define USB_TYPE_KEYBOARD 4 +#define USB_TYPE_MOUSE 3 + +typedef struct xhci_usb_device { + xhci_port_ring_ctx_t* transfer_ring; + xhci_usb_descriptor_t* desc; + xhci_config_descriptor_t* config; + xhci_device_t* dev; + xhci_input_ctx_t* input_ctx; + xhci_port_ring_ctx_t* ep_ctx[30]; + uint64_t phys_buffers[30]; + uint8_t* buffers[30]; + uint8_t main_ep; + uint16_t buffers_need_size[30]; + uint8_t doorbell_values[30]; + xhci_interface_t* interface; + struct xhci_usb_device* next; + uint64_t phys_input_ctx; + uint32_t slotid; + uint32_t portnum; + uint32_t type; + uint8_t _is64byte; + mouse_packet_t last_pack; + int evdev_num; + uint8_t add_buffer[8]; +} xhci_usb_device_t; + +typedef struct { + uint32_t cycle : 1; + uint32_t reserved0 : 1; + uint32_t eventdata : 1; + uint32_t reserved1 : 7; + uint32_t type : 6; + uint32_t ep_id : 5; + uint32_t reserved2 : 3; + uint32_t slot : 8; +} xhci_done_info_trb_t; + +typedef struct { + uint64_t base; + struct { + uint32_t seek : 24; + uint32_t ret_code : 8; + }; + union { + xhci_done_info_trb_t info_s; + uint32_t info; + }; +} xhci_done_trb_t; + +typedef struct { + union { + struct { + uint8_t id; + uint8_t nextcap; + uint16_t info; + }; + uint32_t full; + }; +} xhci_ext_cap_t; + +typedef struct { + union { + struct { + uint8_t id; + uint8_t nextcap; + uint8_t minor; + uint8_t major; + }; + uint32_t firsthalf; + }; + + uint32_t name; + + union { + struct { + uint8_t portoffset; + uint8_t portcount; + uint8_t protocoldefine; + uint8_t protocolspeedid; + }; + uint32_t thirdhalf; + }; + + union { + struct { + uint8_t slottype : 4; + uint32_t reserved0 : 28; + }; + uint32_t fourhalf; + }; +} xhci_usb_cap_t; + +typedef struct { + uint8_t type; + uint8_t request; + uint16_t value; + uint16_t index; + uint16_t len; +} xhci_usb_command_t; + +typedef struct { + xhci_usb_command_t command; + uint32_t len : 17; + uint32_t reserved0 : 5; + uint32_t target : 10; + uint32_t cycle : 1; + uint32_t reserved1 : 3; + uint32_t chain : 1; + uint32_t intoncomp : 1; + uint32_t imdata : 1; + uint32_t reserved2 : 3; + uint32_t type : 6; + uint32_t trt : 2; + uint32_t reserved3 : 14; +} xhci_setupstage_trb_t; + +typedef struct { + uint64_t data; + uint32_t len : 17; + uint32_t tdsize : 5; + uint32_t target : 10; + uint32_t cycle : 1; + uint32_t evnexttrb : 1; + uint32_t intrshortpacket : 1; + uint32_t nosnoop : 1; + uint32_t chain : 1; + uint32_t introncomp : 1; + uint32_t imdata : 1; + uint32_t reserved0 : 3; + uint32_t type : 6; + uint32_t direction : 1; + uint32_t reserved1 : 15; +} xhci_datastage_trb_t; + +typedef struct { + uint64_t base; + uint32_t reserved0 : 22; + uint32_t target : 10; + uint32_t cycle : 1; + uint32_t evnext : 1; + uint32_t reserved1 : 2; + uint32_t chain : 1; + uint32_t intoncomp : 1; + uint32_t reserved2 : 3; + uint32_t blockevent : 1; + uint32_t type : 6; + uint32_t reserved3 : 16; +} xhci_eventdata_trb_t; + +typedef struct { + uint64_t reserved0; + uint32_t reserved1 : 22; + uint32_t target : 10; + uint32_t cycle : 1; + uint32_t evnext : 1; + uint32_t reserved2 : 2; + uint32_t chain : 1; + uint32_t intoncomp : 1; + uint32_t reserved3 : 4; + uint32_t type : 6; + uint32_t direction : 1; + uint32_t reserved4 : 15; +} xhci_statusstage_trb_t; + +typedef struct { + uint32_t cycle : 1; + uint32_t ent : 1; + uint32_t isp : 1; + uint32_t nosnoop : 1; + uint32_t chain : 1; + uint32_t ioc : 1; + uint32_t imdata : 1; + uint32_t reserved0 : 2; + uint32_t bei : 1; + uint32_t type : 6; + uint32_t dir : 1; + uint32_t reserved1 : 15; +} xhci_normal_info_trb_t; + +typedef struct { + uint64_t base; + uint32_t trbtransferlen : 17; + uint32_t tdsize : 5; + uint32_t target : 10; + union { + xhci_normal_info_trb_t info_s; + uint32_t info; + }; +} xhci_normal_trb_t; + +typedef struct { + uint32_t cycle : 1; + uint32_t reserved0 : 9; + uint32_t type : 6; + uint32_t reserved1 : 16; +} xhci_port_change_info_t; + +typedef struct { + struct { + uint32_t reserved0 : 24; + uint32_t port : 8; + }; + uint32_t status; + union { + xhci_port_change_info_t info_s; + uint32_t info; + }; +} xhci_port_change_trb_t; + +typedef struct xhci_hid_driver { + void (*func)(xhci_usb_device_t* usbdev,xhci_done_trb_t* trb); + int type; + struct xhci_hid_driver* next; +} xhci_hid_driver_t; + +#define XHCI_ENDPOINTTYPE_ISOCHRONOUS_OUT 1 +#define XHCI_ENDPOINTTYPE_BULK_OUT 2 +#define XHCI_ENDPOINTTYPE_INTERRUPT_OUT 3 +#define XHCI_ENDPOINTTYPE_ISOCHRONOUS_IN 5 +#define XHCI_ENDPOINTTYPE_BULK_IN 6 +#define XHCI_ENDPOINTTYPE_INTERRUPT_IN 7 +#define TRB_NORMAL_TYPE 1 +#define TRB_SETUPSTAGE_TYPE 2 +#define TRB_DATASTAGE_TYPE 3 +#define TRB_STATUSSTAGE_TYPE 4 +#define TRB_ISOCH_TYPE 5 +#define TRB_LINK_TYPE 6 +#define TRB_EVENTDATA_TYPE 7 +#define TRB_NOOP_TYPE 8 +#define TRB_ENABLESLOTCOMMAND_TYPE 9 +#define TRB_DISABLESLOTCOMMAND_TYPE 10 +#define TRB_ADDRESSDEVICECOMMAND_TYPE 11 +#define TRB_CONFIGUREENDPOINTCOMMAND_TYPE 12 +#define TRB_EVALUATECONTEXTCOMMAND_TYPE 13 +#define TRB_RESETENDPOINTCOMMAND_TYPE 14 +#define TRB_STOPENDPOINTCOMMAND_TYPE 15 +#define TRB_SETTRDEQPOINTERCOMMAND_TYPE 16 +#define TRB_RESETDEVICECOMMAND_TYPE 17 +#define TRB_FORCEEVENTCOMMAND_TYPE 18 +#define TRB_NEGBANDWIDTHCOMMAND_TYPE 19 +#define TRB_SETLATENCYCOMMAND_TYPE 20 +#define TRB_GETPORTBANDWIDTHCOMMAND_TYPE 21 +#define TRB_FORCEHEADERCOMMAND_TYPE 22 +#define TRB_NOOPCOMMAND_TYPE 23 +#define TRB_TRANSFEREVENT_TYPE 32 +#define TRB_COMMANDCOMPLETIONEVENT_TYPE 33 +#define TRB_PORTSTATUSCHANGEEVENT_TYPE 34 +#define TRB_HOSTCONTROLLEREVENT_TYPE 37 +#define TRB_DEVICENOTIFICATIONEVENT_TYPE 38 +#define TRB_MFINDEXWARPEVENT_TYPE 39 + +int xhci_init(); \ No newline at end of file diff --git a/kernel/src/generic/devfs.cpp b/kernel/src/generic/devfs.cpp index e69de29..9b7dc1d 100644 --- a/kernel/src/generic/devfs.cpp +++ b/kernel/src/generic/devfs.cpp @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +devfs_node* head_devfs_node = nullptr; +devfs_node root_devfs_node = {}; + +std::atomic devfs_id = 0; + +locks::preempt_spinlock devfs_lock; + +devfs_node* devfs_lookup(char* path) { + + if(klibc::strcmp(path,"/\0") == 0) + return &root_devfs_node; + + bool state = devfs_lock.lock(); + devfs_node* current_node = head_devfs_node; + while(current_node != nullptr) { + if(klibc::strcmp(current_node->path, path) == 0) { + devfs_lock.unlock(state); + return current_node; + } + } + devfs_lock.unlock(state); + return nullptr; +} + +void create(bool is_tty, char* path, void* arg, std::uint64_t mmap, std::uint64_t mmap_size, std::int32_t (*open)(file_descriptor*fd, devfs_node* node), std::int32_t (*ioctl)(devfs_node* node, std::uint64_t req, void* arg), signed long (*read)(file_descriptor* fd, devfs_node* node, void* buffer, std::size_t count), signed long (*write)(file_descriptor* fd, devfs_node* node, void* buffer, std::size_t count), bool (*poll)(devfs_node* node, vfs_poll_type type), std::int32_t (*close)(file_descriptor* fd, devfs_node* node)) { + bool state = devfs_lock.lock(); + + assert(devfs_lookup(path) == nullptr," afdsfsdfsf!!!"); + + devfs_node* new_node = (devfs_node*)(pmm::freelist::alloc_4k() + etc::hhdm()); + new_node->mmap = mmap; + new_node->mmap_size = mmap_size; + new_node->open = open; + new_node->write = write; + new_node->read = read; + new_node->poll = poll; + new_node->close = close; + new_node->ioctl = ioctl; + new_node->arg = arg; + new_node->is_a_tty = is_tty; + new_node->id = ++devfs_id; + + new_node->next = head_devfs_node; + head_devfs_node = new_node; + + devfs_lock.unlock(state); +} + +std::int32_t devfs_ioctl(file_descriptor* file, std::uint64_t req, void* arg) { + auto node = (devfs_node*)file->fs_specific.tmpfs_pointer; + if(node->ioctl == nullptr) + return -ENOTSUP; + return node->ioctl(node, req, arg); +} + +signed long devfs_read(file_descriptor* fd, void* buffer, std::size_t count) { + auto node = (devfs_node*)fd->fs_specific.tmpfs_pointer; + if(node->read == nullptr) + return -ENOTSUP; + return node->read(fd, node, buffer, count); +} + +signed long devfs_write(file_descriptor* fd, void* buffer, std::size_t count) { + auto node = (devfs_node*)fd->fs_specific.tmpfs_pointer; + if(node->write == nullptr) + return -ENOTSUP; + return node->write(fd, node, buffer, count); +} + +std::int32_t devfs_stat(file_descriptor* file, stat* out) { + if(((devfs_node*)file->other.ls_pointer)->is_root == true) { + out->st_mode = S_IFDIR | 0666; + return 0; + } + (void)file; + (void)out; + out->st_mode = S_IFCHR | 0666; + return 0; +} + +bool devfs_poll(file_descriptor* file, vfs_poll_type type) { + auto node = (devfs_node*)file->fs_specific.tmpfs_pointer; + if(node->poll == nullptr) + return false; + return node->poll(node, type); +} + +std::int32_t devfs_mmap(file_descriptor* file, std::uint64_t* out_phys, std::size_t* out_size) { + auto node = (devfs_node*)file->fs_specific.tmpfs_pointer; + if(node->mmap == 0) + return -EINVAL; + *out_phys = node->mmap; + *out_size = node->mmap_size; + return 0; +} + +void devfs_close(file_descriptor* file) { + auto node = (devfs_node*)file->fs_specific.tmpfs_pointer; + if(node->close == nullptr) + return; + node->close(file, node); + return; +} + +signed long devfs_ls(file_descriptor* file, char* out, std::size_t count) { + bool state = devfs_lock.lock(); + dirent* dir = (dirent*)out; + if(file->other.ls_pointer == nullptr) { + devfs_lock.unlock(state); + return 0; + } else if(file->other.ls_pointer == (void*)1) { + file->other.ls_pointer = (void*)head_devfs_node; + } + + devfs_node* node = (devfs_node*)file->other.ls_pointer; + + if(count < sizeof(dirent) + 1 + klibc::strlen(node->path)) { + devfs_lock.unlock(state); + return 0; + } + + dir->d_ino = node->id; + dir->d_reclen = sizeof(dirent) + 1 + klibc::strlen(node->path + 1); + dir->d_type = DT_CHR; + dir->d_off = 0; + klibc::memcpy(dir->d_name, node->path + 1, klibc::strlen(node->path + 1) + 1); + + file->other.ls_pointer = (void*)(node->next); + + devfs_lock.unlock(state); + return dir->d_reclen; +} + +std::int32_t devfs_open(filesystem* fs, void* file_desc, char* path, bool is_directory) { + (void)fs; + auto node = devfs_lookup(path); + + if(node == nullptr) + return -EINVAL; + + file_descriptor* fd = (file_descriptor*)file_desc; + if(node->is_root && is_directory) { + fd->vnode.stat = devfs_stat; + fd->vnode.ls = devfs_ls; + fd->other.ls_pointer = (void*)1; + fd->fs_specific.tmpfs_pointer = (std::uint64_t)(&root_devfs_node); + return 0; + } + + fd->vnode.stat = devfs_stat; + fd->vnode.ioctl = devfs_ioctl; + fd->vnode.poll = devfs_poll; + fd->vnode.mmap = devfs_mmap; + fd->vnode.read = devfs_read; + fd->vnode.write = devfs_write; + fd->vnode.close = devfs_close; + fd->other.is_a_tty = node->is_a_tty; + fd->fs_specific.tmpfs_pointer = (std::uint64_t)node; + + if(node->open) + node->open(fd, node); + + return 0; + +} + +std::int32_t devfs_readlink(filesystem* fs, char* path, char* buffer) { + (void)fs; + (void)path; + (void)buffer; + return -EINVAL; +} + +std::int32_t devfs_create(filesystem* fs, char* path, vfs_file_type type, std::uint32_t mode) { + (void)fs; + (void)path; + (void)type; + (void)mode; + return -ENOTSUP; +} + +std::int32_t devfs_remove(filesystem* fs, char* path) { + (void)fs; + (void)path; + return -ENOTSUP; +} + +void init(vfs::node* new_node) { + root_devfs_node.is_root = true; + new_node->fs->create = devfs_create; + new_node->fs->open = devfs_open; + new_node->fs->readlink = devfs_readlink; + new_node->fs->remove = devfs_remove; + klibc::memcpy(new_node->path, "/dev\0", sizeof("/dev\0") + 1); +} \ No newline at end of file diff --git a/kernel/src/generic/devfs.hpp b/kernel/src/generic/devfs.hpp index 2c91d83..5497b88 100644 --- a/kernel/src/generic/devfs.hpp +++ b/kernel/src/generic/devfs.hpp @@ -3,11 +3,36 @@ #include struct devfs_node { - vfs::pipe* pipe; + vfs::pipe* write_pipe; + vfs::pipe* read_pipe; + + std::int32_t (*open)(file_descriptor* fd, devfs_node* node); + std::int32_t (*ioctl)(devfs_node* node, std::uint64_t req, void* arg); + signed long (*read)(file_descriptor* fd, devfs_node* node, void* buffer, std::size_t count); + signed long (*write)(file_descriptor* fd, devfs_node* node, void* buffer, std::size_t count); + bool (*poll)(devfs_node* node, vfs_poll_type type); + + std::int32_t (*close)(file_descriptor* fd, devfs_node* node); + + void* arg; + + bool is_root; + + bool is_a_tty; + char path[256]; + + std::uint64_t mmap; + std::uint64_t mmap_size; + + std::uint64_t id; + + devfs_node* next; }; +static_assert(sizeof(devfs_node) < 4096, "fsfsdf"); + // for non input devices namespace devfs { - void create(); + void create(bool is_tty, char* path, void* arg, std::uint64_t mmap, std::uint64_t mmap_size, std::int32_t (*open)(file_descriptor*fd, devfs_node* node), std::int32_t (*ioctl)(devfs_node* node, std::uint64_t req, void* arg), signed long (*read)(file_descriptor* fd, devfs_node* node, void* buffer, std::size_t count), signed long (*write)(file_descriptor* fd, devfs_node* node, void* buffer, std::size_t count), bool (*poll)(devfs_node* node, vfs_poll_type type), std::int32_t (*close)(file_descriptor* fd, devfs_node* node)); void init(vfs::node* new_node); } \ No newline at end of file diff --git a/kernel/src/generic/evdev.cpp b/kernel/src/generic/evdev.cpp index b7bb4c1..409ac71 100644 --- a/kernel/src/generic/evdev.cpp +++ b/kernel/src/generic/evdev.cpp @@ -153,6 +153,7 @@ std::int32_t evdev_stat(file_descriptor* file, stat* out) { std::int32_t evdev_open(filesystem* fs, void* file_desc, char* path, bool is_directory) { file_descriptor* fd = (file_descriptor*)file_desc; + (void)fs; if(klibc::strcmp(path, "/") == 0) { fd->fs_specific.tmpfs_pointer = (std::uint64_t)&evroot_node; diff --git a/kernel/src/generic/mp.cpp b/kernel/src/generic/mp.cpp index 0ab4678..89be3c8 100644 --- a/kernel/src/generic/mp.cpp +++ b/kernel/src/generic/mp.cpp @@ -34,6 +34,7 @@ void mp::sync() { } void smptrampoline(limine_mp_info* smp_info) { + smp_lock.lock(); std::uint32_t enum_cpu = smp_info->processor_id; arch::init(ARCH_INIT_MP); @@ -41,7 +42,7 @@ void smptrampoline(limine_mp_info* smp_info) { x86_64::cpu_data()->cpu = balance_how_much_cpus++; enum_cpu = x86_64::cpu_data()->cpu; #endif - klibc::printf("SMP: Cpu %d is online (%d)\r\n",smp_info->lapic_id,enum_cpu); + log("smp", "cpu %d is online (%d)",smp_info->lapic_id,enum_cpu); smp_lock.unlock(); mp::sync(); if(time::timer) time::timer->sleep(10000); @@ -63,4 +64,5 @@ void mp::init() { mp_info->cpus[i]->goto_address = smptrampoline; } } + log("mp", "detected %d cpus", mp_info->cpu_count); } \ No newline at end of file diff --git a/kernel/src/generic/tmpfs.cpp b/kernel/src/generic/tmpfs.cpp index 650fda3..a399d60 100644 --- a/kernel/src/generic/tmpfs.cpp +++ b/kernel/src/generic/tmpfs.cpp @@ -117,7 +117,6 @@ signed long tmpfs_ls(file_descriptor* file, char* out, std::size_t count) { auto node = (tmpfs::tmpfs_node*)file->fs_specific.tmpfs_pointer; std::size_t current_offset = 0; - dirent file_ls = {}; if(node->type != vfs_file_type::directory) return -ENOTDIR; @@ -151,7 +150,7 @@ again: } file->vnode.fs->lock.unlock(); - return 0; + return current_offset; } std::int32_t tmpfs_create(filesystem* fs, char* path, vfs_file_type type, std::uint32_t mode) { diff --git a/kernel/src/generic/vfs.hpp b/kernel/src/generic/vfs.hpp index ecfd25b..1a79e98 100644 --- a/kernel/src/generic/vfs.hpp +++ b/kernel/src/generic/vfs.hpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #define USERSPACE_PIPE_SIZE (64 * 1024) @@ -237,6 +239,9 @@ struct file_descriptor { struct { int cycle; int queue; + int tty_num; + bool is_a_tty; + void* ls_pointer; } other; struct { @@ -249,6 +254,8 @@ struct file_descriptor { std::int32_t (*stat)(file_descriptor* file, stat* out); void (*close)(file_descriptor* file); + std::int32_t (*mmap)(file_descriptor* file, std::uint64_t* out_phys, std::size_t* out_size); + signed long (*ls)(file_descriptor* file, char* out, std::size_t count); bool (*poll)(file_descriptor* file, vfs_poll_type type); @@ -305,14 +312,10 @@ namespace vfs { class pipe { private: - std::uint64_t read_ptr = 0; - std::atomic_flag is_received = ATOMIC_FLAG_INIT; std::atomic_flag is_n_closed = ATOMIC_FLAG_INIT; - int is_was_writed_ever = 0; - public: char* buffer; @@ -383,7 +386,7 @@ namespace vfs { return count; } - std::uint64_t write(const char* src_buffer, std::uint64_t count,int id) { + std::uint64_t write(const char* src_buffer, std::uint64_t count) { std::uint64_t written = 0; @@ -397,8 +400,6 @@ namespace vfs { continue; } - uint64_t old_size = this->size; - std::uint64_t to_write = (count - written) < space_left ? (count - written) : space_left; if(to_write < 0) to_write = 0; @@ -413,7 +414,7 @@ namespace vfs { return written; } - std::uint64_t nolock_write(const char* src_buffer, std::uint64_t count,int id) { + std::uint64_t nolock_write(const char* src_buffer, std::uint64_t count) { std::uint64_t written = 0; @@ -426,8 +427,6 @@ namespace vfs { std::uint64_t space_left = this->total_size - this->size; - uint64_t old_size = this->size; - std::uint64_t to_write = (count - written) < space_left ? (count - written) : space_left; if(to_write < 0) to_write = 0; @@ -442,10 +441,9 @@ namespace vfs { return written; } - std::int64_t read(std::int64_t* read_count, char* dest_buffer, std::uint64_t count, int is_block) { + std::int64_t read(char* dest_buffer, std::uint64_t count, int is_block) { std::uint64_t read_bytes = 0; - int tries = 0; while (true) { bool state = this->lock.lock(); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index aedd7a1..e523379 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #if defined(__x86_64__) #include @@ -45,6 +46,8 @@ extern "C" void main() { vfs::init(); drivers::powerbutton::init(); drivers::nvme::init(); + xhci_init(); + #if defined(__x86_64__) x86_64::pci::initworkspace(); log("pci", "launched all drivers"); diff --git a/kernel/src/utils/align.hpp b/kernel/src/utils/align.hpp index 2f2c665..f361185 100644 --- a/kernel/src/utils/align.hpp +++ b/kernel/src/utils/align.hpp @@ -1,2 +1,4 @@ #define ALIGNUP(VALUE, c) ((VALUE + c - 1) & ~(c - 1)) -#define ALIGNDOWN(VALUE, c) ((VALUE / c) * c) \ No newline at end of file +#define ALIGNDOWN(VALUE, c) ((VALUE / c) * c) +#define ALIGNPAGEUP(VALUE) ALIGNUP(VALUE, 4096) +#define ALIGNPAGEDOWN(VALUE) ALIGNDOWN(VALUE, 4096) \ No newline at end of file diff --git a/kernel/src/utils/ringbuffer.hpp b/kernel/src/utils/ringbuffer.hpp index d6f6c2c..12b2ef2 100644 --- a/kernel/src/utils/ringbuffer.hpp +++ b/kernel/src/utils/ringbuffer.hpp @@ -46,8 +46,6 @@ namespace utils { objs[tail].cycle = cycle; objs[tail].data = item; - write_counter++; - if (++tail == size) { tail = 0; cycle = !cycle; @@ -69,7 +67,6 @@ namespace utils { while (count < max && objs[q].cycle == (std::uint32_t)c) { out[count] = objs[q].data; - read_counter++; if (++q == size) { q = 0; @@ -85,7 +82,6 @@ namespace utils { return count; } - std::uint64_t get_write_count() const { return write_counter; } }; } \ No newline at end of file diff --git a/limine.conf b/limine.conf index 7d69f1a..720fb63 100644 --- a/limine.conf +++ b/limine.conf @@ -1,7 +1,8 @@ # Timeout in seconds that Limine will use before automatically booting. timeout: 2 term_foreground: EEEEEEEE -term_background: 000011 +# term_background: 000011 +wallpaper: boot():/boot/image.png # The entry name that will be displayed in the boot menu. /Orange -- cgit v1.2.3