diff --git a/.vscode/c_boilerplates.code-snippets b/.vscode/c_boilerplates.code-snippets new file mode 100644 index 0000000..366f30a --- /dev/null +++ b/.vscode/c_boilerplates.code-snippets @@ -0,0 +1,28 @@ +{ + "Header": { + "prefix": [ + "head", + ], + "body": [ + "#ifndef __FENNIX_API_${2:header}_H__", + "#define __FENNIX_API_${2:header}_H__", + "", + "#include ", + "", + "$0", + "", + "#endif // !__FENNIX_API_${2:header}_H__", + "" + ], + "description": "Create header." + }, + "Brief": { + "prefix": [ + "brief", + ], + "body": [ + "/** @brief $0 */" + ], + "description": "Create documentation brief." + } +} \ No newline at end of file diff --git a/Generic/ExampleDriver/Example.cpp b/Generic/ExampleDriver/Example.cpp new file mode 100644 index 0000000..5d81f93 --- /dev/null +++ b/Generic/ExampleDriver/Example.cpp @@ -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; +} diff --git a/Generic/ExampleDriver/Makefile b/Generic/ExampleDriver/Makefile new file mode 100644 index 0000000..bd2e99b --- /dev/null +++ b/Generic/ExampleDriver/Makefile @@ -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) diff --git a/Generic/ExampleDriver/arch/amd64/linker.ld b/Generic/ExampleDriver/arch/amd64/linker.ld new file mode 100644 index 0000000..29cd11c --- /dev/null +++ b/Generic/ExampleDriver/arch/amd64/linker.ld @@ -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.*) + } +} diff --git a/Generic/Makefile b/Generic/Makefile new file mode 100644 index 0000000..b74e7b8 --- /dev/null +++ b/Generic/Makefile @@ -0,0 +1,8 @@ +build: + make --quiet -C ExampleDriver build + +prepare: + $(info Nothing to prepare) + +clean: + make --quiet -C ExampleDriver clean diff --git a/Makefile b/Makefile index 5dcd77b..24c84f1 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ build: mkdir -p out - touch out/dummy.drv + touch out/dummy.fex make --quiet -C Audio build make --quiet -C FileSystem build + make --quiet -C Generic build + make --quiet -C Network build make --quiet -C Video build prepare: @@ -12,4 +14,6 @@ clean: rm -rf out make -C Audio clean make -C FileSystem clean + make -C Generic clean + make -C Network clean make -C Video clean diff --git a/Network/AMDPCNET/Makefile b/Network/AMDPCNET/Makefile new file mode 100644 index 0000000..3cfe77d --- /dev/null +++ b/Network/AMDPCNET/Makefile @@ -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) diff --git a/Network/AMDPCNET/arch/amd64/linker.ld b/Network/AMDPCNET/arch/amd64/linker.ld new file mode 100644 index 0000000..511369e --- /dev/null +++ b/Network/AMDPCNET/arch/amd64/linker.ld @@ -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.*) + } +} diff --git a/Network/AMDPCNET/pcnet.cpp b/Network/AMDPCNET/pcnet.cpp new file mode 100644 index 0000000..a27a41e --- /dev/null +++ b/Network/AMDPCNET/pcnet.cpp @@ -0,0 +1,123 @@ +#include +#include +#include + +#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(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; +} diff --git a/Network/E1000/Makefile b/Network/E1000/Makefile new file mode 100644 index 0000000..b42225d --- /dev/null +++ b/Network/E1000/Makefile @@ -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) diff --git a/Network/E1000/arch/amd64/linker.ld b/Network/E1000/arch/amd64/linker.ld new file mode 100644 index 0000000..511369e --- /dev/null +++ b/Network/E1000/arch/amd64/linker.ld @@ -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.*) + } +} diff --git a/Network/E1000/e1000.cpp b/Network/E1000/e1000.cpp new file mode 100644 index 0000000..e22a121 --- /dev/null +++ b/Network/E1000/e1000.cpp @@ -0,0 +1,419 @@ +#include +#include +#include + +#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(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; +} diff --git a/Network/Makefile b/Network/Makefile new file mode 100644 index 0000000..256c728 --- /dev/null +++ b/Network/Makefile @@ -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 diff --git a/Network/RTL8139/Makefile b/Network/RTL8139/Makefile new file mode 100644 index 0000000..5c37a4c --- /dev/null +++ b/Network/RTL8139/Makefile @@ -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) diff --git a/Network/RTL8139/arch/amd64/linker.ld b/Network/RTL8139/arch/amd64/linker.ld new file mode 100644 index 0000000..511369e --- /dev/null +++ b/Network/RTL8139/arch/amd64/linker.ld @@ -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.*) + } +} diff --git a/Network/RTL8139/rtl8139.cpp b/Network/RTL8139/rtl8139.cpp new file mode 100644 index 0000000..9a13f5a --- /dev/null +++ b/Network/RTL8139/rtl8139.cpp @@ -0,0 +1,200 @@ +#include +#include +#include + +#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(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(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(BAR.MemoryBase + Address), Value); + else + outportl(BAR.IOBase + Address, Value); +} + +uint8_t RTLIB(uint16_t Address) +{ + if (BAR.Type == 0) + return mminb(reinterpret_cast(BAR.MemoryBase + Address)); + else + return inportb(BAR.IOBase + Address); +} + +uint16_t RTLIW(uint16_t Address) +{ + if (BAR.Type == 0) + return mminw(reinterpret_cast(BAR.MemoryBase + Address)); + else + return inportw(BAR.IOBase + Address); +} + +uint32_t RTLIL(uint16_t Address) +{ + if (BAR.Type == 0) + return mminl(reinterpret_cast(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(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(reinterpret_cast(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(reinterpret_cast(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; +} diff --git a/Network/RTL8169/Makefile b/Network/RTL8169/Makefile new file mode 100644 index 0000000..c991bea --- /dev/null +++ b/Network/RTL8169/Makefile @@ -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) diff --git a/Network/RTL8169/arch/amd64/linker.ld b/Network/RTL8169/arch/amd64/linker.ld new file mode 100644 index 0000000..511369e --- /dev/null +++ b/Network/RTL8169/arch/amd64/linker.ld @@ -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.*) + } +} diff --git a/Network/RTL8169/rtl8169.cpp b/Network/RTL8169/rtl8169.cpp new file mode 100644 index 0000000..6056404 --- /dev/null +++ b/Network/RTL8169/rtl8169.cpp @@ -0,0 +1,94 @@ +#include +#include +#include + +#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(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; +} diff --git a/include/io.h b/include/io.h new file mode 100644 index 0000000..ca17bc7 --- /dev/null +++ b/include/io.h @@ -0,0 +1,220 @@ +#ifndef __FENNIX_API_IO_H__ +#define __FENNIX_API_IO_H__ + +#include + +#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__ diff --git a/include/netools.h b/include/netools.h new file mode 100644 index 0000000..7f92626 --- /dev/null +++ b/include/netools.h @@ -0,0 +1,128 @@ +#ifndef __FENNIX_API_NETWORK_UTILS_H__ +#define __FENNIX_API_NETWORK_UTILS_H__ + +#include + +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__ diff --git a/include/pci.h b/include/pci.h new file mode 100644 index 0000000..b0e711e --- /dev/null +++ b/include/pci.h @@ -0,0 +1,72 @@ +#ifndef __FENNIX_API_PCI_H__ +#define __FENNIX_API_PCI_H__ + +#include + +/* 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__ diff --git a/include/types.h b/include/types.h new file mode 100644 index 0000000..b0eecc2 --- /dev/null +++ b/include/types.h @@ -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__