*-----------------------------------------------------------
Title[DiskDefs.mc...November 23, 1982  10:08 AM...Taft];
*** Pilot-only version ***
*-----------------------------------------------------------

*-----------------------------------------------------------
* R-register assignments
*-----------------------------------------------------------

SetRMRegion[DiskRegs];
	RVN[KIOCB];		* IOCB address
	RVN[KDataLo];		* Address of end of data block
	RVN[KDataHi];
	RVN[Sector];		* sector counter
	RVN[MaxSectors];	* maximum number of sectors expected
	RVN[KPtr];		* command block pointer
	RVN[KAddr];		* disk address (or parts thereof)
	RVN[KCmmd];		* disk command (hardware)
	RVN[DskMAddr];		* memory address for data
	RVN[KStatus];		* disk software status
	RVN[KSelect];		* [0..3] zero (tagDrive)
				* [4] one iff sectors do not evenly divide the disk
				* [5] unused
				* [6..10] zero (tagSubSector, tagLoadSubSector)
				* [11] one tagSelectDrive
				* [12..15] currently addressed drive
	RV[K400, 400];		* constant 400
	RVN[KTemp0];
	RVN[KTemp1];
	RVN[KTemp2];
	RVN[KTemp3];

*-----------------------------------------------------------
* Device assignments
*-----------------------------------------------------------

	Device[DiskControl, 10]; * control register (output)
	Device[DiskMuff, 11];	* muffler and wakeup control (output);
				* muffler data in bit 15 (input)
	Device[DiskData, 12];	* disk read/write data (input/output);
				* must be selected to enable WrFifoTW
	Device[DiskRam, 13];	* format ram (output)
	Device[DiskTag, 14];	* tag bus (output)

*-----------------------------------------------------------
* Muffler addresses, as viewed by controller.
* Add 2000 to produce normal (system-wide) muffler addresses.
*-----------------------------------------------------------

MC[muffsState, 0];		* Group of 20 controller state mufflers
*	MC[muffTempSense, muffsState, 0];
	MC[muffIndexTW, muffsState, 1];
	MC[muffSectorTW, muffsState, 2];
	MC[muffSeekTagTW, muffsState, 3];
	MC[muffRdFifoTW, muffsState, 4];
	MC[muffWrFifoTW, muffsState, 5];
*	MC[muffReadData, muffsState, 6];
*	MC[muffWriteData, muffsState, 7];

*	MC[muffEnableRun, muffsState, 10];
*	MC[muffDebugMode, muffsState, 11];
*	MC[muffRdOnlyBlock', muffsState, 12];
*	MC[muffWriteBlock', muffsState, 13];
*	MC[muffCheckBlock', muffsState, 14];
*	MC[muffActive, muffsState, 15];
	MC[muffSelect.0, muffsState, 16];
	MC[muffSelect.1, muffsState, 17];

MC[muffsStatus, 20];		* Group of 20 drive and error status mufflers
*	MC[muffSeekInc, muffsStatus, 0];
*	MC[muffHeadOvfl, muffsStatus, 1];
*	MC[muffDevCheck, muffsStatus, 2];
*	MC[muffNotSelected, muffsStatus, 3];
*	MC[muffNotOnLine, muffsStatus, 4];
	MC[muffNotReady, muffsStatus, 5];
*	MC[muffSectorOvfl, muffsStatus, 6];
	MC[muffFifoUnderflow, muffsStatus, 7];

	MC[muffFifoOverflow, muffsStatus, 10];
*	MC[muffReadDataErr, muffsStatus, 11]; * = compare error usually
*	MC[muffReadOnly, muffsStatus, 12];
*	MC[muffCylOffset, muffsStatus, 13];
*	MC[muffIOBParityErr, muffsStatus, 14];
*	MC[muffFifoParityErr, muffsStatus, 15];
	MC[muffWriteError, muffsStatus, 16];
	MC[muffReadError, muffsStatus, 17];

MC[muffsRam, 40];		* Format Ram address and data
MC[muffsTag, 60];		* Tag bus to drive
MC[muffsFifo, 100];		* Fifo control mufflers

*-----------------------------------------------------------
* Control bits: output to DiskMuff register
*-----------------------------------------------------------

	MC[clearCompareErr, 20000];	* clear CompareErr flipflop
	MC[setCheckSumErr, 10000];	* set ReadDataErr flipflop
	MC[clearIndexTW, 4000];		* clear IndexTW
	MC[clearSectorTW, 2000];	* clear SectorTW
	MC[clearSeekTagTW, 1000];	* clear SeekTagTW
	MC[clearErrors, 400];		* clear error flipflops
*	MC[muffAddr, 377];		* muffler address

	MC[clearAllTWs, clearIndexTW, clearSectorTW, clearSeekTagTW];
	MC[clearAll, clearAllTWs, clearErrors];

*-----------------------------------------------------------
* Control bits: output to DiskControl register
*-----------------------------------------------------------

	MC[clearEnableRun, 2000];	* clear EnableRun
	MC[debugMode, 1000];		* set DebugMode if 1, clear if 0
	MC[blockTilIndex, 400];		* set BlockTilIndex if 1, clear if 0
*	MC[commands, 377];		* disk commands: 4 2-bit bytes,
*					* one per block, indicating:
		MC[commandWrite, 1];
		MC[commandCompare, 2];
		MC[commandRead, 3];

*-----------------------------------------------------------
* Control bits: output to DiskTag register
*-----------------------------------------------------------

	MC[tagDrive, 100000];
	MC[tagCylinder, 40000];
	MC[tagHead, 20000];
	MC[tagControl, 10000];
	MC[tagBus, 7777];

* TagBus interpretation for DriveTag:
*	MC[tagSubSector, 1700];		* subsector count
	MC[tagLoadSubSector, 40];	* load subsector for currently-addressed drive
	MC[tagSelectDrive, 20];		* select the specified drive
	MC[tagDriveNumber, 17];		* drive number

* TagBus interpretation for CylinderTag:
*	MC[tagCylinderNumber, 7777];

* TagBus interpretation for HeadTag:
*	MC[tagOffset, 200];		* offset head position
*	MC[tagOffsetDirection, 100];	* direction of offset
*	MC[tagHeadNumber, 77];

* TagBus interpretation for ControlTag:
	MC[tagAltoLeader, 4000];	* search for Alto Trident sync pattern
*	MC[tagStrobeEarly, 1000];
*	MC[tagStrobeLate, 400];
	MC[tagWrite, 200];
	MC[tagRead, 100];
*	MC[tagResetHAR, 20];
	MC[tagDiskReset, 10];		* reset errors latched in the drive
	MC[tagHeadSelect, 4];		* turn on selected head for read/write
	MC[tagReZero, 2];		* restore disk to cylinder 0
*	MC[tagHeadAdvance, 1];		* increment head address register

*-----------------------------------------------------------
* Pilot disk-related data structures
*-----------------------------------------------------------

* Note: the default initializations in the following record definitions
* indicate values that must be supplied by the software.

* ControllerStatusBlock: TYPE = MACHINE DEPENDENT RECORD [
* next is interpreted only if it is odd.  When an error occurs, microcode
* makes next even, such that (next+1) points to the IOCB that suffered
* the error.  Disk activity thus freezes until the software resets next.
MC[CSB.next, DiskCSB, 0];	* next: POINTER TO IOCB,
MC[CSB.interruptMask, DiskCSB, 1]; * interruptMask: CARDINAL,
MC[CSB.drive, DiskCSB, 2];	* drive: CARDINAL,
* If cylinder is negative, the next command will initiate a restore.
MC[CSB.cylinder, DiskCSB, 3];	* cylinder: CARDINAL,
				* ... ]; -- Other stuff not used by microcode

* -- IOCBs must be odd-word aligned!
* IOCB: TYPE = MACHINE DEPENDENT RECORD [
MC[IOCB.next, 0];		* next: POINTER TO IOCB,
* seal is zeroed when command is done; this is how software detects completion
MC[IOCB.seal, 1];		* seal: CARDINAL ← 125377B,
  MC[IOCBSealValue, 125377];
MC[IOCB.drive, 2];		* drive: CARDINAL, -- not presently used
* pageCount is decremented after each page successfully transferred.
* Thus pageCount=0 upon completion indicates that no errors occurred.
MC[IOCB.pageCount, 3];		* pageCount: CARDINAL,
MC[IOCB.command, 4];		* command: DiskCommand:
* diskAddress is incremented after each page successfully transferred, and
* copied into diskHeader for checking purposes.  After a header read,
* diskHeader contains the header read from the disk.
MC[IOCB.diskAddress, 5];	* diskAddress: DiskAddress,
MC[IOCB.diskHeader, 7];		* diskHeader: DiskAddress,
MC[IOCB.headerPtr, 11];		* headerPtr: LONG POINTER ← @iocb.diskHeader,
MC[IOCB.headerECC, 13];		* headerECC: LONG CARDINAL,
MC[IOCB.headerStatus, 15];	* headerStatus: DiskStatus,
* labelPtr should point to IOCB.diskLabel when checking or writing so that
* updated values are used during runs of pages.  During checking, the first
* 8 words of the label are checked and the last 2 are read.
MC[IOCB.labelPtr, 16];		* labelPtr: LONG POINTER ← @iocb.diskLabel,
MC[IOCB.labelECC, 20];		* labelECC: LONG CARDINAL,
MC[IOCB.labelStatus, 22];	* labelStatus: DiskStatus,
* dataPtr is incremented by 400B after each page successfully transferred,
* if command.incrementDataPointer = TRUE.
MC[IOCB.dataPtr, 23];		* dataPtr: LONG POINTER,
MC[IOCB.dataECC, 25];		* dataECC: LONG CARDINAL,
MC[IOCB.dataStatus, 27];	* dataStatus: DiskStatus,
* Microcode updates this copy of the label after each page successfully
* transferred.  IOCB.labelPtr should point here during checking and writing.
MC[IOCB.diskLabel, 30];		* diskLabel: PilotDisk.Label ];

MC[sizeIOCB, 42];

* Pilot standard disk address
* DiskAddress: TYPE = MACHINE DEPENDENT RECORD [
*	cylinder: CARDINAL,
*	head, sector: [0..377B]];

* Dorado disk command (hardware format except for incrementDataPtr)
* Action: TYPE = {none, write, check, read};
* DiskCommand: TYPE = MACHINE DEPENDENT RECORD [
*	incrementDataPtr: BOOLEAN,
*	unused: [0..177B] ← 0,
*	header: Action,
*	label: Action,
*	data: Action,
*	unused: Action ← none ];

* DiskStatus: TYPE = MACHINE DEPENDENT RECORD [
* -- following are hardware conditions reported directly from the controller:
*				* seekInc: BOOLEAN,
*				* headOvfl: BOOLEAN,
*				* devCheck: BOOLEAN,
*				* notSelected: BOOLEAN,
*				* notOnLine: BOOLEAN,
*				* notReady: BOOLEAN,
MC[DS.sectorOvfl, 1000];	* sectorOvfl: BOOLEAN,
*				* fifoUnderflow: BOOLEAN,
*				* fifoOverflow: BOOLEAN,
MC[DS.checkErr, 100];		* checkErr: BOOLEAN, -- = ReadDataErr
*				* readOnly: BOOLEAN,
*				* cylOffset: BOOLEAN,
*				* iobParityErr: BOOLEAN,
*				* fifoParityErr: BOOLEAN,
* -- following are microcode-detected conditions:
MC[DS.eccErr, 2];		* eccErr: BOOLEAN,
MC[DS.sectorSearchErr, 1];	* sectorSearchErr: BOOLEAN ];

* Excerpt from Pilot Label record, showing fields that must be
* modified by the microcode during runs of pages.
* Label: TYPE = MACHINE DEPENDENT RECORD [
*				* fileID: File.ID,
MC[Lab.filePageLo, 5];		* filePageLo: CARDINAL ], -- increment this
MC[Lab.filePageHi, 6];		* filePageHi: [0..177B],
*				* pad1: [0..77B],
*				* fileFlags: [0..7B], -- zero these
*				* type: File.type,
MC[Lab.bootChainLink, 10];	* bootChainLink: DiskAddress];

MC[sizeHeader, 2];
MC[sizeLabel, 12];
MC[sizeData, 400];

%
The Dorado Trident disk is formatted as 815 cylinders, 5 heads, 28 sectors.
We use only 28 of the usable 29 sectors, because addressing the 29th is
somewhat tricky.

For compatibility with partitioning of Dorado disks for Alto emulation
(one partition on each surface of the disk), we emulate a disk that has
a different shape from the real disk: 4075 (=5*815) cylinders, 1 head,
28 sectors.  This is so that a partition occupies a contiguous interval
of virtual addresses under Pilot's virtual-to-real disk address mapping,
which increments heads before cylinders.  Thus:

	real cylinder = emulated cylinder MOD 815
	real head = emulated cylinder / 815
	real sector = emulated sector

Note that the head number in the emulated disk address is ignored.

The reason the microcode has to know about all this garbage is that
it needs to be able to increment the disk address during runs of pages.
%

* Disk format parameters:
MC[nCylinders, 1457];		* = 815
MC[nSectors, 34];		* = 28
Set[staggerSectors, 1];		* Stagger sectors on adjacent cylinders