1
0
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:
Josh Dersch
2019-05-17 00:47:11 +02:00
parent fc312df0bc
commit 398c54ee3f
5 changed files with 117 additions and 71 deletions

View File

@@ -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;
}

View File

@@ -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;
//

View File

@@ -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;

View File

@@ -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

View File

@@ -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);