Updated DriveController to save/restore the currently mounted disk (which may differ from the pre-configured disk if the user mounted a different disk), and cleaned the interfaces up a little

This commit is contained in:
Jeff Parsons 2017-01-28 17:31:46 -08:00 committed by Jeff Parsons
commit e7329fc277
6 changed files with 609 additions and 494 deletions

View file

@ -1140,6 +1140,7 @@ FDC.prototype.saveDrives = function()
* saveDrive(drive)
*
* @this {FDC}
* @param {Object} drive
* @return {Array}
*/
FDC.prototype.saveDrive = function(drive)

View file

@ -75,7 +75,7 @@ var Config;
*/
class DriveController extends Component {
/**
* DriveController(type, parms, bitsMessage, configDC)
* DriveController(type, parms, bitsMessage, configDC, configDrive, configIO)
*
* The DriveController component has the following component-specific (parms) properties:
*
@ -85,10 +85,10 @@ class DriveController extends Component {
* @param {Object} parms
* @param {number} bitsMessage
* @param {Config} configDC
* @param {Array} driveInfo
* @param {Object} tableIO
* @param {Array} configDrive
* @param {Object} configIO
*/
constructor(type, parms, bitsMessage, configDC, driveInfo, tableIO)
constructor(type, parms, bitsMessage, configDC, configDrive, configIO)
{
super(type, parms, bitsMessage);
@ -100,8 +100,8 @@ class DriveController extends Component {
this.cAutoMount = 0;
this.configDC = configDC;
this.driveInfo = driveInfo;
this.tableIO = tableIO;
this.configDrive = configDrive;
this.configIO = configIO;
this.nDrives = configDC.DRIVES;
this.aDrives = new Array(this.nDrives);
@ -347,15 +347,15 @@ class DriveController extends Component {
}
/*
* If we didn't need auto-mount support, we could defer controller initialization until we received
* a powerUp() notification, at which point reset() would call initController(), or restore() would restore
* the controller; in that case, all we'd need to do here is call setReady().
* If we didn't need auto-mount support, we could defer controller and drive initialization until we received
* a powerUp() notification, at which point reset() would call initController(), or restore() would restore the
* controller.
*/
this.initController();
this.reset();
this.irq = this.cpu.addIRQ(this.configDC.VEC, this.configDC.PRI, this.bitsMessage);
bus.addIOTable(this, this.tableIO);
bus.addIOTable(this, this.configIO);
bus.addResetHandler(this.reset.bind(this));
this.addDisk("None", DriveController.SOURCE.NONE, true);
@ -465,6 +465,7 @@ class DriveController extends Component {
reset()
{
this.initController();
this.initDrives();
}
/**
@ -479,7 +480,8 @@ class DriveController extends Component {
{
var state = new State(this);
state.set(0, this.saveController());
state.set(0, this.saveDeltas());
state.set(1, this.saveHistory());
state.set(2, this.saveDrives());
return state.data();
}
@ -494,37 +496,25 @@ class DriveController extends Component {
*/
restore(data)
{
return this.initController(data[0], data[1]);
var fSuccess = true;
if (!this.initController(data[0])) fSuccess = false;
if (!this.initHistory(data[1])) fSuccess = false;
if (!this.initDrives(data[2])) fSuccess = false;
return fSuccess;
}
/**
* initController(aRegs, aHistory)
* initController(aRegs)
*
* Placeholder for subclasses.
*
* @this {DriveController}
* @param {Array} [aRegs]
* @param {Array} [aHistory]
* @return {boolean} true if successful, false if failure
*/
initController(aRegs, aHistory)
initController(aRegs)
{
var fSuccess = true;
/*
* Initialize the disk history (if available) before initializing the drives, so that any disk deltas can be
* applied to disk images that are already loaded.
*/
if (aHistory) this.aDiskHistory = aHistory;
for (var iDrive = 0; iDrive < this.aDrives.length; iDrive++) {
var drive = this.aDrives[iDrive];
if (drive === undefined) {
drive = this.aDrives[iDrive] = {};
}
if (!this.initDrive(drive, iDrive, this.driveInfo)) {
fSuccess = false;
}
}
return fSuccess;
return true;
}
/**
@ -537,42 +527,20 @@ class DriveController extends Component {
*/
saveController()
{
return [];
}
/**
* saveDeltas()
*
* This returns an array of entries, one for each disk image we've ever mounted, including any deltas; ie:
*
* [name, path, deltas]
*
* aDiskHistory contains exactly that, except that deltas may not be up-to-date for any currently mounted
* disk image(s), so we call updateHistory() for all those disks, and then aDiskHistory is ready to be saved.
*
* @this {DriveController}
* @return {Array}
*/
saveDeltas()
{
for (var iDrive = 0; iDrive < this.aDrives.length; iDrive++) {
var drive = this.aDrives[iDrive];
if (drive.disk) {
this.updateDiskHistory(drive.sDiskName, drive.sDiskPath, drive.disk);
}
}
return this.aDiskHistory;
}
/**
* initDrive(drive, iDrive, driveInfo)
* initDrive(drive, iDrive, configDrive, configDisk)
*
* @this {DriveController}
* @param {Object} drive
* @param {number} iDrive
* @param {Array} driveInfo
* @param {Array} configDrive
* @param {Array} [configDisk]
* @return {boolean} true if successful, false if failure
*/
initDrive(drive, iDrive, driveInfo)
initDrive(drive, iDrive, configDrive, configDisk)
{
var i = 0;
var fSuccess = true;
@ -586,11 +554,11 @@ class DriveController extends Component {
* NOTE: We initialize the following drive properties to their MAXIMUMs; disks may have
* these or SMALLER values (subject to the limits of what the controller supports, of course).
*/
drive.nCylinders = driveInfo[0];
drive.nHeads = driveInfo[1];
drive.nSectors = driveInfo[2];
drive.cbSector = driveInfo[3];
drive.status = driveInfo[4];
drive.nCylinders = configDrive[0];
drive.nHeads = configDrive[1];
drive.nSectors = configDrive[2];
drive.cbSector = configDrive[3];
drive.status = configDrive[4];
/*
* The next group of properties are set by various controller command sequences.
@ -607,11 +575,140 @@ class DriveController extends Component {
drive.ibSector = 0;
drive.sector = null;
if (!drive.disk) drive.sDiskPath = ""; // ensure this is initialized to a default that displayDisk() can deal with
if (!drive.disk) {
drive.sDiskPath = ""; // ensure this is initialized to a default that displayDisk() can deal with
}
if (configDisk) {
var fLocal = configDisk[0];
var sDiskName = configDisk[1];
var sDiskPath = configDisk[2];
/*
* If we're restoring a local disk image, then the entire disk contents should be captured in aDiskHistory,
* so all we have to do is mount a blank disk and let disk.restore() do the rest; ie, there's nothing to
* "load" (it's a purely synchronous operation).
*
* Otherwise, we must call loadDrive(); in the common case, loadDrive() will have already "auto-mounted"
* the disk, so it will return true, and then we restore any deltas to the current image.
*
* However, if loadDrive() returns false, then it has initiated the load for a *different* disk image,
* so we must mark ourselves as "not ready" again, and add another "wait for ready" test in Computer before
* finally powering the CPU.
*/
if (fLocal) {
this.mountDrive(iDrive, sDiskName, sDiskPath);
}
else if (this.loadDrive(iDrive, sDiskName, sDiskPath, true)) {
if (drive.disk) {
if (sDiskPath) {
this.addDiskHistory(sDiskName, sDiskPath, drive.disk);
} else {
if (MAXDEBUG) Component.warning("Disk '" + (drive.disk.sDiskName || sDiskName) + "' not recorded properly in drive " + iDrive);
}
}
} else {
this.setReady(false);
}
}
return fSuccess;
}
/**
* initDrives(aConfigDisks)
*
* @this {DriveController}
* @param {Array} [aConfigDisks]
* @return {boolean} true if successful, false if failure
*/
initDrives(aConfigDisks)
{
var fSuccess = true;
for (var iDrive = 0; iDrive < this.aDrives.length; iDrive++) {
var drive = this.aDrives[iDrive];
if (drive === undefined) {
drive = this.aDrives[iDrive] = {};
}
var configDisk = aConfigDisks && aConfigDisks[iDrive];
if (!this.initDrive(drive, iDrive, this.configDrive, configDisk)) {
fSuccess = false;
}
}
return fSuccess;
}
/**
* saveDrive(drive)
*
* @this {DriveController}
* @param {Object} drive
* @return {Array}
*/
saveDrive(drive)
{
return [
drive.fLocal,
drive.sDiskName,
drive.sDiskPath
]
}
/**
* saveDrives()
*
* @this {DriveController}
* @return {Array}
*/
saveDrives()
{
var data = [];
for (var iDrive = 0; iDrive < this.aDrives.length; iDrive++) {
data.push(this.saveDrive(this.aDrives[iDrive]));
}
return data;
}
/**
* initHistory(aHistory)
*
* @this {DriveController}
* @param {Array} [aHistory]
* @return {boolean} true if successful, false if failure
*/
initHistory(aHistory)
{
/*
* Initialize the disk history (if available) before initializing the drives, so that any disk deltas can be
* applied to disk images that are already loaded.
*/
if (aHistory) this.aDiskHistory = aHistory;
return true;
}
/**
* saveHistory()
*
* This returns an array of entries, one for each disk image we've ever mounted, including any deltas; ie:
*
* [name, path, deltas]
*
* aDiskHistory contains exactly that, except that deltas may not be up-to-date for any currently mounted
* disk image(s), so we call updateHistory() for all those disks, and then aDiskHistory is ready to be saved.
*
* @this {DriveController}
* @return {Array}
*/
saveHistory()
{
for (var iDrive = 0; iDrive < this.aDrives.length; iDrive++) {
var drive = this.aDrives[iDrive];
if (drive.disk) {
this.updateDiskHistory(drive.sDiskName, drive.sDiskPath, drive.disk);
}
}
return this.aDiskHistory;
}
/**
* autoMount(fRemount)
*
@ -724,6 +821,23 @@ class DriveController extends Component {
}
}
/**
* mountDrive(iDrive, sDiskName, sDiskPath)
*
* @this {DriveController}
* @param {number} iDrive
* @param {string} sDiskName
* @param {string} sDiskPath
*/
mountDrive(iDrive, sDiskName, sDiskPath)
{
var drive = this.aDrives[iDrive];
this.unloadDrive(iDrive, true);
drive.fLocal = true;
var disk = new DiskPDP11(this, drive, DiskAPI.MODE.PRELOAD);
this.finishLoadDrive(drive, disk, sDiskName, sDiskPath, true);
}
/**
* loadDrive(iDrive, sDiskName, sDiskPath, fAutoMount, file)
*
@ -931,7 +1045,7 @@ class DriveController extends Component {
* Next, make sure the drive whose disk we're updating is the currently selected drive.
*/
var iDriveSelected = Str.parseInt(controlDrives.value, 10);
var sTargetPath = (drive.fLocal? RL11.SOURCE.LOCAL : drive.sDiskPath);
var sTargetPath = (drive.fLocal? DriveController.SOURCE.LOCAL : drive.sDiskPath);
if (!isNaN(iDriveSelected) && iDriveSelected == iDrive) {
for (i = 0; i < controlDisks.options.length; i++) {
if (controlDisks.options[i].value == sTargetPath) {
@ -998,8 +1112,6 @@ class DriveController extends Component {
drive.disk = null;
drive.fLocal = false;
// this.regInput |= FDC.REG_INPUT.DISK_CHANGE;
if (!fLoading) {
this.notice("Drive " + this.getDriveName(iDrive) + " unloaded", fLoading);
this.sDiskSource = DriveController.SOURCE.NONE;

View file

@ -69,14 +69,13 @@ class RK11 extends DriveController {
}
/**
* initController(aRegs, aHistory)
* initController(aRegs)
*
* @this {RK11}
* @param {Array} [aRegs]
* @param {Array} [aHistory]
* @return {boolean} true if successful, false if failure
*/
initController(aRegs, aHistory)
initController(aRegs)
{
if (!aRegs) {
aRegs = [(RK11.RKDS.RK05 | RK11.RKDS.SOK | RK11.RKDS.RRDY), 0, (RK11.RKCS.CRDY), 0, 0, 0, 0];
@ -96,7 +95,7 @@ class RK11 extends DriveController {
this.regRKDB
] = aRegs;
return super.initController(aRegs, aHistory);
return true;
}
/**

View file

@ -69,14 +69,13 @@ class RL11 extends DriveController {
}
/**
* initController(aRegs, aHistory)
* initController(aRegs)
*
* @this {RL11}
* @param {Array} [aRegs]
* @param {Array} [aHistory]
* @return {boolean} true if successful, false if failure
*/
initController(aRegs, aHistory)
initController(aRegs)
{
if (!aRegs) {
aRegs = [(RL11.RLCS.DRDY | RL11.RLCS.CRDY), 0, 0, 0, 0, 0];
@ -95,7 +94,7 @@ class RL11 extends DriveController {
this.regRLBE
] = aRegs;
return super.initController(aRegs, aHistory);
return true;
}
/**