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