rumpk/libs/membrane/ion_client.nim

63 lines
1.8 KiB
Nim

import ../../core/ion/memory
import ../../core/ring
# Fixed address for the SysTable (provided by Carrier)
const SYS_TABLE_ADDR = 0x83000000'u64
type
SysTable = object
magic*: uint32
s_rx*: pointer
s_tx*: pointer
s_event*: pointer
# The Ring where the Kernel (Switch) pushes packets for this app
var membrane_rx_ring_static: RingBuffer[IonPacket, 256]
var membrane_rx_ring_ptr*: ptr RingBuffer[IonPacket, 256]
proc ion_user_init*() {.exportc.} =
when defined(is_membrane):
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
membrane_rx_ring_ptr = cast[ptr RingBuffer[IonPacket, 256]](sys.s_rx)
else:
membrane_rx_ring_static.init()
membrane_rx_ring_ptr = addr membrane_rx_ring_static
proc ion_user_alloc*(out_pkt: ptr IonPacket): bool {.exportc.} =
## Allocate a slab for the application to write into.
when defined(is_membrane):
# TODO: Implement allocation via Command Ring or shared pool
return false
else:
var pkt = ion_alloc()
if pkt.data == nil:
return false
out_pkt[] = pkt
return true
proc ion_user_free*(pkt: IonPacket) {.exportc.} =
## Return a slab to the pool.
when defined(is_membrane):
# TODO: Implement free via Command Ring
discard
else:
ion_free(pkt)
proc ion_user_tx*(pkt: IonPacket): bool {.exportc.} =
## Push a packet to the Transmission Ring.
when defined(is_membrane):
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
let tx = cast[ptr RingBuffer[IonPacket, 256]](sys.s_tx)
return tx[].push(pkt)
else:
return ion_tx_push(pkt)
proc ion_user_rx*(out_pkt: ptr IonPacket): bool {.exportc.} =
## Pop a packet from the Application's RX Ring.
if membrane_rx_ring_ptr == nil: return false
if membrane_rx_ring_ptr[].isEmpty: return false
let (ok, pkt) = membrane_rx_ring_ptr[].pop()
if not ok: return false
out_pkt[] = pkt
return true