|
|
1.1 root 1: /*
1.1.1.4 root 2: Hatari - fdc.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
1.1 root 6:
1.1.1.7 root 7: Floppy Disk Controller(FDC) emulation. We need to simulate the movement of
8: the head of the floppy disk drive to accurately perform the FDC commands,
9: such as 'Step'. The is important for ST demo disk images. We have to go
1.1.1.6 root 10: into a lot of details - including the start up/stop of the drive motor.
11: To help with this emulation, we keep our own internal commands which are
1.1.1.7 root 12: checked each HBL to perform the transfer of data from our disk image into
1.1.1.6 root 13: the ST RAM area by simulating the DMA.
1.1 root 14: */
1.1.1.9 root 15:
16: /* 2007/11/06 [NP] Add calls to HATARI_TRACE and set FDC_DELAY_HBL=180 */
1.1.1.10 root 17: /* 2008/05/03 [NP] Add more traces to all commandes. */
18: /* FIXME : after a type II read sector with multi bit 'm' on, we */
19: /* should update FDCSectorRegister to be 'max sector for current */
20: /* track'+1 and set command status to 'Record Not Found'. */
21: /* Also, if multi bit is set and sector count is less than number */
22: /* of sectors in the track, then the FDC reads the whole track */
23: /* anyway, setting RNF at the end, but the DMA stops transferring */
24: /* data once DMA sector count $ff8604 reaches 0. */
25: /* Timings for read sector with multi bit are not good and prevent */
26: /* some programs from working (eg Super Monaco GP on Superior 65) */
27: /* because intrq bit 5 in $fffa01 seems to be cleared too late, */
28: /* the command takes more time than a real ST to complete. */
29: /* 2008/10/02 [NP] FDCTrackRegister, FDCSectorRegister and FDCDataRegister are */
30: /* stored on 8 bits in the WD 1772. When writing to $ff8604 to */
31: /* access these registers, we must keep only the lower 8 bits. */
1.1.1.11 root 32: /* (fix High Fidelity Dreams by Aura, writes $fb07 in sector reg). */
1.1.1.10 root 33: /* TODO : FDCxxxxRegister should use Uint8, not Sint16/Uint16. */
1.1.1.11 root 34: /* 2008/12/15 [NP] Although the Read Address command is not supported yet, add a */
35: /* function FDC_UpdateReadAddressCmd that does nothing, but */
36: /* completes with no DMA error and clear bit 6 of $fffa01 (fixes */
37: /* loader routine used in various Pompey Pirates compilations (23, */
38: /* 27, ...) that uses the read address command only to update the */
39: /* status register and get the state of the write protection). */
1.1.1.9 root 40:
1.1.1.10 root 41:
1.1.1.11 root 42: const char FDC_fileid[] = "Hatari fdc.c : " __DATE__ " " __TIME__;
1.1 root 43:
44: #include "main.h"
1.1.1.4 root 45: #include "configuration.h"
1.1 root 46: #include "fdc.h"
1.1.1.3 root 47: #include "hdc.h"
1.1 root 48: #include "floppy.h"
49: #include "ikbd.h"
1.1.1.6 root 50: #include "ioMem.h"
51: #include "log.h"
1.1 root 52: #include "m68000.h"
53: #include "memorySnapShot.h"
54: #include "mfp.h"
55: #include "psg.h"
56: #include "stMemory.h"
1.1.1.10 root 57: #include "video.h"
1.1 root 58:
1.1.1.3 root 59:
1.1 root 60: /*
1.1.1.7 root 61: Floppy Disk Controller
1.1 root 62:
63: Programmable Sound Generator (YM-2149)
64:
65: 0xff8800(even byte) - PSG Register Data (Read, used for parallel port)
66: - PSG Register Select (Write)
67:
68: Write to bits 0-3 to select PSG register to use(then write data to 0xfff8802)
69: Value Register
70:
71: 0000 Channel A Fine Tune
72: 0001 Channel A Coarse Tune
73: 0010 Channel B Fine Tune
74: 0011 Channel B Coarse Tune
75: 0100 Channel C Fine Tune
76: 0101 Channel C Coarse Tune
77: 0110 Noise Generator Control
78: 0111 Mixer Control - I/O enable
79: 1000 Channel A Amplitude
80: 1001 Channel B Amplitude
81: 1010 Channel C Amplitude
82: 1011 Envelope Period Fine Tune
83: 1100 Envelope Peroid Coarse Tune
84: 1101 Envelope Shape
85: 1110 I/O Port A Select (Write only)
86: 1111 I/O Port B Select
87:
88: 0xfff8802(even byte) - Bits according to 0xff8800 Register select
1.1.1.4 root 89:
1.1 root 90: 1110(Register 14) - I/O Port A
91: Bit 0 - Floppy side 0/1
92: Bit 1 - Floppy drive 0 select
93: Bit 2 - Floppy drive 1 select
94: Bit 3 - RS232 Ready to send (RTS)
95: Bit 4 - RS232 Data Terminal Ready (DTR)
96: Bit 5 - Centronics Strobe
97: Bit 6 - General Purpose Output
98: Bit 7 - Reserved
99:
1.1.1.7 root 100: ACSI DMA and Floppy Disk Controller(FDC)
1.1 root 101: 0xff8604 - information from file '1772.info.txt, by David Gahris' (register r0)
102: (write) - Disk controller
103: (read) - Disk controller status
104: Bit 0 - Busy. This bit is 1 when the 177x is busy. This bit is 0 when the 177x is free for CPU commands.
105: Bit 1 - Index / Data Request. On Type I commands, this bit is high during the index pulse that occurs once
106: per disk rotation. This bit is low at all times other than the index pulse. For Type II and III commands,
107: Bit 1 high signals the CPU to handle the data register in order to maintain a continuous flow of data.
108: Bit 1 is high when the data register is full during a read or when the data register is empty during a write.
109: "Worst case service time" for Data Request is 23.5 cycles.
110: Bit 2 - Track Zero / Lost Data. After Type I commands, this bit is 0 if the mechanism is at track zero.
111: This bit is 1 if the head is not at track zero. After Type II or III commands, this bit is 1 if the
112: CPU did not respond to Data Request (Status bit 1) in time for the 177x to maintain a continuous data flow.
113: This bit is 0 if the CPU responded promptly to Data Request.
114: Bit 3 - CRC Error. This bit is high if a sector CRC on disk does not match the CRC which the 177x
115: computed from the data. The CRC polynomial is x^16+x^12+x^5+1. If the stored CRC matches the newly
116: calculated CRC, the CRC Error bit is low. If this bit and the Record Not Found bit are set, the error
117: was in an ID field. If this bit is set but Record Not Found is clear, the error was in a data field.
118: Bit 4 - Record Not Found. This bit is set if the 177x cannot find the track, sector, or side which
119: the CPU requested. Otherwise, this bit is clear.
120: Bit 5 - Spin-up / Record Type. For Type I commands, this bit is low during the 6-revolution motor
121: spin-up time. This bit is high after spin-up. For Type II and Type III commands, Bit 5 low
122: indicates a normal data mark. Bit 5 high indicates a deleted data mark.
123: Bit 6 - Write Protect. This bit is not used during reads. During writes, this bit is high when the disk is write protected.
124: Bit 7 - Motor On. This bit is high when the drive motor is on, and low when the motor is off.
125:
126: 0xff8606 - DMA Status(read), DMA Mode Control(write) - NOTE bits 0,9-15 are not used
127: Bit 1 - FDC Pin A0 (See below)
128: Bit 2 - FDC Pin A1
129: Bit 3 - FDC/HDC Register Select
130: Bit 4 - FDC/Sector count select
131: Bit 5 - Reserved
132: Bit 6 - Enable/Disable DMA
133: Bit 7 - HDC/FDC
134: Bit 8 - Read/Write
135:
136: A1 A0 Read Write(bit 8==1)
137: 0 0 Status Command
138: 0 1 Track Register Track Register
139: 1 0 Sector Register Sector Register
140: 1 1 Data Register Data Register
141:
142:
1.1.1.6 root 143: This handles any read/writes to the FDC and PSG. FDC commands are then sent
1.1.1.7 root 144: through to read/write disk sector code. We have full documents on 1772 FDC,
1.1.1.6 root 145: but they use r0,r1,r2,r3 etc.. which are not seen at first glance as Atari
146: access them via the A0,A1 bits. Once this is understood it is all relativly
1.1.1.7 root 147: easy as a lot of information can be ignored as we are using disk images and
148: not actual disks. We do NOT support the reading of the PC's A: drive - newer
149: PC's cannot read an ST single sided disk, ST disks are very old and so are
1.1.1.6 root 150: dirty which gets onto the PC drive heads and ruins them and also support for
1.1.1.7 root 151: disk sector access under the various modern operating systems is not so easy
1.1.1.6 root 152: (if possible at all).
153:
154: According to the documentation INTRQ is generated at the completion of each
155: command (causes an interrupt in the MFP). INTRQ is reset by reading the status
156: register OR by loading a new command. So, does this mean the GPIP? Or does it
157: actually CANCEL the interrupt? Can this be done?
1.1 root 158: */
159:
160:
1.1.1.7 root 161: Sint16 FDCSectorCountRegister;
1.1 root 162:
1.1.1.7 root 163: Uint16 DiskControllerWord_ff8604wr; /* 0xff8604 (write) */
164: static Uint16 DiskControllerStatus_ff8604rd; /* 0xff8604 (read) */
1.1.1.5 root 165:
1.1.1.6 root 166: Uint16 DMAModeControl_ff8606wr; /* 0xff8606 (write) */
167: static Uint16 DMAStatus_ff8606rd; /* 0xff8606 (read) */
1.1.1.5 root 168:
1.1.1.7 root 169: static Uint16 FDCCommandRegister;
170: static Sint16 FDCTrackRegister, FDCSectorRegister, FDCDataRegister;
1.1.1.5 root 171: static int FDCEmulationCommand; /* FDC emulation command currently being exceuted */
172: static int FDCEmulationRunning; /* Running command under above */
173: static int FDCStepDirection; /* +Track on 'Step' command */
1.1.1.10 root 174: static bool bDMAWaiting; /* Is DMA waiting to copy? */
1.1.1.5 root 175: static int bMotorOn; /* Is motor on? */
176: static int MotorSlowingCount; /* Counter used to slow motor before stopping */
177:
178: static short int nReadWriteTrack; /* Parameters used in sector read/writes */
179: static short int nReadWriteSector;
180: static short int nReadWriteSide;
181: static short int nReadWriteDev;
182: static unsigned short int nReadWriteSectorsPerTrack;
183: static short int nReadWriteSectors;
184:
1.1.1.7 root 185: static Uint8 DMASectorWorkSpace[NUMBYTESPERSECTOR]; /* Workspace used to copy to/from for floppy DMA */
1.1 root 186:
1.1.1.2 root 187:
188: /*-----------------------------------------------------------------------*/
1.1.1.9 root 189: /**
190: * Reset variables used in FDC
191: */
1.1 root 192: void FDC_Reset(void)
193: {
1.1.1.6 root 194: /* Clear out FDC registers */
1.1.1.7 root 195: DiskControllerStatus_ff8604rd = 0;
196: DiskControllerWord_ff8604wr = 0;
1.1.1.6 root 197: DMAStatus_ff8606rd = 0x01;
198: DMAModeControl_ff8606wr = 0;
199: FDC_ResetDMAStatus();
200: FDCCommandRegister = 0;
201: FDCTrackRegister = 0;
202: FDCSectorRegister = 1;
203: FDCDataRegister = 0;
204: FDCSectorCountRegister = 0;
205:
206: FDCEmulationCommand = FDCEMU_CMD_NULL; /* FDC emulation command currently being exceuted */
207: FDCEmulationRunning = FDCEMU_RUN_NULL; /* Running command under above */
208:
209: FDCStepDirection = 1; /* +Track on 'Step' command */
1.1.1.12! root 210: bDMAWaiting = false; /* No DMA waiting */
! 211: bMotorOn = false; /* Motor off */
1.1.1.6 root 212: MotorSlowingCount = 0; /* Counter for motor slowing down before stopping */
1.1 root 213: }
214:
1.1.1.2 root 215:
216: /*-----------------------------------------------------------------------*/
1.1.1.9 root 217: /**
218: * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
219: */
1.1.1.10 root 220: void FDC_MemorySnapShot_Capture(bool bSave)
1.1 root 221: {
1.1.1.6 root 222: /* Save/Restore details */
1.1.1.7 root 223: MemorySnapShot_Store(&DiskControllerStatus_ff8604rd, sizeof(DiskControllerStatus_ff8604rd));
224: MemorySnapShot_Store(&DiskControllerWord_ff8604wr, sizeof(DiskControllerWord_ff8604wr));
1.1.1.6 root 225: MemorySnapShot_Store(&DMAStatus_ff8606rd, sizeof(DMAStatus_ff8606rd));
226: MemorySnapShot_Store(&DMAModeControl_ff8606wr, sizeof(DMAModeControl_ff8606wr));
227: MemorySnapShot_Store(&FDCCommandRegister, sizeof(FDCCommandRegister));
228: MemorySnapShot_Store(&FDCTrackRegister, sizeof(FDCTrackRegister));
229: MemorySnapShot_Store(&FDCSectorRegister, sizeof(FDCSectorRegister));
230: MemorySnapShot_Store(&FDCDataRegister, sizeof(FDCDataRegister));
231: MemorySnapShot_Store(&FDCSectorCountRegister, sizeof(FDCSectorCountRegister));
232: MemorySnapShot_Store(&FDCEmulationCommand, sizeof(FDCEmulationCommand));
233: MemorySnapShot_Store(&FDCEmulationRunning, sizeof(FDCEmulationRunning));
234: MemorySnapShot_Store(&FDCStepDirection, sizeof(FDCStepDirection));
235: MemorySnapShot_Store(&bDMAWaiting, sizeof(bDMAWaiting));
236: MemorySnapShot_Store(&bMotorOn, sizeof(bMotorOn));
237: MemorySnapShot_Store(&MotorSlowingCount, sizeof(MotorSlowingCount));
238: MemorySnapShot_Store(&nReadWriteTrack, sizeof(nReadWriteTrack));
239: MemorySnapShot_Store(&nReadWriteSector, sizeof(nReadWriteSector));
240: MemorySnapShot_Store(&nReadWriteSide, sizeof(nReadWriteSide));
241: MemorySnapShot_Store(&nReadWriteDev, sizeof(nReadWriteDev));
242: MemorySnapShot_Store(&nReadWriteSectorsPerTrack, sizeof(nReadWriteSectorsPerTrack));
243: MemorySnapShot_Store(&nReadWriteSectors, sizeof(nReadWriteSectors));
244: MemorySnapShot_Store(DMASectorWorkSpace, sizeof(DMASectorWorkSpace));
1.1 root 245: }
246:
1.1.1.2 root 247:
248: /*-----------------------------------------------------------------------*/
1.1.1.9 root 249: /**
250: * Turn floppy motor on
251: */
1.1.1.5 root 252: static void FDC_TurnMotorOn(void)
1.1 root 253: {
1.1.1.12! root 254: bMotorOn = true; /* Turn motor on */
1.1.1.6 root 255: MotorSlowingCount = 0;
1.1 root 256: }
257:
1.1.1.2 root 258:
259: /*-----------------------------------------------------------------------*/
1.1.1.9 root 260: /**
261: * Turn floppy motor off (this sets a count as it takes a set amount of time for the motor to slow to a halt)
262: */
1.1.1.5 root 263: static void FDC_TurnMotorOff(void)
1.1 root 264: {
1.1.1.6 root 265: MotorSlowingCount = 160; /* Set timer so takes 'x' HBLs before turn off... */
1.1 root 266: }
267:
1.1.1.2 root 268:
269: /*-----------------------------------------------------------------------*/
1.1.1.9 root 270: /**
271: * Update floppy drive motor each HBL, to simulate slowing down and stopping for drive; needed for New Zealand Story(PP_001)
272: */
1.1.1.5 root 273: static void FDC_UpdateMotor(void)
1.1 root 274: {
1.1.1.6 root 275: /* Is drive slowing down? Decrement counter */
276: if (MotorSlowingCount>0)
277: {
278: MotorSlowingCount--;
279:
280: if (MotorSlowingCount==0)
1.1.1.12! root 281: bMotorOn = false; /* Motor finally stopped */
1.1.1.6 root 282: }
1.1 root 283: }
284:
1.1.1.2 root 285:
286: /*-----------------------------------------------------------------------*/
1.1.1.9 root 287: /**
288: * Reset DMA Status (RD 0xff8606)
289: *
290: * This is done by 'toggling' bit 8 of the DMA Mode Control register
291: */
1.1 root 292: void FDC_ResetDMAStatus(void)
293: {
1.1.1.6 root 294: DMAStatus_ff8606rd = 0; /* Clear out */
1.1 root 295:
1.1.1.6 root 296: FDCSectorCountRegister = 0;
1.1.1.12! root 297: FDC_SetDMAStatus(false); /* Set no error */
1.1.1.3 root 298:
1.1.1.10 root 299: /* Reset HDC command status */
1.1.1.6 root 300: HDCSectorCount = 0;
1.1.1.10 root 301: /*HDCCommand.byteCount = 0;*/ /* Not done on real ST? */
1.1.1.8 root 302: HDCCommand.returnCode = 0;
1.1 root 303: }
304:
1.1.1.2 root 305:
306: /*-----------------------------------------------------------------------*/
1.1.1.9 root 307: /**
308: * Set DMA Status (RD 0xff8606)
1.1.1.10 root 309: *
1.1.1.9 root 310: * NOTE FDC Doc's are incorrect - Bit 0 is '0' on error (See TOS floprd, Ninja III etc...)
311: * Look like Atari(yet again) connected the hardware up differently to the spec'
312: *
313: * Bit 0 - _Error Status (0=Error)
314: * Bit 1 - _Sector Count Zero Status (0=Sector Count Zero)
315: * Bit 2 - _Data Request Inactive Status
316: */
1.1.1.10 root 317: void FDC_SetDMAStatus(bool bError)
1.1 root 318: {
1.1.1.6 root 319: DMAStatus_ff8606rd &= 0x1; /* Clear(except for error) */
1.1 root 320:
1.1.1.6 root 321: /* Set error condition - NOTE this is incorrect in the FDC Doc's! */
322: if (!bError)
323: DMAStatus_ff8606rd |= 0x1;
324:
325: /* Set zero sector count */
326:
327: if (DMAModeControl_ff8606wr&0x08) /* Get which sector count? */
1.1.1.8 root 328: DMAStatus_ff8606rd |= (HDCSectorCount)?0x2:0; /* HDC */
1.1.1.6 root 329: else
330: DMAStatus_ff8606rd |= (FDCSectorCountRegister)?0x2:0; /* FDC */
331: /* Perhaps the DRQ should be set here */
1.1 root 332: }
333:
1.1.1.2 root 334:
335: /*-----------------------------------------------------------------------*/
1.1.1.9 root 336: /**
337: * Read DMA Status (RD 0xff8606)
338: */
1.1.1.6 root 339: void FDC_DmaStatus_ReadWord(void)
1.1 root 340: {
1.1.1.6 root 341: if (nIoMemAccessSize == SIZE_BYTE)
342: {
343: /* This register does not like to be accessed in byte mode on a normal ST */
1.1.1.8 root 344: M68000_BusError(IoAccessBaseAddress, BUS_ERROR_READ);
1.1.1.6 root 345: return;
346: }
347:
348: IoMem_WriteWord(0xff8606, DMAStatus_ff8606rd);
1.1 root 349: }
350:
1.1.1.2 root 351:
352: /*-----------------------------------------------------------------------*/
1.1.1.9 root 353: /**
1.1.1.10 root 354: *
1.1.1.9 root 355: */
1.1.1.7 root 356: static void FDC_UpdateDiskDrive(void)
1.1 root 357: {
1.1.1.6 root 358: /* Set details for current selecte drive */
359: nReadWriteDev = FDC_FindFloppyDrive();
1.1.1.2 root 360:
1.1.1.7 root 361: if (EmulationDrives[nReadWriteDev].bDiskInserted)
362: Floppy_FindDiskDetails(EmulationDrives[nReadWriteDev].pBuffer,EmulationDrives[nReadWriteDev].nImageBytes,&nReadWriteSectorsPerTrack,NULL);
1.1 root 363: }
364:
1.1.1.2 root 365:
366: /*-----------------------------------------------------------------------*/
1.1.1.9 root 367: /**
368: * Set disk controller status (RD 0xff8604)
369: */
1.1.1.7 root 370: static void FDC_SetDiskControllerStatus(void)
1.1 root 371: {
1.1.1.7 root 372: /* Update disk */
373: FDC_UpdateDiskDrive();
1.1 root 374:
1.1.1.6 root 375: /* Clear out to default */
1.1.1.7 root 376: DiskControllerStatus_ff8604rd = 0;
1.1 root 377:
1.1.1.6 root 378: /* ONLY do this if we are running a Type I command */
379: if ((FDCCommandRegister&0x80)==0)
380: {
381: /* Type I - Restore, Seek, Step, Step-In, Step-Out */
382: if (FDCTrackRegister==0)
1.1.1.7 root 383: DiskControllerStatus_ff8604rd |= 0x4; /* Bit 2 - Track Zero, '0' if head is NOT at zero */
1.1.1.6 root 384: }
385:
1.1.1.7 root 386: /* If no disk inserted, tag as error */
387: if (!EmulationDrives[nReadWriteDev].bDiskInserted)
388: DiskControllerStatus_ff8604rd |= 0x10; /* RNF - Record not found, ie no disk in drive */
1.1 root 389: }
390:
1.1.1.2 root 391:
392: /*-----------------------------------------------------------------------*/
1.1.1.9 root 393: /**
394: * Return device for FDC, check PORTA bits 1,2(0=on,1=off)
395: */
1.1 root 396: int FDC_FindFloppyDrive(void)
397: {
1.1.1.6 root 398: /* Check Drive A first */
399: if ((PSGRegisters[PSG_REG_IO_PORTA]&0x2)==0)
400: return 0; /* Device 0 (A:) */
401: /* If off, check Drive B */
402: if ((PSGRegisters[PSG_REG_IO_PORTA]&0x4)==0)
403: return 1; /* Device 1 (B:) */
1.1 root 404:
1.1.1.6 root 405: /* None appear to be selected so default to Drive A */
406: return 0; /* Device 0 (A:) */
1.1 root 407: }
408:
1.1.1.2 root 409:
410: /*-----------------------------------------------------------------------*/
1.1.1.9 root 411: /**
412: * Acknowledge FDC interrupt
413: */
1.1 root 414: void FDC_AcknowledgeInterrupt(void)
415: {
1.1.1.6 root 416: /* Acknowledge in MFP circuit, pass bit, enable, pending */
417: MFP_InputOnChannel(MFP_FDCHDC_BIT,MFP_IERB,&MFP_IPRB);
418: MFP_GPIP &= ~0x20;
1.1 root 419: }
420:
1.1.1.2 root 421:
422: /*-----------------------------------------------------------------------*/
1.1.1.9 root 423: /**
424: * Copy parameters for disk sector/s read/write
425: */
1.1.1.5 root 426: static void FDC_SetReadWriteParameters(int nSectors)
1.1 root 427: {
1.1.1.6 root 428: /* Copy read/write details so we can modify them */
429: nReadWriteTrack = FDCTrackRegister;
430: nReadWriteSector = FDCSectorRegister;
431: nReadWriteSide = (~PSGRegisters[PSG_REG_IO_PORTA]) & 0x01;
432: nReadWriteSectors = nSectors;
1.1.1.7 root 433: /* Update disk */
434: FDC_UpdateDiskDrive();
1.1 root 435: }
436:
1.1.1.2 root 437:
438: /*-----------------------------------------------------------------------*/
1.1.1.9 root 439: /**
440: * ST program (or TOS) has read the MFP GPIP register to check if the FDC
441: * is already done. Then we can skip the usual FDC waiting period!
442: */
1.1.1.8 root 443: void FDC_GpipRead(void)
444: {
445: static int nLastGpipBit;
446:
447: if ((MFP_GPIP & 0x20) == nLastGpipBit)
448: {
1.1.1.12! root 449: if (!ConfigureParams.DiskImage.bSlowFloppy)
1.1.1.9 root 450: {
451: /* Restart FDC update interrupt to occur right after a few cycles */
452: Int_RemovePendingInterrupt(INTERRUPT_FDC);
1.1.1.10 root 453: Int_AddRelativeInterrupt(4, INT_CPU_CYCLE, INTERRUPT_FDC);
1.1.1.9 root 454: }
1.1.1.8 root 455: }
456: else
457: {
458: nLastGpipBit = MFP_GPIP & 0x20;
459: }
460: }
461:
462:
463: /*-----------------------------------------------------------------------*/
1.1.1.9 root 464: /**
465: * Update floppy drive after a while.
466: * Some games/demos (e.g. Fantasia by Dune, Alien World, ...) don't work
467: * if the FDC is too fast. So we use the update "interrupt" for delayed
468: * execution of the commands.
469: * FIXME: We urgently need better timings here!
470: */
471: void FDC_InterruptHandler_Update(void)
1.1 root 472: {
1.1.1.9 root 473: Int_AcknowledgeInterrupt();
1.1.1.6 root 474:
475: /* Do we have a DMA ready to copy? */
476: if (bDMAWaiting)
477: {
478: /* Yes, copy it */
479: FDC_DMADataFromFloppy();
480: /* Signal done */
1.1.1.12! root 481: bDMAWaiting = false;
1.1.1.6 root 482: }
483:
484: /* Update drive motor */
485: FDC_UpdateMotor();
486:
487: /* Is FDC active? */
488: if (FDCEmulationCommand!=FDCEMU_CMD_NULL)
489: {
490: /* Which command are we running? */
491: switch(FDCEmulationCommand)
492: {
493: case FDCEMU_CMD_RESTORE:
494: FDC_UpdateRestoreCmd();
495: break;
496: case FDCEMU_CMD_SEEK:
497: FDC_UpdateSeekCmd();
498: break;
499: case FDCEMU_CMD_STEP:
500: FDC_UpdateStepCmd();
501: break;
502: case FDCEMU_CMD_STEPIN:
503: FDC_UpdateStepInCmd();
504: break;
505: case FDCEMU_CMD_STEPOUT:
506: FDC_UpdateStepOutCmd();
507: break;
508:
509: case FDCEMU_CMD_READSECTORS:
510: case FDCEMU_CMD_READMULTIPLESECTORS:
511: FDC_UpdateReadSectorsCmd();
512: break;
513: case FDCEMU_CMD_WRITESECTORS:
514: case FDCEMU_CMD_WRITEMULTIPLESECTORS:
515: FDC_UpdateWriteSectorsCmd();
516: break;
1.1.1.11 root 517:
518: case FDCEMU_CMD_READADDRESS:
519: FDC_UpdateReadAddressCmd();
520: break;
1.1.1.6 root 521: }
522:
1.1.1.7 root 523: /* Set disk controller status (RD 0xff8604) */
524: FDC_SetDiskControllerStatus();
1.1.1.6 root 525: }
1.1.1.9 root 526:
527: if (FDCEmulationCommand != FDCEMU_CMD_NULL || bMotorOn)
528: {
529: Int_AddAbsoluteInterrupt(FDC_DELAY_CYCLES, INT_CPU_CYCLE, INTERRUPT_FDC);
530: }
1.1 root 531: }
532:
1.1.1.2 root 533:
534: /*-----------------------------------------------------------------------*/
1.1.1.9 root 535: /**
536: * Run 'RESTORE' command
537: */
1.1 root 538: void FDC_UpdateRestoreCmd(void)
539: {
1.1.1.6 root 540: /* Which command is running? */
541: switch (FDCEmulationRunning)
542: {
543: case FDCEMU_RUN_RESTORE_SEEKTOTRACKZERO:
544: /* Are we at track zero? */
545: if (FDCTrackRegister>0)
546: FDCTrackRegister--; /* Move towards track zero */
547: else
548: {
549: FDCTrackRegister = 0; /* We're there */
550: FDCEmulationRunning = FDCEMU_RUN_RESTORE_COMPLETE;
551: }
552: break;
553: case FDCEMU_RUN_RESTORE_COMPLETE:
554: /* Acknowledge interrupt, move along there's nothing more to see */
555: FDC_AcknowledgeInterrupt();
556: /* Set error */
1.1.1.12! root 557: FDC_SetDMAStatus(false); /* No DMA error */
1.1.1.6 root 558: /* Done */
559: FDCEmulationCommand = FDCEMU_CMD_NULL;
560: /* Turn motor off */
561: FDC_TurnMotorOff();
562: break;
563: }
1.1 root 564: }
565:
1.1.1.2 root 566:
567: /*-----------------------------------------------------------------------*/
1.1.1.9 root 568: /**
569: * Run 'SEEK' command
570: */
1.1 root 571: void FDC_UpdateSeekCmd(void)
572: {
1.1.1.6 root 573: /* Which command is running? */
574: switch (FDCEmulationRunning)
575: {
576: case FDCEMU_RUN_SEEK_TOTRACK:
577: /* Are we at the selected track? */
578: if (FDCTrackRegister==FDCDataRegister)
579: FDCEmulationRunning = FDCEMU_RUN_SEEK_COMPLETE;
580: else
581: {
582: /* No, seek towards track */
583: if (FDCDataRegister<FDCTrackRegister)
584: FDCTrackRegister--;
585: else
586: FDCTrackRegister++;
587: }
588: break;
589: case FDCEMU_RUN_SEEK_COMPLETE:
590: /* Acknowledge interrupt, move along there's nothing more to see */
591: FDC_AcknowledgeInterrupt();
592: /* Set error */
1.1.1.12! root 593: FDC_SetDMAStatus(false); /* No DMA error */
1.1.1.6 root 594: /* Done */
595: FDCEmulationCommand = FDCEMU_CMD_NULL;
596: /* Turn motor off */
597: FDC_TurnMotorOff();
598: break;
599: }
1.1 root 600: }
601:
1.1.1.2 root 602:
603: /*-----------------------------------------------------------------------*/
1.1.1.9 root 604: /**
605: * Run 'STEP' command
606: */
1.1 root 607: void FDC_UpdateStepCmd(void)
608: {
1.1.1.6 root 609: /* Which command is running? */
610: switch (FDCEmulationRunning)
611: {
612: case FDCEMU_RUN_STEP_ONCE:
613: /* Move head by one track in same direction as last step */
614: FDCTrackRegister += FDCStepDirection;
615: if (FDCTrackRegister<0) /* Limit to stop */
616: FDCTrackRegister = 0;
617:
618: FDCEmulationRunning = FDCEMU_RUN_STEP_COMPLETE;
619: break;
620: case FDCEMU_RUN_STEP_COMPLETE:
621: /* Acknowledge interrupt, move along there's nothing more to see */
622: FDC_AcknowledgeInterrupt();
623: /* Set error */
1.1.1.12! root 624: FDC_SetDMAStatus(false); /* No DMA error */
1.1.1.6 root 625: /* Done */
626: FDCEmulationCommand = FDCEMU_CMD_NULL;
627: /* Turn motor off */
628: FDC_TurnMotorOff();
629: break;
630: }
1.1 root 631: }
632:
1.1.1.2 root 633:
634: /*-----------------------------------------------------------------------*/
1.1.1.9 root 635: /**
636: * Run 'STEP IN' command
637: */
1.1 root 638: void FDC_UpdateStepInCmd(void)
639: {
1.1.1.6 root 640: /* Which command is running? */
641: switch (FDCEmulationRunning)
642: {
643: case FDCEMU_RUN_STEPIN_ONCE:
644: FDCTrackRegister++;
645:
646: FDCEmulationRunning = FDCEMU_RUN_STEPIN_COMPLETE;
647: break;
648: case FDCEMU_RUN_STEPIN_COMPLETE:
649: /* Acknowledge interrupt, move along there's nothing more to see */
650: FDC_AcknowledgeInterrupt();
651: /* Set error */
1.1.1.12! root 652: FDC_SetDMAStatus(false); /* No DMA error */
1.1.1.6 root 653: /* Done */
654: FDCEmulationCommand = FDCEMU_CMD_NULL;
655: /* Turn motor off */
656: FDC_TurnMotorOff();
657: break;
658: }
1.1 root 659: }
660:
1.1.1.2 root 661:
662: /*-----------------------------------------------------------------------*/
1.1.1.9 root 663: /**
664: * Run 'STEP OUT' command
665: */
1.1 root 666: void FDC_UpdateStepOutCmd(void)
667: {
1.1.1.6 root 668: /* Which command is running? */
669: switch (FDCEmulationRunning)
670: {
671: case FDCEMU_RUN_STEPOUT_ONCE:
672: FDCTrackRegister--;
673: if (FDCTrackRegister < 0) /* Limit to stop */
674: FDCTrackRegister = 0;
675:
676: FDCEmulationRunning = FDCEMU_RUN_STEPOUT_COMPLETE;
677: break;
678: case FDCEMU_RUN_STEPOUT_COMPLETE:
679: /* Acknowledge interrupt, move along there's nothing more to see */
680: FDC_AcknowledgeInterrupt();
681: /* Set error */
1.1.1.12! root 682: FDC_SetDMAStatus(false); /* No DMA error */
1.1.1.6 root 683: /* Done */
684: FDCEmulationCommand = FDCEMU_CMD_NULL;
685: /* Turn motor off */
686: FDC_TurnMotorOff();
687: break;
688: }
1.1 root 689: }
690:
1.1.1.2 root 691:
692: /*-----------------------------------------------------------------------*/
1.1.1.9 root 693: /**
694: * Run 'READ SECTOR/S' command
695: */
1.1 root 696: void FDC_UpdateReadSectorsCmd(void)
697: {
1.1.1.6 root 698: /* Which command is running? */
699: switch (FDCEmulationRunning)
700: {
701: case FDCEMU_RUN_READSECTORS_READDATA:
702: /* Read in a sector */
703: if (FDC_ReadSectorFromFloppy()) /* Read a single sector through DMA */
704: {
705: FDCSectorCountRegister--; /* Decrement FDCSectorCount */
706: if (FDCSectorCountRegister <= 0)
707: FDCSectorCountRegister = 0;
708:
709: /* Have we finished? */
710: nReadWriteSectors--;
711: if (nReadWriteSectors<=0)
712: FDCEmulationRunning = FDCEMU_RUN_READSECTORS_COMPLETE;
713:
1.1.1.12! root 714: bDMAWaiting = true;
1.1.1.6 root 715: }
716: else
717: {
718: /* Acknowledge interrupt, move along there's nothing more to see */
719: FDC_AcknowledgeInterrupt();
720: /* Set error */
1.1.1.12! root 721: FDC_SetDMAStatus(true); /* DMA error */
1.1.1.6 root 722: /* Done */
723: FDCEmulationCommand = FDCEMU_CMD_NULL;
724: /* Turn motor off */
725: FDC_TurnMotorOff();
726: }
727: break;
728: case FDCEMU_RUN_READSECTORS_COMPLETE:
729: /* Acknowledge interrupt, move along there's nothing more to see */
730: FDC_AcknowledgeInterrupt();
731: /* Set error */
1.1.1.12! root 732: FDC_SetDMAStatus(false); /* No DMA error */
1.1.1.6 root 733: /* Done */
734: FDCEmulationCommand = FDCEMU_CMD_NULL;
735: /* Turn motor off */
736: FDC_TurnMotorOff();
737: break;
738: }
1.1 root 739: }
740:
1.1.1.2 root 741:
742: /*-----------------------------------------------------------------------*/
1.1.1.9 root 743: /**
744: * Run 'WRITE SECTOR/S' command
745: */
1.1 root 746: void FDC_UpdateWriteSectorsCmd(void)
747: {
1.1.1.6 root 748: /* Which command is running? */
749: switch (FDCEmulationRunning)
750: {
751: case FDCEMU_RUN_WRITESECTORS_WRITEDATA:
752: /* Write out a sector */
753: if (FDC_WriteSectorFromFloppy()) /* Write a single sector through DMA */
754: {
755: /* Decrement FDCsector count */
756: FDCSectorCountRegister--; /* Decrement FDCSectorCount */
757: if (FDCSectorCountRegister<=0)
758: FDCSectorCountRegister = 0;
759:
760: /* Have we finished? */
761: nReadWriteSectors--;
762: if (nReadWriteSectors<=0)
763: FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_COMPLETE;
764:
765: /* Update DMA pointer */
766: FDC_WriteDMAAddress(FDC_ReadDMAAddress()+NUMBYTESPERSECTOR);
767: }
768: else
769: {
770: /* Acknowledge interrupt, move along there's nothing more to see */
771: FDC_AcknowledgeInterrupt();
772: /* Set error */
1.1.1.12! root 773: FDC_SetDMAStatus(true); /* DMA error */
1.1.1.6 root 774: /* Done */
775: FDCEmulationCommand = FDCEMU_CMD_NULL;
776: /* Turn motor off */
777: FDC_TurnMotorOff();
778: }
779: break;
780: case FDCEMU_RUN_WRITESECTORS_COMPLETE:
781: /* Acknowledge interrupt, move along there's nothing more to see */
782: FDC_AcknowledgeInterrupt();
783: /* Set error */
1.1.1.12! root 784: FDC_SetDMAStatus(false); /* No DMA error */
1.1.1.6 root 785: /* Done */
786: FDCEmulationCommand = FDCEMU_CMD_NULL;
787: /* Turn motor off */
788: FDC_TurnMotorOff();
789: break;
790: }
1.1 root 791: }
792:
1.1.1.2 root 793:
794: /*-----------------------------------------------------------------------*/
1.1.1.9 root 795: /**
1.1.1.11 root 796: * Run 'READ ADDRESS' command
797: */
798: void FDC_UpdateReadAddressCmd(void)
799: {
800: /* Which command is running? */
801: switch (FDCEmulationRunning)
802: {
803: case FDCEMU_RUN_READADDRESS:
804: /* not implemented, just return with no error */
805: FDCEmulationRunning = FDCEMU_RUN_READADDRESS_COMPLETE;
806: break;
807: case FDCEMU_RUN_READADDRESS_COMPLETE:
808: /* Acknowledge interrupt, move along there's nothing more to see */
809: FDC_AcknowledgeInterrupt();
810: /* Set error */
1.1.1.12! root 811: FDC_SetDMAStatus(false); /* No DMA error */
1.1.1.11 root 812: /* Done */
813: FDCEmulationCommand = FDCEMU_CMD_NULL;
814: /* Turn motor off */
815: FDC_TurnMotorOff();
816: break;
817: }
818: }
819:
820:
821: /*-----------------------------------------------------------------------*/
822: /**
1.1.1.9 root 823: * Type I Commands
824: *
825: * Restore, Seek, Step, Step-In and Step-Out
826: */
1.1 root 827:
1.1.1.2 root 828:
829: /*-----------------------------------------------------------------------*/
1.1.1.5 root 830: static void FDC_TypeI_Restore(void)
1.1 root 831: {
1.1.1.12! root 832: int FrameCycles, HblCounterVideo, LineCycles;
! 833:
! 834: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 835:
! 836: LOG_TRACE(TRACE_FDC, "fdc type I restore VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 837: nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 838:
1.1.1.6 root 839: /* Set emulation to seek to track zero */
840: FDCEmulationCommand = FDCEMU_CMD_RESTORE;
841: FDCEmulationRunning = FDCEMU_RUN_RESTORE_SEEKTOTRACKZERO;
1.1 root 842:
1.1.1.7 root 843: FDC_SetDiskControllerStatus();
1.1 root 844: }
845:
1.1.1.2 root 846:
847: /*-----------------------------------------------------------------------*/
1.1.1.5 root 848: static void FDC_TypeI_Seek(void)
1.1 root 849: {
1.1.1.12! root 850: int FrameCycles, HblCounterVideo, LineCycles;
! 851:
! 852: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 853:
! 854: LOG_TRACE(TRACE_FDC, "fdc type I seek track=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 855: FDCDataRegister, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 856:
1.1.1.6 root 857: /* Set emulation to seek to chosen track */
858: FDCEmulationCommand = FDCEMU_CMD_SEEK;
859: FDCEmulationRunning = FDCEMU_RUN_SEEK_TOTRACK;
1.1 root 860:
1.1.1.7 root 861: FDC_SetDiskControllerStatus();
1.1 root 862: }
863:
1.1.1.2 root 864:
865: /*-----------------------------------------------------------------------*/
1.1.1.5 root 866: static void FDC_TypeI_Step(void)
1.1 root 867: {
1.1.1.12! root 868: int FrameCycles, HblCounterVideo, LineCycles;
! 869:
! 870: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 871:
! 872: LOG_TRACE(TRACE_FDC, "fdc type I step %d VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 873: FDCStepDirection, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 874:
1.1.1.6 root 875: /* Set emulation to step(same direction as last seek executed, eg 'FDCStepDirection') */
876: FDCEmulationCommand = FDCEMU_CMD_STEP;
877: FDCEmulationRunning = FDCEMU_RUN_STEP_ONCE;
1.1 root 878:
1.1.1.7 root 879: FDC_SetDiskControllerStatus();
1.1 root 880: }
881:
1.1.1.2 root 882:
883: /*-----------------------------------------------------------------------*/
1.1.1.5 root 884: static void FDC_TypeI_StepIn(void)
1.1 root 885: {
1.1.1.12! root 886: int FrameCycles, HblCounterVideo, LineCycles;
! 887:
! 888: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 889:
! 890: LOG_TRACE(TRACE_FDC, "fdc type I step in VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 891: nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 892:
1.1.1.6 root 893: /* Set emulation to step in(Set 'FDCStepDirection') */
894: FDCEmulationCommand = FDCEMU_CMD_STEPIN;
895: FDCEmulationRunning = FDCEMU_RUN_STEPIN_ONCE;
896: FDCStepDirection = 1; /* Increment track*/
1.1 root 897:
1.1.1.7 root 898: FDC_SetDiskControllerStatus();
1.1 root 899: }
900:
1.1.1.2 root 901:
902: /*-----------------------------------------------------------------------*/
1.1.1.5 root 903: static void FDC_TypeI_StepOut(void)
1.1 root 904: {
1.1.1.12! root 905: int FrameCycles, HblCounterVideo, LineCycles;
! 906:
! 907: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 908:
! 909: LOG_TRACE(TRACE_FDC, "fdc type I step out VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 910: nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 911:
1.1.1.6 root 912: /* Set emulation to step out(Set 'FDCStepDirection') */
913: FDCEmulationCommand = FDCEMU_CMD_STEPOUT;
914: FDCEmulationRunning = FDCEMU_RUN_STEPOUT_ONCE;
915: FDCStepDirection = -1; /* Decrement track */
1.1 root 916:
1.1.1.7 root 917: FDC_SetDiskControllerStatus();
1.1 root 918: }
919:
1.1.1.2 root 920:
921: /*-----------------------------------------------------------------------*/
1.1.1.9 root 922: /**
923: * Type II Commands
924: *
925: * Read Sector, Read Multiple Sectors, Write Sector, Write Multiple Sectors
926: */
1.1 root 927:
1.1.1.2 root 928:
929: /*-----------------------------------------------------------------------*/
1.1.1.5 root 930: static void FDC_TypeII_ReadSector(void)
1.1 root 931: {
1.1.1.12! root 932: int FrameCycles, HblCounterVideo, LineCycles;
! 933:
! 934: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 935:
! 936: LOG_TRACE(TRACE_FDC, "fdc type II read sector %d VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 937: FDCSectorRegister, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 938:
1.1.1.6 root 939: /* Set emulation to read a single sector */
940: FDCEmulationCommand = FDCEMU_CMD_READSECTORS;
941: FDCEmulationRunning = FDCEMU_RUN_READSECTORS_READDATA;
942: /* Set reading parameters */
943: FDC_SetReadWriteParameters(1); /* Read in a single sector */
1.1 root 944:
1.1.1.7 root 945: FDC_SetDiskControllerStatus();
1.1 root 946: }
947:
1.1.1.2 root 948:
949: /*-----------------------------------------------------------------------*/
1.1.1.5 root 950: static void FDC_TypeII_ReadMultipleSectors(void)
1.1 root 951: {
1.1.1.12! root 952: int FrameCycles, HblCounterVideo, LineCycles;
! 953:
! 954: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 955:
! 956: LOG_TRACE(TRACE_FDC, "fdc type II read multi sectors %d count %d VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 957: FDCSectorRegister, FDCSectorCountRegister, nVBLs,
! 958: FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 959:
1.1.1.6 root 960: /* Set emulation to read sectors */
961: FDCEmulationCommand = FDCEMU_CMD_READMULTIPLESECTORS;
962: FDCEmulationRunning = FDCEMU_RUN_READSECTORS_READDATA;
963: /* Set reading parameters */
964: FDC_SetReadWriteParameters(FDCSectorCountRegister); /* Read multiple sectors */
1.1 root 965:
1.1.1.7 root 966: FDC_SetDiskControllerStatus();
1.1 root 967: }
968:
1.1.1.2 root 969:
970: /*-----------------------------------------------------------------------*/
1.1.1.5 root 971: static void FDC_TypeII_WriteSector(void)
1.1 root 972: {
1.1.1.12! root 973: int FrameCycles, HblCounterVideo, LineCycles;
! 974:
! 975: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 976:
! 977: LOG_TRACE(TRACE_FDC, "fdc type II write sector %d VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 978: FDCSectorRegister, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 979:
1.1.1.6 root 980: /* Set emulation to write a single sector */
981: FDCEmulationCommand = FDCEMU_CMD_WRITESECTORS;
982: FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_WRITEDATA;
983: /* Set writing parameters */
984: FDC_SetReadWriteParameters(1); /* Write out a single sector */
1.1 root 985:
1.1.1.7 root 986: FDC_SetDiskControllerStatus();
1.1 root 987: }
988:
1.1.1.2 root 989:
990: /*-----------------------------------------------------------------------*/
1.1.1.5 root 991: static void FDC_TypeII_WriteMultipleSectors(void)
1.1 root 992: {
1.1.1.12! root 993: int FrameCycles, HblCounterVideo, LineCycles;
! 994:
! 995: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 996:
! 997: LOG_TRACE(TRACE_FDC, "fdc type II write multi sectors %d count %d VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 998: FDCSectorRegister, FDCSectorCountRegister, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 999:
1.1.1.6 root 1000: /* Set emulation to write sectors */
1001: FDCEmulationCommand = FDCEMU_CMD_WRITEMULTIPLESECTORS;
1002: FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_WRITEDATA;
1003: /* Set witing parameters */
1004: FDC_SetReadWriteParameters(FDCSectorCountRegister); /* Write multiple sectors */
1.1 root 1005:
1.1.1.7 root 1006: FDC_SetDiskControllerStatus();
1.1 root 1007: }
1008:
1.1.1.2 root 1009:
1010: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1011: /**
1012: * Type III Commands
1013: *
1014: * Read Address, Read Track, Write Track
1015: */
1.1 root 1016:
1.1.1.2 root 1017:
1018: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1019: static void FDC_TypeIII_ReadAddress(void)
1.1 root 1020: {
1.1.1.12! root 1021: int FrameCycles, HblCounterVideo, LineCycles;
! 1022:
! 1023: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1024:
! 1025: LOG_TRACE(TRACE_FDC, "fdc type III read address unimplemented VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 1026: nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 1027:
1028: Log_Printf(LOG_TODO, "FDC type III command 'read address' is not implemented yet!\n");
1.1.1.11 root 1029:
1030: /* Set emulation to seek to track zero */
1031: FDCEmulationCommand = FDCEMU_CMD_READADDRESS;
1032: FDCEmulationRunning = FDCEMU_RUN_READADDRESS;
1033:
1034: FDC_SetDiskControllerStatus();
1.1 root 1035: }
1036:
1.1.1.2 root 1037:
1038: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1039: static void FDC_TypeIII_ReadTrack(void)
1.1 root 1040: {
1.1.1.12! root 1041: int FrameCycles, HblCounterVideo, LineCycles;
! 1042:
! 1043: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1044:
! 1045: LOG_TRACE(TRACE_FDC, "fdc type III read track 0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 1046: FDCTrackRegister, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 1047:
1048: Log_Printf(LOG_TODO, "FDC type III command 'read track' does not work yet!\n");
1.1.1.5 root 1049:
1.1.1.6 root 1050: /* FIXME: "Read track" should read more than only the sectors! (also sector headers, gaps, etc.) */
1.1.1.5 root 1051:
1.1.1.6 root 1052: /* Set emulation to read a single track */
1053: FDCEmulationCommand = FDCEMU_CMD_READSECTORS;
1054: FDCEmulationRunning = FDCEMU_RUN_READSECTORS_READDATA;
1055: /* Set reading parameters */
1056: FDC_SetReadWriteParameters(nReadWriteSectorsPerTrack); /* Read whole track */
1.1 root 1057:
1.1.1.7 root 1058: FDC_SetDiskControllerStatus();
1.1 root 1059: }
1060:
1.1.1.2 root 1061:
1062: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1063: static void FDC_TypeIII_WriteTrack(void)
1.1 root 1064: {
1.1.1.12! root 1065: int FrameCycles, HblCounterVideo, LineCycles;
! 1066:
! 1067: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1068:
! 1069: LOG_TRACE(TRACE_FDC, "fdc type III write track 0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 1070: FDCTrackRegister, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 1071:
1072: Log_Printf(LOG_TODO, "FDC type III command 'write track' does not work yet!\n");
1.1.1.5 root 1073:
1.1.1.6 root 1074: /* FIXME: "Write track" not only writes the sectors! (also sector headers, gaps, etc.) */
1.1.1.5 root 1075:
1.1.1.6 root 1076: /* Set emulation to write a single track */
1077: FDCEmulationCommand = FDCEMU_CMD_WRITESECTORS;
1078: FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_WRITEDATA;
1079: /* Set writing parameters */
1080: FDC_SetReadWriteParameters(nReadWriteSectorsPerTrack); /* Write whole track */
1.1 root 1081:
1.1.1.7 root 1082: FDC_SetDiskControllerStatus();
1.1 root 1083: }
1084:
1.1.1.2 root 1085:
1086: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1087: /**
1088: * Type IV Commands
1089: *
1090: * Force Interrupt
1091: */
1.1 root 1092:
1.1.1.2 root 1093:
1094: /*-----------------------------------------------------------------------*/
1.1.1.10 root 1095: static void FDC_TypeIV_ForceInterrupt(bool bCauseCPUInterrupt)
1.1 root 1096: {
1.1.1.12! root 1097: int FrameCycles, HblCounterVideo, LineCycles;
! 1098:
! 1099: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1100:
! 1101: LOG_TRACE(TRACE_FDC, "fdc type IV force int VBL=%d video_cyc=%d %d@%dpc=%x\n",
! 1102: nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10 root 1103:
1.1.1.6 root 1104: /* Acknowledge interrupt, move along there's nothing more to see */
1105: if (bCauseCPUInterrupt)
1106: FDC_AcknowledgeInterrupt();
1107:
1108: /* Reset FDC */
1109: FDCEmulationCommand = FDCEMU_CMD_NULL;
1110: FDCEmulationRunning = FDCEMU_RUN_NULL;
1.1 root 1111: }
1112:
1.1.1.2 root 1113:
1114: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1115: /**
1116: * Execute Type I commands
1117: */
1.1.1.5 root 1118: static void FDC_ExecuteTypeICommands(void)
1.1 root 1119: {
1.1.1.6 root 1120: MFP_GPIP |= 0x20;
1.1 root 1121:
1.1.1.6 root 1122: /* Check Type I Command */
1123: switch(FDCCommandRegister&0xf0)
1124: {
1125: case 0x00: /* Restore */
1126: FDC_TypeI_Restore();
1127: break;
1128: case 0x10: /* Seek */
1129: FDC_TypeI_Seek();
1130: break;
1131: case 0x20: /* Step */
1132: case 0x30:
1133: FDC_TypeI_Step();
1134: break;
1135: case 0x40: /* Step-In */
1136: case 0x50:
1137: FDC_TypeI_StepIn();
1138: break;
1139: case 0x60: /* Step-Out */
1140: case 0x70:
1141: FDC_TypeI_StepOut();
1142: break;
1143: }
1.1 root 1144:
1.1.1.6 root 1145: /* Signal motor on as we need to execute command */
1146: FDC_TurnMotorOn();
1.1 root 1147: }
1148:
1.1.1.2 root 1149:
1150: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1151: /**
1152: * Execute Type II commands
1153: */
1.1.1.5 root 1154: static void FDC_ExecuteTypeIICommands(void)
1.1 root 1155: {
1.1.1.6 root 1156: MFP_GPIP |= 0x20;
1.1 root 1157:
1.1.1.6 root 1158: /* Check Type II Command */
1159: switch(FDCCommandRegister&0xf0)
1160: {
1161: case 0x80: /* Read Sector */
1162: FDC_TypeII_ReadSector();
1163: break;
1164: case 0x90: /* Read Sectors */
1165: FDC_TypeII_ReadMultipleSectors();
1166: break;
1167: case 0xa0: /* Write Sector */
1168: FDC_TypeII_WriteSector();
1169: break;
1170: case 0xb0: /* Write Sectors */
1171: FDC_TypeII_WriteMultipleSectors();
1172: break;
1173: }
1.1 root 1174:
1.1.1.6 root 1175: /* Signal motor on as we need to execute command */
1176: FDC_TurnMotorOn();
1.1 root 1177: }
1178:
1.1.1.2 root 1179:
1180: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1181: /**
1182: * Execute Type III commands
1183: */
1.1.1.5 root 1184: static void FDC_ExecuteTypeIIICommands(void)
1.1 root 1185: {
1.1.1.6 root 1186: MFP_GPIP |= 0x20;
1.1 root 1187:
1.1.1.6 root 1188: /* Check Type III Command */
1189: switch(FDCCommandRegister&0xf0)
1190: {
1191: case 0xc0: /* Read Address */
1192: FDC_TypeIII_ReadAddress();
1193: break;
1194: case 0xe0: /* Read Track */
1195: FDC_TypeIII_ReadTrack();
1196: break;
1197: case 0xf0: /* Write Track */
1198: FDC_TypeIII_WriteTrack();
1199: break;
1200: }
1.1 root 1201:
1.1.1.6 root 1202: /* Signal motor on as we need to execute command */
1203: FDC_TurnMotorOn();
1.1 root 1204: }
1205:
1.1.1.2 root 1206:
1207: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1208: /**
1209: * Execute Type IV commands
1210: */
1.1.1.5 root 1211: static void FDC_ExecuteTypeIVCommands(void)
1.1 root 1212: {
1.1.1.6 root 1213: if (FDCCommandRegister!=0xD8) /* Is an 'immediate interrupt command'? don't reset interrupt */
1214: MFP_GPIP |= 0x20;
1.1 root 1215:
1.1.1.6 root 1216: /* Check Type IV Command */
1217: if ((FDCCommandRegister&0x0c) == 0) /* I3 and I2 are clear? If so we don't need a CPU interrupt */
1.1.1.12! root 1218: FDC_TypeIV_ForceInterrupt(false); /* Force Interrupt - no interrupt */
1.1.1.6 root 1219: else
1.1.1.12! root 1220: FDC_TypeIV_ForceInterrupt(true); /* Force Interrupt */
1.1 root 1221: }
1222:
1.1.1.2 root 1223:
1224: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1225: /**
1226: * Find FDC command type and execute
1227: */
1.1.1.5 root 1228: static void FDC_ExecuteCommand(void)
1.1 root 1229: {
1.1.1.6 root 1230: /* Check type of command and execute */
1231: if ((FDCCommandRegister&0x80) == 0) /* Type I - Restore,Seek,Step,Step-In,Step-Out */
1232: FDC_ExecuteTypeICommands();
1233: else if ((FDCCommandRegister&0x40) == 0) /* Type II - Read Sector, Write Sector */
1234: FDC_ExecuteTypeIICommands();
1235: else if ((FDCCommandRegister&0xf0) != 0xd0) /* Type III - Read Address, Read Track, Write Track */
1236: FDC_ExecuteTypeIIICommands();
1237: else /* Type IV - Force Interrupt */
1238: FDC_ExecuteTypeIVCommands();
1.1.1.9 root 1239:
1240: Int_AddAbsoluteInterrupt(FDC_DELAY_CYCLES, INT_CPU_CYCLE, INTERRUPT_FDC);
1.1 root 1241: }
1242:
1.1.1.2 root 1243:
1244: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1245: /**
1246: * Write to SectorCount register (WR 0xff8604)
1247: */
1.1.1.5 root 1248: static void FDC_WriteSectorCountRegister(void)
1.1 root 1249: {
1.1.1.12! root 1250: int FrameCycles, HblCounterVideo, LineCycles;
! 1251:
! 1252: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1253:
! 1254: LOG_TRACE(TRACE_FDC, "fdc write 8604 sector count=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 1255: DiskControllerWord_ff8604wr, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.9 root 1256:
1.1.1.7 root 1257: FDCSectorCountRegister = DiskControllerWord_ff8604wr;
1.1 root 1258: }
1259:
1.1.1.2 root 1260:
1261: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1262: /**
1263: * Write to Command register (WR 0xff8604)
1264: */
1.1.1.5 root 1265: static void FDC_WriteCommandRegister(void)
1.1 root 1266: {
1.1.1.12! root 1267: int FrameCycles, HblCounterVideo, LineCycles;
! 1268:
! 1269: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1270:
! 1271: LOG_TRACE(TRACE_FDC, "fdc write 8604 command=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n",
! 1272: DiskControllerWord_ff8604wr, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.9 root 1273:
1.1.1.7 root 1274: FDCCommandRegister = DiskControllerWord_ff8604wr;
1.1.1.6 root 1275: /* And execute */
1276: FDC_ExecuteCommand();
1.1 root 1277: }
1278:
1.1.1.2 root 1279:
1280: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1281: /**
1282: * Write to Track register (WR 0xff8604)
1283: */
1.1.1.5 root 1284: static void FDC_WriteTrackRegister(void)
1.1 root 1285: {
1.1.1.12! root 1286: int FrameCycles, HblCounterVideo, LineCycles;
! 1287:
! 1288: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1289:
! 1290: LOG_TRACE(TRACE_FDC, "fdc write 8604 track=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
! 1291: DiskControllerWord_ff8604wr , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9 root 1292:
1.1.1.10 root 1293: FDCTrackRegister = DiskControllerWord_ff8604wr & 0xff; /* 0...79 */
1.1 root 1294: }
1295:
1.1.1.2 root 1296:
1297: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1298: /**
1299: * Write to Track register (WR 0xff8604)
1300: */
1.1.1.5 root 1301: static void FDC_WriteSectorRegister(void)
1.1 root 1302: {
1.1.1.12! root 1303: int FrameCycles, HblCounterVideo, LineCycles;
! 1304:
! 1305: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1306:
! 1307: LOG_TRACE(TRACE_FDC, "fdc write 8604 sector=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
! 1308: DiskControllerWord_ff8604wr , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9 root 1309:
1.1.1.10 root 1310: FDCSectorRegister = DiskControllerWord_ff8604wr & 0xff; /* 1,2,3..... */
1.1 root 1311: }
1312:
1.1.1.2 root 1313:
1314: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1315: /**
1316: * Write to Data register (WR 0xff8604)
1317: */
1.1.1.5 root 1318: static void FDC_WriteDataRegister(void)
1.1 root 1319: {
1.1.1.12! root 1320: int FrameCycles, HblCounterVideo, LineCycles;
! 1321:
! 1322: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1323:
! 1324: LOG_TRACE(TRACE_FDC, "fdc write 8604 data=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
! 1325: DiskControllerWord_ff8604wr , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9 root 1326:
1.1.1.10 root 1327: FDCDataRegister = DiskControllerWord_ff8604wr & 0xff;
1.1 root 1328: }
1329:
1.1.1.2 root 1330:
1331: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1332: /**
1333: * Store byte in FDC registers, when write to 0xff8604
1334: */
1.1.1.7 root 1335: void FDC_DiskController_WriteWord(void)
1.1 root 1336: {
1.1.1.12! root 1337: int FrameCycles, HblCounterVideo, LineCycles;
! 1338:
1.1.1.6 root 1339: if (nIoMemAccessSize == SIZE_BYTE)
1340: {
1341: /* This register does not like to be accessed in byte mode on a normal ST */
1.1.1.8 root 1342: M68000_BusError(IoAccessBaseAddress, BUS_ERROR_WRITE);
1.1.1.6 root 1343: return;
1344: }
1345:
1.1.1.8 root 1346: M68000_WaitState(4);
1347:
1.1.1.7 root 1348: DiskControllerWord_ff8604wr = IoMem_ReadWord(0xff8604);
1.1.1.6 root 1349:
1.1.1.12! root 1350: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1.1.1.9 root 1351:
1.1.1.12! root 1352: LOG_TRACE(TRACE_FDC, "fdc write 8604 data=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
! 1353: DiskControllerWord_ff8604wr , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.6 root 1354:
1.1.1.12! root 1355: /* Is it an ASCII HD command? */
1.1.1.8 root 1356: if ((DMAModeControl_ff8606wr & 0x0018) == 8)
1.1.1.12! root 1357: {
! 1358: /* Handle HDC functions */
! 1359: HDC_WriteCommandPacket();
1.1.1.10 root 1360: return;
1.1.1.12! root 1361: }
1.1.1.6 root 1362:
1363: /* Are we trying to set the SectorCount? */
1364: if (DMAModeControl_ff8606wr&0x10) /* Bit 4 */
1365: FDC_WriteSectorCountRegister();
1366: else
1.1.1.8 root 1367: {
1368: /* Write to FDC registers */
1.1.1.6 root 1369: switch(DMAModeControl_ff8606wr&0x6)
1370: { /* Bits 1,2 (A1,A0) */
1371: case 0x0: /* 0 0 - Command register */
1372: FDC_WriteCommandRegister();
1373: break;
1374: case 0x2: /* 0 1 - Track register */
1375: FDC_WriteTrackRegister();
1376: break;
1377: case 0x4: /* 1 0 - Sector register */
1378: FDC_WriteSectorRegister();
1379: break;
1380: case 0x6: /* 1 1 - Data register */
1381: FDC_WriteDataRegister();
1382: break;
1383: }
1384: }
1.1 root 1385: }
1386:
1.1.1.2 root 1387:
1388: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1389: /**
1390: * Read Status/FDC registers, when read from 0xff8604
1391: * Return 'DiskControllerByte'
1392: */
1.1.1.7 root 1393: void FDC_DiskControllerStatus_ReadWord(void)
1.1 root 1394: {
1.1.1.7 root 1395: Sint16 DiskControllerByte = 0; /* Used to pass back the parameter */
1.1.1.12! root 1396: int FrameCycles, HblCounterVideo, LineCycles;
! 1397:
1.1.1.6 root 1398:
1399: if (nIoMemAccessSize == SIZE_BYTE)
1400: {
1401: /* This register does not like to be accessed in byte mode on a normal ST */
1.1.1.8 root 1402: M68000_BusError(IoAccessBaseAddress, BUS_ERROR_READ);
1.1.1.6 root 1403: return;
1404: }
1405:
1.1.1.8 root 1406: M68000_WaitState(4);
1407:
1408: if ((DMAModeControl_ff8606wr & 0x18) == 0x08) /* HDC status reg selected? */
1.1.1.6 root 1409: {
1410: /* return the HDC status reg */
1.1.1.7 root 1411: DiskControllerByte = HDCCommand.returnCode;
1.1.1.6 root 1412: }
1.1.1.8 root 1413: else if ((DMAModeControl_ff8606wr & 0x18) == 0x18) /* HDC sector counter??? */
1414: {
1415: Log_Printf(LOG_DEBUG, "*** Read HDC sector counter???\n");
1416: DiskControllerByte = HDCSectorCount;
1417: }
1.1.1.6 root 1418: else
1419: {
1420: /* old FDC code */
1421: switch (DMAModeControl_ff8606wr&0x6) /* Bits 1,2 (A1,A0) */
1422: {
1423: case 0x0: /* 0 0 - Status register */
1.1.1.7 root 1424: DiskControllerByte = DiskControllerStatus_ff8604rd;
1.1.1.6 root 1425: if (bMotorOn)
1.1.1.7 root 1426: DiskControllerByte |= 0x80;
1.1.1.6 root 1427:
1428: if (Floppy_IsWriteProtected(nReadWriteDev))
1.1.1.7 root 1429: DiskControllerByte |= 0x40;
1.1.1.6 root 1430:
1431: if (EmulationDrives[nReadWriteDev].bMediaChanged)
1432: {
1433: /* Some games apparently poll the write-protection signal to check
1434: * for disk image changes (the signal seems to change when you
1435: * exchange disks on a real ST). We now also simulate this behaviour
1436: * here, so that these games can continue with the other disk. */
1.1.1.7 root 1437: DiskControllerByte ^= 0x40;
1.1.1.12! root 1438: EmulationDrives[nReadWriteDev].bMediaChanged = false;
1.1.1.6 root 1439: }
1440:
1441: /* Reset FDC GPIP */
1442: MFP_GPIP |= 0x20;
1443: break;
1444: case 0x2: /* 0 1 - Track register */
1.1.1.7 root 1445: DiskControllerByte = FDCTrackRegister;
1.1.1.6 root 1446: break;
1447: case 0x4: /* 1 0 - Sector register */
1.1.1.7 root 1448: DiskControllerByte = FDCSectorRegister;
1.1.1.6 root 1449: break;
1450: case 0x6: /* 1 1 - Data register */
1.1.1.7 root 1451: DiskControllerByte = FDCDataRegister;
1.1.1.6 root 1452: break;
1453: }
1454: }
1455:
1.1.1.7 root 1456: IoMem_WriteWord(0xff8604, DiskControllerByte);
1.1.1.9 root 1457:
1.1.1.12! root 1458: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1459:
! 1460: LOG_TRACE(TRACE_FDC, "fdc read 8604 ctrl status=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
! 1461: DiskControllerByte , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1 root 1462: }
1463:
1.1.1.2 root 1464:
1465: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1466: /**
1467: * Read DMA address from ST's RAM (always up-to-date)
1468: */
1.1.1.6 root 1469: Uint32 FDC_ReadDMAAddress(void)
1.1 root 1470: {
1.1.1.6 root 1471: Uint32 Address;
1.1 root 1472:
1.1.1.6 root 1473: /* Build up 24-bit address from hardware registers */
1474: Address = ((Uint32)STMemory_ReadByte(0xff8609)<<16) | ((Uint32)STMemory_ReadByte(0xff860b)<<8) | (Uint32)STMemory_ReadByte(0xff860d);
1.1 root 1475:
1.1.1.6 root 1476: return Address;
1.1 root 1477: }
1478:
1.1.1.2 root 1479:
1480: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1481: /**
1482: * Write DMA address to ST's RAM(always keep up-to-date)
1483: */
1.1.1.6 root 1484: void FDC_WriteDMAAddress(Uint32 Address)
1.1 root 1485: {
1.1.1.12! root 1486: int FrameCycles, HblCounterVideo, LineCycles;
! 1487:
! 1488: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1489:
! 1490: LOG_TRACE(TRACE_FDC, "fdc write 0x%x to dma address VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
! 1491: Address , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9 root 1492:
1.1.1.6 root 1493: /* Store as 24-bit address */
1494: STMemory_WriteByte(0xff8609, Address>>16);
1495: STMemory_WriteByte(0xff860b, Address>>8);
1496: STMemory_WriteByte(0xff860d, Address);
1.1 root 1497: }
1498:
1.1.1.2 root 1499:
1500: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1501: /**
1502: * Read sector from floppy drive into workspace
1503: * We copy the bytes in chunks to simulate reading of the floppy using DMA
1504: */
1.1.1.10 root 1505: bool FDC_ReadSectorFromFloppy(void)
1.1 root 1506: {
1.1.1.12! root 1507: int FrameCycles, HblCounterVideo, LineCycles;
! 1508:
! 1509: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1510:
! 1511: LOG_TRACE(TRACE_FDC, "fdc read sector addr=0x%x dev=%d sect=%d track=%d side=%d VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
! 1512: FDC_ReadDMAAddress(), nReadWriteDev, nReadWriteSector, nReadWriteTrack, nReadWriteSide,
! 1513: nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9 root 1514:
1.1.1.6 root 1515: /* Copy in 1 sector to our workspace */
1.1.1.7 root 1516: if (Floppy_ReadSectors(nReadWriteDev, DMASectorWorkSpace, nReadWriteSector, nReadWriteTrack, nReadWriteSide, 1, NULL))
1.1.1.6 root 1517: {
1518: /* Update reading/writing parameters */
1519: nReadWriteSector++;
1520: if (nReadWriteSector > nReadWriteSectorsPerTrack) /* Advance into next track? */
1521: {
1522: nReadWriteSector = 1;
1523: nReadWriteTrack++;
1524: }
1.1.1.12! root 1525: return true;
1.1.1.6 root 1526: }
1.1 root 1527:
1.1.1.6 root 1528: /* Failed */
1.1.1.12! root 1529: LOG_TRACE(TRACE_FDC, "fdc read sector failed\n" );
! 1530: return false;
1.1 root 1531: }
1532:
1.1.1.2 root 1533:
1534: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1535: /**
1536: * Write sector from workspace to floppy drive
1537: * We copy the bytes in chunks to simulate writing of the floppy using DMA
1538: */
1.1.1.10 root 1539: bool FDC_WriteSectorFromFloppy(void)
1.1 root 1540: {
1.1.1.6 root 1541: Uint32 Address;
1.1.1.12! root 1542: int FrameCycles, HblCounterVideo, LineCycles;
! 1543:
1.1 root 1544:
1.1.1.6 root 1545: /* Get DMA address */
1546: Address = FDC_ReadDMAAddress();
1.1 root 1547:
1.1.1.12! root 1548: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1549:
! 1550: LOG_TRACE(TRACE_FDC, "fdc write sector addr=0x%x dev=%d sect=%d track=%d side=%d VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
! 1551: Address, nReadWriteDev, nReadWriteSector, nReadWriteTrack, nReadWriteSide,
! 1552: nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9 root 1553:
1.1.1.6 root 1554: /* Write out 1 sector from our workspace */
1555: if (Floppy_WriteSectors(nReadWriteDev, &STRam[Address], nReadWriteSector, nReadWriteTrack, nReadWriteSide, 1, NULL))
1556: {
1557: /* Update reading/writing parameters */
1558: nReadWriteSector++;
1559: if (nReadWriteSector > nReadWriteSectorsPerTrack) /* Advance to next track? */
1560: {
1561: nReadWriteSector = 1;
1562: nReadWriteTrack++;
1563: }
1.1.1.12! root 1564: return true;
1.1.1.6 root 1565: }
1.1 root 1566:
1.1.1.6 root 1567: /* Failed */
1.1.1.12! root 1568: LOG_TRACE(TRACE_FDC, "fdc write sector failed\n" );
! 1569: return false;
1.1 root 1570: }
1571:
1572:
1.1.1.2 root 1573: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1574: /**
1575: * Copy data from DMA workspace into ST RAM
1576: */
1.1 root 1577: void FDC_DMADataFromFloppy(void)
1578: {
1.1.1.6 root 1579: /* Copy data to DMA address */
1580: memcpy(&STRam[FDC_ReadDMAAddress()], DMASectorWorkSpace, NUMBYTESPERSECTOR );
1.1 root 1581:
1.1.1.6 root 1582: /* Update DMA pointer */
1583: FDC_WriteDMAAddress(FDC_ReadDMAAddress()+NUMBYTESPERSECTOR);
1.1 root 1584: }
1585:
1586:
1.1.1.2 root 1587: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1588: /**
1589: * Write word to 0xff8606 (DMA Mode Control)
1.1.1.10 root 1590: *
1.1.1.9 root 1591: * Eg.
1592: * $80 - Selects command/status register
1593: * $82 - Selects track register
1594: * $84 - Selects sector register
1595: * $86 - Selects data regsiter
1596: * NOTE - OR above values with $100 is transfer from memory to floppy
1597: * Also if bit 4 is set, write to sector count register
1598: */
1.1.1.6 root 1599: void FDC_DmaModeControl_WriteWord(void)
1.1 root 1600: {
1.1.1.6 root 1601: Uint16 DMAModeControl_ff8606wr_prev; /* stores previous write to 0xff8606 for 'toggle' checks */
1.1.1.12! root 1602: int FrameCycles, HblCounterVideo, LineCycles;
! 1603:
1.1 root 1604:
1.1.1.6 root 1605: if (nIoMemAccessSize == SIZE_BYTE)
1606: {
1607: /* This register does not like to be accessed in byte mode on a normal ST */
1.1.1.8 root 1608: M68000_BusError(IoAccessBaseAddress, BUS_ERROR_WRITE);
1.1.1.6 root 1609: return;
1610: }
1611:
1612: DMAModeControl_ff8606wr_prev = DMAModeControl_ff8606wr; /* Store previous to check for _read/_write toggle (DMA reset) */
1613: DMAModeControl_ff8606wr = IoMem_ReadWord(0xff8606); /* Store to DMA Mode control */
1614:
1.1.1.12! root 1615: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 1616:
! 1617: LOG_TRACE(TRACE_FDC, "fdc write 8606 ctrl=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
! 1618: DMAModeControl_ff8606wr , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9 root 1619:
1.1.1.6 root 1620: /* When write to 0xff8606, check bit '8' toggle. This causes DMA status reset */
1621: if ((DMAModeControl_ff8606wr_prev ^ DMAModeControl_ff8606wr) & 0x0100)
1622: FDC_ResetDMAStatus();
1623: }
1.1.1.9 root 1624:
1625:
1626: /*-----------------------------------------------------------------------*/
1627: /**
1628: * Write to floppy mode/control (?) register (0xff860F).
1629: * Used on Falcon only!
1630: * FIXME: I've found hardly any documentation about this register, only
1631: * the following description of the bits:
1632: *
1633: * __________54__10 Floppy Controll-Register
1634: * || ||
1635: * || |+- Prescaler 1
1636: * || +-- Media detect 1
1637: * |+----- Prescaler 2
1638: * +------ Media detect 2
1639: *
1640: * For DD - disks: 0x00
1641: * For HD - disks: 0x03
1642: * for ED - disks: 0x30 (not supported by TOS)
1643: */
1644: void FDC_FloppyMode_WriteByte(void)
1645: {
1646: // printf("Write to floppy mode reg.: 0x%02x\n", IoMem_ReadByte(0xff860f));
1647: }
1648:
1649:
1650: /*-----------------------------------------------------------------------*/
1651: /**
1652: * Read from floppy mode/control (?) register (0xff860F).
1653: * Used on Falcon only!
1654: * FIXME: I've found hardly any documentation about this register, only
1655: * the following description of the bits:
1656: *
1657: * ________76543210 Floppy Controll-Register
1658: * ||||||||
1659: * |||||||+- Prescaler 1
1660: * ||||||+-- Mode select 1
1661: * |||||+--- Media detect 1
1662: * ||||+---- accessed during DMA transfers (?)
1663: * |||+----- Prescaler 2
1664: * ||+------ Mode select 2
1665: * |+------- Media detect 2
1666: * +-------- Disk changed
1667: */
1668: void FDC_FloppyMode_ReadByte(void)
1669: {
1670: IoMem_WriteByte(0xff860f, 0x80); // FIXME: Is this ok?
1671: // printf("Read from floppy mode reg.: 0x%02x\n", IoMem_ReadByte(0xff860f));
1672: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.