diff options
author | Blue Swirl <blauwirbel@gmail.com> | 2009-11-07 14:13:05 +0000 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2009-11-07 14:13:05 +0000 |
commit | 4a6435639781214a14f3c6054955e5ef16298d72 (patch) | |
tree | fb4d38641d83dc4bf98b56aa91a0d070db0ae425 /hw/ide | |
parent | b55a37c981914aa8ecd21b9a2a2fb37f39b917c5 (diff) | |
download | qemu-4a6435639781214a14f3c6054955e5ef16298d72.tar.gz qemu-4a6435639781214a14f3c6054955e5ef16298d72.tar.bz2 qemu-4a6435639781214a14f3c6054955e5ef16298d72.zip |
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 <blauwirbel@gmail.com>
Diffstat (limited to 'hw/ide')
-rw-r--r-- | hw/ide/cmd646.c | 6 | ||||
-rw-r--r-- | hw/ide/core.c | 64 | ||||
-rw-r--r-- | hw/ide/internal.h | 3 | ||||
-rw-r--r-- | hw/ide/isa.c | 8 | ||||
-rw-r--r-- | hw/ide/macio.c | 3 | ||||
-rw-r--r-- | hw/ide/microdrive.c | 2 | ||||
-rw-r--r-- | hw/ide/mmio.c | 8 | ||||
-rw-r--r-- | 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; |