[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] [PATCH 10/16] libqos/ahci: add NCQ frame support
From: |
John Snow |
Subject: |
[Qemu-block] [PATCH 10/16] libqos/ahci: add NCQ frame support |
Date: |
Fri, 19 Jun 2015 21:50:41 -0400 |
NCQ frames are generated a little differently than
their non-NCQ cousins. Add support for them.
Signed-off-by: John Snow <address@hidden>
---
tests/libqos/ahci.c | 44 +++++++++++++++++++++++++++++++++++---------
tests/libqos/ahci.h | 29 ++++++++++++++++++++++++++++-
2 files changed, 63 insertions(+), 10 deletions(-)
diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c
index 922af8b..9a4d510 100644
--- a/tests/libqos/ahci.c
+++ b/tests/libqos/ahci.c
@@ -695,19 +695,34 @@ static void command_header_init(AHCICommand *cmd)
static void command_table_init(AHCICommand *cmd)
{
RegH2DFIS *fis = &(cmd->fis);
+ uint16_t sect_count = (cmd->xbytes / AHCI_SECTOR_SIZE);
fis->fis_type = REG_H2D_FIS;
fis->flags = REG_H2D_FIS_CMD; /* "Command" bit */
fis->command = cmd->name;
- cmd->fis.feature_low = 0x00;
- cmd->fis.feature_high = 0x00;
- if (cmd->props->lba28 || cmd->props->lba48) {
- cmd->fis.device = ATA_DEVICE_LBA;
+
+ if (cmd->props->ncq) {
+ NCQFIS *ncqfis = (NCQFIS *)fis;
+ /* NCQ is weird and re-uses FIS frames for unrelated data.
+ * See SATA 3.2, 13.6.4.1 READ FPDMA QUEUED for an example. */
+ ncqfis->sector_low = sect_count & 0xFF;
+ ncqfis->sector_hi = (sect_count >> 8) & 0xFF;
+ ncqfis->device = NCQ_DEVICE_MAGIC;
+ /* Force Unit Access is bit 7 in the device register */
+ ncqfis->tag = 0; /* bits 3-7 are the NCQ tag */
+ ncqfis->prio = 0; /* bits 6,7 are a prio tag */
+ /* RARC bit is bit 0 of TAG field */
+ } else {
+ fis->feature_low = 0x00;
+ fis->feature_high = 0x00;
+ if (cmd->props->lba28 || cmd->props->lba48) {
+ fis->device = ATA_DEVICE_LBA;
+ }
+ fis->count = (cmd->xbytes / AHCI_SECTOR_SIZE);
}
- cmd->fis.count = (cmd->xbytes / AHCI_SECTOR_SIZE);
- cmd->fis.icc = 0x00;
- cmd->fis.control = 0x00;
- memset(cmd->fis.aux, 0x00, ARRAY_SIZE(cmd->fis.aux));
+ fis->icc = 0x00;
+ fis->control = 0x00;
+ memset(fis->aux, 0x00, ARRAY_SIZE(fis->aux));
}
AHCICommand *ahci_command_create(uint8_t command_name)
@@ -721,6 +736,7 @@ AHCICommand *ahci_command_create(uint8_t command_name)
g_assert(!(props->lba28 && props->lba48));
g_assert(!(props->read && props->write));
g_assert(!props->size || props->data);
+ g_assert(!props->ncq || (props->ncq && props->lba48));
/* Defaults and book-keeping */
cmd->props = props;
@@ -789,6 +805,8 @@ void ahci_command_set_buffer(AHCICommand *cmd, uint64_t
buffer)
void ahci_command_set_sizes(AHCICommand *cmd, uint64_t xbytes,
unsigned prd_size)
{
+ uint16_t sect_count;
+
/* Each PRD can describe up to 4MiB, and must not be odd. */
g_assert_cmphex(prd_size, <=, 4096 * 1024);
g_assert_cmphex(prd_size & 0x01, ==, 0x00);
@@ -796,7 +814,15 @@ void ahci_command_set_sizes(AHCICommand *cmd, uint64_t
xbytes,
cmd->prd_size = prd_size;
}
cmd->xbytes = xbytes;
- cmd->fis.count = (cmd->xbytes / AHCI_SECTOR_SIZE);
+ sect_count = (cmd->xbytes / AHCI_SECTOR_SIZE);
+
+ if (cmd->props->ncq) {
+ NCQFIS *nfis = (NCQFIS *)&(cmd->fis);
+ nfis->sector_low = sect_count & 0xFF;
+ nfis->sector_hi = (sect_count >> 8) & 0xFF;
+ } else {
+ cmd->fis.count = sect_count;
+ }
cmd->header.prdtl = size_to_prdtl(cmd->xbytes, cmd->prd_size);
}
diff --git a/tests/libqos/ahci.h b/tests/libqos/ahci.h
index ca8abee..594a1c9 100644
--- a/tests/libqos/ahci.h
+++ b/tests/libqos/ahci.h
@@ -291,8 +291,9 @@ enum {
#define CMDH_PMP (0xF000)
/* ATA device register masks */
-#define ATA_DEVICE_MAGIC 0xA0
+#define ATA_DEVICE_MAGIC 0xA0 /* used in ata1-3 */
#define ATA_DEVICE_LBA 0x40
+#define NCQ_DEVICE_MAGIC 0x40 /* for ncq device registers */
#define ATA_DEVICE_DRIVE 0x10
#define ATA_DEVICE_HEAD 0x0F
@@ -397,6 +398,32 @@ typedef struct RegH2DFIS {
} __attribute__((__packed__)) RegH2DFIS;
/**
+ * Register host-to-device FIS structure, for NCQ commands.
+ * Actually just a RegH2DFIS, but with fields repurposed.
+ * Repurposed fields are annotated below.
+ */
+typedef struct NCQFIS {
+ /* DW0 */
+ uint8_t fis_type;
+ uint8_t flags;
+ uint8_t command;
+ uint8_t sector_low; /* H2D: Feature 7:0 */
+ /* DW1 */
+ uint8_t lba_lo[3];
+ uint8_t device;
+ /* DW2 */
+ uint8_t lba_hi[3];
+ uint8_t sector_hi; /* H2D: Feature 15:8 */
+ /* DW3 */
+ uint8_t tag; /* H2D: Count 0:7 */
+ uint8_t prio; /* H2D: Count 15:8 */
+ uint8_t icc;
+ uint8_t control;
+ /* DW4 */
+ uint8_t aux[4];
+} __attribute__((__packed__)) NCQFIS;
+
+/**
* Command List entry structure.
* The command list contains between 1-32 of these structures.
*/
--
2.1.0
- [Qemu-block] [PATCH 06/16] ahci: add ncq debug checks, (continued)
[Qemu-block] [PATCH 07/16] ahci: ncq sector count correction, John Snow, 2015/06/19
[Qemu-block] [PATCH 09/16] libqos/ahci: fix cmd_sanity for ncq, John Snow, 2015/06/19
[Qemu-block] [PATCH 10/16] libqos/ahci: add NCQ frame support,
John Snow <=
[Qemu-block] [PATCH 11/16] libqos/ahci: edit wait to be ncq aware, John Snow, 2015/06/19
[Qemu-block] [PATCH 12/16] libqos/ahci: adjust expected NCQ interrupts, John Snow, 2015/06/19
[Qemu-block] [PATCH 13/16] libqos/ahci: set the NCQ tag on command_commit, John Snow, 2015/06/19
[Qemu-block] [PATCH 14/16] libqos/ahci: Force all NCQ commands to be LBA48, John Snow, 2015/06/19
[Qemu-block] [PATCH 16/16] qtest/ahci: ncq migration test, John Snow, 2015/06/19
[Qemu-block] [PATCH 15/16] qtest/ahci: simple ncq data test, John Snow, 2015/06/19
Re: [Qemu-block] [PATCH 00/16] ahci: ncq cleanup, part 1, Stefan Hajnoczi, 2015/06/22