From 1347df1f9f9c0e980c9e7c6cf90a34636a764965 Mon Sep 17 00:00:00 2001 From: Martin Petr Date: Thu, 20 Nov 2025 17:39:19 +0100 Subject: [PATCH] Add PCI driver --- scripts/build_js.js | 2 + src/kernel/kernel.c | 37 ++++++ src/os/src/kernel/drivers/dev/pci.ts | 122 ++++++++++++++++++ src/os/src/kernel/index.ts | 14 +- .../kernel/modules/drivers/drivers.kmod.ts | 3 +- src/os/src/lib/libstd/logger/logger.kmod.ts | 12 ++ src/os/src/lib/libts/dword.ts | 7 + src/os/src/lib/sys/pci/class.ts | 29 +++++ src/os/src/types/c/bindings.d.ts | 2 + src/os/src/types/dev/pci/class.ts | 19 +++ 10 files changed, 234 insertions(+), 13 deletions(-) create mode 100644 src/os/src/kernel/drivers/dev/pci.ts create mode 100644 src/os/src/lib/libstd/logger/logger.kmod.ts create mode 100644 src/os/src/lib/libts/dword.ts create mode 100644 src/os/src/lib/sys/pci/class.ts create mode 100644 src/os/src/types/dev/pci/class.ts diff --git a/scripts/build_js.js b/scripts/build_js.js index ea9a214..4244e23 100755 --- a/scripts/build_js.js +++ b/scripts/build_js.js @@ -6,4 +6,6 @@ writeFileSync( readFileSync("build/index.js", "utf-8") .replaceAll("let ", "var ") .replaceAll("const ", "var ") + .replaceAll("\n`", "\\n`") + .replaceAll("`", "'") ); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index a69d4fb..a670a93 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -56,6 +56,35 @@ duk_ret_t native_ptout(duk_context *ctx) return 0; } +duk_ret_t native_dword_in(duk_context *ctx) +{ + // Get the port (first argument) + uint16_t port = (uint16_t)duk_to_uint32(ctx, 0); + + uint32_t result; + __asm__ volatile("inl %1, %0" + : "=a"(result) + : "Nd"(port)); + + duk_push_uint(ctx, (duk_uint_t)result); + return 1; +} + +duk_ret_t native_dword_out(duk_context *ctx) +{ + // Get the port (first argument) + uint16_t port = (uint16_t)duk_to_uint32(ctx, 0); + + // Get the value to write (second argument) + uint32_t value = (uint32_t)duk_to_uint32(ctx, 1); + + __asm__ volatile("outl %0, %1" + : + : "a"(value), "Nd"(port)); + + return 0; +} + void kmain() { // Initialize Duktape heap @@ -73,6 +102,14 @@ void kmain() duk_push_c_function(ctx, native_ptout, 2); duk_put_global_string(ctx, "$ptout"); + // Register native dword in function + duk_push_c_function(ctx, native_dword_in, 1); + duk_put_global_string(ctx, "$dwordin"); + + // Register native dword out function + duk_push_c_function(ctx, native_dword_out, 2); + duk_put_global_string(ctx, "$dwordout"); + // Execute embedded JavaScript code from build/index.js duk_push_string(ctx, embedded_js_code); duk_int_t returnCode = duk_peval(ctx); diff --git a/src/os/src/kernel/drivers/dev/pci.ts b/src/os/src/kernel/drivers/dev/pci.ts new file mode 100644 index 0000000..2ab0031 --- /dev/null +++ b/src/os/src/kernel/drivers/dev/pci.ts @@ -0,0 +1,122 @@ +import { dwordin, dwordout } from "../../../lib/libts/dword"; +import { portin, portout } from "../../../lib/libts/port"; +import { Logger } from "../../../lib/libstd/logger/logger.kmod"; + +const KDRIVER_PCI_CONFIG_ADDR = 0xcf8; +const KDRIVER_PCI_CONFIG_DATA = 0xcfc; + +export function kdriver_dev_pci_init() {} + +export function kdriver_dev_pci_detectDevices() { + Logger.log("[PCI] Scanning..."); + + for (let bus = 0; bus < 256; bus++) { + for (let device = 0; device < 32; device++) { + kdriver_dev_pci_checkDevice(bus, device, 0); + + const headerType = kdriver_dev_pci_getHeaderType(bus, device, 0); + if ((headerType & 0x80) !== 0) { + for (let func = 1; func < 8; func++) { + kdriver_dev_pci_checkDevice(bus, device, func); + } + } + } + } +} + +export function kdriver_dev_pci_checkDevice( + bus: number, + device: number, + func: number +) { + const vendorId = kdriver_dev_pci_getVendorId(bus, device, func); + + if (vendorId === 0xffff) return; + + const deviceId = kdriver_dev_pci_getDeviceId(bus, device, func); + const classCode = kdriver_dev_pci_getClassCode(bus, device, func); + const subclass = kdriver_dev_pci_getSubclass(bus, device, func); + + Logger.log( + "[PCI] Found device pci:" + + bus + + ":" + + device + + ":" + + func + + " (vendor:" + + vendorId.toString(16) + + ", device:" + + deviceId.toString(16) + + ", class:" + + classCode.toString(16) + + ", subclass:" + + subclass.toString(16) + + ")" + ); +} + +export function kdriver_dev_pci_getDeviceId( + bus: number, + device: number, + func: number +) { + const data = kdriver_dev_pci_readConfigDword(bus, device, func, 0); + + return data >> 16; +} + +export function kdriver_dev_pci_getVendorId( + bus: number, + device: number, + func: number +) { + const data = kdriver_dev_pci_readConfigDword(bus, device, func, 0); + + return data & 0xffff; +} + +export function kdriver_dev_pci_getClassCode( + bus: number, + device: number, + func: number +) { + const data = kdriver_dev_pci_readConfigDword(bus, device, func, 8); + + return (data >> 24) & 0xff; +} + +export function kdriver_dev_pci_getSubclass( + bus: number, + device: number, + func: number +) { + const data = kdriver_dev_pci_readConfigDword(bus, device, func, 8); + + return (data >> 16) & 0xff; +} + +export function kdriver_dev_pci_getHeaderType( + bus: number, + device: number, + func: number +) { + const data = kdriver_dev_pci_readConfigDword(bus, device, func, 12); + + return (data >> 16) & 0xff; +} + +export function kdriver_dev_pci_readConfigDword( + bus: number, + device: number, + func: number, + offset: number +) { + const address = + (1 << 31) | (bus << 16) | (device << 11) | (func << 8) | (offset & 0xfc); + + dwordout(KDRIVER_PCI_CONFIG_ADDR, address); + const data = dwordin(KDRIVER_PCI_CONFIG_DATA); + + return data; +} diff --git a/src/os/src/kernel/index.ts b/src/os/src/kernel/index.ts index 918d4ee..a3064e8 100644 --- a/src/os/src/kernel/index.ts +++ b/src/os/src/kernel/index.ts @@ -1,6 +1,7 @@ import { charc } from "../lib/libts/byte"; import { padStart } from "../lib/libts/string"; import { getDate } from "../lib/sys/date"; +import { kdriver_dev_pci_detectDevices } from "./drivers/dev/pci"; import { kdriver_etc_serial_read, kdriver_etc_serial_transmit, @@ -20,20 +21,9 @@ export function kmain() { kmod_drivers_register(); - kdriver_etc_serial_transmit(charc("H")); - kdriver_etc_serial_transmit(charc("e")); - kdriver_etc_serial_transmit(charc("l")); - kdriver_etc_serial_transmit(charc("l")); - kdriver_etc_serial_transmit(charc("o")); + kdriver_dev_pci_detectDevices(); kmod_graphics_vga_init(); kmod_graphics_vga_pushLine("[Kernel] Kernel initialized successfully."); kmod_graphics_vga_pushLine("Current date: " + getDate().toDateString()); - - while (true) { - const d = kdriver_etc_serial_read(); - kmod_graphics_vga_pushLine( - "Serial input: 0x" + padStart(d.toString(16), 2, "0") - ); - } } diff --git a/src/os/src/kernel/modules/drivers/drivers.kmod.ts b/src/os/src/kernel/modules/drivers/drivers.kmod.ts index 4b18b0e..f6fce60 100644 --- a/src/os/src/kernel/modules/drivers/drivers.kmod.ts +++ b/src/os/src/kernel/modules/drivers/drivers.kmod.ts @@ -1,6 +1,7 @@ +import { kdriver_dev_pci_init } from "../../drivers/dev/pci"; import { kdriver_etc_serial_init } from "../../drivers/etc/serial"; -const drivers = [kdriver_etc_serial_init]; +const drivers = [kdriver_etc_serial_init, kdriver_dev_pci_init]; export function kmod_drivers_init(): void {} diff --git a/src/os/src/lib/libstd/logger/logger.kmod.ts b/src/os/src/lib/libstd/logger/logger.kmod.ts new file mode 100644 index 0000000..2e9d6c2 --- /dev/null +++ b/src/os/src/lib/libstd/logger/logger.kmod.ts @@ -0,0 +1,12 @@ +import { charc } from "../../libts/byte"; +import { kdriver_etc_serial_transmit } from "../../../kernel/drivers/etc/serial"; + +export const Logger = { + log(message: string) { + for (let i = 0; i < message.length; i++) { + kdriver_etc_serial_transmit(charc(message[i]!)); + } + + kdriver_etc_serial_transmit(charc("\n")); + }, +}; diff --git a/src/os/src/lib/libts/dword.ts b/src/os/src/lib/libts/dword.ts new file mode 100644 index 0000000..d78c5ca --- /dev/null +++ b/src/os/src/lib/libts/dword.ts @@ -0,0 +1,7 @@ +export function dwordin(dw: number): number { + return $dwordin(dw); +} + +export function dwordout(dw: number, value: number): void { + $dwordout(dw, value); +} diff --git a/src/os/src/lib/sys/pci/class.ts b/src/os/src/lib/sys/pci/class.ts new file mode 100644 index 0000000..2dd42d5 --- /dev/null +++ b/src/os/src/lib/sys/pci/class.ts @@ -0,0 +1,29 @@ +import { KDriverPCIClass } from "../../../types/dev/pci/class"; + +const sysPCIClassNames = { + [KDriverPCIClass.MassStorageController]: "Mass Storage Controller", + [KDriverPCIClass.NetworkController]: "Network Controller", + [KDriverPCIClass.DisplayController]: "Display Controller", + [KDriverPCIClass.MultimediaController]: "Multimedia Controller", + [KDriverPCIClass.MemoryController]: "Memory Controller", + [KDriverPCIClass.BridgeDevice]: "Bridge Device", + [KDriverPCIClass.SimpleCommunicationsController]: + "Simple Communications Controller", + [KDriverPCIClass.BaseSystemPeripheral]: "Base System Peripheral", + [KDriverPCIClass.InputDevice]: "Input Device", + [KDriverPCIClass.DockingStation]: "Docking Station", + [KDriverPCIClass.Processors]: "Processors", + [KDriverPCIClass.SerialBusController]: "Serial Bus Controller", + [KDriverPCIClass.WirelessController]: "Wireless Controller", + [KDriverPCIClass.IntelligentIOController]: "Intelligent I/O Controller", + [KDriverPCIClass.SatelliteCommunicationController]: + "Satellite Communication Controller", + [KDriverPCIClass.EncryptionDecryptionController]: + "Encryption/Decryption Controller", + [KDriverPCIClass.DataAcquisitionAndSignalProcessingController]: + "Data Acquisition and Signal Processing Controller", +}; + +export function sys_pci_class_name(classId: KDriverPCIClass): string { + return sysPCIClassNames[classId] || "Unknown"; +} diff --git a/src/os/src/types/c/bindings.d.ts b/src/os/src/types/c/bindings.d.ts index 6f38631..ce9b92d 100644 --- a/src/os/src/types/c/bindings.d.ts +++ b/src/os/src/types/c/bindings.d.ts @@ -1,3 +1,5 @@ declare function $addrw(address: number, value: number): void; declare function $ptin(port: number): number; declare function $ptout(port: number, value: number): void; +declare function $dwordin(port: number): number; +declare function $dwordout(port: number, value: number): void; diff --git a/src/os/src/types/dev/pci/class.ts b/src/os/src/types/dev/pci/class.ts new file mode 100644 index 0000000..778812c --- /dev/null +++ b/src/os/src/types/dev/pci/class.ts @@ -0,0 +1,19 @@ +export enum KDriverPCIClass { + MassStorageController = 1, + NetworkController = 2, + DisplayController = 3, + MultimediaController = 4, + MemoryController = 5, + BridgeDevice = 6, + SimpleCommunicationsController = 7, + BaseSystemPeripheral = 8, + InputDevice = 9, + DockingStation = 10, + Processors = 11, + SerialBusController = 12, + WirelessController = 13, + IntelligentIOController = 14, + SatelliteCommunicationController = 15, + EncryptionDecryptionController = 16, + DataAcquisitionAndSignalProcessingController = 17, +}