// File: /workspace/github_c_makefile_star2_O0/intel[P]pf-bb-config/agx100/agx100_cfg_app.c
// Function: agx100_write_config
static int
agx100_write_config(void *dev, void *mapaddr, struct agx100_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;
	/* Maximum number of queues on device */
	uint8_t total_num_queues = agx100_reg_read_32(bar0addr, AGX100_VERSION_QUEUES_REG) >> 24;
	uint8_t num_ul_queues = total_num_queues >> 1;
	uint8_t num_dl_queues = total_num_queues >> 1;

	/* Clear all queues registers */
	payload_32 = AGX100_INVALID_HW_QUEUE_ID;
	for (q_id = 0; q_id < total_num_queues; ++q_id) {
		address = (q_id << 2) + AGX100_QUEUE_MAP;
		agx100_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 AGX100 capabilities.
	 * 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 < total_num_queues; ++q_id) {
			address = (q_id << 2) + AGX100_QUEUE_MAP;
			agx100_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 < AGX100_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
		 * AGX100 capabilities
		 */
		if ((total_ul_q_id > num_ul_queues) ||
			(total_dl_q_id > num_dl_queues) ||
			(total_q_id > total_num_queues)) {
			printf(
					"AGX100 Configuration failed. Too many queues to configure: UL_Q %u, DL_Q %u, AGX100_Q %u",
					total_ul_q_id, total_dl_q_id,
					total_num_queues);
			return -EINVAL;
		}
		total_ul_q_id = 0;
		for (vf_id = 0; vf_id < AGX100_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) +
						AGX100_QUEUE_MAP;
				payload_32 = ((0x80 + vf_id) << 16) | 0x1;
				agx100_reg_write_32(bar0addr, address,
						payload_32);
			}
		}
		total_dl_q_id = 0;
		for (vf_id = 0; vf_id < AGX100_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 + num_ul_queues)
						<< 2) + AGX100_QUEUE_MAP;
				payload_32 = ((0x80 + vf_id) << 16) | 0x1;
				agx100_reg_write_32(bar0addr, address,
						payload_32);
			}
		}
	}

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

	/* Setting length of ring descriptor entry */
	payload_16 = AGX100_RING_DESC_ENTRY_LENGTH;
	address = AGX100_RING_DESC_LEN;
	agx100_reg_write_16(bar0addr, address, payload_16);

	/* Queue PF/VF mapping table is ready */
	payload_16 = 0x1;
	address = AGX100_QUEUE_PF_VF_MAP_DONE;
	agx100_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 $0x50, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rdi
xorl %esi, %esi
callq 0x1e050
shrl $0x18, %eax
movb %al, -0x41(%rbp)
movzbl -0x41(%rbp), %eax
sarl %eax
movb %al, -0x42(%rbp)
movzbl -0x41(%rbp), %eax
sarl %eax
movb %al, -0x43(%rbp)
movl $0xffffffff, -0x24(%rbp) # imm = 0xFFFFFFFF
movw $0x0, -0x2c(%rbp)
movzwl -0x2c(%rbp), %eax
movzbl -0x41(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1dd74
movzwl -0x2c(%rbp), %eax
shll $0x2, %eax
addl $0x100, %eax            # imm = 0x100
movl %eax, -0x28(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movl -0x24(%rbp), %edx
callq 0x1e080
movw -0x2c(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2c(%rbp)
jmp 0x1dd3c
movq -0x20(%rbp), %rax
testb $0x1, (%rax)
je 0x1ddc7
movl $0x1, -0x24(%rbp)
movw $0x0, -0x2c(%rbp)
movzwl -0x2c(%rbp), %eax
movzbl -0x41(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1ddc2
movzwl -0x2c(%rbp), %eax
shll $0x2, %eax
addl $0x100, %eax            # imm = 0x100
movl %eax, -0x28(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movl -0x24(%rbp), %edx
callq 0x1e080
movw -0x2c(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2c(%rbp)
jmp 0x1dd8a
jmp 0x1df95
movw $0x0, -0x34(%rbp)
movw $0x0, -0x32(%rbp)
movw $0x0, -0x2e(%rbp)
movzwl -0x2e(%rbp), %eax
cmpl $0x8, %eax
jge 0x1de1e
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 0x1ddd9
movzwl -0x34(%rbp), %eax
movzwl -0x32(%rbp), %ecx
addl %ecx, %eax
movw %ax, -0x30(%rbp)
movzwl -0x32(%rbp), %eax
movzbl -0x42(%rbp), %ecx
cmpl %ecx, %eax
jg 0x1de50
movzwl -0x34(%rbp), %eax
movzbl -0x43(%rbp), %ecx
cmpl %ecx, %eax
jg 0x1de50
movzwl -0x30(%rbp), %eax
movzbl -0x41(%rbp), %ecx
cmpl %ecx, %eax
jle 0x1de76
movzwl -0x32(%rbp), %esi
movzwl -0x34(%rbp), %edx
movzbl -0x41(%rbp), %ecx
leaq 0x7ae5(%rip), %rdi      # 0x25948
movb $0x0, %al
callq 0xd140
movl $0xffffffea, -0x4(%rbp) # imm = 0xFFFFFFEA
jmp 0x1e038
movw $0x0, -0x32(%rbp)
movw $0x0, -0x2e(%rbp)
movzwl -0x2e(%rbp), %eax
cmpl $0x8, %eax
jge 0x1df00
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 0x1def0
movzwl -0x32(%rbp), %eax
shll $0x2, %eax
addl $0x100, %eax            # imm = 0x100
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 0x1e080
movw -0x2c(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2c(%rbp)
movw -0x32(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x32(%rbp)
jmp 0x1de91
jmp 0x1def2
movw -0x2e(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2e(%rbp)
jmp 0x1de82
movw $0x0, -0x34(%rbp)
movw $0x0, -0x2e(%rbp)
movzwl -0x2e(%rbp), %eax
cmpl $0x8, %eax
jge 0x1df93
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 0x1df80
movzwl -0x34(%rbp), %eax
movzbl -0x42(%rbp), %ecx
addl %ecx, %eax
shll $0x2, %eax
addl $0x100, %eax            # imm = 0x100
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 0x1e080
movw -0x2c(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2c(%rbp)
movw -0x34(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x34(%rbp)
jmp 0x1df1b
jmp 0x1df82
movw -0x2e(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x2e(%rbp)
jmp 0x1df0c
jmp 0x1df95
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 $0xa, -0x28(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movzwl -0x2a(%rbp), %edx
callq 0x1e0b0
movw $0x8, -0x2a(%rbp)
movl $0xc, -0x28(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movzwl -0x2a(%rbp), %edx
callq 0x1e0b0
movw $0x1, -0x2a(%rbp)
movl $0x8, -0x28(%rbp)
movq -0x40(%rbp), %rdi
movl -0x28(%rbp), %esi
movzwl -0x2a(%rbp), %edx
callq 0x1e0b0
movq -0x40(%rbp), %rdi
callq 0x1e0e0
movq -0x20(%rbp), %rax
movb (%rax), %cl
leaq 0x5ecd(%rip), %rsi      # 0x23ee2
leaq 0x742d(%rip), %rax      # 0x25449
testb $0x1, %cl
cmovneq %rax, %rsi
leaq 0x5e9b(%rip), %rdi      # 0x23ec5
movb $0x0, %al
callq 0xd140
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)