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

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

unix.superglobalmegacorp.com

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