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

//	Last modified January 31, 1980  4:43 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
   TFSmNDisks=1			// possible number of disks per bit table
   TFSmNTracks=815		// number of tracks (cylinders)
   T300mNVTracks = 383		// max number of tracks addressable on T-300
   				// using virtual disk addresses
   T80mNHeads=5			// number of heads on T-80
   T300mNHeads = 19		// number of heads on T-300
   TFSmNSectors=9		// number of sectors
   TFSwordsPerPage = 1024	// words in data block of sector
   TFSlnWordsPerPage = 10
// maximum number of virtual pages in a file system
   T80mNVPages = TFSmNTracks*T80mNHeads*TFSmNSectors
   T300mNVPages = T300mNVTracks*T300mNHeads*TFSmNSectors
   packID = 0			// part of FID

// definitions for bit table format
   lengthTFSDDpreamble = 2	// num pages in Disk Descriptor ahead of BT
   lengthTFSBT = (T300mNVPages-1) 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
   ]


// Operations defined on a Disk Descriptor Manager (DDMgr) object.
// See TfsDDMgr.bcpl for details.
structure DDMgrOperations:
   [
   OpenDD word		// Call0
   LockDD word		// Call1
   ReadDDPage word	// Call2
   UnlockDD word	// Call3
   FlushDD word		// Call4
   CloseDD word		// Call5
   DestroyDDMgr word	// Call6
   ]

//Trident disk hardware-related definitions

manifest
   [
   KBLK = #640			// Trident controller CB address
   dcbID = #122645		// disk command seal
// Mask bits for status word
   DSTrestoreBits=#160100
   DSTerrorBits=#177717		// ignore ReadOnly and Offset
// Status word values
   DSTfreeStatus=#17		// init state set by software
   DSTgoodStatus=1		// set by microcode after transfer
// Hardware command bit assignments
   CheckData = #4000
   WriteBit = #200
   ReadBit = #100
   HeadSelect = #4
   ReZero = #12
   CheckReset = #10
// Extended memory bank selection in command word
   selectBank0 = #0
   selectBank1 = #40000
   selectBank2 = #100000
   selectBank3 = #140000
// 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
      ECCerror bit =		//     10 -- reported only in CB
         Sector bit 4		// -- reported only in #643 
      ]
   ]

// Trident Controller Control Block format
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 (80 = T-80, 300 = T-300)
   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
   ]