diff --git a/10.02_devices/2_src/massbus_device.hpp b/10.02_devices/2_src/massbus_device.hpp index 85f7125..71961e0 100644 --- a/10.02_devices/2_src/massbus_device.hpp +++ b/10.02_devices/2_src/massbus_device.hpp @@ -23,6 +23,11 @@ public: // // MASSBUS Register Metadata: // + + // The total number of registers (including RH11 registers) exposed + // by this device. + virtual uint32_t GetRegisterCount() = 0; + // Indicates whether this device implements the specified register. virtual bool ImplementsRegister(uint32_t register) = 0; diff --git a/10.02_devices/2_src/massbus_rp.cpp b/10.02_devices/2_src/massbus_rp.cpp index f69fa31..03468c6 100644 --- a/10.02_devices/2_src/massbus_rp.cpp +++ b/10.02_devices/2_src/massbus_rp.cpp @@ -36,9 +36,9 @@ massbus_rp_c::massbus_rp_c( _workerMutex(PTHREAD_MUTEX_INITIALIZER), _err(false), _ata(false), - _ready(true), _ned(false), - _attnSummary(0) + _attnSummary(0), + _rmr(false) { name.value="MASSBUS_RP"; type_name.value = "massbus_rp_c"; @@ -114,6 +114,20 @@ massbus_rp_c::WriteRegister( { INFO("RP reg write: unit %d register 0%o value 0%o", unit, reg, value); + if (!SelectedDrive()->IsDriveReady() && + reg != 0 && // CS1 is allowed as long as GO isn't set (will be checked in DoCommand) + reg != (uint32_t)Registers::AttentionSummary) + { + // Any attempt to modify a drive register other than Attention Summary + // while the drive is busy is invalid. + INFO("Register modification while drive busy."); + _rmr = true; + UpdateStatus(false); + return; + } + + static uint32_t frup = 0; + switch(static_cast(reg)) { case Registers::Control: @@ -141,10 +155,18 @@ massbus_rp_c::WriteRegister( // Clear bits in the Attention Summary register specified in the // written value: _attnSummary &= ~(value & 0xff); - _controller->WriteRegister(static_cast(Registers::AttentionSummary), _attnSummary); + _controller->WriteRegister(reg, _attnSummary); INFO("Attention Summary write o%o, value is now o%o", value, _attnSummary); break; + case Registers::Error1: + // Clear any bits in the Error 1 Register specified in the + // written value: + _error1 &= ~(value & 0xff); + _controller->WriteRegister(reg, _error1); + INFO("Error 1 Reg write o%o, value is now o%o", value, _error1); + break; + default: FATAL("Unimplemented RP register write."); break; @@ -178,13 +200,19 @@ void massbus_rp_c::DoCommand( return; } + if (!SelectedDrive()->IsDriveReady()) + { + // This should never happen. + FATAL("Command sent while not ready!"); + } + _ned = false; + _ata = false; switch(static_cast(function)) { case FunctionCode::Nop: // Nothing. - _ata = false; UpdateStatus(true); break; @@ -200,11 +228,9 @@ void massbus_rp_c::DoCommand( _desiredSector = 0; _desiredTrack = 0; _offset = 0; - _ata = false; - _ready = true; - UpdateStatus(true); UpdateDesiredSectorTrack(); - UpdateOffset(); + UpdateOffset(); + UpdateStatus(false); /* do not interrupt */ break; case FunctionCode::ReadData: @@ -222,9 +248,7 @@ void massbus_rp_c::DoCommand( SelectedDrive()->SetPositioningInProgress(); } - // Clear ATA and READY - _ata = false; - _ready = false; + // Clear READY UpdateStatus(false); pthread_mutex_lock(&_workerMutex); @@ -273,6 +297,7 @@ massbus_rp_c::UpdateStatus( { _error1 = + (_rmr ? 04 : 0) | (SelectedDrive()->GetAddressOverflow() ? 01000 : 0) | (SelectedDrive()->GetInvalidAddress() ? 02000 : 0) | (SelectedDrive()->GetWriteLockError() ? 04000 : 0); @@ -308,12 +333,13 @@ massbus_rp_c::UpdateStatus( { _attnSummary |= (0x1 << _selectedUnit); // TODO: these only get set, and are latched until // manually cleared? + INFO("Attention Summary is now o%o", _attnSummary); } _controller->WriteRegister(static_cast(Registers::AttentionSummary), _attnSummary); // Inform controller of status update. - _controller->BusStatus(complete, _ready, _ata, _err, SelectedDrive()->IsAvailable(), _ned); + _controller->BusStatus(complete, SelectedDrive()->IsDriveReady(), _ata, _err, SelectedDrive()->IsAvailable(), _ned); } void @@ -323,7 +349,7 @@ massbus_rp_c::UpdateDesiredSectorTrack() _controller->WriteRegister(static_cast(Registers::DesiredSectorTrackAddress), desiredSectorTrack); // Fudge: We update the look-ahead sector value to be the last-requested sector - 1 - uint16_t lookAhead = (((_desiredSector - 5) % 22) << 6); + uint16_t lookAhead = (((_desiredSector - 1) % 22) << 6); _controller->WriteRegister(static_cast(Registers::LookAhead), lookAhead); } @@ -353,8 +379,9 @@ massbus_rp_c::Reset() // Reset registers to their defaults _ata = false; - _ready = true; _attnSummary = 0; + _error1 = 0; + _rmr = false; UpdateStatus(false); _desiredSector = 0; @@ -455,8 +482,6 @@ massbus_rp_c::Worker() // Return drive to ready state SelectedDrive()->SetDriveReady(); - // Signal ready status. - _ready = true; _workerState = WorkerState::Finish; } break; @@ -494,8 +519,6 @@ massbus_rp_c::Worker() // Return drive to ready state SelectedDrive()->SetDriveReady(); - // Signal ready status. - _ready = true; _workerState = WorkerState::Finish; } break; @@ -520,7 +543,6 @@ massbus_rp_c::Worker() // Return to ready state, set attention bit. SelectedDrive()->SetDriveReady(); _ata = true; - _ready = true; _workerState = WorkerState::Finish; } break; diff --git a/10.02_devices/2_src/massbus_rp.hpp b/10.02_devices/2_src/massbus_rp.hpp index 4935287..53c16db 100644 --- a/10.02_devices/2_src/massbus_rp.hpp +++ b/10.02_devices/2_src/massbus_rp.hpp @@ -87,6 +87,12 @@ public: public: void Reset(); + uint32_t GetRegisterCount() override + { + // Total registers for RH11 + RP06: + return 20; + } + bool ImplementsRegister(uint32_t register) override; std::string RegisterName(uint32_t register) override; @@ -141,9 +147,9 @@ private: { // Name DATI DATO { "INV", false, false, 0, 0 }, // 0, not used - { "CS1", false, 0, 0177700 }, // Status - { "ER1", false, true , 0, 0177777 }, // Error #1 - writable by diagnostics - { "MR" , false, true , 0, 0177777 }, // Maintenance + { "CS1", false, true, 0, 0401477 }, // Status + { "ER1", false, true, 0, 0177777 }, // Error #1 - writable by diagnostics + { "MR" , false, true, 0, 0177777 }, // Maintenance { "ATN", false, true, 0, 0377 }, // Attention summary { "DA" , false, true, 0, 0017437 }, // Desired Sector/Track { "LA" , false, false, 0, 0 }, // Look Ahead @@ -177,9 +183,9 @@ private: // Status bits that we track volatile bool _err; volatile bool _ata; + volatile bool _rmr; // RH11 ready signal (ugly: this should be in the rh11 code!) - volatile bool _ready; volatile bool _ned; // ditto // Worker thread diff --git a/10.02_devices/2_src/rh11.cpp b/10.02_devices/2_src/rh11.cpp index 4ccb2cd..890d4ea 100755 --- a/10.02_devices/2_src/rh11.cpp +++ b/10.02_devices/2_src/rh11.cpp @@ -107,14 +107,14 @@ rh11_c::rh11_c() : // base addr, intr-vector, intr level // TODO: make configurable based on type (fixed, tape, moving-head disk) // right now it is hardcoded for moving-head disks. - set_default_bus_params(0776700, 21, 0254, 6); + set_default_bus_params(0776700, 5, 0254, 6); _massbus.reset(new massbus_rp_c(this)); // The RH11 controller exposes up to 32 registers, not all are used // and use depends on the devices attached to the MASSBUS. // TODO: What does an RH11 do when an unimplemented register is accessed? - register_count = 32; + register_count = _massbus->GetRegisterCount(); for (int i=0; iname, "RHCS1"); RH_reg[i]->active_on_dati = false; RH_reg[i]->active_on_dato = true; - RH_reg[i]->reset_value = 0x0080; - RH_reg[i]->writable_bits = 0x037f; + RH_reg[i]->reset_value = 0000200; + RH_reg[i]->writable_bits = 041577; break; case RHWC: @@ -137,7 +137,7 @@ rh11_c::rh11_c() : RH_reg[i]->active_on_dati = false; RH_reg[i]->active_on_dato = true; RH_reg[i]->reset_value = 0; - RH_reg[i]->writable_bits = 0xffff; + RH_reg[i]->writable_bits = 0177777; break; case RHBA: @@ -146,7 +146,7 @@ rh11_c::rh11_c() : RH_reg[i]->active_on_dati = false; RH_reg[i]->active_on_dato = true; RH_reg[i]->reset_value = 0; - RH_reg[i]->writable_bits = 0xfffe; + RH_reg[i]->writable_bits = 0177776; break; case RHCS2: @@ -155,7 +155,7 @@ rh11_c::rh11_c() : RH_reg[i]->active_on_dati = false; RH_reg[i]->active_on_dato = true; RH_reg[i]->reset_value = 0; - RH_reg[i]->writable_bits = 0x223f; + RH_reg[i]->writable_bits = 0021077; break; case RHDB: @@ -164,7 +164,7 @@ rh11_c::rh11_c() : RH_reg[i]->active_on_dati = false; RH_reg[i]->active_on_dato = false; RH_reg[i]->reset_value = 0; - RH_reg[i]->writable_bits = 0xffff; + RH_reg[i]->writable_bits = 0177777; break; default: @@ -229,17 +229,17 @@ rh11_c::BusStatus( INFO("RHCS1 is currently o%o", currentStatus); - currentStatus &= ~(0140300); // clear status bits, IE, and GO bit : move to constant + currentStatus &= ~(0144300); // clear status bits, IE, and GO bit : move to constant currentStatus |= (attention ? 0100000 : 0) | // check when this actually gets set? (error ? 0040000 : 0) | (avail ? 0004000 : 0) | // drive available - (ready ? 0000200 : 0); // controller ready bit (should clear when busy) + (ready ? 0000200 : 0); // controller ready bit if (completion) { // clear the GO bit from the CS word if the drive is finished. - currentStatus &= ~(01); + currentStatus &= ~(01); } set_register_dati_value( @@ -326,6 +326,8 @@ rh11_c::DiskReadTransfer( } else { + // TODO: raise errors, etc. + FATAL("DMA Write failed!"); return false; } } @@ -348,6 +350,11 @@ rh11_c::DiskWriteTransfer( IncrementBusAddress(lengthInWords); DecrementWordCount(lengthInWords); } + else + { + // TODO: raise errors, etc. + FATAL("DMA Read failed!"); + } return buffer; } @@ -607,7 +614,6 @@ void rh11_c::on_after_register_access( void rh11_c::Interrupt(void) { - INFO("interrupt enable is %d", _interruptEnable); if(_interruptEnable) { INFO("Interrupt!"); diff --git a/10.02_devices/2_src/rp_drive.cpp b/10.02_devices/2_src/rp_drive.cpp index 5ea5aa4..3c76499 100644 --- a/10.02_devices/2_src/rp_drive.cpp +++ b/10.02_devices/2_src/rp_drive.cpp @@ -208,11 +208,9 @@ rp_drive_c::Search( timeout_c timeout; INFO("Search commencing."); - _pip = true; - - timeout.wait_ms(500); + timeout.wait_ms(30); _pip = false; - + INFO("Search completed."); _currentCylinder = cylinder; return true;