// File: /workspace/github_c_makefile_star2_O0/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
subq $0x130, %rsp            # imm = 0x130
callq 0x2090
cltq
movq %rax, -0x128(%rbp)
xorl %eax, %eax
movl %eax, %edi
callq 0x2190
movq -0x128(%rbp), %rdi
imulq %rax, %rdi
callq 0x21e0
leaq 0x372f(%rip), %rdi      # 0x61a8
xorl %esi, %esi
movl $0x70, %edx
callq 0x2110
movq $0x400, 0x3780(%rip) # imm = 0x400
movl $0x1e, %edi
callq 0x2220
subq $0x1, %rax
addq $0x400, %rax            # imm = 0x400
movq %rax, -0x120(%rbp)
movl $0x1e, %edi
callq 0x2220
movq %rax, %rcx
movq -0x120(%rbp), %rax
cqto
idivq %rcx
movq %rax, -0x118(%rbp)
movl $0x1e, %edi
callq 0x2220
movq -0x118(%rbp), %rdi
imulq %rax, %rdi
callq 0x21a0
movq %rax, 0x371c(%rip)      # 0x6208
cmpq $0x0, 0x3714(%rip)      # 0x6208
jne 0x2b0e
leaq 0x165f(%rip), %rdi      # 0x415c
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
movq 0x36f3(%rip), %rdi      # 0x6208
movq 0x366c(%rip), %rdx      # 0x6188
movl $0x1, %eax
xorl %ecx, %ecx
cmpq $0x0, %rdx
cmovnel %ecx, %eax
addl $0x7b, %eax
movl $0x400, %edx            # imm = 0x400
movzbl %al, %esi
callq 0x2110
xorl %eax, %eax
movl %eax, %edi
callq 0x2280
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
jne 0x2b66
leaq 0x1624(%rip), %rdi      # 0x4179
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
movq -0x38(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
jne 0x2b90
leaq 0x161a(%rip), %rdi      # 0x4199
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
movq -0x38(%rbp), %rax
movq (%rax), %rdi
callq 0x2040
movq %rax, 0x3605(%rip)      # 0x61a8
cmpq $0x0, 0x35fd(%rip)      # 0x61a8
jne 0x2beb
movq 0x3444(%rip), %rax      # 0x5ff8
movq (%rax), %rax
movq %rax, -0x130(%rbp)
movq -0x40(%rbp), %rdi
callq 0x2060
movq -0x130(%rbp), %rdi
movq %rax, %rdx
leaq 0x15d7(%rip), %rsi      # 0x41af
movb $0x0, %al
callq 0x2150
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
movq 0x35b6(%rip), %rdi      # 0x61a8
callq 0x20f0
movq %rax, 0x35b2(%rip)      # 0x61b0
cmpq $0x0, 0x35aa(%rip)      # 0x61b0
jne 0x2c20
leaq 0x15be(%rip), %rdi      # 0x41cd
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
movq 0x3581(%rip), %rdi      # 0x61a8
movl $0x1, %esi
leaq 0x3575(%rip), %rdx      # 0x61a8
addq $0x28, %rdx
callq 0x2f20
cmpl $0x0, %eax
je 0x2c59
leaq 0x15ac(%rip), %rdi      # 0x41f4
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
movq 0x3550(%rip), %rdx      # 0x61b0
movq 0x35a1(%rip), %rcx      # 0x6208
movq 0x35a2(%rip), %rax      # 0x6210
movq %rdx, -0x10(%rbp)
movq %rcx, -0x18(%rbp)
movq %rax, -0x20(%rbp)
movl $0x7, -0x24(%rbp)
movl $0x1, -0x28(%rbp)
cmpl $0x0, -0x28(%rbp)
je 0x2cb5
movl -0x24(%rbp), %eax
andl $0x3ff00000, %eax       # imm = 0x3FF00000
cmpl $0x0, %eax
jne 0x2cb5
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movl -0x24(%rbp), %ecx
callq 0x2270
movq %rax, -0x8(%rbp)
jmp 0x2cd2
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movq -0x18(%rbp), %rcx
movl -0x24(%rbp), %r8d
callq 0x20a0
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, 0x34db(%rip)      # 0x61b8
cmpq $0x0, 0x34d3(%rip)      # 0x61b8
jne 0x2cff
leaq 0x152c(%rip), %rdi      # 0x421a
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
movq 0x34a2(%rip), %rdi      # 0x61a8
movl $0x7d0, %esi            # imm = 0x7D0
xorl %eax, %eax
movl %eax, %ecx
xorl %r8d, %r8d
movq %rcx, %rdx
callq 0x2080
movq %rax, 0x349f(%rip)      # 0x61c0
cmpq $0x0, 0x3497(%rip)      # 0x61c0
jne 0x2d43
leaq 0x150a(%rip), %rdi      # 0x423c
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
movq $0x0, -0x80(%rbp)
movq 0x346e(%rip), %rax      # 0x61c0
movq %rax, -0x78(%rbp)
movq 0x3463(%rip), %rax      # 0x61c0
movq %rax, -0x70(%rbp)
movq $0x0, -0x68(%rbp)
movl $0x3e8, -0x60(%rbp)     # imm = 0x3E8
movl $0x3e8, -0x5c(%rbp)     # imm = 0x3E8
movl $0x1, -0x58(%rbp)
movl $0x1, -0x54(%rbp)
movl $0x0, -0x50(%rbp)
movl $0x2, -0x4c(%rbp)
movl $0x0, -0x48(%rbp)
movq 0x340f(%rip), %rdi      # 0x61b0
leaq -0x80(%rbp), %rsi
callq 0x2260
movq %rax, 0x3417(%rip)      # 0x61c8
cmpq $0x0, 0x340f(%rip)      # 0x61c8
jne 0x2dd3
leaq 0x149d(%rip), %rdi      # 0x425f
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
leaq -0x110(%rbp), %rdi
xorl %esi, %esi
movl $0x90, %edx
callq 0x2110
movl $0x1, -0x110(%rbp)
movl $0x6, -0xf0(%rbp)
movb $0x1, -0x8f(%rbp)
movq 0x33c0(%rip), %rdi      # 0x61c8
leaq -0x110(%rbp), %rsi
movl $0x39, %edx
callq 0x2050
cmpl $0x0, %eax
je 0x2e36
leaq 0x1457(%rip), %rdi      # 0x427c
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
movzwl 0x33b5(%rip), %eax      # 0x61f2
movl %eax, 0x334d(%rip)      # 0x6190
movzbl 0x33b4(%rip), %eax      # 0x61fe
cmpl $0x1, %eax
jne 0x2e70
cmpl $0x0, 0x333a(%rip)      # 0x6190
jne 0x2e70
leaq 0x143b(%rip), %rdi      # 0x429a
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
movq 0x3351(%rip), %rax      # 0x61c8
movl 0x34(%rax), %eax
movl %eax, 0x3314(%rip)      # 0x6194
callq 0x21c0
andq $0xffffff, %rax         # imm = 0xFFFFFF
movl %eax, 0x3307(%rip)      # 0x6198
cmpq $0x0, 0x32ef(%rip)      # 0x6188
je 0x2ebc
callq 0x25d0
cmpl $0x0, %eax
je 0x2eba
leaq 0x1401(%rip), %rdi      # 0x42ad
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
jmp 0x2edd
callq 0x2780
cmpl $0x0, %eax
je 0x2edb
leaq 0x1400(%rip), %rdi      # 0x42cd
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
jmp 0x2edd
callq 0x2940
cmpl $0x0, %eax
je 0x2efc
leaq 0x13ff(%rip), %rdi      # 0x42ed
callq 0x2210
movl $0x1, -0x2c(%rbp)
jmp 0x2f0c
movq -0x38(%rbp), %rdi
callq 0x20b0
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
nopl (%rax,%rax)