// File: /workspace/github_c_makefile_star2_O1/Arlu[P]RDMA-Hello-World/setup_ib.c
// Function: setup_ib
int setup_ib()
{
    struct ibv_device **dev_list, *ib_dev;

    srand48(getpid() * time(NULL));

    memset(&ib_res, 0, sizeof(struct IBRes));
    ib_res.size = BUFFER_SIZE;
    ib_res.buf = malloc(roundup(BUFFER_SIZE, sysconf(_SC_PAGESIZE)));
    if (!ib_res.buf) {
        perror("Couldn't allocate work buf.\n");
        return 1;
    }

    memset(ib_res.buf, 0x7b + (server_name ? 0 : 1), BUFFER_SIZE);

    // Get an IB devices list:
    dev_list = ibv_get_device_list(NULL);
    if (!dev_list)
    {
        perror("Failed to get IB devices list.\n");
        return 1;
    }

    // Get an IB device:
    ib_dev = *dev_list;
    if (!ib_dev)
    {
        perror("No IB devices found.\n");
        return 1;
    }

    // Open an IB device context:
    ib_res.ctx = ibv_open_device(*dev_list);
    if (!ib_res.ctx)
    {
        fprintf(stderr, "Couldn't get context for %s.\n", ibv_get_device_name(ib_dev));
        return 1;
    }

    // Allocate a Protection Domain:
    ib_res.pd = ibv_alloc_pd(ib_res.ctx);
    if (!ib_res.pd)
    {
        perror("Failed to allocate Protection Domain.\n");
        return 1;
    }

    // Query IB port attribute:
    if (ibv_query_port(ib_res.ctx, IB_PORT, &ib_res.port_info))
    {
        perror("Failed to query IB port information.\n");
        return 1;
    }

    // Register a Memory Region:
    ib_res.mr = ibv_reg_mr(ib_res.pd, ib_res.buf, ib_res.size,
                           IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_READ | IBV_ACCESS_REMOTE_WRITE);
    if (!ib_res.mr)
    {
        perror("Couldn't register Memory Region.\n");
        return 1;
    }

    // Creates a Completion Queue:
    ib_res.cq = ibv_create_cq(ib_res.ctx, 2 * COUNT, NULL, NULL, 0);
    if (!ib_res.cq)
    {
        perror("Couldn't create Completion Queue.\n");
        return 1;
    }

    // Creates a Queue Pair:
    {
        struct ibv_qp_init_attr qp_init_attr = {
                .send_cq = ib_res.cq,
                .recv_cq = ib_res.cq,
                .cap = {
                        .max_send_wr = COUNT,
                        .max_recv_wr = COUNT,
                        .max_send_sge = 1,
                        .max_recv_sge = 1,
                },
                .qp_type = IBV_QPT_RC,
        };

        ib_res.qp = ibv_create_qp(ib_res.pd, &qp_init_attr);
        if (!ib_res.qp) {
            perror("Couldn't create Queue Pair.\n");
            return 1;
        }

        struct ibv_qp_attr qp_attr = {
                .qp_state        = IBV_QPS_INIT,
                .pkey_index      = 0,
                .port_num        = IB_PORT,
                .qp_access_flags = IBV_ACCESS_REMOTE_READ | IBV_ACCESS_REMOTE_WRITE
        };

        if (ibv_modify_qp(ib_res.qp, &qp_attr, IBV_QP_STATE | IBV_QP_PKEY_INDEX | IBV_QP_PORT | IBV_QP_ACCESS_FLAGS)) {
            perror("Failed to modify QP to INIT.\n");
            return 1;
        }
    }

    // Get LID:
    local_dest.lid = ib_res.port_info.lid;
    if (ib_res.port_info.link_layer == IBV_LINK_LAYER_INFINIBAND && !local_dest.lid)
    {
        perror("Couldn't get LID.\n");
        return 1;
    }

    // Get QPN:
    local_dest.qpn = ib_res.qp->qp_num;

    // Set PSN:
    local_dest.psn = lrand48() & 0xffffff;

    // Get details of each side:
    if (server_name)
    {
        if (get_server_dest())
        {
            perror("Couldn't get server's details.\n");
            return 1;
        }
    }
    else
    {
        if (get_client_dest())
        {
            perror("Couldn't get client's details.\n");
            return 1;
        }
    }

    // Connect Queue Pair:
    if (connect_between_qps())
    {
        perror("Couldn't connect between client and server.\n");
        return 1;
    }

    ibv_free_device_list(dev_list);
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0xd8, %rsp
callq 0x10a0
movslq %eax, %r14
xorl %ebx, %ebx
xorl %edi, %edi
callq 0x1150
imulq %rax, %r14
movq %r14, %rdi
callq 0x11a0
xorps %xmm0, %xmm0
movups %xmm0, 0x28e6(%rip)     # 0x41e8
movups %xmm0, 0x28cf(%rip)     # 0x41d8
movups %xmm0, 0x28b8(%rip)     # 0x41c8
movups %xmm0, 0x28a1(%rip)     # 0x41b8
movups %xmm0, 0x288a(%rip)     # 0x41a8
movups %xmm0, 0x2873(%rip)     # 0x4198
movups %xmm0, 0x285c(%rip)     # 0x4188
movq $0x400, 0x28b9(%rip) # imm = 0x400
movl $0x1e, %edi
callq 0x11e0
movq %rax, %r14
addq $0x3ff, %r14            # imm = 0x3FF
movl $0x1e, %edi
callq 0x11e0
movq %rax, %rcx
movq %r14, %rax
cqto
idivq %rcx
movq %rax, %r14
movl $0x1e, %edi
callq 0x11e0
imulq %rax, %r14
movq %r14, %rdi
callq 0x1160
movq %rax, 0x2868(%rip)      # 0x41e8
testq %rax, %rax
je 0x1bfc
cmpq $0x1, 0x27d7(%rip)      # 0x4168
adcl $0x7b, %ebx
movl $0x400, %edx            # imm = 0x400
movq %rax, %rdi
movl %ebx, %esi
callq 0x10e0
xorl %edi, %edi
callq 0x1240
testq %rax, %rax
je 0x1c05
movq %rax, %rbx
movq (%rax), %r14
testq %r14, %r14
je 0x1c0e
movq %r14, %rdi
callq 0x1040
movq %rax, 0x27b7(%rip)      # 0x4188
testq %rax, %rax
je 0x1c17
movq %rax, %rdi
callq 0x10d0
movq %rax, 0x27a7(%rip)      # 0x4190
testq %rax, %rax
je 0x1c21
movq 0x278f(%rip), %rdi      # 0x4188
leaq -0x140(%rdi), %rcx
xorl %eax, %eax
cmpq $-0x1, 0x140(%rdi)
cmovneq %rax, %rcx
jne 0x1a2e
cmpq $0x288, 0x138(%rcx) # imm = 0x288
jae 0x1a21
xorl %eax, %eax
jmp 0x1a2e
movq (%rcx), %rax
testq %rax, %rax
cmoveq %rax, %rcx
movq %rcx, %rax
testq %rax, %rax
je 0x1a48
leaq 0x2776(%rip), %rdx      # 0x41b0
movl $0x34, %ecx
movl $0x1, %esi
callq *(%rax)
jmp 0x1a7b
xorps %xmm0, %xmm0
movups %xmm0, 0x277e(%rip)     # 0x41d0
movups %xmm0, 0x2767(%rip)     # 0x41c0
movups %xmm0, 0x2750(%rip)     # 0x41b0
movl $0x0, 0x2776(%rip)      # 0x41e0
leaq 0x273f(%rip), %rdx      # 0x41b0
movl $0x1, %esi
callq 0x11b0
testl %eax, %eax
jne 0x1c2a
movq 0x2706(%rip), %rdi      # 0x4190
movq 0x2757(%rip), %rsi      # 0x41e8
movq 0x2758(%rip), %rdx      # 0x41f0
movl $0x7, %ecx
callq 0x1230
movq %rax, 0x26ef(%rip)      # 0x4198
testq %rax, %rax
je 0x1c33
movq 0x26cf(%rip), %rdi      # 0x4188
movl $0x7d0, %esi            # imm = 0x7D0
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x1090
movq %rax, 0x26cf(%rip)      # 0x41a0
testq %rax, %rax
je 0x1c3c
xorl %ecx, %ecx
leaq -0x58(%rbp), %rsi
movq %rcx, (%rsi)
movq %rax, 0x8(%rsi)
movq %rax, 0x10(%rsi)
movq %rcx, 0x18(%rsi)
movaps 0x59a(%rip), %xmm0      # 0x2090
movups %xmm0, 0x20(%rsi)
movabsq $0x200000000, %rax      # imm = 0x200000000
movq %rax, 0x30(%rsi)
movl $0x0, 0x38(%rsi)
movq 0x267a(%rip), %rdi      # 0x4190
callq 0x1220
movq %rax, 0x2686(%rip)      # 0x41a8
testq %rax, %rax
je 0x1c45
movq %rax, %r14
leaq -0xe8(%rbp), %r15
movl $0x90, %edx
movq %r15, %rdi
xorl %esi, %esi
callq 0x10e0
movl $0x1, (%r15)
movl $0x6, 0x20(%r15)
movb $0x1, 0x81(%r15)
movq %r14, %rdi
movq %r15, %rsi
movl $0x39, %edx
callq 0x1050
testl %eax, %eax
jne 0x1c4e
movzwl 0x2658(%rip), %eax      # 0x41d2
movzwl %ax, %eax
movl %eax, 0x25ed(%rip)      # 0x4170
cmpb $0x1, 0x2654(%rip)      # 0x41de
setne %cl
testw %ax, %ax
setne %al
orb %cl, %al
je 0x1c57
movq 0x2606(%rip), %rax      # 0x41a8
movl 0x34(%rax), %eax
movl %eax, 0x25c9(%rip)      # 0x4174
callq 0x1180
andl $0xffffff, %eax         # imm = 0xFFFFFF
movl %eax, 0x25bd(%rip)      # 0x4178
cmpq $0x0, 0x25a5(%rip)      # 0x4168
je 0x1bda
callq 0x1568
testl %eax, %eax
je 0x1be7
leaq 0x6ed(%rip), %rdi       # 0x22c2
jmp 0x1c70
callq 0x16b3
testl %eax, %eax
jne 0x1c69
callq 0x17e9
testl %eax, %eax
jne 0x1c60
movq %rbx, %rdi
callq 0x10b0
xorl %eax, %eax
jmp 0x1c7a
leaq 0x56e(%rip), %rdi       # 0x2171
jmp 0x1c70
leaq 0x582(%rip), %rdi       # 0x218e
jmp 0x1c70
leaq 0x599(%rip), %rdi       # 0x21ae
jmp 0x1c70
movq %r14, %rdi
callq 0x12b0
jmp 0x1c75
leaq 0x5ba(%rip), %rdi       # 0x21e2
jmp 0x1c70
leaq 0x5d8(%rip), %rdi       # 0x2209
jmp 0x1c70
leaq 0x5f5(%rip), %rdi       # 0x222f
jmp 0x1c70
leaq 0x60e(%rip), %rdi       # 0x2251
jmp 0x1c70
leaq 0x628(%rip), %rdi       # 0x2274
jmp 0x1c70
leaq 0x63c(%rip), %rdi       # 0x2291
jmp 0x1c70
leaq 0x651(%rip), %rdi       # 0x22af
jmp 0x1c70
leaq 0x69b(%rip), %rdi       # 0x2302
jmp 0x1c70
leaq 0x672(%rip), %rdi       # 0x22e2
callq 0x11d0
movl $0x1, %eax
addq $0xd8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq