Tuesday, 12 October 2021

[Rpcemu] [PATCH 1/4] Implement FDC results as a queue rather than repeated callbacks

This removes some of the callback logic for returning FDC results, and makes it a bit easier to return error status.

diff -r 00a162d7e6cd -r d2affb36a0db src/fdc.c
--- a/src/fdc.c    Wed May 06 20:17:33 2020 +0100
+++ b/src/fdc.c    Wed Oct 06 21:34:59 2021 +0100
@@ -74,6 +74,8 @@
     uint8_t dmadat;
     int rate;
     int oldpos;
+    uint8_t results[16];
+    int result_rp, result_wp;
 } fdc;
 
 /* This enumeration must be kept in sync with the formats[] array */
@@ -176,6 +178,8 @@
 {
     fdccallback = 0;
     motoron = 0;
+    fdc.result_rp = 0;
+    fdc.result_wp = 0;
 }
 
 void
@@ -456,6 +460,7 @@
         case FD_CMD_DUMPREG: /* Used by Linux to identify FDC type. */
             fdc.st0       = 0x80;
             fdcsend(fdc.st0);
+            fdc_irq_raise();
             fdc.incommand = 0;
             fdccallback   = 0;
             fdc.status    = 0x80;
@@ -519,14 +524,19 @@
         fdc_irq_lower();
         return fdc.status;
 
-    case 0x3f5: /* Data (FIFO) */
-        fdc.status &= 0x7f;
-        if (!fdc.incommand) {
+    case 0x3f5: { /* Data (FIFO) */
+        uint8_t data = fdc.results[fdc.result_rp & 0xf];
+
+        if (fdc.result_rp != fdc.result_wp)
+            fdc.result_rp++;
+
+        if (fdc.result_rp == fdc.result_wp)
             fdc.status = 0x80;
-        } else {
-            fdccallback = 100;
-        }
-        return fdc.data;
+        else
+            fdc.status |= 0xc0;
+
+        return data;
+    }
 
     // case 0x3f7: /* Digital Input Register (DIR) */
         // TODO Disc changed flag
@@ -542,16 +552,8 @@
 static void
 fdcsend(uint8_t val)
 {
-    fdc.data   = val;
-    fdc.status = 0xd0;
-    fdc_irq_raise();
-}
-
-static void
-fdcsend2(uint8_t val)
-{
-    fdc.data   = val;
-    fdc.status = 0xd0;
+    fdc.results[fdc.result_wp & 0xf] = val;
+    fdc.result_wp++;
 }
 
 static void
@@ -595,6 +597,8 @@
 
         fdc.incommand = 0;
         fdcsend(fdc.st3);
+        fdc.status = 0xD0;
+        fdc_irq_raise();
         fdc.params    = 0;
         fdc.curparam  = 0;
         break;
@@ -611,14 +615,11 @@
         break;
 
     case FD_CMD_SENSE_INTERRUPT_STATUS:
-        fdc.commandpos++;
-        if (fdc.commandpos == 1) {
-            fdcsend(fdc.st0);
-            fdccallback = 100;
-        } else {
-            fdc.incommand = 0;
-            fdcsend(fdc.track);
-        }
+        fdcsend(fdc.st0);
+        fdcsend(fdc.track);
+        fdc.status = 0xD0;
+        fdc_irq_raise();
+        fdc.incommand = 0;
         break;
 
 //    case FD_CMD_DUMPREG: /*Dump registers - act as invalid command*/
@@ -651,22 +652,19 @@
             fdccallback    = 500;
             fdc.sector++;
         } else if (fdc.commandpos >= (drives[fdc.st0 & 1].format->sectorsize + 1)) {
-            switch (fdc.commandpos - (drives[fdc.st0 & 1].format->sectorsize + 1)) {
-            case 0: fdcsend(fdc.st0); break;
-            case 1: fdcsend2(fdc.st1); break;
-            case 2: fdcsend2(fdc.st2); break;
-            case 3: fdcsend2(fdc.track); break;
-            case 4: fdcsend2((fdc.parameters[0] & 4) ? 1 : 0); break;
-            case 5: fdcsend2(fdc.sector); break;
-            case 6:
-                fdcsend2(fdc_size_code_from_sector_size(drives[fdc.st0 & 1].format->sectorsize));
-                fdc.incommand = 0;
-                fdc.params    = 0;
-                fdc.curparam  = 0;
-                fdccallback   = 0;
-                break;
-            }
-            fdc.commandpos++;
+            fdcsend(fdc.st0);
+            fdcsend(fdc.st1);
+            fdcsend(fdc.st2);
+            fdcsend(fdc.track);
+            fdcsend((fdc.parameters[0] & 4) ? 1 : 0);
+            fdcsend(fdc.sector);
+            fdcsend(fdc_size_code_from_sector_size(drives[fdc.st0 & 1].format->sectorsize));
+            fdc.status = 0xD0;
+            fdc_irq_raise();
+            fdc.incommand = 0;
+            fdc.params    = 0;
+            fdc.curparam  = 0;
+            fdccallback   = 0;
         } else {
             if (fdc.commandpos) {
                 drives[fdc.st0 & 1].disc[fdc.side][fdc.track][fdc.sector][fdc.commandpos - 1] = fdc.dmadat;
@@ -691,22 +689,19 @@
 
     case FD_CMD_READ_DATA_MFM:
         if (fdc.commandpos >= drives[fdc.st0 & 1].format->sectorsize) {
-            switch (fdc.commandpos - drives[fdc.st0 & 1].format->sectorsize) {
-            case 0: fdcsend(fdc.st0); break;
-            case 1: fdcsend2(fdc.st1); break;
-            case 2: fdcsend2(fdc.st2); break;
-            case 3: fdcsend2(fdc.track); break;
-            case 4: fdcsend2((fdc.parameters[0] & 4) ? 1 : 0); break;
-            case 5: fdcsend2(fdc.sector); break;
-            case 6:
-                fdcsend2(fdc_size_code_from_sector_size(drives[fdc.st0 & 1].format->sectorsize));
-                fdc.incommand = 0;
-                fdc.params    = 0;
-                fdc.curparam  = 0;
-                fdccallback   = 0;
-                break;
-            }
-            fdc.commandpos++;
+            fdcsend(fdc.st0);
+            fdcsend(fdc.st1);
+            fdcsend(fdc.st2);
+            fdcsend(fdc.track);
+            fdcsend((fdc.parameters[0] & 4) ? 1 : 0);
+            fdcsend(fdc.sector);
+            fdcsend(fdc_size_code_from_sector_size(drives[fdc.st0 & 1].format->sectorsize));
+            fdc.status = 0xD0;
+            fdc_irq_raise();
+            fdc.incommand = 0;
+            fdc.params    = 0;
+            fdc.curparam  = 0;
+            fdccallback   = 0;
         } else {
             fdcsenddata(drives[fdc.st0 & 1].disc[fdc.side][fdc.track][fdc.sector][fdc.commandpos]);
             fdc.commandpos++;
@@ -731,30 +726,24 @@
             // Reset back to first valid sector
             fdc.sector = drives[fdc.st0 & 1].format->sectorskew;
         }
-        switch (fdc.commandpos) {
-        case 0: fdcsend(fdc.st0); break;
-        case 1: fdcsend2(fdc.st1); break;
-        case 2: fdcsend2(fdc.st2); break;
-        case 3: fdcsend2(fdc.track); break;
-        case 4: fdcsend2((fdc.parameters[0] & 4) ? 1 : 0); break;
-        case 5: fdcsend2(fdc.sector); break;
-        case 6: fdcsend2(fdc_size_code_from_sector_size(drives[fdc.st0 & 1].format->sectorsize)); break;
-        default:
-            printf("Bad ReadID command pos %i\n", fdc.commandpos);
-            exit(-1);
+        fdcsend(fdc.st0);
+        fdcsend(fdc.st1);
+        fdcsend(fdc.st2);
+        fdcsend(fdc.track);
+        fdcsend((fdc.parameters[0] & 4) ? 1 : 0);
+        fdcsend(fdc.sector);
+        fdcsend(fdc_size_code_from_sector_size(drives[fdc.st0 & 1].format->sectorsize));
+        fdc.status = 0xD0;
+        fdc_irq_raise();
+
+        fdc.incommand = 0;
+        fdc.sector++;
+        if (fdc.sector >= drives[fdc.st0 & 1].format->sectors  + drives[fdc.st0 & 1].format->sectorskew) {
+            // Reset back to first valid sector
+            fdc.sector = drives[fdc.st0 & 1].format->sectorskew;
         }
-
-        fdc.commandpos++;
-        if (fdc.commandpos == 7) {
-            fdc.incommand = 0;
-            fdc.sector++;
-            if (fdc.sector >= drives[fdc.st0 & 1].format->sectors  + drives[fdc.st0 & 1].format->sectorskew) {
-                // Reset back to first valid sector
-                fdc.sector = drives[fdc.st0 & 1].format->sectorskew;
-            }
-            fdc.params   = 0;
-            fdc.curparam = 0;
-        }
+        fdc.params   = 0;
+        fdc.curparam = 0;
         break;
 
     case FD_CMD_READ_ID_FM:
@@ -768,23 +757,18 @@
         break;
 
     case FD_CMD_FORMAT_TRACK_MFM:
-        switch (fdc.commandpos) {
-        case 0: fdcsend(fdc.st0);  break;
-        case 1: fdcsend2(fdc.st1); break;
-        case 2: fdcsend2(fdc.st2); break;
-        case 3: fdcsend2(0); break;
-        case 4: fdcsend2(0); break;
-        case 5: fdcsend2(0); break;
-        case 6:
-            fdcsend2(0);
-            fdc.incommand = 0;
-            fdc.params    = 0;
-            fdc.curparam  = 0;
-            break;
-        default:
-            fatal("Bad FormatTrack command pos %i", fdc.commandpos);
-        }
-        fdc.commandpos++;
+        fdcsend(fdc.st0);
+        fdcsend(fdc.st1);
+        fdcsend(fdc.st2);
+        fdcsend(0);
+        fdcsend(0);
+        fdcsend(0);
+        fdcsend(0);
+        fdc.status = 0xD0;
+        fdc_irq_raise();
+        fdc.incommand = 0;
+        fdc.params    = 0;
+        fdc.curparam  = 0;
         break;
 
     case FD_CMD_VERIFY_DATA_MFM:
@@ -794,23 +778,18 @@
         } else {
             fdc.sector = fdc.parameters[5];
         }
-        switch (fdc.commandpos) {
-        case 0: fdcsend(fdc.st0); break;
-        case 1: fdcsend2(fdc.st1); break;
-        case 2: fdcsend2(fdc.st2); break;
-        case 3: fdcsend2(fdc.track); break;
-        case 4: fdcsend2((fdc.parameters[0] & 4) ? 1 : 0); break;
-        case 5: fdcsend2(fdc.sector); break;
-        case 6:
-            fdcsend2(fdc_size_code_from_sector_size(drives[fdc.st0 & 1].format->sectorsize));
-            fdc.incommand = 0;
-            fdc.params    = 0;
-            fdc.curparam  = 0;
-            break;
-        default:
-            fatal("Bad VerifyData command pos %i", fdc.commandpos);
-        }
-        fdc.commandpos++;
+        fdcsend(fdc.st0);
+        fdcsend(fdc.st1);
+        fdcsend(fdc.st2);
+        fdcsend(fdc.track);
+        fdcsend((fdc.parameters[0] & 4) ? 1 : 0);
+        fdcsend(fdc.sector);
+        fdcsend(fdc_size_code_from_sector_size(drives[fdc.st0 & 1].format->sectorsize));
+        fdc.status = 0xD0;
+        fdc_irq_raise();
+        fdc.incommand = 0;
+        fdc.params    = 0;
+        fdc.curparam  = 0;
         break;
     }
 }


_______________________________________________
RPCEmu mailing list
RPCEmu@riscos.info
http://www.riscos.info/cgi-bin/mailman/listinfo/rpcemu

No comments:

Post a Comment