int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)

{

    CPUS390XState *env = &cpu->env;

    uint32_t fh;

    ZpciFib fib;

    S390PCIBusDevice *pbdev;

    uint32_t data;

    uint64_t cc = ZPCI_PCI_LS_OK;



    if (env->psw.mask & PSW_MASK_PSTATE) {

        program_interrupt(env, PGM_PRIVILEGED, 6);

        return 0;

    }



    fh = env->regs[r1] >> 32;



    if (fiba & 0x7) {

        program_interrupt(env, PGM_SPECIFICATION, 6);

        return 0;

    }



    pbdev = s390_pci_find_dev_by_fh(fh);

    if (!pbdev) {

        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);

        return 0;

    }



    memset(&fib, 0, sizeof(fib));



    switch (pbdev->state) {

    case ZPCI_FS_RESERVED:

    case ZPCI_FS_STANDBY:

        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);

        return 0;

    case ZPCI_FS_DISABLED:

        if (fh & FH_MASK_ENABLE) {

            setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);

            return 0;

        }

        goto out;

    /* BLOCKED bit is set to one coincident with the setting of ERROR bit.

     * FH Enabled bit is set to one in states of ENABLED, BLOCKED or ERROR. */

    case ZPCI_FS_ERROR:

        fib.fc |= 0x20;

    case ZPCI_FS_BLOCKED:

        fib.fc |= 0x40;

    case ZPCI_FS_ENABLED:

        fib.fc |= 0x80;

        if (pbdev->iommu_enabled) {

            fib.fc |= 0x10;

        }

        if (!(fh & FH_MASK_ENABLE)) {

            env->regs[r1] |= 1ULL << 63;

        }

        break;

    case ZPCI_FS_PERMANENT_ERROR:

        setcc(cpu, ZPCI_PCI_LS_ERR);

        s390_set_status_code(env, r1, ZPCI_STPCIFC_ST_PERM_ERROR);

        return 0;

    }



    stq_p(&fib.pba, pbdev->pba);

    stq_p(&fib.pal, pbdev->pal);

    stq_p(&fib.iota, pbdev->g_iota);

    stq_p(&fib.aibv, pbdev->routes.adapter.ind_addr);

    stq_p(&fib.aisb, pbdev->routes.adapter.summary_addr);

    stq_p(&fib.fmb_addr, pbdev->fmb_addr);



    data = ((uint32_t)pbdev->isc << 28) | ((uint32_t)pbdev->noi << 16) |

           ((uint32_t)pbdev->routes.adapter.ind_offset << 8) |

           ((uint32_t)pbdev->sum << 7) | pbdev->routes.adapter.summary_offset;

    stl_p(&fib.data, data);



out:

    if (s390_cpu_virt_mem_write(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) {

        return 0;

    }



    setcc(cpu, cc);

    return 0;

}

int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)

{

    CPUS390XState *env = &cpu->env;

    uint32_t fh;

    ZpciFib fib;

    S390PCIBusDevice *pbdev;

    uint32_t data;

    uint64_t cc = ZPCI_PCI_LS_OK;



    if (env->psw.mask & PSW_MASK_PSTATE) {

        program_interrupt(env, PGM_PRIVILEGED, 6);

        return 0;

    }



    fh = env->regs[r1] >> 32;



    if (fiba & 0x7) {

        program_interrupt(env, PGM_SPECIFICATION, 6);

        return 0;

    }



    pbdev = s390_pci_find_dev_by_fh(fh);

    if (!pbdev) {

        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);

        return 0;

    }



    memset(&fib, 0, sizeof(fib));



    switch (pbdev->state) {

    case ZPCI_FS_RESERVED:

    case ZPCI_FS_STANDBY:

        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);

        return 0;

    case ZPCI_FS_DISABLED:

        if (fh & FH_MASK_ENABLE) {

            setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);

            return 0;

        }

        goto out;

    



    case ZPCI_FS_ERROR:

        fib.fc |= 0x20;

    case ZPCI_FS_BLOCKED:

        fib.fc |= 0x40;

    case ZPCI_FS_ENABLED:

        fib.fc |= 0x80;

        if (pbdev->iommu_enabled) {

            fib.fc |= 0x10;

        }

        if (!(fh & FH_MASK_ENABLE)) {

            env->regs[r1] |= 1ULL << 63;

        }

        break;

    case ZPCI_FS_PERMANENT_ERROR:

        setcc(cpu, ZPCI_PCI_LS_ERR);

        s390_set_status_code(env, r1, ZPCI_STPCIFC_ST_PERM_ERROR);

        return 0;

    }



    stq_p(&fib.pba, pbdev->pba);

    stq_p(&fib.pal, pbdev->pal);

    stq_p(&fib.iota, pbdev->g_iota);

    stq_p(&fib.aibv, pbdev->routes.adapter.ind_addr);

    stq_p(&fib.aisb, pbdev->routes.adapter.summary_addr);

    stq_p(&fib.fmb_addr, pbdev->fmb_addr);



    data = ((uint32_t)pbdev->isc << 28) | ((uint32_t)pbdev->noi << 16) |

           ((uint32_t)pbdev->routes.adapter.ind_offset << 8) |

           ((uint32_t)pbdev->sum << 7) | pbdev->routes.adapter.summary_offset;

    stl_p(&fib.data, data);



out:

    if (s390_cpu_virt_mem_write(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) {

        return 0;

    }



    setcc(cpu, cc);

    return 0;

}

    pbdev = s390_pci_find_dev_by_fh(fh);
int FUNC_0(S390CPU *VAR_0, uint8_t VAR_1, uint64_t VAR_2, uint8_t VAR_3)

{

    CPUS390XState *env = &VAR_0->env;

    uint32_t fh;

    ZpciFib fib;

    S390PCIBusDevice *pbdev;

    uint32_t data;

    uint64_t cc = ZPCI_PCI_LS_OK;



    if (env->psw.mask & PSW_MASK_PSTATE) {

        program_interrupt(env, PGM_PRIVILEGED, 6);

        return 0;

    }



    fh = env->regs[VAR_1] >> 32;



    if (VAR_2 & 0x7) {

        program_interrupt(env, PGM_SPECIFICATION, 6);

        return 0;

    }



    pbdev = s390_pci_find_dev_by_fh(fh);

    if (!pbdev) {

        setcc(VAR_0, ZPCI_PCI_LS_INVAL_HANDLE);

        return 0;

    }



    memset(&fib, 0, sizeof(fib));



    switch (pbdev->state) {

    case ZPCI_FS_RESERVED:

    case ZPCI_FS_STANDBY:

        setcc(VAR_0, ZPCI_PCI_LS_INVAL_HANDLE);

        return 0;

    case ZPCI_FS_DISABLED:

        if (fh & FH_MASK_ENABLE) {

            setcc(VAR_0, ZPCI_PCI_LS_INVAL_HANDLE);

            return 0;

        }

        goto out;

    



    case ZPCI_FS_ERROR:

        fib.fc |= 0x20;

    case ZPCI_FS_BLOCKED:

        fib.fc |= 0x40;

    case ZPCI_FS_ENABLED:

        fib.fc |= 0x80;

        if (pbdev->iommu_enabled) {

            fib.fc |= 0x10;

        }

        if (!(fh & FH_MASK_ENABLE)) {

            env->regs[VAR_1] |= 1ULL << 63;

        }

        break;

    case ZPCI_FS_PERMANENT_ERROR:

        setcc(VAR_0, ZPCI_PCI_LS_ERR);

        s390_set_status_code(env, VAR_1, ZPCI_STPCIFC_ST_PERM_ERROR);

        return 0;

    }



    stq_p(&fib.pba, pbdev->pba);

    stq_p(&fib.pal, pbdev->pal);

    stq_p(&fib.iota, pbdev->g_iota);

    stq_p(&fib.aibv, pbdev->routes.adapter.ind_addr);

    stq_p(&fib.aisb, pbdev->routes.adapter.summary_addr);

    stq_p(&fib.fmb_addr, pbdev->fmb_addr);



    data = ((uint32_t)pbdev->isc << 28) | ((uint32_t)pbdev->noi << 16) |

           ((uint32_t)pbdev->routes.adapter.ind_offset << 8) |

           ((uint32_t)pbdev->sum << 7) | pbdev->routes.adapter.summary_offset;

    stl_p(&fib.data, data);



out:

    if (s390_cpu_virt_mem_write(VAR_0, VAR_2, VAR_3, (uint8_t *)&fib, sizeof(fib))) {

        return 0;

    }



    setcc(VAR_0, cc);

    return 0;

}

int FUNC_0(S390CPU *VAR_0, uint8_t VAR_1, uint64_t VAR_2, uint8_t VAR_3)
{ CPUS390XState *env = &VAR_0->env; uint32_t fh; ZpciFib fib; S390PCIBusDevice *pbdev; uint32_t data; uint64_t cc = ZPCI_PCI_LS_OK; if (env->psw.mask & PSW_MASK_PSTATE) { program_interrupt(env, PGM_PRIVILEGED, 6); return 0; } fh = env->regs[VAR_1] >> 32; if (VAR_2 & 0x7) { program_interrupt(env, PGM_SPECIFICATION, 6); return 0; } pbdev = s390_pci_find_dev_by_fh(fh); if (!pbdev) { setcc(VAR_0, ZPCI_PCI_LS_INVAL_HANDLE); return 0; } memset(&fib, 0, sizeof(fib)); switch (pbdev->state) { case ZPCI_FS_RESERVED:
case ZPCI_FS_STANDBY:
setcc(VAR_0, ZPCI_PCI_LS_INVAL_HANDLE); return 0; case ZPCI_FS_DISABLED:
if (fh & FH_MASK_ENABLE) { setcc(VAR_0, ZPCI_PCI_LS_INVAL_HANDLE); return 0; } goto out; case ZPCI_FS_ERROR:
fib.fc |= 0x20; case ZPCI_FS_BLOCKED:
fib.fc |= 0x40; case ZPCI_FS_ENABLED:
fib.fc |= 0x80; if (pbdev->iommu_enabled) { fib.fc |= 0x10; } if (!(fh & FH_MASK_ENABLE)) { env->regs[VAR_1] |= 1ULL << 63; } break; case ZPCI_FS_PERMANENT_ERROR:
setcc(VAR_0, ZPCI_PCI_LS_ERR); s390_set_status_code(env, VAR_1, ZPCI_STPCIFC_ST_PERM_ERROR); return 0; } stq_p(&fib.pba, pbdev->pba); stq_p(&fib.pal, pbdev->pal); stq_p(&fib.iota, pbdev->g_iota); stq_p(&fib.aibv, pbdev->routes.adapter.ind_addr); stq_p(&fib.aisb, pbdev->routes.adapter.summary_addr); stq_p(&fib.fmb_addr, pbdev->fmb_addr); data = ((uint32_t)pbdev->isc << 28) | ((uint32_t)pbdev->noi << 16) |
((uint32_t)pbdev->routes.adapter.ind_offset << 8) |
((uint32_t)pbdev->sum << 7) | pbdev->routes.adapter.summary_offset; stl_p(&fib.data, data); out:
if (s390_cpu_virt_mem_write(VAR_0, VAR_2, VAR_3, (uint8_t *)&fib, sizeof(fib))) { return 0; } setcc(VAR_0, cc); return 0; }