Example #1
0
        private bool TrackWriteByteProcess()
        {
            // stop operation at the next index pulse
            bool index_pulse_state = IsIndexPulse();

            if (index_pulse_state != m_prev_index_pulse_state && index_pulse_state)
            {
                m_operation_state = OperationState.None;
                m_fdc_status     &= ~StatusFlags.BUSY;
                m_reg_hw_status  |= HardwareFlags.INT;
                //m_fdc_status_mode = 1;
                Debug.WriteLine(" END");
            }
            m_prev_index_pulse_state = index_pulse_state;

            int byte_count = TickToByteIndex(m_tvcomputer.GetTicksSince(m_operation_start_tick));

            if (byte_count > m_data_count)
            {
                m_data_count++;
                m_reg_hw_status |= HardwareFlags.DRQ;

                return(true);
            }

            return(false);
        }
Example #2
0
        /// <summary>
        /// Starts head moving operaton in emulated speed (lengthty) or fast mode (immediate).
        /// </summary>
        /// <param name="in_delay_us">Operation length in us</param>
        /// <param name="in_new_status_flags">New status flag after the operation is complete</param>
        /// <param name="in_new_hardware_flags">New hardware status flag after the operation is complete</param>
        /// <param name="in_new_track">Track register value after the operation is complete</param>
        private void StartOperation(int in_delay_us, StatusFlags in_new_status_flags, HardwareFlags in_new_hardware_flags, byte in_new_track)
        {
            if (m_fast_operation)
            {
                // no delay -> immediately execute the operation
                m_fdc_status    = in_new_status_flags;
                m_reg_hw_status = in_new_hardware_flags;
                m_fdc_track     = in_new_track;

                m_operation_state = OperationState.None;
            }
            else
            {
                // start delaying operation
                m_fdc_status |= StatusFlags.BUSY;

                m_pending_status    = in_new_status_flags;
                m_pending_hw_status = in_new_hardware_flags;
                m_pending_track     = in_new_track;

                m_pending_delay = m_tvcomputer.MicrosecToCPUTicks(in_delay_us);

                m_operation_state = OperationState.Seek;
            }
        }
Example #3
0
        public void PeriodicCallback(ulong in_cpu_tick)
        {
            switch (m_operation_state)
            {
            // Type I operation (seek)
            case OperationState.Seek:
                if (m_tvcomputer.GetTicksSince(m_operation_start_tick) > m_pending_delay)
                {
                    // operation delay time is expired
                    m_fdc_status    = m_pending_status;
                    m_reg_hw_status = m_pending_hw_status;
                    m_fdc_track     = m_pending_track;

                    m_disk_drives[m_current_drive_index].Track = m_pending_track;

                    m_operation_state = OperationState.None;
                }
                break;
            }
        }
Example #4
0
        /** Write1793() **********************************************/
        /** Write value V into WD1793 register A. Returns DRQ/IRQ   **/
        /** values.                                                 **/
        /*************************************************************/
        public void PortWrite(ushort in_address, byte in_value)
        {
            if ((in_address & 0x0f) != 8)
            {
                if ((in_address & 0x0f) == 3)
                {
                    //Debug.Write(in_value.ToString("X2") + " ");
                }
                else
                {
                    Debug.Write((in_address & 0x0f).ToString("X2") + ":" + in_value.ToString("X2") + " = ");
                }
            }

            switch (in_address & 0x0f)
            {
            // command address
            case PORT_COMMAND:
                m_fdc_command = in_value;

                // Reset interrupt request
                m_reg_hw_status &= ~(HardwareFlags.INT);

                // If it is FORCE-IRQ command...
                if ((in_value & 0xF0) == 0xD0)
                {
                    m_force_interrupt = (ForceInterruptFlags)(in_value & 0x0f);

                    Debug.WriteLine("Force interrupt: {0}", m_force_interrupt);

                    // Reset any executing command
                    m_data_length     = 0;
                    m_data_count      = 0;
                    m_operation_state = OperationState.None;

                    // Either reset BUSY flag or reset all flags if BUSY=0
                    if ((m_fdc_status & StatusFlags.BUSY) != 0)
                    {
                        m_fdc_status &= ~StatusFlags.BUSY;
                    }
                    else
                    {
                        m_fdc_status      = m_disk_drives[m_current_drive_index].Track == 0 ? StatusFlags.TRACK0 : 0;
                        m_fdc_status_mode = 1;
                    }

                    // Cause immediate interrupt if requested
                    if ((in_value & (byte)CommandFlags.IRQ) != 0)
                    {
                        m_reg_hw_status = HardwareFlags.INT;
                    }

                    // Done
                    return;
                }

                // If busy, drop out
                if ((m_fdc_status & StatusFlags.BUSY) != 0)
                {
                    break;
                }

                // Reset status register
                m_fdc_status    = 0x00;
                m_reg_hw_status = 0x00;

                // Depending on the command...
                switch (in_value & 0xF0)
                {
                // RESTORE (seek track 0)
                case 0x00:
                    Debug.WriteLine("Restore");

                    // command group I
                    m_fdc_status_mode = 1;

                    // set head load
                    m_head_loaded = ((in_value & (byte)CommandFlags.LOADHEAD) != 0);

                    m_fdc_last_step_direction = 0;

                    // if already at track zero
                    if (m_disk_drives[m_current_drive_index].Track == 0)
                    {
                        m_fdc_status     |= StatusFlags.TRACK0;
                        m_reg_hw_status  |= HardwareFlags.INT;
                        m_fdc_track       = 0;
                        m_operation_state = OperationState.None;
                    }
                    else
                    {
                        // not on the first track -> start operation
                        StartOperation((m_disk_drives[m_current_drive_index].Geometry.NumberOfTracks / 2) * SteppingDelays[in_value & (byte)CommandFlags.STEPRATE], StatusFlags.TRACK0 | (StatusFlags)(((in_value & (byte)CommandFlags.LOADHEAD) != 0) ? StatusFlags.HEADLOAD : 0), HardwareFlags.INT, 0);
                    }
                    break;

                // SEEK command
                case 0x10:
                    Debug.WriteLine("Seek: {0:x2}", m_fdc_data);

                    // command group I
                    m_fdc_status_mode = 1;

                    // set head load
                    m_head_loaded = ((in_value & (byte)CommandFlags.LOADHEAD) != 0);

                    if (m_fdc_data > m_fdc_track)
                    {
                        m_fdc_last_step_direction = 0;
                    }
                    else
                    {
                        m_fdc_last_step_direction = 0x20;
                    }

                    // Reset any executing command
                    m_data_count  = 0;
                    m_data_length = 0;

                    StartOperation(Math.Abs((int)m_fdc_data - (int)m_fdc_track) * SteppingDelays[in_value & (byte)CommandFlags.STEPRATE], (StatusFlags)(((in_value & (byte)CommandFlags.LOADHEAD) != 0) ? StatusFlags.HEADLOAD : 0), HardwareFlags.INT, m_fdc_data);
                    break;

                case 0x20: // STEP
                case 0x30: // STEP-AND-UPDATE
                case 0x40: // STEP-IN
                case 0x50: // STEP-IN-AND-UPDATE
                case 0x60: // STEP-OUT
                case 0x70: // STEP-OUT-AND-UPDATE
                {
                    Debug.Write(string.Format("Step: {0:x2}", (in_value & 0xF0)));

                    // command group I
                    m_fdc_status_mode = 1;

                    // set head load
                    m_head_loaded = ((in_value & (byte)CommandFlags.LOADHEAD) != 0);

                    // Either store or fetch step direction
                    if ((in_value & 0x40) != 0)
                    {
                        m_fdc_last_step_direction = (byte)(in_value & 0x20);
                    }
                    else
                    {
                        in_value = (byte)((in_value & ~0x20) | m_fdc_last_step_direction);
                    }

                    // Step the head, update track register if requested
                    byte target_track = m_disk_drives[m_current_drive_index].Track;
                    if ((in_value & 0x20) != 0)
                    {
                        if (m_disk_drives[m_current_drive_index].Track > 0)
                        {
                            target_track--;
                        }
                    }
                    else
                    {
                        if (target_track < m_disk_drives[m_current_drive_index].Geometry.NumberOfTracks - 1)
                        {
                            target_track++;
                        }
                    }
                    Debug.WriteLine(" Track: {0}", target_track);

                    //m_disk_drives[m_current_drive_index].Track = target_track;

                    // Update track register if requested
                    StatusFlags new_status = 0;
                    if ((in_value & (byte)CommandFlags.SETTRACK) != 0)
                    {
                        if (target_track >= m_disk_drives[m_current_drive_index].Geometry.NumberOfTracks)
                        {
                            new_status = StatusFlags.SEEKERR;
                        }

                        m_fdc_track = m_disk_drives[m_current_drive_index].Track;
                    }

                    StartOperation(SteppingDelays[in_value & (byte)CommandFlags.STEPRATE], new_status, HardwareFlags.INT, target_track);
                }
                break;

                // Track write
                case 0xF0:
                    Debug.Write("TrackWrite ");
                    // command group III
                    m_fdc_status_mode = 3;

                    m_operation_start_tick   = m_tvcomputer.GetCPUTicks();
                    m_operation_state        = OperationState.TrackWriteWaitForIndex;
                    m_prev_index_pulse_state = IsIndexPulse();

                    m_fdc_status    = StatusFlags.BUSY;
                    m_reg_hw_status = HardwareFlags.DRQ;

                    break;

                // Sector read
                case 0x80: // single sector read
                case 0x90: // multiple sector read
                    Debug.WriteLine("Sector read, T:{0:d}, S:{1:d}, H:{2:d}", m_fdc_track, m_fdc_sector, GetCurrentDriveSide());

                    // check drive
                    if (m_current_drive_index == InvalidDriveIndex || !m_disk_drives[m_current_drive_index].IsDiskPresent())
                    {
                        m_fdc_status = StatusFlags.NOTREADY;
                    }
                    else
                    {
                        // check sector and track address
                        if (m_fdc_track != m_disk_drives[m_current_drive_index].Track || m_fdc_sector <1 || m_fdc_sector> m_disk_drives[m_current_drive_index].Geometry.SectorPerTrack)
                        {
                            m_fdc_status      = StatusFlags.NOTFOUND;
                            m_reg_hw_status   = HardwareFlags.INT;
                            m_operation_state = OperationState.None;
                            m_fdc_status_mode = 2;
                            m_data_length     = 0;
                        }
                        else
                        {
                            m_disk_drives[m_current_drive_index].Track = m_fdc_track;

                            m_data_count           = 0;
                            m_data_length          = m_disk_drives[m_current_drive_index].Geometry.SectorLength * (((in_value & 0x10) != 0) ? m_disk_drives[m_current_drive_index].Geometry.SectorPerTrack - m_fdc_sector + 1 : 1);
                            m_operation_start_tick = m_tvcomputer.GetCPUTicks();
                            m_operation_state      = OperationState.SectorRead;
                            m_fdc_status           = StatusFlags.BUSY;
                            m_fdc_status_mode      = 2;
                            m_head_loaded          = true;

                            m_disk_drives[m_current_drive_index].SeekSector(m_fdc_sector, GetCurrentDriveSide());
                        }
                    }
                    break;

#if false
                case 0xA0:
                case 0xB0:                                 /* WRITE-SECTORS */
                    if (D->Verbose)
                    {
                        printf("WD1793: WRITE-SECTOR%s %c:%d:%d:%d (%02Xh)\n", V & 0x10 ? "S" : "", 'A' + D->Drive, D->Side, D->R[1], D->R[2], V);
                    }
                    /* Seek to the requested sector */
                    D->Ptr = SeekFDI(
                        D->Disk[D->Drive], D->Side, D->Track[D->Drive],
                        V & C_SIDECOMP ? !!(V & C_SIDE) : D->Side, D->R[1], D->R[2]
                        );
                    /* If seek successful, set up writing operation */
                    if (!D->Ptr)
                    {
                        if (D->Verbose)
                        {
                            printf("WD1793: WRITE ERROR\n");
                        }
                        D->R[0]       = (D->R[0] & ~F_ERRCODE) | F_NOTFOUND;
                        m_irq_pending = true;;
                    }
                    else
                    {
                        m_wr_length = D->Disk[D->Drive]->SecSize
                                      * (V & 0x10 ? (D->Disk[D->Drive]->Sectors - D->R[2] + 1) : 1);
                        D->R[0] |= F_BUSY | F_DRQ;
                        D->IRQ   = WD1793_DRQ;
                        D->Wait  = 255;
                    }
                    break;
#endif
                // Read address
                case 0xC0:
                    Debug.WriteLine("Read address", in_value);

                    m_crc_generator.Reset();
                    m_address_buffer[0] = GetCurrentDriveTrack();
                    m_address_buffer[1] = GetCurrentDriveSide();
                    m_address_buffer[2] = 1;
                    m_address_buffer[3] = GetCurrentSectorLength();
                    m_crc_generator.Add(m_address_buffer, 4);
                    m_address_buffer[4] = m_crc_generator.CRCLow;
                    m_address_buffer[5] = m_crc_generator.CRCHigh;
                    m_data_count        = 0;
                    m_data_length       = 6;
                    m_fdc_sector        = GetCurrentDriveTrack();

                    m_prev_index_pulse_state = IsIndexPulse();
                    m_operation_state        = OperationState.IDReadWaitForIndex;
                    m_fdc_status_mode        = 3;
                    m_head_loaded            = true;
                    break;

#if false
                    /* Read first sector address from the track */
                    if (!D->Disk[D->Drive])
                    {
                        D->Ptr = 0;
                    }
                    else
                    {
                        for (J = 0; J < 256; ++J)
                        {
                            D->Ptr = SeekFDI(
                                D->Disk[D->Drive],
                                D->Side, D->Track[D->Drive],
                                D->Side, D->Track[D->Drive], J
                                );
                            if (D->Ptr)
                            {
                                break;
                            }
                        }
                    }
                    /* If address found, initiate data transfer */
                    if (!D->Ptr)
                    {
                        if (D->Verbose)
                        {
                            printf("WD1793: READ-ADDRESS ERROR\n");
                        }
                        D->R[0]      |= F_NOTFOUND;
                        m_irq_pending = true;;
                    }
                    else
                    {
                        D->Ptr      = D->Disk[D->Drive]->Header;
                        m_rd_length = 6;
                        D->R[0]    |= F_BUSY | F_DRQ;
                        D->IRQ      = WD1793_DRQ;
                        D->Wait     = 255;
                    }
                    break;
#endif
#if false
                case 0xE0:                                 /* READ-TRACK */
                    if (D->Verbose)
                    {
                        printf("WD1793: READ-TRACK %d (%02Xh) UNSUPPORTED!\n", D->R[1], V);
                    }
                    break;

                case 0xF0:                                 /* WRITE-TRACK */
                    if (D->Verbose)
                    {
                        printf("WD1793: WRITE-TRACK %d (%02Xh) UNSUPPORTED!\n", D->R[1], V);
                    }
                    break;

                default:                                 /* UNKNOWN */
                    if (D->Verbose)
                    {
                        printf("WD1793: UNSUPPORTED OPERATION %02Xh!\n", V);
                    }
                    break;
#endif
                }
                break;

            // track register
            case PORT_TRACK:
                Debug.WriteLine("Track register set: {0:x2}", in_value);
                if ((m_fdc_status & StatusFlags.BUSY) == 0 && !m_fdc_reset_state)
                {
                    m_fdc_track = in_value;
                }
                break;

            // sector register
            case PORT_SECTOR:
                Debug.WriteLine("Sector register set: {0:x2}", in_value);
                if ((m_fdc_status & StatusFlags.BUSY) == 0 && !m_fdc_reset_state)
                {
                    m_fdc_sector = in_value;
                }
                break;

            case PORT_DATA:
                m_fdc_data = in_value;

                switch (m_operation_state)
                {
                case OperationState.TrackWriteGap:
                    m_track_write_id_buffer = (m_track_write_id_buffer << 8) | in_value;
                    break;
                }

                m_reg_hw_status &= ~HardwareFlags.DRQ;

                /*
                 *  if ((m_reg_hw_status & HardwareFlags.DRQ) == 0)
                 *  {
                 *    m_track_write_id_buffer = (m_track_write_id_buffer << 8) | in_value;
                 *  }
                 *  else
                 *  {
                 *    // data overrun occured
                 *    m_reg_hw_status = HardwareFlags.INT;
                 *    m_fdc_status |= StatusFlags.LOSTDATA;
                 *    m_operation_state = OperationState.None;
                 *  }
                 */
                break;

#if false
                // check track write mode
                if (m_read_write_mode != ReadWriteMode.TrackWrite)
                {
                    TrackWriteData(in_value);
                }
                else
                {
                    /* When writing data, store value to disk */
                    if (m_wr_length > 0)
                    {
                        Debug.WriteLine(string.Format("WD1793: EXTRA DATA WRITE (%02Xh)\n", in_value));
                    }
                    else
                    {
                        /* Write data */
                        *D->Ptr++ = V;
                        /* Decrement length */
                        if (--m_wr_length > 0)
                        {
                            /* Reset timeout watchdog */
                            D->Wait = 255;
                            /* Advance to the next sector as needed */
                            if (!(m_wr_length & (D->Disk[D->Drive]->SecSize - 1)))
                            {
                                ++D->R[2];
                            }
                        }
                        else
                        {
                            /* Write completed */
                            if (D->Verbose)
                            {
                                printf("WD1793: WRITE COMPLETED\n");
                            }
                            D->R[0]      &= ~(F_DRQ | F_BUSY);
                            m_irq_pending = true;;
                        }
                    }
                }

                // Save last written value
                m_fdc_data = in_value;
#endif


            // parameter register
            case PORT_PARAM:
                Debug.WriteLine("Param register set: {0}", (ParametersFlags)in_value);
                m_reg_param = (ParametersFlags)in_value;

                switch (m_reg_param & ParametersFlags.DriveSelectMask)
                {
                case ParametersFlags.DriveSelect0:
                    m_current_drive_index = 0;
                    break;

                case ParametersFlags.DriveSelect1:
                    m_current_drive_index = 1;
                    break;

                case ParametersFlags.DriveSelect2:
                    m_current_drive_index = 2;
                    break;

                case ParametersFlags.DriveSelect3:
                    m_current_drive_index = 3;
                    break;

                default:
                    m_current_drive_index = InvalidDriveIndex;
                    break;
                }
                break;

            // page register
            case PORT_PAGE:
                m_reg_page        = in_value;
                m_fdc_reset_state = false;

                break;
            }
        }
Example #5
0
        /** Read1793() ***********************************************/
        /** Read value from a WD1793 register A. Returns read data  **/
        /** on success or 0xFF on failure (bad register address).   **/
        /*************************************************************/
        public void PortRead(ushort in_address, ref byte inout_data)
        {
            switch (in_address & 0x0f)
            {
            // read status register
            case PORT_STATUS:
                if (m_fdc_reset_state)
                {
                    return;
                }

                // If no disk present, NOTREADY
                if (IsDriveReady())
                {
                    m_fdc_status &= ~StatusFlags.NOTREADY;
                }
                else
                {
                    m_fdc_status |= StatusFlags.NOTREADY;
                }

                // When reading status, clear interrupt
                m_reg_hw_status &= ~(HardwareFlags.INT);

                // in status mode 0 handle index pulses
                switch (m_fdc_status_mode)
                {
                // Status mode I
                case 1:
                {
                    // index pulse
                    if (IsIndexPulse())
                    {
                        m_fdc_status |= StatusFlags.INDEX;
                    }
                    else
                    {
                        m_fdc_status &= ~StatusFlags.INDEX;
                    }

                    // track 0 bit
                    if (m_current_drive_index == InvalidDriveIndex)
                    {
                        m_fdc_status &= ~StatusFlags.TRACK0;
                    }
                    else
                    {
                        if (m_disk_drives[m_current_drive_index].Track == 0)
                        {
                            m_fdc_status |= StatusFlags.TRACK0;
                        }
                        else
                        {
                            m_fdc_status &= ~StatusFlags.TRACK0;
                        }
                    }

                    // head loaded bit
                    if (m_head_loaded)
                    {
                        m_fdc_status |= StatusFlags.HEADLOAD;
                    }
                    else
                    {
                        m_fdc_status &= ~StatusFlags.HEADLOAD;
                    }
                }
                break;


                // Status mode II
                case 2:
                {
                    // update hw status register
                    UpdateHardwareStatus();

                    // copy DRQ bit from HW register
                    if ((m_reg_hw_status & HardwareFlags.DRQ) != 0)
                    {
                        m_fdc_status |= StatusFlags.DRQ;
                    }
                    else
                    {
                        m_fdc_status &= ~StatusFlags.DRQ;
                    }
                }
                break;

                // Status mode III
                case 3:
                {
                    // update hw status register
                    UpdateHardwareStatus();

                    // copy DRQ bit from HW register
                    if ((m_reg_hw_status & HardwareFlags.DRQ) != 0)
                    {
                        m_fdc_status |= StatusFlags.DRQ;
                    }
                    else
                    {
                        m_fdc_status &= ~StatusFlags.DRQ;
                    }
                }
                break;
                }

                // return status
                inout_data = (byte)m_fdc_status;

                return;

            // return track register
            case PORT_TRACK:
                if (m_fdc_reset_state)
                {
                    return;
                }

                inout_data = m_fdc_track;

                return;

            // return sector register
            case PORT_SECTOR:
                if (m_fdc_reset_state)
                {
                    return;
                }

                inout_data = m_fdc_sector;

                return;

            // return data register
            case PORT_DATA:
                switch (m_operation_state)
                {
                case OperationState.IDRead:
                case OperationState.SectorRead:
                    m_reg_hw_status &= ~HardwareFlags.DRQ;
                    break;
                }

                inout_data = m_fdc_data;

                return;

            // return HW stzatus register
            case PORT_HWSTATUS:
                UpdateHardwareStatus();
                inout_data = (byte)m_reg_hw_status;
                return;
            }
        }
Example #6
0
        private void UpdateHardwareStatus()
        {
            switch (m_operation_state)
            {
            case OperationState.TrackWriteWaitForIndex:
            {
                bool index_pulse_state;

                index_pulse_state = IsIndexPulse();

                if (m_prev_index_pulse_state == false && index_pulse_state == true)
                {
                    // index pulse rising edge
                    m_operation_state      = OperationState.TrackWriteGap;
                    m_operation_start_tick = m_tvcomputer.GetCPUTicks();
                    m_data_count           = 0;
                    m_reg_hw_status       |= HardwareFlags.DRQ;
                }
                m_prev_index_pulse_state = index_pulse_state;
            }
            break;

            case OperationState.TrackWriteGap:
            {
                if (TrackWriteByteProcess())
                {
                    switch (m_track_write_id_buffer)
                    {
                    case TrackIDADDMark:
                        m_data_length     = m_data_count;
                        m_operation_state = OperationState.TrackWriteIDADDR;
                        break;

                    case TrackDATAMark:
                        m_data_length     = m_data_count;
                        m_operation_state = OperationState.TrackWriteData;
                        break;
                    }
                }
            }
            break;

            case OperationState.TrackWriteIDADDR:
            {
                if (TrackWriteByteProcess())
                {
                    switch (m_data_count - m_data_length)
                    {
                    // sector value
                    case 3:
                        m_disk_drives[m_current_drive_index].SeekSector(m_fdc_data, GetCurrentDriveSide());
                        break;

                    case 5:
                        m_operation_state = OperationState.TrackWriteGap;
                        break;
                    }
                }
            }
            break;

            case OperationState.TrackWriteData:
            {
                if (TrackWriteByteProcess())
                {
                    if (m_data_count - m_data_length <= m_disk_drives[m_current_drive_index].Geometry.SectorLength)
                    {
                        m_disk_drives[m_current_drive_index].WriteByte(m_fdc_data);
                    }
                    else
                    {
                        m_operation_state = OperationState.TrackWriteGap;
                    }
                }
            }
            break;

            case OperationState.SectorRead:
            {
                int byte_index = TickToByteIndex(m_tvcomputer.GetTicksSince(m_operation_start_tick));

                if (byte_index > m_data_count)
                {
                    m_fdc_data = m_disk_drives[m_current_drive_index].ReadByte();
                    m_data_count++;
                    m_reg_hw_status |= HardwareFlags.DRQ;

                    if (m_data_count > m_data_length)
                    {
                        // stop operation
                        m_data_length     = 0;
                        m_operation_state = OperationState.None;
                        m_fdc_status     &= ~StatusFlags.BUSY;
                        m_reg_hw_status  |= HardwareFlags.INT;
                        //m_fdc_status_mode = 1;
                    }
                }
            }
            break;

            case OperationState.IDReadWaitForIndex:
            {
                bool index_pulse_state = IsIndexPulse();

                if (m_prev_index_pulse_state == false && index_pulse_state == true)
                {
                    // index pulse rising edge
                    m_operation_state      = OperationState.IDRead;
                    m_operation_start_tick = m_tvcomputer.GetCPUTicks();
                }

                m_prev_index_pulse_state = index_pulse_state;
            }
            break;

            case OperationState.IDRead:
                if (m_data_count < m_data_length)
                {
                    m_fdc_data = m_address_buffer[m_data_count];
                    m_data_count++;
                    m_reg_hw_status |= HardwareFlags.DRQ;
                }
                else
                {
                    m_operation_state = OperationState.None;
                    m_reg_hw_status  |= HardwareFlags.INT;
                }
                break;

            default:
            {
                //int by
            }
            break;
            }
        }