//PrintDisk31.bcpl - handle queued I/O for model 31 disk

// errors 2400

get "PDInternals.d"
get "altofilesys.d"
get "disks.d"
get "bfs.d"

//outgoing procedures
external
	[
	PrintInit31
	PrintRead31
	PrintCheck31
	PrintStop31
	]

//incoming procedures
external
	[
	FileVDA
	PDError
	]

//incoming statics
external
	[
	BitsFile
	sysDisk

	dcbOffset
	nDCBPerBuffer
	dataOffset
	lenDCB
	nextReadPage
	nBufsToRead
	nextReadBuf
	nBufsToCheck
	nextCheckBuf
	]

manifest diskCommand=#521

let PrintInit31(buf) be
[
	if lenDCB ls lKCB then PDError(2400)
	let command=readHLD
	if BitsFile>>F.Device eq DISK31B then command=command+1
	compileif size DH/16 gr 2 then [ foo=nil ]
	let headerBuff=table [ 0;0 ]
	compileif size DL/16 gr 8 then [ foo=nil ]
	let labelBuff=table [ 0;0;0;0;0;0;0;0 ]
	let dcb=buf+dcbOffset
	let dataAddr=buf+dataOffset
	for i=1 to nDCBPerBuffer do
		[
		dcb>>KCB.link=dcb+lKCB
		//dcb>>KCB.status=0 assigned in PrintRead31
		dcb>>KCB.command=command
		dcb>>KCB.headerAddress=headerBuff
		dcb>>KCB.labelAddress=labelBuff
		dcb>>KCB.dataAddress=dataAddr
		dcb>>KCB.normalWakeups=0
		dcb>>KCB.errorWakeups=0
		//dcb>>KCB.DA assigned in PrintRead31
		dataAddr=dataAddr+BFSwordsPerPage
		dcb=dcb+lKCB
		]
	(dcb-lKCB)>>KCB.link=0	//end of the line
]
 
//PrintRead31 pushes new dcbs onto KBLK for buffer read

and PrintRead31() = valof 
[
	if nBufsToRead eq 0 then resultis 0
	if nextReadBuf!-2 ne 0 then resultis nBufsToRead

	let realDA=sysDisk!7
	let dcb=nextReadBuf+dcbOffset
	let xdcb=dcb
	for i=1 to nDCBPerBuffer do
		[
		let vda=FileVDA(BitsFile, nextReadPage+1)
		realDA(sysDisk, vda, lv xdcb>>KCB.diskAddress)
		xdcb>>KCB.status=0
		nextReadPage=nextReadPage+1
		xdcb=xdcb+lKCB
		]
	(xdcb-lKCB)>>KCB.link=0 //end of the line

//QueueDiskCommand
	let np=diskCommand
	until @np eq 0 do np=@np
	@np=dcb
	if @diskCommand eq 0 then @diskCommand=dcb

	nextReadBuf!-2=1
	nextReadBuf=nextReadBuf!-1
	nBufsToRead=nBufsToRead-1
	resultis nBufsToRead
]

//PrintCheck31 checks that a buffer read has completed

and PrintCheck31() = valof
[
	if nBufsToCheck eq 0 then resultis 0
	if nextCheckBuf!-2 ne 1 then resultis nBufsToCheck

	let dcb=nextCheckBuf+dcbOffset
	for i=1 to nDCBPerBuffer do
		[
		if (dcb>>KCB.status&DSTdoneBits) eq 0 then resultis nBufsToCheck
		dcb=dcb+lKCB
		]

	nextCheckBuf!-2=0		//checked
	nextCheckBuf=nextCheckBuf!-1
	nBufsToCheck=nBufsToCheck-1
	resultis nBufsToCheck
]

and PrintStop31() be
[
	let np=@diskCommand
	until np eq 0 do
		[ let n=np>>KCB.link; np>>KCB.link=0; np=n ]
	until @diskCommand eq 0 do [ ]
]