mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-10 11:04:58 -06:00
Block patches for 2.3
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJU/uuVAAoJEH8JsnLIjy/WULwP/jeARjYkFuG3ahSWpeY0JnTK QCkLF06iSQQUiirXI4H+Tofl8kNVBd/Iinv+LbkF27iWbTiwalmLz7NiyboX8dl+ NJZtCrqp44q7KFbl3g19/jop/zdZ9N5Gxp8BARVUILHQb1y5cXJwrDhBxTmNRDL+ sSZXfomCgKtMP40nGLa0CcNIYKlm8MePJEM2TsMoWv7tYz4CXgBG39EqK6NJluCY kTTMcbdrLbR0imfKOVPutCgV8rhRXJ0oGVD3Q+D3/LFmPG++hoRnWCcDm6ZZ62Hi Ra7u87TBfAUUtiT+vFQJnd7hTpN+stQidsCDBLEY3qPTKYhzm648PHvcEwOAv6YW sjAELF2Rrsbe4vkL3/qgYDusnaPMElrHVEdbKtHofWtg6KctLnYIhusV+qKq1Fpa cRQEbQIZMVFeWN1G9WuYH8RBYrwJqp+/qq7DcnV62lUAdY4e3iO7E3yMLFDwpxku PLl7eofU/ZpnAOrrU2QAQvgXZRqy1ie/Unv8jFwefQkK5mXHoCtkAeBlOM8t4kJf HjkC/hYO7kwPdaz6xK80wpXqYd3vT6jKi7mlJqC5oQQLGJbRigxlMZ16UIAx+IrL NxhnQChp7IP21KMATFbpvYjcJyGMw3ZuVRaUhQBgqQArIomVHvM5WcN9M6S5dsmj vClFOIqjlSbtsmChceWr =hlbC -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block patches for 2.3 # gpg: Signature made Tue Mar 10 13:03:17 2015 GMT using RSA key ID C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" * remotes/kevin/tags/for-upstream: (73 commits) MAINTAINERS: Add jcody as blockjobs, block devices maintainer iotests: add O_DIRECT alignment probing test block/raw-posix: fix launching with failed disks MAINTAINERS: Add jsnow as IDE maintainer sheepdog: Fix misleading error messages in sd_snapshot_create() Add testcase for scsi-hd devices without drive property scsi-hd: fix property unset case block/vdi: Add locking for parallel requests iotests: Drop vpc from 004's and 104's format list iotests: Remove 006 iotests: Fix 051's reference output virtio-blk: Remove the stale FIXME comment tests: Check QVIRTIO_F_ANY_LAYOUT flag in virtio-blk test libqos: Solve bug in interrupt checking when using MSIX in virtio-pci.c sheepdog: fix confused return values qtest/ahci: add fragmented dma test qtest/ahci: Add PIO and LBA48 tests qtest/ahci: Add DMA test variants libqos/ahci: add ahci command helpers qtest/ahci: Add a macro bootup routine ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
1976058109
85 changed files with 2693 additions and 840 deletions
|
@ -1160,6 +1160,11 @@ static void ahci_start_dma(IDEDMA *dma, IDEState *s,
|
|||
dma_cb(s, 0);
|
||||
}
|
||||
|
||||
static void ahci_restart_dma(IDEDMA *dma)
|
||||
{
|
||||
/* Nothing to do, ahci_start_dma already resets s->io_buffer_offset. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Called in DMA R/W chains to read the PRDT, utilizing ahci_populate_sglist.
|
||||
* Not currently invoked by PIO R/W chains,
|
||||
|
@ -1226,12 +1231,6 @@ static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int ahci_dma_set_unit(IDEDMA *dma, int unit)
|
||||
{
|
||||
/* only a single unit per link */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ahci_cmd_done(IDEDMA *dma)
|
||||
{
|
||||
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
|
||||
|
@ -1252,19 +1251,14 @@ static void ahci_irq_set(void *opaque, int n, int level)
|
|||
{
|
||||
}
|
||||
|
||||
static void ahci_dma_restart_cb(void *opaque, int running, RunState state)
|
||||
{
|
||||
}
|
||||
|
||||
static const IDEDMAOps ahci_dma_ops = {
|
||||
.start_dma = ahci_start_dma,
|
||||
.restart_dma = ahci_restart_dma,
|
||||
.start_transfer = ahci_start_transfer,
|
||||
.prepare_buf = ahci_dma_prepare_buf,
|
||||
.commit_buf = ahci_commit_buf,
|
||||
.rw_buf = ahci_dma_rw_buf,
|
||||
.set_unit = ahci_dma_set_unit,
|
||||
.cmd_done = ahci_cmd_done,
|
||||
.restart_cb = ahci_dma_restart_cb,
|
||||
};
|
||||
|
||||
void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports)
|
||||
|
@ -1294,6 +1288,7 @@ void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports)
|
|||
ad->port_no = i;
|
||||
ad->port.dma = &ad->dma;
|
||||
ad->port.dma->ops = &ahci_dma_ops;
|
||||
ide_register_restart_cb(&ad->port);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1333,6 +1328,7 @@ static const VMStateDescription vmstate_ahci_device = {
|
|||
.version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_IDE_BUS(port, AHCIDevice),
|
||||
VMSTATE_IDE_DRIVE(port.ifs[0], AHCIDevice),
|
||||
VMSTATE_UINT32(port_state, AHCIDevice),
|
||||
VMSTATE_UINT32(finished, AHCIDevice),
|
||||
VMSTATE_UINT32(port_regs.lst_addr, AHCIDevice),
|
||||
|
@ -1371,16 +1367,23 @@ static int ahci_state_post_load(void *opaque, int version_id)
|
|||
map_page(s->as, &ad->res_fis,
|
||||
((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256);
|
||||
/*
|
||||
* All pending i/o should be flushed out on a migrate. However,
|
||||
* we might not have cleared the busy_slot since this is done
|
||||
* in a bh. Also, issue i/o against any slots that are pending.
|
||||
* If an error is present, ad->busy_slot will be valid and not -1.
|
||||
* In this case, an operation is waiting to resume and will re-check
|
||||
* for additional AHCI commands to execute upon completion.
|
||||
*
|
||||
* In the case where no error was present, busy_slot will be -1,
|
||||
* and we should check to see if there are additional commands waiting.
|
||||
*/
|
||||
if ((ad->busy_slot != -1) &&
|
||||
!(ad->port.ifs[0].status & (BUSY_STAT|DRQ_STAT))) {
|
||||
pr->cmd_issue &= ~(1 << ad->busy_slot);
|
||||
ad->busy_slot = -1;
|
||||
if (ad->busy_slot == -1) {
|
||||
check_cmd(s, i);
|
||||
} else {
|
||||
/* We are in the middle of a command, and may need to access
|
||||
* the command header in guest memory again. */
|
||||
if (ad->busy_slot < 0 || ad->busy_slot >= AHCI_MAX_CMDS) {
|
||||
return -1;
|
||||
}
|
||||
ad->cur_cmd = &((AHCICmdHdr *)ad->lst)[ad->busy_slot];
|
||||
}
|
||||
check_cmd(s, i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -252,7 +252,6 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
|
|||
s->packet_transfer_size = size;
|
||||
s->io_buffer_size = size; /* dma: send the reply data as one chunk */
|
||||
s->elementary_transfer_size = 0;
|
||||
s->io_buffer_index = 0;
|
||||
|
||||
if (s->atapi_dma) {
|
||||
block_acct_start(blk_get_stats(s->blk), &s->acct, size,
|
||||
|
@ -261,6 +260,7 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
|
|||
ide_start_dma(s, ide_atapi_cmd_read_dma_cb);
|
||||
} else {
|
||||
s->status = READY_STAT | SEEK_STAT;
|
||||
s->io_buffer_index = 0;
|
||||
ide_atapi_cmd_reply_end(s);
|
||||
}
|
||||
}
|
||||
|
@ -368,7 +368,6 @@ static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
|
|||
{
|
||||
s->lba = lba;
|
||||
s->packet_transfer_size = nb_sectors * sector_size;
|
||||
s->io_buffer_index = 0;
|
||||
s->io_buffer_size = 0;
|
||||
s->cd_sector_size = sector_size;
|
||||
|
||||
|
|
|
@ -368,8 +368,7 @@ static void pci_cmd646_ide_realize(PCIDevice *dev, Error **errp)
|
|||
|
||||
bmdma_init(&d->bus[i], &d->bmdma[i], d);
|
||||
d->bmdma[i].bus = &d->bus[i];
|
||||
qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb,
|
||||
&d->bmdma[i].dma);
|
||||
ide_register_restart_cb(&d->bus[i]);
|
||||
}
|
||||
|
||||
vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d);
|
||||
|
|
118
hw/ide/core.c
118
hw/ide/core.c
|
@ -561,6 +561,8 @@ static bool ide_sect_range_ok(IDEState *s,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void ide_sector_read(IDEState *s);
|
||||
|
||||
static void ide_sector_read_cb(void *opaque, int ret)
|
||||
{
|
||||
IDEState *s = opaque;
|
||||
|
@ -595,7 +597,7 @@ static void ide_sector_read_cb(void *opaque, int ret)
|
|||
s->io_buffer_offset += 512 * n;
|
||||
}
|
||||
|
||||
void ide_sector_read(IDEState *s)
|
||||
static void ide_sector_read(IDEState *s)
|
||||
{
|
||||
int64_t sector_num;
|
||||
int n;
|
||||
|
@ -646,6 +648,9 @@ static void dma_buf_commit(IDEState *s, uint32_t tx_bytes)
|
|||
void ide_set_inactive(IDEState *s, bool more)
|
||||
{
|
||||
s->bus->dma->aiocb = NULL;
|
||||
s->bus->retry_unit = -1;
|
||||
s->bus->retry_sector_num = 0;
|
||||
s->bus->retry_nsector = 0;
|
||||
if (s->bus->dma->ops->set_inactive) {
|
||||
s->bus->dma->ops->set_inactive(s->bus->dma, more);
|
||||
}
|
||||
|
@ -666,7 +671,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op)
|
|||
BlockErrorAction action = blk_get_error_action(s->blk, is_read, error);
|
||||
|
||||
if (action == BLOCK_ERROR_ACTION_STOP) {
|
||||
s->bus->dma->ops->set_unit(s->bus->dma, s->unit);
|
||||
assert(s->bus->retry_unit == s->unit);
|
||||
s->bus->error_status = op;
|
||||
} else if (action == BLOCK_ERROR_ACTION_REPORT) {
|
||||
if (op & IDE_RETRY_DMA) {
|
||||
|
@ -679,7 +684,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op)
|
|||
return action != BLOCK_ERROR_ACTION_IGNORE;
|
||||
}
|
||||
|
||||
void ide_dma_cb(void *opaque, int ret)
|
||||
static void ide_dma_cb(void *opaque, int ret)
|
||||
{
|
||||
IDEState *s = opaque;
|
||||
int n;
|
||||
|
@ -777,7 +782,6 @@ eot:
|
|||
static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd)
|
||||
{
|
||||
s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
|
||||
s->io_buffer_index = 0;
|
||||
s->io_buffer_size = 0;
|
||||
s->dma_cmd = dma_cmd;
|
||||
|
||||
|
@ -799,11 +803,17 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd)
|
|||
|
||||
void ide_start_dma(IDEState *s, BlockCompletionFunc *cb)
|
||||
{
|
||||
s->io_buffer_index = 0;
|
||||
s->bus->retry_unit = s->unit;
|
||||
s->bus->retry_sector_num = ide_get_sector(s);
|
||||
s->bus->retry_nsector = s->nsector;
|
||||
if (s->bus->dma->ops->start_dma) {
|
||||
s->bus->dma->ops->start_dma(s->bus->dma, s, cb);
|
||||
}
|
||||
}
|
||||
|
||||
static void ide_sector_write(IDEState *s);
|
||||
|
||||
static void ide_sector_write_timer_cb(void *opaque)
|
||||
{
|
||||
IDEState *s = opaque;
|
||||
|
@ -863,7 +873,7 @@ static void ide_sector_write_cb(void *opaque, int ret)
|
|||
}
|
||||
}
|
||||
|
||||
void ide_sector_write(IDEState *s)
|
||||
static void ide_sector_write(IDEState *s)
|
||||
{
|
||||
int64_t sector_num;
|
||||
int n;
|
||||
|
@ -917,7 +927,7 @@ static void ide_flush_cb(void *opaque, int ret)
|
|||
ide_set_irq(s->bus);
|
||||
}
|
||||
|
||||
void ide_flush_cache(IDEState *s)
|
||||
static void ide_flush_cache(IDEState *s)
|
||||
{
|
||||
if (s->blk == NULL) {
|
||||
ide_flush_cb(s, 0);
|
||||
|
@ -2314,22 +2324,101 @@ static int ide_nop_int(IDEDMA *dma, int x)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ide_nop(IDEDMA *dma)
|
||||
{
|
||||
}
|
||||
|
||||
static int32_t ide_nop_int32(IDEDMA *dma, int x)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ide_nop_restart(void *opaque, int x, RunState y)
|
||||
{
|
||||
}
|
||||
|
||||
static const IDEDMAOps ide_dma_nop_ops = {
|
||||
.prepare_buf = ide_nop_int32,
|
||||
.restart_dma = ide_nop,
|
||||
.rw_buf = ide_nop_int,
|
||||
.set_unit = ide_nop_int,
|
||||
.restart_cb = ide_nop_restart,
|
||||
};
|
||||
|
||||
static void ide_restart_dma(IDEState *s, enum ide_dma_cmd dma_cmd)
|
||||
{
|
||||
s->unit = s->bus->retry_unit;
|
||||
ide_set_sector(s, s->bus->retry_sector_num);
|
||||
s->nsector = s->bus->retry_nsector;
|
||||
s->bus->dma->ops->restart_dma(s->bus->dma);
|
||||
s->io_buffer_size = 0;
|
||||
s->dma_cmd = dma_cmd;
|
||||
ide_start_dma(s, ide_dma_cb);
|
||||
}
|
||||
|
||||
static void ide_restart_bh(void *opaque)
|
||||
{
|
||||
IDEBus *bus = opaque;
|
||||
IDEState *s;
|
||||
bool is_read;
|
||||
int error_status;
|
||||
|
||||
qemu_bh_delete(bus->bh);
|
||||
bus->bh = NULL;
|
||||
|
||||
error_status = bus->error_status;
|
||||
if (bus->error_status == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
s = idebus_active_if(bus);
|
||||
is_read = (bus->error_status & IDE_RETRY_READ) != 0;
|
||||
|
||||
/* The error status must be cleared before resubmitting the request: The
|
||||
* request may fail again, and this case can only be distinguished if the
|
||||
* called function can set a new error status. */
|
||||
bus->error_status = 0;
|
||||
|
||||
if (error_status & IDE_RETRY_DMA) {
|
||||
if (error_status & IDE_RETRY_TRIM) {
|
||||
ide_restart_dma(s, IDE_DMA_TRIM);
|
||||
} else {
|
||||
ide_restart_dma(s, is_read ? IDE_DMA_READ : IDE_DMA_WRITE);
|
||||
}
|
||||
} else if (error_status & IDE_RETRY_PIO) {
|
||||
if (is_read) {
|
||||
ide_sector_read(s);
|
||||
} else {
|
||||
ide_sector_write(s);
|
||||
}
|
||||
} else if (error_status & IDE_RETRY_FLUSH) {
|
||||
ide_flush_cache(s);
|
||||
} else {
|
||||
/*
|
||||
* We've not got any bits to tell us about ATAPI - but
|
||||
* we do have the end_transfer_func that tells us what
|
||||
* we're trying to do.
|
||||
*/
|
||||
if (s->end_transfer_func == ide_atapi_cmd) {
|
||||
ide_atapi_dma_restart(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ide_restart_cb(void *opaque, int running, RunState state)
|
||||
{
|
||||
IDEBus *bus = opaque;
|
||||
|
||||
if (!running)
|
||||
return;
|
||||
|
||||
if (!bus->bh) {
|
||||
bus->bh = qemu_bh_new(ide_restart_bh, bus);
|
||||
qemu_bh_schedule(bus->bh);
|
||||
}
|
||||
}
|
||||
|
||||
void ide_register_restart_cb(IDEBus *bus)
|
||||
{
|
||||
if (bus->dma->ops->restart_dma) {
|
||||
qemu_add_vm_change_state_handler(ide_restart_cb, bus);
|
||||
}
|
||||
}
|
||||
|
||||
static IDEDMA ide_dma_nop = {
|
||||
.ops = &ide_dma_nop_ops,
|
||||
.aiocb = NULL,
|
||||
|
@ -2557,10 +2646,13 @@ const VMStateDescription vmstate_ide_drive = {
|
|||
|
||||
static const VMStateDescription vmstate_ide_error_status = {
|
||||
.name ="ide_bus/error",
|
||||
.version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_INT32(error_status, IDEBus),
|
||||
VMSTATE_INT64_V(retry_sector_num, IDEBus, 2),
|
||||
VMSTATE_UINT32_V(retry_nsector, IDEBus, 2),
|
||||
VMSTATE_UINT8_V(retry_unit, IDEBus, 2),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
|
|
@ -436,10 +436,9 @@ struct IDEDMAOps {
|
|||
DMAInt32Func *prepare_buf;
|
||||
DMAu32Func *commit_buf;
|
||||
DMAIntFunc *rw_buf;
|
||||
DMAIntFunc *set_unit;
|
||||
DMAVoidFunc *restart_dma;
|
||||
DMAStopFunc *set_inactive;
|
||||
DMAVoidFunc *cmd_done;
|
||||
DMARestartFunc *restart_cb;
|
||||
DMAVoidFunc *reset;
|
||||
};
|
||||
|
||||
|
@ -455,6 +454,8 @@ struct IDEBus {
|
|||
IDEDevice *master;
|
||||
IDEDevice *slave;
|
||||
IDEState ifs[2];
|
||||
QEMUBH *bh;
|
||||
|
||||
int bus_id;
|
||||
int max_units;
|
||||
IDEDMA *dma;
|
||||
|
@ -463,6 +464,9 @@ struct IDEBus {
|
|||
qemu_irq irq;
|
||||
|
||||
int error_status;
|
||||
uint8_t retry_unit;
|
||||
int64_t retry_sector_num;
|
||||
uint32_t retry_nsector;
|
||||
};
|
||||
|
||||
#define TYPE_IDE_DEVICE "ide-device"
|
||||
|
@ -522,6 +526,9 @@ extern const VMStateDescription vmstate_ide_drive;
|
|||
#define VMSTATE_IDE_DRIVES(_field, _state) \
|
||||
VMSTATE_STRUCT_ARRAY(_field, _state, 2, 3, vmstate_ide_drive, IDEState)
|
||||
|
||||
#define VMSTATE_IDE_DRIVE(_field, _state) \
|
||||
VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_drive, IDEState)
|
||||
|
||||
void ide_bus_reset(IDEBus *bus);
|
||||
int64_t ide_get_sector(IDEState *s);
|
||||
void ide_set_sector(IDEState *s, int64_t sector_num);
|
||||
|
@ -550,12 +557,9 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
|
|||
int chs_trans);
|
||||
void ide_init2(IDEBus *bus, qemu_irq irq);
|
||||
void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
|
||||
void ide_register_restart_cb(IDEBus *bus);
|
||||
|
||||
void ide_exec_cmd(IDEBus *bus, uint32_t val);
|
||||
void ide_dma_cb(void *opaque, int ret);
|
||||
void ide_sector_write(IDEState *s);
|
||||
void ide_sector_read(IDEState *s);
|
||||
void ide_flush_cache(IDEState *s);
|
||||
|
||||
void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
|
||||
EndTransferFunc *end_transfer_func);
|
||||
|
|
|
@ -74,7 +74,8 @@ static void isa_ide_realizefn(DeviceState *dev, Error **errp)
|
|||
isa_init_irq(isadev, &s->irq, s->isairq);
|
||||
ide_init2(&s->bus, s->irq);
|
||||
vmstate_register(dev, 0, &vmstate_ide_isa, s);
|
||||
};
|
||||
ide_register_restart_cb(&s->bus);
|
||||
}
|
||||
|
||||
ISADevice *isa_ide_init(ISABus *bus, int iobase, int iobase2, int isairq,
|
||||
DriveInfo *hd0, DriveInfo *hd1)
|
||||
|
|
|
@ -558,10 +558,6 @@ static int32_t ide_nop_int32(IDEDMA *dma, int x)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ide_nop_restart(void *opaque, int x, RunState y)
|
||||
{
|
||||
}
|
||||
|
||||
static void ide_dbdma_start(IDEDMA *dma, IDEState *s,
|
||||
BlockCompletionFunc *cb)
|
||||
{
|
||||
|
@ -576,8 +572,6 @@ static const IDEDMAOps dbdma_ops = {
|
|||
.start_dma = ide_dbdma_start,
|
||||
.prepare_buf = ide_nop_int32,
|
||||
.rw_buf = ide_nop_int,
|
||||
.set_unit = ide_nop_int,
|
||||
.restart_cb = ide_nop_restart,
|
||||
};
|
||||
|
||||
static void macio_ide_realizefn(DeviceState *dev, Error **errp)
|
||||
|
|
109
hw/ide/pci.c
109
hw/ide/pci.c
|
@ -42,13 +42,10 @@ static void bmdma_start_dma(IDEDMA *dma, IDEState *s,
|
|||
{
|
||||
BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
|
||||
|
||||
bm->unit = s->unit;
|
||||
bm->dma_cb = dma_cb;
|
||||
bm->cur_prd_last = 0;
|
||||
bm->cur_prd_addr = 0;
|
||||
bm->cur_prd_len = 0;
|
||||
bm->sector_num = ide_get_sector(s);
|
||||
bm->nsector = s->nsector;
|
||||
|
||||
if (bm->status & BM_STATUS_DMAING) {
|
||||
bm->dma_cb(bmdma_active_if(bm), 0);
|
||||
|
@ -163,20 +160,11 @@ static int bmdma_rw_buf(IDEDMA *dma, int is_write)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int bmdma_set_unit(IDEDMA *dma, int unit)
|
||||
{
|
||||
BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
|
||||
bm->unit = unit;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bmdma_set_inactive(IDEDMA *dma, bool more)
|
||||
{
|
||||
BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
|
||||
|
||||
bm->dma_cb = NULL;
|
||||
bm->unit = -1;
|
||||
if (more) {
|
||||
bm->status |= BM_STATUS_DMAING;
|
||||
} else {
|
||||
|
@ -184,83 +172,11 @@ static void bmdma_set_inactive(IDEDMA *dma, bool more)
|
|||
}
|
||||
}
|
||||
|
||||
static void bmdma_restart_dma(BMDMAState *bm, enum ide_dma_cmd dma_cmd)
|
||||
static void bmdma_restart_dma(IDEDMA *dma)
|
||||
{
|
||||
IDEState *s = bmdma_active_if(bm);
|
||||
|
||||
ide_set_sector(s, bm->sector_num);
|
||||
s->io_buffer_index = 0;
|
||||
s->io_buffer_size = 0;
|
||||
s->nsector = bm->nsector;
|
||||
s->dma_cmd = dma_cmd;
|
||||
bm->cur_addr = bm->addr;
|
||||
bm->dma_cb = ide_dma_cb;
|
||||
bmdma_start_dma(&bm->dma, s, bm->dma_cb);
|
||||
}
|
||||
|
||||
/* TODO This should be common IDE code */
|
||||
static void bmdma_restart_bh(void *opaque)
|
||||
{
|
||||
BMDMAState *bm = opaque;
|
||||
IDEBus *bus = bm->bus;
|
||||
bool is_read;
|
||||
int error_status;
|
||||
|
||||
qemu_bh_delete(bm->bh);
|
||||
bm->bh = NULL;
|
||||
|
||||
if (bm->unit == (uint8_t) -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_read = (bus->error_status & IDE_RETRY_READ) != 0;
|
||||
|
||||
/* The error status must be cleared before resubmitting the request: The
|
||||
* request may fail again, and this case can only be distinguished if the
|
||||
* called function can set a new error status. */
|
||||
error_status = bus->error_status;
|
||||
bus->error_status = 0;
|
||||
|
||||
if (error_status & IDE_RETRY_DMA) {
|
||||
if (error_status & IDE_RETRY_TRIM) {
|
||||
bmdma_restart_dma(bm, IDE_DMA_TRIM);
|
||||
} else {
|
||||
bmdma_restart_dma(bm, is_read ? IDE_DMA_READ : IDE_DMA_WRITE);
|
||||
}
|
||||
} else if (error_status & IDE_RETRY_PIO) {
|
||||
if (is_read) {
|
||||
ide_sector_read(bmdma_active_if(bm));
|
||||
} else {
|
||||
ide_sector_write(bmdma_active_if(bm));
|
||||
}
|
||||
} else if (error_status & IDE_RETRY_FLUSH) {
|
||||
ide_flush_cache(bmdma_active_if(bm));
|
||||
} else {
|
||||
IDEState *s = bmdma_active_if(bm);
|
||||
|
||||
/*
|
||||
* We've not got any bits to tell us about ATAPI - but
|
||||
* we do have the end_transfer_func that tells us what
|
||||
* we're trying to do.
|
||||
*/
|
||||
if (s->end_transfer_func == ide_atapi_cmd) {
|
||||
ide_atapi_dma_restart(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bmdma_restart_cb(void *opaque, int running, RunState state)
|
||||
{
|
||||
IDEDMA *dma = opaque;
|
||||
BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
|
||||
|
||||
if (!running)
|
||||
return;
|
||||
|
||||
if (!bm->bh) {
|
||||
bm->bh = qemu_bh_new(bmdma_restart_bh, &bm->dma);
|
||||
qemu_bh_schedule(bm->bh);
|
||||
}
|
||||
bm->cur_addr = bm->addr;
|
||||
}
|
||||
|
||||
static void bmdma_cancel(BMDMAState *bm)
|
||||
|
@ -286,8 +202,6 @@ static void bmdma_reset(IDEDMA *dma)
|
|||
bm->cur_prd_last = 0;
|
||||
bm->cur_prd_addr = 0;
|
||||
bm->cur_prd_len = 0;
|
||||
bm->sector_num = 0;
|
||||
bm->nsector = 0;
|
||||
}
|
||||
|
||||
static void bmdma_irq(void *opaque, int n, int level)
|
||||
|
@ -404,6 +318,9 @@ static void ide_bmdma_pre_save(void *opaque)
|
|||
BMDMAState *bm = opaque;
|
||||
uint8_t abused_bits = BM_MIGRATION_COMPAT_STATUS_BITS;
|
||||
|
||||
bm->migration_retry_unit = bm->bus->retry_unit;
|
||||
bm->migration_retry_sector_num = bm->bus->retry_sector_num;
|
||||
bm->migration_retry_nsector = bm->bus->retry_nsector;
|
||||
bm->migration_compat_status =
|
||||
(bm->status & ~abused_bits) | (bm->bus->error_status & abused_bits);
|
||||
}
|
||||
|
@ -420,6 +337,11 @@ static int ide_bmdma_post_load(void *opaque, int version_id)
|
|||
bm->status = bm->migration_compat_status & ~abused_bits;
|
||||
bm->bus->error_status |= bm->migration_compat_status & abused_bits;
|
||||
}
|
||||
if (bm->bus->error_status) {
|
||||
bm->bus->retry_sector_num = bm->migration_retry_sector_num;
|
||||
bm->bus->retry_nsector = bm->migration_retry_nsector;
|
||||
bm->bus->retry_unit = bm->migration_retry_unit;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -456,9 +378,9 @@ static const VMStateDescription vmstate_bmdma = {
|
|||
VMSTATE_UINT8(cmd, BMDMAState),
|
||||
VMSTATE_UINT8(migration_compat_status, BMDMAState),
|
||||
VMSTATE_UINT32(addr, BMDMAState),
|
||||
VMSTATE_INT64(sector_num, BMDMAState),
|
||||
VMSTATE_UINT32(nsector, BMDMAState),
|
||||
VMSTATE_UINT8(unit, BMDMAState),
|
||||
VMSTATE_INT64(migration_retry_sector_num, BMDMAState),
|
||||
VMSTATE_UINT32(migration_retry_nsector, BMDMAState),
|
||||
VMSTATE_UINT8(migration_retry_unit, BMDMAState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (VMStateSubsection []) {
|
||||
|
@ -482,7 +404,7 @@ static int ide_pci_post_load(void *opaque, int version_id)
|
|||
for(i = 0; i < 2; i++) {
|
||||
/* current versions always store 0/1, but older version
|
||||
stored bigger values. We only need last bit */
|
||||
d->bmdma[i].unit &= 1;
|
||||
d->bmdma[i].migration_retry_unit &= 1;
|
||||
ide_bmdma_post_load(&d->bmdma[i], -1);
|
||||
}
|
||||
|
||||
|
@ -523,9 +445,8 @@ static const struct IDEDMAOps bmdma_ops = {
|
|||
.start_dma = bmdma_start_dma,
|
||||
.prepare_buf = bmdma_prepare_buf,
|
||||
.rw_buf = bmdma_rw_buf,
|
||||
.set_unit = bmdma_set_unit,
|
||||
.restart_dma = bmdma_restart_dma,
|
||||
.set_inactive = bmdma_set_inactive,
|
||||
.restart_cb = bmdma_restart_cb,
|
||||
.reset = bmdma_reset,
|
||||
};
|
||||
|
||||
|
|
12
hw/ide/pci.h
12
hw/ide/pci.h
|
@ -22,18 +22,18 @@ typedef struct BMDMAState {
|
|||
uint32_t cur_prd_last;
|
||||
uint32_t cur_prd_addr;
|
||||
uint32_t cur_prd_len;
|
||||
uint8_t unit;
|
||||
BlockCompletionFunc *dma_cb;
|
||||
int64_t sector_num;
|
||||
uint32_t nsector;
|
||||
MemoryRegion addr_ioport;
|
||||
MemoryRegion extra_io;
|
||||
QEMUBH *bh;
|
||||
qemu_irq irq;
|
||||
|
||||
/* Bit 0-2 and 7: BM status register
|
||||
* Bit 3-6: bus->error_status */
|
||||
uint8_t migration_compat_status;
|
||||
uint8_t migration_retry_unit;
|
||||
int64_t migration_retry_sector_num;
|
||||
uint32_t migration_retry_nsector;
|
||||
|
||||
struct PCIIDEState *pci_dev;
|
||||
} BMDMAState;
|
||||
|
||||
|
@ -62,8 +62,8 @@ typedef struct PCIIDEState {
|
|||
|
||||
static inline IDEState *bmdma_active_if(BMDMAState *bmdma)
|
||||
{
|
||||
assert(bmdma->unit != (uint8_t)-1);
|
||||
return bmdma->bus->ifs + bmdma->unit;
|
||||
assert(bmdma->bus->retry_unit != (uint8_t)-1);
|
||||
return bmdma->bus->ifs + bmdma->bus->retry_unit;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -143,8 +143,7 @@ static void pci_piix_init_ports(PCIIDEState *d) {
|
|||
|
||||
bmdma_init(&d->bus[i], &d->bmdma[i], d);
|
||||
d->bmdma[i].bus = &d->bus[i];
|
||||
qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb,
|
||||
&d->bmdma[i].dma);
|
||||
ide_register_restart_cb(&d->bus[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -163,6 +163,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
|
|||
return -1;
|
||||
}
|
||||
|
||||
blkconf_blocksizes(&dev->conf);
|
||||
if (dev->conf.logical_block_size != 512) {
|
||||
error_report("logical_block_size must be 512 for IDE");
|
||||
return -1;
|
||||
|
|
|
@ -166,8 +166,7 @@ static void vt82c686b_init_ports(PCIIDEState *d) {
|
|||
|
||||
bmdma_init(&d->bus[i], &d->bmdma[i], d);
|
||||
d->bmdma[i].bus = &d->bus[i];
|
||||
qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb,
|
||||
&d->bmdma[i].dma);
|
||||
ide_register_restart_cb(&d->bus[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue