1
0
mirror of https://github.com/livingcomputermuseum/UniBone.git synced 2026-01-11 23:52:51 +00:00
Josh Dersch e037b0d36d Added dato_mask to allow discerning DATOB operations to emulated registers.
This allows the RH11's RHCS1 register to function properly.  2.11BSD now boots!
2020-03-25 07:06:54 +01:00

203 lines
5.4 KiB
C++

/*
massbus_rp_c.hpp: Implements MASSBUS device logic for moving-head RP04/05/06 drives.
Copyright Vulcan Inc. 2020 via Living Computers: Museum + Labs, Seattle, WA.
Contributed under the BSD 2-clause license.
*/
#ifndef _MASSBUS_RP_HPP_
#define _MASSBUS_RP_HPP_
#include <stdint.h>
#include <string.h>
using namespace std;
#include "storagedrive.hpp"
#include "rh11.hpp"
#include "massbus_device.hpp"
// Registers
enum class Registers
{
Control = 00,
Status = 01,
Error1 = 02,
Maintenance = 03,
AttentionSummary = 04,
DesiredSectorTrackAddress = 05,
LookAhead = 07,
DriveType = 06,
SerialNo = 014,
Offset = 011,
DesiredCylinderAddress = 012,
CurrentCylinderAddress = 013,
Error2 = 010,
Error3 = 015,
ECCPosition = 016,
ECCPattern = 017,
};
// Control Function codes
#define RP_GO 01
#define RP_FUNC 076
enum class FunctionCode
{
Nop = 00,
Unload = 01,
Recalibrate = 03,
DriveClear = 04,
Release = 05,
Search = 014,
WriteCheckData = 024,
WriteCheckHeaderAndData = 025,
WriteData = 030,
WriteHeaderAndData = 031,
ReadData = 034,
ReadHeaderAndData = 035,
Seek = 02,
Offset = 06,
ReturnToCenterline = 07,
PackAcknowledge = 011,
ReadInPreset = 010,
};
//
// Register metadata
//
struct rp_register_data
{
char Name[16];
bool ActiveOnDATI;
bool ActiveOnDATO;
uint16_t ResetValue;
uint16_t WritableBits;
};
//
// Encapsulates MASSBUS control logic for RP04/05/06 moving-head disks.
// Talks to one or more rp_drive units.
//
class massbus_rp_c: public device_c, public massbus_device_c
{
public:
massbus_rp_c(rh11_c* controller);
virtual ~massbus_rp_c();
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;
bool RegisterActiveOnDATI(uint32_t register) override;
bool RegisterActiveOnDATO(uint32_t register) override;
uint16_t RegisterResetValue(uint32_t register) override;
uint16_t RegisterWritableBits(uint32_t register) override;
void WriteRegister(uint32_t unit, uint32_t register, uint16_t value) override;
uint16_t ReadRegister(uint32_t unit, uint32_t register) override;
// Background worker functions
void Worker();
void Spin();
private:
struct WorkerCommand
{
volatile uint32_t unit;
volatile uint32_t bus_address;
volatile uint32_t word_count;
volatile FunctionCode function;
volatile uint32_t cylinder;
volatile uint32_t track;
volatile uint32_t sector;
volatile bool ready;
} _newCommand;
enum WorkerState
{
Idle = 0,
Execute = 1,
Finish = 2,
} _workerState;
void DoCommand(uint32_t unit, uint16_t command);
void on_power_changed(void) override;
void on_init_changed(void) override;
void UpdateStatus(bool completion, bool diagForceError);
void UpdateDesiredSectorTrack();
void UpdateDesiredCylinder();
void UpdateOffset();
void UpdateCurrentCylinder();
rp_drive_c* SelectedDrive();
private:
rh11_c* _controller;
rp_register_data _registerMetadata[16] =
{
// Name DATI DATO
{ "INV", false, false, 0, 0 }, // 0, not used
{ "CS1", false, true, 0, 0041777 }, // 1, Status
{ "ER1", false, true, 0, 0177777 }, // 2, Error #1 - writable by diagnostics
{ "MR" , false, true, 0, 0177777 }, // 3, Maintenance
{ "ATN", false, true, 0, 0377 }, // 4, Attention summary
{ "DA" , false, true, 0, 0017437 }, // 5, Desired Sector/Track
{ "DT" , true, true, 0, 0 }, // 6, Drive Type
{ "LA" , false, false, 0, 0 }, // 7, Look Ahead
{ "ER2", false, false, 0, 0 }, // 10, Error #2
{ "OFF", false, false, 0, 0177777 }, // 11, Offset
{ "DCY", false, true, 0, 0001777 }, // 12, Desired Cylinder
{ "CCY", false, false, 0, 0 }, // 13, Current Cylinder
{ "SN" , true, true, 0, 0 }, // 14, Serial Number
{ "ER3", false, false, 0, 0 }, // 15, Error #3
{ "EPO", false, false, 0, 0 }, // 16, ECC Position
{ "EPA", false, false, 0, 0 }, // 17, ECC Pattern
};
// Unit selected by last command register write
volatile uint32_t _selectedUnit;
// Register data
volatile uint16_t _status;
volatile uint16_t _error1;
volatile uint16_t _maint;
volatile uint16_t _attnSummary;
volatile uint16_t _desiredSector;
volatile uint16_t _desiredTrack;
volatile uint16_t _offset;
volatile uint16_t _desiredCylinder;
volatile uint16_t _currentCylinder;
volatile uint16_t _error2;
volatile uint16_t _error3;
// 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 _ned; // ditto
// Worker thread
pthread_t _workerThread;
pthread_cond_t _workerWakeupCond;
pthread_mutex_t _workerMutex;
// Spin thread
pthread_t _spinThread;
};
#endif