qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 06/15] qtest/ahci: Add link_cmd_slot helper


From: John Snow
Subject: [Qemu-devel] [PATCH 06/15] qtest/ahci: Add link_cmd_slot helper
Date: Thu, 18 Sep 2014 19:43:30 -0400

link_cmd_slot creates the command header, by
setting a pointer to the command table as well as
adjusting other metadata, like DMA direction and
PRDT length.

It effectively links a command, via its table,
to the indicated command slot.

Signed-off-by: John Snow <address@hidden>
---
 tests/ahci-test.c | 72 +++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 57 insertions(+), 15 deletions(-)

diff --git a/tests/ahci-test.c b/tests/ahci-test.c
index f07495f..3e65435 100644
--- a/tests/ahci-test.c
+++ b/tests/ahci-test.c
@@ -252,11 +252,26 @@
 #define AHCI_VERSION_1_2         (0x00010200)
 #define AHCI_VERSION_1_3         (0x00010300)
 
+/* AHCI COMMAND HEADER FLAGS */
+
+#define CMDH_CFL        (0x1F)
+#define CMDH_ATAPI      (0x20)
+#define CMDH_READ       (0x00) /* Fake. */
+#define CMDH_WRITE      (0x40)
+#define CMDH_PREFETCH   (0x80)
+#define CMDH_RESET     (0x100)
+#define CMDH_BIST      (0x200)
+#define CMDH_CLR_BSY   (0x400)
+#define CMDH_RES       (0x800)
+#define CMDH_PMP      (0xF000)
+
 /*** Structures ***/
 
 typedef struct AHCIPortState {
     uint64_t fb;
     uint64_t clb;
+    uint64_t _ctba;
+    uint16_t _prdtl;
     uint64_t ctba[32];
     uint16_t prdtl[32];
     uint8_t next; /** Next Command Slot to Use **/
@@ -341,8 +356,7 @@ typedef struct RegH2DFIS {
  * The command list contains between 1-32 of these structures.
  */
 typedef struct AHCICommand {
-    uint8_t b1;
-    uint8_t b2;
+    uint16_t flags; /* Cmd-Fis-Len, PMP#, and flags. */
     uint16_t prdtl; /* Phys Region Desc. Table Length */
     uint32_t prdbc; /* Phys Region Desc. Byte Count */
     uint64_t ctba;  /* Command Table Descriptor Base Address */
@@ -1286,6 +1300,7 @@ static void get_command_header(AHCIState *ahci, uint8_t 
px,
     ba += cx * sizeof(AHCICommand);
     memread(ba, cmd, sizeof(AHCICommand));
 
+    cmd->flags = le16_to_cpu(cmd->flags);
     cmd->prdtl = le16_to_cpu(cmd->prdtl);
     cmd->prdbc = le32_to_cpu(cmd->prdbc);
     cmd->ctba = le64_to_cpu(cmd->ctba);
@@ -1298,6 +1313,7 @@ static void set_command_header(AHCIState *ahci, uint8_t 
px,
     uint64_t ba = ahci->port[px].clb;
     ba += cx * sizeof(AHCICommand);
 
+    cmd->flags = cpu_to_le16(cmd->flags);
     cmd->prdtl = cpu_to_le16(cmd->prdtl);
     cmd->prdbc = cpu_to_le32(cmd->prdbc);
     cmd->ctba = cpu_to_le64(cmd->ctba);
@@ -1408,10 +1424,47 @@ static uint64_t build_cmd_table(AHCIState *ahci, 
uint8_t px, size_t sz,
     /* Commit the Command FIS to the Command Table */
     memwrite(table_ptr, &fis, sizeof(fis));
 
+    /* Bookmark these values. */
+    ahci->port[px]._prdtl = prdtl;
+    ahci->port[px]._ctba = table_ptr;
+
     return table_ptr;
 }
 
 /**
+ * Given a pointer to a Command Table, create a Command Header for it and write
+ * it to a free slot in the Command List buffer.
+ * @return The command slot number we picked.
+ */
+static unsigned link_cmd_slot(AHCIState *ahci, uint8_t px, uint64_t table_ptr,
+                              uint8_t cmdh_flags)
+{
+    AHCICommand cmd = { .flags = 0 };
+    uint8_t cx;
+
+    cx = pick_cmd(ahci, px);
+
+    /* Construct our Command Header */
+    cmd.flags = 5;
+    cmd.flags |= CMDH_CLR_BSY;
+    cmd.flags |= cmdh_flags;
+    cmd.prdtl = (table_ptr == ahci->port[px]._ctba) ? ahci->port[px]._prdtl : 
1;
+    cmd.prdbc = 0;
+    cmd.ctba = table_ptr;
+
+    /* Commit Command #cx, pointing to the Table, to the Command List Buffer. 
*/
+    set_command_header(ahci, px, cx, &cmd);
+
+    /* For convenience only. */
+    ahci->port[px].ctba[cx] = table_ptr;
+    ahci->port[px].prdtl[cx] = cmd.prdtl;
+    ahci->port[px]._ctba = 0;
+    ahci->port[px]._prdtl = 0;
+
+    return cx;
+}
+
+/**
  * Utilizing an initialized AHCI HBA, issue an IDENTIFY command to the first
  * device we see, then read and check the response.
  */
@@ -1458,19 +1511,8 @@ static void ahci_test_identify(AHCIState *ahci)
     /* 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);
-
-    /* Construct our Command Header (set_command_header handles endianness.) */
-    memset(&cmd, 0x00, sizeof(cmd));
-    cmd.b1 = 5;    /* reg_h2d_fis is 5 double-words long */
-    cmd.b2 = 0x04; /* clear PxTFD.STS.BSY when done */
-    cmd.prdtl = 1; /* One PRD table entry. */
-    cmd.prdbc = 0;
-    cmd.ctba = table_ptr;
-
-    /* Commit Command #cx, pointing to the Table, to the Command List Buffer. 
*/
-    set_command_header(ahci, i, cx, &cmd);
+    /* Pick a command slot and link it to the command table we've built */
+    cx = link_cmd_slot(ahci, i, table_ptr, CMDH_READ);
 
     /* Everything is in place, but we haven't given the go-ahead yet,
      * so we should find that there are no pending interrupts yet. */
-- 
1.9.3




reply via email to

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