IDE: Fix reset handling
authorBlue Swirl <blauwirbel@gmail.com>
Sat, 7 Nov 2009 14:13:05 +0000 (14:13 +0000)
committerBlue Swirl <blauwirbel@gmail.com>
Sat, 7 Nov 2009 14:13:05 +0000 (14:13 +0000)
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>
hw/ide/cmd646.c
hw/ide/core.c
hw/ide/internal.h
hw/ide/isa.c
hw/ide/macio.c
hw/ide/microdrive.c
hw/ide/mmio.c
hw/ide/piix.c

index 45e2cdb..b2a3e43 100644 (file)
@@ -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 */
index fffcd00..eafb510 100644 (file)
@@ -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;
+}
index cfae4c2..567616e 100644 (file)
@@ -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);
index fe67bcd..dff7c79 100644 (file)
@@ -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),
index 424eb45..d1bdb49 100644 (file)
@@ -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 */
index 9f7789d..37087ca 100644 (file)
@@ -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)
index 84a20e5..cca883f 100644 (file)
@@ -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);
 }
 
index 60b37a3..8958d56 100644 (file)
@@ -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;