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