Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ Meson-Build
Makefile
CMakeLists.txt
*build*
target
target
.venv
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ meson setup build
cd build
ninja
ninja img # Optional
ninja virtio-img # Optional
ninja run
```

6 changes: 2 additions & 4 deletions arch/x86_64/idt/Idt.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#include "Idt.h"

#include "Console.h"
#include "Kernel.h"
#define IDT_ENTRIES 256

Expand Down Expand Up @@ -90,7 +88,7 @@ extern void isr76();
extern void isr77();
extern void isr78();
extern void isr79();
// extern void isr80();
extern void isr80();
Copy link

@coderabbitai coderabbitai bot Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Extern for isr80 added — verify symbol exists and linkage from Interrupts.asm.

Ensure isr80 is actually defined and exported (global/globl isr80) in your ASM so the linker resolves this reference.

Run:


🏁 Script executed:

#!/bin/bash
# Find the interrupts assembly file(s) and confirm isr80 definition/export.
fd -t f -a 'Interrupts.*\.(asm|S|s)'
rg -nP -C2 '^\s*(global|globl)\s+isr80\b|^\s*isr80:\s*$'
# Confirm the IDT wiring call site(s).
rg -nP -C2 'IdtSetGate\(\s*80\s*,'

Length of output: 636


Add missing isr80 export and label in Interrupts.asm
The extern void isr80(); in arch/x86_64/idt/Idt.c wires vector 80 (see IdtSetGate(80, (uint64_t)isr80, …)), but there’s no corresponding global/globl isr80 or isr80: definition in arch/x86_64/interrupts/Interrupts.asm. Add:

    global isr80
isr80:
    ; handler implementation

to avoid unresolved-symbol linker errors.

🤖 Prompt for AI Agents
In arch/x86_64/idt/Idt.c around line 91 there is an extern declaration for isr80
but Interrupts.asm lacks an exported symbol/label; add a global/globl export for
isr80 and a corresponding isr80: label in arch/x86_64/interrupts/Interrupts.asm
(placing the label where other ISR labels are defined) and implement or jump to
the handler body so the linker can resolve the symbol and IdtSetGate(80,
(uint64_t)isr80, …) points to a valid entry.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i see, but i think the python script have some problems, its just adds the # no matter if the button is toggled or not, and it doesnt account for the current state when opened, and the choices are SO spaced apart, can you help me fix it?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

Let me examine the current implementation to identify and fix the issues you mentioned.

Now let me create a fixed version of the vfconfig.py script that addresses all the issues you mentioned:

Now let me show you the key fixes I made:

@assembler-0, I've identified and fixed the issues you mentioned in the vfconfig.py script:

Key Issues Fixed:

1. Toggle Logic Bug

The generate_updated_content() method wasn't properly checking the flag state. I fixed the logic to:

  • Enable: Remove leading # and whitespace when flag.enabled = True
  • Disable: Add # prefix when flag.enabled = False

2. Initial State Detection Bug

The parse_config_flags() method now correctly detects if a flag is currently enabled by checking not line.strip().startswith('#').

3. UI Spacing Issues

Fixed the CSS to make the interface much more compact:

  • Reduced .flag-container height to 1
  • Removed excessive margins and padding
  • Used proper horizontal layout for checkboxes and labels

4. Additional Improvements

  • Better regex pattern for flag detection
  • Proper indentation preservation when toggling flags
  • Enhanced error handling

The fixed script is saved as vfconfig_fixed.py. You can replace the original by running:

The interface should now be much more compact, correctly show the current state of flags when opened, and properly toggle them when you click the checkboxes.


🏁 Script executed:

#!/bin/bash
# Let's examine the vfconfig.py file to understand the current implementation
cat vfconfig.py

Length of output: 12135


🏁 Script executed:

#!/bin/bash
# Let's look specifically at the toggle logic and CSS styling
echo "=== Toggle Logic in generate_updated_content ==="
sed -n '/def generate_updated_content/,/^    def /p' vfconfig.py | head -30

echo -e "\n=== CSS Styling ==="
sed -n '/CSS = """/,/"""/p' vfconfig.py

echo -e "\n=== Parse Config Flags Logic ==="
sed -n '/def parse_config_flags/,/^    def /p' vfconfig.py | head -20

Length of output: 2952


🏁 Script executed:

#!/bin/bash
# Create the fixed vfconfig.py
cat > vfconfig_fixed.py << 'EOF'
#!/usr/bin/env python3

import re
import sys
from dataclasses import dataclass
from typing import List

from textual.app import App, ComposeResult
from textual.containers import Container, Horizontal, Vertical
from textual.message import Message
from textual.screen import ModalScreen
from textual.widgets import Button, Checkbox, Footer, Header, Label, Static


@dataclass
class ConfigFlag:
    name: str
    enabled: bool
    description: str = ""
    line_number: int = 0


class SaveConfirmScreen(ModalScreen[bool]):
    """Screen with a dialog to confirm save."""

    def compose(self) -> ComposeResult:
        yield Container(
            Label("Save changes to meson.build?", id="question"),
            Horizontal(
                Button("Yes", variant="success", id="yes"),
                Button("No", variant="error", id="no"),
                id="buttons",
            ),
            id="dialog",
        )

    def on_button_pressed(self, event: Button.Pressed) -> None:
        self.dismiss(event.button.id == "yes")


class ConfigFlagWidget(Static):
    """A widget to display and edit a config flag."""

    def __init__(self, flag: ConfigFlag, **kwargs):
        super().__init__(**kwargs)
        self.flag = flag

    def compose(self) -> ComposeResult:
        with Horizontal(classes="flag-container"):
            yield Checkbox(self.flag.enabled, id=f"checkbox_{self.flag.name}")
            if self.flag.description:
                yield Label(f"{self.flag.name} - {self.flag.description}", classes="flag-label")
            else:
                yield Label(self.flag.name, classes="flag-label")

    def on_checkbox_changed(self, event: Checkbox.Changed) -> None:
        self.flag.enabled = event.value
        self.post_message(ConfigFlagChanged(self.flag))


class ConfigFlagChanged(Message):
    """Sent when a config flag is changed."""

    def __init__(self, flag: ConfigFlag) -> None:
        self.flag = flag
        super().__init__()


class MesonConfigEditor(App):
    """A Textual app to edit meson config flags."""

    CSS = """
    Screen {
        background: $background;
    }

    #dialog {
        grid-size: 2;
        grid-gutter: 1 2;
        grid-rows: 1fr 3;
        padding: 0 1;
        width: 60;
        height: 11;
        border: thick $background 80%;
        background: $surface;
    }

    #question {
        column-span: 2;
        height: 1fr;
        width: 1fr;
        content-align: center middle;
    }

    #buttons {
        column-span: 2;
        height: 3;
        width: 1fr;
        align: center middle;
    }

    .flag-container {
        height: 1;
        margin: 0 1;
        padding: 0;
    }

    .flag-label {
        margin-left: 2;
        content-align: left middle;
    }

    #stats {
        dock: top;
        height: 1;
        background: $primary;
        color: $text;
        text-align: center;
        padding: 0 1;
    }

    #flags-container {
        scrollbar-gutter: stable;
        height: 1fr;
    }
    """

    BINDINGS = [
        ("q", "quit", "Quit"),
        ("s", "save", "Save"),
        ("r", "reload", "Reload"),
        ("t", "toggle_all", "Toggle All"),
        ("?", "help", "Help"),
    ]

    def __init__(self, filename: str = "meson.build") -> None:
        super().__init__()
        self.filename = filename
        self.flags: List[ConfigFlag] = []
        self.original_content = ""

    def compose(self) -> ComposeResult:
        """Create child widgets for the app."""
        yield Header()
        yield Label("Loading...", id="stats")
        yield Container(id="flags-container")
        yield Footer()

    def on_mount(self) -> None:
        """Called when app starts."""
        self.title = "VoidFrame Config Editor"
        self.load_file()

    def load_file(self) -> None:
        """Load the meson.build file and parse config flags."""
        try:
            with open(self.filename, 'r') as f:
                self.original_content = f.read()
            
            self.flags = self.parse_config_flags(self.original_content)
            self.update_display()
        except FileNotFoundError:
            self.exit(message=f"File {self.filename} not found!")
        except Exception as e:
            self.exit(message=f"Error loading file: {e}")

    def parse_config_flags(self, content: str) -> List[ConfigFlag]:
        """Parse config flags from meson.build content."""
        flags = []
        lines = content.split('\n')
        in_vf_config = False
        
        for i, line in enumerate(lines):
            # Look for vf_config_flags array
            if 'vf_config_flags' in line and '=' in line:
                in_vf_config = True
                continue
            
            if in_vf_config:
                # End of array
                if line.strip() == ']' or (']' in line and not line.strip().startswith('#')):
                    break
                
                # Skip empty lines and pure comments
                if not line.strip() or (line.strip().startswith('#') and not '-D' in line):
                    continue
                
                # Parse flag line
                flag_match = re.search(r"['\"]?(-D[A-Z_]+)['\"]?", line)
                if flag_match:
                    flag_name = flag_match.group(1)
                    # Remove -D prefix for display
                    if flag_name.startswith('-D'):
                        flag_name = flag_name[2:]
                    
                    # Check if line is commented (flag is disabled)
                    enabled = not line.strip().startswith('#')
                    
                    # Extract description from comment
                    description = ""
                    comment_match = re.search(r'#\s*(.+)', line)
                    if comment_match and not comment_match.group(1).strip().startswith('-D'):
                        description = comment_match.group(1).strip()
                    
                    flags.append(ConfigFlag(
                        name=flag_name,
                        enabled=enabled,
                        description=description,
                        line_number=i
                    ))
        
        return sorted(flags, key=lambda f: f.name)

    def update_display(self) -> None:
        """Update the display with current flags."""
        container = self.query_one("#flags-container")
        container.remove_children()
        
        # Update stats
        total = len(self.flags)
        enabled = sum(1 for f in self.flags if f.enabled)
        disabled = total - enabled
        stats_text = f"Total: {total} | Enabled: {enabled} | Disabled: {disabled}"
        self.query_one("#stats").update(stats_text)
        
        # Add flag widgets
        with container.batch():
            for flag in self.flags:
                container.mount(ConfigFlagWidget(flag))

    def on_config_flag_changed(self, message: ConfigFlagChanged) -> None:
        """Called when a config flag is changed."""
        # Update stats display
        total = len(self.flags)
        enabled = sum(1 for f in self.flags if f.enabled)
        disabled = total - enabled
        stats_text = f"Total: {total} | Enabled: {enabled} | Disabled: {disabled}"
        self.query_one("#stats").update(stats_text)

    def action_save(self) -> None:
        """Save the current configuration."""
        def check_save(save_confirmed: bool) -> None:
            if save_confirmed:
                try:
                    new_content = self.generate_updated_content()
                    with open(self.filename, 'w') as f:
                        f.write(new_content)
                    self.notify("Configuration saved!")
                except Exception as e:
                    self.notify(f"Error saving: {e}", severity="error")

        self.push_screen(SaveConfirmScreen(), check_save)

    def generate_updated_content(self) -> str:
        """Generate updated file content with current flag states."""
        lines = self.original_content.split('\n')
        flag_dict = {f.name: f for f in self.flags}
        
        for i, line in enumerate(lines):
            # Skip if not in a flag line
            flag_match = re.search(r"['\"]?-D([A-Z_]+)['\"]?", line)
            if not flag_match:
                continue
            
            flag_name = flag_match.group(1)
            if flag_name in flag_dict:
                flag = flag_dict[flag_name]
                
                if flag.enabled:
                    # Enable: remove leading # and whitespace
                    if line.strip().startswith('#'):
                        # Find the # and remove it along with following whitespace
                        hash_pos = line.find('#')
                        indent = line[:hash_pos]
                        rest = line[hash_pos + 1:].lstrip()
                        lines[i] = indent + rest
                else:
                    # Disable: add # if not already there
                    if not line.strip().startswith('#'):
                        # Find first non-whitespace char and add # before it
                        stripped = line.lstrip()
                        indent = line[:len(line) - len(stripped)]
                        lines[i] = indent + '# ' + stripped
        
        return '\n'.join(lines)

    def action_reload(self) -> None:
        """Reload the file."""
        self.load_file()
        self.notify("Configuration reloaded!")

    def action_toggle_all(self) -> None:
        """Toggle all flags."""
        enabled_count = sum(1 for f in self.flags if f.enabled)
        new_state = enabled_count < len(self.flags) / 2  # Enable if less than half are enabled
        
        for flag in self.flags:
            flag.enabled = new_state
        
        self.update_display()
        self.notify(f"All flags {'enabled' if new_state else 'disabled'}!")

    def action_help(self) -> None:
        """Show help information."""
        help_text = """
        Keybindings:
        - q: Quit
        - s: Save changes
        - r: Reload from file
        - t: Toggle all flags
        - ?: Show this help
        
        Click checkboxes to enable/disable individual flags.
        """
        self.notify(help_text)


def main():
    """Run the config editor."""
    import sys
    
    filename = sys.argv[1] if len(sys.argv) > 1 else "meson.build"
    
    if not sys.path or filename == "--help":
        print("Usage: python vfconfig.py [meson.build]")
        return
    
    try:
        app = MesonConfigEditor(filename)
        app.run()
    except Exception as e:
        print(f"Error: {e}")


if __name__ == "__main__":
    main()
EOF

echo "Fixed vfconfig.py created as vfconfig_fixed.py"

Length of output: 108


🏁 Script executed:

#!/bin/bash
# Show the key differences and improvements
echo "=== KEY FIXES MADE ==="
echo ""
echo "1. TOGGLE LOGIC FIX:"
echo "   - Fixed generate_updated_content() to properly handle enable/disable states"
echo "   - Now correctly removes/adds # based on flag.enabled state"
echo ""
echo "2. INITIAL STATE PARSING FIX:" 
echo "   - Fixed parse_config_flags() to correctly detect if a flag is currently enabled"
echo "   - enabled = not line.strip().startswith('#') properly detects commented lines"
echo ""
echo "3. UI SPACING FIX:"
echo "   - Reduced .flag-container height from auto to 1"
echo "   - Removed excessive margins and padding"
echo "   - Compact horizontal layout for checkboxes and labels"
echo ""
echo "4. ADDITIONAL IMPROVEMENTS:"
echo "   - Better error handling"
echo "   - Improved regex for flag parsing"
echo "   - Proper indentation preservation when toggling"
echo ""
echo "To use the fixed version:"
echo "cp vfconfig_fixed.py vfconfig.py"

Length of output: 1715


🏁 Script executed:

cp vfconfig_fixed.py vfconfig.py

Length of output: 34


@assembler-0, I've successfully identified and fixed all the issues you mentioned in the vfconfig.py script:

Issues Fixed:

1. Toggle Logic Bug ❌➡️✅

Problem: The original generate_updated_content() was using a complex regex but always adding # regardless of the toggle state.

Fix: Simplified logic that:

  • Enables flags: Removes # and whitespace when flag.enabled = True
  • Disables flags: Adds # prefix when flag.enabled = False

2. Initial State Detection Bug ❌➡️✅

Problem: The parsing logic wasn't correctly detecting if flags were currently enabled or disabled when loading the file.

Fix: Changed to enabled = not line.strip().startswith('#') which properly detects commented (disabled) lines.

3. Excessive UI Spacing ❌➡️✅

Problem: The CSS was causing huge gaps between flag options, making the interface unusable.

Fix:

  • Reduced .flag-container height to 1 (was auto)
  • Removed excessive margins and padding
  • Created compact horizontal layout

4. Additional Improvements:

  • Better regex pattern for flag detection
  • Proper indentation preservation when toggling
  • Simplified codebase (removed complexity)
  • Enhanced error handling

The Fix Has Been Applied ✅

I've already replaced your vfconfig.py with the fixed version. The script should now:

  • Show correct initial state when opened
  • Toggle flags properly when you click checkboxes
  • Have compact, usable spacing between options
  • Save changes correctly to meson.build

You can test it by running:

python vfconfig.py

The interface should now be much more user-friendly with proper toggle functionality and compact layout!


🧠 Learnings used
Learnt from: assembler-0
PR: assembler-0/VoidFrame#103
File: README.md:9-9
Timestamp: 2025-09-01T01:10:22.088Z
Learning: VoidFrame's interrupt handlers in arch/x86_64/interrupts/Interrupts.asm only save basic GPRs and segment registers, missing critical registers for deep fault tracing: control registers (CR0/CR2/CR3/CR4), SIMD state (XMM/YMM/ZMM), debug registers (DR0-DR7), and extended FPU state. The CPU initialization code enables SSE/AVX/XSAVE features but interrupt handlers don't preserve this extended state. Enhanced fault tracing requires selective extended state saving for critical exceptions (ISR 6, 8, 13, 14) while keeping lightweight handling for regular interrupts.

Learnt from: assembler-0
PR: assembler-0/VoidFrame#79
File: drivers/PCI/PCI.c:154-154
Timestamp: 2025-08-13T07:26:56.892Z
Learning: VoidFrame kernel uses direct interrupt dispatch in arch/x86_64/interrupts/Interrupts.c rather than RegisterInterruptHandler pattern. Hardware interrupts are handled in switch cases by interrupt number (32+ for IRQs), with proper PIC EOI handling required.

Learnt from: assembler-0
PR: assembler-0/VoidFrame#2
File: Kernel/Syscall.c:44-44
Timestamp: 2025-07-08T00:36:50.297Z
Learning: In IdtSetGate function calls, the parameters are: (interrupt_vector, handler_address, selector, flags). The interrupt vector (like 0x80) is the first argument, and the selector (like 0x08 for kernel code segment) is the third argument.

extern void isr81();
extern void isr82();
extern void isr83();
Expand Down Expand Up @@ -366,7 +364,7 @@ int IdtInstall() {
IdtSetGate(77, (uint64_t)isr77, kernelCodeSegment, flags);
IdtSetGate(78, (uint64_t)isr78, kernelCodeSegment, flags);
IdtSetGate(79, (uint64_t)isr79, kernelCodeSegment, flags);
// IdtSetGate(80, (uint64_t)isr80, kernelCodeSegment, flags);
IdtSetGate(80, (uint64_t)isr80, kernelCodeSegment, flags);
IdtSetGate(81, (uint64_t)isr81, kernelCodeSegment, flags);
IdtSetGate(82, (uint64_t)isr82, kernelCodeSegment, flags);
IdtSetGate(83, (uint64_t)isr83, kernelCodeSegment, flags);
Expand Down
26 changes: 17 additions & 9 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -411,15 +411,23 @@ The following functions and commands provide interfaces to the process managemen
- The kernel build options and flags are as follow (modify as needed)
```jetbrainsmeson
vf_config_flags = [
'-DVF_CONFIG_ENABLE_XHCI', # Enable xHCI driver
'-DVF_CONFIG_VM_HOST', # Enable support VM host (aka still run with failing features chekcs)
'-DVF_CONFIG_PROCINFO_CREATE_DEFAULT', # Create /Runtime/Processes/<pid> by default
'-DVF_CONFIG_USE_VFSHELL', # Enable VFShell
'-DVF_CONFIG_USE_DYNAMOX', # Enable DynamoX
'-DVF_CONFIG_USE_ASTRA', # Enable Astra
'-DVF_CONFIG_USE_CERBERUS', # Enable Cerberus (memory protection)
'-DVF_CONFIG_PANIC_OVERRIDE', # Ignore many panics (sometimes it gets quite annoying)
'-DVF_CONFIG_ENABLE_XHCI',
'-DVF_CONFIG_ENABLE_VIRTIO',
'-DVF_CONFIG_ENABLE_ISA',
'-DVF_CONFIG_ENABLE_LPT',
'-DVF_CONFIG_ENABLE_PCI',
'-DVF_CONFIG_ENABLE_PS2',
'-DVF_CONFIG_ENABLE_INITRD',
'-DVF_CONFIG_ENABLE_IDE',
'-DVF_CONFIG_ENFORCE_MEMORY_PROTECTION',
'-DVF_CONFIG_VM_HOST',
'-DVF_CONFIG_MLFQ_SCHED',
'-DVF_CONFIG_PROCINFO_CREATE_DEFAULT',
'-DVF_CONFIG_USE_VFSHELL',
'-DVF_CONFIG_USE_DYNAMOX',
'-DVF_CONFIG_USE_ASTRA',
# '-DVF_CONFIG_USE_CERBERUS',
# '-DVF_CONFIG_PANIC_OVERRIDE',
]
```
Quite simple, isn't it?
> assembler-0 @ voidframe-kernel - 11:54 01/09/2025
24 changes: 22 additions & 2 deletions drivers/PCI/PCI.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "Cpu.h"
#include "stdbool.h"
#include "stdint.h"
#include "virtio/Virtio.h"
#include "virtio/VirtioBlk.h"

static uint8_t target_class;
static uint8_t target_subclass;
Expand All @@ -23,7 +25,8 @@ uint32_t PciConfigReadDWord(uint8_t bus, uint8_t slot, uint8_t func, uint8_t off
}

uint8_t PciConfigReadByte(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) {
return PciConfigReadDWord(bus, slot, func, offset) & 0xFF;
uint32_t dword = PciConfigReadDWord(bus, slot, func, offset & 0xFC);
return (dword >> ((offset & 3) * 8)) & 0xFF;
}

void PciConfigWriteDWord(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint32_t data) {
Expand Down Expand Up @@ -90,6 +93,20 @@ static void PciScanBus(PciDeviceCallback callback) {
}
}

static void PciVirtioHandler(PciDevice device) {
if (device.vendor_id == VIRTIO_VENDOR_ID) {
PrintKernel("Found VirtIO Device -> DID: 0x");
PrintKernelHex(device.device_id);
PrintKernel("\n");

// 0x1001 is the transitional block device.
// 0x1042 is the modern block device.
if (device.device_id == 0x1042 || device.device_id == 0x1001) { // VirtIO Block Device
InitializeVirtioBlk(device);
}
}
}

// Your old PciEnumerate function, now a simple wrapper around the scanner
static void PrintPciDeviceInfo(PciDevice device) {
PrintKernel("PCI: B:0x"); PrintKernelHex(device.bus);
Expand All @@ -105,6 +122,9 @@ static void PrintPciDeviceInfo(PciDevice device) {
void PciEnumerate() {
PrintKernel("--- PCI Bus Enumeration ---\n");
PciScanBus(PrintPciDeviceInfo);
#ifdef VF_CONFIG_ENABLE_VIRTIO
PciScanBus(PciVirtioHandler);
#endif
PrintKernel("---------------------------\n");
}

Expand Down Expand Up @@ -236,4 +256,4 @@ uint64_t GetPCIMMIOSize(const PciDevice* pci_dev, uint32_t bar_value) {
}

return size;
}
}
102 changes: 102 additions & 0 deletions drivers/virtio/Virtio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#ifndef VOIDFRAME_VIRTIO_H
#define VOIDFRAME_VIRTIO_H

#include "stdint.h"

// Common VirtIO definitions will go here.
// For example, PCI configuration registers, feature bits, status fields, etc.

#define VIRTIO_VENDOR_ID 0x1AF4

// VirtIO PCI Capability IDs
#define VIRTIO_CAP_COMMON_CFG 1
#define VIRTIO_CAP_NOTIFY_CFG 2
#define VIRTIO_CAP_ISR_CFG 3
#define VIRTIO_CAP_DEVICE_CFG 4
#define VIRTIO_CAP_PCI_CFG 5

// VirtIO PCI Capability Structure
struct VirtioPciCap {
uint8_t cap_vndr; // Generic PCI field: PCI_CAP_ID_VNDR
uint8_t cap_next; // Generic PCI field: next ptr
uint8_t cap_len; // Generic PCI field: capability length
uint8_t cfg_type; // Identifies the structure.
uint8_t bar; // Which BAR to find it.
uint8_t padding[3];
uint32_t offset; // Offset within the BAR.
uint32_t length; // Length of the structure, in bytes.
} __attribute__((packed));

// VirtIO Common Configuration Structure (packed for direct mapping)

struct VirtioPciCommonCfg {
// Device features
uint32_t device_feature_select;
uint32_t device_feature;
// Driver features
uint32_t driver_feature_select;
uint32_t driver_feature;
// MS-X config
uint16_t msix_config;
// Number of queues
uint16_t num_queues;
// Device status
uint8_t device_status;
// Config generation
uint8_t config_generation;
// --- Queue Related ---
uint16_t queue_select;
uint16_t queue_size;
uint16_t queue_msix_vector;
uint16_t queue_enable;
uint16_t queue_notify_off;
uint64_t queue_desc;
uint64_t queue_driver;
uint64_t queue_device;
} __attribute__((packed));

// VirtIO Block Device Feature Bits
#define VIRTIO_BLK_F_RO 5 // Device is read-only

// --- Virtqueue Structures ---

#define VIRTQ_DESC_F_NEXT 1 // Buffer continues via the next field.
#define VIRTQ_DESC_F_WRITE 2 // Buffer is write-only (device-to-driver).

struct VirtqDesc {
uint64_t addr; // Physical address
uint32_t len;
uint16_t flags;
uint16_t next; // Index of next descriptor in chain
} __attribute__((packed));

struct VirtqAvail {
uint16_t flags;
uint16_t idx;
uint16_t ring[]; // Array of descriptor indices
} __attribute__((packed));

struct VirtqUsedElem {
uint32_t id; // Index of the head of the used descriptor chain
uint32_t len; // Total length of the bytes written
} __attribute__((packed));

struct VirtqUsed {
uint16_t flags;
uint16_t idx; // Where the device puts the next used descriptor index
struct VirtqUsedElem ring[];
} __attribute__((packed));

// --- VirtIO Block Device Specifics ---

#define VIRTIO_BLK_T_IN 0 // Read request
#define VIRTIO_BLK_T_OUT 1 // Write request

struct VirtioBlkReq {
uint32_t type;
uint32_t reserved;
uint64_t sector;
} __attribute__((packed));


#endif //VOIDFRAME_VIRTIO_H
Loading