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

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

unix.superglobalmegacorp.com

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