// File: /workspace/github_c_makefile_star2_O0/intel[P]pf-bb-config/fpga_5gnr/fpga_5gnr_cfg_app.c
// Function: fpga_write_config
static int
fpga_write_config(void *dev, void *mapaddr, struct fpga_5gnr_fec_conf *conf)
{

	uint32_t payload_32, address;
	uint16_t payload_16;
	uint16_t q_id, vf_id, total_q_id, total_ul_q_id, total_dl_q_id;

	uint32_t *bar0addr = mapaddr;

	/*
	 * Configure UL:DL ratio.
	 * [7:0]: UL weight
	 * [15:8]: DL weight
	 */
	payload_16 = (conf->dl_bandwidth << 8) | conf->ul_bandwidth;
	address = FPGA_5GNR_FEC_CONFIGURATION;
	fpga_reg_write_16(bar0addr, address, payload_16);

	/* Clear all queues registers */
	payload_32 = FPGA_INVALID_HW_QUEUE_ID;
	for (q_id = 0; q_id < FPGA_TOTAL_NUM_QUEUES; ++q_id) {
		address = (q_id << 2) + FPGA_5GNR_FEC_QUEUE_MAP;
		fpga_reg_write_32(bar0addr, address, payload_32);
	}

	/*
	 * If PF mode is enabled allocate all queues for PF only.
	 *
	 * For VF mode each VF can have different number of UL and DL queues.
	 * Total number of queues to configure cannot exceed FPGA
	 * capabilities - 64 queues - 32 queues for UL and 32 queues for DL.
	 * Queues mapping is done according to configuration:
	 *
	 * UL queues:
	 * |                Q_ID              | VF_ID |
	 * |                 0                |   0   |
	 * |                ...               |   0   |
	 * | conf->vf_dl_queues_number[0] - 1 |   0   |
	 * | conf->vf_dl_queues_number[0]     |   1   |
	 * |                ...               |   1   |
	 * | conf->vf_dl_queues_number[1] - 1 |   1   |
	 * |                ...               |  ...  |
	 * | conf->vf_dl_queues_number[7] - 1 |   7   |
	 *
	 * DL queues:
	 * |                Q_ID              | VF_ID |
	 * |                 32               |   0   |
	 * |                ...               |   0   |
	 * | conf->vf_ul_queues_number[0] - 1 |   0   |
	 * | conf->vf_ul_queues_number[0]     |   1   |
	 * |                ...               |   1   |
	 * | conf->vf_ul_queues_number[1] - 1 |   1   |
	 * |                ...               |  ...  |
	 * | conf->vf_ul_queues_number[7] - 1 |   7   |
	 *
	 * Example of configuration:
	 * conf->vf_ul_queues_number[0] = 4;  -> 4 UL queues for VF0
	 * conf->vf_dl_queues_number[0] = 4;  -> 4 DL queues for VF0
	 * conf->vf_ul_queues_number[1] = 2;  -> 2 UL queues for VF1
	 * conf->vf_dl_queues_number[1] = 2;  -> 2 DL queues for VF1
	 *
	 * UL:
	 * | Q_ID | VF_ID |
	 * |   0  |   0   |
	 * |   1  |   0   |
	 * |   2  |   0   |
	 * |   3  |   0   |
	 * |   4  |   1   |
	 * |   5  |   1   |
	 *
	 * DL:
	 * | Q_ID | VF_ID |
	 * |  32  |   0   |
	 * |  33  |   0   |
	 * |  34  |   0   |
	 * |  35  |   0   |
	 * |  36  |   1   |
	 * |  37  |   1   |
	 */
	if (conf->pf_mode_en) {
		payload_32 = 0x1;
		for (q_id = 0; q_id < FPGA_TOTAL_NUM_QUEUES; ++q_id) {
			address = (q_id << 2) + FPGA_5GNR_FEC_QUEUE_MAP;
			fpga_reg_write_32(bar0addr, address, payload_32);
		}
	} else {
		/* Calculate total number of UL and DL queues to configure */
		total_ul_q_id = total_dl_q_id = 0;
		for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
			total_ul_q_id += conf->vf_ul_queues_number[vf_id];
			total_dl_q_id += conf->vf_dl_queues_number[vf_id];
		}
		total_q_id = total_dl_q_id + total_ul_q_id;
		/*
		 * Check if total number of queues to configure does not exceed
		 * FPGA capabilities (64 queues - 32 UL and 32 DL queues)
		 */
		if ((total_ul_q_id > FPGA_NUM_UL_QUEUES) ||
			(total_dl_q_id > FPGA_NUM_DL_QUEUES) ||
			(total_q_id > FPGA_TOTAL_NUM_QUEUES)) {
			printf(
					"FPGA Configuration failed. Too many queues to configure: UL_Q %u, DL_Q %u, FPGA_Q %u",
					total_ul_q_id, total_dl_q_id,
					FPGA_TOTAL_NUM_QUEUES);
			return -EINVAL;
		}
		total_ul_q_id = 0;
		for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
			for (q_id = 0; q_id < conf->vf_ul_queues_number[vf_id];
					++q_id, ++total_ul_q_id) {
				address = (total_ul_q_id << 2) +
						FPGA_5GNR_FEC_QUEUE_MAP;
				payload_32 = ((0x80 + vf_id) << 16) | 0x1;
				fpga_reg_write_32(bar0addr, address,
						payload_32);
			}
		}
		total_dl_q_id = 0;
		for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
			for (q_id = 0; q_id < conf->vf_dl_queues_number[vf_id];
					++q_id, ++total_dl_q_id) {
				address = ((total_dl_q_id + FPGA_NUM_UL_QUEUES)
						<< 2) + FPGA_5GNR_FEC_QUEUE_MAP;
				payload_32 = ((0x80 + vf_id) << 16) | 0x1;
				fpga_reg_write_32(bar0addr, address,
						payload_32);
			}
		}
	}

	/* Setting Load Balance Factor */
	payload_16 = (conf->dl_load_balance << 8) | (conf->ul_load_balance);
	address = FPGA_5GNR_FEC_LOAD_BALANCE_FACTOR;
	fpga_reg_write_16(bar0addr, address, payload_16);

	/* Setting length of ring descriptor entry */
	payload_16 = FPGA_RING_DESC_ENTRY_LENGTH;
	address = FPGA_5GNR_FEC_RING_DESC_LEN;
	fpga_reg_write_16(bar0addr, address, payload_16);

	/* Queue PF/VF mapping table is ready */
	payload_16 = 0x1;
	address = FPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE;
	fpga_reg_write_16(bar0addr, address, payload_16);

	print_static_reg_debug_info(bar0addr);
	printf("Mode of operation = %s-mode\n",
			conf->pf_mode_en ? "PF" : "VF");

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x20(%rbp), %rax
movzbl 0x12(%rax), %eax
shll $0x8, %eax
movq -0x20(%rbp), %rcx
movzbl 0x11(%rcx), %ecx
orl %ecx, %eax
movw %ax, -0x2a(%rbp)
movl $0x4, -0x28(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movzwl -0x2a(%rbp), %edx
callq 0x12c50
movl $0xffffffff, -0x24(%rbp) # imm = 0xFFFFFFFF
movw $0x0, -0x2c(%rbp)
movzwl -0x2c(%rbp), %eax
cmpl $0x40, %eax
jge 0x1298c
movzwl -0x2c(%rbp), %eax
shll $0x2, %eax
addl $0x40, %eax
movl %eax, -0x28(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movl -0x24(%rbp), %edx
callq 0x12c80
movw -0x2c(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2c(%rbp)
jmp 0x12959
movq -0x20(%rbp), %rax
testb $0x1, (%rax)
je 0x129da
movl $0x1, -0x24(%rbp)
movw $0x0, -0x2c(%rbp)
movzwl -0x2c(%rbp), %eax
cmpl $0x40, %eax
jge 0x129d5
movzwl -0x2c(%rbp), %eax
shll $0x2, %eax
addl $0x40, %eax
movl %eax, -0x28(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movl -0x24(%rbp), %edx
callq 0x12c80
movw -0x2c(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2c(%rbp)
jmp 0x129a2
jmp 0x12b96
movw $0x0, -0x34(%rbp)
movw $0x0, -0x32(%rbp)
movw $0x0, -0x2e(%rbp)
movzwl -0x2e(%rbp), %eax
cmpl $0x8, %eax
jge 0x12a31
movq -0x20(%rbp), %rax
movzwl -0x2e(%rbp), %ecx
movzbl 0x1(%rax,%rcx), %ecx
movzwl -0x32(%rbp), %eax
addl %ecx, %eax
movw %ax, -0x32(%rbp)
movq -0x20(%rbp), %rax
movzwl -0x2e(%rbp), %ecx
movzbl 0x9(%rax,%rcx), %ecx
movzwl -0x34(%rbp), %eax
addl %ecx, %eax
movw %ax, -0x34(%rbp)
movw -0x2e(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2e(%rbp)
jmp 0x129ec
movzwl -0x34(%rbp), %eax
movzwl -0x32(%rbp), %ecx
addl %ecx, %eax
movw %ax, -0x30(%rbp)
movzwl -0x32(%rbp), %eax
cmpl $0x20, %eax
jg 0x12a5a
movzwl -0x34(%rbp), %eax
cmpl $0x20, %eax
jg 0x12a5a
movzwl -0x30(%rbp), %eax
cmpl $0x40, %eax
jle 0x12a81
movzwl -0x32(%rbp), %esi
movzwl -0x34(%rbp), %edx
leaq 0x11407(%rip), %rdi     # 0x23e70
movl $0x40, %ecx
movb $0x0, %al
callq 0xd140
movl $0xffffffea, -0x4(%rbp) # imm = 0xFFFFFFEA
jmp 0x12c39
movw $0x0, -0x32(%rbp)
movw $0x0, -0x2e(%rbp)
movzwl -0x2e(%rbp), %eax
cmpl $0x8, %eax
jge 0x12b09
movw $0x0, -0x2c(%rbp)
movzwl -0x2c(%rbp), %eax
movq -0x20(%rbp), %rcx
movzwl -0x2e(%rbp), %edx
movzbl 0x1(%rcx,%rdx), %ecx
cmpl %ecx, %eax
jge 0x12af9
movzwl -0x32(%rbp), %eax
shll $0x2, %eax
addl $0x40, %eax
movl %eax, -0x28(%rbp)
movzwl -0x2e(%rbp), %eax
addl $0x80, %eax
shll $0x10, %eax
orl $0x1, %eax
movl %eax, -0x24(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movl -0x24(%rbp), %edx
callq 0x12c80
movw -0x2c(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2c(%rbp)
movw -0x32(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x32(%rbp)
jmp 0x12a9c
jmp 0x12afb
movw -0x2e(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2e(%rbp)
jmp 0x12a8d
movw $0x0, -0x34(%rbp)
movw $0x0, -0x2e(%rbp)
movzwl -0x2e(%rbp), %eax
cmpl $0x8, %eax
jge 0x12b94
movw $0x0, -0x2c(%rbp)
movzwl -0x2c(%rbp), %eax
movq -0x20(%rbp), %rcx
movzwl -0x2e(%rbp), %edx
movzbl 0x9(%rcx,%rdx), %ecx
cmpl %ecx, %eax
jge 0x12b84
movzwl -0x34(%rbp), %eax
addl $0x20, %eax
shll $0x2, %eax
addl $0x40, %eax
movl %eax, -0x28(%rbp)
movzwl -0x2e(%rbp), %eax
addl $0x80, %eax
shll $0x10, %eax
orl $0x1, %eax
movl %eax, -0x24(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movl -0x24(%rbp), %edx
callq 0x12c80
movw -0x2c(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2c(%rbp)
movw -0x34(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x34(%rbp)
jmp 0x12b24
jmp 0x12b86
movw -0x2e(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2e(%rbp)
jmp 0x12b15
jmp 0x12b96
movq -0x20(%rbp), %rax
movzbl 0x14(%rax), %eax
shll $0x8, %eax
movq -0x20(%rbp), %rcx
movzbl 0x13(%rcx), %ecx
orl %ecx, %eax
movw %ax, -0x2a(%rbp)
movl $0xa, -0x28(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movzwl -0x2a(%rbp), %edx
callq 0x12c50
movw $0x8, -0x2a(%rbp)
movl $0xc, -0x28(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movzwl -0x2a(%rbp), %edx
callq 0x12c50
movw $0x1, -0x2a(%rbp)
movl $0x8, -0x28(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movzwl -0x2a(%rbp), %edx
callq 0x12c50
movq -0x40(%rbp), %rdi
callq 0x12cb0
movq -0x20(%rbp), %rax
movb (%rax), %cl
leaq 0x112cc(%rip), %rsi     # 0x23ee2
leaq 0x1282c(%rip), %rax     # 0x25449
testb $0x1, %cl
cmovneq %rax, %rsi
leaq 0x1129a(%rip), %rdi     # 0x23ec5
movb $0x0, %al
callq 0xd140
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)