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