diff --git a/Components/8272/i8272.cpp b/Components/8272/i8272.cpp index 92c42832a..eaa769fb1 100644 --- a/Components/8272/i8272.cpp +++ b/Components/8272/i8272.cpp @@ -13,12 +13,18 @@ using namespace Intel; namespace { -const uint8_t StatusRQM = 0x80; // Set indicates: ready to send or receive from processor. +const uint8_t StatusRQM = 0x80; // Set: ready to send or receive from processor. +const uint8_t StatusDIO = 0x40; // Set: data is expected to be taken from the 8272 by the processor. +const uint8_t StatusNDM = 0x20; // Set: the execution phase of a data transfer command is ongoing and DMA mode is disabled. +const uint8_t StatusD3B = 0x08; // Set: drive 3 is seeking. +const uint8_t StatusD2B = 0x04; // Set: drive 2 is seeking. +const uint8_t StatusD1B = 0x02; // Set: drive 1 is seeking. +const uint8_t StatusD0B = 0x01; // Set: drive 0 is seeking. } i8272::i8272(Cycles clock_rate, int clock_rate_multiplier, int revolutions_per_minute) : Storage::Disk::MFMController(clock_rate, clock_rate_multiplier, revolutions_per_minute), - status_(StatusRQM), + main_status_(StatusRQM), interesting_event_mask_((int)Event8272::CommandByte), resume_point_(0), delay_time_(0) { @@ -42,7 +48,7 @@ void i8272::set_register(int address, uint8_t value) { if(!address) return; // if not ready for commands, do nothing - if(!(status_ & StatusRQM)) return; + if(!(main_status_ & StatusRQM)) return; // accumulate latest byte in the command byte sequence command_.push_back(value); @@ -52,10 +58,14 @@ void i8272::set_register(int address, uint8_t value) { uint8_t i8272::get_register(int address) { if(address) { printf("8272 get data\n"); - return 0xff; + if(result_.empty()) return 0xff; + uint8_t result = result_.back(); + result_.pop_back(); + if(result_.empty()) posit_event((int)Event8272::ResultEmpty); + return result; } else { - printf("8272 get status\n"); - return status_; + printf("8272 get main status\n"); + return main_status_; } } @@ -75,9 +85,9 @@ void i8272::posit_event(int type) { command_.clear(); wait_for_complete_command_sequence: - status_ |= StatusRQM; + main_status_ |= StatusRQM; WAIT_FOR_EVENT(Event8272::CommandByte) - status_ &= ~StatusRQM; + main_status_ &= ~StatusRQM; switch(command_[0] & 0x1f) { case 0x06: // read data @@ -144,55 +154,57 @@ void i8272::posit_event(int type) { } read_data: - printf("Read data unimplemented!!"); + printf("Read data unimplemented!!\n"); goto wait_for_command; read_deleted_data: - printf("Read deleted data unimplemented!!"); + printf("Read deleted data unimplemented!!\n"); goto wait_for_command; write_data: - printf("Write data unimplemented!!"); + printf("Write data unimplemented!!\n"); goto wait_for_command; write_deleted_data: - printf("Write deleted data unimplemented!!"); + printf("Write deleted data unimplemented!!\n"); goto wait_for_command; read_track: - printf("Read track unimplemented!!"); + printf("Read track unimplemented!!\n"); goto wait_for_command; read_id: - printf("Read ID unimplemented!!"); + printf("Read ID unimplemented!!\n"); goto wait_for_command; format_track: - printf("Fromat track unimplemented!!"); + printf("Fromat track unimplemented!!\n"); goto wait_for_command; scan_low: - printf("Scan low unimplemented!!"); + printf("Scan low unimplemented!!\n"); goto wait_for_command; scan_low_or_equal: - printf("Scan low or equal unimplemented!!"); + printf("Scan low or equal unimplemented!!\n"); goto wait_for_command; scan_high_or_equal: - printf("Scan high or equal unimplemented!!"); + printf("Scan high or equal unimplemented!!\n"); goto wait_for_command; recalibrate: - printf("Recalibrate unimplemented!!"); + printf("Recalibrate unimplemented!!\n"); goto wait_for_command; sense_interrupt_status: - printf("Sense interrupt status unimplemented!!"); - goto wait_for_command; + printf("Sense interrupt status\n"); + result_.push_back(head_position_); + result_.push_back(status_[0]); + goto post_result; specify: - printf("Specify"); + printf("Specify\n"); step_rate_time_ = command_[1] &0xf0; // i.e. 16 to 240m head_unload_time_ = command_[1] & 0x0f; // i.e. 1 to 16ms head_load_time_ = command_[2] & ~1; // i.e. 2 to 254 ms in increments of 2ms @@ -200,16 +212,23 @@ void i8272::posit_event(int type) { goto wait_for_command; sense_drive_status: - printf("Sense drive status unimplemented!!"); - goto wait_for_command; + printf("Sense drive status\n"); + result_.push_back(status_[3]); + goto post_result; seek: - printf("Seek unimplemented!!"); + printf("Seek unimplemented!!\n"); goto wait_for_command; invalid: // A no-op, causing the FDC to go back into standby mode. goto wait_for_command; + post_result: + main_status_ |= StatusRQM | StatusDIO; + WAIT_FOR_EVENT(Event8272::ResultEmpty); + main_status_ &= ~StatusDIO; + goto wait_for_command; + END_SECTION() } diff --git a/Components/8272/i8272.hpp b/Components/8272/i8272.hpp index 6adc7d62e..41ebec243 100644 --- a/Components/8272/i8272.hpp +++ b/Components/8272/i8272.hpp @@ -27,13 +27,16 @@ class i8272: public Storage::Disk::MFMController { private: void posit_event(int type); - uint8_t status_; + uint8_t main_status_; + uint8_t status_[4]; + std::vector command_; + std::vector result_; enum class Event8272: int { CommandByte = (1 << 3), Timer = (1 << 4), - + ResultEmpty = (1 << 5), }; int interesting_event_mask_; @@ -44,6 +47,8 @@ class i8272: public Storage::Disk::MFMController { int head_unload_time_; int head_load_time_; bool dma_mode_; + + uint8_t head_position_; }; }