From 4a6435639781214a14f3c6054955e5ef16298d72 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sat, 7 Nov 2009 14:13:05 +0000 Subject: [PATCH] IDE: Fix reset handling Problem: x86 systems could not survive a few system_resets. Clear most of IDE state when reset. Implement the missing reset handlers. Signed-off-by: Blue Swirl --- hw/ide/cmd646.c | 6 +++-- hw/ide/core.c | 64 ++++++++++++++++++++++++++++++++++++++++++--- hw/ide/internal.h | 3 ++- hw/ide/isa.c | 8 ++++++ hw/ide/macio.c | 3 +-- hw/ide/microdrive.c | 2 +- hw/ide/mmio.c | 8 ++++++ hw/ide/piix.c | 6 +++-- 8 files changed, 88 insertions(+), 12 deletions(-) diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 45e2cdb9a5..b2a3e434b3 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -193,8 +193,10 @@ static void cmd646_reset(void *opaque) PCIIDEState *d = opaque; unsigned int i; - for (i = 0; i < 2; i++) - ide_dma_cancel(&d->bmdma[i]); + for (i = 0; i < 2; i++) { + ide_bus_reset(&d->bus[i]); + ide_dma_reset(&d->bmdma[i]); + } } /* CMD646 PCI IDE controller */ diff --git a/hw/ide/core.c b/hw/ide/core.c index fffcd00280..eafb510b63 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2500,17 +2500,48 @@ static void ide_dummy_transfer_stop(IDEState *s) s->io_buffer[3] = 0xff; } -void ide_reset(IDEState *s) +static void ide_reset(IDEState *s) { - IDEBus *bus = s->bus; - +#ifdef DEBUG_IDE + printf("ide: reset\n"); +#endif if (s->is_cf) s->mult_sectors = 0; else s->mult_sectors = MAX_MULT_SECTORS; - bus->unit = s->unit; + /* ide regs */ + s->feature = 0; + s->error = 0; + s->nsector = 0; + s->sector = 0; + s->lcyl = 0; + s->hcyl = 0; + + /* lba48 */ + s->hob_feature = 0; + s->hob_sector = 0; + s->hob_nsector = 0; + s->hob_lcyl = 0; + s->hob_hcyl = 0; + s->select = 0xa0; s->status = READY_STAT | SEEK_STAT; + + s->lba48 = 0; + + /* ATAPI specific */ + s->sense_key = 0; + s->asc = 0; + s->cdrom_changed = 0; + s->packet_transfer_size = 0; + s->elementary_transfer_size = 0; + s->io_buffer_index = 0; + s->cd_sector_size = 0; + s->atapi_dma = 0; + /* ATA DMA state */ + s->io_buffer_size = 0; + s->req_nb_sectors = 0; + ide_set_signature(s); /* init the transfer handler so that 0xffff is returned on data accesses */ @@ -2519,6 +2550,15 @@ void ide_reset(IDEState *s) s->media_changed = 0; } +void ide_bus_reset(IDEBus *bus) +{ + bus->unit = 0; + bus->cmd = 0; + ide_reset(&bus->ifs[0]); + ide_reset(&bus->ifs[1]); + ide_clear_hob(bus); +} + void ide_init_drive(IDEState *s, DriveInfo *dinfo) { int cylinders, heads, secs; @@ -2704,3 +2744,19 @@ void ide_dma_cancel(BMDMAState *bm) } } +void ide_dma_reset(BMDMAState *bm) +{ +#ifdef DEBUG_IDE + printf("ide: dma_reset\n"); +#endif + ide_dma_cancel(bm); + bm->cmd = 0; + bm->status = 0; + bm->addr = 0; + bm->cur_addr = 0; + bm->cur_prd_last = 0; + bm->cur_prd_addr = 0; + bm->cur_prd_len = 0; + bm->sector_num = 0; + bm->nsector = 0; +} diff --git a/hw/ide/internal.h b/hw/ide/internal.h index cfae4c29be..567616e138 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -525,13 +525,14 @@ extern const VMStateDescription vmstate_ide_drive; #define VMSTATE_IDE_DRIVES(_field, _state) \ VMSTATE_STRUCT_ARRAY(_field, _state, 2, 3, vmstate_ide_drive, IDEState) -void ide_reset(IDEState *s); +void ide_bus_reset(IDEBus *bus); int64_t ide_get_sector(IDEState *s); void ide_set_sector(IDEState *s, int64_t sector_num); void ide_dma_cancel(BMDMAState *bm); void ide_dma_restart_cb(void *opaque, int running, int reason); void ide_dma_error(IDEState *s); +void ide_dma_reset(BMDMAState *bm); void ide_atapi_cmd_ok(IDEState *s); void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc); diff --git a/hw/ide/isa.c b/hw/ide/isa.c index fe67bcdf7c..dff7c796f7 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -44,6 +44,13 @@ typedef struct ISAIDEState { qemu_irq irq; } ISAIDEState; +static void isa_ide_reset(DeviceState *d) +{ + ISAIDEState *s = container_of(d, ISAIDEState, dev.qdev); + + ide_bus_reset(&s->bus); +} + static const VMStateDescription vmstate_ide_isa = { .name = "isa-ide", .version_id = 3, @@ -93,6 +100,7 @@ static ISADeviceInfo isa_ide_info = { .qdev.name = "isa-ide", .qdev.size = sizeof(ISAIDEState), .init = isa_ide_initfn, + .qdev.reset = isa_ide_reset, .qdev.props = (Property[]) { DEFINE_PROP_HEX32("iobase", ISAIDEState, iobase, 0x1f0), DEFINE_PROP_HEX32("iobase2", ISAIDEState, iobase2, 0x3f6), diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 424eb454b7..d1bdb4967f 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -307,8 +307,7 @@ static void pmac_ide_reset(void *opaque) { MACIOIDEState *d = opaque; - ide_reset(d->bus.ifs +0); - ide_reset(d->bus.ifs +1); + ide_bus_reset(&d->bus); } /* hd_table must contain 4 block drivers */ diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 9f7789d611..37087ca0ca 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -110,7 +110,7 @@ static void md_reset(MicroDriveState *s) s->pins = 0; s->cycle = 0; s->ctrl = 0; - ide_reset(s->bus.ifs); + ide_bus_reset(&s->bus); } static uint8_t md_attr_read(void *opaque, uint32_t at) diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index 84a20e5ea9..cca883f613 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -41,6 +41,13 @@ typedef struct { int shift; } MMIOState; +static void mmio_ide_reset(void *opaque) +{ + MMIOState *s = opaque; + + ide_bus_reset(&s->bus); +} + static uint32_t mmio_ide_read (void *opaque, target_phys_addr_t addr) { MMIOState *s = opaque; @@ -127,5 +134,6 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2, cpu_register_physical_memory(membase, 16 << shift, mem1); cpu_register_physical_memory(membase2, 2 << shift, mem2); vmstate_register(0, &vmstate_ide_mmio, s); + qemu_register_reset(mmio_ide_reset, s); } diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 60b37a36a5..8958d56a5c 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -101,8 +101,10 @@ static void piix3_reset(void *opaque) uint8_t *pci_conf = d->dev.config; int i; - for (i = 0; i < 2; i++) - ide_dma_cancel(&d->bmdma[i]); + for (i = 0; i < 2; i++) { + ide_bus_reset(&d->bus[i]); + ide_dma_reset(&d->bmdma[i]); + } pci_conf[0x04] = 0x00; pci_conf[0x05] = 0x00;