summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcpplover0 <osdev555@yandex.com>2026-03-30 18:21:18 +0300
committercpplover0 <osdev555@yandex.com>2026-03-30 18:21:18 +0300
commit8844a7888ea94a11939b1c92915162f2e5acd378 (patch)
tree1b4ef74fde17d6f8bb6e054f3266e9342b41c836
parentbe997311c240f49db247ccce05ecb8ea5d3bfc31 (diff)
trying to get xhci working on vboxHEADmain
-rw-r--r--GNUmakefile2
-rw-r--r--kernel/src/arch/x86_64/assembly.hpp20
-rw-r--r--kernel/src/arch/x86_64/drivers/pci.cpp3
-rw-r--r--kernel/src/arch/x86_64/drivers/tsc.cpp7
-rw-r--r--kernel/src/arch/x86_64/panic.cpp12
-rw-r--r--kernel/src/arch/x86_64/x86_64.cpp2
-rw-r--r--kernel/src/drivers/xhci.cpp1666
-rw-r--r--kernel/src/drivers/xhci.hpp707
-rw-r--r--kernel/src/generic/devfs.cpp205
-rw-r--r--kernel/src/generic/devfs.hpp29
-rw-r--r--kernel/src/generic/evdev.cpp1
-rw-r--r--kernel/src/generic/mp.cpp4
-rw-r--r--kernel/src/generic/tmpfs.cpp3
-rw-r--r--kernel/src/generic/vfs.hpp22
-rw-r--r--kernel/src/main.cpp3
-rw-r--r--kernel/src/utils/align.hpp4
-rw-r--r--kernel/src/utils/ringbuffer.hpp4
-rw-r--r--limine.conf3
18 files changed, 2666 insertions, 31 deletions
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 <cstdint>
+#include <klibc/string.hpp>
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 <cstdint>
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 <utils/gobject.hpp>
#include <arch/x86_64/cpu/sse.hpp>
#include <arch/x86_64/drivers/pvclock.hpp>
+#include <utils/assert.hpp>
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 <drivers/xhci.hpp>
+#include <klibc/stdio.hpp>
+#include <klibc/string.hpp>
+#include <klibc/stdlib.hpp>
+#include <generic/hhdm.hpp>
+#include <generic/pmm.hpp>
+#include <generic/time.hpp>
+#include <generic/scheduling.hpp>
+#include <generic/paging.hpp>
+#include <utils/align.hpp>
+#include <generic/evdev.hpp>
+#include <utils/gobject.hpp>
+
+#if defined(__x86_64__)
+#include <arch/x86_64/assembly.hpp>
+#include <arch/x86_64/drivers/pci.hpp>
+#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 <cstdint>
+
+#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 <generic/vfs.hpp>
+#include <generic/devfs.hpp>
+#include <klibc/string.hpp>
+#include <generic/pmm.hpp>
+#include <generic/hhdm.hpp>
+#include <utils/errno.hpp>
+#include <generic/lock/spinlock.hpp>
+#include <cstdint>
+#include <atomic>
+
+devfs_node* head_devfs_node = nullptr;
+devfs_node root_devfs_node = {};
+
+std::atomic<std::uint64_t> 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 <generic/vfs.hpp>
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 <generic/lock/mutex.hpp>
#include <utils/linux.hpp>
#include <utils/assert.hpp>
+#include <generic/pmm.hpp>
+#include <generic/hhdm.hpp>
#include <generic/scheduling.hpp>
#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 <drivers/powerbutton.hpp>
#include <generic/mp.hpp>
#include <generic/vfs.hpp>
+#include <drivers/xhci.hpp>
#if defined(__x86_64__)
#include <arch/x86_64/drivers/pci.hpp>
@@ -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