diff -r d2affb36a0db -r 592604520b7e src/ArmDynarec.c
--- a/src/ArmDynarec.c Wed Oct 06 21:34:59 2021 +0100
+++ b/src/ArmDynarec.c Sat Oct 09 14:01:30 2021 +0100
@@ -48,6 +48,7 @@
#include "arm.h"
#include "cp15.h"
#include "fdc.h"
+#include "disc_adf.h"
#if defined __amd64__
# include "codegen_amd64.h"
@@ -61,7 +62,6 @@
ARMState arm;
-static int fdci=0;
static int cycles;
int prefabort;
uint32_t inscount;
@@ -940,14 +940,8 @@
callbackide();
}
}
- if (motoron) {
- fdci--;
- if (fdci <= 0) {
- fdci = 20000;
- iomd.irqa.status |= IOMD_IRQA_FLOPPY_INDEX;
- updateirqs();
- }
- }
+ if (motoron)
+ disc_poll();
cycles -= 1000;
}
}
diff -r d2affb36a0db -r 592604520b7e src/arm.c
--- a/src/arm.c Wed Oct 06 21:34:59 2021 +0100
+++ b/src/arm.c Sat Oct 09 14:01:30 2021 +0100
@@ -54,11 +54,11 @@
#include "keyboard.h"
#include "fdc.h"
#include "ide.h"
+#include "disc_adf.h"
ARMState arm;
int blockend;
-static int fdci=0;
static int cycles;
int prefabort;
uint32_t inscount;
@@ -1975,14 +1975,8 @@
callbackide();
}
}
- if (motoron) {
- fdci--;
- if (fdci <= 0) {
- fdci = 20000;
- iomd.irqa.status |= IOMD_IRQA_FLOPPY_INDEX;
- updateirqs();
- }
- }
+ if (motoron)
+ disc_poll();
// cyc=(oldcyc-cycles);
cycles -= 200;
}
diff -r d2affb36a0db -r 592604520b7e src/disc_adf.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/disc_adf.c Sat Oct 09 14:01:30 2021 +0100
@@ -0,0 +1,279 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include "rpcemu.h"
+#include "disc_adf.h"
+#include "fdc.h"
+
+static struct {
+ FILE *f;
+ uint8_t track_data[2][20*1024];
+
+ int dblside;
+ int sectors, size, track;
+ int dblstep;
+ int density;
+ int maxsector;
+ int skew;
+ int write_prot;
+} adf[4];
+
+static struct {
+ int sector;
+ int track;
+ int side;
+ int drive;
+
+ int readpos;
+
+ int inread;
+ int inwrite;
+ int inreadaddr;
+ int informat;
+
+ int notfound;
+ int cur_sector;
+
+ int pause;
+ int index;
+} adf_state;
+
+void adf_init(void)
+{
+ memset(adf, 0, sizeof(adf));
+ memset(&adf_state, 0, sizeof(adf_state));
+}
+
+void adf_load(int drive, const char *fn, int sectors, int size, int sides, int dblstep, int density, int skew)
+{
+// rpclog("adf_load: drive=%i fn=%s\n", drive, fn);
+ adf[drive].write_prot = 0;
+ adf[drive].f = fopen(fn, "rb+");
+ if (!adf[drive].f) {
+ adf[drive].f = fopen(fn, "rb");
+ if (!adf[drive].f) {
+ rpclog("adf_load: failed!\n");
+ return;
+ }
+ adf[drive].write_prot = 1;
+ }
+ fseek(adf[drive].f, -1, SEEK_END);
+
+ adf[drive].sectors = sectors;
+ adf[drive].size = size;
+ adf[drive].dblside = sides;
+ adf[drive].dblstep = dblstep;
+ adf[drive].density = density;
+ adf[drive].maxsector = (ftell(adf[drive].f)+1 ) / size;
+ adf[drive].skew = skew;
+
+ adf_seek(drive, 0);
+}
+
+
+void adf_close(int drive)
+{
+ if (adf[drive].f)
+ fclose(adf[drive].f);
+ adf[drive].f = NULL;
+}
+
+void adf_seek(int drive, int track)
+{
+ if (!adf[drive].f)
+ return;
+// rpclog("Seek %i %i\n", drive, track);
+ if (adf[drive].dblstep)
+ track /= 2;
+ adf[drive].track = track;
+ if (adf[drive].dblside) {
+ fseek(adf[drive].f, track * adf[drive].sectors * adf[drive].size * 2, SEEK_SET);
+ fread(adf[drive].track_data[0], adf[drive].sectors * adf[drive].size, 1, adf[drive].f);
+ fread(adf[drive].track_data[1], adf[drive].sectors * adf[drive].size, 1, adf[drive].f);
+ } else {
+ fseek(adf[drive].f, track * adf[drive].sectors * adf[drive].size, SEEK_SET);
+ fread(adf[drive].track_data[0], adf[drive].sectors * adf[drive].size, 1, adf[drive].f);
+ }
+}
+void adf_writeback(int drive, int track)
+{
+ if (!adf[drive].f)
+ return;
+
+ if (adf[drive].dblstep)
+ track /= 2;
+
+ if (adf[drive].dblside) {
+ fseek(adf[drive].f, track * adf[drive].sectors * adf[drive].size * 2, SEEK_SET);
+ fwrite(adf[drive].track_data[0], adf[drive].sectors * adf[drive].size, 1, adf[drive].f);
+ fwrite(adf[drive].track_data[1], adf[drive].sectors * adf[drive].size, 1, adf[drive].f);
+ } else {
+ fseek(adf[drive].f, track * adf[drive].sectors * adf[drive].size, SEEK_SET);
+ fwrite(adf[drive].track_data[0], adf[drive].sectors * adf[drive].size, 1, adf[drive].f);
+ }
+}
+
+void adf_readsector(int drive, int sector, int track, int side, int density)
+{
+ int sector_nr = (sector - adf[drive].skew) + adf[drive].sectors * (track * (adf[drive].dblside ? 2 : 1) + (side ? 1 : 0));
+
+// rpclog("adf_readsector: drive=%i sector=%i track=%i side=%i density=%i\n", drive, sector, track, side, density);
+ adf_state.sector = sector - adf[drive].skew;
+ adf_state.track = track;
+ adf_state.side = side;
+ adf_state.drive = drive;
+
+ if (!adf[drive].f || (side && !adf[drive].dblside) || (density != adf[drive].density) ||
+ (track != adf[drive].track) || (sector_nr >= adf[drive].maxsector) ||
+ (adf_state.sector > adf[drive].sectors)) {
+ adf_state.notfound=500;
+ return;
+ }
+
+ adf_state.inread = 1;
+ adf_state.readpos = 0;
+}
+
+void adf_writesector(int drive, int sector, int track, int side, int density)
+{
+ int sector_nr = (sector - adf[drive].skew) + adf[drive].sectors * (track * (adf[drive].dblside ? 2 : 1) + (side ? 1 : 0));
+
+// rpclog("adf_writesector: drive=%i sector=%i track=%i side=%i density=%i\n", drive, sector, track, side, density);
+ adf_state.sector = sector - adf[drive].skew;
+ adf_state.track = track;
+ adf_state.side = side;
+ adf_state.drive = drive;
+
+ if (!adf[drive].f || (side && !adf[drive].dblside) || (density != adf[drive].density) ||
+ (track != adf[drive].track) || (sector_nr >= adf[drive].maxsector) ||
+ (adf_state.sector > adf[drive].sectors)) {
+ adf_state.notfound = 500;
+ return;
+ }
+ adf_state.inwrite = 1;
+ adf_state.readpos = 0;
+}
+
+void adf_readaddress(int drive, int track, int side, int density)
+{
+ if (adf[drive].dblstep)
+ track /= 2;
+
+// rpclog("adf_readaddress: drive=%i track=%i side=%i density=%i\n", drive, track, side, density);
+ adf_state.drive = drive;
+ adf_state.track = track;
+ adf_state.side = side;
+
+ if (!adf[drive].f || (side && !adf[drive].dblside) ||
+ (density != adf[drive].density) || (track != adf[drive].track)) {
+ adf_state.notfound=500;
+ return;
+ }
+ adf_state.inreadaddr = 1;
+ adf_state.readpos = 0;
+ adf_state.pause = 100;//500;
+}
+
+void adf_format(int drive, int track, int side, int density)
+{
+ if (adf[drive].dblstep)
+ track /= 2;
+
+ adf_state.drive = drive;
+ adf_state.track = track;
+ adf_state.side = side;
+
+ if (!adf[drive].f || (side && !adf[drive].dblside) || (density != adf[drive].density) ||
+ track != adf[drive].track) {
+ adf_state.notfound = 500;
+ return;
+ }
+ adf_state.sector = 0;
+ adf_state.readpos = 0;
+ adf_state.informat = 1;
+}
+
+void adf_stop(void)
+{
+// rpclog("adf_stop\n");
+
+ adf_state.pause = 0;
+ adf_state.notfound = 0;
+ adf_state.inread = 0;
+ adf_state.inwrite = 0;
+ adf_state.inreadaddr = 0;
+ adf_state.informat = 0;
+}
+
+void adf_poll(void)
+{
+ int c;
+
+ adf_state.index--;
+ if (adf_state.index <= 0) {
+ adf_state.index = 6250;
+ fdc_indexpulse();
+ }
+
+ if (adf_state.pause) {
+ adf_state.pause--;
+ if (adf_state.pause)
+ return;
+ }
+
+ if (adf_state.notfound) {
+ adf_state.notfound--;
+ if (!adf_state.notfound)
+ fdc_notfound();
+ }
+ if (adf_state.inread && adf[adf_state.drive].f) {
+ fdc_data(adf[adf_state.drive].track_data[adf_state.side][(adf_state.sector * adf[adf_state.drive].size) + adf_state.readpos]);
+ adf_state.readpos++;
+ if (adf_state.readpos == adf[adf_state.drive].size) {
+ adf_state.inread = 0;
+ fdc_finishread();
+ }
+ }
+ if (adf_state.inwrite && adf[adf_state.drive].f) {
+ if (adf[adf_state.drive].write_prot) {
+ fdc_writeprotect();
+ adf_state.inwrite = 0;
+ return;
+ }
+ c = fdc_getdata(adf_state.readpos == (adf[adf_state.drive].size - 1));
+ if (c == -1)
+ return;
+ adf[adf_state.drive].track_data[adf_state.side][(adf_state.sector * adf[adf_state.drive].size) + adf_state.readpos] = c;
+ adf_state.readpos++;
+ if (adf_state.readpos == adf[adf_state.drive].size) {
+ adf_state.inwrite = 0;
+ fdc_finishread();
+ adf_writeback(adf_state.drive, adf_state.track);
+ }
+ }
+ if (adf_state.inreadaddr && adf[adf_state.drive].f) {
+ fdc_sectorid(adf_state.track, adf_state.side, adf_state.sector + adf[adf_state.drive].skew, (adf[adf_state.drive].size == 256) ? 1 : ((adf[adf_state.drive].size == 512) ? 2 : 3));
+ adf_state.inreadaddr = 0;
+ adf_state.sector++;
+ if (adf_state.sector >= adf[adf_state.drive].sectors)
+ adf_state.sector=0;
+ }
+ if (adf_state.informat && adf[adf_state.drive].f) {
+ if (adf[adf_state.drive].write_prot) {
+ fdc_writeprotect();
+ adf_state.informat = 0;
+ return;
+ }
+ adf[adf_state.drive].track_data[adf_state.side][(adf_state.sector * adf[adf_state.drive].size) + adf_state.readpos] = 0;
+ adf_state.readpos++;
+ if (adf_state.readpos == adf[adf_state.drive].size) {
+ adf_state.readpos = 0;
+ adf_state.sector++;
+ if (adf_state.sector == adf[adf_state.drive].sectors) {
+ adf_state.informat = 0;
+ fdc_finishread();
+ adf_writeback(adf_state.drive, adf_state.track);
+ }
+ }
+ }
+}
diff -r d2affb36a0db -r 592604520b7e src/disc_adf.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/disc_adf.h Sat Oct 09 14:01:30 2021 +0100
@@ -0,0 +1,20 @@
+extern void adf_init(void);
+
+extern void adf_load(int drive, const char *fn, int sectors, int size, int dblside, int dblstep, int density, int skew);
+
+extern void adf_close(int drive);
+extern void adf_seek(int drive, int track);
+extern void adf_readsector(int drive, int sector, int track, int side, int density);
+extern void adf_writesector(int drive, int sector, int track, int side, int density);
+extern void adf_readaddress(int drive, int sector, int side, int density);
+extern void adf_format(int drive, int sector, int side, int density);
+extern void adf_stop(void);
+extern void adf_poll(void);
+
+#define disc_seek adf_seek
+#define disc_readsector adf_readsector
+#define disc_writesector adf_writesector
+#define disc_readaddress adf_readaddress
+#define disc_format adf_format
+#define disc_stop adf_stop
+#define disc_poll adf_poll
\ No newline at end of file
diff -r d2affb36a0db -r 592604520b7e src/fdc.c
--- a/src/fdc.c Wed Oct 06 21:34:59 2021 +0100
+++ b/src/fdc.c Sat Oct 09 14:01:30 2021 +0100
@@ -32,6 +32,7 @@
#include "iomd.h"
#include "ide.h"
#include "arm.h"
+#include "disc_adf.h"
/* FDC commands */
enum {
@@ -63,7 +64,6 @@
uint8_t st1;
uint8_t st2;
uint8_t st3;
- int commandpos;
int track;
int sector;
int side;
@@ -76,6 +76,12 @@
int oldpos;
uint8_t results[16];
int result_rp, result_wp;
+ int drive;
+ int density;
+ int tc;
+ int data_ready;
+ int written;
+ int in_read;
} fdc;
/* This enumeration must be kept in sync with the formats[] array */
@@ -109,19 +115,6 @@
{ "DOS 1440KB", "img", 2, 80, 18, 512, 1, 0 }
};
-/**
- * Structure to hold information about a specific floppy drive and the disc
- * image inside it
- */
-typedef struct {
- uint8_t disc[2][80][19][1024]; /**< side, Track, Sector (+ max skew), Bytes, large enough to hold all format variants */
- const Format *format;
- int discchanged;
-} Drive;
-
-/** Floppy controller has two disc drives attached */
-static Drive drives[2];
-
int fdccallback = 0;
int motoron = 0;
@@ -153,26 +146,6 @@
updateirqs();
}
-/**
- * Calculate the size code for a given length of sector
- *
- * @param sectorsize size of one sector on disc (in bytes)
- * @return code used to represent that sectorsize
- */
-static uint8_t
-fdc_size_code_from_sector_size(int sectorsize)
-{
- switch (sectorsize) {
- case 128: return 0;
- case 256: return 1;
- case 512: return 2;
- case 1024: return 3;
- }
-
- UNIMPLEMENTED("fdc", "Unsupported sectorsize %d", sectorsize);
- return 0;
-}
-
void
fdc_reset(void)
{
@@ -185,12 +158,6 @@
void
fdc_init(void)
{
- int d;
-
- for (d = 0; d < 2; d++) {
- // Configure a default format
- drives[d].format = &formats[DISC_FORMAT_ADFS_DE_800K];
- }
}
/**
@@ -204,9 +171,9 @@
fdc_image_load(const char *fn, int drive)
{
FILE *f;
- int h, t, s, b;
const char *extension;
long len;
+ static const Format *format;
assert(drive == 0 || drive == 1); // Only support two drives
assert(fn != NULL); // Must have filename
@@ -235,94 +202,39 @@
if (strcasecmp(extension, ".adf") == 0) {
if (len > 1000000) {
- drives[drive].format = &formats[DISC_FORMAT_ADFS_F_1600K];
+ format = &formats[DISC_FORMAT_ADFS_F_1600K];
} else {
- drives[drive].format = &formats[DISC_FORMAT_ADFS_DE_800K];
+ format = &formats[DISC_FORMAT_ADFS_DE_800K];
}
} else if (strcasecmp(extension, ".adl") == 0) {
- drives[drive].format = &formats[DISC_FORMAT_ADFS_L_640K];
+ format = &formats[DISC_FORMAT_ADFS_L_640K];
} else if (strcasecmp(extension, ".img") == 0) {
if (len > 1250000) {
- drives[drive].format = &formats[DISC_FORMAT_DOS_1440K];
+ format = &formats[DISC_FORMAT_DOS_1440K];
} else if (len > 400000) {
- drives[drive].format = &formats[DISC_FORMAT_DOS_720K];
+ format = &formats[DISC_FORMAT_DOS_720K];
} else {
- drives[drive].format = &formats[DISC_FORMAT_DOS_360K];
+ format = &formats[DISC_FORMAT_DOS_360K];
}
} else {
error("Unknown disc image file extension '%s', must be .adf or .adl", extension);
fclose(f);
return;
}
-
- rpclog("fdc_image_load: %s (%ld) loaded as '%s'\n", fn, len, drives[drive].format->name);
-
- drives[drive].discchanged = 0;
- rewind(f);
+ fclose(f);
- for (t = 0; t < drives[drive].format->tracks ; t++) {
- for (h = 0; h < drives[drive].format->sides; h++) {
- for (s = drives[drive].format->sectorskew; s < drives[drive].format->sectors + drives[drive].format->sectorskew; s++) {
- for (b = 0; b < drives[drive].format->sectorsize; b++) {
- drives[drive].disc[h][t][s][b] = fgetc(f);
- }
- }
- }
- }
-
- // reset the sector to the first valid one
- fdc.sector = drives[drive].format->sectorskew;
-
- fclose(f);
+ rpclog("fdc_image_load: %s (%ld) loaded as '%s'\n", fn, len, format->name);
+ adf_load(drive, fn, format->sectors, format->sectorsize, format->sides, format->tracks == 40,
+ format->density ? 1 : 2, format->sectorskew);
}
-/**
- * Save a disc image from one of the two virtual floppy
- * disc drives to host disc.
- *
- * @param fn Filename of disc image to load (including .adf .adl extension)
- * @param drive Which drive to save image from 0 or 1
- */
void
fdc_image_save(const char *fn, int drive)
{
- FILE *f;
- int h, t, s, b;
-
- assert(drive == 0 || drive == 1); // Only support two drives
- assert(fn != NULL); // Must have filename
-
- if (!drives[drive].discchanged) {
- return;
- }
-
- // must be at least a.ext
- if (strlen(fn) < 5 || fn[strlen(fn) - 4] != '.') {
- error("Disc image filename must include a file extension (.adf,.adl)");
- return;
- }
-
- f = fopen(fn, "wb");
- if (f == NULL) {
-// error("Unable to open disc image '%s'", fn);
- return;
- }
- drives[drive].discchanged = 0;
-
- for (t = 0; t < drives[drive].format->tracks; t++) {
- for (h = 0; h < drives[drive].format->sides; h++) {
- for (s = drives[drive].format->sectorskew; s < drives[drive].format->sectors + drives[drive].format->sectorskew; s++) {
- for (b = 0; b < drives[drive].format->sectorsize; b++) {
- putc(drives[drive].disc[h][t][s][b], f);
- }
- }
- }
- }
-
- fclose(f);
+ (void)fn;
+ adf_close(drive);
}
-
void
fdc_write(uint32_t addr, uint32_t val)
{
@@ -347,6 +259,9 @@
if (fdc.curparam == fdc.params) {
fdc.status &= ~0x80;
+ fdc.tc = 0;
+ fdc.data_ready = 0;
+ fdc.in_read = 0;
switch (fdc.command) {
case FD_CMD_SPECIFY:
fdccallback = 100;
@@ -357,9 +272,15 @@
break;
case FD_CMD_RECALIBRATE:
+ fdccallback = 500;
+ fdc.status |= 1;
+ disc_seek(fdc.parameters[0] & 1, 0);
+ break;
+
case FD_CMD_SEEK:
fdccallback = 500;
fdc.status |= 1;
+ disc_seek(fdc.parameters[0] & 1, fdc.parameters[1]);
break;
case FD_CMD_CONFIGURE:
@@ -367,54 +288,51 @@
break;
case FD_CMD_WRITE_DATA_MFM:
- fdc.commandpos = 0;
- fdccallback = 1000;
fdc.st0 = fdc.parameters[0] & 7;
fdc.st1 = 0;
fdc.st2 = 0;
fdc.track = fdc.parameters[1];
fdc.side = fdc.parameters[2];
fdc.sector = fdc.parameters[3];
- drives[fdc.st0 & 1].discchanged = 1;
+ fdc.drive = fdc.st0 & 1;
+ disc_writesector(fdc.st0 & 1, fdc.sector, fdc.track, fdc.side, fdc.density);
+ fdc_dma_raise();
break;
case FD_CMD_READ_DATA_MFM:
+ fdc.in_read = 1;
case FD_CMD_VERIFY_DATA_MFM:
- fdc.commandpos = 0;
- fdccallback = 1000;
fdc.st0 = fdc.parameters[0] & 7;
fdc.st1 = 0;
fdc.st2 = 0;
fdc.track = fdc.parameters[1];
fdc.side = fdc.parameters[2];
fdc.sector = fdc.parameters[3];
+ fdc.drive = fdc.st0 & 1;
+ disc_readsector(fdc.st0 & 1, fdc.sector, fdc.track, fdc.side, fdc.density);
break;
case FD_CMD_READ_ID_MFM:
- fdc.commandpos = 0;
+ fdc.st0 = fdc.parameters[0] & 7;
+ fdc.st1 = 0;
+ fdc.st2 = 0;
+ fdc.drive = fdc.st0 & 1;
+ disc_readaddress(fdc.st0 & 1, fdc.track, fdc.side, fdc.density);
+ break;
+
+ case FD_CMD_READ_ID_FM:
fdccallback = 4000;
fdc.st0 = fdc.parameters[0] & 7;
fdc.st1 = 0;
fdc.st2 = 0;
- if (fdc.rate != drives[fdc.st0 & 1].format->density) {
- fdc.command = FD_CMD_READ_ID_FM;
- }
+ fdc.drive = fdc.st0 & 1;
break;
- case FD_CMD_READ_ID_FM:
- fdc.commandpos = 0;
- fdccallback = 4000;
+ case FD_CMD_FORMAT_TRACK_MFM:
fdc.st0 = fdc.parameters[0] & 7;
fdc.st1 = 0;
fdc.st2 = 0;
- break;
-
- case FD_CMD_FORMAT_TRACK_MFM:
- fdc.commandpos = 0;
- fdc.st0 = fdc.parameters[0] & 7;
- fdc.st1 = 0;
- fdc.st2 = 0;
- fdccallback = 1000;
+ fdc.drive = fdc.st0 & 1;
break;
default:
@@ -430,7 +348,6 @@
fatal("FDC already in command\n");
}
fdc.incommand = 1;
- fdc.commandpos = 0;
fdc.command = val;
switch (fdc.command) {
@@ -508,6 +425,17 @@
case 0x3f7: /* Configuration Control Register (CCR) */
fdc.rate = val & 3;
+ switch (val & 3) {
+ case 0:
+ fdc.density = 2;
+ break;
+ case 1: case 2:
+ fdc.density = 1;
+ break;
+ case 3:
+ fdc.density = 3;
+ break;
+ }
break;
default:
@@ -556,11 +484,13 @@
fdc.result_wp++;
}
-static void
-fdcsenddata(uint8_t val)
+static void fdc_end_command(void)
{
- fdc.dmadat = val;
- fdc_dma_raise();
+ fdc.status = 0xD0;
+ fdc.incommand = 0;
+ fdc.params = 0;
+ fdccallback = 0;
+ fdc_irq_raise();
}
void
@@ -646,19 +576,17 @@
break;
case FD_CMD_WRITE_DATA_MFM:
- if (fdc.commandpos == 2048) { // DMA Write
- drives[fdc.st0 & 1].disc[fdc.side][fdc.track][fdc.sector][fdc.oldpos - 1] = fdc.dmadat;
- fdc.commandpos = drives[fdc.st0 & 1].format->sectorsize + 1;
- fdccallback = 500;
- fdc.sector++;
- } else if (fdc.commandpos >= (drives[fdc.st0 & 1].format->sectorsize + 1)) {
+ fdc.sector++;
+ if (fdc.sector > fdc.parameters[5])
+ fdc.tc = 1;
+ if (fdc.tc) {
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));
+ fdcsend(fdc.parameters[4]);
fdc.status = 0xD0;
fdc_irq_raise();
fdc.incommand = 0;
@@ -666,36 +594,23 @@
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;
- }
- fdc.commandpos++;
- if (fdc.commandpos == drives[fdc.st0 & 1].format->sectorsize + 1) {
- fdc.sector++;
- if (fdc.sector <= fdc.parameters[5]) {
- fdc.commandpos = 0;
- fdccallback = 100;
- return;
- } else {
- fdccallback = 100;
- return;
- }
- } else {
- fdc_dma_raise();
- }
- fdccallback = 0;
+ disc_writesector(fdc.drive, fdc.sector, fdc.track, fdc.side, fdc.density);
+ fdc_dma_raise();
}
break;
case FD_CMD_READ_DATA_MFM:
- if (fdc.commandpos >= drives[fdc.st0 & 1].format->sectorsize) {
+ fdc.sector++;
+ if (fdc.sector > fdc.parameters[5])
+ fdc.tc = 1;
+ if (fdc.tc) {
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));
+ fdcsend(fdc.parameters[4]);
fdc.status = 0xD0;
fdc_irq_raise();
fdc.incommand = 0;
@@ -703,49 +618,10 @@
fdc.curparam = 0;
fdccallback = 0;
} else {
- fdcsenddata(drives[fdc.st0 & 1].disc[fdc.side][fdc.track][fdc.sector][fdc.commandpos]);
- fdc.commandpos++;
- if (fdc.commandpos == drives[fdc.st0 & 1].format->sectorsize) {
- fdc.sector++;
- if (fdc.sector <= fdc.parameters[5]) {
- fdc.commandpos = 0;
- }
- /*
- else {
- // printf("End of read op\n");
- fdc.sector = 1;
- }
- */
- }
- fdccallback = 0;
+ disc_readsector(fdc.drive, fdc.sector, fdc.track, fdc.side, fdc.density);
}
break;
- case FD_CMD_READ_ID_MFM:
- 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;
- }
- 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.params = 0;
- fdc.curparam = 0;
- break;
-
case FD_CMD_READ_ID_FM:
fdc.st0 = 0x40 | (fdc.parameters[0] & 7);
fdc.st1 = 1;
@@ -784,7 +660,7 @@
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));
+ fdcsend(fdc.parameters[4]);
fdc.status = 0xD0;
fdc_irq_raise();
fdc.incommand = 0;
@@ -794,16 +670,125 @@
}
}
+static void fdc_overrun(void)
+{
+ disc_stop();
+
+ fdcsend(0x40 | (fdc.side ? 4 : 0) | fdc.drive);
+ fdcsend(0x10); /*Overrun*/
+ fdcsend(0);
+ fdcsend(fdc.track);
+ fdcsend(fdc.side);
+ fdcsend(fdc.sector);
+ fdcsend(fdc.parameters[4]);
+ fdc_end_command();
+}
+
+void fdc_data(uint8_t dat)
+{
+ if (fdc.tc || !fdc.in_read)
+ return;
+
+ if (fdc.data_ready) {
+ fdc_overrun();
+ } else {
+ fdc.dmadat = dat;
+ fdc.data_ready = 1;
+ fdc_dma_raise();
+ }
+}
+
+void fdc_finishread(void)
+{
+ fdccallback = 25;
+}
+
+void fdc_notfound(void)
+{
+ fdcsend(0x40 | (fdc.side ? 4 : 0) | fdc.drive);
+ fdcsend(5);
+ fdcsend(0);
+ fdcsend(0);
+ fdcsend(0);
+ fdcsend(0);
+ fdcsend(0);
+ fdc_end_command();
+}
+
+void fdc_datacrcerror(void)
+{
+ fdcsend(0x40 | (fdc.side ? 4 : 0) | fdc.drive);
+ fdcsend(0x20); /*Data error*/
+ fdcsend(0x20); /*Data error in data field*/
+ fdcsend(fdc.track);
+ fdcsend(fdc.side);
+ fdcsend(fdc.sector);
+ fdcsend(fdc.parameters[4]);
+ fdc_end_command();
+}
+
+void fdc_headercrcerror(void)
+{
+ fdcsend(0x40 | (fdc.side ? 4 : 0) | fdc.drive);
+ fdcsend(0x20); /*Data error*/
+ fdcsend(0);
+ fdcsend(fdc.track);
+ fdcsend(fdc.side);
+ fdcsend(fdc.sector);
+ fdcsend(fdc.parameters[4]);
+ fdc_end_command();
+}
+
+void fdc_writeprotect(void)
+{
+ fdcsend(0x40 | (fdc.side ? 4 : 0) | fdc.drive);
+ fdcsend(0x02); /*Not writeable*/
+ fdcsend(0);
+ fdcsend(0);
+ fdcsend(0);
+ fdcsend(0);
+ fdcsend(0);
+ fdc_end_command();
+}
+
+int fdc_getdata(int last)
+{
+ uint8_t temp;
+
+ if (!fdc.written && !fdc.tc)
+ return -1;
+ if (!last && !fdc.tc)
+ fdc_dma_raise();
+ fdc.written = 0;
+ temp = fdc.dmadat;
+ return temp;
+}
+
+void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size)
+{
+ fdcsend((fdc.side ? 4 : 0) | fdc.drive);
+ fdcsend(0);
+ fdcsend(0);
+ fdcsend(track);
+ fdcsend(side);
+ fdcsend(sector);
+ fdcsend(size);
+ fdc_end_command();
+}
+
+void fdc_indexpulse(void)
+{
+ iomd.irqa.status |= IOMD_IRQA_FLOPPY_INDEX;
+ updateirqs();
+}
+
uint8_t
fdc_dma_read(uint32_t addr)
{
fdc_dma_lower();
- fdccallback = 100;
- if (!fdc.commandpos) {
- fdccallback = 2000;
- }
+ fdc.data_ready = 0;
if (addr == 0x302a000) {
- fdc.commandpos = drives[fdc.st0 & 1].format->sectorsize;
- fdccallback = 2000;
+ fdc.tc = 1;
fdc.st0 = 0;
}
@@ -814,15 +799,11 @@
fdc_dma_write(uint32_t addr, uint8_t val)
{
fdc_dma_lower();
- fdccallback = 200;
- if (!fdc.commandpos) {
- fdccallback = 2000;
- }
if (addr == 0x302a000) {
- fdc.oldpos = fdc.commandpos;
- fdc.commandpos = 2048;
- fdccallback = 2000;
+ fdc.tc = 1;
fdc.st0 = 0;
}
+ fdc.written = 1;
fdc.dmadat = val;
}
diff -r d2affb36a0db -r 592604520b7e src/fdc.h
--- a/src/fdc.h Wed Oct 06 21:34:59 2021 +0100
+++ b/src/fdc.h Sat Oct 09 14:01:30 2021 +0100
@@ -34,4 +34,14 @@
extern int fdccallback;
extern int motoron;
+extern void fdc_data(uint8_t dat);
+extern void fdc_finishread(void);
+extern void fdc_notfound(void);
+extern void fdc_datacrcerror(void);
+extern void fdc_headercrcerror(void);
+extern void fdc_writeprotect(void);
+extern int fdc_getdata(int last);
+extern void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size);
+extern void fdc_indexpulse(void);
+
No comments:
Post a Comment