aboutsummaryrefslogtreecommitdiff
path: root/tests/ahci-test.c
diff options
context:
space:
mode:
authorJohn Snow <jsnow@redhat.com>2015-02-05 12:41:23 -0500
committerStefan Hajnoczi <stefanha@redhat.com>2015-02-16 15:07:17 +0000
commit64a5a272e31c99cfb348f908d71c98d2eb83ba28 (patch)
tree088f9ca5577d6b19e58dbfb78b740610da2bd5e5 /tests/ahci-test.c
parent716b64079ceaa6fede724f8a24a24b0209fa5173 (diff)
libqos/ahci: add ahci command functions
This patch adds the AHCICommand structure, and a set of functions to operate on the structure. ahci_command_create - Initialize and create a new AHCICommand in memory ahci_command_free - Destroy this object. ahci_command_set_buffer - Set where the guest memory DMA buffer is. ahci_command_commit - Write this command to the AHCI HBA. ahci_command_issue - Issue the committed command synchronously. ahci_command_issue_async - Issue the committed command asynchronously. ahci_command_wait - Wait for an asynchronous command to finish. ahci_command_slot - Get the number of the command slot we committed to. Helpers: size_to_prdtl - Calculate the required minimum PRDTL size from a buffer size. ahci_command_find - Given an ATA command mnemonic, look it up in the properties table to obtain info about the command. command_header_init - Initialize the command header with sane values. command_table_init - Initialize the command table with sane values. [Peter Maydell <peter.maydell@linaro.org> reported the following clang warning: tests/libqos/ahci.c:598:3: warning: redefinition of typedef 'AHCICommand' is a C11 feature [-Wtypedef-redefinition] } AHCICommand; I have replaced typedef struct ... AHCICommand; with struct ... ; --Stefan] Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: John Snow <jsnow@redhat.com> Message-id: 1423158090-25580-13-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'tests/ahci-test.c')
-rw-r--r--tests/ahci-test.c73
1 files changed, 17 insertions, 56 deletions
diff --git a/tests/ahci-test.c b/tests/ahci-test.c
index 658956d6a1..08340207b3 100644
--- a/tests/ahci-test.c
+++ b/tests/ahci-test.c
@@ -657,30 +657,28 @@ static void ahci_test_port_spec(AHCIQState *ahci, uint8_t port)
*/
static void ahci_test_identify(AHCIQState *ahci)
{
- RegH2DFIS fis;
- AHCICommandHeader cmd;
- PRD prd;
uint32_t data_ptr;
uint16_t buff[256];
unsigned i;
int rc;
+ AHCICommand *cmd;
uint8_t cx;
- uint64_t table;
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
+ * (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.
- * (3) Create a data buffer for the IDENTIFY response to be sent to
* (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
+ * (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 */
@@ -690,61 +688,24 @@ static void ahci_test_identify(AHCIQState *ahci)
/* Clear out the FIS Receive area and any pending interrupts. */
ahci_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 = ahci_alloc(ahci, CMD_TBL_SIZ(1));
- g_assert(table);
- ASSERT_BIT_CLEAR(table, 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 = ahci_alloc(ahci, 512);
g_assert(data_ptr);
- /* pick a command slot (should be 0!) */
- cx = ahci_pick_cmd(ahci, i);
-
- /* Construct our Command Header (set_command_header handles endianness.) */
- memset(&cmd, 0x00, sizeof(cmd));
- cmd.flags = 5; /* reg_h2d_fis is 5 double-words long */
- cmd.flags |= CMDH_CLR_BSY; /* clear PxTFD.STS.BSY when done */
- cmd.prdtl = 1; /* One PRD table entry. */
- cmd.prdbc = 0;
- cmd.ctba = table;
-
- /* 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 = REG_H2D_FIS; /* Register Host-to-Device FIS */
- fis.command = CMD_IDENTIFY;
- fis.device = 0;
- fis.flags = REG_H2D_FIS_CMD; /* Indicate this is a command FIS */
-
- /* We've committed nothing yet, no interrupts should be posted yet. */
- g_assert_cmphex(ahci_px_rreg(ahci, i, AHCI_PX_IS), ==, 0);
-
- /* Commit the Command FIS to the Command Table */
- ahci_write_fis(ahci, &fis, table);
-
- /* Commit the PRD entry to the Command Table */
- memwrite(table + 0x80, &prd, sizeof(prd));
-
- /* Commit Command #cx, pointing to the Table, to the Command List Buffer. */
- ahci_set_command_header(ahci, i, cx, &cmd);
+ /* Construct the Command Table (FIS and PRDT) and Command Header */
+ cmd = ahci_command_create(CMD_IDENTIFY);
+ ahci_command_set_buffer(cmd, data_ptr);
+ /* Write the command header and PRDT to guest memory */
+ ahci_command_commit(ahci, cmd, i);
/* Everything is in place, but we haven't given the go-ahead yet,
* so we should find that there are no pending interrupts yet. */
g_assert_cmphex(ahci_px_rreg(ahci, i, AHCI_PX_IS), ==, 0);
/* Issue Command #cx via PxCI */
- ahci_px_wreg(ahci, i, AHCI_PX_CI, (1 << cx));
- while (BITSET(ahci_px_rreg(ahci, i, AHCI_PX_TFD), AHCI_PX_TFD_STS_BSY)) {
- usleep(50);
- }
+ ahci_command_issue(ahci, cmd);
+ cx = ahci_command_slot(cmd);
+
/* Check registers for post-command consistency */
ahci_port_check_error(ahci, i);
/* BUG: we expect AHCI_PX_IS_DPS to be set. */