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

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

unix.superglobalmegacorp.com

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