mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 03:13:44 +08:00
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:
commit
b5ce42f5d1
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
124
hw/ide/core.c
124
hw/ide/core.c
@ -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;
|
||||
|
@ -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(),
|
||||
};
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
12
hw/ide/pci.c
12
hw/ide/pci.c
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user