qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] Fix multiple floppy controller issues
@ 2008-02-12 17:09 Hervé Poussineau
  2008-02-12 18:04 ` Blue Swirl
  0 siblings, 1 reply; 2+ messages in thread
From: Hervé Poussineau @ 2008-02-12 17:09 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 500 bytes --]

Hi,

Attached patch fixes some issues in the floppy disk controller:
- Enhance reset support (external and software)
- Use MAX_FD constant when possible
- Support up to 4 drives if MAX_FD is set to 4
- Fix DOR register, which should be writable at any time
- Let MSR return 0x20 when non-DMA transfer is happening
- Don't assume caller wants to read whole track at once
- Add seek to next sector when in non-DMA mode

Credits to Stuart Brady to help me to debug some issues...

Hervé


[-- Attachment #2: fdc.patch --]
[-- Type: text/plain, Size: 8783 bytes --]

Index: fdc.c
===================================================================
RCS file: /sources/qemu/qemu/hw/fdc.c,v
retrieving revision 1.37
diff -u -r1.37 fdc.c
--- fdc.c	1 Jan 2008 17:06:38 -0000	1.37
+++ fdc.c	12 Feb 2008 17:02:17 -0000
@@ -306,10 +306,9 @@
     drv->drflags &= ~FDRIVE_MOTOR_ON;
 }
 
-/* Re-initialise a drives (motor off, repositioned) */
+/* Re-initialise a drive (repositioned) */
 static void fd_reset (fdrive_t *drv)
 {
-    fd_stop(drv);
     fd_recalibrate(drv);
 }
 
@@ -402,7 +401,7 @@
     /* Sun4m quirks? */
     int sun4m;
     /* Floppy drives */
-    fdrive_t drives[2];
+    fdrive_t drives[MAX_FD];
 };
 
 static uint32_t fdctrl_read (void *opaque, uint32_t reg)
@@ -622,20 +621,16 @@
     fdctrl->dma_chann = dma_chann;
     fdctrl->io_base = io_base;
     fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */
-    if (fdctrl->dma_chann != -1) {
-        fdctrl->dma_en = 1;
+    if (fdctrl->dma_chann != -1)
         DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
-    } else {
-        fdctrl->dma_en = 0;
-    }
-    for (i = 0; i < 2; i++) {
+    for (i = 0; i < MAX_FD; i++) {
         fd_init(&fdctrl->drives[i], fds[i]);
     }
     fdctrl_reset(fdctrl, 0);
     fdctrl->state = FD_CTRL_ACTIVE;
     register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl);
     qemu_register_reset(fdctrl_external_reset, fdctrl);
-    for (i = 0; i < 2; i++) {
+    for (i = 0; i < MAX_FD; i++) {
         fd_revalidate(&fdctrl->drives[i]);
     }
 
@@ -735,6 +730,7 @@
     fdctrl_reset_fifo(fdctrl);
     if (do_irq)
         fdctrl_raise_irq(fdctrl, 0xc0);
+    fdctrl->dma_en = (fdctrl->dma_chann != -1) ? 1 : 0;
 }
 
 static inline fdrive_t *drv0 (fdctrl_t *fdctrl)
@@ -744,12 +740,41 @@
 
 static inline fdrive_t *drv1 (fdctrl_t *fdctrl)
 {
-    return &fdctrl->drives[1 - fdctrl->bootsel];
+    if (fdctrl->bootsel < 1)
+        return &fdctrl->drives[1];
+    else
+        return &fdctrl->drives[0];
+}
+
+#if MAX_FD >= 4
+static inline fdrive_t *drv2 (fdctrl_t *fdctrl)
+{
+    if (fdctrl->bootsel < 2)
+        return &fdctrl->drives[2];
+    else
+        return &fdctrl->drives[1];
 }
 
+static inline fdrive_t *drv3 (fdctrl_t *fdctrl)
+{
+    if (fdctrl->bootsel < 3)
+        return &fdctrl->drives[3];
+    else
+        return &fdctrl->drives[2];
+}
+#endif
+
 static fdrive_t *get_cur_drv (fdctrl_t *fdctrl)
 {
-    return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl);
+    switch (fdctrl->cur_drv) {
+        case 0: return drv0(fdctrl);
+        case 1: return drv1(fdctrl);
+#if MAX_FD >= 4
+        case 2: return drv2(fdctrl);
+        case 3: return drv3(fdctrl);
+#endif
+        default: return NULL;
+    }
 }
 
 /* Status B register : 0x01 (read-only) */
@@ -765,9 +790,15 @@
     uint32_t retval = 0;
 
     /* Drive motors state indicators */
-    if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON)
-        retval |= 1 << 5;
+#if MAX_FD >= 4
+    if (drv3(fdctrl)->drflags & FDRIVE_MOTOR_ON)
+        retval |= 1 << 7;
+    if (drv2(fdctrl)->drflags & FDRIVE_MOTOR_ON)
+        retval |= 1 << 6;
+#endif
     if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON)
+        retval |= 1 << 5;
+    if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON)
         retval |= 1 << 4;
     /* DMA enable */
     retval |= fdctrl->dma_en << 3;
@@ -782,15 +813,18 @@
 
 static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
 {
-    /* Reset mode */
-    if (fdctrl->state & FD_CTRL_RESET) {
-        if (!(value & 0x04)) {
-            FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
-            return;
-        }
-    }
     FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value);
     /* Drive motors state indicators */
+#if MAX_FD >= 4
+    if (value & 0x80)
+        fd_start(drv3(fdctrl));
+    else
+        fd_stop(drv3(fdctrl));
+    if (value & 0x40)
+        fd_start(drv2(fdctrl));
+    else
+        fd_stop(drv2(fdctrl));
+#endif
     if (value & 0x20)
         fd_start(drv1(fdctrl));
     else
@@ -818,7 +852,11 @@
         }
     }
     /* Selected drive */
+#if MAX_FD >= 4
+    fdctrl->cur_drv = value & 3;
+#else
     fdctrl->cur_drv = value & 1;
+#endif
 }
 
 /* Tape drive register : 0x03 */
@@ -843,7 +881,11 @@
     }
     FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value);
     /* Disk boot selection indicator */
+#if MAX_FD >= 4
+    fdctrl->bootsel = (value >> 2) & 3;
+#else
     fdctrl->bootsel = (value >> 2) & 1;
+#endif
     /* Tape indicators: never allow */
 }
 
@@ -860,7 +902,10 @@
         if (fdctrl->data_dir == FD_DIR_READ)
             retval |= 0x40;
     }
-    /* Should handle 0x20 for SPECIFY command */
+    /* Non-DMA indicator */
+    if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA &&
+        !fdctrl->dma_en)
+        retval |= 0x20;
     /* Command busy indicator */
     if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA ||
         FD_STATE(fdctrl->data_state) == FD_STATE_STATUS)
@@ -956,6 +1001,40 @@
 #endif
 }
 
+/* Seek to next sector */
+static int fdctrl_seek_to_next_sect (fdctrl_t *fdctrl, fdrive_t *cur_drv)
+{
+    FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d)\n",
+                   cur_drv->head, cur_drv->track, cur_drv->sect,
+                   fd_sector(cur_drv));
+    /* XXX: cur_drv->sect >= cur_drv->last_sect should be an
+       error in fact */
+    if (cur_drv->sect >= cur_drv->last_sect ||
+        cur_drv->sect == fdctrl->eot) {
+        cur_drv->sect = 1;
+        if (FD_MULTI_TRACK(fdctrl->data_state)) {
+            if (cur_drv->head == 0 &&
+                (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
+                cur_drv->head = 1;
+            } else {
+                cur_drv->head = 0;
+                cur_drv->track++;
+                if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
+                    return 0;
+            }
+        } else {
+            cur_drv->track++;
+            return 0;
+        }
+        FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
+                       cur_drv->head, cur_drv->track,
+                       cur_drv->sect, fd_sector(cur_drv));
+    } else {
+        cur_drv->sect++;
+    }
+    return 1;
+}
+
 /* Callback for transfer end (stop or abort) */
 static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,
                                   uint8_t status1, uint8_t status2)
@@ -1042,9 +1121,9 @@
     } else {
         int tmp;
         fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]);
-        tmp = (cur_drv->last_sect - ks + 1);
+        tmp = (fdctrl->fifo[6] - ks + 1);
         if (fdctrl->fifo[0] & 0x80)
-            tmp += cur_drv->last_sect;
+            tmp += fdctrl->fifo[6];
         fdctrl->data_len *= tmp;
     }
     fdctrl->eot = fdctrl->fifo[6];
@@ -1178,35 +1257,8 @@
         rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
         if (rel_pos == 0) {
             /* Seek to next sector */
-            FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n",
-                           cur_drv->head, cur_drv->track, cur_drv->sect,
-                           fd_sector(cur_drv),
-                           fdctrl->data_pos - len);
-            /* XXX: cur_drv->sect >= cur_drv->last_sect should be an
-               error in fact */
-            if (cur_drv->sect >= cur_drv->last_sect ||
-                cur_drv->sect == fdctrl->eot) {
-                cur_drv->sect = 1;
-                if (FD_MULTI_TRACK(fdctrl->data_state)) {
-                    if (cur_drv->head == 0 &&
-                        (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
-                        cur_drv->head = 1;
-                    } else {
-                        cur_drv->head = 0;
-                        cur_drv->track++;
-                        if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
-                            break;
-                    }
-                } else {
-                    cur_drv->track++;
-                    break;
-                }
-                FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
-                               cur_drv->head, cur_drv->track,
-                               cur_drv->sect, fd_sector(cur_drv));
-            } else {
-                cur_drv->sect++;
-            }
+            if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv))
+                break;
         }
     }
  end_transfer:
@@ -1244,6 +1296,8 @@
     if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
         pos %= FD_SECTOR_LEN;
         if (pos == 0) {
+            if (fdctrl->data_pos != 0)
+                fdctrl_seek_to_next_sect(fdctrl, cur_drv);
             len = fdctrl->data_len - fdctrl->data_pos;
             if (len > FD_SECTOR_LEN)
                 len = FD_SECTOR_LEN;


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Qemu-devel] [PATCH] Fix multiple floppy controller issues
  2008-02-12 17:09 [Qemu-devel] [PATCH] Fix multiple floppy controller issues Hervé Poussineau
@ 2008-02-12 18:04 ` Blue Swirl
  0 siblings, 0 replies; 2+ messages in thread
From: Blue Swirl @ 2008-02-12 18:04 UTC (permalink / raw)
  To: qemu-devel

On 2/12/08, Hervé Poussineau <hpoussin@reactos.org> wrote:
> Hi,
>
> Attached patch fixes some issues in the floppy disk controller:
> - Enhance reset support (external and software)
> - Use MAX_FD constant when possible
> - Support up to 4 drives if MAX_FD is set to 4
> - Fix DOR register, which should be writable at any time
> - Let MSR return 0x20 when non-DMA transfer is happening
> - Don't assume caller wants to read whole track at once
> - Add seek to next sector when in non-DMA mode
>
> Credits to Stuart Brady to help me to debug some issues...

It's good to see someone working on FDC issues. As you may know,
floppy on Sparc is still broken. Maybe you could spot the problem in
the following logs (from splack-24oct2k3.iso, your patch applied,
DEBUG_FLOPPY enabled):

# network

Network support for NFS install, 19-May-2001 volkerdi@slackware.com

Please insert the network supplemental diskette (network.dsk),
and hit [enter] to continue.

FLOPPY: write reg2: 0x0c
FLOPPY: digital output register set to 0x0c
FLOPPY: write reg2: 0x0c
FLOPPY: digital output register set to 0x0c
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg2: 0x1c
FLOPPY: digital output register set to 0x1c
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: revalidate
FLOPPY: 1.44 MB 3"1/2 floppy disk (2 h 80 t 18 s) ro
FLOPPY: Floppy digital input register: 0x80
FLOPPY: read reg7: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg7: 0x00
FLOPPY: read reg7: 0x00
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x12
FLOPPY: PERPENDICULAR_MODE command
FLOPPY: fdctrl_write_data: 12
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x00
FLOPPY: fdctrl_write_data: 00
FLOPPY: treat PERPENDICULAR_MODE command
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x13
FLOPPY: CONFIGURE command
FLOPPY: fdctrl_write_data: 13
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x00
FLOPPY: fdctrl_write_data: 00
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x1a
FLOPPY: fdctrl_write_data: 1a
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x00
FLOPPY: fdctrl_write_data: 00
FLOPPY: treat CONFIGURE command
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x03
FLOPPY: SPECIFY command
FLOPPY: fdctrl_write_data: 03
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0xc1
FLOPPY: fdctrl_write_data: c1
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x11
FLOPPY: fdctrl_write_data: 11
FLOPPY: treat SPECIFY command
FLOPPY: read reg7: 0x00
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x07
FLOPPY: RECALIBRATE command
FLOPPY: fdctrl_write_data: 07
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x00
FLOPPY: fdctrl_write_data: 00
FLOPPY: treat RECALIBRATE command
FLOPPY: recalibrate
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
mount: block device /dev/fd0 is write-protected, mounting read-only
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg4: 0x80
FLOPPY: select rate register set to 0x80
FLOPPY: reset controller
FLOPPY: Reset interrupt
FLOPPY: recalibrate
FLOPPY: recalibrate
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg4: 0x80
FLOPPY: select rate register set to 0x80
FLOPPY: reset controller
FLOPPY: Reset interrupt
FLOPPY: recalibrate
FLOPPY: recalibrate
FLOPPY: Set interrupt status to 0xc0
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x08
FLOPPY: SENSE_INTERRUPT_STATUS command (c0)
FLOPPY: Reset interrupt
FLOPPY: main status register: 0xd0
FLOPPY: read reg4: 0xd0
FLOPPY: data register: 0x20
FLOPPY: read reg5: 0x20
FLOPPY: main status register: 0xd0
FLOPPY: read reg4: 0xd0
FLOPPY: Reset interrupt
FLOPPY: data register: 0x00
FLOPPY: read reg5: 0x00
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: read reg7: 0x00
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: read reg7: 0x00
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x12
FLOPPY: PERPENDICULAR_MODE command
FLOPPY: fdctrl_write_data: 12
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x00
FLOPPY: fdctrl_write_data: 00
FLOPPY: treat PERPENDICULAR_MODE command
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x13
FLOPPY: CONFIGURE command
FLOPPY: fdctrl_write_data: 13
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x00
FLOPPY: fdctrl_write_data: 00
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x1a
FLOPPY: fdctrl_write_data: 1a
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x00
FLOPPY: fdctrl_write_data: 00
FLOPPY: treat CONFIGURE command
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x03
FLOPPY: SPECIFY command
FLOPPY: fdctrl_write_data: 03
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0xc1
FLOPPY: fdctrl_write_data: c1
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x11
FLOPPY: fdctrl_write_data: 11
FLOPPY: treat SPECIFY command
FLOPPY: read reg7: 0x00
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x07
FLOPPY: RECALIBRATE command
FLOPPY: fdctrl_write_data: 07
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x00
FLOPPY: fdctrl_write_data: 00
FLOPPY: treat RECALIBRATE command
FLOPPY: recalibrate
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg4: 0x80
FLOPPY: select rate register set to 0x80
FLOPPY: reset controller
FLOPPY: Reset interrupt
FLOPPY: recalibrate
FLOPPY: recalibrate
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
mount: wrong fs type, bad option, bad superblock on /dev/fd0,
       or too many mounted file systems
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg4: 0x80
FLOPPY: select rate register set to 0x80
FLOPPY: reset controller
FLOPPY: Reset interrupt
FLOPPY: recalibrate
FLOPPY: recalibrate
FLOPPY: Set interrupt status to 0xc0
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: write reg5: 0x08
FLOPPY: SENSE_INTERRUPT_STATUS command (c0)
FLOPPY: Reset interrupt
FLOPPY: main status register: 0xd0
FLOPPY: read reg4: 0xd0
FLOPPY: data register: 0x20
FLOPPY: read reg5: 0x20
FLOPPY: main status register: 0xd0
FLOPPY: read reg4: 0xd0
FLOPPY: Reset interrupt
FLOPPY: data register: 0x00
FLOPPY: read reg5: 0x00
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
FLOPPY: read reg7: 0x00
FLOPPY: main status register: 0x80
FLOPPY: read reg4: 0x80
ERROR:  /network/scripts/network.sh not found.

This does not appear to be the correct disk.  Please make sure
the network supplemental diskette (network.dsk) is in the floppy
drive, and hit enter to continue, or control-c to abort.

Please insert the network supplemental diskette (network.dsk),
and hit [enter] to continue.FLOPPY: read reg7: 0x00
FLOPPY: write reg2: 0x0c
FLOPPY: digital output register set to 0x0c

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-02-12 18:04 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-12 17:09 [Qemu-devel] [PATCH] Fix multiple floppy controller issues Hervé Poussineau
2008-02-12 18:04 ` Blue Swirl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).