/* * Fast POG422 ETH→UART inject burst for EtherGold / fixture bridge. * * Linux + MaxLinear XR USB serial (GPIO7 SLV-OUT, 57600 9-bit wide/preciseflags). * Intended to replace the Python pyserial+tcdrain hot path — not full bridge logic. */ #ifndef POG422_INJECT_H #define POG422_INJECT_H #include #include #include #include "pog422_xr_ioctl.h" #ifndef POG422_INJECT_FORENSICS_WIDE_MAX #define POG422_INJECT_FORENSICS_WIDE_MAX 512u #endif #ifndef POG422_COPPER_PHASE_MAX #define POG422_COPPER_PHASE_MAX 16u #endif #define POG422_COPPER_PHASE_PRE_DE 0u #define POG422_COPPER_PHASE_DE_ON 1u #define POG422_COPPER_PHASE_PRE_DONE 2u #define POG422_COPPER_PHASE_POST_IOCTL 3u #define POG422_COPPER_PHASE_PRE_OFF 4u #define POG422_COPPER_PHASE_POST_OFF 5u #define POG422_INJECT_API 1 #ifdef __cplusplus extern "C" { #endif typedef void (*pog422_inject_poll_fn)(void *ctx); typedef struct { uint32_t pre_tx_us; uint32_t post_hold_us; uint8_t flush_rx_before_tx; uint8_t use_realtime; uint8_t rt_priority; /* 1–99 if use_realtime */ uint8_t require_idle; /* wait for SLV-IN inactive before DE */ uint16_t idle_wait_ms; /* 0 = fail immediately with EBUSY if busy */ uint8_t _pad[2]; pog422_inject_poll_fn poll_fn; /* optional — uartd uses for capture during inject */ void *poll_ctx; } pog422_inject_opts_t; /* On-board copper proxy sample (GPIO_STAT + FIFOs) — scope substitute. */ typedef struct { uint32_t t_us; /* µs from DE assert (0 before DE) */ uint16_t gpio_stat; /* XR GPIO_STAT @ 0x10 */ uint16_t tx_fifo; /* TX_FIFO_COUNT; 0xFFFF = read fail */ uint16_t rx_fifo; /* RX_FIFO_COUNT; 0xFFFF = read fail */ uint8_t phase; /* POG422_COPPER_PHASE_* */ uint8_t gpio7; /* DE / SLV-OUT bit */ uint8_t gpio1; /* SLV-IN bit */ uint8_t _pad; } pog422_copper_sample_t; /* * SLV-IN sample states. The DE-high samples are tri-state: GET_REG is banned * while DE is asserted (EG 3.0.1.15), so if the driver's GPIO1 interrupt cache * is unavailable there is no reading to report. UNKNOWN must not be scored as * "SLV-IN low" — 3.0.1.15 did exactly that and produced two false * slv_hs_misalign per inject. */ #define POG422_SLV_IN_INACTIVE 0u #define POG422_SLV_IN_ACTIVE 1u #define POG422_SLV_IN_UNKNOWN 2u typedef struct { uint64_t tx_ns; /* first GPIO7 TX through tcdrain */ uint64_t total_ns; /* flush through GPIO7 RX */ uint32_t air_us; /* theoretical UART air time at 57600 9N1 */ int32_t err; /* 0 ok, else errno */ uint8_t slv_in_before; /* GPIO1 / SLV-IN (GPIOB1 silk) before burst */ uint8_t slv_in_after_on; /* POG422_SLV_IN_* — GPIO1 event cache, DE high */ uint8_t slv_in_after_body; /* POG422_SLV_IN_* — same sample as after_on */ uint8_t slv_in_after_drain; /* POG422_SLV_IN_* — GPIO1 event cache, DE high */ uint8_t slv_in_after_off; uint8_t gpio1_edges; /* SLV-IN edges seen during burst (from tx0) */ uint8_t copper_n; /* valid copper[] entries */ uint32_t gpio1_first_edge_us; /* us from first UART write; 0 if none */ uint32_t gpio1_last_edge_us; /* Pos3 inject forensics (eth→UART diagnosis) */ uint8_t inject_method; uint8_t wide_is_wire; int16_t driver_errno; uint16_t wide_len; uint32_t rx_fifo_before; uint32_t rx_fifo_after; uint32_t drain_wait_ns; /* kernel wire wait before wide off (driver 1L+) */ /* Driver 1S+ TX path samples (0 if older driver / failed GET_REG → 0xffffffff) */ uint32_t tx_fifo_before; uint32_t tx_fifo_after_bulk; uint32_t tx_fifo_after_drain; uint32_t usb_actual; /* EG 2.2 — DE release forensics */ uint32_t de_hold_us; /* GPIO7 assert → release */ uint8_t tx_empty_reason; /* POG422_TX_EMPTY_REASON_* at DE release */ uint8_t de_release_reason; /* POG422_DE_RELEASE_* */ uint8_t _pad_de[2]; /* EG 3.0.1.57 — stage split (idle wait vs bulk vs DE) */ uint32_t idle_wait_elapsed_us; uint32_t pre_bulk_us; uint32_t bulk_wall_us; uint16_t idle_wait_budget_ms; uint8_t require_idle; uint8_t idle_saw_busy; uint32_t gpio_mode; /* ch2 snapshot at inject start */ uint32_t uart_flow; pog422_copper_sample_t copper[POG422_COPPER_PHASE_MAX]; uint8_t wide_buf[POG422_INJECT_FORENSICS_WIDE_MAX]; } pog422_inject_result_t; #define POG422_INJECT_METHOD_NONE 0u #define POG422_INJECT_METHOD_DRIVER_WIDE 1u /* 2/3 reserved — legacy MARK/SPACE paths removed in uartd 1.0.51 */ #define POG422_DE_RELEASE_NONE 0u #define POG422_DE_RELEASE_TEMT 1u #define POG422_DE_RELEASE_TIMEOUT 2u #define POG422_DE_RELEASE_ERROR 3u #define POG422_DE_RELEASE_DEADLINE 4u /* air_us + post_hold margin (EG 2.2.1.12) */ const char *pog422_inject_version(void); /* Assert / release SLV-OUT (GPIO7). Requires driver 1N+ manual GPIO7 mode on SLV block. */ int pog422_gpio7_tx(int fd); int pog422_gpio7_rx(int fd); /* Enable wide/preciseflags on the tty (idempotent). Required before inject/capture. */ int pog422_port_enable_wide(int fd); /* 1N: MST ch0 RS485 auto + SLV ch2 manual GPIO7 + wide/preciseflags (driver probe primary; fallback here). */ int pog422_hat_init(int fd); /* Read hat UART registers (channel 2 / machine port by default). */ int pog422_hat_read_regs(int fd, uint32_t *gpio_mode, uint32_t *uart_flow); /* Read GPIO_MODE + UART_FLOW for a specific XR21 UART block (0=MST, 2=SLV). */ int pog422_hat_read_regs_ch(int fd, int channel, uint32_t *gpio_mode, uint32_t *uart_flow); /* XR21 RX_FIFO_COUNT @ 0x044 — bytes in chip RX FIFO (not kernel tty buffer). */ int pog422_hat_read_rx_fifo_count(int fd, int channel, uint32_t *count); /* XR21 TX_FIFO_COUNT @ 0x041 — bytes in chip TX FIFO (diag; unreliable as DE gate). */ int pog422_hat_read_tx_fifo_count(int fd, int channel, uint32_t *count); /* Driver RX stats: chars inserted into tty flip buffer (ioctl, driver 1H+). */ int pog422_hat_read_rx_stats(int fd, struct xr_pog422_rx_stats *stats); /* Reset driver RX stats counters (does not clear orphan extra_byte state). */ int pog422_hat_reset_rx_stats(int fd); /* DTtty: driver-side RX ring (driver 1I+). Capture bypasses kernel tty read(). */ int pog422_dttty_enable(int fd, int enable); int pog422_dttty_is_enabled(int fd); int pog422_dttty_avail(int fd, uint32_t *avail); int pog422_dttty_flush(int fd); ssize_t pog422_dttty_read(int fd, void *buf, size_t max_len); /* Wide RX tee: packed [data][flags]; bit0=9th data (9-bit wide), bit 0x10=HS (EG 2.2.1.15+). */ int pog422_wide_rx_enable(int fd, int enable); int pog422_wide_rx_is_enabled(int fd); int pog422_wide_rx_avail(int fd, uint32_t *avail); int pog422_wide_rx_flush(int fd); ssize_t pog422_wide_rx_read(int fd, void *buf, size_t max_len); /* Read SLV-IN (GPIO1): 1 = bus active. Default: driver GPIO1 interrupt cache (POG422 fork). */ int pog422_slv_in_active(int fd, uint8_t *active); /* Live GPIOB1 level via XR_GET_REG (GPIO_STAT). Use for uartd capture gating. */ int pog422_slv_in_live(int fd, uint8_t *active); /* Block until next SLV-IN edge (WAIT_GPIO1). Requires gpio1-interrupt mode. */ int pog422_slv_in_wait_edge(int fd, struct xr_pog422_gpio1_event *ev); /* "gpio1-interrupt" or "register-poll" after hat init / first read. */ const char *pog422_slv_in_mode(void); /* EG 3.0.1.6 runtime timing ring (driver 2.2.2.9+). Returns -EOPNOTSUPP on older. */ int pog422_timing_trace_set(int fd, int enable); int pog422_timing_trace_status(int fd, struct xr_pog422_timing_status *st); int pog422_timing_trace_reset(int fd); int pog422_timing_trace_drain( int fd, struct xr_pog422_timing_event *out, uint32_t max_out, uint32_t *out_n, uint32_t *dropped ); /* Full inject burst: refuse if SLV-IN active (EBUSY); INJECT_TX wide fifo + GPIO7 DE. * Requires preciseflags/wide enabled (pog422_hat_init). Release GPIO7 promptly after burst. */ int pog422_inject_burst( int fd, const uint8_t *frame, size_t len, const pog422_inject_opts_t *opts, pog422_inject_result_t *result ); #ifdef __cplusplus } #endif #endif /* POG422_INJECT_H */