// BFS.DEF

structure [ wordAddr bit 12; bitAddr bit 4 ]

manifest [ msb=#100000
	 ]

manifest lFID=3


// disk data structures, transcribed from osstructures

// page 1 locations
manifest [
	nextDiskCommand = #521		// pointer to DCB
	diskStatus = #522		// @DS
	lastDiskAddress = #523		// @DA
	sectorInterrupts = #524
	]

// disk address
structure DA[
	sector bit 4
	track bit 9
	head bit 1
	disk bit 1
	restore bit 1
	]

// disk header
structure DH[
	packId word
	diskAddress @DA
	]

// disk label. *=set by DoDiskCommand
structure DL[
	next word		// disk address of next file
				// page, or eofDA
	previous word		// disk address of previous
				// file page, or eofDA
	blank word
	numChars word		// between 0 and charsPerPage inclusive.
				// ne charsPerPage only on last page
	pageNumber word		// * leader is page 0, first data
				// page is page 1
	fileId word lFID	// *
	]
manifest lDL=size DL/16

// disk status word.  See hardware manual for detailed definitions
structure DS[
	sector bit 4
	done bit 4
	seekFailed bit
	seekInProgress bit
	notReady bit
	dataLate bit
	noTransfer bit
	checksumError bit
	finalStatus bit 2
	]

// disk command
structure DC[
	seal bit 8			// must be #110
	headerAction bit 2
	labelAction bit 2
	dataAction bit 2
	seekOnly bit 1
	exchangeDisks bit 1		// disk controller inverts
					// DCB.diskAddress if this bit 
					// is set
	]
manifest diskCommandSeal=#110
// possible disk actions in command word
manifest [ diskRead = 0; diskCheck = 1; diskWrite = 2]

// disk command block. *=set by DoDiskCommand, $=defaulted by
// DoDiskCommand if 0
structure DCB[
	nextCommand word	// *
	status @DS		// set when command is completed
	command @DC		// *
	headerAddress word	// * these are memory addresses
	labelAddress word	// $
	dataAddress word	// *
	normalWakeups word	// $
	errorWakeups word	// $
	header @DH =
		[
		blank word
		diskAddress @DA	// * if DA argument ne fillInDA
		]
	]
manifest lDCB=size DCB/16

// *=initialized by InitializeCbStorage; everything else is zeroed
structure CBZ[
	length word		// *
	DAs word
	cleanupRoutine word
	currentDA	word
	currentPage word	// * set only by InitCbStorage
	currentNumChars word
	normalWakeups word
	errorWakeups word
	errorCount word
	errorRoutine	word
	extra	word
	queueHead word		// * address of first entry
	queueTail word		// * address of last entry + 1
	endQueueVec word	// * address of first word beyond
	queueVec ↑ 0, 1000 word	// * contains one more entry than
				// there are cb's in the zone

	]
manifest [
	lCBZ=offset CBZ.queueVec/16+1
	CBZqueueHead=offset CBZ.queueHead/16
	CBZqueueTail=offset CBZ.queueTail/16
	]

// *=initialized by InitializeCbStorage; everything else is zeroed
structure CB[
// the DCB must come first
	@DCB			// a free CB must have
				// status=DSgoodStatus;
				// initialization leaves it
				// that way
	label @DL

	truePageNumber word
// 'variable' part of the cb ends here
	zone word		// *
	retry word		// *
	]
manifest [ lCB=size CB/16; lVarCB=offset CB.zone/16 ]

// normally we want room for 3 cb's in a zone
manifest CBzoneLength=lCBZ+3*(lCB+1)

manifest [
	DSerrorBits=msb rshift offset DS.seekFailed +
		    msb rshift offset DS.notReady +
		    msb rshift offset DS.dataLate +
	  	    msb rshift offset DS.checksumError +
		    (-(msb rshift (size DS.finalStatus-1)))
			rshift offset DS.finalStatus;
	DSdoneBits=(-(msb rshift (size DS.done-1)))
			rshift offset DS.done;
	DSgoodStatusMask=DSerrorBits % DSdoneBits;
// good status means that all the error bits are 0
	DSgoodStatus=DSdoneBits
	DSfreeStatus=msb rshift (offset DS.done+size DS.done-1)
	]


// disk command actions
manifest [
 DCheaderx=msb rshift (offset DC.headerAction+size DC.headerAction-1)
 DClabelx=msb rshift (offset DC.labelAction+size DC.labelAction-1)
 DCdatax=msb rshift (offset DC.dataAction+size DC.dataAction-1)
	]

manifest [
	DCactionSeal=#321
	DCaS=DCactionSeal*(msb rshift (offset DC.seal+size DC.seal-1))
	]