static void rtas_ibm_change_msi(sPAPREnvironment *spapr,

                                uint32_t token, uint32_t nargs,

                                target_ulong args, uint32_t nret,

                                target_ulong rets)

{

    uint32_t config_addr = rtas_ld(args, 0);

    uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);

    unsigned int func = rtas_ld(args, 3);

    unsigned int req_num = rtas_ld(args, 4); /* 0 == remove all */

    unsigned int seq_num = rtas_ld(args, 5);

    unsigned int ret_intr_type;

    int ndev, irq;

    sPAPRPHBState *phb = NULL;

    PCIDevice *pdev = NULL;



    switch (func) {

    case RTAS_CHANGE_MSI_FN:

    case RTAS_CHANGE_FN:

        ret_intr_type = RTAS_TYPE_MSI;

        break;

    case RTAS_CHANGE_MSIX_FN:

        ret_intr_type = RTAS_TYPE_MSIX;

        break;

    default:

        fprintf(stderr, "rtas_ibm_change_msi(%u) is not implemented\n", func);

        rtas_st(rets, 0, -3); /* Parameter error */

        return;

    }



    /* Fins sPAPRPHBState */

    phb = find_phb(spapr, buid);

    if (phb) {

        pdev = find_dev(spapr, buid, config_addr);

    }

    if (!phb || !pdev) {

        rtas_st(rets, 0, -3); /* Parameter error */

        return;

    }



    /* Releasing MSIs */

    if (!req_num) {

        ndev = spapr_msicfg_find(phb, config_addr, false);

        if (ndev < 0) {

            trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr);

            rtas_st(rets, 0, -1); /* Hardware error */

            return;

        }

        trace_spapr_pci_msi("Released MSIs", ndev, config_addr);

        rtas_st(rets, 0, 0);

        rtas_st(rets, 1, 0);

        return;

    }



    /* Enabling MSI */



    /* Find a device number in the map to add or reuse the existing one */

    ndev = spapr_msicfg_find(phb, config_addr, true);

    if (ndev >= SPAPR_MSIX_MAX_DEVS || ndev < 0) {

        fprintf(stderr, "No free entry for a new MSI device\n");

        rtas_st(rets, 0, -1); /* Hardware error */

        return;

    }

    trace_spapr_pci_msi("Configuring MSI", ndev, config_addr);



    /* Check if there is an old config and MSI number has not changed */

    if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) {

        /* Unexpected behaviour */

        fprintf(stderr, "Cannot reuse MSI config for device#%d", ndev);

        rtas_st(rets, 0, -1); /* Hardware error */

        return;

    }



    /* There is no cached config, allocate MSIs */

    if (!phb->msi_table[ndev].nvec) {

        irq = spapr_allocate_irq_block(req_num, false);

        if (irq < 0) {

            fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev);

            rtas_st(rets, 0, -1); /* Hardware error */

            return;

        }

        phb->msi_table[ndev].irq = irq;

        phb->msi_table[ndev].nvec = req_num;

        phb->msi_table[ndev].config_addr = config_addr;

    }



    /* Setup MSI/MSIX vectors in the device (via cfgspace or MSIX BAR) */

    spapr_msi_setmsg(pdev, phb->msi_win_addr | (ndev << 16),

                     ret_intr_type == RTAS_TYPE_MSIX, req_num);



    rtas_st(rets, 0, 0);

    rtas_st(rets, 1, req_num);

    rtas_st(rets, 2, ++seq_num);

    rtas_st(rets, 3, ret_intr_type);



    trace_spapr_pci_rtas_ibm_change_msi(func, req_num);

}

static void rtas_ibm_change_msi(sPAPREnvironment *spapr,

                                uint32_t token, uint32_t nargs,

                                target_ulong args, uint32_t nret,

                                target_ulong rets)

{

    uint32_t config_addr = rtas_ld(args, 0);

    uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);

    unsigned int func = rtas_ld(args, 3);

    unsigned int req_num = rtas_ld(args, 4); 

    unsigned int seq_num = rtas_ld(args, 5);

    unsigned int ret_intr_type;

    int ndev, irq;

    sPAPRPHBState *phb = NULL;

    PCIDevice *pdev = NULL;



    switch (func) {

    case RTAS_CHANGE_MSI_FN:

    case RTAS_CHANGE_FN:

        ret_intr_type = RTAS_TYPE_MSI;

        break;

    case RTAS_CHANGE_MSIX_FN:

        ret_intr_type = RTAS_TYPE_MSIX;

        break;

    default:

        fprintf(stderr, "rtas_ibm_change_msi(%u) is not implemented\n", func);

        rtas_st(rets, 0, -3); 

        return;

    }



    

    phb = find_phb(spapr, buid);

    if (phb) {

        pdev = find_dev(spapr, buid, config_addr);

    }

    if (!phb || !pdev) {

        rtas_st(rets, 0, -3); 

        return;

    }



    

    if (!req_num) {

        ndev = spapr_msicfg_find(phb, config_addr, false);

        if (ndev < 0) {

            trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr);

            rtas_st(rets, 0, -1); 

            return;

        }

        trace_spapr_pci_msi("Released MSIs", ndev, config_addr);

        rtas_st(rets, 0, 0);

        rtas_st(rets, 1, 0);

        return;

    }



    



    

    ndev = spapr_msicfg_find(phb, config_addr, true);

    if (ndev >= SPAPR_MSIX_MAX_DEVS || ndev < 0) {

        fprintf(stderr, "No free entry for a new MSI device\n");

        rtas_st(rets, 0, -1); 

        return;

    }

    trace_spapr_pci_msi("Configuring MSI", ndev, config_addr);



    

    if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) {

        

        fprintf(stderr, "Cannot reuse MSI config for device#%d", ndev);

        rtas_st(rets, 0, -1); 

        return;

    }



    

    if (!phb->msi_table[ndev].nvec) {

        irq = spapr_allocate_irq_block(req_num, false);

        if (irq < 0) {

            fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev);

            rtas_st(rets, 0, -1); 

            return;

        }

        phb->msi_table[ndev].irq = irq;

        phb->msi_table[ndev].nvec = req_num;

        phb->msi_table[ndev].config_addr = config_addr;

    }



    

    spapr_msi_setmsg(pdev, phb->msi_win_addr | (ndev << 16),

                     ret_intr_type == RTAS_TYPE_MSIX, req_num);



    rtas_st(rets, 0, 0);

    rtas_st(rets, 1, req_num);

    rtas_st(rets, 2, ++seq_num);

    rtas_st(rets, 3, ret_intr_type);



    trace_spapr_pci_rtas_ibm_change_msi(func, req_num);

}

static void FUNC_0(sPAPREnvironment *VAR_0,

                                uint32_t VAR_1, uint32_t VAR_2,

                                target_ulong VAR_3, uint32_t VAR_4,

                                target_ulong VAR_5)

{

    uint32_t config_addr = rtas_ld(VAR_3, 0);

    uint64_t buid = ((uint64_t)rtas_ld(VAR_3, 1) << 32) | rtas_ld(VAR_3, 2);

    unsigned int VAR_6 = rtas_ld(VAR_3, 3);

    unsigned int VAR_7 = rtas_ld(VAR_3, 4); 

    unsigned int VAR_8 = rtas_ld(VAR_3, 5);

    unsigned int VAR_9;

    int VAR_10, VAR_11;

    sPAPRPHBState *phb = NULL;

    PCIDevice *pdev = NULL;



    switch (VAR_6) {

    case RTAS_CHANGE_MSI_FN:

    case RTAS_CHANGE_FN:

        VAR_9 = RTAS_TYPE_MSI;

        break;

    case RTAS_CHANGE_MSIX_FN:

        VAR_9 = RTAS_TYPE_MSIX;

        break;

    default:

        fprintf(stderr, "FUNC_0(%u) is not implemented\n", VAR_6);

        rtas_st(VAR_5, 0, -3); 

        return;

    }



    

    phb = find_phb(VAR_0, buid);

    if (phb) {

        pdev = find_dev(VAR_0, buid, config_addr);

    }

    if (!phb || !pdev) {

        rtas_st(VAR_5, 0, -3); 

        return;

    }



    

    if (!VAR_7) {

        VAR_10 = spapr_msicfg_find(phb, config_addr, false);

        if (VAR_10 < 0) {

            trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr);

            rtas_st(VAR_5, 0, -1); 

            return;

        }

        trace_spapr_pci_msi("Released MSIs", VAR_10, config_addr);

        rtas_st(VAR_5, 0, 0);

        rtas_st(VAR_5, 1, 0);

        return;

    }



    



    

    VAR_10 = spapr_msicfg_find(phb, config_addr, true);

    if (VAR_10 >= SPAPR_MSIX_MAX_DEVS || VAR_10 < 0) {

        fprintf(stderr, "No free entry for a new MSI device\n");

        rtas_st(VAR_5, 0, -1); 

        return;

    }

    trace_spapr_pci_msi("Configuring MSI", VAR_10, config_addr);



    

    if (phb->msi_table[VAR_10].nvec && (VAR_7 != phb->msi_table[VAR_10].nvec)) {

        

        fprintf(stderr, "Cannot reuse MSI config for device#%d", VAR_10);

        rtas_st(VAR_5, 0, -1); 

        return;

    }



    

    if (!phb->msi_table[VAR_10].nvec) {

        VAR_11 = spapr_allocate_irq_block(VAR_7, false);

        if (VAR_11 < 0) {

            fprintf(stderr, "Cannot allocate MSIs for device#%d", VAR_10);

            rtas_st(VAR_5, 0, -1); 

            return;

        }

        phb->msi_table[VAR_10].VAR_11 = VAR_11;

        phb->msi_table[VAR_10].nvec = VAR_7;

        phb->msi_table[VAR_10].config_addr = config_addr;

    }



    

    spapr_msi_setmsg(pdev, phb->msi_win_addr | (VAR_10 << 16),

                     VAR_9 == RTAS_TYPE_MSIX, VAR_7);



    rtas_st(VAR_5, 0, 0);

    rtas_st(VAR_5, 1, VAR_7);

    rtas_st(VAR_5, 2, ++VAR_8);

    rtas_st(VAR_5, 3, VAR_9);



    trace_spapr_pci_rtas_ibm_change_msi(VAR_6, VAR_7);

}

static void FUNC_0(sPAPREnvironment *VAR_0,
uint32_t VAR_1, uint32_t VAR_2,
target_ulong VAR_3, uint32_t VAR_4,
target_ulong VAR_5)
{ uint32_t config_addr = rtas_ld(VAR_3, 0); uint64_t buid = ((uint64_t)rtas_ld(VAR_3, 1) << 32) | rtas_ld(VAR_3, 2); unsigned int VAR_6 = rtas_ld(VAR_3, 3); unsigned int VAR_7 = rtas_ld(VAR_3, 4); unsigned int VAR_8 = rtas_ld(VAR_3, 5); unsigned int VAR_9; int VAR_10, VAR_11; sPAPRPHBState *phb = NULL; PCIDevice *pdev = NULL; switch (VAR_6) { case RTAS_CHANGE_MSI_FN:
case RTAS_CHANGE_FN:
VAR_9 = RTAS_TYPE_MSI; break; case RTAS_CHANGE_MSIX_FN:
VAR_9 = RTAS_TYPE_MSIX; break; default:
fprintf(stderr, "FUNC_0(%u) is not implemented\n", VAR_6); rtas_st(VAR_5, 0, -3); return; } phb = find_phb(VAR_0, buid); if (phb) { pdev = find_dev(VAR_0, buid, config_addr); } if (!phb || !pdev) { rtas_st(VAR_5, 0, -3); return; } if (!VAR_7) { VAR_10 = spapr_msicfg_find(phb, config_addr, false); if (VAR_10 < 0) { trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr); rtas_st(VAR_5, 0, -1); return; } trace_spapr_pci_msi("Released MSIs", VAR_10, config_addr); rtas_st(VAR_5, 0, 0); rtas_st(VAR_5, 1, 0); return; } VAR_10 = spapr_msicfg_find(phb, config_addr, true); if (VAR_10 >= SPAPR_MSIX_MAX_DEVS || VAR_10 < 0) { fprintf(stderr, "No free entry for a new MSI device\n"); rtas_st(VAR_5, 0, -1); return; } trace_spapr_pci_msi("Configuring MSI", VAR_10, config_addr); if (phb->msi_table[VAR_10].nvec && (VAR_7 != phb->msi_table[VAR_10].nvec)) { fprintf(stderr, "Cannot reuse MSI config for device#%d", VAR_10); rtas_st(VAR_5, 0, -1); return; } if (!phb->msi_table[VAR_10].nvec) { VAR_11 = spapr_allocate_irq_block(VAR_7, false); if (VAR_11 < 0) { fprintf(stderr, "Cannot allocate MSIs for device#%d", VAR_10); rtas_st(VAR_5, 0, -1); return; } phb->msi_table[VAR_10].VAR_11 = VAR_11; phb->msi_table[VAR_10].nvec = VAR_7; phb->msi_table[VAR_10].config_addr = config_addr; } spapr_msi_setmsg(pdev, phb->msi_win_addr | (VAR_10 << 16),
VAR_9 == RTAS_TYPE_MSIX, VAR_7); rtas_st(VAR_5, 0, 0); rtas_st(VAR_5, 1, VAR_7); rtas_st(VAR_5, 2, ++VAR_8); rtas_st(VAR_5, 3, VAR_9); trace_spapr_pci_rtas_ibm_change_msi(VAR_6, VAR_7); }