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
};