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

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

unix.superglobalmegacorp.com

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