qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 4/5] qtest/ide-test: Add simple DMA read/write t


From: Paolo Bonzini
Subject: Re: [Qemu-devel] [PATCH 4/5] qtest/ide-test: Add simple DMA read/write test case
Date: Wed, 08 May 2013 18:28:16 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130311 Thunderbird/17.0.4

Il 08/05/2013 11:43, Kevin Wolf ha scritto:
> This tests that single sectors can be successfully written and correctly
> read back.
> 
> Signed-off-by: Kevin Wolf <address@hidden>
> ---
>  tests/ide-test.c | 221 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 221 insertions(+)
> 
> diff --git a/tests/ide-test.c b/tests/ide-test.c
> index 45036e3..5fc496f 100644
> --- a/tests/ide-test.c
> +++ b/tests/ide-test.c
> @@ -29,8 +29,12 @@
>  #include <glib.h>
>  
>  #include "libqtest.h"
> +#include "libqos/pci-pc.h"
> +#include "libqos/malloc-pc.h"
>  
>  #include "qemu-common.h"
> +#include "hw/pci/pci_ids.h"
> +#include "hw/pci/pci_regs.h"
>  
>  #define TEST_IMAGE_SIZE 64 * 1024 * 1024
>  
> @@ -60,12 +64,42 @@ enum {
>  };
>  
>  enum {
> +    LBA     = 0x40,
> +};
> +
> +enum {
> +    bmreg_cmd       = 0x0,
> +    bmreg_status    = 0x2,
> +    bmreg_prdt      = 0x4,
> +};
> +
> +enum {
> +    CMD_READ_DMA    = 0xc8,
> +    CMD_WRITE_DMA   = 0xca,
>      CMD_IDENTIFY    = 0xec,
>  };
>  
> +enum {
> +    BM_CMD_START    =  0x1,
> +    BM_CMD_WRITE    =  0x8, /* write = from device to memory */
> +};
> +
> +enum {
> +    BM_STS_ACTIVE   =  0x1,
> +    BM_STS_ERROR    =  0x2,
> +    BM_STS_INTR     =  0x4,
> +};
> +
> +enum {
> +    PRDT_EOT        = 0x80000000,
> +};
> +
>  #define assert_bit_set(data, mask) g_assert_cmphex((data) & (mask), ==, 
> (mask))
>  #define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0)
>  
> +static QPCIBus *pcibus = NULL;
> +static QGuestAllocator *guest_malloc;
> +
>  static char tmp_path[] = "/tmp/qtest.XXXXXX";
>  
>  static void ide_test_start(const char *cmdline_fmt, ...)
> @@ -79,6 +113,7 @@ static void ide_test_start(const char *cmdline_fmt, ...)
>  
>      qtest_start(cmdline);
>      qtest_irq_intercept_in(global_qtest, "ioapic");
> +    guest_malloc = pc_alloc_init();
>  }
>  
>  static void ide_test_quit(void)
> @@ -86,6 +121,188 @@ static void ide_test_quit(void)
>      qtest_quit(global_qtest);
>  }
>  
> +static QPCIDevice *get_pci_device(uint16_t *bmdma_base)
> +{
> +    QPCIDevice *dev;
> +    uint16_t vendor_id, device_id;
> +
> +    if (!pcibus) {
> +        pcibus = qpci_init_pc();
> +    }
> +
> +    /* Find PCI device and verify it's the right one */
> +    dev = qpci_device_find(pcibus, QPCI_DEVFN(IDE_PCI_DEV, IDE_PCI_FUNC));
> +    g_assert(dev != NULL);
> +
> +    vendor_id = qpci_config_readw(dev, PCI_VENDOR_ID);
> +    device_id = qpci_config_readw(dev, PCI_DEVICE_ID);
> +    g_assert(vendor_id == PCI_VENDOR_ID_INTEL);
> +    g_assert(device_id == PCI_DEVICE_ID_INTEL_82371SB_1);
> +
> +    /* Map bmdma BAR */
> +    *bmdma_base = (uint16_t)(uintptr_t) qpci_iomap(dev, 4);
> +
> +    qpci_device_enable(dev);
> +
> +    return dev;
> +}
> +
> +static void free_pci_device(QPCIDevice *dev)
> +{
> +    /* libqos doesn't have a function for this, so free it manually */
> +    g_free(dev);
> +}
> +
> +typedef struct PrdtEntry {
> +    uint32_t addr;
> +    uint32_t size;
> +} QEMU_PACKED PrdtEntry;
> +
> +#define assert_bit_set(data, mask) g_assert_cmphex((data) & (mask), ==, 
> (mask))
> +#define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0)
> +
> +static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
> +                            PrdtEntry *prdt, int prdt_entries)
> +{
> +    QPCIDevice *dev;
> +    uint16_t bmdma_base;
> +    uintptr_t guest_prdt;
> +    size_t len;
> +    bool from_dev;
> +    uint8_t status;
> +
> +    dev = get_pci_device(&bmdma_base);
> +
> +    switch (cmd) {
> +    case CMD_READ_DMA:
> +        from_dev = true;
> +        break;
> +    case CMD_WRITE_DMA:
> +        from_dev = false;
> +        break;
> +    default:
> +        g_assert_not_reached();
> +    }
> +
> +    /* Select device 0 */
> +    outb(IDE_BASE + reg_device, 0 | LBA);
> +
> +    /* Stop any running transfer, clear any pending interrupt */
> +    outb(bmdma_base + bmreg_cmd, 0);
> +    outb(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);

What endianness?

Paolo

> +    outl(bmdma_base + bmreg_prdt, guest_prdt);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]