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

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: 
1.1.1.2 ! root      150: 
        !           151: /*-----------------------------------------------------------------------*/
1.1       root      152: /*
                    153:   Reset variables used in FDC
                    154: */
                    155: void FDC_Reset(void)
                    156: {
1.1.1.2 ! root      157:   /* Clear out FDC registers */
1.1       root      158:   DiscControllerStatus_ff8604rd = 0;
                    159:   DiscControllerWord_ff8604wr = 0;
                    160:   DMAStatus_ff8606rd = 0x01;
                    161:   DMAModeControl_ff8606wr = DMAModeControl_ff8606wr_prev = 0;
                    162:   FDC_ResetDMAStatus();
                    163:   FDCCommandRegister = 0;
                    164:   FDCTrackRegister = 0;
                    165:   FDCSectorRegister = 1;
                    166:   FDCDataRegister = 0;
                    167:   FDCSectorCountRegister = 0;
                    168: 
                    169:   FDCEmulationCommand = FDCEMU_CMD_NULL;        /* FDC emulation command currently being exceuted */
                    170:   FDCEmulationRunning = FDCEMU_RUN_NULL;        /* Running command under above */
                    171: 
                    172:   FDCStepDirection = 1;                         /* +Track on 'Step' command */
                    173:   bDMAWaiting = FALSE;                          /* No DMA waiting */
                    174:   bMotorOn = FALSE;                             /* Motor off */
                    175:   MotorSlowingCount = 0;                        /* Counter for motor slowing down before stopping */
                    176: }
                    177: 
1.1.1.2 ! root      178: 
        !           179: /*-----------------------------------------------------------------------*/
1.1       root      180: /*
                    181:   Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                    182: */
                    183: void FDC_MemorySnapShot_Capture(BOOL bSave)
                    184: {
1.1.1.2 ! root      185:   /* Save/Restore details */
1.1       root      186:   MemorySnapShot_Store(&DiscControllerStatus_ff8604rd,sizeof(DiscControllerStatus_ff8604rd));
                    187:   MemorySnapShot_Store(&DiscControllerWord_ff8604wr,sizeof(DiscControllerWord_ff8604wr));
                    188:   MemorySnapShot_Store(&DMAStatus_ff8606rd,sizeof(DMAStatus_ff8606rd));
                    189:   MemorySnapShot_Store(&DMAModeControl_ff8606wr,sizeof(DMAModeControl_ff8606wr));
                    190:   MemorySnapShot_Store(&DMAModeControl_ff8606wr_prev,sizeof(DMAModeControl_ff8606wr_prev));
                    191:   MemorySnapShot_Store(&FDCCommandRegister,sizeof(FDCCommandRegister));
                    192:   MemorySnapShot_Store(&FDCTrackRegister,sizeof(FDCTrackRegister));
                    193:   MemorySnapShot_Store(&FDCSectorRegister,sizeof(FDCSectorRegister));
                    194:   MemorySnapShot_Store(&FDCDataRegister,sizeof(FDCDataRegister));
                    195:   MemorySnapShot_Store(&FDCSectorCountRegister,sizeof(FDCSectorCountRegister));
                    196:   MemorySnapShot_Store(&FDCEmulationCommand,sizeof(FDCEmulationCommand));
                    197:   MemorySnapShot_Store(&FDCEmulationRunning,sizeof(FDCEmulationRunning));
                    198:   MemorySnapShot_Store(&FDCStepDirection,sizeof(FDCStepDirection));
                    199:   MemorySnapShot_Store(&DiscControllerByte,sizeof(DiscControllerByte));
                    200:   MemorySnapShot_Store(&bDMAWaiting,sizeof(bDMAWaiting));
                    201:   MemorySnapShot_Store(&bMotorOn,sizeof(bMotorOn));
                    202:   MemorySnapShot_Store(&MotorSlowingCount,sizeof(MotorSlowingCount));
                    203:   MemorySnapShot_Store(&nReadWriteTrack,sizeof(nReadWriteTrack));
                    204:   MemorySnapShot_Store(&nReadWriteSector,sizeof(nReadWriteSector));
                    205:   MemorySnapShot_Store(&nReadWriteSide,sizeof(nReadWriteSide));
                    206:   MemorySnapShot_Store(&nReadWriteDev,sizeof(nReadWriteDev));
                    207:   MemorySnapShot_Store(&nReadWriteSectorsPerTrack,sizeof(nReadWriteSectorsPerTrack));
                    208:   MemorySnapShot_Store(&nReadWriteSectors,sizeof(nReadWriteSectors));
                    209:   MemorySnapShot_Store(DMASectorWorkSpace,sizeof(DMASectorWorkSpace));
                    210: }
                    211: 
1.1.1.2 ! root      212: 
        !           213: /*-----------------------------------------------------------------------*/
1.1       root      214: /*
                    215:   Turn floppy motor on
                    216: */
                    217: void FDC_TurnMotorOn(void)
                    218: {
                    219:   bMotorOn = TRUE;                  /* Turn motor on */
                    220:   MotorSlowingCount = 0;
                    221: }
                    222: 
1.1.1.2 ! root      223: 
        !           224: /*-----------------------------------------------------------------------*/
1.1       root      225: /*
                    226:   Turn floppy motor off(this sets a count as it takes a set amount of time for the motor to slow to a halt)
                    227: */
                    228: void FDC_TurnMotorOff(void)
                    229: {
                    230:   MotorSlowingCount = 10;           /* Set timer so takes 'x' HBLs before turn off... */
                    231: }
                    232: 
1.1.1.2 ! root      233: 
        !           234: /*-----------------------------------------------------------------------*/
1.1       root      235: /*
                    236:   Update floppy drive motor each HBL, to simulate slowing down and stopping for drive; needed for New Zealand Story(PP_001)
                    237: */
                    238: void FDC_UpdateMotor(void)
                    239: {
1.1.1.2 ! root      240:   /* Is drive slowing down? Decrement counter */
1.1       root      241:   if (MotorSlowingCount>0) {
                    242:     MotorSlowingCount--;
                    243: 
                    244:     if (MotorSlowingCount==0)
                    245:       bMotorOn = FALSE;             /* Motor finally stopped */
                    246:   }
                    247: }
                    248: 
1.1.1.2 ! root      249: 
        !           250: /*-----------------------------------------------------------------------*/
1.1       root      251: /*
                    252:   Reset DMA Status (RD 0xff8606)
                    253: 
                    254:   This is done by 'toggling' bit 8 of the DMA Mode Control register
                    255: */
                    256: void FDC_ResetDMAStatus(void)
                    257: {
                    258:   DMAStatus_ff8606rd = 0;           /* Clear out */
                    259: 
                    260:   FDCSectorCountRegister = 0;
                    261:   FDC_SetDMAStatus(FALSE);          /* Set no error */
                    262: }
                    263: 
1.1.1.2 ! root      264: 
        !           265: /*-----------------------------------------------------------------------*/
1.1       root      266: /*
                    267:   Set DMA Status (RD 0xff8606)
                    268:   
                    269:   NOTE FDC Doc's are incorrect - Bit 0 is '0' on error (See TOS floprd, Ninja III etc...)
                    270:   Look like Atari(yet again) connected the hardware up differently to the spec'
                    271: 
                    272:   Bit 0 - _Error Status (0=Error)
                    273:   Bit 1 - _Sector Count Zero Status (0=Sector Count Zero)
                    274:   Bit 2 - _Data Request Inactive Status
                    275: */
                    276: void FDC_SetDMAStatus(BOOL bError)
                    277: {
                    278:   DMAStatus_ff8606rd &= 0x1;        /* Clear(except for error) */
                    279: 
1.1.1.2 ! root      280:   /* Set error condition - NOTE this is incorrect in the FDC Doc's! */
1.1       root      281:   if (!bError)
                    282:     DMAStatus_ff8606rd |= 0x1;
                    283: 
1.1.1.2 ! root      284:   /* Set zero sector count */
1.1       root      285:   if (FDCSectorCountRegister!=0)
                    286:     DMAStatus_ff8606rd |= 0x2;
                    287: }
                    288: 
1.1.1.2 ! root      289: 
        !           290: /*-----------------------------------------------------------------------*/
1.1       root      291: /*
                    292:   Read DMA Status (RD 0xff8606)
                    293: */
                    294: long FDC_ReadDMAStatus(void)
                    295: {
                    296:  return (0xffff0000|DMAStatus_ff8606rd);
                    297: }
                    298: 
1.1.1.2 ! root      299: 
        !           300: /*-----------------------------------------------------------------------*/
1.1       root      301: /*
                    302: */
                    303: void FDC_UpdateDiscDrive(void)
                    304: {
                    305:   /* Set details for current selecte drive */
                    306:   nReadWriteDev = FDC_FindFloppyDrive();
                    307: 
                    308:   if (EmulationDrives[nReadWriteDev].bDiscInserted)
                    309:     Floppy_FindDiscDetails(EmulationDrives[nReadWriteDev].pBuffer,EmulationDrives[nReadWriteDev].nImageBytes,&nReadWriteSectorsPerTrack,NULL);
                    310: }
                    311: 
1.1.1.2 ! root      312: 
        !           313: /*-----------------------------------------------------------------------*/
1.1       root      314: /*
                    315:   When write to 0xff8606 (DMA Mode Control) check bit '8' toggle. This causes DMA status reset
                    316: */
                    317: void FDC_CheckForDMAStatusReset(void)
                    318: {
                    319:   /* Test for 'toggle' of _read/_write bit '8' */
                    320:   if ((DMAModeControl_ff8606wr_prev ^ DMAModeControl_ff8606wr)&0x0100)
                    321:     FDC_ResetDMAStatus();
                    322: }
                    323: 
1.1.1.2 ! root      324: 
        !           325: /*-----------------------------------------------------------------------*/
1.1       root      326: /*
                    327:   Set disc controller status (RD 0xff8604)
                    328: */
                    329: void FDC_SetDiscControllerStatus(void)
                    330: {
                    331:   /* Update disc */
                    332:   FDC_UpdateDiscDrive();
                    333: 
                    334:   /* Clear out to default */
                    335:   DiscControllerStatus_ff8604rd = 0;
                    336: 
                    337:   /* ONLY do this if we are running a Type I command */
                    338:   if ((FDCCommandRegister&0x80)==0) {          /* Type I - Restore,Seek,Step,Step-In,Step-Out */
                    339:     if (FDCTrackRegister==0)
                    340:       DiscControllerStatus_ff8604rd |= 0x4;    /* Bit 2 - Track Zero, '0' if head is NOT at zero */
                    341:   }
                    342: 
                    343:   /* If no disc inserted, tag as error */
                    344:   if (!EmulationDrives[nReadWriteDev].bDiscInserted)
                    345:     DiscControllerStatus_ff8604rd |= 0x10;     /* RNF - Record not found, ie no disc in drive */
                    346: }
                    347: 
1.1.1.2 ! root      348: 
        !           349: /*-----------------------------------------------------------------------*/
1.1       root      350: /*
                    351:   Return device for FDC, check PORTA bits 1,2(0=on,1=off)
                    352: */
                    353: int FDC_FindFloppyDrive(void)
                    354: {
                    355:   /* Check Drive A first */
                    356:   if ((PSGRegisters[PSG_REG_IO_PORTA]&0x2)==0)
1.1.1.2 ! root      357:     return(0);                    /* Device 0 (A:) */
1.1       root      358:   /* If off, check Drive B */
                    359:   if ((PSGRegisters[PSG_REG_IO_PORTA]&0x4)==0)
1.1.1.2 ! root      360:     return(1);                    /* Device 1 (B:) */
1.1       root      361: 
                    362:   /* None appear to be selected so default to Drive A */
1.1.1.2 ! root      363:   return(0);                      /* Device 0 (A:) */
1.1       root      364: }
                    365: 
1.1.1.2 ! root      366: 
        !           367: /*-----------------------------------------------------------------------*/
1.1       root      368: /*
                    369:   Acknowledge FDC interrupt
                    370: */
                    371: void FDC_AcknowledgeInterrupt(void)
                    372: {
1.1.1.2 ! root      373:   /* Acknowledge in MFP circuit, pass bit, enable, pending */
1.1       root      374:   MFP_InputOnChannel(MFP_FDCHDC_BIT,MFP_IERB,&MFP_IPRB);
                    375:   MFP_GPIP &= ~0x20;
                    376: }
                    377: 
1.1.1.2 ! root      378: 
        !           379: /*-----------------------------------------------------------------------*/
1.1       root      380: /*
                    381:   Copy parameters for disc sector/s read/write
                    382: */
                    383: void FDC_SetReadWriteParameters(int nSectors)
                    384: {
1.1.1.2 ! root      385:   /* Copy read/write details so we can modify them */
1.1       root      386:   nReadWriteTrack = FDCTrackRegister;
                    387:   nReadWriteSector = FDCSectorRegister;
                    388:   nReadWriteSide = (~PSGRegisters[PSG_REG_IO_PORTA]) & 0x01;
                    389:   nReadWriteSectors = nSectors;
1.1.1.2 ! root      390:   /* Update disc */
1.1       root      391:   FDC_UpdateDiscDrive();
                    392: }
                    393: 
1.1.1.2 ! root      394: 
        !           395: /*-----------------------------------------------------------------------*/
1.1       root      396: /*
                    397:   Update floppy drive on each HBL(approx' 512 cycles)
                    398: */
                    399: void FDC_UpdateHBL(void)
                    400: {
1.1.1.2 ! root      401:   /* Do we have a DMA ready to copy? */
1.1       root      402:   if (bDMAWaiting) {
1.1.1.2 ! root      403:     /* Yes, copy it */
1.1       root      404:     FDC_DMADataFromFloppy();
1.1.1.2 ! root      405:     /* Signal done */
1.1       root      406:     bDMAWaiting = FALSE;
                    407:   }
                    408: 
1.1.1.2 ! root      409:   /* Update drive motor */
1.1       root      410:   FDC_UpdateMotor();
                    411: 
1.1.1.2 ! root      412:   /* Is FDC active? */
1.1       root      413:   if (FDCEmulationCommand!=FDCEMU_CMD_NULL) {
1.1.1.2 ! root      414:     /* Which command are we running? */
1.1       root      415:     switch(FDCEmulationCommand) {
                    416:       case FDCEMU_CMD_RESTORE:
                    417:         FDC_UpdateRestoreCmd();
                    418:         break;
                    419:       case FDCEMU_CMD_SEEK:
                    420:         FDC_UpdateSeekCmd();
                    421:         break;
                    422:       case FDCEMU_CMD_STEP:
                    423:         FDC_UpdateStepCmd();
                    424:         break;
                    425:       case FDCEMU_CMD_STEPIN:
                    426:         FDC_UpdateStepInCmd();
                    427:         break;
                    428:       case FDCEMU_CMD_STEPOUT:
                    429:         FDC_UpdateStepOutCmd();
                    430:         break;
                    431: 
                    432:       case FDCEMU_CMD_READSECTORS:
                    433:       case FDCEMU_CMD_READMULTIPLESECTORS:
                    434:         FDC_UpdateReadSectorsCmd();
                    435:         break;
                    436:       case FDCEMU_CMD_WRITESECTORS:
                    437:       case FDCEMU_CMD_WRITEMULTIPLESECTORS:
                    438:         FDC_UpdateWriteSectorsCmd();
                    439:         break;
                    440:     }
                    441: 
1.1.1.2 ! root      442:     /* Set disc controller status (RD 0xff8604) */
1.1       root      443:     FDC_SetDiscControllerStatus();
                    444:   }
                    445: }
                    446: 
1.1.1.2 ! root      447: 
        !           448: /*-----------------------------------------------------------------------*/
1.1       root      449: /*
                    450:   Run 'RESTORE' command
                    451: */
                    452: void FDC_UpdateRestoreCmd(void)
                    453: {
1.1.1.2 ! root      454:   /* Which command is running? */
1.1       root      455:   switch (FDCEmulationRunning) {
                    456:     case FDCEMU_RUN_RESTORE_SEEKTOTRACKZERO:
1.1.1.2 ! root      457:       /* Are we at track zero? */
1.1       root      458:       if (FDCTrackRegister>0)
                    459:         FDCTrackRegister--;             /* Move towards track zero */
                    460:       else {
                    461:         FDCTrackRegister = 0;           /* We're there */
                    462:         FDCEmulationRunning = FDCEMU_RUN_RESTORE_COMPLETE;
                    463:       }
                    464:       break;
                    465:     case FDCEMU_RUN_RESTORE_COMPLETE:
1.1.1.2 ! root      466:       /* Acknowledge interrupt, move along there's nothing more to see */
1.1       root      467:       FDC_AcknowledgeInterrupt();
1.1.1.2 ! root      468:       /* Set error */
1.1       root      469:       FDC_SetDMAStatus(FALSE);          /* No DMA error */
1.1.1.2 ! root      470:       /* Done */
1.1       root      471:       FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 ! root      472:       /* Turn motor off */
1.1       root      473:       FDC_TurnMotorOff();
                    474:       break;
                    475:   }
                    476: }
                    477: 
1.1.1.2 ! root      478: 
        !           479: /*-----------------------------------------------------------------------*/
1.1       root      480: /*
                    481:   Run 'SEEK' command
                    482: */
                    483: void FDC_UpdateSeekCmd(void)
                    484: {
1.1.1.2 ! root      485:   /* Which command is running? */
1.1       root      486:   switch (FDCEmulationRunning) {
                    487:     case FDCEMU_RUN_SEEK_TOTRACK:
1.1.1.2 ! root      488:       /* Are we at the selected track? */
1.1       root      489:       if (FDCTrackRegister==FDCDataRegister)
                    490:         FDCEmulationRunning = FDCEMU_RUN_SEEK_COMPLETE;
                    491:       else {
1.1.1.2 ! root      492:         /* No, seek towards track */
1.1       root      493:         if (FDCDataRegister<FDCTrackRegister)
                    494:           FDCTrackRegister--;
                    495:         else
                    496:           FDCTrackRegister++;
                    497:       }
                    498:       break;
                    499:     case FDCEMU_RUN_SEEK_COMPLETE:
1.1.1.2 ! root      500:       /* Acknowledge interrupt, move along there's nothing more to see */
1.1       root      501:       FDC_AcknowledgeInterrupt();
1.1.1.2 ! root      502:       /* Set error */
        !           503:       FDC_SetDMAStatus(FALSE);          /* No DMA error */
        !           504:       /* Done */
1.1       root      505:       FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 ! root      506:       /* Turn motor off */
1.1       root      507:       FDC_TurnMotorOff();
                    508:       break;
                    509:   }
                    510: }
                    511: 
1.1.1.2 ! root      512: 
        !           513: /*-----------------------------------------------------------------------*/
1.1       root      514: /*
                    515:   Run 'STEP' command
                    516: */
                    517: void FDC_UpdateStepCmd(void)
                    518: {
1.1.1.2 ! root      519:   /* Which command is running? */
1.1       root      520:   switch (FDCEmulationRunning) {
                    521:     case FDCEMU_RUN_STEP_ONCE:
1.1.1.2 ! root      522:       /* Move head by one track in same direction as last step */
1.1       root      523:       FDCTrackRegister += FDCStepDirection;
                    524:       if (FDCTrackRegister<0)             /* Limit to stop */
                    525:         FDCTrackRegister = 0;
                    526: 
                    527:       FDCEmulationRunning = FDCEMU_RUN_STEP_COMPLETE;
                    528:       break;
                    529:     case FDCEMU_RUN_STEP_COMPLETE:
1.1.1.2 ! root      530:       /* Acknowledge interrupt, move along there's nothing more to see */
1.1       root      531:       FDC_AcknowledgeInterrupt();
1.1.1.2 ! root      532:       /* Set error */
1.1       root      533:       FDC_SetDMAStatus(FALSE);            /* No DMA error */
1.1.1.2 ! root      534:       /* Done */
1.1       root      535:       FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 ! root      536:       /* Turn motor off */
1.1       root      537:       FDC_TurnMotorOff();
                    538:       break;
                    539:   }
                    540: }
                    541: 
1.1.1.2 ! root      542: 
        !           543: /*-----------------------------------------------------------------------*/
1.1       root      544: /*
                    545:   Run 'STEP IN' command
                    546: */
                    547: void FDC_UpdateStepInCmd(void)
                    548: {
1.1.1.2 ! root      549:   /* Which command is running? */
1.1       root      550:   switch (FDCEmulationRunning) {
                    551:     case FDCEMU_RUN_STEPIN_ONCE:
                    552:       FDCTrackRegister++;
                    553: 
                    554:       FDCEmulationRunning = FDCEMU_RUN_STEPIN_COMPLETE;
                    555:       break;
                    556:     case FDCEMU_RUN_STEPIN_COMPLETE:
1.1.1.2 ! root      557:       /* Acknowledge interrupt, move along there's nothing more to see */
1.1       root      558:       FDC_AcknowledgeInterrupt();
1.1.1.2 ! root      559:       /* Set error */
1.1       root      560:       FDC_SetDMAStatus(FALSE);            /* No DMA error */
1.1.1.2 ! root      561:       /* Done */
1.1       root      562:       FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 ! root      563:       /* Turn motor off */
1.1       root      564:       FDC_TurnMotorOff();
                    565:       break;
                    566:   }
                    567: }
                    568: 
1.1.1.2 ! root      569: 
        !           570: /*-----------------------------------------------------------------------*/
1.1       root      571: /*
                    572:   Run 'STEP OUT' command
                    573: */
                    574: void FDC_UpdateStepOutCmd(void)
                    575: {
1.1.1.2 ! root      576:   /* Which command is running? */
1.1       root      577:   switch (FDCEmulationRunning) {
                    578:     case FDCEMU_RUN_STEPOUT_ONCE:
                    579:       FDCTrackRegister--;
1.1.1.2 ! root      580:       if (FDCTrackRegister<0)             /* Limit to stop */
1.1       root      581:         FDCTrackRegister = 0;
                    582: 
                    583:       FDCEmulationRunning = FDCEMU_RUN_STEPOUT_COMPLETE;
                    584:       break;
                    585:     case FDCEMU_RUN_STEPOUT_COMPLETE:
1.1.1.2 ! root      586:       /* Acknowledge interrupt, move along there's nothing more to see */
1.1       root      587:       FDC_AcknowledgeInterrupt();
1.1.1.2 ! root      588:       /* Set error */
        !           589:       FDC_SetDMAStatus(FALSE);            /* No DMA error */
        !           590:       /* Done */
1.1       root      591:       FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 ! root      592:       /* Turn motor off */
1.1       root      593:       FDC_TurnMotorOff();
                    594:       break;
                    595:   }
                    596: }
                    597: 
1.1.1.2 ! root      598: 
        !           599: /*-----------------------------------------------------------------------*/
1.1       root      600: /*
                    601:   Run 'READ SECTOR/S' command
                    602: */
                    603: void FDC_UpdateReadSectorsCmd(void)
                    604: {
1.1.1.2 ! root      605:   /* Which command is running? */
1.1       root      606:   switch (FDCEmulationRunning) {
                    607:     case FDCEMU_RUN_READSECTORS_READDATA:
1.1.1.2 ! root      608:       /* Read in a sector */
1.1       root      609:       if (FDC_ReadSectorFromFloppy()) {     /* Read a single sector through DMA */
                    610:         FDCSectorCountRegister--;           /* Decrement FDCSectorCount */
                    611:         if (FDCSectorCountRegister<=0)
                    612:           FDCSectorCountRegister = 0;
                    613: 
1.1.1.2 ! root      614:         /* Have we finished? */
1.1       root      615:         nReadWriteSectors--;
                    616:         if (nReadWriteSectors<=0)
                    617:           FDCEmulationRunning = FDCEMU_RUN_READSECTORS_COMPLETE;
                    618: 
                    619:         bDMAWaiting = TRUE;
                    620:       }
                    621:       else {
1.1.1.2 ! root      622:         /* Acknowledge interrupt, move along there's nothing more to see */
1.1       root      623:         FDC_AcknowledgeInterrupt();
1.1.1.2 ! root      624:         /* Set error */
1.1       root      625:         FDC_SetDMAStatus(TRUE);             /* DMA error */
1.1.1.2 ! root      626:         /* Done */
1.1       root      627:         FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 ! root      628:         /* Turn motor off */
1.1       root      629:         FDC_TurnMotorOff();
                    630:       }
                    631:       break;
                    632:     case FDCEMU_RUN_READSECTORS_COMPLETE:
1.1.1.2 ! root      633:       /* Acknowledge interrupt, move along there's nothing more to see */
1.1       root      634:       FDC_AcknowledgeInterrupt();
1.1.1.2 ! root      635:       /* Set error */
1.1       root      636:       FDC_SetDMAStatus(FALSE);              /* No DMA error */
1.1.1.2 ! root      637:       /* Done */
1.1       root      638:       FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 ! root      639:       /* Turn motor off */
1.1       root      640:       FDC_TurnMotorOff();
                    641:       break;
                    642:   }
                    643: }
                    644: 
1.1.1.2 ! root      645: 
        !           646: /*-----------------------------------------------------------------------*/
1.1       root      647: /*
                    648:   Run 'WRITE SECTOR/S' command
                    649: */
                    650: void FDC_UpdateWriteSectorsCmd(void)
                    651: {
1.1.1.2 ! root      652:   /* Which command is running? */
1.1       root      653:   switch (FDCEmulationRunning) {
                    654:     case FDCEMU_RUN_WRITESECTORS_WRITEDATA:
1.1.1.2 ! root      655:       /* Write out a sector */
1.1       root      656:       if (FDC_WriteSectorFromFloppy()) {    /* Write a single sector through DMA */
1.1.1.2 ! root      657:         /* Decrement FDCsector count */
1.1       root      658:         FDCSectorCountRegister--;           /* Decrement FDCSectorCount */
                    659:         if (FDCSectorCountRegister<=0)
                    660:           FDCSectorCountRegister = 0;
                    661: 
1.1.1.2 ! root      662:         /* Have we finished? */
1.1       root      663:         nReadWriteSectors--;
                    664:         if (nReadWriteSectors<=0)
                    665:           FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_COMPLETE;
                    666: 
1.1.1.2 ! root      667:         /* Update DMA pointer */
1.1       root      668:         FDC_WriteDMAAddress(FDC_ReadDMAAddress()+NUMBYTESPERSECTOR);
                    669:       }
                    670:       else {
1.1.1.2 ! root      671:         /* Acknowledge interrupt, move along there's nothing more to see */
1.1       root      672:         FDC_AcknowledgeInterrupt();
1.1.1.2 ! root      673:         /* Set error */
1.1       root      674:         FDC_SetDMAStatus(TRUE);             /* DMA error */
1.1.1.2 ! root      675:         /* Done */
1.1       root      676:         FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 ! root      677:         /* Turn motor off */
1.1       root      678:         FDC_TurnMotorOff();
                    679:       }
                    680:       break;
                    681:     case FDCEMU_RUN_WRITESECTORS_COMPLETE:
1.1.1.2 ! root      682:       /* Acknowledge interrupt, move along there's nothing more to see */
1.1       root      683:       FDC_AcknowledgeInterrupt();
1.1.1.2 ! root      684:       /* Set error */
1.1       root      685:       FDC_SetDMAStatus(FALSE);              /* No DMA error */
1.1.1.2 ! root      686:       /* Done */
1.1       root      687:       FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 ! root      688:       /* Turn motor off */
1.1       root      689:       FDC_TurnMotorOff();
                    690:       break;
                    691:   }
                    692: }
                    693: 
1.1.1.2 ! root      694: 
        !           695: /*-----------------------------------------------------------------------*/
1.1       root      696: /*
                    697:   Type I Commands
                    698: 
                    699:   Restore, Seek, Step, Step-In and Step-Out
                    700: */
                    701: 
1.1.1.2 ! root      702: 
        !           703: /*-----------------------------------------------------------------------*/
1.1       root      704: void FDC_TypeI_Restore(void)
                    705: {
1.1.1.2 ! root      706:   /* Set emulation to seek to track zero */
1.1       root      707:   FDCEmulationCommand = FDCEMU_CMD_RESTORE;
                    708:   FDCEmulationRunning = FDCEMU_RUN_RESTORE_SEEKTOTRACKZERO;
                    709: 
                    710:   FDC_SetDiscControllerStatus();
                    711: }
                    712: 
1.1.1.2 ! root      713: 
        !           714: /*-----------------------------------------------------------------------*/
1.1       root      715: void FDC_TypeI_Seek(void)
                    716: {
1.1.1.2 ! root      717:   /* Set emulation to seek to chosen track */
1.1       root      718:   FDCEmulationCommand = FDCEMU_CMD_SEEK;
                    719:   FDCEmulationRunning = FDCEMU_RUN_SEEK_TOTRACK;
                    720: 
                    721:   FDC_SetDiscControllerStatus();
                    722: }
                    723: 
1.1.1.2 ! root      724: 
        !           725: /*-----------------------------------------------------------------------*/
1.1       root      726: void FDC_TypeI_Step(void)
                    727: {
1.1.1.2 ! root      728:   /* Set emulation to step(same direction as last seek executed, eg 'FDCStepDirection') */
1.1       root      729:   FDCEmulationCommand = FDCEMU_CMD_STEP;
                    730:   FDCEmulationRunning = FDCEMU_RUN_STEP_ONCE;
                    731: 
                    732:   FDC_SetDiscControllerStatus();
                    733: }
                    734: 
1.1.1.2 ! root      735: 
        !           736: /*-----------------------------------------------------------------------*/
1.1       root      737: void FDC_TypeI_StepIn(void)
                    738: {
1.1.1.2 ! root      739:   /* Set emulation to step in(Set 'FDCStepDirection') */
1.1       root      740:   FDCEmulationCommand = FDCEMU_CMD_STEPIN;
                    741:   FDCEmulationRunning = FDCEMU_RUN_STEPIN_ONCE;
1.1.1.2 ! root      742:   FDCStepDirection = 1;                 /* Increment track*/
1.1       root      743: 
                    744:   FDC_SetDiscControllerStatus();
                    745: }
                    746: 
1.1.1.2 ! root      747: 
        !           748: /*-----------------------------------------------------------------------*/
1.1       root      749: void FDC_TypeI_StepOut(void)
                    750: {
1.1.1.2 ! root      751:   /* Set emulation to step out(Set 'FDCStepDirection') */
1.1       root      752:   FDCEmulationCommand = FDCEMU_CMD_STEPOUT;
                    753:   FDCEmulationRunning = FDCEMU_RUN_STEPOUT_ONCE;
1.1.1.2 ! root      754:   FDCStepDirection = -1;                /* Decrement track */
1.1       root      755: 
                    756:   FDC_SetDiscControllerStatus();
                    757: }
                    758: 
1.1.1.2 ! root      759: 
        !           760: /*-----------------------------------------------------------------------*/
1.1       root      761: /*
                    762:   Type II Commands
                    763: 
                    764:   Read Sector, Read Multiple Sectors, Write Sector, Write Multiple Sectors
                    765: */
                    766: 
1.1.1.2 ! root      767: 
        !           768: /*-----------------------------------------------------------------------*/
1.1       root      769: void FDC_TypeII_ReadSector(void)
                    770: {
1.1.1.2 ! root      771:   /* Set emulation to read a single sector */
1.1       root      772:   FDCEmulationCommand = FDCEMU_CMD_READSECTORS;
                    773:   FDCEmulationRunning = FDCEMU_RUN_READSECTORS_READDATA;
1.1.1.2 ! root      774:   /* Set reading parameters */
        !           775:   FDC_SetReadWriteParameters(1);        /* Read in a single sector */
1.1       root      776: 
                    777:   FDC_SetDiscControllerStatus();
                    778: }
                    779: 
1.1.1.2 ! root      780: 
        !           781: /*-----------------------------------------------------------------------*/
1.1       root      782: void FDC_TypeII_ReadMultipleSectors(void)
                    783: {
1.1.1.2 ! root      784:   /* Set emulation to read sectors */
1.1       root      785:   FDCEmulationCommand = FDCEMU_CMD_READMULTIPLESECTORS;
                    786:   FDCEmulationRunning = FDCEMU_RUN_READSECTORS_READDATA;
1.1.1.2 ! root      787:   /* Set reading parameters */
        !           788:   FDC_SetReadWriteParameters(FDCSectorCountRegister);   /* Read multiple sectors */
1.1       root      789: 
                    790:   FDC_SetDiscControllerStatus();
                    791: }
                    792: 
1.1.1.2 ! root      793: 
        !           794: /*-----------------------------------------------------------------------*/
1.1       root      795: void FDC_TypeII_WriteSector(void)
                    796: {
1.1.1.2 ! root      797:   /* Set emulation to write a single sector */
1.1       root      798:   FDCEmulationCommand = FDCEMU_CMD_WRITESECTORS;
                    799:   FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_WRITEDATA;
1.1.1.2 ! root      800:   /* Set writing parameters */
        !           801:   FDC_SetReadWriteParameters(1);                        /* Write out a single sector */
1.1       root      802: 
                    803:   FDC_SetDiscControllerStatus();
                    804: }
                    805: 
1.1.1.2 ! root      806: 
        !           807: /*-----------------------------------------------------------------------*/
1.1       root      808: void FDC_TypeII_WriteMultipleSectors(void)
                    809: {
1.1.1.2 ! root      810:   /* Set emulation to write sectors */
1.1       root      811:   FDCEmulationCommand = FDCEMU_CMD_WRITEMULTIPLESECTORS;
                    812:   FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_WRITEDATA;
1.1.1.2 ! root      813:   /* Set witing parameters */
        !           814:   FDC_SetReadWriteParameters(FDCSectorCountRegister);   /* Write multiple sectors */
1.1       root      815: 
                    816:   FDC_SetDiscControllerStatus();
                    817: }
                    818: 
1.1.1.2 ! root      819: 
        !           820: /*-----------------------------------------------------------------------*/
1.1       root      821: /*
                    822:   Type III Commands
                    823: 
                    824:   Read Address, Read Track, Write Track
                    825: */
                    826: 
1.1.1.2 ! root      827: 
        !           828: /*-----------------------------------------------------------------------*/
1.1       root      829: void FDC_TypeIII_ReadAddress(void)
                    830: {
                    831: }
                    832: 
1.1.1.2 ! root      833: 
        !           834: /*-----------------------------------------------------------------------*/
1.1       root      835: void FDC_TypeIII_ReadTrack(void)
                    836: {
1.1.1.2 ! root      837:   /* Set emulation to read a single track */
1.1       root      838:   FDCEmulationCommand = FDCEMU_CMD_READSECTORS;
                    839:   FDCEmulationRunning = FDCEMU_RUN_READSECTORS_READDATA;
1.1.1.2 ! root      840:   /* Set reading parameters */
        !           841:   FDC_SetReadWriteParameters(nReadWriteSectorsPerTrack);  /* Read whole track */
1.1       root      842: 
                    843:   FDC_SetDiscControllerStatus();
                    844: }
                    845: 
1.1.1.2 ! root      846: 
        !           847: /*-----------------------------------------------------------------------*/
1.1       root      848: void FDC_TypeIII_WriteTrack(void)
                    849: {
1.1.1.2 ! root      850:   /* Set emulation to write a single track */
1.1       root      851:   FDCEmulationCommand = FDCEMU_CMD_WRITESECTORS;
                    852:   FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_WRITEDATA;
1.1.1.2 ! root      853:   /* Set writing parameters */
        !           854:   FDC_SetReadWriteParameters(nReadWriteSectorsPerTrack);  /* Write whole track */
1.1       root      855: 
                    856:   FDC_SetDiscControllerStatus();
                    857: }
                    858: 
1.1.1.2 ! root      859: 
        !           860: /*-----------------------------------------------------------------------*/
1.1       root      861: /*
                    862:   Type IV Commands
                    863: 
                    864:   Force Interrupt
                    865: */
                    866: 
1.1.1.2 ! root      867: 
        !           868: /*-----------------------------------------------------------------------*/
1.1       root      869: void FDC_TypeIV_ForceInterrupt(BOOL bCauseCPUInterrupt)
                    870: {
1.1.1.2 ! root      871:   /* Acknowledge interrupt, move along there's nothing more to see */
1.1       root      872:   if (bCauseCPUInterrupt)
                    873:     FDC_AcknowledgeInterrupt();
                    874: 
1.1.1.2 ! root      875:   /* Reset FDC */
1.1       root      876:   FDCEmulationCommand = FDCEMU_CMD_NULL;
                    877:   FDCEmulationRunning = FDCEMU_RUN_NULL;
                    878: }
                    879: 
1.1.1.2 ! root      880: 
        !           881: /*-----------------------------------------------------------------------*/
1.1       root      882: /*
                    883:   Execute Type I commands
                    884: */
                    885: void FDC_ExecuteTypeICommands(void)
                    886: {
                    887:   MFP_GPIP |= 0x20;
                    888: 
1.1.1.2 ! root      889:   /* Check Type I Command */
1.1       root      890:   switch(FDCCommandRegister&0xf0) {
1.1.1.2 ! root      891:     case 0x00:            /* Restore */
1.1       root      892:       FDC_TypeI_Restore();
                    893:       break;
1.1.1.2 ! root      894:     case 0x10:            /* Seek */
1.1       root      895:       FDC_TypeI_Seek();
                    896:       break;
1.1.1.2 ! root      897:     case 0x20:            /* Step */
1.1       root      898:     case 0x30:
                    899:       FDC_TypeI_Step();
                    900:       break;
1.1.1.2 ! root      901:     case 0x40:            /* Step-In */
1.1       root      902:     case 0x50:
                    903:       FDC_TypeI_StepIn();
                    904:       break;
1.1.1.2 ! root      905:     case 0x60:            /* Step-Out */
1.1       root      906:     case 0x70:
                    907:       FDC_TypeI_StepOut();
                    908:       break;
                    909:   }
                    910: 
1.1.1.2 ! root      911:   /* Signal motor on as we need to execute command */
1.1       root      912:   FDC_TurnMotorOn();
                    913: }
                    914: 
1.1.1.2 ! root      915: 
        !           916: /*-----------------------------------------------------------------------*/
1.1       root      917: /*
                    918:   Execute Type II commands
                    919: */
                    920: void FDC_ExecuteTypeIICommands(void)
                    921: {
                    922:   MFP_GPIP |= 0x20;
                    923: 
1.1.1.2 ! root      924:   /* Check Type II Command */
1.1       root      925:   switch(FDCCommandRegister&0xf0) {
1.1.1.2 ! root      926:     case 0x80:            /* Read Sector */
1.1       root      927:       FDC_TypeII_ReadSector();
                    928:       break;
1.1.1.2 ! root      929:     case 0x90:            /* Read Sectors */
1.1       root      930:       FDC_TypeII_ReadMultipleSectors();
                    931:       break;
1.1.1.2 ! root      932:     case 0xa0:            /* Write Sector */
1.1       root      933:       FDC_TypeII_WriteSector();
                    934:       break;
1.1.1.2 ! root      935:     case 0xb0:            /* Write Sectors */
1.1       root      936:       FDC_TypeII_WriteMultipleSectors();
                    937:       break;
                    938:   }
                    939: 
1.1.1.2 ! root      940:   /* Signal motor on as we need to execute command */
1.1       root      941:   FDC_TurnMotorOn();
                    942: }
                    943: 
1.1.1.2 ! root      944: 
        !           945: /*-----------------------------------------------------------------------*/
1.1       root      946: /*
                    947:   Execute Type III commands
                    948: */
                    949: void FDC_ExecuteTypeIIICommands(void)
                    950: {
                    951:   MFP_GPIP |= 0x20;
                    952: 
1.1.1.2 ! root      953:   /* Check Type III Command */
1.1       root      954:   switch(FDCCommandRegister&0xf0) {
1.1.1.2 ! root      955:     case 0xc0:          /* Read Address */
1.1       root      956:       FDC_TypeIII_ReadAddress();
                    957:       break;
1.1.1.2 ! root      958:     case 0xe0:          /* Read Track */
1.1       root      959:       FDC_TypeIII_ReadTrack();
                    960:       break;
1.1.1.2 ! root      961:     case 0xf0:          /* Write Track */
1.1       root      962:       FDC_TypeIII_WriteTrack();
                    963:       break;
                    964:   }
                    965: 
1.1.1.2 ! root      966:   /* Signal motor on as we need to execute command */
1.1       root      967:   FDC_TurnMotorOn();
                    968: }
                    969: 
1.1.1.2 ! root      970: 
        !           971: /*-----------------------------------------------------------------------*/
1.1       root      972: /*
                    973:   Execute Type IV commands
                    974: */
                    975: void FDC_ExecuteTypeIVCommands(void)
                    976: {
                    977:   if (FDCCommandRegister!=0xD8)         /* Is an 'immediate interrupt command'? don't reset interrupt */
                    978:     MFP_GPIP |= 0x20;
                    979: 
1.1.1.2 ! root      980:   /* Check Type IV Command */
1.1       root      981:   if ((FDCCommandRegister&0x0c)==0)     /* I3 and I2 are clear? If so we don't need a CPU interrupt */
                    982:     FDC_TypeIV_ForceInterrupt(FALSE);   /* Force Interrupt - no interrupt */
                    983:   else
                    984:     FDC_TypeIV_ForceInterrupt(TRUE);    /* Force Interrupt */
                    985: }
                    986: 
1.1.1.2 ! root      987: 
        !           988: /*-----------------------------------------------------------------------*/
1.1       root      989: /*
                    990:   Find FDC command type and execute
                    991: */
                    992: void FDC_ExecuteCommand(void)
                    993: {
                    994:   /* Check type of command and execute */
                    995:   if ((FDCCommandRegister&0x80)==0)           /* Type I - Restore,Seek,Step,Step-In,Step-Out */
                    996:     FDC_ExecuteTypeICommands();
                    997:   else if ((FDCCommandRegister&0x40)==0)      /* Type II - Read Sector, Write Sector */
                    998:     FDC_ExecuteTypeIICommands();
                    999:   else if ((FDCCommandRegister&0xf0)!=0xd0)   /* Type III - Read Address, Read Track, Write Track */
                   1000:     FDC_ExecuteTypeIIICommands();
1.1.1.2 ! root     1001:   else                                        /* Type IV - Force Interrupt */
1.1       root     1002:     FDC_ExecuteTypeIVCommands();
                   1003: }
                   1004: 
1.1.1.2 ! root     1005: 
        !          1006: /*-----------------------------------------------------------------------*/
1.1       root     1007: /*
                   1008:   Write to SectorCount register (WR 0xff8604)
                   1009: */
                   1010: void FDC_WriteSectorCountRegister(void)
                   1011: {
                   1012:   FDCSectorCountRegister = DiscControllerWord_ff8604wr;
                   1013: }
                   1014: 
1.1.1.2 ! root     1015: 
        !          1016: /*-----------------------------------------------------------------------*/
1.1       root     1017: /*
                   1018:   Write to Command register (WR 0xff8604)
                   1019: */
                   1020: void FDC_WriteCommandRegister(void)
                   1021: {
                   1022:   FDCCommandRegister = DiscControllerWord_ff8604wr;
                   1023:   /* And execute */
                   1024:   FDC_ExecuteCommand();
                   1025: }
                   1026: 
1.1.1.2 ! root     1027: 
        !          1028: /*-----------------------------------------------------------------------*/
1.1       root     1029: /*
                   1030:   Write to Track register (WR 0xff8604)
                   1031: */
                   1032: void FDC_WriteTrackRegister(void)
                   1033: {
                   1034:   FDCTrackRegister = DiscControllerWord_ff8604wr;    /* 0...79 */
                   1035: }
                   1036: 
1.1.1.2 ! root     1037: 
        !          1038: /*-----------------------------------------------------------------------*/
1.1       root     1039: /*
                   1040:   Write to Track register (WR 0xff8604)
                   1041: */
                   1042: void FDC_WriteSectorRegister(void)
                   1043: {
                   1044:   FDCSectorRegister = DiscControllerWord_ff8604wr;  /* 1,2,3..... */
                   1045: }
                   1046: 
1.1.1.2 ! root     1047: 
        !          1048: /*-----------------------------------------------------------------------*/
1.1       root     1049: /*
                   1050:   Write to Data register (WR 0xff8604)
                   1051: */
                   1052: void FDC_WriteDataRegister(void)
                   1053: {
                   1054:   FDCDataRegister = DiscControllerWord_ff8604wr;
                   1055: }
                   1056: 
1.1.1.2 ! root     1057: 
        !          1058: /*-----------------------------------------------------------------------*/
1.1       root     1059: /*
                   1060:   Store byte in FDC registers, when write to 0xff8604
                   1061: */
                   1062: void FDC_WriteDiscControllerByte(void)
                   1063: {
1.1.1.2 ! root     1064:   /* Are we trying to set the SectorCount? */
1.1       root     1065:   if (DMAModeControl_ff8606wr&0x10)         /* Bit 4 */
                   1066:     FDC_WriteSectorCountRegister();
1.1.1.2 ! root     1067:   else {  /* Write to FDC registers */
1.1       root     1068:     switch(DMAModeControl_ff8606wr&0x6) {   /* Bits 1,2 (A1,A0) */
                   1069:       case 0x0:                             /* 0 0 - Command register */
                   1070:         FDC_WriteCommandRegister();
                   1071:         break;
                   1072:       case 0x2:                             /* 0 1 - Track register */
                   1073:         FDC_WriteTrackRegister();
                   1074:         break;
                   1075:       case 0x4:                             /* 1 0 - Sector register */
                   1076:         FDC_WriteSectorRegister();
                   1077:         break;
                   1078:       case 0x6:                             /* 1 1 - Data register */
                   1079:         FDC_WriteDataRegister();
                   1080:         break;
                   1081:     }
                   1082:   }
                   1083: }
                   1084: 
1.1.1.2 ! root     1085: 
        !          1086: /*-----------------------------------------------------------------------*/
1.1       root     1087: /*
                   1088:   Read Status/FDC registers, when read from 0xff8604
                   1089:   Return 'DiscControllerByte'
                   1090: */
                   1091: void FDC_ReadDiscControllerStatusByte(void)
                   1092: {
                   1093:   switch(DMAModeControl_ff8606wr&0x6) {     /* Bits 1,2 (A1,A0) */
                   1094:     case 0x0:                               /* 0 0 - Status register */
                   1095:       DiscControllerByte = DiscControllerStatus_ff8604rd;
                   1096:       if (bMotorOn)
                   1097:         DiscControllerByte |= 0x80;
                   1098: 
                   1099:       /* Reset FDC GPIP */
                   1100:       MFP_GPIP |= 0x20;
                   1101:       break;
                   1102:     case 0x2:                               /* 0 1 - Track register */
                   1103:       DiscControllerByte = FDCTrackRegister;
                   1104:       break;
                   1105:     case 0x4:                               /* 1 0 - Sector register */
                   1106:       DiscControllerByte = FDCSectorRegister;
                   1107:       break;
                   1108:     case 0x6:                               /* 1 1 - Data register */
                   1109:       DiscControllerByte = FDCDataRegister;
                   1110:       break;
                   1111:   }
                   1112: }
                   1113: 
1.1.1.2 ! root     1114: 
        !          1115: /*-----------------------------------------------------------------------*/
1.1       root     1116: /*
                   1117:   Read DMA address from ST's RAM(always up-to-date)
                   1118: */
                   1119: unsigned long FDC_ReadDMAAddress(void)
                   1120: {
                   1121:   unsigned long Address;
                   1122: 
                   1123:   /* Build up 24-bit address from hardware registers */
                   1124:   Address = ((unsigned long)STMemory_ReadByte(0xff8609)<<16) | ((unsigned long)STMemory_ReadByte(0xff860b)<<8) | (unsigned long)STMemory_ReadByte(0xff860d);
                   1125: 
                   1126:   return(Address);
                   1127: }
                   1128: 
1.1.1.2 ! root     1129: 
        !          1130: /*-----------------------------------------------------------------------*/
1.1       root     1131: /*
                   1132:   Write DMA address to ST's RAM(always keep up-to-date)
                   1133: */
                   1134: void FDC_WriteDMAAddress(unsigned long Address)
                   1135: {
                   1136:   /* Store as 24-bit address */
                   1137:   STMemory_WriteByte(0xff8609,Address>>16);
                   1138:   STMemory_WriteByte(0xff860b,Address>>8);
                   1139:   STMemory_WriteByte(0xff860d,Address);
                   1140: }
                   1141: 
1.1.1.2 ! root     1142: 
        !          1143: /*-----------------------------------------------------------------------*/
1.1       root     1144: /*
                   1145:   Read sector from floppy drive into workspace
                   1146:   We copy the bytes in chunks to simulate reading of the floppy using DMA
                   1147: */
                   1148: BOOL FDC_ReadSectorFromFloppy(void)
                   1149: {
1.1.1.2 ! root     1150:   /* Copy in 1 sector to our workspace */
1.1       root     1151:   if (Floppy_ReadSectors(nReadWriteDev,(char *)DMASectorWorkSpace,nReadWriteSector,nReadWriteTrack,nReadWriteSide,1,NULL)) {
1.1.1.2 ! root     1152:     /* Update reading/writing parameters */
1.1       root     1153:     nReadWriteSector++;
1.1.1.2 ! root     1154:     if (nReadWriteSector>nReadWriteSectorsPerTrack) {  /* Advance into next track? */
1.1       root     1155:       nReadWriteSector = 1;
                   1156:       nReadWriteTrack++;
                   1157:     }
                   1158:     return(TRUE);
                   1159:   }
                   1160: 
1.1.1.2 ! root     1161:   /* Failed */
1.1       root     1162:   return(FALSE);
                   1163: }
                   1164: 
1.1.1.2 ! root     1165: 
        !          1166: /*-----------------------------------------------------------------------*/
1.1       root     1167: /*
                   1168:   Write sector from workspace to floppy drive
                   1169:   We copy the bytes in chunks to simulate writing of the floppy using DMA
                   1170: */
                   1171: BOOL FDC_WriteSectorFromFloppy(void)
                   1172: {
                   1173:   unsigned long Address;
                   1174: 
1.1.1.2 ! root     1175:   /* Get DMA address */
1.1       root     1176:   Address = FDC_ReadDMAAddress();
                   1177: 
1.1.1.2 ! root     1178:   /* Write out 1 sector from our workspace */
1.1       root     1179:   if (Floppy_WriteSectors(nReadWriteDev,(char *)((unsigned long)STRam+Address),nReadWriteSector,nReadWriteTrack,nReadWriteSide,1,NULL)) {
1.1.1.2 ! root     1180:     /* Update reading/writing parameters */
1.1       root     1181:     nReadWriteSector++;
1.1.1.2 ! root     1182:     if (nReadWriteSector>nReadWriteSectorsPerTrack) {  /* Advance to next track? */
1.1       root     1183:       nReadWriteSector = 1;
                   1184:       nReadWriteTrack++;
                   1185:     }
                   1186:     return(TRUE);
                   1187:   }
                   1188: 
1.1.1.2 ! root     1189:   /* Failed */
1.1       root     1190:   return(FALSE);
                   1191: }
                   1192: 
                   1193: 
1.1.1.2 ! root     1194: /*-----------------------------------------------------------------------*/
1.1       root     1195: /*
                   1196:   Copy data from DMA workspace into ST RAM
                   1197: */
                   1198: void FDC_DMADataFromFloppy(void)
                   1199: {
1.1.1.2 ! root     1200:   /* Copy data to DMA address */
1.1       root     1201:   memcpy( (char *)((unsigned long)STRam+FDC_ReadDMAAddress()), DMASectorWorkSpace, NUMBYTESPERSECTOR );
                   1202: 
1.1.1.2 ! root     1203:   /* Update DMA pointer */
1.1       root     1204:   FDC_WriteDMAAddress(FDC_ReadDMAAddress()+NUMBYTESPERSECTOR);
                   1205: }
                   1206: 
                   1207: 
1.1.1.2 ! root     1208: /*-----------------------------------------------------------------------*/
1.1       root     1209: /*
                   1210:   Write byte to 0xff8604
                   1211: */
                   1212: void FDC_WriteDiscController(unsigned short v)
                   1213: {
                   1214:  DiscControllerWord_ff8604wr = v;
                   1215:  FDC_WriteDiscControllerByte();
                   1216: }
                   1217: 
                   1218: 
1.1.1.2 ! root     1219: /*-----------------------------------------------------------------------*/
1.1       root     1220: /*
                   1221:   Read word from 0xff8604
                   1222: */
                   1223: short FDC_ReadDiscControllerStatus(void)
                   1224: {
                   1225:  FDC_ReadDiscControllerStatusByte();    /* Read Status/Track/Sector/Data according to 'DiscControllerWord_ff8604wr' */
                   1226:  return DiscControllerByte;
                   1227: }
                   1228: 
                   1229: 
1.1.1.2 ! root     1230: /*-----------------------------------------------------------------------*/
1.1       root     1231: /*
                   1232:   Write word to 0xff8606 (DMA Mode Control)
                   1233: 
                   1234:   Eg.
                   1235:   $80 - Selects command/status register
                   1236:   $82 - Selects track register
                   1237:   $84 - Selects sector register
                   1238:   $86 - Selects data regsiter
                   1239:   NOTE - OR above values with $100 is transfer from memory to floppy
                   1240:   Also if bit 4 is set, write to sector count register
                   1241: */
                   1242: void FDC_WriteDMAModeControl(unsigned short v)
                   1243: {
                   1244:  DMAModeControl_ff8606wr_prev = DMAModeControl_ff8606wr;  /* Store previous to check for _read/_write toggle(DMA reset) */
                   1245:  DMAModeControl_ff8606wr = v;          /* Store to DMA Mode control */
                   1246:  FDC_CheckForDMAStatusReset();
                   1247: }
                   1248: 

unix.superglobalmegacorp.com

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