aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/ide/ahci.c28
-rw-r--r--hw/ide/ahci.h3
2 files changed, 27 insertions, 4 deletions
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 9647d94..f2acddb 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -854,6 +854,21 @@ static void ncq_cb(void *opaque, int ret)
ncq_tfs->used = 0;
}
+static int is_ncq(uint8_t ata_cmd)
+{
+ /* Based on SATA 3.2 section 13.6.3.2 */
+ switch (ata_cmd) {
+ case READ_FPDMA_QUEUED:
+ case WRITE_FPDMA_QUEUED:
+ case NCQ_NON_DATA:
+ case RECEIVE_FPDMA_QUEUED:
+ case SEND_FPDMA_QUEUED:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
int slot)
{
@@ -919,9 +934,15 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
ncq_cb, ncq_tfs);
break;
default:
- DPRINTF(port, "error: tried to process non-NCQ command as NCQ\n");
+ if (is_ncq(cmd_fis[2])) {
+ DPRINTF(port,
+ "error: unsupported NCQ command (0x%02x) received\n",
+ cmd_fis[2]);
+ } else {
+ DPRINTF(port,
+ "error: tried to process non-NCQ command as NCQ\n");
+ }
qemu_sglist_destroy(&ncq_tfs->sglist);
- break;
}
}
@@ -1013,8 +1034,7 @@ static int handle_cmd(AHCIState *s, int port, int slot)
if (cmd_fis[1] == SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER) {
/* Check for NCQ command */
- if ((cmd_fis[2] == READ_FPDMA_QUEUED) ||
- (cmd_fis[2] == WRITE_FPDMA_QUEUED)) {
+ if (is_ncq(cmd_fis[2])) {
process_ncq_command(s, port, cmd_fis, slot);
goto out;
}
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index b123237..e0d2eb8 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -186,6 +186,9 @@
#define READ_FPDMA_QUEUED 0x60
#define WRITE_FPDMA_QUEUED 0x61
+#define NCQ_NON_DATA 0x63
+#define RECEIVE_FPDMA_QUEUED 0x65
+#define SEND_FPDMA_QUEUED 0x64
#define RES_FIS_DSFIS 0x00
#define RES_FIS_PSFIS 0x20