1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 23:52:26 +00:00

Merge pull request #699 from TomHarte/SpuriousCRCErrors

Ensure the WD won't confuse sector contents for header content.
This commit is contained in:
Thomas Harte 2019-12-23 21:15:15 -05:00 committed by GitHub
commit 8a1fe99fa4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 31 deletions

View File

@ -18,9 +18,9 @@ using namespace WD;
WD1770::WD1770(Personality p) : WD1770::WD1770(Personality p) :
Storage::Disk::MFMController(8000000), Storage::Disk::MFMController(8000000),
personality_(p), personality_(p),
interesting_event_mask_(static_cast<int>(Event1770::Command)) { interesting_event_mask_(int(Event1770::Command)) {
set_is_double_density(false); set_is_double_density(false);
posit_event(static_cast<int>(Event1770::Command)); posit_event(int(Event1770::Command));
} }
void WD1770::set_register(int address, uint8_t value) { void WD1770::set_register(int address, uint8_t value) {
@ -30,7 +30,7 @@ void WD1770::set_register(int address, uint8_t value) {
if(value == 0xd0) { if(value == 0xd0) {
// Force interrupt **immediately**. // Force interrupt **immediately**.
LOG("Force interrupt immediately"); LOG("Force interrupt immediately");
posit_event(static_cast<int>(Event1770::ForceInterrupt)); posit_event(int(Event1770::ForceInterrupt));
} else { } else {
ERROR("!!!TODO: force interrupt!!!"); ERROR("!!!TODO: force interrupt!!!");
update_status([] (Status &status) { update_status([] (Status &status) {
@ -39,7 +39,7 @@ void WD1770::set_register(int address, uint8_t value) {
} }
} else { } else {
command_ = value; command_ = value;
posit_event(static_cast<int>(Event1770::Command)); posit_event(int(Event1770::Command));
} }
} }
break; break;
@ -91,6 +91,7 @@ uint8_t WD1770::get_register(int address) {
if(status_.type == Status::One) if(status_.type == Status::One)
status |= (status_.spin_up ? Flag::SpinUp : 0); status |= (status_.spin_up ? Flag::SpinUp : 0);
} }
// LOG("Returned status " << PADHEX(2) << int(status) << " of type " << 1+int(status_.type));
return status; return status;
} }
case 1: return track_; case 1: return track_;
@ -110,25 +111,27 @@ void WD1770::run_for(const Cycles cycles) {
const auto number_of_cycles = cycles.as_integral(); const auto number_of_cycles = cycles.as_integral();
if(delay_time_ <= number_of_cycles) { if(delay_time_ <= number_of_cycles) {
delay_time_ = 0; delay_time_ = 0;
posit_event(static_cast<int>(Event1770::Timer)); posit_event(int(Event1770::Timer));
} else { } else {
delay_time_ -= number_of_cycles; delay_time_ -= number_of_cycles;
} }
} }
} }
#define WAIT_FOR_EVENT(mask) resume_point_ = __LINE__; interesting_event_mask_ = static_cast<int>(mask); return; case __LINE__: #define WAIT_FOR_EVENT(mask) resume_point_ = __LINE__; interesting_event_mask_ = int(mask); return; case __LINE__:
#define WAIT_FOR_TIME(ms) resume_point_ = __LINE__; delay_time_ = ms * 8000; WAIT_FOR_EVENT(Event1770::Timer); #define WAIT_FOR_TIME(ms) resume_point_ = __LINE__; delay_time_ = ms * 8000; WAIT_FOR_EVENT(Event1770::Timer);
#define WAIT_FOR_BYTES(count) resume_point_ = __LINE__; distance_into_section_ = 0; WAIT_FOR_EVENT(Event::Token); if(get_latest_token().type == Token::Byte) distance_into_section_++; if(distance_into_section_ < count) { interesting_event_mask_ = static_cast<int>(Event::Token); return; } #define WAIT_FOR_BYTES(count) resume_point_ = __LINE__; distance_into_section_ = 0; WAIT_FOR_EVENT(Event::Token); if(get_latest_token().type == Token::Byte) distance_into_section_++; if(distance_into_section_ < count) { interesting_event_mask_ = int(Event::Token); return; }
#define BEGIN_SECTION() switch(resume_point_) { default: #define BEGIN_SECTION() switch(resume_point_) { default:
#define END_SECTION() (void)0; } #define END_SECTION() (void)0; }
#define READ_ID() \ #define READ_ID() \
if(new_event_type == static_cast<int>(Event::Token)) { \ if(new_event_type == int(Event::Token)) { \
if(!distance_into_section_ && get_latest_token().type == Token::ID) {set_data_mode(DataMode::Reading); distance_into_section_++; } \ if(!distance_into_section_ && get_latest_token().type == Token::ID) {\
else if(distance_into_section_ && distance_into_section_ < 7 && get_latest_token().type == Token::Byte) { \ set_data_mode(DataMode::Reading); \
++distance_into_section_; \
} else if(distance_into_section_ && distance_into_section_ < 7 && get_latest_token().type == Token::Byte) { \
header_[distance_into_section_ - 1] = get_latest_token().byte_value; \ header_[distance_into_section_ - 1] = get_latest_token().byte_value; \
distance_into_section_++; \ ++distance_into_section_; \
} \ } \
} }
@ -161,10 +164,10 @@ void WD1770::run_for(const Cycles cycles) {
// +--------+----------+-------------------------+ // +--------+----------+-------------------------+
void WD1770::posit_event(int new_event_type) { void WD1770::posit_event(int new_event_type) {
if(new_event_type == static_cast<int>(Event::IndexHole)) { if(new_event_type == int(Event::IndexHole)) {
index_hole_count_++; index_hole_count_++;
if(index_hole_count_target_ == index_hole_count_) { if(index_hole_count_target_ == index_hole_count_) {
posit_event(static_cast<int>(Event1770::IndexHoleTarget)); posit_event(int(Event1770::IndexHoleTarget));
index_hole_count_target_ = -1; index_hole_count_target_ = -1;
} }
@ -179,7 +182,7 @@ void WD1770::posit_event(int new_event_type) {
} }
} }
if(new_event_type == static_cast<int>(Event1770::ForceInterrupt)) { if(new_event_type == int(Event1770::ForceInterrupt)) {
interesting_event_mask_ = 0; interesting_event_mask_ = 0;
resume_point_ = 0; resume_point_ = 0;
update_status([] (Status &status) { update_status([] (Status &status) {
@ -187,7 +190,7 @@ void WD1770::posit_event(int new_event_type) {
status.data_request = false; status.data_request = false;
}); });
} else { } else {
if(!(interesting_event_mask_ & static_cast<int>(new_event_type))) return; if(!(interesting_event_mask_ & int(new_event_type))) return;
interesting_event_mask_ &= ~new_event_type; interesting_event_mask_ &= ~new_event_type;
} }
@ -242,6 +245,7 @@ void WD1770::posit_event(int new_event_type) {
status.data_request = false; status.data_request = false;
}); });
LOG("Step/Seek/Restore with track " << int(track_) << " data " << int(data_));
if(!has_motor_on_line() && !has_head_load_line()) goto test_type1_type; if(!has_motor_on_line() && !has_head_load_line()) goto test_type1_type;
if(has_motor_on_line()) goto begin_type1_spin_up; if(has_motor_on_line()) goto begin_type1_spin_up;
@ -278,7 +282,7 @@ void WD1770::posit_event(int new_event_type) {
step_direction_ = (data_ > track_); step_direction_ = (data_ > track_);
adjust_track: adjust_track:
if(step_direction_) track_++; else track_--; if(step_direction_) ++track_; else --track_;
perform_step: perform_step:
if(!step_direction_ && get_drive().get_is_track_zero()) { if(!step_direction_ && get_drive().get_is_track_zero()) {
@ -311,7 +315,7 @@ void WD1770::posit_event(int new_event_type) {
distance_into_section_ = 0; distance_into_section_ = 0;
verify_read_data: verify_read_data:
WAIT_FOR_EVENT(static_cast<int>(Event::IndexHole) | static_cast<int>(Event::Token)); WAIT_FOR_EVENT(int(Event::IndexHole) | int(Event::Token));
READ_ID(); READ_ID();
if(index_hole_count_ == 6) { if(index_hole_count_ == 6) {
@ -321,7 +325,9 @@ void WD1770::posit_event(int new_event_type) {
goto wait_for_command; goto wait_for_command;
} }
if(distance_into_section_ == 7) { if(distance_into_section_ == 7) {
distance_into_section_ = 0;
set_data_mode(DataMode::Scanning); set_data_mode(DataMode::Scanning);
if(get_crc_generator().get_value()) { if(get_crc_generator().get_value()) {
update_status([] (Status &status) { update_status([] (Status &status) {
status.crc_error = true; status.crc_error = true;
@ -336,8 +342,6 @@ void WD1770::posit_event(int new_event_type) {
}); });
goto wait_for_command; goto wait_for_command;
} }
distance_into_section_ = 0;
} }
goto verify_read_data; goto verify_read_data;
@ -394,8 +398,11 @@ void WD1770::posit_event(int new_event_type) {
goto wait_for_command; goto wait_for_command;
} }
distance_into_section_ = 0;
set_data_mode(DataMode::Scanning);
type2_get_header: type2_get_header:
WAIT_FOR_EVENT(static_cast<int>(Event::IndexHole) | static_cast<int>(Event::Token)); WAIT_FOR_EVENT(int(Event::IndexHole) | int(Event::Token));
READ_ID(); READ_ID();
if(index_hole_count_ == 5) { if(index_hole_count_ == 5) {
@ -406,8 +413,10 @@ void WD1770::posit_event(int new_event_type) {
goto wait_for_command; goto wait_for_command;
} }
if(distance_into_section_ == 7) { if(distance_into_section_ == 7) {
LOG("Considering " << std::dec << int(header_[0]) << "/" << int(header_[2])); distance_into_section_ = 0;
set_data_mode(DataMode::Scanning); set_data_mode(DataMode::Scanning);
LOG("Considering " << std::dec << int(header_[0]) << "/" << int(header_[2]));
if( header_[0] == track_ && header_[2] == sector_ && if( header_[0] == track_ && header_[2] == sector_ &&
(has_motor_on_line() || !(command_&0x02) || ((command_&0x08) >> 3) == header_[1])) { (has_motor_on_line() || !(command_&0x02) || ((command_&0x08) >> 3) == header_[1])) {
LOG("Found " << std::dec << int(header_[0]) << "/" << int(header_[2])); LOG("Found " << std::dec << int(header_[0]) << "/" << int(header_[2]));
@ -424,7 +433,6 @@ void WD1770::posit_event(int new_event_type) {
}); });
goto type2_read_or_write_data; goto type2_read_or_write_data;
} }
distance_into_section_ = 0;
} }
goto type2_get_header; goto type2_get_header;
@ -467,6 +475,9 @@ void WD1770::posit_event(int new_event_type) {
header_[distance_into_section_] = get_latest_token().byte_value; header_[distance_into_section_] = get_latest_token().byte_value;
distance_into_section_++; distance_into_section_++;
if(distance_into_section_ == 2) { if(distance_into_section_ == 2) {
distance_into_section_ = 0;
set_data_mode(DataMode::Scanning);
if(get_crc_generator().get_value()) { if(get_crc_generator().get_value()) {
LOG("CRC error; terminating"); LOG("CRC error; terminating");
update_status([this] (Status &status) { update_status([this] (Status &status) {
@ -475,11 +486,13 @@ void WD1770::posit_event(int new_event_type) {
goto wait_for_command; goto wait_for_command;
} }
LOG("Finished reading sector " << std::dec << int(sector_));
if(command_ & 0x10) { if(command_ & 0x10) {
sector_++; sector_++;
LOG("Advancing to search for sector " << std::dec << int(sector_));
goto test_type2_write_protection; goto test_type2_write_protection;
} }
LOG("Finished reading sector " << std::dec << int(sector_));
goto wait_for_command; goto wait_for_command;
} }
goto type2_check_crc; goto type2_check_crc;
@ -612,8 +625,8 @@ void WD1770::posit_event(int new_event_type) {
distance_into_section_ = 0; distance_into_section_ = 0;
read_address_get_header: read_address_get_header:
WAIT_FOR_EVENT(static_cast<int>(Event::IndexHole) | static_cast<int>(Event::Token)); WAIT_FOR_EVENT(int(Event::IndexHole) | int(Event::Token));
if(new_event_type == static_cast<int>(Event::Token)) { if(new_event_type == int(Event::Token)) {
if(!distance_into_section_ && get_latest_token().type == Token::ID) {set_data_mode(DataMode::Reading); distance_into_section_++; } if(!distance_into_section_ && get_latest_token().type == Token::ID) {set_data_mode(DataMode::Reading); distance_into_section_++; }
else if(distance_into_section_ && distance_into_section_ < 7 && get_latest_token().type == Token::Byte) { else if(distance_into_section_ && distance_into_section_ < 7 && get_latest_token().type == Token::Byte) {
if(status_.data_request) { if(status_.data_request) {
@ -627,9 +640,11 @@ void WD1770::posit_event(int new_event_type) {
update_status([] (Status &status) { update_status([] (Status &status) {
status.data_request = true; status.data_request = true;
}); });
distance_into_section_++; ++distance_into_section_;
if(distance_into_section_ == 7) { if(distance_into_section_ == 7) {
distance_into_section_ = 0;
if(get_crc_generator().get_value()) { if(get_crc_generator().get_value()) {
update_status([] (Status &status) { update_status([] (Status &status) {
status.crc_error = true; status.crc_error = true;
@ -653,7 +668,7 @@ void WD1770::posit_event(int new_event_type) {
index_hole_count_ = 0; index_hole_count_ = 0;
read_track_read_byte: read_track_read_byte:
WAIT_FOR_EVENT(static_cast<int>(Event::Token) | static_cast<int>(Event::IndexHole)); WAIT_FOR_EVENT(int(Event::Token) | int(Event::IndexHole));
if(index_hole_count_) { if(index_hole_count_) {
goto wait_for_command; goto wait_for_command;
} }
@ -720,7 +735,7 @@ void WD1770::posit_event(int new_event_type) {
case 0xfd: case 0xfe: case 0xfd: case 0xfe:
// clock is 0xc7 = 1010 0000 0010 1010 = 0xa022 // clock is 0xc7 = 1010 0000 0010 1010 = 0xa022
write_raw_short( write_raw_short(
static_cast<uint16_t>( uint16_t(
0xa022 | 0xa022 |
((data_ & 0x80) << 7) | ((data_ & 0x80) << 7) |
((data_ & 0x40) << 6) | ((data_ & 0x40) << 6) |
@ -788,7 +803,7 @@ void WD1770::set_motor_on(bool motor_on) {}
void WD1770::set_head_loaded(bool head_loaded) { void WD1770::set_head_loaded(bool head_loaded) {
head_is_loaded_ = head_loaded; head_is_loaded_ = head_loaded;
if(head_loaded) posit_event(static_cast<int>(Event1770::HeadLoad)); if(head_loaded) posit_event(int(Event1770::HeadLoad));
} }
ClockingHint::Preference WD1770::preferred_clocking() { ClockingHint::Preference WD1770::preferred_clocking() {

View File

@ -80,7 +80,7 @@ void MFMController::process_input_bit(int value) {
break; break;
} }
latest_token_.byte_value = shifter_.get_byte(); latest_token_.byte_value = shifter_.get_byte();
posit_event(static_cast<int>(Event::Token)); posit_event(int(Event::Token));
} }
void MFMController::write_bit(int bit) { void MFMController::write_bit(int bit) {

View File

@ -108,7 +108,7 @@ void Shifter::add_input_bit(int value) {
} }
uint8_t Shifter::get_byte() const { uint8_t Shifter::get_byte() const {
return static_cast<uint8_t>( return uint8_t(
((shift_register_ & 0x0001) >> 0) | ((shift_register_ & 0x0001) >> 0) |
((shift_register_ & 0x0004) >> 1) | ((shift_register_ & 0x0004) >> 1) |
((shift_register_ & 0x0010) >> 2) | ((shift_register_ & 0x0010) >> 2) |