// Tfs.d - definitions file for driving the Trident with TFS
// Copyright Xerox Corporation 1979, 1980, 1981

//	Last modified June 27, 1981  2:17 PM by Taft

// Format of file DiskDescriptor:
// Data Page 1:  This is mostly empty.  First lTFSKDHeader words have the
//	initial portion of the TFSKD structure recorded -- remainder empty
// Data Pages 2 through n (n is at most 5). These have bit table
//	(KDH.diskBTSize total words).
// The virtual disk addresses of all data pages are kept in the
//	TFSKD structure (VDAdiskDD) so they can be referenced directly.


manifest
   [
// low memory cells of interest
   DAstart = #420		// display location
// disk accessing constants (same for BFS and TFS)
   lFID = 3			// length of a FID
// TFS file-related constants
// Note that the physical disk shape parameters vary according to the
// disk model, and are determined dynamically by DetermineDiskModel.
   TFSwordsPerPage = 1024	// words in data block of sector
   TFSlnWordsPerPage = 10
   packID = 0			// part of FID

// definitions for bit table format
   lengthTFSDDpreamble = 2	// num pages in Disk Descriptor ahead of BT
   lengthTFSBT = 177777B rshift (TFSlnWordsPerPage+4) +1
   				// max length of TFS Bit Table (pages)
   ]

//used by disk bit table routines to compute bit locations
structure VDA:  // Virtual Disk Address
   [
   wordNum bit 12 =	// word index in whole file
      [
      pageNum bit 12-TFSlnWordsPerPage
      wordNumInPage bit TFSlnWordsPerPage
      ]
   bitNum bit 4		// bit index
   ]

//Trident disk hardware-related definitions

manifest
   [
   dcbID = #122645		// disk command seal
// Hardware command bit assignments
   CheckData = #4000
   WriteBit = #200
   ReadBit = #100
   HeadSelect = #4
   ReZero = #12
   CheckReset = #10
// Hardware disk commands used in conjunction with above
   diskRead = ReadBit + HeadSelect
   diskWrite = WriteBit + HeadSelect
   diskCheck = CheckData + ReadBit + HeadSelect
   diskReset = CheckReset
   diskRestore = ReZero
   diskNoop = HeadSelect

// Special disk command for verifying free labels:
   DCreadLnD=diskMagic+8	//Check header, read label, no data
   DCreadnD=diskMagic+9		//Check header, check label, no data
   DCwriteLnD=diskMagic+10	//check header, write label, no data
   ]

// Disk status word.  See hardware manual for detailed definitions
structure DST:
   [
   Status word =
      [
      Errors bit 10 =
         [  // * = may require a restore to clear
         SeekInc bit		// 100000 *
         CylOvfl bit		//  40000 -misnamed, really bad head #
         DeviceCk bit		//  20000 *
         NotSelected bit	//  10000
         NotOnLine bit		//   4000
         NotReady bit		//   2000
         SecOvfl bit		//   1000
         DataLate bit 2 =
            [
            WrLate bit		//    400
            RdLate bit		//    200
            ]
         CompErr bit		//    100
         ]
      ReadOnly bit		//     40
      Offset bit		//     20
      Sector bit 4 =		//     17 -- reported only in #643 
         [			// following reported only in CB:
         ECCerror bit		//     10
         Forgotten bit		//      4 -- set by software only
         Timeout bit		//      2 -- set by software only
         Done bit		//      1
         ]
      ]
   ]

manifest
   [
// Some bit masks corresponding to the DST structure
   dstDataLate=#600
   dstCompErr=#100
   dstECCerror=#10
   dstForgotten=#4
   dstTimeout=#2
   dstDone=#1
// Mask bits for status word
   dstErrors=#177716		// all errors -- ignore ReadOnly and Offset
   dstRestore=#160100		// errors that may require a restore to clear
   dstRetryIndefinitely=#604	// retry these errors without counting them
// Status word values
   dstFree=#177777		// denotes free CB -- set by software
   ]

// Trident Controller Control Block format
manifest KBLK = #640		// Trident controller CB address
structure KBLK:
   [
   ptr word	// KBLK+0 = #640 = pointer to command block
   drive word	// KBLK+1 = #641 = number of currently selected drive
   track word	// KBLK+2 = #642 = track number in last command
   @DST		// KBLK+3 = #643 = status at last sector pulse
   aborted word	// KBLK+4 = non-zero if a command was aborted
   ]


//Header,Label,Data formats on disk

// Hardware disk address - same as disk address used in the KCB
structure DA:
   [
   track word
   head byte
   sector byte
   ]

// Disk header - must be the same as DA
structure DH: @DA
manifest lDH = size DH/16

// Disk label.
// The last two words must be the next sector address in DH format
// (used for chaining operations)
// *=set by DoDiskCommand
// #=constant for all pages
structure DL:
   [
   fileId word lFID	// #*
   packID word		// #* 
   numChars word	// between 0 and charsPerPage inclusive.
   			// ne charsPerPage only on last page
   pageNumber word	// * page number in file of this page
   previous @DH		// disk address of previous file page, or eofDA
   next @DH		// disk address of next file page, or eofDA
   ]
manifest lDL=size DL/16

// Disk command block.
// one for each sector transfer
structure KCB:
   [
   diskAddress @DH = @DH	// +0 + 1
   drive word			// +2
   nextKCB word			// +3
   ID word			// +4 command seal
   CommH word			// +5 header command block 
   CountH word			// +6
   AddrH word			// +7
   ECC0H word			// +10
   ECC1H word			// +11
   StatusH @DST			// +12
   CommL word			// +13 label command block 
   CountL word			// +14
   AddrL word			// +15
   ECC0L word			// +16
   ECC1L word			// +17
   StatusL @DST			// +20
   CommD word			// +21 data command block 
   CountD word			// +22
   AddrD word			// +23
   ECC0D word			// +24
   ECC1D word			// +25
   StatusD @DST			// +26
   endWord word			// +27
   blank word			// +30 interrupt bits when implemented
   normalWakeups word		// +31
   errorWakeups word		// +32
   ]
manifest lKCB=size KCB/16

// Command format for each block within a sector
// used to fill in CB
structure KCBblock :
   [
   Comm word
   Count word
   Addr word
   ECC0 word
   ECC1 word
   Status word
   ]
manifest lKCBbl=size KCBblock/16


// TFS specialization of the Disk CBZ
structure TFSCBZ:
   [
   @CBZ				// standard part
   CBs word 0			// * as many CBs as will fit start here
   ]
manifest lTFSCBZ = size TFSCBZ/16  // fixed part of CBZ

// each CBZ contains a CB for each possible transfer enqueued
// the label must come first followed by the DCB (for chaining)
// a free CB must have status=DSTfreeStatus (initialization does that)
// *=initialized by InitializeCbStorage; everything else is zeroed
structure CB:
   [
   label @DL		// label (10 words)
   @KCB			// hardware oriented control block  (27 words)
   truePageNumber word	// 'variable' part of the cb ends here
// remaining words are not zeroed by TFSGetCb
   cbz word		// *
   vDiskAddress word	// VDA for this xfer (offset = 38.)
   nextCB word		// * pointer to next CB on CBZ queue
   ]
manifest
   [ 
   lCB = size CB/16
   lVarCB = offset CB.cbz/16
   CBzoneLength = lTFSCBZ+6*lCB  //6 CBs required to run at disk speed
   ]

// DSK structure for Trident
// First, the local definitions for Trident only:
// first lTFSKDHeader words are read in from disk at normal startup
manifest TFSKDversion=2

structure TFSKD:
   [
   @KDH				// standard 1st part
   version word			// version number of this DiskDescriptor
   model word			// disk model number
   packID word			// field setup when disk initialized
   VDAdiskDD↑1,lengthTFSBT+1 word  // VDAs of the data part of DD
   firstVTrack word		// first track used in file system
   nVTracks word		// number of tracks used in file system
   nTransfers word 2		// total number of transfers on this disk
   nErrors word 2		// total number of errors -- see TfsGetCb
   nECCErrors word 2		// total number of ECC errors encountered
   nECCFixes word 2		// total number of times recovery successful
   nRestores word 2		// number of "restore" operations done
   nUnRecov word 2		// number of unrecoverable errors
   nBTErrors word 2		// number of bit table discrepancies
   lastPageAlloc word		// last VDA allocated -- for biasing search

// words beyond here are not saved on the disk
   initmode word		// nonzero if permitted to create new files
   zone word			// zone of this DSK
   ddMgr word			// pointer to DiskDescriptor Manager object
   fpTFSSysDirblk word lFP	// storage for FP
   fpTFSDDblk word lFP		// storage for FP
   fpTFSWDblk word lFP		// storage for FP
   WDNameblk word maxLengthFnInWords  // storage for name
   ]
manifest lTFSKDHeader = (offset TFSKD.initmode/16)

// extended version of the disk structure
structure TFSDSK:
   [
   @DSK
   @TFSKD
   ]
manifest lTFSDSK = size TFSDSK/16

// TFSDSK offsets known to TfsA.Asm
compileif offset TFSDSK.nHeads/16 ne 26 % offset TFSDSK.nSectors/16 ne 27 %
 offset TFSDSK.firstVTrack/16 ne 48 % offset TFSDSK.nVTracks/16 ne 49 then
   [ Barf("TFSDSK offsets wrong") ]

// bad page list (on physical page 0 of pack)
structure BPL:
   [
   seal word		// indicates presence of bad page list
   nBadPages word	// number of bad pages
   da↑0,0 @DA		// real disk addresses of bad pages
   ]
manifest bplSeal = #123456

// error codes
manifest
   [
   ecOsVersion = 2403
   ecTfsQueue = 2404
   ecNoCreationAbility = 2405
   ecBadAction = 2406
   ecBadBtPage = 2407
   ecEssentialFile = 2408
   ecBadAssignPage = 2409
   ecReadOnly = 2410
   ecDriveHung = 2411
   ecUnRecovDiskError = 2412
   ecDiskFull=2413
   ]