Skip to main content

HAL

The Hardware Abstraction Layer is an important part of Ethereal's hardware API.

Interrupts

Handlers

Registering interrupts can be done with the HAL through the following function:

int hal_registerInterruptHandler(uintptr_t int_number, hal_interrupt_handler_t handler, void *context);
  • int_number: The target interrupt number to use
  • handler: The handler to use
  • context: The context to pass to the handler

The interrupt handler is declared as:

typedef int (*hal_interrupt_handler_t)(void *context);
danger

Returning nonzero from an interrupt handler will cause IRQ_HANDLER_FAILED to be thrown.

You can unregister interrupt handlers using the following function:

void hal_unregisterInterruptHandler(uintptr_t int_no);

Putting it all together

Let's combine our knowledge of the PCI and HAL API to register an interrupt handler for our fake device.


/**
* @brief PCI example
*/

#include <kernel/loader/driver.h>
#include <kernel/debug.h>
#include <kernel/drivers/pci.h>
#include <kernel/mem/mem.h>
#include <kernel/hal.h>
#include <string.h>

int handler(void *context) {
dprintf(DEBUG, "IRQ handler!\n");
return 0;
}


int driver_scanCallback(pci_device_t *device, void *context) {
dprintf(INFO, "Found matching device at bus %d slot %d func %d\n", device->bus, device->slot, device->function);

// Get BAR0
pci_bar_t *b = pci_getBAR(device->bus, device->slot, device->function, 0);
assert(b);

// Map it as MMIO
uintptr_t m = mem_mapMMIO(b->address, b->size);
dprintf(DEBUG, "Mapped memory to 0x%016llX\n", m);
memset(m, 0, b->size);

mem_unmapMMIO(m, b->size);

// Enable an MSI interrupt
uint8_t irq = pci_enableMSI(device->bus, device->slot, device->function);
if (irq == 0xFF) return 1; // MSI not supported or error

// Register the handler
hal_registerInterruptHandler(irq, handler, (void*)0xDEADBEEF);

return 0;
}

int driver_init(int argc, char *argv[]) {
dprintf(DEBUG, "Scanning for example PCI device with VID 1234 and PID 1111...\n");

pci_id_mapping_t id_list[] = {
{ .vid = 0x1234, .pid = { 0x1111, PCI_NONE }},
PCI_ID_MAPPING_END
};

pci_scan_parameters_t params = {
.class_code = 0, // No class code
.subclass_code = 0, // No class code
.id_list = id_list
};

return pci_scan(driver_scanCallback, &params, NULL);
}

int driver_deinit() { return DRIVER_STATUS_SUCCESS; }

struct driver_metadata driver_metadata = {
.name = "Example Driver",
.author = "Your Name Here",
.init = driver_init,
.deinit = driver_deinit
};