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

1.1       root        1: /*
1.1.1.4   root        2:   Hatari - fdc.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
1.1       root        6: 
1.1.1.7   root        7:   Floppy Disk Controller(FDC) emulation. We need to simulate the movement of
                      8:   the head of the floppy disk drive to accurately perform the FDC commands,
                      9:   such as 'Step'. The is important for ST demo disk images. We have to go
1.1.1.6   root       10:   into a lot of details - including the start up/stop of the drive motor.
                     11:   To help with this emulation, we keep our own internal commands which are
1.1.1.7   root       12:   checked each HBL to perform the transfer of data from our disk image into
1.1.1.6   root       13:   the ST RAM area by simulating the DMA.
1.1       root       14: */
1.1.1.9   root       15: 
1.1.1.13  root       16: /* FIXME : after a type II read sector with multi bit 'm' on, we       */
                     17: /* should update FDCSectorRegister to be 'max sector for current       */
                     18: /* track'+1 and set command status to 'Record Not Found'.              */
                     19: /* Also,  if multi bit is set and sector count is less than number     */
                     20: /* of sectors in the track, then the FDC reads the whole track         */
                     21: /* anyway, setting RNF at the end, but the DMA stops transferring      */
                     22: /* data once DMA sector count $ff8604 reaches 0.                       */
                     23: /* Timings for read sector with multi bit are not good and prevent     */
                     24: /* some programs from working (eg Super Monaco GP on Superior 65)      */
                     25: /* because intrq bit 5 in $fffa01 seems to be cleared too late,        */
                     26: /* the command takes more time than a real ST to complete.             */
1.1.1.10  root       27: 
1.1.1.11  root       28: const char FDC_fileid[] = "Hatari fdc.c : " __DATE__ " " __TIME__;
1.1       root       29: 
                     30: #include "main.h"
1.1.1.4   root       31: #include "configuration.h"
1.1       root       32: #include "fdc.h"
1.1.1.3   root       33: #include "hdc.h"
1.1       root       34: #include "floppy.h"
                     35: #include "ikbd.h"
1.1.1.6   root       36: #include "ioMem.h"
                     37: #include "log.h"
1.1       root       38: #include "m68000.h"
                     39: #include "memorySnapShot.h"
                     40: #include "mfp.h"
                     41: #include "psg.h"
                     42: #include "stMemory.h"
1.1.1.14! root       43: #include "screen.h"
1.1.1.10  root       44: #include "video.h"
1.1       root       45: 
1.1.1.3   root       46: 
1.1       root       47: /*
1.1.1.7   root       48:   Floppy Disk Controller
1.1       root       49: 
                     50: Programmable Sound Generator (YM-2149)
                     51: 
                     52:   0xff8800(even byte)  - PSG Register Data (Read, used for parallel port)
                     53:             - PSG Register Select (Write)
                     54: 
                     55:   Write to bits 0-3 to select PSG register to use(then write data to 0xfff8802)
                     56:     Value    Register
                     57: 
                     58:     0000    Channel A Fine Tune
                     59:     0001    Channel A Coarse Tune
                     60:     0010    Channel B Fine Tune
                     61:     0011    Channel B Coarse Tune
                     62:     0100    Channel C Fine Tune
                     63:     0101    Channel C Coarse Tune
                     64:     0110    Noise Generator Control
                     65:     0111    Mixer Control - I/O enable
                     66:     1000    Channel A Amplitude
                     67:     1001    Channel B Amplitude
                     68:     1010    Channel C Amplitude
                     69:     1011    Envelope Period Fine Tune
                     70:     1100    Envelope Peroid Coarse Tune
                     71:     1101    Envelope Shape
                     72:     1110    I/O Port A Select (Write only)
                     73:     1111    I/O Port B Select
                     74: 
                     75:   0xfff8802(even byte)  - Bits according to 0xff8800 Register select
1.1.1.4   root       76: 
1.1       root       77:   1110(Register 14) - I/O Port A
                     78:     Bit 0 - Floppy side 0/1
                     79:     Bit 1 - Floppy drive 0 select
                     80:     Bit 2 - Floppy drive 1 select
                     81:     Bit 3 - RS232 Ready to send (RTS)
                     82:     Bit 4 - RS232 Data Terminal Ready (DTR)
                     83:     Bit 5 - Centronics Strobe
                     84:     Bit 6 - General Purpose Output
                     85:     Bit 7 - Reserved
                     86: 
1.1.1.7   root       87: ACSI DMA and Floppy Disk Controller(FDC)
1.1       root       88:   0xff8604 - information from file '1772.info.txt, by David Gahris' (register r0)
                     89:   (write) - Disk controller
                     90:   (read) - Disk controller status
                     91:     Bit 0 - Busy.  This bit is 1 when the 177x is busy.  This bit is 0 when the 177x is free for CPU commands.
                     92:     Bit 1 - Index / Data Request.  On Type I commands, this bit is high during the index pulse that occurs once
                     93:       per disk rotation.  This bit is low at all times other than the index pulse.  For Type II and III commands,
                     94:       Bit 1 high signals the CPU to handle the data register in order to maintain a continuous flow of data.
                     95:       Bit 1 is high when the data register is full during a read or when the data register is empty during a write.
                     96:       "Worst case service time" for Data Request is 23.5 cycles.
                     97:     Bit 2 - Track Zero / Lost Data.  After Type I commands, this bit is 0 if the mechanism is at track zero.
                     98:       This bit is 1 if the head is not at track zero.  After Type II or III commands, this bit is 1 if the
                     99:       CPU did not respond to Data Request (Status bit 1) in time for the 177x to maintain a continuous data flow.
                    100:       This bit is 0 if the CPU responded promptly to Data Request.
                    101:     Bit 3 - CRC Error.  This bit is high if a sector CRC on disk does not match the CRC which the 177x
                    102:       computed from the data.  The CRC polynomial is x^16+x^12+x^5+1.  If the stored CRC matches the newly
                    103:       calculated CRC, the CRC Error bit is low.  If this bit and the Record Not Found bit are set, the error
                    104:       was in an ID field.  If this bit is set but Record Not Found is clear, the error was in a data field.
                    105:     Bit 4 - Record Not Found.  This bit is set if the 177x cannot find the track, sector, or side which
                    106:       the CPU requested.  Otherwise, this bit is clear.
                    107:     Bit 5 - Spin-up / Record Type.  For Type I commands, this bit is low during the 6-revolution motor
                    108:       spin-up time.  This bit is high after spin-up.  For Type II and Type III commands, Bit 5 low
                    109:       indicates a normal data mark.  Bit 5 high indicates a deleted data mark.
                    110:     Bit 6 - Write Protect.  This bit is not used during reads.  During writes, this bit is high when the disk is write protected.
                    111:     Bit 7 - Motor On.  This bit is high when the drive motor is on, and low when the motor is off.
                    112: 
                    113:   0xff8606 - DMA Status(read), DMA Mode Control(write) - NOTE bits 0,9-15 are not used
                    114:     Bit 1 - FDC Pin A0 (See below)
                    115:     Bit 2 - FDC Pin A1
                    116:     Bit 3 - FDC/HDC Register Select
                    117:     Bit 4 - FDC/Sector count select
                    118:     Bit 5 - Reserved
                    119:     Bit 6 - Enable/Disable DMA
                    120:     Bit 7 - HDC/FDC
                    121:     Bit 8 - Read/Write
                    122: 
                    123:     A1  A0    Read        Write(bit 8==1)
                    124:     0  0    Status        Command
                    125:     0  1    Track Register    Track Register
                    126:     1  0    Sector Register    Sector Register
                    127:     1  1    Data Register    Data Register
                    128: 
                    129: 
1.1.1.6   root      130:   This handles any read/writes to the FDC and PSG. FDC commands are then sent
1.1.1.7   root      131:   through to read/write disk sector code. We have full documents on 1772 FDC,
1.1.1.6   root      132:   but they use r0,r1,r2,r3 etc.. which are not seen at first glance as Atari
                    133:   access them via the A0,A1 bits. Once this is understood it is all relativly
1.1.1.7   root      134:   easy as a lot of information can be ignored as we are using disk images and
                    135:   not actual disks. We do NOT support the reading of the PC's A: drive - newer
                    136:   PC's cannot read an ST single sided disk, ST disks are very old and so are
1.1.1.6   root      137:   dirty which gets onto the PC drive heads and ruins them and also support for
1.1.1.7   root      138:   disk sector access under the various modern operating systems is not so easy
1.1.1.6   root      139:   (if possible at all).
                    140: 
                    141:   According to the documentation INTRQ is generated at the completion of each
                    142:   command (causes an interrupt in the MFP). INTRQ is reset by reading the status
                    143:   register OR by loading a new command. So, does this mean the GPIP? Or does it
                    144:   actually CANCEL the interrupt? Can this be done?
1.1       root      145: */
                    146: 
1.1.1.14! root      147: /*-----------------------------------------------------------------------*/
        !           148: /* FDC Emulation commands */
        !           149: enum
        !           150: {
        !           151:        FDCEMU_CMD_NULL = 0,
        !           152:        /* Type I */
        !           153:        FDCEMU_CMD_RESTORE,
        !           154:        FDCEMU_CMD_SEEK,
        !           155:        FDCEMU_CMD_STEP,
        !           156:        FDCEMU_CMD_STEPIN,
        !           157:        FDCEMU_CMD_STEPOUT,
        !           158:        /* Type II */
        !           159:        FDCEMU_CMD_READSECTORS,
        !           160:        FDCEMU_CMD_READMULTIPLESECTORS,
        !           161:        FDCEMU_CMD_WRITESECTORS,
        !           162:        FDCEMU_CMD_WRITEMULTIPLESECTORS,
        !           163:        /* Type III */
        !           164:        FDCEMU_CMD_READADDRESS,
        !           165: };
        !           166: 
        !           167: /* FDC Emulation commands */
        !           168: #define  FDCEMU_RUN_NULL      0
        !           169: 
        !           170: /* FDC Running Restore commands */
        !           171: enum
        !           172: {
        !           173:        FDCEMU_RUN_RESTORE_SEEKTOTRACKZERO,
        !           174:        FDCEMU_RUN_RESTORE_COMPLETE
        !           175: };
        !           176: 
        !           177: /* FDC Running Seek commands */
        !           178: enum
        !           179: {
        !           180:        FDCEMU_RUN_SEEK_TOTRACK,
        !           181:        FDCEMU_RUN_SEEK_COMPLETE
        !           182: };
        !           183: 
        !           184: /* FDC Running Step commands */
        !           185: enum
        !           186: {
        !           187:        FDCEMU_RUN_STEP_ONCE,
        !           188:        FDCEMU_RUN_STEP_COMPLETE
        !           189: };
        !           190: 
        !           191: /* FDC Running Step In commands */
        !           192: enum
        !           193: {
        !           194:        FDCEMU_RUN_STEPIN_ONCE,
        !           195:        FDCEMU_RUN_STEPIN_COMPLETE
        !           196: };
        !           197: 
        !           198: /* FDC Running Step Out commands */
        !           199: enum
        !           200: {
        !           201:        FDCEMU_RUN_STEPOUT_ONCE,
        !           202:        FDCEMU_RUN_STEPOUT_COMPLETE
        !           203: };
        !           204: 
        !           205: /* FDC Running Read Sector/s commands */
        !           206: enum
        !           207: {
        !           208:        FDCEMU_RUN_READSECTORS_READDATA,
        !           209:        FDCEMU_RUN_READSECTORS_COMPLETE
        !           210: };
        !           211: 
        !           212: /* FDC Running write Sector/s commands */
        !           213: enum
        !           214: {
        !           215:        FDCEMU_RUN_WRITESECTORS_WRITEDATA,
        !           216:        FDCEMU_RUN_WRITESECTORS_COMPLETE
        !           217: };
        !           218: 
        !           219: /* FDC Running Read Address commands */
        !           220: enum
        !           221: {
        !           222:        FDCEMU_RUN_READADDRESS,
        !           223:        FDCEMU_RUN_READADDRESS_COMPLETE
        !           224: };
        !           225: 
        !           226: 
        !           227: /* Commands are taking the equivalent of FDC_DELAY_CYCLES cpu cycles to execute */
        !           228: /* to try to simulate the speed of a real ST floppy drive */
        !           229: #define FDC_DELAY_CYCLES               92160
        !           230: //#define FDC_DELAY_CYCLES             1536    // 'Just Bugging Demo' by ACF requires a very fast delay (bug in the loader)
        !           231: 
1.1       root      232: 
1.1.1.7   root      233: Sint16 FDCSectorCountRegister;
1.1       root      234: 
1.1.1.7   root      235: Uint16 DiskControllerWord_ff8604wr;                             /* 0xff8604 (write) */
                    236: static Uint16 DiskControllerStatus_ff8604rd;                    /* 0xff8604 (read) */
1.1.1.5   root      237: 
1.1.1.6   root      238: Uint16 DMAModeControl_ff8606wr;                                 /* 0xff8606 (write) */
                    239: static Uint16 DMAStatus_ff8606rd;                               /* 0xff8606 (read) */
1.1.1.5   root      240: 
1.1.1.7   root      241: static Uint16 FDCCommandRegister;
                    242: static Sint16 FDCTrackRegister, FDCSectorRegister, FDCDataRegister;
1.1.1.5   root      243: static int FDCEmulationCommand;                                 /* FDC emulation command currently being exceuted */
                    244: static int FDCEmulationRunning;                                 /* Running command under above */
                    245: static int FDCStepDirection;                                    /* +Track on 'Step' command */
1.1.1.10  root      246: static bool bDMAWaiting;                                        /* Is DMA waiting to copy? */
1.1.1.5   root      247: static int bMotorOn;                                            /* Is motor on? */
                    248: static int MotorSlowingCount;                                   /* Counter used to slow motor before stopping */
                    249: 
                    250: static short int nReadWriteTrack;                               /* Parameters used in sector read/writes */
                    251: static short int nReadWriteSector;
                    252: static short int nReadWriteSide;
                    253: static short int nReadWriteDev;
                    254: static unsigned short int nReadWriteSectorsPerTrack;
                    255: static short int nReadWriteSectors;
                    256: 
1.1.1.7   root      257: static Uint8 DMASectorWorkSpace[NUMBYTESPERSECTOR];             /* Workspace used to copy to/from for floppy DMA */
1.1       root      258: 
1.1.1.2   root      259: 
1.1.1.14! root      260: static void FDC_ResetDMAStatus(void);
        !           261: static int  FDC_FindFloppyDrive(void);
        !           262: static void FDC_UpdateRestoreCmd(void);
        !           263: static void FDC_UpdateSeekCmd(void);
        !           264: static void FDC_UpdateStepCmd(void);
        !           265: static void FDC_UpdateStepInCmd(void);
        !           266: static void FDC_UpdateStepOutCmd(void);
        !           267: static void FDC_UpdateReadSectorsCmd(void);
        !           268: static void FDC_UpdateWriteSectorsCmd(void);
        !           269: static void FDC_UpdateReadAddressCmd(void);
        !           270: static bool FDC_ReadSectorFromFloppy(void);
        !           271: static bool FDC_WriteSectorFromFloppy(void);
        !           272: 
1.1.1.2   root      273: /*-----------------------------------------------------------------------*/
1.1.1.9   root      274: /**
                    275:  * Reset variables used in FDC
                    276:  */
1.1       root      277: void FDC_Reset(void)
                    278: {
1.1.1.6   root      279:        /* Clear out FDC registers */
1.1.1.7   root      280:        DiskControllerStatus_ff8604rd = 0;
                    281:        DiskControllerWord_ff8604wr = 0;
1.1.1.6   root      282:        DMAStatus_ff8606rd = 0x01;
                    283:        DMAModeControl_ff8606wr = 0;
                    284:        FDC_ResetDMAStatus();
                    285:        FDCCommandRegister = 0;
                    286:        FDCTrackRegister = 0;
                    287:        FDCSectorRegister = 1;
                    288:        FDCDataRegister = 0;
                    289:        FDCSectorCountRegister = 0;
                    290: 
                    291:        FDCEmulationCommand = FDCEMU_CMD_NULL;        /* FDC emulation command currently being exceuted */
                    292:        FDCEmulationRunning = FDCEMU_RUN_NULL;        /* Running command under above */
                    293: 
                    294:        FDCStepDirection = 1;                         /* +Track on 'Step' command */
1.1.1.12  root      295:        bDMAWaiting = false;                          /* No DMA waiting */
                    296:        bMotorOn = false;                             /* Motor off */
1.1.1.6   root      297:        MotorSlowingCount = 0;                        /* Counter for motor slowing down before stopping */
1.1       root      298: }
                    299: 
1.1.1.2   root      300: 
                    301: /*-----------------------------------------------------------------------*/
1.1.1.9   root      302: /**
                    303:  * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                    304:  */
1.1.1.10  root      305: void FDC_MemorySnapShot_Capture(bool bSave)
1.1       root      306: {
1.1.1.6   root      307:        /* Save/Restore details */
1.1.1.7   root      308:        MemorySnapShot_Store(&DiskControllerStatus_ff8604rd, sizeof(DiskControllerStatus_ff8604rd));
                    309:        MemorySnapShot_Store(&DiskControllerWord_ff8604wr, sizeof(DiskControllerWord_ff8604wr));
1.1.1.6   root      310:        MemorySnapShot_Store(&DMAStatus_ff8606rd, sizeof(DMAStatus_ff8606rd));
                    311:        MemorySnapShot_Store(&DMAModeControl_ff8606wr, sizeof(DMAModeControl_ff8606wr));
                    312:        MemorySnapShot_Store(&FDCCommandRegister, sizeof(FDCCommandRegister));
                    313:        MemorySnapShot_Store(&FDCTrackRegister, sizeof(FDCTrackRegister));
                    314:        MemorySnapShot_Store(&FDCSectorRegister, sizeof(FDCSectorRegister));
                    315:        MemorySnapShot_Store(&FDCDataRegister, sizeof(FDCDataRegister));
                    316:        MemorySnapShot_Store(&FDCSectorCountRegister, sizeof(FDCSectorCountRegister));
                    317:        MemorySnapShot_Store(&FDCEmulationCommand, sizeof(FDCEmulationCommand));
                    318:        MemorySnapShot_Store(&FDCEmulationRunning, sizeof(FDCEmulationRunning));
                    319:        MemorySnapShot_Store(&FDCStepDirection, sizeof(FDCStepDirection));
                    320:        MemorySnapShot_Store(&bDMAWaiting, sizeof(bDMAWaiting));
                    321:        MemorySnapShot_Store(&bMotorOn, sizeof(bMotorOn));
                    322:        MemorySnapShot_Store(&MotorSlowingCount, sizeof(MotorSlowingCount));
                    323:        MemorySnapShot_Store(&nReadWriteTrack, sizeof(nReadWriteTrack));
                    324:        MemorySnapShot_Store(&nReadWriteSector, sizeof(nReadWriteSector));
                    325:        MemorySnapShot_Store(&nReadWriteSide, sizeof(nReadWriteSide));
                    326:        MemorySnapShot_Store(&nReadWriteDev, sizeof(nReadWriteDev));
                    327:        MemorySnapShot_Store(&nReadWriteSectorsPerTrack, sizeof(nReadWriteSectorsPerTrack));
                    328:        MemorySnapShot_Store(&nReadWriteSectors, sizeof(nReadWriteSectors));
                    329:        MemorySnapShot_Store(DMASectorWorkSpace, sizeof(DMASectorWorkSpace));
1.1       root      330: }
                    331: 
1.1.1.2   root      332: 
                    333: /*-----------------------------------------------------------------------*/
1.1.1.9   root      334: /**
                    335:  * Turn floppy motor on
                    336:  */
1.1.1.5   root      337: static void FDC_TurnMotorOn(void)
1.1       root      338: {
1.1.1.12  root      339:        bMotorOn = true;                  /* Turn motor on */
1.1.1.6   root      340:        MotorSlowingCount = 0;
1.1       root      341: }
                    342: 
1.1.1.2   root      343: 
                    344: /*-----------------------------------------------------------------------*/
1.1.1.9   root      345: /**
                    346:  * Turn floppy motor off (this sets a count as it takes a set amount of time for the motor to slow to a halt)
                    347:  */
1.1.1.5   root      348: static void FDC_TurnMotorOff(void)
1.1       root      349: {
1.1.1.6   root      350:        MotorSlowingCount = 160;          /* Set timer so takes 'x' HBLs before turn off... */
1.1       root      351: }
                    352: 
1.1.1.2   root      353: 
                    354: /*-----------------------------------------------------------------------*/
1.1.1.9   root      355: /**
                    356:  * Update floppy drive motor each HBL, to simulate slowing down and stopping for drive; needed for New Zealand Story(PP_001)
                    357:  */
1.1.1.5   root      358: static void FDC_UpdateMotor(void)
1.1       root      359: {
1.1.1.6   root      360:        /* Is drive slowing down? Decrement counter */
                    361:        if (MotorSlowingCount>0)
                    362:        {
                    363:                MotorSlowingCount--;
                    364: 
                    365:                if (MotorSlowingCount==0)
1.1.1.12  root      366:                        bMotorOn = false;         /* Motor finally stopped */
1.1.1.6   root      367:        }
1.1       root      368: }
                    369: 
1.1.1.2   root      370: 
                    371: /*-----------------------------------------------------------------------*/
1.1.1.9   root      372: /**
                    373:  * Reset DMA Status (RD 0xff8606)
                    374:  *
                    375:  * This is done by 'toggling' bit 8 of the DMA Mode Control register
                    376:  */
1.1.1.14! root      377: static void FDC_ResetDMAStatus(void)
1.1       root      378: {
1.1.1.6   root      379:        DMAStatus_ff8606rd = 0;           /* Clear out */
1.1       root      380: 
1.1.1.6   root      381:        FDCSectorCountRegister = 0;
1.1.1.12  root      382:        FDC_SetDMAStatus(false);          /* Set no error */
1.1.1.3   root      383: 
1.1.1.10  root      384:        /* Reset HDC command status */
1.1.1.6   root      385:        HDCSectorCount = 0;
1.1.1.10  root      386:        /*HDCCommand.byteCount = 0;*/  /* Not done on real ST? */
1.1.1.8   root      387:        HDCCommand.returnCode = 0;
1.1       root      388: }
                    389: 
1.1.1.2   root      390: 
                    391: /*-----------------------------------------------------------------------*/
1.1.1.9   root      392: /**
                    393:  * Set DMA Status (RD 0xff8606)
1.1.1.10  root      394:  *
1.1.1.9   root      395:  * NOTE FDC Doc's are incorrect - Bit 0 is '0' on error (See TOS floprd, Ninja III etc...)
                    396:  * Look like Atari(yet again) connected the hardware up differently to the spec'
                    397:  *
                    398:  * Bit 0 - _Error Status (0=Error)
                    399:  * Bit 1 - _Sector Count Zero Status (0=Sector Count Zero)
                    400:  * Bit 2 - _Data Request Inactive Status
                    401:  */
1.1.1.10  root      402: void FDC_SetDMAStatus(bool bError)
1.1       root      403: {
1.1.1.6   root      404:        DMAStatus_ff8606rd &= 0x1;        /* Clear(except for error) */
1.1       root      405: 
1.1.1.6   root      406:        /* Set error condition - NOTE this is incorrect in the FDC Doc's! */
                    407:        if (!bError)
                    408:                DMAStatus_ff8606rd |= 0x1;
                    409: 
                    410:        /* Set zero sector count */
                    411: 
                    412:        if (DMAModeControl_ff8606wr&0x08)         /* Get which sector count? */
1.1.1.8   root      413:                DMAStatus_ff8606rd |= (HDCSectorCount)?0x2:0;         /* HDC */
1.1.1.6   root      414:        else
                    415:                DMAStatus_ff8606rd |= (FDCSectorCountRegister)?0x2:0; /* FDC */
                    416:        /* Perhaps the DRQ should be set here */
1.1       root      417: }
                    418: 
1.1.1.2   root      419: 
                    420: /*-----------------------------------------------------------------------*/
1.1.1.9   root      421: /**
                    422:  * Read DMA Status (RD 0xff8606)
                    423:  */
1.1.1.6   root      424: void FDC_DmaStatus_ReadWord(void)
1.1       root      425: {
1.1.1.6   root      426:        if (nIoMemAccessSize == SIZE_BYTE)
                    427:        {
                    428:                /* This register does not like to be accessed in byte mode on a normal ST */
1.1.1.8   root      429:                M68000_BusError(IoAccessBaseAddress, BUS_ERROR_READ);
1.1.1.6   root      430:                return;
                    431:        }
                    432: 
                    433:        IoMem_WriteWord(0xff8606, DMAStatus_ff8606rd);
1.1       root      434: }
                    435: 
1.1.1.2   root      436: 
                    437: /*-----------------------------------------------------------------------*/
1.1.1.9   root      438: /**
1.1.1.14! root      439:  * Copy data from DMA workspace into ST RAM
        !           440:  */
        !           441: static void FDC_DMADataFromFloppy(void)
        !           442: {
        !           443:        Uint32 Address = FDC_ReadDMAAddress();
        !           444:        STMemory_SafeCopy(Address, DMASectorWorkSpace, NUMBYTESPERSECTOR, "FDC DMA data read");
        !           445:        /* Update DMA pointer */
        !           446:        FDC_WriteDMAAddress(Address+NUMBYTESPERSECTOR);
        !           447: }
        !           448: 
        !           449: 
        !           450: /*-----------------------------------------------------------------------*/
        !           451: /**
1.1.1.10  root      452:  *
1.1.1.9   root      453:  */
1.1.1.7   root      454: static void FDC_UpdateDiskDrive(void)
1.1       root      455: {
1.1.1.6   root      456:        /* Set details for current selecte drive */
                    457:        nReadWriteDev = FDC_FindFloppyDrive();
1.1.1.2   root      458: 
1.1.1.7   root      459:        if (EmulationDrives[nReadWriteDev].bDiskInserted)
                    460:                Floppy_FindDiskDetails(EmulationDrives[nReadWriteDev].pBuffer,EmulationDrives[nReadWriteDev].nImageBytes,&nReadWriteSectorsPerTrack,NULL);
1.1       root      461: }
                    462: 
1.1.1.2   root      463: 
                    464: /*-----------------------------------------------------------------------*/
1.1.1.9   root      465: /**
                    466:  * Set disk controller status (RD 0xff8604)
                    467:  */
1.1.1.7   root      468: static void FDC_SetDiskControllerStatus(void)
1.1       root      469: {
1.1.1.7   root      470:        /* Update disk */
                    471:        FDC_UpdateDiskDrive();
1.1       root      472: 
1.1.1.6   root      473:        /* Clear out to default */
1.1.1.7   root      474:        DiskControllerStatus_ff8604rd = 0;
1.1       root      475: 
1.1.1.6   root      476:        /* ONLY do this if we are running a Type I command */
                    477:        if ((FDCCommandRegister&0x80)==0)
                    478:        {
                    479:                /* Type I - Restore, Seek, Step, Step-In, Step-Out */
                    480:                if (FDCTrackRegister==0)
1.1.1.7   root      481:                        DiskControllerStatus_ff8604rd |= 0x4;    /* Bit 2 - Track Zero, '0' if head is NOT at zero */
1.1.1.6   root      482:        }
                    483: 
1.1.1.7   root      484:        /* If no disk inserted, tag as error */
                    485:        if (!EmulationDrives[nReadWriteDev].bDiskInserted)
                    486:                DiskControllerStatus_ff8604rd |= 0x10;     /* RNF - Record not found, ie no disk in drive */
1.1       root      487: }
                    488: 
1.1.1.2   root      489: 
                    490: /*-----------------------------------------------------------------------*/
1.1.1.9   root      491: /**
                    492:  * Return device for FDC, check PORTA bits 1,2(0=on,1=off)
                    493:  */
1.1.1.14! root      494: static int FDC_FindFloppyDrive(void)
1.1       root      495: {
1.1.1.6   root      496:        /* Check Drive A first */
                    497:        if ((PSGRegisters[PSG_REG_IO_PORTA]&0x2)==0)
                    498:                return 0;                     /* Device 0 (A:) */
                    499:        /* If off, check Drive B */
                    500:        if ((PSGRegisters[PSG_REG_IO_PORTA]&0x4)==0)
                    501:                return 1;                     /* Device 1 (B:) */
1.1       root      502: 
1.1.1.6   root      503:        /* None appear to be selected so default to Drive A */
                    504:        return 0;                         /* Device 0 (A:) */
1.1       root      505: }
                    506: 
1.1.1.2   root      507: 
                    508: /*-----------------------------------------------------------------------*/
1.1.1.9   root      509: /**
                    510:  * Acknowledge FDC interrupt
                    511:  */
1.1       root      512: void FDC_AcknowledgeInterrupt(void)
                    513: {
1.1.1.6   root      514:        /* Acknowledge in MFP circuit, pass bit, enable, pending */
                    515:        MFP_InputOnChannel(MFP_FDCHDC_BIT,MFP_IERB,&MFP_IPRB);
                    516:        MFP_GPIP &= ~0x20;
1.1       root      517: }
                    518: 
1.1.1.2   root      519: 
                    520: /*-----------------------------------------------------------------------*/
1.1.1.9   root      521: /**
                    522:  * Copy parameters for disk sector/s read/write
                    523:  */
1.1.1.5   root      524: static void FDC_SetReadWriteParameters(int nSectors)
1.1       root      525: {
1.1.1.6   root      526:        /* Copy read/write details so we can modify them */
                    527:        nReadWriteTrack = FDCTrackRegister;
                    528:        nReadWriteSector = FDCSectorRegister;
                    529:        nReadWriteSide = (~PSGRegisters[PSG_REG_IO_PORTA]) & 0x01;
                    530:        nReadWriteSectors = nSectors;
1.1.1.7   root      531:        /* Update disk */
                    532:        FDC_UpdateDiskDrive();
1.1       root      533: }
                    534: 
1.1.1.2   root      535: 
                    536: /*-----------------------------------------------------------------------*/
1.1.1.9   root      537: /**
                    538:  * ST program (or TOS) has read the MFP GPIP register to check if the FDC
                    539:  * is already done. Then we can skip the usual FDC waiting period!
                    540:  */
1.1.1.8   root      541: void FDC_GpipRead(void)
                    542: {
                    543:        static int nLastGpipBit;
                    544: 
                    545:        if ((MFP_GPIP & 0x20) == nLastGpipBit)
                    546:        {
1.1.1.12  root      547:                if (!ConfigureParams.DiskImage.bSlowFloppy)
1.1.1.9   root      548:                {
                    549:                        /* Restart FDC update interrupt to occur right after a few cycles */
1.1.1.13  root      550:                        CycInt_RemovePendingInterrupt(INTERRUPT_FDC);
                    551:                        CycInt_AddRelativeInterrupt(4, INT_CPU_CYCLE, INTERRUPT_FDC);
1.1.1.9   root      552:                }
1.1.1.8   root      553:        }
                    554:        else
                    555:        {
                    556:                nLastGpipBit = MFP_GPIP & 0x20;
                    557:        }
                    558: }
                    559: 
                    560: 
                    561: /*-----------------------------------------------------------------------*/
1.1.1.9   root      562: /**
                    563:  * Update floppy drive after a while.
                    564:  * Some games/demos (e.g. Fantasia by Dune, Alien World, ...) don't work
                    565:  * if the FDC is too fast. So we use the update "interrupt" for delayed
                    566:  * execution of the commands.
                    567:  * FIXME: We urgently need better timings here!
                    568:  */
                    569: void FDC_InterruptHandler_Update(void)
1.1       root      570: {
1.1.1.13  root      571:        CycInt_AcknowledgeInterrupt();
1.1.1.6   root      572: 
                    573:        /* Do we have a DMA ready to copy? */
                    574:        if (bDMAWaiting)
                    575:        {
                    576:                /* Yes, copy it */
                    577:                FDC_DMADataFromFloppy();
                    578:                /* Signal done */
1.1.1.12  root      579:                bDMAWaiting = false;
1.1.1.6   root      580:        }
                    581: 
                    582:        /* Update drive motor */
                    583:        FDC_UpdateMotor();
                    584: 
                    585:        /* Is FDC active? */
                    586:        if (FDCEmulationCommand!=FDCEMU_CMD_NULL)
                    587:        {
                    588:                /* Which command are we running? */
                    589:                switch(FDCEmulationCommand)
                    590:                {
                    591:                 case FDCEMU_CMD_RESTORE:
                    592:                        FDC_UpdateRestoreCmd();
                    593:                        break;
                    594:                 case FDCEMU_CMD_SEEK:
                    595:                        FDC_UpdateSeekCmd();
                    596:                        break;
                    597:                 case FDCEMU_CMD_STEP:
                    598:                        FDC_UpdateStepCmd();
                    599:                        break;
                    600:                 case FDCEMU_CMD_STEPIN:
                    601:                        FDC_UpdateStepInCmd();
                    602:                        break;
                    603:                 case FDCEMU_CMD_STEPOUT:
                    604:                        FDC_UpdateStepOutCmd();
                    605:                        break;
                    606: 
                    607:                 case FDCEMU_CMD_READSECTORS:
                    608:                 case FDCEMU_CMD_READMULTIPLESECTORS:
                    609:                        FDC_UpdateReadSectorsCmd();
                    610:                        break;
                    611:                 case FDCEMU_CMD_WRITESECTORS:
                    612:                 case FDCEMU_CMD_WRITEMULTIPLESECTORS:
                    613:                        FDC_UpdateWriteSectorsCmd();
                    614:                        break;
1.1.1.11  root      615: 
                    616:                 case FDCEMU_CMD_READADDRESS:
                    617:                        FDC_UpdateReadAddressCmd();
                    618:                        break;
1.1.1.6   root      619:                }
                    620: 
1.1.1.7   root      621:                /* Set disk controller status (RD 0xff8604) */
                    622:                FDC_SetDiskControllerStatus();
1.1.1.6   root      623:        }
1.1.1.9   root      624: 
                    625:        if (FDCEmulationCommand != FDCEMU_CMD_NULL || bMotorOn)
                    626:        {
1.1.1.13  root      627:                CycInt_AddAbsoluteInterrupt(FDC_DELAY_CYCLES,  INT_CPU_CYCLE, INTERRUPT_FDC);
1.1.1.9   root      628:        }
1.1       root      629: }
                    630: 
1.1.1.2   root      631: 
                    632: /*-----------------------------------------------------------------------*/
1.1.1.9   root      633: /**
                    634:  * Run 'RESTORE' command
                    635:  */
1.1.1.14! root      636: static void FDC_UpdateRestoreCmd(void)
1.1       root      637: {
1.1.1.6   root      638:        /* Which command is running? */
                    639:        switch (FDCEmulationRunning)
                    640:        {
                    641:         case FDCEMU_RUN_RESTORE_SEEKTOTRACKZERO:
                    642:                /* Are we at track zero? */
                    643:                if (FDCTrackRegister>0)
                    644:                        FDCTrackRegister--;             /* Move towards track zero */
                    645:                else
                    646:                {
                    647:                        FDCTrackRegister = 0;           /* We're there */
                    648:                        FDCEmulationRunning = FDCEMU_RUN_RESTORE_COMPLETE;
                    649:                }
                    650:                break;
                    651:         case FDCEMU_RUN_RESTORE_COMPLETE:
                    652:                /* Acknowledge interrupt, move along there's nothing more to see */
                    653:                FDC_AcknowledgeInterrupt();
                    654:                /* Set error */
1.1.1.12  root      655:                FDC_SetDMAStatus(false);          /* No DMA error */
1.1.1.6   root      656:                /* Done */
                    657:                FDCEmulationCommand = FDCEMU_CMD_NULL;
                    658:                /* Turn motor off */
                    659:                FDC_TurnMotorOff();
                    660:                break;
                    661:        }
1.1       root      662: }
                    663: 
1.1.1.2   root      664: 
                    665: /*-----------------------------------------------------------------------*/
1.1.1.9   root      666: /**
                    667:  * Run 'SEEK' command
                    668:  */
1.1.1.14! root      669: static void FDC_UpdateSeekCmd(void)
1.1       root      670: {
1.1.1.6   root      671:        /* Which command is running? */
                    672:        switch (FDCEmulationRunning)
                    673:        {
                    674:         case FDCEMU_RUN_SEEK_TOTRACK:
                    675:                /* Are we at the selected track? */
                    676:                if (FDCTrackRegister==FDCDataRegister)
                    677:                        FDCEmulationRunning = FDCEMU_RUN_SEEK_COMPLETE;
                    678:                else
                    679:                {
                    680:                        /* No, seek towards track */
                    681:                        if (FDCDataRegister<FDCTrackRegister)
                    682:                                FDCTrackRegister--;
                    683:                        else
                    684:                                FDCTrackRegister++;
                    685:                }
                    686:                break;
                    687:         case FDCEMU_RUN_SEEK_COMPLETE:
                    688:                /* Acknowledge interrupt, move along there's nothing more to see */
                    689:                FDC_AcknowledgeInterrupt();
                    690:                /* Set error */
1.1.1.12  root      691:                FDC_SetDMAStatus(false);          /* No DMA error */
1.1.1.6   root      692:                /* Done */
                    693:                FDCEmulationCommand = FDCEMU_CMD_NULL;
                    694:                /* Turn motor off */
                    695:                FDC_TurnMotorOff();
                    696:                break;
                    697:        }
1.1       root      698: }
                    699: 
1.1.1.2   root      700: 
                    701: /*-----------------------------------------------------------------------*/
1.1.1.9   root      702: /**
                    703:  * Run 'STEP' command
                    704:  */
1.1.1.14! root      705: static void FDC_UpdateStepCmd(void)
1.1       root      706: {
1.1.1.6   root      707:        /* Which command is running? */
                    708:        switch (FDCEmulationRunning)
                    709:        {
                    710:         case FDCEMU_RUN_STEP_ONCE:
                    711:                /* Move head by one track in same direction as last step */
                    712:                FDCTrackRegister += FDCStepDirection;
                    713:                if (FDCTrackRegister<0)             /* Limit to stop */
                    714:                        FDCTrackRegister = 0;
                    715: 
                    716:                FDCEmulationRunning = FDCEMU_RUN_STEP_COMPLETE;
                    717:                break;
                    718:         case FDCEMU_RUN_STEP_COMPLETE:
                    719:                /* Acknowledge interrupt, move along there's nothing more to see */
                    720:                FDC_AcknowledgeInterrupt();
                    721:                /* Set error */
1.1.1.12  root      722:                FDC_SetDMAStatus(false);            /* No DMA error */
1.1.1.6   root      723:                /* Done */
                    724:                FDCEmulationCommand = FDCEMU_CMD_NULL;
                    725:                /* Turn motor off */
                    726:                FDC_TurnMotorOff();
                    727:                break;
                    728:        }
1.1       root      729: }
                    730: 
1.1.1.2   root      731: 
                    732: /*-----------------------------------------------------------------------*/
1.1.1.9   root      733: /**
                    734:  * Run 'STEP IN' command
                    735:  */
1.1.1.14! root      736: static void FDC_UpdateStepInCmd(void)
1.1       root      737: {
1.1.1.6   root      738:        /* Which command is running? */
                    739:        switch (FDCEmulationRunning)
                    740:        {
                    741:         case FDCEMU_RUN_STEPIN_ONCE:
                    742:                FDCTrackRegister++;
                    743: 
                    744:                FDCEmulationRunning = FDCEMU_RUN_STEPIN_COMPLETE;
                    745:                break;
                    746:         case FDCEMU_RUN_STEPIN_COMPLETE:
                    747:                /* Acknowledge interrupt, move along there's nothing more to see */
                    748:                FDC_AcknowledgeInterrupt();
                    749:                /* Set error */
1.1.1.12  root      750:                FDC_SetDMAStatus(false);            /* No DMA error */
1.1.1.6   root      751:                /* Done */
                    752:                FDCEmulationCommand = FDCEMU_CMD_NULL;
                    753:                /* Turn motor off */
                    754:                FDC_TurnMotorOff();
                    755:                break;
                    756:        }
1.1       root      757: }
                    758: 
1.1.1.2   root      759: 
                    760: /*-----------------------------------------------------------------------*/
1.1.1.9   root      761: /**
                    762:  * Run 'STEP OUT' command
                    763:  */
1.1.1.14! root      764: static void FDC_UpdateStepOutCmd(void)
1.1       root      765: {
1.1.1.6   root      766:        /* Which command is running? */
                    767:        switch (FDCEmulationRunning)
                    768:        {
                    769:         case FDCEMU_RUN_STEPOUT_ONCE:
                    770:                FDCTrackRegister--;
                    771:                if (FDCTrackRegister < 0)           /* Limit to stop */
                    772:                        FDCTrackRegister = 0;
                    773: 
                    774:                FDCEmulationRunning = FDCEMU_RUN_STEPOUT_COMPLETE;
                    775:                break;
                    776:         case FDCEMU_RUN_STEPOUT_COMPLETE:
                    777:                /* Acknowledge interrupt, move along there's nothing more to see */
                    778:                FDC_AcknowledgeInterrupt();
                    779:                /* Set error */
1.1.1.12  root      780:                FDC_SetDMAStatus(false);            /* No DMA error */
1.1.1.6   root      781:                /* Done */
                    782:                FDCEmulationCommand = FDCEMU_CMD_NULL;
                    783:                /* Turn motor off */
                    784:                FDC_TurnMotorOff();
                    785:                break;
                    786:        }
1.1       root      787: }
                    788: 
1.1.1.2   root      789: 
                    790: /*-----------------------------------------------------------------------*/
1.1.1.9   root      791: /**
                    792:  * Run 'READ SECTOR/S' command
                    793:  */
1.1.1.14! root      794: static void FDC_UpdateReadSectorsCmd(void)
1.1       root      795: {
1.1.1.6   root      796:        /* Which command is running? */
                    797:        switch (FDCEmulationRunning)
                    798:        {
                    799:         case FDCEMU_RUN_READSECTORS_READDATA:
                    800:                /* Read in a sector */
                    801:                if (FDC_ReadSectorFromFloppy())         /* Read a single sector through DMA */
                    802:                {
                    803:                        FDCSectorCountRegister--;           /* Decrement FDCSectorCount */
                    804:                        if (FDCSectorCountRegister <= 0)
                    805:                                FDCSectorCountRegister = 0;
                    806: 
                    807:                        /* Have we finished? */
                    808:                        nReadWriteSectors--;
                    809:                        if (nReadWriteSectors<=0)
                    810:                                FDCEmulationRunning = FDCEMU_RUN_READSECTORS_COMPLETE;
                    811: 
1.1.1.12  root      812:                        bDMAWaiting = true;
1.1.1.6   root      813:                }
                    814:                else
                    815:                {
                    816:                        /* Acknowledge interrupt, move along there's nothing more to see */
                    817:                        FDC_AcknowledgeInterrupt();
                    818:                        /* Set error */
1.1.1.12  root      819:                        FDC_SetDMAStatus(true);             /* DMA error */
1.1.1.6   root      820:                        /* Done */
                    821:                        FDCEmulationCommand = FDCEMU_CMD_NULL;
                    822:                        /* Turn motor off */
                    823:                        FDC_TurnMotorOff();
                    824:                }
                    825:                break;
                    826:         case FDCEMU_RUN_READSECTORS_COMPLETE:
                    827:                /* Acknowledge interrupt, move along there's nothing more to see */
                    828:                FDC_AcknowledgeInterrupt();
                    829:                /* Set error */
1.1.1.12  root      830:                FDC_SetDMAStatus(false);              /* No DMA error */
1.1.1.6   root      831:                /* Done */
                    832:                FDCEmulationCommand = FDCEMU_CMD_NULL;
                    833:                /* Turn motor off */
                    834:                FDC_TurnMotorOff();
                    835:                break;
                    836:        }
1.1       root      837: }
                    838: 
1.1.1.2   root      839: 
                    840: /*-----------------------------------------------------------------------*/
1.1.1.9   root      841: /**
                    842:  * Run 'WRITE SECTOR/S' command
                    843:  */
1.1.1.14! root      844: static void FDC_UpdateWriteSectorsCmd(void)
1.1       root      845: {
1.1.1.6   root      846:        /* Which command is running? */
                    847:        switch (FDCEmulationRunning)
                    848:        {
                    849:         case FDCEMU_RUN_WRITESECTORS_WRITEDATA:
                    850:                /* Write out a sector */
                    851:                if (FDC_WriteSectorFromFloppy())        /* Write a single sector through DMA */
                    852:                {
                    853:                        /* Decrement FDCsector count */
                    854:                        FDCSectorCountRegister--;           /* Decrement FDCSectorCount */
                    855:                        if (FDCSectorCountRegister<=0)
                    856:                                FDCSectorCountRegister = 0;
                    857: 
                    858:                        /* Have we finished? */
                    859:                        nReadWriteSectors--;
                    860:                        if (nReadWriteSectors<=0)
                    861:                                FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_COMPLETE;
                    862: 
                    863:                        /* Update DMA pointer */
                    864:                        FDC_WriteDMAAddress(FDC_ReadDMAAddress()+NUMBYTESPERSECTOR);
                    865:                }
                    866:                else
                    867:                {
                    868:                        /* Acknowledge interrupt, move along there's nothing more to see */
                    869:                        FDC_AcknowledgeInterrupt();
                    870:                        /* Set error */
1.1.1.12  root      871:                        FDC_SetDMAStatus(true);             /* DMA error */
1.1.1.6   root      872:                        /* Done */
                    873:                        FDCEmulationCommand = FDCEMU_CMD_NULL;
                    874:                        /* Turn motor off */
                    875:                        FDC_TurnMotorOff();
                    876:                }
                    877:                break;
                    878:         case FDCEMU_RUN_WRITESECTORS_COMPLETE:
                    879:                /* Acknowledge interrupt, move along there's nothing more to see */
                    880:                FDC_AcknowledgeInterrupt();
                    881:                /* Set error */
1.1.1.12  root      882:                FDC_SetDMAStatus(false);              /* No DMA error */
1.1.1.6   root      883:                /* Done */
                    884:                FDCEmulationCommand = FDCEMU_CMD_NULL;
                    885:                /* Turn motor off */
                    886:                FDC_TurnMotorOff();
                    887:                break;
                    888:        }
1.1       root      889: }
                    890: 
1.1.1.2   root      891: 
                    892: /*-----------------------------------------------------------------------*/
1.1.1.9   root      893: /**
1.1.1.11  root      894:  * Run 'READ ADDRESS' command
                    895:  */
1.1.1.14! root      896: static void FDC_UpdateReadAddressCmd(void)
1.1.1.11  root      897: {
                    898:        /* Which command is running? */
                    899:        switch (FDCEmulationRunning)
                    900:        {
                    901:         case FDCEMU_RUN_READADDRESS:
                    902:                /* not implemented, just return with no error */
                    903:                FDCEmulationRunning = FDCEMU_RUN_READADDRESS_COMPLETE;
                    904:                break;
                    905:         case FDCEMU_RUN_READADDRESS_COMPLETE:
                    906:                /* Acknowledge interrupt, move along there's nothing more to see */
                    907:                FDC_AcknowledgeInterrupt();
                    908:                /* Set error */
1.1.1.12  root      909:                FDC_SetDMAStatus(false);            /* No DMA error */
1.1.1.11  root      910:                /* Done */
                    911:                FDCEmulationCommand = FDCEMU_CMD_NULL;
                    912:                /* Turn motor off */
                    913:                FDC_TurnMotorOff();
                    914:                break;
                    915:        }
                    916: }
                    917: 
                    918: 
                    919: /*-----------------------------------------------------------------------*/
                    920: /**
1.1.1.9   root      921:  * Type I Commands
                    922:  *
                    923:  * Restore, Seek, Step, Step-In and Step-Out
                    924:  */
1.1       root      925: 
1.1.1.2   root      926: 
                    927: /*-----------------------------------------------------------------------*/
1.1.1.5   root      928: static void FDC_TypeI_Restore(void)
1.1       root      929: {
1.1.1.12  root      930:        int FrameCycles, HblCounterVideo, LineCycles;
                    931: 
                    932:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    933: 
                    934:        LOG_TRACE(TRACE_FDC, "fdc type I restore VBL=%d video_cyc=%d %d@%d pc=%x\n",
                    935:                  nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root      936: 
1.1.1.6   root      937:        /* Set emulation to seek to track zero */
                    938:        FDCEmulationCommand = FDCEMU_CMD_RESTORE;
                    939:        FDCEmulationRunning = FDCEMU_RUN_RESTORE_SEEKTOTRACKZERO;
1.1       root      940: 
1.1.1.7   root      941:        FDC_SetDiskControllerStatus();
1.1       root      942: }
                    943: 
1.1.1.2   root      944: 
                    945: /*-----------------------------------------------------------------------*/
1.1.1.5   root      946: static void FDC_TypeI_Seek(void)
1.1       root      947: {
1.1.1.12  root      948:        int FrameCycles, HblCounterVideo, LineCycles;
                    949: 
                    950:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    951: 
                    952:        LOG_TRACE(TRACE_FDC, "fdc type I seek track=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n",
                    953:                  FDCDataRegister, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root      954: 
1.1.1.6   root      955:        /* Set emulation to seek to chosen track */
                    956:        FDCEmulationCommand = FDCEMU_CMD_SEEK;
                    957:        FDCEmulationRunning = FDCEMU_RUN_SEEK_TOTRACK;
1.1       root      958: 
1.1.1.7   root      959:        FDC_SetDiskControllerStatus();
1.1       root      960: }
                    961: 
1.1.1.2   root      962: 
                    963: /*-----------------------------------------------------------------------*/
1.1.1.5   root      964: static void FDC_TypeI_Step(void)
1.1       root      965: {
1.1.1.12  root      966:        int FrameCycles, HblCounterVideo, LineCycles;
                    967: 
                    968:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    969: 
                    970:        LOG_TRACE(TRACE_FDC, "fdc type I step %d VBL=%d video_cyc=%d %d@%d pc=%x\n",
                    971:                  FDCStepDirection, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root      972: 
1.1.1.6   root      973:        /* Set emulation to step(same direction as last seek executed, eg 'FDCStepDirection') */
                    974:        FDCEmulationCommand = FDCEMU_CMD_STEP;
                    975:        FDCEmulationRunning = FDCEMU_RUN_STEP_ONCE;
1.1       root      976: 
1.1.1.7   root      977:        FDC_SetDiskControllerStatus();
1.1       root      978: }
                    979: 
1.1.1.2   root      980: 
                    981: /*-----------------------------------------------------------------------*/
1.1.1.5   root      982: static void FDC_TypeI_StepIn(void)
1.1       root      983: {
1.1.1.12  root      984:        int FrameCycles, HblCounterVideo, LineCycles;
                    985: 
                    986:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    987: 
                    988:        LOG_TRACE(TRACE_FDC, "fdc type I step in VBL=%d video_cyc=%d %d@%d pc=%x\n",
                    989:                  nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root      990: 
1.1.1.6   root      991:        /* Set emulation to step in(Set 'FDCStepDirection') */
                    992:        FDCEmulationCommand = FDCEMU_CMD_STEPIN;
                    993:        FDCEmulationRunning = FDCEMU_RUN_STEPIN_ONCE;
                    994:        FDCStepDirection = 1;                 /* Increment track*/
1.1       root      995: 
1.1.1.7   root      996:        FDC_SetDiskControllerStatus();
1.1       root      997: }
                    998: 
1.1.1.2   root      999: 
                   1000: /*-----------------------------------------------------------------------*/
1.1.1.5   root     1001: static void FDC_TypeI_StepOut(void)
1.1       root     1002: {
1.1.1.12  root     1003:        int FrameCycles, HblCounterVideo, LineCycles;
                   1004: 
                   1005:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1006: 
                   1007:        LOG_TRACE(TRACE_FDC, "fdc type I step out VBL=%d video_cyc=%d %d@%d pc=%x\n",
                   1008:                  nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root     1009: 
1.1.1.6   root     1010:        /* Set emulation to step out(Set 'FDCStepDirection') */
                   1011:        FDCEmulationCommand = FDCEMU_CMD_STEPOUT;
                   1012:        FDCEmulationRunning = FDCEMU_RUN_STEPOUT_ONCE;
                   1013:        FDCStepDirection = -1;                /* Decrement track */
1.1       root     1014: 
1.1.1.7   root     1015:        FDC_SetDiskControllerStatus();
1.1       root     1016: }
                   1017: 
1.1.1.2   root     1018: 
                   1019: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1020: /**
                   1021:  * Type II Commands
                   1022:  *
                   1023:  * Read Sector, Read Multiple Sectors, Write Sector, Write Multiple Sectors
                   1024:  */
1.1       root     1025: 
1.1.1.2   root     1026: 
                   1027: /*-----------------------------------------------------------------------*/
1.1.1.5   root     1028: static void FDC_TypeII_ReadSector(void)
1.1       root     1029: {
1.1.1.12  root     1030:        int FrameCycles, HblCounterVideo, LineCycles;
                   1031: 
                   1032:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1033: 
                   1034:        LOG_TRACE(TRACE_FDC, "fdc type II read sector %d VBL=%d video_cyc=%d %d@%d pc=%x\n",
                   1035:                  FDCSectorRegister, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root     1036: 
1.1.1.6   root     1037:        /* Set emulation to read a single sector */
                   1038:        FDCEmulationCommand = FDCEMU_CMD_READSECTORS;
                   1039:        FDCEmulationRunning = FDCEMU_RUN_READSECTORS_READDATA;
                   1040:        /* Set reading parameters */
                   1041:        FDC_SetReadWriteParameters(1);        /* Read in a single sector */
1.1       root     1042: 
1.1.1.7   root     1043:        FDC_SetDiskControllerStatus();
1.1       root     1044: }
                   1045: 
1.1.1.2   root     1046: 
                   1047: /*-----------------------------------------------------------------------*/
1.1.1.5   root     1048: static void FDC_TypeII_ReadMultipleSectors(void)
1.1       root     1049: {
1.1.1.12  root     1050:        int FrameCycles, HblCounterVideo, LineCycles;
                   1051: 
                   1052:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1053: 
                   1054:        LOG_TRACE(TRACE_FDC, "fdc type II read multi sectors %d count %d VBL=%d video_cyc=%d %d@%d pc=%x\n",
                   1055:                  FDCSectorRegister, FDCSectorCountRegister, nVBLs,
                   1056:                  FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root     1057: 
1.1.1.6   root     1058:        /* Set emulation to read sectors */
                   1059:        FDCEmulationCommand = FDCEMU_CMD_READMULTIPLESECTORS;
                   1060:        FDCEmulationRunning = FDCEMU_RUN_READSECTORS_READDATA;
                   1061:        /* Set reading parameters */
                   1062:        FDC_SetReadWriteParameters(FDCSectorCountRegister);   /* Read multiple sectors */
1.1       root     1063: 
1.1.1.7   root     1064:        FDC_SetDiskControllerStatus();
1.1       root     1065: }
                   1066: 
1.1.1.2   root     1067: 
                   1068: /*-----------------------------------------------------------------------*/
1.1.1.5   root     1069: static void FDC_TypeII_WriteSector(void)
1.1       root     1070: {
1.1.1.12  root     1071:        int FrameCycles, HblCounterVideo, LineCycles;
                   1072: 
                   1073:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1074: 
                   1075:        LOG_TRACE(TRACE_FDC, "fdc type II write sector %d VBL=%d video_cyc=%d %d@%d pc=%x\n",
                   1076:                  FDCSectorRegister, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root     1077: 
1.1.1.6   root     1078:        /* Set emulation to write a single sector */
                   1079:        FDCEmulationCommand = FDCEMU_CMD_WRITESECTORS;
                   1080:        FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_WRITEDATA;
                   1081:        /* Set writing parameters */
                   1082:        FDC_SetReadWriteParameters(1);                        /* Write out a single sector */
1.1       root     1083: 
1.1.1.7   root     1084:        FDC_SetDiskControllerStatus();
1.1       root     1085: }
                   1086: 
1.1.1.2   root     1087: 
                   1088: /*-----------------------------------------------------------------------*/
1.1.1.5   root     1089: static void FDC_TypeII_WriteMultipleSectors(void)
1.1       root     1090: {
1.1.1.12  root     1091:        int FrameCycles, HblCounterVideo, LineCycles;
                   1092: 
                   1093:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1094: 
                   1095:        LOG_TRACE(TRACE_FDC, "fdc type II write multi sectors %d count %d VBL=%d video_cyc=%d %d@%d pc=%x\n",
                   1096:                  FDCSectorRegister, FDCSectorCountRegister, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root     1097: 
1.1.1.6   root     1098:        /* Set emulation to write sectors */
                   1099:        FDCEmulationCommand = FDCEMU_CMD_WRITEMULTIPLESECTORS;
                   1100:        FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_WRITEDATA;
                   1101:        /* Set witing parameters */
                   1102:        FDC_SetReadWriteParameters(FDCSectorCountRegister);   /* Write multiple sectors */
1.1       root     1103: 
1.1.1.7   root     1104:        FDC_SetDiskControllerStatus();
1.1       root     1105: }
                   1106: 
1.1.1.2   root     1107: 
                   1108: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1109: /**
                   1110:  * Type III Commands
                   1111:  *
                   1112:  * Read Address, Read Track, Write Track
                   1113:  */
1.1       root     1114: 
1.1.1.2   root     1115: 
                   1116: /*-----------------------------------------------------------------------*/
1.1.1.5   root     1117: static void FDC_TypeIII_ReadAddress(void)
1.1       root     1118: {
1.1.1.12  root     1119:        int FrameCycles, HblCounterVideo, LineCycles;
                   1120: 
                   1121:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1122: 
                   1123:        LOG_TRACE(TRACE_FDC, "fdc type III read address unimplemented VBL=%d video_cyc=%d %d@%d pc=%x\n",
                   1124:                  nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root     1125: 
                   1126:        Log_Printf(LOG_TODO, "FDC type III command 'read address' is not implemented yet!\n");
1.1.1.11  root     1127: 
                   1128:        /* Set emulation to seek to track zero */
                   1129:        FDCEmulationCommand = FDCEMU_CMD_READADDRESS;
                   1130:        FDCEmulationRunning = FDCEMU_RUN_READADDRESS;
                   1131: 
                   1132:        FDC_SetDiskControllerStatus();
1.1       root     1133: }
                   1134: 
1.1.1.2   root     1135: 
                   1136: /*-----------------------------------------------------------------------*/
1.1.1.5   root     1137: static void FDC_TypeIII_ReadTrack(void)
1.1       root     1138: {
1.1.1.12  root     1139:        int FrameCycles, HblCounterVideo, LineCycles;
                   1140: 
                   1141:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1142: 
                   1143:        LOG_TRACE(TRACE_FDC, "fdc type III read track 0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n",
                   1144:                  FDCTrackRegister, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root     1145: 
                   1146:        Log_Printf(LOG_TODO, "FDC type III command 'read track' does not work yet!\n");
1.1.1.5   root     1147: 
1.1.1.6   root     1148:        /* FIXME: "Read track" should read more than only the sectors! (also sector headers, gaps, etc.) */
1.1.1.5   root     1149: 
1.1.1.6   root     1150:        /* Set emulation to read a single track */
                   1151:        FDCEmulationCommand = FDCEMU_CMD_READSECTORS;
                   1152:        FDCEmulationRunning = FDCEMU_RUN_READSECTORS_READDATA;
                   1153:        /* Set reading parameters */
                   1154:        FDC_SetReadWriteParameters(nReadWriteSectorsPerTrack);  /* Read whole track */
1.1       root     1155: 
1.1.1.7   root     1156:        FDC_SetDiskControllerStatus();
1.1       root     1157: }
                   1158: 
1.1.1.2   root     1159: 
                   1160: /*-----------------------------------------------------------------------*/
1.1.1.5   root     1161: static void FDC_TypeIII_WriteTrack(void)
1.1       root     1162: {
1.1.1.12  root     1163:        int FrameCycles, HblCounterVideo, LineCycles;
                   1164: 
                   1165:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1166: 
                   1167:        LOG_TRACE(TRACE_FDC, "fdc type III write track 0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n",
                   1168:                  FDCTrackRegister, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root     1169: 
                   1170:        Log_Printf(LOG_TODO, "FDC type III command 'write track' does not work yet!\n");
1.1.1.5   root     1171: 
1.1.1.6   root     1172:        /* FIXME: "Write track" not only writes the sectors! (also sector headers, gaps, etc.) */
1.1.1.5   root     1173: 
1.1.1.6   root     1174:        /* Set emulation to write a single track */
                   1175:        FDCEmulationCommand = FDCEMU_CMD_WRITESECTORS;
                   1176:        FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_WRITEDATA;
                   1177:        /* Set writing parameters */
                   1178:        FDC_SetReadWriteParameters(nReadWriteSectorsPerTrack);  /* Write whole track */
1.1       root     1179: 
1.1.1.7   root     1180:        FDC_SetDiskControllerStatus();
1.1       root     1181: }
                   1182: 
1.1.1.2   root     1183: 
                   1184: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1185: /**
                   1186:  * Type IV Commands
                   1187:  *
                   1188:  * Force Interrupt
                   1189:  */
1.1       root     1190: 
1.1.1.2   root     1191: 
                   1192: /*-----------------------------------------------------------------------*/
1.1.1.10  root     1193: static void FDC_TypeIV_ForceInterrupt(bool bCauseCPUInterrupt)
1.1       root     1194: {
1.1.1.12  root     1195:        int FrameCycles, HblCounterVideo, LineCycles;
                   1196: 
                   1197:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1198: 
                   1199:        LOG_TRACE(TRACE_FDC, "fdc type IV force int VBL=%d video_cyc=%d %d@%dpc=%x\n",
                   1200:                  nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.10  root     1201: 
1.1.1.6   root     1202:        /* Acknowledge interrupt, move along there's nothing more to see */
                   1203:        if (bCauseCPUInterrupt)
                   1204:                FDC_AcknowledgeInterrupt();
                   1205: 
                   1206:        /* Reset FDC */
                   1207:        FDCEmulationCommand = FDCEMU_CMD_NULL;
                   1208:        FDCEmulationRunning = FDCEMU_RUN_NULL;
1.1       root     1209: }
                   1210: 
1.1.1.2   root     1211: 
                   1212: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1213: /**
                   1214:  * Execute Type I commands
                   1215:  */
1.1.1.5   root     1216: static void FDC_ExecuteTypeICommands(void)
1.1       root     1217: {
1.1.1.6   root     1218:        MFP_GPIP |= 0x20;
1.1       root     1219: 
1.1.1.6   root     1220:        /* Check Type I Command */
                   1221:        switch(FDCCommandRegister&0xf0)
                   1222:        {
                   1223:         case 0x00:             /* Restore */
                   1224:                FDC_TypeI_Restore();
                   1225:                break;
                   1226:         case 0x10:             /* Seek */
                   1227:                FDC_TypeI_Seek();
                   1228:                break;
                   1229:         case 0x20:             /* Step */
                   1230:         case 0x30:
                   1231:                FDC_TypeI_Step();
                   1232:                break;
                   1233:         case 0x40:             /* Step-In */
                   1234:         case 0x50:
                   1235:                FDC_TypeI_StepIn();
                   1236:                break;
                   1237:         case 0x60:             /* Step-Out */
                   1238:         case 0x70:
                   1239:                FDC_TypeI_StepOut();
                   1240:                break;
                   1241:        }
1.1       root     1242: 
1.1.1.6   root     1243:        /* Signal motor on as we need to execute command */
                   1244:        FDC_TurnMotorOn();
1.1       root     1245: }
                   1246: 
1.1.1.2   root     1247: 
                   1248: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1249: /**
                   1250:  * Execute Type II commands
                   1251:  */
1.1.1.5   root     1252: static void FDC_ExecuteTypeIICommands(void)
1.1       root     1253: {
1.1.1.6   root     1254:        MFP_GPIP |= 0x20;
1.1       root     1255: 
1.1.1.6   root     1256:        /* Check Type II Command */
                   1257:        switch(FDCCommandRegister&0xf0)
                   1258:        {
                   1259:         case 0x80:             /* Read Sector */
                   1260:                FDC_TypeII_ReadSector();
                   1261:                break;
                   1262:         case 0x90:             /* Read Sectors */
                   1263:                FDC_TypeII_ReadMultipleSectors();
                   1264:                break;
                   1265:         case 0xa0:             /* Write Sector */
                   1266:                FDC_TypeII_WriteSector();
                   1267:                break;
                   1268:         case 0xb0:             /* Write Sectors */
                   1269:                FDC_TypeII_WriteMultipleSectors();
                   1270:                break;
                   1271:        }
1.1       root     1272: 
1.1.1.6   root     1273:        /* Signal motor on as we need to execute command */
                   1274:        FDC_TurnMotorOn();
1.1       root     1275: }
                   1276: 
1.1.1.2   root     1277: 
                   1278: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1279: /**
                   1280:  * Execute Type III commands
                   1281:  */
1.1.1.5   root     1282: static void FDC_ExecuteTypeIIICommands(void)
1.1       root     1283: {
1.1.1.6   root     1284:        MFP_GPIP |= 0x20;
1.1       root     1285: 
1.1.1.6   root     1286:        /* Check Type III Command */
                   1287:        switch(FDCCommandRegister&0xf0)
                   1288:        {
                   1289:         case 0xc0:             /* Read Address */
                   1290:                FDC_TypeIII_ReadAddress();
                   1291:                break;
                   1292:         case 0xe0:             /* Read Track */
                   1293:                FDC_TypeIII_ReadTrack();
                   1294:                break;
                   1295:         case 0xf0:             /* Write Track */
                   1296:                FDC_TypeIII_WriteTrack();
                   1297:                break;
                   1298:        }
1.1       root     1299: 
1.1.1.6   root     1300:        /* Signal motor on as we need to execute command */
                   1301:        FDC_TurnMotorOn();
1.1       root     1302: }
                   1303: 
1.1.1.2   root     1304: 
                   1305: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1306: /**
                   1307:  * Execute Type IV commands
                   1308:  */
1.1.1.5   root     1309: static void FDC_ExecuteTypeIVCommands(void)
1.1       root     1310: {
1.1.1.6   root     1311:        if (FDCCommandRegister!=0xD8)           /* Is an 'immediate interrupt command'? don't reset interrupt */
                   1312:                MFP_GPIP |= 0x20;
1.1       root     1313: 
1.1.1.6   root     1314:        /* Check Type IV Command */
                   1315:        if ((FDCCommandRegister&0x0c) == 0)     /* I3 and I2 are clear? If so we don't need a CPU interrupt */
1.1.1.12  root     1316:                FDC_TypeIV_ForceInterrupt(false);   /* Force Interrupt - no interrupt */
1.1.1.6   root     1317:        else
1.1.1.12  root     1318:                FDC_TypeIV_ForceInterrupt(true);    /* Force Interrupt */
1.1       root     1319: }
                   1320: 
1.1.1.2   root     1321: 
                   1322: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1323: /**
                   1324:  * Find FDC command type and execute
                   1325:  */
1.1.1.5   root     1326: static void FDC_ExecuteCommand(void)
1.1       root     1327: {
1.1.1.6   root     1328:        /* Check type of command and execute */
                   1329:        if ((FDCCommandRegister&0x80) == 0)           /* Type I - Restore,Seek,Step,Step-In,Step-Out */
                   1330:                FDC_ExecuteTypeICommands();
                   1331:        else if ((FDCCommandRegister&0x40) == 0)      /* Type II - Read Sector, Write Sector */
                   1332:                FDC_ExecuteTypeIICommands();
                   1333:        else if ((FDCCommandRegister&0xf0) != 0xd0)   /* Type III - Read Address, Read Track, Write Track */
                   1334:                FDC_ExecuteTypeIIICommands();
                   1335:        else                                          /* Type IV - Force Interrupt */
                   1336:                FDC_ExecuteTypeIVCommands();
1.1.1.9   root     1337: 
1.1.1.13  root     1338:        CycInt_AddAbsoluteInterrupt(FDC_DELAY_CYCLES,  INT_CPU_CYCLE, INTERRUPT_FDC);
1.1       root     1339: }
                   1340: 
1.1.1.2   root     1341: 
                   1342: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1343: /**
                   1344:  * Write to SectorCount register (WR 0xff8604)
                   1345:  */
1.1.1.5   root     1346: static void FDC_WriteSectorCountRegister(void)
1.1       root     1347: {
1.1.1.12  root     1348:        int FrameCycles, HblCounterVideo, LineCycles;
                   1349: 
                   1350:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1351: 
                   1352:        LOG_TRACE(TRACE_FDC, "fdc write 8604 sector count=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n",
                   1353:                  DiskControllerWord_ff8604wr, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.9   root     1354: 
1.1.1.7   root     1355:        FDCSectorCountRegister = DiskControllerWord_ff8604wr;
1.1       root     1356: }
                   1357: 
1.1.1.2   root     1358: 
                   1359: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1360: /**
                   1361:  * Write to Command register (WR 0xff8604)
                   1362:  */
1.1.1.5   root     1363: static void FDC_WriteCommandRegister(void)
1.1       root     1364: {
1.1.1.12  root     1365:        int FrameCycles, HblCounterVideo, LineCycles;
                   1366: 
                   1367:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1368: 
                   1369:        LOG_TRACE(TRACE_FDC, "fdc write 8604 command=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n",
                   1370:                  DiskControllerWord_ff8604wr, nVBLs, FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC());
1.1.1.9   root     1371: 
1.1.1.7   root     1372:        FDCCommandRegister = DiskControllerWord_ff8604wr;
1.1.1.6   root     1373:        /* And execute */
                   1374:        FDC_ExecuteCommand();
1.1       root     1375: }
                   1376: 
1.1.1.2   root     1377: 
                   1378: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1379: /**
                   1380:  * Write to Track register (WR 0xff8604)
                   1381:  */
1.1.1.5   root     1382: static void FDC_WriteTrackRegister(void)
1.1       root     1383: {
1.1.1.12  root     1384:        int FrameCycles, HblCounterVideo, LineCycles;
                   1385: 
                   1386:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1387: 
                   1388:        LOG_TRACE(TRACE_FDC, "fdc write 8604 track=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
                   1389:                DiskControllerWord_ff8604wr , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9   root     1390: 
1.1.1.10  root     1391:        FDCTrackRegister = DiskControllerWord_ff8604wr & 0xff;  /* 0...79 */
1.1       root     1392: }
                   1393: 
1.1.1.2   root     1394: 
                   1395: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1396: /**
                   1397:  * Write to Track register (WR 0xff8604)
                   1398:  */
1.1.1.5   root     1399: static void FDC_WriteSectorRegister(void)
1.1       root     1400: {
1.1.1.12  root     1401:        int FrameCycles, HblCounterVideo, LineCycles;
                   1402: 
                   1403:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1404: 
                   1405:        LOG_TRACE(TRACE_FDC, "fdc write 8604 sector=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
                   1406:                DiskControllerWord_ff8604wr , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9   root     1407: 
1.1.1.10  root     1408:        FDCSectorRegister = DiskControllerWord_ff8604wr & 0xff; /* 1,2,3..... */
1.1       root     1409: }
                   1410: 
1.1.1.2   root     1411: 
                   1412: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1413: /**
                   1414:  * Write to Data register (WR 0xff8604)
                   1415:  */
1.1.1.5   root     1416: static void FDC_WriteDataRegister(void)
1.1       root     1417: {
1.1.1.12  root     1418:        int FrameCycles, HblCounterVideo, LineCycles;
                   1419: 
                   1420:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1421: 
                   1422:        LOG_TRACE(TRACE_FDC, "fdc write 8604 data=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
                   1423:                DiskControllerWord_ff8604wr , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9   root     1424: 
1.1.1.10  root     1425:        FDCDataRegister = DiskControllerWord_ff8604wr & 0xff;
1.1       root     1426: }
                   1427: 
1.1.1.2   root     1428: 
                   1429: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1430: /**
                   1431:  * Store byte in FDC registers, when write to 0xff8604
                   1432:  */
1.1.1.7   root     1433: void FDC_DiskController_WriteWord(void)
1.1       root     1434: {
1.1.1.12  root     1435:        int FrameCycles, HblCounterVideo, LineCycles;
                   1436: 
1.1.1.6   root     1437:        if (nIoMemAccessSize == SIZE_BYTE)
                   1438:        {
                   1439:                /* This register does not like to be accessed in byte mode on a normal ST */
1.1.1.8   root     1440:                M68000_BusError(IoAccessBaseAddress, BUS_ERROR_WRITE);
1.1.1.6   root     1441:                return;
                   1442:        }
                   1443: 
1.1.1.8   root     1444:        M68000_WaitState(4);
                   1445: 
1.1.1.7   root     1446:        DiskControllerWord_ff8604wr = IoMem_ReadWord(0xff8604);
1.1.1.6   root     1447: 
1.1.1.12  root     1448:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1.1.1.9   root     1449: 
1.1.1.12  root     1450:        LOG_TRACE(TRACE_FDC, "fdc write 8604 data=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
                   1451:                DiskControllerWord_ff8604wr , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.6   root     1452: 
1.1.1.12  root     1453:        /* Is it an ASCII HD command? */
1.1.1.8   root     1454:        if ((DMAModeControl_ff8606wr & 0x0018) == 8)
1.1.1.12  root     1455:        {
                   1456:                /*  Handle HDC functions */
                   1457:                HDC_WriteCommandPacket();
1.1.1.10  root     1458:                return;
1.1.1.12  root     1459:        }
1.1.1.6   root     1460: 
                   1461:        /* Are we trying to set the SectorCount? */
                   1462:        if (DMAModeControl_ff8606wr&0x10)         /* Bit 4 */
                   1463:                FDC_WriteSectorCountRegister();
                   1464:        else
1.1.1.8   root     1465:        {
                   1466:                /* Write to FDC registers */
1.1.1.6   root     1467:                switch(DMAModeControl_ff8606wr&0x6)
                   1468:                {   /* Bits 1,2 (A1,A0) */
                   1469:                 case 0x0:                            /* 0 0 - Command register */
                   1470:                        FDC_WriteCommandRegister();
                   1471:                        break;
                   1472:                 case 0x2:                            /* 0 1 - Track register */
                   1473:                        FDC_WriteTrackRegister();
                   1474:                        break;
                   1475:                 case 0x4:                            /* 1 0 - Sector register */
                   1476:                        FDC_WriteSectorRegister();
                   1477:                        break;
                   1478:                 case 0x6:                            /* 1 1 - Data register */
                   1479:                        FDC_WriteDataRegister();
                   1480:                        break;
                   1481:                }
                   1482:        }
1.1       root     1483: }
                   1484: 
1.1.1.2   root     1485: 
                   1486: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1487: /**
                   1488:  * Read Status/FDC registers, when read from 0xff8604
                   1489:  * Return 'DiskControllerByte'
                   1490:  */
1.1.1.7   root     1491: void FDC_DiskControllerStatus_ReadWord(void)
1.1       root     1492: {
1.1.1.7   root     1493:        Sint16 DiskControllerByte = 0;            /* Used to pass back the parameter */
1.1.1.12  root     1494:        int FrameCycles, HblCounterVideo, LineCycles;
                   1495: 
1.1.1.6   root     1496: 
                   1497:        if (nIoMemAccessSize == SIZE_BYTE)
                   1498:        {
                   1499:                /* This register does not like to be accessed in byte mode on a normal ST */
1.1.1.8   root     1500:                M68000_BusError(IoAccessBaseAddress, BUS_ERROR_READ);
1.1.1.6   root     1501:                return;
                   1502:        }
                   1503: 
1.1.1.8   root     1504:        M68000_WaitState(4);
                   1505: 
                   1506:        if ((DMAModeControl_ff8606wr & 0x18) == 0x08)     /* HDC status reg selected? */
1.1.1.6   root     1507:        {
                   1508:                /* return the HDC status reg */
1.1.1.7   root     1509:                DiskControllerByte = HDCCommand.returnCode;
1.1.1.6   root     1510:        }
1.1.1.8   root     1511:        else if ((DMAModeControl_ff8606wr & 0x18) == 0x18)  /* HDC sector counter??? */
                   1512:        {
                   1513:                Log_Printf(LOG_DEBUG, "*** Read HDC sector counter???\n");
                   1514:                DiskControllerByte = HDCSectorCount;
                   1515:        }
1.1.1.6   root     1516:        else
                   1517:        {
                   1518:                /* old FDC code */
                   1519:                switch (DMAModeControl_ff8606wr&0x6)      /* Bits 1,2 (A1,A0) */
                   1520:                {
                   1521:                 case 0x0:                               /* 0 0 - Status register */
1.1.1.7   root     1522:                        DiskControllerByte = DiskControllerStatus_ff8604rd;
1.1.1.6   root     1523:                        if (bMotorOn)
1.1.1.7   root     1524:                                DiskControllerByte |= 0x80;
1.1.1.6   root     1525: 
                   1526:                        if (Floppy_IsWriteProtected(nReadWriteDev))
1.1.1.7   root     1527:                                DiskControllerByte |= 0x40;
1.1.1.6   root     1528: 
                   1529:                        if (EmulationDrives[nReadWriteDev].bMediaChanged)
                   1530:                        {
                   1531:                                /* Some games apparently poll the write-protection signal to check
                   1532:                                 * for disk image changes (the signal seems to change when you
                   1533:                                 * exchange disks on a real ST). We now also simulate this behaviour
                   1534:                                 * here, so that these games can continue with the other disk. */
1.1.1.7   root     1535:                                DiskControllerByte ^= 0x40;
1.1.1.12  root     1536:                                EmulationDrives[nReadWriteDev].bMediaChanged = false;
1.1.1.6   root     1537:                        }
                   1538: 
                   1539:                        /* Reset FDC GPIP */
                   1540:                        MFP_GPIP |= 0x20;
                   1541:                        break;
                   1542:                 case 0x2:                               /* 0 1 - Track register */
1.1.1.7   root     1543:                        DiskControllerByte = FDCTrackRegister;
1.1.1.6   root     1544:                        break;
                   1545:                 case 0x4:                               /* 1 0 - Sector register */
1.1.1.7   root     1546:                        DiskControllerByte = FDCSectorRegister;
1.1.1.6   root     1547:                        break;
                   1548:                 case 0x6:                               /* 1 1 - Data register */
1.1.1.7   root     1549:                        DiskControllerByte = FDCDataRegister;
1.1.1.6   root     1550:                        break;
                   1551:                }
                   1552:        }
                   1553: 
1.1.1.7   root     1554:        IoMem_WriteWord(0xff8604, DiskControllerByte);
1.1.1.9   root     1555: 
1.1.1.12  root     1556:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1557: 
                   1558:        LOG_TRACE(TRACE_FDC, "fdc read 8604 ctrl status=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
                   1559:                DiskControllerByte , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1       root     1560: }
                   1561: 
1.1.1.2   root     1562: 
                   1563: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1564: /**
                   1565:  * Read DMA address from ST's RAM (always up-to-date)
                   1566:  */
1.1.1.6   root     1567: Uint32 FDC_ReadDMAAddress(void)
1.1       root     1568: {
1.1.1.6   root     1569:        Uint32 Address;
1.1       root     1570: 
1.1.1.6   root     1571:        /* Build up 24-bit address from hardware registers */
                   1572:        Address = ((Uint32)STMemory_ReadByte(0xff8609)<<16) | ((Uint32)STMemory_ReadByte(0xff860b)<<8) | (Uint32)STMemory_ReadByte(0xff860d);
1.1       root     1573: 
1.1.1.6   root     1574:        return Address;
1.1       root     1575: }
                   1576: 
1.1.1.2   root     1577: 
                   1578: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1579: /**
                   1580:  * Write DMA address to ST's RAM(always keep up-to-date)
                   1581:  */
1.1.1.6   root     1582: void FDC_WriteDMAAddress(Uint32 Address)
1.1       root     1583: {
1.1.1.12  root     1584:        int FrameCycles, HblCounterVideo, LineCycles;
                   1585: 
                   1586:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1587: 
                   1588:        LOG_TRACE(TRACE_FDC, "fdc write 0x%x to dma address VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
                   1589:                Address , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9   root     1590: 
1.1.1.6   root     1591:        /* Store as 24-bit address */
                   1592:        STMemory_WriteByte(0xff8609, Address>>16);
                   1593:        STMemory_WriteByte(0xff860b, Address>>8);
                   1594:        STMemory_WriteByte(0xff860d, Address);
1.1       root     1595: }
                   1596: 
1.1.1.2   root     1597: 
                   1598: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1599: /**
                   1600:  * Read sector from floppy drive into workspace
                   1601:  * We copy the bytes in chunks to simulate reading of the floppy using DMA
                   1602:  */
1.1.1.14! root     1603: static bool FDC_ReadSectorFromFloppy(void)
1.1       root     1604: {
1.1.1.12  root     1605:        int FrameCycles, HblCounterVideo, LineCycles;
                   1606: 
                   1607:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1608: 
                   1609:        LOG_TRACE(TRACE_FDC, "fdc read sector addr=0x%x dev=%d sect=%d track=%d side=%d VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
                   1610:                FDC_ReadDMAAddress(), nReadWriteDev, nReadWriteSector, nReadWriteTrack, nReadWriteSide,
                   1611:                nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9   root     1612: 
1.1.1.6   root     1613:        /* Copy in 1 sector to our workspace */
1.1.1.7   root     1614:        if (Floppy_ReadSectors(nReadWriteDev, DMASectorWorkSpace, nReadWriteSector, nReadWriteTrack, nReadWriteSide, 1, NULL))
1.1.1.6   root     1615:        {
                   1616:                /* Update reading/writing parameters */
                   1617:                nReadWriteSector++;
                   1618:                if (nReadWriteSector > nReadWriteSectorsPerTrack)   /* Advance into next track? */
                   1619:                {
                   1620:                        nReadWriteSector = 1;
                   1621:                        nReadWriteTrack++;
                   1622:                }
1.1.1.12  root     1623:                return true;
1.1.1.6   root     1624:        }
1.1       root     1625: 
1.1.1.6   root     1626:        /* Failed */
1.1.1.12  root     1627:        LOG_TRACE(TRACE_FDC, "fdc read sector failed\n" );
                   1628:        return false;
1.1       root     1629: }
                   1630: 
1.1.1.2   root     1631: 
                   1632: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1633: /**
                   1634:  * Write sector from workspace to floppy drive
                   1635:  * We copy the bytes in chunks to simulate writing of the floppy using DMA
                   1636:  */
1.1.1.14! root     1637: static bool FDC_WriteSectorFromFloppy(void)
1.1       root     1638: {
1.1.1.6   root     1639:        Uint32 Address;
1.1.1.12  root     1640:        int FrameCycles, HblCounterVideo, LineCycles;
                   1641: 
1.1       root     1642: 
1.1.1.6   root     1643:        /* Get DMA address */
                   1644:        Address = FDC_ReadDMAAddress();
1.1       root     1645: 
1.1.1.12  root     1646:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1647: 
                   1648:        LOG_TRACE(TRACE_FDC, "fdc write sector addr=0x%x dev=%d sect=%d track=%d side=%d VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
                   1649:                Address, nReadWriteDev, nReadWriteSector, nReadWriteTrack, nReadWriteSide,
                   1650:                nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9   root     1651: 
1.1.1.6   root     1652:        /* Write out 1 sector from our workspace */
                   1653:        if (Floppy_WriteSectors(nReadWriteDev, &STRam[Address], nReadWriteSector, nReadWriteTrack, nReadWriteSide, 1, NULL))
                   1654:        {
                   1655:                /* Update reading/writing parameters */
                   1656:                nReadWriteSector++;
                   1657:                if (nReadWriteSector > nReadWriteSectorsPerTrack)   /* Advance to next track? */
                   1658:                {
                   1659:                        nReadWriteSector = 1;
                   1660:                        nReadWriteTrack++;
                   1661:                }
1.1.1.12  root     1662:                return true;
1.1.1.6   root     1663:        }
1.1       root     1664: 
1.1.1.6   root     1665:        /* Failed */
1.1.1.12  root     1666:        LOG_TRACE(TRACE_FDC, "fdc write sector failed\n" );
                   1667:        return false;
1.1       root     1668: }
                   1669: 
                   1670: 
1.1.1.2   root     1671: /*-----------------------------------------------------------------------*/
1.1.1.9   root     1672: /**
                   1673:  * Write word to 0xff8606 (DMA Mode Control)
1.1.1.10  root     1674:  *
1.1.1.9   root     1675:  * Eg.
                   1676:  * $80 - Selects command/status register
                   1677:  * $82 - Selects track register
                   1678:  * $84 - Selects sector register
                   1679:  * $86 - Selects data regsiter
                   1680:  * NOTE - OR above values with $100 is transfer from memory to floppy
                   1681:  * Also if bit 4 is set, write to sector count register
                   1682:  */
1.1.1.6   root     1683: void FDC_DmaModeControl_WriteWord(void)
1.1       root     1684: {
1.1.1.6   root     1685:        Uint16 DMAModeControl_ff8606wr_prev;                     /* stores previous write to 0xff8606 for 'toggle' checks */
1.1.1.12  root     1686:        int FrameCycles, HblCounterVideo, LineCycles;
                   1687: 
1.1       root     1688: 
1.1.1.6   root     1689:        if (nIoMemAccessSize == SIZE_BYTE)
                   1690:        {
                   1691:                /* This register does not like to be accessed in byte mode on a normal ST */
1.1.1.8   root     1692:                M68000_BusError(IoAccessBaseAddress, BUS_ERROR_WRITE);
1.1.1.6   root     1693:                return;
                   1694:        }
                   1695: 
                   1696:        DMAModeControl_ff8606wr_prev = DMAModeControl_ff8606wr;  /* Store previous to check for _read/_write toggle (DMA reset) */
                   1697:        DMAModeControl_ff8606wr = IoMem_ReadWord(0xff8606);      /* Store to DMA Mode control */
                   1698: 
1.1.1.12  root     1699:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   1700: 
                   1701:        LOG_TRACE(TRACE_FDC, "fdc write 8606 ctrl=0x%x VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
                   1702:                DMAModeControl_ff8606wr , nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
1.1.1.9   root     1703: 
1.1.1.6   root     1704:        /* When write to 0xff8606, check bit '8' toggle. This causes DMA status reset */
                   1705:        if ((DMAModeControl_ff8606wr_prev ^ DMAModeControl_ff8606wr) & 0x0100)
                   1706:                FDC_ResetDMAStatus();
                   1707: }
1.1.1.9   root     1708: 
                   1709: 
                   1710: /*-----------------------------------------------------------------------*/
                   1711: /**
                   1712:  * Write to floppy mode/control (?) register (0xff860F).
                   1713:  * Used on Falcon only!
                   1714:  * FIXME: I've found hardly any documentation about this register, only
                   1715:  * the following description of the bits:
                   1716:  *
                   1717:  *   __________54__10  Floppy Controll-Register
                   1718:  *             ||  ||
                   1719:  *             ||  |+- Prescaler 1
                   1720:  *             ||  +-- Media detect 1
                   1721:  *             |+----- Prescaler 2
                   1722:  *             +------ Media detect 2
                   1723:  *
                   1724:  * For DD - disks:  0x00
                   1725:  * For HD - disks:  0x03
                   1726:  * for ED - disks:  0x30 (not supported by TOS)
                   1727:  */
                   1728: void FDC_FloppyMode_WriteByte(void)
                   1729: {
                   1730:        // printf("Write to floppy mode reg.: 0x%02x\n", IoMem_ReadByte(0xff860f));
                   1731: }
                   1732: 
                   1733: 
                   1734: /*-----------------------------------------------------------------------*/
                   1735: /**
                   1736:  * Read from floppy mode/control (?) register (0xff860F).
                   1737:  * Used on Falcon only!
                   1738:  * FIXME: I've found hardly any documentation about this register, only
                   1739:  * the following description of the bits:
                   1740:  *
                   1741:  *   ________76543210  Floppy Controll-Register
                   1742:  *           ||||||||
                   1743:  *           |||||||+- Prescaler 1
                   1744:  *           ||||||+-- Mode select 1
                   1745:  *           |||||+--- Media detect 1
                   1746:  *           ||||+---- accessed during DMA transfers (?)
                   1747:  *           |||+----- Prescaler 2
                   1748:  *           ||+------ Mode select 2
                   1749:  *           |+------- Media detect 2
                   1750:  *           +-------- Disk changed
                   1751:  */
                   1752: void FDC_FloppyMode_ReadByte(void)
                   1753: {
                   1754:        IoMem_WriteByte(0xff860f, 0x80);  // FIXME: Is this ok?
                   1755:        // printf("Read from floppy mode reg.: 0x%02x\n", IoMem_ReadByte(0xff860f));
                   1756: }

unix.superglobalmegacorp.com

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