Update filesystem structure

This commit is contained in:
Alex 2023-05-20 04:46:51 +03:00
parent 1e7632657e
commit 488b0a84e0
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
48 changed files with 66 additions and 4732 deletions

View File

@ -1,394 +0,0 @@
#include "ac97.hpp"
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(void *Data);
int CallbackHandler(KernelCallback *Data);
int InterruptCallback(CPURegisters *Registers);
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "Audio Codec '97 Driver",
.Type = FexDriverType_Audio,
.TypeFlags = FexDriverInputTypes_None,
.OverrideOnConflict = false,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x8086},
.DeviceID = {0x2415},
.Class = 0x4,
.SubClass = 0x3,
.ProgIF = 0x0,
}}}};
KernelAPI *KAPI;
#define print(msg) KAPI->Util.DebugPrint((char *)(msg), KAPI->Info.DriverUID)
/* --------------------------------------------------------------------------------------------------------- */
/* https://wiki.osdev.org/AC97 */
PCIDeviceHeader *PCIBaseAddress;
BARData BAR;
BufferDescriptorList *DescriptorList = nullptr;
AudioEncodingValues Encoding = AE_PCMs16le;
char Channels = 2;
char 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:
{
print("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
print("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 = PCIBAR0 & (~3);
BAR.BusMasterAddress = PCIBAR1 & (~15);
if (BAR.Type != 1)
{
print("BAR0 is not I/O.");
return INVALID_PCI_BAR;
}
uint16_t OutputPCMTransferControl = BAR.BusMasterAddress + PCMOUT_TransferControl;
/* DescriptorList address MUST be physical. */
DescriptorList = (BufferDescriptorList *)KAPI->Memory.RequestPage((sizeof(BufferDescriptorList) * DescriptorListLength) / KAPI->Memory.PageSize + 1);
KAPI->Util.memset(DescriptorList, 0, sizeof(BufferDescriptorList) * DescriptorListLength);
uint16_t DLSampleCount = KAPI->Memory.PageSize / SampleSize;
char DLLogBuffer[128];
for (int i = 0; i < DescriptorListLength; i++)
{
int DescriptorPages = 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;
KAPI->Util.sprintf(DLLogBuffer, "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);
print(DLLogBuffer);
}
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(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(BAR.BusMasterAddress + PCMOUT_BufferDescriptorList, (uint32_t)(uint64_t)DescriptorList);
outl(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);
print("AC'97 configured.");
break;
}
case AdjustReason:
{
if (Data->AudioCallback.Adjust._Volume)
{
Volume = 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)
{
print("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;
print("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;
print("Invalid channel count. Defaulting to 2.");
break;
}
}
}
break;
}
case FetchReason:
{
Data->AudioCallback.Fetch.Volume = (inw(BAR.MixerAddress + NAM_MasterVolume) & 0x3F) * 100 / 0x3F;
Data->AudioCallback.Fetch.Encoding = Encoding; /* FIXME */
Data->AudioCallback.Fetch.SampleRate = SampleRate;
Data->AudioCallback.Fetch.Channels = Channels;
break;
}
case SendReason:
{
unsigned char *Buffer = (unsigned char *)Data->AudioCallback.Send.Data;
unsigned int Length = Data->AudioCallback.Send.Length;
if (Buffer == nullptr)
{
print("Invalid buffer.");
return INVALID_DATA;
}
if ((Length == 0) || (Length % (SampleSize * Channels)))
{
print("Invalid buffer length.");
return INVALID_DATA;
}
int TotalBDLToFill = (Length + KAPI->Memory.PageSize - 1) >> 12;
while (Length > 0)
{
bool ActiveDMA = !(inw(BAR.BusMasterAddress + PCMOUT_Status) & TC_DMAControllerControl);
if (ActiveDMA)
{
int RemainingBDL = 0;
do
{
int CurrentBDL = inb(BAR.BusMasterAddress + PCMOUT_BufferDescriptorEntry);
int LastBDL = inb(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(BAR.BusMasterAddress + PCMOUT_Status) & TC_DMAControllerControl));
}
{
int CurrentBDL = inb(BAR.BusMasterAddress + PCMOUT_BufferDescriptorEntry);
int LastBDL = inb(BAR.BusMasterAddress + PCMOUT_DescriptorEntries);
int NextBDL = LastBDL % DescriptorListLength;
ActiveDMA = !(inw(BAR.BusMasterAddress + PCMOUT_Status) & TC_DMAControllerControl);
if (ActiveDMA)
{
NextBDL = (LastBDL + 1) % DescriptorListLength;
if (NextBDL == CurrentBDL)
continue;
}
do
{
int Wrote = (KAPI->Memory.PageSize > Length) ? Length : KAPI->Memory.PageSize;
if (Wrote == 0)
break;
KAPI->Util.memcpy((void *)((uint64_t)DescriptorList[NextBDL].Address), Buffer, Wrote);
DescriptorList[NextBDL].Flags = 0;
Buffer += Wrote;
Length -= Wrote;
DescriptorList[NextBDL].SampleCount = Wrote / SampleSize;
TotalBDLToFill--;
NextBDL = (NextBDL + 1) % DescriptorListLength;
} while (TotalBDLToFill-- && NextBDL != CurrentBDL);
outb(BAR.BusMasterAddress + PCMOUT_DescriptorEntries, NextBDL - 1);
ActiveDMA = !(inw(BAR.BusMasterAddress + PCMOUT_Status) & TC_DMAControllerControl);
if (!ActiveDMA)
{
// Start DMA
outb(BAR.BusMasterAddress + PCMOUT_TransferControl, inb(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(BAR.BusMasterAddress + PCMOUT_TransferControl, inb(BAR.BusMasterAddress + PCMOUT_TransferControl) & ~TC_DMAControllerControl);
// Disable interrupts
uint8_t TransferControl = inb(BAR.BusMasterAddress + PCMOUT_TransferControl);
TransferControl &= ~(TC_LastBufferEntryInterruptEnable | TC_IOCInterruptEnable | TC_FifoERRORInterruptEnable);
outb(BAR.BusMasterAddress + PCMOUT_TransferControl, TransferControl);
// Disable global control
uint32_t GlobalControl = inl(BAR.BusMasterAddress + NABM_GlobalControl);
GlobalControl &= ~GC_GlobalInterruptEnable;
GlobalControl |= GC_ShutDown;
outl(BAR.BusMasterAddress + NABM_GlobalControl, GlobalControl);
print("Driver stopped.");
break;
}
default:
{
print("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
uint16_t Status = inw(BAR.MixerAddress + PCMOUT_Status);
if (Status & TC_IOCInterruptEnable)
{
print("Interrupt on completion.");
}
else if (Status & TC_LastBufferEntryInterruptEnable)
{
print("Last buffer entry.");
// Stop DMA
outb(BAR.BusMasterAddress + PCMOUT_TransferControl, inb(BAR.BusMasterAddress + PCMOUT_TransferControl) & ~TC_DMAControllerControl);
}
else if (Status & TC_FifoERRORInterruptEnable)
{
print("FIFO error.");
}
else if (Status != 0x0)
{
char UnknownStatusText[64];
KAPI->Util.sprintf(UnknownStatusText, "Unknown status: %#lx", Status);
print(UnknownStatusText);
}
outw(BAR.MixerAddress + PCMOUT_Status, 0xFFFF);
return OK;
}

View File

@ -1,99 +0,0 @@
# Config file
include ../../../Makefile.conf
FILENAME = AudioCodec97.fex
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
INCLUDE_DIR = ../../include
LDFLAGS := \
-fPIC -fPIE -pie -Wl,-eDriverEntry \
-Wl,-static,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -static -Tlinker.ld
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=i386 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i386)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i386)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -1,325 +0,0 @@
#ifndef __FENNIX_API_AC97_H__
#define __FENNIX_API_AC97_H__
#include <types.h>
#include <pci.h>
#include <io.h>
#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;
uint64_t MixerAddress;
uint64_t BusMasterAddress;
};
#endif // !__FENNIX_API_AC97_H__

View File

@ -1,40 +0,0 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:x86-64)
ENTRY(DriverEntry)
SECTIONS
{
.header :
{
*(.header .header.*)
*(.extended .extended.*)
}
.text :
{
*(.text .text.*)
}
.data :
{
*(.data .data.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.bss :
{
*(COMMON)
*(.bss .bss.*)
}
/DISCARD/ :
{
*(.eh_frame)
*(.note .note.*)
}
}

View File

@ -1,5 +1,3 @@
build:
make -C AudioCodec97 build
clean:
make -C AudioCodec97 clean

View File

@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = "Fennix Drivers"
PROJECT_NAME = "Fennix Modules"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
@ -864,7 +864,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = Drivers tools/Doxygen_README.md
INPUT = Modules tools/Doxygen_README.md
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@ -1224,7 +1224,7 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = doxygen-doc/drivers
HTML_OUTPUT = doxygen-doc/modules
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).

View File

@ -1,5 +1,3 @@
build:
make -C ext2 build
clean:
make -C ext2 clean

View File

@ -1,5 +0,0 @@
build:
clean:

View File

@ -10,75 +10,83 @@ int InterruptCallback(CPURegisters *Registers);
* * * * */
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
// Ignore the warning about missing field initializers
/* Ignore the warning about missing field initializers. */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
// Extended header which is used to give additional information to the kernel
/* Extended header which is used to give additional information to the kernel. */
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "Example Driver",
.Type = FexDriverType_Generic,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_INTERRUPT,
.Interrupt = {
.Vector = {222}, // IRQ222
}}}};
.Driver = {
.Name = "Example Driver",
.Type = FexDriverType_Generic,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_INTERRUPT,
.Interrupt = {
.Vector = {222}, /* IRQ222 */
}}}};
// Global variable that holds the kernel API
KernelAPI *KAPI;
#pragma GCC diagnostic pop
// Macro that prints a message to UART
#define print(msg) KAPI->Util.DebugPrint((char *)(msg), KAPI->Info.DriverUID)
/* Global structure that holds the kernel API. */
KernelAPI KAPI{};
/* Macro that prints a message to the kernel debugger. */
#define print(msg) KAPI.Util.DebugPrint((char *)(msg), KAPI.Info.DriverUID)
/* --------------------------------------------------------------------------------------------------------- */
// Driver entry point. This is called at initialization. "Data" argument points to the kernel API structure.
/* Driver entry point. This is called at initialization.
"Data" argument points to the kernel API structure. */
int DriverEntry(void *Data)
{
// Check if kernel API is valid
if (!Data)
return INVALID_KERNEL_API;
/* Check if kernel API is valid */
if (!Data)
return INVALID_KERNEL_API;
// Set the global variable to the kernel API
KAPI = (KernelAPI *)Data;
/* Set the global structure to the kernel API. */
KAPI = *(KernelAPI *)Data;
// Check if kernel API version is valid. this is important because the kernel API may change in the future.
if (KAPI->Version.Major < 0 || KAPI->Version.Minor < 0 || KAPI->Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
/* Check if kernel API version is valid.
This is important because the kernel
API may change in the future. */
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
// We print "Hello World!" to UART.
print("Hello World!");
return OK;
/* We print "Hello World!" to the kernel debugger. */
print("Hello World!");
return OK;
}
// This is called when the driver is bound to an interrupt, process, or PCI device or when the kernel wants to send a message to the driver.
/* This is called when the driver is bound to an interrupt, process,
or PCI device or when the kernel wants to send a message to the driver. */
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
print("Kernel acknowledged the driver.");
break;
}
case StopReason:
{
print("Driver stopped.");
break;
}
default:
{
print("Unknown reason.");
break;
}
}
return OK;
switch (Data->Reason)
{
case AcknowledgeReason:
{
print("Kernel acknowledged the driver.");
break;
}
case StopReason:
{
print("Driver stopped.");
break;
}
default:
{
print("Unknown reason.");
break;
}
}
return OK;
}
/* Interrupt handler. */
int InterruptCallback(CPURegisters *)
{
print("Interrupt received.");
return OK;
print("Interrupt received.");
return OK;
}

View File

@ -70,7 +70,7 @@ else ifeq ($(OSARCH), i386)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
mv $(FILENAME) ../../out/modules/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
@ -89,4 +89,4 @@ $(FILENAME): $(OBJ)
$(AS) -o $@ $<
clean:
rm -f *.o file.map file_dump.map $(OBJ)
rm -f file.map file_dump.map $(OBJ)

View File

@ -1,8 +1,5 @@
build:
make -C ExampleDriver build
prepare:
$(info Nothing to prepare)
clean:
make -C ExampleDriver clean

View File

@ -1,9 +1,3 @@
build:
make -C PS2Mouse build
make -C VMwareMouse build
make -C VirtualBoxMouse build
clean:
make -C PS2Mouse clean
make -C VMwareMouse clean
make -C VirtualBoxMouse clean

View File

@ -1,98 +0,0 @@
# Config file
include ../../../Makefile.conf
FILENAME = PS2Mouse.fex
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
INCLUDE_DIR = ../../include
LDFLAGS := \
-fPIC -fPIE -pie -Wl,-eDriverEntry \
-Wl,-static,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -static -Tlinker.ld
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i386)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i386)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -1,278 +0,0 @@
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(void *Data);
int CallbackHandler(KernelCallback *Data);
int InterruptCallback(CPURegisters *Registers);
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "PS/2 Mouse Driver",
.Type = FexDriverType_Input,
.TypeFlags = FexDriverInputTypes_Mouse,
.OverrideOnConflict = false,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_INTERRUPT,
.Interrupt = {
.Vector = {12}, // IRQ12
}}}};
KernelAPI *KAPI;
#define print(msg) KAPI->Util.DebugPrint((char *)(msg), KAPI->Info.DriverUID)
/* --------------------------------------------------------------------------------------------------------- */
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)
};
#define PS2LeftButton 0b00000001
#define PS2MiddleButton 0b00000100
#define PS2RightButton 0b00000010
#define PS2XSign 0b00010000
#define PS2YSign 0b00100000
#define PS2XOverflow 0b01000000
#define PS2YOverflow 0b10000000
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:
{
print("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();
print("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();
print("Driver stopped.");
break;
}
default:
{
print("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] = 256 - Packet[1];
MouseX -= Packet[1];
if (XOverflow)
MouseX -= 255;
}
if (!YNegative)
{
MouseY -= Packet[2];
if (YOverflow)
MouseY -= 255;
}
else
{
Packet[2] = 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;
}
}
return OK;
}

View File

@ -1,40 +0,0 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:x86-64)
ENTRY(DriverEntry)
SECTIONS
{
.header :
{
*(.header .header.*)
*(.extended .extended.*)
}
.text :
{
*(.text .text.*)
}
.data :
{
*(.data .data.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.bss :
{
*(COMMON)
*(.bss .bss.*)
}
/DISCARD/ :
{
*(.eh_frame)
*(.note .note.*)
}
}

View File

@ -1,98 +0,0 @@
# Config file
include ../../../Makefile.conf
FILENAME = VMwareMouseDriver.fex
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
INCLUDE_DIR = ../../include
LDFLAGS := \
-fPIC -fPIE -pie -Wl,-eDriverEntry \
-Wl,-static,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -static -Tlinker.ld
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i386)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i386)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -1,284 +0,0 @@
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(void *Data);
int CallbackHandler(KernelCallback *Data);
int InterruptCallback(CPURegisters *Registers);
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "VMware Virtual Mouse Driver",
.Type = FexDriverType_Input,
.TypeFlags = FexDriverInputTypes_Mouse,
.OverrideOnConflict = true,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_INTERRUPT,
.Interrupt = {
.Vector = {12}, // IRQ12
}}}};
KernelAPI *KAPI;
#define print(msg) KAPI->Util.DebugPrint((char *)(msg), KAPI->Info.DriverUID)
/* --------------------------------------------------------------------------------------------------------- */
/* https://wiki.osdev.org/VMware_tools */
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;
#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 */
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:
{
print("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();
print("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();
print("Driver stopped.");
break;
}
default:
{
print("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)
{
print("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;
}

View File

@ -1,40 +0,0 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:x86-64)
ENTRY(DriverEntry)
SECTIONS
{
.header :
{
*(.header .header.*)
*(.extended .extended.*)
}
.text :
{
*(.text .text.*)
}
.data :
{
*(.data .data.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.bss :
{
*(COMMON)
*(.bss .bss.*)
}
/DISCARD/ :
{
*(.eh_frame)
*(.note .note.*)
}
}

View File

@ -1,98 +0,0 @@
# Config file
include ../../../Makefile.conf
FILENAME = VirtualBoxMouseDriver.fex
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
INCLUDE_DIR = ../../include
LDFLAGS := \
-fPIC -fPIE -pie -Wl,-eDriverEntry \
-Wl,-static,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -static -Tlinker.ld
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i386)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i386)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -1,94 +0,0 @@
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(void *Data);
int CallbackHandler(KernelCallback *Data);
int InterruptCallback(CPURegisters *Registers);
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "VMware Virtual Mouse Driver",
.Type = FexDriverType_Input,
.TypeFlags = FexDriverInputTypes_Mouse,
.OverrideOnConflict = true,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x80EE},
.DeviceID = {0xCAFE},
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
KernelAPI *KAPI;
#define print(msg) KAPI->Util.DebugPrint((char *)(msg), KAPI->Info.DriverUID)
/* --------------------------------------------------------------------------------------------------------- */
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;
print("Not implemented!");
return NOT_IMPLEMENTED;
// return OK;
}
int MouseX = 0, MouseY = 0, MouseZ = 0;
int MouseButton = 0;
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
print("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
break;
}
case FetchReason:
{
Data->InputCallback.Mouse.X = MouseX;
Data->InputCallback.Mouse.Y = MouseY;
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:
{
break;
}
default:
{
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
return OK;
}

View File

@ -1,40 +0,0 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:x86-64)
ENTRY(DriverEntry)
SECTIONS
{
.header :
{
*(.header .header.*)
*(.extended .extended.*)
}
.text :
{
*(.text .text.*)
}
.data :
{
*(.data .data.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.bss :
{
*(COMMON)
*(.bss .bss.*)
}
/DISCARD/ :
{
*(.eh_frame)
*(.note .note.*)
}
}

View File

@ -1,5 +1,6 @@
build:
mkdir -p out
mkdir -p out/modules
make -C Input build
make -C Storage build
make -C Audio build

View File

@ -1,98 +0,0 @@
# Config file
include ../../../Makefile.conf
FILENAME = AMD-PCNET.fex
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
INCLUDE_DIR = ../../include
LDFLAGS := \
-fPIC -fPIE -pie -Wl,-eDriverEntry \
-Wl,-static,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -static -Tlinker.ld
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i386)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i386)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -1,40 +0,0 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:x86-64)
ENTRY(DriverEntry)
SECTIONS
{
.header :
{
*(.header .header.*)
*(.extended .extended.*)
}
.text :
{
*(.text .text.*)
}
.data :
{
*(.data .data.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.bss :
{
*(COMMON)
*(.bss .bss.*)
}
/DISCARD/ :
{
*(.eh_frame)
*(.note .note.*)
}
}

View File

@ -1,141 +0,0 @@
#include <netools.h>
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(void *Data);
int CallbackHandler(KernelCallback *Data);
int InterruptCallback(CPURegisters *Registers);
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "AMD PCNET",
.Type = FexDriverType_Network,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x1022},
.DeviceID = {0x2000},
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
KernelAPI *KAPI;
#define print(msg) KAPI->Util.DebugPrint((char *)(msg), KAPI->Info.DriverUID)
/* --------------------------------------------------------------------------------------------------------- */
struct BARData
{
uint8_t Type;
uint64_t IOBase;
uint64_t MemoryBase;
};
PCIDeviceHeader *PCIBaseAddress;
BARData BAR;
MediaAccessControl MAC;
InternetProtocol4 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:
{
print("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
print("Driver received configuration data.");
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
if (PCIBaseAddress->VendorID == 0x1022 && PCIBaseAddress->DeviceID == 0x2000)
{
print("Found AMD PCNET.");
uint32_t PCIBAR = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
BAR.Type = PCIBAR & 1;
BAR.IOBase = PCIBAR & (~3);
BAR.MemoryBase = PCIBAR & (~15);
}
else
return DEVICE_NOT_SUPPORTED;
break;
}
case FetchReason:
{
KAPI->Util.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.
print("Driver stopped.");
break;
}
default:
{
print("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
return OK;
}

View File

@ -1,537 +0,0 @@
#include <netools.h>
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(void *Data);
int CallbackHandler(KernelCallback *Data);
int InterruptCallback(CPURegisters *Registers);
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "Intel Gigabit Ethernet Controller",
.Type = FexDriverType_Network,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x8086},
.DeviceID = {0x100E, 0x100F, 0x10D3, 0x10EA, 0x153A},
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
KernelAPI *KAPI;
#define print(msg) KAPI->Util.DebugPrint((char *)(msg), KAPI->Info.DriverUID)
/* --------------------------------------------------------------------------------------------------------- */
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;
uint64_t IOBase;
uint64_t MemoryBase;
};
PCIDeviceHeader *PCIBaseAddress;
uint32_t CurrentPacket;
BARData BAR;
bool EEPROMAvailable;
#define E1000_NUM_RX_DESC 32
#define E1000_NUM_TX_DESC 8
uint16_t RXCurrent;
uint16_t TXCurrent;
RXDescriptor *RX[E1000_NUM_RX_DESC];
TXDescriptor *TX[E1000_NUM_TX_DESC];
MediaAccessControl MAC;
InternetProtocol4 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] = temp >> 8;
temp = ReadEEPROM(1);
mac.Address[2] = temp & 0xff;
mac.Address[3] = temp >> 8;
temp = ReadEEPROM(2);
mac.Address[4] = temp & 0xff;
mac.Address[5] = 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
{
print("No MAC address found.");
return MediaAccessControl();
}
}
return mac;
}
void InitializeRX()
{
print("Initializing RX...");
uint8_t *Ptr = (uint8_t *)KAPI->Memory.RequestPage((((sizeof(RXDescriptor) * E1000_NUM_RX_DESC + 16)) / KAPI->Memory.PageSize) + 1);
RXDescriptor *Descriptor = (RXDescriptor *)Ptr;
for (int i = 0; i < E1000_NUM_RX_DESC; i++)
{
RX[i] = (RXDescriptor *)((uint8_t *)Descriptor + i * 16);
RX[i]->Address = (uint64_t)(uint8_t *)KAPI->Memory.RequestPage(((8192 + 16) / KAPI->Memory.PageSize) + 1);
RX[i]->Status = 0;
}
WriteCMD(REG::TXDESCLO, (uint32_t)((uint64_t)Ptr >> 32));
WriteCMD(REG::TXDESCHI, (uint32_t)((uint64_t)Ptr & 0xFFFFFFFF));
WriteCMD(REG::RXDESCLO, (uint64_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()
{
print("Initializing TX...");
uint8_t *Ptr = (uint8_t *)KAPI->Memory.RequestPage(((sizeof(TXDescriptor) * E1000_NUM_RX_DESC + 16) / KAPI->Memory.PageSize) + 1);
TXDescriptor *Descriptor = (TXDescriptor *)Ptr;
for (int i = 0; i < E1000_NUM_TX_DESC; i++)
{
TX[i] = (TXDescriptor *)((uint8_t *)Descriptor + 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:
{
print("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
print("Driver received configuration data.");
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
switch (PCIBaseAddress->DeviceID)
{
case 0x100E:
{
print("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 = 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
print("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(0x5200 + i * 4, 0);
WriteCMD(REG::IMASK, 0x1F6DC);
WriteCMD(REG::IMASK, 0xFF & ~4);
ReadCMD(0xC0);
InitializeRX();
InitializeTX();
return OK;
}
case 0x100F:
{
print("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 = 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
print("MAC address found.");
MAC = GetMAC();
return NOT_IMPLEMENTED;
}
case 0x10D3:
{
print("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 = 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
print("MAC address found.");
MAC = GetMAC();
return NOT_IMPLEMENTED;
}
case 0x10EA:
{
print("Found Intel I217-LM Gigabit Ethernet Controller.");
return NOT_IMPLEMENTED;
}
case 0x153A:
{
print("Found Intel 82577LM Gigabit Ethernet Controller.");
return NOT_IMPLEMENTED;
}
default:
{
print("Unsupported Intel Ethernet Controller.");
return DEVICE_NOT_SUPPORTED;
}
}
return ERROR;
}
case FetchReason:
{
KAPI->Util.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 = Data->NetworkCallback.Send.Length;
TX[TXCurrent]->Command = CMD::EOP | CMD::IFCS | CMD::RS;
TX[TXCurrent]->Status = 0;
uint8_t OldTXCurrent = TXCurrent;
TXCurrent = (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
uint64_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 */
print("Driver stopped.");
break;
}
default:
{
print("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 = (RXCurrent + 1) % E1000_NUM_RX_DESC;
WriteCMD(REG::RXDESCTAIL, OldRXCurrent);
}
return OK;
}

View File

@ -1,98 +0,0 @@
# Config file
include ../../../Makefile.conf
FILENAME = Intel-Gigabit.fex
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
INCLUDE_DIR = ../../include
LDFLAGS := \
-fPIC -fPIE -pie -Wl,-eDriverEntry \
-Wl,-static,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -static -Tlinker.ld
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i386)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i386)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -1,40 +0,0 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:x86-64)
ENTRY(DriverEntry)
SECTIONS
{
.header :
{
*(.header .header.*)
*(.extended .extended.*)
}
.text :
{
*(.text .text.*)
}
.data :
{
*(.data .data.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.bss :
{
*(COMMON)
*(.bss .bss.*)
}
/DISCARD/ :
{
*(.eh_frame)
*(.note .note.*)
}
}

View File

@ -1,14 +1,3 @@
build:
make -C AMDPCNET build
make -C IntelGigabit build
make -C RTL8139 build
make -C RTL8169 build
prepare:
$(info Nothing to prepare)
clean:
make -C AMDPCNET clean
make -C IntelGigabit clean
make -C RTL8139 clean
make -C RTL8169 clean

View File

@ -1,98 +0,0 @@
# Config file
include ../../../Makefile.conf
FILENAME = Realtek-8139.fex
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
INCLUDE_DIR = ../../include
LDFLAGS := \
-fPIC -fPIE -pie -Wl,-eDriverEntry \
-Wl,-static,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -static -Tlinker.ld
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i386)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i386)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -1,40 +0,0 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:x86-64)
ENTRY(DriverEntry)
SECTIONS
{
.header :
{
*(.header .header.*)
*(.extended .extended.*)
}
.text :
{
*(.text .text.*)
}
.data :
{
*(.data .data.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.bss :
{
*(COMMON)
*(.bss .bss.*)
}
/DISCARD/ :
{
*(.eh_frame)
*(.note .note.*)
}
}

View File

@ -1,217 +0,0 @@
#include <netools.h>
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(void *Data);
int CallbackHandler(KernelCallback *Data);
int InterruptCallback(CPURegisters *Registers);
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "RTL8139",
.Type = FexDriverType_Network,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x10EC},
.DeviceID = {0x8139},
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
KernelAPI *KAPI;
#define print(msg) KAPI->Util.DebugPrint((char *)(msg), KAPI->Info.DriverUID)
/* --------------------------------------------------------------------------------------------------------- */
struct BARData
{
uint8_t Type;
uint64_t IOBase;
uint64_t MemoryBase;
};
PCIDeviceHeader *PCIBaseAddress;
BARData BAR;
uint8_t *RXBuffer;
int TXCurrent;
uint32_t CurrentPacket;
MediaAccessControl MAC;
InternetProtocol4 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] = MAC1,
mac.Address[1] = (MAC1 >> 8),
mac.Address[2] = (MAC1 >> 16),
mac.Address[3] = (MAC1 >> 24),
mac.Address[4] = MAC2,
mac.Address[5] = (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:
{
print("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
print("Driver received configuration data.");
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
if (PCIBaseAddress->VendorID == 0x10EC && PCIBaseAddress->DeviceID == 0x8139)
{
print("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 = 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:
{
KAPI->Util.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++], Data->NetworkCallback.Send.Length);
if (TXCurrent > 3)
TXCurrent = 0;
break;
}
case StopReason:
{
// TODO: Stop the driver.
print("Driver stopped.");
break;
}
default:
{
print("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 = (CurrentPacket + DataLength + 4 + 3) & (~3);
if (CurrentPacket > 8192)
CurrentPacket -= 8192;
RTLOW(0x38, CurrentPacket - 0x10);
RTLOW(0x3E, (1 << 0) | (1 << 2));
return OK;
}

View File

@ -1,98 +0,0 @@
# Config file
include ../../../Makefile.conf
FILENAME = Realtek-8169.fex
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
INCLUDE_DIR = ../../include
LDFLAGS := \
-fPIC -fPIE -pie -Wl,-eDriverEntry \
-Wl,-static,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -static -Tlinker.ld
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i386)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i386)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -1,40 +0,0 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:x86-64)
ENTRY(DriverEntry)
SECTIONS
{
.header :
{
*(.header .header.*)
*(.extended .extended.*)
}
.text :
{
*(.text .text.*)
}
.data :
{
*(.data .data.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.bss :
{
*(COMMON)
*(.bss .bss.*)
}
/DISCARD/ :
{
*(.eh_frame)
*(.note .note.*)
}
}

View File

@ -1,111 +0,0 @@
#include <netools.h>
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(void *Data);
int CallbackHandler(KernelCallback *Data);
int InterruptCallback(CPURegisters *Registers);
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "RTL8169",
.Type = FexDriverType_Network,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x10EC},
.DeviceID = {0x8169},
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
KernelAPI *KAPI;
#define print(msg) KAPI->Util.DebugPrint((char *)(msg), KAPI->Info.DriverUID)
/* --------------------------------------------------------------------------------------------------------- */
struct BARData
{
uint8_t Type;
uint64_t IOBase;
uint64_t MemoryBase;
};
PCIDeviceHeader *PCIBaseAddress;
BARData BAR;
MediaAccessControl MAC;
InternetProtocol4 IP;
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:
{
print("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
print("Driver received configuration data.");
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
if (PCIBaseAddress->VendorID == 0x10EC && PCIBaseAddress->DeviceID == 0x8169)
{
print("Found RTL-8169.");
return NOT_IMPLEMENTED;
}
else
return DEVICE_NOT_SUPPORTED;
break;
}
case FetchReason:
{
KAPI->Util.memcpy(Data->NetworkCallback.Fetch.Name, (void *)"RTL-8169", 9);
Data->NetworkCallback.Fetch.MAC = MAC.ToHex();
break;
}
case SendReason:
{
break;
}
case StopReason:
{
// TODO: Stop the driver.
print("Driver stopped.");
break;
}
default:
{
print("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
return OK;
}

View File

@ -1,98 +0,0 @@
# Config file
include ../../../Makefile.conf
FILENAME = VirtioNetworkDriver.fex
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
INCLUDE_DIR = ../../include
LDFLAGS := \
-fPIC -fPIE -pie -Wl,-eDriverEntry \
-Wl,-static,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -static -Tlinker.ld
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i386)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i386)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -1,111 +0,0 @@
#include <netools.h>
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(void *Data);
int CallbackHandler(KernelCallback *Data);
int InterruptCallback(CPURegisters *Registers);
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "Virtio Network",
.Type = FexDriverType_Network,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x1AF4},
.DeviceID = {0x1000},
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
KernelAPI *KAPI;
#define print(msg) KAPI->Util.DebugPrint((char *)(msg), KAPI->Info.DriverUID)
/* --------------------------------------------------------------------------------------------------------- */
struct BARData
{
uint8_t Type;
uint64_t IOBase;
uint64_t MemoryBase;
};
PCIDeviceHeader *PCIBaseAddress;
BARData BAR;
MediaAccessControl MAC;
InternetProtocol4 IP;
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:
{
print("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
print("Driver received configuration data.");
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
if (PCIBaseAddress->VendorID == 0x1AF4 && PCIBaseAddress->DeviceID == 0x1000)
{
print("Found Virtio Network.");
return NOT_IMPLEMENTED;
}
else
return DEVICE_NOT_SUPPORTED;
break;
}
case FetchReason:
{
KAPI->Util.memcpy(Data->NetworkCallback.Fetch.Name, (void *)"Virtio Network", 15);
Data->NetworkCallback.Fetch.MAC = MAC.ToHex();
break;
}
case SendReason:
{
break;
}
case StopReason:
{
// TODO: Stop the driver.
print("Driver stopped.");
break;
}
default:
{
print("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
return OK;
}

View File

@ -1,40 +0,0 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:x86-64)
ENTRY(DriverEntry)
SECTIONS
{
.header :
{
*(.header .header.*)
*(.extended .extended.*)
}
.text :
{
*(.text .text.*)
}
.data :
{
*(.data .data.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.bss :
{
*(COMMON)
*(.bss .bss.*)
}
/DISCARD/ :
{
*(.eh_frame)
*(.note .note.*)
}
}

View File

@ -1,6 +1,6 @@
# Drivers
# Modules
Drivers for [Fennix](https://github.com/Fennix-Project/Fennix).
Modules for [Fennix](https://github.com/Fennix-Project/Fennix).
---

View File

@ -1,514 +0,0 @@
#include <netools.h>
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(void *Data);
int CallbackHandler(KernelCallback *Data);
int InterruptCallback(CPURegisters *Registers);
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "AHCI",
.Type = FexDriverType_Storage,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = {0x8086, 0x15AD},
.DeviceID = {0x2922, 0x2829, 0x07E0},
.Class = 0x1,
.SubClass = 0x6,
.ProgIF = 0x1,
}}}};
KernelAPI *KAPI;
#define print(msg) KAPI->Util.DebugPrint((char *)(msg), KAPI->Info.DriverUID)
/* --------------------------------------------------------------------------------------------------------- */
#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;
uint64_t IOBase;
uint64_t MemoryBase;
};
typedef enum
{
_URC_NO_REASON = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
_URC_FATAL_PHASE2_ERROR = 2,
_URC_FATAL_PHASE1_ERROR = 3,
_URC_NORMAL_STOP = 4,
_URC_END_OF_STACK = 5,
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8
} _Unwind_Reason_Code;
struct _Unwind_Context;
typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__)));
typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code, struct _Unwind_Exception *);
typedef int _Unwind_Action;
struct _Unwind_Exception
{
_Unwind_Exception_Class exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
#if !defined(__USING_SJLJ_EXCEPTIONS__) && defined(__SEH__)
_Unwind_Word private_[6];
#else
_Unwind_Word private_1;
_Unwind_Word private_2;
#endif
} __attribute__((__aligned__));
extern "C" _Unwind_Reason_Code __gxx_personality_v0(int, _Unwind_Action, _Unwind_Exception_Class, _Unwind_Exception *, _Unwind_Context *)
{
print("__gxx_personality_v0");
return _URC_NO_REASON;
}
extern "C" void _Unwind_Resume(_Unwind_Exception *) { print("_Unwind_Resume"); }
void *operator new(size_t Size) { return KAPI->Memory.RequestPage(Size / KAPI->Memory.PageSize + 1); }
void operator delete(void *Ptr) { KAPI->Memory.FreePage(Ptr, 1); } // Potential memory leak
void operator delete(void *Ptr, size_t Size) { KAPI->Memory.FreePage(Ptr, Size / KAPI->Memory.PageSize + 1); }
class Port
{
public:
PortType AHCIPortType;
HBAPort *HBAPortPtr;
uint8_t *Buffer;
uint8_t PortNumber;
Port(PortType Type, HBAPort *PortPtr, uint8_t PortNumber)
{
this->AHCIPortType = Type;
this->HBAPortPtr = PortPtr;
this->Buffer = static_cast<uint8_t *>(KAPI->Memory.RequestPage(1));
KAPI->Util.memset(this->Buffer, 0, KAPI->Memory.PageSize);
this->PortNumber = PortNumber;
}
~Port() { KAPI->Memory.FreePage(Buffer, 1); }
void StartCMD()
{
while (HBAPortPtr->CommandStatus & HBA_PxCMD_CR)
;
HBAPortPtr->CommandStatus |= HBA_PxCMD_FRE;
HBAPortPtr->CommandStatus |= HBA_PxCMD_ST;
}
void 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 Configure()
{
StopCMD();
void *NewBase = KAPI->Memory.RequestPage(1);
HBAPortPtr->CommandListBase = (uint32_t)(uint64_t)NewBase;
HBAPortPtr->CommandListBaseUpper = (uint32_t)((uint64_t)NewBase >> 32);
KAPI->Util.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);
KAPI->Util.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);
KAPI->Util.memset(CommandTableAddress, 0, 256);
}
StartCMD();
}
bool ReadWrite(uint64_t Sector, uint32_t SectorCount, uint8_t *Buffer, bool Write)
{
if (this->PortNumber == PortType::SATAPI && Write)
{
// err("SATAPI port does not support write.");
print("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);
KAPI->Util.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);
CommandTable->PRDTEntry[0].ByteCount = (SectorCount << 9) - 1; // 512 bytes per sector
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)
{
// err("Port not responding.");
print("Port not responding.");
return false;
}
HBAPortPtr->CommandIssue = 1;
Spin = 0;
int TryCount = 0;
while (true)
{
if (Spin > 100000000)
{
// err("Port %d not responding. (%d)", this->PortNumber, TryCount);
print("Port not responding.");
Spin = 0;
TryCount++;
if (TryCount > 10)
return false;
}
if ((HBAPortPtr->CommandIssue == 0))
break;
Spin++;
if (HBAPortPtr->InterruptStatus & HBA_PxIS_TFES)
{
// err("Error reading/writing (%d).", Write);
print("Error reading/writing.");
return false;
}
}
return true;
}
};
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;
}
}
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 (KAPI->Info.KernelDebug) /* FIXME: TCG doesn't like this driver. */
return NOT_AVAILABLE;
return OK;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
print("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
print("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);
print("SATA drive found.");
Ports[PortCount] = new Port(portType, &ABAR->Ports[i], PortCount);
PortCount++;
}
else
{
if (portType != PortType::None)
print("Unsupported port type found.");
// 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.
print("Driver stopped.");
break;
}
case SendReason:
case ReceiveReason:
{
Ports[Data->DiskCallback.RW.Port]->ReadWrite(Data->DiskCallback.RW.Sector,
Data->DiskCallback.RW.SectorCount,
Data->DiskCallback.RW.Buffer,
Data->DiskCallback.RW.Write);
break;
}
default:
{
print("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *)
{
/* There's no need to do anything here. */
return OK;
}

View File

@ -1,98 +0,0 @@
# Config file
include ../../../Makefile.conf
FILENAME = AHCI.fex
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
INCLUDE_DIR = ../../include
LDFLAGS := \
-fPIC -fPIE -pie -Wl,-eDriverEntry \
-Wl,-static,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -static -Tlinker.ld
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i386)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i386)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -1,40 +0,0 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:x86-64)
ENTRY(DriverEntry)
SECTIONS
{
.header :
{
*(.header .header.*)
*(.extended .extended.*)
}
.text :
{
*(.text .text.*)
}
.data :
{
*(.data .data.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.bss :
{
*(COMMON)
*(.bss .bss.*)
}
/DISCARD/ :
{
*(.eh_frame)
*(.note .note.*)
}
}

View File

@ -1,110 +0,0 @@
#include <netools.h>
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(void *Data);
int CallbackHandler(KernelCallback *Data);
int InterruptCallback(CPURegisters *Registers);
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "ATA",
.Type = FexDriverType_Storage,
.Callback = CallbackHandler,
.InterruptCallback = InterruptCallback,
.Bind = {
.Type = BIND_INTERRUPT,
.Interrupt = {
.Vector = {14, 15}, // IRQ14, IRQ15
}}}};
KernelAPI *KAPI;
#define print(msg) KAPI->Util.DebugPrint((char *)(msg), KAPI->Info.DriverUID)
/* --------------------------------------------------------------------------------------------------------- */
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;
print("ATA device found.");
return NOT_IMPLEMENTED;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
print("Kernel acknowledged the driver.");
break;
}
case ConfigurationReason:
{
print("Driver received configuration data.");
break;
}
case FetchReason:
{
break;
}
case SendReason:
case ReceiveReason:
{
break;
}
case StopReason:
{
// TODO: Stop the driver.
print("Driver stopped.");
break;
}
default:
{
print("Unknown reason.");
break;
}
}
return OK;
}
int InterruptCallback(CPURegisters *Registers)
{
if (Registers->InterruptNumber == 0xE)
{
print("IRQ14");
}
else if (Registers->InterruptNumber == 0xF)
{
print("IRQ15");
}
return OK;
}

View File

@ -1,98 +0,0 @@
# Config file
include ../../../Makefile.conf
FILENAME = ATA.fex
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
INCLUDE_DIR = ../../include
LDFLAGS := \
-fPIC -fPIE -pie -Wl,-eDriverEntry \
-Wl,-static,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -static -Tlinker.ld
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i386)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i386)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -1,40 +0,0 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:x86-64)
ENTRY(DriverEntry)
SECTIONS
{
.header :
{
*(.header .header.*)
*(.extended .extended.*)
}
.text :
{
*(.text .text.*)
}
.data :
{
*(.data .data.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.bss :
{
*(COMMON)
*(.bss .bss.*)
}
/DISCARD/ :
{
*(.eh_frame)
*(.note .note.*)
}
}

View File

@ -1,7 +1,3 @@
build:
make -C AHCI build
make -C ATA build
clean:
make -C AHCI clean
make -C ATA clean

View File

@ -1,5 +0,0 @@
build:
clean:

View File

@ -1,5 +1,3 @@
build:
make -C Framebuffer build
clean:
make -C Framebuffer clean