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