diff options
author | John Snow <jsnow@redhat.com> | 2015-02-05 12:41:23 -0500 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2015-02-16 15:07:17 +0000 |
commit | 64a5a272e31c99cfb348f908d71c98d2eb83ba28 (patch) | |
tree | 088f9ca5577d6b19e58dbfb78b740610da2bd5e5 /tests/ahci-test.c | |
parent | 716b64079ceaa6fede724f8a24a24b0209fa5173 (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.c | 73 |
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. */ |