ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_eth_gwca_queue.c File Reference

Ethernet CPU Agent driver – per-queue descriptor + ring primitives. More...

#include <stdint.h>
#include <string.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_eth_gwca.h"
#include "ra8_eth_gwca_internal.h"
#include "ra8_ether_regs.h"
#include "ra8_hw_err.h"
#include "ra8_log.h"
Include dependency graph for ra8_eth_gwca_queue.c:

Go to the source code of this file.

Functions

static uint32_t internal_compose_gwdcc (const ra8_eth_gwca_queue_cfg_t *cfg)
 Compose the GWDCC[i] 32-bit value from a queue config.
void priv_ra8_eth_gwca_set_linkfix_entry (ra8_gwca_basic_descriptor_t *entry, const void *chain_head)
 Promote a LINKFIX entry from LEMPTY to LINKFIX with chain-head PTR.
ra8_err_t ra8_eth_gwca_configure_queue (ra8_gwca_basic_descriptor_t *linkfix_table, uint32_t queue_index, const ra8_eth_gwca_queue_cfg_t *cfg)
 Wire a per-queue config into GWDCC[i] + LINKFIX[i].
ra8_err_t ra8_eth_gwca_reload_queue (uint32_t queue_index)
 Reload a descriptor queue: pulse GWDCC[i].BALR, wait for clear.
ra8_err_t ra8_eth_gwca_init_ring (ra8_gwca_basic_descriptor_t *chain, uint32_t ring_depth, uint32_t slot_bytes)
 Initialise a descriptor chain as a ring of FEMPTY slots.
ra8_err_t ra8_eth_gwca_set_descriptor_buffer (ra8_gwca_basic_descriptor_t *desc, void *buffer)
 Set a descriptor's data-buffer pointer.
ra8_err_t ra8_eth_gwca_attach_buffers (ra8_gwca_basic_descriptor_t *chain, uint32_t ring_depth, uint32_t slot_bytes, uint8_t *pool)
 Walk a ring and attach per-slot buffers from a static pool.
ra8_err_t ra8_eth_gwca_kick_tx (uint32_t queue_index)
 Kick a TX queue via GWTRC.
ra8_err_t ra8_eth_gwca_find_slot (const ra8_gwca_basic_descriptor_t *chain, uint32_t ring_depth, ra8_gwdcc_dt_t match_dt, uint32_t start_idx, uint32_t *out_index)
 Find the next slot in a ring matching a target descriptor type.
uint8_t * priv_ra8_eth_gwca_decode_ptr (const ra8_gwca_basic_descriptor_t *desc)
 Decode a descriptor's 40-bit PTR back to a host pointer.
ra8_err_t ra8_eth_gwca_tx_frame (ra8_gwca_basic_descriptor_t *chain, uint32_t ring_depth, uint32_t *tail_idx, const uint8_t *frame, uint32_t frame_len, uint32_t slot_bytes)
 Enqueue one frame on a TX queue's descriptor ring.

Variables

static const char * s_tag = "ETHGWC"

Detailed Description

Ethernet CPU Agent driver – per-queue descriptor + ring primitives.

Tag
[Ring 3 / HAL] {World: NS}

Per-queue and per-descriptor surface of the RA8D2 GWCA block, split out of ra8_eth_gwca.c to stay under the per-file line-count cap: configure_queue, reload_queue, init_ring, set_descriptor_buffer, attach_buffers, kick_tx, find_slot, and tx_frame, plus the address-encoding helpers shared with the default-state TU. Every register access carries a HUM Ch 34 citation.

Since
0.1.0

Definition in file ra8_eth_gwca_queue.c.

Function Documentation

◆ internal_compose_gwdcc()

uint32_t internal_compose_gwdcc ( const ra8_eth_gwca_queue_cfg_t * cfg)
static

Compose the GWDCC[i] 32-bit value from a queue config.

Pure value composition: DQT + DCP[18:16] + SL.

GWDCC.SM[1:0] (Synchronization Mode) is left at 00b – "Normal mode (full descriptor write back)" per HUM Ch 34.3 "GWDCCi" p 9060. SM is NOT a source-MAC field: 01b is "No-write-back mode (no descriptor write back)", which would leave every RX descriptor stuck at FEMPTY because the GWCA never updates it. Bench-confirmed on EK-RA8D2. EDE/ETS stay 0 (basic descriptors), BALR stays 0 (default AXI burst), OSID stays 0 (default stream). No MMIO touched.

Parameters
[in]cfgPer-queue config.
Returns
Packed GWDCC value with DQT, SL, DCP bits set per cfg.
Return values
valuePacked register word.
Precondition
cfg is non-null with priority <= 7.
Caller validated the bounds before invoking.
Postcondition
Returned value reflects the cfg fields; SM stays 00b.
No global state is modified.
Note
Not thread-safe.
Since
0.1.0

Definition at line 60 of file ra8_eth_gwca_queue.c.

References ra8_eth_gwca_queue_cfg_t::extended, ra8_eth_gwca_queue_cfg_t::is_tx, k_ra8_gwdcc_dcp_mask, k_ra8_gwdcc_dcp_shift, k_ra8_gwdcc_dqt, k_ra8_gwdcc_ede, k_ra8_gwdcc_sl, ra8_eth_gwca_queue_cfg_t::priority, and ra8_eth_gwca_queue_cfg_t::stop_on_last.

Referenced by ra8_eth_gwca_configure_queue().

◆ priv_ra8_eth_gwca_decode_ptr()

uint8_t * priv_ra8_eth_gwca_decode_ptr ( const ra8_gwca_basic_descriptor_t * desc)

Decode a descriptor's 40-bit PTR back to a host pointer.

Reverses the ptr_h / ptr_l split applied by ra8_eth_gwca_set_descriptor_buffer. On a 32-bit MCU like the RA8D2 the high byte is always zero, but the function handles the 40-bit format generically. Defined in ra8_eth_gwca_queue.c and shared with ra8_eth_gwca_default.c (the RX drain path decodes the filled slot's buffer pointer through it).

Parameters
[in]descDescriptor whose PTR to decode.
Returns
Host-visible buffer pointer or nullptr if desc is null.
Return values
pointerValid buffer address.
nullptrdesc was null.
Precondition
desc was previously initialised via attach_buffers or set_descriptor_buffer.
Caller treats a nullptr return as an invalid descriptor.
Postcondition
Returned pointer matches the address the descriptor encodes.
No state is modified.
Note
Pure helper; no thread-safety concerns.
Since
0.1.0

< RA8 pointer upper shift.

< RA8 pointer low mask.

Definition at line 421 of file ra8_eth_gwca_queue.c.

References ra8_gwca_basic_descriptor_t::ptr_h, and ra8_gwca_basic_descriptor_t::ptr_l.

Referenced by internal_drain_rx_slot(), and ra8_eth_gwca_tx_frame().

◆ priv_ra8_eth_gwca_set_linkfix_entry()

void priv_ra8_eth_gwca_set_linkfix_entry ( ra8_gwca_basic_descriptor_t * entry,
const void * chain_head )

Promote a LINKFIX entry from LEMPTY to LINKFIX with chain-head PTR.

Splits the 40-bit chain-head address into ptr_h (high 8 bits) + ptr_l (low 32 bits) and writes them with dt = LINKFIX. No MMIO is touched – caller-owned table memory only. Defined in ra8_eth_gwca_queue.c and shared with ra8_eth_gwca_default.c (the re-arm path restores a LINK terminator through it).

Parameters
[in,out]entryLINKFIX entry to rewrite.
[in]chain_headAddress to encode into the 40-bit PTR field (basic or extended descriptor array head).
Returns
void This helper never fails.
Note
Always returns normally.
Precondition
entry is non-null and previously initialised by install_linkfix.
chain_head is the head of the queue's descriptor array.
Postcondition
entry->dt == LINKFIX; ptr_h/ptr_l carry the 40-bit address.
No other LINKFIX entries are modified.
Note
Not thread-safe.
Since
0.1.0

< RA8 linkfix pointer upper shift.

< RA8 linkfix pointer upper mask.

< RA8 linkfix pointer lower mask.

Definition at line 80 of file ra8_eth_gwca_queue.c.

References ra8_gwca_basic_descriptor_t::dt, k_ra8_gwdcc_dt_linkfix, ra8_gwca_basic_descriptor_t::ptr_h, and ra8_gwca_basic_descriptor_t::ptr_l.

Referenced by internal_rearm_queue_if_disabled(), ra8_eth_gwca_configure_queue(), and ra8_eth_gwca_init_ring().

◆ ra8_eth_gwca_attach_buffers()

ra8_err_t ra8_eth_gwca_attach_buffers ( ra8_gwca_basic_descriptor_t * chain,
uint32_t ring_depth,
uint32_t slot_bytes,
uint8_t * pool )
nodiscard

Walk a ring and attach per-slot buffers from a static pool.

See header for the canonical contract. Iterates the FEMPTY slots (chain[0..ring_depth-2]) and sets each PTR to pool + i * slot_bytes via ra8_eth_gwca_set_descriptor_buffer.

Parameters
[in,out]chainRing from init_ring.
[in]ring_depthSame depth as init_ring.
[in]slot_bytesPer-slot buffer size.
[in,out]poolContiguous buffer pool.
Returns
ra8_err_t Error code.
Return values
k_ra8_okEvery FEMPTY slot has its buffer wired.
k_ra8_err_null_ptrchain or pool is null.
k_ra8_err_invalid_argring_depth < 2 or slot_bytes == 0.
Precondition
Caller is in GWMC.OPC = CONFIG.
Pool spans at least (ring_depth - 1) * slot_bytes bytes.
Postcondition
Each chain[i].ptr_h/ptr_l (i in [0, ring_depth-1)) encodes pool + i * slot_bytes.
Chain[ring_depth-1] (the LINK terminator) is unchanged.
Note
Not thread-safe.
Since
0.1.0

Definition at line 307 of file ra8_eth_gwca_queue.c.

References k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_eth_gwca_set_descriptor_buffer(), and s_tag.

Referenced by internal_default_open_rings().

◆ ra8_eth_gwca_configure_queue()

ra8_err_t ra8_eth_gwca_configure_queue ( ra8_gwca_basic_descriptor_t * linkfix_table,
uint32_t queue_index,
const ra8_eth_gwca_queue_cfg_t * cfg )
nodiscard

Wire a per-queue config into GWDCC[i] + LINKFIX[i].

Wire a per-queue config into GWDCC[i] and the matching LINKFIX entry.

See header for the canonical contract. Composes the GWDCC value from cfg's DQT / DCP / SL bits via internal_compose_gwdcc, writes it to GWDCC[queue_index], then promotes the LINKFIX entry to LINKFIX via priv_ra8_eth_gwca_set_linkfix_entry.

Parameters
[in,out]linkfix_tableSame table passed to install_linkfix.
[in]queue_indexQueue 0..31.
[in]cfgPer-queue config (priority, dir, head).
Returns
ra8_err_t Error code.
Return values
k_ra8_okGWDCC[i] + LINKFIX[i] wired.
k_ra8_err_invalid_argNull pointer or queue out of range.
k_ra8_err_null_ptrlinkfix_table, cfg, or cfg->chain_head is null.
Precondition
ra8_eth_gwca_install_linkfix returned ok.
Caller is in GWMC.OPC = CONFIG.
Postcondition
GWDCC[queue_index] reflects cfg's settings.
linkfix_table[queue_index] has dt = LINKFIX with PTR = chain_head.
Note
Not thread-safe.
Since
0.1.0

< DCP field width 3 bits -> max value 7.

Definition at line 120 of file ra8_eth_gwca_queue.c.

References ra8_eth_gwca_queue_cfg_t::chain_head, internal_compose_gwdcc(), k_ra8_err_invalid_arg, k_ra8_ok, ra8_eth_gwca_queue_cfg_t::priority, priv_ra8_eth_gwca_set_linkfix_entry(), RA8_CHECK_NULL_PTR, ra8_gwca_gwdcc(), and s_tag.

Referenced by internal_default_open_queues().

◆ ra8_eth_gwca_find_slot()

ra8_err_t ra8_eth_gwca_find_slot ( const ra8_gwca_basic_descriptor_t * chain,
uint32_t ring_depth,
ra8_gwdcc_dt_t match_dt,
uint32_t start_idx,
uint32_t * out_index )
nodiscard

Find the next slot in a ring matching a target descriptor type.

Find the next FEMPTY slot in a descriptor ring.

See header for the canonical contract. Walks chain[start_idx .. ring_depth-2] looking for an entry where dt == match_dt, wrapping around to chain[0..start_idx-1] if needed. Skips chain[ring_depth-1] (the LINK terminator).

Parameters
[in]chainRing from init_ring.
[in]ring_depthSame depth as init_ring.
[in]match_dtDescriptor type to find (FEMPTY / FSINGLE).
[in]start_idxSlot to start scanning from.
[out]out_indexFirst matching slot.
Returns
ra8_err_t Error code.
Return values
k_ra8_ok*out_index set.
k_ra8_err_no_dataNo slot matched match_dt.
k_ra8_err_invalid_argnull pointer / ring_depth < 2 / start_idx out of range.
Precondition
Caller is in GWMC.OPC = OPERATION.
chain has been initialised via init_ring + attach_buffers.
Postcondition
On success *out_index < ring_depth - 1.
On failure *out_index is unchanged.
Note
Not thread-safe with concurrent chip-side updates.
Since
0.1.0

Definition at line 395 of file ra8_eth_gwca_queue.c.

References k_ra8_err_invalid_arg, k_ra8_err_no_data, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by ra8_eth_gwca_rx_frame(), and ra8_eth_gwca_tx_frame().

◆ ra8_eth_gwca_init_ring()

ra8_err_t ra8_eth_gwca_init_ring ( ra8_gwca_basic_descriptor_t * chain,
uint32_t ring_depth,
uint32_t slot_bytes )
nodiscard

Initialise a descriptor chain as a ring of FEMPTY slots.

See header for the canonical contract. Walks chain[], setting every entry except the last to FEMPTY with ds = slot_bytes, and the last entry to LINK with PTR pointing back at chain[0].

Parameters
[in,out]chainCaller-owned descriptor array.
[in]ring_depthNumber of entries (>= 2).
[in]slot_bytesPer-slot buffer size in bytes.
Returns
ra8_err_t Error code.
Return values
k_ra8_okRing initialised.
k_ra8_err_null_ptrchain is null.
k_ra8_err_invalid_argring_depth < 2 or slot_bytes out of range.
Precondition
Caller is in GWMC.OPC = CONFIG.
chain is 8-byte aligned.
Postcondition
chain[0..ring_depth-2] have dt = FEMPTY, ds = slot_bytes.
chain[ring_depth-1] has dt = LINK with PTR = &chain[0].
Note
Not thread-safe.
Since
0.1.0

< Need at least one FEMPTY + one LINK.

< HUM DS field is 12 bits (max 2048).

< ds_l carries 8 bits.

< ds_h packs the upper 4 bits.

< ds_h field width 4 bits.

Definition at line 212 of file ra8_eth_gwca_queue.c.

References ra8_gwca_basic_descriptor_t::ds_h, ra8_gwca_basic_descriptor_t::ds_l, ra8_gwca_basic_descriptor_t::dt, k_ra8_err_invalid_arg, k_ra8_gwdcc_dt_fempty, k_ra8_gwdcc_dt_link, k_ra8_ok, memset(), priv_ra8_eth_gwca_set_linkfix_entry(), RA8_CHECK_NULL_PTR, and s_tag.

Referenced by internal_default_open_rings().

◆ ra8_eth_gwca_kick_tx()

ra8_err_t ra8_eth_gwca_kick_tx ( uint32_t queue_index)
nodiscard

Kick a TX queue via GWTRC.

Kick a TX queue – request the chip to start transmitting.

See header. Sets the bit for queue_index in GWTRC0 (queues 0..31) or GWTRC1 (queues 32..63). Read-modify-write so other already-pending TX requests on the same 32-queue word are preserved.

Parameters
[in]queue_indexTX queue 0..63.
Returns
ra8_err_t Error code.
Return values
k_ra8_okGWTRCi bit set.
k_ra8_err_invalid_argqueue_index >= 64.
Precondition
Queue's chain has at least one FSINGLE descriptor ready.
GWCA is in GWMC.OPC = OPERATION.
Postcondition
Matching GWTRC bit is 1.
Other already-pending TX requests on the same word are preserved.
Note
Not thread-safe across writes to the same GWTRC word.
Since
0.1.0

< RA8 gwca maximum TX queues.

< RA8 gwca queues per register.

Definition at line 349 of file ra8_eth_gwca_queue.c.

References k_ra8_err_invalid_arg, k_ra8_gwca0_base_addr, k_ra8_gwca_off_gwtrc0, k_ra8_gwca_off_gwtrc1, and k_ra8_ok.

Referenced by ra8_eth_gwca_default_send().

◆ ra8_eth_gwca_reload_queue()

ra8_err_t ra8_eth_gwca_reload_queue ( uint32_t queue_index)
nodiscard

Reload a descriptor queue: pulse GWDCC[i].BALR, wait for clear.

Reload (arm) a descriptor queue by pulsing GWDCC[i].BALR.

HUM Ch 34.3 "GWDCCi" p 1811 defines BALR (Base Address Load Request) as the request that resets the AXI address RAM current_address field for queue i to the chain base ({GWDCBAC} + i x 8). Until BALR runs, the GWCA never scans the descriptor chain – every RX descriptor stays FEMPTY and no frame is delivered. BALR self-clears once the reload completes. FSP r_layer3_switch.c::R_LAYER3_SWITCH_StartDescriptorQueue performs this same pulse, with the GWCA in OPERATION mode.

Parameters
[in]queue_indexGWCA descriptor-queue number 0..63.
Returns
ra8_err_t Error code.
Return values
k_ra8_okBALR pulsed and self-cleared.
k_ra8_err_invalid_argqueue_index has no GWDCC register.
k_ra8_err_hw_timeoutBALR never self-cleared.
Precondition
Caller is in GWMC.OPC = OPERATION.
ra8_eth_gwca_configure_queue ran for queue_index.
Postcondition
The AXI address RAM current_address for queue_index points at the chain base.
GWDCC[queue_index].BALR reads 0.
Note
Not thread-safe.
Since
0.1.0

Definition at line 170 of file ra8_eth_gwca_queue.c.

References k_ra8_err_invalid_arg, k_ra8_eth_gwca_balr_spin, k_ra8_gwdcc_balr, k_ra8_ok, ra8_gwca_gwdcc(), ra8_hw_wait_flag_clear32(), ra8_log_error, and s_tag.

Referenced by internal_rearm_queue_if_disabled(), internal_tx_ext_rearm(), ra8_eth_gwca_default_open(), and ra8_eth_gwca_default_send().

◆ ra8_eth_gwca_set_descriptor_buffer()

ra8_err_t ra8_eth_gwca_set_descriptor_buffer ( ra8_gwca_basic_descriptor_t * desc,
void * buffer )
nodiscard

Set a descriptor's data-buffer pointer.

Set a single descriptor's data-buffer pointer.

Wraps priv_ra8_eth_gwca_set_linkfix_entry-style address split for external callers wiring buffer pointers into FEMPTY slots.

Parameters
[in,out]descDescriptor to update.
[in]bufferBuffer address to encode.
Returns
ra8_err_t Error code.
Return values
k_ra8_okPTR field updated.
k_ra8_err_null_ptrdesc is null.
Precondition
Caller is in GWMC.OPC = CONFIG.
desc was previously zeroed (e.g. by init_ring).
Postcondition
desc->ptr_h / ptr_l encode buffer.
desc->dt / ds / etc unchanged.
Note
Not thread-safe.
Since
0.1.0

< RA8 buffer pointer upper shift.

< RA8 buffer pointer upper mask.

< RA8 buffer pointer lower mask.

Definition at line 267 of file ra8_eth_gwca_queue.c.

References k_ra8_ok, ra8_gwca_basic_descriptor_t::ptr_h, ra8_gwca_basic_descriptor_t::ptr_l, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by ra8_eth_gwca_attach_buffers().

◆ ra8_eth_gwca_tx_frame()

ra8_err_t ra8_eth_gwca_tx_frame ( ra8_gwca_basic_descriptor_t * chain,
uint32_t ring_depth,
uint32_t * tail_idx,
const uint8_t * frame,
uint32_t frame_len,
uint32_t slot_bytes )
nodiscard

Enqueue one frame on a TX queue's descriptor ring.

See header for the canonical contract. Finds the next FEMPTY slot, memcpy's the frame into the slot's pre-attached buffer, sets ds to frame_len, flips dt to FSINGLE, and advances the caller's tail_idx cursor.

Parameters
[in,out]chainTX descriptor ring.
[in]ring_depthRing depth.
[in,out]tail_idxRound-robin write cursor.
[in]frameSource bytes.
[in]frame_lenFrame length.
[in]slot_bytesPer-slot capacity.
Returns
ra8_err_t Error code.
Return values
k_ra8_okFrame queued; FSINGLE marked.
k_ra8_err_no_dataAll slots already FSINGLE (queue full).
k_ra8_err_invalid_argNull pointer or frame_len > slot_bytes.
k_ra8_err_null_ptrchain / tail_idx / frame is null.
Precondition
Caller is in GWMC.OPC = OPERATION.
chain initialised via init_ring + attach_buffers.
Postcondition
On success the chosen slot is FSINGLE with the frame copied.
On success *tail_idx advanced past the chosen slot.
Note
Not thread-safe.
Since
0.1.0

< RA8 ds low byte mask.

< RA8 ds high shift.

< RA8 ds high nibble.

Definition at line 469 of file ra8_eth_gwca_queue.c.

References ra8_gwca_basic_descriptor_t::ds_h, ra8_gwca_basic_descriptor_t::ds_l, ra8_gwca_basic_descriptor_t::dt, k_ra8_err_invalid_arg, k_ra8_gwdcc_dt_fempty, k_ra8_gwdcc_dt_fsingle, k_ra8_ok, memcpy(), priv_ra8_eth_gwca_decode_ptr(), RA8_CHECK_NULL_PTR, ra8_eth_gwca_find_slot(), and s_tag.

Variable Documentation

◆ s_tag

const char* s_tag = "ETHGWC"
static

Definition at line 33 of file ra8_eth_gwca_queue.c.