Added drivers

This commit is contained in:
Alex 2022-11-01 02:01:47 +02:00
parent 417eeca40b
commit 8dbabcbde6
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
23 changed files with 2134 additions and 1 deletions

28
.vscode/c_boilerplates.code-snippets vendored Normal file
View File

@ -0,0 +1,28 @@
{
"Header": {
"prefix": [
"head",
],
"body": [
"#ifndef __FENNIX_API_${2:header}_H__",
"#define __FENNIX_API_${2:header}_H__",
"",
"#include <types.h>",
"",
"$0",
"",
"#endif // !__FENNIX_API_${2:header}_H__",
""
],
"description": "Create header."
},
"Brief": {
"prefix": [
"brief",
],
"body": [
"/** @brief $0 */"
],
"description": "Create documentation brief."
}
}

View File

@ -0,0 +1,73 @@
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(KernelAPI *Data);
int CallbackHandler(KernelCallback *Data);
/* The driver is
* This is a driver for Fennix Driver Entry Extended Header
* * * * */
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
// Ignore the warning about missing field initializers
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
// 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,
.Bind = {
.Type = BIND_INTERRUPT,
.Interrupt = {
.Vector = 0xFE,
}}}};
// Global variable that holds the kernel API
KernelAPI *KAPI;
/* --------------------------------------------------------------------------------------------------------- */
// Driver entry point. This is called at initialization. "Data" argument points to the kernel API structure.
int DriverEntry(KernelAPI *Data)
{
// Check if kernel API is valid
if (!Data)
return INVALID_KERNEL_API;
// // Check if kernel API version is valid. this is important because the kernel API may change in the future.
if (Data->Version.Major < 0 || Data->Version.Minor < 0 || Data->Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
// Set the global variable to the kernel API
KAPI = Data;
// We print "Hello World!" to UART.
KAPI->Util.DebugPrint(((char *)"Hello World!" + KAPI->Info.Offset), KAPI->Info.DriverUID);
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.
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
KAPI->Util.DebugPrint(((char *)"Kernel acknowledged the driver." + KAPI->Info.Offset), KAPI->Info.DriverUID);
break;
}
case InterruptReason:
{
KAPI->Util.DebugPrint(((char *)"Interrupt received." + KAPI->Info.Offset), KAPI->Info.DriverUID);
break;
}
default:
{
KAPI->Util.DebugPrint(((char *)"Unknown reason." + KAPI->Info.Offset), KAPI->Info.DriverUID);
break;
}
}
return OK;
}

View File

@ -0,0 +1,100 @@
# Config file
include ../../../Makefile.conf
FILENAME = ExampleDriver.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/i686/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i686/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i686/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i686)
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/i686/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i686/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i686/*")
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 -fno-pie \
-Wl,-static,--no-dynamic-linker,-ztext \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fno-pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-mcmodel=kernel -msoft-float -fno-builtin
LDFLAGS += -Tarch/amd64/linker.ld
else ifeq ($(OSARCH), i686)
CFLAGS += -fPIC -fno-pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i686 -pipe -msoft-float -fno-builtin
LDFLAGS += -Tarch/i686/linker.ld
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
LDFLAGS += -Tarch/aarch64/linker.ld
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i686)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(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 $@ -fno-rtti
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i686)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -0,0 +1,40 @@
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.*)
}
}

8
Generic/Makefile Normal file
View File

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

View File

@ -1,8 +1,10 @@
build: build:
mkdir -p out mkdir -p out
touch out/dummy.drv touch out/dummy.fex
make --quiet -C Audio build make --quiet -C Audio build
make --quiet -C FileSystem build make --quiet -C FileSystem build
make --quiet -C Generic build
make --quiet -C Network build
make --quiet -C Video build make --quiet -C Video build
prepare: prepare:
@ -12,4 +14,6 @@ clean:
rm -rf out rm -rf out
make -C Audio clean make -C Audio clean
make -C FileSystem clean make -C FileSystem clean
make -C Generic clean
make -C Network clean
make -C Video clean make -C Video clean

100
Network/AMDPCNET/Makefile Normal file
View File

@ -0,0 +1,100 @@
# 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/i686/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i686/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i686/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i686)
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/i686/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i686/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i686/*")
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 -fno-pie \
-Wl,-static,--no-dynamic-linker,-ztext \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fno-pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-mcmodel=kernel -msoft-float -fno-builtin
LDFLAGS += -Tarch/amd64/linker.ld
else ifeq ($(OSARCH), i686)
CFLAGS += -fPIC -fno-pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i686 -pipe -msoft-float -fno-builtin
LDFLAGS += -Tarch/i686/linker.ld
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
LDFLAGS += -Tarch/aarch64/linker.ld
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i686)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(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 $@ -fno-rtti
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i686)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -0,0 +1,42 @@
/* EXPERIMENTAL */
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.*)
}
}

123
Network/AMDPCNET/pcnet.cpp Normal file
View File

@ -0,0 +1,123 @@
#include <netools.h>
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(KernelAPI *Data);
int CallbackHandler(KernelCallback *Data);
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,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = 0x1022,
.DeviceID = 0x2000,
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
KernelAPI *KAPI;
/* --------------------------------------------------------------------------------------------------------- */
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(KernelAPI *Data)
{
if (!Data)
return INVALID_KERNEL_API;
if (Data->Version.Major < 0 || Data->Version.Minor < 0 || Data->Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
KAPI = Data;
return OK;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
KAPI->Util.DebugPrint(((char *)"Kernel acknowledged the driver." + KAPI->Info.Offset), KAPI->Info.DriverUID);
break;
}
case ConfigurationReason:
{
KAPI->Util.DebugPrint(((char *)"Kernel received configuration data." + KAPI->Info.Offset), KAPI->Info.DriverUID);
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
if (PCIBaseAddress->VendorID == 0x1022 && PCIBaseAddress->DeviceID == 0x2000)
{
KAPI->Util.DebugPrint(((char *)"Found AMD PCNET." + KAPI->Info.Offset), KAPI->Info.DriverUID);
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 InterruptReason:
{
break;
}
case SendReason:
{
}
default:
{
KAPI->Util.DebugPrint(((char *)"Unknown reason." + KAPI->Info.Offset), KAPI->Info.DriverUID);
break;
}
}
return OK;
}

100
Network/E1000/Makefile Normal file
View File

@ -0,0 +1,100 @@
# Config file
include ../../../Makefile.conf
FILENAME = e1000.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/i686/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i686/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i686/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i686)
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/i686/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i686/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i686/*")
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 -fno-pie \
-Wl,-static,--no-dynamic-linker,-ztext \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fno-pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-mcmodel=kernel -msoft-float -fno-builtin
LDFLAGS += -Tarch/amd64/linker.ld
else ifeq ($(OSARCH), i686)
CFLAGS += -fPIC -fno-pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i686 -pipe -msoft-float -fno-builtin
LDFLAGS += -Tarch/i686/linker.ld
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
LDFLAGS += -Tarch/aarch64/linker.ld
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i686)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(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 $@ -fno-rtti
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i686)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -0,0 +1,42 @@
/* EXPERIMENTAL */
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.*)
}
}

419
Network/E1000/e1000.cpp Normal file
View File

@ -0,0 +1,419 @@
#include <netools.h>
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(KernelAPI *Data);
int CallbackHandler(KernelCallback *Data);
HEAD(FexFormatType_Driver, FexOSType_Fennix, DriverEntry);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
__attribute__((section(".extended"))) FexExtended ExtendedHeader = {
.Driver = {
.Name = "E1000 Network Controller Driver",
.Type = FexDriverType_Network,
.Callback = CallbackHandler,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = 0x8086,
.DeviceID = 0x100E,
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
KernelAPI *KAPI;
/* --------------------------------------------------------------------------------------------------------- */
enum REG
{
CTRL = 0x0000,
STATUS = 0x0008,
EEPROM = 0x0014,
CTRL_EXT = 0x0018,
IMASK = 0x00D0,
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 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 OutCMD(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 InCMD(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)
{
OutCMD(REG::EEPROM, (1) | ((uint32_t)(Address) << 8));
while (!((temp = InCMD(REG::EEPROM)) & (1 << 4)))
;
}
else
{
OutCMD(REG::EEPROM, (1) | ((uint32_t)(Address) << 2));
while (!((temp = InCMD(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
{
KAPI->Util.DebugPrint(((char *)"No MAC address found." + KAPI->Info.Offset), KAPI->Info.DriverUID);
return MediaAccessControl();
}
}
return mac;
}
void InitializeRX()
{
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;
}
OutCMD(REG::TXDESCLO, (uint32_t)((uint64_t)Ptr >> 32));
OutCMD(REG::TXDESCHI, (uint32_t)((uint64_t)Ptr & 0xFFFFFFFF));
OutCMD(REG::RXDESCLO, (uint64_t)Ptr);
OutCMD(REG::RXDESCHI, 0);
OutCMD(REG::RXDESCLEN, E1000_NUM_RX_DESC * 16);
OutCMD(REG::RXDESCHEAD, 0);
OutCMD(REG::RXDESCTAIL, E1000_NUM_RX_DESC - 1);
RXCurrent = 0;
OutCMD(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()
{
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;
}
OutCMD(REG::TXDESCHI, (uint32_t)((uint64_t)Ptr >> 32));
OutCMD(REG::TXDESCLO, (uint32_t)((uint64_t)Ptr & 0xFFFFFFFF));
OutCMD(REG::TXDESCLEN, E1000_NUM_TX_DESC * 16);
OutCMD(REG::TXDESCHEAD, 0);
OutCMD(REG::TXDESCTAIL, 0);
TXCurrent = 0;
OutCMD(REG::TCTRL, TCTL::EN_ | TCTL::PSP | (15 << TCTL::CT_SHIFT) | (64 << TCTL::COLD_SHIFT) | TCTL::RTLC);
OutCMD(REG::TCTRL, 0b0110000000000111111000011111010);
OutCMD(REG::TIPG, 0x0060200A);
}
int DriverEntry(KernelAPI *Data)
{
if (!Data)
return INVALID_KERNEL_API;
if (Data->Version.Major < 0 || Data->Version.Minor < 0 || Data->Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
KAPI = Data;
return OK;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
KAPI->Util.DebugPrint(((char *)"Kernel acknowledged the driver." + KAPI->Info.Offset), KAPI->Info.DriverUID);
break;
}
case ConfigurationReason:
{
KAPI->Util.DebugPrint(((char *)"Kernel received configuration data." + KAPI->Info.Offset), KAPI->Info.DriverUID);
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
if (PCIBaseAddress->VendorID == 0x8086 && PCIBaseAddress->DeviceID == 0x100E)
{
KAPI->Util.DebugPrint(((char *)"Found Intel 82540EM Gigabit Ethernet Controller." + KAPI->Info.Offset), KAPI->Info.DriverUID);
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
OutCMD(REG::EEPROM, 0x1);
for (int i = 0; i < 1000 && !EEPROMAvailable; i++)
if (InCMD(REG::EEPROM) & 0x10)
EEPROMAvailable = true;
else
EEPROMAvailable = false;
// Get MAC address
if (!GetMAC().Valid())
return false;
MAC = GetMAC();
// Start link
uint32_t cmdret = InCMD(REG::CTRL);
OutCMD(REG::CTRL, cmdret | ECTRL::SLU);
for (int i = 0; i < 0x80; i++)
OutCMD(0x5200 + i * 4, 0);
OutCMD(REG::IMASK, 0x1F6DC);
OutCMD(REG::IMASK, 0xFF & ~4);
InCMD(0xC0);
InitializeRX();
InitializeTX();
}
else if (PCIBaseAddress->VendorID == 0x8086 && PCIBaseAddress->DeviceID == 0x153A)
{
KAPI->Util.DebugPrint(((char *)"Found Intel I217 Gigabit Ethernet Controller." + KAPI->Info.Offset), KAPI->Info.DriverUID);
return NOT_IMPLEMENTED;
}
else if (PCIBaseAddress->VendorID == 0x8086 && PCIBaseAddress->DeviceID == 0x10EA)
{
KAPI->Util.DebugPrint(((char *)"Found Intel 82577LM Gigabit Ethernet Controller." + KAPI->Info.Offset), KAPI->Info.DriverUID);
return NOT_IMPLEMENTED;
}
else
return DEVICE_NOT_SUPPORTED;
break;
}
case InterruptReason:
{
OutCMD(REG::IMASK, 0x1);
uint32_t status = InCMD(0xC0);
UNUSED(status);
while ((RX[RXCurrent]->Status & 0x1))
{
uint8_t *Data = (uint8_t *)RX[RXCurrent]->Address;
uint16_t DataLength = RX[RXCurrent]->Length;
KAPI->Commmand.Network.ReceivePacket(KAPI->Info.DriverUID, Data, DataLength);
RX[RXCurrent]->Status = 0;
uint16_t OldRXCurrent = RXCurrent;
RXCurrent = (RXCurrent + 1) % E1000_NUM_RX_DESC;
OutCMD(REG::RXDESCTAIL, OldRXCurrent);
}
break;
}
case SendReason:
{
TX[TXCurrent]->Address = (uint64_t)Data->NetworkCallback.Data;
TX[TXCurrent]->Length = Data->NetworkCallback.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;
OutCMD(REG::TXDESCTAIL, TXCurrent);
while (!(TX[OldTXCurrent]->Status & 0xFF))
;
break;
}
default:
{
KAPI->Util.DebugPrint(((char *)"Unknown reason." + KAPI->Info.Offset), KAPI->Info.DriverUID);
break;
}
}
return OK;
}

14
Network/Makefile Normal file
View File

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

100
Network/RTL8139/Makefile Normal file
View File

@ -0,0 +1,100 @@
# Config file
include ../../../Makefile.conf
FILENAME = rtl8139.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/i686/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i686/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i686/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i686)
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/i686/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i686/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i686/*")
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 -fno-pie \
-Wl,-static,--no-dynamic-linker,-ztext \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fno-pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-mcmodel=kernel -msoft-float -fno-builtin
LDFLAGS += -Tarch/amd64/linker.ld
else ifeq ($(OSARCH), i686)
CFLAGS += -fPIC -fno-pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i686 -pipe -msoft-float -fno-builtin
LDFLAGS += -Tarch/i686/linker.ld
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
LDFLAGS += -Tarch/aarch64/linker.ld
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i686)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(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 $@ -fno-rtti
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i686)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -0,0 +1,42 @@
/* EXPERIMENTAL */
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.*)
}
}

200
Network/RTL8139/rtl8139.cpp Normal file
View File

@ -0,0 +1,200 @@
#include <netools.h>
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(KernelAPI *Data);
int CallbackHandler(KernelCallback *Data);
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,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = 0x10EC,
.DeviceID = 0x8139,
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
KernelAPI *KAPI;
/* --------------------------------------------------------------------------------------------------------- */
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(KernelAPI *Data)
{
if (!Data)
return INVALID_KERNEL_API;
if (Data->Version.Major < 0 || Data->Version.Minor < 0 || Data->Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
KAPI = Data;
return OK;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
KAPI->Util.DebugPrint(((char *)"Kernel acknowledged the driver." + KAPI->Info.Offset), KAPI->Info.DriverUID);
break;
}
case ConfigurationReason:
{
KAPI->Util.DebugPrint(((char *)"Kernel received configuration data." + KAPI->Info.Offset), KAPI->Info.DriverUID);
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
if (PCIBaseAddress->VendorID == 0x10EC && PCIBaseAddress->DeviceID == 0x8139)
{
KAPI->Util.DebugPrint(((char *)"Found RTL-8139." + KAPI->Info.Offset), KAPI->Info.DriverUID);
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 InterruptReason:
{
uint16_t Status = RTLIW(0x3E);
UNUSED(Status);
uint16_t *Data = (uint16_t *)(RXBuffer + CurrentPacket);
uint16_t DataLength = *(Data + 1);
Data = Data + 2;
KAPI->Commmand.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));
break;
}
case SendReason:
{
RTLOL(TSAD[TXCurrent], static_cast<uint32_t>(reinterpret_cast<uint64_t>(Data->NetworkCallback.Data)));
RTLOL(TSD[TXCurrent++], Data->NetworkCallback.Length);
if (TXCurrent > 3)
TXCurrent = 0;
break;
}
default:
{
KAPI->Util.DebugPrint(((char *)"Unknown reason." + KAPI->Info.Offset), KAPI->Info.DriverUID);
break;
}
}
return OK;
}

100
Network/RTL8169/Makefile Normal file
View File

@ -0,0 +1,100 @@
# Config file
include ../../../Makefile.conf
FILENAME = rtl8169.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/i686/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i686/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i686/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i686)
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/i686/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i686/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i686/*")
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 -fno-pie \
-Wl,-static,--no-dynamic-linker,-ztext \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared
WARNCFLAG = -Wall -Wextra
CFLAGS := \
-I$(INCLUDE_DIR) \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fno-pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-mcmodel=kernel -msoft-float -fno-builtin
LDFLAGS += -Tarch/amd64/linker.ld
else ifeq ($(OSARCH), i686)
CFLAGS += -fPIC -fno-pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i686 -pipe -msoft-float -fno-builtin
LDFLAGS += -Tarch/i686/linker.ld
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
LDFLAGS += -Tarch/aarch64/linker.ld
endif
build: $(FILENAME)
ifeq ($(OSARCH), amd64)
$(OBJDUMP) -b binary -D -m i386:x86-64 -d $(FILENAME) > file_dump.map
else ifeq ($(OSARCH), i686)
else ifeq ($(OSARCH), aarch64)
endif
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(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 $@ -fno-rtti
%.o: %.S
$(info Compiling $<)
ifeq ($(OSARCH), amd64)
$(AS) -o $@ $<
else ifeq ($(OSARCH), i686)
$(AS) -o $@ $<
else ifeq ($(OSARCH), aarch64)
$(AS) -o $@ $<
endif
clean:
rm -f *.o file.map file_dump.map $(OBJ)

View File

@ -0,0 +1,42 @@
/* EXPERIMENTAL */
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

@ -0,0 +1,94 @@
#include <netools.h>
#include <pci.h>
#include <io.h>
#include "../../../Kernel/DAPI.hpp"
#include "../../../Kernel/Fex.hpp"
extern "C" int DriverEntry(KernelAPI *Data);
int CallbackHandler(KernelCallback *Data);
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,
.Bind = {
.Type = BIND_PCI,
.PCI = {
.VendorID = 0x10EC,
.DeviceID = 0x8169,
.Class = 0x2,
.SubClass = 0x0,
.ProgIF = 0x0,
}}}};
KernelAPI *KAPI;
/* --------------------------------------------------------------------------------------------------------- */
struct BARData
{
uint8_t Type;
uint64_t IOBase;
uint64_t MemoryBase;
};
PCIDeviceHeader *PCIBaseAddress;
BARData BAR;
MediaAccessControl MAC;
InternetProtocol4 IP;
int DriverEntry(KernelAPI *Data)
{
if (!Data)
return INVALID_KERNEL_API;
if (Data->Version.Major < 0 || Data->Version.Minor < 0 || Data->Version.Patch < 0)
return KERNEL_API_VERSION_NOT_SUPPORTED;
KAPI = Data;
return OK;
}
int CallbackHandler(KernelCallback *Data)
{
switch (Data->Reason)
{
case AcknowledgeReason:
{
KAPI->Util.DebugPrint(((char *)"Kernel acknowledged the driver." + KAPI->Info.Offset), KAPI->Info.DriverUID);
break;
}
case ConfigurationReason:
{
KAPI->Util.DebugPrint(((char *)"Kernel received configuration data." + KAPI->Info.Offset), KAPI->Info.DriverUID);
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
if (PCIBaseAddress->VendorID == 0x10EC && PCIBaseAddress->DeviceID == 0x8169)
{
KAPI->Util.DebugPrint(((char *)"Found RTL-8169." + KAPI->Info.Offset), KAPI->Info.DriverUID);
return NOT_IMPLEMENTED;
}
else
return DEVICE_NOT_SUPPORTED;
break;
}
case InterruptReason:
{
break;
}
case SendReason:
{
break;
}
default:
{
KAPI->Util.DebugPrint(((char *)"Unknown reason." + KAPI->Info.Offset), KAPI->Info.DriverUID);
break;
}
}
return OK;
}

220
include/io.h Normal file
View File

@ -0,0 +1,220 @@
#ifndef __FENNIX_API_IO_H__
#define __FENNIX_API_IO_H__
#include <types.h>
#if defined(__amd64__) || defined(__i386__)
#ifdef __cplusplus
extern "C"
{
#endif
static inline uint8_t inportb(uint16_t Port)
{
uint8_t Result;
__asm__("in %%dx, %%al"
: "=a"(Result)
: "d"(Port));
return Result;
}
static inline uint16_t inportw(uint16_t Port)
{
uint16_t Result;
__asm__("in %%dx, %%ax"
: "=a"(Result)
: "d"(Port));
return Result;
}
static inline uint32_t inportl(uint16_t Port)
{
uint32_t Result;
__asm__ volatile("inl %1, %0"
: "=a"(Result)
: "dN"(Port));
return Result;
}
static inline void outportb(uint16_t Port, uint8_t Data)
{
__asm__ volatile("out %%al, %%dx"
:
: "a"(Data), "d"(Port));
}
static inline void outportw(uint16_t Port, uint16_t Data)
{
__asm__ volatile("out %%ax, %%dx"
:
: "a"(Data), "d"(Port));
}
static inline void outportl(uint16_t Port, uint32_t Data)
{
__asm__ volatile("outl %1, %0"
:
: "dN"(Port), "a"(Data));
}
static inline uint8_t mmioin8(uint64_t Address)
{
__asm__ volatile("" ::
: "memory");
uint8_t Result = *(volatile uint8_t *)Address;
__asm__ volatile("" ::
: "memory");
return Result;
}
static inline uint16_t mmioin16(uint64_t Address)
{
__asm__ volatile("" ::
: "memory");
uint16_t Result = *(volatile uint16_t *)Address;
__asm__ volatile("" ::
: "memory");
return Result;
}
static inline uint32_t mmioin32(uint64_t Address)
{
__asm__ volatile("" ::
: "memory");
uint32_t Result = *(volatile uint32_t *)Address;
__asm__ volatile("" ::
: "memory");
return Result;
}
static inline uint64_t mmioin64(uint64_t Address)
{
__asm__ volatile("" ::
: "memory");
uint64_t Result = *(volatile uint64_t *)Address;
__asm__ volatile("" ::
: "memory");
return Result;
}
static inline void mmioout8(uint64_t Address, uint8_t Data)
{
__asm__ volatile("" ::
: "memory");
*(volatile uint8_t *)Address = Data;
__asm__ volatile("" ::
: "memory");
}
static inline void mmioout16(uint64_t Address, uint16_t Data)
{
__asm__ volatile("" ::
: "memory");
*(volatile uint16_t *)Address = Data;
__asm__ volatile("" ::
: "memory");
}
static inline void mmioout32(uint64_t Address, uint32_t Data)
{
__asm__ volatile("" ::
: "memory");
*(volatile uint32_t *)Address = Data;
__asm__ volatile("" ::
: "memory");
}
static inline void mmioout64(uint64_t Address, uint64_t Data)
{
__asm__ volatile("" ::
: "memory");
*(volatile uint64_t *)Address = Data;
__asm__ volatile("" ::
: "memory");
}
static inline void mmoutb(void *Address, uint8_t Value)
{
__asm__ volatile("mov %1, %0"
: "=m"((*(uint8_t *)(Address)))
: "r"(Value)
: "memory");
}
static inline void mmoutw(void *Address, uint16_t Value)
{
__asm__ volatile("mov %1, %0"
: "=m"((*(uint16_t *)(Address)))
: "r"(Value)
: "memory");
}
static inline void mmoutl(void *Address, uint32_t Value)
{
__asm__ volatile("mov %1, %0"
: "=m"((*(uint32_t *)(Address)))
: "r"(Value)
: "memory");
}
static inline void mmoutq(void *Address, uint64_t Value)
{
__asm__ volatile("mov %1, %0"
: "=m"((*(uint64_t *)(Address)))
: "r"(Value)
: "memory");
}
static inline uint8_t mminb(void *Address)
{
uint8_t Result;
__asm__ volatile("mov %1, %0"
: "=r"(Result)
: "m"((*(uint8_t *)(Address)))
: "memory");
return Result;
}
static inline uint16_t mminw(void *Address)
{
uint16_t Result;
__asm__ volatile("mov %1, %0"
: "=r"(Result)
: "m"((*(uint16_t *)(Address)))
: "memory");
return Result;
}
static inline uint32_t mminl(void *Address)
{
uint32_t Result;
__asm__ volatile("mov %1, %0"
: "=r"(Result)
: "m"((*(uint32_t *)(Address)))
: "memory");
return Result;
}
static inline uint64_t mminq(void *Address)
{
uint64_t Result;
__asm__ volatile("mov %1, %0"
: "=r"(Result)
: "m"((*(uint64_t *)(Address)))
: "memory");
return Result;
}
#ifdef __cplusplus
}
#endif
#define inb(Port) inportb(Port)
#define inw(Port) inportw(Port)
#define inl(Port) inportl(Port)
#define outb(Port, Data) outportb(Port, Data)
#define outw(Port, Data) outportw(Port, Data)
#define outl(Port, Data) outportl(Port, Data)
#endif // defined(__amd64__) || defined(__i386__)
#endif // !__FENNIX_API_IO_H__

128
include/netools.h Normal file
View File

@ -0,0 +1,128 @@
#ifndef __FENNIX_API_NETWORK_UTILS_H__
#define __FENNIX_API_NETWORK_UTILS_H__
#include <types.h>
typedef __UINT64_TYPE__ uint48_t;
struct MediaAccessControl
{
uint8_t Address[6];
inline bool operator==(const MediaAccessControl &lhs) const
{
return lhs.Address[0] == this->Address[0] &&
lhs.Address[1] == this->Address[1] &&
lhs.Address[2] == this->Address[2] &&
lhs.Address[3] == this->Address[3] &&
lhs.Address[4] == this->Address[4] &&
lhs.Address[5] == this->Address[5];
}
inline bool operator==(const uint48_t &lhs) const
{
MediaAccessControl MAC;
MAC.Address[0] = (uint8_t)((lhs >> 40) & 0xFF);
MAC.Address[1] = (uint8_t)((lhs >> 32) & 0xFF);
MAC.Address[2] = (uint8_t)((lhs >> 24) & 0xFF);
MAC.Address[3] = (uint8_t)((lhs >> 16) & 0xFF);
MAC.Address[4] = (uint8_t)((lhs >> 8) & 0xFF);
MAC.Address[5] = (uint8_t)(lhs & 0xFF);
return MAC.Address[0] == this->Address[0] &&
MAC.Address[1] == this->Address[1] &&
MAC.Address[2] == this->Address[2] &&
MAC.Address[3] == this->Address[3] &&
MAC.Address[4] == this->Address[4] &&
MAC.Address[5] == this->Address[5];
}
inline bool operator!=(const MediaAccessControl &lhs) const { return !(*this == lhs); }
inline bool operator!=(const uint48_t &lhs) const { return !(*this == lhs); }
inline uint48_t ToHex()
{
return ((uint48_t)this->Address[0] << 40) |
((uint48_t)this->Address[1] << 32) |
((uint48_t)this->Address[2] << 24) |
((uint48_t)this->Address[3] << 16) |
((uint48_t)this->Address[4] << 8) |
((uint48_t)this->Address[5]);
}
inline MediaAccessControl FromHex(uint48_t Hex)
{
this->Address[0] = (uint8_t)((Hex >> 40) & 0xFF);
this->Address[1] = (uint8_t)((Hex >> 32) & 0xFF);
this->Address[2] = (uint8_t)((Hex >> 24) & 0xFF);
this->Address[3] = (uint8_t)((Hex >> 16) & 0xFF);
this->Address[4] = (uint8_t)((Hex >> 8) & 0xFF);
this->Address[5] = (uint8_t)(Hex & 0xFF);
return *this;
}
inline bool Valid()
{
// TODO: More complex MAC validation
return (this->Address[0] != 0 ||
this->Address[1] != 0 ||
this->Address[2] != 0 ||
this->Address[3] != 0 ||
this->Address[4] != 0 ||
this->Address[5] != 0) &&
(this->Address[0] != 0xFF ||
this->Address[1] != 0xFF ||
this->Address[2] != 0xFF ||
this->Address[3] != 0xFF ||
this->Address[4] != 0xFF ||
this->Address[5] != 0xFF);
}
};
struct InternetProtocol4
{
uint8_t Address[4];
inline bool operator==(const InternetProtocol4 &lhs) const
{
return lhs.Address[0] == this->Address[0] &&
lhs.Address[1] == this->Address[1] &&
lhs.Address[2] == this->Address[2] &&
lhs.Address[3] == this->Address[3];
}
inline bool operator==(const uint32_t &lhs) const
{
InternetProtocol4 IP;
IP.Address[0] = (uint8_t)((lhs >> 24) & 0xFF);
IP.Address[1] = (uint8_t)((lhs >> 16) & 0xFF);
IP.Address[2] = (uint8_t)((lhs >> 8) & 0xFF);
IP.Address[3] = (uint8_t)(lhs & 0xFF);
return IP.Address[0] == this->Address[0] &&
IP.Address[1] == this->Address[1] &&
IP.Address[2] == this->Address[2] &&
IP.Address[3] == this->Address[3];
}
inline bool operator!=(const InternetProtocol4 &lhs) const { return !(*this == lhs); }
inline bool operator!=(const uint32_t &lhs) const { return !(*this == lhs); }
inline uint32_t ToHex()
{
return ((uint64_t)this->Address[0] << 24) |
((uint64_t)this->Address[1] << 16) |
((uint64_t)this->Address[2] << 8) |
((uint64_t)this->Address[3]);
}
inline InternetProtocol4 FromHex(uint32_t Hex)
{
this->Address[0] = (uint8_t)((Hex >> 24) & 0xFF);
this->Address[1] = (uint8_t)((Hex >> 16) & 0xFF);
this->Address[2] = (uint8_t)((Hex >> 8) & 0xFF);
this->Address[3] = (uint8_t)(Hex & 0xFF);
return *this;
}
};
#endif // !__FENNIX_API_NETWORK_UTILS_H__

72
include/pci.h Normal file
View File

@ -0,0 +1,72 @@
#ifndef __FENNIX_API_PCI_H__
#define __FENNIX_API_PCI_H__
#include <types.h>
/* https://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html */
enum PCICommands
{
/** @brief Enable response in I/O space */
PCI_COMMAND_IO = 0x1,
/** @brief Enable response in Memory space */
PCI_COMMAND_MEMORY = 0x2,
/** @brief Enable bus mastering */
PCI_COMMAND_MASTER = 0x4,
/** @brief Enable response to special cycles */
PCI_COMMAND_SPECIAL = 0x8,
/** @brief Use memory write and invalidate */
PCI_COMMAND_INVALIDATE = 0x10,
/** @brief Enable palette snooping */
PCI_COMMAND_VGA_PALETTE = 0x20,
/** @brief Enable parity checking */
PCI_COMMAND_PARITY = 0x40,
/** @brief Enable address/data stepping */
PCI_COMMAND_WAIT = 0x80,
/** @brief Enable SERR */
PCI_COMMAND_SERR = 0x100,
/** @brief Enable back-to-back writes */
PCI_COMMAND_FAST_BACK = 0x200,
/** @brief INTx Emulation Disable */
PCI_COMMAND_INTX_DISABLE = 0x400
};
struct PCIDeviceHeader
{
uint16_t VendorID;
uint16_t DeviceID;
uint16_t Command;
uint16_t Status;
uint8_t RevisionID;
uint8_t ProgIF;
uint8_t Subclass;
uint8_t Class;
uint8_t CacheLineSize;
uint8_t LatencyTimer;
uint8_t HeaderType;
uint8_t BIST;
};
struct PCIHeader0
{
PCIDeviceHeader Header;
uint32_t BAR0;
uint32_t BAR1;
uint32_t BAR2;
uint32_t BAR3;
uint32_t BAR4;
uint32_t BAR5;
uint32_t CardbusCISPtr;
uint16_t SubsystemVendorID;
uint16_t SubsystemID;
uint32_t ExpansionROMBaseAddr;
uint8_t CapabilitiesPtr;
uint8_t Rsv0;
uint16_t Rsv1;
uint32_t Rsv2;
uint8_t InterruptLine;
uint8_t InterruptPin;
uint8_t MinGrant;
uint8_t MaxLatency;
};
#endif // !__FENNIX_API_PCI_H__

42
include/types.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef __FENNIX_API_TYPES_H__
#define __FENNIX_API_TYPES_H__
typedef __INT8_TYPE__ int8_t;
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
typedef __INT64_TYPE__ int64_t;
typedef __UINT8_TYPE__ uint8_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;
typedef __INT_LEAST8_TYPE__ int_least8_t;
typedef __INT_LEAST16_TYPE__ int_least16_t;
typedef __INT_LEAST32_TYPE__ int_least32_t;
typedef __INT_LEAST64_TYPE__ int_least64_t;
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
typedef __INT_FAST8_TYPE__ int_fast8_t;
typedef __INT_FAST16_TYPE__ int_fast16_t;
typedef __INT_FAST32_TYPE__ int_fast32_t;
typedef __INT_FAST64_TYPE__ int_fast64_t;
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __SIZE_TYPE__ size_t;
#define UNUSED(x) (void)(x)
#endif // !__FENNIX_API_TYPES_H__