Annotation of hatari/src/fdc.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.