feat: refactored some pci code and added pretty print of classes

This commit is contained in:
2021-03-06 15:10:21 +01:00
parent 310f3621a2
commit 38b5b611fa
9 changed files with 459 additions and 15 deletions

View File

@@ -3,7 +3,7 @@ project(new_kernel C ASM)
#SET(CMAKE_VERBOSE_MAKEFILE ON) #SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(GCC_INCLUDE_DIR "/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include") 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_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") SET(CMAKE_EXE_LINKER_FLAGS "-T${CMAKE_CURRENT_LIST_DIR}/linker.ld -lgcc -ffreestanding -nostdlib -no-pie")
include_directories(AFTER kernel boot) 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) # Run IDE in DMA mode if available (NYI)
#add_compile_definitions(IDE_ENABLE_INTERRUPT) #add_compile_definitions(IDE_ENABLE_INTERRUPT)
# Run the kernel shell as the main task # 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_compile_definitions(K_SHELL)
add_executable(my-kernel.bin ${kernel_src} ${kernel_asm} ${boot_asm}) add_executable(my-kernel.bin ${kernel_src} ${kernel_asm} ${boot_asm})

View File

@@ -95,6 +95,10 @@ void print(const char *arg) {
pci_print_info(); pci_print_info();
} else if (strcmp(arg, "pci_caps") == 0) { } else if (strcmp(arg, "pci_caps") == 0) {
pci_dump_caps(); pci_dump_caps();
#ifdef ENABLE_PCIPP
} else if (strcmp(arg, "pcipp") == 0) {
pci_pretty_print();
#endif
} else if (strcmp(arg, "ide") == 0) { } else if (strcmp(arg, "ide") == 0) {
ide_print_devices(); ide_print_devices();
} else { } else {

View File

@@ -331,6 +331,8 @@ const pci_driver ide_pci_driver = {
.description = "Default PCI IDE Driver", .description = "Default PCI IDE Driver",
.order = 0xFF, // let other block_dev_drivers precede if they can .order = 0xFF, // let other block_dev_drivers precede if they can
.pci_use_subclass = true, .pci_use_subclass = true,
.validatable = true,
.initialisable = true,
.pci_class = PCI_CLASS_MASS_STORAGE, .pci_class = PCI_CLASS_MASS_STORAGE,
.pci_subclass = PCI_SUB_CLASS_IDE, .pci_subclass = PCI_SUB_CLASS_IDE,

View File

@@ -10,6 +10,12 @@
#include <libk/libk.h> #include <libk/libk.h>
#include <libc/kprintf.h> #include <libc/kprintf.h>
#ifdef ENABLE_PCIPP
#include <drivers/pci_devices.h>
#endif
#define PCI_CONFIG_ENABLE (1 << 31) #define PCI_CONFIG_ENABLE (1 << 31)
#define PCI_CONFIG_SHIFT_BUS_NUMBER 16 #define PCI_CONFIG_SHIFT_BUS_NUMBER 16
@@ -28,6 +34,17 @@
#define MASK_BAR_IOSPACE 0xFFFFFFFC #define MASK_BAR_IOSPACE 0xFFFFFFFC
#define MASK_BAR_MEMSPACE 0xFFFFFFF0 #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]; const pci_driver *pci_drivers[MAX_PCI_DRIVERS];
int last_pci_device_index = 0; int last_pci_device_index = 0;
pci_device pci_devices[MAX_PCI_DEVICES]; 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) { 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) { for (int i = 0; i < MAX_PCI_DRIVERS; ++i) {
if (pci_drivers[i] == NULL) { if (pci_drivers[i] == NULL) {
continue; 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) { if (pci_drivers[i]->pci_use_subclass && device->subclass != pci_drivers[i]->pci_subclass) {
continue; continue;
} }
if (!pci_drivers[i]->validatable) {
continue;
}
if (pci_drivers[i]->validate(device) != PCI_VALIDATE_OK) { if (pci_drivers[i]->validate(device) != PCI_VALIDATE_OK) {
continue; 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; pci_devices[last_pci_device_index].device_state.present = 1;
last_pci_device_index++; last_pci_device_index++;
if (pci_devices[last_pci_device_index-1].class == 0x06 && pci_devices[last_pci_device_index-1].subclass == 0x04) { pci_pick_driver(&pci_devices[last_pci_device_index - 1]);
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]);
}
// todo do something with the function // todo do something with the function
} }
@@ -203,7 +227,9 @@ void pci_init_drivers() {
if (pci_devices[device_index].pci_driver == NULL) { if (pci_devices[device_index].pci_driver == NULL) {
continue; // no driver found 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; 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) { void pci_init_bar(pci_device *device, uint8_t bar_index) {
if (device->headerType != 0x00) { if (device->headerType != 0x00) {
k_panics("Only header 0x00 supported for now"); k_panics("Only header 0x00 supported for now");

View File

@@ -90,7 +90,9 @@ typedef struct pci_driver {
uint8_t pci_class; uint8_t pci_class;
uint8_t pci_subclass; uint8_t pci_subclass;
struct { struct {
uint8_t pci_use_subclass: 1; bool pci_use_subclass: 1;
bool validatable: 1;
bool initialisable: 1;
}; };
pci_driver_validate validate; pci_driver_validate validate;
pci_driver_initialize initialize; pci_driver_initialize initialize;
@@ -190,6 +192,12 @@ void pci_print_info();
void pci_dump_caps(); void pci_dump_caps();
#ifdef ENABLE_PCIPP
void pci_pretty_print();
#endif
uint32_t pci_register_driver(const pci_driver *pci_driver); uint32_t pci_register_driver(const pci_driver *pci_driver);
void pci_sort_drivers(); void pci_sort_drivers();

View File

@@ -0,0 +1,296 @@
//
// Created by rick on 06-03-21.
//
#ifndef NEW_KERNEL_PCI_DEVICES_H
#define NEW_KERNEL_PCI_DEVICES_H
#include <types.h>
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

View File

@@ -9,7 +9,7 @@
#include <libk/kprint.h> #include <libk/kprint.h>
#include <libk/libk.h> #include <libk/libk.h>
#include <types.h> #include <types.h>
const char* printf_null_str = "NULL";
/* /*
* Integer to string * Integer to string
*/ */
@@ -46,7 +46,10 @@ uint32_t vasprintf(char *buf, const char *fmt, va_list args) {
} }
switch (fmt[i]) { switch (fmt[i]) {
case 's': { // string 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) { while (*s_fmt) {
buf[ptr++] = *s_fmt++; buf[ptr++] = *s_fmt++;
} }

58
launch-qemu.sh Executable file
View File

@@ -0,0 +1,58 @@
#!/bin/bash
ARGS=""
KERNEL="-kernel cmake-build-debug/my-kernel.bin"
NOHUP=0
function print_help() {
cat <<EOF
Usage: $0 [OPTION]...
Options:
-h, --help Print help info
-d, --debug Start qemu with halted cpu and GDB port 1234 open. Also print guest errors and interrupts
-i [disk], --ide [disk] Use [disk] as a hda on an IDE bus
-n, --nohup Run QEMU using nohup and output to /dev/null
-m, --max-cpu Run qemu with -m max
EOF
}
while [[ "$#" -gt 0 ]]; do
key=$1
case $key in
-d | --debug)
ARGS="${ARGS} -S -s -d guest_errors,int"
shift
;;
-i | --ide)
ARGS="${ARGS} -hda $2"
shift 2
;;
-s | --sata)
ARGS="${ARGS} -drive id=disk1,file=$2,if=none -device ahci,id=ahci -device ide-drive,drive=disk1,bus=ahci.0"
shift 2
;;
-m | --max-cpu)
ARGS="${ARGS} -cpu max"
shift
;;
-n | --nophup)
NOHUP=1
shift
;;
-h | --help)
print_help
exit
;;
esac
done
echo "Launching with args ${ARGS} ${KERNEL}"
if [ "$NOHUP" -gt 0 ]; then
# shellcheck disable=SC2086
nohup qemu-system-i386 ${ARGS} ${KERNEL} >/dev/null &
disown
else
# shellcheck disable=SC2086
qemu-system-i386 ${ARGS} ${KERNEL}
fi

View File

@@ -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