diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2022-11-30 13:02:38 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2023-01-06 00:50:32 +0100 |
commit | 1ea17d228e582b1cfbf6f61e9da5fafef4063be8 (patch) | |
tree | 66317c375c866f2052c59526daa6497422533a0f | |
parent | 9b063b7ea697d796914b3651d15c3457b7b1135c (diff) |
ide: Add 8-bit data mode
CompactFlash uses features 0x01 and 0x81 to enable/disable 8-bit data
path. Implement them.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Message-Id: <20221130120238.706717-1-lkundrak@v3.sk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | hw/ide/core.c | 43 | ||||
-rw-r--r-- | include/hw/ide/internal.h | 1 |
2 files changed, 34 insertions, 10 deletions
diff --git a/hw/ide/core.c b/hw/ide/core.c index 39afdc0006..5d1039378f 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -1648,6 +1648,13 @@ static bool cmd_set_features(IDEState *s, uint8_t cmd) /* XXX: valid for CDROM ? */ switch (s->feature) { + case 0x01: /* 8-bit I/O enable (CompactFlash) */ + case 0x81: /* 8-bit I/O disable (CompactFlash) */ + if (s->drive_kind != IDE_CFATA) { + goto abort_cmd; + } + s->io8 = !(s->feature & 0x80); + return true; case 0x02: /* write cache enable */ blk_set_enable_write_cache(s->blk, true); identify_data = (uint16_t *)s->identify_data; @@ -2374,12 +2381,20 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val) } p = s->data_ptr; - if (p + 2 > s->data_end) { - return; - } + if (s->io8) { + if (p + 1 > s->data_end) { + return; + } + + *p++ = val; + } else { + if (p + 2 > s->data_end) { + return; + } - *(uint16_t *)p = le16_to_cpu(val); - p += 2; + *(uint16_t *)p = le16_to_cpu(val); + p += 2; + } s->data_ptr = p; if (p >= s->data_end) { s->status &= ~DRQ_STAT; @@ -2401,12 +2416,20 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr) } p = s->data_ptr; - if (p + 2 > s->data_end) { - return 0; - } + if (s->io8) { + if (p + 1 > s->data_end) { + return 0; + } - ret = cpu_to_le16(*(uint16_t *)p); - p += 2; + ret = *p++; + } else { + if (p + 2 > s->data_end) { + return 0; + } + + ret = cpu_to_le16(*(uint16_t *)p); + p += 2; + } s->data_ptr = p; if (p >= s->data_end) { s->status &= ~DRQ_STAT; diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h index b17f36df95..fc0aa81a88 100644 --- a/include/hw/ide/internal.h +++ b/include/hw/ide/internal.h @@ -402,6 +402,7 @@ struct IDEState { uint8_t select; uint8_t status; + bool io8; bool reset_reverts; /* set for lba48 access */ |