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