|
|
1.1 root 1: /*
1.1.1.4 root 2: Hatari - fdc.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
1.1 root 6:
1.1.1.7 ! root 7: Floppy Disk Controller(FDC) emulation. We need to simulate the movement of
! 8: the head of the floppy disk drive to accurately perform the FDC commands,
! 9: such as 'Step'. The is important for ST demo disk images. We have to go
1.1.1.6 root 10: into a lot of details - including the start up/stop of the drive motor.
11: To help with this emulation, we keep our own internal commands which are
1.1.1.7 ! root 12: checked each HBL to perform the transfer of data from our disk image into
1.1.1.6 root 13: the ST RAM area by simulating the DMA.
1.1 root 14: */
1.1.1.7 ! root 15: char FDC_rcsid[] = "Hatari $Id: fdc.c,v 1.23 2005/09/26 15:20:14 thothy Exp $";
1.1 root 16:
17: #include "main.h"
1.1.1.4 root 18: #include "configuration.h"
1.1 root 19: #include "fdc.h"
1.1.1.3 root 20: #include "hdc.h"
1.1 root 21: #include "floppy.h"
22: #include "ikbd.h"
1.1.1.6 root 23: #include "ioMem.h"
24: #include "log.h"
1.1 root 25: #include "m68000.h"
26: #include "memorySnapShot.h"
27: #include "mfp.h"
28: #include "misc.h"
29: #include "psg.h"
30: #include "stMemory.h"
31:
1.1.1.3 root 32:
1.1 root 33: /*
1.1.1.7 ! root 34: Floppy Disk Controller
1.1 root 35:
36: Programmable Sound Generator (YM-2149)
37:
38: 0xff8800(even byte) - PSG Register Data (Read, used for parallel port)
39: - PSG Register Select (Write)
40:
41: Write to bits 0-3 to select PSG register to use(then write data to 0xfff8802)
42: Value Register
43:
44: 0000 Channel A Fine Tune
45: 0001 Channel A Coarse Tune
46: 0010 Channel B Fine Tune
47: 0011 Channel B Coarse Tune
48: 0100 Channel C Fine Tune
49: 0101 Channel C Coarse Tune
50: 0110 Noise Generator Control
51: 0111 Mixer Control - I/O enable
52: 1000 Channel A Amplitude
53: 1001 Channel B Amplitude
54: 1010 Channel C Amplitude
55: 1011 Envelope Period Fine Tune
56: 1100 Envelope Peroid Coarse Tune
57: 1101 Envelope Shape
58: 1110 I/O Port A Select (Write only)
59: 1111 I/O Port B Select
60:
61: 0xfff8802(even byte) - Bits according to 0xff8800 Register select
1.1.1.4 root 62:
1.1 root 63: 1110(Register 14) - I/O Port A
64: Bit 0 - Floppy side 0/1
65: Bit 1 - Floppy drive 0 select
66: Bit 2 - Floppy drive 1 select
67: Bit 3 - RS232 Ready to send (RTS)
68: Bit 4 - RS232 Data Terminal Ready (DTR)
69: Bit 5 - Centronics Strobe
70: Bit 6 - General Purpose Output
71: Bit 7 - Reserved
72:
1.1.1.7 ! root 73: ACSI DMA and Floppy Disk Controller(FDC)
1.1 root 74: 0xff8604 - information from file '1772.info.txt, by David Gahris' (register r0)
75: (write) - Disk controller
76: (read) - Disk controller status
77: Bit 0 - Busy. This bit is 1 when the 177x is busy. This bit is 0 when the 177x is free for CPU commands.
78: Bit 1 - Index / Data Request. On Type I commands, this bit is high during the index pulse that occurs once
79: per disk rotation. This bit is low at all times other than the index pulse. For Type II and III commands,
80: Bit 1 high signals the CPU to handle the data register in order to maintain a continuous flow of data.
81: Bit 1 is high when the data register is full during a read or when the data register is empty during a write.
82: "Worst case service time" for Data Request is 23.5 cycles.
83: Bit 2 - Track Zero / Lost Data. After Type I commands, this bit is 0 if the mechanism is at track zero.
84: This bit is 1 if the head is not at track zero. After Type II or III commands, this bit is 1 if the
85: CPU did not respond to Data Request (Status bit 1) in time for the 177x to maintain a continuous data flow.
86: This bit is 0 if the CPU responded promptly to Data Request.
87: Bit 3 - CRC Error. This bit is high if a sector CRC on disk does not match the CRC which the 177x
88: computed from the data. The CRC polynomial is x^16+x^12+x^5+1. If the stored CRC matches the newly
89: calculated CRC, the CRC Error bit is low. If this bit and the Record Not Found bit are set, the error
90: was in an ID field. If this bit is set but Record Not Found is clear, the error was in a data field.
91: Bit 4 - Record Not Found. This bit is set if the 177x cannot find the track, sector, or side which
92: the CPU requested. Otherwise, this bit is clear.
93: Bit 5 - Spin-up / Record Type. For Type I commands, this bit is low during the 6-revolution motor
94: spin-up time. This bit is high after spin-up. For Type II and Type III commands, Bit 5 low
95: indicates a normal data mark. Bit 5 high indicates a deleted data mark.
96: Bit 6 - Write Protect. This bit is not used during reads. During writes, this bit is high when the disk is write protected.
97: Bit 7 - Motor On. This bit is high when the drive motor is on, and low when the motor is off.
98:
99: 0xff8606 - DMA Status(read), DMA Mode Control(write) - NOTE bits 0,9-15 are not used
100: Bit 1 - FDC Pin A0 (See below)
101: Bit 2 - FDC Pin A1
102: Bit 3 - FDC/HDC Register Select
103: Bit 4 - FDC/Sector count select
104: Bit 5 - Reserved
105: Bit 6 - Enable/Disable DMA
106: Bit 7 - HDC/FDC
107: Bit 8 - Read/Write
108:
109: A1 A0 Read Write(bit 8==1)
110: 0 0 Status Command
111: 0 1 Track Register Track Register
112: 1 0 Sector Register Sector Register
113: 1 1 Data Register Data Register
114:
115:
1.1.1.6 root 116: This handles any read/writes to the FDC and PSG. FDC commands are then sent
1.1.1.7 ! root 117: through to read/write disk sector code. We have full documents on 1772 FDC,
1.1.1.6 root 118: but they use r0,r1,r2,r3 etc.. which are not seen at first glance as Atari
119: access them via the A0,A1 bits. Once this is understood it is all relativly
1.1.1.7 ! root 120: easy as a lot of information can be ignored as we are using disk images and
! 121: not actual disks. We do NOT support the reading of the PC's A: drive - newer
! 122: PC's cannot read an ST single sided disk, ST disks are very old and so are
1.1.1.6 root 123: dirty which gets onto the PC drive heads and ruins them and also support for
1.1.1.7 ! root 124: disk sector access under the various modern operating systems is not so easy
1.1.1.6 root 125: (if possible at all).
126:
127: According to the documentation INTRQ is generated at the completion of each
128: command (causes an interrupt in the MFP). INTRQ is reset by reading the status
129: register OR by loading a new command. So, does this mean the GPIP? Or does it
130: actually CANCEL the interrupt? Can this be done?
1.1 root 131: */
132:
133:
1.1.1.7 ! root 134: Sint16 FDCSectorCountRegister;
1.1 root 135:
1.1.1.7 ! root 136: Uint16 DiskControllerWord_ff8604wr; /* 0xff8604 (write) */
! 137: static Uint16 DiskControllerStatus_ff8604rd; /* 0xff8604 (read) */
1.1.1.5 root 138:
1.1.1.6 root 139: Uint16 DMAModeControl_ff8606wr; /* 0xff8606 (write) */
140: static Uint16 DMAStatus_ff8606rd; /* 0xff8606 (read) */
1.1.1.5 root 141:
1.1.1.7 ! root 142: static Uint16 FDCCommandRegister;
! 143: static Sint16 FDCTrackRegister, FDCSectorRegister, FDCDataRegister;
1.1.1.5 root 144: static int FDCEmulationCommand; /* FDC emulation command currently being exceuted */
145: static int FDCEmulationRunning; /* Running command under above */
146: static int FDCStepDirection; /* +Track on 'Step' command */
147: static BOOL bDMAWaiting; /* Is DMA waiting to copy? */
148: static int bMotorOn; /* Is motor on? */
149: static int MotorSlowingCount; /* Counter used to slow motor before stopping */
150:
151: static short int nReadWriteTrack; /* Parameters used in sector read/writes */
152: static short int nReadWriteSector;
153: static short int nReadWriteSide;
154: static short int nReadWriteDev;
155: static unsigned short int nReadWriteSectorsPerTrack;
156: static short int nReadWriteSectors;
157:
1.1.1.7 ! root 158: static Uint8 DMASectorWorkSpace[NUMBYTESPERSECTOR]; /* Workspace used to copy to/from for floppy DMA */
1.1 root 159:
1.1.1.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 */
1.1.1.7 ! root 168: DiskControllerStatus_ff8604rd = 0;
! 169: DiskControllerWord_ff8604wr = 0;
1.1.1.6 root 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 */
1.1.1.7 ! root 196: MemorySnapShot_Store(&DiskControllerStatus_ff8604rd, sizeof(DiskControllerStatus_ff8604rd));
! 197: MemorySnapShot_Store(&DiskControllerWord_ff8604wr, sizeof(DiskControllerWord_ff8604wr));
1.1.1.6 root 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.7 ! root 327: static void FDC_UpdateDiskDrive(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.7 ! root 332: if (EmulationDrives[nReadWriteDev].bDiskInserted)
! 333: Floppy_FindDiskDetails(EmulationDrives[nReadWriteDev].pBuffer,EmulationDrives[nReadWriteDev].nImageBytes,&nReadWriteSectorsPerTrack,NULL);
1.1 root 334: }
335:
1.1.1.2 root 336:
337: /*-----------------------------------------------------------------------*/
1.1 root 338: /*
1.1.1.7 ! root 339: Set disk controller status (RD 0xff8604)
1.1 root 340: */
1.1.1.7 ! root 341: static void FDC_SetDiskControllerStatus(void)
1.1 root 342: {
1.1.1.7 ! root 343: /* Update disk */
! 344: FDC_UpdateDiskDrive();
1.1 root 345:
1.1.1.6 root 346: /* Clear out to default */
1.1.1.7 ! root 347: DiskControllerStatus_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)
1.1.1.7 ! root 354: DiskControllerStatus_ff8604rd |= 0x4; /* Bit 2 - Track Zero, '0' if head is NOT at zero */
1.1.1.6 root 355: }
356:
1.1.1.7 ! root 357: /* If no disk inserted, tag as error */
! 358: if (!EmulationDrives[nReadWriteDev].bDiskInserted)
! 359: DiskControllerStatus_ff8604rd |= 0x10; /* RNF - Record not found, ie no disk 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: /*
1.1.1.7 ! root 395: Copy parameters for disk sector/s read/write
1.1 root 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;
1.1.1.7 ! root 404: /* Update disk */
! 405: FDC_UpdateDiskDrive();
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
1.1.1.7 ! root 424: nDelayHBLs = 180;
1.1.1.6 root 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:
1.1.1.7 ! root 471: /* Set disk controller status (RD 0xff8604) */
! 472: FDC_SetDiskControllerStatus();
1.1.1.6 root 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.7 ! root 752: FDC_SetDiskControllerStatus();
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.7 ! root 763: FDC_SetDiskControllerStatus();
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.7 ! root 774: FDC_SetDiskControllerStatus();
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.7 ! root 786: FDC_SetDiskControllerStatus();
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.7 ! root 798: FDC_SetDiskControllerStatus();
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.7 ! root 819: FDC_SetDiskControllerStatus();
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.7 ! root 832: FDC_SetDiskControllerStatus();
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.7 ! root 845: FDC_SetDiskControllerStatus();
1.1 root 846: }
847:
1.1.1.2 root 848:
849: /*-----------------------------------------------------------------------*/
1.1.1.5 root 850: static void FDC_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.7 ! root 858: FDC_SetDiskControllerStatus();
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.7 ! root 890: FDC_SetDiskControllerStatus();
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.7 ! root 907: FDC_SetDiskControllerStatus();
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.7 ! root 1066: FDCSectorCountRegister = DiskControllerWord_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.7 ! root 1076: FDCCommandRegister = DiskControllerWord_ff8604wr;
1.1.1.6 root 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.7 ! root 1088: FDCTrackRegister = DiskControllerWord_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.7 ! root 1098: FDCSectorRegister = DiskControllerWord_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.7 ! root 1108: FDCDataRegister = DiskControllerWord_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.7 ! root 1116: void FDC_DiskController_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:
1.1.1.7 ! root 1125: DiskControllerWord_ff8604wr = IoMem_ReadWord(0xff8604);
1.1.1.6 root 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
1.1.1.7 ! root 1160: Return 'DiskControllerByte'
1.1 root 1161: */
1.1.1.7 ! root 1162: void FDC_DiskControllerStatus_ReadWord(void)
1.1 root 1163: {
1.1.1.7 ! root 1164: Sint16 DiskControllerByte = 0; /* Used to pass back the parameter */
1.1.1.6 root 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 */
1.1.1.7 ! root 1176: DiskControllerByte = HDCCommand.returnCode;
1.1.1.6 root 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 */
1.1.1.7 ! root 1184: DiskControllerByte = DiskControllerStatus_ff8604rd;
1.1.1.6 root 1185: if (bMotorOn)
1.1.1.7 ! root 1186: DiskControllerByte |= 0x80;
1.1.1.6 root 1187:
1188: if (Floppy_IsWriteProtected(nReadWriteDev))
1.1.1.7 ! root 1189: DiskControllerByte |= 0x40;
1.1.1.6 root 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. */
1.1.1.7 ! root 1197: DiskControllerByte ^= 0x40;
1.1.1.6 root 1198: EmulationDrives[nReadWriteDev].bMediaChanged = FALSE;
1199: }
1200:
1201: /* Reset FDC GPIP */
1202: MFP_GPIP |= 0x20;
1203: break;
1204: case 0x2: /* 0 1 - Track register */
1.1.1.7 ! root 1205: DiskControllerByte = FDCTrackRegister;
1.1.1.6 root 1206: break;
1207: case 0x4: /* 1 0 - Sector register */
1.1.1.7 ! root 1208: DiskControllerByte = FDCSectorRegister;
1.1.1.6 root 1209: break;
1210: case 0x6: /* 1 1 - Data register */
1.1.1.7 ! root 1211: DiskControllerByte = FDCDataRegister;
1.1.1.6 root 1212: break;
1213: }
1214: }
1215:
1.1.1.7 ! root 1216: IoMem_WriteWord(0xff8604, DiskControllerByte);
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 */
1.1.1.7 ! root 1256: if (Floppy_ReadSectors(nReadWriteDev, DMASectorWorkSpace, nReadWriteSector, nReadWriteTrack, nReadWriteSide, 1, NULL))
1.1.1.6 root 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.