From ae029620173239f3643925299790ecc5e1d72db1 Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 5 Feb 2015 12:41:27 -0500 Subject: libqos/ahci: add ahci_io ahci_io is a wrapper around ahci_guest_io that takes a pointer to host memory instead, and will create a guest memory buffer and copy the data to/from as needed and as appropriate for a read/write command, such that after a read, the guest data will be in a host buffer, and for a write, the data will be transmitted to guest memory prior to the block operation. Now that we have all the syntactic sugar functions in place for AHCI, we can convert the identify test to be very, very short. Signed-off-by: John Snow Reviewed-by: Paolo Bonzini Message-id: 1423158090-25580-17-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi --- tests/ahci-test.c | 63 ++++++++++++++++++++++--------------------------------- 1 file changed, 25 insertions(+), 38 deletions(-) (limited to 'tests/ahci-test.c') diff --git a/tests/ahci-test.c b/tests/ahci-test.c index 6e7b76533f..47491fe96c 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -657,56 +657,43 @@ static void ahci_test_port_spec(AHCIQState *ahci, uint8_t port) */ static void ahci_test_identify(AHCIQState *ahci) { - uint32_t data_ptr; uint16_t buff[256]; - unsigned i; + unsigned px; int rc; - AHCICommand *cmd; + const size_t buffsize = 512; g_assert(ahci != NULL); - /* We need to: - * (1) Create a data buffer for the IDENTIFY response to be sent to, - * (2) Create a Command Table Buffer + /** + * This serves as a bit of a tutorial on AHCI device programming: + * + * (1) Create a data buffer for the IDENTIFY response to be sent to + * (2) Create a Command Table buffer, where we will store the + * command and PRDT (Physical Region Descriptor Table) * (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) 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. - * (7) We inform the HBA via PxCI that there is a command ready in slot #0. + * the top of the Command Table buffer. + * (4) Create one or more Physical Region Descriptors (PRDs) that describe + * a location in memory where data may be stored/retrieved. + * (5) Write these PRDTs to the bottom (offset 0x80) of the Command Table. + * (6) Each AHCI port has up to 32 command slots. Each slot contains a + * header that points to a Command Table buffer. Pick an unused slot + * and update it to point to the Command Table we have built. + * (7) Now: Command #n points to our Command Table, and our Command Table + * contains the FIS (that describes our command) and the PRDTL, which + * describes our buffer. + * (8) We inform the HBA via PxCI (Command Issue) that the command in slot + * #n is ready for processing. */ /* Pick the first implemented and running port */ - i = ahci_port_select(ahci); - g_test_message("Selected port %u for test", i); + px = ahci_port_select(ahci); + g_test_message("Selected port %u for test", px); /* Clear out the FIS Receive area and any pending interrupts. */ - ahci_port_clear(ahci, i); - - /* Create a data buffer where we will dump the IDENTIFY data to. */ - data_ptr = ahci_alloc(ahci, 512); - g_assert(data_ptr); - - /* 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 and sanity check response. */ - ahci_command_issue(ahci, cmd); - ahci_command_verify(ahci, cmd); + ahci_port_clear(ahci, px); - /* Last, but not least: Investigate the IDENTIFY response data. */ - memread(data_ptr, &buff, 512); + /* "Read" 512 bytes using CMD_IDENTIFY into the host buffer. */ + ahci_io(ahci, px, CMD_IDENTIFY, &buff, buffsize); /* Check serial number/version in the buffer */ /* NB: IDENTIFY strings are packed in 16bit little endian chunks. -- cgit v1.2.3