From 38b5b611fa12a00ade9bb140fe26e000e44c67e2 Mon Sep 17 00:00:00 2001 From: Rick Rongen Date: Sat, 6 Mar 2021 15:10:21 +0100 Subject: [PATCH] feat: refactored some pci code and added pretty print of classes --- CMakeLists.txt | 3 +- kernel/command.c | 4 + kernel/drivers/ide.c | 2 + kernel/drivers/pci.c | 91 ++++++++++- kernel/drivers/pci.h | 10 +- kernel/drivers/pci_devices.h | 296 +++++++++++++++++++++++++++++++++++ kernel/libc/kprintf.c | 7 +- launch-qemu.sh | 58 +++++++ qemu-debug.sh | 3 - 9 files changed, 459 insertions(+), 15 deletions(-) create mode 100644 kernel/drivers/pci_devices.h create mode 100755 launch-qemu.sh delete mode 100755 qemu-debug.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 38e7e49..26f18dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ project(new_kernel C ASM) #SET(CMAKE_VERBOSE_MAKEFILE ON) SET(GCC_INCLUDE_DIR "/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include") SET(CMAKE_C_FLAGS "-I${GCC_INCLUDE_DIR} -mno-sse -g -ffreestanding -Wall -Wextra -fno-exceptions -fno-stack-protector -nostdinc -nostdlib -fno-pie -m32") -SET(CMAKE_ASM_FLAGS "${CFLAGS} -m32 -x assembler-with-cpp" ) +SET(CMAKE_ASM_FLAGS "${CFLAGS} -m32 -x assembler-with-cpp") SET(CMAKE_EXE_LINKER_FLAGS "-T${CMAKE_CURRENT_LIST_DIR}/linker.ld -lgcc -ffreestanding -nostdlib -no-pie") include_directories(AFTER kernel boot) @@ -17,6 +17,7 @@ FILE(GLOB_RECURSE boot_asm boot/boot.S) # Run IDE in DMA mode if available (NYI) #add_compile_definitions(IDE_ENABLE_INTERRUPT) # Run the kernel shell as the main task +add_compile_definitions(ENABLE_PCIPP) # Support for pretty printing pci class/subclass/interface add_compile_definitions(K_SHELL) add_executable(my-kernel.bin ${kernel_src} ${kernel_asm} ${boot_asm}) diff --git a/kernel/command.c b/kernel/command.c index f35929b..be35831 100644 --- a/kernel/command.c +++ b/kernel/command.c @@ -95,6 +95,10 @@ void print(const char *arg) { pci_print_info(); } else if (strcmp(arg, "pci_caps") == 0) { pci_dump_caps(); +#ifdef ENABLE_PCIPP + } else if (strcmp(arg, "pcipp") == 0) { + pci_pretty_print(); +#endif } else if (strcmp(arg, "ide") == 0) { ide_print_devices(); } else { diff --git a/kernel/drivers/ide.c b/kernel/drivers/ide.c index aca63cd..fe10ec3 100644 --- a/kernel/drivers/ide.c +++ b/kernel/drivers/ide.c @@ -331,6 +331,8 @@ const pci_driver ide_pci_driver = { .description = "Default PCI IDE Driver", .order = 0xFF, // let other block_dev_drivers precede if they can .pci_use_subclass = true, + .validatable = true, + .initialisable = true, .pci_class = PCI_CLASS_MASS_STORAGE, .pci_subclass = PCI_SUB_CLASS_IDE, diff --git a/kernel/drivers/pci.c b/kernel/drivers/pci.c index 4120107..813e35c 100644 --- a/kernel/drivers/pci.c +++ b/kernel/drivers/pci.c @@ -10,6 +10,12 @@ #include #include +#ifdef ENABLE_PCIPP + +#include + +#endif + #define PCI_CONFIG_ENABLE (1 << 31) #define PCI_CONFIG_SHIFT_BUS_NUMBER 16 @@ -28,6 +34,17 @@ #define MASK_BAR_IOSPACE 0xFFFFFFFC #define MASK_BAR_MEMSPACE 0xFFFFFFF0 +const pci_driver pci_internal_secondary_bus = { + .name = "pci-secondary-bus", + .description = "A PCI bus connected to the primary bus", + .order = 0, + .pci_class = 0x06, + .pci_subclass = 0x04, + .pci_use_subclass = true, + .validate = NULL, + .initialize = NULL, +}; + const pci_driver *pci_drivers[MAX_PCI_DRIVERS]; int last_pci_device_index = 0; pci_device pci_devices[MAX_PCI_DEVICES]; @@ -114,6 +131,16 @@ uint8_t pci_get_header_type(uint8_t bus, uint8_t slot, uint8_t func) { } void pci_pick_driver(pci_device *device) { + // check special drivers + // PCI Secondary bus + if (device->class == pci_internal_secondary_bus.pci_class && device->subclass == pci_internal_secondary_bus.pci_subclass) { + uint8_t secondary_bus = pci_config_read_byte(device->bus, device->slot, device->func, PCI_CONFIG_SECONDARY_BUS_NUMBER); + device->pci_driver = &pci_internal_secondary_bus; + pci_check_bus(secondary_bus); + return; + } + + // use normal drivers for (int i = 0; i < MAX_PCI_DRIVERS; ++i) { if (pci_drivers[i] == NULL) { continue; @@ -124,6 +151,9 @@ void pci_pick_driver(pci_device *device) { if (pci_drivers[i]->pci_use_subclass && device->subclass != pci_drivers[i]->pci_subclass) { continue; } + if (!pci_drivers[i]->validatable) { + continue; + } if (pci_drivers[i]->validate(device) != PCI_VALIDATE_OK) { continue; } @@ -141,13 +171,7 @@ void pci_check_function(uint8_t bus, uint8_t slot, uint8_t func) { pci_devices[last_pci_device_index].device_state.present = 1; last_pci_device_index++; - if (pci_devices[last_pci_device_index-1].class == 0x06 && pci_devices[last_pci_device_index-1].subclass == 0x04) { - uint8_t secondary_bus = pci_config_read_byte(bus, slot, func, PCI_CONFIG_SECONDARY_BUS_NUMBER); - printf("Found secondary bus: %d\n", secondary_bus); - pci_check_bus(secondary_bus); - } else { - pci_pick_driver(&pci_devices[last_pci_device_index-1]); - } + pci_pick_driver(&pci_devices[last_pci_device_index - 1]); // todo do something with the function } @@ -203,7 +227,9 @@ void pci_init_drivers() { if (pci_devices[device_index].pci_driver == NULL) { continue; // no driver found } - pci_devices[device_index].pci_driver->initialize(&pci_devices[device_index]); + if (pci_devices[device_index].pci_driver->initialisable) { + pci_devices[device_index].pci_driver->initialize(&pci_devices[device_index]); + } pci_devices[device_index].driver_state.initialized = 1; } } @@ -243,6 +269,55 @@ void pci_dump_caps() { } } +#ifdef ENABLE_PCIPP + +void pci_pretty_print() { + for (int i = 0; i < last_pci_device_index; ++i) { + char *class = NULL; + char *subclass = NULL; + char *function = NULL; + pci_device_info *class_info = NULL; + pci_device_info *subclass_info = NULL; + pci_device_info *function_info = NULL; + pci_device_info *current = pci_root_info; + while (current->name != NULL) { + if (current->code == pci_devices[i].class) { + class = current->name; + class_info = current; + break; + } + current = current + 1; + } + if (class_info != NULL && class_info->sub != NULL) { + current = class_info->sub; + while (current->name != NULL) { + if (current->code == pci_devices[i].subclass) { + subclass = current->name; + subclass_info = current; + break; + } + current = current + 1; + } + } + if (subclass_info != NULL && subclass_info->sub != NULL) { + current = subclass_info->sub; + while (current->name != NULL) { + if (current->code == pci_devices[i].programInterface) { + function = current->name; + function_info = current; + break; + } + current = current + 1; + } + } + printf("PCI BSF: %2x/%2x/%2x %s %s %s\n", + pci_devices[i].bus, pci_devices[i].slot, pci_devices[i].func, + class, subclass, function); + } +} + +#endif + void pci_init_bar(pci_device *device, uint8_t bar_index) { if (device->headerType != 0x00) { k_panics("Only header 0x00 supported for now"); diff --git a/kernel/drivers/pci.h b/kernel/drivers/pci.h index 4552ead..21c1219 100644 --- a/kernel/drivers/pci.h +++ b/kernel/drivers/pci.h @@ -90,7 +90,9 @@ typedef struct pci_driver { uint8_t pci_class; uint8_t pci_subclass; struct { - uint8_t pci_use_subclass: 1; + bool pci_use_subclass: 1; + bool validatable: 1; + bool initialisable: 1; }; pci_driver_validate validate; pci_driver_initialize initialize; @@ -190,6 +192,12 @@ void pci_print_info(); void pci_dump_caps(); +#ifdef ENABLE_PCIPP + +void pci_pretty_print(); + +#endif + uint32_t pci_register_driver(const pci_driver *pci_driver); void pci_sort_drivers(); diff --git a/kernel/drivers/pci_devices.h b/kernel/drivers/pci_devices.h new file mode 100644 index 0000000..5a70271 --- /dev/null +++ b/kernel/drivers/pci_devices.h @@ -0,0 +1,296 @@ +// +// Created by rick on 06-03-21. +// +#ifndef NEW_KERNEL_PCI_DEVICES_H +#define NEW_KERNEL_PCI_DEVICES_H + +#include + +typedef struct pci_device_info_t { + uint8_t code; + char *name; + struct pci_device_info_t *sub; +} pci_device_info; + +// build from https://wiki.osdev.org/PCI#Class_Codes + +pci_device_info info_unclassified[] = { + {0x00, "Non VGA Compatible", NULL}, + {0x01, "VGA Compatible", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_mass_storage_ide[] = { + {0x00, "ISA comp only", NULL}, + {0x05, "PCI native only", NULL}, + {0x0A, "ISA compatibility controller, 2C, PCI native", NULL}, + {0x0F, "PCI native controller, 2C, ISA comp", NULL}, + {0x80, "ISA comp only, BM", NULL}, + {0x85, "PCI native only, BM", NULL}, + {0x8A, "ISA Comp only, 2C, BM, PCI native", NULL}, + {0x8F, "PCI native, 2C, BM, ISA comp", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_mass_storage_ata[] = { + {0x20, "Single DMA", NULL}, + {0x30, "Chained DMA", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_mass_storage_sata[] = { + {0x00, "Vendor specific", NULL}, + {0x01, "AHCI 1.0", NULL}, + {0x02, "Serial Storage Bus", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_mass_storage_sas[] = { + {0x00, "SAS", NULL}, + {0x01, "Serial Storage Bus", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_mass_storage_nvm[] = { + {0x01, "NVMHCI", NULL}, + {0x02, "NVM Express", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_mass_storage[] = { + {0x00, "SCSI Bus Controller", NULL}, + {0x01, "IDE Controller", info_mass_storage_ide}, + {0x02, "Floppy Disk Controller", NULL}, + {0x03, "IPI Bus Controller", NULL}, + {0x04, "RAID Controller", NULL}, + {0x05, "ATA Controller", info_mass_storage_ata}, + {0x06, "Serial ATA", info_mass_storage_sata}, + {0x07, "Serial Attached SCSI", info_mass_storage_sas}, + {0x08, "NVM Controller", info_mass_storage_nvm}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_network_controller[] = { + {0x00, "Ethernet", NULL}, + {0x01, "Token Ring", NULL}, + {0x02, "FDDI", NULL}, + {0x03, "ATM", NULL}, + {0x04, "ISDN", NULL}, + {0x05, "WordFip", NULL}, + {0x06, "FICMG 2.14 Multi Computing", NULL}, + {0x07, "Infiniband", NULL}, + {0x08, "Fabric", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_display_vga_comp[] = { + {0x00, "VGA", NULL}, + {0x01, "8514", NULL}, + {0, NULL, 0}, +}; + +pci_device_info info_display_controller[] = { + {0x00, "VGA Compatible", info_display_vga_comp}, + {0x01, "XGA", NULL}, + {0x02, "3D", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_multimedia_controller[] = { + {0x00, "Video", NULL}, + {0x01, "Audio", NULL}, + {0x02, "Computer Telephony", NULL}, + {0x03, "Audio", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_memory_controller[] = { + {0x00, "RAM", NULL}, + {0x01, "Flash", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_bridge_pci4[] = { + {0x00, "Normal", NULL}, + {0x01, "Subtractive", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_bridge_raceway[] = { + {0x00, "Transparent", NULL}, + {0x01, "Endpoint", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_bridge_pci9[] = { + {0x40, "Semi-transparent, primary", NULL}, + {0x80, "Semi-transparent, secondary", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_bridge_device[] = { + {0x00, "Host", NULL}, + {0x01, "ISA", NULL}, + {0x02, "EISA", NULL}, + {0x03, "MCA", NULL}, + {0x04, "PCI-to-PCI4", info_bridge_pci4}, + {0x05, "PMCIA", NULL}, + {0x06, "NuBus", NULL}, + {0x07, "CardBus", NULL}, + {0x08, "RACEway", info_bridge_raceway}, + {0x09, "PCI-to-PCI9", info_bridge_pci9}, + {0x0A, "Infiniband-to-host", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_simple_comm[] = { + {0x00, "Serial", NULL}, // todo sub + {0x01, "Parallel", NULL}, // todo sub + {0x02, "Multiport serial", NULL}, + {0x03, "Modem", NULL}, // todo sub + {0x04, "IEEE 488.1/2 GPIB", NULL}, + {0x05, "Smart card", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_base_system_peripheral[] = { + {0x00, "PIC", NULL}, // todo sub + {0x01, "DMA", NULL}, // todo sub + {0x02, "Timer", NULL}, // todo sub + {0x03, "RTC", NULL}, // todo sub + {0x04, "PCI Hot Plug", NULL}, + {0x05, "SD", NULL}, + {0x06, "IOMMU", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_input_device[] = { + {0x00, "Keyboard", NULL}, + {0x01, "Digitizer pen", NULL}, + {0x02, "Mouse", NULL}, + {0x03, "Scanner", NULL}, + {0x04, "Game Port", NULL}, // todo sub + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_docking_station[] = { + {0x00, "Generic", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_processor[] = { + {0x00, "386", NULL}, + {0x01, "486", NULL}, + {0x02, "Pentium", NULL}, + {0x03, "Pentium Pro", NULL}, + {0x10, "Alpha", NULL}, + {0x20, "PowerPC", NULL}, + {0x30, "MIPS", NULL}, + {0x40, "Co-Processor", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_serial_bus_usb[] = { + {0x00, "UHCI (1.0)", NULL}, + {0x10, "OHCI (1.1)", NULL}, + {0x20, "EHCI (2.0)", NULL}, + {0x30, "XHCI (3.0)", NULL}, + {0x80, "Unspecified", NULL}, + {0xFE, "Device", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_serial_bus[] = { + {0x00, "FireWire", NULL}, // todo sub + {0x01, "ACCESS bus", NULL}, + {0x02, "SSA", NULL}, + {0x03, "USB", info_serial_bus_usb}, + {0x04, "Fibre Channel", NULL}, + {0x05, "SMBus", NULL}, + {0x06, "InfiniBand", NULL}, + {0x07, "IPMI Interface", NULL}, // todo sub + {0x08, "SERCOS", NULL}, + {0x09, "CanBus", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_wireless[] = { + {0x00, "IRDA Comp", NULL}, + {0x01, "Consumer IR", NULL}, + {0x10, "RF", NULL}, + {0x11, "Bluetooth", NULL}, + {0x12, "Broadband", NULL}, + {0x20, "Ethernet 802.1a", NULL}, + {0x21, "Ethernet 802.1b", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_intelligent[] = { + {0x00, "I20", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_satellite[] = { + {0x01, "Satellite TV", NULL}, + {0x02, "Satellite Audio", NULL}, + {0x03, "Satellite Voice", NULL}, + {0x04, "Satellite Data", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_encryption[] = { + {0x00, "Network and Computing", NULL}, + {0x10, "Entertainment", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info info_signal_processing[] = { + {0x00, "DPIO Modules", NULL}, + {0x01, "Performance Counters", NULL}, + {0x10, "Communication Synchronizer", NULL}, + {0x20, "Signal Processing Management", NULL}, + {0x80, "Other", NULL}, + {0, NULL, NULL}, +}; + +pci_device_info pci_root_info[] = { + {0x00, "Unclassified", info_unclassified}, + {0x01, "Mass Storage", info_mass_storage}, + {0x02, "Network", info_network_controller}, + {0x03, "Display", info_display_controller}, + {0x04, "Multimedia", info_multimedia_controller}, + {0x05, "Memory", info_memory_controller}, + {0x06, "Bridge", info_bridge_device}, + {0x07, "Simple Communication", info_simple_comm}, + {0x08, "Base System Peripheral", info_base_system_peripheral}, + {0x09, "Input Device", info_input_device}, + {0x0a, "Docking", info_docking_station}, + {0x0b, "Processor", info_processor}, + {0x0c, "Serial Bus", info_serial_bus}, + {0x0d, "Wireless", info_wireless}, + {0x0e, "Intelligent", info_intelligent}, + {0x0f, "Satellite Comm", info_satellite}, + {0x10, "Encryption", info_encryption}, + {0x11, "Signal Processing", info_signal_processing}, + {0x12, "Processing Accelerator", NULL}, + {0x13, "Non-Essential", NULL}, + {0x40, "Co-Processor", NULL}, + {0xFF, "Unassigned", NULL}, + {0, NULL, NULL}, +}; + +#endif //NEW_KERNEL_PCI_DEVICES_H diff --git a/kernel/libc/kprintf.c b/kernel/libc/kprintf.c index 0ecde04..56ea77c 100644 --- a/kernel/libc/kprintf.c +++ b/kernel/libc/kprintf.c @@ -9,7 +9,7 @@ #include #include #include - +const char* printf_null_str = "NULL"; /* * Integer to string */ @@ -46,7 +46,10 @@ uint32_t vasprintf(char *buf, const char *fmt, va_list args) { } switch (fmt[i]) { case 's': { // string - char *s_fmt = (char *) va_arg(args, char*); + const char *s_fmt = (char *) va_arg(args, char*); + if (s_fmt == NULL) { + s_fmt = printf_null_str; + } while (*s_fmt) { buf[ptr++] = *s_fmt++; } diff --git a/launch-qemu.sh b/launch-qemu.sh new file mode 100755 index 0000000..54b2985 --- /dev/null +++ b/launch-qemu.sh @@ -0,0 +1,58 @@ +#!/bin/bash +ARGS="" +KERNEL="-kernel cmake-build-debug/my-kernel.bin" +NOHUP=0 + +function print_help() { + cat </dev/null & + disown +else + # shellcheck disable=SC2086 + qemu-system-i386 ${ARGS} ${KERNEL} +fi diff --git a/qemu-debug.sh b/qemu-debug.sh deleted file mode 100755 index f43f94e..0000000 --- a/qemu-debug.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -nohup qemu-system-i386 -cpu max -S -s -kernel cmake-build-debug/my-kernel.bin -hda tmp.img -d guest_errors,int -m 1G > /dev/null & -disown