int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)

{

    CPUS390XState *env = &cpu->env;

    uint32_t fh;

    S390PCIBusDevice *pbdev;

    S390PCIIOMMU *iommu;

    hwaddr start, end;

    IOMMUTLBEntry entry;

    MemoryRegion *mr;



    cpu_synchronize_state(CPU(cpu));



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

        program_interrupt(env, PGM_PRIVILEGED, 4);

        goto out;

    }



    if (r2 & 0x1) {

        program_interrupt(env, PGM_SPECIFICATION, 4);

        goto out;

    }



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

    start = env->regs[r2];

    end = start + env->regs[r2 + 1];



    pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);

    if (!pbdev) {

        DPRINTF("rpcit no pci dev\n");

        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);

        goto out;

    }



    switch (pbdev->state) {

    case ZPCI_FS_RESERVED:

    case ZPCI_FS_STANDBY:

    case ZPCI_FS_DISABLED:

    case ZPCI_FS_PERMANENT_ERROR:

        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);

        return 0;

    case ZPCI_FS_ERROR:

        setcc(cpu, ZPCI_PCI_LS_ERR);

        s390_set_status_code(env, r1, ZPCI_MOD_ST_ERROR_RECOVER);

        return 0;

    default:

        break;

    }



    iommu = pbdev->iommu;

    if (!iommu->g_iota) {

        pbdev->state = ZPCI_FS_ERROR;

        setcc(cpu, ZPCI_PCI_LS_ERR);

        s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);

        s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid,

                                      start, 0);

        goto out;

    }



    if (end < iommu->pba || start > iommu->pal) {

        pbdev->state = ZPCI_FS_ERROR;

        setcc(cpu, ZPCI_PCI_LS_ERR);

        s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);

        s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid,

                                      start, 0);

        goto out;

    }



    mr = &iommu->iommu_mr;

    while (start < end) {

        entry = mr->iommu_ops->translate(mr, start, 0);



        if (!entry.translated_addr) {

            pbdev->state = ZPCI_FS_ERROR;

            setcc(cpu, ZPCI_PCI_LS_ERR);

            s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);

            s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid,

                                          start, ERR_EVENT_Q_BIT);

            goto out;

        }



        memory_region_notify_iommu(mr, entry);

        start += entry.addr_mask + 1;

    }



    setcc(cpu, ZPCI_PCI_LS_OK);

out:

    return 0;

}

int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)

{

    CPUS390XState *env = &cpu->env;

    uint32_t fh;

    S390PCIBusDevice *pbdev;

    S390PCIIOMMU *iommu;

    hwaddr start, end;

    IOMMUTLBEntry entry;

    MemoryRegion *mr;



    cpu_synchronize_state(CPU(cpu));



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

        program_interrupt(env, PGM_PRIVILEGED, 4);

        goto out;

    }



    if (r2 & 0x1) {

        program_interrupt(env, PGM_SPECIFICATION, 4);

        goto out;

    }



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

    start = env->regs[r2];

    end = start + env->regs[r2 + 1];



    pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);

    if (!pbdev) {

        DPRINTF("rpcit no pci dev\n");

        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);

        goto out;

    }



    switch (pbdev->state) {

    case ZPCI_FS_RESERVED:

    case ZPCI_FS_STANDBY:

    case ZPCI_FS_DISABLED:

    case ZPCI_FS_PERMANENT_ERROR:

        setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);

        return 0;

    case ZPCI_FS_ERROR:

        setcc(cpu, ZPCI_PCI_LS_ERR);

        s390_set_status_code(env, r1, ZPCI_MOD_ST_ERROR_RECOVER);

        return 0;

    default:

        break;

    }



    iommu = pbdev->iommu;

    if (!iommu->g_iota) {

        pbdev->state = ZPCI_FS_ERROR;

        setcc(cpu, ZPCI_PCI_LS_ERR);

        s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);

        s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid,

                                      start, 0);

        goto out;

    }



    if (end < iommu->pba || start > iommu->pal) {

        pbdev->state = ZPCI_FS_ERROR;

        setcc(cpu, ZPCI_PCI_LS_ERR);

        s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);

        s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid,

                                      start, 0);

        goto out;

    }



    mr = &iommu->iommu_mr;

    while (start < end) {

        entry = mr->iommu_ops->translate(mr, start, 0);



        if (!entry.translated_addr) {

            pbdev->state = ZPCI_FS_ERROR;

            setcc(cpu, ZPCI_PCI_LS_ERR);

            s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);

            s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid,

                                          start, ERR_EVENT_Q_BIT);

            goto out;

        }



        memory_region_notify_iommu(mr, entry);

        start += entry.addr_mask + 1;

    }



    setcc(cpu, ZPCI_PCI_LS_OK);

out:

    return 0;

}

int FUNC_0(S390CPU *VAR_0, uint8_t VAR_1, uint8_t VAR_2)

{

    CPUS390XState *env = &VAR_0->env;

    uint32_t fh;

    S390PCIBusDevice *pbdev;

    S390PCIIOMMU *iommu;

    hwaddr start, end;

    IOMMUTLBEntry entry;

    MemoryRegion *mr;



    cpu_synchronize_state(CPU(VAR_0));



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

        program_interrupt(env, PGM_PRIVILEGED, 4);

        goto out;

    }



    if (VAR_2 & 0x1) {

        program_interrupt(env, PGM_SPECIFICATION, 4);

        goto out;

    }



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

    start = env->regs[VAR_2];

    end = start + env->regs[VAR_2 + 1];



    pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);

    if (!pbdev) {

        DPRINTF("rpcit no pci dev\n");

        setcc(VAR_0, ZPCI_PCI_LS_INVAL_HANDLE);

        goto out;

    }



    switch (pbdev->state) {

    case ZPCI_FS_RESERVED:

    case ZPCI_FS_STANDBY:

    case ZPCI_FS_DISABLED:

    case ZPCI_FS_PERMANENT_ERROR:

        setcc(VAR_0, ZPCI_PCI_LS_INVAL_HANDLE);

        return 0;

    case ZPCI_FS_ERROR:

        setcc(VAR_0, ZPCI_PCI_LS_ERR);

        s390_set_status_code(env, VAR_1, ZPCI_MOD_ST_ERROR_RECOVER);

        return 0;

    default:

        break;

    }



    iommu = pbdev->iommu;

    if (!iommu->g_iota) {

        pbdev->state = ZPCI_FS_ERROR;

        setcc(VAR_0, ZPCI_PCI_LS_ERR);

        s390_set_status_code(env, VAR_1, ZPCI_PCI_ST_INSUF_RES);

        s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid,

                                      start, 0);

        goto out;

    }



    if (end < iommu->pba || start > iommu->pal) {

        pbdev->state = ZPCI_FS_ERROR;

        setcc(VAR_0, ZPCI_PCI_LS_ERR);

        s390_set_status_code(env, VAR_1, ZPCI_PCI_ST_INSUF_RES);

        s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid,

                                      start, 0);

        goto out;

    }



    mr = &iommu->iommu_mr;

    while (start < end) {

        entry = mr->iommu_ops->translate(mr, start, 0);



        if (!entry.translated_addr) {

            pbdev->state = ZPCI_FS_ERROR;

            setcc(VAR_0, ZPCI_PCI_LS_ERR);

            s390_set_status_code(env, VAR_1, ZPCI_PCI_ST_INSUF_RES);

            s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid,

                                          start, ERR_EVENT_Q_BIT);

            goto out;

        }



        memory_region_notify_iommu(mr, entry);

        start += entry.addr_mask + 1;

    }



    setcc(VAR_0, ZPCI_PCI_LS_OK);

out:

    return 0;

}

int FUNC_0(S390CPU *VAR_0, uint8_t VAR_1, uint8_t VAR_2)
{ CPUS390XState *env = &VAR_0->env; uint32_t fh; S390PCIBusDevice *pbdev; S390PCIIOMMU *iommu; hwaddr start, end; IOMMUTLBEntry entry; MemoryRegion *mr; cpu_synchronize_state(CPU(VAR_0)); if (env->psw.mask & PSW_MASK_PSTATE) { program_interrupt(env, PGM_PRIVILEGED, 4); goto out; } if (VAR_2 & 0x1) { program_interrupt(env, PGM_SPECIFICATION, 4); goto out; } fh = env->regs[VAR_1] >> 32; start = env->regs[VAR_2]; end = start + env->regs[VAR_2 + 1]; pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh); if (!pbdev) { DPRINTF("rpcit no pci dev\n"); setcc(VAR_0, ZPCI_PCI_LS_INVAL_HANDLE); goto out; } switch (pbdev->state) { case ZPCI_FS_RESERVED:
case ZPCI_FS_STANDBY:
case ZPCI_FS_DISABLED:
case ZPCI_FS_PERMANENT_ERROR:
setcc(VAR_0, ZPCI_PCI_LS_INVAL_HANDLE); return 0; case ZPCI_FS_ERROR:
setcc(VAR_0, ZPCI_PCI_LS_ERR); s390_set_status_code(env, VAR_1, ZPCI_MOD_ST_ERROR_RECOVER); return 0; default:
break; } iommu = pbdev->iommu; if (!iommu->g_iota) { pbdev->state = ZPCI_FS_ERROR; setcc(VAR_0, ZPCI_PCI_LS_ERR); s390_set_status_code(env, VAR_1, ZPCI_PCI_ST_INSUF_RES); s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid,
start, 0); goto out; } if (end < iommu->pba || start > iommu->pal) { pbdev->state = ZPCI_FS_ERROR; setcc(VAR_0, ZPCI_PCI_LS_ERR); s390_set_status_code(env, VAR_1, ZPCI_PCI_ST_INSUF_RES); s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid,
start, 0); goto out; } mr = &iommu->iommu_mr; while (start < end) { entry = mr->iommu_ops->translate(mr, start, 0); if (!entry.translated_addr) { pbdev->state = ZPCI_FS_ERROR; setcc(VAR_0, ZPCI_PCI_LS_ERR); s390_set_status_code(env, VAR_1, ZPCI_PCI_ST_INSUF_RES); s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid,
start, ERR_EVENT_Q_BIT); goto out; } memory_region_notify_iommu(mr, entry); start += entry.addr_mask + 1; } setcc(VAR_0, ZPCI_PCI_LS_OK); out:
return 0; }