Code: Select all
#include <efi.h>
#include <efilib.h>
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif
#pragma pack(push, 1)
typedef struct {
uint32_t info[8]; // Slot Context
uint32_t ep0[8]; // Endpoint 0 Context
uint32_t reserved[8 * 30];
} DeviceContext;
typedef struct {
uint32_t drop_flags;
uint32_t add_flags; // Slot (bit 0) + EP0 (bit 1) = 3
uint32_t reserved[6];
DeviceContext dev;
} InputContext;
#pragma pack(pop)
// --- xHCI Register ve TRB Yapıları ---
#pragma pack(push, 1)
typedef struct {
uint64_t parameter;
uint32_t status;
uint32_t control;
} TRB;
typedef struct {
uint64_t base_address;
uint32_t size;
uint32_t reserved;
} ERST_Entry;
#pragma pack(pop)
static TRB* kbd_transfer_ring = NULL;
// --- Global Değişkenler ---
static uintptr_t xhci_mmio = 0;
#define cap_base xhci_mmio
static uintptr_t op_base = 0;
static uintptr_t rt_base = 0;
static uintptr_t db_base = 0;
static uint32_t cmd_idx = 0;
static TRB* cmd_ring = NULL;
static TRB* ev_ring = NULL;
static ERST_Entry* erst = NULL;
static uint64_t* dcbaa = NULL;
static uint32_t g_rcs_bit = 0;
// --- Temel MMIO ve PCI Araçları ---
static inline void mmio_w32(uintptr_t a, uint32_t v) { *(volatile uint32_t*)a = v; }
static inline uint32_t mmio_r32(uintptr_t a) { return *(volatile uint32_t*)a; }
// Fonksiyon prototipleri
bool xhci_initialize_full(void);
int find_and_reset_connected_port(uintptr_t cap_base, uintptr_t op_base);
bool address_device(uint8_t slot_id, uint32_t port_idx);
void* alloc_pages_aligned(UINTN pages);
uint8_t do_enable_slot_sync(void);
void configure_command_ring(void);
void update_erdp(uintptr_t rt_base, uintptr_t event_trb_ptr);
void check_xhci_status(void);
void xhci_bios_handover(uintptr_t xhci_mmio);
uint32_t pci_readd(uint8_t b, uint8_t d, uint8_t f, uint8_t off) {
uint32_t addr = (uint32_t)((1u << 31) | (b << 16) | (d << 11) | (f << 8) | (off & 0xFC));
__outdword(0xCF8, addr);
return __indword(0xCFC);
}
void pci_writed(uint8_t b, uint8_t d, uint8_t f, uint8_t off, uint32_t val) {
uint32_t addr = (uint32_t)((1u << 31) | (b << 16) | (d << 11) | (f << 8) | (off & 0xFC));
__outdword(0xCF8, addr);
__outdword(0xCFC, val);
}
void* alloc_pages_aligned(UINTN pages) {
EFI_PHYSICAL_ADDRESS addr = 0;
EFI_STATUS status;
Print(L"\n [alloc] %d sayfa isteniyor...", pages);
status = gBS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, &addr);
if (EFI_ERROR(status)) {
Print(L" HATA: %r", status);
return NULL;
}
if (addr < 0x1000) {
Print(L" GECERSIZ ADRES: %016llx", addr);
return NULL;
}
Print(L" adres: %016llx", addr);
char* ptr = (char*)addr;
for (UINTN i = 0; i < pages * 4096; i++) {
ptr[i] = 0;
}
Print(L" (sifirlandi)");
return (void*)addr;
}
bool wait_reg(uintptr_t addr, uint32_t mask, uint32_t target, uint32_t retry_ms) {
for (uint32_t i = 0; i < retry_ms; i++) {
uint32_t val = mmio_r32(addr) & mask;
if (val == target) {
return true;
}
gBS->Stall(1000);
}
return false;
}
// --- 8-bit PCI okuma/yazma fonksiyonları (eklendi) ---
uint8_t pci_readb(uint8_t b, uint8_t d, uint8_t f, uint8_t off) {
uint32_t addr = (uint32_t)((1u << 31) | (b << 16) | (d << 11) | (f << 8) | (off & 0xFC));
__outdword(0xCF8, addr);
return (uint8_t)(__indword(0xCFC) >> ((off & 3) * 8));
}
void pci_writeb(uint8_t b, uint8_t d, uint8_t f, uint8_t off, uint8_t val) {
uint32_t addr = (uint32_t)((1u << 31) | (b << 16) | (d << 11) | (f << 8) | (off & 0xFC));
uint32_t reg = __indword(0xCFC);
uint32_t shift = (off & 3) * 8;
reg &= ~(0xFF << shift);
reg |= (val << shift);
__outdword(0xCF8, addr);
__outdword(0xCFC, reg);
}
// --- xHCI Fonksiyonları ---
bool xhci_initialize_full() {
uint8_t bus, dev, func;
bool found = false;
Print(L"\n=== XHCI BASLATILIYOR ===");
// 1. PCI Tarama
for (int b = 0; b < 256 && !found; b++) {
for (int d = 0; d < 32 && !found; d++) {
for (int f = 0; f < 8; f++) {
uint32_t id = pci_readd(b, d, f, 0x08);
if ((id >> 8) == 0x0C0330) {
bus = b; dev = d; func = f; found = true;
Print(L"\n[xHCI] PCI'da bulundu: %02x:%02x.%x", b, d, f);
uint16_t vendor = id & 0xFFFF;
uint16_t device = (id >> 16) & 0xFFFF;
Print(L" (Vendor:%04x Device:%04x)", vendor, device);
break;
}
}
}
}
if (!found) {
Print(L"\n[xHCI] HATA: Denetleyici bulunamadı!");
return false;
}
// 2. PCI Command Register
uint32_t pci_cmd = pci_readd(bus, dev, func, 0x04);
Print(L"\n[xHCI] PCI Command (once): %04x", pci_cmd & 0xFFFF);
// TÜM bitleri set et (IO, MMIO, Bus Master)
pci_writed(bus, dev, func, 0x04, pci_cmd | 0x07);
// OKU ve doğrula
pci_cmd = pci_readd(bus, dev, func, 0x04);
Print(L"\n[xHCI] PCI Command (sonra): %04x", pci_cmd & 0xFFFF);
// Bus Master hala 0 ise, dene
if (!(pci_cmd & 0x04)) {
Print(L"\n[xHCI] Bus Master set edilemedi! Tekrar deneniyor...");
pci_writed(bus, dev, func, 0x04, pci_cmd | 0x04);
pci_cmd = pci_readd(bus, dev, func, 0x04);
Print(L"\n[xHCI] PCI Command (tekrar): %04x", pci_cmd & 0xFFFF);
}
// 3. BAR
uint32_t bar0 = pci_readd(bus, dev, func, 0x10);
uint32_t bar2 = pci_readd(bus, dev, func, 0x14);
Print(L"\n[xHCI] BAR0: %08x BAR2: %08x", bar0, bar2);
if ((bar0 & 0x06) == 0x04) {
Print(L"\n[xHCI] 64-bit MMIO");
xhci_mmio = bar0 & ~0xF;
xhci_mmio |= ((uint64_t)bar2 << 32);
}
else {
Print(L"\n[xHCI] 32-bit MMIO");
xhci_mmio = bar0 & ~0xF;
}
Print(L"\n[xHCI] MMIO base: %016llx", (uint64_t)xhci_mmio);
// MMIO'ya basit bir test yaz
Print(L"\n[xHCI] MMIO test yazılıyor...");
// Yazmak yerine sadece oku ve doğrula
uint32_t cap_reg = mmio_r32(xhci_mmio);
uint8_t len = cap_reg & 0xFF;
if (len < 0x20 || len > 0x100) { // xHCI için makul sınırlar
Print(L"\n[HATA] Gecersiz CAPLENGTH: %02x", len);
return false;
}
uint32_t test_read = mmio_r32(xhci_mmio);
Print(L"\n[xHCI] MMIO test okuma: %08x", test_read);
if (test_read != 0x12345678) {
Print(L"\n[xHCI] HATA: MMIO yazma/okuma basarisiz!");
Print(L"\n[xHCI] BAR yanlis olabilir!");
return false;
}
xhci_bios_handover(xhci_mmio);
// 4. Capability registers
uint32_t caplength = mmio_r32(xhci_mmio);
uint8_t cap_length = caplength & 0xFF;
uint32_t hcsparams1 = mmio_r32(xhci_mmio + 0x04);
uint32_t max_slots = (hcsparams1 >> 8) & 0xFF;
uint32_t max_ports = (hcsparams1 >> 24) & 0xFF;
Print(L"\n[xHCI] CAPLENGTH: %08x", caplength);
Print(L"\n[xHCI] Max Slots: %d", max_slots);
Print(L"\n[xHCI] Max Ports: %d", max_ports);
// 5. Base registers
op_base = xhci_mmio + cap_length;
db_base = xhci_mmio + (mmio_r32(xhci_mmio + 0x14) & ~0x3);
rt_base = xhci_mmio + (mmio_r32(xhci_mmio + 0x18) & ~0x1F);
// 6. Stop controller
Print(L"\n[xHCI] Denetleyici durduruluyor...");
mmio_w32(op_base + 0x00, 0);
int wait_halt = 0;
while (wait_halt < 100) {
if (mmio_r32(op_base + 0x04) & 0x01) {
Print(L"\n [%d] HALTED", wait_halt);
break;
}
for (volatile int w = 0; w < 100000; w++);
wait_halt++;
}
// 7. Reset
Print(L"\n[xHCI] Controller Reset...");
mmio_w32(op_base + 0x00, 0x02);
int wait_reset = 0;
while (wait_reset < 1000) {
if ((mmio_r32(op_base + 0x00) & 0x02) == 0) {
Print(L"\n [%d] Reset tamam", wait_reset);
break;
}
for (volatile int w = 0; w < 100000; w++);
wait_reset++;
}
// 7.1 CNR (Controller Not Ready) bitinin temizlenmesini bekle
Print(L"\n[xHCI] Donanimin hazir olmasi bekleniyor (CNR)...");
int wait_cnr = 0;
while (wait_cnr < 1000) {
uint32_t status = mmio_r32(op_base + 0x04);
if (!(status & (1 << 11))) { // Bit 11 = CNR
Print(L" Hazir!");
break;
}
gBS->Stall(1000);
wait_cnr++;
}
if (wait_cnr >= 1000) {
Print(L"\n[HATA] Denetleyici CNR bitini temizlemedi!");
return false;
}
// 8. Hata durumunu temizle
uint32_t usbsts = mmio_r32(op_base + 0x04);
if (usbsts & 0x10) { // HSE biti
Print(L"\n[xHCI] HSE biti temizleniyor...");
mmio_w32(op_base + 0x04, 0x10); // Write 1 to clear
}
// 9. Memory allocation
Print(L"\n[xHCI] Bellek tahsis ediliyor...");
Print(L"\n Command ring icin:");
cmd_ring = (TRB*)alloc_pages_aligned(1);
if (!cmd_ring) return false;
Print(L"\n Event ring icin:");
ev_ring = (TRB*)alloc_pages_aligned(1);
if (!ev_ring) return false;
Print(L"\n ERST icin:");
erst = (ERST_Entry*)alloc_pages_aligned(1);
if (!erst) return false;
Print(L"\n DCBAA icin:");
dcbaa = (uint64_t*)alloc_pages_aligned(1);
if (!dcbaa) return false;
// 10. DCBAA
mmio_w32(op_base + 0x30, (uint32_t)(uintptr_t)dcbaa);
mmio_w32(op_base + 0x34, (uint32_t)((uintptr_t)dcbaa >> 32));
// 11. Command Ring - first TRB
volatile uint32_t* first_cmd = (volatile uint32_t*)cmd_ring;
first_cmd[0] = 0;
first_cmd[1] = 0;
first_cmd[2] = 0;
first_cmd[3] = 1;
_mm_mfence();
// Command Ring'i disable et (CRCR'nin en düşük bitini 0 yap)
uint64_t crcr_disable = (uintptr_t)cmd_ring & ~0x01;
mmio_w32(op_base + 0x18, (uint32_t)crcr_disable);
mmio_w32(op_base + 0x1C, (uint32_t)(crcr_disable >> 32));
for (volatile int w = 0; w < 100000; w++);
// Sonra enable et
uint64_t crcr_enable = (uintptr_t)cmd_ring | 0x01;
mmio_w32(op_base + 0x18, (uint32_t)crcr_enable);
mmio_w32(op_base + 0x1C, (uint32_t)(crcr_enable >> 32));
uint32_t read_low = mmio_r32(op_base + 0x18);
uint32_t read_high = mmio_r32(op_base + 0x1C);
Print(L"\n[xHCI] Okuma: %08x %08x", read_high, read_low);
mmio_w32(op_base + 0x18, 1);
read_low = mmio_r32(op_base + 0x18);
Print(L"\n[xHCI] CRCR=1 okuma: %08x", read_low);
// 12. Configure command ring
configure_command_ring();
// 13. Event Ring
Print(L"\n[xHCI] Event ring yapilandiriliyor...");
SetMem(ev_ring, 4096, 0);
erst[0].base_address = (uintptr_t)ev_ring;
erst[0].size = 256;
erst[0].reserved = 0;
uintptr_t int0 = rt_base + 0x20;
mmio_w32(int0 + 0x00, 0);
mmio_w32(int0 + 0x08, 1);
mmio_w32(int0 + 0x10, (uint32_t)(uintptr_t)erst);
mmio_w32(int0 + 0x14, (uint32_t)((uintptr_t)erst >> 32));
uint64_t erdp = ((uintptr_t)ev_ring & ~0xF) | 0x08;
mmio_w32(int0 + 0x18, (uint32_t)erdp);
mmio_w32(int0 + 0x1C, (uint32_t)(erdp >> 32));
mmio_w32(int0 + 0x00, 0x03);
// 14. Max slots
mmio_w32(op_base + 0x38, max_slots);
// 15. Start controller
Print(L"\n[xHCI] Denetleyici baslatiliyor...");
mmio_w32(op_base + 0x00, 0x01 | 0x04 | 0x08);
// HSE bitini temizle
usbsts = mmio_r32(op_base + 0x04);
if (usbsts & 0x10) {
Print(L"\n[xHCI] HSE biti temizleniyor...");
mmio_w32(op_base + 0x04, 0x10); // Write 1 to clear
usbsts = mmio_r32(op_base + 0x04);
Print(L"\n[xHCI] Yeni USBSTS: %08x", usbsts);
}
int wait_run = 0;
while (wait_run < 1000) {
usbsts = mmio_r32(op_base + 0x04);
if ((usbsts & 0x01) == 0) {
Print(L"\n [%d] CALISIYOR! USBSTS: %08x", wait_run, usbsts);
break;
}
for (volatile int w = 0; w < 100000; w++);
wait_run++;
}
Print(L"\n=== XHCI BASARIYLA BASLATILDI ===");
return true;
}
void update_erdp(uintptr_t rt_base, uintptr_t event_trb_ptr) {
uint64_t val = (event_trb_ptr & ~0xF) | 0x08;
uintptr_t erdp_low = rt_base + 0x20 + 0x18;
uintptr_t erdp_high = rt_base + 0x20 + 0x1C;
mmio_w32(erdp_high, (uint32_t)(val >> 32));
mmio_w32(erdp_low, (uint32_t)val);
}
void configure_command_ring() {
Print(L"\n[xHCI] Command Ring yapilandiriliyor (SON DENEME)...");
uint64_t crcr_value = (uintptr_t)cmd_ring | 0x01;
uint32_t low = (uint32_t)crcr_value;
uint32_t high = (uint32_t)(crcr_value >> 32);
Print(L"\n[xHCI] CRCR degeri: %016llx", crcr_value);
Print(L"\n[xHCI] Low: %08x, High: %08x", low, high);
// Önce disable
uint64_t crcr_disable = (uintptr_t)cmd_ring & ~0x01;
mmio_w32(op_base + 0x18, (uint32_t)crcr_disable);
mmio_w32(op_base + 0x1C, (uint32_t)(crcr_disable >> 32));
for (volatile int w = 0; w < 1000000; w++);
// Şimdi enable - farklı sıra dene
mmio_w32(op_base + 0x18, low);
mmio_w32(op_base + 0x1C, high);
// CRCR yazarken önce High sonra Low yazmayı deneyin
//mmio_w32(op_base + 0x1C, high); // Önce yüksek 32 bit
//mmio_w32(op_base + 0x18, low | 0x01); // Sonra düşük 32 bit + RCS
// Hemen oku
uint32_t read_low = mmio_r32(op_base + 0x18);
uint32_t read_high = mmio_r32(op_base + 0x1C);
Print(L"\n[xHCI] Okuma: %08x %08x", read_high, read_low);
if ((read_low & 1) == 1) {
Print(L"\n[xHCI] BASARILI! RCS=1");
g_rcs_bit = 1;
}
else {
Print(L"\n[xHCI] HATA: RCS hala 0");
// Test: sadece 1 yaz
mmio_w32(op_base + 0x18, 1);
read_low = mmio_r32(op_base + 0x18);
Print(L"\n[xHCI] CRCR=1 okuma: %08x", read_low);
g_rcs_bit = 0;
}
}
uint8_t do_enable_slot_sync() {
Print(L"\n\n=== SLOT ALMA ISLEMI ===");
uint32_t crcr_low = mmio_r32(op_base + 0x18);
uint32_t rcs = crcr_low & 1;
Print(L"\nCRCR: %08x (RCS=%d)", crcr_low, rcs);
if (rcs == 0) {
Print(L"\nHATA: Command Ring calismiyor! (RCS=0)");
configure_command_ring();
crcr_low = mmio_r32(op_base + 0x18);
rcs = crcr_low & 1;
if (rcs == 0) {
return 0;
}
}
SetMem(ev_ring, 4096, 0);
uint64_t erdp = ((uintptr_t)ev_ring & ~0xF) | 0x08;
mmio_w32(rt_base + 0x20 + 0x18, (uint32_t)erdp);
mmio_w32(rt_base + 0x20 + 0x1C, (uint32_t)(erdp >> 32));
volatile uint32_t* cmd = (volatile uint32_t*)cmd_ring;
cmd[0] = 0;
cmd[1] = 0;
cmd[2] = 0;
cmd[3] = (9 << 10) | rcs;
Print(L"\nEnable Slot TRB: %08x %08x %08x %08x", cmd[0], cmd[1], cmd[2], cmd[3]);
Print(L"\nDoorbell caliniyor...");
mmio_w32(db_base, 0);
Print(L"\nCommand Completion bekleniyor...");
for (int timeout = 0; timeout < 5000; timeout++) {
for (int j = 0; j < 16; j++) {
volatile uint32_t* ev = (volatile uint32_t*)&ev_ring[j];
if (ev[3] & 1) {
uint32_t type = (ev[3] >> 10) & 0x3F;
if (type == 33) {
uint8_t slot = (ev[3] >> 24) & 0xFF;
uint32_t code = (ev[2] >> 24) & 0xFF;
Print(L"\n>>> Slot:%d Kod:%d", slot, code);
if (code == 1) {
Print(L"\n*** SLOT %d ALINDI! ***", slot);
return slot;
}
}
}
}
if (timeout % 500 == 0) Print(L".");
for (volatile int w = 0; w < 100000; w++);
}
Print(L"\n[HATA] Command Completion gelmedi!");
return 0;
}
int find_and_reset_connected_port(uintptr_t cap_base, uintptr_t op_base) {
uint32_t hcs1 = mmio_r32(cap_base + 0x04);
uint32_t max_ports = (hcs1 >> 24) & 0xFF;
Print(L"\n[xHCI] %d port taranıyor...", max_ports);
for (uint32_t i = 0; i < max_ports; i++) {
uintptr_t port_reg = op_base + 0x400 + (i * 0x10);
uint32_t status = mmio_r32(port_reg);
Print(L"\n[PORT %d] Status: %08x", i + 1, status);
if (status & 0x01) {
Print(L" CIHAZ VAR!");
uint32_t portsc = status;
portsc |= (1 << 4);
portsc &= ~(1 << 9);
mmio_w32(port_reg, portsc);
Print(L" Reset basladi");
int reset_timeout = 0;
while (reset_timeout < 1000) {
status = mmio_r32(port_reg);
if (!(status & (1 << 4))) {
Print(L" Tamam (%d)", reset_timeout);
break;
}
for (volatile int w = 0; w < 100000; w++);
reset_timeout++;
}
int enable_timeout = 0;
while (enable_timeout < 500) {
status = mmio_r32(port_reg);
if (status & (1 << 9)) {
Print(L" ENABLED");
break;
}
for (volatile int w = 0; w < 100000; w++);
enable_timeout++;
}
return i;
}
}
return -1;
}
bool address_device(uint8_t slot_id, uint32_t port_idx) {
Print(L"\n\n=== ADDRESS DEVICE ISLEMI ===");
InputContext* input = (InputContext*)alloc_pages_aligned(1);
DeviceContext* output = (DeviceContext*)alloc_pages_aligned(1);
if (!input || !output) return false;
dcbaa[slot_id] = (uintptr_t)output;
input->add_flags = 3;
uint32_t port_status = mmio_r32(op_base + 0x400 + (port_idx * 0x10));
uint32_t speed = (port_status >> 10) & 0x0F;
uint32_t portno = port_idx + 1;
input->dev.info[0] = (1 << 27);
input->dev.info[1] = (portno << 16);
input->dev.info[2] = (speed << 20);
input->dev.ep0[1] = (2 << 3) | (8 << 16);
volatile TRB* cmd = &cmd_ring[cmd_idx];
cmd->parameter = (uintptr_t)input;
cmd->status = 0;
cmd->control = (11 << 10) | (slot_id << 24) | 1;
Print(L"\nAddress Device TRB gonderildi");
mmio_w32(db_base, 0);
for (int timeout = 0; timeout < 30000; timeout++) {
for (int j = 0; j < 16; j++) {
volatile uint32_t* ev = (volatile uint32_t*)&ev_ring[j];
if (ev[3] & 1) {
uint32_t type = (ev[3] >> 10) & 0x3F;
if (type == 33) {
uint32_t completion = (ev[2] >> 24) & 0xFF;
ev[3] &= ~1;
update_erdp(rt_base, (uintptr_t)&ev_ring[j]);
if (completion == 1) {
Print(L"\n*** ADDRESS DEVICE BASARILI! ***");
cmd_idx++;
return true;
}
}
}
}
if (timeout % 1000 == 0) Print(L".");
for (volatile int w = 0; w < 10000; w++);
}
return false;
}
void check_xhci_status() {
Print(L"\n\n=== XHCI DURUM KONTROLÜ ===");
Print(L"\nUSBCMD: %08x", mmio_r32(op_base + 0x00));
Print(L"\nUSBSTS: %08x", mmio_r32(op_base + 0x04));
Print(L"\nCRCR: %08x %08x",
mmio_r32(op_base + 0x1C), mmio_r32(op_base + 0x18));
}
// Global buffer - HID raporu için
static uint8_t keyboard_hid_buffer[8] __attribute__((aligned(64)));
// Interrupt TRB ile klavye verisi okuma
void setup_keyboard_interrupt(uint8_t slot_id) {
Print(L"\n\n=== KLAVYE INTERRUPT AYARLANIYOR ===");
// 1. Input Context hazırla
InputContext* input = (InputContext*)alloc_pages_aligned(1);
if (!input) return;
// 2. Klavye için Transfer Ring (Halka) oluştur
// Bu global değişken olmalı ki read_keyboard içinde erişebilesin
kbd_transfer_ring = (TRB*)alloc_pages_aligned(1);
// 3. Add Context Flags Ayarı
// Bit 0: Slot Context güncellenecek
// Bit 3: EP1-IN konfigüre edilecek (Klavye genelde EP1-IN kullanır)
input->add_flags = (1 << 0) | (1 << 3);
// 4. Slot Context Ayarları (Mevcut slot bilgilerini korumak için)
// Önemli: Context Entries sayısını EP1-IN'i kapsayacak şekilde (3) güncellemelisin
input->dev.info[0] = (3 << 27); // Context Entries = 3 (Slot + EP0 + EP1-OUT + EP1-IN)
// 5. EP1-IN Context (Index 3) Doldurma
// Senin struct yapında reserved[8 * 30] olduğu için:
// reserved[0..7] -> Index 2 (EP1-OUT)
// reserved[8..15] -> Index 3 (EP1-IN)
uint32_t* ep1_in_ctx = &input->dev.reserved[8];
// EP State = 0, Mult = 0, MaxPStreams = 0, LSA = 0, Interval = 1ms (genelde 7 veya 3)
ep1_in_ctx[1] = (5 << 3) | (3 << 1) | (8 << 16) | (7 << 24);
// Type: 5 (Interrupt IN), Error Count: 3, Max Packet Size: 8, Interval: 1ms (2^(7-3))
// Transfer Ring Adresi + DCS (Dequeue Cycle State)
uint64_t tr_ptr = (uintptr_t)kbd_transfer_ring | 1; // Başlangıç Cycle Bit = 1
ep1_in_ctx[2] = (uint32_t)tr_ptr;
ep1_in_ctx[3] = (uint32_t)(tr_ptr >> 32);
ep1_in_ctx[4] = 8; // Average TRB Length (Klavye için 8 byte)
// 6. Configure Endpoint Komutunu Gönder (Type 12)
volatile TRB* cmd = &cmd_ring[cmd_idx];
cmd->parameter = (uintptr_t)input;
cmd->status = 0;
cmd->control = (12 << 10) | (slot_id << 24) | 1; // 12: Configure Endpoint
Print(L"\n[xHCI] Configure Endpoint (EP1-IN) TRB gonderildi. Slot: %d", slot_id);
mmio_w32(db_base, 0); // Command Ring Doorbell
// Command Completion bekleme döngüsü (Mevcut mantığın doğru)
// ... (Wait loop) ...
// ... (Configure Endpoint gönderildikten sonra)
bool success = false;
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 16; j++) {
volatile uint32_t* ev = (volatile uint32_t*)&ev_ring[j];
if (ev[3] & 1) { // Cycle bit kontrolü
uint32_t type = (ev[3] >> 10) & 0x3F;
if (type == 33) { // Command Completion Event
uint32_t code = (ev[2] >> 24) & 0xFF;
if (code == 1) success = true; // 1 = Success
}
ev[3] &= ~1; // Event'i işlemiş say
update_erdp(rt_base, (uintptr_t)&ev_ring[j]);
}
}
if (success) break;
gBS->Stall(1000);
}
if (!success) Print(L"\n[HATA] Endpoint konf. basarisiz!");
cmd_idx++; // Komut indeksini artırmayı unutma!
}
static uint8_t kbd_cycle = 1; // Global takip
char read_keyboard(uint8_t slot_id) {
if (!kbd_transfer_ring) return 0;
// 0. indeksi kullanıyoruz (basitlik için)
volatile TRB* trb = &kbd_transfer_ring[0];
trb->parameter = (uintptr_t)keyboard_hid_buffer;
trb->status = 8; // 8 byte bekle
// IOC=1 (Bit 5), Type=1 (Normal, Bit 10-15), Cycle Bit
trb->control = (1 << 10) | (1 << 5) | kbd_cycle;
// Doorbell: Slot x, Target 3 (EP1-IN)
// db_base genelde uint32_t pointer gibi davranır
((uint32_t*)db_base)[slot_id] = 3;
// Event bekleme
for (int timeout = 0; timeout < 100000; timeout++) {
for (int j = 0; j < 256; j++) { // Event ring boyutu kadar tara
volatile uint32_t* ev = (volatile uint32_t*)&ev_ring[j];
// Cycle bit kontrolü (Donanım burayı 1 yaptı mı?)
if ((ev[3] & 1) == 1) {
uint32_t type = (ev[3] >> 10) & 0x3F;
if (type == 32) { // Transfer Event
uint8_t keycode = keyboard_hid_buffer[2];
// ERDP Güncelle (Okuduğumuz TRB'nin adresi)
uintptr_t erdp_val = (uintptr_t)ev | 0x08;
mmio_w32(rt_base + 0x20 + 0x18, (uint32_t)erdp_val);
mmio_w32(rt_base + 0x20 + 0x1C, (uint32_t)(erdp_val >> 32));
// Temizlik ve bir sonraki sefer için cycle bit hazırlığı (basit mantık)
// Gerçek sürücüde burada enqueue/dequeue yönetilir
if (keycode >= 4 && keycode <= 29) return 'a' + (keycode - 4);
}
}
}
gBS->Stall(1);
}
return 0;
}
void xhci_bios_handover(uintptr_t xhci_mmio) {
uint32_t hccparams1 = mmio_r32(xhci_mmio + 0x10);
uint32_t xecp = (hccparams1 >> 16) << 2; // Dword offset to byte offset
while (xecp) {
uintptr_t addr = xhci_mmio + xecp;
uint32_t cap = mmio_r32(addr);
uint8_t id = cap & 0xFF;
if (id == 1) { // USB Legacy Support Capability
uint32_t bios_owned = mmio_r32(addr);
if (bios_owned & (1 << 16)) { // BIOS Semaphore bit
Print(L"\n[xHCI] BIOS mülkiyeti bırakıyor...");
mmio_w32(addr, bios_owned | (1 << 24)); // OS Semaphore bit set
// BIOS'un mülkiyeti bırakmasını bekle (bit 16 sıfırlanmalı)
for (int i = 0; i < 1000; i++) {
if (!(mmio_r32(addr) & (1 << 16))) break;
gBS->Stall(1000);
}
}
}
uint8_t next = (cap >> 8) & 0xFF;
if (!next) break;
xecp += (next << 2);
}
}
static uint32_t kbd_enq_idx = 0; // Bizim yazacağımız yer
static uint8_t kbd_pcs = 1; // Producer Cycle State (Donanımın beklediği bit)
// Klavye TRB'sini halkaya ekleyen fonksiyon
void enqueue_kbd_trb(uint8_t slot_id) {
volatile TRB* trb = &kbd_transfer_ring[kbd_enq_idx];
trb->parameter = (uintptr_t)keyboard_hid_buffer;
trb->status = 8; // Max Packet Size
// IOC (Interrupt on Completion) + TRB Type (1 = Normal) + Cycle Bit
trb->control = (1 << 5) | (1 << 10) | kbd_pcs;
// Doorbell çal: Target 3 (EP1-IN)
uint32_t* db = (uint32_t*)db_base;
db[slot_id] = 3;
// İndeksi ilerlet
kbd_enq_idx++;
// Ring sonuna geldik mi? (Genelde 256 TRB'lik bir sayfa ayırdık)
if (kbd_enq_idx >= 255) { // Son TRB Link TRB olmalı ama basitlik için başa dönüyoruz
// Gerçek bir sürücüde buraya "Link TRB" konur.
// Şimdilik halkayı manuel sıfırlıyoruz:
kbd_enq_idx = 0;
kbd_pcs ^= 1; // Tur bittiğinde Cycle Bit tersine döner
}
}
static uint32_t ev_deq_idx = 0;
static uint8_t ev_ccs = 1; // Consumer Cycle State (Donanımın yazdığı bit)
char poll_keyboard_event(uint8_t slot_id) {
volatile TRB* ev = &ev_ring[ev_deq_idx];
// Donanım bu indekse bir şey yazdı mı? (Cycle Bit kontrolü)
if ((ev->control & 1) == ev_ccs) {
uint32_t type = (ev->control >> 10) & 0x3F;
char result = 0;
if (type == 32) { // Transfer Event
uint32_t completion_code = (ev->status >> 24) & 0xFF;
if (completion_code == 1) { // Success
uint8_t keycode = keyboard_hid_buffer[2];
if (keycode >= 4 && keycode <= 29) {
result = 'a' + (keycode - 4);
}
}
// Yeni bir transfer isteği gönder (Klavye sürekli dinlenmeli)
enqueue_kbd_trb(slot_id);
}
// Event işlendi, Dequeue Pointer'ı ilerlet
ev_deq_idx++;
if (ev_deq_idx >= 256) {
ev_deq_idx = 0;
ev_ccs ^= 1;
}
// ERDP Güncelle (Donanıma "buraya kadar okudum" de)
uintptr_t erdp_val = (uintptr_t)&ev_ring[ev_deq_idx] | 0x08;
mmio_w32(rt_base + 0x20 + 0x18, (uint32_t)erdp_val);
mmio_w32(rt_base + 0x20 + 0x1C, (uint32_t)(erdp_val >> 32));
return result;
}
return 0;
}
Code: Select all
//...
Rnder = false; //Normally I exit boot services and do the OS loop somewhere else...
Rnder_OS = true;
Print(L"\n=== USB KLAVYE BASLATILIYOR ===");
if (xhci_initialize_full()) {
// Durum kontrolü
uint32_t usbsts = mmio_r32(op_base + 0x04);
Print(L"\nUSBSTS: %08x", usbsts);
// Portları tara ve klavyeyi bul
int device_port = find_and_reset_connected_port(cap_base, op_base);
if (device_port != -1) {
Print(L"\nKlavye port %d'de bulundu!", device_port + 1);
// Slot al
uint8_t slot = do_enable_slot_sync();
// Slot alındıktan ve device address yapıldıktan sonra:
if (slot > 0 && address_device(slot, device_port)) {
Print(L"\n✓✓✓ KLAVYE HAZIR! ✓✓✓");
// Interrupt endpoint'i yapılandır
setup_keyboard_interrupt(slot);
// Klavye okuma döngüsü
while (Rnder_OS) {
char key = read_keyboard(slot);
if (key >= 'a' && key <= 'z') {
Print(L"\nTuş: %c", key); // A'ya basınca 'a' yazacak
}
// ESC tuşu için (HID Usage ID 41 = ESC)
// Basit bekleme
for (volatile int w = 0; w < 1000000; w++);
}
}
}
}
//...

Problem is RCS always comes zero.
How to solve this problem?


