Move drivers to kernel

This commit is contained in:
Alex 2023-05-19 07:27:42 +03:00
parent e2063130ea
commit 80980ecfaf
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
71 changed files with 9794 additions and 8394 deletions

View File

@ -20,321 +20,317 @@
#include <memory.hpp>
#include <ints.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../Drivers/drv.hpp"
#include "../../kernel.h"
#include "../../DAPI.hpp"
#include "../../Fex.hpp"
#include "api.hpp"
NewLock(DriverInitLock);
NewLock(DriverInterruptLock);
namespace Driver
{
void Driver::Panic()
{
#ifdef DEBUG
size_t DriversNum = Drivers.size();
debug("%ld drivers loaded, [DUIDs: %ld]", DriversNum, DriverUIDs);
debug("driver size %ld", DriversNum);
#endif
void Driver::Panic()
{
debug("%ld drivers loaded, [DriverUIDs: %ld]", Drivers.size(), DriverUIDs - 1);
foreach (auto drv in Drivers)
{
KernelCallback callback{};
callback.Reason = StopReason;
DriverManager->IOCB(drv.DriverUID, &callback);
foreach (auto Drv in Drivers)
{
KernelCallback callback{};
callback.Reason = StopReason;
DriverManager->IOCB(Drv.DriverUID, &callback);
for (size_t j = 0; j < sizeof(drv.InterruptHook) / sizeof(drv.InterruptHook[0]); j++)
{
if (!drv.InterruptHook[j])
continue;
drv.InterruptHook[j]->Disable();
debug("Interrupt hook %#lx disabled", drv.InterruptHook[j]);
}
}
}
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
{
if (!Drv.InterruptHook[j])
continue;
void Driver::UnloadAllDrivers()
{
#ifdef DEBUG
size_t DriversNum = Drivers.size();
debug("%ld drivers loaded, [DUIDs: %ld]", DriversNum, DriverUIDs);
debug("driver size %ld", DriversNum);
#endif
Drv.InterruptHook[j]->Disable();
debug("Interrupt hook %#lx disabled", Drv.InterruptHook[j]);
}
}
}
foreach (auto drv in Drivers)
{
KernelCallback callback{};
callback.Reason = StopReason;
debug("Stopping & unloading driver %ld [%#lx]", drv.DriverUID, drv.Address);
DriverManager->IOCB(drv.DriverUID, &callback);
void Driver::UnloadAllDrivers()
{
debug("%ld drivers loaded, [DriverUIDs: %ld]", Drivers.size(), DriverUIDs - 1);
for (size_t j = 0; j < sizeof(drv.InterruptHook) / sizeof(drv.InterruptHook[0]); j++)
{
if (!drv.InterruptHook[j])
continue;
debug("Interrupt hook %#lx", drv.InterruptHook[j]);
delete drv.InterruptHook[j], drv.InterruptHook[j] = nullptr;
}
if (drv.MemTrk)
delete drv.MemTrk, drv.MemTrk = nullptr;
}
Drivers.clear();
}
foreach (auto Drv in Drivers)
{
KernelCallback callback{};
callback.Reason = StopReason;
debug("Stopping & unloading driver %ld [%#lx]", Drv.DriverUID, Drv.Address);
DriverManager->IOCB(Drv.DriverUID, &callback);
bool Driver::UnloadDriver(unsigned long DUID)
{
debug("Searching for driver %ld", DUID);
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
{
if (!Drv.InterruptHook[j])
continue;
foreach (auto drv in Drivers)
{
if (drv.DriverUID == DUID)
{
KernelCallback callback{};
callback.Reason = StopReason;
debug("Stopping and unloading driver %ld [%#lx]", drv.DriverUID, drv.Address);
this->IOCB(drv.DriverUID, &callback);
debug("Interrupt hook %#lx", Drv.InterruptHook[j]);
delete Drv.InterruptHook[j], Drv.InterruptHook[j] = nullptr;
}
for (size_t j = 0; j < sizeof(drv.InterruptHook) / sizeof(drv.InterruptHook[0]); j++)
{
if (!drv.InterruptHook[j])
continue;
debug("Interrupt hook %#lx", drv.InterruptHook[j]);
delete drv.InterruptHook[j], drv.InterruptHook[j] = nullptr;
}
delete drv.MemTrk, drv.MemTrk = nullptr;
Drivers.remove(drv);
return true;
}
}
return false;
}
if (Drv.MemTrk)
delete Drv.MemTrk, Drv.MemTrk = nullptr;
}
Drivers.clear();
}
int Driver::IOCB(unsigned long DUID, void *KCB)
{
foreach (auto Drv in Drivers)
{
if (Drv.DriverUID == DUID)
{
FexExtended *DrvExtHdr = (FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS);
int ret = ((int (*)(void *))((uintptr_t)DrvExtHdr->Driver.Callback + (uintptr_t)Drv.Address))(KCB);
__sync;
return ret;
}
}
return -1;
}
bool Driver::UnloadDriver(unsigned long DUID)
{
debug("Searching for driver %ld", DUID);
DriverCode Driver::CallDriverEntryPoint(void *fex, void *KAPIAddress)
{
memcpy(KAPIAddress, &KernelAPITemplate, sizeof(KernelAPI));
foreach (auto Drv in Drivers)
{
if (Drv.DriverUID != DUID)
continue;
((KernelAPI *)KAPIAddress)->Info.Offset = (unsigned long)fex;
((KernelAPI *)KAPIAddress)->Info.DriverUID = DriverUIDs++;
((KernelAPI *)KAPIAddress)->Info.KernelDebug = DebuggerIsAttached;
KernelCallback callback{};
callback.Reason = StopReason;
debug("Stopping & unloading driver %ld [%#lx]", Drv.DriverUID, Drv.Address);
this->IOCB(Drv.DriverUID, &callback);
#ifdef DEBUG
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("DRIVER: %s HAS DRIVER ID %ld", fexExtended->Driver.Name, ((KernelAPI *)KAPIAddress)->Info.DriverUID);
#endif
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
{
if (!Drv.InterruptHook[j])
continue;
debug("Calling driver entry point ( %#lx %ld )", (unsigned long)fex, ((KernelAPI *)KAPIAddress)->Info.DriverUID);
int ret = ((int (*)(KernelAPI *))((uintptr_t)((Fex *)fex)->EntryPoint + (uintptr_t)fex))(((KernelAPI *)KAPIAddress));
debug("Interrupt hook %#lx", Drv.InterruptHook[j]);
delete Drv.InterruptHook[j], Drv.InterruptHook[j] = nullptr;
}
if (DriverReturnCode::OK != ret)
return DriverCode::DRIVER_RETURNED_ERROR;
return DriverCode::OK;
}
if (Drv.MemTrk)
delete Drv.MemTrk, Drv.MemTrk = nullptr;
DriverCode Driver::LoadDriver(uintptr_t DriverAddress, uintptr_t Size)
{
Fex *DrvHdr = (Fex *)DriverAddress;
if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0')
{
if (Size > 0x1000)
{
Fex *ElfDrvHdr = (Fex *)(DriverAddress + 0x1000);
if (ElfDrvHdr->Magic[0] != 'F' || ElfDrvHdr->Magic[1] != 'E' || ElfDrvHdr->Magic[2] != 'X' || ElfDrvHdr->Magic[3] != '\0')
return DriverCode::INVALID_FEX_HEADER;
else
{
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", ElfDrvHdr->Magic, ElfDrvHdr->Type, ElfDrvHdr->OS, ElfDrvHdr->EntryPoint);
Drivers.remove(Drv);
return true;
}
return false;
}
if (ElfDrvHdr->Type == FexFormatType::FexFormatType_Driver)
{
FexExtended *ElfDrvExtHdr = (FexExtended *)((uintptr_t)ElfDrvHdr + EXTENDED_SECTION_ADDRESS);
debug("Name: \"%s\"; Type: %d; Callback: %#lx", ElfDrvExtHdr->Driver.Name, ElfDrvExtHdr->Driver.Type, ElfDrvExtHdr->Driver.Callback);
int Driver::IOCB(unsigned long DUID, void *KCB)
{
foreach (auto Drv in Drivers)
{
if (Drv.DriverUID != DUID)
continue;
if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
return this->DriverLoadBindPCI(ElfDrvExtHdr, DriverAddress, Size, true);
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
return this->DriverLoadBindInterrupt(ElfDrvExtHdr, DriverAddress, Size, true);
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
return this->DriverLoadBindProcess(ElfDrvExtHdr, DriverAddress, Size, true);
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
return this->DriverLoadBindInput(ElfDrvExtHdr, DriverAddress, Size, true);
else
error("Unknown driver bind type: %d", ElfDrvExtHdr->Driver.Bind.Type);
}
else
return DriverCode::NOT_DRIVER;
}
}
else
return DriverCode::INVALID_FEX_HEADER;
}
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", DrvHdr->Magic, DrvHdr->Type, DrvHdr->OS, DrvHdr->EntryPoint);
FexExtended *fexE = (FexExtended *)Drv.ExtendedHeaderAddress;
return ((int (*)(void *))((uintptr_t)fexE->Driver.Callback + (uintptr_t)Drv.Address))(KCB);
}
return -1;
}
if (DrvHdr->Type == FexFormatType::FexFormatType_Driver)
{
FexExtended *DrvExtHdr = (FexExtended *)((uintptr_t)DrvHdr + EXTENDED_SECTION_ADDRESS);
debug("Name: \"%s\"; Type: %d; Callback: %#lx", DrvExtHdr->Driver.Name, DrvExtHdr->Driver.Type, DrvExtHdr->Driver.Callback);
DriverCode Driver::CallDriverEntryPoint(void *fex, bool BuiltIn)
{
DriverCode ret{};
KernelAPI DriverKAPI = KernelAPITemplate;
if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
return this->DriverLoadBindPCI(DrvExtHdr, DriverAddress, Size);
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
return this->DriverLoadBindInterrupt(DrvExtHdr, DriverAddress, Size);
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
return this->DriverLoadBindProcess(DrvExtHdr, DriverAddress, Size);
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
return this->DriverLoadBindInput(DrvExtHdr, DriverAddress, Size);
else
error("Unknown driver bind type: %d", DrvExtHdr->Driver.Bind.Type);
}
else
return DriverCode::NOT_DRIVER;
return DriverCode::ERROR;
}
DriverKAPI.Info.DriverUID = DriverUIDs++;
DriverKAPI.Info.KernelDebug = DebuggerIsAttached;
Driver::Driver()
{
SmartCriticalSection(DriverInitLock);
debug("Calling driver entry point ( %#lx %ld )", (unsigned long)fex, DriverKAPI.Info.DriverUID);
std::string DriverConfigFile = Config.DriverDirectory;
DriverConfigFile << "/config.ini";
fixme("Loading driver config file: %s", DriverConfigFile.c_str());
if (!BuiltIn)
{
DriverKAPI.Info.Offset = (unsigned long)fex;
VirtualFileSystem::File DriverDirectory = vfs->Open(Config.DriverDirectory);
if (DriverDirectory.IsOK())
{
foreach (auto driver in DriverDirectory.node->Children)
if (driver->Flags == VirtualFileSystem::NodeFlags::FILE)
if (cwk_path_has_extension(driver->Name))
{
const char *extension;
size_t extension_length;
cwk_path_get_extension(driver->Name, &extension, &extension_length);
debug("Driver: %s; Extension: %s", driver->Name, extension);
if (strcmp(extension, ".fex") == 0 || strcmp(extension, ".elf") == 0)
{
uintptr_t ret = this->LoadDriver(driver->Address, driver->Length);
char RetString[128];
if (ret == DriverCode::OK)
strncpy(RetString, "\e058C19OK", 10);
else if (ret == DriverCode::NOT_AVAILABLE)
strncpy(RetString, "\eFF7900NOT AVAILABLE", 21);
else
sprintf(RetString, "\eE85230FAILED (%#lx)", ret);
KPrint("%s %s", driver->Name, RetString);
}
}
}
else
KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory.Status);
vfs->Close(DriverDirectory);
}
debug("DRIVER: %s HAS DRIVER ID %ld",
((FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS))->Driver.Name,
DriverKAPI.Info.DriverUID);
ret = ((DriverCode(*)(KernelAPI *))((uintptr_t)((Fex *)fex)->EntryPoint + (uintptr_t)fex))(((KernelAPI *)&DriverKAPI));
}
else
{
debug("DRIVER: BUILTIN HAS DRIVER ID %ld", DriverKAPI.Info.DriverUID);
ret = ((DriverCode(*)(KernelAPI *))((uintptr_t)fex))(((KernelAPI *)&DriverKAPI));
}
Driver::~Driver()
{
debug("Destructor called");
this->UnloadAllDrivers();
}
if (DriverCode::OK != ret)
{
DriverUIDs--;
return ret;
}
return DriverCode::OK;
}
DriverCode Driver::LoadDriver(uintptr_t DriverAddress, uintptr_t Size)
{
Fex *DrvHdr = (Fex *)DriverAddress;
if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0')
return DriverCode::INVALID_FEX_HEADER;
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", DrvHdr->Magic, DrvHdr->Type, DrvHdr->OS, DrvHdr->EntryPoint);
if (DrvHdr->Type != FexFormatType::FexFormatType_Driver)
return DriverCode::NOT_DRIVER;
FexExtended *fexE = (FexExtended *)((uintptr_t)DrvHdr + EXTENDED_SECTION_ADDRESS);
debug("Name: \"%s\"; Type: %d; Callback: %#lx", fexE->Driver.Name, fexE->Driver.Type, fexE->Driver.Callback);
switch (fexE->Driver.Bind.Type)
{
case DriverBindType::BIND_PCI:
return this->DriverLoadBindPCI(DriverAddress, Size);
case DriverBindType::BIND_INTERRUPT:
return this->DriverLoadBindInterrupt(DriverAddress, Size);
case DriverBindType::BIND_PROCESS:
return this->DriverLoadBindProcess(DriverAddress, Size);
case DriverBindType::BIND_INPUT:
return this->DriverLoadBindInput(DriverAddress, Size);
default:
{
error("Unknown driver bind type: %d", fexE->Driver.Bind.Type);
return DriverCode::UNKNOWN_DRIVER_BIND_TYPE;
}
}
}
void Driver::LoadDrivers()
{
SmartCriticalSection(DriverInitLock);
std::string DriverConfigFile = Config.DriverDirectory;
DriverConfigFile << "/config.ini";
fixme("Loading driver config file: %s", DriverConfigFile.c_str());
VirtualFileSystem::File DriverDirectory = vfs->Open(Config.DriverDirectory);
if (!DriverDirectory.IsOK())
{
KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory.Status);
vfs->Close(DriverDirectory);
}
debug("Loading built-in drivers");
StartAHCI();
StartVMwareMouse();
StartPS2Mouse();
StartATA();
StartAC97();
StartRTL8139();
StartPCNET();
StartGigabit();
debug("Loading drivers from %s", Config.DriverDirectory);
foreach (auto DrvFile in DriverDirectory.node->Children)
{
if (DrvFile->Flags != VirtualFileSystem::NodeFlags::FILE)
continue;
if (cwk_path_has_extension(DrvFile->Name))
{
const char *extension;
size_t extension_length;
cwk_path_get_extension(DrvFile->Name, &extension, &extension_length);
debug("File: %s; Extension: %s", DrvFile->Name, extension);
if (strcmp(extension, ".fex") == 0)
{
uintptr_t ret = this->LoadDriver(DrvFile->Address, DrvFile->Length);
std::string RetString;
if (ret == DriverCode::OK)
RetString << "\e058C19OK";
else if (ret == DriverCode::NOT_AVAILABLE)
RetString << "\eFF7900NOT AVAILABLE";
else
RetString << "\eE85230FAILED";
KPrint("%s %s %#lx", DrvFile->Name, RetString.c_str(), ret);
}
}
}
vfs->Close(DriverDirectory);
}
Driver::Driver() {}
Driver::~Driver()
{
debug("Destructor called");
this->UnloadAllDrivers();
}
#if defined(a64)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
#elif defined(a32)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
#elif defined(aa64)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
#endif
{
SmartLock(DriverInterruptLock); /* Lock in case of multiple interrupts firing at the same time */
if (!this->Enabled)
{
debug("Interrupt hook is not enabled");
return;
}
{
SmartLock(DriverInterruptLock); /* Lock in case of multiple interrupts firing at the same time */
if (!this->Enabled)
{
debug("Interrupt hook is not enabled");
return;
}
if (!Handle.InterruptCallback)
{
if (!Handle.InterruptCallback)
{
#if defined(a86)
uint64_t IntNum = Frame->InterruptNumber - 32;
uint64_t IntNum = Frame->InterruptNumber - 32;
#elif defined(aa64)
uint64_t IntNum = Frame->InterruptNumber;
uint64_t IntNum = Frame->InterruptNumber;
#endif
warn("Interrupt callback for %ld is not set for driver %ld!", IntNum, Handle.DriverUID);
return;
}
CPURegisters regs;
warn("Interrupt callback for %ld is not set for driver %ld!", IntNum, Handle.DriverUID);
return;
}
CPURegisters regs;
#if defined(a64)
regs.r15 = Frame->r15;
regs.r14 = Frame->r14;
regs.r13 = Frame->r13;
regs.r12 = Frame->r12;
regs.r11 = Frame->r11;
regs.r10 = Frame->r10;
regs.r9 = Frame->r9;
regs.r8 = Frame->r8;
regs.r15 = Frame->r15;
regs.r14 = Frame->r14;
regs.r13 = Frame->r13;
regs.r12 = Frame->r12;
regs.r11 = Frame->r11;
regs.r10 = Frame->r10;
regs.r9 = Frame->r9;
regs.r8 = Frame->r8;
regs.rbp = Frame->rbp;
regs.rdi = Frame->rdi;
regs.rsi = Frame->rsi;
regs.rdx = Frame->rdx;
regs.rcx = Frame->rcx;
regs.rbx = Frame->rbx;
regs.rax = Frame->rax;
regs.rbp = Frame->rbp;
regs.rdi = Frame->rdi;
regs.rsi = Frame->rsi;
regs.rdx = Frame->rdx;
regs.rcx = Frame->rcx;
regs.rbx = Frame->rbx;
regs.rax = Frame->rax;
regs.InterruptNumber = Frame->InterruptNumber;
regs.ErrorCode = Frame->ErrorCode;
regs.rip = Frame->rip;
regs.cs = Frame->cs;
regs.rflags = Frame->rflags.raw;
regs.rsp = Frame->rsp;
regs.ss = Frame->ss;
regs.InterruptNumber = Frame->InterruptNumber;
regs.ErrorCode = Frame->ErrorCode;
regs.rip = Frame->rip;
regs.cs = Frame->cs;
regs.rflags = Frame->rflags.raw;
regs.rsp = Frame->rsp;
regs.ss = Frame->ss;
#elif defined(a32)
regs.ebp = Frame->ebp;
regs.edi = Frame->edi;
regs.esi = Frame->esi;
regs.edx = Frame->edx;
regs.ecx = Frame->ecx;
regs.ebx = Frame->ebx;
regs.eax = Frame->eax;
regs.ebp = Frame->ebp;
regs.edi = Frame->edi;
regs.esi = Frame->esi;
regs.edx = Frame->edx;
regs.ecx = Frame->ecx;
regs.ebx = Frame->ebx;
regs.eax = Frame->eax;
regs.InterruptNumber = Frame->InterruptNumber;
regs.ErrorCode = Frame->ErrorCode;
regs.eip = Frame->eip;
regs.cs = Frame->cs;
regs.eflags = Frame->eflags.raw;
regs.esp = Frame->esp;
regs.ss = Frame->ss;
regs.InterruptNumber = Frame->InterruptNumber;
regs.ErrorCode = Frame->ErrorCode;
regs.eip = Frame->eip;
regs.cs = Frame->cs;
regs.eflags = Frame->eflags.raw;
regs.esp = Frame->esp;
regs.ss = Frame->ss;
#elif defined(aa64)
#endif
((int (*)(void *))(Handle.InterruptCallback))(&regs);
UNUSED(Frame);
}
((int (*)(void *))(Handle.InterruptCallback))(&regs);
UNUSED(Frame);
}
DriverInterruptHook::DriverInterruptHook(int Interrupt, DriverFile Handle) : Interrupts::Handler(Interrupt)
{
this->Handle = Handle;
DriverInterruptHook::DriverInterruptHook(int Interrupt, DriverFile Handle) : Interrupts::Handler(Interrupt)
{
this->Handle = Handle;
#if defined(a86)
trace("Interrupt %d hooked to driver %ld", Interrupt, Handle.DriverUID);
trace("Interrupt %d hooked to driver %ld", Interrupt, Handle.DriverUID);
#elif defined(aa64)
trace("Interrupt %d hooked to driver %ld", Interrupt, Handle.DriverUID);
trace("Interrupt %d hooked to driver %ld", Interrupt, Handle.DriverUID);
#endif
}
}
}

View File

@ -39,165 +39,165 @@ void DriverDebugPrint(char *String, unsigned long DriverUID) { trace("[%ld] %s",
void DriverDisplayPrint(char *String)
{
SmartLock(DriverDisplayPrintLock);
for (unsigned long i = 0; i < strlen(String); i++)
Display->Print(String[i], 0, true);
SmartLock(DriverDisplayPrintLock);
for (unsigned long i = 0; i < strlen(String); i++)
Display->Print(String[i], 0, true);
}
void *RequestPage(unsigned long Size)
{
void *ret = KernelAllocator.RequestPages(Size + 1);
drvdbg("Allocated %ld pages (%#lx-%#lx)", Size, (unsigned long)ret, (unsigned long)ret + FROM_PAGES(Size));
return ret;
void *ret = KernelAllocator.RequestPages(Size + 1);
drvdbg("Allocated %ld pages (%#lx-%#lx)", Size, (unsigned long)ret, (unsigned long)ret + FROM_PAGES(Size));
return ret;
}
void FreePage(void *Page, unsigned long Size)
{
drvdbg("Freeing %ld pages (%#lx-%#lx)", Size, (unsigned long)Page, (unsigned long)Page + FROM_PAGES(Size));
KernelAllocator.FreePages(Page, Size + 1);
drvdbg("Freeing %ld pages (%#lx-%#lx)", Size, (unsigned long)Page, (unsigned long)Page + FROM_PAGES(Size));
KernelAllocator.FreePages(Page, Size + 1);
}
void MapMemory(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags)
{
SmartLock(DriverDisplayPrintLock);
drvdbg("Mapping %#lx to %#lx with flags %#lx...", (unsigned long)VirtualAddress, (unsigned long)PhysicalAddress, Flags);
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
SmartLock(DriverDisplayPrintLock);
drvdbg("Mapping %#lx to %#lx with flags %#lx...", (unsigned long)VirtualAddress, (unsigned long)PhysicalAddress, Flags);
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
}
void UnmapMemory(void *VirtualAddress)
{
SmartLock(DriverDisplayPrintLock);
drvdbg("Unmapping %#lx...", (unsigned long)VirtualAddress);
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
SmartLock(DriverDisplayPrintLock);
drvdbg("Unmapping %#lx...", (unsigned long)VirtualAddress);
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
}
void *Drivermemcpy(void *Destination, void *Source, unsigned long Size)
{
SmartLock(DriverDisplayPrintLock);
drvdbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size,
(unsigned long)Source, (unsigned long)Source + Size,
(unsigned long)Destination, (unsigned long)Destination + Size);
return memcpy(Destination, Source, Size);
SmartLock(DriverDisplayPrintLock);
drvdbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size,
(unsigned long)Source, (unsigned long)Source + Size,
(unsigned long)Destination, (unsigned long)Destination + Size);
return memcpy(Destination, Source, Size);
}
void *Drivermemset(void *Destination, int Value, unsigned long Size)
{
SmartLock(DriverDisplayPrintLock);
drvdbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value,
(unsigned long)Destination, (unsigned long)Destination + Size,
Size);
return memset(Destination, Value, Size);
SmartLock(DriverDisplayPrintLock);
drvdbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value,
(unsigned long)Destination, (unsigned long)Destination + Size,
Size);
return memset(Destination, Value, Size);
}
void DriverNetSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
{
// This is useless I guess...
if (NIManager)
NIManager->DrvSend(DriverID, Data, Size);
// This is useless I guess...
if (NIManager)
NIManager->DrvSend(DriverID, Data, Size);
}
void DriverNetReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
{
if (NIManager)
NIManager->DrvReceive(DriverID, Data, Size);
if (NIManager)
NIManager->DrvReceive(DriverID, Data, Size);
}
void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
{
DumpData("DriverDiskRead", Data, SectorCount * 512);
UNUSED(DriverID);
UNUSED(Sector);
UNUSED(Port);
DumpData("DriverDiskRead", Data, SectorCount * 512);
UNUSED(DriverID);
UNUSED(Sector);
UNUSED(Port);
}
void DriverAHCIDiskWrite(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
{
DumpData("DriverDiskWrite", Data, SectorCount * 512);
UNUSED(DriverID);
UNUSED(Sector);
UNUSED(Port);
DumpData("DriverDiskWrite", Data, SectorCount * 512);
UNUSED(DriverID);
UNUSED(Sector);
UNUSED(Port);
}
char *DriverPCIGetDeviceName(unsigned int VendorID, unsigned int DeviceID)
{
UNUSED(VendorID);
UNUSED(DeviceID);
return (char *)"Unknown";
UNUSED(VendorID);
UNUSED(DeviceID);
return (char *)"Unknown";
}
unsigned int DriverGetWidth()
{
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
return Display->GetBuffer(0)->Width;
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
return Display->GetBuffer(0)->Width;
}
unsigned int DriverGetHeight()
{
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
return Display->GetBuffer(0)->Height;
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
return Display->GetBuffer(0)->Height;
}
void DriverSleep(unsigned long Milliseconds)
{
SmartLock(DriverDisplayPrintLock);
drvdbg("Sleeping for %ld milliseconds...", Milliseconds);
if (TaskManager)
TaskManager->Sleep(Milliseconds);
else
TimeManager->Sleep(Milliseconds, Time::Units::Milliseconds);
SmartLock(DriverDisplayPrintLock);
drvdbg("Sleeping for %ld milliseconds...", Milliseconds);
if (TaskManager)
TaskManager->Sleep(Milliseconds);
else
TimeManager->Sleep(Milliseconds, Time::Units::Milliseconds);
}
int Driversprintf(char *Buffer, const char *Format, ...)
{
va_list args;
va_start(args, Format);
int ret = vsprintf(Buffer, Format, args);
va_end(args);
return ret;
va_list args;
va_start(args, Format);
int ret = vsprintf(Buffer, Format, args);
va_end(args);
return ret;
}
KernelAPI KernelAPITemplate = {
.Version = {
.Major = 0,
.Minor = 0,
.Patch = 1},
.Info = {
.Offset = 0,
.DriverUID = 0,
.KernelDebug = false,
},
.Memory = {
.PageSize = PAGE_SIZE,
.RequestPage = RequestPage,
.FreePage = FreePage,
.Map = MapMemory,
.Unmap = UnmapMemory,
},
.PCI = {
.GetDeviceName = DriverPCIGetDeviceName,
},
.Util = {
.DebugPrint = DriverDebugPrint,
.DisplayPrint = DriverDisplayPrint,
.memcpy = Drivermemcpy,
.memset = Drivermemset,
.Sleep = DriverSleep,
.sprintf = Driversprintf,
},
.Command = {
.Network = {
.SendPacket = DriverNetSend,
.ReceivePacket = DriverNetReceive,
},
.Disk = {
.AHCI = {
.ReadSector = DriverAHCIDiskRead,
.WriteSector = DriverAHCIDiskWrite,
},
},
},
.Display = {
.GetWidth = DriverGetWidth,
.GetHeight = DriverGetHeight,
},
.Version = {
.Major = 0,
.Minor = 0,
.Patch = 1},
.Info = {
.Offset = 0,
.DriverUID = 0,
.KernelDebug = false,
},
.Memory = {
.PageSize = PAGE_SIZE,
.RequestPage = RequestPage,
.FreePage = FreePage,
.Map = MapMemory,
.Unmap = UnmapMemory,
},
.PCI = {
.GetDeviceName = DriverPCIGetDeviceName,
},
.Util = {
.DebugPrint = DriverDebugPrint,
.DisplayPrint = DriverDisplayPrint,
.memcpy = Drivermemcpy,
.memset = Drivermemset,
.Sleep = DriverSleep,
.sprintf = Driversprintf,
},
.Command = {
.Network = {
.SendPacket = DriverNetSend,
.ReceivePacket = DriverNetReceive,
},
.Disk = {
.AHCI = {
.ReadSector = DriverAHCIDiskRead,
.WriteSector = DriverAHCIDiskWrite,
},
},
},
.Display = {
.GetWidth = DriverGetWidth,
.GetHeight = DriverGetHeight,
},
};

View File

@ -31,43 +31,9 @@
namespace Driver
{
DriverCode Driver::DriverLoadBindInput(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
{
UNUSED(DrvExtHdr);
UNUSED(IsElf);
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
memcpy(fex, (void *)DriverAddress, Size);
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
#ifdef DEBUG
uint8_t *result = md5File((uint8_t *)fex, Size);
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
kfree(result);
#endif
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI) + 1));
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
{
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
switch (fexExtended->Driver.Type)
{
case FexDriverType::FexDriverType_Input:
return BindInputInput(mem, fex);
default:
{
warn("Unknown driver type: %d", fexExtended->Driver.Type);
delete mem, mem = nullptr;
return DriverCode::UNKNOWN_DRIVER_TYPE;
}
}
return DriverCode::OK;
}
DriverCode Driver::DriverLoadBindInput(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
{
stub;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -31,55 +31,88 @@
namespace Driver
{
DriverCode Driver::DriverLoadBindInterrupt(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
{
UNUSED(DrvExtHdr);
UNUSED(IsElf);
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
memcpy(fex, (void *)DriverAddress, Size);
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
#ifdef DEBUG
uint8_t *result = md5File((uint8_t *)fex, Size);
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
kfree(result);
#endif
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI) + 1));
DriverCode Driver::DriverLoadBindInterrupt(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
{
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
{
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress;
Fex *fex = nullptr;
if (!IsBuiltIn)
{
fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
memcpy(fex, (void *)DriverAddress, Size);
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
}
else
fex = (Fex *)bidi->EntryPoint;
DriverCode ret = CallDriverEntryPoint(fex, IsBuiltIn);
if (ret != DriverCode::OK)
{
delete mem;
return ret;
}
switch (fexExtended->Driver.Type)
{
case FexDriverType::FexDriverType_Generic:
return BindInterruptGeneric(mem, fex);
case FexDriverType::FexDriverType_Display:
return BindInterruptDisplay(mem, fex);
case FexDriverType::FexDriverType_Network:
return BindInterruptNetwork(mem, fex);
case FexDriverType::FexDriverType_Storage:
return BindInterruptStorage(mem, fex);
case FexDriverType::FexDriverType_FileSystem:
return BindInterruptFileSystem(mem, fex);
case FexDriverType::FexDriverType_Input:
return BindInterruptInput(mem, fex);
case FexDriverType::FexDriverType_Audio:
return BindInterruptAudio(mem, fex);
default:
{
warn("Unknown driver type: %d", fexExtended->Driver.Type);
delete mem, mem = nullptr;
return DriverCode::UNKNOWN_DRIVER_TYPE;
}
}
if (IsBuiltIn)
fex = 0x0; /* Addresses are absolute if built-in. */
return DriverCode::OK;
}
FexExtended *fexE = IsBuiltIn ? (FexExtended *)bidi->ExtendedHeader : (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("Starting driver %s", fexE->Driver.Name);
switch (fexE->Driver.Type)
{
case FexDriverType::FexDriverType_Generic:
case FexDriverType::FexDriverType_Display:
case FexDriverType::FexDriverType_Network:
case FexDriverType::FexDriverType_Storage:
case FexDriverType::FexDriverType_FileSystem:
case FexDriverType::FexDriverType_Input:
case FexDriverType::FexDriverType_Audio:
{
FexExtended *DriverExtendedHeader = (FexExtended *)mem->RequestPages(TO_PAGES(sizeof(FexExtended) + 1));
memcpy(DriverExtendedHeader, fexE, sizeof(FexExtended));
DriverFile DrvFile = {
.Enabled = true,
.BuiltIn = IsBuiltIn,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.ExtendedHeaderAddress = (void *)DriverExtendedHeader,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexE->Driver.InterruptCallback),
.MemTrk = mem,
};
if (fexE->Driver.InterruptCallback)
{
for (uint16_t i = 0; i < sizeof(fexE->Driver.Bind.Interrupt.Vector) / sizeof(fexE->Driver.Bind.Interrupt.Vector[0]); i++)
{
if (fexE->Driver.Bind.Interrupt.Vector[i] == 0)
break;
DrvFile.InterruptHook[i] = new DriverInterruptHook(fexE->Driver.Bind.Interrupt.Vector[i], DrvFile);
}
}
KernelCallback KCallback{};
KCallback.RawPtr = nullptr;
KCallback.Reason = CallbackReason::ConfigurationReason;
DriverCode CallbackRet = ((DriverCode(*)(KernelCallback *))((uintptr_t)fexE->Driver.Callback + (uintptr_t)fex))(&KCallback);
if (CallbackRet != DriverCode::OK)
{
error("Driver %s returned error %d", fexE->Driver.Name, CallbackRet);
delete mem;
return CallbackRet;
}
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
default:
{
warn("Unknown driver type: %d", fexE->Driver.Type);
delete mem;
return DriverCode::UNKNOWN_DRIVER_TYPE;
}
}
}
}

View File

@ -31,171 +31,114 @@
namespace Driver
{
void Driver::MapPCIAddresses(PCI::PCIDeviceHeader *PCIDevice)
{
debug("Header Type: %d", PCIDevice->HeaderType);
switch (PCIDevice->HeaderType)
{
case 0: // PCI Header 0
{
uint32_t BAR[6] = {0};
size_t BARsSize[6] = {0};
DriverCode Driver::DriverLoadBindPCI(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
{
FexExtended *DrvExtHdr = (FexExtended *)(DriverAddress + EXTENDED_SECTION_ADDRESS);
if (IsBuiltIn)
DrvExtHdr = (FexExtended *)(((BuiltInDriverInfo *)DriverAddress)->ExtendedHeader);
BAR[0] = ((PCI::PCIHeader0 *)PCIDevice)->BAR0;
BAR[1] = ((PCI::PCIHeader0 *)PCIDevice)->BAR1;
BAR[2] = ((PCI::PCIHeader0 *)PCIDevice)->BAR2;
BAR[3] = ((PCI::PCIHeader0 *)PCIDevice)->BAR3;
BAR[4] = ((PCI::PCIHeader0 *)PCIDevice)->BAR4;
BAR[5] = ((PCI::PCIHeader0 *)PCIDevice)->BAR5;
uint16_t SizeOfVendorID = sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) /
sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID[0]);
uint16_t SizeOfDeviceID = sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID) /
sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID[0]);
#ifdef DEBUG
uintptr_t BAR_Type = BAR[0] & 1;
uintptr_t BAR_IOBase = BAR[1] & (~3);
uintptr_t BAR_MemoryBase = BAR[0] & (~15);
for (uint16_t vID = 0; vID < SizeOfVendorID; vID++)
{
for (uint16_t dID = 0; dID < SizeOfDeviceID; dID++)
{
if (DrvExtHdr->Driver.Bind.PCI.VendorID[vID] == 0 ||
DrvExtHdr->Driver.Bind.PCI.DeviceID[dID] == 0)
continue;
debug("Type: %d; IOBase: %#lx; MemoryBase: %#lx", BAR_Type, BAR_IOBase, BAR_MemoryBase);
#endif
std::vector<PCI::PCIDeviceHeader *> devices =
PCIManager->FindPCIDevice(DrvExtHdr->Driver.Bind.PCI.VendorID[vID],
DrvExtHdr->Driver.Bind.PCI.DeviceID[dID]);
if (devices.size() == 0)
continue;
/* BARs Size */
for (short i = 0; i < 6; i++)
{
if (BAR[i] == 0)
continue;
foreach (auto PCIDevice in devices)
{
debug("[%ld] VendorID: %#x; DeviceID: %#x",
devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID);
if ((BAR[i] & 1) == 0) // Memory Base
{
((PCI::PCIHeader0 *)PCIDevice)->BAR0 = 0xFFFFFFFF;
size_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR0;
((PCI::PCIHeader0 *)PCIDevice)->BAR0 = BAR[i];
BARsSize[i] = size & (~15);
BARsSize[i] = ~BARsSize[i] + 1;
BARsSize[i] = BARsSize[i] & 0xFFFFFFFF;
debug("BAR%d %#lx size: %d", i, BAR[i], BARsSize[i]);
}
else if ((BAR[i] & 1) == 1) // I/O Base
{
((PCI::PCIHeader0 *)PCIDevice)->BAR1 = 0xFFFFFFFF;
size_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR1;
((PCI::PCIHeader0 *)PCIDevice)->BAR1 = BAR[i];
BARsSize[i] = size & (~3);
BARsSize[i] = ~BARsSize[i] + 1;
BARsSize[i] = BARsSize[i] & 0xFFFF;
debug("BAR%d %#lx size: %d", i, BAR[i], BARsSize[i]);
}
}
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
/* Mapping the BARs */
for (short i = 0; i < 6; i++)
{
if (BAR[i] == 0)
continue;
BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress;
Fex *fex = nullptr;
if (!IsBuiltIn)
{
fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
memcpy(fex, (void *)DriverAddress, Size);
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
}
else
fex = (Fex *)bidi->EntryPoint;
DriverCode ret = CallDriverEntryPoint(fex, IsBuiltIn);
if (ret != DriverCode::OK)
{
delete mem;
return ret;
}
if ((BAR[i] & 1) == 0) // Memory Base
{
uintptr_t BARBase = BAR[i] & (~15);
size_t BARSize = BARsSize[i];
if (IsBuiltIn)
fex = 0x0; /* Addresses are absolute if built-in. */
debug("Mapping BAR%d %#lx-%#lx", i, BARBase, BARBase + BARSize);
Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, Memory::PTFlag::RW | Memory::PTFlag::PWT);
}
else if ((BAR[i] & 1) == 1) // I/O Base
{
uintptr_t BARBase = BAR[i] & (~3);
size_t BARSize = BARsSize[i];
FexExtended *fexE = IsBuiltIn ? (FexExtended *)bidi->ExtendedHeader : (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("Starting driver %s", fexE->Driver.Name);
debug("Mapping BAR%d %#x-%#x", i, BARBase, BARBase + BARSize);
Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, Memory::PTFlag::RW | Memory::PTFlag::PWT);
}
}
break;
}
case 1: // PCI Header 1 (PCI-to-PCI Bridge)
{
fixme("PCI Header 1 (PCI-to-PCI Bridge) not implemented yet");
break;
}
case 2: // PCI Header 2 (PCI-to-CardBus Bridge)
{
fixme("PCI Header 2 (PCI-to-CardBus Bridge) not implemented yet");
break;
}
default:
{
error("Unknown header type %d", PCIDevice->HeaderType);
return;
}
}
}
PCIManager->MapPCIAddresses(PCIDevice);
DriverCode Driver::DriverLoadBindPCI(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
{
UNUSED(IsElf);
for (unsigned long Vidx = 0; Vidx < sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID) / sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[0]); Vidx++)
{
for (unsigned long Didx = 0; Didx < sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID) / sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[0]); Didx++)
{
if (Vidx >= sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID) && Didx >= sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID))
break;
switch (fexE->Driver.Type)
{
case FexDriverType::FexDriverType_Generic:
case FexDriverType::FexDriverType_Display:
case FexDriverType::FexDriverType_Network:
case FexDriverType::FexDriverType_Storage:
case FexDriverType::FexDriverType_FileSystem:
case FexDriverType::FexDriverType_Input:
case FexDriverType::FexDriverType_Audio:
{
FexExtended *DriverExtendedHeader = (FexExtended *)mem->RequestPages(TO_PAGES(sizeof(FexExtended) + 1));
memcpy(DriverExtendedHeader, fexE, sizeof(FexExtended));
if (((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[Vidx] == 0 || ((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[Didx] == 0)
continue;
DriverFile DrvFile = {
.Enabled = true,
.BuiltIn = IsBuiltIn,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.ExtendedHeaderAddress = (void *)DriverExtendedHeader,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexE->Driver.InterruptCallback),
.MemTrk = mem,
};
std::vector<PCI::PCIDeviceHeader *> devices = PCIManager->FindPCIDevice(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[Vidx], ((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[Didx]);
if (devices.size() == 0)
continue;
if (fexE->Driver.InterruptCallback)
DrvFile.InterruptHook[0] = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine), DrvFile);
foreach (auto PCIDevice in devices)
{
debug("[%ld] VendorID: %#x; DeviceID: %#x", devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID);
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
memcpy(fex, (void *)DriverAddress, Size);
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
#ifdef DEBUG
uint8_t *result = md5File((uint8_t *)fex, Size);
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
kfree(result);
#endif
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI) + 1));
KernelCallback KCallback{};
KCallback.RawPtr = PCIDevice;
KCallback.Reason = CallbackReason::ConfigurationReason;
DriverCode CallbackRet = ((DriverCode(*)(KernelCallback *))((uintptr_t)fexE->Driver.Callback + (uintptr_t)fex))(&KCallback);
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
{
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
debug("Starting driver %s", fexExtended->Driver.Name);
if (CallbackRet != DriverCode::OK)
{
error("Driver %s returned error %d", fexE->Driver.Name, CallbackRet);
delete mem;
return CallbackRet;
}
MapPCIAddresses(PCIDevice);
switch (fexExtended->Driver.Type)
{
case FexDriverType::FexDriverType_Generic:
return BindPCIGeneric(mem, fex, PCIDevice);
case FexDriverType::FexDriverType_Display:
return BindPCIDisplay(mem, fex, PCIDevice);
case FexDriverType::FexDriverType_Network:
return BindPCINetwork(mem, fex, PCIDevice);
case FexDriverType::FexDriverType_Storage:
return BindPCIStorage(mem, fex, PCIDevice);
case FexDriverType::FexDriverType_FileSystem:
return BindPCIFileSystem(mem, fex, PCIDevice);
case FexDriverType::FexDriverType_Input:
return BindPCIInput(mem, fex, PCIDevice);
case FexDriverType::FexDriverType_Audio:
return BindPCIAudio(mem, fex, PCIDevice);
default:
{
warn("Unknown driver type: %d", fexExtended->Driver.Type);
delete mem, mem = nullptr;
return DriverCode::UNKNOWN_DRIVER_TYPE;
}
}
}
}
}
return DriverCode::PCI_DEVICE_NOT_FOUND;
}
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
default:
{
warn("Unknown driver type: %d", fexE->Driver.Type);
delete mem;
return DriverCode::UNKNOWN_DRIVER_TYPE;
}
}
}
}
}
return DriverCode::PCI_DEVICE_NOT_FOUND;
}
}

View File

@ -31,12 +31,9 @@
namespace Driver
{
DriverCode Driver::DriverLoadBindProcess(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
{
fixme("Process driver: %s", ((FexExtended *)DrvExtHdr)->Driver.Name);
UNUSED(Size);
UNUSED(DriverAddress);
UNUSED(IsElf);
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::DriverLoadBindProcess(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
{
stub;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInputFileSystem(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInputGeneric(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,67 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInputInput(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
KernelCallback KCallback{};
fixme("Input driver: %s", fexExtended->Driver.Name);
KCallback.RawPtr = nullptr;
KCallback.Reason = CallbackReason::ConfigurationReason;
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
{
delete mem, mem = nullptr;
error("Driver %s is not implemented", fexExtended->Driver.Name);
return DriverCode::NOT_IMPLEMENTED;
}
else if (CallbackRet != DriverReturnCode::OK)
{
delete mem, mem = nullptr;
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
return DriverCode::DRIVER_RETURNED_ERROR;
}
fixme("Input driver: %s", fexExtended->Driver.Name);
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.MemTrk = mem,
};
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInputNetwork(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInputStorage(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,81 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInterruptAudio(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Audio driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,81 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInterruptDisplay(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Display driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,81 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInterruptFileSystem(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,88 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInterruptGeneric(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Generic driver: %s", fexExtended->Driver.Name);
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
.MemTrk = mem,
};
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

View File

@ -1,124 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInterruptInput(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("Searching for conflicting drivers...");
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if ((fe->Driver.TypeFlags & FexDriverInputTypes_Mouse &&
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Mouse) ||
(fe->Driver.TypeFlags & FexDriverInputTypes_Keyboard &&
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Keyboard))
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
DriversToRemove.push_back(Drv.DriverUID);
}
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if ((fe->Driver.TypeFlags & FexDriverInputTypes_Mouse &&
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Mouse) ||
(fe->Driver.TypeFlags & FexDriverInputTypes_Keyboard &&
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Keyboard))
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
}
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
.MemTrk = mem,
};
if (fexExtended->Driver.InterruptCallback)
{
for (unsigned long i = 0; i < sizeof(fexExtended->Driver.Bind.Interrupt.Vector) / sizeof(fexExtended->Driver.Bind.Interrupt.Vector[0]); i++)
{
if (fexExtended->Driver.Bind.Interrupt.Vector[i] == 0)
break;
DrvFile.InterruptHook[i] = new DriverInterruptHook(fexExtended->Driver.Bind.Interrupt.Vector[i], DrvFile);
}
}
KernelCallback KCallback{};
KCallback.RawPtr = nullptr;
KCallback.Reason = CallbackReason::ConfigurationReason;
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
{
error("Driver %s is not implemented", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
else if (CallbackRet != DriverReturnCode::OK)
{
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

View File

@ -1,81 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInterruptNetwork(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Network driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,115 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInterruptStorage(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
.MemTrk = mem,
};
if (fexExtended->Driver.InterruptCallback)
{
for (unsigned long i = 0; i < sizeof(fexExtended->Driver.Bind.Interrupt.Vector) / sizeof(fexExtended->Driver.Bind.Interrupt.Vector[0]); i++)
{
if (fexExtended->Driver.Bind.Interrupt.Vector[i] == 0)
break;
DrvFile.InterruptHook[i] = new DriverInterruptHook(fexExtended->Driver.Bind.Interrupt.Vector[i], DrvFile);
}
}
KernelCallback KCallback{};
KCallback.RawPtr = nullptr;
KCallback.Reason = CallbackReason::ConfigurationReason;
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
{
error("Driver %s is not implemented", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
else if (CallbackRet != DriverReturnCode::OK)
{
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

View File

@ -1,110 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindPCIAudio(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
.MemTrk = mem,
};
if (fexExtended->Driver.InterruptCallback)
DrvFile.InterruptHook[0] = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine), DrvFile);
KernelCallback KCallback{};
KCallback.RawPtr = PCIDevice;
KCallback.Reason = CallbackReason::ConfigurationReason;
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
{
error("Driver %s is not implemented", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
else if (CallbackRet == DriverReturnCode::OK)
trace("Device found for driver: %s", fexExtended->Driver.Name);
else
{
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

View File

@ -1,82 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindPCIDisplay(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
UNUSED(PCIDevice);
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Display driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,82 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindPCIFileSystem(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
UNUSED(PCIDevice);
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,82 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindPCIGeneric(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
UNUSED(PCIDevice);
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Generic driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,82 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindPCIInput(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
UNUSED(PCIDevice);
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Input driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,110 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindPCINetwork(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
.MemTrk = mem,
};
if (fexExtended->Driver.InterruptCallback)
DrvFile.InterruptHook[0] = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine), DrvFile);
KernelCallback KCallback{};
KCallback.RawPtr = PCIDevice;
KCallback.Reason = CallbackReason::ConfigurationReason;
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
{
error("Driver %s is not implemented", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
else if (CallbackRet == DriverReturnCode::OK)
trace("Device found for driver: %s", fexExtended->Driver.Name);
else
{
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

View File

@ -1,110 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindPCIStorage(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<size_t> DriversToRemove = std::vector<size_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
.MemTrk = mem,
};
if (fexExtended->Driver.InterruptCallback)
DrvFile.InterruptHook[0] = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine), DrvFile);
KernelCallback KCallback{};
KCallback.RawPtr = PCIDevice;
KCallback.Reason = CallbackReason::ConfigurationReason;
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
{
error("Driver %s is not implemented", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
else if (CallbackRet == DriverReturnCode::OK)
trace("Device found for driver: %s", fexExtended->Driver.Name);
else
{
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindProcessAudio(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindProcessDisplay(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindProcessFileSystem(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindProcessGeneric(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindProcessInput(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindProcessNetwork(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindProcessStorage(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -32,70 +32,70 @@
namespace Time
{
bool HighPrecisionEventTimer::Sleep(uint64_t Duration, Units Unit)
bool HighPrecisionEventTimer::Sleep(size_t Duration, Units Unit)
{
#if defined(a64)
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
CPU::Pause();
return true;
size_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
CPU::Pause();
return true;
#elif defined(a32)
uint64_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
while (mminl(&((HPET *)hpet)->MainCounterValue) < Target)
CPU::Pause();
return true;
size_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
while (mminl(&((HPET *)hpet)->MainCounterValue) < Target)
CPU::Pause();
return true;
#endif
return false;
}
uint64_t HighPrecisionEventTimer::GetCounter()
size_t HighPrecisionEventTimer::GetCounter()
{
#if defined(a64)
return mminq(&((HPET *)hpet)->MainCounterValue);
return mminq(&((HPET *)hpet)->MainCounterValue);
#elif defined(a32)
return mminl(&((HPET *)hpet)->MainCounterValue);
return mminl(&((HPET *)hpet)->MainCounterValue);
#endif
}
uint64_t HighPrecisionEventTimer::CalculateTarget(uint64_t Target, Units Unit)
size_t HighPrecisionEventTimer::CalculateTarget(size_t Target, Units Unit)
{
#if defined(a64)
return mminq(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
return mminq(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
#elif defined(a32)
return mminl(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
return mminl(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
#endif
}
uint64_t HighPrecisionEventTimer::GetNanosecondsSinceClassCreation()
size_t HighPrecisionEventTimer::GetNanosecondsSinceClassCreation()
{
#if defined(a86)
uint64_t Subtraction = this->GetCounter() - this->ClassCreationTime;
if (Subtraction <= 0 || this->clk <= 0)
return 0;
return Subtraction / (this->clk / ConvertUnit(Units::Nanoseconds));
size_t Subtraction = this->GetCounter() - this->ClassCreationTime;
if (Subtraction <= 0 || this->clk <= 0)
return 0;
return Subtraction / (this->clk / ConvertUnit(Units::Nanoseconds));
#endif
}
HighPrecisionEventTimer::HighPrecisionEventTimer(void *hpet)
{
#if defined(a86)
ACPI::ACPI::HPETHeader *HPET_HDR = (ACPI::ACPI::HPETHeader *)hpet;
Memory::Virtual().Remap((void *)HPET_HDR->Address.Address,
(void *)HPET_HDR->Address.Address,
Memory::PTFlag::RW | Memory::PTFlag::PCD);
this->hpet = (HPET *)HPET_HDR->Address.Address;
trace("%s timer is at address %016p", HPET_HDR->Header.OEMID, (void *)HPET_HDR->Address.Address);
clk = s_cst(uint32_t, (uint64_t)this->hpet->GeneralCapabilities >> 32);
ACPI::ACPI::HPETHeader *HPET_HDR = (ACPI::ACPI::HPETHeader *)hpet;
Memory::Virtual().Remap((void *)HPET_HDR->Address.Address,
(void *)HPET_HDR->Address.Address,
Memory::PTFlag::RW | Memory::PTFlag::PCD);
this->hpet = (HPET *)HPET_HDR->Address.Address;
trace("%s timer is at address %016p", HPET_HDR->Header.OEMID, (void *)HPET_HDR->Address.Address);
clk = s_cst(uint32_t, (uint64_t)this->hpet->GeneralCapabilities >> 32);
#ifdef a64
mmoutq(&this->hpet->GeneralConfiguration, 0);
mmoutq(&this->hpet->MainCounterValue, 0);
mmoutq(&this->hpet->GeneralConfiguration, 1);
mmoutq(&this->hpet->GeneralConfiguration, 0);
mmoutq(&this->hpet->MainCounterValue, 0);
mmoutq(&this->hpet->GeneralConfiguration, 1);
#else
mmoutl(&this->hpet->GeneralConfiguration, 0);
mmoutl(&this->hpet->MainCounterValue, 0);
mmoutl(&this->hpet->GeneralConfiguration, 1);
mmoutl(&this->hpet->GeneralConfiguration, 0);
mmoutl(&this->hpet->MainCounterValue, 0);
mmoutl(&this->hpet->GeneralConfiguration, 1);
#endif
ClassCreationTime = this->GetCounter();
ClassCreationTime = this->GetCounter();
#endif
}

View File

@ -31,51 +31,51 @@
namespace Time
{
bool TimeStampCounter::Sleep(uint64_t Duration, Units Unit)
{
bool TimeStampCounter::Sleep(size_t Duration, Units Unit)
{
#if defined(a86)
uint64_t Target = this->GetCounter() + (Duration * ConvertUnit(Unit)) / this->clk;
while (this->GetCounter() < Target)
CPU::Pause();
return true;
size_t Target = this->GetCounter() + (Duration * ConvertUnit(Unit)) / this->clk;
while (this->GetCounter() < Target)
CPU::Pause();
return true;
#endif
}
}
uint64_t TimeStampCounter::GetCounter()
{
size_t TimeStampCounter::GetCounter()
{
#if defined(a86)
return CPU::Counter();
return CPU::Counter();
#endif
}
}
uint64_t TimeStampCounter::CalculateTarget(uint64_t Target, Units Unit)
{
size_t TimeStampCounter::CalculateTarget(size_t Target, Units Unit)
{
#if defined(a86)
return this->GetCounter() + (Target * ConvertUnit(Unit)) / this->clk;
return this->GetCounter() + (Target * ConvertUnit(Unit)) / this->clk;
#endif
}
}
uint64_t TimeStampCounter::GetNanosecondsSinceClassCreation()
{
size_t TimeStampCounter::GetNanosecondsSinceClassCreation()
{
#if defined(a86)
return (this->GetCounter() - this->ClassCreationTime) / this->clk;
return (this->GetCounter() - this->ClassCreationTime) / this->clk;
#endif
}
}
TimeStampCounter::TimeStampCounter()
{
TimeStampCounter::TimeStampCounter()
{
#if defined(a86)
fixme(""); // FIXME: This is not a good way to measure the clock speed
uint64_t Start = CPU::Counter();
TimeManager->Sleep(1, Units::Milliseconds);
uint64_t End = CPU::Counter();
fixme(""); // FIXME: This is not a good way to measure the clock speed
size_t Start = CPU::Counter();
TimeManager->Sleep(1, Units::Milliseconds);
size_t End = CPU::Counter();
this->clk = End - Start;
this->ClassCreationTime = this->GetCounter();
this->clk = End - Start;
this->ClassCreationTime = this->GetCounter();
#endif
}
}
TimeStampCounter::~TimeStampCounter()
{
}
TimeStampCounter::~TimeStampCounter()
{
}
}

View File

@ -32,184 +32,184 @@
namespace Time
{
bool time::Sleep(uint64_t Duration, Units Unit)
{
switch (ActiveTimer)
{
case NONE:
error("No timer is active");
return false;
case RTC:
fixme("RTC sleep not implemented");
return false;
case PIT:
fixme("PIT sleep not implemented");
return false;
case HPET:
return this->hpet->Sleep(Duration, Unit);
case ACPI:
fixme("ACPI sleep not implemented");
return false;
case APIC:
fixme("APIC sleep not implemented");
return false;
case TSC:
return this->tsc->Sleep(Duration, Unit);
default:
error("Unknown timer");
return false;
}
}
bool time::Sleep(size_t Duration, Units Unit)
{
switch (ActiveTimer)
{
case NONE:
error("No timer is active");
return false;
case RTC:
fixme("RTC sleep not implemented");
return false;
case PIT:
fixme("PIT sleep not implemented");
return false;
case HPET:
return this->hpet->Sleep(Duration, Unit);
case ACPI:
fixme("ACPI sleep not implemented");
return false;
case APIC:
fixme("APIC sleep not implemented");
return false;
case TSC:
return this->tsc->Sleep(Duration, Unit);
default:
error("Unknown timer");
return false;
}
}
uint64_t time::GetCounter()
{
switch (ActiveTimer)
{
case NONE:
error("No timer is active");
return false;
case RTC:
fixme("RTC sleep not implemented");
return false;
case PIT:
fixme("PIT sleep not implemented");
return false;
case HPET:
return this->hpet->GetCounter();
case ACPI:
fixme("ACPI sleep not implemented");
return false;
case APIC:
fixme("APIC sleep not implemented");
return false;
case TSC:
return this->tsc->GetCounter();
default:
error("Unknown timer");
return false;
}
}
size_t time::GetCounter()
{
switch (ActiveTimer)
{
case NONE:
error("No timer is active");
return false;
case RTC:
fixme("RTC sleep not implemented");
return false;
case PIT:
fixme("PIT sleep not implemented");
return false;
case HPET:
return this->hpet->GetCounter();
case ACPI:
fixme("ACPI sleep not implemented");
return false;
case APIC:
fixme("APIC sleep not implemented");
return false;
case TSC:
return this->tsc->GetCounter();
default:
error("Unknown timer");
return false;
}
}
uint64_t time::CalculateTarget(uint64_t Target, Units Unit)
{
switch (ActiveTimer)
{
case NONE:
error("No timer is active");
return false;
case RTC:
fixme("RTC sleep not implemented");
return false;
case PIT:
fixme("PIT sleep not implemented");
return false;
case HPET:
return this->hpet->CalculateTarget(Target, Unit);
case ACPI:
fixme("ACPI sleep not implemented");
return false;
case APIC:
fixme("APIC sleep not implemented");
return false;
case TSC:
return this->tsc->CalculateTarget(Target, Unit);
default:
error("Unknown timer");
return false;
}
}
size_t time::CalculateTarget(size_t Target, Units Unit)
{
switch (ActiveTimer)
{
case NONE:
error("No timer is active");
return false;
case RTC:
fixme("RTC sleep not implemented");
return false;
case PIT:
fixme("PIT sleep not implemented");
return false;
case HPET:
return this->hpet->CalculateTarget(Target, Unit);
case ACPI:
fixme("ACPI sleep not implemented");
return false;
case APIC:
fixme("APIC sleep not implemented");
return false;
case TSC:
return this->tsc->CalculateTarget(Target, Unit);
default:
error("Unknown timer");
return false;
}
}
uint64_t time::GetNanosecondsSinceClassCreation()
{
switch (ActiveTimer)
{
case NONE:
error("No timer is active");
return false;
case RTC:
fixme("RTC sleep not implemented");
return false;
case PIT:
fixme("PIT sleep not implemented");
return false;
case HPET:
return this->hpet->GetNanosecondsSinceClassCreation();
case ACPI:
fixme("ACPI sleep not implemented");
return false;
case APIC:
fixme("APIC sleep not implemented");
return false;
case TSC:
return this->tsc->GetNanosecondsSinceClassCreation();
default:
error("Unknown timer");
return false;
}
}
size_t time::GetNanosecondsSinceClassCreation()
{
switch (ActiveTimer)
{
case NONE:
error("No timer is active");
return false;
case RTC:
fixme("RTC sleep not implemented");
return false;
case PIT:
fixme("PIT sleep not implemented");
return false;
case HPET:
return this->hpet->GetNanosecondsSinceClassCreation();
case ACPI:
fixme("ACPI sleep not implemented");
return false;
case APIC:
fixme("APIC sleep not implemented");
return false;
case TSC:
return this->tsc->GetNanosecondsSinceClassCreation();
default:
error("Unknown timer");
return false;
}
}
void time::FindTimers(void *acpi)
{
void time::FindTimers(void *acpi)
{
#if defined(a86)
/* TODO: RTC check */
/* TODO: PIT check */
/* TODO: RTC check */
/* TODO: PIT check */
if (acpi)
{
if (((ACPI::ACPI *)acpi)->HPET)
{
hpet = new HighPrecisionEventTimer(((ACPI::ACPI *)acpi)->HPET);
ActiveTimer = HPET;
SupportedTimers |= HPET;
KPrint("\e11FF11HPET found");
}
else
{
KPrint("\eFF2200HPET not found");
}
if (acpi)
{
if (((ACPI::ACPI *)acpi)->HPET)
{
hpet = new HighPrecisionEventTimer(((ACPI::ACPI *)acpi)->HPET);
ActiveTimer = HPET;
SupportedTimers |= HPET;
KPrint("\e11FF11HPET found");
}
else
{
KPrint("\eFF2200HPET not found");
}
/* TODO: ACPI check */
/* TODO: APIC check */
}
else
{
KPrint("\eFF2200ACPI not found");
}
/* TODO: ACPI check */
/* TODO: APIC check */
}
else
{
KPrint("\eFF2200ACPI not found");
}
bool TSCInvariant = false;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
CPU::x86::AMD::CPUID0x80000007 cpuid80000007;
cpuid80000007.Get();
if (cpuid80000007.EDX.TscInvariant)
TSCInvariant = true;
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
// TODO: Intel 0x80000007
CPU::x86::AMD::CPUID0x80000007 cpuid80000007;
cpuid80000007.Get();
if (cpuid80000007.EDX.TscInvariant)
TSCInvariant = true;
}
bool TSCInvariant = false;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
CPU::x86::AMD::CPUID0x80000007 cpuid80000007;
cpuid80000007.Get();
if (cpuid80000007.EDX.TscInvariant)
TSCInvariant = true;
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
// TODO: Intel 0x80000007
CPU::x86::AMD::CPUID0x80000007 cpuid80000007;
cpuid80000007.Get();
if (cpuid80000007.EDX.TscInvariant)
TSCInvariant = true;
}
if (TSCInvariant)
{
tsc = new TimeStampCounter;
// FIXME: ActiveTimer = TSC;
SupportedTimers |= TSC;
KPrint("\e11FF11Invariant TSC found");
}
else
KPrint("\eFF2200TSC is not invariant");
if (TSCInvariant)
{
tsc = new TimeStampCounter;
// FIXME: ActiveTimer = TSC;
SupportedTimers |= TSC;
KPrint("\e11FF11Invariant TSC found");
}
else
KPrint("\eFF2200TSC is not invariant");
#endif
}
}
time::time()
{
}
time::time()
{
}
time::~time()
{
}
time::~time()
{
}
}

646
DAPI.hpp
View File

@ -46,386 +46,386 @@
enum DriverReturnCode
{
ERROR,
OK,
NOT_IMPLEMENTED,
NOT_FOUND,
NOT_READY,
NOT_AVAILABLE,
NOT_AUTHORIZED,
NOT_VALID,
NOT_ACCEPTED,
INVALID_PCI_BAR,
INVALID_KERNEL_API,
INVALID_MEMORY_ALLOCATION,
INVALID_DATA,
DEVICE_NOT_SUPPORTED,
SYSTEM_NOT_SUPPORTED,
KERNEL_API_VERSION_NOT_SUPPORTED,
ERROR,
OK,
NOT_IMPLEMENTED,
NOT_FOUND,
NOT_READY,
NOT_AVAILABLE,
NOT_AUTHORIZED,
NOT_VALID,
NOT_ACCEPTED,
INVALID_PCI_BAR,
INVALID_KERNEL_API,
INVALID_MEMORY_ALLOCATION,
INVALID_DATA,
DEVICE_NOT_SUPPORTED,
SYSTEM_NOT_SUPPORTED,
KERNEL_API_VERSION_NOT_SUPPORTED,
};
enum DriverBindType
{
BIND_NULL,
BIND_INTERRUPT,
BIND_PROCESS,
BIND_PCI,
BIND_INPUT
BIND_NULL,
BIND_INTERRUPT,
BIND_PROCESS,
BIND_PCI,
BIND_INPUT
};
struct KernelAPI
{
struct KAPIVersion
{
int Major;
int Minor;
int Patch;
} Version;
struct KAPIVersion
{
int Major;
int Minor;
int Patch;
} Version;
struct KAPIInfo
{
unsigned long Offset;
unsigned long DriverUID;
char KernelDebug;
} Info;
struct KAPIInfo
{
unsigned long Offset;
unsigned int DriverUID;
char KernelDebug;
} Info;
struct KAPIMemory
{
unsigned long PageSize;
void *(*RequestPage)(unsigned long Size);
void (*FreePage)(void *Page, unsigned long Size);
void (*Map)(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags);
void (*Unmap)(void *VirtualAddress);
} Memory;
struct KAPIMemory
{
unsigned long PageSize;
void *(*RequestPage)(unsigned long Size);
void (*FreePage)(void *Page, unsigned long Size);
void (*Map)(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags);
void (*Unmap)(void *VirtualAddress);
} Memory;
struct KAPIPCI
{
char *(*GetDeviceName)(unsigned int VendorID, unsigned int DeviceID);
} PCI;
struct KAPIPCI
{
char *(*GetDeviceName)(unsigned int VendorID, unsigned int DeviceID);
} PCI;
struct KAPIUtilities
{
void (*DebugPrint)(char *String, unsigned long DriverUID);
void (*DisplayPrint)(char *Value);
void *(*memcpy)(void *Destination, void *Source, unsigned long Size);
void *(*memset)(void *Destination, int Value, unsigned long Size);
void (*Sleep)(unsigned long Milliseconds);
int (*sprintf)(char *Buffer, const char *Format, ...);
} Util;
struct KAPIUtilities
{
void (*DebugPrint)(char *String, unsigned long DriverUID);
void (*DisplayPrint)(char *Value);
void *(*memcpy)(void *Destination, void *Source, unsigned long Size);
void *(*memset)(void *Destination, int Value, unsigned long Size);
void (*Sleep)(unsigned long Milliseconds);
int (*sprintf)(char *Buffer, const char *Format, ...);
} Util;
struct KAPIDriverTalk
{
/** @brief Connects to the network manager */
struct
{
void (*SendPacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size);
void (*ReceivePacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size);
} Network;
struct KAPIDriverTalk
{
/** @brief Connects to the network manager */
struct
{
void (*SendPacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size);
void (*ReceivePacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size);
} Network;
/** @brief Connects to the disk manager */
struct
{
struct
{
void (*ReadSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port);
void (*WriteSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port);
} AHCI;
} Disk;
} Command;
/** @brief Connects to the disk manager */
struct
{
struct
{
void (*ReadSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port);
void (*WriteSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port);
} AHCI;
} Disk;
} Command;
struct KAPIDisplay
{
unsigned int (*GetWidth)(void);
unsigned int (*GetHeight)(void);
/* TODO: Add more */
} Display;
struct KAPIDisplay
{
unsigned int (*GetWidth)(void);
unsigned int (*GetHeight)(void);
/* TODO: Add more */
} Display;
} __attribute__((packed));
enum CallbackReason
{
/**
* @brief This is used to detect memory corruption, not used.
*/
UnknownReason,
/**
* @brief This is used to detect memory corruption, not used.
*/
UnknownReason,
/**
* @brief This is called once the kernel is ready to use the driver and call @see ConfigurationReason .
*/
AcknowledgeReason,
/**
* @brief This is called once the kernel is ready to use the driver and call @see ConfigurationReason .
*/
AcknowledgeReason,
/**
* @brief This is used after the driver is loaded and the kernel is ready to use the driver.
*
* For PCI drivers, @see RawPtr will be the PCI device address.
*/
ConfigurationReason,
/**
* @brief This is used after the driver is loaded and the kernel is ready to use the driver.
*
* For PCI drivers, @see RawPtr will be the PCI device address.
*/
ConfigurationReason,
/**
* @brief This is used when the kernel wants to stop the driver.
*
* The memory allocated by the driver will be freed automatically.
*/
StopReason,
/**
* @brief This is used when the kernel wants to stop the driver.
*
* The memory allocated by the driver will be freed automatically.
*/
StopReason,
ProcessReason,
InputReason,
ProcessReason,
InputReason,
/* Kernel reserved callbacks. */
/* ------------------------------------------------------- */
/* Driver callbacks for basic usage. */
/* Kernel reserved callbacks. */
/* ------------------------------------------------------- */
/* Driver callbacks for basic usage. */
/**
* @brief This is used when the kernel sends data.
*
* - Network
* - Packet
* - Audio
* - PCM Data
*/
SendReason,
/**
* @brief This is used when the kernel sends data.
*
* - Network
* - Packet
* - Audio
* - PCM Data
*/
SendReason,
/**
* @brief This is used when the kernel wants to receive data.
* Currently not used.
*/
ReceiveReason,
/**
* @brief This is used when the kernel wants to receive data.
* Currently not used.
*/
ReceiveReason,
/**
* @brief This is used to adjust driver settings.
*
* - Audio
* - Volume
* - PCM Encoding
*/
AdjustReason,
/**
* @brief This is used to adjust driver settings.
*
* - Audio
* - Volume
* - PCM Encoding
*/
AdjustReason,
/**
* @brief This is used when the kernel wants to fetch information about the driver.
*
* - Input
* - Mouse
* - Position
* - Buttons
* - Keyboard
* - Key
*/
FetchReason,
/**
* @brief This is used when the kernel wants to fetch information about the driver.
*
* - Input
* - Mouse
* - Position
* - Buttons
* - Keyboard
* - Key
*/
FetchReason,
};
union KernelCallback
{
struct
{
CallbackReason Reason;
void *RawPtr;
unsigned long RawData;
struct
{
CallbackReason Reason;
void *RawPtr;
unsigned long RawData;
/** @brief When the kernel wants to send a packet. */
struct
{
struct
{
unsigned char *Data;
unsigned long Length;
} Send;
/** @brief When the kernel wants to send a packet. */
struct
{
struct
{
unsigned char *Data;
unsigned long Length;
} Send;
struct
{
char Name[128];
unsigned long MAC;
} Fetch;
} NetworkCallback;
struct
{
char Name[128];
unsigned long MAC;
} Fetch;
} NetworkCallback;
/** @brief When the kernel wants to write to disk. */
struct
{
struct
{
unsigned long Sector;
unsigned long SectorCount;
unsigned char Port;
unsigned char *Buffer;
bool Write;
} RW;
/** @brief When the kernel wants to write to disk. */
struct
{
struct
{
unsigned long Sector;
unsigned long SectorCount;
unsigned char Port;
unsigned char *Buffer;
bool Write;
} RW;
struct
{
unsigned char Ports;
int BytesPerSector;
} Fetch;
} DiskCallback;
struct
{
unsigned char Ports;
int BytesPerSector;
} Fetch;
} DiskCallback;
/** @brief When the kernel wants to get mouse position / keyboard key */
struct
{
struct
{
unsigned long X;
unsigned long Y;
unsigned long Z;
struct
{
bool Left;
bool Right;
bool Middle;
} Buttons;
} Mouse;
} InputCallback;
/** @brief When the kernel wants to get mouse position / keyboard key */
struct
{
struct
{
unsigned long X;
unsigned long Y;
unsigned long Z;
struct
{
bool Left;
bool Right;
bool Middle;
} Buttons;
} Mouse;
} InputCallback;
struct
{
struct
{
bool _Volume;
bool _Encoding;
bool _SampleRate;
bool _Channels;
struct
{
struct
{
bool _Volume;
bool _Encoding;
bool _SampleRate;
bool _Channels;
/**
* @brief Adjust the volume.
*
* 0 - 100
*/
unsigned char Volume;
/**
* @brief Adjust the volume.
*
* 0 - 100
*/
unsigned char Volume;
/**
* @brief Adjust the encoding.
*
* 0 - None, use default
*
* 1 - Signed PCM 8-bit
* 2 - Unsigned PCM 8-bit
*
* 3 - Signed PCM 16-bit Little Endian
* 4 - Signed PCM 20-bit Little Endian
* 5 - Signed PCM 24-bit Little Endian
* 6 - Signed PCM 32-bit Little Endian
*
* 7 - Unsigned PCM 16-bit Little Endian
* 8 - Unsigned PCM 20-bit Little Endian
* 9 - Unsigned PCM 24-bit Little Endian
* 10 - Unsigned PCM 32-bit Little Endian
*
* 11 - Signed PCM 16-bit Big Endian
* 12 - Signed PCM 20-bit Big Endian
* 13 - Signed PCM 24-bit Big Endian
* 14 - Signed PCM 32-bit Big Endian
*
* 15 - Unsigned PCM 16-bit Big Endian
* 16 - Unsigned PCM 20-bit Big Endian
* 17 - Unsigned PCM 24-bit Big Endian
* 18 - Unsigned PCM 32-bit Big Endian
*
* 19 - Float PCM 32-bit Little Endian
* 20 - Float PCM 64-bit Little Endian
*
* 21 - Float PCM 32-bit Big Endian
* 22 - Float PCM 64-bit Big Endian
*
* 23 - PCM A-law
* 24 - PCM Mu-law
*
* ... - More
*/
unsigned short Encoding;
/**
* @brief Adjust the encoding.
*
* 0 - None, use default
*
* 1 - Signed PCM 8-bit
* 2 - Unsigned PCM 8-bit
*
* 3 - Signed PCM 16-bit Little Endian
* 4 - Signed PCM 20-bit Little Endian
* 5 - Signed PCM 24-bit Little Endian
* 6 - Signed PCM 32-bit Little Endian
*
* 7 - Unsigned PCM 16-bit Little Endian
* 8 - Unsigned PCM 20-bit Little Endian
* 9 - Unsigned PCM 24-bit Little Endian
* 10 - Unsigned PCM 32-bit Little Endian
*
* 11 - Signed PCM 16-bit Big Endian
* 12 - Signed PCM 20-bit Big Endian
* 13 - Signed PCM 24-bit Big Endian
* 14 - Signed PCM 32-bit Big Endian
*
* 15 - Unsigned PCM 16-bit Big Endian
* 16 - Unsigned PCM 20-bit Big Endian
* 17 - Unsigned PCM 24-bit Big Endian
* 18 - Unsigned PCM 32-bit Big Endian
*
* 19 - Float PCM 32-bit Little Endian
* 20 - Float PCM 64-bit Little Endian
*
* 21 - Float PCM 32-bit Big Endian
* 22 - Float PCM 64-bit Big Endian
*
* 23 - PCM A-law
* 24 - PCM Mu-law
*
* ... - More
*/
unsigned short Encoding;
/**
* @brief Adjust the sample rate.
*
* 0 - 8000 Hz
* 1 - 11025 Hz
* 2 - 16000 Hz
* 3 - 22050 Hz
* 4 - 32000 Hz
* 5 - 44100 Hz
* 6 - 48000 Hz
* 7 - 88200 Hz
* 8 - 96000 Hz
*/
unsigned char SampleRate;
/**
* @brief Adjust the sample rate.
*
* 0 - 8000 Hz
* 1 - 11025 Hz
* 2 - 16000 Hz
* 3 - 22050 Hz
* 4 - 32000 Hz
* 5 - 44100 Hz
* 6 - 48000 Hz
* 7 - 88200 Hz
* 8 - 96000 Hz
*/
unsigned char SampleRate;
/**
* @brief Adjust the channels.
*
* 0 - Mono
* 1 - Stereo
*/
unsigned char Channels;
} Adjust;
/**
* @brief Adjust the channels.
*
* 0 - Mono
* 1 - Stereo
*/
unsigned char Channels;
} Adjust;
struct
{
unsigned char *Data;
unsigned long Length;
} Send;
struct
{
unsigned char *Data;
unsigned long Length;
} Send;
struct
{
unsigned char Volume;
unsigned short Encoding;
unsigned char SampleRate;
unsigned char Channels;
} Fetch;
} AudioCallback;
struct
{
unsigned char Volume;
unsigned short Encoding;
unsigned char SampleRate;
unsigned char Channels;
} Fetch;
} AudioCallback;
struct
{
unsigned char Vector;
} InterruptInfo;
};
unsigned long raw;
struct
{
unsigned char Vector;
} InterruptInfo;
};
unsigned long raw;
} __attribute__((packed));
union CPURegisters
{
struct
{
struct
{
#if defined(__x86_64__) || defined(__amd64__)
unsigned long r15;
unsigned long r14;
unsigned long r13;
unsigned long r12;
unsigned long r11;
unsigned long r10;
unsigned long r9;
unsigned long r8;
unsigned long r15;
unsigned long r14;
unsigned long r13;
unsigned long r12;
unsigned long r11;
unsigned long r10;
unsigned long r9;
unsigned long r8;
unsigned long rbp;
unsigned long rdi;
unsigned long rsi;
unsigned long rdx;
unsigned long rcx;
unsigned long rbx;
unsigned long rax;
unsigned long rbp;
unsigned long rdi;
unsigned long rsi;
unsigned long rdx;
unsigned long rcx;
unsigned long rbx;
unsigned long rax;
unsigned long InterruptNumber;
unsigned long ErrorCode;
unsigned long rip;
unsigned long cs;
unsigned long rflags;
unsigned long rsp;
unsigned long ss;
unsigned long InterruptNumber;
unsigned long ErrorCode;
unsigned long rip;
unsigned long cs;
unsigned long rflags;
unsigned long rsp;
unsigned long ss;
#elif defined(__i386__)
unsigned int ebp;
unsigned int edi;
unsigned int esi;
unsigned int edx;
unsigned int ecx;
unsigned int ebx;
unsigned int eax;
unsigned int ebp;
unsigned int edi;
unsigned int esi;
unsigned int edx;
unsigned int ecx;
unsigned int ebx;
unsigned int eax;
unsigned int InterruptNumber;
unsigned int ErrorCode;
unsigned int eip;
unsigned int cs;
unsigned int eflags;
unsigned int esp;
unsigned int ss;
unsigned int InterruptNumber;
unsigned int ErrorCode;
unsigned int eip;
unsigned int cs;
unsigned int eflags;
unsigned int esp;
unsigned int ss;
#else
#warning "Unsupported architecture"
#endif
};
unsigned long raw;
};
unsigned long raw;
} __attribute__((packed));
#endif // !__FENNIX_DRIVER_API_H__

View File

@ -0,0 +1,311 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "ahci.hpp"
#include <debug.h>
#include <pci.hpp>
#include "../../DAPI.hpp"
#include "../drv.hpp"
using namespace PCI;
namespace AdvancedHostControllerInterface
{
KernelAPI KAPI;
HBAMemory *ABAR;
Port *Ports[32];
uint8_t PortCount = 0;
PCIDeviceHeader *PCIBaseAddress;
const char *PortTypeName[] = {"None",
"SATA",
"SEMB",
"PM",
"SATAPI"};
PortType CheckPortType(HBAPort *Port)
{
uint32_t SataStatus = Port->SataStatus;
uint8_t InterfacePowerManagement = (SataStatus >> 8) & 0b111;
uint8_t DeviceDetection = SataStatus & 0b111;
if (DeviceDetection != HBA_PORT_DEV_PRESENT)
return PortType::None;
if (InterfacePowerManagement != HBA_PORT_IPM_ACTIVE)
return PortType::None;
switch (Port->Signature)
{
case SATA_SIG_ATAPI:
return PortType::SATAPI;
case SATA_SIG_ATA:
return PortType::SATA;
case SATA_SIG_PM:
return PortType::PM;
case SATA_SIG_SEMB:
return PortType::SEMB;
default:
return PortType::None;
}
}
Port::Port(PortType Type, HBAPort *PortPtr, uint8_t PortNumber)
{
this->AHCIPortType = Type;
this->HBAPortPtr = PortPtr;
this->Buffer = static_cast<uint8_t *>(KAPI.Memory.RequestPage(1));
memset(this->Buffer, 0, KAPI.Memory.PageSize);
this->PortNumber = PortNumber;
}
Port::~Port()
{
KAPI.Memory.FreePage(this->Buffer, 1);
}
void Port::StartCMD()
{
while (HBAPortPtr->CommandStatus & HBA_PxCMD_CR)
;
HBAPortPtr->CommandStatus |= HBA_PxCMD_FRE;
HBAPortPtr->CommandStatus |= HBA_PxCMD_ST;
}
void Port::StopCMD()
{
HBAPortPtr->CommandStatus &= ~HBA_PxCMD_ST;
HBAPortPtr->CommandStatus &= ~HBA_PxCMD_FRE;
while (true)
{
if (HBAPortPtr->CommandStatus & HBA_PxCMD_FR)
continue;
if (HBAPortPtr->CommandStatus & HBA_PxCMD_CR)
continue;
break;
}
}
void Port::Configure()
{
StopCMD();
void *NewBase = KAPI.Memory.RequestPage(1);
HBAPortPtr->CommandListBase = (uint32_t)(uint64_t)NewBase;
HBAPortPtr->CommandListBaseUpper = (uint32_t)((uint64_t)NewBase >> 32);
memset(reinterpret_cast<void *>(HBAPortPtr->CommandListBase), 0, 1024);
void *FISBase = KAPI.Memory.RequestPage(1);
HBAPortPtr->FISBaseAddress = (uint32_t)(uint64_t)FISBase;
HBAPortPtr->FISBaseAddressUpper = (uint32_t)((uint64_t)FISBase >> 32);
memset(FISBase, 0, 256);
HBACommandHeader *CommandHeader = (HBACommandHeader *)((uint64_t)HBAPortPtr->CommandListBase + ((uint64_t)HBAPortPtr->CommandListBaseUpper << 32));
for (int i = 0; i < 32; i++)
{
CommandHeader[i].PRDTLength = 8;
void *CommandTableAddress = KAPI.Memory.RequestPage(1);
uint64_t Address = (uint64_t)CommandTableAddress + (i << 8);
CommandHeader[i].CommandTableBaseAddress = (uint32_t)(uint64_t)Address;
CommandHeader[i].CommandTableBaseAddressUpper = (uint32_t)((uint64_t)Address >> 32);
memset(CommandTableAddress, 0, 256);
}
StartCMD();
}
bool Port::ReadWrite(uint64_t Sector, uint32_t SectorCount, uint8_t *Buffer, bool Write)
{
if (this->PortNumber == PortType::SATAPI && Write)
{
error("SATAPI port does not support write.");
return false;
}
uint32_t SectorL = (uint32_t)Sector;
uint32_t SectorH = (uint32_t)(Sector >> 32);
HBAPortPtr->InterruptStatus = (uint32_t)-1; // Clear pending interrupt bits
HBACommandHeader *CommandHeader = reinterpret_cast<HBACommandHeader *>(HBAPortPtr->CommandListBase);
CommandHeader->CommandFISLength = sizeof(FIS_REG_H2D) / sizeof(uint32_t);
if (Write)
CommandHeader->Write = 1;
else
CommandHeader->Write = 0;
CommandHeader->PRDTLength = 1;
HBACommandTable *CommandTable = reinterpret_cast<HBACommandTable *>(CommandHeader->CommandTableBaseAddress);
memset(CommandTable, 0, sizeof(HBACommandTable) + (CommandHeader->PRDTLength - 1) * sizeof(HBAPRDTEntry));
CommandTable->PRDTEntry[0].DataBaseAddress = (uint32_t)(uint64_t)Buffer;
CommandTable->PRDTEntry[0].DataBaseAddressUpper = (uint32_t)((uint64_t)Buffer >> 32);
#pragma GCC diagnostic push
/* conversion from uint32_t {aka unsigned int} to unsigned int:22 may change value */
#pragma GCC diagnostic ignored "-Wconversion"
CommandTable->PRDTEntry[0].ByteCount = (SectorCount << 9) - 1; /* 512 bytes per sector */
#pragma GCC diagnostic pop
CommandTable->PRDTEntry[0].InterruptOnCompletion = 1;
FIS_REG_H2D *CommandFIS = (FIS_REG_H2D *)(&CommandTable->CommandFIS);
CommandFIS->FISType = FIS_TYPE_REG_H2D;
CommandFIS->CommandControl = 1;
if (Write)
CommandFIS->Command = ATA_CMD_WRITE_DMA_EX;
else
CommandFIS->Command = ATA_CMD_READ_DMA_EX;
CommandFIS->LBA0 = (uint8_t)SectorL;
CommandFIS->LBA1 = (uint8_t)(SectorL >> 8);
CommandFIS->LBA2 = (uint8_t)(SectorL >> 16);
CommandFIS->LBA3 = (uint8_t)SectorH;
CommandFIS->LBA4 = (uint8_t)(SectorH >> 8);
CommandFIS->LBA5 = (uint8_t)(SectorH >> 16);
CommandFIS->DeviceRegister = 1 << 6; // LBA mode
CommandFIS->CountLow = SectorCount & 0xFF;
CommandFIS->CountHigh = (SectorCount >> 8) & 0xFF;
uint64_t Spin = 0;
while ((HBAPortPtr->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && Spin < 1000000)
Spin++;
if (Spin == 1000000)
{
error("Port not responding.");
return false;
}
HBAPortPtr->CommandIssue = 1;
Spin = 0;
int TryCount = 0;
while (true)
{
if (Spin > 100000000)
{
error("Port %d not responding. (%d)", this->PortNumber, TryCount);
Spin = 0;
TryCount++;
if (TryCount > 10)
return false;
}
if (HBAPortPtr->CommandIssue == 0)
break;
Spin++;
if (HBAPortPtr->InterruptStatus & HBA_PxIS_TFES)
{
error("Error reading/writing (%d).", Write);
return false;
}
}
return true;
}
int DriverEntry(void *Data)
{
if (!Data)
return INVALID_KERNEL_API;
KAPI = *(KernelAPI *)Data;
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
return OK;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
debug("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
debug("Driver received configuration data.");
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
ABAR = reinterpret_cast<HBAMemory *>(((PCIHeader0 *)PCIBaseAddress)->BAR5);
KAPI.Memory.Map((void *)ABAR, (void *)ABAR, (1 << 1));
uint32_t PortsImplemented = ABAR->PortsImplemented;
for (int i = 0; i < 32; i++)
{
if (PortsImplemented & (1 << i))
{
PortType portType = CheckPortType(&ABAR->Ports[i]);
if (portType == PortType::SATA || portType == PortType::SATAPI)
{
trace("%s drive found at port %d", PortTypeName[portType], i);
Ports[PortCount] = new Port(portType, &ABAR->Ports[i], PortCount);
PortCount++;
}
else
{
if (portType != PortType::None)
warn("Unsupported drive type %s found at port %d", PortTypeName[portType], i);
}
}
}
for (int i = 0; i < PortCount; i++)
Ports[i]->Configure();
break;
}
case FetchReason:
{
Data->DiskCallback.Fetch.Ports = PortCount;
Data->DiskCallback.Fetch.BytesPerSector = 512;
break;
}
case StopReason:
{
// TODO: Stop the driver.
debug("Driver stopped.");
break;
}
case SendReason:
case ReceiveReason:
{
Ports[Data->DiskCallback.RW.Port]->ReadWrite(Data->DiskCallback.RW.Sector,
(uint32_t)Data->DiskCallback.RW.SectorCount,
Data->DiskCallback.RW.Buffer,
Data->DiskCallback.RW.Write);
break;
}
default:
{
warn("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
/* There's no need to do anything here. */
return OK;
}
}

193
Drivers/AHCI/ahci.hpp Normal file
View File

@ -0,0 +1,193 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_AHCI_H__
#define __FENNIX_KERNEL_AHCI_H__
#include <types.h>
#include "../../DAPI.hpp"
namespace AdvancedHostControllerInterface
{
#define ATA_DEV_BUSY 0x80
#define ATA_DEV_DRQ 0x08
#define ATA_CMD_WRITE_DMA_EX 0x35
#define ATA_CMD_READ_DMA_EX 0x25
#define HBA_PxIS_TFES (1 << 30)
#define HBA_PORT_DEV_PRESENT 0x3
#define HBA_PORT_IPM_ACTIVE 0x1
#define SATA_SIG_ATAPI 0xEB140101
#define SATA_SIG_ATA 0x00000101
#define SATA_SIG_SEMB 0xC33C0101
#define SATA_SIG_PM 0x96690101
#define HBA_PxCMD_CR 0x8000
#define HBA_PxCMD_FRE 0x0010
#define HBA_PxCMD_ST 0x0001
#define HBA_PxCMD_FR 0x4000
enum PortType
{
None = 0,
SATA = 1,
SEMB = 2,
PM = 3,
SATAPI = 4,
};
enum FIS_TYPE
{
FIS_TYPE_REG_H2D = 0x27,
FIS_TYPE_REG_D2H = 0x34,
FIS_TYPE_DMA_ACT = 0x39,
FIS_TYPE_DMA_SETUP = 0x41,
FIS_TYPE_DATA = 0x46,
FIS_TYPE_BIST = 0x58,
FIS_TYPE_PIO_SETUP = 0x5F,
FIS_TYPE_DEV_BITS = 0xA1,
};
struct HBAPort
{
uint32_t CommandListBase;
uint32_t CommandListBaseUpper;
uint32_t FISBaseAddress;
uint32_t FISBaseAddressUpper;
uint32_t InterruptStatus;
uint32_t InterruptEnable;
uint32_t CommandStatus;
uint32_t Reserved0;
uint32_t TaskFileData;
uint32_t Signature;
uint32_t SataStatus;
uint32_t SataControl;
uint32_t SataError;
uint32_t SataActive;
uint32_t CommandIssue;
uint32_t SataNotification;
uint32_t FISSwitchControl;
uint32_t Reserved1[11];
uint32_t Vendor[4];
};
struct HBAMemory
{
uint32_t HostCapability;
uint32_t GlobalHostControl;
uint32_t InterruptStatus;
uint32_t PortsImplemented;
uint32_t Version;
uint32_t CCCControl;
uint32_t CCCPorts;
uint32_t EnclosureManagementLocation;
uint32_t EnclosureManagementControl;
uint32_t HostCapabilitiesExtended;
uint32_t BIOSHandoffControlStatus;
uint8_t Reserved0[0x74];
uint8_t Vendor[0x60];
HBAPort Ports[1];
};
struct HBACommandHeader
{
uint8_t CommandFISLength : 5;
uint8_t ATAPI : 1;
uint8_t Write : 1;
uint8_t Preferable : 1;
uint8_t Reset : 1;
uint8_t BIST : 1;
uint8_t ClearBusy : 1;
uint8_t Reserved0 : 1;
uint8_t PortMultiplier : 4;
uint16_t PRDTLength;
uint32_t PRDBCount;
uint32_t CommandTableBaseAddress;
uint32_t CommandTableBaseAddressUpper;
uint32_t Reserved1[4];
};
struct HBAPRDTEntry
{
uint32_t DataBaseAddress;
uint32_t DataBaseAddressUpper;
uint32_t Reserved0;
uint32_t ByteCount : 22;
uint32_t Reserved1 : 9;
uint32_t InterruptOnCompletion : 1;
};
struct HBACommandTable
{
uint8_t CommandFIS[64];
uint8_t ATAPICommand[16];
uint8_t Reserved[48];
HBAPRDTEntry PRDTEntry[];
};
struct FIS_REG_H2D
{
uint8_t FISType;
uint8_t PortMultiplier : 4;
uint8_t Reserved0 : 3;
uint8_t CommandControl : 1;
uint8_t Command;
uint8_t FeatureLow;
uint8_t LBA0;
uint8_t LBA1;
uint8_t LBA2;
uint8_t DeviceRegister;
uint8_t LBA3;
uint8_t LBA4;
uint8_t LBA5;
uint8_t FeatureHigh;
uint8_t CountLow;
uint8_t CountHigh;
uint8_t ISOCommandCompletion;
uint8_t Control;
uint8_t Reserved1[4];
};
struct BARData
{
uint8_t Type;
uint16_t IOBase;
uint64_t MemoryBase;
};
class Port
{
public:
PortType AHCIPortType;
HBAPort *HBAPortPtr;
uint8_t *Buffer;
uint8_t PortNumber;
Port(PortType Type, HBAPort *PortPtr, uint8_t PortNumber);
~Port();
void StartCMD();
void StopCMD();
void Configure();
bool ReadWrite(uint64_t Sector, uint32_t SectorCount, uint8_t *Buffer, bool Write);
};
int DriverEntry(void *);
int CallbackHandler(KernelCallback *);
int InterruptCallback(CPURegisters *);
}
#endif // !__FENNIX_KERNEL_AHCI_H__

View File

@ -0,0 +1,91 @@
#include "ata.hpp"
#include <debug.h>
#include <pci.hpp>
#include <io.h>
#include "../../DAPI.hpp"
#include "../drv.hpp"
namespace AdvancedTechnologyAttachment
{
KernelAPI KAPI;
bool IsATAPresent()
{
outb(0x1F0 + 2, 0);
outb(0x1F0 + 3, 0);
outb(0x1F0 + 4, 0);
outb(0x1F0 + 5, 0);
outb(0x1F0 + 7, 0xEC);
if (inb(0x1F0 + 7) == 0 || inb(0x1F0 + 1) != 0)
return false;
return true;
}
int DriverEntry(void *Data)
{
if (!Data)
return INVALID_KERNEL_API;
KAPI = *(KernelAPI *)Data;
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
if (!IsATAPresent())
return NOT_AVAILABLE;
trace("ATA device found.");
return NOT_IMPLEMENTED;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
debug("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
debug("Driver received configuration data.");
break;
}
case FetchReason:
{
break;
}
case SendReason:
case ReceiveReason:
{
break;
}
case StopReason:
{
// TODO: Stop the driver.
debug("Driver stopped.");
break;
}
default:
{
warn("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *Registers)
{
if (Registers->InterruptNumber == 0xE)
{
fixme("IRQ14");
}
else if (Registers->InterruptNumber == 0xF)
{
fixme("IRQ15");
}
return OK;
}
}

View File

@ -15,26 +15,17 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#ifndef __FENNIX_KERNEL_ATA_H__
#define __FENNIX_KERNEL_ATA_H__
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include <types.h>
#include "../../DAPI.hpp"
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
namespace AdvancedTechnologyAttachment
{
DriverCode Driver::BindInputAudio(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
int DriverEntry(void *);
int CallbackHandler(KernelCallback *);
int InterruptCallback(CPURegisters *);
}
#endif // !__FENNIX_KERNEL_ATA_H__

View File

@ -0,0 +1,114 @@
#include "pcnet.hpp"
#include <net/net.hpp>
#include <debug.h>
#include <pci.hpp>
#include <io.h>
#include "../../DAPI.hpp"
#include "../drv.hpp"
using namespace PCI;
namespace PCNET
{
KernelAPI KAPI;
PCIDeviceHeader *PCIBaseAddress;
BARData BAR;
MediaAccessControl MAC;
InternetProtocol::Version4 IP;
void WriteRAP32(uint32_t Value) { outportl(BAR.IOBase + 0x14, Value); }
void WriteRAP16(uint16_t Value) { outportw(BAR.IOBase + 0x12, Value); }
uint32_t ReadCSR32(uint32_t CSR)
{
WriteRAP32(CSR);
return inportl(BAR.IOBase + 0x10);
}
uint16_t ReadCSR16(uint16_t CSR)
{
WriteRAP32(CSR);
return inportw(BAR.IOBase + 0x10);
}
void WriteCSR32(uint32_t CSR, uint32_t Value)
{
WriteRAP32(CSR);
outportl(BAR.IOBase + 0x10, Value);
}
void WriteCSR16(uint16_t CSR, uint16_t Value)
{
WriteRAP16(CSR);
outportw(BAR.IOBase + 0x10, Value);
}
int DriverEntry(void *Data)
{
if (!Data)
return INVALID_KERNEL_API;
KAPI = *(KernelAPI *)Data;
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
return OK;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
debug("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
debug("Driver received configuration data.");
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
if (PCIBaseAddress->VendorID == 0x1022 && PCIBaseAddress->DeviceID == 0x2000)
{
trace("Found AMD PCNET.");
uint32_t PCIBAR = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
BAR.Type = PCIBAR & 1;
BAR.IOBase = (uint16_t)(PCIBAR & (~3));
BAR.MemoryBase = PCIBAR & (~15);
}
else
return DEVICE_NOT_SUPPORTED;
break;
}
case FetchReason:
{
memcpy(Data->NetworkCallback.Fetch.Name, (void *)"AMD PCNET", 10);
Data->NetworkCallback.Fetch.MAC = MAC.ToHex();
break;
}
case SendReason:
{
break;
}
case StopReason:
{
// TODO: Stop the driver.
debug("Driver stopped.");
break;
}
default:
{
warn("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
return OK;
}
}

View File

@ -15,26 +15,24 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#ifndef __FENNIX_KERNEL_AMD_PCNET_H__
#define __FENNIX_KERNEL_AMD_PCNET_H__
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include <types.h>
#include "../../DAPI.hpp"
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
namespace PCNET
{
DriverCode Driver::BindInputDisplay(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
struct BARData
{
uint8_t Type;
uint16_t IOBase;
uint64_t MemoryBase;
};
int DriverEntry(void *);
int CallbackHandler(KernelCallback *);
int InterruptCallback(CPURegisters *);
}
#endif // !__FENNIX_KERNEL_AMD_PCNET_H__

View File

@ -0,0 +1,370 @@
#include "ac97.hpp"
#include <debug.h>
#include <pci.hpp>
#include <io.h>
#include "../../DAPI.hpp"
#include "../drv.hpp"
using namespace PCI;
namespace AudioCodec97
{
KernelAPI KAPI;
/* https://wiki.osdev.org/AC97 */
PCIDeviceHeader *PCIBaseAddress;
BARData BAR;
BufferDescriptorList *DescriptorList = nullptr;
AudioEncodingValues Encoding = AE_PCMs16le;
char Channels = 2;
uint8_t Volume = AV_Maximum;
bool Mute = false;
int SampleRate = 48000;
char SampleSize = 2;
uint16_t MixerVolume(uint8_t Left, uint8_t Right, bool Mute)
{
return ((uint16_t)((Right & 0x3F) |
((Left & 0x3F) << 0x8) |
(Mute & 1 << 0xF)));
}
int DriverEntry(void *Data)
{
if (!Data)
return INVALID_KERNEL_API;
KAPI = *(KernelAPI *)Data;
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
return OK;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
debug("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
debug("Driver received configuration data.");
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
PCIBaseAddress->Command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
/* Native Audio Mixer Base Address */
uint32_t PCIBAR0 = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
/* Native Audio Bus Master Base Address */
uint32_t PCIBAR1 = ((PCIHeader0 *)PCIBaseAddress)->BAR1;
BAR.Type = PCIBAR0 & 1;
BAR.MixerAddress = (uint16_t)(PCIBAR0 & (~3));
BAR.BusMasterAddress = PCIBAR1 & (~15);
if (BAR.Type != 1)
{
error("BAR0 is not I/O.");
return INVALID_PCI_BAR;
}
uint16_t OutputPCMTransferControl = (uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl);
/* DescriptorList address MUST be physical. */
DescriptorList = (BufferDescriptorList *)KAPI.Memory.RequestPage((sizeof(BufferDescriptorList) * DescriptorListLength) / KAPI.Memory.PageSize + 1);
memset(DescriptorList, 0, sizeof(BufferDescriptorList) * DescriptorListLength);
uint16_t DLSampleCount = (uint16_t)(KAPI.Memory.PageSize / SampleSize);
for (int i = 0; i < DescriptorListLength; i++)
{
int DescriptorPages = (int)(sizeof(uint16_t *) / KAPI.Memory.PageSize + 1);
DescriptorList[i].Address = (uint32_t)(uint64_t)KAPI.Memory.RequestPage(DescriptorPages);
DescriptorList[i].SampleCount = DLSampleCount;
DescriptorList[i].Flags = 0;
debug("DescriptorList[%d] = { Address: 0x%x (%d %s), SampleCount: %d, Flags: 0x%x }",
i,
DescriptorList[i].Address, DescriptorPages, DescriptorPages == 1 ? "page" : "pages",
DescriptorList[i].SampleCount,
DescriptorList[i].Flags);
}
outw(BAR.MixerAddress + NAM_MasterVolume, MixerVolume(Volume, Volume, Mute));
outw(BAR.MixerAddress + NAM_PCMOutVolume, MixerVolume(Volume, Volume, Mute));
outb(OutputPCMTransferControl, inb(OutputPCMTransferControl) | TC_TransferReset);
while (inb(OutputPCMTransferControl) & TC_TransferReset)
;
uint32_t GlobalControl = inl((uint16_t)(BAR.BusMasterAddress + NABM_GlobalControl));
GlobalControl = (GlobalControl & ~((0x3U) << 22)); /* PCM 16-bit mode */
GlobalControl = (GlobalControl & ~((0x3U) << 20)); /* 2 channels */
GlobalControl |= GC_GlobalInterruptEnable;
GlobalControl &= ~GC_ShutDown;
outl((uint16_t)(BAR.BusMasterAddress + PCMOUT_BufferDescriptorList), (uint32_t)(uint64_t)DescriptorList);
outl((uint16_t)(BAR.BusMasterAddress + NABM_GlobalControl), GlobalControl);
uint8_t TransferControl = inb(OutputPCMTransferControl);
TransferControl |= TC_LastBufferEntryInterruptEnable | TC_IOCInterruptEnable | TC_FifoERRORInterruptEnable;
outb(OutputPCMTransferControl, TransferControl);
// Stop DMA
outb(OutputPCMTransferControl, inb(OutputPCMTransferControl) & ~TC_DMAControllerControl);
debug("AC'97 configured.");
break;
}
case AdjustReason:
{
if (Data->AudioCallback.Adjust._Volume)
{
Volume = (uint8_t)(0x3F - (0x3F * Data->AudioCallback.Adjust.Volume / 100));
outw(BAR.MixerAddress + NAM_MasterVolume, MixerVolume(Volume, Volume, Mute));
// outw(BAR.MixerAddress + NAM_PCMOutVolume, MixerVolume(Volume, Volume, Mute));
}
else if (Data->AudioCallback.Adjust._Encoding)
{
fixme("Encoding changing not supported yet.");
}
else if (Data->AudioCallback.Adjust._SampleRate)
{
switch (Data->AudioCallback.Adjust.SampleRate)
{
case 0:
{
SampleRate = 8000;
break;
}
case 1:
{
SampleRate = 11025;
break;
}
case 2:
{
SampleRate = 16000;
break;
}
case 3:
{
SampleRate = 22050;
break;
}
case 4:
{
SampleRate = 32000;
break;
}
case 5:
{
SampleRate = 44100;
break;
}
case 6:
{
SampleRate = 48000;
break;
}
case 7:
{
SampleRate = 88200;
break;
}
case 8:
{
SampleRate = 96000;
break;
}
default:
{
SampleRate = 16000;
error("Invalid sample rate. Defaulting to 16000.");
break;
}
}
}
else if (Data->AudioCallback.Adjust._Channels)
{
switch (Data->AudioCallback.Adjust.Channels)
{
case 0:
{
Channels = 1; // Mono
break;
}
case 1:
{
Channels = 2; // Stereo
break;
}
default:
{
Channels = 2;
error("Invalid channel count. Defaulting to 2.");
break;
}
}
}
break;
}
case FetchReason:
{
Data->AudioCallback.Fetch.Volume = (unsigned char)((inw(BAR.MixerAddress + NAM_MasterVolume) & 0x3F) * 100 / 0x3F);
Data->AudioCallback.Fetch.Encoding = Encoding; /* FIXME */
// Data->AudioCallback.Fetch.SampleRate = SampleRate; /* FIXME */
Data->AudioCallback.Fetch.Channels = Channels;
break;
}
case SendReason:
{
unsigned char *Buffer = (unsigned char *)Data->AudioCallback.Send.Data;
unsigned int Length = (unsigned int)Data->AudioCallback.Send.Length;
if (Buffer == nullptr)
{
error("Invalid buffer.");
return INVALID_DATA;
}
if ((Length == 0) || (Length % (SampleSize * Channels)))
{
error("Invalid buffer length.");
return INVALID_DATA;
}
int TotalBDLToFill = (int)((Length + KAPI.Memory.PageSize - 1) >> 12);
while (Length > 0)
{
bool ActiveDMA = !(inw((uint16_t)(BAR.BusMasterAddress + PCMOUT_Status)) & TC_DMAControllerControl);
if (ActiveDMA)
{
int RemainingBDL = 0;
do
{
int CurrentBDL = inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_BufferDescriptorEntry));
int LastBDL = inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_DescriptorEntries));
RemainingBDL = LastBDL - CurrentBDL;
if (RemainingBDL < 0)
RemainingBDL += DescriptorListLength;
RemainingBDL += 1;
if (RemainingBDL >= DescriptorListLength - 1)
{
long SampleCount = DescriptorList[(CurrentBDL + 1) % DescriptorListLength].SampleCount / Channels;
if (SampleCount > 0)
KAPI.Util.Sleep(SampleCount * 1000 / SampleRate); // milliseconds
}
} while (RemainingBDL >= DescriptorListLength - 1 && !(inw((uint16_t)(BAR.BusMasterAddress + PCMOUT_Status)) & TC_DMAControllerControl));
}
{
uint8_t CurrentBDL = inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_BufferDescriptorEntry));
uint8_t LastBDL = inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_DescriptorEntries));
uint8_t NextBDL = LastBDL % DescriptorListLength;
ActiveDMA = !(inw((uint16_t)(BAR.BusMasterAddress + PCMOUT_Status)) & TC_DMAControllerControl);
if (ActiveDMA)
{
NextBDL = (uint8_t)((LastBDL + 1) % DescriptorListLength);
if (NextBDL == CurrentBDL)
continue;
}
do
{
size_t Wrote = (KAPI.Memory.PageSize > Length) ? Length : KAPI.Memory.PageSize;
if (Wrote == 0)
break;
memcpy((void *)((uint64_t)DescriptorList[NextBDL].Address), Buffer, Wrote);
DescriptorList[NextBDL].Flags = 0;
Buffer += Wrote;
Length -= (unsigned int)Wrote;
DescriptorList[NextBDL].SampleCount = (uint16_t)(Wrote / SampleSize);
TotalBDLToFill--;
NextBDL = (uint8_t)((NextBDL + 1) % DescriptorListLength);
} while (TotalBDLToFill-- && NextBDL != CurrentBDL);
outb((uint16_t)(BAR.BusMasterAddress + PCMOUT_DescriptorEntries), NextBDL - 1);
ActiveDMA = !(inw((uint16_t)(BAR.BusMasterAddress + PCMOUT_Status)) & TC_DMAControllerControl);
if (!ActiveDMA)
{
// Start DMA
outb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl), inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl) | TC_DMAControllerControl));
}
}
}
break;
}
case StopReason:
{
outw(BAR.MixerAddress + NAM_MasterVolume, MixerVolume(AV_Maximum, AV_Maximum, true));
outw(BAR.MixerAddress + NAM_PCMOutVolume, MixerVolume(AV_Maximum, AV_Maximum, true));
// Stop DMA
outb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl), inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl)) & ~TC_DMAControllerControl);
// Disable interrupts
uint8_t TransferControl = inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl));
TransferControl &= ~(TC_LastBufferEntryInterruptEnable | TC_IOCInterruptEnable | TC_FifoERRORInterruptEnable);
outb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl), TransferControl);
// Disable global control
uint32_t GlobalControl = inl((uint16_t)(BAR.BusMasterAddress + NABM_GlobalControl));
GlobalControl &= ~GC_GlobalInterruptEnable;
GlobalControl |= GC_ShutDown;
outl((uint16_t)(BAR.BusMasterAddress + NABM_GlobalControl), GlobalControl);
debug("Driver stopped.");
break;
}
default:
{
warn("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
uint16_t Status = inw(BAR.MixerAddress + PCMOUT_Status);
if (Status & TC_IOCInterruptEnable)
{
debug("Interrupt on completion.");
}
else if (Status & TC_LastBufferEntryInterruptEnable)
{
debug("Last buffer entry.");
// Stop DMA
outb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl), inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl)) & ~TC_DMAControllerControl);
}
else if (Status & TC_FifoERRORInterruptEnable)
{
debug("FIFO error.");
}
else if (Status != 0x0)
{
error("Unknown status: %#lx", Status);
}
outw(BAR.MixerAddress + PCMOUT_Status, 0xFFFF);
return OK;
}
}

View File

@ -0,0 +1,348 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_AC97_H__
#define __FENNIX_KERNEL_AC97_H__
#include <types.h>
#include "../../DAPI.hpp"
namespace AudioCodec97
{
#define DescriptorListLength 0x20
enum AudioVolumeValues
{
AV_Maximum = 0x0,
AV_Minimum = 0x3F,
};
enum AudioEncodingValues
{
AE_PCMs8,
AE_PCMu8,
AE_PCMs16le,
AE_PCMs20le,
AE_PCMs24le,
AE_PCMs32le,
AE_PCMu16le,
AE_PCMu20le,
AE_PCMu24le,
AE_PCMu32le,
AE_PCMs16be,
AE_PCMs20be,
AE_PCMs24be,
AE_PCMs32be,
AE_PCMu16be,
AE_PCMu20be,
AE_PCMu24be,
AE_PCMu32be,
};
enum NativeAudioMixerRegisters
{
/**
* @brief Reset Register
* @note Length: word
*/
NAM_Reset = 0x00,
/**
* @brief Master Volume Register
* @note Length: word
*/
NAM_MasterVolume = 0x02,
/**
* @brief Microphone Volume Register
* @note Length: word
*/
NAM_MicrophoneVolume = 0x0E,
/**
* @brief PCM Out Volume Register
* @note Length: word
*/
NAM_PCMOutVolume = 0x18,
/**
* @brief Select Record Input Register
* @note Length: word
*/
NAM_SelectRecordInput = 0x1A,
/**
* @brief Record Gain Register
* @note Length: word
*/
NAM_RecordGain = 0x1C,
/**
* @brief Record Gain Microphone Register
* @note Length: word
*/
NAM_RecordGainMicrophone = 0x1E,
};
enum NativeAudioBusMasterRegisters
{
/**
* @brief Register box for PCM IN
* @note Length: below
*/
NABM_PCMInBox = 0x00,
/**
* @brief Register box for PCM OUT
* @note Length: below
*/
NABM_PCMOutBox = 0x10,
/**
* @brief Register box for Microphone
* @note Length: below
*/
NABM_MicrophoneBox = 0x20,
/**
* @brief Global Control Register
* @note Length: dword
*/
NABM_GlobalControl = 0x2C, /* 0x30 */
/**
* @brief Global Status Register
* @note Length: dword
*/
NABM_GlobalStatus = 0x30, /* 0x34 */
};
enum NativeAudioBusMasterBoxOffsets
{
/**
* @brief Physical Address of Buffer Descriptor List
* @note Length: dword
*/
NABMBOFF_BufferDescriptorList = 0x00,
/**
* @brief Number of Actual Processed Buffer Descriptor Entry
* @note Length: byte
*/
NABMBOFF_BufferDescriptorEntry = 0x04,
/**
* @brief Number of all Descriptor Entries
* @note Length: byte
*/
NABMBOFF_DescriptorEntries = 0x05,
/**
* @brief Status of transferring Data
* @note Length: word
*/
NABMBOFF_Status = 0x06,
/**
* @brief Number of transferred Samples in Actual Processed Entry
* @note Length: word
*/
NABMBOFF_TransferredSamples = 0x08,
/**
* @brief Number of next processed Buffer Entry
* @note Length: byte
*/
NABMBOFF_NextProcessedBufferEntry = 0x0A,
/**
* @brief Transfer Control
* @note Length: byte
*/
NABMBOFF_TransferControl = 0x0B,
};
enum OutputPulseCodeModulationRegisters
{
/**
* @brief Physical Address of Buffer Descriptor List
* @note Length: dword
*/
PCMOUT_BufferDescriptorList = (int)NABM_PCMOutBox + (int)NABMBOFF_BufferDescriptorList,
/**
* @brief Number of Actual Processed Buffer Descriptor Entry
* @note Length: byte
*/
PCMOUT_BufferDescriptorEntry = (int)NABM_PCMOutBox + (int)NABMBOFF_BufferDescriptorEntry,
/**
* @brief Number of all Descriptor Entries
* @note Length: byte
*/
PCMOUT_DescriptorEntries = (int)NABM_PCMOutBox + (int)NABMBOFF_DescriptorEntries,
/**
* @brief Status of transferring Data
* @note Length: word
*/
PCMOUT_Status = (int)NABM_PCMOutBox + (int)NABMBOFF_Status,
/**
* @brief Number of transferred Samples in Actual Processed Entry
* @note Length: word
*/
PCMOUT_TransferredSamples = (int)NABM_PCMOutBox + (int)NABMBOFF_TransferredSamples,
/**
* @brief Number of next processed Buffer Entry
* @note Length: byte
*/
PCMOUT_NextProcessedBufferEntry = (int)NABM_PCMOutBox + (int)NABMBOFF_NextProcessedBufferEntry,
/**
* @brief Transfer Control
* @note Length: byte
*/
PCMOUT_TransferControl = (int)NABM_PCMOutBox + (int)NABMBOFF_TransferControl,
};
enum TransferControlRegisters
{
/**
* @brief DMA controller control
* 0 = Pause transfer
* 1 = Transfer sound data
*/
TC_DMAControllerControl = 0x01,
/**
* @brief Reset
* 0 = Remove reset condition
* 1 = Reset this NABM register box, this bit is cleared by card when is reset complete
*/
TC_TransferReset = 0x02,
/**
* @brief Last Buffer Entry Interrupt enable
* 0 = Disable interrupt
* 1 = Enable interrupt
*/
TC_LastBufferEntryInterruptEnable = 0x04,
/**
* @brief IOC Interrupt enable
* 0 = Disable interrupt
* 1 = Enable interrupt
*/
TC_IOCInterruptEnable = 0x08,
/**
* @brief Fifo ERROR Interrupt enable
* 0 = Disable interrupt
* 1 = Enable interrupt
*/
TC_FifoERRORInterruptEnable = 0x10,
};
enum GlobalControlRegisters
{
/**
* @brief Global Interrupt Enable
* 0 = Disable Interrupts
* 1 = Enable Interrupts
*/
GC_GlobalInterruptEnable = 0x01,
/**
* @brief Cold reset
* 0 = Device is in reset and can not be used
* 1 = Resume to operational state
*/
GC_ColdReset = 0x02,
/**
* @brief Warm reset
*/
GC_WarmReset = 0x04,
/**
* @brief Shut down
* 0 = Device is powered
* 1 = Shut down
*/
GC_ShutDown = 0x08,
/**
* @brief Channels for PCM Output
* 00 = 2 channels
* 01 = 4 channels
* 10 = 6 channels
* 11 = Reserved
*/
GC_ChannelsForPCMOutput = 0x30,
/**
* @brief PCM Output mode
* 00 = 16 bit samples
* 01 = 20 bit samples
*/
GC_PCMOutputMode = 0xC0,
};
struct BufferDescriptorList
{
/**
* @brief Physical Address to sound data in memory
* @note Length: dword
*/
uint32_t Address;
/**
* @brief Number of samples in this buffer
* @note Length: word
*/
uint16_t SampleCount;
/**
* @brief Flags
* @note Length: word
*
* Bit 15 = Interrupt fired when data from this entry is transferred
* Bit 14 = Last entry of buffer, stop playing
* Other bits = Reserved
*/
uint16_t Flags;
} __attribute__((packed));
struct BARData
{
uint8_t Type;
uint16_t MixerAddress;
uint64_t BusMasterAddress;
};
int DriverEntry(void *);
int CallbackHandler(KernelCallback *);
int InterruptCallback(CPURegisters *);
}
#endif // !__FENNIX_KERNEL_AC97_H__

View File

@ -0,0 +1,278 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "drv.hpp"
#include "AHCI/ahci.hpp"
#include "VMware/mouse.hpp"
#include "PersonalSystem2/mouse.hpp"
#include "ATA/ata.hpp"
#include "AudioCodec97/ac97.hpp"
#include "Realtek/rtl8139.hpp"
#include "AdvancedMicroDevices/pcnet.hpp"
#include "Intel/gigabit.hpp"
#include <pci.hpp>
#include <vector>
#include "../Core/Driver/api.hpp"
#include "../kernel.h"
#include "../DAPI.hpp"
#include "../Fex.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
FexExtended AHCIExtendedHeader = {
.Driver = {
.Name = "Advanced Host Controller Interface",
.Type = FexDriverType_Storage,
.Callback = AdvancedHostControllerInterface::CallbackHandler,
.InterruptCallback = AdvancedHostControllerInterface::InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x8086, 0x15AD},
.DeviceID = {0x2922, 0x2829, 0x07E0},
.Class = 0x1,
.SubClass = 0x6,
.ProgIF = 0x1,
}}}};
FexExtended VMwareVirtualMouseExtendedHeader = {
.Driver = {
.Name = "VMware Virtual Mouse",
.Type = FexDriverType_Input,
.TypeFlags = FexDriverInputTypes_Mouse,
.OverrideOnConflict = true,
.Callback = VMwareMouse::CallbackHandler,
.InterruptCallback = VMwareMouse::InterruptCallback,
.Bind = {
.Type = BIND_INTERRUPT,
.Interrupt = {
.Vector = {12}, // IRQ12
}}}};
FexExtended PS2MouseExtendedHeader = {
.Driver = {
.Name = "PS/2 Mouse",
.Type = FexDriverType_Input,
.TypeFlags = FexDriverInputTypes_Mouse,
.Callback = PS2Mouse::CallbackHandler,
.InterruptCallback = PS2Mouse::InterruptCallback,
.Bind = {
.Type = BIND_INTERRUPT,
.Interrupt = {
.Vector = {12}, // IRQ12
}}}};
FexExtended ATAExtendedHeader = {
.Driver = {
.Name = "Advanced Technology Attachment",
.Type = FexDriverType_Storage,
.Callback = AdvancedTechnologyAttachment::CallbackHandler,
.InterruptCallback = AdvancedTechnologyAttachment::InterruptCallback,
.Bind = {
.Type = BIND_INTERRUPT,
.Interrupt = {
.Vector = {14, 15}, // IRQ14, IRQ15
}}}};
FexExtended AC97ExtendedHeader = {
.Driver = {
.Name = "Audio Codec '97 Driver",
.Type = FexDriverType_Audio,
.TypeFlags = FexDriverInputTypes_None,
.OverrideOnConflict = false,
.Callback = AudioCodec97::CallbackHandler,
.InterruptCallback = AudioCodec97::InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x8086},
.DeviceID = {0x2415},
.Class = 0x4,
.SubClass = 0x3,
.ProgIF = 0x0,
}}}};
FexExtended RTL8139ExtendedHeader = {
.Driver = {
.Name = "Realtek RTL8139",
.Type = FexDriverType_Network,
.Callback = RTL8139::CallbackHandler,
.InterruptCallback = RTL8139::InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x10EC},
.DeviceID = {0x8139},
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
FexExtended AMDPCNETExtendedHeader = {
.Driver = {
.Name = "Advanced Micro Devices PCNET",
.Type = FexDriverType_Network,
.Callback = PCNET::CallbackHandler,
.InterruptCallback = PCNET::InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x1022},
.DeviceID = {0x2000},
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
FexExtended IntelGigabitExtendedHeader = {
.Driver = {
.Name = "Intel Gigabit Ethernet Controller",
.Type = FexDriverType_Network,
.Callback = Gigabit::CallbackHandler,
.InterruptCallback = Gigabit::InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x8086},
.DeviceID = {0x100E, 0x100F, 0x10D3, 0x10EA, 0x153A},
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
#pragma GCC diagnostic pop
std::vector<PCI::PCIDeviceHeader *> FindPCI(uint16_t VendorID[16], uint16_t DeviceID[16])
{
for (uint16_t Vidx = 0; Vidx < 16; Vidx++)
{
for (uint16_t Didx = 0; Didx < 16; Didx++)
{
if (VendorID[Vidx] == 0 || DeviceID[Didx] == 0)
break;
std::vector<PCI::PCIDeviceHeader *> devices = PCIManager->FindPCIDevice(VendorID[Vidx], DeviceID[Didx]);
if (devices.size() == 0)
continue;
return devices;
}
}
warn("No PCI device found");
return std::vector<PCI::PCIDeviceHeader *>();
}
bool StartAHCI()
{
Driver::BuiltInDriverInfo BIDI = {
.EntryPoint = AdvancedHostControllerInterface::DriverEntry,
.ExtendedHeader = &AHCIExtendedHeader};
if (DriverManager->DriverLoadBindPCI((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
return true;
return false;
}
bool StartVMwareMouse()
{
Driver::BuiltInDriverInfo BIDI = {
.EntryPoint = VMwareMouse::DriverEntry,
.ExtendedHeader = &VMwareVirtualMouseExtendedHeader};
if (DriverManager->DriverLoadBindInterrupt((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
return true;
return false;
}
bool StartPS2Mouse()
{
Driver::BuiltInDriverInfo BIDI = {
.EntryPoint = PS2Mouse::DriverEntry,
.ExtendedHeader = &PS2MouseExtendedHeader};
if (DriverManager->DriverLoadBindInterrupt((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
return true;
return false;
}
bool StartATA()
{
Driver::BuiltInDriverInfo BIDI = {
.EntryPoint = AdvancedTechnologyAttachment::DriverEntry,
.ExtendedHeader = &ATAExtendedHeader};
if (DriverManager->DriverLoadBindInterrupt((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
return true;
return false;
}
bool StartAC97()
{
Driver::BuiltInDriverInfo BIDI = {
.EntryPoint = AudioCodec97::DriverEntry,
.ExtendedHeader = &AC97ExtendedHeader};
if (DriverManager->DriverLoadBindPCI((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
return true;
return false;
}
bool StartRTL8139()
{
Driver::BuiltInDriverInfo BIDI = {
.EntryPoint = RTL8139::DriverEntry,
.ExtendedHeader = &RTL8139ExtendedHeader};
if (DriverManager->DriverLoadBindPCI((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
return true;
return false;
}
bool StartPCNET()
{
Driver::BuiltInDriverInfo BIDI = {
.EntryPoint = PCNET::DriverEntry,
.ExtendedHeader = &AMDPCNETExtendedHeader};
if (DriverManager->DriverLoadBindPCI((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
return true;
return false;
}
bool StartGigabit()
{
Driver::BuiltInDriverInfo BIDI = {
.EntryPoint = Gigabit::DriverEntry,
.ExtendedHeader = &IntelGigabitExtendedHeader};
if (DriverManager->DriverLoadBindPCI((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
return true;
return false;
}

369
Drivers/Intel/Gigabit.cpp Normal file
View File

@ -0,0 +1,369 @@
#include "gigabit.hpp"
#include <net/net.hpp>
#include <debug.h>
#include <pci.hpp>
#include <io.h>
#include "../../DAPI.hpp"
#include "../drv.hpp"
using namespace PCI;
namespace Gigabit
{
KernelAPI KAPI;
PCIDeviceHeader *PCIBaseAddress;
uint32_t CurrentPacket;
BARData BAR;
bool EEPROMAvailable;
uint16_t RXCurrent;
uint16_t TXCurrent;
RXDescriptor *RX[E1000_NUM_RX_DESC];
TXDescriptor *TX[E1000_NUM_TX_DESC];
MediaAccessControl MAC;
InternetProtocol::Version4 IP;
void WriteCMD(uint16_t Address, uint32_t Value)
{
if (BAR.Type == 0)
mmioout32(BAR.MemoryBase + Address, Value);
else
{
outportl(BAR.IOBase, Address);
outportl(BAR.IOBase + 4, Value);
}
}
uint32_t ReadCMD(uint16_t Address)
{
if (BAR.Type == 0)
return mmioin32(BAR.MemoryBase + Address);
else
{
outportl(BAR.IOBase, Address);
return inportl(BAR.IOBase + 0x4);
}
}
uint32_t ReadEEPROM(uint8_t Address)
{
uint16_t Data = 0;
uint32_t temp = 0;
if (EEPROMAvailable)
{
WriteCMD(REG::EEPROM, (1) | ((uint32_t)(Address) << 8));
while (!((temp = ReadCMD(REG::EEPROM)) & (1 << 4)))
;
}
else
{
WriteCMD(REG::EEPROM, (1) | ((uint32_t)(Address) << 2));
while (!((temp = ReadCMD(REG::EEPROM)) & (1 << 1)))
;
}
Data = (uint16_t)((temp >> 16) & 0xFFFF);
return Data;
}
MediaAccessControl GetMAC()
{
MediaAccessControl mac;
if (EEPROMAvailable)
{
uint32_t temp;
temp = ReadEEPROM(0);
mac.Address[0] = temp & 0xff;
mac.Address[1] = (uint8_t)(temp >> 8);
temp = ReadEEPROM(1);
mac.Address[2] = temp & 0xff;
mac.Address[3] = (uint8_t)(temp >> 8);
temp = ReadEEPROM(2);
mac.Address[4] = temp & 0xff;
mac.Address[5] = (uint8_t)(temp >> 8);
}
else
{
uint8_t *BaseMac8 = (uint8_t *)(BAR.MemoryBase + 0x5400);
uint32_t *BaseMac32 = (uint32_t *)(BAR.MemoryBase + 0x5400);
if (BaseMac32[0] != 0)
for (int i = 0; i < 6; i++)
mac.Address[i] = BaseMac8[i];
else
{
error("No MAC address found.");
return MediaAccessControl();
}
}
return mac;
}
void InitializeRX()
{
debug("Initializing RX...");
uintptr_t Ptr = (uintptr_t)KAPI.Memory.RequestPage((((sizeof(RXDescriptor) * E1000_NUM_RX_DESC + 16)) / KAPI.Memory.PageSize) + 1);
for (int i = 0; i < E1000_NUM_RX_DESC; i++)
{
RX[i] = (RXDescriptor *)(Ptr + i * 16);
RX[i]->Address = (uint64_t)(uintptr_t)KAPI.Memory.RequestPage(((8192 + 16) / KAPI.Memory.PageSize) + 1);
RX[i]->Status = 0;
}
WriteCMD(REG::TXDESCLO, (uint32_t)(Ptr >> 32));
WriteCMD(REG::TXDESCHI, (uint32_t)(Ptr & 0xFFFFFFFF));
WriteCMD(REG::RXDESCLO, (uint32_t)Ptr);
WriteCMD(REG::RXDESCHI, 0);
WriteCMD(REG::RXDESCLEN, E1000_NUM_RX_DESC * 16);
WriteCMD(REG::RXDESCHEAD, 0);
WriteCMD(REG::RXDESCTAIL, E1000_NUM_RX_DESC - 1);
RXCurrent = 0;
WriteCMD(REG::RCTRL, RCTL::EN | RCTL::SBP | RCTL::UPE | RCTL::MPE | RCTL::LBM_NONE | RTCL::RDMTS_HALF | RCTL::BAM | RCTL::SECRC | RCTL::BSIZE_8192);
}
void InitializeTX()
{
debug("Initializing TX...");
uintptr_t Ptr = (uintptr_t)KAPI.Memory.RequestPage(((sizeof(TXDescriptor) * E1000_NUM_RX_DESC + 16) / KAPI.Memory.PageSize) + 1);
for (short i = 0; i < E1000_NUM_TX_DESC; i++)
{
TX[i] = (TXDescriptor *)((uintptr_t)Ptr + i * 16);
TX[i]->Address = 0;
TX[i]->Command = 0;
TX[i]->Status = TSTA::DD;
}
WriteCMD(REG::TXDESCHI, (uint32_t)((uint64_t)Ptr >> 32));
WriteCMD(REG::TXDESCLO, (uint32_t)((uint64_t)Ptr & 0xFFFFFFFF));
WriteCMD(REG::TXDESCLEN, E1000_NUM_TX_DESC * 16);
WriteCMD(REG::TXDESCHEAD, 0);
WriteCMD(REG::TXDESCTAIL, 0);
TXCurrent = 0;
WriteCMD(REG::TCTRL, TCTL::EN_ | TCTL::PSP | (15 << TCTL::CT_SHIFT) | (64 << TCTL::COLD_SHIFT) | TCTL::RTLC);
WriteCMD(REG::TCTRL, 0b0110000000000111111000011111010);
WriteCMD(REG::TIPG, 0x0060200A);
}
int DriverEntry(void *Data)
{
if (!Data)
return INVALID_KERNEL_API;
KAPI = *(KernelAPI *)Data;
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
return OK;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
debug("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
debug("Driver received configuration data.");
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
switch (PCIBaseAddress->DeviceID)
{
case 0x100E:
{
trace("Found Intel 82540EM Gigabit Ethernet Controller.");
PCIBaseAddress->Command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
uint32_t PCIBAR0 = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
uint32_t PCIBAR1 = ((PCIHeader0 *)PCIBaseAddress)->BAR1;
BAR.Type = PCIBAR0 & 1;
BAR.IOBase = (uint16_t)(PCIBAR1 & (~3));
BAR.MemoryBase = PCIBAR0 & (~15);
// Detect EEPROM
WriteCMD(REG::EEPROM, 0x1);
for (int i = 0; i < 1000 && !EEPROMAvailable; i++)
if (ReadCMD(REG::EEPROM) & 0x10)
EEPROMAvailable = true;
else
EEPROMAvailable = false;
// Get MAC address
if (!GetMAC().Valid())
return NOT_AVAILABLE;
else
debug("MAC address found.");
MAC = GetMAC();
// Start link
uint32_t cmdret = ReadCMD(REG::CTRL);
WriteCMD(REG::CTRL, cmdret | ECTRL::SLU);
for (int i = 0; i < 0x80; i++)
WriteCMD((uint16_t)(0x5200 + i * 4), 0);
WriteCMD(REG::IMASK, 0x1F6DC);
WriteCMD(REG::IMASK, 0xFF & ~4);
ReadCMD(0xC0);
InitializeRX();
InitializeTX();
return OK;
}
case 0x100F:
{
trace("Found Intel 82545EM Gigabit Ethernet Controller.");
PCIBaseAddress->Command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
uint32_t PCIBAR0 = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
uint32_t PCIBAR1 = ((PCIHeader0 *)PCIBaseAddress)->BAR1;
BAR.Type = PCIBAR0 & 1;
BAR.IOBase = (uint16_t)(PCIBAR1 & (~3));
BAR.MemoryBase = PCIBAR0 & (~15);
// Detect EEPROM
WriteCMD(REG::EEPROM, 0x1);
for (int i = 0; i < 1000 && !EEPROMAvailable; i++)
if (ReadCMD(REG::EEPROM) & 0x10)
EEPROMAvailable = true;
else
EEPROMAvailable = false;
// Get MAC address
if (!GetMAC().Valid())
return NOT_AVAILABLE;
else
debug("MAC address found.");
MAC = GetMAC();
return NOT_IMPLEMENTED;
}
case 0x10D3:
{
trace("Found Intel 82574L Gigabit Ethernet Controller.");
PCIBaseAddress->Command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
uint32_t PCIBAR0 = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
uint32_t PCIBAR1 = ((PCIHeader0 *)PCIBaseAddress)->BAR1;
BAR.Type = PCIBAR0 & 1;
BAR.IOBase = (uint16_t)(PCIBAR1 & (~3));
BAR.MemoryBase = PCIBAR0 & (~15);
// Detect EEPROM
WriteCMD(REG::EEPROM, 0x1);
for (int i = 0; i < 1000 && !EEPROMAvailable; i++)
if (ReadCMD(REG::EEPROM) & 0x10)
EEPROMAvailable = true;
else
EEPROMAvailable = false;
// Get MAC address
if (!GetMAC().Valid())
return NOT_AVAILABLE;
else
debug("MAC address found.");
MAC = GetMAC();
return NOT_IMPLEMENTED;
}
case 0x10EA:
{
fixme("Found Intel I217-LM Gigabit Ethernet Controller.");
return NOT_IMPLEMENTED;
}
case 0x153A:
{
fixme("Found Intel 82577LM Gigabit Ethernet Controller.");
return NOT_IMPLEMENTED;
}
default:
{
error("Unsupported Intel Ethernet Controller.");
return DEVICE_NOT_SUPPORTED;
}
}
return ERROR;
}
case FetchReason:
{
memcpy(Data->NetworkCallback.Fetch.Name, (void *)"Intel Gigabit Ethernet Controller", 34);
Data->NetworkCallback.Fetch.MAC = MAC.ToHex();
break;
}
case SendReason:
{
TX[TXCurrent]->Address = (uint64_t)Data->NetworkCallback.Send.Data;
TX[TXCurrent]->Length = (uint16_t)Data->NetworkCallback.Send.Length;
TX[TXCurrent]->Command = CMD::EOP | CMD::IFCS | CMD::RS;
TX[TXCurrent]->Status = 0;
uint16_t OldTXCurrent = TXCurrent;
TXCurrent = (uint16_t)((TXCurrent + 1) % E1000_NUM_TX_DESC);
WriteCMD(REG::TXDESCTAIL, TXCurrent);
while (!(TX[OldTXCurrent]->Status & 0xFF))
;
break;
}
case StopReason:
{
// Clearing Enable bit in Receive Control Register
uint32_t cmdret = ReadCMD(REG::RCTRL);
WriteCMD(REG::RCTRL, cmdret & ~RCTL::EN);
// Masking Interrupt Mask, Interrupt Throttling Rate & Interrupt Auto-Mask
WriteCMD(REG::IMASK, 0x00000000);
WriteCMD(REG::ITR, 0x00000000);
WriteCMD(REG::IAM, 0x00000000);
// Clearing SLU bit in Device Control Register
cmdret = ReadCMD(REG::CTRL);
WriteCMD(REG::CTRL, cmdret & ~ECTRL::SLU);
// Clear the Interrupt Cause Read register by reading it
ReadCMD(REG::ICR);
// Powering down the device (?)
WriteCMD(REG::CTRL, PCTRL::POWER_DOWN);
/* TODO: Stop link; further testing required */
debug("Driver stopped.");
break;
}
default:
{
warn("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
WriteCMD(REG::IMASK, 0x1);
uint32_t status = ReadCMD(0xC0);
UNUSED(status);
while ((RX[RXCurrent]->Status & 0x1))
{
uint8_t *Data = (uint8_t *)RX[RXCurrent]->Address;
uint16_t DataLength = RX[RXCurrent]->Length;
KAPI.Command.Network.ReceivePacket(KAPI.Info.DriverUID, Data, DataLength);
RX[RXCurrent]->Status = 0;
uint16_t OldRXCurrent = RXCurrent;
RXCurrent = (uint16_t)((RXCurrent + 1) % E1000_NUM_RX_DESC);
WriteCMD(REG::RXDESCTAIL, OldRXCurrent);
}
return OK;
}
}

177
Drivers/Intel/gigabit.hpp Normal file
View File

@ -0,0 +1,177 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_INTEL_GIGABIT_H__
#define __FENNIX_KERNEL_INTEL_GIGABIT_H__
#include <types.h>
#include "../../DAPI.hpp"
namespace Gigabit
{
#define E1000_NUM_RX_DESC 32
#define E1000_NUM_TX_DESC 8
enum REG
{
CTRL = 0x0000,
STATUS = 0x0008,
ICR = 0x000C,
EEPROM = 0x0014,
CTRL_EXT = 0x0018,
ITR = 0x00C4,
IMASK = 0x00D0,
IAM = 0x00D8,
RCTRL = 0x0100,
RXDESCLO = 0x2800,
RXDESCHI = 0x2804,
RXDESCLEN = 0x2808,
RXDESCHEAD = 0x2810,
RXDESCTAIL = 0x2818,
TCTRL = 0x0400,
TXDESCLO = 0x3800,
TXDESCHI = 0x3804,
TXDESCLEN = 0x3808,
TXDESCHEAD = 0x3810,
TXDESCTAIL = 0x3818,
RDTR = 0x2820,
RXDCTL = 0x3828,
RADV = 0x282C,
RSRPD = 0x2C00,
TIPG = 0x0410
};
enum PCTRL
{
RESERVED = 0b000000, // bits 5:0
SPEED_SELECTION_MSB = 0b010000, // bit 6
UPDATE_COLLISION_TEST = 0b001000, // bit 7
DUPLEX_MODE = 0b000100, // bit 8
RESTART_AUTO_NEGOTIATION = 0b000010, // bit 9
ISOLATE = 0b000001, // bit 10
POWER_DOWN = 0b100000, // bit 11
SPEED_SELECTION_LSB = 0b100000, // bit 13
};
enum ECTRL
{
SLU = 0x40
};
enum RTCL
{
RDMTS_HALF = (0 << 8),
RDMTS_QUARTER = (1 << 8),
RDMTS_EIGHTH = (2 << 8)
};
enum RCTL
{
EN = (1 << 1),
SBP = (1 << 2),
UPE = (1 << 3),
MPE = (1 << 4),
LPE = (1 << 5),
LBM_NONE = (0 << 6),
LBM_PHY = (3 << 6),
MO_36 = (0 << 12),
MO_35 = (1 << 12),
MO_34 = (2 << 12),
MO_32 = (3 << 12),
BAM = (1 << 15),
VFE = (1 << 18),
CFIEN = (1 << 19),
CFI = (1 << 20),
DPF = (1 << 22),
PMCF = (1 << 23),
SECRC = (1 << 26),
BSIZE_256 = (3 << 16),
BSIZE_512 = (2 << 16),
BSIZE_1024 = (1 << 16),
BSIZE_2048 = (0 << 16),
BSIZE_4096 = ((3 << 16) | (1 << 25)),
BSIZE_8192 = ((2 << 16) | (1 << 25)),
BSIZE_16384 = ((1 << 16) | (1 << 25))
};
enum CMD
{
EOP = (1 << 0),
IFCS = (1 << 1),
IC = (1 << 2),
RS = (1 << 3),
RPS = (1 << 4),
VLE = (1 << 6),
IDE = (1 << 7)
};
enum TCTL
{
EN_ = (1 << 1),
PSP = (1 << 3),
CT_SHIFT = 4,
COLD_SHIFT = 12,
SWXOFF = (1 << 22),
RTLC = (1 << 24)
};
enum TSTA
{
DD = (1 << 0),
EC = (1 << 1),
LC = (1 << 2)
};
enum LSTA
{
LSTA_TU = (1 << 3)
};
struct RXDescriptor
{
volatile uint64_t Address;
volatile uint16_t Length;
volatile uint16_t Checksum;
volatile uint8_t Status;
volatile uint8_t Errors;
volatile uint16_t Special;
} __attribute__((packed));
struct TXDescriptor
{
volatile uint64_t Address;
volatile uint16_t Length;
volatile uint8_t cso;
volatile uint8_t Command;
volatile uint8_t Status;
volatile uint8_t css;
volatile uint16_t Special;
} __attribute__((packed));
struct BARData
{
uint8_t Type;
uint16_t IOBase;
uint64_t MemoryBase;
};
int DriverEntry(void *);
int CallbackHandler(KernelCallback *);
int InterruptCallback(CPURegisters *);
}
#endif // !__FENNIX_KERNEL_INTEL_GIGABIT_H__

View File

@ -0,0 +1,234 @@
#include "mouse.hpp"
#include <debug.h>
#include <io.h>
#include "../../DAPI.hpp"
#include "../drv.hpp"
namespace PS2Mouse
{
KernelAPI KAPI;
int MouseX = 0, MouseY = 0, MouseZ = 0;
int MouseLeft = 0, MouseMiddle = 0, MouseRight = 0;
uint8_t Packet[4];
bool PacketReady = false;
uint8_t Cycle = 0;
void WaitRead()
{
uint64_t Timeout = 100000;
while (Timeout--)
if (inb(Ports::STATUS) & State::OUTPUT_FULL)
return;
}
void WaitWrite()
{
uint64_t Timeout = 100000;
while (Timeout--)
if ((inb(Ports::STATUS) & State::INPUT_FULL) == 0)
return;
}
uint8_t Read()
{
WaitRead();
return inb(Ports::DATA);
}
void Write(uint16_t Port, uint8_t Value)
{
WaitWrite();
outb(Port, Value);
}
int DriverEntry(void *Data)
{
if (!Data)
return INVALID_KERNEL_API;
KAPI = *(KernelAPI *)Data;
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
return OK;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
debug("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
outb(COMMAND, 0xA8);
Write(COMMAND, READ_CONFIG);
uint8_t Status = Read();
Status |= 0b10;
Write(COMMAND, WRITE_CONFIG);
Write(DATA, Status);
Write(COMMAND, 0xD4);
Write(DATA, 0xF6);
Read();
Write(COMMAND, 0xD4);
Write(DATA, 0xF4);
Read();
trace("PS/2 mouse configured.");
break;
}
case FetchReason:
{
Data->InputCallback.Mouse.X = MouseX;
Data->InputCallback.Mouse.Y = MouseY;
Data->InputCallback.Mouse.Z = MouseZ;
Data->InputCallback.Mouse.Buttons.Left = MouseLeft;
Data->InputCallback.Mouse.Buttons.Right = MouseRight;
Data->InputCallback.Mouse.Buttons.Middle = MouseMiddle;
break;
}
case StopReason:
{
outb(COMMAND, 0xA8);
Write(COMMAND, READ_CONFIG);
uint8_t Status = Read();
Status &= ~0b10;
Write(COMMAND, WRITE_CONFIG);
Write(DATA, Status);
Write(COMMAND, 0xD4);
Write(DATA, 0xF5);
Read();
debug("Driver stopped.");
break;
}
default:
{
warn("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
uint8_t Data = inb(0x60);
if (__builtin_expect(!!(PacketReady), 0))
{
bool XNegative, YNegative, XOverflow, YOverflow;
if (Packet[0] & PS2XSign)
XNegative = true;
else
XNegative = false;
if (Packet[0] & PS2YSign)
YNegative = true;
else
YNegative = false;
if (Packet[0] & PS2XOverflow)
XOverflow = true;
else
XOverflow = false;
if (Packet[0] & PS2YOverflow)
YOverflow = true;
else
YOverflow = false;
if (!XNegative)
{
MouseX += Packet[1];
if (XOverflow)
MouseX += 255;
}
else
{
Packet[1] = (uint8_t)(256 - Packet[1]);
MouseX -= Packet[1];
if (XOverflow)
MouseX -= 255;
}
if (!YNegative)
{
MouseY -= Packet[2];
if (YOverflow)
MouseY -= 255;
}
else
{
Packet[2] = (uint8_t)(256 - Packet[2]);
MouseY += Packet[2];
if (YOverflow)
MouseY += 255;
}
uint32_t Width = KAPI.Display.GetWidth();
uint32_t Height = KAPI.Display.GetHeight();
if (MouseX < 0)
MouseX = 0;
if ((uint32_t)MouseX > Width - 1)
MouseX = Width - 1;
if (MouseY < 0)
MouseY = 0;
if ((uint32_t)MouseY > Height - 1)
MouseY = Height - 1;
MouseLeft = 0;
MouseMiddle = 0;
MouseRight = 0;
if (Packet[0] & PS2LeftButton)
MouseLeft = 1;
if (Packet[0] & PS2MiddleButton)
MouseMiddle = 1;
if (Packet[0] & PS2RightButton)
MouseRight = 1;
PacketReady = false;
}
switch (Cycle)
{
case 0:
{
if ((Data & 0b00001000) == 0)
break;
Packet[0] = Data;
Cycle++;
break;
}
case 1:
{
Packet[1] = Data;
Cycle++;
break;
}
case 2:
{
Packet[2] = Data;
PacketReady = true;
Cycle = 0;
break;
}
default:
{
warn("Unknown cycle %d", Cycle);
break;
}
}
return OK;
}
}

View File

@ -0,0 +1,59 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_PS2_MOUSE_H__
#define __FENNIX_KERNEL_PS2_MOUSE_H__
#include <types.h>
#include "../../DAPI.hpp"
namespace PS2Mouse
{
#define PS2LeftButton 0b00000001
#define PS2MiddleButton 0b00000100
#define PS2RightButton 0b00000010
#define PS2XSign 0b00010000
#define PS2YSign 0b00100000
#define PS2XOverflow 0b01000000
#define PS2YOverflow 0b10000000
enum Config
{
READ_CONFIG = 0x20,
WRITE_CONFIG = 0x60
};
enum Ports
{
DATA = 0x60,
STATUS = 0x64,
COMMAND = 0x64,
};
enum State
{
OUTPUT_FULL = (1 << 0),
INPUT_FULL = (1 << 1),
MOUSE_BYTE = (1 << 5)
};
int DriverEntry(void *);
int CallbackHandler(KernelCallback *);
int InterruptCallback(CPURegisters *);
}
#endif // !__FENNIX_KERNEL_PS2_MOUSE_H__

190
Drivers/Realtek/RTL8139.cpp Normal file
View File

@ -0,0 +1,190 @@
#include "rtl8139.hpp"
#include <net/net.hpp>
#include <debug.h>
#include <pci.hpp>
#include <io.h>
#include "../../DAPI.hpp"
#include "../drv.hpp"
using namespace PCI;
namespace RTL8139
{
KernelAPI KAPI;
PCIDeviceHeader *PCIBaseAddress;
BARData BAR;
uint8_t *RXBuffer;
int TXCurrent;
uint16_t CurrentPacket;
MediaAccessControl MAC;
InternetProtocol::Version4 IP;
uint8_t TSAD[4] = {0x20, 0x24, 0x28, 0x2C};
uint8_t TSD[4] = {0x10, 0x14, 0x18, 0x1C};
void RTLOB(uint16_t Address, uint8_t Value)
{
if (BAR.Type == 0)
mmoutb(reinterpret_cast<void *>(BAR.MemoryBase + Address), Value);
else
outportb(BAR.IOBase + Address, Value);
}
void RTLOW(uint16_t Address, uint16_t Value)
{
if (BAR.Type == 0)
mmoutw(reinterpret_cast<void *>(BAR.MemoryBase + Address), Value);
else
outportw(BAR.IOBase + Address, Value);
}
void RTLOL(uint16_t Address, uint32_t Value)
{
if (BAR.Type == 0)
mmoutl(reinterpret_cast<void *>(BAR.MemoryBase + Address), Value);
else
outportl(BAR.IOBase + Address, Value);
}
uint8_t RTLIB(uint16_t Address)
{
if (BAR.Type == 0)
return mminb(reinterpret_cast<void *>(BAR.MemoryBase + Address));
else
return inportb(BAR.IOBase + Address);
}
uint16_t RTLIW(uint16_t Address)
{
if (BAR.Type == 0)
return mminw(reinterpret_cast<void *>(BAR.MemoryBase + Address));
else
return inportw(BAR.IOBase + Address);
}
uint32_t RTLIL(uint16_t Address)
{
if (BAR.Type == 0)
return mminl(reinterpret_cast<void *>(BAR.MemoryBase + Address));
else
return inportl(BAR.IOBase + Address);
}
MediaAccessControl GetMAC()
{
uint32_t MAC1 = RTLIL(0x0);
uint16_t MAC2 = RTLIW(0x4);
MediaAccessControl mac = {
mac.Address[0] = (uint8_t)MAC1,
mac.Address[1] = (uint8_t)(MAC1 >> 8),
mac.Address[2] = (uint8_t)(MAC1 >> 16),
mac.Address[3] = (uint8_t)(MAC1 >> 24),
mac.Address[4] = (uint8_t)MAC2,
mac.Address[5] = (uint8_t)(MAC2 >> 8)};
return mac;
}
int DriverEntry(void *Data)
{
if (!Data)
return INVALID_KERNEL_API;
KAPI = *(KernelAPI *)Data;
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
return OK;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
debug("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
debug("Driver received configuration data.");
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
if (PCIBaseAddress->VendorID == 0x10EC && PCIBaseAddress->DeviceID == 0x8139)
{
trace("Found RTL-8139.");
PCIBaseAddress->Command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
uint32_t PCIBAR0 = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
uint32_t PCIBAR1 = ((PCIHeader0 *)PCIBaseAddress)->BAR1;
BAR.Type = PCIBAR1 & 1;
BAR.IOBase = (uint16_t)(PCIBAR0 & (~3));
BAR.MemoryBase = PCIBAR1 & (~15);
RXBuffer = (uint8_t *)KAPI.Memory.RequestPage(2);
RTLOB(0x52, 0x0);
RTLOB(0x37, (1 << 4));
while ((RTLIB(0x37) & (1 << 4)))
;
RTLOL(0x30, static_cast<uint32_t>(reinterpret_cast<uint64_t>(RXBuffer)));
RTLOW(0x3C, ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) |
(1 << 4) | (1 << 5) | (1 << 6) | (1 << 13) |
(1 << 14) | (1 << 15)));
RTLOL(0x44, ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 7)));
RTLOB(0x37, 0x0C);
MAC = GetMAC();
}
else
return DEVICE_NOT_SUPPORTED;
break;
}
case FetchReason:
{
memcpy(Data->NetworkCallback.Fetch.Name, (void *)"RTL-8139", 9);
Data->NetworkCallback.Fetch.MAC = MAC.ToHex();
break;
}
case SendReason:
{
RTLOL(TSAD[TXCurrent], static_cast<uint32_t>(reinterpret_cast<uint64_t>(Data->NetworkCallback.Send.Data)));
RTLOL(TSD[TXCurrent++], (uint32_t)Data->NetworkCallback.Send.Length);
if (TXCurrent > 3)
TXCurrent = 0;
break;
}
case StopReason:
{
// TODO: Stop the driver.
debug("Driver stopped.");
break;
}
default:
{
warn("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
uint16_t Status = RTLIW(0x3E);
UNUSED(Status);
uint16_t *Data = (uint16_t *)(RXBuffer + CurrentPacket);
uint16_t DataLength = *(Data + 1);
Data = Data + 2;
KAPI.Command.Network.ReceivePacket(KAPI.Info.DriverUID, (uint8_t *)Data, DataLength);
CurrentPacket = (uint16_t)((CurrentPacket + DataLength + 4 + 3) & (~3));
if (CurrentPacket > 8192)
CurrentPacket -= 8192;
RTLOW(0x38, CurrentPacket - 0x10);
RTLOW(0x3E, (1 << 0) | (1 << 2));
return OK;
}
}

View File

@ -0,0 +1,38 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_RTL8139_H__
#define __FENNIX_KERNEL_RTL8139_H__
#include <types.h>
#include "../../DAPI.hpp"
namespace RTL8139
{
struct BARData
{
uint8_t Type;
uint16_t IOBase;
uint64_t MemoryBase;
};
int DriverEntry(void *);
int CallbackHandler(KernelCallback *);
int InterruptCallback(CPURegisters *);
}
#endif // !__FENNIX_KERNEL_RTL8139_H__

225
Drivers/VMware/Mouse.cpp Normal file
View File

@ -0,0 +1,225 @@
#include "mouse.hpp"
#include <debug.h>
#include <io.h>
#include "../../DAPI.hpp"
#include "../drv.hpp"
/* https://wiki.osdev.org/VMware_tools */
namespace VMwareMouse
{
KernelAPI KAPI;
void CommandSend(VMwareCommand *cmd)
{
cmd->magic = VMWARE_MAGIC;
cmd->port = VMWARE_PORT;
asm volatile("in %%dx, %0"
: "+a"(cmd->ax), "+b"(cmd->bx), "+c"(cmd->cx), "+d"(cmd->dx), "+S"(cmd->si), "+D"(cmd->di));
}
bool IsVMwareBackdoorAvailable(void)
{
VMwareCommand cmd;
cmd.bx = ~VMWARE_MAGIC;
cmd.command = CMD_GETVERSION;
CommandSend(&cmd);
if (cmd.bx != VMWARE_MAGIC || cmd.ax == 0xFFFFFFFF)
return false;
return true;
}
int DriverEntry(void *Data)
{
if (!Data)
return INVALID_KERNEL_API;
KAPI = *(KernelAPI *)Data;
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
if (!IsVMwareBackdoorAvailable())
return SYSTEM_NOT_SUPPORTED;
return OK;
}
void Absolute(void)
{
VMwareCommand cmd;
/* Enable */
cmd.bx = ABSPOINTER_ENABLE;
cmd.command = CMD_ABSPOINTER_COMMAND;
CommandSend(&cmd);
/* Status */
cmd.bx = 0;
cmd.command = CMD_ABSPOINTER_STATUS;
CommandSend(&cmd);
/* Read data (1) */
cmd.bx = 1;
cmd.command = CMD_ABSPOINTER_DATA;
CommandSend(&cmd);
/* Enable absolute */
cmd.bx = ABSPOINTER_ABSOLUTE;
cmd.command = CMD_ABSPOINTER_COMMAND;
CommandSend(&cmd);
}
void Relative(void)
{
VMwareCommand cmd;
cmd.bx = ABSPOINTER_RELATIVE;
cmd.command = CMD_ABSPOINTER_COMMAND;
CommandSend(&cmd);
}
enum Config
{
READ_CONFIG = 0x20,
WRITE_CONFIG = 0x60
};
enum Ports
{
DATA = 0x60,
STATUS = 0x64,
COMMAND = 0x64,
};
enum State
{
OUTPUT_FULL = (1 << 0),
INPUT_FULL = (1 << 1),
MOUSE_BYTE = (1 << 5)
};
void WaitRead()
{
uint64_t Timeout = 100000;
while (Timeout--)
if (inb(Ports::STATUS) & State::OUTPUT_FULL)
return;
}
void WaitWrite()
{
uint64_t Timeout = 100000;
while (Timeout--)
if ((inb(Ports::STATUS) & State::INPUT_FULL) == 0)
return;
}
void Write(uint16_t Port, uint8_t Value)
{
WaitWrite();
outb(Port, Value);
}
uint8_t Read()
{
WaitRead();
return inb(Ports::DATA);
}
int MouseX = 0, MouseY = 0, MouseZ = 0;
int MouseButton = 0;
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
debug("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
outb(COMMAND, 0xA8);
Write(COMMAND, READ_CONFIG);
uint8_t Status = Read();
Status |= 0b10;
Write(COMMAND, WRITE_CONFIG);
Write(DATA, Status);
Write(COMMAND, 0xD4);
Write(DATA, 0xF6);
Read();
Write(COMMAND, 0xD4);
Write(DATA, 0xF4);
Read();
Absolute();
trace("VMware mouse configured.");
break;
}
case FetchReason:
{
Data->InputCallback.Mouse.X = (MouseX * KAPI.Display.GetWidth()) / 0xFFFF;
Data->InputCallback.Mouse.Y = (MouseY * KAPI.Display.GetHeight()) / 0xFFFF;
Data->InputCallback.Mouse.Z = MouseZ;
Data->InputCallback.Mouse.Buttons.Left = MouseButton & 0x20;
Data->InputCallback.Mouse.Buttons.Right = MouseButton & 0x10;
Data->InputCallback.Mouse.Buttons.Middle = MouseButton & 0x08;
break;
}
case StopReason:
{
Relative();
// TODO: UNTESTED!!!
outb(COMMAND, 0xA8);
Write(COMMAND, READ_CONFIG);
uint8_t Status = Read();
Status &= ~0b10;
Write(COMMAND, WRITE_CONFIG);
Write(DATA, Status);
Write(COMMAND, 0xD4);
Write(DATA, 0xF5);
Read();
debug("Driver stopped.");
break;
}
default:
{
warn("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
uint8_t Data = inb(0x60);
(void)Data;
VMwareCommand cmd;
cmd.bx = 0;
cmd.command = CMD_ABSPOINTER_STATUS;
CommandSend(&cmd);
if (cmd.ax == 0xFFFF0000)
{
warn("VMware mouse is not connected?");
Relative();
Absolute();
return ERROR;
}
if ((cmd.ax & 0xFFFF) < 4)
return ERROR;
cmd.bx = 4;
cmd.command = CMD_ABSPOINTER_DATA;
CommandSend(&cmd);
int flags = (cmd.ax & 0xFFFF0000) >> 16; /* Not important */
(void)flags;
MouseButton = (cmd.ax & 0xFFFF); /* 0x10 = Right, 0x20 = Left, 0x08 = Middle */
MouseX = cmd.bx; /* Both X and Y are scaled from 0 to 0xFFFF */
MouseY = cmd.cx; /* You should map these somewhere to the actual resolution. */
MouseZ = (int8_t)cmd.dx; /* Z is a single signed byte indicating scroll direction. */
return OK;
}
}

69
Drivers/VMware/mouse.hpp Normal file
View File

@ -0,0 +1,69 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_VMWARE_MOUSE_H__
#define __FENNIX_KERNEL_VMWARE_MOUSE_H__
#include <types.h>
#include "../../DAPI.hpp"
namespace VMwareMouse
{
#define VMWARE_MAGIC 0x564D5868 /* hXMV */
#define VMWARE_PORT 0x5658
#define CMD_GETVERSION 0xA
#define CMD_ABSPOINTER_DATA 0x27
#define CMD_ABSPOINTER_STATUS 0x28
#define CMD_ABSPOINTER_COMMAND 0x29
#define ABSPOINTER_ENABLE 0x45414552 /* Q E A E */
#define ABSPOINTER_RELATIVE 0xF5
#define ABSPOINTER_ABSOLUTE 0x53424152 /* R A B S */
typedef struct
{
union
{
uint32_t ax;
uint32_t magic;
};
union
{
uint32_t bx;
size_t size;
};
union
{
uint32_t cx;
uint16_t command;
};
union
{
uint32_t dx;
uint16_t port;
};
uint32_t si;
uint32_t di;
} VMwareCommand;
int DriverEntry(void *);
int CallbackHandler(KernelCallback *);
int InterruptCallback(CPURegisters *);
}
#endif // !__FENNIX_KERNEL_VMWARE_MOUSE_H__

32
Drivers/drv.hpp Normal file
View File

@ -0,0 +1,32 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_DRV_H__
#define __FENNIX_KERNEL_DRV_H__
#include <types.h>
bool StartAHCI();
bool StartVMwareMouse();
bool StartPS2Mouse();
bool StartATA();
bool StartAC97();
bool StartRTL8139();
bool StartPCNET();
bool StartGigabit();
#endif // !__FENNIX_KERNEL_DRV_H__

136
Fex.hpp
View File

@ -48,48 +48,48 @@
enum FexFormatType
{
FexFormatType_Unknown,
FexFormatType_Executable,
FexFormatType_Driver
/* ... */
FexFormatType_Unknown,
FexFormatType_Executable,
FexFormatType_Driver
/* ... */
};
enum FexOSType
{
FexOSType_Unknown,
FexOSType_Fennix,
FexOSType_Linux
/* ... */
FexOSType_Unknown,
FexOSType_Fennix,
FexOSType_Linux
/* ... */
};
enum FexDriverType
{
FexDriverType_Unknown,
FexDriverType_Generic,
FexDriverType_Display,
FexDriverType_Network,
FexDriverType_Storage,
FexDriverType_FileSystem,
FexDriverType_Input,
FexDriverType_Audio,
FexDriverType_ACPI,
/* ... */
FexDriverType_Unknown,
FexDriverType_Generic,
FexDriverType_Display,
FexDriverType_Network,
FexDriverType_Storage,
FexDriverType_FileSystem,
FexDriverType_Input,
FexDriverType_Audio,
FexDriverType_ACPI,
/* ... */
};
enum FexDriverInputTypes
{
FexDriverInputTypes_None = 0b00000000,
FexDriverInputTypes_Mouse = 0b00000001,
FexDriverInputTypes_Keyboard = 0b00000010,
/* ... */
FexDriverInputTypes_None = 0b00000000,
FexDriverInputTypes_Mouse = 0b00000001,
FexDriverInputTypes_Keyboard = 0b00000010,
/* ... */
};
struct Fex
{
char Magic[4];
enum FexFormatType Type : 4;
enum FexOSType OS : 4;
int (*EntryPoint)(void *);
char Magic[4];
enum FexFormatType Type : 4;
enum FexOSType OS : 4;
int (*EntryPoint)(void *);
} __attribute__((packed));
union KernelCallback;
@ -97,49 +97,49 @@ union CPURegisters;
struct FexExtended
{
struct
{
struct
{
} Executable;
} Executable;
struct
{
char Name[64];
enum FexDriverType Type : 4;
enum FexDriverInputTypes TypeFlags : 4;
char OverrideOnConflict : 1;
int (*Callback)(union KernelCallback *);
int (*InterruptCallback)(union CPURegisters *);
struct
{
char Name[64];
enum FexDriverType Type : 4;
enum FexDriverInputTypes TypeFlags : 4;
char OverrideOnConflict;
int (*Callback)(union KernelCallback *);
int (*InterruptCallback)(union CPURegisters *);
struct DriverBind
{
int Type;
struct
{
unsigned char Vector[16];
} Interrupt;
struct DriverBind
{
int Type;
struct
{
unsigned char Vector[16];
} Interrupt;
struct
{
unsigned int ProcessId[16];
} Process;
struct
{
unsigned int ProcessId[16];
} Process;
struct
{
unsigned short VendorID[16];
unsigned short DeviceID[16];
unsigned short Class;
unsigned short SubClass;
unsigned short ProgIF;
} PCI;
struct
{
unsigned short VendorID[16];
unsigned short DeviceID[16];
unsigned short Class;
unsigned short SubClass;
unsigned short ProgIF;
} PCI;
struct
{
char AttachToMouse;
char AttachToKeyboard;
} Input;
} Bind;
} Driver;
struct
{
char AttachToMouse;
char AttachToKeyboard;
} Input;
} Bind;
} Driver;
} __attribute__((packed));
/**
@ -152,10 +152,10 @@ struct FexExtended
* @note Must include ".header : { *(.header .header.*) }" in linker script
*/
#define HEAD(FormatType, OperatingSystem, Address) \
__attribute__((section(".header"))) struct Fex FexHeader = { \
.Magic = {'F', 'E', 'X', '\0'}, \
.Type = FormatType, \
.OS = OperatingSystem, \
.EntryPoint = Address}
__attribute__((section(".header"))) struct Fex FexHeader = { \
.Magic = {'F', 'E', 'X', '\0'}, \
.Type = FormatType, \
.OS = OperatingSystem, \
.EntryPoint = Address}
#endif // !__FENNIX_FILE_FEX_H__

File diff suppressed because it is too large Load Diff

View File

@ -28,132 +28,132 @@
namespace GraphicalUserInterface
{
void WidgetCollection::OnPaintBackground(Event *e)
{
UNUSED(e);
}
void WidgetCollection::OnPaintBackground(Event *e)
{
UNUSED(e);
}
void WidgetCollection::OnPaintForeground(Event *e)
{
UNUSED(e);
foreach (auto Panel in this->Panels)
{
PutRect(this->Buffer, Panel->rect, Panel->Color);
}
void WidgetCollection::OnPaintForeground(Event *e)
{
UNUSED(e);
foreach (auto Panel in this->Panels)
{
PutRect(this->Buffer, Panel->rect, Panel->Color);
}
foreach (auto Label in this->Labels)
{
Label->CharCursorX = Label->rect.Left;
Label->CharCursorY = Label->rect.Top;
for (uint64_t i = 0; i < strlen(Label->Text); i++)
PaintChar(this->CurrentFont, this->Buffer, Label->Text[i], 0xFFFFFF, &Label->CharCursorX, &Label->CharCursorY);
}
foreach (auto Label in this->Labels)
{
Label->CharCursorX = Label->rect.Left;
Label->CharCursorY = Label->rect.Top;
for (uint64_t i = 0; i < strlen(Label->Text); i++)
PaintChar(this->CurrentFont, this->Buffer, Label->Text[i], 0xFFFFFF, &Label->CharCursorX, &Label->CharCursorY);
}
foreach (auto Button in this->Buttons)
{
if (Button->Pressed)
PutRect(this->Buffer, Button->rect, Button->PressedColor);
else if (Button->Hover)
PutRect(this->Buffer, Button->rect, Button->HoverColor);
else
PutRect(this->Buffer, Button->rect, Button->Color);
Button->CharCursorX = Button->rect.Left + (((Button->rect.Width / 2) - (this->CurrentFont->GetInfo().Width * strlen(Button->Text) / 2)));
Button->CharCursorY = Button->rect.Top + (((Button->rect.Height / 2) - (this->CurrentFont->GetInfo().Height / 2)));
for (uint64_t i = 0; i < strlen(Button->Text); i++)
PaintChar(this->CurrentFont, this->Buffer, Button->Text[i], 0xFFFFFF, &Button->CharCursorX, &Button->CharCursorY);
}
}
foreach (auto Button in this->Buttons)
{
if (Button->Pressed)
PutRect(this->Buffer, Button->rect, Button->PressedColor);
else if (Button->Hover)
PutRect(this->Buffer, Button->rect, Button->HoverColor);
else
PutRect(this->Buffer, Button->rect, Button->Color);
Button->CharCursorX = Button->rect.Left + (((Button->rect.Width / 2) - (this->CurrentFont->GetInfo().Width * strlen(Button->Text) / 2)));
Button->CharCursorY = Button->rect.Top + (((Button->rect.Height / 2) - (this->CurrentFont->GetInfo().Height / 2)));
for (uint64_t i = 0; i < strlen(Button->Text); i++)
PaintChar(this->CurrentFont, this->Buffer, Button->Text[i], 0xFFFFFF, &Button->CharCursorX, &Button->CharCursorY);
}
}
void WidgetCollection::OnPaint(Event *e)
{
static int64_t LastWidth = 0;
static int64_t LastHeight = 0;
void WidgetCollection::OnPaint(Event *e)
{
static size_t LastWidth = 0;
static size_t LastHeight = 0;
if (LastWidth != ((Window *)this->ParentWindow)->GetPosition().Width ||
LastHeight != ((Window *)this->ParentWindow)->GetPosition().Height)
{
LastWidth = ((Window *)this->ParentWindow)->GetPosition().Width;
LastHeight = ((Window *)this->ParentWindow)->GetPosition().Height;
if (LastWidth != ((Window *)this->ParentWindow)->GetPosition().Width ||
LastHeight != ((Window *)this->ParentWindow)->GetPosition().Height)
{
LastWidth = ((Window *)this->ParentWindow)->GetPosition().Width;
LastHeight = ((Window *)this->ParentWindow)->GetPosition().Height;
this->mem->FreePages(this->Buffer->Data, TO_PAGES(this->Buffer->Size + 1));
this->Buffer->Data = nullptr;
delete this->Buffer, this->Buffer = nullptr;
this->mem->FreePages(this->Buffer->Data, TO_PAGES(this->Buffer->Size + 1));
this->Buffer->Data = nullptr;
delete this->Buffer, this->Buffer = nullptr;
this->Buffer = new ScreenBitmap;
this->Buffer->Width = LastWidth;
this->Buffer->Height = LastHeight;
this->Buffer->BitsPerPixel = Display->GetBitsPerPixel();
this->Buffer->Pitch = Display->GetPitch();
this->Buffer->Size = this->Buffer->Pitch * (size_t)LastHeight;
this->Buffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->Buffer->Size + 1));
memset(this->Buffer->Data, 0, this->Buffer->Size);
this->Buffer = new ScreenBitmap;
this->Buffer->Width = LastWidth;
this->Buffer->Height = LastHeight;
this->Buffer->BitsPerPixel = Display->GetBitsPerPixel();
this->Buffer->Pitch = Display->GetPitch();
this->Buffer->Size = this->Buffer->Pitch * (size_t)LastHeight;
this->Buffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->Buffer->Size + 1));
memset(this->Buffer->Data, 0, this->Buffer->Size);
this->NeedRedraw = true;
}
this->NeedRedraw = true;
}
if (this->NeedRedraw)
{
memset(this->Buffer->Data, 0, this->Buffer->Size);
this->OnPaintBackground(e);
this->OnPaintForeground(e);
this->NeedRedraw = false;
}
DrawOverBitmap(((Window *)this->ParentWindow)->GetBuffer(), this->Buffer, 0, 0);
}
if (this->NeedRedraw)
{
memset(this->Buffer->Data, 0, this->Buffer->Size);
this->OnPaintBackground(e);
this->OnPaintForeground(e);
this->NeedRedraw = false;
}
DrawOverBitmap(((Window *)this->ParentWindow)->GetBuffer(), this->Buffer, 0, 0);
}
void WidgetCollection::OnMouseDown(Event *e)
{
foreach (auto Button in this->Buttons)
{
if (Button->rect.Contains(e->MouseDown.X, e->MouseDown.Y))
{
if (e->MouseDown.Left)
{
debug("Button Hold");
Button->Pressed = true;
this->NeedRedraw = true;
}
}
}
}
void WidgetCollection::OnMouseDown(Event *e)
{
foreach (auto Button in this->Buttons)
{
if (Button->rect.Contains(e->MouseDown.X, e->MouseDown.Y))
{
if (e->MouseDown.Left)
{
debug("Button Hold");
Button->Pressed = true;
this->NeedRedraw = true;
}
}
}
}
void WidgetCollection::OnMouseUp(Event *e)
{
foreach (auto Button in this->Buttons)
{
if (Button->rect.Contains(e->MouseUp.X, e->MouseUp.Y))
{
if (e->MouseUp.Left)
{
debug("Button Release");
if (Button->Pressed)
{
debug("Button Clicked");
if (Button->OnClick != (uintptr_t) nullptr)
((void (*)(void))Button->OnClick)();
void WidgetCollection::OnMouseUp(Event *e)
{
foreach (auto Button in this->Buttons)
{
if (Button->rect.Contains(e->MouseUp.X, e->MouseUp.Y))
{
if (e->MouseUp.Left)
{
debug("Button Release");
if (Button->Pressed)
{
debug("Button Clicked");
if (Button->OnClick != (uintptr_t) nullptr)
((void (*)(void))Button->OnClick)();
Button->Pressed = false;
this->NeedRedraw = true;
}
}
}
}
}
Button->Pressed = false;
this->NeedRedraw = true;
}
}
}
}
}
void WidgetCollection::OnMouseMove(Event *e)
{
foreach (auto Button in this->Buttons)
{
if (Button->rect.Contains(e->MouseMove.X, e->MouseMove.Y))
{
Button->Hover = true;
this->NeedRedraw = true;
}
else
{
Button->Hover = false;
this->NeedRedraw = true;
}
}
}
void WidgetCollection::OnMouseMove(Event *e)
{
foreach (auto Button in this->Buttons)
{
if (Button->rect.Contains(e->MouseMove.X, e->MouseMove.Y))
{
Button->Hover = true;
this->NeedRedraw = true;
}
else
{
Button->Hover = false;
this->NeedRedraw = true;
}
}
}
}

View File

@ -28,110 +28,110 @@
namespace GraphicalUserInterface
{
void Window::OnResize(Event *e)
{
// TODO: Optimize this
this->mem->FreePages(this->Buffer->Data, TO_PAGES(this->Buffer->Size + 1));
this->Buffer->Data = nullptr;
delete this->Buffer, this->Buffer = nullptr;
void Window::OnResize(Event *e)
{
// TODO: Optimize this
this->mem->FreePages(this->Buffer->Data, TO_PAGES(this->Buffer->Size + 1));
this->Buffer->Data = nullptr;
delete this->Buffer, this->Buffer = nullptr;
this->Buffer = new ScreenBitmap;
this->Buffer->Width = e->Resize.Width;
this->Buffer->Height = e->Resize.Height;
this->Buffer->BitsPerPixel = Display->GetBitsPerPixel();
this->Buffer->Pitch = Display->GetPitch();
this->Buffer->Size = this->Buffer->Pitch * e->Resize.Height;
this->Buffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->Buffer->Size + 1));
memset(this->Buffer->Data, 0, this->Buffer->Size);
this->OnPaint(e);
}
this->Buffer = new ScreenBitmap;
this->Buffer->Width = e->Resize.Width;
this->Buffer->Height = e->Resize.Height;
this->Buffer->BitsPerPixel = Display->GetBitsPerPixel();
this->Buffer->Pitch = Display->GetPitch();
this->Buffer->Size = this->Buffer->Pitch * e->Resize.Height;
this->Buffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->Buffer->Size + 1));
memset(this->Buffer->Data, 0, this->Buffer->Size);
this->OnPaint(e);
}
void Window::OnMinimize(Event *e)
{
UNUSED(e);
fixme("Window::OnMinimize() not implemented");
}
void Window::OnMinimize(Event *e)
{
UNUSED(e);
fixme("Window::OnMinimize() not implemented");
}
void Window::OnMaximize(Event *e)
{
UNUSED(e);
fixme("Window::OnMaximize() not implemented");
}
void Window::OnMaximize(Event *e)
{
UNUSED(e);
fixme("Window::OnMaximize() not implemented");
}
void Window::OnClose(Event *e)
{
UNUSED(e);
fixme("Window::OnClose() not implemented");
}
void Window::OnClose(Event *e)
{
UNUSED(e);
fixme("Window::OnClose() not implemented");
}
void Window::OnPaintBackground(Event *e)
{
UNUSED(e);
Rect PaintPosition = this->Position;
PaintPosition.Left = 0;
PaintPosition.Top = 0;
PutRect(this->Buffer, PaintPosition, 0x121212);
}
void Window::OnPaintBackground(Event *e)
{
UNUSED(e);
Rect PaintPosition = this->Position;
PaintPosition.Left = 0;
PaintPosition.Top = 0;
PutRect(this->Buffer, PaintPosition, 0x121212);
}
void Window::OnPaintForeground(Event *e)
{
// Window content
if (!this->Maximized)
{
char buf[256];
sprintf(buf, "Left:\eAA11FF%lld\eFFFFFF Top:\eAA11FF%lld\eFFFFFF W:\eAA11FF%ld\eFFFFFF H:\eAA11FF%ld\eFFFFFF", this->Position.Left, this->Position.Top, this->Position.Width, this->Position.Height);
// Display->DrawString(buf, this->Position.Left + 20, this->Position.Top + 25, 200);
}
void Window::OnPaintForeground(Event *e)
{
// Window content
if (!this->Maximized)
{
char buf[256];
sprintf(buf, "Left:\eAA11FF%ld\eFFFFFF Top:\eAA11FF%ld\eFFFFFF W:\eAA11FF%ld\eFFFFFF H:\eAA11FF%ld\eFFFFFF", this->Position.Left, this->Position.Top, this->Position.Width, this->Position.Height);
// Display->DrawString(buf, this->Position.Left + 20, this->Position.Top + 25, 200);
}
foreach (auto var in this->Widgets)
{
var->OnPaint(e);
}
}
foreach (auto var in this->Widgets)
{
var->OnPaint(e);
}
}
void Window::OnPaint(Event *e)
{
memset(this->Buffer->Data, 0, this->Buffer->Size);
this->OnPaintBackground(e);
this->OnPaintForeground(e);
}
void Window::OnPaint(Event *e)
{
memset(this->Buffer->Data, 0, this->Buffer->Size);
this->OnPaintBackground(e);
this->OnPaintForeground(e);
}
void Window::OnMouseDown(Event *e)
{
Event WindowPos = *e;
void Window::OnMouseDown(Event *e)
{
Event WindowPos = *e;
WindowPos.MouseDown.X -= this->Position.Left;
WindowPos.MouseDown.Y -= this->Position.Top;
WindowPos.MouseDown.X -= this->Position.Left;
WindowPos.MouseDown.Y -= this->Position.Top;
foreach (auto var in this->Widgets)
{
var->OnMouseDown(&WindowPos);
}
}
foreach (auto var in this->Widgets)
{
var->OnMouseDown(&WindowPos);
}
}
void Window::OnMouseUp(Event *e)
{
Event WindowPos = *e;
void Window::OnMouseUp(Event *e)
{
Event WindowPos = *e;
WindowPos.MouseUp.X -= this->Position.Left;
WindowPos.MouseUp.Y -= this->Position.Top;
WindowPos.MouseUp.X -= this->Position.Left;
WindowPos.MouseUp.Y -= this->Position.Top;
foreach (auto var in this->Widgets)
{
var->OnMouseUp(&WindowPos);
}
}
foreach (auto var in this->Widgets)
{
var->OnMouseUp(&WindowPos);
}
}
void Window::OnMouseMove(Event *e)
{
Event WindowPos = *e;
void Window::OnMouseMove(Event *e)
{
Event WindowPos = *e;
WindowPos.MouseMove.X -= this->Position.Left;
WindowPos.MouseMove.Y -= this->Position.Top;
WindowPos.MouseMove.X -= this->Position.Left;
WindowPos.MouseMove.Y -= this->Position.Top;
foreach (auto var in this->Widgets)
{
var->OnMouseMove(&WindowPos);
}
}
foreach (auto var in this->Widgets)
{
var->OnMouseMove(&WindowPos);
}
}
}

View File

@ -76,6 +76,7 @@ LockClass mExtTrkLock;
* - [ ] Update SMBIOS functions to support newer versions and actually use it.
* - [ ] COW (Copy On Write) for the virtual memory. (https://en.wikipedia.org/wiki/Copy-on-write)
* - [ ] Bootstrap should have a separate bss section + PHDR.
* - [ ] Reimplement the driver conflict detection.
*
* ISSUES:
* - [x] Kernel stack is smashed when an interrupt occurs. (this bug it occurs when an interrupt like IRQ1 or IRQ12 occurs)
@ -207,16 +208,16 @@ VirtualFileSystem::Virtual *vfs = nullptr;
VirtualFileSystem::Virtual *bootanim_vfs = nullptr;
KernelConfig Config = {
.AllocatorType = Memory::MemoryAllocatorType::XallocV1,
.SchedulerType = 1,
.DriverDirectory = {'/', 's', 'y', 's', 't', 'e', 'm', '/', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\0'},
.InitPath = {'/', 's', 'y', 's', 't', 'e', 'm', '/', 'i', 'n', 'i', 't', '\0'},
.InterruptsOnCrash = true,
.Cores = 0,
.IOAPICInterruptCore = 0,
.UnlockDeadLock = false,
.SIMD = false,
.BootAnimation = false,
.AllocatorType = Memory::MemoryAllocatorType::XallocV1,
.SchedulerType = 1,
.DriverDirectory = {'/', 's', 'y', 's', 't', 'e', 'm', '/', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\0'},
.InitPath = {'/', 's', 'y', 's', 't', 'e', 'm', '/', 'i', 'n', 'i', 't', '\0'},
.InterruptsOnCrash = true,
.Cores = 0,
.IOAPICInterruptCore = 0,
.UnlockDeadLock = false,
.SIMD = false,
.BootAnimation = false,
};
extern bool EnableProfiler;
@ -225,264 +226,264 @@ extern bool EnableProfiler;
int PutCharBufferIndex = 0;
EXTERNC void putchar(char c)
{
if (Display)
Display->Print(c, PutCharBufferIndex);
else
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(c);
if (Display)
Display->Print(c, PutCharBufferIndex);
else
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(c);
}
EXTERNC void KPrint(const char *Format, ...)
{
SmartLock(KernelLock);
SmartLock(KernelLock);
if (TimeManager)
{
uint64_t Nanoseconds = TimeManager->GetNanosecondsSinceClassCreation();
if (Nanoseconds != 0)
{
printf("\eCCCCCC[\e00AEFF%llu.%07llu\eCCCCCC] ",
Nanoseconds / 10000000,
Nanoseconds % 10000000);
}
}
if (TimeManager)
{
uint64_t Nanoseconds = TimeManager->GetNanosecondsSinceClassCreation();
if (Nanoseconds != 0)
{
printf("\eCCCCCC[\e00AEFF%lu.%07lu\eCCCCCC] ",
Nanoseconds / 10000000,
Nanoseconds % 10000000);
}
}
va_list args;
va_start(args, Format);
vprintf(Format, args);
va_end(args);
va_list args;
va_start(args, Format);
vprintf(Format, args);
va_end(args);
printf("\eCCCCCC\n");
if (!Config.BootAnimation && Display)
Display->SetBuffer(0);
printf("\eCCCCCC\n");
if (!Config.BootAnimation && Display)
Display->SetBuffer(0);
}
EXTERNC NIF void Main()
{
Display = new Video::Display(bInfo.Framebuffer[0]);
KPrint("%s - %s [\e058C19%s\eFFFFFF]", KERNEL_NAME, KERNEL_VERSION, GIT_COMMIT_SHORT);
KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s", CPU::Hypervisor(), CPU::Vendor(), CPU::Name());
if (DebuggerIsAttached)
KPrint("\eFFA500Kernel debugger detected.");
Display = new Video::Display(bInfo.Framebuffer[0]);
KPrint("%s - %s [\e058C19%s\eFFFFFF]", KERNEL_NAME, KERNEL_VERSION, GIT_COMMIT_SHORT);
KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s", CPU::Hypervisor(), CPU::Vendor(), CPU::Name());
if (DebuggerIsAttached)
KPrint("\eFFA500Kernel debugger detected.");
/**************************************************************************************/
/**************************************************************************************/
KPrint("Initializing GDT and IDT");
Interrupts::Initialize(0);
KPrint("Initializing GDT and IDT");
Interrupts::Initialize(0);
KPrint("Loading Kernel Symbols");
KernelSymbolTable = new SymbolResolver::Symbols((uintptr_t)bInfo.Kernel.FileBase);
KPrint("Loading Kernel Symbols");
KernelSymbolTable = new SymbolResolver::Symbols((uintptr_t)bInfo.Kernel.FileBase);
if (KernelSymbolTable->GetTotalEntries() == 0 &&
bInfo.Kernel.Symbols.Num &&
bInfo.Kernel.Symbols.EntSize &&
bInfo.Kernel.Symbols.Shndx)
KernelSymbolTable->AddBySymbolInfo(bInfo.Kernel.Symbols.Num,
bInfo.Kernel.Symbols.EntSize,
bInfo.Kernel.Symbols.Shndx,
bInfo.Kernel.Symbols.Sections);
if (KernelSymbolTable->GetTotalEntries() == 0 &&
bInfo.Kernel.Symbols.Num &&
bInfo.Kernel.Symbols.EntSize &&
bInfo.Kernel.Symbols.Shndx)
KernelSymbolTable->AddBySymbolInfo(bInfo.Kernel.Symbols.Num,
bInfo.Kernel.Symbols.EntSize,
bInfo.Kernel.Symbols.Shndx,
bInfo.Kernel.Symbols.Sections);
KPrint("Reading Kernel Parameters");
ParseConfig((char *)bInfo.Kernel.CommandLine, &Config);
KPrint("Reading Kernel Parameters");
ParseConfig((char *)bInfo.Kernel.CommandLine, &Config);
if (Config.BootAnimation)
{
Display->CreateBuffer(0, 0, 1);
if (Config.BootAnimation)
{
Display->CreateBuffer(0, 0, 1);
Display->SetDoNotScroll(true, 1);
Video::ScreenBuffer *buf = Display->GetBuffer(1);
Video::FontInfo fi = Display->GetCurrentFont()->GetInfo();
Display->SetBufferCursor(1, 0, buf->Height - fi.Height);
PutCharBufferIndex = 1;
printf("Fennix Operating System - %s [\e058C19%s\eFFFFFF]\n", KERNEL_VERSION, GIT_COMMIT_SHORT);
Display->SetBuffer(1);
PutCharBufferIndex = 0;
}
Display->SetDoNotScroll(true, 1);
Video::ScreenBuffer *buf = Display->GetBuffer(1);
Video::FontInfo fi = Display->GetCurrentFont()->GetInfo();
Display->SetBufferCursor(1, 0, buf->Height - fi.Height);
PutCharBufferIndex = 1;
printf("Fennix Operating System - %s [\e058C19%s\eFFFFFF]\n", KERNEL_VERSION, GIT_COMMIT_SHORT);
Display->SetBuffer(1);
PutCharBufferIndex = 0;
}
KPrint("Initializing CPU Features");
CPU::InitializeFeatures(0);
KPrint("Initializing CPU Features");
CPU::InitializeFeatures(0);
KPrint("Initializing Power Manager");
PowerManager = new Power::Power;
KPrint("Initializing Power Manager");
PowerManager = new Power::Power;
KPrint("Enabling Interrupts on Bootstrap Processor");
Interrupts::Enable(0);
KPrint("Enabling Interrupts on Bootstrap Processor");
Interrupts::Enable(0);
#if defined(a64)
PowerManager->InitDSDT();
PowerManager->InitDSDT();
#elif defined(a32)
// FIXME: Add ACPI support for i386
// FIXME: Add ACPI support for i386
#elif defined(aa64)
#endif
KPrint("Initializing Timers");
TimeManager = new Time::time;
TimeManager->FindTimers(PowerManager->GetACPI());
KPrint("Initializing Timers");
TimeManager = new Time::time;
TimeManager->FindTimers(PowerManager->GetACPI());
KPrint("Initializing PCI Manager");
PCIManager = new PCI::PCI;
KPrint("Initializing PCI Manager");
PCIManager = new PCI::PCI;
foreach (auto Device in PCIManager->GetDevices())
{
KPrint("PCI: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
PCI::Descriptors::GetVendorName(Device->VendorID),
PCI::Descriptors::GetDeviceName(Device->VendorID, Device->DeviceID),
PCI::Descriptors::DeviceClasses[Device->Class],
PCI::Descriptors::GetSubclassName(Device->Class, Device->Subclass),
PCI::Descriptors::GetProgIFName(Device->Class, Device->Subclass, Device->ProgIF));
}
foreach (auto Device in PCIManager->GetDevices())
{
KPrint("PCI: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
PCI::Descriptors::GetVendorName(Device->VendorID),
PCI::Descriptors::GetDeviceName(Device->VendorID, Device->DeviceID),
PCI::Descriptors::DeviceClasses[Device->Class],
PCI::Descriptors::GetSubclassName(Device->Class, Device->Subclass),
PCI::Descriptors::GetProgIFName(Device->Class, Device->Subclass, Device->ProgIF));
}
KPrint("Initializing Bootstrap Processor Timer");
Interrupts::InitializeTimer(0);
KPrint("Initializing Bootstrap Processor Timer");
Interrupts::InitializeTimer(0);
KPrint("Initializing SMP");
SMP::Initialize(PowerManager->GetMADT());
KPrint("Initializing SMP");
SMP::Initialize(PowerManager->GetMADT());
if (SMBIOS::CheckSMBIOS())
{
SMBIOS::SMBIOSEntryPoint *smbios = SMBIOS::GetSMBIOSEntryPoint();
SMBIOS::SMBIOSBIOSInformation *bios = SMBIOS::GetBIOSInformation();
SMBIOS::SMBIOSSystemInformation *system = SMBIOS::GetSystemInformation();
SMBIOS::SMBIOSBaseBoardInformation *baseboard = SMBIOS::GetBaseBoardInformation();
if (SMBIOS::CheckSMBIOS())
{
SMBIOS::SMBIOSEntryPoint *smbios = SMBIOS::GetSMBIOSEntryPoint();
SMBIOS::SMBIOSBIOSInformation *bios = SMBIOS::GetBIOSInformation();
SMBIOS::SMBIOSSystemInformation *system = SMBIOS::GetSystemInformation();
SMBIOS::SMBIOSBaseBoardInformation *baseboard = SMBIOS::GetBaseBoardInformation();
debug("SMBIOS: %p", smbios);
debug("BIOS: %p", bios);
debug("System: %p", system);
debug("Baseboard: %p", baseboard);
debug("SMBIOS: %p", smbios);
debug("BIOS: %p", bios);
debug("System: %p", system);
debug("Baseboard: %p", baseboard);
if (smbios)
KPrint("SMBIOS: \eCCCCCCString:\e8888FF%.4s \eCCCCCCVersion (Major Minor):\e8888FF%d %d \eCCCCCCTable:\e8888FF%#x \eCCCCCCLength:\e8888FF%d",
smbios->EntryPointString, smbios->MajorVersion, smbios->MinorVersion,
smbios->TableAddress, smbios->TableLength);
else
KPrint("SMBIOS: \e8888FFSMBIOS found but not supported?");
if (smbios)
KPrint("SMBIOS: \eCCCCCCString:\e8888FF%.4s \eCCCCCCVersion (Major Minor):\e8888FF%d %d \eCCCCCCTable:\e8888FF%#x \eCCCCCCLength:\e8888FF%d",
smbios->EntryPointString, smbios->MajorVersion, smbios->MinorVersion,
smbios->TableAddress, smbios->TableLength);
else
KPrint("SMBIOS: \e8888FFSMBIOS found but not supported?");
if (bios)
{
const char *BIOSVendor = bios->GetString(bios->Vendor);
const char *BIOSVersion = bios->GetString(bios->Version);
const char *BIOSReleaseDate = bios->GetString(bios->ReleaseDate);
debug("%d %d %d", bios->Vendor, bios->Version, bios->ReleaseDate);
KPrint("BIOS: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
BIOSVendor, BIOSVersion, BIOSReleaseDate);
}
if (bios)
{
const char *BIOSVendor = bios->GetString(bios->Vendor);
const char *BIOSVersion = bios->GetString(bios->Version);
const char *BIOSReleaseDate = bios->GetString(bios->ReleaseDate);
debug("%d %d %d", bios->Vendor, bios->Version, bios->ReleaseDate);
KPrint("BIOS: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
BIOSVendor, BIOSVersion, BIOSReleaseDate);
}
if (system)
{
const char *SystemManufacturer = system->GetString(system->Manufacturer);
const char *SystemProductName = system->GetString(system->ProductName);
const char *SystemVersion = system->GetString(system->Version);
const char *SystemSerialNumber = system->GetString(system->SerialNumber);
const char *SystemSKU = system->GetString(system->SKU);
const char *SystemFamily = system->GetString(system->Family);
debug("%d %d %d %d %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c %d %d", system->Manufacturer, system->ProductName, system->Version,
system->SerialNumber,
system->UUID[0], system->UUID[1], system->UUID[2], system->UUID[3],
system->UUID[4], system->UUID[5], system->UUID[6], system->UUID[7],
system->UUID[8], system->UUID[9], system->UUID[10], system->UUID[11],
system->UUID[12], system->UUID[13], system->UUID[14], system->UUID[15],
system->SKU, system->Family);
KPrint("System: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
SystemManufacturer, SystemProductName, SystemVersion, SystemSerialNumber, SystemSKU, SystemFamily);
}
if (system)
{
const char *SystemManufacturer = system->GetString(system->Manufacturer);
const char *SystemProductName = system->GetString(system->ProductName);
const char *SystemVersion = system->GetString(system->Version);
const char *SystemSerialNumber = system->GetString(system->SerialNumber);
const char *SystemSKU = system->GetString(system->SKU);
const char *SystemFamily = system->GetString(system->Family);
debug("%d %d %d %d %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c %d %d", system->Manufacturer, system->ProductName, system->Version,
system->SerialNumber,
system->UUID[0], system->UUID[1], system->UUID[2], system->UUID[3],
system->UUID[4], system->UUID[5], system->UUID[6], system->UUID[7],
system->UUID[8], system->UUID[9], system->UUID[10], system->UUID[11],
system->UUID[12], system->UUID[13], system->UUID[14], system->UUID[15],
system->SKU, system->Family);
KPrint("System: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
SystemManufacturer, SystemProductName, SystemVersion, SystemSerialNumber, SystemSKU, SystemFamily);
}
if (baseboard)
{
const char *Manufacturer = baseboard->GetString(baseboard->Manufacturer);
const char *Product = baseboard->GetString(baseboard->Product);
const char *Version = baseboard->GetString(baseboard->Version);
const char *SerialNumber = baseboard->GetString(baseboard->SerialNumber);
debug("%d %d %d %d", baseboard->Manufacturer, baseboard->Product, baseboard->Version, baseboard->SerialNumber);
KPrint("Baseboard: \eCCCCCC\e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
Manufacturer, Product, Version, SerialNumber);
}
}
else
KPrint("SMBIOS: \eFF0000Not Found");
if (baseboard)
{
const char *Manufacturer = baseboard->GetString(baseboard->Manufacturer);
const char *Product = baseboard->GetString(baseboard->Product);
const char *Version = baseboard->GetString(baseboard->Version);
const char *SerialNumber = baseboard->GetString(baseboard->SerialNumber);
debug("%d %d %d %d", baseboard->Manufacturer, baseboard->Product, baseboard->Version, baseboard->SerialNumber);
KPrint("Baseboard: \eCCCCCC\e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
Manufacturer, Product, Version, SerialNumber);
}
}
else
KPrint("SMBIOS: \eFF0000Not Found");
KPrint("Initializing Filesystem...");
vfs = new VirtualFileSystem::Virtual;
KPrint("Initializing Filesystem...");
vfs = new VirtualFileSystem::Virtual;
if (Config.BootAnimation)
bootanim_vfs = new VirtualFileSystem::Virtual;
if (Config.BootAnimation)
bootanim_vfs = new VirtualFileSystem::Virtual;
for (size_t i = 0; i < MAX_MODULES; i++)
{
if (!bInfo.Modules[i].Address)
continue;
for (size_t i = 0; i < MAX_MODULES; i++)
{
if (!bInfo.Modules[i].Address)
continue;
if (strcmp(bInfo.Modules[i].CommandLine, "initrd") == 0)
{
debug("Found initrd at %p", bInfo.Modules[i].Address);
static char initrd = 0;
if (!initrd++)
new VirtualFileSystem::USTAR((uintptr_t)bInfo.Modules[i].Address, vfs);
}
if (strcmp(bInfo.Modules[i].CommandLine, "bootanim") == 0 && Config.BootAnimation)
{
debug("Found bootanim at %p", bInfo.Modules[i].Address);
static char bootanim = 0;
if (!bootanim++)
new VirtualFileSystem::USTAR((uintptr_t)bInfo.Modules[i].Address, bootanim_vfs);
}
}
if (strcmp(bInfo.Modules[i].CommandLine, "initrd") == 0)
{
debug("Found initrd at %p", bInfo.Modules[i].Address);
static char initrd = 0;
if (!initrd++)
new VirtualFileSystem::USTAR((uintptr_t)bInfo.Modules[i].Address, vfs);
}
if (strcmp(bInfo.Modules[i].CommandLine, "bootanim") == 0 && Config.BootAnimation)
{
debug("Found bootanim at %p", bInfo.Modules[i].Address);
static char bootanim = 0;
if (!bootanim++)
new VirtualFileSystem::USTAR((uintptr_t)bInfo.Modules[i].Address, bootanim_vfs);
}
}
if (vfs->GetRootNode()->Children.size() == 0)
{
VirtualFileSystem::FileSystemOperations null_op = {
.Name = "null",
};
if (vfs->GetRootNode()->Children.size() == 0)
{
VirtualFileSystem::FileSystemOperations null_op = {
.Name = "null",
};
vfs->CreateRoot("/", &null_op);
}
vfs->CreateRoot("/", &null_op);
}
if (!vfs->PathExists("/system"))
vfs->Create("/system", NodeFlags::DIRECTORY);
if (!vfs->PathExists("/system"))
vfs->Create("/system", NodeFlags::DIRECTORY);
if (!vfs->PathExists("/system/dev"))
DevFS = vfs->Create("/system/dev", NodeFlags::DIRECTORY);
else
{
File dev = vfs->Open("/system/dev");
if (dev.node->Flags != NodeFlags::DIRECTORY)
{
KPrint("\eE85230/system/dev is not a directory! Halting...");
CPU::Stop();
}
vfs->Close(dev);
DevFS = dev.node;
}
if (!vfs->PathExists("/system/dev"))
DevFS = vfs->Create("/system/dev", NodeFlags::DIRECTORY);
else
{
File dev = vfs->Open("/system/dev");
if (dev.node->Flags != NodeFlags::DIRECTORY)
{
KPrint("\eE85230/system/dev is not a directory! Halting...");
CPU::Stop();
}
vfs->Close(dev);
DevFS = dev.node;
}
if (!vfs->PathExists("/system/mnt"))
MntFS = vfs->Create("/system/mnt", NodeFlags::DIRECTORY);
else
{
File mnt = vfs->Open("/system/mnt");
if (mnt.node->Flags != NodeFlags::DIRECTORY)
{
KPrint("\eE85230/system/mnt is not a directory! Halting...");
CPU::Stop();
}
vfs->Close(mnt);
MntFS = mnt.node;
}
if (!vfs->PathExists("/system/mnt"))
MntFS = vfs->Create("/system/mnt", NodeFlags::DIRECTORY);
else
{
File mnt = vfs->Open("/system/mnt");
if (mnt.node->Flags != NodeFlags::DIRECTORY)
{
KPrint("\eE85230/system/mnt is not a directory! Halting...");
CPU::Stop();
}
vfs->Close(mnt);
MntFS = mnt.node;
}
if (!vfs->PathExists("/system/proc"))
ProcFS = vfs->Create("/system/proc", NodeFlags::DIRECTORY);
else
{
File proc = vfs->Open("/system/proc", nullptr);
if (proc.node->Flags != NodeFlags::DIRECTORY)
{
KPrint("\eE85230/system/proc is not a directory! Halting...");
CPU::Stop();
}
vfs->Close(proc);
ProcFS = proc.node;
}
if (!vfs->PathExists("/system/proc"))
ProcFS = vfs->Create("/system/proc", NodeFlags::DIRECTORY);
else
{
File proc = vfs->Open("/system/proc", nullptr);
if (proc.node->Flags != NodeFlags::DIRECTORY)
{
KPrint("\eE85230/system/proc is not a directory! Halting...");
CPU::Stop();
}
vfs->Close(proc);
ProcFS = proc.node;
}
KPrint("\e058C19################################");
TaskManager = new Tasking::Task((Tasking::IP)KernelMainThread);
CPU::Halt(true);
KPrint("\e058C19################################");
TaskManager = new Tasking::Task((Tasking::IP)KernelMainThread);
CPU::Halt(true);
}
typedef void (*CallPtr)(void);
@ -491,104 +492,104 @@ extern CallPtr __fini_array_start[0], __fini_array_end[0];
EXTERNC __no_stack_protector NIF void Entry(BootInfo *Info)
{
trace("Hello, World!");
trace("Hello, World!");
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0)
{
debug("\n\n----------------------------------------\nDEBUGGER DETECTED\n----------------------------------------\n\n");
DebuggerIsAttached = true;
}
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0)
{
debug("\n\n----------------------------------------\nDEBUGGER DETECTED\n----------------------------------------\n\n");
DebuggerIsAttached = true;
}
memcpy(&bInfo, Info, sizeof(BootInfo));
debug("BootInfo structure is at %p", &bInfo);
memcpy(&bInfo, Info, sizeof(BootInfo));
debug("BootInfo structure is at %p", &bInfo);
// https://wiki.osdev.org/Calling_Global_Constructors
trace("There are %d constructors to call", __init_array_end - __init_array_start);
for (CallPtr *func = __init_array_start; func != __init_array_end; func++)
(*func)();
// https://wiki.osdev.org/Calling_Global_Constructors
trace("There are %d constructors to call", __init_array_end - __init_array_start);
for (CallPtr *func = __init_array_start; func != __init_array_end; func++)
(*func)();
InitializeMemoryManagement();
InitializeMemoryManagement();
void *KernelStackAddress = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
uintptr_t KernelStack = (uintptr_t)KernelStackAddress + STACK_SIZE - 0x10;
debug("Kernel stack: %#lx-%#lx", KernelStackAddress, KernelStack);
void *KernelStackAddress = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
uintptr_t KernelStack = (uintptr_t)KernelStackAddress + STACK_SIZE - 0x10;
debug("Kernel stack: %#lx-%#lx", KernelStackAddress, KernelStack);
#if defined(a64)
asmv("mov %0, %%rsp"
:
: "r"(KernelStack)
: "memory");
asmv("mov $0, %rbp");
asmv("mov %0, %%rsp"
:
: "r"(KernelStack)
: "memory");
asmv("mov $0, %rbp");
#elif defined(a32)
asmv("mov %0, %%esp"
:
: "r"(KernelStack)
: "memory");
asmv("mov $0, %ebp");
asmv("mov %0, %%esp"
:
: "r"(KernelStack)
: "memory");
asmv("mov $0, %ebp");
#elif defined(aa64)
#warning "Kernel stack is not set!"
#endif
#ifdef DEBUG
/* I had to do this because KernelAllocator
* is a global constructor but we need
* memory management to be initialized first.
*/
TestString();
TestMemoryAllocation();
/* I had to do this because KernelAllocator
* is a global constructor but we need
* memory management to be initialized first.
*/
TestString();
TestMemoryAllocation();
#endif
EnableProfiler = true;
Main();
EnableProfiler = true;
Main();
}
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
EXTERNC __no_stack_protector void BeforeShutdown(bool Reboot)
{
UNUSED(Reboot);
/* TODO: Announce shutdown */
UNUSED(Reboot);
/* TODO: Announce shutdown */
trace("\n\n\n#################### SYSTEM SHUTTING DOWN ####################\n\n");
trace("\n\n\n#################### SYSTEM SHUTTING DOWN ####################\n\n");
if (RecoveryScreen)
delete RecoveryScreen, RecoveryScreen = nullptr;
if (RecoveryScreen)
delete RecoveryScreen, RecoveryScreen = nullptr;
if (NIManager)
delete NIManager, NIManager = nullptr;
if (NIManager)
delete NIManager, NIManager = nullptr;
if (DiskManager)
delete DiskManager, DiskManager = nullptr;
if (DiskManager)
delete DiskManager, DiskManager = nullptr;
if (DriverManager)
delete DriverManager, DriverManager = nullptr;
if (DriverManager)
delete DriverManager, DriverManager = nullptr;
if (TaskManager)
{
TaskManager->SignalShutdown();
delete TaskManager, TaskManager = nullptr;
}
if (TaskManager)
{
TaskManager->SignalShutdown();
delete TaskManager, TaskManager = nullptr;
}
if (vfs)
delete vfs, vfs = nullptr;
if (vfs)
delete vfs, vfs = nullptr;
if (bootanim_vfs)
delete bootanim_vfs, bootanim_vfs = nullptr;
if (bootanim_vfs)
delete bootanim_vfs, bootanim_vfs = nullptr;
if (TimeManager)
delete TimeManager, TimeManager = nullptr;
if (TimeManager)
delete TimeManager, TimeManager = nullptr;
if (Display)
delete Display, Display = nullptr;
// PowerManager should not be called
if (Display)
delete Display, Display = nullptr;
// PowerManager should not be called
// https://wiki.osdev.org/Calling_Global_Constructors
debug("Calling destructors...");
for (CallPtr *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
debug("Done.");
// https://wiki.osdev.org/Calling_Global_Constructors
debug("Calling destructors...");
for (CallPtr *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
debug("Done.");
}
EXTERNC void TaskingPanic()
{
if (TaskManager)
TaskManager->Panic();
if (TaskManager)
TaskManager->Panic();
}

View File

@ -57,220 +57,220 @@ NewLock(ShutdownLock);
#ifdef DEBUG
void TreeFS(Node *node, int Depth)
{
return;
foreach (auto Chld in node->Children)
{
printf("%*c %s\eFFFFFF\n", Depth, ' ', Chld->Name);
if (!Config.BootAnimation)
Display->SetBuffer(0);
TaskManager->Sleep(100);
TreeFS(Chld, Depth + 1);
}
return;
foreach (auto Chld in node->Children)
{
printf("%*c %s\eFFFFFF\n", Depth, ' ', Chld->Name);
if (!Config.BootAnimation)
Display->SetBuffer(0);
TaskManager->Sleep(100);
TreeFS(Chld, Depth + 1);
}
}
const char *Statuses[] = {
"FF0000", /* Unknown */
"AAFF00", /* Ready */
"00AA00", /* Running */
"FFAA00", /* Sleeping */
"FFAA00", /* Waiting */
"FF0088", /* Stopped */
"FF0000", /* Terminated */
"FF0000", /* Unknown */
"AAFF00", /* Ready */
"00AA00", /* Running */
"FFAA00", /* Sleeping */
"FFAA00", /* Waiting */
"FF0088", /* Stopped */
"FF0000", /* Terminated */
};
const char *StatusesSign[] = {
"Unknown",
"Ready",
"Run",
"Sleep",
"Wait",
"Stop",
"Terminated",
"Unknown",
"Ready",
"Run",
"Sleep",
"Wait",
"Stop",
"Terminated",
};
const char *SuccessSourceStrings[] = {
"Unknown",
"GetNextAvailableThread",
"GetNextAvailableProcess",
"SchedulerSearchProcessThread",
"Unknown",
"GetNextAvailableThread",
"GetNextAvailableProcess",
"SchedulerSearchProcessThread",
};
void TaskMgr_Dummy100Usage()
{
while (1)
;
while (1)
;
}
void TaskMgr_Dummy0Usage()
{
while (1)
TaskManager->Sleep(1000000);
while (1)
TaskManager->Sleep(1000000);
}
uint64_t GetUsage(uint64_t OldSystemTime, Tasking::TaskInfo *Info)
{
/* https://github.com/reactos/reactos/blob/560671a784c1e0e0aa7590df5e0598c1e2f41f5a/base/applications/taskmgr/perfdata.c#L347 */
if (Info->OldKernelTime || Info->OldUserTime)
{
uint64_t SystemTime = TimeManager->GetCounter() - OldSystemTime;
uint64_t CurrentTime = Info->KernelTime + Info->UserTime;
uint64_t OldTime = Info->OldKernelTime + Info->OldUserTime;
uint64_t CpuUsage = (CurrentTime - OldTime) / SystemTime;
CpuUsage = CpuUsage * 100;
/* https://github.com/reactos/reactos/blob/560671a784c1e0e0aa7590df5e0598c1e2f41f5a/base/applications/taskmgr/perfdata.c#L347 */
if (Info->OldKernelTime || Info->OldUserTime)
{
uint64_t SystemTime = TimeManager->GetCounter() - OldSystemTime;
uint64_t CurrentTime = Info->KernelTime + Info->UserTime;
uint64_t OldTime = Info->OldKernelTime + Info->OldUserTime;
uint64_t CpuUsage = (CurrentTime - OldTime) / SystemTime;
CpuUsage = CpuUsage * 100;
// debug("CurrentTime: %ld OldTime: %ld Time Diff: %ld Usage: %ld%%",
// CurrentTime, OldTime, SystemTime, CpuUsage);
// debug("CurrentTime: %ld OldTime: %ld Time Diff: %ld Usage: %ld%%",
// CurrentTime, OldTime, SystemTime, CpuUsage);
Info->OldKernelTime = Info->KernelTime;
Info->OldUserTime = Info->UserTime;
return CpuUsage;
}
Info->OldKernelTime = Info->KernelTime;
Info->OldUserTime = Info->UserTime;
return 0;
Info->OldKernelTime = Info->KernelTime;
Info->OldUserTime = Info->UserTime;
return CpuUsage;
}
Info->OldKernelTime = Info->KernelTime;
Info->OldUserTime = Info->UserTime;
return 0;
}
static int ShowTaskManager = 0;
void TaskMgr()
{
TaskManager->GetCurrentThread()->Rename("Debug Task Manager");
TaskManager->GetCurrentThread()->SetPriority(Tasking::Low);
TaskManager->GetCurrentThread()->Rename("Debug Task Manager");
TaskManager->GetCurrentThread()->SetPriority(Tasking::Low);
while (ShowTaskManager == 0)
CPU::Pause();
while (ShowTaskManager == 0)
CPU::Pause();
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr_Dummy100Usage)->Rename("Dummy 100% Usage");
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr_Dummy0Usage)->Rename("Dummy 0% Usage");
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr_Dummy100Usage)->Rename("Dummy 100% Usage");
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr_Dummy0Usage)->Rename("Dummy 0% Usage");
while (true)
{
while (ShowTaskManager == 0)
CPU::Pause();
while (true)
{
while (ShowTaskManager == 0)
CPU::Pause();
static int sanity = 0;
Video::ScreenBuffer *sb = Display->GetBuffer(0);
for (short i = 0; i < 1000; i++)
{
for (short j = 0; j < 500; j++)
{
uint32_t *Pixel = (uint32_t *)((uintptr_t)sb->Buffer + (j * sb->Width + i) * (bInfo.Framebuffer[0].BitsPerPixel / 8));
*Pixel = 0x222222;
}
}
static int sanity = 0;
Video::ScreenBuffer *sb = Display->GetBuffer(0);
for (short i = 0; i < 1000; i++)
{
for (short j = 0; j < 500; j++)
{
uint32_t *Pixel = (uint32_t *)((uintptr_t)sb->Buffer + (j * sb->Width + i) * (bInfo.Framebuffer[0].BitsPerPixel / 8));
*Pixel = 0x222222;
}
}
uint32_t tmpX, tmpY;
Display->GetBufferCursor(0, &tmpX, &tmpY);
Display->SetBufferCursor(0, 0, 0);
printf("\eF02C21Task Manager\n");
static uint64_t OldSystemTime = 0;
foreach (auto Proc in TaskManager->GetProcessList())
{
if (!Proc)
continue;
int Status = Proc->Status;
uint64_t ProcessCpuUsage = GetUsage(OldSystemTime, &Proc->Info);
printf("\e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld)\n",
Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime);
uint32_t tmpX, tmpY;
Display->GetBufferCursor(0, &tmpX, &tmpY);
Display->SetBufferCursor(0, 0, 0);
printf("\eF02C21Task Manager\n");
static uint64_t OldSystemTime = 0;
foreach (auto Proc in TaskManager->GetProcessList())
{
if (!Proc)
continue;
int Status = Proc->Status;
uint64_t ProcessCpuUsage = GetUsage(OldSystemTime, &Proc->Info);
printf("\e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld)\n",
Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime);
foreach (auto Thd in Proc->Threads)
{
if (!Thd)
continue;
Status = Thd->Status;
uint64_t ThreadCpuUsage = GetUsage(OldSystemTime, &Thd->Info);
foreach (auto Thd in Proc->Threads)
{
if (!Thd)
continue;
Status = Thd->Status;
uint64_t ThreadCpuUsage = GetUsage(OldSystemTime, &Thd->Info);
#if defined(a64)
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC",
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime,
Thd->Info.UserTime, Thd->Registers.rip,
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.rip) : "unknown");
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC",
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime,
Thd->Info.UserTime, Thd->Registers.rip,
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.rip) : "unknown");
#elif defined(a32)
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC",
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime,
Thd->Info.UserTime, Thd->Registers.eip,
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.eip) : "unknown");
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC",
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime,
Thd->Info.UserTime, Thd->Registers.eip,
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.eip) : "unknown");
#elif defined(aa64)
#endif
}
}
OldSystemTime = TimeManager->GetCounter();
}
}
OldSystemTime = TimeManager->GetCounter();
#if defined(a64)
register uintptr_t CurrentStackAddress asm("rsp");
register uintptr_t CurrentStackAddress asm("rsp");
#elif defined(a32)
register uintptr_t CurrentStackAddress asm("esp");
register uintptr_t CurrentStackAddress asm("esp");
#elif defined(aa64)
register uintptr_t CurrentStackAddress asm("sp");
register uintptr_t CurrentStackAddress asm("sp");
#endif
printf("Sanity: %d, Stack: %#lx", sanity++, CurrentStackAddress);
if (sanity > 1000)
sanity = 0;
Display->SetBufferCursor(0, tmpX, tmpY);
if (!Config.BootAnimation)
Display->SetBuffer(0);
printf("Sanity: %d, Stack: %#lx", sanity++, CurrentStackAddress);
if (sanity > 1000)
sanity = 0;
Display->SetBufferCursor(0, tmpX, tmpY);
if (!Config.BootAnimation)
Display->SetBuffer(0);
TaskManager->Sleep(100);
}
TaskManager->Sleep(100);
}
}
void TestSyscallsKernel()
{
return;
KPrint("Testing syscalls...");
Tasking::PCB *SyscallsTestProcess = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(),
"Syscalls Test",
Tasking::TaskTrustLevel::User,
KernelSymbolTable);
return;
KPrint("Testing syscalls...");
Tasking::PCB *SyscallsTestProcess = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(),
"Syscalls Test",
Tasking::TaskTrustLevel::User,
KernelSymbolTable);
Tasking::TCB *SyscallsTestThread = TaskManager->CreateThread(SyscallsTestProcess,
(Tasking::IP)TestSyscalls,
nullptr,
nullptr,
std::vector<AuxiliaryVector>(),
0,
Tasking::TaskArchitecture::x64,
Tasking::TaskCompatibility::Native,
true);
SyscallsTestThread->SetCritical(true);
TaskManager->GetSecurityManager()->TrustToken(SyscallsTestThread->Security.UniqueToken, Tasking::TTL::FullTrust);
Tasking::TCB *SyscallsTestThread = TaskManager->CreateThread(SyscallsTestProcess,
(Tasking::IP)TestSyscalls,
nullptr,
nullptr,
std::vector<AuxiliaryVector>(),
0,
Tasking::TaskArchitecture::x64,
Tasking::TaskCompatibility::Native,
true);
SyscallsTestThread->SetCritical(true);
TaskManager->GetSecurityManager()->TrustToken(SyscallsTestThread->Security.UniqueToken, Tasking::TTL::FullTrust);
Memory::Virtual va = Memory::Virtual(SyscallsTestProcess->PageTable);
Memory::Virtual va = Memory::Virtual(SyscallsTestProcess->PageTable);
// va.Remap((void *)TestSyscalls, va.GetPhysical((void *)TestSyscalls), Memory::P | Memory::RW | Memory::US);
// va.Remap((void *)TestSyscalls, va.GetPhysical((void *)TestSyscalls), Memory::P | Memory::RW | Memory::US);
// for (uintptr_t k = (uintptr_t)&_kernel_start; k < (uintptr_t)&_kernel_end; k += PAGE_SIZE)
// {
// va.Remap((void *)k, (void *)va.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US);
// debug("Remapped %#lx %#lx", k, va.GetPhysical((void *)k));
// }
// for (uintptr_t k = (uintptr_t)&_kernel_start; k < (uintptr_t)&_kernel_end; k += PAGE_SIZE)
// {
// va.Remap((void *)k, (void *)va.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US);
// debug("Remapped %#lx %#lx", k, va.GetPhysical((void *)k));
// }
for (uintptr_t k = (uintptr_t)TestSyscalls - PAGE_SIZE; k < (uintptr_t)TestSyscalls + FROM_PAGES(5); k += PAGE_SIZE)
{
va.Remap((void *)k, (void *)va.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US);
debug("Remapped %#lx %#lx", k, va.GetPhysical((void *)k));
}
for (uintptr_t k = (uintptr_t)TestSyscalls - PAGE_SIZE; k < (uintptr_t)TestSyscalls + FROM_PAGES(5); k += PAGE_SIZE)
{
va.Remap((void *)k, (void *)va.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US);
debug("Remapped %#lx %#lx", k, va.GetPhysical((void *)k));
}
SyscallsTestThread->Status = Tasking::TaskStatus::Ready;
TaskManager->WaitForThread(SyscallsTestThread);
KPrint("Test complete");
SyscallsTestThread->Status = Tasking::TaskStatus::Ready;
TaskManager->WaitForThread(SyscallsTestThread);
KPrint("Test complete");
}
#endif
Execute::SpawnData SpawnInit()
{
const char *envp[5] = {
"PATH=/system:/system/bin",
"TERM=tty",
"HOME=/",
"USER=root",
nullptr};
const char *envp[5] = {
"PATH=/system:/system/bin",
"TERM=tty",
"HOME=/",
"USER=root",
nullptr};
const char *argv[4] = {
Config.InitPath,
"--init",
"--critical",
nullptr};
const char *argv[4] = {
Config.InitPath,
"--init",
"--critical",
nullptr};
return Execute::Spawn(Config.InitPath, argv, envp);
return Execute::Spawn(Config.InitPath, argv, envp);
}
/* Files: 0.tga 1.tga ... 26.tga */
@ -280,261 +280,262 @@ size_t FrameCount = 1;
void BootLogoAnimationThread()
{
char BootAnimPath[16];
while (FrameCount < 27)
{
sprintf(BootAnimPath, "%ld.tga", FrameCount);
File ba = bootanim_vfs->Open(BootAnimPath);
if (!ba.IsOK())
{
bootanim_vfs->Close(ba);
debug("Failed to load boot animation frame %s", BootAnimPath);
break;
}
char BootAnimPath[16];
while (FrameCount < 27)
{
sprintf(BootAnimPath, "%ld.tga", FrameCount);
File ba = bootanim_vfs->Open(BootAnimPath);
if (!ba.IsOK())
{
bootanim_vfs->Close(ba);
debug("Failed to load boot animation frame %s", BootAnimPath);
break;
}
FrameSizes[FrameCount] = s_cst(uint32_t, ba.node->Length);
Frames[FrameCount] = new uint8_t[ba.node->Length];
memcpy((void *)Frames[FrameCount], (void *)ba.node->Address, ba.node->Length);
bootanim_vfs->Close(ba);
FrameCount++;
}
FrameSizes[FrameCount] = s_cst(uint32_t, ba.node->Length);
Frames[FrameCount] = new uint8_t[ba.node->Length];
memcpy((void *)Frames[FrameCount], (void *)ba.node->Address, ba.node->Length);
bootanim_vfs->Close(ba);
FrameCount++;
}
uint32_t DispX = Display->GetBuffer(1)->Width;
uint32_t DispY = Display->GetBuffer(1)->Height;
uint32_t DispX = Display->GetBuffer(1)->Width;
uint32_t DispY = Display->GetBuffer(1)->Height;
for (size_t i = 1; i < FrameCount; i++)
{
int x, y, channels;
for (size_t i = 1; i < FrameCount; i++)
{
int x, y, channels;
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels))
continue;
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels))
continue;
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, STBI_rgb_alpha);
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, STBI_rgb_alpha);
if (img == NULL)
continue;
if (img == NULL)
continue;
int offsetX = DispX / 2 - x / 2;
int offsetY = DispY / 2 - y / 2;
int offsetX = DispX / 2 - x / 2;
int offsetY = DispY / 2 - y / 2;
for (int i = 0; i < x * y; i++)
{
uint32_t pixel = ((uint32_t *)img)[i];
int r = (pixel >> 16) & 0xFF;
int g = (pixel >> 8) & 0xFF;
int b = (pixel >> 0) & 0xFF;
int a = (pixel >> 24) & 0xFF;
for (int i = 0; i < x * y; i++)
{
uint32_t pixel = ((uint32_t *)img)[i];
int r = (pixel >> 16) & 0xFF;
int g = (pixel >> 8) & 0xFF;
int b = (pixel >> 0) & 0xFF;
int a = (pixel >> 24) & 0xFF;
if (a != 0xFF)
{
r = (r * a) / 0xFF;
g = (g * a) / 0xFF;
b = (b * a) / 0xFF;
}
if (a != 0xFF)
{
r = (r * a) / 0xFF;
g = (g * a) / 0xFF;
b = (b * a) / 0xFF;
}
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1);
}
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1);
}
free(img);
Display->SetBuffer(1);
TaskManager->Sleep(50);
}
free(img);
Display->SetBuffer(1);
TaskManager->Sleep(50);
}
int brightness = 100;
while (brightness >= 0)
{
brightness -= 10;
Display->SetBrightness(brightness, 1);
Display->SetBuffer(1);
TaskManager->Sleep(5);
}
int brightness = 100;
while (brightness >= 0)
{
brightness -= 10;
Display->SetBrightness(brightness, 1);
Display->SetBuffer(1);
TaskManager->Sleep(5);
}
}
void ExitLogoAnimationThread()
{
Display->SetBrightness(100, 1);
Display->SetBuffer(1);
Display->SetBrightness(100, 1);
Display->SetBuffer(1);
/* Files: 26.tga 25.tga ... 1.tga */
uint32_t DispX = Display->GetBuffer(1)->Width;
uint32_t DispY = Display->GetBuffer(1)->Height;
/* Files: 26.tga 25.tga ... 1.tga */
uint32_t DispX = Display->GetBuffer(1)->Width;
uint32_t DispY = Display->GetBuffer(1)->Height;
for (size_t i = 40; i > 25; i--)
{
int x, y, channels;
for (size_t i = 40; i > 25; i--)
{
int x, y, channels;
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels))
continue;
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels))
continue;
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, STBI_rgb_alpha);
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, STBI_rgb_alpha);
if (img == NULL)
continue;
if (img == NULL)
continue;
int offsetX = DispX / 2 - x / 2;
int offsetY = DispY / 2 - y / 2;
int offsetX = DispX / 2 - x / 2;
int offsetY = DispY / 2 - y / 2;
for (int i = 0; i < x * y; i++)
{
uint32_t pixel = ((uint32_t *)img)[i];
int r = (pixel >> 16) & 0xFF;
int g = (pixel >> 8) & 0xFF;
int b = (pixel >> 0) & 0xFF;
int a = (pixel >> 24) & 0xFF;
for (int i = 0; i < x * y; i++)
{
uint32_t pixel = ((uint32_t *)img)[i];
int r = (pixel >> 16) & 0xFF;
int g = (pixel >> 8) & 0xFF;
int b = (pixel >> 0) & 0xFF;
int a = (pixel >> 24) & 0xFF;
if (a != 0xFF)
{
r = (r * a) / 0xFF;
g = (g * a) / 0xFF;
b = (b * a) / 0xFF;
}
if (a != 0xFF)
{
r = (r * a) / 0xFF;
g = (g * a) / 0xFF;
b = (b * a) / 0xFF;
}
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1);
}
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1);
}
free(img);
Display->SetBuffer(1);
TaskManager->Sleep(50);
}
free(img);
Display->SetBuffer(1);
TaskManager->Sleep(50);
}
int brightness = 100;
while (brightness >= 0)
{
brightness -= 10;
Display->SetBrightness(brightness, 1);
Display->SetBuffer(1);
TaskManager->Sleep(5);
}
int brightness = 100;
while (brightness >= 0)
{
brightness -= 10;
Display->SetBrightness(brightness, 1);
Display->SetBuffer(1);
TaskManager->Sleep(5);
}
}
void CleanupProcessesThreadWrapper() { TaskManager->CleanupProcessesThread(); }
void KernelMainThread()
{
Tasking::TCB *clnThd = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)CleanupProcessesThreadWrapper);
clnThd->SetPriority(Tasking::Idle);
TaskManager->SetCleanupThread(clnThd);
TaskManager->GetCurrentThread()->SetPriority(Tasking::Critical);
Tasking::TCB *clnThd = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)CleanupProcessesThreadWrapper);
clnThd->SetPriority(Tasking::Idle);
TaskManager->SetCleanupThread(clnThd);
TaskManager->GetCurrentThread()->SetPriority(Tasking::Critical);
Tasking::TCB *blaThread = nullptr;
Tasking::TCB *blaThread = nullptr;
if (Config.BootAnimation)
{
blaThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)BootLogoAnimationThread);
blaThread->Rename("Logo Animation");
}
if (Config.BootAnimation)
{
blaThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)BootLogoAnimationThread);
blaThread->Rename("Logo Animation");
}
#ifdef DEBUG
Tasking::TCB *tskMgr = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr);
TreeFS(vfs->GetRootNode(), 0);
TestSyscallsKernel();
Tasking::TCB *tskMgr = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr);
TreeFS(vfs->GetRootNode(), 0);
TestSyscallsKernel();
#endif
KPrint("Kernel Compiled at: %s %s with C++ Standard: %d", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
KPrint("C++ Language Version (__cplusplus): %ld", __cplusplus);
KPrint("Kernel Compiled at: %s %s with C++ Standard: %d", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
KPrint("C++ Language Version (__cplusplus): %ld", __cplusplus);
KPrint("Initializing Disk Manager...");
DiskManager = new Disk::Manager;
KPrint("Initializing Disk Manager...");
DiskManager = new Disk::Manager;
KPrint("Loading Drivers...");
DriverManager = new Driver::Driver;
KPrint("Loading Drivers...");
DriverManager = new Driver::Driver;
DriverManager->LoadDrivers();
KPrint("Fetching Disks...");
if (DriverManager->GetDrivers().size() > 0)
{
foreach (auto Driver in DriverManager->GetDrivers())
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Storage)
DiskManager->FetchDisks(Driver.DriverUID);
}
else
KPrint("\eE85230No disk drivers found! Cannot fetch disks!");
KPrint("Fetching Disks...");
if (DriverManager->GetDrivers().size() > 0)
{
foreach (auto Driver in DriverManager->GetDrivers())
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Storage)
DiskManager->FetchDisks(Driver.DriverUID);
}
else
KPrint("\eE85230No disk drivers found! Cannot fetch disks!");
KPrint("Initializing Network Interface Manager...");
NIManager = new NetworkInterfaceManager::NetworkInterface;
KPrint("Starting Network Interface Manager...");
NIManager->StartService();
KPrint("Initializing Network Interface Manager...");
NIManager = new NetworkInterfaceManager::NetworkInterface;
KPrint("Starting Network Interface Manager...");
NIManager->StartService();
printf("\eCCCCCC[\e00AEFFKernel Thread\eCCCCCC] Setting up userspace");
if (!Config.BootAnimation)
Display->SetBuffer(0);
printf("\eCCCCCC[\e00AEFFKernel Thread\eCCCCCC] Setting up userspace");
if (!Config.BootAnimation)
Display->SetBuffer(0);
Execute::SpawnData ret = {Execute::ExStatus::Unknown, nullptr, nullptr};
Tasking::TCB *ExecuteThread = nullptr;
int ExitCode = -1;
ExecuteThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)Execute::StartExecuteService);
ExecuteThread->Rename("Library Manager");
ExecuteThread->SetCritical(true);
ExecuteThread->SetPriority(Tasking::Idle);
Execute::SpawnData ret = {Execute::ExStatus::Unknown, nullptr, nullptr};
Tasking::TCB *ExecuteThread = nullptr;
int ExitCode = -1;
ExecuteThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)Execute::StartExecuteService);
ExecuteThread->Rename("Library Manager");
ExecuteThread->SetCritical(true);
ExecuteThread->SetPriority(Tasking::Idle);
Display->Print('.', 0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
Display->Print('.', 0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
ret = SpawnInit();
ret = SpawnInit();
Display->Print('.', 0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
Display->Print('.', 0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
if (ret.Status != Execute::ExStatus::OK)
{
KPrint("\eE85230Failed to start %s! Code: %d", Config.InitPath, ret.Status);
goto Exit;
}
ret.Thread->SetCritical(true);
TaskManager->GetSecurityManager()->TrustToken(ret.Process->Security.UniqueToken, Tasking::TTL::FullTrust);
TaskManager->GetSecurityManager()->TrustToken(ret.Thread->Security.UniqueToken, Tasking::TTL::FullTrust);
if (ret.Status != Execute::ExStatus::OK)
{
KPrint("\eE85230Failed to start %s! Code: %d", Config.InitPath, ret.Status);
goto Exit;
}
ret.Thread->SetCritical(true);
TaskManager->GetSecurityManager()->TrustToken(ret.Process->Security.UniqueToken, Tasking::TTL::FullTrust);
TaskManager->GetSecurityManager()->TrustToken(ret.Thread->Security.UniqueToken, Tasking::TTL::FullTrust);
Display->Print('.', 0);
Display->Print('\n', 0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
Display->Print('.', 0);
Display->Print('\n', 0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath);
TaskManager->GetCurrentThread()->SetPriority(Tasking::Idle);
KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath);
TaskManager->GetCurrentThread()->SetPriority(Tasking::Idle);
TaskManager->WaitForThread(ret.Thread);
ExitCode = ret.Thread->GetExitCode();
TaskManager->WaitForThread(ret.Thread);
ExitCode = ret.Thread->GetExitCode();
Exit:
if (ExitCode != 0)
{
KPrint("\eE85230Userspace process exited with code %d", ExitCode);
KPrint("Dropping to recovery screen...");
TaskManager->Sleep(2500);
TaskManager->WaitForThread(blaThread);
RecoveryScreen = new Recovery::KernelRecovery;
}
else
{
KPrint("\eFF7900%s process exited with code %d and it didn't invoked the shutdown function.",
Config.InitPath, ExitCode);
KPrint("System Halted");
}
CPU::Halt(true);
if (ExitCode != 0)
{
KPrint("\eE85230Userspace process exited with code %d", ExitCode);
KPrint("Dropping to recovery screen...");
TaskManager->Sleep(2500);
TaskManager->WaitForThread(blaThread);
RecoveryScreen = new Recovery::KernelRecovery;
}
else
{
KPrint("\eFF7900%s process exited with code %d and it didn't invoked the shutdown function.",
Config.InitPath, ExitCode);
KPrint("System Halted");
}
CPU::Halt(true);
}
void __no_stack_protector KernelShutdownThread(bool Reboot)
{
SmartLock(ShutdownLock);
debug("KernelShutdownThread(%s)", Reboot ? "true" : "false");
if (Config.BootAnimation && TaskManager)
{
if (RecoveryScreen)
delete RecoveryScreen, RecoveryScreen = nullptr;
SmartLock(ShutdownLock);
debug("KernelShutdownThread(%s)", Reboot ? "true" : "false");
if (Config.BootAnimation && TaskManager)
{
if (RecoveryScreen)
delete RecoveryScreen, RecoveryScreen = nullptr;
Tasking::TCB *elaThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)ExitLogoAnimationThread);
elaThread->Rename("Logo Animation");
TaskManager->WaitForThread(elaThread);
}
Tasking::TCB *elaThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)ExitLogoAnimationThread);
elaThread->Rename("Logo Animation");
TaskManager->WaitForThread(elaThread);
}
BeforeShutdown(Reboot);
BeforeShutdown(Reboot);
trace("%s...", Reboot ? "Rebooting" : "Shutting down");
if (Reboot)
PowerManager->Reboot();
else
PowerManager->Shutdown();
CPU::Stop();
trace("%s...", Reboot ? "Rebooting" : "Shutting down");
if (Reboot)
PowerManager->Reboot();
else
PowerManager->Shutdown();
CPU::Stop();
}
void KST_Reboot() { KernelShutdownThread(true); }

View File

@ -34,64 +34,64 @@
namespace NetworkInterfaceManager
{
std::vector<Events *> RegisteredEvents;
std::vector<Events *> RegisteredEvents;
NetworkInterface::NetworkInterface()
{
mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
if (DriverManager->GetDrivers().size() > 0)
{
foreach (auto Driver in DriverManager->GetDrivers())
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Network)
this->FetchNetworkCards(Driver.DriverUID);
}
else
KPrint("\eE85230No network drivers found! Cannot fetch network cards!");
NetworkInterface::NetworkInterface()
{
mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
if (DriverManager->GetDrivers().size() > 0)
{
foreach (auto Driver in DriverManager->GetDrivers())
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Network)
this->FetchNetworkCards(Driver.DriverUID);
}
else
KPrint("\eE85230No network drivers found! Cannot fetch network cards!");
DbgNetwork();
}
DbgNetwork();
}
NetworkInterface::~NetworkInterface()
{
debug("Destructor called");
NetworkInterface::~NetworkInterface()
{
debug("Destructor called");
// Stop the network stack
this->StopNetworkStack();
// Stop the network stack
this->StopNetworkStack();
// Unregister all events
RegisteredEvents.clear();
// Unregister all events
RegisteredEvents.clear();
foreach (auto inf in Interfaces)
{
if (inf)
{
Interfaces.remove(inf);
delete inf, inf = nullptr;
}
}
foreach (auto inf in Interfaces)
{
if (inf)
{
Interfaces.remove(inf);
delete inf, inf = nullptr;
}
}
// Delete all interfaces and their callbacks and free the memory
delete mem, mem = nullptr;
}
// Delete all interfaces and their callbacks and free the memory
delete mem, mem = nullptr;
}
void NetworkInterface::FetchNetworkCards(unsigned long DriverUID)
{
KernelCallback cb{};
cb.Reason = FetchReason;
DriverManager->IOCB(DriverUID, &cb);
void NetworkInterface::FetchNetworkCards(unsigned long DriverUID)
{
KernelCallback cb{};
cb.Reason = FetchReason;
DriverManager->IOCB(DriverUID, &cb);
DeviceInterface *Iface = (DeviceInterface *)mem->RequestPages(TO_PAGES(sizeof(DeviceInterface) + 1));
strcpy(Iface->Name, cb.NetworkCallback.Fetch.Name);
Iface->ID = this->CardIDs++;
Iface->MAC.FromHex(cb.NetworkCallback.Fetch.MAC);
Iface->DriverID = DriverUID;
Interfaces.push_back(Iface);
DeviceInterface *Iface = (DeviceInterface *)mem->RequestPages(TO_PAGES(sizeof(DeviceInterface) + 1));
strcpy(Iface->Name, cb.NetworkCallback.Fetch.Name);
Iface->ID = this->CardIDs++;
Iface->MAC.FromHex(cb.NetworkCallback.Fetch.MAC);
Iface->DriverID = DriverUID;
Interfaces.push_back(Iface);
foreach (auto var in RegisteredEvents)
var->OnInterfaceAdded(Iface);
foreach (auto var in RegisteredEvents)
var->OnInterfaceAdded(Iface);
debug("Network Card: %s; MAC: %#lx", Iface->Name, Iface->MAC.ToHex());
}
debug("Network Card: %s; MAC: %#lx", Iface->Name, Iface->MAC.ToHex());
}
#ifdef DEBUG_NETWORK
#define DbgWriteScreen(x, ...) KPrint(x, ##__VA_ARGS__)
@ -99,152 +99,152 @@ namespace NetworkInterfaceManager
#define DbgWriteScreen(x, ...) debug(x, ##__VA_ARGS__)
#endif
void NetworkInterface::StartNetworkStack()
{
TaskManager->GetCurrentThread()->SetPriority(Tasking::TaskPriority::Critical);
DeviceInterface *DefaultDevice = nullptr;
foreach (auto inf in Interfaces)
if (inf)
{
DefaultDevice = inf;
break;
}
void NetworkInterface::StartNetworkStack()
{
TaskManager->GetCurrentThread()->SetPriority(Tasking::TaskPriority::Critical);
DeviceInterface *DefaultDevice = nullptr;
foreach (auto inf in Interfaces)
if (inf)
{
DefaultDevice = inf;
break;
}
if (!DefaultDevice)
error("No network device found!");
else
{
DbgWriteScreen("Using %s (%s) as the default network device", DefaultDevice->Name, DefaultDevice->MAC.ToString());
NetworkEthernet::Ethernet *eth = new NetworkEthernet::Ethernet(DefaultDevice); // Use the first device found as the ethernet device
NetworkARP::ARP *arp = new NetworkARP::ARP(eth);
NetworkIPv4::IPv4 *ipv4 = new NetworkIPv4::IPv4(arp, eth);
NetworkUDP::UDP *udp = new NetworkUDP::UDP(ipv4, DefaultDevice);
NetworkUDP::Socket *DHCP_Socket = udp->Connect(InternetProtocol() /* Default value is 255.255.255.255 */, 67);
NetworkDHCP::DHCP *dhcp = new NetworkDHCP::DHCP(DHCP_Socket, DefaultDevice);
debug("eth: %p; arp: %p; ipv4: %p; udp: %p; dhcp: %p", eth, arp, ipv4, udp, dhcp);
udp->Bind(DHCP_Socket, dhcp);
dhcp->Request();
if (!DefaultDevice)
error("No network device found!");
else
{
DbgWriteScreen("Using %s (%s) as the default network device", DefaultDevice->Name, DefaultDevice->MAC.ToString());
NetworkEthernet::Ethernet *eth = new NetworkEthernet::Ethernet(DefaultDevice); // Use the first device found as the ethernet device
NetworkARP::ARP *arp = new NetworkARP::ARP(eth);
NetworkIPv4::IPv4 *ipv4 = new NetworkIPv4::IPv4(arp, eth);
NetworkUDP::UDP *udp = new NetworkUDP::UDP(ipv4, DefaultDevice);
NetworkUDP::Socket *DHCP_Socket = udp->Connect(InternetProtocol() /* Default value is 255.255.255.255 */, 67);
NetworkDHCP::DHCP *dhcp = new NetworkDHCP::DHCP(DHCP_Socket, DefaultDevice);
debug("eth: %p; arp: %p; ipv4: %p; udp: %p; dhcp: %p", eth, arp, ipv4, udp, dhcp);
udp->Bind(DHCP_Socket, dhcp);
dhcp->Request();
DefaultDevice->IP.v4.FromHex(dhcp->IP.v4.ToHex());
ipv4->SubNetworkMaskIP = dhcp->SubNetworkMask;
ipv4->GatewayIP = dhcp->Gateway;
arp->Broadcast(dhcp->Gateway);
TaskManager->Sleep(200);
DbgWriteScreen("IP: %s", dhcp->IP.v4.ToStringLittleEndian());
DbgWriteScreen("SubNetwork Mask: %s", dhcp->SubNetworkMask.v4.ToStringLittleEndian());
DbgWriteScreen("Gateway: %s", dhcp->Gateway.v4.ToStringLittleEndian());
DbgWriteScreen("DNS: %s", dhcp->DomainNameSystem.v4.ToStringLittleEndian());
TaskManager->Sleep(200);
DefaultDevice->IP.v4.FromHex(dhcp->IP.v4.ToHex());
ipv4->SubNetworkMaskIP = dhcp->SubNetworkMask;
ipv4->GatewayIP = dhcp->Gateway;
arp->Broadcast(dhcp->Gateway);
TaskManager->Sleep(200);
DbgWriteScreen("IP: %s", dhcp->IP.v4.ToStringLittleEndian());
DbgWriteScreen("SubNetwork Mask: %s", dhcp->SubNetworkMask.v4.ToStringLittleEndian());
DbgWriteScreen("Gateway: %s", dhcp->Gateway.v4.ToStringLittleEndian());
DbgWriteScreen("DNS: %s", dhcp->DomainNameSystem.v4.ToStringLittleEndian());
TaskManager->Sleep(200);
/* TODO: This is a quick workaround we need DNS resolver asap.
/* TODO: This is a quick workaround we need DNS resolver asap.
https://tf.nist.gov/tf-cgi/servers.cgi
https://www.ntppool.org
https://tf.nist.gov/tf-cgi/servers.cgi
https://www.ntppool.org
- 0.ro.pool.ntp.org ( {86, 127, 71, 168} )
- time-a-g.nist.gov ( {129, 6, 15, 28} )
*/
// InternetProtocol ip = {.v4 = {.Address = {129, 6, 15, 28}},
// .v6 = {.Address = {}}};
// NetworkUDP::Socket *NTP_Socket = udp->Connect(ip, 123);
// NetworkNTP::NTP *ntp = new NetworkNTP::NTP(NTP_Socket);
// udp->Bind(NTP_Socket, ntp);
// int UnixTimestamp = ntp->ReadTime();
// Time::Clock time = Time::ConvertFromUnix(UnixTimestamp);
// DbgWriteScreen("NTP: %d - %d.%d.%d %d:%d:%d", time.Counter,
// time.Day, time.Month, time.Year,
// time.Hour, time.Minute, time.Second);
TaskManager->Sleep(200);
- 0.ro.pool.ntp.org ( {86, 127, 71, 168} )
- time-a-g.nist.gov ( {129, 6, 15, 28} )
*/
// InternetProtocol ip = {.v4 = {.Address = {129, 6, 15, 28}},
// .v6 = {.Address = {}}};
// NetworkUDP::Socket *NTP_Socket = udp->Connect(ip, 123);
// NetworkNTP::NTP *ntp = new NetworkNTP::NTP(NTP_Socket);
// udp->Bind(NTP_Socket, ntp);
// int UnixTimestamp = ntp->ReadTime();
// Time::Clock time = Time::ConvertFromUnix(UnixTimestamp);
// DbgWriteScreen("NTP: %d - %d.%d.%d %d:%d:%d", time.Counter,
// time.Day, time.Month, time.Year,
// time.Hour, time.Minute, time.Second);
TaskManager->Sleep(200);
/* TODO: Store everything in an vector and initialize all network cards */
}
/* TODO: Store everything in an vector and initialize all network cards */
}
TaskManager->GetCurrentThread()->SetPriority(Tasking::TaskPriority::Idle);
CPU::Halt(true);
}
TaskManager->GetCurrentThread()->SetPriority(Tasking::TaskPriority::Idle);
CPU::Halt(true);
}
void NetworkInterface::StopNetworkStack()
{
fixme("Stop network stack");
}
void NetworkInterface::StopNetworkStack()
{
fixme("Stop network stack");
}
ReadFSFunction(NetRead)
{
UNUSED(node);
UNUSED(Offset);
UNUSED(Size);
UNUSED(Buffer);
fixme("Not implemented.");
return Size;
}
ReadFSFunction(NetRead)
{
UNUSED(node);
UNUSED(Offset);
UNUSED(Size);
UNUSED(Buffer);
fixme("Not implemented.");
return Size;
}
WriteFSFunction(NetWrite)
{
UNUSED(node);
UNUSED(Offset);
UNUSED(Size);
UNUSED(Buffer);
fixme("Not implemented.");
return Size;
}
WriteFSFunction(NetWrite)
{
UNUSED(node);
UNUSED(Offset);
UNUSED(Size);
UNUSED(Buffer);
fixme("Not implemented.");
return Size;
}
void CallStartNetworkStackWrapper() { NIManager->StartNetworkStack(); }
void CallStartNetworkStackWrapper() { NIManager->StartNetworkStack(); }
void NetworkInterface::StartService()
{
this->NetSvcThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)CallStartNetworkStackWrapper);
this->NetSvcThread->Rename("Network Service");
}
void NetworkInterface::StartService()
{
this->NetSvcThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)CallStartNetworkStackWrapper);
this->NetSvcThread->Rename("Network Service");
}
void NetworkInterface::DrvSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
{
foreach (auto inf in this->Interfaces)
if (inf->DriverID == DriverID)
NIManager->Send(inf, Data, Size);
}
void NetworkInterface::DrvSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
{
foreach (auto inf in this->Interfaces)
if (inf->DriverID == DriverID)
NIManager->Send(inf, Data, Size);
}
void NetworkInterface::DrvReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
{
foreach (auto inf in this->Interfaces)
if (inf->DriverID == DriverID)
NIManager->Receive(inf, Data, Size);
}
void NetworkInterface::DrvReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
{
foreach (auto inf in this->Interfaces)
if (inf->DriverID == DriverID)
NIManager->Receive(inf, Data, Size);
}
void NetworkInterface::Send(DeviceInterface *Interface, uint8_t *Data, size_t Length)
{
void *DataToBeSent = mem->RequestPages(TO_PAGES(Length + 1));
memcpy(DataToBeSent, Data, Length);
void NetworkInterface::Send(DeviceInterface *Interface, uint8_t *Data, size_t Length)
{
void *DataToBeSent = mem->RequestPages(TO_PAGES(Length + 1));
memcpy(DataToBeSent, Data, Length);
KernelCallback cb{};
cb.Reason = SendReason;
cb.NetworkCallback.Send.Data = (uint8_t *)DataToBeSent;
cb.NetworkCallback.Send.Length = Length;
DriverManager->IOCB(Interface->DriverID, &cb);
KernelCallback cb{};
cb.Reason = SendReason;
cb.NetworkCallback.Send.Data = (uint8_t *)DataToBeSent;
cb.NetworkCallback.Send.Length = Length;
DriverManager->IOCB(Interface->DriverID, &cb);
mem->FreePages(DataToBeSent, TO_PAGES(Length + 1));
foreach (auto var in RegisteredEvents)
var->OnInterfaceSent(Interface, Data, Length);
}
mem->FreePages(DataToBeSent, TO_PAGES(Length + 1));
foreach (auto var in RegisteredEvents)
var->OnInterfaceSent(Interface, Data, Length);
}
void NetworkInterface::Receive(DeviceInterface *Interface, uint8_t *Data, size_t Length)
{
foreach (auto re in RegisteredEvents)
re->OnInterfaceReceived(Interface, Data, Length);
}
void NetworkInterface::Receive(DeviceInterface *Interface, uint8_t *Data, size_t Length)
{
foreach (auto re in RegisteredEvents)
re->OnInterfaceReceived(Interface, Data, Length);
}
Events::Events(DeviceInterface *Interface)
{
UNUSED(Interface);
RegisteredEvents.push_back(this);
}
Events::Events(DeviceInterface *Interface)
{
UNUSED(Interface);
RegisteredEvents.push_back(this);
}
Events::~Events()
{
for (size_t i = 0; i < RegisteredEvents.size(); i++)
if (RegisteredEvents[i] == this)
{
RegisteredEvents.remove(i);
return;
}
}
Events::~Events()
{
for (size_t i = 0; i < RegisteredEvents.size(); i++)
if (RegisteredEvents[i] == this)
{
RegisteredEvents.remove(i);
return;
}
}
}

View File

@ -44,327 +44,327 @@ NewLock(PlayAudioLock);
namespace Recovery
{
WidgetCollection *wdgDbgWin = nullptr;
Window *DbgWin = nullptr;
WidgetCollection *wdgDbgWin = nullptr;
Window *DbgWin = nullptr;
char *AudioFile = (char *)"/home/default/Music/Ludwig van Beethoven - Fur Elise.mp3";
char *AudioFile = (char *)"/home/default/Music/Ludwig van Beethoven - Fur Elise.mp3";
void PlayAudio()
{
TaskManager->GetCurrentThread()->Rename("PlayAudio Test");
SmartLock(PlayAudioLock);
Driver::DriverFile AudioDrv;
void PlayAudio()
{
TaskManager->GetCurrentThread()->Rename("PlayAudio Test");
SmartLock(PlayAudioLock);
Driver::DriverFile AudioDrv;
foreach (auto Driver in DriverManager->GetDrivers())
{
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Audio)
{
AudioDrv = Driver;
break;
}
}
foreach (auto Driver in DriverManager->GetDrivers())
{
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Audio)
{
AudioDrv = Driver;
break;
}
}
if (!AudioDrv.Enabled)
{
error("No audio drivers found! Cannot play audio!");
return;
}
if (!AudioDrv.Enabled)
{
error("No audio drivers found! Cannot play audio!");
return;
}
VirtualFileSystem::File pcm = vfs->Open(AudioFile);
VirtualFileSystem::File pcm = vfs->Open(AudioFile);
if (!pcm.IsOK())
{
error("Cannot open audio file! Cannot play audio!");
return;
}
if (!pcm.IsOK())
{
error("Cannot open audio file! Cannot play audio!");
return;
}
void *PCMRaw = KernelAllocator.RequestPages(TO_PAGES(pcm.node->Length + 1));
memcpy(PCMRaw, (void *)pcm.node->Address, pcm.node->Length);
void *PCMRaw = KernelAllocator.RequestPages(TO_PAGES(pcm.node->Length + 1));
memcpy(PCMRaw, (void *)pcm.node->Address, pcm.node->Length);
KernelCallback callback{};
callback.Reason = SendReason;
callback.AudioCallback.Send.Data = (uint8_t *)PCMRaw;
callback.AudioCallback.Send.Length = pcm.node->Length;
debug("Playing audio...");
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
UNUSED(status);
debug("Audio played! %d", status);
KernelAllocator.FreePages((void *)PCMRaw, TO_PAGES(pcm.node->Length + 1));
vfs->Close(pcm);
TEXIT(0);
}
KernelCallback callback{};
callback.Reason = SendReason;
callback.AudioCallback.Send.Data = (uint8_t *)PCMRaw;
callback.AudioCallback.Send.Length = pcm.node->Length;
debug("Playing audio...");
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
UNUSED(status);
debug("Audio played! %d", status);
KernelAllocator.FreePages((void *)PCMRaw, TO_PAGES(pcm.node->Length + 1));
vfs->Close(pcm);
TEXIT(0);
}
void PlayAudioWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)PlayAudio)->SetPriority(Tasking::TaskPriority::Idle); }
void PlayAudioWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)PlayAudio)->SetPriority(Tasking::TaskPriority::Idle); }
void ChangeSampleRate(char SR)
{
Driver::DriverFile AudioDrv;
void ChangeSampleRate(char SR)
{
Driver::DriverFile AudioDrv;
foreach (auto Driver in DriverManager->GetDrivers())
{
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Audio)
{
AudioDrv = Driver;
break;
}
}
foreach (auto Driver in DriverManager->GetDrivers())
{
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Audio)
{
AudioDrv = Driver;
break;
}
}
if (!AudioDrv.Enabled)
{
error("No audio drivers found! Cannot play audio!");
return;
}
if (!AudioDrv.Enabled)
{
error("No audio drivers found! Cannot play audio!");
return;
}
KernelCallback callback{};
callback.Reason = AdjustReason;
callback.AudioCallback.Adjust._SampleRate = true;
callback.AudioCallback.Adjust.SampleRate = SR;
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
UNUSED(status);
debug("Sample rate changed! %d", status);
}
KernelCallback callback{};
callback.Reason = AdjustReason;
callback.AudioCallback.Adjust._SampleRate = true;
callback.AudioCallback.Adjust.SampleRate = SR;
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
UNUSED(status);
debug("Sample rate changed! %d", status);
}
void CSR8000() { ChangeSampleRate(0); }
void CSR11025() { ChangeSampleRate(1); }
void CSR16000() { ChangeSampleRate(2); }
void CSR22050() { ChangeSampleRate(3); }
void CSR32000() { ChangeSampleRate(4); }
void CSR44100() { ChangeSampleRate(5); }
void CSR48000() { ChangeSampleRate(6); }
void CSR88200() { ChangeSampleRate(7); }
void CSR96000() { ChangeSampleRate(8); }
void CSR8000() { ChangeSampleRate(0); }
void CSR11025() { ChangeSampleRate(1); }
void CSR16000() { ChangeSampleRate(2); }
void CSR22050() { ChangeSampleRate(3); }
void CSR32000() { ChangeSampleRate(4); }
void CSR44100() { ChangeSampleRate(5); }
void CSR48000() { ChangeSampleRate(6); }
void CSR88200() { ChangeSampleRate(7); }
void CSR96000() { ChangeSampleRate(8); }
void ChangeVolume(char percentage)
{
Driver::DriverFile AudioDrv;
void ChangeVolume(char percentage)
{
Driver::DriverFile AudioDrv;
foreach (auto Driver in DriverManager->GetDrivers())
{
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Audio)
{
AudioDrv = Driver;
break;
}
}
foreach (auto Driver in DriverManager->GetDrivers())
{
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Audio)
{
AudioDrv = Driver;
break;
}
}
if (!AudioDrv.Enabled)
{
error("No audio drivers found! Cannot play audio!");
return;
}
if (!AudioDrv.Enabled)
{
error("No audio drivers found! Cannot play audio!");
return;
}
KernelCallback callback{};
callback.Reason = AdjustReason;
callback.AudioCallback.Adjust._Volume = true;
callback.AudioCallback.Adjust.Volume = percentage;
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
UNUSED(status);
debug("Volume changed! %d", status);
}
KernelCallback callback{};
callback.Reason = AdjustReason;
callback.AudioCallback.Adjust._Volume = true;
callback.AudioCallback.Adjust.Volume = percentage;
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
UNUSED(status);
debug("Volume changed! %d", status);
}
void CV0() { ChangeVolume(0); }
void CV10() { ChangeVolume(10); }
void CV20() { ChangeVolume(20); }
void CV30() { ChangeVolume(30); }
void CV40() { ChangeVolume(40); }
void CV50() { ChangeVolume(50); }
void CV60() { ChangeVolume(60); }
void CV70() { ChangeVolume(70); }
void CV80() { ChangeVolume(80); }
void CV90() { ChangeVolume(90); }
void CV100() { ChangeVolume(100); }
void CV0() { ChangeVolume(0); }
void CV10() { ChangeVolume(10); }
void CV20() { ChangeVolume(20); }
void CV30() { ChangeVolume(30); }
void CV40() { ChangeVolume(40); }
void CV50() { ChangeVolume(50); }
void CV60() { ChangeVolume(60); }
void CV70() { ChangeVolume(70); }
void CV80() { ChangeVolume(80); }
void CV90() { ChangeVolume(90); }
void CV100() { ChangeVolume(100); }
void BufBight10() { Display->SetBrightness(10, 200); }
void BufBight20() { Display->SetBrightness(20, 200); }
void BufBight30() { Display->SetBrightness(30, 200); }
void BufBight40() { Display->SetBrightness(40, 200); }
void BufBight50() { Display->SetBrightness(50, 200); }
void BufBight60() { Display->SetBrightness(60, 200); }
void BufBight70() { Display->SetBrightness(70, 200); }
void BufBight80() { Display->SetBrightness(80, 200); }
void BufBight90() { Display->SetBrightness(90, 200); }
void BufBight100() { Display->SetBrightness(100, 200); }
void BufBight10() { Display->SetBrightness(10, 200); }
void BufBight20() { Display->SetBrightness(20, 200); }
void BufBight30() { Display->SetBrightness(30, 200); }
void BufBight40() { Display->SetBrightness(40, 200); }
void BufBight50() { Display->SetBrightness(50, 200); }
void BufBight60() { Display->SetBrightness(60, 200); }
void BufBight70() { Display->SetBrightness(70, 200); }
void BufBight80() { Display->SetBrightness(80, 200); }
void BufBight90() { Display->SetBrightness(90, 200); }
void BufBight100() { Display->SetBrightness(100, 200); }
// void audio_dev_connected() { AudioFile = (char *)"/system/config/audio/media/dev_connected.mp3"; }
// void audio_dev_disconnected() { AudioFile = (char *)"/system/config/audio/media/dev_disconnected.mp3"; }
// void audio_dev_error() { AudioFile = (char *)"/system/config/audio/media/dev_error.mp3"; }
// void audio_error() { AudioFile = (char *)"/system/config/audio/media/error.mp3"; }
// void audio_notification() { AudioFile = (char *)"/system/config/audio/media/notification.mp3"; }
// void audio_warning() { AudioFile = (char *)"/system/config/audio/media/warning.mp3"; }
// void audio_dev_connected() { AudioFile = (char *)"/system/config/audio/media/dev_connected.mp3"; }
// void audio_dev_disconnected() { AudioFile = (char *)"/system/config/audio/media/dev_disconnected.mp3"; }
// void audio_dev_error() { AudioFile = (char *)"/system/config/audio/media/dev_error.mp3"; }
// void audio_error() { AudioFile = (char *)"/system/config/audio/media/error.mp3"; }
// void audio_notification() { AudioFile = (char *)"/system/config/audio/media/notification.mp3"; }
// void audio_warning() { AudioFile = (char *)"/system/config/audio/media/warning.mp3"; }
void KernelRecovery::RecoveryThread()
{
while (wdgDbgWin == nullptr || DbgWin == nullptr)
TaskManager->Sleep(100);
void KernelRecovery::RecoveryThread()
{
while (wdgDbgWin == nullptr || DbgWin == nullptr)
TaskManager->Sleep(100);
wdgDbgWin->CreateLabel({5, 0, 0, 0}, "Scheduler Ticks / Last Task Ticks");
GraphicalUserInterface::Handle SchedLblHnd = wdgDbgWin->CreateLabel({5, 15, 0, 0}, "0000000000000000 / 0000000000000000");
wdgDbgWin->CreateLabel({5, 0, 0, 0}, "Scheduler Ticks / Last Task Ticks");
GraphicalUserInterface::Handle SchedLblHnd = wdgDbgWin->CreateLabel({5, 15, 0, 0}, "0000000000000000 / 0000000000000000");
wdgDbgWin->CreateLabel({5, 40, 0, 0}, "Memory Usage");
GraphicalUserInterface::Handle MemLblHnd = wdgDbgWin->CreateLabel({5, 55, 0, 0}, "0MB / 0GB (0MB reserved) 0% (0000000000000000 bytes allocated)");
wdgDbgWin->CreateLabel({5, 40, 0, 0}, "Memory Usage");
GraphicalUserInterface::Handle MemLblHnd = wdgDbgWin->CreateLabel({5, 55, 0, 0}, "0MB / 0GB (0MB reserved) 0% (0000000000000000 bytes allocated)");
#ifdef DEBUG
wdgDbgWin->CreateLabel({5, 95, 0, 0}, "GUI Info");
wdgDbgWin->CreateLabel({5, 110, 0, 0}, " Fetch Inputs / Paint Desktop / Paint Widgets");
GraphicalUserInterface::Handle GUI1LblHnd = wdgDbgWin->CreateLabel({5, 125, 0, 0}, "0000000000000000 / 0000000000000000 / 0000000000000000");
wdgDbgWin->CreateLabel({5, 140, 0, 0}, " Paint Windows / Paint Cursor / Memset & Update");
GraphicalUserInterface::Handle GUI2LblHnd = wdgDbgWin->CreateLabel({5, 155, 0, 0}, "0000000000000000 / 0000000000000000 / 0000000000000000");
wdgDbgWin->CreateLabel({5, 95, 0, 0}, "GUI Info");
wdgDbgWin->CreateLabel({5, 110, 0, 0}, " Fetch Inputs / Paint Desktop / Paint Widgets");
GraphicalUserInterface::Handle GUI1LblHnd = wdgDbgWin->CreateLabel({5, 125, 0, 0}, "0000000000000000 / 0000000000000000 / 0000000000000000");
wdgDbgWin->CreateLabel({5, 140, 0, 0}, " Paint Windows / Paint Cursor / Memset & Update");
GraphicalUserInterface::Handle GUI2LblHnd = wdgDbgWin->CreateLabel({5, 155, 0, 0}, "0000000000000000 / 0000000000000000 / 0000000000000000");
#endif
wdgDbgWin->CreateLabel({5, 195, 0, 0}, "Audio");
wdgDbgWin->CreateButton({5, 210, 85, 15}, "Play Audio", (uintptr_t)PlayAudioWrapper);
wdgDbgWin->CreateLabel({5, 195, 0, 0}, "Audio");
wdgDbgWin->CreateButton({5, 210, 85, 15}, "Play Audio", (uintptr_t)PlayAudioWrapper);
wdgDbgWin->CreateLabel({5, 235, 0, 0}, "Sample Rate");
wdgDbgWin->CreateButton({5, 250, 45, 15}, "8000", (uintptr_t)CSR8000);
wdgDbgWin->CreateButton({55, 250, 45, 15}, "11025", (uintptr_t)CSR11025);
wdgDbgWin->CreateButton({105, 250, 45, 15}, "16000", (uintptr_t)CSR16000);
wdgDbgWin->CreateButton({155, 250, 45, 15}, "22050", (uintptr_t)CSR22050);
wdgDbgWin->CreateButton({205, 250, 45, 15}, "32000", (uintptr_t)CSR32000);
wdgDbgWin->CreateButton({255, 250, 45, 15}, "44100", (uintptr_t)CSR44100);
wdgDbgWin->CreateButton({305, 250, 45, 15}, "48000", (uintptr_t)CSR48000);
wdgDbgWin->CreateButton({355, 250, 45, 15}, "88200", (uintptr_t)CSR88200);
wdgDbgWin->CreateButton({405, 250, 45, 15}, "96000", (uintptr_t)CSR96000);
wdgDbgWin->CreateLabel({5, 235, 0, 0}, "Sample Rate");
wdgDbgWin->CreateButton({5, 250, 45, 15}, "8000", (uintptr_t)CSR8000);
wdgDbgWin->CreateButton({55, 250, 45, 15}, "11025", (uintptr_t)CSR11025);
wdgDbgWin->CreateButton({105, 250, 45, 15}, "16000", (uintptr_t)CSR16000);
wdgDbgWin->CreateButton({155, 250, 45, 15}, "22050", (uintptr_t)CSR22050);
wdgDbgWin->CreateButton({205, 250, 45, 15}, "32000", (uintptr_t)CSR32000);
wdgDbgWin->CreateButton({255, 250, 45, 15}, "44100", (uintptr_t)CSR44100);
wdgDbgWin->CreateButton({305, 250, 45, 15}, "48000", (uintptr_t)CSR48000);
wdgDbgWin->CreateButton({355, 250, 45, 15}, "88200", (uintptr_t)CSR88200);
wdgDbgWin->CreateButton({405, 250, 45, 15}, "96000", (uintptr_t)CSR96000);
wdgDbgWin->CreateLabel({5, 265, 0, 0}, "Volume");
wdgDbgWin->CreateButton({5, 280, 25, 15}, "0%", (uintptr_t)CV0);
wdgDbgWin->CreateButton({35, 280, 25, 15}, "10%", (uintptr_t)CV10);
wdgDbgWin->CreateButton({65, 280, 25, 15}, "20%", (uintptr_t)CV20);
wdgDbgWin->CreateButton({95, 280, 25, 15}, "30%", (uintptr_t)CV30);
wdgDbgWin->CreateButton({125, 280, 25, 15}, "40%", (uintptr_t)CV40);
wdgDbgWin->CreateButton({155, 280, 25, 15}, "50%", (uintptr_t)CV50);
wdgDbgWin->CreateButton({185, 280, 25, 15}, "60%", (uintptr_t)CV60);
wdgDbgWin->CreateButton({215, 280, 25, 15}, "70%", (uintptr_t)CV70);
wdgDbgWin->CreateButton({245, 280, 25, 15}, "80%", (uintptr_t)CV80);
wdgDbgWin->CreateButton({275, 280, 25, 15}, "90%", (uintptr_t)CV90);
wdgDbgWin->CreateButton({305, 280, 25, 15}, "100%", (uintptr_t)CV100);
wdgDbgWin->CreateLabel({5, 265, 0, 0}, "Volume");
wdgDbgWin->CreateButton({5, 280, 25, 15}, "0%", (uintptr_t)CV0);
wdgDbgWin->CreateButton({35, 280, 25, 15}, "10%", (uintptr_t)CV10);
wdgDbgWin->CreateButton({65, 280, 25, 15}, "20%", (uintptr_t)CV20);
wdgDbgWin->CreateButton({95, 280, 25, 15}, "30%", (uintptr_t)CV30);
wdgDbgWin->CreateButton({125, 280, 25, 15}, "40%", (uintptr_t)CV40);
wdgDbgWin->CreateButton({155, 280, 25, 15}, "50%", (uintptr_t)CV50);
wdgDbgWin->CreateButton({185, 280, 25, 15}, "60%", (uintptr_t)CV60);
wdgDbgWin->CreateButton({215, 280, 25, 15}, "70%", (uintptr_t)CV70);
wdgDbgWin->CreateButton({245, 280, 25, 15}, "80%", (uintptr_t)CV80);
wdgDbgWin->CreateButton({275, 280, 25, 15}, "90%", (uintptr_t)CV90);
wdgDbgWin->CreateButton({305, 280, 25, 15}, "100%", (uintptr_t)CV100);
GraphicalUserInterface::Handle wdgDbgCurrentAudioLbl = wdgDbgWin->CreateLabel({5, 295, 0, 0}, "Current Audio: ");
// wdgDbgWin->CreateButton({5, 310, 85, 15}, "dev_connected.mp3", (uintptr_t)audio_dev_connected);
// wdgDbgWin->CreateButton({95, 310, 85, 15}, "dev_disconnected.mp3", (uintptr_t)audio_dev_disconnected);
// wdgDbgWin->CreateButton({185, 310, 85, 15}, "dev_error.mp3", (uintptr_t)audio_dev_error);
// wdgDbgWin->CreateButton({275, 310, 85, 15}, "error.mp3", (uintptr_t)audio_error);
// wdgDbgWin->CreateButton({365, 310, 85, 15}, "notification.mp3", (uintptr_t)audio_notification);
// wdgDbgWin->CreateButton({455, 310, 85, 15}, "warning.mp3", (uintptr_t)audio_warning);
GraphicalUserInterface::Handle wdgDbgCurrentAudioLbl = wdgDbgWin->CreateLabel({5, 295, 0, 0}, "Current Audio: ");
// wdgDbgWin->CreateButton({5, 310, 85, 15}, "dev_connected.mp3", (uintptr_t)audio_dev_connected);
// wdgDbgWin->CreateButton({95, 310, 85, 15}, "dev_disconnected.mp3", (uintptr_t)audio_dev_disconnected);
// wdgDbgWin->CreateButton({185, 310, 85, 15}, "dev_error.mp3", (uintptr_t)audio_dev_error);
// wdgDbgWin->CreateButton({275, 310, 85, 15}, "error.mp3", (uintptr_t)audio_error);
// wdgDbgWin->CreateButton({365, 310, 85, 15}, "notification.mp3", (uintptr_t)audio_notification);
// wdgDbgWin->CreateButton({455, 310, 85, 15}, "warning.mp3", (uintptr_t)audio_warning);
wdgDbgWin->CreateLabel({5, 325, 0, 0}, "Display Brightness");
wdgDbgWin->CreateButton({5, 340, 25, 15}, "10%", (uintptr_t)BufBight10);
wdgDbgWin->CreateButton({35, 340, 25, 15}, "20%", (uintptr_t)BufBight20);
wdgDbgWin->CreateButton({65, 340, 25, 15}, "30%", (uintptr_t)BufBight30);
wdgDbgWin->CreateButton({95, 340, 25, 15}, "40%", (uintptr_t)BufBight40);
wdgDbgWin->CreateButton({125, 340, 25, 15}, "50%", (uintptr_t)BufBight50);
wdgDbgWin->CreateButton({155, 340, 25, 15}, "60%", (uintptr_t)BufBight60);
wdgDbgWin->CreateButton({185, 340, 25, 15}, "70%", (uintptr_t)BufBight70);
wdgDbgWin->CreateButton({215, 340, 25, 15}, "80%", (uintptr_t)BufBight80);
wdgDbgWin->CreateButton({245, 340, 25, 15}, "90%", (uintptr_t)BufBight90);
wdgDbgWin->CreateButton({275, 340, 25, 15}, "100%", (uintptr_t)BufBight100);
wdgDbgWin->CreateLabel({5, 325, 0, 0}, "Display Brightness");
wdgDbgWin->CreateButton({5, 340, 25, 15}, "10%", (uintptr_t)BufBight10);
wdgDbgWin->CreateButton({35, 340, 25, 15}, "20%", (uintptr_t)BufBight20);
wdgDbgWin->CreateButton({65, 340, 25, 15}, "30%", (uintptr_t)BufBight30);
wdgDbgWin->CreateButton({95, 340, 25, 15}, "40%", (uintptr_t)BufBight40);
wdgDbgWin->CreateButton({125, 340, 25, 15}, "50%", (uintptr_t)BufBight50);
wdgDbgWin->CreateButton({155, 340, 25, 15}, "60%", (uintptr_t)BufBight60);
wdgDbgWin->CreateButton({185, 340, 25, 15}, "70%", (uintptr_t)BufBight70);
wdgDbgWin->CreateButton({215, 340, 25, 15}, "80%", (uintptr_t)BufBight80);
wdgDbgWin->CreateButton({245, 340, 25, 15}, "90%", (uintptr_t)BufBight90);
wdgDbgWin->CreateButton({275, 340, 25, 15}, "100%", (uintptr_t)BufBight100);
GraphicalUserInterface::Handle wdgDbgCurrentCPUSchedCoreLbl = wdgDbgWin->CreateLabel({5, 355, 0, 0}, "CPU Scheduled Core: Unknown");
GraphicalUserInterface::Handle wdgDbgCurrentCPUSchedCoreLbl = wdgDbgWin->CreateLabel({5, 355, 0, 0}, "CPU Scheduled Core: Unknown");
DbgWin->AddWidget(wdgDbgWin);
DbgWin->AddWidget(wdgDbgWin);
char TicksText[128];
uint64_t MemUsed = 0;
uint64_t MemTotal = 0;
uint64_t MemReserved = 0;
while (true)
{
sprintf(TicksText, "%016lld / %016lld", TaskManager->GetSchedulerTicks(), TaskManager->GetLastTaskTicks());
wdgDbgWin->SetText(SchedLblHnd, TicksText);
sprintf(TicksText, "CPU Scheduled Core: %lld", TaskManager->GetLastCore());
wdgDbgWin->SetText(wdgDbgCurrentCPUSchedCoreLbl, TicksText);
static int RefreshMemCounter = 0;
if (RefreshMemCounter-- == 0)
{
MemUsed = KernelAllocator.GetUsedMemory();
MemTotal = KernelAllocator.GetTotalMemory();
MemReserved = KernelAllocator.GetReservedMemory();
uint64_t MemPercent = (MemUsed * 100) / MemTotal;
sprintf(TicksText, "%lldMB / %lldGB (%lldMB reserved) %lld%% (%lld bytes allocated)", TO_MB(MemUsed), TO_GB(MemTotal), TO_MB(MemReserved), MemPercent, MemUsed);
wdgDbgWin->SetText(MemLblHnd, TicksText);
RefreshMemCounter = 25;
}
sprintf(TicksText, "Debug - %ldx%ld", DbgWin->GetPosition().Width, DbgWin->GetPosition().Height);
DbgWin->SetTitle(TicksText);
sprintf(TicksText, "Current Audio: %s", AudioFile);
wdgDbgWin->SetText(wdgDbgCurrentAudioLbl, TicksText);
char TicksText[128];
uint64_t MemUsed = 0;
uint64_t MemTotal = 0;
uint64_t MemReserved = 0;
while (true)
{
sprintf(TicksText, "%016ld / %016ld", TaskManager->GetSchedulerTicks(), TaskManager->GetLastTaskTicks());
wdgDbgWin->SetText(SchedLblHnd, TicksText);
sprintf(TicksText, "CPU Scheduled Core: %d", TaskManager->GetLastCore());
wdgDbgWin->SetText(wdgDbgCurrentCPUSchedCoreLbl, TicksText);
static int RefreshMemCounter = 0;
if (RefreshMemCounter-- == 0)
{
MemUsed = KernelAllocator.GetUsedMemory();
MemTotal = KernelAllocator.GetTotalMemory();
MemReserved = KernelAllocator.GetReservedMemory();
uint64_t MemPercent = (MemUsed * 100) / MemTotal;
sprintf(TicksText, "%ldMB / %ldGB (%ldMB reserved) %ld%% (%ld bytes allocated)", TO_MB(MemUsed), TO_GB(MemTotal), TO_MB(MemReserved), MemPercent, MemUsed);
wdgDbgWin->SetText(MemLblHnd, TicksText);
RefreshMemCounter = 25;
}
sprintf(TicksText, "Debug - %ldx%ld", DbgWin->GetPosition().Width, DbgWin->GetPosition().Height);
DbgWin->SetTitle(TicksText);
sprintf(TicksText, "Current Audio: %s", AudioFile);
wdgDbgWin->SetText(wdgDbgCurrentAudioLbl, TicksText);
#ifdef DEBUG
static int RefreshGUIDbgCounter = 0;
if (RefreshGUIDbgCounter-- == 0)
{
sprintf(TicksText, "%016lld / %016lld / %016lld", FIi, PDi, PWi);
wdgDbgWin->SetText(GUI1LblHnd, TicksText);
sprintf(TicksText, "%016lld / %016lld / %016lld", PWWi, PCi, mmi);
wdgDbgWin->SetText(GUI2LblHnd, TicksText);
RefreshGUIDbgCounter = 5;
}
static int RefreshGUIDbgCounter = 0;
if (RefreshGUIDbgCounter-- == 0)
{
sprintf(TicksText, "%016ld / %016ld / %016ld", FIi, PDi, PWi);
wdgDbgWin->SetText(GUI1LblHnd, TicksText);
sprintf(TicksText, "%016ld / %016ld / %016ld", PWWi, PCi, mmi);
wdgDbgWin->SetText(GUI2LblHnd, TicksText);
RefreshGUIDbgCounter = 5;
}
#endif
TaskManager->Sleep(100);
}
}
TaskManager->Sleep(100);
}
}
void RecoveryThreadWrapper()
{
while (!RecoveryScreen)
CPU::Pause();
RecoveryScreen->RecoveryThread();
}
void RecoveryThreadWrapper()
{
while (!RecoveryScreen)
CPU::Pause();
RecoveryScreen->RecoveryThread();
}
void RebootCommandThread() { KST_Reboot(); }
void ShutdownCommandThread() { KST_Shutdown(); }
void RebootCommandThread() { KST_Reboot(); }
void ShutdownCommandThread() { KST_Shutdown(); }
void RebootCommandWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RebootCommandThread); }
void ShutdownCommandWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)ShutdownCommandThread); }
void RebootCommandWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RebootCommandThread); }
void ShutdownCommandWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)ShutdownCommandThread); }
GraphicalUserInterface::GUI *gui = nullptr;
void GUIWrapper() { gui->Loop(); }
GraphicalUserInterface::GUI *gui = nullptr;
void GUIWrapper() { gui->Loop(); }
KernelRecovery::KernelRecovery()
{
// PCB *proc = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), "Recovery", TaskTrustLevel::Kernel, nullptr);
KernelRecovery::KernelRecovery()
{
// PCB *proc = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), "Recovery", TaskTrustLevel::Kernel, nullptr);
gui = new GraphicalUserInterface::GUI;
gui = new GraphicalUserInterface::GUI;
guiThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)GUIWrapper);
guiThread->Rename("GUI Thread");
guiThread->SetPriority(Tasking::TaskPriority::Critical);
guiThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)GUIWrapper);
guiThread->Rename("GUI Thread");
guiThread->SetPriority(Tasking::TaskPriority::Critical);
Rect RecoveryModeWindow;
RecoveryModeWindow.Width = 460;
RecoveryModeWindow.Height = 100;
RecoveryModeWindow.Left = Display->GetBuffer(200)->Width / 2 - RecoveryModeWindow.Width / 2;
RecoveryModeWindow.Top = Display->GetBuffer(200)->Height / 2 - RecoveryModeWindow.Height / 2;
Window *RecWin = new Window(gui, RecoveryModeWindow, "Recovery Mode");
gui->AddWindow(RecWin);
Rect RecoveryModeWindow;
RecoveryModeWindow.Width = 460;
RecoveryModeWindow.Height = 100;
RecoveryModeWindow.Left = Display->GetBuffer(200)->Width / 2 - RecoveryModeWindow.Width / 2;
RecoveryModeWindow.Top = Display->GetBuffer(200)->Height / 2 - RecoveryModeWindow.Height / 2;
Window *RecWin = new Window(gui, RecoveryModeWindow, "Recovery Mode");
gui->AddWindow(RecWin);
WidgetCollection *wdgRecWin = new WidgetCollection(RecWin);
wdgRecWin->CreateLabel({80, 10, 0, 0}, "This is not fully implemented.");
wdgRecWin->CreateLabel({10, 40, 0, 0}, "All you can do is shutdown/reboot the system.");
wdgRecWin->CreateButton({10, 70, 90, 20}, "Reboot", (uintptr_t)RebootCommandWrapper);
wdgRecWin->CreateButton({110, 70, 90, 20}, "Shutdown", (uintptr_t)ShutdownCommandWrapper);
RecWin->AddWidget(wdgRecWin);
WidgetCollection *wdgRecWin = new WidgetCollection(RecWin);
wdgRecWin->CreateLabel({80, 10, 0, 0}, "This is not fully implemented.");
wdgRecWin->CreateLabel({10, 40, 0, 0}, "All you can do is shutdown/reboot the system.");
wdgRecWin->CreateButton({10, 70, 90, 20}, "Reboot", (uintptr_t)RebootCommandWrapper);
wdgRecWin->CreateButton({110, 70, 90, 20}, "Shutdown", (uintptr_t)ShutdownCommandWrapper);
RecWin->AddWidget(wdgRecWin);
Rect DebugWindow;
DebugWindow.Width = 460;
DebugWindow.Height = 380;
DebugWindow.Left = 5;
DebugWindow.Top = 25;
DbgWin = new Window(gui, DebugWindow, "Debug");
gui->AddWindow(DbgWin);
Rect DebugWindow;
DebugWindow.Width = 460;
DebugWindow.Height = 380;
DebugWindow.Left = 5;
DebugWindow.Top = 25;
DbgWin = new Window(gui, DebugWindow, "Debug");
gui->AddWindow(DbgWin);
wdgDbgWin = new WidgetCollection(DbgWin);
Video::Font *NewFont = new Video::Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, Video::FontType::PCScreenFont2);
wdgDbgWin->ReplaceFont(NewFont);
recoveryThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RecoveryThreadWrapper);
recoveryThread->Rename("Recovery Thread");
recoveryThread->SetPriority(Tasking::TaskPriority::Idle);
}
wdgDbgWin = new WidgetCollection(DbgWin);
Video::Font *NewFont = new Video::Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, Video::FontType::PCScreenFont2);
wdgDbgWin->ReplaceFont(NewFont);
recoveryThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RecoveryThreadWrapper);
recoveryThread->Rename("Recovery Thread");
recoveryThread->SetPriority(Tasking::TaskPriority::Idle);
}
KernelRecovery::~KernelRecovery()
{
debug("Destructor called");
TaskManager->KillThread(guiThread, 0);
TaskManager->KillThread(recoveryThread, 0);
delete gui, gui = nullptr;
}
KernelRecovery::~KernelRecovery()
{
debug("Destructor called");
TaskManager->KillThread(guiThread, 0);
TaskManager->KillThread(recoveryThread, 0);
delete gui, gui = nullptr;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -22,24 +22,24 @@
enum DebugLevel
{
DebugLevelNone = 0,
DebugLevelError = 1,
DebugLevelWarning = 2,
DebugLevelInfo = 3,
DebugLevelDebug = 4,
DebugLevelTrace = 5,
DebugLevelFixme = 6,
DebugLevelUbsan = 7
DebugLevelNone = 0,
DebugLevelError = 1,
DebugLevelWarning = 2,
DebugLevelInfo = 3,
DebugLevelDebug = 4,
DebugLevelTrace = 5,
DebugLevelFixme = 6,
DebugLevelUbsan = 7
};
#ifdef __cplusplus
namespace SysDbg
{
void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
}
#define error(Format, ...) SysDbg::WriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
@ -103,4 +103,6 @@ void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, co
#endif // __cplusplus
#define stub fixme("stub")
#endif // !__FENNIX_KERNEL_DEBUGGER_H__

View File

@ -22,6 +22,7 @@
#include <memory.hpp>
#include <ints.hpp>
#include <lock.hpp>
#include <debug.h>
#include <cpu.hpp>
#include <pci.hpp>
@ -29,114 +30,207 @@
namespace Driver
{
enum DriverCode
{
ERROR,
OK,
NOT_AVAILABLE,
INVALID_FEX_HEADER,
INVALID_DRIVER_DATA,
NOT_DRIVER,
NOT_IMPLEMENTED,
DRIVER_RETURNED_ERROR,
UNKNOWN_DRIVER_TYPE,
PCI_DEVICE_NOT_FOUND,
DRIVER_CONFLICT
};
enum DriverCode
{
/* This must be the same as in DAPI.hpp DriverReturnCode */
ERROR,
OK,
NOT_IMPLEMENTED,
NOT_FOUND,
NOT_READY,
NOT_AVAILABLE,
NOT_AUTHORIZED,
NOT_VALID,
NOT_ACCEPTED,
INVALID_PCI_BAR,
INVALID_KERNEL_API,
INVALID_MEMORY_ALLOCATION,
INVALID_DATA,
DEVICE_NOT_SUPPORTED,
SYSTEM_NOT_SUPPORTED,
KERNEL_API_VERSION_NOT_SUPPORTED,
class DriverInterruptHook;
struct DriverFile
{
bool Enabled = false;
size_t DriverUID = 0;
void *Address = nullptr;
void *InterruptCallback = nullptr;
Memory::MemMgr *MemTrk = nullptr;
DriverInterruptHook *InterruptHook[16]{};
/* End of driver-only errors */
bool operator==(const DriverFile &Other) const
{
return DriverUID == Other.DriverUID;
}
};
INVALID_FEX_HEADER,
INVALID_DRIVER_DATA,
NOT_DRIVER,
DRIVER_RETURNED_ERROR,
UNKNOWN_DRIVER_TYPE,
UNKNOWN_DRIVER_BIND_TYPE,
PCI_DEVICE_NOT_FOUND,
DRIVER_CONFLICT
};
class DriverInterruptHook : public Interrupts::Handler
{
private:
DriverFile Handle;
bool Enabled = true;
class DriverInterruptHook;
struct DriverFile
{
bool Enabled = false;
bool BuiltIn = false;
unsigned int DriverUID = 0;
void *Address = nullptr;
void *ExtendedHeaderAddress = nullptr;
void *InterruptCallback = nullptr;
Memory::MemMgr *MemTrk = nullptr;
DriverInterruptHook *InterruptHook[16]{};
bool operator==(const DriverFile &Other) const
{
return DriverUID == Other.DriverUID;
}
};
struct BuiltInDriverInfo
{
int (*EntryPoint)(void *);
void *ExtendedHeader;
};
class DriverInterruptHook : public Interrupts::Handler
{
private:
NewLock(DriverInterruptLock);
DriverFile Handle;
bool Enabled = true;
#if defined(a64)
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
#elif defined(a32)
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
#elif defined(aa64)
void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame);
void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame);
#endif
public:
void Enable() { Enabled = true; }
void Disable() { Enabled = false; }
bool IsEnabled() { return Enabled; }
DriverInterruptHook(int Interrupt, DriverFile Handle);
virtual ~DriverInterruptHook() = default;
};
public:
void Enable() { Enabled = true; }
void Disable() { Enabled = false; }
bool IsEnabled() { return Enabled; }
DriverInterruptHook(int Interrupt, DriverFile Handle);
virtual ~DriverInterruptHook() = default;
};
class Driver
{
private:
std::vector<DriverFile> Drivers;
unsigned long DriverUIDs = 0;
DriverCode CallDriverEntryPoint(void *fex, void *KAPIAddress);
class Driver
{
private:
NewLock(DriverInitLock);
void MapPCIAddresses(PCI::PCIDeviceHeader *PCIDevice);
DriverCode BindPCIGeneric(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
DriverCode BindPCIDisplay(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
DriverCode BindPCINetwork(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
DriverCode BindPCIStorage(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
DriverCode BindPCIFileSystem(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
DriverCode BindPCIInput(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
DriverCode BindPCIAudio(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
DriverCode DriverLoadBindPCI(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf = false);
std::vector<DriverFile> Drivers;
unsigned int DriverUIDs = 0;
/* If BuiltIn is true, the "fex" is the entry point. */
DriverCode CallDriverEntryPoint(void *fex, bool BuiltIn = false);
DriverCode BindInterruptGeneric(Memory::MemMgr *mem, void *fex);
DriverCode BindInterruptDisplay(Memory::MemMgr *mem, void *fex);
DriverCode BindInterruptNetwork(Memory::MemMgr *mem, void *fex);
DriverCode BindInterruptStorage(Memory::MemMgr *mem, void *fex);
DriverCode BindInterruptFileSystem(Memory::MemMgr *mem, void *fex);
DriverCode BindInterruptInput(Memory::MemMgr *mem, void *fex);
DriverCode BindInterruptAudio(Memory::MemMgr *mem, void *fex);
DriverCode DriverLoadBindInterrupt(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf = false);
public:
/**
* @brief Load and bind a driver to a PCI device.
*
* This function will search for a PCI device with the given VendorID and DeviceID.
* If the device is found, the driver will be loaded and bound to the device.
*
* @param DriverAddress The address of the driver. The file will be copied to a new location.
* @param Size The size of the driver.
* @param IsBuiltIn If the driver is built-in, the @param DriverAddress will be @see BuiltInDriverInfo and the @param Size will be ignored.
* @return DriverCode The result of the operation.
*/
DriverCode DriverLoadBindPCI(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn = false);
DriverCode BindInputGeneric(Memory::MemMgr *mem, void *fex);
DriverCode BindInputDisplay(Memory::MemMgr *mem, void *fex);
DriverCode BindInputNetwork(Memory::MemMgr *mem, void *fex);
DriverCode BindInputStorage(Memory::MemMgr *mem, void *fex);
DriverCode BindInputFileSystem(Memory::MemMgr *mem, void *fex);
DriverCode BindInputInput(Memory::MemMgr *mem, void *fex);
DriverCode BindInputAudio(Memory::MemMgr *mem, void *fex);
DriverCode DriverLoadBindInput(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf = false);
/**
* @brief Load and bind a driver to an interrupt.
*
* This function will search for an interrupt with the given IRQ.
* If the interrupt is found, the driver will be loaded and bound to the interrupt.
*
* @param DriverAddress The address of the driver. The file will be copied to a new location.
* @param Size The size of the driver.
* @param IsBuiltIn If the driver is built-in, the @param DriverAddress will be @see BuiltInDriverInfo and the @param Size will be ignored.
* @return DriverCode The result of the operation.
*/
DriverCode DriverLoadBindInterrupt(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn = false);
DriverCode BindProcessGeneric(Memory::MemMgr *mem, void *fex);
DriverCode BindProcessDisplay(Memory::MemMgr *mem, void *fex);
DriverCode BindProcessNetwork(Memory::MemMgr *mem, void *fex);
DriverCode BindProcessStorage(Memory::MemMgr *mem, void *fex);
DriverCode BindProcessFileSystem(Memory::MemMgr *mem, void *fex);
DriverCode BindProcessInput(Memory::MemMgr *mem, void *fex);
DriverCode BindProcessAudio(Memory::MemMgr *mem, void *fex);
DriverCode DriverLoadBindProcess(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf = false);
/**
* @brief Load and bind a driver to an input device.
*
* This function will attach the driver to the input device.
*
* @param DriverAddress The address of the driver. The file will be copied to a new location.
* @param Size The size of the driver.
* @param IsBuiltIn If the driver is built-in, the @param DriverAddress will be @see BuiltInDriverInfo and the @param Size will be ignored.
* @return DriverCode The result of the operation.
*/
DriverCode DriverLoadBindInput(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn = false);
public:
std::vector<DriverFile> GetDrivers() { return Drivers; }
void Panic();
void UnloadAllDrivers();
bool UnloadDriver(unsigned long DUID);
int IOCB(unsigned long DUID, /* KernelCallback */ void *KCB);
DriverCode LoadDriver(uintptr_t DriverAddress, size_t Size);
DriverCode StartDrivers();
Driver();
~Driver();
};
/**
* @brief Load and bind a driver to a process.
*
* This function will attach the driver to the process.
*
* @param DriverAddress The address of the driver. The file will be copied to a new location.
* @param Size The size of the driver.
* @param IsBuiltIn If the driver is built-in, the @param DriverAddress will be @see BuiltInDriverInfo and the @param Size will be ignored.
* @return DriverCode The result of the operation.
*/
DriverCode DriverLoadBindProcess(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn = false);
/**
* @brief Get the currently loaded drivers.
*
* This function returns a clone of the drivers vector.
* This means that the vector can be modified without affecting the drivers.
*
* @return std::vector<DriverFile> A clone of the drivers vector.
*/
std::vector<DriverFile> GetDrivers() { return Drivers; }
/* Reserved by the kernel */
void Panic();
/**
* @brief Unload all drivers.
*
* This function will unload all drivers.
*/
void UnloadAllDrivers();
/**
* @brief Unload a driver.
*
* This function will unload a driver with the given driver unique ID.
* It will free the memory and remove the driver from the drivers vector.
*
* @param DUID The driver unique ID.
* @return true If the driver was found and unloaded successfully, false otherwise.
*/
bool UnloadDriver(unsigned long DUID);
/**
* @brief Send a callback to a driver.
*
* This function will send a callback to a driver with the given driver unique ID.
* This is used to communicate with drivers.
*
* @param DUID The driver unique ID.
* @param KCB The @see KernelCallback structure.
* @return int The result of the operation.
*/
int IOCB(unsigned long DUID, /* KernelCallback */ void *KCB);
/**
* @brief Load a driver.
* @param DriverAddress The address of the driver file.
* @param Size The size of the driver file.
* @return DriverCode The result of the operation.
*/
DriverCode LoadDriver(uintptr_t DriverAddress, size_t Size);
/* Reserved by the kernel */
void LoadDrivers();
/* Reserved by the kernel */
Driver();
/* Reserved by the kernel */
~Driver();
};
}
#endif // !__FENNIX_KERNEL_DRIVER_H__

View File

@ -26,383 +26,383 @@
namespace GraphicalUserInterface
{
typedef uintptr_t Handle;
typedef uintptr_t Handle;
struct MouseData
{
int64_t X;
int64_t Y;
int64_t Z;
bool Left;
bool Right;
bool Middle;
};
struct MouseData
{
int64_t X;
int64_t Y;
int64_t Z;
bool Left;
bool Right;
bool Middle;
};
struct ScreenBitmap
{
int64_t Width;
int64_t Height;
size_t Size;
size_t Pitch;
uint64_t BitsPerPixel;
uint8_t *Data;
};
struct ScreenBitmap
{
int64_t Width;
int64_t Height;
size_t Size;
size_t Pitch;
uint64_t BitsPerPixel;
uint8_t *Data;
};
struct Rect
{
int64_t Left;
int64_t Top;
size_t Width;
size_t Height;
struct Rect
{
size_t Left;
size_t Top;
size_t Width;
size_t Height;
bool Contains(int64_t X, int64_t Y)
{
return (X >= Left && X <= Left + Width && Y >= Top && Y <= Top + Height);
}
bool Contains(size_t X, size_t Y)
{
return (X >= Left && X <= Left + Width && Y >= Top && Y <= Top + Height);
}
bool Contains(Rect rect)
{
return (rect.Left >= Left && rect.Left + rect.Width <= Left + Width && rect.Top >= Top && rect.Top + rect.Height <= Top + Height);
}
};
bool Contains(Rect rect)
{
return (rect.Left >= Left && rect.Left + rect.Width <= Left + Width && rect.Top >= Top && rect.Top + rect.Height <= Top + Height);
}
};
enum CursorType
{
Visible = 0,
Hidden,
Arrow,
Hand,
Wait,
IBeam,
ResizeHorizontal,
ResizeVertical,
ResizeDiagonalLeft,
ResizeDiagonalRight,
ResizeAll,
Cross,
Help,
No,
AppStarting,
};
enum CursorType
{
Visible = 0,
Hidden,
Arrow,
Hand,
Wait,
IBeam,
ResizeHorizontal,
ResizeVertical,
ResizeDiagonalLeft,
ResizeDiagonalRight,
ResizeAll,
Cross,
Help,
No,
AppStarting,
};
struct Event
{
struct
{
size_t Width;
size_t Height;
} Resize;
struct Event
{
struct
{
size_t Width;
size_t Height;
} Resize;
struct
{
int64_t X;
int64_t Y;
bool Left;
bool Right;
bool Middle;
} MouseDown;
struct
{
int64_t X;
int64_t Y;
bool Left;
bool Right;
bool Middle;
} MouseDown;
struct
{
int64_t X;
int64_t Y;
bool Left;
bool Right;
bool Middle;
} MouseUp;
struct
{
int64_t X;
int64_t Y;
bool Left;
bool Right;
bool Middle;
} MouseUp;
struct
{
int64_t X;
int64_t Y;
bool Left;
bool Right;
bool Middle;
} MouseMove;
};
struct
{
int64_t X;
int64_t Y;
bool Left;
bool Right;
bool Middle;
} MouseMove;
};
/*
virtual void OnMouseMove(Event *e) {}
virtual void OnMouseClick(Event *e) {}
virtual void OnMouseDoubleClick(Event *e) {}
virtual void OnMouseDown(Event *e) {}
virtual void OnMouseUp(Event *e) {}
virtual void OnMouseWheel(Event *e) {}
virtual void OnMouseEnter(Event *e) {}
virtual void OnMouseLeave(Event *e) {}
virtual void OnMouseHover(Event *e) {}
virtual void OnMouseDrag(Event *e) {}
virtual void OnMouseDragStart(Event *e) {}
virtual void OnMouseDragEnd(Event *e) {}
virtual void OnMouseDragEnter(Event *e) {}
virtual void OnMouseDragLeave(Event *e) {}
virtual void OnMouseDragHover(Event *e) {}
virtual void OnMouseDragDrop(Event *e) {}
virtual void OnMouseDragDropEnter(Event *e) {}
virtual void OnMouseDragDropLeave(Event *e) {}
virtual void OnMouseDragDropHover(Event *e) {}
virtual void OnMouseDragDropEnd(Event *e) {}
virtual void OnMouseDragDropStart(Event *e) {}
virtual void OnMouseDragDropCancel(Event *e) {}
virtual void OnMouseDragDropComplete(Event *e) {}
virtual void OnMouseDragDropAbort(Event *e) {}
/*
virtual void OnMouseMove(Event *e) {}
virtual void OnMouseClick(Event *e) {}
virtual void OnMouseDoubleClick(Event *e) {}
virtual void OnMouseDown(Event *e) {}
virtual void OnMouseUp(Event *e) {}
virtual void OnMouseWheel(Event *e) {}
virtual void OnMouseEnter(Event *e) {}
virtual void OnMouseLeave(Event *e) {}
virtual void OnMouseHover(Event *e) {}
virtual void OnMouseDrag(Event *e) {}
virtual void OnMouseDragStart(Event *e) {}
virtual void OnMouseDragEnd(Event *e) {}
virtual void OnMouseDragEnter(Event *e) {}
virtual void OnMouseDragLeave(Event *e) {}
virtual void OnMouseDragHover(Event *e) {}
virtual void OnMouseDragDrop(Event *e) {}
virtual void OnMouseDragDropEnter(Event *e) {}
virtual void OnMouseDragDropLeave(Event *e) {}
virtual void OnMouseDragDropHover(Event *e) {}
virtual void OnMouseDragDropEnd(Event *e) {}
virtual void OnMouseDragDropStart(Event *e) {}
virtual void OnMouseDragDropCancel(Event *e) {}
virtual void OnMouseDragDropComplete(Event *e) {}
virtual void OnMouseDragDropAbort(Event *e) {}
virtual void OnKeyDown(Event *e) {}
virtual void OnKeyUp(Event *e) {}
virtual void OnKeyPress(Event *e) {}
virtual void OnKeyDown(Event *e) {}
virtual void OnKeyUp(Event *e) {}
virtual void OnKeyPress(Event *e) {}
virtual void OnFocusEnter(Event *e) {}
virtual void OnFocusLeave(Event *e) {}
virtual void OnFocusHover(Event *e) {}
virtual void OnFocusEnter(Event *e) {}
virtual void OnFocusLeave(Event *e) {}
virtual void OnFocusHover(Event *e) {}
virtual void OnResize(Event *e) {}
virtual void OnMinimize(Event *e) {}
virtual void OnMaximize(Event *e) {}
virtual void OnMove(Event *e) {}
virtual void OnShow(Event *e) {}
virtual void OnHide(Event *e) {}
virtual void OnClose(Event *e) {}
virtual void OnDestroy(Event *e) {}
virtual void OnResize(Event *e) {}
virtual void OnMinimize(Event *e) {}
virtual void OnMaximize(Event *e) {}
virtual void OnMove(Event *e) {}
virtual void OnShow(Event *e) {}
virtual void OnHide(Event *e) {}
virtual void OnClose(Event *e) {}
virtual void OnDestroy(Event *e) {}
virtual void OnPaint(Event *e) {}
virtual void OnPaintBackground(Event *e) {}
virtual void OnPaintForeground(Event *e) {}
virtual void OnPaintOverlay(Event *e) {}
virtual void OnPaintAll(Event *e) {}
virtual void OnPaintChildren(Event *e) {}
virtual void OnPaintChildrenBackground(Event *e) {}
virtual void OnPaintChildrenForeground(Event *e) {}
virtual void OnPaintChildrenBorder(Event *e) {}
virtual void OnPaintChildrenShadow(Event *e) {}
virtual void OnPaintChildrenOverlay(Event *e) {}
virtual void OnPaintChildrenAll(Event *e) {}
*/
virtual void OnPaint(Event *e) {}
virtual void OnPaintBackground(Event *e) {}
virtual void OnPaintForeground(Event *e) {}
virtual void OnPaintOverlay(Event *e) {}
virtual void OnPaintAll(Event *e) {}
virtual void OnPaintChildren(Event *e) {}
virtual void OnPaintChildrenBackground(Event *e) {}
virtual void OnPaintChildrenForeground(Event *e) {}
virtual void OnPaintChildrenBorder(Event *e) {}
virtual void OnPaintChildrenShadow(Event *e) {}
virtual void OnPaintChildrenOverlay(Event *e) {}
virtual void OnPaintChildrenAll(Event *e) {}
*/
void SetPixel(ScreenBitmap *Bitmap, int64_t X, int64_t Y, uint32_t Color);
void DrawOverBitmap(ScreenBitmap *DestinationBitmap,
ScreenBitmap *SourceBitmap,
int64_t Top,
int64_t Left,
bool IgnoreZero = true);
void PutRect(ScreenBitmap *Bitmap, Rect rect, uint32_t Color);
void PutBorder(ScreenBitmap *Bitmap, Rect rect, uint32_t Color);
uint32_t BlendColors(uint32_t c1, uint32_t c2, float t);
void PutBorderWithShadow(ScreenBitmap *Bitmap, Rect rect, uint32_t Color);
void DrawShadow(ScreenBitmap *Bitmap, Rect rect);
void PaintChar(Video::Font *font, ScreenBitmap *Bitmap, char c, uint32_t Color, int64_t *CharCursorX, int64_t *CharCursorY);
void DrawString(ScreenBitmap *Bitmap, Rect rect, const char *Text, uint32_t Color);
void SetPixel(ScreenBitmap *Bitmap, int64_t X, int64_t Y, uint32_t Color);
void DrawOverBitmap(ScreenBitmap *DestinationBitmap,
ScreenBitmap *SourceBitmap,
int64_t Top,
int64_t Left,
bool IgnoreZero = true);
void PutRect(ScreenBitmap *Bitmap, Rect rect, uint32_t Color);
void PutBorder(ScreenBitmap *Bitmap, Rect rect, uint32_t Color);
uint32_t BlendColors(uint32_t c1, uint32_t c2, float t);
void PutBorderWithShadow(ScreenBitmap *Bitmap, Rect rect, uint32_t Color);
void DrawShadow(ScreenBitmap *Bitmap, Rect rect);
void PaintChar(Video::Font *font, ScreenBitmap *Bitmap, char c, uint32_t Color, int64_t *CharCursorX, int64_t *CharCursorY);
void DrawString(ScreenBitmap *Bitmap, Rect rect, const char *Text, uint32_t Color);
class WidgetCollection
{
private:
Memory::MemMgr *mem;
ScreenBitmap *Buffer;
Video::Font *CurrentFont;
void *ParentWindow;
bool NeedRedraw;
class WidgetCollection
{
private:
Memory::MemMgr *mem;
ScreenBitmap *Buffer;
Video::Font *CurrentFont;
void *ParentWindow;
bool NeedRedraw;
struct HandleMeta
{
char Type[4];
};
struct HandleMeta
{
char Type[4];
};
struct LabelObject
{
HandleMeta Handle;
Rect rect;
char Text[512];
uint32_t Color;
int64_t CharCursorX, CharCursorY;
};
struct LabelObject
{
HandleMeta Handle;
Rect rect;
char Text[512];
uint32_t Color;
int64_t CharCursorX, CharCursorY;
};
struct PanelObject
{
HandleMeta Handle;
Rect rect;
uint32_t Color;
uint32_t BorderColor;
uint32_t ShadowColor;
bool Shadow;
};
struct PanelObject
{
HandleMeta Handle;
Rect rect;
uint32_t Color;
uint32_t BorderColor;
uint32_t ShadowColor;
bool Shadow;
};
struct ButtonObject
{
HandleMeta Handle;
Rect rect;
char Text[512];
uint32_t Color;
uint32_t HoverColor;
uint32_t PressedColor;
uint32_t BorderColor;
uint32_t ShadowColor;
int64_t CharCursorX, CharCursorY;
bool Shadow;
bool Hover;
bool Pressed;
uintptr_t OnClick;
};
struct ButtonObject
{
HandleMeta Handle;
Rect rect;
char Text[512];
uint32_t Color;
uint32_t HoverColor;
uint32_t PressedColor;
uint32_t BorderColor;
uint32_t ShadowColor;
int64_t CharCursorX, CharCursorY;
bool Shadow;
bool Hover;
bool Pressed;
uintptr_t OnClick;
};
std::vector<LabelObject *> Labels;
std::vector<PanelObject *> Panels;
std::vector<ButtonObject *> Buttons;
std::vector<LabelObject *> Labels;
std::vector<PanelObject *> Panels;
std::vector<ButtonObject *> Buttons;
public:
void ReplaceFont(Video::Font *NewFont)
{
delete this->CurrentFont;
this->CurrentFont = NewFont;
}
public:
void ReplaceFont(Video::Font *NewFont)
{
delete this->CurrentFont;
this->CurrentFont = NewFont;
}
Handle CreatePanel(Rect rect, uint32_t Color);
Handle CreateButton(Rect rect, const char *Text, uintptr_t OnClick = (uintptr_t) nullptr);
Handle CreateLabel(Rect rect, const char *Text);
Handle CreateTextBox(Rect rect, const char *Text);
Handle CreateCheckBox(Rect rect, const char *Text);
Handle CreateRadioButton(Rect rect, const char *Text);
Handle CreateComboBox(Rect rect, const char *Text);
Handle CreateListBox(Rect rect, const char *Text);
Handle CreateProgressBar(Rect rect, const char *Text);
Handle CreateContextMenu(Rect rect, const char *Text);
Handle CreatePanel(Rect rect, uint32_t Color);
Handle CreateButton(Rect rect, const char *Text, uintptr_t OnClick = (uintptr_t) nullptr);
Handle CreateLabel(Rect rect, const char *Text);
Handle CreateTextBox(Rect rect, const char *Text);
Handle CreateCheckBox(Rect rect, const char *Text);
Handle CreateRadioButton(Rect rect, const char *Text);
Handle CreateComboBox(Rect rect, const char *Text);
Handle CreateListBox(Rect rect, const char *Text);
Handle CreateProgressBar(Rect rect, const char *Text);
Handle CreateContextMenu(Rect rect, const char *Text);
void SetText(Handle handle, const char *Text);
void SetText(Handle handle, const char *Text);
WidgetCollection(void /* Window */ *ParentWindow);
~WidgetCollection();
WidgetCollection(void /* Window */ *ParentWindow);
~WidgetCollection();
void OnMouseMove(Event *e);
void OnMouseClick(Event *e);
void OnMouseDoubleClick(Event *e);
void OnMouseDown(Event *e);
void OnMouseUp(Event *e);
void OnMouseWheel(Event *e);
void OnMouseEnter(Event *e);
void OnMouseLeave(Event *e);
void OnMouseHover(Event *e);
void OnMouseDrag(Event *e);
void OnMouseDragStart(Event *e);
void OnMouseDragEnd(Event *e);
void OnMouseMove(Event *e);
void OnMouseClick(Event *e);
void OnMouseDoubleClick(Event *e);
void OnMouseDown(Event *e);
void OnMouseUp(Event *e);
void OnMouseWheel(Event *e);
void OnMouseEnter(Event *e);
void OnMouseLeave(Event *e);
void OnMouseHover(Event *e);
void OnMouseDrag(Event *e);
void OnMouseDragStart(Event *e);
void OnMouseDragEnd(Event *e);
void OnKeyDown(Event *e);
void OnKeyUp(Event *e);
void OnKeyPress(Event *e);
void OnKeyDown(Event *e);
void OnKeyUp(Event *e);
void OnKeyPress(Event *e);
void OnShow(Event *e);
void OnHide(Event *e);
void OnDestroy(Event *e);
void OnShow(Event *e);
void OnHide(Event *e);
void OnDestroy(Event *e);
void OnPaint(Event *e);
void OnPaintBackground(Event *e);
void OnPaintForeground(Event *e);
};
void OnPaint(Event *e);
void OnPaintBackground(Event *e);
void OnPaintForeground(Event *e);
};
class Window
{
private:
Memory::MemMgr *mem;
ScreenBitmap *Buffer;
Rect Position;
Rect LastPosition;
char Title[256];
std::vector<WidgetCollection *> Widgets;
void *ParentGUI;
class Window
{
private:
Memory::MemMgr *mem;
ScreenBitmap *Buffer;
Rect Position;
Rect LastPosition;
char Title[256];
std::vector<WidgetCollection *> Widgets;
void *ParentGUI;
bool Maximized;
bool Minimized;
bool Maximized;
bool Minimized;
public:
bool IsMaximized() { return Maximized; }
bool IsMinimized() { return Minimized; }
ScreenBitmap *GetBuffer() { return Buffer; }
Rect GetPosition() { return Position; }
Rect *GetPositionPtr() { return &Position; }
const char *GetTitle() { return (const char *)Title; }
void SetTitle(const char *Title) { strcpy(this->Title, Title); }
void AddWidget(WidgetCollection *widget);
public:
bool IsMaximized() { return Maximized; }
bool IsMinimized() { return Minimized; }
ScreenBitmap *GetBuffer() { return Buffer; }
Rect GetPosition() { return Position; }
Rect *GetPositionPtr() { return &Position; }
const char *GetTitle() { return (const char *)Title; }
void SetTitle(const char *Title) { strcpy(this->Title, Title); }
void AddWidget(WidgetCollection *widget);
Window(void *ParentGUI, Rect rect, const char *Title);
~Window();
Window(void *ParentGUI, Rect rect, const char *Title);
~Window();
void OnMouseMove(Event *e);
void OnMouseClick(Event *e);
void OnMouseDoubleClick(Event *e);
void OnMouseDown(Event *e);
void OnMouseUp(Event *e);
void OnMouseWheel(Event *e);
void OnMouseEnter(Event *e);
void OnMouseLeave(Event *e);
void OnMouseHover(Event *e);
void OnMouseDrag(Event *e);
void OnMouseDragStart(Event *e);
void OnMouseDragEnd(Event *e);
void OnMouseMove(Event *e);
void OnMouseClick(Event *e);
void OnMouseDoubleClick(Event *e);
void OnMouseDown(Event *e);
void OnMouseUp(Event *e);
void OnMouseWheel(Event *e);
void OnMouseEnter(Event *e);
void OnMouseLeave(Event *e);
void OnMouseHover(Event *e);
void OnMouseDrag(Event *e);
void OnMouseDragStart(Event *e);
void OnMouseDragEnd(Event *e);
void OnKeyDown(Event *e);
void OnKeyUp(Event *e);
void OnKeyPress(Event *e);
void OnKeyDown(Event *e);
void OnKeyUp(Event *e);
void OnKeyPress(Event *e);
void OnFocusEnter(Event *e);
void OnFocusLeave(Event *e);
void OnFocusHover(Event *e);
void OnFocusEnter(Event *e);
void OnFocusLeave(Event *e);
void OnFocusHover(Event *e);
void OnResize(Event *e);
void OnMinimize(Event *e);
void OnMaximize(Event *e);
void OnMove(Event *e);
void OnShow(Event *e);
void OnHide(Event *e);
void OnClose(Event *e);
void OnDestroy(Event *e);
void OnResize(Event *e);
void OnMinimize(Event *e);
void OnMaximize(Event *e);
void OnMove(Event *e);
void OnShow(Event *e);
void OnHide(Event *e);
void OnClose(Event *e);
void OnDestroy(Event *e);
void OnPaint(Event *e);
void OnPaintBackground(Event *e);
void OnPaintForeground(Event *e);
void OnPaintOverlay(Event *e);
void OnPaintAll(Event *e);
void OnPaintChildren(Event *e);
void OnPaintChildrenBackground(Event *e);
void OnPaintChildrenForeground(Event *e);
void OnPaintChildrenBorder(Event *e);
void OnPaintChildrenShadow(Event *e);
void OnPaintChildrenOverlay(Event *e);
void OnPaintChildrenAll(Event *e);
};
void OnPaint(Event *e);
void OnPaintBackground(Event *e);
void OnPaintForeground(Event *e);
void OnPaintOverlay(Event *e);
void OnPaintAll(Event *e);
void OnPaintChildren(Event *e);
void OnPaintChildrenBackground(Event *e);
void OnPaintChildrenForeground(Event *e);
void OnPaintChildrenBorder(Event *e);
void OnPaintChildrenShadow(Event *e);
void OnPaintChildrenOverlay(Event *e);
void OnPaintChildrenAll(Event *e);
};
class GUI
{
private:
MouseData MouseArray[256];
Memory::MemMgr *mem;
Video::Font *CurrentFont;
Rect Desktop;
ScreenBitmap *BackBuffer;
ScreenBitmap *DesktopBuffer;
ScreenBitmap *OverlayBuffer;
ScreenBitmap *CursorBuffer;
std::vector<WidgetCollection *> Widgets;
std::vector<Window *> Windows;
CursorType Cursor = CursorType::Arrow;
CursorType LastCursor = CursorType::Arrow;
bool CursorVisible = true;
bool IsRunning = false;
class GUI
{
private:
MouseData MouseArray[256];
Memory::MemMgr *mem;
Video::Font *CurrentFont;
Rect Desktop;
ScreenBitmap *BackBuffer;
ScreenBitmap *DesktopBuffer;
ScreenBitmap *OverlayBuffer;
ScreenBitmap *CursorBuffer;
std::vector<WidgetCollection *> Widgets;
std::vector<Window *> Windows;
CursorType Cursor = CursorType::Arrow;
CursorType LastCursor = CursorType::Arrow;
bool CursorVisible = true;
bool IsRunning = false;
bool DesktopBufferRepaint = true;
bool OverlayBufferRepaint = true;
bool OverlayFullRepaint = true;
bool CursorBufferRepaint = true;
bool DesktopBufferRepaint = true;
bool OverlayBufferRepaint = true;
bool OverlayFullRepaint = true;
bool CursorBufferRepaint = true;
void FetchInputs();
void PaintDesktop();
void PaintWidgets();
void PaintWindows();
void PaintCursor();
void FetchInputs();
void PaintDesktop();
void PaintWidgets();
void PaintWindows();
void PaintCursor();
public:
void SetCursorType(CursorType Type = CursorType::Visible) { this->Cursor = Type; }
void Loop();
void AddWindow(Window *window);
void AddWidget(WidgetCollection *widget);
GUI();
~GUI();
};
public:
void SetCursorType(CursorType Type = CursorType::Visible) { this->Cursor = Type; }
void Loop();
void AddWindow(Window *window);
void AddWidget(WidgetCollection *widget);
GUI();
~GUI();
};
}
#endif // !__FENNIX_KERNEL_GUI_H__

View File

@ -20,221 +20,223 @@
#include <types.h>
#include <memory.hpp>
#include <debug.h>
#include <vector>
namespace PCI
{
namespace Descriptors
{
enum PCIVendors
{
SymbiosLogic = 0x1000,
RedHat = 0x1AF4,
REDHat2 = 0x1B36,
Realtek = 0x10EC,
VirtualBox = 0x80EE,
Ensoniq = 0x1274,
QEMU = 0x1234,
VMware = 0x15AD,
IntelCorporation = 0x8086,
AdvancedMicroDevices = 0x1022,
NVIDIACorporation = 0x10DE
};
namespace Descriptors
{
enum PCIVendors
{
SymbiosLogic = 0x1000,
RedHat = 0x1AF4,
REDHat2 = 0x1B36,
Realtek = 0x10EC,
VirtualBox = 0x80EE,
Ensoniq = 0x1274,
QEMU = 0x1234,
VMware = 0x15AD,
IntelCorporation = 0x8086,
AdvancedMicroDevices = 0x1022,
NVIDIACorporation = 0x10DE
};
const char *const DeviceClasses[]{
"Unclassified",
"Mass Storage Controller",
"Network Controller",
"Display Controller",
"Multimedia Controller",
"Memory Controller",
"Bridge Device",
"Simple Communication Controller",
"Base System Peripheral",
"Input Device Controller",
"Docking Station",
"Processor",
"Serial Bus Controller",
"Wireless Controller",
"Intelligent Controller",
"Satellite Communication Controller",
"Encryption Controller",
"Signal Processing Controller",
"Processing Accelerator",
"Non Essential Instrumentation"};
const char *const DeviceClasses[]{
"Unclassified",
"Mass Storage Controller",
"Network Controller",
"Display Controller",
"Multimedia Controller",
"Memory Controller",
"Bridge Device",
"Simple Communication Controller",
"Base System Peripheral",
"Input Device Controller",
"Docking Station",
"Processor",
"Serial Bus Controller",
"Wireless Controller",
"Intelligent Controller",
"Satellite Communication Controller",
"Encryption Controller",
"Signal Processing Controller",
"Processing Accelerator",
"Non Essential Instrumentation"};
const char *MassStorageControllerSubclassName(uint8_t SubclassCode);
const char *NetworkControllerSubclassName(uint8_t SubclassCode);
const char *DisplayControllerSubclassName(uint8_t SubclassCode);
const char *CommunicationControllerSubclassName(uint8_t SubclassCode);
const char *BaseSystemPeripheralSubclassName(uint8_t SubclassCode);
const char *SerialBusControllerSubclassName(uint8_t SubclassCode);
const char *BridgeDeviceSubclassName(uint8_t SubclassCode);
const char *WirelessControllerSubclassName(uint8_t SubclassCode);
const char *GetVendorName(uint32_t VendorID);
const char *GetDeviceName(uint32_t VendorID, uint32_t DeviceID);
const char *GetSubclassName(uint8_t ClassCode, uint8_t SubclassCode);
const char *GetProgIFName(uint8_t ClassCode, uint8_t SubclassCode, uint8_t ProgIF);
}
const char *MassStorageControllerSubclassName(uint8_t SubclassCode);
const char *NetworkControllerSubclassName(uint8_t SubclassCode);
const char *DisplayControllerSubclassName(uint8_t SubclassCode);
const char *CommunicationControllerSubclassName(uint8_t SubclassCode);
const char *BaseSystemPeripheralSubclassName(uint8_t SubclassCode);
const char *SerialBusControllerSubclassName(uint8_t SubclassCode);
const char *BridgeDeviceSubclassName(uint8_t SubclassCode);
const char *WirelessControllerSubclassName(uint8_t SubclassCode);
const char *GetVendorName(uint32_t VendorID);
const char *GetDeviceName(uint32_t VendorID, uint32_t DeviceID);
const char *GetSubclassName(uint8_t ClassCode, uint8_t SubclassCode);
const char *GetProgIFName(uint8_t ClassCode, uint8_t SubclassCode, uint8_t ProgIF);
}
/* https://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html */
enum PCICommands
{
/** @brief Enable response in I/O space */
PCI_COMMAND_IO = 0x1,
/** @brief Enable response in Memory space */
PCI_COMMAND_MEMORY = 0x2,
/** @brief Enable bus mastering */
PCI_COMMAND_MASTER = 0x4,
/** @brief Enable response to special cycles */
PCI_COMMAND_SPECIAL = 0x8,
/** @brief Use memory write and invalidate */
PCI_COMMAND_INVALIDATE = 0x10,
/** @brief Enable palette snooping */
PCI_COMMAND_VGA_PALETTE = 0x20,
/** @brief Enable parity checking */
PCI_COMMAND_PARITY = 0x40,
/** @brief Enable address/data stepping */
PCI_COMMAND_WAIT = 0x80,
/** @brief Enable SERR */
PCI_COMMAND_SERR = 0x100,
/** @brief Enable back-to-back writes */
PCI_COMMAND_FAST_BACK = 0x200,
/** @brief INTx Emulation Disable */
PCI_COMMAND_INTX_DISABLE = 0x400
};
/* https://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html */
enum PCICommands
{
/** @brief Enable response in I/O space */
PCI_COMMAND_IO = 0x1,
/** @brief Enable response in Memory space */
PCI_COMMAND_MEMORY = 0x2,
/** @brief Enable bus mastering */
PCI_COMMAND_MASTER = 0x4,
/** @brief Enable response to special cycles */
PCI_COMMAND_SPECIAL = 0x8,
/** @brief Use memory write and invalidate */
PCI_COMMAND_INVALIDATE = 0x10,
/** @brief Enable palette snooping */
PCI_COMMAND_VGA_PALETTE = 0x20,
/** @brief Enable parity checking */
PCI_COMMAND_PARITY = 0x40,
/** @brief Enable address/data stepping */
PCI_COMMAND_WAIT = 0x80,
/** @brief Enable SERR */
PCI_COMMAND_SERR = 0x100,
/** @brief Enable back-to-back writes */
PCI_COMMAND_FAST_BACK = 0x200,
/** @brief INTx Emulation Disable */
PCI_COMMAND_INTX_DISABLE = 0x400
};
struct PCIDeviceHeader
{
uint16_t VendorID;
uint16_t DeviceID;
uint16_t Command;
uint16_t Status;
uint8_t RevisionID;
uint8_t ProgIF;
uint8_t Subclass;
uint8_t Class;
uint8_t CacheLineSize;
uint8_t LatencyTimer;
uint8_t HeaderType;
uint8_t BIST;
};
struct PCIDeviceHeader
{
uint16_t VendorID;
uint16_t DeviceID;
uint16_t Command;
uint16_t Status;
uint8_t RevisionID;
uint8_t ProgIF;
uint8_t Subclass;
uint8_t Class;
uint8_t CacheLineSize;
uint8_t LatencyTimer;
uint8_t HeaderType;
uint8_t BIST;
};
/**
* @brief PCI Header Type 0
*
*/
struct PCIHeader0
{
PCIDeviceHeader Header;
uint32_t BAR0;
uint32_t BAR1;
uint32_t BAR2;
uint32_t BAR3;
uint32_t BAR4;
uint32_t BAR5;
uint32_t CardbusCISPointer;
uint16_t SubsystemVendorID;
uint16_t SubsystemID;
uint32_t ExpansionROMBaseAddress;
uint8_t CapabilitiesPointer;
uint8_t Reserved0;
uint16_t Reserved1;
uint32_t Reserved2;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint8_t MinGrant;
uint8_t MaxLatency;
};
/**
* @brief PCI Header Type 0
*
*/
struct PCIHeader0
{
PCIDeviceHeader Header;
uint32_t BAR0;
uint32_t BAR1;
uint32_t BAR2;
uint32_t BAR3;
uint32_t BAR4;
uint32_t BAR5;
uint32_t CardbusCISPointer;
uint16_t SubsystemVendorID;
uint16_t SubsystemID;
uint32_t ExpansionROMBaseAddress;
uint8_t CapabilitiesPointer;
uint8_t Reserved0;
uint16_t Reserved1;
uint32_t Reserved2;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint8_t MinGrant;
uint8_t MaxLatency;
};
/**
* @brief PCI Header Type 1 (PCI-to-PCI Bridge)
*/
struct PCIHeader1
{
PCIDeviceHeader Header;
uint32_t BAR0;
uint32_t BAR1;
uint8_t PrimaryBusNumber;
uint8_t SecondaryBusNumber;
uint8_t SubordinateBusNumber;
uint8_t SecondaryLatencyTimer;
uint8_t IOBase;
uint8_t IOLimit;
uint16_t SecondaryStatus;
uint16_t MemoryBase;
uint16_t MemoryLimit;
uint16_t PrefetchableMemoryBase;
uint16_t PrefetchableMemoryLimit;
uint32_t PrefetchableMemoryBaseUpper32;
uint32_t PrefetchableMemoryLimitUpper32;
uint16_t IOBaseUpper16;
uint16_t IOLimitUpper16;
uint8_t CapabilitiesPointer;
uint8_t Reserved0;
uint16_t Reserved1;
uint32_t ExpansionROMBaseAddress;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint16_t BridgeControl;
};
/**
* @brief PCI Header Type 1 (PCI-to-PCI Bridge)
*/
struct PCIHeader1
{
PCIDeviceHeader Header;
uint32_t BAR0;
uint32_t BAR1;
uint8_t PrimaryBusNumber;
uint8_t SecondaryBusNumber;
uint8_t SubordinateBusNumber;
uint8_t SecondaryLatencyTimer;
uint8_t IOBase;
uint8_t IOLimit;
uint16_t SecondaryStatus;
uint16_t MemoryBase;
uint16_t MemoryLimit;
uint16_t PrefetchableMemoryBase;
uint16_t PrefetchableMemoryLimit;
uint32_t PrefetchableMemoryBaseUpper32;
uint32_t PrefetchableMemoryLimitUpper32;
uint16_t IOBaseUpper16;
uint16_t IOLimitUpper16;
uint8_t CapabilitiesPointer;
uint8_t Reserved0;
uint16_t Reserved1;
uint32_t ExpansionROMBaseAddress;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint16_t BridgeControl;
};
/**
* @brief PCI Header Type 2 (PCI-to-CardBus Bridge)
*/
struct PCIHeader2
{
PCIDeviceHeader Header;
uint32_t CardbusSocketRegistersBaseAddress;
uint8_t CapabilitiesPointer;
uint8_t Reserved0;
uint16_t SecondaryStatus;
uint8_t PCIbusNumber;
uint8_t CardbusBusNumber;
uint8_t SubordinateBusNumber;
uint8_t CardbusLatencyTimer;
uint32_t MemoryBase0;
uint32_t MemoryLimit0;
uint32_t MemoryBase1;
uint32_t MemoryLimit1;
uint32_t IOBase0;
uint32_t IOLimit0;
uint32_t IOBase1;
uint32_t IOLimit1;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint16_t BridgeControl;
uint16_t SubsystemVendorID;
uint16_t SubsystemID;
uint32_t LegacyBaseAddress;
};
/**
* @brief PCI Header Type 2 (PCI-to-CardBus Bridge)
*/
struct PCIHeader2
{
PCIDeviceHeader Header;
uint32_t CardbusSocketRegistersBaseAddress;
uint8_t CapabilitiesPointer;
uint8_t Reserved0;
uint16_t SecondaryStatus;
uint8_t PCIbusNumber;
uint8_t CardbusBusNumber;
uint8_t SubordinateBusNumber;
uint8_t CardbusLatencyTimer;
uint32_t MemoryBase0;
uint32_t MemoryLimit0;
uint32_t MemoryBase1;
uint32_t MemoryLimit1;
uint32_t IOBase0;
uint32_t IOLimit0;
uint32_t IOBase1;
uint32_t IOLimit1;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint16_t BridgeControl;
uint16_t SubsystemVendorID;
uint16_t SubsystemID;
uint32_t LegacyBaseAddress;
};
struct DeviceConfig
{
uintptr_t BaseAddress;
uint16_t PCISegGroup;
uint8_t StartBus;
uint8_t EndBus;
uint32_t Reserved;
} __packed;
struct DeviceConfig
{
uintptr_t BaseAddress;
uint16_t PCISegGroup;
uint8_t StartBus;
uint8_t EndBus;
uint32_t Reserved;
} __packed;
class PCI
{
private:
std::vector<PCIDeviceHeader *> Devices;
class PCI
{
private:
std::vector<PCIDeviceHeader *> Devices;
public:
std::vector<PCIDeviceHeader *> &GetDevices() { return Devices; }
void EnumerateFunction(uintptr_t DeviceAddress, uintptr_t Function);
void EnumerateDevice(uintptr_t BusAddress, uintptr_t Device);
void EnumerateBus(uintptr_t BaseAddress, uintptr_t Bus);
std::vector<PCIDeviceHeader *> FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF);
std::vector<PCIDeviceHeader *> FindPCIDevice(int VendorID, int DeviceID);
public:
std::vector<PCIDeviceHeader *> &GetDevices() { return Devices; }
void MapPCIAddresses(PCIDeviceHeader *PCIDevice, Memory::PageTable *Table = nullptr);
void EnumerateFunction(uintptr_t DeviceAddress, uintptr_t Function);
void EnumerateDevice(uintptr_t BusAddress, uintptr_t Device);
void EnumerateBus(uintptr_t BaseAddress, uintptr_t Bus);
std::vector<PCIDeviceHeader *> FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF);
std::vector<PCIDeviceHeader *> FindPCIDevice(int VendorID, int DeviceID);
PCI();
~PCI();
};
PCI();
~PCI();
};
}
#endif // !__FENNIX_KERNEL_PCI_H__

View File

@ -32,331 +32,331 @@
namespace Tasking
{
typedef unsigned long IP;
typedef __UINTPTR_TYPE__ IPOffset;
typedef unsigned long UPID;
typedef unsigned long UTID;
typedef __UINTPTR_TYPE__ Token;
typedef unsigned long IP;
typedef __UINTPTR_TYPE__ IPOffset;
typedef unsigned long UPID;
typedef unsigned long UTID;
typedef __UINTPTR_TYPE__ Token;
enum TaskArchitecture
{
UnknownArchitecture,
x32,
x64,
ARM32,
ARM64
};
enum TaskArchitecture
{
UnknownArchitecture,
x32,
x64,
ARM32,
ARM64
};
enum TaskCompatibility
{
UnknownPlatform,
Native,
Linux,
Windows
};
enum TaskCompatibility
{
UnknownPlatform,
Native,
Linux,
Windows
};
enum TaskTrustLevel
{
UnknownElevation,
Kernel,
System,
User
};
enum TaskTrustLevel
{
UnknownElevation,
Kernel,
System,
User
};
enum TaskStatus
{
UnknownStatus,
Ready,
Running,
Sleeping,
Waiting,
Stopped,
Terminated
};
enum TaskStatus
{
UnknownStatus,
Ready,
Running,
Sleeping,
Waiting,
Stopped,
Terminated
};
enum TaskPriority
{
UnknownPriority = 0,
Idle = 1,
Low = 2,
Normal = 5,
High = 8,
Critical = 10
};
enum TaskPriority
{
UnknownPriority = 0,
Idle = 1,
Low = 2,
Normal = 5,
High = 8,
Critical = 10
};
struct TaskSecurity
{
TaskTrustLevel TrustLevel;
Token UniqueToken;
bool IsCritical;
bool IsDebugEnabled;
bool IsKernelDebugEnabled;
};
struct TaskSecurity
{
TaskTrustLevel TrustLevel;
Token UniqueToken;
bool IsCritical;
bool IsDebugEnabled;
bool IsKernelDebugEnabled;
};
struct TaskInfo
{
uint64_t OldUserTime = 0;
uint64_t OldKernelTime = 0;
struct TaskInfo
{
size_t OldUserTime = 0;
size_t OldKernelTime = 0;
uint64_t SleepUntil = 0;
uint64_t KernelTime = 0, UserTime = 0, SpawnTime = 0, LastUpdateTime = 0;
uint64_t Year, Month, Day, Hour, Minute, Second;
bool Affinity[256]; // MAX_CPU
TaskPriority Priority;
TaskArchitecture Architecture;
TaskCompatibility Compatibility;
};
size_t SleepUntil = 0;
size_t KernelTime = 0, UserTime = 0, SpawnTime = 0, LastUpdateTime = 0;
uint64_t Year, Month, Day, Hour, Minute, Second;
bool Affinity[256]; // MAX_CPU
TaskPriority Priority;
TaskArchitecture Architecture;
TaskCompatibility Compatibility;
};
struct TCB
{
UTID ID;
char Name[256];
struct PCB *Parent;
IP EntryPoint;
IPOffset Offset;
int ExitCode;
Memory::StackGuard *Stack;
Memory::MemMgr *Memory;
TaskStatus Status;
struct TCB
{
UTID ID;
char Name[256];
struct PCB *Parent;
IP EntryPoint;
IPOffset Offset;
int ExitCode;
Memory::StackGuard *Stack;
Memory::MemMgr *Memory;
TaskStatus Status;
#if defined(a64)
CPU::x64::TrapFrame Registers;
uint64_t ShadowGSBase, GSBase, FSBase;
CPU::x64::TrapFrame Registers;
uint64_t ShadowGSBase, GSBase, FSBase;
#elif defined(a32)
CPU::x32::TrapFrame Registers; // TODO
uint64_t ShadowGSBase, GSBase, FSBase;
CPU::x32::TrapFrame Registers; // TODO
uint64_t ShadowGSBase, GSBase, FSBase;
#elif defined(aa64)
uint64_t Registers; // TODO
uint64_t Registers; // TODO
#endif
uintptr_t IPHistory[128];
TaskSecurity Security;
TaskInfo Info;
CPU::x64::FXState *FPU;
uintptr_t IPHistory[128];
TaskSecurity Security;
TaskInfo Info;
CPU::x64::FXState *FPU;
void Rename(const char *name)
{
CriticalSection cs;
if (strlen(name) > 256 || strlen(name) == 0)
{
debug("Invalid thread name");
return;
}
void Rename(const char *name)
{
CriticalSection cs;
if (strlen(name) > 256 || strlen(name) == 0)
{
debug("Invalid thread name");
return;
}
trace("Renaming thread %s to %s", Name, name);
strncpy(Name, name, 256);
}
trace("Renaming thread %s to %s", Name, name);
strncpy(Name, name, 256);
}
void SetPriority(TaskPriority priority)
{
CriticalSection cs;
trace("Setting priority of thread %s to %d", Name, priority);
Info.Priority = priority;
}
void SetPriority(TaskPriority priority)
{
CriticalSection cs;
trace("Setting priority of thread %s to %d", Name, priority);
Info.Priority = priority;
}
int GetExitCode() { return ExitCode; }
int GetExitCode() { return ExitCode; }
void SetCritical(bool Critical)
{
CriticalSection cs;
trace("Setting criticality of thread %s to %s", Name, Critical ? "true" : "false");
Security.IsCritical = Critical;
}
void SetCritical(bool Critical)
{
CriticalSection cs;
trace("Setting criticality of thread %s to %s", Name, Critical ? "true" : "false");
Security.IsCritical = Critical;
}
void SetDebugMode(bool Enable)
{
CriticalSection cs;
trace("Setting debug mode of thread %s to %s", Name, Enable ? "true" : "false");
Security.IsDebugEnabled = Enable;
}
void SetDebugMode(bool Enable)
{
CriticalSection cs;
trace("Setting debug mode of thread %s to %s", Name, Enable ? "true" : "false");
Security.IsDebugEnabled = Enable;
}
void SetKernelDebugMode(bool Enable)
{
CriticalSection cs;
trace("Setting kernel debug mode of thread %s to %s", Name, Enable ? "true" : "false");
Security.IsKernelDebugEnabled = Enable;
}
};
void SetKernelDebugMode(bool Enable)
{
CriticalSection cs;
trace("Setting kernel debug mode of thread %s to %s", Name, Enable ? "true" : "false");
Security.IsKernelDebugEnabled = Enable;
}
};
struct PCB
{
UPID ID;
char Name[256];
PCB *Parent;
int ExitCode;
TaskStatus Status;
TaskSecurity Security;
TaskInfo Info;
std::vector<TCB *> Threads;
std::vector<PCB *> Children;
InterProcessCommunication::IPC *IPC;
Memory::PageTable *PageTable;
SymbolResolver::Symbols *ELFSymbolTable;
VirtualFileSystem::Node *CurrentWorkingDirectory;
VirtualFileSystem::Node *ProcessDirectory;
VirtualFileSystem::Node *memDirectory;
struct PCB
{
UPID ID;
char Name[256];
PCB *Parent;
int ExitCode;
TaskStatus Status;
TaskSecurity Security;
TaskInfo Info;
std::vector<TCB *> Threads;
std::vector<PCB *> Children;
InterProcessCommunication::IPC *IPC;
Memory::PageTable *PageTable;
SymbolResolver::Symbols *ELFSymbolTable;
VirtualFileSystem::Node *CurrentWorkingDirectory;
VirtualFileSystem::Node *ProcessDirectory;
VirtualFileSystem::Node *memDirectory;
void SetWorkingDirectory(VirtualFileSystem::Node *node)
{
CriticalSection cs;
trace("Setting working directory of process %s to %#lx (%s)", Name, node, node->Name);
CurrentWorkingDirectory = node;
}
};
void SetWorkingDirectory(VirtualFileSystem::Node *node)
{
CriticalSection cs;
trace("Setting working directory of process %s to %#lx (%s)", Name, node, node->Name);
CurrentWorkingDirectory = node;
}
};
/** @brief Token Trust Level */
enum TTL
{
UnknownTrustLevel = 0b0001,
Untrusted = 0b0010,
Trusted = 0b0100,
TrustedByKernel = 0b1000,
FullTrust = Trusted | TrustedByKernel
};
/** @brief Token Trust Level */
enum TTL
{
UnknownTrustLevel = 0b0001,
Untrusted = 0b0010,
Trusted = 0b0100,
TrustedByKernel = 0b1000,
FullTrust = Trusted | TrustedByKernel
};
class Security
{
private:
struct TokenData
{
Token token;
int TrustLevel;
uint64_t OwnerID;
bool Process;
};
class Security
{
private:
struct TokenData
{
Token token;
int TrustLevel;
uint64_t OwnerID;
bool Process;
};
std::vector<TokenData> Tokens;
std::vector<TokenData> Tokens;
public:
Token CreateToken();
bool TrustToken(Token token, TTL TrustLevel);
bool AddTrustLevel(Token token, TTL TrustLevel);
bool RemoveTrustLevel(Token token, TTL TrustLevel);
bool UntrustToken(Token token);
bool DestroyToken(Token token);
bool IsTokenTrusted(Token token, TTL TrustLevel);
bool IsTokenTrusted(Token token, int TrustLevel);
int GetTokenTrustLevel(Token token);
Security();
~Security();
};
public:
Token CreateToken();
bool TrustToken(Token token, TTL TrustLevel);
bool AddTrustLevel(Token token, TTL TrustLevel);
bool RemoveTrustLevel(Token token, TTL TrustLevel);
bool UntrustToken(Token token);
bool DestroyToken(Token token);
bool IsTokenTrusted(Token token, TTL TrustLevel);
bool IsTokenTrusted(Token token, int TrustLevel);
int GetTokenTrustLevel(Token token);
Security();
~Security();
};
class Task : public Interrupts::Handler
{
private:
Security SecurityManager;
UPID NextPID = 0;
UTID NextTID = 0;
class Task : public Interrupts::Handler
{
private:
Security SecurityManager;
UPID NextPID = 0;
UTID NextTID = 0;
std::vector<PCB *> ProcessList;
PCB *IdleProcess = nullptr;
TCB *IdleThread = nullptr;
TCB *CleanupThread = nullptr;
std::atomic_uint64_t SchedulerTicks = 0;
std::atomic_uint64_t LastTaskTicks = 0;
std::atomic_int LastCore = 0;
bool StopScheduler = false;
bool InvalidPCB(PCB *pcb);
bool InvalidTCB(TCB *tcb);
std::vector<PCB *> ProcessList;
PCB *IdleProcess = nullptr;
TCB *IdleThread = nullptr;
TCB *CleanupThread = nullptr;
std::atomic_size_t SchedulerTicks = 0;
std::atomic_size_t LastTaskTicks = 0;
std::atomic_int LastCore = 0;
bool StopScheduler = false;
bool InvalidPCB(PCB *pcb);
bool InvalidTCB(TCB *tcb);
void RemoveThread(TCB *tcb);
void RemoveProcess(PCB *pcb);
void RemoveThread(TCB *tcb);
void RemoveProcess(PCB *pcb);
void UpdateUsage(TaskInfo *Info, TaskSecurity *Security, int Core);
void UpdateUsage(TaskInfo *Info, TaskSecurity *Security, int Core);
bool FindNewProcess(void *CPUDataPointer);
bool GetNextAvailableThread(void *CPUDataPointer);
bool GetNextAvailableProcess(void *CPUDataPointer);
bool SchedulerSearchProcessThread(void *CPUDataPointer);
void UpdateProcessStatus();
void WakeUpThreads();
bool FindNewProcess(void *CPUDataPointer);
bool GetNextAvailableThread(void *CPUDataPointer);
bool GetNextAvailableProcess(void *CPUDataPointer);
bool SchedulerSearchProcessThread(void *CPUDataPointer);
void UpdateProcessStatus();
void WakeUpThreads();
#if defined(a64)
void Schedule(CPU::x64::TrapFrame *Frame);
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
void Schedule(CPU::x64::TrapFrame *Frame);
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
#elif defined(a32)
void Schedule(void *Frame);
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
void Schedule(void *Frame);
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
#elif defined(aa64)
void Schedule(CPU::aarch64::TrapFrame *Frame);
void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame);
void Schedule(CPU::aarch64::TrapFrame *Frame);
void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame);
#endif
public:
void SetCleanupThread(TCB *Thread) { CleanupThread = Thread; }
uint64_t GetSchedulerTicks() { return SchedulerTicks.load(); }
uint64_t GetLastTaskTicks() { return LastTaskTicks.load(); }
uint64_t GetLastCore() { return LastCore.load(); }
std::vector<PCB *> GetProcessList() { return ProcessList; }
Security *GetSecurityManager() { return &SecurityManager; }
void CleanupProcessesThread();
void Panic() { StopScheduler = true; }
void Schedule();
void SignalShutdown();
void RevertProcessCreation(PCB *Process);
void RevertThreadCreation(TCB *Thread);
public:
void SetCleanupThread(TCB *Thread) { CleanupThread = Thread; }
size_t GetSchedulerTicks() { return SchedulerTicks.load(); }
size_t GetLastTaskTicks() { return LastTaskTicks.load(); }
int GetLastCore() { return LastCore.load(); }
std::vector<PCB *> GetProcessList() { return ProcessList; }
Security *GetSecurityManager() { return &SecurityManager; }
void CleanupProcessesThread();
void Panic() { StopScheduler = true; }
void Schedule();
void SignalShutdown();
void RevertProcessCreation(PCB *Process);
void RevertThreadCreation(TCB *Thread);
void KillThread(TCB *tcb, int Code)
{
tcb->Status = TaskStatus::Terminated;
tcb->ExitCode = Code;
}
void KillThread(TCB *tcb, int Code)
{
tcb->Status = TaskStatus::Terminated;
tcb->ExitCode = Code;
}
void KillProcess(PCB *pcb, int Code)
{
pcb->Status = TaskStatus::Terminated;
pcb->ExitCode = Code;
}
void KillProcess(PCB *pcb, int Code)
{
pcb->Status = TaskStatus::Terminated;
pcb->ExitCode = Code;
}
/**
* @brief Get the Current Process object
* @return PCB*
*/
PCB *GetCurrentProcess();
/**
* @brief Get the Current Process object
* @return PCB*
*/
PCB *GetCurrentProcess();
/**
* @brief Get the Current Thread object
* @return TCB*
*/
TCB *GetCurrentThread();
/**
* @brief Get the Current Thread object
* @return TCB*
*/
TCB *GetCurrentThread();
PCB *GetProcessByID(UPID ID);
PCB *GetProcessByID(UPID ID);
TCB *GetThreadByID(UTID ID);
TCB *GetThreadByID(UTID ID);
/** @brief Wait for process to terminate */
void WaitForProcess(PCB *pcb);
/** @brief Wait for process to terminate */
void WaitForProcess(PCB *pcb);
/** @brief Wait for thread to terminate */
void WaitForThread(TCB *tcb);
/** @brief Wait for thread to terminate */
void WaitForThread(TCB *tcb);
void WaitForProcessStatus(PCB *pcb, TaskStatus Status);
void WaitForThreadStatus(TCB *tcb, TaskStatus Status);
void WaitForProcessStatus(PCB *pcb, TaskStatus Status);
void WaitForThreadStatus(TCB *tcb, TaskStatus Status);
/**
* @brief Sleep for a given amount of milliseconds
*
* @param Milliseconds Amount of milliseconds to sleep
*/
void Sleep(uint64_t Milliseconds);
/**
* @brief Sleep for a given amount of milliseconds
*
* @param Milliseconds Amount of milliseconds to sleep
*/
void Sleep(uint64_t Milliseconds);
PCB *CreateProcess(PCB *Parent,
const char *Name,
TaskTrustLevel TrustLevel,
void *Image = nullptr,
bool DoNotCreatePageTable = false);
PCB *CreateProcess(PCB *Parent,
const char *Name,
TaskTrustLevel TrustLevel,
void *Image = nullptr,
bool DoNotCreatePageTable = false);
TCB *CreateThread(PCB *Parent,
IP EntryPoint,
const char **argv = nullptr,
const char **envp = nullptr,
const std::vector<AuxiliaryVector> &auxv = std::vector<AuxiliaryVector>(),
IPOffset Offset = 0,
TaskArchitecture Architecture = TaskArchitecture::x64,
TaskCompatibility Compatibility = TaskCompatibility::Native,
bool ThreadNotReady = false);
TCB *CreateThread(PCB *Parent,
IP EntryPoint,
const char **argv = nullptr,
const char **envp = nullptr,
const std::vector<AuxiliaryVector> &auxv = std::vector<AuxiliaryVector>(),
IPOffset Offset = 0,
TaskArchitecture Architecture = TaskArchitecture::x64,
TaskCompatibility Compatibility = TaskCompatibility::Native,
bool ThreadNotReady = false);
Task(const IP EntryPoint);
~Task();
};
Task(const IP EntryPoint);
~Task();
};
}
#define PEXIT(Code) TaskManager->GetCurrentProcess()->ExitCode = Code

View File

@ -23,180 +23,180 @@
namespace Time
{
struct Clock
{
int Year, Month, Day, Hour, Minute, Second;
uint64_t Counter;
};
struct Clock
{
int Year, Month, Day, Hour, Minute, Second;
size_t Counter;
};
Clock ReadClock();
Clock ConvertFromUnix(int Timestamp);
Clock ReadClock();
Clock ConvertFromUnix(int Timestamp);
enum Units
{
Femtoseconds,
Picoseconds,
Nanoseconds,
Microseconds,
Milliseconds,
Seconds,
Minutes,
Hours,
Days,
Months,
Years
};
enum Units
{
Femtoseconds,
Picoseconds,
Nanoseconds,
Microseconds,
Milliseconds,
Seconds,
Minutes,
Hours,
Days,
Months,
Years
};
class HighPrecisionEventTimer
{
private:
struct HPET
{
uintptr_t GeneralCapabilities;
uintptr_t Reserved0;
uintptr_t GeneralConfiguration;
uintptr_t Reserved1;
uintptr_t GeneralIntStatus;
uintptr_t Reserved2;
uintptr_t Reserved3[24];
uintptr_t MainCounterValue;
uintptr_t Reserved4;
};
class HighPrecisionEventTimer
{
private:
struct HPET
{
uintptr_t GeneralCapabilities;
uintptr_t Reserved0;
uintptr_t GeneralConfiguration;
uintptr_t Reserved1;
uintptr_t GeneralIntStatus;
uintptr_t Reserved2;
uintptr_t Reserved3[24];
uintptr_t MainCounterValue;
uintptr_t Reserved4;
};
uint32_t clk = 0;
HPET *hpet = nullptr;
uint64_t ClassCreationTime = 0;
uint32_t clk = 0;
HPET *hpet = nullptr;
size_t ClassCreationTime = 0;
inline uint64_t ConvertUnit(Units Unit)
{
switch (Unit)
{
case Femtoseconds:
return 1;
case Picoseconds:
return 1000;
case Nanoseconds:
return 1000000;
case Microseconds:
return 1000000000;
case Milliseconds:
return 1000000000000;
case Seconds:
return 1000000000000000;
case Minutes:
return 1000000000000000000;
// case Hours:
// return 1000000000000000000000;
// case Days:
// return 1000000000000000000000000;
// case Months:
// return 1000000000000000000000000000;
// case Years:
// return 1000000000000000000000000000000;
default:
error("Invalid time unit %d", Unit);
return 1;
}
}
inline size_t ConvertUnit(Units Unit)
{
switch (Unit)
{
case Femtoseconds:
return 1;
case Picoseconds:
return 1000;
case Nanoseconds:
return 1000000;
case Microseconds:
return 1000000000;
case Milliseconds:
return 1000000000000;
case Seconds:
return 1000000000000000;
case Minutes:
return 1000000000000000000;
// case Hours:
// return 1000000000000000000000;
// case Days:
// return 1000000000000000000000000;
// case Months:
// return 1000000000000000000000000000;
// case Years:
// return 1000000000000000000000000000000;
default:
error("Invalid time unit %d", Unit);
return 1;
}
}
public:
bool Sleep(uint64_t Duration, Units Unit);
uint64_t GetCounter();
uint64_t CalculateTarget(uint64_t Target, Units Unit);
uint64_t GetNanosecondsSinceClassCreation();
public:
bool Sleep(size_t Duration, Units Unit);
size_t GetCounter();
size_t CalculateTarget(size_t Target, Units Unit);
size_t GetNanosecondsSinceClassCreation();
HighPrecisionEventTimer(void *hpet);
~HighPrecisionEventTimer();
};
HighPrecisionEventTimer(void *hpet);
~HighPrecisionEventTimer();
};
class TimeStampCounter
{
private:
uint64_t clk = 0;
uint64_t ClassCreationTime = 0;
class TimeStampCounter
{
private:
size_t clk = 0;
size_t ClassCreationTime = 0;
inline uint64_t ConvertUnit(Units Unit)
{
switch (Unit)
{
case Femtoseconds:
return 1;
case Picoseconds:
return 1000;
case Nanoseconds:
return 1000000;
case Microseconds:
return 1000000000;
case Milliseconds:
return 1000000000000;
case Seconds:
return 1000000000000000;
case Minutes:
return 1000000000000000000;
// case Hours:
// return 1000000000000000000000;
// case Days:
// return 1000000000000000000000000;
// case Months:
// return 1000000000000000000000000000;
// case Years:
// return 1000000000000000000000000000000;
default:
error("Invalid time unit %d", Unit);
return 1;
}
}
inline size_t ConvertUnit(Units Unit)
{
switch (Unit)
{
case Femtoseconds:
return 1;
case Picoseconds:
return 1000;
case Nanoseconds:
return 1000000;
case Microseconds:
return 1000000000;
case Milliseconds:
return 1000000000000;
case Seconds:
return 1000000000000000;
case Minutes:
return 1000000000000000000;
// case Hours:
// return 1000000000000000000000;
// case Days:
// return 1000000000000000000000000;
// case Months:
// return 1000000000000000000000000000;
// case Years:
// return 1000000000000000000000000000000;
default:
error("Invalid time unit %d", Unit);
return 1;
}
}
public:
bool Sleep(uint64_t Duration, Units Unit);
uint64_t GetCounter();
uint64_t CalculateTarget(uint64_t Target, Units Unit);
uint64_t GetNanosecondsSinceClassCreation();
public:
bool Sleep(size_t Duration, Units Unit);
size_t GetCounter();
size_t CalculateTarget(size_t Target, Units Unit);
size_t GetNanosecondsSinceClassCreation();
TimeStampCounter();
~TimeStampCounter();
};
TimeStampCounter();
~TimeStampCounter();
};
class time
{
public:
enum TimeActiveTimer
{
NONE = 0b0,
RTC = 0b1,
PIT = 0b10,
HPET = 0b100,
ACPI = 0b1000,
APIC = 0b10000,
TSC = 0b100000
};
class time
{
public:
enum TimeActiveTimer
{
NONE = 0b0,
RTC = 0b1,
PIT = 0b10,
HPET = 0b100,
ACPI = 0b1000,
APIC = 0b10000,
TSC = 0b100000
};
private:
int SupportedTimers = 0;
TimeActiveTimer ActiveTimer = NONE;
private:
int SupportedTimers = 0;
TimeActiveTimer ActiveTimer = NONE;
HighPrecisionEventTimer *hpet;
TimeStampCounter *tsc;
HighPrecisionEventTimer *hpet;
TimeStampCounter *tsc;
public:
int GetSupportedTimers() { return SupportedTimers; }
TimeActiveTimer GetActiveTimer() { return ActiveTimer; }
bool ChangeActiveTimer(TimeActiveTimer Timer)
{
if (!(SupportedTimers & Timer))
return false;
ActiveTimer = Timer;
return true;
}
public:
int GetSupportedTimers() { return SupportedTimers; }
TimeActiveTimer GetActiveTimer() { return ActiveTimer; }
bool ChangeActiveTimer(TimeActiveTimer Timer)
{
if (!(SupportedTimers & Timer))
return false;
ActiveTimer = Timer;
return true;
}
bool Sleep(uint64_t Duration, Units Unit);
uint64_t GetCounter();
uint64_t CalculateTarget(uint64_t Target, Units Unit);
uint64_t GetNanosecondsSinceClassCreation();
void FindTimers(void *acpi);
time();
~time();
};
bool Sleep(size_t Duration, Units Unit);
size_t GetCounter();
size_t CalculateTarget(size_t Target, Units Unit);
size_t GetNanosecondsSinceClassCreation();
void FindTimers(void *acpi);
time();
~time();
};
}
#endif // !__FENNIX_KERNEL_TIME_H__

File diff suppressed because it is too large Load Diff