]> Git Repo - qemu.git/blobdiff - hw/fdc.c
Take advantage of subpage support.
[qemu.git] / hw / fdc.c
index 930c0e21b8d94060c90739e6b2643d24e052279d..ca2d3207242af7119b9bacd49c85c66a220df186 100644 (file)
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1,7 +1,7 @@
 /*
  * QEMU Floppy disk emulator (Intel 82078)
  * 
- * Copyright (c) 2003 Jocelyn Mayer
+ * Copyright (c) 2003, 2007 Jocelyn Mayer
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -368,9 +368,9 @@ struct fdctrl_t {
     /* Controller's identification */
     uint8_t version;
     /* HW */
-    int irq_lvl;
+    qemu_irq irq;
     int dma_chann;
-    uint32_t io_base;
+    target_phys_addr_t io_base;
     /* Controller state */
     QEMUTimer *result_timer;
     uint8_t state;
@@ -464,13 +464,13 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
 
 static uint32_t fdctrl_read_mem (void *opaque, target_phys_addr_t reg)
 {
-    return fdctrl_read(opaque, reg);
+    return fdctrl_read(opaque, (uint32_t)reg);
 }
 
 static void fdctrl_write_mem (void *opaque, 
                               target_phys_addr_t reg, uint32_t value)
 {
-    fdctrl_write(opaque, reg, value);
+    fdctrl_write(opaque, (uint32_t)reg, value);
 }
 
 static CPUReadMemoryFunc *fdctrl_mem_read[3] = {
@@ -485,8 +485,101 @@ static CPUWriteMemoryFunc *fdctrl_mem_write[3] = {
     fdctrl_write_mem,
 };
 
-fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, 
-                       uint32_t io_base,
+static void fd_save (QEMUFile *f, fdrive_t *fd)
+{
+    uint8_t tmp;
+
+    tmp = fd->drflags;
+    qemu_put_8s(f, &tmp);
+    qemu_put_8s(f, &fd->head);
+    qemu_put_8s(f, &fd->track);
+    qemu_put_8s(f, &fd->sect);
+    qemu_put_8s(f, &fd->dir);
+    qemu_put_8s(f, &fd->rw);
+}
+
+static void fdc_save (QEMUFile *f, void *opaque)
+{
+    fdctrl_t *s = opaque;
+
+    qemu_put_8s(f, &s->state);
+    qemu_put_8s(f, &s->dma_en);
+    qemu_put_8s(f, &s->cur_drv);
+    qemu_put_8s(f, &s->bootsel);
+    qemu_put_buffer(f, s->fifo, FD_SECTOR_LEN);
+    qemu_put_be32s(f, &s->data_pos);
+    qemu_put_be32s(f, &s->data_len);
+    qemu_put_8s(f, &s->data_state);
+    qemu_put_8s(f, &s->data_dir);
+    qemu_put_8s(f, &s->int_status);
+    qemu_put_8s(f, &s->eot);
+    qemu_put_8s(f, &s->timer0);
+    qemu_put_8s(f, &s->timer1);
+    qemu_put_8s(f, &s->precomp_trk);
+    qemu_put_8s(f, &s->config);
+    qemu_put_8s(f, &s->lock);
+    qemu_put_8s(f, &s->pwrd);
+    fd_save(f, &s->drives[0]);
+    fd_save(f, &s->drives[1]);
+}
+
+static int fd_load (QEMUFile *f, fdrive_t *fd)
+{
+    uint8_t tmp;
+
+    qemu_get_8s(f, &tmp);
+    fd->drflags = tmp;
+    qemu_get_8s(f, &fd->head);
+    qemu_get_8s(f, &fd->track);
+    qemu_get_8s(f, &fd->sect);
+    qemu_get_8s(f, &fd->dir);
+    qemu_get_8s(f, &fd->rw);
+
+    return 0;
+}
+
+static int fdc_load (QEMUFile *f, void *opaque, int version_id)
+{
+    fdctrl_t *s = opaque;
+    int ret;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_8s(f, &s->state);
+    qemu_get_8s(f, &s->dma_en);
+    qemu_get_8s(f, &s->cur_drv);
+    qemu_get_8s(f, &s->bootsel);
+    qemu_get_buffer(f, s->fifo, FD_SECTOR_LEN);
+    qemu_get_be32s(f, &s->data_pos);
+    qemu_get_be32s(f, &s->data_len);
+    qemu_get_8s(f, &s->data_state);
+    qemu_get_8s(f, &s->data_dir);
+    qemu_get_8s(f, &s->int_status);
+    qemu_get_8s(f, &s->eot);
+    qemu_get_8s(f, &s->timer0);
+    qemu_get_8s(f, &s->timer1);
+    qemu_get_8s(f, &s->precomp_trk);
+    qemu_get_8s(f, &s->config);
+    qemu_get_8s(f, &s->lock);
+    qemu_get_8s(f, &s->pwrd);
+
+    ret = fd_load(f, &s->drives[0]);
+    if (ret == 0)
+        ret = fd_load(f, &s->drives[1]);
+
+    return ret;
+}
+
+static void fdctrl_external_reset(void *opaque)
+{
+    fdctrl_t *s = opaque;
+
+    fdctrl_reset(s, 0);
+}
+
+fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped, 
+                       target_phys_addr_t io_base,
                        BlockDriverState **fds)
 {
     fdctrl_t *fdctrl;
@@ -501,7 +594,7 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
                                           fdctrl_result_timer, fdctrl);
 
     fdctrl->version = 0x90; /* Intel 82078 controller */
-    fdctrl->irq_lvl = irq_lvl;
+    fdctrl->irq = irq;
     fdctrl->dma_chann = dma_chann;
     fdctrl->io_base = io_base;
     fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */
@@ -520,11 +613,17 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
         io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write, fdctrl);
         cpu_register_physical_memory(io_base, 0x08, io_mem);
     } else {
-        register_ioport_read(io_base + 0x01, 5, 1, &fdctrl_read, fdctrl);
-        register_ioport_read(io_base + 0x07, 1, 1, &fdctrl_read, fdctrl);
-        register_ioport_write(io_base + 0x01, 5, 1, &fdctrl_write, fdctrl);
-        register_ioport_write(io_base + 0x07, 1, 1, &fdctrl_write, fdctrl);
+        register_ioport_read((uint32_t)io_base + 0x01, 5, 1, &fdctrl_read,
+                             fdctrl);
+        register_ioport_read((uint32_t)io_base + 0x07, 1, 1, &fdctrl_read,
+                             fdctrl);
+        register_ioport_write((uint32_t)io_base + 0x01, 5, 1, &fdctrl_write,
+                              fdctrl);
+        register_ioport_write((uint32_t)io_base + 0x07, 1, 1, &fdctrl_write,
+                              fdctrl);
     }
+    register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl);
+    qemu_register_reset(fdctrl_external_reset, fdctrl);
     for (i = 0; i < 2; i++) {
         fd_revalidate(&fdctrl->drives[i]);
     }
@@ -542,7 +641,7 @@ int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num)
 static void fdctrl_reset_irq (fdctrl_t *fdctrl)
 {
     FLOPPY_DPRINTF("Reset interrupt\n");
-    pic_set_irq(fdctrl->irq_lvl, 0);
+    qemu_set_irq(fdctrl->irq, 0);
     fdctrl->state &= ~FD_CTRL_INTR;
 }
 
@@ -557,7 +656,7 @@ static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status)
     }
 #endif
     if (~(fdctrl->state & FD_CTRL_INTR)) {
-        pic_set_irq(fdctrl->irq_lvl, 1);
+        qemu_set_irq(fdctrl->irq, 1);
         fdctrl->state |= FD_CTRL_INTR;
     }
     FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status);
@@ -888,7 +987,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
         fdctrl->data_len = fdctrl->fifo[8];
     } else {
        int tmp;
-        fdctrl->data_len = 128 << fdctrl->fifo[5];
+        fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]);
         tmp = (cur_drv->last_sect - ks + 1);
         if (fdctrl->fifo[0] & 0x80)
             tmp += cur_drv->last_sect;
@@ -1673,8 +1772,9 @@ enqueue:
 #else
            cur_drv->last_sect = fdctrl->fifo[3];
 #endif
-           /* Bochs BIOS is buggy and don't send format informations
-            * for each sector. So, pretend all's done right now...
+           /* TODO: implement format using DMA expected by the Bochs BIOS
+            * and Linux fdformat (read 3 bytes per sector via DMA and fill
+            * the sector with the specified fill byte
             */
            fdctrl->data_state &= ~FD_STATE_FORMAT;
            fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
This page took 0.030045 seconds and 4 git commands to generate.