universalisos/kernel/drivers/gpio.h
Fábio Coutada 9540b0528c feat(universalisos): PikeOS-style Phase B/C device drivers + Phase D microkernel
Phase B (Core Device Support) — all drivers verified in QEMU:
- Network: virtio-net cleanup, RTL8139, E1000, clause-22 MDIO PHY management,
  CAN bus, industrial protocols (Modbus/Profibus/EtherCAT), controller probe+dispatch
- Block storage: RAM disk backend (write->read->verify PASSED), virtio-blk transport,
  backend dispatch, real MBR+GPT partition parsers, SD/eMMC command framework
- GPIO: PL061 (verified), I2C: DesignWare (verified), SPI: PL022 (verified)

Phase C (Advanced Features):
- PCI: FULL PikeOS ARMv7 replica — transport-agnostic uos_pci_ops, config-address
  encoding, BAR sizing, capability walk, enumeration+bridge recursion, MSI/MSI-X
- USB: PikeOS-style layered stack — usb.h contract, usb_core.cpp (enumeration
  state machine), usb_ehci.cpp (EHCI transport)
- Display: FULL 1:1 PikeOS fbcon replica + copied font_8x16

Build foundation fixes:
- Freestanding aeabi_runtime.cpp (__aeabi_uidiv/__aeabi_uldivmod)
- PikeOS-style flat 4GB MMU section map + proper enable (unblocked device MMIO)
- guest.h MAX_GUEST_IMAGE_SIZE 256MB->16MB (BSS was 259MB)
- C/C++ linkage fixes, duplicate-virtio_net_init, MMIO access-size handling

Phase D (PikeOS ARMv7 Microkernel Port):
- D-1: Per-VM address spaces — cloned pgdirs, ASID-tagged TLB, 4K page walker,
  isolation PASSED (two guests, same VA->different PAs), guest fault recovery
- D-2: IRQ dispatch backbone — 1024-slot dispatch table, real GICv2 hardware
  (GICD_CTLR/GICC_CTLR/GICC_PMR/GICC_IAR/GICC_EOIR), arm_irq_handler wired
- D-3: Time subsystem — CNTVCT ns-since-boot, CNTP periodic ticker via D-2
- D-4: KDEV framework — linker-section driver registration, uos_kdev_init_all,
  name lookup
- D-5: VFP/NEON — lazy enable (undef trap->CPACR+FPEXC.EN), FPEXC=0x40000000
- D-6: SMP — per-CPU state, MPIDR, IPI/SGI framework (reschedule+TLB flush)

All uos_ naming (PikeOS p4_ convention adapted). Compiles -Werror freestanding C++17.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-09 09:10:53 +01:00

127 lines
3.3 KiB
C

/*
* Universalisos GPIO Driver
* Phase B Priority 6: Platform I/O - General Purpose I/O
*
* ARM PrimeCell PL061 GPIO controller (8-bit ports), as emulated by QEMU virt.
* Provides pin configuration, read/write, edge/level interrupts, and
* virtualization hooks for guest VM passthrough.
*
* MISRA C++ compliant, freestanding, no dynamic allocation.
*
* Author: PortugalFuturista Hypervisor Development Team
*/
#ifndef UNIVERSALISOS_DRIVERS_GPIO_H
#define UNIVERSALISOS_DRIVERS_GPIO_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* GPIO pin direction
*/
typedef enum {
GPIO_DIR_INPUT = 0,
GPIO_DIR_OUTPUT
} gpio_direction_t;
/**
* GPIO interrupt trigger mode
*/
typedef enum {
GPIO_INT_NONE = 0, /* Disable interrupts */
GPIO_INT_LEVEL_LOW, /* Level-sensitive, active low */
GPIO_INT_LEVEL_HIGH, /* Level-sensitive, active high */
GPIO_INT_EDGE_FALLING, /* Falling edge */
GPIO_INT_EDGE_RISING, /* Rising edge */
GPIO_INT_EDGE_BOTH /* Both edges */
} gpio_int_mode_t;
/**
* Maximum number of PL061 ports (one PL061 = 8 pins; virt exposes several)
*/
#define MAX_GPIO_PORTS 8
#define GPIO_PINS_PER_PORT 8
/**
* PL061 masked-data access: bits are accessed via address bits [9:2].
* Offset 0x3FC addresses all 8 bits at once.
*/
#define GPIO_DATA_ALL 0x3FCU
/**
* Initialize a PL061 GPIO port.
* @param port_id Logical port index (0..MAX_GPIO_PORTS-1)
* @param base_address MMIO base of the PL061 controller
* @return 0 on success, negative on error
*/
int gpio_init(uint8_t port_id, uint32_t base_address);
/**
* Configure pin direction(s).
* @param port_id Port index
* @param pin_mask Bitmask of pins to configure (1 = affected)
* @param direction Input or output
* @return 0 on success, negative on error
*/
int gpio_set_direction(uint8_t port_id, uint8_t pin_mask, gpio_direction_t direction);
/**
* Write to output pin(s). Only pins set in pin_mask are driven.
*/
int gpio_write(uint8_t port_id, uint8_t pin_mask, uint8_t value);
/**
* Read the current level of all 8 pins.
*/
int gpio_read(uint8_t port_id, uint8_t* value);
/**
* Configure interrupt trigger mode for a single pin.
*/
int gpio_config_interrupt(uint8_t port_id, uint8_t pin, gpio_int_mode_t mode);
/**
* Enable/disable the interrupt for a pin mask.
*/
int gpio_enable_interrupt(uint8_t port_id, uint8_t pin_mask, bool enable);
/**
* Acknowledge (clear) pending interrupts for a pin mask.
*/
int gpio_acknowledge_interrupt(uint8_t port_id, uint8_t pin_mask);
/**
* Read masked interrupt status (only enabled, pending interrupts).
*/
uint8_t gpio_get_interrupt_status(uint8_t port_id);
/**
* GPIO interrupt handler (called by the GIC dispatch for the port's IRQ).
*/
void gpio_interrupt_handler(uint8_t port_id);
/**
* Create a virtual GPIO port for a guest VM (passthrough subset).
* @param vm_id Owning VM
* @param physical_port_id Backing physical port
* @param allowed_mask Bitmask of pins the VM may access
* @return Virtual port id (>=0) on success, negative on error
*/
int gpio_create_virtual(uint32_t vm_id, uint8_t physical_port_id, uint8_t allowed_mask);
/**
* Driver init / self-test demonstration.
*/
void gpio_driver_init(void);
void gpio_driver_demo(void);
#ifdef __cplusplus
}
#endif
#endif /* UNIVERSALISOS_DRIVERS_GPIO_H */