static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,

                            PrdtEntry *prdt, int prdt_entries,

                            void(*post_exec)(QPCIDevice *dev, void *ide_base,

                                             uint64_t sector, int nb_sectors))

{

    QPCIDevice *dev;

    void *bmdma_base;

    void *ide_base;

    uintptr_t guest_prdt;

    size_t len;

    bool from_dev;

    uint8_t status;

    int flags;



    dev = get_pci_device(&bmdma_base, &ide_base);



    flags = cmd & ~0xff;

    cmd &= 0xff;



    switch (cmd) {

    case CMD_READ_DMA:

    case CMD_PACKET:

        /* Assuming we only test data reads w/ ATAPI, otherwise we need to know

         * the SCSI command being sent in the packet, too. */

        from_dev = true;

        break;

    case CMD_WRITE_DMA:

        from_dev = false;

        break;

    default:

        g_assert_not_reached();

    }



    if (flags & CMDF_NO_BM) {

        qpci_config_writew(dev, PCI_COMMAND,

                           PCI_COMMAND_IO | PCI_COMMAND_MEMORY);

    }



    /* Select device 0 */

    qpci_io_writeb(dev, ide_base + reg_device, 0 | LBA);



    /* Stop any running transfer, clear any pending interrupt */

    qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0);

    qpci_io_writeb(dev, bmdma_base + bmreg_status, BM_STS_INTR);



    /* Setup PRDT */

    len = sizeof(*prdt) * prdt_entries;

    guest_prdt = guest_alloc(guest_malloc, len);

    memwrite(guest_prdt, prdt, len);

    qpci_io_writel(dev, bmdma_base + bmreg_prdt, guest_prdt);



    /* ATA DMA command */

    if (cmd == CMD_PACKET) {

        /* Enables ATAPI DMA; otherwise PIO is attempted */

        qpci_io_writeb(dev, ide_base + reg_feature, 0x01);

    } else {

        qpci_io_writeb(dev, ide_base + reg_nsectors, nb_sectors);

        qpci_io_writeb(dev, ide_base + reg_lba_low,    sector & 0xff);

        qpci_io_writeb(dev, ide_base + reg_lba_middle, (sector >> 8) & 0xff);

        qpci_io_writeb(dev, ide_base + reg_lba_high,   (sector >> 16) & 0xff);

    }



    qpci_io_writeb(dev, ide_base + reg_command, cmd);



    if (post_exec) {

        post_exec(dev, ide_base, sector, nb_sectors);

    }



    /* Start DMA transfer */

    qpci_io_writeb(dev, bmdma_base + bmreg_cmd,

                   BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0));



    if (flags & CMDF_ABORT) {

        qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0);

    }



    /* Wait for the DMA transfer to complete */

    do {

        status = qpci_io_readb(dev, bmdma_base + bmreg_status);

    } while ((status & (BM_STS_ACTIVE | BM_STS_INTR)) == BM_STS_ACTIVE);



    g_assert_cmpint(get_irq(IDE_PRIMARY_IRQ), ==, !!(status & BM_STS_INTR));



    /* Check IDE status code */

    assert_bit_set(qpci_io_readb(dev, ide_base + reg_status), DRDY);

    assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), BSY | DRQ);



    /* Reading the status register clears the IRQ */

    g_assert(!get_irq(IDE_PRIMARY_IRQ));



    /* Stop DMA transfer if still active */

    if (status & BM_STS_ACTIVE) {

        qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0);

    }



    free_pci_device(dev);



    return status;

}

static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,

                            PrdtEntry *prdt, int prdt_entries,

                            void(*post_exec)(QPCIDevice *dev, void *ide_base,

                                             uint64_t sector, int nb_sectors))

{

    QPCIDevice *dev;

    void *bmdma_base;

    void *ide_base;

    uintptr_t guest_prdt;

    size_t len;

    bool from_dev;

    uint8_t status;

    int flags;



    dev = get_pci_device(&bmdma_base, &ide_base);



    flags = cmd & ~0xff;

    cmd &= 0xff;



    switch (cmd) {

    case CMD_READ_DMA:

    case CMD_PACKET:

        



        from_dev = true;

        break;

    case CMD_WRITE_DMA:

        from_dev = false;

        break;

    default:

        g_assert_not_reached();

    }



    if (flags & CMDF_NO_BM) {

        qpci_config_writew(dev, PCI_COMMAND,

                           PCI_COMMAND_IO | PCI_COMMAND_MEMORY);

    }



    

    qpci_io_writeb(dev, ide_base + reg_device, 0 | LBA);



    

    qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0);

    qpci_io_writeb(dev, bmdma_base + bmreg_status, BM_STS_INTR);



    

    len = sizeof(*prdt) * prdt_entries;

    guest_prdt = guest_alloc(guest_malloc, len);

    memwrite(guest_prdt, prdt, len);

    qpci_io_writel(dev, bmdma_base + bmreg_prdt, guest_prdt);



    

    if (cmd == CMD_PACKET) {

        

        qpci_io_writeb(dev, ide_base + reg_feature, 0x01);

    } else {

        qpci_io_writeb(dev, ide_base + reg_nsectors, nb_sectors);

        qpci_io_writeb(dev, ide_base + reg_lba_low,    sector & 0xff);

        qpci_io_writeb(dev, ide_base + reg_lba_middle, (sector >> 8) & 0xff);

        qpci_io_writeb(dev, ide_base + reg_lba_high,   (sector >> 16) & 0xff);

    }



    qpci_io_writeb(dev, ide_base + reg_command, cmd);



    if (post_exec) {

        post_exec(dev, ide_base, sector, nb_sectors);

    }



    

    qpci_io_writeb(dev, bmdma_base + bmreg_cmd,

                   BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0));



    if (flags & CMDF_ABORT) {

        qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0);

    }



    

    do {

        status = qpci_io_readb(dev, bmdma_base + bmreg_status);

    } while ((status & (BM_STS_ACTIVE | BM_STS_INTR)) == BM_STS_ACTIVE);



    g_assert_cmpint(get_irq(IDE_PRIMARY_IRQ), ==, !!(status & BM_STS_INTR));



    

    assert_bit_set(qpci_io_readb(dev, ide_base + reg_status), DRDY);

    assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), BSY | DRQ);



    

    g_assert(!get_irq(IDE_PRIMARY_IRQ));



    

    if (status & BM_STS_ACTIVE) {

        qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0);

    }



    free_pci_device(dev);



    return status;

}

                            void(*post_exec)(QPCIDevice *dev, void *ide_base,     void *bmdma_base;     void *ide_base;     dev = get_pci_device(&bmdma_base, &ide_base);     qpci_io_writeb(dev, ide_base + reg_device, 0 | LBA);     qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0);     qpci_io_writeb(dev, bmdma_base + bmreg_status, BM_STS_INTR);     qpci_io_writel(dev, bmdma_base + bmreg_prdt, guest_prdt);         qpci_io_writeb(dev, ide_base + reg_feature, 0x01);         qpci_io_writeb(dev, ide_base + reg_nsectors, nb_sectors);         qpci_io_writeb(dev, ide_base + reg_lba_low,    sector & 0xff);         qpci_io_writeb(dev, ide_base + reg_lba_middle, (sector >> 8) & 0xff);         qpci_io_writeb(dev, ide_base + reg_lba_high,   (sector >> 16) & 0xff);     qpci_io_writeb(dev, ide_base + reg_command, cmd);         post_exec(dev, ide_base, sector, nb_sectors);     qpci_io_writeb(dev, bmdma_base + bmreg_cmd,         qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0);         status = qpci_io_readb(dev, bmdma_base + bmreg_status);     assert_bit_set(qpci_io_readb(dev, ide_base + reg_status), DRDY);     assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), BSY | DRQ);         qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0);     dev = get_pci_device(&bmdma_base, &ide_base);     dev = get_pci_device(&bmdma_base, &ide_base);     dev = get_pci_device(&bmdma_base, &ide_base);     dev = get_pci_device(&bmdma_base, &ide_base);     dev = get_pci_device(&bmdma_base, &ide_base);     dev = get_pci_device(&bmdma_base, &ide_base);     dev = get_pci_device(&bmdma_base, &ide_base);     dev = get_pci_device(&bmdma_base, &ide_base);     dev = get_pci_device(&bmdma_base, &ide_base);     dev = get_pci_device(&bmdma_base, &ide_base);     dev = get_pci_device(&bmdma_base, &ide_base);     dev = get_pci_device(&bmdma_base, &ide_base);
static int FUNC_0(int VAR_0, uint64_t VAR_8, int VAR_8,

                            PrdtEntry *VAR_3, int VAR_4,

                            void(*VAR_5)(QPCIDevice *VAR_6, void *VAR_9,

                                             uint64_t VAR_8, int VAR_8))

{

    QPCIDevice *VAR_6;

    void *VAR_8;

    void *VAR_9;

    uintptr_t guest_prdt;

    size_t len;

    bool from_dev;

    uint8_t status;

    int VAR_9;



    VAR_6 = get_pci_device(&VAR_8, &VAR_9);



    VAR_9 = VAR_0 & ~0xff;

    VAR_0 &= 0xff;



    switch (VAR_0) {

    case CMD_READ_DMA:

    case CMD_PACKET:

        



        from_dev = true;

        break;

    case CMD_WRITE_DMA:

        from_dev = false;

        break;

    default:

        g_assert_not_reached();

    }



    if (VAR_9 & CMDF_NO_BM) {

        qpci_config_writew(VAR_6, PCI_COMMAND,

                           PCI_COMMAND_IO | PCI_COMMAND_MEMORY);

    }



    

    qpci_io_writeb(VAR_6, VAR_9 + reg_device, 0 | LBA);



    

    qpci_io_writeb(VAR_6, VAR_8 + bmreg_cmd, 0);

    qpci_io_writeb(VAR_6, VAR_8 + bmreg_status, BM_STS_INTR);



    

    len = sizeof(*VAR_3) * VAR_4;

    guest_prdt = guest_alloc(guest_malloc, len);

    memwrite(guest_prdt, VAR_3, len);

    qpci_io_writel(VAR_6, VAR_8 + bmreg_prdt, guest_prdt);



    

    if (VAR_0 == CMD_PACKET) {

        

        qpci_io_writeb(VAR_6, VAR_9 + reg_feature, 0x01);

    } else {

        qpci_io_writeb(VAR_6, VAR_9 + reg_nsectors, VAR_8);

        qpci_io_writeb(VAR_6, VAR_9 + reg_lba_low,    VAR_8 & 0xff);

        qpci_io_writeb(VAR_6, VAR_9 + reg_lba_middle, (VAR_8 >> 8) & 0xff);

        qpci_io_writeb(VAR_6, VAR_9 + reg_lba_high,   (VAR_8 >> 16) & 0xff);

    }



    qpci_io_writeb(VAR_6, VAR_9 + reg_command, VAR_0);



    if (VAR_5) {

        VAR_5(VAR_6, VAR_9, VAR_8, VAR_8);

    }



    

    qpci_io_writeb(VAR_6, VAR_8 + bmreg_cmd,

                   BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0));



    if (VAR_9 & CMDF_ABORT) {

        qpci_io_writeb(VAR_6, VAR_8 + bmreg_cmd, 0);

    }



    

    do {

        status = qpci_io_readb(VAR_6, VAR_8 + bmreg_status);

    } while ((status & (BM_STS_ACTIVE | BM_STS_INTR)) == BM_STS_ACTIVE);



    g_assert_cmpint(get_irq(IDE_PRIMARY_IRQ), ==, !!(status & BM_STS_INTR));



    

    assert_bit_set(qpci_io_readb(VAR_6, VAR_9 + reg_status), DRDY);

    assert_bit_clear(qpci_io_readb(VAR_6, VAR_9 + reg_status), BSY | DRQ);



    

    g_assert(!get_irq(IDE_PRIMARY_IRQ));



    

    if (status & BM_STS_ACTIVE) {

        qpci_io_writeb(VAR_6, VAR_8 + bmreg_cmd, 0);

    }



    free_pci_device(VAR_6);



    return status;

}

static int FUNC_0(int VAR_0, uint64_t VAR_8, int VAR_8,
PrdtEntry *VAR_3, int VAR_4,
void(*VAR_5)(QPCIDevice *VAR_6, void *VAR_9,
uint64_t VAR_8, int VAR_8))
{ QPCIDevice *VAR_6; void *VAR_8; void *VAR_9; uintptr_t guest_prdt; size_t len; bool from_dev; uint8_t status; int VAR_9; VAR_6 = get_pci_device(&VAR_8, &VAR_9); VAR_9 = VAR_0 & ~0xff; VAR_0 &= 0xff; switch (VAR_0) { case CMD_READ_DMA:
case CMD_PACKET:
from_dev = true; break; case CMD_WRITE_DMA:
from_dev = false; break; default:
g_assert_not_reached(); } if (VAR_9 & CMDF_NO_BM) { qpci_config_writew(VAR_6, PCI_COMMAND,
PCI_COMMAND_IO | PCI_COMMAND_MEMORY); } qpci_io_writeb(VAR_6, VAR_9 + reg_device, 0 | LBA); qpci_io_writeb(VAR_6, VAR_8 + bmreg_cmd, 0); qpci_io_writeb(VAR_6, VAR_8 + bmreg_status, BM_STS_INTR); len = sizeof(*VAR_3) * VAR_4; guest_prdt = guest_alloc(guest_malloc, len); memwrite(guest_prdt, VAR_3, len); qpci_io_writel(VAR_6, VAR_8 + bmreg_prdt, guest_prdt); if (VAR_0 == CMD_PACKET) { qpci_io_writeb(VAR_6, VAR_9 + reg_feature, 0x01); } else { qpci_io_writeb(VAR_6, VAR_9 + reg_nsectors, VAR_8); qpci_io_writeb(VAR_6, VAR_9 + reg_lba_low,    VAR_8 & 0xff); qpci_io_writeb(VAR_6, VAR_9 + reg_lba_middle, (VAR_8 >> 8) & 0xff); qpci_io_writeb(VAR_6, VAR_9 + reg_lba_high,   (VAR_8 >> 16) & 0xff); } qpci_io_writeb(VAR_6, VAR_9 + reg_command, VAR_0); if (VAR_5) { VAR_5(VAR_6, VAR_9, VAR_8, VAR_8); } qpci_io_writeb(VAR_6, VAR_8 + bmreg_cmd,
BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0)); if (VAR_9 & CMDF_ABORT) { qpci_io_writeb(VAR_6, VAR_8 + bmreg_cmd, 0); } do { status = qpci_io_readb(VAR_6, VAR_8 + bmreg_status); } while ((status & (BM_STS_ACTIVE | BM_STS_INTR)) == BM_STS_ACTIVE); g_assert_cmpint(get_irq(IDE_PRIMARY_IRQ), ==, !!(status & BM_STS_INTR)); assert_bit_set(qpci_io_readb(VAR_6, VAR_9 + reg_status), DRDY); assert_bit_clear(qpci_io_readb(VAR_6, VAR_9 + reg_status), BSY | DRQ); g_assert(!get_irq(IDE_PRIMARY_IRQ)); if (status & BM_STS_ACTIVE) { qpci_io_writeb(VAR_6, VAR_8 + bmreg_cmd, 0); } free_pci_device(VAR_6); return status; }