/*
 * harness_dcn10.c — unit-level proof of the hw_translate_dcn10 defects
 * (DragonFlyBSD pass-2 audit, file:
 *   sys/dev/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c)
 *
 * offset_to_id() and id_to_offset() below are VERBATIM copies from
 * hw_translate_dcn10.c lines 61-201 and 203-388 with exactly one substitution:
 * ASSERT_CRITICAL(false) maps to a printf marker.
 * Register constants are the real DCN10/Raven values:
 *   REG(x) = DCE_BASE__INST0_SEG2 (0x34C0) + mm x   (vega10_ip_offset.h:277,
 *   dcn_1_0_offset.h: BASE_IDX 2 for all DC_GPIO regs).
 * Enums are the real gpio_types.h values.
 *
 * Tests:
 *   T1 (DF-4946): all eight DDC-family offsets return true WITHOUT writing *id;
 *                 en=6 (DDC_VGA) / en=7 (I2C_PAD) index hpd_regs[6] OOB when the
 *                 garbage id decodes to GPIO_ID_HPD in dal_gpio_create_irq.
 *   T2 (negative): no GPIOPAD cross-domain case (DF-4942 producer absent);
 *                 "Not implemented" offsets return false.
 *   T3 (DF-4947): id_to_offset(DDC_DATA, I2C_PAD) hands out the DDC6DATA mask
 *                 0x100 for DC_GPIO_I2CPAD_A whose SDA field is bit 1 (0x2) —
 *                 per ddc_regs.h the factory table uses SDA_A_MASK for that pin.
 *   T4 (negative): the HPD branch is well-formed (id written, en 0..5).
 */
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#define ASSERT_CRITICAL(x) printf("    [ASSERT_CRITICAL hit]\n")

enum gpio_id {
	GPIO_ID_UNKNOWN = (-1),
	GPIO_ID_DDC_DATA, GPIO_ID_DDC_CLOCK, GPIO_ID_GENERIC, GPIO_ID_HPD,
	GPIO_ID_GPIO_PAD, GPIO_ID_VIP_PAD, GPIO_ID_SYNC, GPIO_ID_GSL,
	GPIO_ID_COUNT,
};
#define GPIO_ENUM_UNKNOWN 32
struct gpio_pin_info {
	uint32_t offset, offset_y, offset_en, offset_mask;
	uint32_t mask, mask_y, mask_en, mask_mask;
};
enum gpio_generic { GPIO_GENERIC_UNKNOWN=(-1), GPIO_GENERIC_A, GPIO_GENERIC_B,
	GPIO_GENERIC_C, GPIO_GENERIC_D, GPIO_GENERIC_E, GPIO_GENERIC_F,
	GPIO_GENERIC_G, GPIO_GENERIC_COUNT };
enum gpio_hpd { GPIO_HPD_UNKNOWN=(-1), GPIO_HPD_1, GPIO_HPD_2, GPIO_HPD_3,
	GPIO_HPD_4, GPIO_HPD_5, GPIO_HPD_6, GPIO_HPD_COUNT };
enum gpio_sync { GPIO_SYNC_UNKNOWN=(-1), GPIO_SYNC_HSYNC_A, GPIO_SYNC_VSYNC_A,
	GPIO_SYNC_HSYNC_B, GPIO_SYNC_VSYNC_B, GPIO_SYNC_COUNT };
enum gpio_gsl { GPIO_GSL_UNKNOWN=(-1), GPIO_GSL_GENLOCK_CLOCK,
	GPIO_GSL_GENLOCK_VSYNC, GPIO_GSL_SWAPLOCK_A, GPIO_GSL_SWAPLOCK_B,
	GPIO_GSL_COUNT };
enum gpio_ddc_line { GPIO_DDC_LINE_UNKNOWN=(-1), GPIO_DDC_LINE_DDC1,
	GPIO_DDC_LINE_DDC2, GPIO_DDC_LINE_DDC3, GPIO_DDC_LINE_DDC4,
	GPIO_DDC_LINE_DDC5, GPIO_DDC_LINE_DDC6, GPIO_DDC_LINE_DDC_VGA,
	GPIO_DDC_LINE_VIP_PAD, GPIO_DDC_LINE_I2C_PAD = GPIO_DDC_LINE_VIP_PAD,
	GPIO_DDC_LINE_COUNT };

/* REG() arithmetic per hw_translate_dcn10.c:44-56 */
#define BASE_INNER(seg)	DCE_BASE__INST0_SEG ## seg
#define BASE(seg)	BASE_INNER(seg)
#define REG(reg_name)	BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name

#define DCE_BASE__INST0_SEG2 0x34C0

/* dcn_1_0_offset.h (all BASE_IDX 2) */
#define mmDC_GPIO_GENERIC_A	0x28c9
#define mmDC_GPIO_GENERIC_A_BASE_IDX	2
#define mmDC_GPIO_DDC1_A	0x28d1
#define mmDC_GPIO_DDC1_A_BASE_IDX	2
#define mmDC_GPIO_DDC2_A	0x28d5
#define mmDC_GPIO_DDC2_A_BASE_IDX	2
#define mmDC_GPIO_DDC3_A	0x28d9
#define mmDC_GPIO_DDC3_A_BASE_IDX	2
#define mmDC_GPIO_DDC4_A	0x28dd
#define mmDC_GPIO_DDC4_A_BASE_IDX	2
#define mmDC_GPIO_DDC5_A	0x28e1
#define mmDC_GPIO_DDC5_A_BASE_IDX	2
#define mmDC_GPIO_DDC6_A	0x28e5
#define mmDC_GPIO_DDC6_A_BASE_IDX	2
#define mmDC_GPIO_DDCVGA_A	0x28e9
#define mmDC_GPIO_DDCVGA_A_BASE_IDX	2
#define mmDC_GPIO_SYNCA_A	0x28ed
#define mmDC_GPIO_SYNCA_A_BASE_IDX	2
#define mmDC_GPIO_GENLK_A	0x28f1
#define mmDC_GPIO_GENLK_A_BASE_IDX	2
#define mmDC_GPIO_HPD_A	0x28f5
#define mmDC_GPIO_HPD_A_BASE_IDX	2
#define mmDC_GPIO_PWRSEQ_A	0x28f9
#define mmDC_GPIO_PWRSEQ_A_BASE_IDX	2
#define mmDC_GPIO_PAD_STRENGTH_1	0x28fc
#define mmDC_GPIO_PAD_STRENGTH_1_BASE_IDX	2
#define mmDC_GPIO_PAD_STRENGTH_2	0x28fd
#define mmDC_GPIO_PAD_STRENGTH_2_BASE_IDX	2
#define mmDC_GPIO_I2CPAD_A	0x2901
#define mmDC_GPIO_I2CPAD_A_BASE_IDX	2
#define mmDC_GPIO_DEBUG	0x286c
#define mmDC_GPIO_DEBUG_BASE_IDX	2

/* dcn_1_0_sh_mask.h */
#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK 0x00000001L
#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK 0x00000100L
#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK 0x00010000L
#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK 0x00100000L
#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK 0x00200000L
#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK 0x00400000L
#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK 0x00800000L
#define DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK 0x00000001L
#define DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK 0x00000100L
#define DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK 0x00010000L
#define DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK 0x01000000L
#define DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK 0x04000000L
#define DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK 0x10000000L
#define DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK 0x00000001L
#define DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK 0x00000100L
#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK 0x00000001L
#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK 0x00000100L
#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK 0x00010000L
#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK 0x01000000L
#define DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK 0x00000100L
#define DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK 0x00000001L

/* truth for T3: DC_GPIO_I2CPAD_A's SDA/SCL field positions (dcn_1_0_sh_mask.h
 * 41216-41219) and the factory table's own use of them (ddc_regs.h:69-71) */
#define DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A_MASK  0x00000001L
#define DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK  0x00000002L

#define HPD_REGS_SIZE 6 /* hw_factory_dcn10.c:71-78 hpd_regs[] */
#define DDC_REGS_SIZE 8 /* hw_factory_dcn10.c:94-114 ddc_data_regs/ddc_clk_regs[] */

/* ============ VERBATIM from hw_translate_dcn10.c:61-201 ============ */
static bool offset_to_id(
	uint32_t offset,
	uint32_t mask,
	enum gpio_id *id,
	uint32_t *en)
{
	switch (offset) {
	/* GENERIC */
	case REG(DC_GPIO_GENERIC_A):
		*id = GPIO_ID_GENERIC;
		switch (mask) {
		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK:
			*en = GPIO_GENERIC_A;
			return true;
		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK:
			*en = GPIO_GENERIC_B;
			return true;
		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK:
			*en = GPIO_GENERIC_C;
			return true;
		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK:
			*en = GPIO_GENERIC_D;
			return true;
		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK:
			*en = GPIO_GENERIC_E;
			return true;
		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK:
			*en = GPIO_GENERIC_F;
			return true;
		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK:
			*en = GPIO_GENERIC_G;
			return true;
		default:
			ASSERT_CRITICAL(false);
			return false;
		}
	break;
	/* HPD */
	case REG(DC_GPIO_HPD_A):
		*id = GPIO_ID_HPD;
		switch (mask) {
		case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK:
			*en = GPIO_HPD_1;
			return true;
		case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK:
			*en = GPIO_HPD_2;
			return true;
		case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK:
			*en = GPIO_HPD_3;
			return true;
		case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK:
			*en = GPIO_HPD_4;
			return true;
		case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK:
			*en = GPIO_HPD_5;
			return true;
		case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK:
			*en = GPIO_HPD_6;
			return true;
		default:
			ASSERT_CRITICAL(false);
			return false;
		}
	break;
	/* SYNCA */
	case REG(DC_GPIO_SYNCA_A):
		*id = GPIO_ID_SYNC;
		switch (mask) {
		case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK:
			*en = GPIO_SYNC_HSYNC_A;
			return true;
		case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK:
			*en = GPIO_SYNC_VSYNC_A;
			return true;
		default:
			ASSERT_CRITICAL(false);
			return false;
		}
	break;
	/* REG(DC_GPIO_GENLK_MASK */
	case REG(DC_GPIO_GENLK_A):
		*id = GPIO_ID_GSL;
		switch (mask) {
		case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK:
			*en = GPIO_GSL_GENLOCK_CLOCK;
			return true;
		case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK:
			*en = GPIO_GSL_GENLOCK_VSYNC;
			return true;
		case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK:
			*en = GPIO_GSL_SWAPLOCK_A;
			return true;
		case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK:
			*en = GPIO_GSL_SWAPLOCK_B;
			return true;
		default:
			ASSERT_CRITICAL(false);
			return false;
		}
	break;
	/* DDC */
	/* we don't care about the GPIO_ID for DDC
	 * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK
	 * directly in the create method */
	case REG(DC_GPIO_DDC1_A):
		*en = GPIO_DDC_LINE_DDC1;
		return true;
	case REG(DC_GPIO_DDC2_A):
		*en = GPIO_DDC_LINE_DDC2;
		return true;
	case REG(DC_GPIO_DDC3_A):
		*en = GPIO_DDC_LINE_DDC3;
		return true;
	case REG(DC_GPIO_DDC4_A):
		*en = GPIO_DDC_LINE_DDC4;
		return true;
	case REG(DC_GPIO_DDC5_A):
		*en = GPIO_DDC_LINE_DDC5;
		return true;
	case REG(DC_GPIO_DDC6_A):
		*en = GPIO_DDC_LINE_DDC6;
		return true;
	case REG(DC_GPIO_DDCVGA_A):
		*en = GPIO_DDC_LINE_DDC_VGA;
		return true;
	/* GPIO_I2CPAD */
	case REG(DC_GPIO_I2CPAD_A):
		*en = GPIO_DDC_LINE_I2C_PAD;
		return true;
	/* Not implemented */
	case REG(DC_GPIO_PWRSEQ_A):
	case REG(DC_GPIO_PAD_STRENGTH_1):
	case REG(DC_GPIO_PAD_STRENGTH_2):
	case REG(DC_GPIO_DEBUG):
		return false;
	/* UNEXPECTED */
	default:
		ASSERT_CRITICAL(false);
		return false;
	}
}

/* ============ VERBATIM from hw_translate_dcn10.c:203-388 ============ */
static bool id_to_offset(
	enum gpio_id id,
	uint32_t en,
	struct gpio_pin_info *info)
{
	bool result = true;

	switch (id) {
	case GPIO_ID_DDC_DATA:
		info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK;
		switch (en) {
		case GPIO_DDC_LINE_DDC1:
			info->offset = REG(DC_GPIO_DDC1_A);
		break;
		case GPIO_DDC_LINE_DDC2:
			info->offset = REG(DC_GPIO_DDC2_A);
		break;
		case GPIO_DDC_LINE_DDC3:
			info->offset = REG(DC_GPIO_DDC3_A);
		break;
		case GPIO_DDC_LINE_DDC4:
			info->offset = REG(DC_GPIO_DDC4_A);
		break;
		case GPIO_DDC_LINE_DDC5:
			info->offset = REG(DC_GPIO_DDC5_A);
		break;
		case GPIO_DDC_LINE_DDC6:
			info->offset = REG(DC_GPIO_DDC6_A);
		break;
		case GPIO_DDC_LINE_DDC_VGA:
			info->offset = REG(DC_GPIO_DDCVGA_A);
		break;
		case GPIO_DDC_LINE_I2C_PAD:
			info->offset = REG(DC_GPIO_I2CPAD_A);
		break;
		default:
			ASSERT_CRITICAL(false);
			result = false;
		}
	break;
	case GPIO_ID_DDC_CLOCK:
		info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK;
		switch (en) {
		case GPIO_DDC_LINE_DDC1:
			info->offset = REG(DC_GPIO_DDC1_A);
		break;
		case GPIO_DDC_LINE_DDC2:
			info->offset = REG(DC_GPIO_DDC2_A);
		break;
		case GPIO_DDC_LINE_DDC3:
			info->offset = REG(DC_GPIO_DDC3_A);
		break;
		case GPIO_DDC_LINE_DDC4:
			info->offset = REG(DC_GPIO_DDC4_A);
		break;
		case GPIO_DDC_LINE_DDC5:
			info->offset = REG(DC_GPIO_DDC5_A);
		break;
		case GPIO_DDC_LINE_DDC6:
			info->offset = REG(DC_GPIO_DDC6_A);
		break;
		case GPIO_DDC_LINE_DDC_VGA:
			info->offset = REG(DC_GPIO_DDCVGA_A);
		break;
		case GPIO_DDC_LINE_I2C_PAD:
			info->offset = REG(DC_GPIO_I2CPAD_A);
		break;
		default:
			ASSERT_CRITICAL(false);
			result = false;
		}
	break;
	case GPIO_ID_GENERIC:
		info->offset = REG(DC_GPIO_GENERIC_A);
		switch (en) {
		case GPIO_GENERIC_A:
			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK;
		break;
		case GPIO_GENERIC_B:
			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK;
		break;
		case GPIO_GENERIC_C:
			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK;
		break;
		case GPIO_GENERIC_D:
			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK;
		break;
		case GPIO_GENERIC_E:
			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK;
		break;
		case GPIO_GENERIC_F:
			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK;
		break;
		case GPIO_GENERIC_G:
			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK;
		break;
		default:
			ASSERT_CRITICAL(false);
			result = false;
		}
	break;
	case GPIO_ID_HPD:
		info->offset = REG(DC_GPIO_HPD_A);
		switch (en) {
		case GPIO_HPD_1:
			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK;
		break;
		case GPIO_HPD_2:
			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK;
		break;
		case GPIO_HPD_3:
			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK;
		break;
		case GPIO_HPD_4:
			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK;
		break;
		case GPIO_HPD_5:
			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK;
		break;
		case GPIO_HPD_6:
			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK;
		break;
		default:
			ASSERT_CRITICAL(false);
			result = false;
		}
	break;
	case GPIO_ID_SYNC:
		switch (en) {
		case GPIO_SYNC_HSYNC_A:
			info->offset = REG(DC_GPIO_SYNCA_A);
			info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK;
		break;
		case GPIO_SYNC_VSYNC_A:
			info->offset = REG(DC_GPIO_SYNCA_A);
			info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK;
		break;
		case GPIO_SYNC_HSYNC_B:
		case GPIO_SYNC_VSYNC_B:
		default:
			ASSERT_CRITICAL(false);
			result = false;
		}
	break;
	case GPIO_ID_GSL:
		switch (en) {
		case GPIO_GSL_GENLOCK_CLOCK:
			info->offset = REG(DC_GPIO_GENLK_A);
			info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK;
		break;
		case GPIO_GSL_GENLOCK_VSYNC:
			info->offset = REG(DC_GPIO_GENLK_A);
			info->mask =
				DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK;
		break;
		case GPIO_GSL_SWAPLOCK_A:
			info->offset = REG(DC_GPIO_GENLK_A);
			info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK;
		break;
		case GPIO_GSL_SWAPLOCK_B:
			info->offset = REG(DC_GPIO_GENLK_A);
			info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK;
		break;
		default:
			ASSERT_CRITICAL(false);
			result = false;
		}
	break;
	case GPIO_ID_VIP_PAD:
	default:
		ASSERT_CRITICAL(false);
		result = false;
	}

	if (result) {
		info->offset_y = info->offset + 2;
		info->offset_en = info->offset + 1;
		info->offset_mask = info->offset - 1;

		info->mask_y = info->mask;
		info->mask_en = info->mask;
		info->mask_mask = info->mask;
	}

	return result;
}

int main(void)
{
	int fails = 0;
	enum gpio_id id;
	uint32_t en;
	bool r;
	struct gpio_pin_info info;
	int i;

	printf("== DCN10 REG() domain: REG(DC_GPIO_DDC1_A)=0x%x REG(DC_GPIO_DDCVGA_A)=0x%x REG(DC_GPIO_I2CPAD_A)=0x%x ==\n",
		REG(DC_GPIO_DDC1_A), REG(DC_GPIO_DDCVGA_A), REG(DC_GPIO_I2CPAD_A));
	printf("(VBIOS gpio_pin_lut data_a_reg_index stores these full offsets — bios_parser2.c:537-539)\n\n");

	printf("== T1: DDC/VGA/I2CPAD offsets return success WITHOUT writing *id (DF-4946) ==\n");
	printf("(dal_gpio_service_create_irq gpio_service.c:148-149 declares 'enum gpio_id id;' uninitialized)\n");
	{
		static const struct { uint32_t off; const char *nm; } ddc8[] = {
			{ REG(DC_GPIO_DDC1_A),   "DDC1" },
			{ REG(DC_GPIO_DDC2_A),   "DDC2" },
			{ REG(DC_GPIO_DDC3_A),   "DDC3" },
			{ REG(DC_GPIO_DDC4_A),   "DDC4" },
			{ REG(DC_GPIO_DDC5_A),   "DDC5" },
			{ REG(DC_GPIO_DDC6_A),   "DDC6" },
			{ REG(DC_GPIO_DDCVGA_A), "DDCVGA" },
			{ REG(DC_GPIO_I2CPAD_A), "I2CPAD" },
		};
		for (i = 0; i < 8; i++) {
			id = (enum gpio_id)0x7B7B7B7B;
			r = offset_to_id(ddc8[i].off, 0x100 /* mask ignored in these branches */, &id, &en);
			printf("offset_to_id(REG(%-6s),0x100) = %-5s en=%d (id==0x%x %s)\n",
				ddc8[i].nm, r ? "true" : "false", en, (unsigned)id,
				id == (enum gpio_id)0x7B7B7B7B ? "UNTOUCHED" : "written");
			if (r && id == (enum gpio_id)0x7B7B7B7B) {
				fails++;
				printf("  -> BUG(DF-4946): success, *id never written");
				if (en >= HPD_REGS_SIZE)
					printf("; garbage id==GPIO_ID_HPD(3) => dal_gpio_create(HPD, en=%d) indexes hpd_regs[%d] OOB (hpd_regs has %d entries)",
						en, en, HPD_REGS_SIZE);
				else if (en >= DDC_REGS_SIZE)
					printf("; en=%d also exceeds ddc_regs[%d]", en, DDC_REGS_SIZE);
				printf("\n");
			}
		}
	}

	printf("\n== T2 (negative): no GPIOPAD cross-domain case; Not-implemented rejects ==\n");
	id = (enum gpio_id)0x7B7B7B7B;
	r = offset_to_id(0x183 /* mmGPIOPAD_A raw, the DF-4942 dce80 producer */, 1u << 20, &id, &en);
	printf("offset_to_id(0x183,1<<20)        = %s (no GPIOPAD mapping -> rejected: OK;"
	       " the dce80-style deterministic producer does not exist on DCN10)\n",
		r ? "true" : "false");
	if (r) fails++;
	id = (enum gpio_id)0x7B7B7B7B;
	r = offset_to_id(REG(DC_GPIO_DEBUG), 1, &id, &en);
	printf("offset_to_id(REG(DC_GPIO_DEBUG)) = %s (Not-implemented path: OK)\n",
		r ? "true" : "false");
	if (r) fails++;

	printf("\n== T3: id_to_offset DDC mask-vs-index — I2C_PAD data mask is WRONG (DF-4947) ==\n");
	memset(&info, 0, sizeof(info));
	r = id_to_offset(GPIO_ID_DDC_DATA, GPIO_DDC_LINE_I2C_PAD, &info);
	printf("id_to_offset(DDC_DATA, I2C_PAD)   = %s offset=0x%x mask=0x%x"
	       " — DC_GPIO_I2CPAD_A SDA field is bit1 (0x%x): WRONG BIT\n",
		r ? "true" : "false", info.offset, info.mask,
		(unsigned)DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK);
	if (r && info.mask != DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK) fails++;
	memset(&info, 0, sizeof(info));
	r = id_to_offset(GPIO_ID_DDC_CLOCK, GPIO_DDC_LINE_I2C_PAD, &info);
	printf("id_to_offset(DDC_CLOCK, I2C_PAD)  = %s offset=0x%x mask=0x%x"
	       " — SCL field is bit0: coincidentally correct\n",
		r ? "true" : "false", info.offset, info.mask);
	memset(&info, 0, sizeof(info));
	r = id_to_offset(GPIO_ID_DDC_DATA, GPIO_DDC_LINE_DDC_VGA, &info);
	printf("id_to_offset(DDC_DATA, DDC_VGA)   = %s offset=0x%x mask=0x%x"
	       " — DDCVGADATA_A_MASK is also 0x100: correct by layout\n",
		r ? "true" : "false", info.offset, info.mask);

	printf("\n== T4 (negative): HPD branch well-formed ==\n");
	for (i = 0; i < 6; i++) {
		static const uint32_t hmask[6] = {
			DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK,
			DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK,
			DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK,
			DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK,
			DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK,
			DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK };
		id = (enum gpio_id)0x7B7B7B7B;
		r = offset_to_id(REG(DC_GPIO_HPD_A), hmask[i], &id, &en);
		printf("offset_to_id(REG(HPD),HPD%d mask) = %-5s id=%d en=%d\n",
			i + 1, r ? "true" : "false", (int)id, en);
		if (!r || id != GPIO_ID_HPD || en != (uint32_t)i) fails++;
	}

	printf("\n%d contract-violation reproductions\n", fails);
	return (fails > 0) ? 0 : 1;
}
