From 35fe4d50d4a919610253d7c18739802c0ae63c35 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 15 Sep 2017 20:26:41 -0400 Subject: [PATCH] Adds command termination upon drive becoming unready, and copies head and drive selection into ST0. --- Components/8272/i8272.cpp | 16 +++++++++++++++- Components/8272/i8272.hpp | 10 ++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Components/8272/i8272.cpp b/Components/8272/i8272.cpp index 30cbb0cb1..3f02acf15 100644 --- a/Components/8272/i8272.cpp +++ b/Components/8272/i8272.cpp @@ -26,7 +26,7 @@ using namespace Intel::i8272; #define SetBusy() (main_status_ |= 0x10) #define ResetBusy() (main_status_ &= ~0x10) -#define Busy() (main_status_ & 0x10) +#define IsBusy() (main_status_ & 0x10) #define SetAbnormalTermination() (status_[0] |= 0x40) #define SetInvalidCommand() (status_[0] |= 0x80) @@ -34,6 +34,7 @@ using namespace Intel::i8272; #define SetSeekEnd() (status_[0] |= 0x20) #define SetEquipmentCheck() (status_[0] |= 0x10) #define SetNotReady() (status_[0] |= 0x08) +#define SetSide2() (status_[0] |= 0x04) #define SetEndOfCylinder() (status_[1] |= 0x80) #define SetDataError() (status_[1] |= 0x20) @@ -158,6 +159,11 @@ void i8272::run_for(Cycles cycles) { } } + // check for busy plus ready disabled + if(is_executing_ && !get_drive().get_is_ready()) { + posit_event((int)Event8272::NoLongerReady); + } + is_sleeping_ = !delay_time_ && !drives_seeking_ && !head_timers_running_; if(is_sleeping_) update_sleep_observer(); } @@ -230,6 +236,7 @@ uint8_t i8272::get_register(int address) { #define SET_DRIVE_HEAD_MFM() \ active_drive_ = command_[1]&3; \ active_head_ = (command_[1] >> 2)&1; \ + status_[0] = (command_[1]&7); \ select_drive(active_drive_); \ get_drive().set_head((unsigned int)active_head_); \ set_is_double_density(command_[0] & 0x40); @@ -263,6 +270,10 @@ uint8_t i8272::get_register(int address) { void i8272::posit_event(int event_type) { if(event_type == (int)Event::IndexHole) index_hole_count_++; + if(event_type == (int)Event8272::NoLongerReady) { + SetNotReady(); + goto abort; + } if(!(interesting_event_mask_ & event_type)) return; interesting_event_mask_ &= ~event_type; @@ -332,6 +343,7 @@ void i8272::posit_event(int event_type) { } // Establishes the drive and head being addressed, and whether in double density mode; populates the internal // cylinder, head, sector and size registers from the command stream. + is_executing_ = true; if(!dma_mode_) SetNonDMAExecution(); SET_DRIVE_HEAD_MFM(); LOAD_HEAD(); @@ -811,6 +823,7 @@ void i8272::posit_event(int event_type) { // Sets abnormal termination of the current command and proceeds to an ST0, ST1, ST2, C, H, R, N result phase. abort: + end_writing(); SetAbnormalTermination(); goto post_st012chrn; @@ -839,6 +852,7 @@ void i8272::posit_event(int event_type) { printf("\n"); // Set ready to send data to the processor, no longer in non-DMA execution phase. + is_executing_ = false; ResetNonDMAExecution(); SetDataRequest(); SetDataDirectionToProcessor(); diff --git a/Components/8272/i8272.hpp b/Components/8272/i8272.hpp index 2edab4e24..1907b020e 100644 --- a/Components/8272/i8272.hpp +++ b/Components/8272/i8272.hpp @@ -65,6 +65,7 @@ class i8272: public Storage::Disk::MFMController { CommandByte = (1 << 3), Timer = (1 << 4), ResultEmpty = (1 << 5), + NoLongerReady = (1 << 6) }; void posit_event(int type); int interesting_event_mask_; @@ -107,10 +108,11 @@ class i8272: public Storage::Disk::MFMController { bool seek_is_satisfied(int drive); // User-supplied parameters; as per the specify command. - int step_rate_time_; - int head_unload_time_; - int head_load_time_; - bool dma_mode_; + int step_rate_time_ = 1; + int head_unload_time_ = 1; + int head_load_time_ = 1; + bool dma_mode_ = false; + bool is_executing_ = false; // A count of head unload timers currently running. int head_timers_running_;