mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-28 15:34:33 +00:00
Move drivers to kernel
This commit is contained in:
parent
e2063130ea
commit
80980ecfaf
@ -20,69 +20,61 @@
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../Drivers/drv.hpp"
|
||||
#include "../../kernel.h"
|
||||
#include "../../DAPI.hpp"
|
||||
#include "../../Fex.hpp"
|
||||
#include "api.hpp"
|
||||
|
||||
NewLock(DriverInitLock);
|
||||
NewLock(DriverInterruptLock);
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
void Driver::Panic()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
size_t DriversNum = Drivers.size();
|
||||
debug("%ld drivers loaded, [DUIDs: %ld]", DriversNum, DriverUIDs);
|
||||
debug("driver size %ld", DriversNum);
|
||||
#endif
|
||||
debug("%ld drivers loaded, [DriverUIDs: %ld]", Drivers.size(), DriverUIDs - 1);
|
||||
|
||||
foreach (auto drv in Drivers)
|
||||
foreach (auto Drv in Drivers)
|
||||
{
|
||||
KernelCallback callback{};
|
||||
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;
|
||||
drv.InterruptHook[j]->Disable();
|
||||
debug("Interrupt hook %#lx disabled", drv.InterruptHook[j]);
|
||||
|
||||
Drv.InterruptHook[j]->Disable();
|
||||
debug("Interrupt hook %#lx disabled", Drv.InterruptHook[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Driver::UnloadAllDrivers()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
size_t DriversNum = Drivers.size();
|
||||
debug("%ld drivers loaded, [DUIDs: %ld]", DriversNum, DriverUIDs);
|
||||
debug("driver size %ld", DriversNum);
|
||||
#endif
|
||||
debug("%ld drivers loaded, [DriverUIDs: %ld]", Drivers.size(), DriverUIDs - 1);
|
||||
|
||||
foreach (auto drv in Drivers)
|
||||
foreach (auto Drv in Drivers)
|
||||
{
|
||||
KernelCallback callback{};
|
||||
callback.Reason = StopReason;
|
||||
debug("Stopping & unloading driver %ld [%#lx]", drv.DriverUID, drv.Address);
|
||||
DriverManager->IOCB(drv.DriverUID, &callback);
|
||||
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++)
|
||||
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
|
||||
{
|
||||
if (!drv.InterruptHook[j])
|
||||
if (!Drv.InterruptHook[j])
|
||||
continue;
|
||||
debug("Interrupt hook %#lx", drv.InterruptHook[j]);
|
||||
delete drv.InterruptHook[j], drv.InterruptHook[j] = nullptr;
|
||||
|
||||
debug("Interrupt hook %#lx", Drv.InterruptHook[j]);
|
||||
delete Drv.InterruptHook[j], Drv.InterruptHook[j] = nullptr;
|
||||
}
|
||||
if (drv.MemTrk)
|
||||
delete drv.MemTrk, drv.MemTrk = nullptr;
|
||||
|
||||
if (Drv.MemTrk)
|
||||
delete Drv.MemTrk, Drv.MemTrk = nullptr;
|
||||
}
|
||||
Drivers.clear();
|
||||
}
|
||||
@ -91,27 +83,31 @@ namespace Driver
|
||||
{
|
||||
debug("Searching for driver %ld", DUID);
|
||||
|
||||
foreach (auto drv in Drivers)
|
||||
{
|
||||
if (drv.DriverUID == DUID)
|
||||
foreach (auto Drv in Drivers)
|
||||
{
|
||||
if (Drv.DriverUID != DUID)
|
||||
continue;
|
||||
|
||||
KernelCallback callback{};
|
||||
callback.Reason = StopReason;
|
||||
debug("Stopping and unloading driver %ld [%#lx]", drv.DriverUID, drv.Address);
|
||||
this->IOCB(drv.DriverUID, &callback);
|
||||
debug("Stopping & 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++)
|
||||
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
|
||||
{
|
||||
if (!drv.InterruptHook[j])
|
||||
if (!Drv.InterruptHook[j])
|
||||
continue;
|
||||
debug("Interrupt hook %#lx", drv.InterruptHook[j]);
|
||||
delete drv.InterruptHook[j], drv.InterruptHook[j] = nullptr;
|
||||
|
||||
debug("Interrupt hook %#lx", Drv.InterruptHook[j]);
|
||||
delete Drv.InterruptHook[j], Drv.InterruptHook[j] = nullptr;
|
||||
}
|
||||
delete drv.MemTrk, drv.MemTrk = nullptr;
|
||||
Drivers.remove(drv);
|
||||
|
||||
if (Drv.MemTrk)
|
||||
delete Drv.MemTrk, Drv.MemTrk = nullptr;
|
||||
|
||||
Drivers.remove(Drv);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -119,35 +115,45 @@ namespace Driver
|
||||
{
|
||||
foreach (auto Drv in Drivers)
|
||||
{
|
||||
if (Drv.DriverUID == DUID)
|
||||
{
|
||||
FexExtended *DrvExtHdr = (FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS);
|
||||
int ret = ((int (*)(void *))((uintptr_t)DrvExtHdr->Driver.Callback + (uintptr_t)Drv.Address))(KCB);
|
||||
__sync;
|
||||
return ret;
|
||||
}
|
||||
if (Drv.DriverUID != DUID)
|
||||
continue;
|
||||
|
||||
FexExtended *fexE = (FexExtended *)Drv.ExtendedHeaderAddress;
|
||||
return ((int (*)(void *))((uintptr_t)fexE->Driver.Callback + (uintptr_t)Drv.Address))(KCB);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
DriverCode Driver::CallDriverEntryPoint(void *fex, void *KAPIAddress)
|
||||
DriverCode Driver::CallDriverEntryPoint(void *fex, bool BuiltIn)
|
||||
{
|
||||
memcpy(KAPIAddress, &KernelAPITemplate, sizeof(KernelAPI));
|
||||
DriverCode ret{};
|
||||
KernelAPI DriverKAPI = KernelAPITemplate;
|
||||
|
||||
((KernelAPI *)KAPIAddress)->Info.Offset = (unsigned long)fex;
|
||||
((KernelAPI *)KAPIAddress)->Info.DriverUID = DriverUIDs++;
|
||||
((KernelAPI *)KAPIAddress)->Info.KernelDebug = DebuggerIsAttached;
|
||||
DriverKAPI.Info.DriverUID = DriverUIDs++;
|
||||
DriverKAPI.Info.KernelDebug = DebuggerIsAttached;
|
||||
|
||||
#ifdef DEBUG
|
||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||
debug("DRIVER: %s HAS DRIVER ID %ld", fexExtended->Driver.Name, ((KernelAPI *)KAPIAddress)->Info.DriverUID);
|
||||
#endif
|
||||
debug("Calling driver entry point ( %#lx %ld )", (unsigned long)fex, DriverKAPI.Info.DriverUID);
|
||||
|
||||
debug("Calling driver entry point ( %#lx %ld )", (unsigned long)fex, ((KernelAPI *)KAPIAddress)->Info.DriverUID);
|
||||
int ret = ((int (*)(KernelAPI *))((uintptr_t)((Fex *)fex)->EntryPoint + (uintptr_t)fex))(((KernelAPI *)KAPIAddress));
|
||||
if (!BuiltIn)
|
||||
{
|
||||
DriverKAPI.Info.Offset = (unsigned long)fex;
|
||||
|
||||
if (DriverReturnCode::OK != ret)
|
||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
||||
debug("DRIVER: %s HAS DRIVER ID %ld",
|
||||
((FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS))->Driver.Name,
|
||||
DriverKAPI.Info.DriverUID);
|
||||
ret = ((DriverCode(*)(KernelAPI *))((uintptr_t)((Fex *)fex)->EntryPoint + (uintptr_t)fex))(((KernelAPI *)&DriverKAPI));
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("DRIVER: BUILTIN HAS DRIVER ID %ld", DriverKAPI.Info.DriverUID);
|
||||
ret = ((DriverCode(*)(KernelAPI *))((uintptr_t)fex))(((KernelAPI *)&DriverKAPI));
|
||||
}
|
||||
|
||||
if (DriverCode::OK != ret)
|
||||
{
|
||||
DriverUIDs--;
|
||||
return ret;
|
||||
}
|
||||
return DriverCode::OK;
|
||||
}
|
||||
|
||||
@ -155,63 +161,35 @@ namespace Driver
|
||||
{
|
||||
Fex *DrvHdr = (Fex *)DriverAddress;
|
||||
if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0')
|
||||
{
|
||||
if (Size > 0x1000)
|
||||
{
|
||||
Fex *ElfDrvHdr = (Fex *)(DriverAddress + 0x1000);
|
||||
if (ElfDrvHdr->Magic[0] != 'F' || ElfDrvHdr->Magic[1] != 'E' || ElfDrvHdr->Magic[2] != 'X' || ElfDrvHdr->Magic[3] != '\0')
|
||||
return DriverCode::INVALID_FEX_HEADER;
|
||||
else
|
||||
{
|
||||
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", ElfDrvHdr->Magic, ElfDrvHdr->Type, ElfDrvHdr->OS, ElfDrvHdr->EntryPoint);
|
||||
|
||||
if (ElfDrvHdr->Type == FexFormatType::FexFormatType_Driver)
|
||||
{
|
||||
FexExtended *ElfDrvExtHdr = (FexExtended *)((uintptr_t)ElfDrvHdr + EXTENDED_SECTION_ADDRESS);
|
||||
debug("Name: \"%s\"; Type: %d; Callback: %#lx", ElfDrvExtHdr->Driver.Name, ElfDrvExtHdr->Driver.Type, ElfDrvExtHdr->Driver.Callback);
|
||||
|
||||
if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
|
||||
return this->DriverLoadBindPCI(ElfDrvExtHdr, DriverAddress, Size, true);
|
||||
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
|
||||
return this->DriverLoadBindInterrupt(ElfDrvExtHdr, DriverAddress, Size, true);
|
||||
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
|
||||
return this->DriverLoadBindProcess(ElfDrvExtHdr, DriverAddress, Size, true);
|
||||
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
|
||||
return this->DriverLoadBindInput(ElfDrvExtHdr, DriverAddress, Size, true);
|
||||
else
|
||||
error("Unknown driver bind type: %d", ElfDrvExtHdr->Driver.Bind.Type);
|
||||
}
|
||||
else
|
||||
return DriverCode::NOT_DRIVER;
|
||||
}
|
||||
}
|
||||
else
|
||||
return DriverCode::INVALID_FEX_HEADER;
|
||||
}
|
||||
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", DrvHdr->Magic, DrvHdr->Type, DrvHdr->OS, DrvHdr->EntryPoint);
|
||||
|
||||
if (DrvHdr->Type == FexFormatType::FexFormatType_Driver)
|
||||
{
|
||||
FexExtended *DrvExtHdr = (FexExtended *)((uintptr_t)DrvHdr + EXTENDED_SECTION_ADDRESS);
|
||||
debug("Name: \"%s\"; Type: %d; Callback: %#lx", DrvExtHdr->Driver.Name, DrvExtHdr->Driver.Type, DrvExtHdr->Driver.Callback);
|
||||
|
||||
if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
|
||||
return this->DriverLoadBindPCI(DrvExtHdr, DriverAddress, Size);
|
||||
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
|
||||
return this->DriverLoadBindInterrupt(DrvExtHdr, DriverAddress, Size);
|
||||
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
|
||||
return this->DriverLoadBindProcess(DrvExtHdr, DriverAddress, Size);
|
||||
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
|
||||
return this->DriverLoadBindInput(DrvExtHdr, DriverAddress, Size);
|
||||
else
|
||||
error("Unknown driver bind type: %d", DrvExtHdr->Driver.Bind.Type);
|
||||
}
|
||||
else
|
||||
if (DrvHdr->Type != FexFormatType::FexFormatType_Driver)
|
||||
return DriverCode::NOT_DRIVER;
|
||||
return DriverCode::ERROR;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Driver::Driver()
|
||||
void Driver::LoadDrivers()
|
||||
{
|
||||
SmartCriticalSection(DriverInitLock);
|
||||
|
||||
@ -220,35 +198,53 @@ namespace Driver
|
||||
fixme("Loading driver config file: %s", DriverConfigFile.c_str());
|
||||
|
||||
VirtualFileSystem::File DriverDirectory = vfs->Open(Config.DriverDirectory);
|
||||
if (DriverDirectory.IsOK())
|
||||
if (!DriverDirectory.IsOK())
|
||||
{
|
||||
foreach (auto driver in DriverDirectory.node->Children)
|
||||
if (driver->Flags == VirtualFileSystem::NodeFlags::FILE)
|
||||
if (cwk_path_has_extension(driver->Name))
|
||||
{
|
||||
const char *extension;
|
||||
size_t extension_length;
|
||||
cwk_path_get_extension(driver->Name, &extension, &extension_length);
|
||||
debug("Driver: %s; Extension: %s", driver->Name, extension);
|
||||
if (strcmp(extension, ".fex") == 0 || strcmp(extension, ".elf") == 0)
|
||||
{
|
||||
uintptr_t ret = this->LoadDriver(driver->Address, driver->Length);
|
||||
char RetString[128];
|
||||
if (ret == DriverCode::OK)
|
||||
strncpy(RetString, "\e058C19OK", 10);
|
||||
else if (ret == DriverCode::NOT_AVAILABLE)
|
||||
strncpy(RetString, "\eFF7900NOT AVAILABLE", 21);
|
||||
else
|
||||
sprintf(RetString, "\eE85230FAILED (%#lx)", ret);
|
||||
KPrint("%s %s", driver->Name, RetString);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory.Status);
|
||||
vfs->Close(DriverDirectory);
|
||||
}
|
||||
|
||||
debug("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");
|
||||
|
@ -31,43 +31,9 @@
|
||||
|
||||
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);
|
||||
UNUSED(IsElf);
|
||||
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
|
||||
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
|
||||
memcpy(fex, (void *)DriverAddress, Size);
|
||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
||||
#ifdef DEBUG
|
||||
uint8_t *result = md5File((uint8_t *)fex, Size);
|
||||
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
|
||||
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
|
||||
kfree(result);
|
||||
#endif
|
||||
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI) + 1));
|
||||
|
||||
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
|
||||
{
|
||||
delete mem, mem = nullptr;
|
||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
||||
}
|
||||
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
|
||||
|
||||
switch (fexExtended->Driver.Type)
|
||||
{
|
||||
case FexDriverType::FexDriverType_Input:
|
||||
return BindInputInput(mem, fex);
|
||||
default:
|
||||
{
|
||||
warn("Unknown driver type: %d", fexExtended->Driver.Type);
|
||||
delete mem, mem = nullptr;
|
||||
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
return DriverCode::OK;
|
||||
stub;
|
||||
return DriverCode::NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
|
@ -31,55 +31,88 @@
|
||||
|
||||
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);
|
||||
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;
|
||||
if (!IsBuiltIn)
|
||||
{
|
||||
delete mem, mem = nullptr;
|
||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
||||
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;
|
||||
}
|
||||
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
|
||||
|
||||
switch (fexExtended->Driver.Type)
|
||||
if (IsBuiltIn)
|
||||
fex = 0x0; /* Addresses are absolute if built-in. */
|
||||
|
||||
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:
|
||||
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);
|
||||
{
|
||||
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", fexExtended->Driver.Type);
|
||||
delete mem, mem = nullptr;
|
||||
warn("Unknown driver type: %d", fexE->Driver.Type);
|
||||
delete mem;
|
||||
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
return DriverCode::OK;
|
||||
}
|
||||
}
|
||||
|
@ -31,165 +31,108 @@
|
||||
|
||||
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);
|
||||
switch (PCIDevice->HeaderType)
|
||||
FexExtended *DrvExtHdr = (FexExtended *)(DriverAddress + EXTENDED_SECTION_ADDRESS);
|
||||
if (IsBuiltIn)
|
||||
DrvExtHdr = (FexExtended *)(((BuiltInDriverInfo *)DriverAddress)->ExtendedHeader);
|
||||
|
||||
uint16_t SizeOfVendorID = sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) /
|
||||
sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID[0]);
|
||||
uint16_t SizeOfDeviceID = sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID) /
|
||||
sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID[0]);
|
||||
|
||||
for (uint16_t vID = 0; vID < SizeOfVendorID; vID++)
|
||||
{
|
||||
case 0: // PCI Header 0
|
||||
for (uint16_t dID = 0; dID < SizeOfDeviceID; dID++)
|
||||
{
|
||||
uint32_t BAR[6] = {0};
|
||||
size_t BARsSize[6] = {0};
|
||||
|
||||
BAR[0] = ((PCI::PCIHeader0 *)PCIDevice)->BAR0;
|
||||
BAR[1] = ((PCI::PCIHeader0 *)PCIDevice)->BAR1;
|
||||
BAR[2] = ((PCI::PCIHeader0 *)PCIDevice)->BAR2;
|
||||
BAR[3] = ((PCI::PCIHeader0 *)PCIDevice)->BAR3;
|
||||
BAR[4] = ((PCI::PCIHeader0 *)PCIDevice)->BAR4;
|
||||
BAR[5] = ((PCI::PCIHeader0 *)PCIDevice)->BAR5;
|
||||
|
||||
#ifdef DEBUG
|
||||
uintptr_t BAR_Type = BAR[0] & 1;
|
||||
uintptr_t BAR_IOBase = BAR[1] & (~3);
|
||||
uintptr_t BAR_MemoryBase = BAR[0] & (~15);
|
||||
|
||||
debug("Type: %d; IOBase: %#lx; MemoryBase: %#lx", BAR_Type, BAR_IOBase, BAR_MemoryBase);
|
||||
#endif
|
||||
|
||||
/* BARs Size */
|
||||
for (short i = 0; i < 6; i++)
|
||||
{
|
||||
if (BAR[i] == 0)
|
||||
if (DrvExtHdr->Driver.Bind.PCI.VendorID[vID] == 0 ||
|
||||
DrvExtHdr->Driver.Bind.PCI.DeviceID[dID] == 0)
|
||||
continue;
|
||||
|
||||
if ((BAR[i] & 1) == 0) // Memory Base
|
||||
{
|
||||
((PCI::PCIHeader0 *)PCIDevice)->BAR0 = 0xFFFFFFFF;
|
||||
size_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR0;
|
||||
((PCI::PCIHeader0 *)PCIDevice)->BAR0 = BAR[i];
|
||||
BARsSize[i] = size & (~15);
|
||||
BARsSize[i] = ~BARsSize[i] + 1;
|
||||
BARsSize[i] = BARsSize[i] & 0xFFFFFFFF;
|
||||
debug("BAR%d %#lx size: %d", i, BAR[i], BARsSize[i]);
|
||||
}
|
||||
else if ((BAR[i] & 1) == 1) // I/O Base
|
||||
{
|
||||
((PCI::PCIHeader0 *)PCIDevice)->BAR1 = 0xFFFFFFFF;
|
||||
size_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR1;
|
||||
((PCI::PCIHeader0 *)PCIDevice)->BAR1 = BAR[i];
|
||||
BARsSize[i] = size & (~3);
|
||||
BARsSize[i] = ~BARsSize[i] + 1;
|
||||
BARsSize[i] = BARsSize[i] & 0xFFFF;
|
||||
debug("BAR%d %#lx size: %d", i, BAR[i], BARsSize[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Mapping the BARs */
|
||||
for (short i = 0; i < 6; i++)
|
||||
{
|
||||
if (BAR[i] == 0)
|
||||
continue;
|
||||
|
||||
if ((BAR[i] & 1) == 0) // Memory Base
|
||||
{
|
||||
uintptr_t BARBase = BAR[i] & (~15);
|
||||
size_t BARSize = BARsSize[i];
|
||||
|
||||
debug("Mapping BAR%d %#lx-%#lx", i, BARBase, BARBase + BARSize);
|
||||
Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, Memory::PTFlag::RW | Memory::PTFlag::PWT);
|
||||
}
|
||||
else if ((BAR[i] & 1) == 1) // I/O Base
|
||||
{
|
||||
uintptr_t BARBase = BAR[i] & (~3);
|
||||
size_t BARSize = BARsSize[i];
|
||||
|
||||
debug("Mapping BAR%d %#x-%#x", i, BARBase, BARBase + BARSize);
|
||||
Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, Memory::PTFlag::RW | Memory::PTFlag::PWT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: // PCI Header 1 (PCI-to-PCI Bridge)
|
||||
{
|
||||
fixme("PCI Header 1 (PCI-to-PCI Bridge) not implemented yet");
|
||||
break;
|
||||
}
|
||||
case 2: // PCI Header 2 (PCI-to-CardBus Bridge)
|
||||
{
|
||||
fixme("PCI Header 2 (PCI-to-CardBus Bridge) not implemented yet");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Unknown header type %d", PCIDevice->HeaderType);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DriverCode Driver::DriverLoadBindPCI(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
|
||||
{
|
||||
UNUSED(IsElf);
|
||||
for (unsigned long Vidx = 0; Vidx < sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID) / sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[0]); Vidx++)
|
||||
{
|
||||
for (unsigned long Didx = 0; Didx < sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID) / sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[0]); Didx++)
|
||||
{
|
||||
if (Vidx >= sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID) && Didx >= sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID))
|
||||
break;
|
||||
|
||||
if (((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[Vidx] == 0 || ((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[Didx] == 0)
|
||||
continue;
|
||||
|
||||
std::vector<PCI::PCIDeviceHeader *> devices = PCIManager->FindPCIDevice(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[Vidx], ((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[Didx]);
|
||||
std::vector<PCI::PCIDeviceHeader *> devices =
|
||||
PCIManager->FindPCIDevice(DrvExtHdr->Driver.Bind.PCI.VendorID[vID],
|
||||
DrvExtHdr->Driver.Bind.PCI.DeviceID[dID]);
|
||||
if (devices.size() == 0)
|
||||
continue;
|
||||
|
||||
foreach (auto PCIDevice in devices)
|
||||
{
|
||||
debug("[%ld] VendorID: %#x; DeviceID: %#x", devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID);
|
||||
debug("[%ld] VendorID: %#x; DeviceID: %#x",
|
||||
devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID);
|
||||
|
||||
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
|
||||
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
|
||||
memcpy(fex, (void *)DriverAddress, Size);
|
||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
||||
#ifdef DEBUG
|
||||
uint8_t *result = md5File((uint8_t *)fex, Size);
|
||||
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
|
||||
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
|
||||
kfree(result);
|
||||
#endif
|
||||
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI) + 1));
|
||||
|
||||
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
|
||||
BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress;
|
||||
Fex *fex = nullptr;
|
||||
if (!IsBuiltIn)
|
||||
{
|
||||
delete mem, mem = nullptr;
|
||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
||||
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;
|
||||
}
|
||||
debug("Starting driver %s", fexExtended->Driver.Name);
|
||||
|
||||
MapPCIAddresses(PCIDevice);
|
||||
if (IsBuiltIn)
|
||||
fex = 0x0; /* Addresses are absolute if built-in. */
|
||||
|
||||
switch (fexExtended->Driver.Type)
|
||||
FexExtended *fexE = IsBuiltIn ? (FexExtended *)bidi->ExtendedHeader : (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||
debug("Starting driver %s", fexE->Driver.Name);
|
||||
|
||||
PCIManager->MapPCIAddresses(PCIDevice);
|
||||
|
||||
switch (fexE->Driver.Type)
|
||||
{
|
||||
case FexDriverType::FexDriverType_Generic:
|
||||
return BindPCIGeneric(mem, fex, PCIDevice);
|
||||
case FexDriverType::FexDriverType_Display:
|
||||
return BindPCIDisplay(mem, fex, PCIDevice);
|
||||
case FexDriverType::FexDriverType_Network:
|
||||
return BindPCINetwork(mem, fex, PCIDevice);
|
||||
case FexDriverType::FexDriverType_Storage:
|
||||
return BindPCIStorage(mem, fex, PCIDevice);
|
||||
case FexDriverType::FexDriverType_FileSystem:
|
||||
return BindPCIFileSystem(mem, fex, PCIDevice);
|
||||
case FexDriverType::FexDriverType_Input:
|
||||
return BindPCIInput(mem, fex, PCIDevice);
|
||||
case FexDriverType::FexDriverType_Audio:
|
||||
return BindPCIAudio(mem, fex, PCIDevice);
|
||||
{
|
||||
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)
|
||||
DrvFile.InterruptHook[0] = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine), DrvFile);
|
||||
|
||||
KernelCallback KCallback{};
|
||||
KCallback.RawPtr = PCIDevice;
|
||||
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", fexExtended->Driver.Type);
|
||||
delete mem, mem = nullptr;
|
||||
warn("Unknown driver type: %d", fexE->Driver.Type);
|
||||
delete mem;
|
||||
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
||||
}
|
||||
}
|
||||
|
@ -31,12 +31,9 @@
|
||||
|
||||
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);
|
||||
UNUSED(Size);
|
||||
UNUSED(DriverAddress);
|
||||
UNUSED(IsElf);
|
||||
stub;
|
||||
return DriverCode::NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -17,7 +17,6 @@
|
||||
|
||||
#include <pci.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <power.hpp>
|
||||
#if defined(a64)
|
||||
#include "../Architecture/amd64/acpi.hpp"
|
||||
@ -789,6 +788,101 @@ namespace PCI
|
||||
}
|
||||
#endif
|
||||
|
||||
void PCI::MapPCIAddresses(PCIDeviceHeader *PCIDevice, Memory::PageTable *Table)
|
||||
{
|
||||
debug("Header Type: %d", PCIDevice->HeaderType);
|
||||
switch (PCIDevice->HeaderType)
|
||||
{
|
||||
case 0: /* PCI Header 0 */
|
||||
{
|
||||
uint32_t BAR[6] = {0};
|
||||
size_t BARsSize[6] = {0};
|
||||
|
||||
BAR[0] = ((PCIHeader0 *)PCIDevice)->BAR0;
|
||||
BAR[1] = ((PCIHeader0 *)PCIDevice)->BAR1;
|
||||
BAR[2] = ((PCIHeader0 *)PCIDevice)->BAR2;
|
||||
BAR[3] = ((PCIHeader0 *)PCIDevice)->BAR3;
|
||||
BAR[4] = ((PCIHeader0 *)PCIDevice)->BAR4;
|
||||
BAR[5] = ((PCIHeader0 *)PCIDevice)->BAR5;
|
||||
|
||||
debug("Type: %d; IOBase: %#lx; MemoryBase: %#lx",
|
||||
BAR[0] & 1,
|
||||
BAR[1] & (~3),
|
||||
BAR[0] & (~15));
|
||||
|
||||
/* BARs Size */
|
||||
for (short i = 0; i < 6; i++)
|
||||
{
|
||||
if (BAR[i] == 0)
|
||||
continue;
|
||||
|
||||
if ((BAR[i] & 1) == 0) /* Memory Base */
|
||||
{
|
||||
((PCIHeader0 *)PCIDevice)->BAR0 = 0xFFFFFFFF;
|
||||
size_t size = ((PCIHeader0 *)PCIDevice)->BAR0;
|
||||
((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 */
|
||||
{
|
||||
((PCIHeader0 *)PCIDevice)->BAR1 = 0xFFFFFFFF;
|
||||
size_t size = ((PCIHeader0 *)PCIDevice)->BAR1;
|
||||
((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 */
|
||||
for (short i = 0; i < 6; i++)
|
||||
{
|
||||
if (BAR[i] == 0)
|
||||
continue;
|
||||
|
||||
if ((BAR[i] & 1) == 0) /* Memory Base */
|
||||
{
|
||||
uintptr_t BARBase = BAR[i] & (~15);
|
||||
size_t BARSize = BARsSize[i];
|
||||
|
||||
debug("Mapping BAR%d %#lx-%#lx", i, BARBase, BARBase + BARSize);
|
||||
Memory::Virtual(Table).Map((void *)BARBase, (void *)BARBase, BARSize,
|
||||
Memory::PTFlag::RW | Memory::PTFlag::PWT);
|
||||
}
|
||||
else if ((BAR[i] & 1) == 1) /* I/O Base */
|
||||
{
|
||||
uintptr_t BARBase = BAR[i] & (~3);
|
||||
size_t BARSize = BARsSize[i];
|
||||
|
||||
debug("Mapping BAR%d %#x-%#x", i, BARBase, BARBase + BARSize);
|
||||
Memory::Virtual(Table).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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PCI::EnumerateFunction(uintptr_t DeviceAddress, uintptr_t Function)
|
||||
{
|
||||
uintptr_t Offset = Function << 12;
|
||||
|
@ -32,15 +32,15 @@
|
||||
|
||||
namespace Time
|
||||
{
|
||||
bool HighPrecisionEventTimer::Sleep(uint64_t Duration, Units Unit)
|
||||
bool HighPrecisionEventTimer::Sleep(size_t Duration, Units Unit)
|
||||
{
|
||||
#if defined(a64)
|
||||
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
||||
size_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
||||
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
|
||||
CPU::Pause();
|
||||
return true;
|
||||
#elif defined(a32)
|
||||
uint64_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
||||
size_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
||||
while (mminl(&((HPET *)hpet)->MainCounterValue) < Target)
|
||||
CPU::Pause();
|
||||
return true;
|
||||
@ -48,7 +48,7 @@ namespace Time
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t HighPrecisionEventTimer::GetCounter()
|
||||
size_t HighPrecisionEventTimer::GetCounter()
|
||||
{
|
||||
#if defined(a64)
|
||||
return mminq(&((HPET *)hpet)->MainCounterValue);
|
||||
@ -57,7 +57,7 @@ return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t HighPrecisionEventTimer::CalculateTarget(uint64_t Target, Units Unit)
|
||||
size_t HighPrecisionEventTimer::CalculateTarget(size_t Target, Units Unit)
|
||||
{
|
||||
#if defined(a64)
|
||||
return mminq(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
|
||||
@ -66,10 +66,10 @@ return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t HighPrecisionEventTimer::GetNanosecondsSinceClassCreation()
|
||||
size_t HighPrecisionEventTimer::GetNanosecondsSinceClassCreation()
|
||||
{
|
||||
#if defined(a86)
|
||||
uint64_t Subtraction = this->GetCounter() - this->ClassCreationTime;
|
||||
size_t Subtraction = this->GetCounter() - this->ClassCreationTime;
|
||||
if (Subtraction <= 0 || this->clk <= 0)
|
||||
return 0;
|
||||
return Subtraction / (this->clk / ConvertUnit(Units::Nanoseconds));
|
||||
|
@ -31,31 +31,31 @@
|
||||
|
||||
namespace Time
|
||||
{
|
||||
bool TimeStampCounter::Sleep(uint64_t Duration, Units Unit)
|
||||
bool TimeStampCounter::Sleep(size_t Duration, Units Unit)
|
||||
{
|
||||
#if defined(a86)
|
||||
uint64_t Target = this->GetCounter() + (Duration * ConvertUnit(Unit)) / this->clk;
|
||||
size_t Target = this->GetCounter() + (Duration * ConvertUnit(Unit)) / this->clk;
|
||||
while (this->GetCounter() < Target)
|
||||
CPU::Pause();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t TimeStampCounter::GetCounter()
|
||||
size_t TimeStampCounter::GetCounter()
|
||||
{
|
||||
#if defined(a86)
|
||||
return CPU::Counter();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t TimeStampCounter::CalculateTarget(uint64_t Target, Units Unit)
|
||||
size_t TimeStampCounter::CalculateTarget(size_t Target, Units Unit)
|
||||
{
|
||||
#if defined(a86)
|
||||
return this->GetCounter() + (Target * ConvertUnit(Unit)) / this->clk;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t TimeStampCounter::GetNanosecondsSinceClassCreation()
|
||||
size_t TimeStampCounter::GetNanosecondsSinceClassCreation()
|
||||
{
|
||||
#if defined(a86)
|
||||
return (this->GetCounter() - this->ClassCreationTime) / this->clk;
|
||||
@ -66,9 +66,9 @@ namespace Time
|
||||
{
|
||||
#if defined(a86)
|
||||
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);
|
||||
uint64_t End = CPU::Counter();
|
||||
size_t End = CPU::Counter();
|
||||
|
||||
this->clk = End - Start;
|
||||
this->ClassCreationTime = this->GetCounter();
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
namespace Time
|
||||
{
|
||||
bool time::Sleep(uint64_t Duration, Units Unit)
|
||||
bool time::Sleep(size_t Duration, Units Unit)
|
||||
{
|
||||
switch (ActiveTimer)
|
||||
{
|
||||
@ -61,7 +61,7 @@ namespace Time
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t time::GetCounter()
|
||||
size_t time::GetCounter()
|
||||
{
|
||||
switch (ActiveTimer)
|
||||
{
|
||||
@ -90,7 +90,7 @@ namespace Time
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t time::CalculateTarget(uint64_t Target, Units Unit)
|
||||
size_t time::CalculateTarget(size_t Target, Units Unit)
|
||||
{
|
||||
switch (ActiveTimer)
|
||||
{
|
||||
@ -119,7 +119,7 @@ namespace Time
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t time::GetNanosecondsSinceClassCreation()
|
||||
size_t time::GetNanosecondsSinceClassCreation()
|
||||
{
|
||||
switch (ActiveTimer)
|
||||
{
|
||||
|
2
DAPI.hpp
2
DAPI.hpp
@ -85,7 +85,7 @@ struct KernelAPI
|
||||
struct KAPIInfo
|
||||
{
|
||||
unsigned long Offset;
|
||||
unsigned long DriverUID;
|
||||
unsigned int DriverUID;
|
||||
char KernelDebug;
|
||||
} Info;
|
||||
|
||||
|
311
Drivers/AHCI/AdvancedHostControllerInterface.cpp
Normal file
311
Drivers/AHCI/AdvancedHostControllerInterface.cpp
Normal 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
193
Drivers/AHCI/ahci.hpp
Normal 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__
|
91
Drivers/ATA/AdvancedTechnologyAttachment.cpp
Normal file
91
Drivers/ATA/AdvancedTechnologyAttachment.cpp
Normal 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;
|
||||
}
|
||||
}
|
@ -15,26 +15,17 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../../api.hpp"
|
||||
#ifndef __FENNIX_KERNEL_ATA_H__
|
||||
#define __FENNIX_KERNEL_ATA_H__
|
||||
|
||||
#include <ints.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <task.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
#include <types.h>
|
||||
#include "../../DAPI.hpp"
|
||||
|
||||
#include "../../../../kernel.h"
|
||||
#include "../../../../DAPI.hpp"
|
||||
#include "../../../../Fex.hpp"
|
||||
|
||||
namespace Driver
|
||||
namespace AdvancedTechnologyAttachment
|
||||
{
|
||||
DriverCode Driver::BindInputAudio(Memory::MemMgr *mem, void *fex)
|
||||
{
|
||||
UNUSED(mem);
|
||||
UNUSED(fex);
|
||||
return DriverCode::NOT_IMPLEMENTED;
|
||||
}
|
||||
int DriverEntry(void *);
|
||||
int CallbackHandler(KernelCallback *);
|
||||
int InterruptCallback(CPURegisters *);
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_ATA_H__
|
114
Drivers/AdvancedMicroDevices/PCNET.cpp
Normal file
114
Drivers/AdvancedMicroDevices/PCNET.cpp
Normal 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;
|
||||
}
|
||||
}
|
@ -15,26 +15,24 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../../api.hpp"
|
||||
#ifndef __FENNIX_KERNEL_AMD_PCNET_H__
|
||||
#define __FENNIX_KERNEL_AMD_PCNET_H__
|
||||
|
||||
#include <ints.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <task.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
#include <types.h>
|
||||
#include "../../DAPI.hpp"
|
||||
|
||||
#include "../../../../kernel.h"
|
||||
#include "../../../../DAPI.hpp"
|
||||
#include "../../../../Fex.hpp"
|
||||
|
||||
namespace Driver
|
||||
namespace PCNET
|
||||
{
|
||||
DriverCode Driver::BindInputDisplay(Memory::MemMgr *mem, void *fex)
|
||||
struct BARData
|
||||
{
|
||||
UNUSED(mem);
|
||||
UNUSED(fex);
|
||||
return DriverCode::NOT_IMPLEMENTED;
|
||||
}
|
||||
uint8_t Type;
|
||||
uint16_t IOBase;
|
||||
uint64_t MemoryBase;
|
||||
};
|
||||
|
||||
int DriverEntry(void *);
|
||||
int CallbackHandler(KernelCallback *);
|
||||
int InterruptCallback(CPURegisters *);
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_AMD_PCNET_H__
|
370
Drivers/AudioCodec97/AudioCodec97Driver.cpp
Normal file
370
Drivers/AudioCodec97/AudioCodec97Driver.cpp
Normal 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;
|
||||
}
|
||||
}
|
348
Drivers/AudioCodec97/ac97.hpp
Normal file
348
Drivers/AudioCodec97/ac97.hpp
Normal 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__
|
278
Drivers/BuiltinDriverLoader.cpp
Normal file
278
Drivers/BuiltinDriverLoader.cpp
Normal 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
369
Drivers/Intel/Gigabit.cpp
Normal 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
177
Drivers/Intel/gigabit.hpp
Normal 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__
|
234
Drivers/PersonalSystem2/Mouse.cpp
Normal file
234
Drivers/PersonalSystem2/Mouse.cpp
Normal 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;
|
||||
}
|
||||
}
|
59
Drivers/PersonalSystem2/mouse.hpp
Normal file
59
Drivers/PersonalSystem2/mouse.hpp
Normal 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
190
Drivers/Realtek/RTL8139.cpp
Normal 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;
|
||||
}
|
||||
}
|
38
Drivers/Realtek/rtl8139.hpp
Normal file
38
Drivers/Realtek/rtl8139.hpp
Normal 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
225
Drivers/VMware/Mouse.cpp
Normal 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
69
Drivers/VMware/mouse.hpp
Normal 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
32
Drivers/drv.hpp
Normal 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__
|
2
Fex.hpp
2
Fex.hpp
@ -107,7 +107,7 @@ struct FexExtended
|
||||
char Name[64];
|
||||
enum FexDriverType Type : 4;
|
||||
enum FexDriverInputTypes TypeFlags : 4;
|
||||
char OverrideOnConflict : 1;
|
||||
char OverrideOnConflict;
|
||||
int (*Callback)(union KernelCallback *);
|
||||
int (*InterruptCallback)(union CPURegisters *);
|
||||
|
||||
|
@ -30,7 +30,7 @@ extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end;
|
||||
extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_size;
|
||||
|
||||
#ifdef DEBUG
|
||||
uint64_t FIi = 0, PDi = 0, PWi = 0, PWWi = 0, PCi = 0, mmi = 0;
|
||||
size_t FIi = 0, PDi = 0, PWi = 0, PWWi = 0, PCi = 0, mmi = 0;
|
||||
#endif
|
||||
|
||||
namespace GraphicalUserInterface
|
||||
@ -43,8 +43,8 @@ namespace GraphicalUserInterface
|
||||
{
|
||||
foreach (auto Driver in DriverManager->GetDrivers())
|
||||
{
|
||||
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Input &&
|
||||
((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.TypeFlags & FexDriverInputTypes::FexDriverInputTypes_Mouse)
|
||||
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Input &&
|
||||
((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.TypeFlags & FexDriverInputTypes::FexDriverInputTypes_Mouse)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
static int once = 0;
|
||||
@ -116,7 +116,7 @@ namespace GraphicalUserInterface
|
||||
TopBarPos.Top -= 20;
|
||||
TopBarPos.Height = 20;
|
||||
TopBarPos.Width -= 60; /* buttons */
|
||||
if (unlikely(TopBarPos.Top < 0))
|
||||
if (unlikely((int64_t)TopBarPos.Top < 0))
|
||||
{
|
||||
TopBarPos.Top = 0;
|
||||
wnd->GetPositionPtr()->Top = 20;
|
||||
@ -263,7 +263,7 @@ namespace GraphicalUserInterface
|
||||
Rect TopBarPos = WndPos;
|
||||
TopBarPos.Top -= 20;
|
||||
TopBarPos.Height = 20;
|
||||
if (TopBarPos.Top < 0)
|
||||
if ((int64_t)TopBarPos.Top < 0)
|
||||
{
|
||||
TopBarPos.Top = 0;
|
||||
wnd->GetPositionPtr()->Top = 20;
|
||||
@ -279,10 +279,10 @@ namespace GraphicalUserInterface
|
||||
|
||||
MinimizeButtonPos.Left = TopBarPos.Left + TopBarPos.Width - 60;
|
||||
|
||||
if (unlikely(MouseArray[0].X >= MinimizeButtonPos.Left &&
|
||||
MouseArray[0].X <= CloseButtonPos.Left + CloseButtonPos.Width &&
|
||||
MouseArray[0].Y >= CloseButtonPos.Top &&
|
||||
MouseArray[0].Y <= CloseButtonPos.Top + CloseButtonPos.Height))
|
||||
if (unlikely(MouseArray[0].X >= (int64_t)(MinimizeButtonPos.Left) &&
|
||||
MouseArray[0].X <= (int64_t)(CloseButtonPos.Left + CloseButtonPos.Width) &&
|
||||
MouseArray[0].Y >= (int64_t)(CloseButtonPos.Top) &&
|
||||
MouseArray[0].Y <= (int64_t)(CloseButtonPos.Top + CloseButtonPos.Height)))
|
||||
{
|
||||
OverlayBufferRepaint = true;
|
||||
}
|
||||
@ -311,10 +311,10 @@ namespace GraphicalUserInterface
|
||||
|
||||
PutRect(this->OverlayBuffer, TopBarPos, 0x282828);
|
||||
// Title bar buttons (close, minimize, maximize) on the right
|
||||
if (MouseArray[0].X >= CloseButtonPos.Left &&
|
||||
MouseArray[0].X <= CloseButtonPos.Left + CloseButtonPos.Width &&
|
||||
MouseArray[0].Y >= CloseButtonPos.Top &&
|
||||
MouseArray[0].Y <= CloseButtonPos.Top + CloseButtonPos.Height)
|
||||
if (MouseArray[0].X >= (int64_t)(CloseButtonPos.Left) &&
|
||||
MouseArray[0].X <= (int64_t)(CloseButtonPos.Left + CloseButtonPos.Width) &&
|
||||
MouseArray[0].Y >= (int64_t)(CloseButtonPos.Top) &&
|
||||
MouseArray[0].Y <= (int64_t)(CloseButtonPos.Top + CloseButtonPos.Height))
|
||||
{
|
||||
PutRect(this->OverlayBuffer, CloseButtonPos, MouseArray[0].Left ? 0xFF5500 : 0xFF0000);
|
||||
RepaintNeeded = true;
|
||||
@ -324,10 +324,10 @@ namespace GraphicalUserInterface
|
||||
PutRect(this->OverlayBuffer, MaximizeButtonPos, 0x282828);
|
||||
}
|
||||
|
||||
if (MouseArray[0].X >= MaximizeButtonPos.Left &&
|
||||
MouseArray[0].X <= MaximizeButtonPos.Left + MaximizeButtonPos.Width &&
|
||||
MouseArray[0].Y >= MaximizeButtonPos.Top &&
|
||||
MouseArray[0].Y <= MaximizeButtonPos.Top + MaximizeButtonPos.Height)
|
||||
if (MouseArray[0].X >= (int64_t)(MaximizeButtonPos.Left) &&
|
||||
MouseArray[0].X <= (int64_t)(MaximizeButtonPos.Left + MaximizeButtonPos.Width) &&
|
||||
MouseArray[0].Y >= (int64_t)(MaximizeButtonPos.Top) &&
|
||||
MouseArray[0].Y <= (int64_t)(MaximizeButtonPos.Top + MaximizeButtonPos.Height))
|
||||
{
|
||||
PutRect(this->OverlayBuffer, MaximizeButtonPos, MouseArray[0].Left ? 0x454545 : 0x404040);
|
||||
RepaintNeeded = true;
|
||||
@ -337,10 +337,10 @@ namespace GraphicalUserInterface
|
||||
PutRect(this->OverlayBuffer, MaximizeButtonPos, 0x282828);
|
||||
}
|
||||
|
||||
if (MouseArray[0].X >= MinimizeButtonPos.Left &&
|
||||
MouseArray[0].X <= MinimizeButtonPos.Left + MinimizeButtonPos.Width &&
|
||||
MouseArray[0].Y >= MinimizeButtonPos.Top &&
|
||||
MouseArray[0].Y <= MinimizeButtonPos.Top + MinimizeButtonPos.Height)
|
||||
if (MouseArray[0].X >= (int64_t)(MinimizeButtonPos.Left) &&
|
||||
MouseArray[0].X <= (int64_t)(MinimizeButtonPos.Left + MinimizeButtonPos.Width) &&
|
||||
MouseArray[0].Y >= (int64_t)(MinimizeButtonPos.Top) &&
|
||||
MouseArray[0].Y <= (int64_t)(MinimizeButtonPos.Top + MinimizeButtonPos.Height))
|
||||
{
|
||||
PutRect(this->OverlayBuffer, MinimizeButtonPos, MouseArray[0].Left ? 0x454545 : 0x404040);
|
||||
RepaintNeeded = true;
|
||||
|
@ -66,8 +66,8 @@ namespace GraphicalUserInterface
|
||||
|
||||
void WidgetCollection::OnPaint(Event *e)
|
||||
{
|
||||
static int64_t LastWidth = 0;
|
||||
static int64_t LastHeight = 0;
|
||||
static size_t LastWidth = 0;
|
||||
static size_t LastHeight = 0;
|
||||
|
||||
if (LastWidth != ((Window *)this->ParentWindow)->GetPosition().Width ||
|
||||
LastHeight != ((Window *)this->ParentWindow)->GetPosition().Height)
|
||||
|
@ -79,7 +79,7 @@ namespace GraphicalUserInterface
|
||||
if (!this->Maximized)
|
||||
{
|
||||
char buf[256];
|
||||
sprintf(buf, "Left:\eAA11FF%lld\eFFFFFF Top:\eAA11FF%lld\eFFFFFF W:\eAA11FF%ld\eFFFFFF H:\eAA11FF%ld\eFFFFFF", this->Position.Left, this->Position.Top, this->Position.Width, this->Position.Height);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,7 @@ LockClass mExtTrkLock;
|
||||
* - [ ] Update SMBIOS functions to support newer versions and actually use it.
|
||||
* - [ ] COW (Copy On Write) for the virtual memory. (https://en.wikipedia.org/wiki/Copy-on-write)
|
||||
* - [ ] Bootstrap should have a separate bss section + PHDR.
|
||||
* - [ ] Reimplement the driver conflict detection.
|
||||
*
|
||||
* ISSUES:
|
||||
* - [x] Kernel stack is smashed when an interrupt occurs. (this bug it occurs when an interrupt like IRQ1 or IRQ12 occurs)
|
||||
@ -240,7 +241,7 @@ EXTERNC void KPrint(const char *Format, ...)
|
||||
uint64_t Nanoseconds = TimeManager->GetNanosecondsSinceClassCreation();
|
||||
if (Nanoseconds != 0)
|
||||
{
|
||||
printf("\eCCCCCC[\e00AEFF%llu.%07llu\eCCCCCC] ",
|
||||
printf("\eCCCCCC[\e00AEFF%lu.%07lu\eCCCCCC] ",
|
||||
Nanoseconds / 10000000,
|
||||
Nanoseconds % 10000000);
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ void TaskMgr()
|
||||
continue;
|
||||
int Status = Proc->Status;
|
||||
uint64_t ProcessCpuUsage = GetUsage(OldSystemTime, &Proc->Info);
|
||||
printf("\e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld)\n",
|
||||
printf("\e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld)\n",
|
||||
Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime);
|
||||
|
||||
foreach (auto Thd in Proc->Threads)
|
||||
@ -438,12 +438,13 @@ void KernelMainThread()
|
||||
|
||||
KPrint("Loading Drivers...");
|
||||
DriverManager = new Driver::Driver;
|
||||
DriverManager->LoadDrivers();
|
||||
|
||||
KPrint("Fetching Disks...");
|
||||
if (DriverManager->GetDrivers().size() > 0)
|
||||
{
|
||||
foreach (auto Driver in DriverManager->GetDrivers())
|
||||
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Storage)
|
||||
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Storage)
|
||||
DiskManager->FetchDisks(Driver.DriverUID);
|
||||
}
|
||||
else
|
||||
|
@ -42,7 +42,7 @@ namespace NetworkInterfaceManager
|
||||
if (DriverManager->GetDrivers().size() > 0)
|
||||
{
|
||||
foreach (auto Driver in DriverManager->GetDrivers())
|
||||
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Network)
|
||||
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Network)
|
||||
this->FetchNetworkCards(Driver.DriverUID);
|
||||
}
|
||||
else
|
||||
|
@ -57,7 +57,7 @@ namespace Recovery
|
||||
|
||||
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;
|
||||
break;
|
||||
@ -102,7 +102,7 @@ namespace Recovery
|
||||
|
||||
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;
|
||||
break;
|
||||
@ -140,7 +140,7 @@ namespace Recovery
|
||||
|
||||
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;
|
||||
break;
|
||||
@ -268,9 +268,9 @@ namespace Recovery
|
||||
uint64_t MemReserved = 0;
|
||||
while (true)
|
||||
{
|
||||
sprintf(TicksText, "%016lld / %016lld", TaskManager->GetSchedulerTicks(), TaskManager->GetLastTaskTicks());
|
||||
sprintf(TicksText, "%016ld / %016ld", TaskManager->GetSchedulerTicks(), TaskManager->GetLastTaskTicks());
|
||||
wdgDbgWin->SetText(SchedLblHnd, TicksText);
|
||||
sprintf(TicksText, "CPU Scheduled Core: %lld", TaskManager->GetLastCore());
|
||||
sprintf(TicksText, "CPU Scheduled Core: %d", TaskManager->GetLastCore());
|
||||
wdgDbgWin->SetText(wdgDbgCurrentCPUSchedCoreLbl, TicksText);
|
||||
static int RefreshMemCounter = 0;
|
||||
if (RefreshMemCounter-- == 0)
|
||||
@ -279,7 +279,7 @@ namespace Recovery
|
||||
MemTotal = KernelAllocator.GetTotalMemory();
|
||||
MemReserved = KernelAllocator.GetReservedMemory();
|
||||
uint64_t MemPercent = (MemUsed * 100) / MemTotal;
|
||||
sprintf(TicksText, "%lldMB / %lldGB (%lldMB reserved) %lld%% (%lld bytes allocated)", TO_MB(MemUsed), TO_GB(MemTotal), TO_MB(MemReserved), MemPercent, MemUsed);
|
||||
sprintf(TicksText, "%ldMB / %ldGB (%ldMB reserved) %ld%% (%ld bytes allocated)", TO_MB(MemUsed), TO_GB(MemTotal), TO_MB(MemReserved), MemPercent, MemUsed);
|
||||
wdgDbgWin->SetText(MemLblHnd, TicksText);
|
||||
RefreshMemCounter = 25;
|
||||
}
|
||||
@ -292,9 +292,9 @@ namespace Recovery
|
||||
static int 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);
|
||||
sprintf(TicksText, "%016lld / %016lld / %016lld", PWWi, PCi, mmi);
|
||||
sprintf(TicksText, "%016ld / %016ld / %016ld", PWWi, PCi, mmi);
|
||||
wdgDbgWin->SetText(GUI2LblHnd, TicksText);
|
||||
RefreshGUIDbgCounter = 5;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ typedef __INT32_TYPE__ mode_t;
|
||||
fixme("Unimplemented Syscall: %lld %lld %lld %lld %lld %lld %lld", a, b, c, d, e, f, g); \
|
||||
}
|
||||
|
||||
#define stub(a, b, c, d, e, f, g) \
|
||||
#define syscall_stub(a, b, c, d, e, f, g) \
|
||||
{ \
|
||||
fixme("( %lld %lld %lld %lld %lld %lld %lld ) stub", a, b, c, d, e, f, g); \
|
||||
}
|
||||
@ -648,7 +648,7 @@ static uint64_t sys_ptrace(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint6
|
||||
|
||||
static unsigned int sys_getuid(void)
|
||||
{
|
||||
stub(0, 0, 0, 0, 0, 0, 0);
|
||||
syscall_stub(0, 0, 0, 0, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -660,7 +660,7 @@ static uint64_t sys_syslog(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint6
|
||||
|
||||
static unsigned int sys_getgid(void)
|
||||
{
|
||||
stub(0, 0, 0, 0, 0, 0, 0);
|
||||
syscall_stub(0, 0, 0, 0, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -678,13 +678,13 @@ static uint64_t sys_setgid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint6
|
||||
|
||||
static unsigned int sys_geteuid(void)
|
||||
{
|
||||
stub(0, 0, 0, 0, 0, 0, 0);
|
||||
syscall_stub(0, 0, 0, 0, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int sys_getegid(void)
|
||||
{
|
||||
stub(0, 0, 0, 0, 0, 0, 0);
|
||||
syscall_stub(0, 0, 0, 0, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -103,4 +103,6 @@ void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, co
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#define stub fixme("stub")
|
||||
|
||||
#endif // !__FENNIX_KERNEL_DEBUGGER_H__
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <debug.h>
|
||||
#include <cpu.hpp>
|
||||
#include <pci.hpp>
|
||||
@ -31,15 +32,32 @@ namespace Driver
|
||||
{
|
||||
enum DriverCode
|
||||
{
|
||||
/* This must be the same as in DAPI.hpp DriverReturnCode */
|
||||
ERROR,
|
||||
OK,
|
||||
NOT_IMPLEMENTED,
|
||||
NOT_FOUND,
|
||||
NOT_READY,
|
||||
NOT_AVAILABLE,
|
||||
NOT_AUTHORIZED,
|
||||
NOT_VALID,
|
||||
NOT_ACCEPTED,
|
||||
INVALID_PCI_BAR,
|
||||
INVALID_KERNEL_API,
|
||||
INVALID_MEMORY_ALLOCATION,
|
||||
INVALID_DATA,
|
||||
DEVICE_NOT_SUPPORTED,
|
||||
SYSTEM_NOT_SUPPORTED,
|
||||
KERNEL_API_VERSION_NOT_SUPPORTED,
|
||||
|
||||
/* End of driver-only errors */
|
||||
|
||||
INVALID_FEX_HEADER,
|
||||
INVALID_DRIVER_DATA,
|
||||
NOT_DRIVER,
|
||||
NOT_IMPLEMENTED,
|
||||
DRIVER_RETURNED_ERROR,
|
||||
UNKNOWN_DRIVER_TYPE,
|
||||
UNKNOWN_DRIVER_BIND_TYPE,
|
||||
PCI_DEVICE_NOT_FOUND,
|
||||
DRIVER_CONFLICT
|
||||
};
|
||||
@ -48,8 +66,10 @@ namespace Driver
|
||||
struct DriverFile
|
||||
{
|
||||
bool Enabled = false;
|
||||
size_t DriverUID = 0;
|
||||
bool BuiltIn = false;
|
||||
unsigned int DriverUID = 0;
|
||||
void *Address = nullptr;
|
||||
void *ExtendedHeaderAddress = nullptr;
|
||||
void *InterruptCallback = nullptr;
|
||||
Memory::MemMgr *MemTrk = nullptr;
|
||||
DriverInterruptHook *InterruptHook[16]{};
|
||||
@ -60,9 +80,17 @@ namespace Driver
|
||||
}
|
||||
};
|
||||
|
||||
struct BuiltInDriverInfo
|
||||
{
|
||||
int (*EntryPoint)(void *);
|
||||
void *ExtendedHeader;
|
||||
};
|
||||
|
||||
class DriverInterruptHook : public Interrupts::Handler
|
||||
{
|
||||
private:
|
||||
NewLock(DriverInterruptLock);
|
||||
|
||||
DriverFile Handle;
|
||||
bool Enabled = true;
|
||||
|
||||
@ -85,56 +113,122 @@ namespace Driver
|
||||
class Driver
|
||||
{
|
||||
private:
|
||||
NewLock(DriverInitLock);
|
||||
|
||||
std::vector<DriverFile> Drivers;
|
||||
unsigned long DriverUIDs = 0;
|
||||
DriverCode CallDriverEntryPoint(void *fex, void *KAPIAddress);
|
||||
|
||||
void MapPCIAddresses(PCI::PCIDeviceHeader *PCIDevice);
|
||||
DriverCode BindPCIGeneric(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
||||
DriverCode BindPCIDisplay(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
||||
DriverCode BindPCINetwork(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
||||
DriverCode BindPCIStorage(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
||||
DriverCode BindPCIFileSystem(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
||||
DriverCode BindPCIInput(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
||||
DriverCode BindPCIAudio(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
||||
DriverCode DriverLoadBindPCI(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf = false);
|
||||
|
||||
DriverCode BindInterruptGeneric(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindInterruptDisplay(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindInterruptNetwork(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindInterruptStorage(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindInterruptFileSystem(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindInterruptInput(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindInterruptAudio(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode DriverLoadBindInterrupt(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf = false);
|
||||
|
||||
DriverCode BindInputGeneric(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindInputDisplay(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindInputNetwork(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindInputStorage(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindInputFileSystem(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindInputInput(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindInputAudio(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode DriverLoadBindInput(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf = false);
|
||||
|
||||
DriverCode BindProcessGeneric(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindProcessDisplay(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindProcessNetwork(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindProcessStorage(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindProcessFileSystem(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindProcessInput(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode BindProcessAudio(Memory::MemMgr *mem, void *fex);
|
||||
DriverCode DriverLoadBindProcess(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf = false);
|
||||
unsigned int DriverUIDs = 0;
|
||||
/* If BuiltIn is true, the "fex" is the entry point. */
|
||||
DriverCode CallDriverEntryPoint(void *fex, bool BuiltIn = false);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Load and bind a driver to a PCI device.
|
||||
*
|
||||
* This function will search for a PCI device with the given VendorID and DeviceID.
|
||||
* If the device is found, the driver will be loaded and bound to the device.
|
||||
*
|
||||
* @param DriverAddress The address of the driver. The file will be copied to a new location.
|
||||
* @param Size The size of the driver.
|
||||
* @param IsBuiltIn If the driver is built-in, the @param DriverAddress will be @see BuiltInDriverInfo and the @param Size will be ignored.
|
||||
* @return DriverCode The result of the operation.
|
||||
*/
|
||||
DriverCode DriverLoadBindPCI(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn = false);
|
||||
|
||||
/**
|
||||
* @brief Load and bind a driver to an interrupt.
|
||||
*
|
||||
* This function will search for an interrupt with the given IRQ.
|
||||
* If the interrupt is found, the driver will be loaded and bound to the interrupt.
|
||||
*
|
||||
* @param DriverAddress The address of the driver. The file will be copied to a new location.
|
||||
* @param Size The size of the driver.
|
||||
* @param IsBuiltIn If the driver is built-in, the @param DriverAddress will be @see BuiltInDriverInfo and the @param Size will be ignored.
|
||||
* @return DriverCode The result of the operation.
|
||||
*/
|
||||
DriverCode DriverLoadBindInterrupt(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn = false);
|
||||
|
||||
/**
|
||||
* @brief Load and bind a driver to an input device.
|
||||
*
|
||||
* This function will attach the driver to the input device.
|
||||
*
|
||||
* @param DriverAddress The address of the driver. The file will be copied to a new location.
|
||||
* @param Size The size of the driver.
|
||||
* @param IsBuiltIn If the driver is built-in, the @param DriverAddress will be @see BuiltInDriverInfo and the @param Size will be ignored.
|
||||
* @return DriverCode The result of the operation.
|
||||
*/
|
||||
DriverCode DriverLoadBindInput(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn = false);
|
||||
|
||||
/**
|
||||
* @brief Load and bind a driver to a process.
|
||||
*
|
||||
* This function will attach the driver to the process.
|
||||
*
|
||||
* @param DriverAddress The address of the driver. The file will be copied to a new location.
|
||||
* @param Size The size of the driver.
|
||||
* @param IsBuiltIn If the driver is built-in, the @param DriverAddress will be @see BuiltInDriverInfo and the @param Size will be ignored.
|
||||
* @return DriverCode The result of the operation.
|
||||
*/
|
||||
DriverCode DriverLoadBindProcess(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn = false);
|
||||
|
||||
/**
|
||||
* @brief Get the currently loaded drivers.
|
||||
*
|
||||
* This function returns a clone of the drivers vector.
|
||||
* This means that the vector can be modified without affecting the drivers.
|
||||
*
|
||||
* @return std::vector<DriverFile> A clone of the drivers vector.
|
||||
*/
|
||||
std::vector<DriverFile> GetDrivers() { return Drivers; }
|
||||
|
||||
/* Reserved by the kernel */
|
||||
void Panic();
|
||||
|
||||
/**
|
||||
* @brief Unload all drivers.
|
||||
*
|
||||
* This function will unload all drivers.
|
||||
*/
|
||||
void UnloadAllDrivers();
|
||||
|
||||
/**
|
||||
* @brief Unload a driver.
|
||||
*
|
||||
* This function will unload a driver with the given driver unique ID.
|
||||
* It will free the memory and remove the driver from the drivers vector.
|
||||
*
|
||||
* @param DUID The driver unique ID.
|
||||
* @return true If the driver was found and unloaded successfully, false otherwise.
|
||||
*/
|
||||
bool UnloadDriver(unsigned long DUID);
|
||||
|
||||
/**
|
||||
* @brief Send a callback to a driver.
|
||||
*
|
||||
* This function will send a callback to a driver with the given driver unique ID.
|
||||
* This is used to communicate with drivers.
|
||||
*
|
||||
* @param DUID The driver unique ID.
|
||||
* @param KCB The @see KernelCallback structure.
|
||||
* @return int The result of the operation.
|
||||
*/
|
||||
int IOCB(unsigned long DUID, /* KernelCallback */ void *KCB);
|
||||
|
||||
/**
|
||||
* @brief Load a driver.
|
||||
* @param DriverAddress The address of the driver file.
|
||||
* @param Size The size of the driver file.
|
||||
* @return DriverCode The result of the operation.
|
||||
*/
|
||||
DriverCode LoadDriver(uintptr_t DriverAddress, size_t Size);
|
||||
DriverCode StartDrivers();
|
||||
|
||||
/* Reserved by the kernel */
|
||||
void LoadDrivers();
|
||||
|
||||
/* Reserved by the kernel */
|
||||
Driver();
|
||||
|
||||
/* Reserved by the kernel */
|
||||
~Driver();
|
||||
};
|
||||
}
|
||||
|
@ -50,12 +50,12 @@ namespace GraphicalUserInterface
|
||||
|
||||
struct Rect
|
||||
{
|
||||
int64_t Left;
|
||||
int64_t Top;
|
||||
size_t Left;
|
||||
size_t Top;
|
||||
size_t Width;
|
||||
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);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
#include <vector>
|
||||
|
||||
@ -226,6 +227,7 @@ namespace PCI
|
||||
|
||||
public:
|
||||
std::vector<PCIDeviceHeader *> &GetDevices() { return Devices; }
|
||||
void MapPCIAddresses(PCIDeviceHeader *PCIDevice, Memory::PageTable *Table = nullptr);
|
||||
void EnumerateFunction(uintptr_t DeviceAddress, uintptr_t Function);
|
||||
void EnumerateDevice(uintptr_t BusAddress, uintptr_t Device);
|
||||
void EnumerateBus(uintptr_t BaseAddress, uintptr_t Bus);
|
||||
|
@ -95,11 +95,11 @@ namespace Tasking
|
||||
|
||||
struct TaskInfo
|
||||
{
|
||||
uint64_t OldUserTime = 0;
|
||||
uint64_t OldKernelTime = 0;
|
||||
size_t OldUserTime = 0;
|
||||
size_t OldKernelTime = 0;
|
||||
|
||||
uint64_t SleepUntil = 0;
|
||||
uint64_t KernelTime = 0, UserTime = 0, SpawnTime = 0, LastUpdateTime = 0;
|
||||
size_t SleepUntil = 0;
|
||||
size_t KernelTime = 0, UserTime = 0, SpawnTime = 0, LastUpdateTime = 0;
|
||||
uint64_t Year, Month, Day, Hour, Minute, Second;
|
||||
bool Affinity[256]; // MAX_CPU
|
||||
TaskPriority Priority;
|
||||
@ -250,8 +250,8 @@ namespace Tasking
|
||||
PCB *IdleProcess = nullptr;
|
||||
TCB *IdleThread = nullptr;
|
||||
TCB *CleanupThread = nullptr;
|
||||
std::atomic_uint64_t SchedulerTicks = 0;
|
||||
std::atomic_uint64_t LastTaskTicks = 0;
|
||||
std::atomic_size_t SchedulerTicks = 0;
|
||||
std::atomic_size_t LastTaskTicks = 0;
|
||||
std::atomic_int LastCore = 0;
|
||||
bool StopScheduler = false;
|
||||
bool InvalidPCB(PCB *pcb);
|
||||
@ -282,9 +282,9 @@ namespace Tasking
|
||||
|
||||
public:
|
||||
void SetCleanupThread(TCB *Thread) { CleanupThread = Thread; }
|
||||
uint64_t GetSchedulerTicks() { return SchedulerTicks.load(); }
|
||||
uint64_t GetLastTaskTicks() { return LastTaskTicks.load(); }
|
||||
uint64_t GetLastCore() { return LastCore.load(); }
|
||||
size_t GetSchedulerTicks() { return SchedulerTicks.load(); }
|
||||
size_t GetLastTaskTicks() { return LastTaskTicks.load(); }
|
||||
int GetLastCore() { return LastCore.load(); }
|
||||
std::vector<PCB *> GetProcessList() { return ProcessList; }
|
||||
Security *GetSecurityManager() { return &SecurityManager; }
|
||||
void CleanupProcessesThread();
|
||||
|
@ -26,7 +26,7 @@ namespace Time
|
||||
struct Clock
|
||||
{
|
||||
int Year, Month, Day, Hour, Minute, Second;
|
||||
uint64_t Counter;
|
||||
size_t Counter;
|
||||
};
|
||||
|
||||
Clock ReadClock();
|
||||
@ -65,9 +65,9 @@ namespace Time
|
||||
|
||||
uint32_t clk = 0;
|
||||
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)
|
||||
{
|
||||
@ -100,10 +100,10 @@ namespace Time
|
||||
}
|
||||
|
||||
public:
|
||||
bool Sleep(uint64_t Duration, Units Unit);
|
||||
uint64_t GetCounter();
|
||||
uint64_t CalculateTarget(uint64_t Target, Units Unit);
|
||||
uint64_t GetNanosecondsSinceClassCreation();
|
||||
bool Sleep(size_t Duration, Units Unit);
|
||||
size_t GetCounter();
|
||||
size_t CalculateTarget(size_t Target, Units Unit);
|
||||
size_t GetNanosecondsSinceClassCreation();
|
||||
|
||||
HighPrecisionEventTimer(void *hpet);
|
||||
~HighPrecisionEventTimer();
|
||||
@ -112,10 +112,10 @@ namespace Time
|
||||
class TimeStampCounter
|
||||
{
|
||||
private:
|
||||
uint64_t clk = 0;
|
||||
uint64_t ClassCreationTime = 0;
|
||||
size_t clk = 0;
|
||||
size_t ClassCreationTime = 0;
|
||||
|
||||
inline uint64_t ConvertUnit(Units Unit)
|
||||
inline size_t ConvertUnit(Units Unit)
|
||||
{
|
||||
switch (Unit)
|
||||
{
|
||||
@ -148,10 +148,10 @@ namespace Time
|
||||
}
|
||||
|
||||
public:
|
||||
bool Sleep(uint64_t Duration, Units Unit);
|
||||
uint64_t GetCounter();
|
||||
uint64_t CalculateTarget(uint64_t Target, Units Unit);
|
||||
uint64_t GetNanosecondsSinceClassCreation();
|
||||
bool Sleep(size_t Duration, Units Unit);
|
||||
size_t GetCounter();
|
||||
size_t CalculateTarget(size_t Target, Units Unit);
|
||||
size_t GetNanosecondsSinceClassCreation();
|
||||
|
||||
TimeStampCounter();
|
||||
~TimeStampCounter();
|
||||
@ -189,10 +189,10 @@ namespace Time
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sleep(uint64_t Duration, Units Unit);
|
||||
uint64_t GetCounter();
|
||||
uint64_t CalculateTarget(uint64_t Target, Units Unit);
|
||||
uint64_t GetNanosecondsSinceClassCreation();
|
||||
bool Sleep(size_t Duration, Units Unit);
|
||||
size_t GetCounter();
|
||||
size_t CalculateTarget(size_t Target, Units Unit);
|
||||
size_t GetNanosecondsSinceClassCreation();
|
||||
void FindTimers(void *acpi);
|
||||
time();
|
||||
~time();
|
||||
|
@ -42,9 +42,9 @@ namespace std
|
||||
class string
|
||||
{
|
||||
private:
|
||||
char *Data;
|
||||
size_t Length;
|
||||
size_t Capacity;
|
||||
char *Data{};
|
||||
size_t Length{};
|
||||
size_t Capacity{};
|
||||
|
||||
public:
|
||||
static const size_t npos = -1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user