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