From 810cb13942d851f3563f23f9ced0da7acb89ea2d Mon Sep 17 00:00:00 2001 From: bassaer Date: Mon, 21 Mar 2022 19:58:01 +0900 Subject: [PATCH 1/3] read USBSTS --- Makefile | 3 ++ drivers/xhci.c | 76 ++++++++++++++++++++++------- graphics/desktop.c | 11 +++++ include/drivers/xhci.h | 98 ++++++++++++++++++++++++++++++++++++++ include/graphics/desktop.h | 2 + kernel/Makefile | 2 +- 6 files changed, 174 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index 84fd0fe..3d341b8 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,7 @@ drivers: run: img qemu-system-x86_64 -name myos \ + -m 1G \ -monitor stdio \ -bios /usr/share/ovmf/OVMF.fd \ -drive format=raw,file=$(IMG) \ @@ -44,6 +45,8 @@ run: img -d guest_errors \ || true + #-bios /usr/share/ovmf/OVMF.fd \ + -drive file=/usr/share/ovmf/x86_64/bios.bin,format=raw,if=pflash,readonly usb: arch/x86/BOOTX64.EFI kernel/vmmyos sudo mount /dev/sda /mnt diff --git a/drivers/xhci.c b/drivers/xhci.c index c6cba09..8b49d2f 100644 --- a/drivers/xhci.c +++ b/drivers/xhci.c @@ -36,27 +36,28 @@ UINT32 inl(CHAR16 port) { return ret; } +UINT32 read_config(UINT8 bus, UINT8 device, UINT8 function, UINT8 offset) { + set_config_address(build_address(bus, device, function, offset)); + return read_data(); +} + UINT8 read_header_type(UINT8 bus, UINT8 device, UINT8 function) { - set_config_address(build_address(bus, device, function, 0x0C)); - return (read_data() >> 16) & 0xFFU; + return (read_config(bus, device, function, 0x0C) >> 16) & 0xFFU; } void read_class_code(UINT8 bus, UINT8 device, UINT8 function, class_code_t* class_code) { - set_config_address(build_address(bus, device, function, 0x08)); - UINT32 data = read_data(); + UINT32 data = read_config(bus, device, function, 0x08); class_code->base = (data >> 24) & 0xFFU; class_code->sub = (data >> 16) & 0xFFU; class_code->interface = (data >> 8) & 0xFFU; } UINT32 read_bus_number(UINT8 bus, UINT8 device, UINT8 function) { - set_config_address(build_address(bus, device, function, 0x18)); - return read_data(); + return read_config(bus, device, function, 0x18); } UINT16 get_vendor_id(UINT8 bus, UINT8 device, UINT8 function) { - set_config_address(build_address(bus, device, function, 0x00)); - return read_data() & 0xFFFFU; + return read_config(bus, device, function, 0x00) & 0xFFFFU; } STATUS add_device(UINT8 bus, UINT8 device, UINT8 function, UINT8 header_type, class_code_t class_code) { @@ -68,7 +69,6 @@ STATUS add_device(UINT8 bus, UINT8 device, UINT8 function, UINT8 header_type, cl return OK; } - STATUS find_function(UINT8 bus, UINT8 device) { for (UINT8 function = 0; function < 32; ++function) { if (get_vendor_id(bus, device, function) == INVALID_ID) { @@ -128,25 +128,67 @@ bool is_xhci(class_code_t* code) { return code->base == 0x0CU && code->sub == 0x03U && code->interface == 0x30U; } +UINT64 read_bar(device_t* dev, UINT8 index) { + UINT8 bar_address = 0x10 + 4 * index; + UINT32 lower = read_config(dev->bus, dev->device, dev->function, bar_address); + UINT32 upper = read_config(dev->bus, dev->device, dev->function, bar_address + 4); + return lower | (((UINT64)upper) << 32); +} + +void set_msi(device_t* dev) { + UINT8 local_apic_id = *(UINT32*)(0xFEE00020) >> 24; + UINT32 msg_addr = 0xFEE00000U | (local_apic_id << 12); + UINT32 msg_data = 0xC000U | 0x40U; + UINT8 cap_pointer = read_config(dev->bus, dev->device, dev->function, 0x34); +} + +void start_xhc(UINT64 mmio) { + capability_registers_t *cr = (capability_registers_t *)mmio; + log("mmio : %x\n", mmio + cr->CAPLENGTH); + log("CAPLENGTH : %d, HCIVERSION: %x, HCCPARAMS1: %x\n", cr->CAPLENGTH, cr->HCIVERSION, cr->HCCPARAMS1); + operational_registers_t *or = (operational_registers_t *)(mmio + cr->CAPLENGTH); + usbsts_t usbsts = (usbsts_t)or->USBSTS; + log("hch: %d, hse: %d, ei: %d, pcd: %d, sss: %d, rss: %d, sre: %d, cnr: %d, hce: %d \n", + usbsts.hcHalted, + usbsts.hostSystemError, + usbsts.eventInterrupt, + usbsts.portChangeDetect, + usbsts.saveStateStatus, + usbsts.restoreStateStatus, + usbsts.saveRestoreError, + usbsts.controllerNotReady, + usbsts.hostControllerError + ); + if (!usbsts.hcHalted) { + usbcmd_t usbcmd = (usbcmd_t)or->USBCMD; + usbcmd.runStop = false; + or->USBCMD = usbcmd; + log("write cmd\n"); + usbsts = (usbsts_t)or->USBSTS; + while(!usbsts.hcHalted); + } +} + void init_xhci() { - int y = 0; STATUS status = find_all_device(); - printf(0, y, "init xhci => %d\n", status); - y += 20; + log("init xhci => %d\n", status); device_t* xhc_device = NULL; for(int i = 0; i < device_num; i++) { device_t device = device_list[i]; UINT16 vendor_id = get_vendor_id(device.bus, device.device, device.function); if (is_xhci(&device.class_code)) { - printf(0, y, "bus: %d, device: %d, func: %d, base: %x, sub: %x, interface: %x, vendor_id: %x, header: %x\n", + log("bus: %d, device: %d, func: %d, base: %x, sub: %x, interface: %x, vendor_id: %x, header: %x\n", device.bus, device.device, device.function, device.class_code.base, device.class_code.sub, device.class_code.interface, vendor_id, device.header_type); xhc_device = &device; - y += 20; } } if (xhc_device == NULL) { - printf(0, y, "not found\n"); - y += 20; + log("not found\n"); + return; } - printf(0, y, "done xhci\n", status); + UINT64 bar = read_bar(xhc_device, 0); + UINT64 mmio = bar & ~0xFUL; // mask lower 4bit + log("bar: %x, mmio: %x", bar, mmio); + start_xhc(mmio); + log("done xhci\n", status); } diff --git a/graphics/desktop.c b/graphics/desktop.c index 6768f9d..b17c19c 100644 --- a/graphics/desktop.c +++ b/graphics/desktop.c @@ -100,3 +100,14 @@ void printf(unsigned int x, unsigned int y, char *format, ...) { put_s(x, y, WHITE, buf); va_end(list); } + +int y = 0; +void log(char *format, ...) { + char buf[256]; + va_list list; + va_start(list, format); + format_str(buf, format, &list); + put_s(0, y, WHITE, buf); + y += 20; + va_end(list); +} diff --git a/include/drivers/xhci.h b/include/drivers/xhci.h index 519c16f..31b98d7 100644 --- a/include/drivers/xhci.h +++ b/include/drivers/xhci.h @@ -48,4 +48,102 @@ STATUS add_device(UINT8 bus, UINT8 device, UINT8 function, UINT8 header_type, cl STATUS find_function(UINT8 bus, UINT8 device); STATUS find_device(UINT8 bus); +/* +typedef union { + UINT32 data[1]; + struct { + UINT8 CAPLENGTH; + UINT8 : 8; + UINT16 HCIVERSION; + UINT32 HCSPARAMS1; + UINT32 HCSPARAMS2; + UINT32 HCSPARAMS3; + UINT32 HCCPARAMS1; + UINT32 DBOFF; + UINT32 RTSOFF; + UINT32 HCCPARAMS2; + } __attribute__((packed)) bits; +} __attribute__((packed)) capability_registers_t; +*/ + +typedef struct { + UINT8 CAPLENGTH; + UINT8 : 8; + UINT16 HCIVERSION; + UINT32 HCSPARAMS1; + UINT32 HCSPARAMS2; + UINT32 HCSPARAMS3; + UINT32 HCCPARAMS1; + UINT32 DBOFF; + UINT32 RTSOFF; + UINT32 HCCPARAMS2; +} capability_registers_t; + + + +typedef struct { + UINT32 runStop: 1; + UINT32 hostControllerRest: 1; + UINT32 interrupterEnable: 1; + UINT32 hostSystemErrorEnable: 1; + UINT32 : 3; + UINT32 hightHostControllerRest: 1; + UINT32 controllerSaveState: 1; + UINT32 controllerRestoreState: 1; + UINT32 enableWrapEvent: 1; + UINT32 enableU3MfindexStop: 1; + UINT32 : 1; + UINT32 cemEnable: 1; + UINT32 extendedTbcEnable: 1; + UINT32 extendedTbcstatusEnable: 1; + UINT32 vtioEnable: 1; + UINT32 : 15; +} usbcmd_t; + +typedef struct { + UINT32 hcHalted: 1; + UINT32 : 1; + UINT32 hostSystemError: 1; + UINT32 eventInterrupt: 1; + UINT32 portChangeDetect: 1; + UINT32 : 3; + UINT32 saveStateStatus: 1; + UINT32 restoreStateStatus: 1; + UINT32 saveRestoreError: 1; + UINT32 controllerNotReady: 1; + UINT32 hostControllerError: 1; + UINT32 : 19; +} usbsts_t; + +typedef struct { + +} pagesize_t; + +typedef struct { + +} dnctrl_t; + +typedef struct { + +} crcr_t; + +typedef struct { + +} dcbaap_t; + +typedef struct { +} config_t; + +typedef struct { + usbcmd_t USBCMD; + usbsts_t USBSTS; + UINT32 pagesize; //pagesize_t pagesize; + UINT32 reserved_1[1]; + UINT32 dnctrl; // dnctrl_t dnctrl; + UINT32 crcr; //crcr_t crcr; + UINT32 reserved_2[4]; + UINT64 dcbaap; + config_t config; +} __attribute__((packed)) operational_registers_t; + #endif diff --git a/include/graphics/desktop.h b/include/graphics/desktop.h index 8ad60aa..3b0b809 100644 --- a/include/graphics/desktop.h +++ b/include/graphics/desktop.h @@ -17,4 +17,6 @@ void put_s(unsigned int x, unsigned int y, int color, char *str); void printf(unsigned int x, unsigned int y, char *format, ...); +void log(char *format, ...); + #endif diff --git a/kernel/Makefile b/kernel/Makefile index 1782a7f..70988db 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,5 +1,5 @@ CC = gcc -INCLUDE = -I../include -I../graphics/include -I../drivers/include +INCLUDE = -I../include -I../include/graphics -I../include/drivers CFLAGS = -c -Wall -Wextra $(INCLUDE) -nostdlib -fno-builtin -fPIE KERN_OBJ = main.o WIN_OBJ = ../graphics/desktop.o \ From 16822f13f190dfd1a1f7f50bd1f766dc0f94a915 Mon Sep 17 00:00:00 2001 From: bassaer Date: Wed, 23 Mar 2022 00:01:51 +0900 Subject: [PATCH 2/3] add dcbaap --- drivers/xhci.c | 29 ++++++++++++++++++++++++++--- include/drivers/xhci.h | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/drivers/xhci.c b/drivers/xhci.c index 8b49d2f..b823a06 100644 --- a/drivers/xhci.c +++ b/drivers/xhci.c @@ -142,6 +142,15 @@ void set_msi(device_t* dev) { UINT8 cap_pointer = read_config(dev->bus, dev->device, dev->function, 0x34); } +void wait() { + unsigned long long a = 0; + while(1) { + if (++a == 1000000000) { + break; + } + } +} + void start_xhc(UINT64 mmio) { capability_registers_t *cr = (capability_registers_t *)mmio; log("mmio : %x\n", mmio + cr->CAPLENGTH); @@ -159,14 +168,28 @@ void start_xhc(UINT64 mmio) { usbsts.controllerNotReady, usbsts.hostControllerError ); + usbcmd_t usbcmd = (usbcmd_t)or->USBCMD; if (!usbsts.hcHalted) { - usbcmd_t usbcmd = (usbcmd_t)or->USBCMD; usbcmd.runStop = false; or->USBCMD = usbcmd; - log("write cmd\n"); + while(!usbsts.hcHalted) { + usbsts = (usbsts_t)or->USBSTS; + }; + } + usbcmd.hostControllerReset = true; + or->USBCMD = usbcmd; + while(usbcmd.hostControllerReset || usbsts.controllerNotReady) { + usbcmd = (usbcmd_t)or->USBCMD; usbsts = (usbsts_t)or->USBSTS; - while(!usbsts.hcHalted); } + hcsparams1_t hcsparams1 = (hcsparams1_t)cr->HCSPARAMS1; + log("max_device_slots: %d\n", hcsparams1.number_of_device_slots); + config_t config = (config_t)or->CONFIG; + config.max_device_slots_enabled = 8; + or->CONFIG = config; + + + log("done xhc"); } void init_xhci() { diff --git a/include/drivers/xhci.h b/include/drivers/xhci.h index 31b98d7..4c0df5e 100644 --- a/include/drivers/xhci.h +++ b/include/drivers/xhci.h @@ -66,12 +66,28 @@ typedef union { } __attribute__((packed)) capability_registers_t; */ +typedef struct { + UINT32 number_of_device_slots: 8; + UINT32 number_of_interrupters: 11; + UINT32 : 5; + UINT32 number_of_ports: 8; +} hcsparams1_t; + +typedef struct { + UINT32 isochronousSchedulingThreshold: 4; + UINT32 eventRingSegmentTableMax: 4; + UINT32 : 13; + UINT32 max_scratchpad_buffers_high: 5; + UINT32 scratchpad_restore: 1; + UINT32 max_scratchpad_buffers_low: 5; +} hcsparams2_t; + typedef struct { UINT8 CAPLENGTH; UINT8 : 8; UINT16 HCIVERSION; - UINT32 HCSPARAMS1; - UINT32 HCSPARAMS2; + hcsparams1_t HCSPARAMS1; + hcsparams2_t HCSPARAMS2; UINT32 HCSPARAMS3; UINT32 HCCPARAMS1; UINT32 DBOFF; @@ -79,11 +95,9 @@ typedef struct { UINT32 HCCPARAMS2; } capability_registers_t; - - typedef struct { UINT32 runStop: 1; - UINT32 hostControllerRest: 1; + UINT32 hostControllerReset: 1; UINT32 interrupterEnable: 1; UINT32 hostSystemErrorEnable: 1; UINT32 : 3; @@ -128,10 +142,15 @@ typedef struct { } crcr_t; typedef struct { - + UINT32 : 6; + UINT64 dcbaa_pointer: 58; } dcbaap_t; typedef struct { + UINT32 max_device_slots_enabled: 8; + UINT32 u3_entry_enable: 1; + UINT32 configuration_information_enable: 1; + UINT32 : 12; } config_t; typedef struct { @@ -142,8 +161,8 @@ typedef struct { UINT32 dnctrl; // dnctrl_t dnctrl; UINT32 crcr; //crcr_t crcr; UINT32 reserved_2[4]; - UINT64 dcbaap; - config_t config; -} __attribute__((packed)) operational_registers_t; + dcbaap_t DCBAAP; + config_t CONFIG; +} operational_registers_t; #endif From 257ed374489c0aa36f6c982f176758c62ea73e40 Mon Sep 17 00:00:00 2001 From: bassaer Date: Thu, 24 Mar 2022 00:09:40 +0900 Subject: [PATCH 3/3] add device context --- drivers/xhci.c | 15 +++++--- include/drivers/xhci.h | 82 ++++++++++++++++++++++++++++++++++-------- kernel/main.c | 3 +- 3 files changed, 79 insertions(+), 21 deletions(-) diff --git a/drivers/xhci.c b/drivers/xhci.c index b823a06..03ef95a 100644 --- a/drivers/xhci.c +++ b/drivers/xhci.c @@ -151,7 +151,7 @@ void wait() { } } -void start_xhc(UINT64 mmio) { +void start_xhc(UINT64 mmio, device_context_t** device_contexts) { capability_registers_t *cr = (capability_registers_t *)mmio; log("mmio : %x\n", mmio + cr->CAPLENGTH); log("CAPLENGTH : %d, HCIVERSION: %x, HCCPARAMS1: %x\n", cr->CAPLENGTH, cr->HCIVERSION, cr->HCCPARAMS1); @@ -185,14 +185,19 @@ void start_xhc(UINT64 mmio) { hcsparams1_t hcsparams1 = (hcsparams1_t)cr->HCSPARAMS1; log("max_device_slots: %d\n", hcsparams1.number_of_device_slots); config_t config = (config_t)or->CONFIG; - config.max_device_slots_enabled = 8; + config.max_device_slots_enabled = MAX_DEVICE_SLOTS; or->CONFIG = config; - + for (int i = 0; i <= MAX_DEVICE_SLOTS; i++) { + device_contexts[i] = NULL; + } + dcbaap_t dcbaap = (dcbaap_t)or->DCBAAP; + dcbaap.dcbaa_pointer = ((UINT64)device_contexts) >> 6; + or->DCBAAP = dcbaap; log("done xhc"); } -void init_xhci() { +void init_xhci(device_context_t** device_contexts) { STATUS status = find_all_device(); log("init xhci => %d\n", status); device_t* xhc_device = NULL; @@ -212,6 +217,6 @@ void init_xhci() { UINT64 bar = read_bar(xhc_device, 0); UINT64 mmio = bar & ~0xFUL; // mask lower 4bit log("bar: %x, mmio: %x", bar, mmio); - start_xhc(mmio); + start_xhc(mmio, device_contexts); log("done xhci\n", status); } diff --git a/include/drivers/xhci.h b/include/drivers/xhci.h index 4c0df5e..6cbb835 100644 --- a/include/drivers/xhci.h +++ b/include/drivers/xhci.h @@ -19,6 +19,8 @@ typedef int STATUS; #define BASE_CLASS 0x06U #define SUB_CLASS 0x04U +#define MAX_DEVICE_SLOTS 8 + typedef struct { UINT8 base; UINT8 sub; @@ -33,21 +35,6 @@ typedef struct { class_code_t class_code; } device_t; -void init_xhci(); - -UINT32 build_address(UINT8 bus, UINT8 device, UINT8 function, UINT8 offset); -void set_config_address(UINT32 address); -void write_config_data(UINT32 data); -void outl(CHAR16 port, UINT32 value); -UINT32 inl(CHAR16 port); -UINT8 read_header_type(UINT8 bus, UINT8 device, UINT8 function); -void read_class_code(UINT8 bus, UINT8 device, UINT8 function, class_code_t* class_code); -UINT32 read_bus_number(UINT8 bus, UINT8 device, UINT8 function); -UINT16 get_vendor_id(UINT8 bus, UINT8 device, UINT8 function); -STATUS add_device(UINT8 bus, UINT8 device, UINT8 function, UINT8 header_type, class_code_t class_code); -STATUS find_function(UINT8 bus, UINT8 device); -STATUS find_device(UINT8 bus); - /* typedef union { UINT32 data[1]; @@ -165,4 +152,69 @@ typedef struct { config_t CONFIG; } operational_registers_t; +typedef struct { + UINT32 route_string: 20; + UINT32 speed: 4; + UINT32 : 1; + UINT32 multi_tt: 1; + UINT32 hub: 1; + UINT32 context_entries: 5; + UINT32 max_exit_latency: 16; + UINT32 root_hub_port_number: 8; + UINT32 number_of_ports: 8; + UINT32 parent_hub_slot_id: 8; + UINT32 parent_port_number: 8; + UINT32 tt_think_time: 2; + UINT32 : 4; + UINT32 interrupter_target: 10; + UINT32 usb_device_address: 8; + UINT32 : 19; + UINT32 slot_state: 5; + UINT32 reserved[4]; +} slot_context_t; + +typedef struct { + UINT32 endpoint_state: 3; + UINT32 : 5; + UINT32 mult: 2; + UINT32 max_primary_stream: 5; + UINT32 linear_stream_array: 1; + UINT32 interval: 8; + UINT32 max_esit_payload_hi: 8; + UINT32 : 1; + UINT32 error_count: 2; + UINT32 endpoint_type: 3; + UINT32 : 1; + UINT32 host_initiate_disable: 1; + UINT32 max_burst_size: 8; + UINT32 max_packet_size: 16; + UINT32 dequeue_cycle_state: 1; + UINT32 : 3; + UINT64 tr_dequeue_pointer: 60; + UINT32 average_trb_length: 16; + UINT32 max_esit_payload_lo: 16; + UINT32 reserved[3]; +} endpoint_context_t; + +typedef struct { + slot_context_t slot_context; + endpoint_context_t endpoint_context[31]; +} device_context_t; + + +void init_xhci(device_context_t** device_contexts); + +UINT32 build_address(UINT8 bus, UINT8 device, UINT8 function, UINT8 offset); +void set_config_address(UINT32 address); +void write_config_data(UINT32 data); +void outl(CHAR16 port, UINT32 value); +UINT32 inl(CHAR16 port); +UINT8 read_header_type(UINT8 bus, UINT8 device, UINT8 function); +void read_class_code(UINT8 bus, UINT8 device, UINT8 function, class_code_t* class_code); +UINT32 read_bus_number(UINT8 bus, UINT8 device, UINT8 function); +UINT16 get_vendor_id(UINT8 bus, UINT8 device, UINT8 function); +STATUS add_device(UINT8 bus, UINT8 device, UINT8 function, UINT8 header_type, class_code_t class_code); +STATUS find_function(UINT8 bus, UINT8 device); +STATUS find_device(UINT8 bus); + #endif diff --git a/kernel/main.c b/kernel/main.c index 722eafe..188493d 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -13,7 +13,8 @@ void kernel_main(BootInfo *boot) { init_desktop(boot); - init_xhci(); + device_context_t* device_context[MAX_DEVICE_SLOTS + 1]; + init_xhci(&device_context); while (1) __asm__ volatile("hlt"); }