hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
# IOMMU Controller

## Overview

The `IommuController` is the central IOMMU management object. It handles hardware probing, IOVA space management, and DMA buffer mapping through the IOMMU translation tables.

## Probing

`IommuController::probe()` attempts to detect IOMMU hardware:

1. **Intel VT-d** (x86_64): Reads the DMAR (DMA Remapping) ACPI table via `acpi::find_vtd_base()`. If found, the base address points to the VT-d MMIO registers.

2. **ARM SMMU** (AArch64): Reads the DeviceTree via `devicetree::find_smmu_base()`. If found, the base address points to the SMMU global registers.

Returns `None` on platforms without IOMMU support.

## IOVA allocation

IOVA (I/O Virtual Address) space is managed with a simple bump allocator:

```
IOVA_BASE = 0x1_0000_0000  (4 GB)
IOVA_LIMIT = 0x2_0000_0000  (8 GB)
```

`alloc_iova(size, align)`:
1. Aligns `iova_next` up to `align`
2. Checks that `iova_next + size <= IOVA_LIMIT`
3. Atomically advances `iova_next`
4. Returns the allocated IOVA

This allocator does not support freeing — IOVAs are allocated monotonically. This is acceptable for the crate's use case of long-lived DMA regions.

## DMA buffer mapping

`map_dma_buffer(buf: &DmaBuffer, align) -> Option<usize>`:

1. Calls `alloc_iova(buf.len(), align)` to get an IOVA
2. Programs the IOMMU to translate that IOVA to `buf.phys_addr()`
3. Stores the mapping in the `mappings` array
4. Returns the IOVA

Devices use the returned IOVA instead of the physical address for DMA transfers.

## Translation

`translate_iova(iova) -> Option<usize>` searches the mappings array for a matching IOVA and returns the corresponding physical address.

## Limits

| Limit | Value |
|-------|-------|
| Max mappings | 64 |
| IOVA range | 4 GB (4 GB – 8 GB) |
| Max domains | 16 |