mirror of
https://github.com/livingcomputermuseum/UniBone.git
synced 2026-02-27 01:00:00 +00:00
Status bit fixes; 2.11BSD gets a bit further.
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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<Registers>(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<uint32_t>(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<FunctionCode>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; i<register_count; i++)
|
||||
{
|
||||
@@ -127,8 +127,8 @@ rh11_c::rh11_c() :
|
||||
strcpy(RH_reg[i]->name, "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!");
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user