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

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

unix.superglobalmegacorp.com

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