Pull request

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+ber27ys35W+dsvQfe+BBqr8OQ4FAl92FLEACgkQfe+BBqr8
 OQ7Wrw//RBz3sjP6AFR1oz4fZk+SvVJcTW/4MONtRRrHrfYCyBSeBY8R0PotsGAm
 ROYRxMS9EdOnJ/tU5Ww0jlJDKwJvo4dKBM5nddR5b6mrquu8xuR4Ln7gsdB6a74I
 b+yyI1Gk1wIbE1H0tV5upLaakK8p9XTHFiilbc4Y1bZrrNbnywIM16GM+IW6CR0h
 PvlvRsV+JtJ+O5+aT8ZpVbmDgUjPumbVkhwlGQy1xzesGF1oZO53eu9P7GvJ9RHd
 wtvwLHcDywNKlqmp0zOyGXPKNeZURIhYnsw4hatCBhjbyJhkJZpQqMQSi2LfHRCi
 iDr31EK3/X0s2b+IeZVbD3It9UH6soTNxWhYW+4xoFNuVfxGSuduoURicNaqrgcM
 ojfXlfLiTeDaX1Uywq96pBeqXTOmLfYgzWlySHvU3UwQaVjMon6VJxeEiPUACTLi
 Go5vpMOTVUOxJiM+xEEYfh1aS49jQDCarmU/bb3ynBofQOvoNFRMmSpgTCGOllPX
 uUNohkrpa7DgdozqwiI8WLkOOsUUHdgn+Fv1OYolEc5yXVOHSTUz4VoEoQ3L76c0
 6NBQfpZYNc0JTu/TQCXdLKdhrsBCbnumspGpmAjw1YutP8Lx/s17pg+FIz2IFcs5
 xY6GeGKXduRCButI7qOctkDe+uYIaXlstApyvxCTZ20VZ2mIXZc=
 =/PcE
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/jsnow-gitlab/tags/ide-pull-request' into staging

Pull request

# gpg: Signature made Thu 01 Oct 2020 18:41:05 BST
# gpg:                using RSA key F9B7ABDBBCACDF95BE76CBD07DEF8106AAFC390E
# gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" [full]
# Primary key fingerprint: FAEB 9711 A12C F475 812F  18F2 88A9 064D 1835 61EB
#      Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76  CBD0 7DEF 8106 AAFC 390E

* remotes/jsnow-gitlab/tags/ide-pull-request:
  ide: cancel pending callbacks on SRST
  ide: clear interrupt on command write
  ide: remove magic constants from the device register
  ide: reorder set/get sector functions
  ide: model HOB correctly
  ide: don't tamper with the device register
  ide: rename cmd_write to ctrl_write
  hw/ide/ahci: Do not dma_memory_unmap(NULL)
  MAINTAINERS: Update my git address

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-10-01 19:55:10 +01:00
commit b5ce42f5d1
9 changed files with 110 additions and 69 deletions

View File

@ -1577,7 +1577,7 @@ F: tests/qtest/ide-test.c
F: tests/qtest/ahci-test.c
F: tests/qtest/cdrom-test.c
F: tests/qtest/libqos/ahci*
T: git https://github.com/jnsnow/qemu.git ide
T: git https://gitlab.com/jsnow/qemu.git ide
IPMI
M: Corey Minyard <minyard@acm.org>
@ -1595,7 +1595,7 @@ S: Supported
F: hw/block/fdc.c
F: include/hw/block/fdc.h
F: tests/qtest/fdc-test.c
T: git https://github.com/jnsnow/qemu.git ide
T: git https://gitlab.com/jsnow/qemu.git ide
OMAP
M: Peter Maydell <peter.maydell@linaro.org>
@ -2169,7 +2169,7 @@ F: block/commit.c
F: block/stream.c
F: block/mirror.c
F: qapi/job.json
T: git https://github.com/jnsnow/qemu.git jobs
T: git https://gitlab.com/jsnow/qemu.git jobs
Block QAPI, monitor, command line
M: Markus Armbruster <armbru@redhat.com>

View File

@ -250,7 +250,7 @@ static void map_page(AddressSpace *as, uint8_t **ptr, uint64_t addr,
}
*ptr = dma_memory_map(as, addr, &len, DMA_DIRECTION_FROM_DEVICE);
if (len < wanted) {
if (len < wanted && *ptr) {
dma_memory_unmap(as, *ptr, len, DMA_DIRECTION_FROM_DEVICE, len);
*ptr = NULL;
}

View File

@ -367,7 +367,7 @@ fill_buffer:
static void ide_set_signature(IDEState *s)
{
s->select &= 0xf0; /* clear head */
s->select &= ~(ATA_DEV_HS); /* clear head */
/* put signature */
s->nsector = 1;
s->sector = 1;
@ -586,48 +586,54 @@ void ide_transfer_stop(IDEState *s)
int64_t ide_get_sector(IDEState *s)
{
int64_t sector_num;
if (s->select & 0x40) {
/* lba */
if (!s->lba48) {
sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |
(s->lcyl << 8) | s->sector;
} else {
if (s->select & (ATA_DEV_LBA)) {
if (s->lba48) {
sector_num = ((int64_t)s->hob_hcyl << 40) |
((int64_t) s->hob_lcyl << 32) |
((int64_t) s->hob_sector << 24) |
((int64_t) s->hcyl << 16) |
((int64_t) s->lcyl << 8) | s->sector;
} else {
/* LBA28 */
sector_num = ((s->select & (ATA_DEV_LBA_MSB)) << 24) |
(s->hcyl << 16) | (s->lcyl << 8) | s->sector;
}
} else {
/* CHS */
sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +
(s->select & 0x0f) * s->sectors + (s->sector - 1);
(s->select & (ATA_DEV_HS)) * s->sectors + (s->sector - 1);
}
return sector_num;
}
void ide_set_sector(IDEState *s, int64_t sector_num)
{
unsigned int cyl, r;
if (s->select & 0x40) {
if (!s->lba48) {
s->select = (s->select & 0xf0) | (sector_num >> 24);
s->hcyl = (sector_num >> 16);
s->lcyl = (sector_num >> 8);
s->sector = (sector_num);
} else {
if (s->select & (ATA_DEV_LBA)) {
if (s->lba48) {
s->sector = sector_num;
s->lcyl = sector_num >> 8;
s->hcyl = sector_num >> 16;
s->hob_sector = sector_num >> 24;
s->hob_lcyl = sector_num >> 32;
s->hob_hcyl = sector_num >> 40;
} else {
/* LBA28 */
s->select = (s->select & ~(ATA_DEV_LBA_MSB)) |
((sector_num >> 24) & (ATA_DEV_LBA_MSB));
s->hcyl = (sector_num >> 16);
s->lcyl = (sector_num >> 8);
s->sector = (sector_num);
}
} else {
/* CHS */
cyl = sector_num / (s->heads * s->sectors);
r = sector_num % (s->heads * s->sectors);
s->hcyl = cyl >> 8;
s->lcyl = cyl;
s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f);
s->select = (s->select & ~(ATA_DEV_HS)) |
((r / s->sectors) & (ATA_DEV_HS));
s->sector = (r % s->sectors) + 1;
}
}
@ -1215,8 +1221,7 @@ static void ide_cmd_lba48_transform(IDEState *s, int lba48)
static void ide_clear_hob(IDEBus *bus)
{
/* any write clears HOB high bit of device control register */
bus->ifs[0].select &= ~(1 << 7);
bus->ifs[1].select &= ~(1 << 7);
bus->cmd &= ~(IDE_CTRL_HOB);
}
/* IOport [W]rite [R]egisters */
@ -1256,12 +1261,14 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
return;
}
/* NOTE: Device0 and Device1 both receive incoming register writes.
* (They're on the same bus! They have to!) */
switch (reg_num) {
case 0:
break;
case ATA_IOPORT_WR_FEATURES:
ide_clear_hob(bus);
/* NOTE: data is written to the two drives */
bus->ifs[0].hob_feature = bus->ifs[0].feature;
bus->ifs[1].hob_feature = bus->ifs[1].feature;
bus->ifs[0].feature = val;
@ -1296,15 +1303,16 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
bus->ifs[1].hcyl = val;
break;
case ATA_IOPORT_WR_DEVICE_HEAD:
/* FIXME: HOB readback uses bit 7 */
bus->ifs[0].select = (val & ~0x10) | 0xa0;
bus->ifs[1].select = (val | 0x10) | 0xa0;
ide_clear_hob(bus);
bus->ifs[0].select = val | (ATA_DEV_ALWAYS_ON);
bus->ifs[1].select = val | (ATA_DEV_ALWAYS_ON);
/* select drive */
bus->unit = (val >> 4) & 1;
bus->unit = (val & (ATA_DEV_SELECT)) ? 1 : 0;
break;
default:
case ATA_IOPORT_WR_COMMAND:
/* command */
ide_clear_hob(bus);
qemu_irq_lower(bus->irq);
ide_exec_cmd(bus, val);
break;
}
@ -1338,7 +1346,7 @@ static void ide_reset(IDEState *s)
s->hob_lcyl = 0;
s->hob_hcyl = 0;
s->select = 0xa0;
s->select = (ATA_DEV_ALWAYS_ON);
s->status = READY_STAT | SEEK_STAT;
s->lba48 = 0;
@ -2142,9 +2150,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr)
int ret, hob;
reg_num = addr & 7;
/* FIXME: HOB readback uses bit 7, but it's always set right now */
//hob = s->select & (1 << 7);
hob = 0;
hob = bus->cmd & (IDE_CTRL_HOB);
switch (reg_num) {
case ATA_IOPORT_RR_DATA:
ret = 0xff;
@ -2235,34 +2241,56 @@ uint32_t ide_status_read(void *opaque, uint32_t addr)
return ret;
}
void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
static void ide_perform_srst(IDEState *s)
{
s->status |= BUSY_STAT;
/* Halt PIO (Via register state); PIO BH remains scheduled. */
ide_transfer_halt(s);
/* Cancel DMA -- may drain block device and invoke callbacks */
ide_cancel_dma_sync(s);
/* Cancel PIO callback, reset registers/signature, etc */
ide_reset(s);
if (s->drive_kind == IDE_CD) {
/* ATAPI drives do not set READY or SEEK */
s->status = 0x00;
}
}
static void ide_bus_perform_srst(void *opaque)
{
IDEBus *bus = opaque;
IDEState *s;
int i;
trace_ide_cmd_write(addr, val, bus);
for (i = 0; i < 2; i++) {
s = &bus->ifs[i];
ide_perform_srst(s);
}
}
/* common for both drives */
if (!(bus->cmd & IDE_CMD_RESET) &&
(val & IDE_CMD_RESET)) {
/* reset low to high */
for(i = 0;i < 2; i++) {
void ide_ctrl_write(void *opaque, uint32_t addr, uint32_t val)
{
IDEBus *bus = opaque;
IDEState *s;
int i;
trace_ide_ctrl_write(addr, val, bus);
/* Device0 and Device1 each have their own control register,
* but QEMU models it as just one register in the controller. */
if ((bus->cmd & IDE_CTRL_RESET) &&
!(val & IDE_CTRL_RESET)) {
/* SRST triggers on falling edge */
for (i = 0; i < 2; i++) {
s = &bus->ifs[i];
s->status = BUSY_STAT | SEEK_STAT;
s->error = 0x01;
}
} else if ((bus->cmd & IDE_CMD_RESET) &&
!(val & IDE_CMD_RESET)) {
/* high to low */
for(i = 0;i < 2; i++) {
s = &bus->ifs[i];
if (s->drive_kind == IDE_CD)
s->status = 0x00; /* NOTE: READY is _not_ set */
else
s->status = READY_STAT | SEEK_STAT;
ide_set_signature(s);
s->status |= BUSY_STAT;
}
aio_bh_schedule_oneshot(qemu_get_aio_context(),
ide_bus_perform_srst, bus);
}
bus->cmd = val;

View File

@ -46,7 +46,7 @@ static const MemoryRegionPortio ide_portio_list[] = {
};
static const MemoryRegionPortio ide_portio2_list[] = {
{ 0, 1, 1, .read = ide_status_read, .write = ide_cmd_write },
{ 0, 1, 1, .read = ide_status_read, .write = ide_ctrl_write },
PORTIO_END_OF_LIST(),
};

View File

@ -329,7 +329,7 @@ static void pmac_ide_write(void *opaque, hwaddr addr, uint64_t val,
case 0x8:
case 0x16:
if (size == 1) {
ide_cmd_write(&d->bus, 0, val);
ide_ctrl_write(&d->bus, 0, val);
}
break;
case 0x20:

View File

@ -98,16 +98,16 @@ static uint64_t mmio_ide_status_read(void *opaque, hwaddr addr,
return ide_status_read(&s->bus, 0);
}
static void mmio_ide_cmd_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
static void mmio_ide_ctrl_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
MMIOState *s = opaque;
ide_cmd_write(&s->bus, 0, val);
ide_ctrl_write(&s->bus, 0, val);
}
static const MemoryRegionOps mmio_ide_cs_ops = {
.read = mmio_ide_status_read,
.write = mmio_ide_cmd_write,
.write = mmio_ide_ctrl_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};

View File

@ -38,7 +38,7 @@
(IDE_RETRY_DMA | IDE_RETRY_PIO | \
IDE_RETRY_READ | IDE_RETRY_FLUSH)
static uint64_t pci_ide_cmd_read(void *opaque, hwaddr addr, unsigned size)
static uint64_t pci_ide_status_read(void *opaque, hwaddr addr, unsigned size)
{
IDEBus *bus = opaque;
@ -48,20 +48,20 @@ static uint64_t pci_ide_cmd_read(void *opaque, hwaddr addr, unsigned size)
return ide_status_read(bus, addr + 2);
}
static void pci_ide_cmd_write(void *opaque, hwaddr addr,
uint64_t data, unsigned size)
static void pci_ide_ctrl_write(void *opaque, hwaddr addr,
uint64_t data, unsigned size)
{
IDEBus *bus = opaque;
if (addr != 2 || size != 1) {
return;
}
ide_cmd_write(bus, addr + 2, data);
ide_ctrl_write(bus, addr + 2, data);
}
const MemoryRegionOps pci_ide_cmd_le_ops = {
.read = pci_ide_cmd_read,
.write = pci_ide_cmd_write,
.read = pci_ide_status_read,
.write = pci_ide_ctrl_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};

View File

@ -5,7 +5,7 @@
ide_ioport_read(uint32_t addr, const char *reg, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (%s); val 0x%02"PRIx32"; bus %p IDEState %p"
ide_ioport_write(uint32_t addr, const char *reg, uint32_t val, void *bus, void *s) "IDE PIO wr @ 0x%"PRIx32" (%s); val 0x%02"PRIx32"; bus %p IDEState %p"
ide_status_read(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (Alt Status); val 0x%02"PRIx32"; bus %p; IDEState %p"
ide_cmd_write(uint32_t addr, uint32_t val, void *bus) "IDE PIO wr @ 0x%"PRIx32" (Device Control); val 0x%02"PRIx32"; bus %p"
ide_ctrl_write(uint32_t addr, uint32_t val, void *bus) "IDE PIO wr @ 0x%"PRIx32" (Device Control); val 0x%02"PRIx32"; bus %p"
# Warning: verbose
ide_data_readw(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (Data: Word); val 0x%04"PRIx32"; bus %p; IDEState %p"
ide_data_writew(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO wr @ 0x%"PRIx32" (Data: Word); val 0x%04"PRIx32"; bus %p; IDEState %p"

View File

@ -29,6 +29,17 @@ OBJECT_DECLARE_SIMPLE_TYPE(IDEBus, IDE_BUS)
#define MAX_IDE_DEVS 2
/* Device/Head ("select") Register */
#define ATA_DEV_SELECT 0x10
/* ATA1,3: Defined as '1'.
* ATA2: Reserved.
* ATA3-7: obsolete. */
#define ATA_DEV_ALWAYS_ON 0xA0
#define ATA_DEV_LBA 0x40
#define ATA_DEV_LBA_MSB 0x0F /* LBA 24:27 */
#define ATA_DEV_HS 0x0F /* HS 3:0 */
/* Bits of HD_STATUS */
#define ERR_STAT 0x01
#define INDEX_STAT 0x02
@ -57,8 +68,10 @@ OBJECT_DECLARE_SIMPLE_TYPE(IDEBus, IDE_BUS)
#define REL 0x04
#define TAG_MASK 0xf8
#define IDE_CMD_RESET 0x04
#define IDE_CMD_DISABLE_IRQ 0x02
/* Bits of Device Control register */
#define IDE_CTRL_HOB 0x80
#define IDE_CTRL_RESET 0x04
#define IDE_CTRL_DISABLE_IRQ 0x02
/* ACS-2 T13/2015-D Table B.2 Command codes */
#define WIN_NOP 0x00
@ -559,7 +572,7 @@ static inline IDEState *idebus_active_if(IDEBus *bus)
static inline void ide_set_irq(IDEBus *bus)
{
if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) {
if (!(bus->cmd & IDE_CTRL_DISABLE_IRQ)) {
qemu_irq_raise(bus->irq);
}
}
@ -598,7 +611,7 @@ void ide_atapi_io_error(IDEState *s, int ret);
void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val);
uint32_t ide_ioport_read(void *opaque, uint32_t addr1);
uint32_t ide_status_read(void *opaque, uint32_t addr);
void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val);
void ide_ctrl_write(void *opaque, uint32_t addr, uint32_t val);
void ide_data_writew(void *opaque, uint32_t addr, uint32_t val);
uint32_t ide_data_readw(void *opaque, uint32_t addr);
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);