import ../../core/ion/memory import ../../core/ring # Fixed address for the SysTable (provided by Carrier) const SYS_TABLE_ADDR = 0x801FFF00'u64 type SysTable = object s_yield*: pointer s_alloc*: proc(): IonPacket {.cdecl.} s_free*: proc(pkt: IonPacket) {.cdecl.} s_tx*: proc(pkt: IonPacket): bool {.cdecl.} s_rx*: 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*() = 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 = ## Allocate a slab for the application to write into. when defined(is_membrane): let sys = cast[ptr SysTable](SYS_TABLE_ADDR) let pkt = sys.s_alloc() if pkt.data == nil: return false out_pkt[] = pkt return true else: var pkt = ion_alloc() if pkt.data == nil: return false out_pkt[] = pkt return true proc ion_user_free*(pkt: IonPacket) = ## Return a slab to the pool. when defined(is_membrane): let sys = cast[ptr SysTable](SYS_TABLE_ADDR) sys.s_free(pkt) else: ion_free(pkt) proc ion_user_tx*(pkt: IonPacket): bool = ## Push a packet to the Transmission Ring. when defined(is_membrane): let sys = cast[ptr SysTable](SYS_TABLE_ADDR) return sys.s_tx(pkt) else: return ion_tx_push(pkt) proc ion_user_rx*(out_pkt: ptr IonPacket): bool = ## 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