Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand All @@ -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
Expand Down
106 changes: 88 additions & 18 deletions drivers/xhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -128,25 +128,95 @@ bool is_xhci(class_code_t* code) {
return code->base == 0x0CU && code->sub == 0x03U && code->interface == 0x30U;
}

void init_xhci() {
int y = 0;
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 wait() {
unsigned long long a = 0;
while(1) {
if (++a == 1000000000) {
break;
}
}
}

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);
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
);
usbcmd_t usbcmd = (usbcmd_t)or->USBCMD;
if (!usbsts.hcHalted) {
usbcmd.runStop = false;
or->USBCMD = usbcmd;
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;
}
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 = 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(device_context_t** device_contexts) {
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, device_contexts);
log("done xhci\n", status);
}
11 changes: 11 additions & 0 deletions graphics/desktop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
171 changes: 170 additions & 1 deletion include/drivers/xhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -33,7 +35,174 @@ typedef struct {
class_code_t class_code;
} device_t;

void init_xhci();
/*
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 {
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;
hcsparams1_t HCSPARAMS1;
hcsparams2_t HCSPARAMS2;
UINT32 HCSPARAMS3;
UINT32 HCCPARAMS1;
UINT32 DBOFF;
UINT32 RTSOFF;
UINT32 HCCPARAMS2;
} capability_registers_t;

typedef struct {
UINT32 runStop: 1;
UINT32 hostControllerReset: 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 {
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 {
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];
dcbaap_t DCBAAP;
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);
Expand Down
2 changes: 2 additions & 0 deletions include/graphics/desktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion kernel/Makefile
Original file line number Diff line number Diff line change
@@ -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 \
Expand Down
3 changes: 2 additions & 1 deletion kernel/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}