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