Drivers - cupidthecat/cupid-os GitHub Wiki

Drivers

cupid-os includes several device drivers that provide hardware abstraction and control. These drivers handle input/output devices, timing, and system control, allowing the kernel to interact with computer hardware.

Overview

The driver architecture follows a modular design where each driver:

  • Provides a clean interface through header files
  • Handles hardware-specific operations
  • Integrates with the interrupt system
  • Offers both low-level and high-level APIs

Keyboard Driver (PS/2)

Overview

The PS/2 keyboard driver provides full keyboard input support with advanced features like modifier key handling, command history, and tab completion.

Features

Input Processing

  • Scancode Translation: Converts PS/2 scancodes to ASCII characters
  • US Keyboard Layout: Full support for US keyboard mapping
  • Extended Keys: Arrow keys, function keys, delete, etc.
  • Interrupt-Driven: Uses IRQ1 for real-time input processing

Modifier Keys

  • Shift: Left and right shift key support
  • Caps Lock: Toggle behavior with visual feedback
  • Control/Alt: Modifier state tracking (for future use)

Advanced Features

  • Circular Buffer: 256-event buffer for reliable input queuing
  • Debouncing: Timestamp-based key press filtering
  • State Tracking: Per-key press/release state management

API

Initialization

void keyboard_init(void);
  • Registers IRQ1 handler
  • Initializes keyboard state
  • Enables keyboard interface

Input Reading

char keyboard_get_char(void);           // Blocking read
bool keyboard_read_event(key_event_t* event); // Non-blocking event read

State Queries

bool keyboard_get_key_state(uint8_t scancode);    // Key press state
bool keyboard_get_caps_lock(void);                // Caps lock status
bool keyboard_get_shift(void);                    // Shift key status

Event Structure

typedef struct {
    uint8_t scancode;      // Raw keyboard scancode
    char character;        // Translated ASCII character
    bool pressed;          // Press (true) or release (false)
    uint32_t timestamp;    // System timestamp
} key_event_t;

Usage Example

#include "keyboard.h"

void example(void) {
    keyboard_init();

    // Read keyboard events
    key_event_t event;
    if (keyboard_read_event(&event)) {
        if (event.pressed && event.character) {
            print("Key pressed: %c\n", event.character);
        }
    }
}

Timer Driver (PIT)

Overview

The Programmable Interval Timer (PIT) driver provides system timing, delays, and CPU frequency measurement using the Intel 8253/8254 PIT chip.

Features

System Timing

  • Tick Counter: High-resolution system tick tracking
  • Uptime Reporting: Millisecond-precision system uptime
  • Frequency Calibration: Automatic CPU frequency detection using TSC

Multi-Channel Support

  • Channel 0: System timer (default 100Hz)
  • Channel 1: Available for custom timing
  • Channel 2: PC speaker control

Precision Timing

  • Sleep Functions: Millisecond and microsecond delays
  • Measurement Tools: Timer-based performance measurement
  • Callback System: Configurable timer event handlers

API

Initialization

void timer_init(uint32_t hz);
  • Configures PIT channel 0
  • Sets timer frequency (19Hz - 1.19MHz)
  • Registers system tick handler

Timing Functions

uint64_t timer_get_ticks(void);         // Current tick count
uint32_t timer_get_frequency(void);     // Timer frequency in Hz
uint32_t timer_get_uptime_ms(void);     // System uptime in milliseconds

Delay Functions

void timer_sleep_ms(uint32_t ms);       // Sleep for milliseconds
void timer_delay_us(uint32_t us);       // Delay for microseconds

Measurement API

void timer_start_measure(timer_measure_t* measure);
uint64_t timer_end_measure(timer_measure_t* measure);

Channel Configuration

bool timer_configure_channel(uint8_t channel, uint32_t frequency,
                           timer_callback_t callback);

Usage Example

#include "timer.h"

void timing_example(void) {
    timer_init(100);  // 100Hz system timer

    // Simple delay
    timer_sleep_ms(1000);  // Sleep 1 second

    // Performance measurement
    timer_measure_t measure;
    timer_start_measure(&measure);

    // Code to measure
    some_function();

    uint64_t elapsed = timer_end_measure(&measure);
    print("Elapsed: %d ms\n", elapsed);

    // Get system uptime
    uint32_t uptime = timer_get_uptime_ms();
    print("Uptime: %d ms\n", uptime);
}

Speaker Driver (PC Speaker)

Overview

The PC speaker driver provides basic audio output through the legacy PC speaker hardware, controlled via PIT channel 2.

Features

Tone Generation

  • Square Wave Output: Basic tone generation via PIT
  • Frequency Control: 1Hz to ~1kHz range
  • Duration Control: Timed tone playback

Simple API

  • Beep Function: Pre-configured system beep
  • Custom Tones: Programmable frequency and duration
  • On/Off Control: Direct speaker control

API

Basic Functions

void beep(void);                    // Standard system beep
void pc_speaker_on(uint32_t freq);  // Start tone at frequency
void pc_speaker_off(void);          // Stop current tone

Usage Example

#include "speaker.h"

void audio_example(void) {
    // Simple beep
    beep();

    // Custom tones
    pc_speaker_on(440);   // A4 note
    timer_sleep_ms(500);  // Play for 500ms
    pc_speaker_off();

    // Rising tone
    for (uint32_t freq = 200; freq < 800; freq += 50) {
        pc_speaker_on(freq);
        timer_sleep_ms(50);
    }
    pc_speaker_off();
}

Driver Architecture

Common Patterns

Initialization Sequence

  1. Hardware Setup: Configure device registers
  2. Interrupt Registration: Register IRQ handlers
  3. State Initialization: Set up driver data structures
  4. Enable Device: Enable interrupts and device operation

Error Handling

  • Timeout Protection: Prevent infinite waits
  • Status Checking: Verify hardware operations
  • Graceful Degradation: Continue operation on non-critical failures

Resource Management

  • Memory Allocation: Use kernel heap for dynamic data
  • Interrupt Safety: Disable interrupts during critical sections
  • State Consistency: Maintain valid driver state

Integration Points

Interrupt System

  • IRQ Registration: irq_install_handler()
  • EOI Handling: pic_send_eoi() in handlers
  • Priority Management: Handle interrupts appropriately

Memory System

  • Heap Allocation: kmalloc()/kfree() for buffers
  • Page Management: Physical memory for DMA (future)
  • Cache Coherency: Ensure data consistency

System Services

  • Timing: Coordinate with timer system
  • Debugging: Use kernel print functions
  • Synchronization: Atomic operations for shared data

Testing and Debugging

Driver Testing

Keyboard Testing

// Test keyboard input
void test_keyboard(void) {
    keyboard_init();
    print("Press keys (ESC to exit):\n");

    while (1) {
        key_event_t event;
        if (keyboard_read_event(&event)) {
            if (event.pressed) {
                if (event.character == 27) break; // ESC
                print("Key: %c (scancode: 0x%x)\n",
                      event.character, event.scancode);
            }
        }
    }
}

Timer Testing

// Test timer accuracy
void test_timer(void) {
    timer_init(1000); // 1kHz

    uint32_t start = timer_get_uptime_ms();
    timer_sleep_ms(1000); // Sleep 1 second
    uint32_t end = timer_get_uptime_ms();

    uint32_t actual_delay = end - start;
    print("Requested: 1000ms, Actual: %dms\n", actual_delay);
}

Speaker Testing

// Test speaker functionality
void test_speaker(void) {
    print("Testing speaker...\n");

    // Frequency sweep
    for (uint32_t freq = 100; freq <= 1000; freq += 100) {
        pc_speaker_on(freq);
        timer_sleep_ms(100);
        pc_speaker_off();
        timer_sleep_ms(50);
    }

    print("Speaker test complete\n");
}

Common Issues

Keyboard Problems

  • No Input: Check IRQ1 registration and PIC setup
  • Wrong Characters: Verify scancode mapping table
  • Buffer Overflows: Monitor buffer usage in circular buffer

Timer Issues

  • Inaccurate Timing: Check PIT frequency calculation
  • Interrupt Storms: Verify EOI handling in timer ISR
  • TSC Calibration: Ensure CPU frequency detection works

Speaker Problems

  • No Sound: Check PIT channel 2 configuration
  • Wrong Frequency: Verify divisor calculations
  • Distortion: Ensure proper square wave generation

Debug Techniques

Status Monitoring

// Print driver status
void debug_drivers(void) {
    print("Keyboard buffer count: %d\n",
          keyboard_state.buffer.count);
    print("Timer ticks: %d\n", timer_get_ticks());
    print("System uptime: %d ms\n", timer_get_uptime_ms());
}

Hardware Inspection

// Check hardware registers
void inspect_hardware(void) {
    uint8_t keyboard_status = inb(KEYBOARD_STATUS_PORT);
    print("Keyboard status: 0x%x\n", keyboard_status);

    uint8_t timer_status = inb(PIT_COMMAND);
    print("Timer status: 0x%x\n", timer_status);
}

Future Enhancements

Planned Improvements

Keyboard Driver

  • International Layouts: Support for non-US keyboard layouts
  • USB Keyboard: USB HID keyboard support
  • Advanced Features: Key repeat, macro support

Timer Driver

  • High-Resolution Timers: TSC-based high-precision timing
  • Timer Queues: Scheduled timer events
  • Real-Time Clock: RTC integration for wall time

Audio System

  • Advanced Audio: Multi-channel audio support
  • Sound Blaster: ISA sound card support
  • MIDI Support: Musical instrument interface

New Drivers

  • Serial Port: RS-232 communication
  • Hard Disk: IDE disk driver
  • Network Card: Ethernet support
  • Graphics: VGA graphics modes

Driver Framework

  • Common Interface: Standardized driver API
  • Hotplug Support: Dynamic device detection
  • Power Management: Device power state control
  • Performance Monitoring: Driver statistics and profiling

References

  • PS/2 Specification: Keyboard and mouse protocol details
  • Intel 8253/8254 Datasheet: PIT hardware specifications
  • OSDev Wiki: Driver implementation guides and examples
  • Linux Kernel: Reference driver implementations

For more information about system components: