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