From: John Snow <jsnow@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, mst@redhat.com, armbru@redhat.com,
stefanha@redhat.com, pbonzini@redhat.com,
John Snow <jsnow@redhat.com>
Subject: [Qemu-devel] [PATCH 05/15] qtest/ahci: Add build cmd table helper
Date: Thu, 18 Sep 2014 19:43:29 -0400 [thread overview]
Message-ID: <1411083819-9284-6-git-send-email-jsnow@redhat.com> (raw)
In-Reply-To: <1411083819-9284-1-git-send-email-jsnow@redhat.com>
build_cmd_table is a helper routine to build
the command table, which consists of the Command
FIS and the Physical Region Descriptor Table.
Signed-off-by: John Snow <jsnow@redhat.com>
---
tests/ahci-test.c | 113 +++++++++++++++++++++++++++++++++++-------------------
1 file changed, 74 insertions(+), 39 deletions(-)
diff --git a/tests/ahci-test.c b/tests/ahci-test.c
index 7a62eef..f07495f 100644
--- a/tests/ahci-test.c
+++ b/tests/ahci-test.c
@@ -1350,6 +1350,67 @@ static unsigned pick_cmd(AHCIState *ahci, uint8_t px)
g_assert_not_reached();
}
+static inline unsigned size_to_prdtl(unsigned bytes, unsigned bytes_per_prd)
+{
+ /* Each PRD can describe up to 4MiB */
+ g_assert_cmphex(bytes_per_prd, <=, 4096 * 1024);
+ g_assert_cmphex(bytes_per_prd & 0x01, ==, 0x00);
+ return (bytes + bytes_per_prd - 1) / bytes_per_prd;
+}
+
+static uint64_t build_cmd_table(AHCIState *ahci, uint8_t px, size_t sz,
+ uint8_t cmd, uint64_t buffer)
+{
+ PRD prd;
+ RegH2DFIS fis;
+
+ const unsigned bytes_per_prd = 4096;
+ unsigned prdtl = size_to_prdtl(sz, bytes_per_prd);
+ unsigned table_size = CMD_TBL_SIZ(prdtl);
+ uint64_t table_ptr;
+ unsigned remaining, i;
+
+ /* Create a Command Table buffer. 0x80 for the bulk,
+ * plus enough room for `prdtl` entries. */
+ table_ptr = guest_alloc(guest_malloc, table_size);
+ g_assert(table_ptr);
+ /* AHCI 1.3 spec states that it must be 0x80 aligned. */
+ ASSERT_BIT_CLEAR(table_ptr, 0x7F);
+
+ /* Construct our Command FIS */
+ memset(&fis, 0x00, sizeof(fis));
+ fis.fis_type = 0x27; /* Register Host-to-Device FIS */
+ fis.flags = 0x80; /* Command FIS. ('C bit') */
+ fis.command = cmd; /* e.g, 0xEC : Identify */
+ fis.count = cpu_to_le16(sz / 512);
+
+ /* Construct the PRDs. */
+ remaining = sz;
+ for (i = 0; i < prdtl; ++i) {
+ prd.dba = cpu_to_le64(buffer + (bytes_per_prd * i));
+ prd.res = 0;
+ if (remaining > bytes_per_prd) {
+ /* Note that byte count is 0-based. */
+ prd.dbc = cpu_to_le32(bytes_per_prd - 1);
+ remaining -= bytes_per_prd;
+ } else {
+ /* Again, dbc is 0-based. */
+ prd.dbc = cpu_to_le32(remaining - 1);
+ remaining = 0;
+ }
+ prd.dbc |= cpu_to_le32(0x80000000); /* Request DPS Interrupt */
+
+ /* Commit the PRD entry to the Command Table */
+ memwrite(table_ptr + 0x80 + (i * sizeof(PRD)),
+ &prd, sizeof(PRD));
+ }
+
+ /* Commit the Command FIS to the Command Table */
+ memwrite(table_ptr, &fis, sizeof(fis));
+
+ return table_ptr;
+}
+
/**
* Utilizing an initialized AHCI HBA, issue an IDENTIFY command to the first
* device we see, then read and check the response.
@@ -1358,9 +1419,7 @@ static void ahci_test_identify(AHCIState *ahci)
{
RegD2HFIS *d2h = g_malloc0(0x20);
RegD2HFIS *pio = g_malloc0(0x20);
- RegH2DFIS fis;
AHCICommand cmd;
- PRD prd;
uint32_t reg, data_ptr;
uint16_t buff[256];
unsigned i;
@@ -1371,17 +1430,18 @@ static void ahci_test_identify(AHCIState *ahci)
g_assert(ahci != NULL);
/* We need to:
- * (1) Create a Command Table Buffer and update the Command List Slot #0
- * to point to this buffer.
- * (2) Construct an FIS host-to-device command structure, and write it to
- * the top of the command table buffer.
- * (3) Create a data buffer for the IDENTIFY response to be sent to
+ * (1) Create a data buffer for the IDENTIFY response to be sent to,
+ * (2) Create a Command Table Buffer
+ * (3) Construct an FIS host-to-device command structure, and write it to
+ * the top of the Command Table Buffer.
* (4) Create a Physical Region Descriptor that points to the data buffer,
- * and write it to the bottom (offset 0x80) of the command table.
- * (5) Now, PxCLB points to the command list, command 0 points to
+ * and write it to the bottom (offset 0x80) of the Command Table.
+ * (5) Obtain a Command List slot, and update this header to point to
+ * the Command Table we built above.
+ * (6) Now, PxCLB points to the command list, command 0 points to
* our table, and our table contains an FIS instruction and a
* PRD that points to our rx buffer.
- * (6) We inform the HBA via PxCI that there is a command ready in slot #0.
+ * (7) We inform the HBA via PxCI that there is a command ready in slot #0.
*/
/* Pick the first implemented and running port */
@@ -1391,16 +1451,13 @@ static void ahci_test_identify(AHCIState *ahci)
/* Clear out the FIS Receive area and any pending interrupts. */
port_clear(ahci, i);
- /* Create a Command Table buffer. 0x80 is the smallest with a PRDTL of 0. */
- /* We need at least one PRD, so round up to the nearest 0x80 multiple. */
- table_ptr = guest_alloc(guest_malloc, CMD_TBL_SIZ(1));
- g_assert(table_ptr);
- ASSERT_BIT_CLEAR(table_ptr, 0x7F);
-
- /* Create a data buffer ... where we will dump the IDENTIFY data to. */
+ /* Create a data buffer where we will dump the IDENTIFY data to. */
data_ptr = guest_alloc(guest_malloc, 512);
g_assert(data_ptr);
+ /* Construct the Command Table (FIS and PRDT) */
+ table_ptr = build_cmd_table(ahci, i, 512, 0xEC, data_ptr);
+
/* pick a command slot (should be 0!) */
cx = pick_cmd(ahci, i);
@@ -1412,28 +1469,6 @@ static void ahci_test_identify(AHCIState *ahci)
cmd.prdbc = 0;
cmd.ctba = table_ptr;
- /* Construct our PRD, noting that DBC is 0-indexed. */
- prd.dba = cpu_to_le64(data_ptr);
- prd.res = 0;
- /* 511+1 bytes, request DPS interrupt */
- prd.dbc = cpu_to_le32(511 | 0x80000000);
-
- /* Construct our Command FIS, Based on http://wiki.osdev.org/AHCI */
- memset(&fis, 0x00, sizeof(fis));
- fis.fis_type = 0x27; /* Register Host-to-Device FIS */
- fis.command = 0xEC; /* IDENTIFY */
- fis.device = 0;
- fis.flags = 0x80; /* Indicate this is a command FIS */
-
- /* We've committed nothing yet, no interrupts should be posted yet. */
- g_assert_cmphex(PX_RREG(i, AHCI_PX_IS), ==, 0);
-
- /* Commit the Command FIS to the Command Table */
- memwrite(table_ptr, &fis, sizeof(fis));
-
- /* Commit the PRD entry to the Command Table */
- memwrite(table_ptr + 0x80, &prd, sizeof(prd));
-
/* Commit Command #cx, pointing to the Table, to the Command List Buffer. */
set_command_header(ahci, i, cx, &cmd);
--
1.9.3
next prev parent reply other threads:[~2014-09-18 23:44 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-18 23:43 [Qemu-devel] [PATCH 00/15] AHCI test helper refactors John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 01/15] qtest/ahci: Add AHCIState structure John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 02/15] qtest/ahci: Add port_select helper John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 03/15] qtest/ahci: Add port_clear helper John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 04/15] qtest/ahci: Add command header helpers John Snow
2014-09-18 23:43 ` John Snow [this message]
2014-09-18 23:43 ` [Qemu-devel] [PATCH 06/15] qtest/ahci: Add link_cmd_slot helper John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 07/15] qtest/ahci: Add port_check_error helper John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 08/15] qtest/ahci: Add issue_command helper John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 09/15] qtest/ahci: Add port_check_interrupts helper John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 10/15] qtest/ahci: Add port_check_nonbusy helper John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 11/15] qtest/ahci: Add cmd response sanity check helpers John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 12/15] qtest/ahci: Enforce zero-leaks for guest mem usage John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 13/15] qtest/ahci: Add a macro bootup routine John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 14/15] qtest/ahci: Add human-readable command names John Snow
2014-09-18 23:43 ` [Qemu-devel] [PATCH 15/15] qtest/ahci: Don't use a magic constant for buffer size John Snow
2014-09-19 10:53 ` [Qemu-devel] [PATCH 00/15] AHCI test helper refactors Markus Armbruster
2014-09-19 12:57 ` Stefan Hajnoczi
2014-09-19 15:28 ` John Snow
2014-11-03 18:41 ` John Snow
2015-01-08 16:25 ` John Snow
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=1411083819-9284-6-git-send-email-jsnow@redhat.com \
--to=jsnow@redhat.com \
--cc=armbru@redhat.com \
--cc=kwolf@redhat.com \
--cc=mst@redhat.com \
--cc=pbonzini@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).