mirror of
https://github.com/livingcomputermuseum/UniBone.git
synced 2026-01-27 20:37:36 +00:00
Fixed Unit and Controller ID fields (word order was scrambled) and removed hacked-in constant values for same.
Made RCT table size dynamic based on the drive type. The above allow RSTS/E to boot! Huzzah!
This commit is contained in:
@@ -23,12 +23,7 @@ mscp_drive_c::mscp_drive_c(
|
||||
SetOffline();
|
||||
|
||||
// Calculate the unit's ID:
|
||||
// drive number in upper 32 bits, class/model in lower.
|
||||
_unitID = (static_cast<uint64_t>(driveNumber + 1) << 32) | 0xffffffff;
|
||||
|
||||
// Initialize the RCT area
|
||||
_rctData.reset(new uint8_t[GetBlockSize()]);
|
||||
memset(reinterpret_cast<void *>(_rctData.get()), 0, GetBlockSize());
|
||||
_unitIDDeviceNumber = driveNumber + 1;
|
||||
}
|
||||
|
||||
mscp_drive_c::~mscp_drive_c()
|
||||
@@ -65,12 +60,7 @@ uint32_t mscp_drive_c::GetBlockCount()
|
||||
|
||||
uint32_t mscp_drive_c::GetRCTBlockCount()
|
||||
{
|
||||
//
|
||||
// We provide only a single RCT block. Per the latest MSCP spec no RCT is required,
|
||||
// however several operating systems appear to expect at least one block be present
|
||||
// for volume write-protect flags.
|
||||
//
|
||||
return 1;
|
||||
return _driveInfo.RCTSize * GetRCTCopies();
|
||||
}
|
||||
|
||||
uint32_t mscp_drive_c::GetMediaID()
|
||||
@@ -78,14 +68,19 @@ uint32_t mscp_drive_c::GetMediaID()
|
||||
return _driveInfo.MediaID;
|
||||
}
|
||||
|
||||
uint64_t mscp_drive_c::GetUnitID()
|
||||
uint32_t mscp_drive_c::GetUnitIDDeviceNumber()
|
||||
{
|
||||
return _unitID;
|
||||
return _unitIDDeviceNumber;
|
||||
}
|
||||
|
||||
uint16_t mscp_drive_c::GetUnitIDClassModel()
|
||||
{
|
||||
return _unitIDClassModel;
|
||||
}
|
||||
|
||||
uint16_t mscp_drive_c::GetRCTSize()
|
||||
{
|
||||
return 1;
|
||||
return _driveInfo.RCTSize;
|
||||
}
|
||||
|
||||
uint8_t mscp_drive_c::GetRBNs()
|
||||
@@ -207,6 +202,17 @@ void mscp_drive_c::UpdateCapacity()
|
||||
GetBlockCount() * GetBlockSize();
|
||||
}
|
||||
|
||||
void mscp_drive_c::UpdateMetadata()
|
||||
{
|
||||
_unitIDClassModel = 0x0200 | _driveInfo.Model;
|
||||
|
||||
// Initialize the RCT area
|
||||
size_t rctSize = _driveInfo.RCTSize * GetBlockSize();
|
||||
_rctData.reset(new uint8_t[rctSize]);
|
||||
assert(_rctData != nullptr);
|
||||
memset(reinterpret_cast<void *>(_rctData.get()), 0, rctSize);
|
||||
}
|
||||
|
||||
bool mscp_drive_c::on_param_changed(
|
||||
parameter_c *param)
|
||||
{
|
||||
@@ -253,7 +259,8 @@ bool mscp_drive_c::SetDriveType(const char* typeName)
|
||||
{
|
||||
_driveInfo = g_driveTable[index];
|
||||
type_name.value = _driveInfo.TypeName;
|
||||
UpdateCapacity();
|
||||
UpdateCapacity();
|
||||
UpdateMetadata();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ public:
|
||||
uint32_t GetBlockCount(void);
|
||||
uint32_t GetRCTBlockCount(void);
|
||||
uint32_t GetMediaID(void);
|
||||
uint64_t GetUnitID(void);
|
||||
uint32_t GetUnitIDDeviceNumber(void);
|
||||
uint16_t GetUnitIDClassModel(void);
|
||||
uint16_t GetRCTSize(void);
|
||||
uint8_t GetRBNs(void);
|
||||
uint8_t GetRCTCopies(void);
|
||||
@@ -66,41 +67,50 @@ private:
|
||||
char TypeName[16];
|
||||
size_t BlockCount;
|
||||
uint32_t MediaID;
|
||||
uint8_t Model;
|
||||
uint16_t RCTSize;
|
||||
bool Removable;
|
||||
bool ReadOnly;
|
||||
};
|
||||
|
||||
DriveInfo g_driveTable[22]
|
||||
//
|
||||
// TODO: add a lot more drive types.
|
||||
// Does it make sense to support drive types not native to Unibus machines (SCSI types, for example?)
|
||||
// Need to add a ClassID table entry in that eventuality...
|
||||
// Also TODO: RCTSize parameters taken from SIMH rq source; how valid are these?
|
||||
DriveInfo g_driveTable[21]
|
||||
{
|
||||
{ "RX50", 800, 0x25658032, true, false },
|
||||
{ "RX33", 2400, 0x25658021, true, false },
|
||||
{ "RD51", 21600, 0x25644033, false, false },
|
||||
{ "RD31", 41560, 0x2564401f, false, false },
|
||||
{ "RC25", 50902, 0x20643019, true, false },
|
||||
{ "RC25F", 50902, 0x20643319, true, false },
|
||||
{ "RD52", 60480, 0x25644034, false, false },
|
||||
{ "RD32", 83236, 0x25641047, false, false },
|
||||
{ "RD53", 138672, 0x25644035, false, false },
|
||||
{ "RA80", 237212, 0x20643019, false, false },
|
||||
{ "RD54", 311200, 0x25644036, false, false },
|
||||
{ "RA60", 400176, 0x22a4103c, true, false },
|
||||
{ "RA70", 547041, 0x20643019, false, false },
|
||||
{ "RA81", 891072, 0x25641051, false, false },
|
||||
{ "RA82", 1216665, 0x25641052, false, false },
|
||||
{ "RA71", 1367310, 0x25641047, false, false },
|
||||
{ "RRD40", 1331200, 0x25652228, true, true },
|
||||
{ "RA72", 1953300, 0x25641048, false, false },
|
||||
{ "RA90", 2376153, 0x2564105a, false, false },
|
||||
{ "RA92", 2940951, 0x2564105c, false, false },
|
||||
{ "RA73", 3920490, 0x25641049, false, false },
|
||||
{ "", 0, 0, false, false }
|
||||
// Name Blocks MediaID Model RCTSize Removable ReadOnly
|
||||
{ "RX50", 800, 0x25658032, 7, 0, true, false },
|
||||
{ "RX33", 2400, 0x25658021, 10, 0, true, false },
|
||||
{ "RD51", 21600, 0x25644033, 6, 36, false, false },
|
||||
{ "RD31", 41560, 0x2564401f, 12, 3, false, false },
|
||||
{ "RC25", 50902, 0x20643019, 2, 0, true, false },
|
||||
{ "RC25F", 50902, 0x20643319, 3, 0, true, false },
|
||||
{ "RD52", 60480, 0x25644034, 8, 4, false, false },
|
||||
{ "RD32", 83236, 0x25641047, 15, 4, false, false },
|
||||
{ "RD53", 138672, 0x25644035, 9, 5, false, false },
|
||||
{ "RA80", 237212, 0x20643019, 1, 0, false, false },
|
||||
{ "RD54", 311200, 0x25644036, 13, 7, false, false },
|
||||
{ "RA60", 400176, 0x22a4103c, 4, 1008, true, false },
|
||||
{ "RA70", 547041, 0x20643019, 18, 198, false, false },
|
||||
{ "RA81", 891072, 0x25641051, 5, 2856, false, false },
|
||||
{ "RA82", 1216665, 0x25641052, 11, 3420, false, false },
|
||||
{ "RA71", 1367310, 0x25641047, 40, 1428, false, false },
|
||||
{ "RA72", 1953300, 0x25641048, 37, 2040, false, false },
|
||||
{ "RA90", 2376153, 0x2564105a, 19, 1794, false, false },
|
||||
{ "RA92", 2940951, 0x2564105c, 29, 949, false, false },
|
||||
{ "RA73", 3920490, 0x25641049, 47, 198, false, false },
|
||||
{ "", 0, 0, 0, 0, false, false }
|
||||
};
|
||||
|
||||
bool SetDriveType(const char* typeName);
|
||||
void UpdateCapacity(void);
|
||||
void UpdateMetadata(void);
|
||||
DriveInfo _driveInfo;
|
||||
bool _online;
|
||||
uint64_t _unitID;
|
||||
uint32_t _unitIDDeviceNumber;
|
||||
uint16_t _unitIDClassModel;
|
||||
bool _useImageSize;
|
||||
|
||||
//
|
||||
|
||||
@@ -195,7 +195,7 @@ mscp_server::Poll(void)
|
||||
ControlMessageHeader* header =
|
||||
reinterpret_cast<ControlMessageHeader*>(message->Message);
|
||||
|
||||
INFO ("Message size 0x%x opcode 0x%x rsvd 0x%x mod 0x%x unit %d, ursvd 0x%x, ref 0x%x",
|
||||
DEBUG("Message size 0x%x opcode 0x%x rsvd 0x%x mod 0x%x unit %d, ursvd 0x%x, ref 0x%x",
|
||||
message->MessageLength,
|
||||
header->Word3.Command.Opcode,
|
||||
header->Word3.Command.Reserved,
|
||||
@@ -270,7 +270,7 @@ mscp_server::Poll(void)
|
||||
break;
|
||||
}
|
||||
|
||||
INFO ("cmd 0x%x st 0x%x fl 0x%x", cmdStatus, GET_STATUS(cmdStatus), GET_FLAGS(cmdStatus));
|
||||
DEBUG("cmd 0x%x st 0x%x fl 0x%x", cmdStatus, GET_STATUS(cmdStatus), GET_FLAGS(cmdStatus));
|
||||
|
||||
//
|
||||
// Set the endcode and status bits
|
||||
@@ -491,7 +491,9 @@ mscp_server::GetUnitStatus(
|
||||
uint16_t MultiUnitCode;
|
||||
uint16_t UnitFlags;
|
||||
uint32_t Reserved0;
|
||||
uint64_t UnitIdentifier;
|
||||
uint32_t UnitIdDeviceNumber;
|
||||
uint16_t UnitIdUnused;
|
||||
uint16_t UnitIdClassModel;
|
||||
uint32_t MediaTypeIdentifier;
|
||||
uint16_t ShadowUnit;
|
||||
uint16_t Reserved1;
|
||||
@@ -505,7 +507,7 @@ mscp_server::GetUnitStatus(
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
INFO ("MSCP GET UNIT STATUS drive %d", unitNumber);
|
||||
DEBUG("MSCP GET UNIT STATUS drive %d", unitNumber);
|
||||
|
||||
// Adjust message length for response
|
||||
message->MessageLength = sizeof(GetUnitStatusResponseParameters) +
|
||||
@@ -534,29 +536,24 @@ mscp_server::GetUnitStatus(
|
||||
reinterpret_cast<GetUnitStatusResponseParameters*>(
|
||||
GetParameterPointer(message));
|
||||
|
||||
if (nullptr == drive)
|
||||
if (nullptr == drive || !drive->IsAvailable())
|
||||
{
|
||||
// No such drive
|
||||
params->UnitIdentifier = 0;
|
||||
// No such drive or drive image not loaded.
|
||||
params->UnitIdDeviceNumber = 0;
|
||||
params->UnitIdClassModel = 0;
|
||||
params->UnitIdUnused = 0;
|
||||
params->ShadowUnit = 0;
|
||||
return STATUS(Status::UNIT_OFFLINE, UnitOfflineSubcodes::UNIT_UNKNOWN, 0);
|
||||
}
|
||||
|
||||
if(!drive->IsAvailable())
|
||||
{
|
||||
// Known drive, but not available at this time.
|
||||
params->UnitIdentifier = 0;
|
||||
params->ShadowUnit = 0;
|
||||
|
||||
return STATUS(Status::UNIT_OFFLINE, UnitOfflineSubcodes::NO_VOLUME, 0); // offline; no volume available
|
||||
}
|
||||
|
||||
params->Reserved0 = 0;
|
||||
params->Reserved1 = 0;
|
||||
params->Reserved2 = 0;
|
||||
params->UnitFlags = 0; // TODO: 0 for now, which is sane.
|
||||
params->MultiUnitCode = 0; // Controller dependent, we don't support multi-unit drives.
|
||||
params->UnitIdentifier = drive->GetUnitID();
|
||||
params->UnitIdDeviceNumber = drive->GetUnitIDDeviceNumber();
|
||||
params->UnitIdClassModel = drive->GetUnitIDClassModel();
|
||||
params->UnitIdUnused = 0;
|
||||
params->MediaTypeIdentifier = drive->GetMediaID();
|
||||
params->ShadowUnit = unitNumber; // Always equal to unit number
|
||||
|
||||
@@ -631,7 +628,9 @@ mscp_server::Online(
|
||||
uint16_t UnitFlags;
|
||||
uint16_t MultiUnitCode;
|
||||
uint32_t Reserved0;
|
||||
uint64_t UnitIdentifier;
|
||||
uint32_t UnitIdDeviceNumber;
|
||||
uint16_t UnitIdUnused;
|
||||
uint16_t UnitIdClassModel;
|
||||
uint32_t MediaTypeIdentifier;
|
||||
uint32_t Reserved1;
|
||||
uint32_t UnitSize;
|
||||
@@ -663,7 +662,9 @@ mscp_server::Online(
|
||||
|
||||
params->UnitFlags = 0; // TODO: 0 for now, which is sane.
|
||||
params->MultiUnitCode = 0; // Controller dependent, we don't support multi-unit drives.
|
||||
params->UnitIdentifier = drive->GetUnitID();
|
||||
params->UnitIdDeviceNumber = drive->GetUnitIDDeviceNumber();
|
||||
params->UnitIdClassModel = drive->GetUnitIDClassModel();
|
||||
params->UnitIdUnused = 0;
|
||||
params->MediaTypeIdentifier = drive->GetMediaID();
|
||||
params->UnitSize = drive->GetBlockCount();
|
||||
params->VolumeSerialNumber = 1; // We report no serial
|
||||
@@ -710,7 +711,16 @@ mscp_server::SetControllerCharacteristics(
|
||||
uint16_t ControllerFlags;
|
||||
uint16_t HostTimeout;
|
||||
uint16_t Reserved;
|
||||
uint64_t TimeAndDate;
|
||||
union
|
||||
{
|
||||
uint64_t TimeAndDate;
|
||||
struct
|
||||
{
|
||||
uint32_t UniqueDeviceNumber;
|
||||
uint16_t Unused;
|
||||
uint16_t ClassModel;
|
||||
} ControllerId;
|
||||
} w;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
@@ -743,8 +753,10 @@ mscp_server::SetControllerCharacteristics(
|
||||
params->ControllerFlags = _controllerFlags & 0xfe; // Mask off 576 byte sectors bit.
|
||||
// it's read-only and we're a 512
|
||||
// byte sector shop here.
|
||||
params->HostTimeout = 0x10; // Controller timeout: return the max value.
|
||||
params->TimeAndDate = _port->GetControllerIdentifier(); // Controller ID
|
||||
params->HostTimeout = 0xff; // Controller timeout: return the max value.
|
||||
params->w.ControllerId.UniqueDeviceNumber = _port->GetControllerIdentifier();
|
||||
params->w.ControllerId.ClassModel = _port->GetControllerClassModel();
|
||||
params->w.ControllerId.Unused = 0;
|
||||
|
||||
return STATUS(Status::SUCCESS, 0, 0);
|
||||
}
|
||||
@@ -781,7 +793,9 @@ mscp_server::SetUnitCharacteristics(
|
||||
uint16_t UnitFlags;
|
||||
uint16_t MultiUnitCode;
|
||||
uint32_t Reserved0;
|
||||
uint64_t UnitIdentifier;
|
||||
uint32_t UnitIdDeviceNumber;
|
||||
uint16_t UnitIdUnused;
|
||||
uint16_t UnitIdClassModel;
|
||||
uint32_t MediaTypeIdentifier;
|
||||
uint32_t Reserved1;
|
||||
uint16_t ShadowUnit;
|
||||
@@ -808,7 +822,9 @@ mscp_server::SetUnitCharacteristics(
|
||||
|
||||
params->UnitFlags = 0; // TODO: 0 for now, which is sane.
|
||||
params->MultiUnitCode = 0; // Controller dependent, we don't support multi-unit drives.
|
||||
params->UnitIdentifier = drive->GetUnitID();
|
||||
params->UnitIdDeviceNumber = drive->GetUnitIDDeviceNumber();
|
||||
params->UnitIdClassModel = drive->GetUnitIDClassModel();
|
||||
params->UnitIdUnused = 0;
|
||||
params->MediaTypeIdentifier = drive->GetMediaID();
|
||||
params->UnitSize = drive->GetBlockCount();
|
||||
params->VolumeSerialNumber = 0; // We report no serial
|
||||
@@ -864,7 +880,7 @@ mscp_server::DoDiskTransfer(
|
||||
ReadWriteEraseParameters* params =
|
||||
reinterpret_cast<ReadWriteEraseParameters*>(GetParameterPointer(message));
|
||||
|
||||
INFO ("MSCP RWE 0x%x unit %d mod 0x%x chan o%o pa o%o count %d lbn %d",
|
||||
DEBUG("MSCP RWE 0x%x unit %d mod 0x%x chan o%o pa o%o count %d lbn %d",
|
||||
operation,
|
||||
unitNumber,
|
||||
modifiers,
|
||||
@@ -886,6 +902,11 @@ mscp_server::DoDiskTransfer(
|
||||
return STATUS(Status::UNIT_OFFLINE, UnitOfflineSubcodes::UNIT_UNKNOWN, 0);
|
||||
}
|
||||
|
||||
if (!drive->IsOnline())
|
||||
{
|
||||
return STATUS(Status::UNIT_AVAILABLE, 0, 0);
|
||||
}
|
||||
|
||||
// Are we accessing the RCT area?
|
||||
bool rctAccess = params->LBN >= drive->GetBlockCount();
|
||||
uint32_t rctBlockNumber = params->LBN - drive->GetBlockCount();
|
||||
@@ -967,7 +988,7 @@ mscp_server::DoDiskTransfer(
|
||||
case Opcodes::READ:
|
||||
{
|
||||
unique_ptr<uint8_t> diskBuffer;
|
||||
|
||||
|
||||
if (rctAccess)
|
||||
{
|
||||
diskBuffer.reset(drive->ReadRCTBlock(rctBlockNumber));
|
||||
@@ -981,6 +1002,7 @@ mscp_server::DoDiskTransfer(
|
||||
params->BufferPhysicalAddress & 0x00ffffff,
|
||||
params->ByteCount,
|
||||
diskBuffer.get());
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -715,12 +715,18 @@ uda_c::PostResponse(
|
||||
return res;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
uint32_t
|
||||
uda_c::GetControllerIdentifier()
|
||||
{
|
||||
// TODO: make this not hardcoded
|
||||
// ID 0x1234568, device class 1 (mass storage), model 2 (UDA50)
|
||||
return 0x1234567801020000;
|
||||
// ID 0x12345678
|
||||
return 0x12345678;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
uda_c::GetControllerClassModel()
|
||||
{
|
||||
return 0x0102; // Class 1 (mass storage), model 2 (UDA50)
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -68,7 +68,8 @@ public:
|
||||
// Returns FALSE if the ring is full.
|
||||
bool PostResponse(Message* response);
|
||||
|
||||
uint64_t GetControllerIdentifier(void);
|
||||
uint32_t GetControllerIdentifier(void);
|
||||
uint16_t GetControllerClassModel(void);
|
||||
|
||||
uint32_t GetDriveCount(void);
|
||||
mscp_drive_c* GetDrive(uint32_t driveNumber);
|
||||
|
||||
Reference in New Issue
Block a user