lona.io¶
Device I/O intrinsics for driver development.
MMIO Operations¶
Memory-mapped I/O for device register access.
mmio-map¶
Map physical device memory.
Cache attributes: :device, :uncached, :write-combine, :cached
mmio-unmap¶
Unmap region.
Read Operations¶
(mmio-read8 vaddr) ; → u8
(mmio-read16 vaddr) ; → u16
(mmio-read32 vaddr) ; → u32
(mmio-read64 vaddr) ; → u64
;; @todo
;; MMIO reads return fixed-width integers
(def base (mmio-map (paddr 0x3000u64) 0x1000 :device))
(integer? (mmio-read8 base)) ; => true
(integer? (mmio-read16 base)) ; => true
(integer? (mmio-read32 base)) ; => true
(integer? (mmio-read64 base)) ; => true
Write Operations¶
(mmio-write8! vaddr val) ; → :ok
(mmio-write16! vaddr val) ; → :ok
(mmio-write32! vaddr val) ; → :ok
(mmio-write64! vaddr val) ; → :ok
;; @todo
(def base (mmio-map (paddr 0x4000u64) 0x1000 :device))
(mmio-write8! base 0xFFu8) ; => :ok
(mmio-write16! base 0x1234u16) ; => :ok
(mmio-write32! base 0x12345678u32) ; => :ok
(mmio-write64! base 0x123456789ABCDEFu64) ; => :ok
Offset Helpers¶
;; @todo
(def base (mmio-map (paddr 0x5000u64) 0x1000 :device))
(integer? (mmio-read32-off base 4)) ; => true
(mmio-write32-off! base 4 0x12345678u32) ; => :ok
Memory Barriers¶
memory-barrier!¶
Full memory barrier.
read-barrier!¶
Load-load barrier.
write-barrier!¶
Store-store barrier.
device-barrier!¶
Device synchronization barrier.
instruction-barrier!¶
Instruction synchronization barrier.
Port I/O (x86)¶
Legacy I/O port access.
port-request¶
Request port range capability.
Read Operations¶
;; @todo @x86_64
(def cap (port-request 0x3F8 8))
(integer? (port-in8 cap 0)) ; => true
(integer? (port-in16 cap 0)) ; => true
(integer? (port-in32 cap 0)) ; => true
Write Operations¶
(port-out8! cap offset val) ; → :ok
(port-out16! cap offset val) ; → :ok
(port-out32! cap offset val) ; → :ok
;; @todo @x86_64
(def cap (port-request 0x3F8 8))
(port-out8! cap 0 65) ; => :ok
(port-out16! cap 0 1000) ; => :ok
(port-out32! cap 0 100000) ; => :ok
DMA Operations¶
dma-alloc¶
Allocate DMA buffer.
Attrs: :dma/coherent, :dma/uncached, :dma/write-combine, :dma/cached
dma-free!¶
Free DMA buffer.
Buffer Access¶
;; @todo
(def buf (dma-alloc 4096 :dma/coherent))
(vaddr? (dma-vaddr buf)) ; => true
(paddr? (dma-paddr buf)) ; => true
(dma-size buf) ; => 4096
Cache Synchronization¶
(dma-sync-for-device! buf offset size) ; Before device reads
(dma-sync-for-cpu! buf offset size) ; After device writes
;; @todo
(def buf (dma-alloc 4096 :dma/coherent))
(dma-sync-for-device! buf 0 64) ; => :ok
(dma-sync-for-cpu! buf 0 64) ; => :ok
Cache Operations¶
cache-clean!¶
Write dirty lines to RAM.
cache-invalidate!¶
Discard cache lines.
cache-clean-invalidate!¶
Clean then invalidate.
;; @todo
(def buf (dma-alloc 4096 :dma/cached))
(cache-clean-invalidate! (dma-vaddr buf) 4096) ; => :ok
cache-unify-instruction!¶
Sync instruction cache with data cache.
;; @todo
(def buf (dma-alloc 4096 :dma/cached))
(cache-unify-instruction! (dma-vaddr buf) 4096) ; => :ok
IRQ Operations¶
irq-register!¶
Register interrupt handler.
irq-unregister!¶
Remove handler.
irq-ack!¶
Acknowledge interrupt.
irq-wait¶
Wait for interrupt. Equivalent to lona.kernel/wait!.
;; @todo
(def n (make-notification))
(def h (irq-register! 33 n))
;; irq-wait blocks until interrupt fires
;; Signal notification to unblock
(signal! n)
(integer? (irq-wait n)) ; => true
(irq-unregister! h)
irq-poll¶
Poll for interrupt. Equivalent to lona.kernel/poll!.
MSI/MSI-X¶
Register MSI/MSI-X interrupt vectors for PCI devices.
(msi-register! pci-dev vector notification) ; → irq-handler
(msix-register! pci-dev vector notification) ; → irq-handler
Note: pci-dev is an opaque handle representing a PCI device. The full PCI
discovery and configuration API (enumeration, BAR access, etc.) will be specified
when implementing device drivers.
;; @todo
;; MSI registration requires PCI device handle
(def n (make-notification))
;; Would use actual PCI device in real code:
;; (def h (msi-register! pci-dev 0 n))
;; (irq-handler-cap? h) ; => true
Physical Memory¶
vaddr->paddr¶
Virtual to physical translation.
paddr->vaddr¶
Physical to virtual (if mapped).
;; @todo
;; Unmapped address returns nil
(paddr->vaddr (paddr 0xDEADBEEFu64)) ; => nil
;; Mapped address returns vaddr
(def buf (dma-alloc 4096 :dma/coherent))
(vaddr? (paddr->vaddr (dma-paddr buf))) ; => true
phys-alloc¶
Allocate contiguous physical memory.
;; @todo
(def r (phys-alloc 4096 4096))
(map? r) ; => true
(contains? r :vaddr) ; => true
(contains? r :paddr) ; => true
(contains? r :size) ; => true
(contains? r :frames) ; => true
(vaddr? (:vaddr r)) ; => true
(paddr? (:paddr r)) ; => true
(= (:size r) 4096) ; => true
phys-free!¶
Release physical memory.
Ring Buffers¶
Lock-free ring buffers for driver communication.
Concurrency model: Ring buffers are SPSC (Single Producer, Single Consumer).
One realm produces, one realm consumes. ring-share grants either :produce or
:consume access, not both.
ring-create¶
Create ring buffer.
ring-share¶
Share with realm.
;; @todo
(def r (ring-create 64 256))
(def child (realm-create %{:name 'ring-consumer}))
(ring-share r child :consume) ; => :ok
(realm-terminate child)
(ring-destroy! r)
ring-destroy!¶
Destroy ring.
Producer Operations¶
Consumer Operations¶
;; @todo
(def r (ring-create 4 8))
(ring-produce! r #bytes[1 2 3 4])
(binary? (ring-consume r)) ; => true
Batch operations:
;; @todo
(def r (ring-create 8 8))
(ring-produce-batch! r {#bytes[1] #bytes[2] #bytes[3]}) ; => 3
(ring-available r) ; => 3
(def entries (ring-consume-batch r 10))
(vector? entries) ; => true
(count entries) ; => 3
(ring-destroy! r)
Statistics¶
(ring-available ring) ; → count
(ring-free-space ring) ; → count
(ring-full? ring) ; → boolean
(ring-empty? ring) ; → boolean
;; @todo
(def r (ring-create 4 8))
(ring-empty? r) ; => true
(ring-full? r) ; => false
(ring-available r) ; => 0
(ring-free-space r) ; => 4
;; @todo
(def r (ring-create 4 8))
(ring-produce! r #bytes[1])
(ring-produce! r #bytes[2])
(ring-empty? r) ; => false
(ring-available r) ; => 2
(ring-free-space r) ; => 2
Device Tree¶
Flattened Device Tree access. FDT access is capability-controlled via fdt-cap?.
Typically only the root realm and explicitly authorized driver realms hold this
capability.
fdt-find-node¶
Find node by path.
fdt-get-property¶
Get property value.
fdt-get-reg¶
Get register address and size.
;; @todo
;; fdt-get-reg returns nil for nodes without reg property
(def root (fdt-find-node "/"))
(or (nil? (fdt-get-reg root))
(map? (fdt-get-reg root))) ; => true
fdt-get-interrupts¶
Get interrupt numbers.
;; @todo
;; fdt-get-interrupts returns vector or nil
(def root (fdt-find-node "/"))
(or (nil? (fdt-get-interrupts root))
(vector? (fdt-get-interrupts root))) ; => true
fdt-compatible?¶
Check device compatibility.
;; @todo
(def root (fdt-find-node "/"))
(boolean? (fdt-compatible? root "some-compat-string")) ; => true
Appendix: Expected Derived Functions¶
All functions in this namespace are intrinsics. No derived functions expected.