From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44734) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XUlNV-000660-1H for qemu-devel@nongnu.org; Thu, 18 Sep 2014 19:44:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XUlN9-0003Xm-0u for qemu-devel@nongnu.org; Thu, 18 Sep 2014 19:44:44 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44967) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XUlN8-0003Lb-QW for qemu-devel@nongnu.org; Thu, 18 Sep 2014 19:44:22 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s8INiHuV020474 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Thu, 18 Sep 2014 19:44:17 -0400 From: John Snow Date: Thu, 18 Sep 2014 19:43:30 -0400 Message-Id: <1411083819-9284-7-git-send-email-jsnow@redhat.com> In-Reply-To: <1411083819-9284-1-git-send-email-jsnow@redhat.com> References: <1411083819-9284-1-git-send-email-jsnow@redhat.com> Subject: [Qemu-devel] [PATCH 06/15] qtest/ahci: Add link_cmd_slot helper List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, mst@redhat.com, armbru@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, John Snow 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 --- 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