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

View File

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

View File

@ -31,43 +31,9 @@
namespace Driver namespace Driver
{ {
DriverCode Driver::DriverLoadBindInput(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf) DriverCode Driver::DriverLoadBindInput(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
{ {
UNUSED(DrvExtHdr); stub;
UNUSED(IsElf); return DriverCode::NOT_IMPLEMENTED;
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;
}
} }

View File

@ -31,55 +31,88 @@
namespace Driver namespace Driver
{ {
DriverCode Driver::DriverLoadBindInterrupt(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf) DriverCode Driver::DriverLoadBindInterrupt(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
{ {
UNUSED(DrvExtHdr); Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
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) BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress;
{ Fex *fex = nullptr;
delete mem, mem = nullptr; if (!IsBuiltIn)
return DriverCode::DRIVER_RETURNED_ERROR; {
} fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex); 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) if (IsBuiltIn)
{ fex = 0x0; /* Addresses are absolute if built-in. */
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;
}
}
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 namespace Driver
{ {
void Driver::MapPCIAddresses(PCI::PCIDeviceHeader *PCIDevice) DriverCode Driver::DriverLoadBindPCI(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
{ {
debug("Header Type: %d", PCIDevice->HeaderType); FexExtended *DrvExtHdr = (FexExtended *)(DriverAddress + EXTENDED_SECTION_ADDRESS);
switch (PCIDevice->HeaderType) if (IsBuiltIn)
{ DrvExtHdr = (FexExtended *)(((BuiltInDriverInfo *)DriverAddress)->ExtendedHeader);
case 0: // PCI Header 0
{
uint32_t BAR[6] = {0};
size_t BARsSize[6] = {0};
BAR[0] = ((PCI::PCIHeader0 *)PCIDevice)->BAR0; uint16_t SizeOfVendorID = sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) /
BAR[1] = ((PCI::PCIHeader0 *)PCIDevice)->BAR1; sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID[0]);
BAR[2] = ((PCI::PCIHeader0 *)PCIDevice)->BAR2; uint16_t SizeOfDeviceID = sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID) /
BAR[3] = ((PCI::PCIHeader0 *)PCIDevice)->BAR3; sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID[0]);
BAR[4] = ((PCI::PCIHeader0 *)PCIDevice)->BAR4;
BAR[5] = ((PCI::PCIHeader0 *)PCIDevice)->BAR5;
#ifdef DEBUG for (uint16_t vID = 0; vID < SizeOfVendorID; vID++)
uintptr_t BAR_Type = BAR[0] & 1; {
uintptr_t BAR_IOBase = BAR[1] & (~3); for (uint16_t dID = 0; dID < SizeOfDeviceID; dID++)
uintptr_t BAR_MemoryBase = BAR[0] & (~15); {
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); std::vector<PCI::PCIDeviceHeader *> devices =
#endif PCIManager->FindPCIDevice(DrvExtHdr->Driver.Bind.PCI.VendorID[vID],
DrvExtHdr->Driver.Bind.PCI.DeviceID[dID]);
if (devices.size() == 0)
continue;
/* BARs Size */ foreach (auto PCIDevice in devices)
for (short i = 0; i < 6; i++) {
{ debug("[%ld] VendorID: %#x; DeviceID: %#x",
if (BAR[i] == 0) devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID);
continue;
if ((BAR[i] & 1) == 0) // Memory Base Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
{
((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]);
}
}
/* Mapping the BARs */ BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress;
for (short i = 0; i < 6; i++) Fex *fex = nullptr;
{ if (!IsBuiltIn)
if (BAR[i] == 0) {
continue; 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 if (IsBuiltIn)
{ fex = 0x0; /* Addresses are absolute if built-in. */
uintptr_t BARBase = BAR[i] & (~15);
size_t BARSize = BARsSize[i];
debug("Mapping BAR%d %#lx-%#lx", i, BARBase, BARBase + BARSize); FexExtended *fexE = IsBuiltIn ? (FexExtended *)bidi->ExtendedHeader : (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, Memory::PTFlag::RW | Memory::PTFlag::PWT); debug("Starting driver %s", fexE->Driver.Name);
}
else if ((BAR[i] & 1) == 1) // I/O Base
{
uintptr_t BARBase = BAR[i] & (~3);
size_t BARSize = BARsSize[i];
debug("Mapping BAR%d %#x-%#x", i, BARBase, BARBase + BARSize); PCIManager->MapPCIAddresses(PCIDevice);
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;
}
}
}
DriverCode Driver::DriverLoadBindPCI(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf) switch (fexE->Driver.Type)
{ {
UNUSED(IsElf); case FexDriverType::FexDriverType_Generic:
for (unsigned long Vidx = 0; Vidx < sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID) / sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[0]); Vidx++) case FexDriverType::FexDriverType_Display:
{ case FexDriverType::FexDriverType_Network:
for (unsigned long Didx = 0; Didx < sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID) / sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[0]); Didx++) case FexDriverType::FexDriverType_Storage:
{ case FexDriverType::FexDriverType_FileSystem:
if (Vidx >= sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID) && Didx >= sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID)) case FexDriverType::FexDriverType_Input:
break; 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) DriverFile DrvFile = {
continue; .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 (fexE->Driver.InterruptCallback)
if (devices.size() == 0) DrvFile.InterruptHook[0] = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine), DrvFile);
continue;
foreach (auto PCIDevice in devices) KernelCallback KCallback{};
{ KCallback.RawPtr = PCIDevice;
debug("[%ld] VendorID: %#x; DeviceID: %#x", devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID); KCallback.Reason = CallbackReason::ConfigurationReason;
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory); DriverCode CallbackRet = ((DriverCode(*)(KernelCallback *))((uintptr_t)fexE->Driver.Callback + (uintptr_t)fex))(&KCallback);
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) if (CallbackRet != DriverCode::OK)
{ {
delete mem, mem = nullptr; error("Driver %s returned error %d", fexE->Driver.Name, CallbackRet);
return DriverCode::DRIVER_RETURNED_ERROR; delete mem;
} return CallbackRet;
debug("Starting driver %s", fexExtended->Driver.Name); }
MapPCIAddresses(PCIDevice); Drivers.push_back(DrvFile);
return DriverCode::OK;
switch (fexExtended->Driver.Type) }
{ default:
case FexDriverType::FexDriverType_Generic: {
return BindPCIGeneric(mem, fex, PCIDevice); warn("Unknown driver type: %d", fexE->Driver.Type);
case FexDriverType::FexDriverType_Display: delete mem;
return BindPCIDisplay(mem, fex, PCIDevice); return DriverCode::UNKNOWN_DRIVER_TYPE;
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); return DriverCode::PCI_DEVICE_NOT_FOUND;
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;
}
} }

View File

@ -31,12 +31,9 @@
namespace Driver namespace Driver
{ {
DriverCode Driver::DriverLoadBindProcess(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf) DriverCode Driver::DriverLoadBindProcess(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
{ {
fixme("Process driver: %s", ((FexExtended *)DrvExtHdr)->Driver.Name); stub;
UNUSED(Size); return DriverCode::NOT_IMPLEMENTED;
UNUSED(DriverAddress); }
UNUSED(IsElf);
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 namespace Time
{ {
bool HighPrecisionEventTimer::Sleep(uint64_t Duration, Units Unit) bool HighPrecisionEventTimer::Sleep(size_t Duration, Units Unit)
{ {
#if defined(a64) #if defined(a64)
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk; size_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target) while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
CPU::Pause(); CPU::Pause();
return true; return true;
#elif defined(a32) #elif defined(a32)
uint64_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk; size_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
while (mminl(&((HPET *)hpet)->MainCounterValue) < Target) while (mminl(&((HPET *)hpet)->MainCounterValue) < Target)
CPU::Pause(); CPU::Pause();
return true; return true;
#endif #endif
return false; return false;
} }
uint64_t HighPrecisionEventTimer::GetCounter() size_t HighPrecisionEventTimer::GetCounter()
{ {
#if defined(a64) #if defined(a64)
return mminq(&((HPET *)hpet)->MainCounterValue); return mminq(&((HPET *)hpet)->MainCounterValue);
#elif defined(a32) #elif defined(a32)
return mminl(&((HPET *)hpet)->MainCounterValue); return mminl(&((HPET *)hpet)->MainCounterValue);
#endif #endif
} }
uint64_t HighPrecisionEventTimer::CalculateTarget(uint64_t Target, Units Unit) size_t HighPrecisionEventTimer::CalculateTarget(size_t Target, Units Unit)
{ {
#if defined(a64) #if defined(a64)
return mminq(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk; return mminq(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
#elif defined(a32) #elif defined(a32)
return mminl(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk; return mminl(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
#endif #endif
} }
uint64_t HighPrecisionEventTimer::GetNanosecondsSinceClassCreation() size_t HighPrecisionEventTimer::GetNanosecondsSinceClassCreation()
{ {
#if defined(a86) #if defined(a86)
uint64_t Subtraction = this->GetCounter() - this->ClassCreationTime; size_t Subtraction = this->GetCounter() - this->ClassCreationTime;
if (Subtraction <= 0 || this->clk <= 0) if (Subtraction <= 0 || this->clk <= 0)
return 0; return 0;
return Subtraction / (this->clk / ConvertUnit(Units::Nanoseconds)); return Subtraction / (this->clk / ConvertUnit(Units::Nanoseconds));
#endif #endif
} }
HighPrecisionEventTimer::HighPrecisionEventTimer(void *hpet) HighPrecisionEventTimer::HighPrecisionEventTimer(void *hpet)
{ {
#if defined(a86) #if defined(a86)
ACPI::ACPI::HPETHeader *HPET_HDR = (ACPI::ACPI::HPETHeader *)hpet; ACPI::ACPI::HPETHeader *HPET_HDR = (ACPI::ACPI::HPETHeader *)hpet;
Memory::Virtual().Remap((void *)HPET_HDR->Address.Address, Memory::Virtual().Remap((void *)HPET_HDR->Address.Address,
(void *)HPET_HDR->Address.Address, (void *)HPET_HDR->Address.Address,
Memory::PTFlag::RW | Memory::PTFlag::PCD); Memory::PTFlag::RW | Memory::PTFlag::PCD);
this->hpet = (HPET *)HPET_HDR->Address.Address; this->hpet = (HPET *)HPET_HDR->Address.Address;
trace("%s timer is at address %016p", HPET_HDR->Header.OEMID, (void *)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); clk = s_cst(uint32_t, (uint64_t)this->hpet->GeneralCapabilities >> 32);
#ifdef a64 #ifdef a64
mmoutq(&this->hpet->GeneralConfiguration, 0); mmoutq(&this->hpet->GeneralConfiguration, 0);
mmoutq(&this->hpet->MainCounterValue, 0); mmoutq(&this->hpet->MainCounterValue, 0);
mmoutq(&this->hpet->GeneralConfiguration, 1); mmoutq(&this->hpet->GeneralConfiguration, 1);
#else #else
mmoutl(&this->hpet->GeneralConfiguration, 0); mmoutl(&this->hpet->GeneralConfiguration, 0);
mmoutl(&this->hpet->MainCounterValue, 0); mmoutl(&this->hpet->MainCounterValue, 0);
mmoutl(&this->hpet->GeneralConfiguration, 1); mmoutl(&this->hpet->GeneralConfiguration, 1);
#endif #endif
ClassCreationTime = this->GetCounter(); ClassCreationTime = this->GetCounter();
#endif #endif
} }

View File

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

View File

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

646
DAPI.hpp
View File

@ -46,386 +46,386 @@
enum DriverReturnCode enum DriverReturnCode
{ {
ERROR, ERROR,
OK, OK,
NOT_IMPLEMENTED, NOT_IMPLEMENTED,
NOT_FOUND, NOT_FOUND,
NOT_READY, NOT_READY,
NOT_AVAILABLE, NOT_AVAILABLE,
NOT_AUTHORIZED, NOT_AUTHORIZED,
NOT_VALID, NOT_VALID,
NOT_ACCEPTED, NOT_ACCEPTED,
INVALID_PCI_BAR, INVALID_PCI_BAR,
INVALID_KERNEL_API, INVALID_KERNEL_API,
INVALID_MEMORY_ALLOCATION, INVALID_MEMORY_ALLOCATION,
INVALID_DATA, INVALID_DATA,
DEVICE_NOT_SUPPORTED, DEVICE_NOT_SUPPORTED,
SYSTEM_NOT_SUPPORTED, SYSTEM_NOT_SUPPORTED,
KERNEL_API_VERSION_NOT_SUPPORTED, KERNEL_API_VERSION_NOT_SUPPORTED,
}; };
enum DriverBindType enum DriverBindType
{ {
BIND_NULL, BIND_NULL,
BIND_INTERRUPT, BIND_INTERRUPT,
BIND_PROCESS, BIND_PROCESS,
BIND_PCI, BIND_PCI,
BIND_INPUT BIND_INPUT
}; };
struct KernelAPI struct KernelAPI
{ {
struct KAPIVersion struct KAPIVersion
{ {
int Major; int Major;
int Minor; int Minor;
int Patch; int Patch;
} Version; } Version;
struct KAPIInfo struct KAPIInfo
{ {
unsigned long Offset; unsigned long Offset;
unsigned long DriverUID; unsigned int DriverUID;
char KernelDebug; char KernelDebug;
} Info; } Info;
struct KAPIMemory struct KAPIMemory
{ {
unsigned long PageSize; unsigned long PageSize;
void *(*RequestPage)(unsigned long Size); void *(*RequestPage)(unsigned long Size);
void (*FreePage)(void *Page, unsigned long Size); void (*FreePage)(void *Page, unsigned long Size);
void (*Map)(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags); void (*Map)(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags);
void (*Unmap)(void *VirtualAddress); void (*Unmap)(void *VirtualAddress);
} Memory; } Memory;
struct KAPIPCI struct KAPIPCI
{ {
char *(*GetDeviceName)(unsigned int VendorID, unsigned int DeviceID); char *(*GetDeviceName)(unsigned int VendorID, unsigned int DeviceID);
} PCI; } PCI;
struct KAPIUtilities struct KAPIUtilities
{ {
void (*DebugPrint)(char *String, unsigned long DriverUID); void (*DebugPrint)(char *String, unsigned long DriverUID);
void (*DisplayPrint)(char *Value); void (*DisplayPrint)(char *Value);
void *(*memcpy)(void *Destination, void *Source, unsigned long Size); void *(*memcpy)(void *Destination, void *Source, unsigned long Size);
void *(*memset)(void *Destination, int Value, unsigned long Size); void *(*memset)(void *Destination, int Value, unsigned long Size);
void (*Sleep)(unsigned long Milliseconds); void (*Sleep)(unsigned long Milliseconds);
int (*sprintf)(char *Buffer, const char *Format, ...); int (*sprintf)(char *Buffer, const char *Format, ...);
} Util; } Util;
struct KAPIDriverTalk struct KAPIDriverTalk
{ {
/** @brief Connects to the network manager */ /** @brief Connects to the network manager */
struct struct
{ {
void (*SendPacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size); void (*SendPacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size);
void (*ReceivePacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size); void (*ReceivePacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size);
} Network; } Network;
/** @brief Connects to the disk manager */ /** @brief Connects to the disk manager */
struct struct
{ {
struct struct
{ {
void (*ReadSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port); 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); void (*WriteSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port);
} AHCI; } AHCI;
} Disk; } Disk;
} Command; } Command;
struct KAPIDisplay struct KAPIDisplay
{ {
unsigned int (*GetWidth)(void); unsigned int (*GetWidth)(void);
unsigned int (*GetHeight)(void); unsigned int (*GetHeight)(void);
/* TODO: Add more */ /* TODO: Add more */
} Display; } Display;
} __attribute__((packed)); } __attribute__((packed));
enum CallbackReason enum CallbackReason
{ {
/** /**
* @brief This is used to detect memory corruption, not used. * @brief This is used to detect memory corruption, not used.
*/ */
UnknownReason, UnknownReason,
/** /**
* @brief This is called once the kernel is ready to use the driver and call @see ConfigurationReason . * @brief This is called once the kernel is ready to use the driver and call @see ConfigurationReason .
*/ */
AcknowledgeReason, AcknowledgeReason,
/** /**
* @brief This is used after the driver is loaded and the kernel is ready to use the driver. * @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. * For PCI drivers, @see RawPtr will be the PCI device address.
*/ */
ConfigurationReason, ConfigurationReason,
/** /**
* @brief This is used when the kernel wants to stop the driver. * @brief This is used when the kernel wants to stop the driver.
* *
* The memory allocated by the driver will be freed automatically. * The memory allocated by the driver will be freed automatically.
*/ */
StopReason, StopReason,
ProcessReason, ProcessReason,
InputReason, InputReason,
/* Kernel reserved callbacks. */ /* Kernel reserved callbacks. */
/* ------------------------------------------------------- */ /* ------------------------------------------------------- */
/* Driver callbacks for basic usage. */ /* Driver callbacks for basic usage. */
/** /**
* @brief This is used when the kernel sends data. * @brief This is used when the kernel sends data.
* *
* - Network * - Network
* - Packet * - Packet
* - Audio * - Audio
* - PCM Data * - PCM Data
*/ */
SendReason, SendReason,
/** /**
* @brief This is used when the kernel wants to receive data. * @brief This is used when the kernel wants to receive data.
* Currently not used. * Currently not used.
*/ */
ReceiveReason, ReceiveReason,
/** /**
* @brief This is used to adjust driver settings. * @brief This is used to adjust driver settings.
* *
* - Audio * - Audio
* - Volume * - Volume
* - PCM Encoding * - PCM Encoding
*/ */
AdjustReason, AdjustReason,
/** /**
* @brief This is used when the kernel wants to fetch information about the driver. * @brief This is used when the kernel wants to fetch information about the driver.
* *
* - Input * - Input
* - Mouse * - Mouse
* - Position * - Position
* - Buttons * - Buttons
* - Keyboard * - Keyboard
* - Key * - Key
*/ */
FetchReason, FetchReason,
}; };
union KernelCallback union KernelCallback
{ {
struct struct
{ {
CallbackReason Reason; CallbackReason Reason;
void *RawPtr; void *RawPtr;
unsigned long RawData; unsigned long RawData;
/** @brief When the kernel wants to send a packet. */ /** @brief When the kernel wants to send a packet. */
struct struct
{ {
struct struct
{ {
unsigned char *Data; unsigned char *Data;
unsigned long Length; unsigned long Length;
} Send; } Send;
struct struct
{ {
char Name[128]; char Name[128];
unsigned long MAC; unsigned long MAC;
} Fetch; } Fetch;
} NetworkCallback; } NetworkCallback;
/** @brief When the kernel wants to write to disk. */ /** @brief When the kernel wants to write to disk. */
struct struct
{ {
struct struct
{ {
unsigned long Sector; unsigned long Sector;
unsigned long SectorCount; unsigned long SectorCount;
unsigned char Port; unsigned char Port;
unsigned char *Buffer; unsigned char *Buffer;
bool Write; bool Write;
} RW; } RW;
struct struct
{ {
unsigned char Ports; unsigned char Ports;
int BytesPerSector; int BytesPerSector;
} Fetch; } Fetch;
} DiskCallback; } DiskCallback;
/** @brief When the kernel wants to get mouse position / keyboard key */ /** @brief When the kernel wants to get mouse position / keyboard key */
struct struct
{ {
struct struct
{ {
unsigned long X; unsigned long X;
unsigned long Y; unsigned long Y;
unsigned long Z; unsigned long Z;
struct struct
{ {
bool Left; bool Left;
bool Right; bool Right;
bool Middle; bool Middle;
} Buttons; } Buttons;
} Mouse; } Mouse;
} InputCallback; } InputCallback;
struct struct
{ {
struct struct
{ {
bool _Volume; bool _Volume;
bool _Encoding; bool _Encoding;
bool _SampleRate; bool _SampleRate;
bool _Channels; bool _Channels;
/** /**
* @brief Adjust the volume. * @brief Adjust the volume.
* *
* 0 - 100 * 0 - 100
*/ */
unsigned char Volume; unsigned char Volume;
/** /**
* @brief Adjust the encoding. * @brief Adjust the encoding.
* *
* 0 - None, use default * 0 - None, use default
* *
* 1 - Signed PCM 8-bit * 1 - Signed PCM 8-bit
* 2 - Unsigned PCM 8-bit * 2 - Unsigned PCM 8-bit
* *
* 3 - Signed PCM 16-bit Little Endian * 3 - Signed PCM 16-bit Little Endian
* 4 - Signed PCM 20-bit Little Endian * 4 - Signed PCM 20-bit Little Endian
* 5 - Signed PCM 24-bit Little Endian * 5 - Signed PCM 24-bit Little Endian
* 6 - Signed PCM 32-bit Little Endian * 6 - Signed PCM 32-bit Little Endian
* *
* 7 - Unsigned PCM 16-bit Little Endian * 7 - Unsigned PCM 16-bit Little Endian
* 8 - Unsigned PCM 20-bit Little Endian * 8 - Unsigned PCM 20-bit Little Endian
* 9 - Unsigned PCM 24-bit Little Endian * 9 - Unsigned PCM 24-bit Little Endian
* 10 - Unsigned PCM 32-bit Little Endian * 10 - Unsigned PCM 32-bit Little Endian
* *
* 11 - Signed PCM 16-bit Big Endian * 11 - Signed PCM 16-bit Big Endian
* 12 - Signed PCM 20-bit Big Endian * 12 - Signed PCM 20-bit Big Endian
* 13 - Signed PCM 24-bit Big Endian * 13 - Signed PCM 24-bit Big Endian
* 14 - Signed PCM 32-bit Big Endian * 14 - Signed PCM 32-bit Big Endian
* *
* 15 - Unsigned PCM 16-bit Big Endian * 15 - Unsigned PCM 16-bit Big Endian
* 16 - Unsigned PCM 20-bit Big Endian * 16 - Unsigned PCM 20-bit Big Endian
* 17 - Unsigned PCM 24-bit Big Endian * 17 - Unsigned PCM 24-bit Big Endian
* 18 - Unsigned PCM 32-bit Big Endian * 18 - Unsigned PCM 32-bit Big Endian
* *
* 19 - Float PCM 32-bit Little Endian * 19 - Float PCM 32-bit Little Endian
* 20 - Float PCM 64-bit Little Endian * 20 - Float PCM 64-bit Little Endian
* *
* 21 - Float PCM 32-bit Big Endian * 21 - Float PCM 32-bit Big Endian
* 22 - Float PCM 64-bit Big Endian * 22 - Float PCM 64-bit Big Endian
* *
* 23 - PCM A-law * 23 - PCM A-law
* 24 - PCM Mu-law * 24 - PCM Mu-law
* *
* ... - More * ... - More
*/ */
unsigned short Encoding; unsigned short Encoding;
/** /**
* @brief Adjust the sample rate. * @brief Adjust the sample rate.
* *
* 0 - 8000 Hz * 0 - 8000 Hz
* 1 - 11025 Hz * 1 - 11025 Hz
* 2 - 16000 Hz * 2 - 16000 Hz
* 3 - 22050 Hz * 3 - 22050 Hz
* 4 - 32000 Hz * 4 - 32000 Hz
* 5 - 44100 Hz * 5 - 44100 Hz
* 6 - 48000 Hz * 6 - 48000 Hz
* 7 - 88200 Hz * 7 - 88200 Hz
* 8 - 96000 Hz * 8 - 96000 Hz
*/ */
unsigned char SampleRate; unsigned char SampleRate;
/** /**
* @brief Adjust the channels. * @brief Adjust the channels.
* *
* 0 - Mono * 0 - Mono
* 1 - Stereo * 1 - Stereo
*/ */
unsigned char Channels; unsigned char Channels;
} Adjust; } Adjust;
struct struct
{ {
unsigned char *Data; unsigned char *Data;
unsigned long Length; unsigned long Length;
} Send; } Send;
struct struct
{ {
unsigned char Volume; unsigned char Volume;
unsigned short Encoding; unsigned short Encoding;
unsigned char SampleRate; unsigned char SampleRate;
unsigned char Channels; unsigned char Channels;
} Fetch; } Fetch;
} AudioCallback; } AudioCallback;
struct struct
{ {
unsigned char Vector; unsigned char Vector;
} InterruptInfo; } InterruptInfo;
}; };
unsigned long raw; unsigned long raw;
} __attribute__((packed)); } __attribute__((packed));
union CPURegisters union CPURegisters
{ {
struct struct
{ {
#if defined(__x86_64__) || defined(__amd64__) #if defined(__x86_64__) || defined(__amd64__)
unsigned long r15; unsigned long r15;
unsigned long r14; unsigned long r14;
unsigned long r13; unsigned long r13;
unsigned long r12; unsigned long r12;
unsigned long r11; unsigned long r11;
unsigned long r10; unsigned long r10;
unsigned long r9; unsigned long r9;
unsigned long r8; unsigned long r8;
unsigned long rbp; unsigned long rbp;
unsigned long rdi; unsigned long rdi;
unsigned long rsi; unsigned long rsi;
unsigned long rdx; unsigned long rdx;
unsigned long rcx; unsigned long rcx;
unsigned long rbx; unsigned long rbx;
unsigned long rax; unsigned long rax;
unsigned long InterruptNumber; unsigned long InterruptNumber;
unsigned long ErrorCode; unsigned long ErrorCode;
unsigned long rip; unsigned long rip;
unsigned long cs; unsigned long cs;
unsigned long rflags; unsigned long rflags;
unsigned long rsp; unsigned long rsp;
unsigned long ss; unsigned long ss;
#elif defined(__i386__) #elif defined(__i386__)
unsigned int ebp; unsigned int ebp;
unsigned int edi; unsigned int edi;
unsigned int esi; unsigned int esi;
unsigned int edx; unsigned int edx;
unsigned int ecx; unsigned int ecx;
unsigned int ebx; unsigned int ebx;
unsigned int eax; unsigned int eax;
unsigned int InterruptNumber; unsigned int InterruptNumber;
unsigned int ErrorCode; unsigned int ErrorCode;
unsigned int eip; unsigned int eip;
unsigned int cs; unsigned int cs;
unsigned int eflags; unsigned int eflags;
unsigned int esp; unsigned int esp;
unsigned int ss; unsigned int ss;
#else #else
#warning "Unsupported architecture" #warning "Unsupported architecture"
#endif #endif
}; };
unsigned long raw; unsigned long raw;
} __attribute__((packed)); } __attribute__((packed));
#endif // !__FENNIX_DRIVER_API_H__ #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/>. 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 <types.h>
#include <memory.hpp> #include "../../DAPI.hpp"
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h" namespace AdvancedTechnologyAttachment
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{ {
DriverCode Driver::BindInputAudio(Memory::MemMgr *mem, void *fex) int DriverEntry(void *);
{ int CallbackHandler(KernelCallback *);
UNUSED(mem); int InterruptCallback(CPURegisters *);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
} }
#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/>. 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 <types.h>
#include <memory.hpp> #include "../../DAPI.hpp"
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h" namespace PCNET
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{ {
DriverCode Driver::BindInputDisplay(Memory::MemMgr *mem, void *fex) struct BARData
{ {
UNUSED(mem); uint8_t Type;
UNUSED(fex); uint16_t IOBase;
return DriverCode::NOT_IMPLEMENTED; 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 enum FexFormatType
{ {
FexFormatType_Unknown, FexFormatType_Unknown,
FexFormatType_Executable, FexFormatType_Executable,
FexFormatType_Driver FexFormatType_Driver
/* ... */ /* ... */
}; };
enum FexOSType enum FexOSType
{ {
FexOSType_Unknown, FexOSType_Unknown,
FexOSType_Fennix, FexOSType_Fennix,
FexOSType_Linux FexOSType_Linux
/* ... */ /* ... */
}; };
enum FexDriverType enum FexDriverType
{ {
FexDriverType_Unknown, FexDriverType_Unknown,
FexDriverType_Generic, FexDriverType_Generic,
FexDriverType_Display, FexDriverType_Display,
FexDriverType_Network, FexDriverType_Network,
FexDriverType_Storage, FexDriverType_Storage,
FexDriverType_FileSystem, FexDriverType_FileSystem,
FexDriverType_Input, FexDriverType_Input,
FexDriverType_Audio, FexDriverType_Audio,
FexDriverType_ACPI, FexDriverType_ACPI,
/* ... */ /* ... */
}; };
enum FexDriverInputTypes enum FexDriverInputTypes
{ {
FexDriverInputTypes_None = 0b00000000, FexDriverInputTypes_None = 0b00000000,
FexDriverInputTypes_Mouse = 0b00000001, FexDriverInputTypes_Mouse = 0b00000001,
FexDriverInputTypes_Keyboard = 0b00000010, FexDriverInputTypes_Keyboard = 0b00000010,
/* ... */ /* ... */
}; };
struct Fex struct Fex
{ {
char Magic[4]; char Magic[4];
enum FexFormatType Type : 4; enum FexFormatType Type : 4;
enum FexOSType OS : 4; enum FexOSType OS : 4;
int (*EntryPoint)(void *); int (*EntryPoint)(void *);
} __attribute__((packed)); } __attribute__((packed));
union KernelCallback; union KernelCallback;
@ -97,49 +97,49 @@ union CPURegisters;
struct FexExtended struct FexExtended
{ {
struct struct
{ {
} Executable; } Executable;
struct struct
{ {
char Name[64]; char Name[64];
enum FexDriverType Type : 4; enum FexDriverType Type : 4;
enum FexDriverInputTypes TypeFlags : 4; enum FexDriverInputTypes TypeFlags : 4;
char OverrideOnConflict : 1; char OverrideOnConflict;
int (*Callback)(union KernelCallback *); int (*Callback)(union KernelCallback *);
int (*InterruptCallback)(union CPURegisters *); int (*InterruptCallback)(union CPURegisters *);
struct DriverBind struct DriverBind
{ {
int Type; int Type;
struct struct
{ {
unsigned char Vector[16]; unsigned char Vector[16];
} Interrupt; } Interrupt;
struct struct
{ {
unsigned int ProcessId[16]; unsigned int ProcessId[16];
} Process; } Process;
struct struct
{ {
unsigned short VendorID[16]; unsigned short VendorID[16];
unsigned short DeviceID[16]; unsigned short DeviceID[16];
unsigned short Class; unsigned short Class;
unsigned short SubClass; unsigned short SubClass;
unsigned short ProgIF; unsigned short ProgIF;
} PCI; } PCI;
struct struct
{ {
char AttachToMouse; char AttachToMouse;
char AttachToKeyboard; char AttachToKeyboard;
} Input; } Input;
} Bind; } Bind;
} Driver; } Driver;
} __attribute__((packed)); } __attribute__((packed));
/** /**
@ -152,10 +152,10 @@ struct FexExtended
* @note Must include ".header : { *(.header .header.*) }" in linker script * @note Must include ".header : { *(.header .header.*) }" in linker script
*/ */
#define HEAD(FormatType, OperatingSystem, Address) \ #define HEAD(FormatType, OperatingSystem, Address) \
__attribute__((section(".header"))) struct Fex FexHeader = { \ __attribute__((section(".header"))) struct Fex FexHeader = { \
.Magic = {'F', 'E', 'X', '\0'}, \ .Magic = {'F', 'E', 'X', '\0'}, \
.Type = FormatType, \ .Type = FormatType, \
.OS = OperatingSystem, \ .OS = OperatingSystem, \
.EntryPoint = Address} .EntryPoint = Address}
#endif // !__FENNIX_FILE_FEX_H__ #endif // !__FENNIX_FILE_FEX_H__

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -22,24 +22,24 @@
enum DebugLevel enum DebugLevel
{ {
DebugLevelNone = 0, DebugLevelNone = 0,
DebugLevelError = 1, DebugLevelError = 1,
DebugLevelWarning = 2, DebugLevelWarning = 2,
DebugLevelInfo = 3, DebugLevelInfo = 3,
DebugLevelDebug = 4, DebugLevelDebug = 4,
DebugLevelTrace = 5, DebugLevelTrace = 5,
DebugLevelFixme = 6, DebugLevelFixme = 6,
DebugLevelUbsan = 7 DebugLevelUbsan = 7
}; };
#ifdef __cplusplus #ifdef __cplusplus
namespace SysDbg namespace SysDbg
{ {
void Write(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 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 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 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__) #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 #endif // __cplusplus
#define stub fixme("stub")
#endif // !__FENNIX_KERNEL_DEBUGGER_H__ #endif // !__FENNIX_KERNEL_DEBUGGER_H__

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff