ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
board_periph_eth.c
Go to the documentation of this file.
1
45
46#include <stdint.h>
47#include <stdio.h>
48
49#include "board_console.h"
50#include "board_net.h"
51#include "board_periph_block.h"
53#include "ra8_etha_regs.h"
54#include "ra8_ether_regs.h"
55#include "ra8_rmac_regs.h"
56
68typedef enum : uint64_t {
70 k_eth_win_span = 0xF000UL,
72
104
125
127typedef enum : uint32_t {
130
141typedef struct {
143 uint32_t linkfix_base;
144 uint32_t rx_queue;
146 uint32_t tx_frames;
147 uint32_t rx_frames;
149
152
153/* ------------------------------------------------------------------------- */
154/* Flat-shadow + descriptor byte helpers. */
155/* ------------------------------------------------------------------------- */
156
172RA8_INTERNAL static uint64_t internal_eth_shadow_read(uint64_t off, unsigned size)
173{
174 uint64_t v = 0U;
175 for (unsigned i = 0U; (i < size) && ((off + (uint64_t)i) < (uint64_t)k_eth_win_span); ++i) {
176 v |= (uint64_t)s_eth.win[off + (uint64_t)i] << (k_eth_shift_byte * i);
177 }
178 return v;
179}
180
196RA8_INTERNAL static void internal_eth_shadow_write(uint64_t off, unsigned size, uint64_t value)
197{
198 for (unsigned i = 0U; (i < size) && ((off + (uint64_t)i) < (uint64_t)k_eth_win_span); ++i) {
199 s_eth.win[off + (uint64_t)i] = (uint8_t)(value >> (k_eth_shift_byte * i));
200 }
201}
202
214RA8_INTERNAL static uint32_t internal_eth_shadow_u32(uint64_t off)
215{
216 return (uint32_t)internal_eth_shadow_read(off, k_eth_reg32_bytes);
217}
218
230RA8_INTERNAL static uint32_t internal_eth_bytes_u32(const uint8_t* p)
231{
232 uint32_t v = 0U;
233 for (unsigned i = 0U; i < k_eth_reg32_bytes; ++i) {
234 v |= (uint32_t)p[i] << (k_eth_shift_byte * i);
235 }
236 return v;
237}
238
250RA8_INTERNAL static void internal_eth_desc_read(uc_engine* uc, uint32_t addr, uint8_t* out8)
251{
252 (void)emu_mem_read(uc, (uint64_t)addr, out8, (size_t)k_eth_desc_bytes);
253}
254
266RA8_INTERNAL static uint32_t internal_eth_desc_dt(const uint8_t* d8)
267{
268 return ((uint32_t)d8[k_eth_desc_dt_byte] >> k_eth_desc_dt_shift) & (uint32_t)k_eth_desc_dt_lo;
269}
270
282RA8_INTERNAL static uint32_t internal_eth_desc_ds(const uint8_t* d8)
283{
284 return (uint32_t)d8[0] |
285 (((uint32_t)d8[k_eth_desc_ds_byte1] & (uint32_t)k_eth_desc_ds_hi) << k_eth_shift_byte);
286}
287
299RA8_INTERNAL static uint32_t internal_eth_desc_ptr(const uint8_t* d8)
300{
302}
303
319RA8_INTERNAL static void internal_eth_desc_set_dt(uc_engine* uc, uint32_t addr, uint32_t dt)
320{
321 uint8_t b = 0U;
322 (void)emu_mem_read(uc, (uint64_t)addr + (uint64_t)k_eth_desc_dt_byte, &b, 1U);
323 b = (uint8_t)((b & (uint8_t)k_eth_desc_dt_lo) |
324 (uint8_t)((dt & (uint32_t)k_eth_desc_dt_lo) << k_eth_desc_dt_shift));
325 (void)emu_mem_write(uc, (uint64_t)addr + (uint64_t)k_eth_desc_dt_byte, &b, 1U);
326}
327
343RA8_INTERNAL static void internal_eth_desc_set_ds(uc_engine* uc, uint32_t addr, uint32_t ds)
344{
345 const uint8_t lo = (uint8_t)(ds & (uint32_t)k_eth_byte_mask);
346 uint8_t hi = 0U;
347 (void)emu_mem_read(uc, (uint64_t)addr + (uint64_t)k_eth_desc_ds_byte1, &hi, 1U);
348 hi = (uint8_t)((hi & (uint8_t)k_eth_desc_ds_keep) |
349 (uint8_t)((ds >> k_eth_shift_byte) & (uint32_t)k_eth_desc_ds_hi));
350 (void)emu_mem_write(uc, (uint64_t)addr, &lo, 1U);
351 (void)emu_mem_write(uc, (uint64_t)addr + (uint64_t)k_eth_desc_ds_byte1, &hi, 1U);
352}
353
354/* ------------------------------------------------------------------------- */
355/* Sub-block address predicates (bases + offsets from the register headers). */
356/* ------------------------------------------------------------------------- */
357
370RA8_INTERNAL static bool internal_eth_is_etha_reg(uint64_t addr, uint64_t off)
371{
372 return (addr == (uint64_t)k_ra8_etha0_base_addr + off) ||
373 (addr == (uint64_t)k_ra8_etha1_base_addr + off);
374}
375
388RA8_INTERNAL static bool internal_eth_is_rmac_reg(uint64_t addr, uint64_t off)
389{
390 return (addr == (uint64_t)k_ra8_rmac0_base_addr + off) ||
391 (addr == (uint64_t)k_ra8_rmac1_base_addr + off);
392}
393
407RA8_INTERNAL static bool internal_eth_is_gwdcc(uint64_t addr, uint32_t* queue)
408{
409 const uint64_t base = (uint64_t)k_ra8_gwca0_base_addr + (uint64_t)k_ra8_gwca_off_gwdcc_base;
410 const uint64_t top = base + ((uint64_t)k_eth_phy_reg_count * (uint64_t)k_eth_reg32_bytes);
411 if ((addr < base) || (addr >= top) || (((addr - base) % (uint64_t)k_eth_reg32_bytes) != 0U)) {
412 return false;
413 }
414 *queue = (uint32_t)((addr - base) / (uint64_t)k_eth_reg32_bytes);
415 return true;
416}
417
418/* ------------------------------------------------------------------------- */
419/* PHY (MDIO) model. */
420/* ------------------------------------------------------------------------- */
421
433RA8_INTERNAL static uint16_t internal_eth_phy_read(uint32_t reg)
434{
435 if (reg >= (uint32_t)k_eth_phy_reg_count) {
436 return 0U;
437 }
438 return s_eth.phy[reg];
439}
440
456RA8_INTERNAL static void internal_eth_phy_write(uint32_t reg, uint16_t value)
457{
458 if (reg >= (uint32_t)k_eth_phy_reg_count) {
459 return;
460 }
461 if (reg == (uint32_t)k_eth_phy_reg_bmcr) {
462 value = (uint16_t)(value & (uint16_t)~(k_eth_phy_bmcr_reset | k_eth_phy_bmcr_anrst));
463 }
464 s_eth.phy[reg] = value;
465}
466
487RA8_INTERNAL static void internal_eth_mpsm_exec(uint64_t mpsm_off, uint32_t value)
488{
489 const uint32_t pop =
490 (value >> (uint32_t)k_ra8_rmac_shift_mpsm_pop) & (uint32_t)k_ra8_rmac_mask_mpsm_op;
491 const uint32_t pra =
492 (value >> (uint32_t)k_ra8_rmac_shift_mpsm_pra) & (uint32_t)k_ra8_rmac_mask_mpsm_phy_reg;
493 const uint32_t prd =
494 (value >> (uint32_t)k_ra8_rmac_shift_mpsm_prd) & (uint32_t)k_ra8_rmac_mask_mpsm_data;
495 const bool c45 = (value & (uint32_t)k_eth_mpsm_mff) != 0U;
496 uint32_t out = value & ~(uint32_t)k_ra8_rmac_mpsm_psme; /* PSME self-clears. */
497 if (!c45 && (pop == (uint32_t)k_ra8_rmac_mdio_op_c22_read)) {
498 out = ((uint32_t)internal_eth_phy_read(pra) & (uint32_t)k_ra8_rmac_mask_mpsm_data)
499 << (uint32_t)k_ra8_rmac_shift_mpsm_prd;
500 } else if (!c45 && (pop == (uint32_t)k_ra8_rmac_mdio_op_c22_write)) {
501 internal_eth_phy_write(pra, (uint16_t)prd);
502 }
504}
505
506/* ------------------------------------------------------------------------- */
507/* TX descriptor DMA (GWTRC kick -> peer). */
508/* ------------------------------------------------------------------------- */
509
530RA8_INTERNAL static void internal_eth_tx_kick_queue(uc_engine* uc, uint32_t queue)
531{
532 if (s_eth.linkfix_base == 0U) {
533 return;
534 }
535 uint8_t lf[k_eth_desc_bytes];
536 const uint32_t lf_addr = s_eth.linkfix_base + (queue * (uint32_t)k_eth_desc_bytes);
537 internal_eth_desc_read(uc, lf_addr, lf);
538 const uint32_t chain = internal_eth_desc_ptr(lf);
539 if (chain == 0U) {
540 return;
541 }
542 uint8_t head[k_eth_desc_bytes];
543 internal_eth_desc_read(uc, chain, head);
544 if (internal_eth_desc_dt(head) != (uint32_t)k_ra8_gwdcc_dt_fsingle) {
545 return; /* multi-fragment / empty head is unmodelled here -- honest no-op. */
546 }
547 const uint32_t len = internal_eth_desc_ds(head);
548 const uint32_t buf = internal_eth_desc_ptr(head);
549 if ((len == 0U) || (len > (uint32_t)k_eth_frame_max) || (buf == 0U)) {
550 return;
551 }
552 uint8_t frame[k_eth_frame_max];
553 if (emu_mem_read(uc, (uint64_t)buf, frame, (size_t)len) != UC_ERR_OK) {
554 return;
555 }
556 board_net_on_tx(frame, len);
558 s_eth.tx_frames++;
559 char ln[k_eth_console_cap];
560 (void)snprintf(ln, sizeof(ln), "ETH tx q%u %uB", (unsigned)queue, (unsigned)len);
562}
563
575RA8_INTERNAL static void internal_eth_gwtrc_kick(uc_engine* uc, uint32_t bits, uint32_t base_queue)
576{
577 for (uint32_t i = 0U; i < (uint32_t)k_eth_phy_reg_count; ++i) {
578 if ((bits & (1UL << i)) != 0U) {
579 internal_eth_tx_kick_queue(uc, base_queue + i);
580 }
581 }
582}
583
584/* ------------------------------------------------------------------------- */
585/* RX descriptor DMA (peer -> ring, once per tick). */
586/* ------------------------------------------------------------------------- */
587
605RA8_INTERNAL static bool
606internal_eth_rx_find_slot(uc_engine* uc, uint32_t chain, uint32_t* out_slot)
607{
608 uint32_t cur = chain;
609 for (uint32_t i = 0U; i < (uint32_t)k_eth_ring_walk_max; ++i) {
610 uint8_t d8[k_eth_desc_bytes];
611 internal_eth_desc_read(uc, cur, d8);
612 const uint32_t dt = internal_eth_desc_dt(d8);
613 if (dt == (uint32_t)k_ra8_gwdcc_dt_fempty) {
614 *out_slot = cur;
615 return true;
616 }
617 if ((dt == (uint32_t)k_ra8_gwdcc_dt_link) || (dt == (uint32_t)k_ra8_gwdcc_dt_linkfix)) {
618 const uint32_t next = internal_eth_desc_ptr(d8);
619 if ((next == 0U) || (next == cur)) {
620 return false;
621 }
622 cur = next;
623 } else {
624 cur += (uint32_t)k_eth_desc_bytes;
625 }
626 }
627 return false;
628}
629
649RA8_INTERNAL static void internal_eth_rx_drain_peer(uc_engine* uc, uint32_t chain)
650{
651 for (uint32_t n = 0U; n < (uint32_t)k_eth_rx_inject_max; ++n) {
652 uint32_t slot = 0U;
653 if (!internal_eth_rx_find_slot(uc, chain, &slot)) {
654 return; /* ring full -- backpressure, peer frame stays queued. */
655 }
656 uint8_t d8[k_eth_desc_bytes];
657 internal_eth_desc_read(uc, slot, d8);
658 const uint32_t cap = internal_eth_desc_ds(d8);
659 const uint32_t buf = internal_eth_desc_ptr(d8);
660 if ((buf == 0U) || (cap == 0U)) {
661 return;
662 }
663 const uint32_t want = (cap < (uint32_t)k_eth_frame_max) ? cap : (uint32_t)k_eth_frame_max;
664 uint8_t frame[k_eth_frame_max];
665 const uint32_t got = board_net_poll_rx(frame, want);
666 if (got == 0U) {
667 return; /* peer has nothing more. */
668 }
669 (void)emu_mem_write(uc, (uint64_t)buf, frame, (size_t)got);
670 internal_eth_desc_set_ds(uc, slot, got);
672 s_eth.rx_frames++;
673 }
674}
675
685RA8_INTERNAL static void internal_eth_tick(uc_engine* uc)
686{
687 if ((s_eth.linkfix_base == 0U) || (s_eth.rx_queue == (uint32_t)k_eth_queue_none)) {
688 return;
689 }
690 const uint64_t gwmc_woff =
691 ((uint64_t)k_ra8_gwca0_base_addr - (uint64_t)k_eth_win_base) + (uint64_t)k_ra8_gwca_off_gwmc;
692 const uint32_t opc = internal_eth_shadow_u32(gwmc_woff) & (uint32_t)k_ra8_gwmc_opc_mask;
693 if (opc != (uint32_t)k_ra8_gwmc_opc_operation) {
694 return; /* rings only live in OPERATION mode. */
695 }
696 uint8_t lf[k_eth_desc_bytes];
697 const uint32_t lf_addr = s_eth.linkfix_base + (s_eth.rx_queue * (uint32_t)k_eth_desc_bytes);
698 internal_eth_desc_read(uc, lf_addr, lf);
699 const uint32_t chain = internal_eth_desc_ptr(lf);
700 if (chain != 0U) {
702 }
703}
704
705/* ------------------------------------------------------------------------- */
706/* MMIO dispatch. */
707/* ------------------------------------------------------------------------- */
708
725RA8_INTERNAL static uint64_t internal_eth_read(uc_engine* uc, uint64_t addr, unsigned size)
726{
727 (void)uc;
728 const uint64_t off = addr - (uint64_t)k_eth_win_base;
729 uint32_t queue = 0U;
730 if (internal_eth_is_etha_reg(addr, (uint64_t)k_ra8_etha_off_eams)) {
731 /* EAMS.OPS mirrors the commanded EAMC.OPC (the mode machine converges). */
732 /* HUM Ch 32.3.1.2 "EAMS : Mode Status Register" p 1631 */
733 const uint64_t eamc = off - ((uint64_t)k_ra8_etha_off_eams - (uint64_t)k_ra8_etha_off_eamc);
734 return internal_eth_shadow_u32(eamc) & (uint32_t)k_ra8_etha_mask_ops;
735 }
736 if (addr == (uint64_t)k_ra8_gwca0_base_addr + (uint64_t)k_ra8_gwca_off_gwms) {
737 /* GWMS.OPS mirrors the commanded GWMC.OPC. */
738 /* HUM Ch 34.3.2 "GWMS : Mode Status Register" p 1792 */
739 const uint64_t gwmc = off - ((uint64_t)k_ra8_gwca_off_gwms - (uint64_t)k_ra8_gwca_off_gwmc);
740 return internal_eth_shadow_u32(gwmc) & (uint32_t)k_ra8_gwmc_opc_mask;
741 }
742 if (addr == (uint64_t)k_ra8_gwca0_base_addr + (uint64_t)k_ra8_gwca_off_gwarirm) {
743 /* GWARIRM.ARR (AXI-init done) follows the ARIOG request. */
744 /* HUM Ch 34 "Ethernet CPU Agent (GWCA)" p 1787 */
745 const uint32_t v = internal_eth_shadow_u32(off);
746 return ((v & (uint32_t)k_eth_gwarirm_ariog) != 0U) ? (v | (uint32_t)k_eth_gwarirm_arr) : v;
747 }
748 if (addr == (uint64_t)k_ra8_coma_base_addr + (uint64_t)k_ra8_coma_off_cabpirm) {
749 /* CABPIRM.BPR self-sets after the BPIOG kick (buffer-pool init completes
750 * ~512 clocks later); modelling it lets the board bring-up's non-emulator
751 * BPR poll converge. */
752 /* HUM Ch 31.3.2.7 "CABPIRM" p 1599 */
753 const uint32_t v = internal_eth_shadow_u32(off);
754 return ((v & (uint32_t)k_ra8_coma_cabpirm_bpiog) != 0U) ? (v | (uint32_t)k_ra8_coma_cabpirm_bpr)
755 : v;
756 }
757 if (internal_eth_is_gwdcc(addr, &queue)) {
758 /* GWDCC.BALR self-clears after the reload completes. */
759 /* HUM Ch 34.3 "GWDCCi" p 1811 */
760 return internal_eth_shadow_u32(off) & ~(uint32_t)k_ra8_gwdcc_balr;
761 }
762 if (internal_eth_is_rmac_reg(addr, (uint64_t)k_ra8_rmac_off_mtgfce)) {
763 return s_eth.tx_frames;
764 }
765 if (internal_eth_is_rmac_reg(addr, (uint64_t)k_eth_rmac_off_mrfc) ||
767 return s_eth.rx_frames;
768 }
769 return internal_eth_shadow_read(off, size);
770}
771
788RA8_INTERNAL static void
789internal_eth_write(uc_engine* uc, uint64_t addr, unsigned size, uint64_t value)
790{
791 const uint64_t off = addr - (uint64_t)k_eth_win_base;
792 uint32_t queue = 0U;
793 if (addr == (uint64_t)k_ra8_gwca0_base_addr + (uint64_t)k_ra8_gwca_off_gwtrc0) {
794 internal_eth_shadow_write(off, size, 0U); /* request register clears when consumed. */
795 internal_eth_gwtrc_kick(uc, (uint32_t)value, 0U);
796 return;
797 }
798 if (addr == (uint64_t)k_ra8_gwca0_base_addr + (uint64_t)k_ra8_gwca_off_gwtrc1) {
799 internal_eth_shadow_write(off, size, 0U);
800 internal_eth_gwtrc_kick(uc, (uint32_t)value, (uint32_t)k_eth_phy_reg_count);
801 return;
802 }
803 if (addr == (uint64_t)k_ra8_gwca0_base_addr + (uint64_t)k_ra8_gwca_off_gwdcbac1) {
804 /* Capture the descriptor-chain base so the DMA can walk the rings. */
805 /* HUM Ch 34 "Ethernet CPU Agent (GWCA)" p 1787 */
806 s_eth.linkfix_base = (uint32_t)value;
807 internal_eth_shadow_write(off, size, value);
808 return;
809 }
810 if (internal_eth_is_rmac_reg(addr, (uint64_t)k_ra8_rmac_off_mpsm) &&
811 ((value & (uint32_t)k_ra8_rmac_mpsm_psme) != 0U)) {
812 internal_eth_mpsm_exec(off, (uint32_t)value);
813 return;
814 }
815 internal_eth_shadow_write(off, size, value);
816 if (internal_eth_is_gwdcc(addr, &queue) && ((value & (uint32_t)k_ra8_gwdcc_dqt) == 0U)) {
817 s_eth.rx_queue = queue; /* GWDCC.DQT == 0 marks the reception queue. */
818 }
819}
820
830{
831 s_eth = (eth_state_t){};
832 s_eth.rx_queue = (uint32_t)k_eth_queue_none;
836}
837
847{
848 if ((s_eth.tx_frames == 0U) && (s_eth.rx_frames == 0U)) {
849 return; /* not a networking run -- stay quiet. */
850 }
851 (void)priv_emu_io_errf(" R-Switch : TX %u frame(s) RX %u frame(s) via GWCA/ETHA/RMAC "
852 "regs; link 100M/FD (MDIO)\n",
853 s_eth.tx_frames,
854 s_eth.rx_frames);
855}
856
859 .base = (uint64_t)k_eth_win_base,
860 .span = (uint64_t)k_eth_win_span,
861 .order = (uint32_t)k_eth_block_order,
862 .read = internal_eth_read,
864 .tick = internal_eth_tick,
865 .reset = internal_eth_reset,
866 .report = internal_eth_report,
867 .name = "R-Switch(ETH)",
868};
869
871[[gnu::constructor]] RA8_INTERNAL static void internal_eth_block_register(void)
872{
875}
Multi-channel console log store backing the board view's tabbed console.
void board_console_push(board_console_ch_t ch, const char *line)
Append one completed line to a channel ring and the ALL ring.
@ k_board_console_ch_net
Ethernet / IPv4 / TCP packet summaries.
Virtual network peer for ra8_emulator – talks TCP/IP to the firmware.
uint32_t board_net_poll_rx(uint8_t *buf, uint32_t max)
Fetch the next frame the peer wants the firmware to receive.
Definition board_net.c:733
void board_net_on_tx(const uint8_t *frame, uint32_t len)
Hand one frame the firmware transmitted to the peer (ra8_eth_write).
Definition board_net.c:710
Decentralized peripheral-block registry for the board emulator core.
void board_periph_register_block(const board_periph_block_t *block)
Register a peripheral block's descriptor with the core registry.
static void internal_eth_desc_set_ds(uc_engine *uc, uint32_t addr, uint32_t ds)
Write the 12-bit DS field of the descriptor at address addr.
static void internal_eth_block_register(void)
Register the R-Switch block + seed the PHY file before main runs.
static void internal_eth_shadow_write(uint64_t off, unsigned size, uint64_t value)
Write up to size bytes little-endian into the register shadow.
static eth_state_t s_eth
Singleton R-Switch model state.
static bool internal_eth_is_rmac_reg(uint64_t addr, uint64_t off)
True if addr is the given off in either RMAC port window.
static void internal_eth_mpsm_exec(uint64_t mpsm_off, uint32_t value)
Execute an MPSM (PHY Station Management) transaction on write.
eth_order_t
Per-tick order slot: after the DTC/DMAC transfer engines.
@ k_eth_block_order
Report + tick order (just after DTC=55).
static uint16_t internal_eth_phy_read(uint32_t reg)
Read a modelled Clause-22 PHY register (out-of-range reads 0).
static bool internal_eth_is_etha_reg(uint64_t addr, uint64_t off)
True if addr is the given off in either ETHA port window.
static uint64_t internal_eth_shadow_read(uint64_t off, unsigned size)
Read up to size bytes little-endian from the register shadow.
static uint32_t internal_eth_shadow_u32(uint64_t off)
Read a 32-bit shadow register at window offset off.
static void internal_eth_rx_drain_peer(uc_engine *uc, uint32_t chain)
Drain waiting peer frames into free slots of the RX ring chain.
eth_model_const_t
Descriptor-byte layout, MDIO decode, and ring-walk bounds.
@ k_eth_gwarirm_ariog
GWARIRM.ARIOG AXI-init request.
@ k_eth_desc_ptr_off
PTR[31:0] at descriptor byte 4.
@ k_eth_desc_ds_hi
DS high-nibble mask.
@ k_eth_shift_byte
One-byte shift.
@ k_eth_ring_walk_max
Bound on a descriptor-ring scan.
@ k_eth_mpsm_mff
MPSM.MFF: 1 = Clause-45 frame format.
@ k_eth_byte_mask
Low 8 bits of a value.
@ k_eth_reg32_bytes
One 32-bit register.
@ k_eth_queue_none
"No RX queue configured yet" sentinel.
@ k_eth_rx_inject_max
Max frames injected into the ring / tick.
@ k_eth_desc_ds_keep
Byte-1 high-nibble kept on a DS set.
@ k_eth_desc_bytes
Basic-descriptor / LINKFIX entry size.
@ k_eth_desc_dt_shift
DT occupies bits [7:4] of that byte.
@ k_eth_rmac_off_mrfc
RMAC MRFC (RX total frame count).
@ k_eth_gwarirm_arr
GWARIRM.ARR AXI-init response.
@ k_eth_desc_dt_byte
DT lives in descriptor byte 2.
@ k_eth_desc_ds_byte1
DS[11:8] in low nibble of byte 1.
@ k_eth_desc_dt_lo
Low-nibble mask (bits kept on a DT set).
@ k_eth_frame_max
Marshal buffer cap (>= max 802.3 frame).
@ k_eth_console_cap
Console NET-tab line capacity.
static void internal_eth_desc_read(uc_engine *uc, uint32_t addr, uint8_t *out8)
Read an 8-byte descriptor header from emulated memory addr.
eth_win_geom_t
Absolute window the block owns (the contiguous R-Switch cluster).
@ k_eth_win_base
MFWD base = window base.
@ k_eth_win_span
MFWD..GWCA end.
static void internal_eth_tx_kick_queue(uc_engine *uc, uint32_t queue)
Move the frame queued on GWCA queue queue out to the peer.
static void internal_eth_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
MMIO write handler for the R-Switch window.
static void internal_eth_desc_set_dt(uc_engine *uc, uint32_t addr, uint32_t dt)
Write the DT field of the descriptor at emulated address addr.
static void internal_eth_report(void)
End-of-run R-Switch section: frames moved through the register model.
static uint32_t internal_eth_desc_dt(const uint8_t *d8)
Decode the DT (descriptor type) field of an 8-byte header.
static uint32_t internal_eth_desc_ds(const uint8_t *d8)
Decode the 12-bit DS (descriptor size) field of an 8-byte header.
eth_phy_reg_t
Modelled Clause-22 PHY register indices, seed values, and mode bits.
@ k_eth_phy_bmsr_seed
100/10 abilities + AN done + LINK.
@ k_eth_phy_bmcr_anrst
BMCR.AN_RESTART (self-clearing).
@ k_eth_phy_reg_bmcr
BMCR (basic control).
@ k_eth_phy_anlpar_seed
100F/100H/10F/10H + selector.
@ k_eth_phy_bmcr_reset
BMCR.RESET (self-clearing).
@ k_eth_phy_reg_bmsr
BMSR (basic status).
@ k_eth_phy_bmcr_seed
AN enable + 100 Mb/s + full duplex.
@ k_eth_phy_reg_count
Clause-22 register-space size.
@ k_eth_phy_reg_anlpar
ANLPAR (link-partner ability).
static const board_periph_block_t s_k_eth_block
R-Switch cluster block descriptor.
static uint32_t internal_eth_desc_ptr(const uint8_t *d8)
Decode the 32-bit PTR (buffer / chain address) of an 8-byte header.
static bool internal_eth_is_gwdcc(uint64_t addr, uint32_t *queue)
True if addr is one of GWCA GWDCC[0..31]; sets *queue.
static bool internal_eth_rx_find_slot(uc_engine *uc, uint32_t chain, uint32_t *out_slot)
Walk an RX ring from chain for the next FEMPTY slot.
static void internal_eth_gwtrc_kick(uc_engine *uc, uint32_t bits, uint32_t base_queue)
Fire internal_eth_tx_kick_queue for every set bit of a GWTRC word.
static uint32_t internal_eth_bytes_u32(const uint8_t *p)
Assemble a little-endian 32-bit value from four bytes p[0..3].
static uint64_t internal_eth_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read handler for the R-Switch window.
static void internal_eth_tick(uc_engine *uc)
Per-tick RX pump: stage peer frames once the GWCA is in OPERATION.
static void internal_eth_phy_write(uint32_t reg, uint16_t value)
Write a modelled Clause-22 PHY register (self-clearing BMCR bits).
static void internal_eth_reset(void)
Reset the R-Switch model and re-seed the modelled PHY register file.
Bounded raw-descriptor I/O seam for the RA8 emulator.
emu_io_result_t priv_emu_io_errf(const char *format,...)
Format bounded text and write it to the injected error descriptor.
uc_err emu_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t count)
Read guest memory through the central access seam.
uc_err emu_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t count)
Write guest memory through the central access seam.
-proof
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Ethernet Agent (ETHA) per-port register layout for the RA8D2.
@ k_ra8_etha_off_eams
EAMS: Mode Status.
@ k_ra8_etha_off_eamc
EAMC: Mode Configuration.
@ k_ra8_etha_mask_ops
EAMS.OPS[1:0].
Ethernet controller base addresses for the Renesas RA8D2.
@ k_ra8_gwca_off_gwtrc0
TX Request Cfg, queues 0..31.
@ k_ra8_gwca_off_gwdcc_base
GWDCC[0]; stride 4 bytes.
@ k_ra8_gwca_off_gwmc
Mode Configuration.
@ k_ra8_gwca_off_gwdcbac1
Descriptor chain base addr 1 (lower).
@ k_ra8_gwca_off_gwms
Mode Status.
@ k_ra8_gwca_off_gwarirm
AXI RAM Init Req Monitoring (FSP-confirmed offset).
@ k_ra8_gwca_off_gwtrc1
TX Request Cfg, queues 32..63.
@ k_ra8_coma_off_cabpirm
Buf-pool Init/Reset (BPIOG / BPR).
@ k_ra8_gwdcc_dt_fsingle
FSINGLE – single-fragment frame.
@ k_ra8_gwdcc_dt_link
LINK – chain continuation.
@ k_ra8_gwdcc_dt_fempty
FEMPTY – empty, full frame slot.
@ k_ra8_gwdcc_dt_linkfix
LINKFIX – chain head pointer.
@ k_ra8_rmac1_base_addr
RA8 rmac1 base address.
@ k_ra8_mfwd_base_addr
RA8 mfwd base address.
@ k_ra8_gwca0_base_addr
RA8 gwca0 base address.
@ k_ra8_etha0_base_addr
RA8 etha0 base address.
@ k_ra8_rmac0_base_addr
RA8 rmac0 base address.
@ k_ra8_etha1_base_addr
RA8 etha1 base address.
@ k_ra8_coma_base_addr
RA8 coma base address.
@ k_ra8_gwdcc_balr
RA8 gwdcc balr.
@ k_ra8_gwdcc_dqt
0 = RX queue, 1 = TX queue.
@ k_ra8_coma_cabpirm_bpiog
CABPIRM.BPIOG – buf-pool init kick.
@ k_ra8_coma_cabpirm_bpr
CABPIRM.BPR – buf-pool ready flag.
@ k_ra8_gwmc_opc_mask
RA8 gwmc opc mask.
@ k_ra8_gwmc_opc_operation
OR: Operation request – frames flow.
Ethernet MAC (RMAC) per-port register layout for the RA8D2.
@ k_ra8_rmac_mdio_op_c22_read
10 – C22 read.
@ k_ra8_rmac_mdio_op_c22_write
01 – C22 write.
@ k_ra8_rmac_mask_mpsm_data
MPSM.PRD[31:16].
@ k_ra8_rmac_mask_mpsm_phy_reg
5-bit PHY reg/dev.
@ k_ra8_rmac_mask_mpsm_op
MPSM.POP[14:13].
@ k_ra8_rmac_mpsm_psme
PHY Station Management Enable / busy.
@ k_ra8_rmac_off_mpsm
PHY Station Management.
@ k_ra8_rmac_off_mrgfce
RX good E-frame cnt.
@ k_ra8_rmac_off_mtgfce
TX good E-frame cnt.
@ k_ra8_rmac_shift_mpsm_prd
MPSM.PRD[31:16].
@ k_ra8_rmac_shift_mpsm_pra
MPSM.PRA[12:8].
@ k_ra8_rmac_shift_mpsm_pop
MPSM.POP[14:13].
A modelled peripheral block's self-description for the core registry.
Runtime state of the R-Switch model.
uint32_t tx_frames
Frames moved firmware -> peer (MTGFCE).
uint16_t phy[k_eth_phy_reg_count]
Modelled PHY Clause-22 register file.
uint32_t linkfix_base
GWDCBAC descriptor-chain base address.
uint32_t rx_queue
Configured RX queue index (or NONE).
uint8_t win[k_eth_win_span]
Flat register shadow (config reflect).
uint32_t rx_frames
Frames moved peer -> firmware (MRFC).