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