Annotation of hatari/src/fdc.c, revision 1.1.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.