diff --git a/Makefile b/Makefile index c553ba1..365f8be 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,21 @@ CC = ${HOME}/opt/cross/bin/i686-elf-gcc CPP = ${HOME}/opt/cross/bin/i686-elf-g++ CFLAGS = -ffreestanding -O2 -Wall -Wextra -OFILES = $(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/PhysicalMemoryManager.o $(BUILD_DIR)/io.o $(BUILD_DIR)/PageDirectory.o $(BUILD_DIR)/gdtc.o $(BUILD_DIR)/idt.o $(BUILD_DIR)/pci.o $(BUILD_DIR)/pic.o $(BUILD_DIR)/string.o +OFILES = \ +$(BUILD_DIR)/boot.o \ +$(BUILD_DIR)/kterm.o \ +$(BUILD_DIR)/kernel.o \ +$(BUILD_DIR)/PhysicalMemoryManager.o \ +$(BUILD_DIR)/io.o \ +$(BUILD_DIR)/PageDirectory.o \ +$(BUILD_DIR)/gdtc.o \ +$(BUILD_DIR)/idt.o \ +$(BUILD_DIR)/pci.o \ +$(BUILD_DIR)/pic.o \ +$(BUILD_DIR)/string.o \ +$(BUILD_DIR)/pcidevice.o + + SRC_DIR = src BUILD_DIR = build @@ -88,3 +102,6 @@ $(BUILD_DIR)/PhysicalMemoryManager.o: $(BUILD_DIR)/pci.o: $(CPP) -c $(SRC_DIR)/kernel/pci.cpp -o $(BUILD_DIR)/pci.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(BUILD_DIR)/pcidevice.o: + $(CPP) -c $(SRC_DIR)/kernel/pci/pciDevice.cpp -o $(BUILD_DIR)/pcidevice.o $(CFLAGS) -fno-exceptions -fno-rtti diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp index 03654bf..8157292 100644 --- a/src/kernel/kernel.cpp +++ b/src/kernel/kernel.cpp @@ -62,53 +62,16 @@ extern "C" void kernel_main (void); init_serial(); print_serial("Serial port initialized!"); + + // Enumerate the PCI bus - - int devicesFound = 0; - // loop through all possible busses, devices and their functions; - for( int bus = 0 ; bus < 256 ; bus++) - { - - for(int device = 0; device < 32 ; device ++) - { - for ( int function = 0; function < 8; function++) - { - - uint64_t DeviceIdentify = ConfigReadWord(bus, device, function,0x0); - uint32_t VendorID = DeviceIdentify & 0xFFFF; - uint32_t DeviceID = DeviceIdentify >> 16; + PCI_Enumerate(); - - if( DeviceID != 0xFFFF){ - printf("bus: %d, device: %d, function %d \n"); - printf("Device found!\n"); - printf("DeviceID: 0x%x, VendorID: 0x%x\n", DeviceID, VendorID); - - uint32_t classcodes = ConfigReadWord(bus, device, function, 0x8); - uint32_t classData = classcodes >> 16; // We only care for the last 2 bytes! - uint32_t deviceClass = classData >> 8; - uint32_t subclass = classData & 0xFF; - - printf(" class: %d, subClass: %d\n\n", deviceClass, subclass); - devicesFound++; - - } - - - - } - - } - - } - - printf("Found %d devices!", devicesFound); - while (true){ //Read time indefinetely - //read_rtc(); - //printf( "UTC time: %02d-%02d-%02d %02d:%02d:%02d [ Formatted as YY-MM-DD h:mm:ss]\r" ,year, month, day, hour, minute, second); + read_rtc(); + printf( "UTC time: %02d-%02d-%02d %02d:%02d:%02d [ Formatted as YY-MM-DD h:mm:ss]\r" ,year, month, day, hour, minute, second); delay(1000); } diff --git a/src/kernel/kernel.h b/src/kernel/kernel.h index ff76ffa..cb9755a 100644 --- a/src/kernel/kernel.h +++ b/src/kernel/kernel.h @@ -19,6 +19,7 @@ extern "C"{ #include "pci.h" + #define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit))) #define PANIC(message) { return; } diff --git a/src/kernel/pci.cpp b/src/kernel/pci.cpp index a579fbd..e2d213c 100644 --- a/src/kernel/pci.cpp +++ b/src/kernel/pci.cpp @@ -1,11 +1,119 @@ #include "pci.h" -#include "tty/kterm.h" + #define PCI_BUS_ADDR_SHIFT 16 #define PCI_DEVICE_ADDR_SHIFT 11 #define PCI_FUNCTION_ADDR_SHIFT 8 #define PCI_ENABLE_ADDR_SHIFT 31 +const char* GetClassCodeName (uint64_t ClassCode ) { + + switch (ClassCode) + { + case 0x0 : + return "Unclassified"; + break; + case 0x1: + return "Mass Storage Controller"; + break; + + case 0x2: + return "Network Controller"; + break; + + case 0x3: + return "Display Controller"; + break; + + case 0x4: + return "Multimedia Controller"; + break; + + case 0x5: + return "Memory Controller"; + break; + + case 0x6: + return "Bridge"; + break; + + case 0x7 : + return "Simple Communication Controller"; + break; + + case 0x8: + return "Base System Peripheral"; + break; + + case 0x9: + return "Input Device Controller"; + break; + + case 0xA: + return "Docking station"; + break; + case 0xB: + return "Processor"; + break; + + case 0xC: + return "Serial Bus Controller"; + break; + + case 0xD: + return "Wireless Controller"; + break; + + case 0xE: + return "Intelligent Controller"; + break; + + case 0xF: + return "Satellite Communication Controller"; + break; + + case 0x10: + return "Encryption Controller"; + break; + + case 0x11: + return "Signal Processing Controller"; + break; + + case 0x12: + return "Processing Accelerator"; + break; + + case 0x13: + return "Non-Essential Instrumentation"; + break; + + default: + return "Unknown"; + break; + } + +} + +const char* getVendor( uint64_t VendorID){ + switch (VendorID) + { + case 0x8086: + return "Intel Corporation"; + break; + + default: + return "Vendor Unkown"; + break; + } +} + + + +uint32_t ConfigReadWord ( PCIBusAddress& PCIDeviceAddress , uint8_t offset){ + outl(CONFIG_ADDRESS , PCIDeviceAddress.getAddress() | offset ); + return inl(CONFIG_DATA); +} uint32_t ConfigReadWord (uint8_t bus, uint8_t device, uint8_t func, uint8_t offset){ uint32_t address; @@ -16,9 +124,6 @@ uint32_t ConfigReadWord (uint8_t bus, uint8_t device, uint8_t func, uint8_t offs ((uint32_t)device << PCI_DEVICE_ADDR_SHIFT) | ((uint32_t)func << PCI_FUNCTION_ADDR_SHIFT) | offset ); - // printf("PCI address read 0x%x", address); - - outl(CONFIG_ADDRESS, address); @@ -26,3 +131,67 @@ uint32_t ConfigReadWord (uint8_t bus, uint8_t device, uint8_t func, uint8_t offs return inl(CONFIG_DATA); } + + +uint8_t GetHeaderType( PCIBusAddress& PCIDeviceAddress ){ + uint32_t header_information = ConfigReadWord(PCIDeviceAddress , 0xC); + return (uint8_t) ( + (header_information >> 16) //Get higher half + & 0x00FF ); // Select the last two bytes +} + +uint16_t GetClassCodes( PCIBusAddress& PCIDeviceAddress ){ + uint32_t classcodes = ConfigReadWord(PCIDeviceAddress, 0x8); + return (uint16_t)((uint32_t)classcodes >> 16); + +} + +void PCI_Enumerate(){ + int devicesFound = 0; + // loop through all possible busses, devices and their functions; + for( int bus = 0 ; bus < 256 ; bus++) + { + + for(int device = 0; device < 32 ; device ++) + { + + + int function = 0; + + //uint64_t DeviceIdentify = ConfigReadWord(bus, device, function,0x0); + uint32_t VendorID = GetDevice(bus, device, function) & 0xFFFF; + uint32_t DeviceID = GetDevice(bus, device, function) >> 16; + + + + if( DeviceID != 0xFFFF){ + printf("Device found!\n"); + printf("Bus: %d, Device: %d, function: %d \n", bus, device, function); + printf("DeviceID: 0x%x, VendorID: %s\n", DeviceID, getVendor(VendorID) ); + + // iterate over the functions if it is a multi function device! + if( false ){ + for ( function ++ ; function < 8; function++) + { + + } + } + + PCIBusAddress busAddress = + PCIBusAddress{bus, device, function }; + + uint8_t header_type = GetHeaderType(busAddress); + printf( "Header type: 0x%x\n", header_type); + + uint16_t deviceClasses = GetClassCodes(busAddress); + printf(" class: %s, subClass: %d\n\n", + (deviceClasses >>8) > 0x13 ? "Unknown": GetClassCodeName((deviceClasses >>8)), deviceClasses & 0xFF); + + devicesFound++; + } + } + + } + + printf("Found %d PCI devices!\n", devicesFound); +} diff --git a/src/kernel/pci.h b/src/kernel/pci.h index 7f5ed47..137f950 100644 --- a/src/kernel/pci.h +++ b/src/kernel/pci.h @@ -1,17 +1,35 @@ #pragma once #include #include "io.h" +#include "tty/kterm.h" +#include "pci/pciDevice.h" + // Configuration Space Access Mechanism #1 #define CONFIG_ADDRESS 0xCF8 // Configuration adress that is to be accessed #define CONFIG_DATA 0xCFC // Will do the actual configuration operation +extern const char* ClassCodeTable [0x13]; + + + +// Note: this could be used to make the api for receiving PCI class codes a bit +// nicer. +struct ClassCodes { + uint8_t ClassCode; + uint8_t DeviceClass; +}__attribute__((packed)); + uint32_t ConfigReadWord (uint8_t bus, uint8_t device, uint8_t func, uint8_t offset); +uint32_t ConfigReadWord ( PCIBusAddress& PCIDeviceAddress , uint8_t offset); + inline uint64_t GetDevice (int bus, int device, int function ){ + return ConfigReadWord(bus, device, function,0x0); + } -inline uint16_t getVendorID(uint8_t bus, uint8_t device, uint8_t function ){ - return ConfigReadWord ( bus , device, function, 0); -} +uint8_t GetHeaderType( PCIBusAddress& PCIDeviceAddress ); -inline uint16_t getDeviceID(uint8_t bus, uint8_t device, uint8_t function ){ - return ConfigReadWord(bus, device, function , 16); -} +uint16_t GetClassCodes( PCIBusAddress& PICDeviceAddress ); +const char* getVendor( uint64_t VendorID); +const char* GetClassCodeName (uint64_t ClassCode ); + +void PCI_Enumerate(); \ No newline at end of file diff --git a/src/kernel/pci/pciDevice.cpp b/src/kernel/pci/pciDevice.cpp new file mode 100644 index 0000000..e4507fb --- /dev/null +++ b/src/kernel/pci/pciDevice.cpp @@ -0,0 +1,7 @@ + #include "pciDevice.h" + +// NOTE: we would really like to return a pointer +// to the newly created PCIBusAddress struct; + PCIBusAddress const PCIDevice::PCIAddress(){ + return PCIBusAddress{bus ,device, function}; + } \ No newline at end of file diff --git a/src/kernel/pci/pciDevice.h b/src/kernel/pci/pciDevice.h new file mode 100644 index 0000000..adc52f0 --- /dev/null +++ b/src/kernel/pci/pciDevice.h @@ -0,0 +1,36 @@ +#pragma once +#include + +/* +* PCI devices API +*/ +struct PCIBusAddress{ + + int bus ; + int device ; + int function[8]; + + + uint32_t getAddress( int deviceFunction = 0 ){ + return ((uint32_t) 1 << 31) | + ((uint32_t) bus << 16) | + ((uint32_t) device << 11)| + ((uint32_t) function[deviceFunction] << 8) | + 0x0000; + + }; +}; + +class PCIDevice { + public : + PCIDevice (PCIBusAddress* , int ); + ~PCIDevice(); + PCIBusAddress const PCIAddress(); + + private: + int bus; + int device; + int function; + int headerType; + +};