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

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

unix.superglobalmegacorp.com

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