From: Paolo Bonzini <pbonzini@redhat.com>
To: Kevin Wolf <kwolf@redhat.com>
Cc: qemu-devel@nongnu.org, stefanha@redhat.com
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 [thread overview]
Message-ID: <518A7D20.2080400@redhat.com> (raw)
In-Reply-To: <1368006206-2602-5-git-send-email-kwolf@redhat.com>
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 <kwolf@redhat.com>
> ---
> 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);
next prev parent reply other threads:[~2013-05-08 16:28 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-08 9:43 [Qemu-devel] [PATCH 1.5 0/5] ide: Test cases and a corner case fix Kevin Wolf
2013-05-08 9:43 ` [Qemu-devel] [PATCH 1/5] ide: Reset BMIDEA bit when the bus master is stopped Kevin Wolf
2013-05-08 14:35 ` Stefan Hajnoczi
2013-05-08 9:43 ` [Qemu-devel] [PATCH 2/5] libqos/pci: Enable bus mastering Kevin Wolf
2013-05-08 9:43 ` [Qemu-devel] [PATCH 3/5] qtest: Add IDE test case Kevin Wolf
2013-05-08 9:43 ` [Qemu-devel] [PATCH 4/5] qtest/ide-test: Add simple DMA read/write " Kevin Wolf
2013-05-08 16:28 ` Paolo Bonzini [this message]
2013-05-08 9:43 ` [Qemu-devel] [PATCH 5/5] qtest/ide-test: Test short and long PRDTs Kevin Wolf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=518A7D20.2080400@redhat.com \
--to=pbonzini@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).