{  File: Buffer.asm
Modification History:
last modification by Jim Frandeen:  September 15, 1982  4:53 PM: Initialize KeyMap in the IO Page.
last modification by Jim Frandeen:  August 9, 1982  4:15 PM: Add BlockBuffer for Processor ReadBlock and WriteBlock commands. Put initial code and Burdock code in the Floppy buffer.
last modification by Jim Frandeen:  April 22, 1982  1:05 PM: Rewrite RS232C
}

{  This file contains the allocation of the large buffer areas for Domino.  The buffers are allocated at the end of the code, so that they do not take up room during the loading of Domino during booting.  This module should always be the LAST module in the Domino
configuration. }

	GET	"RS232CDefs.asm"
	GET	"SysDefs.asm"
	GET	"CommonDefs.asm"

	IMP	CheckCPDmaComplete	;CPSubs
	IMP	ClearMiscControl1Bit	;Common
	IMP	DisableRST	;Common
	IMP	GetTOD		;BookKeepingTask
	IMP	MainLoop	;BookKeepingTask
	IMP	ProcData0	;BookKeepingTask
	IMP	ProcData1	;BookKeepingTask
	IMP	ProcData2	;BookKeepingTask
	IMP	PutMPanel	;Common
	IMP	ReadKeyboard	;BookKeepingTask
	IMP	ResetProcessorCommand	;BookKeepingTask
	IMP	SetMiscControl1Bit	;Common
	IMP	StartCPReadDma	;CPSubs
	IMP	StartCPWriteDma	;CPSubs
	IMP	TransferProcessorCSB	;BookKeepingTask
	IMP	Wait		;Common

	EXP	BlockBuffer
	EXP	DoReadIOPCmd
	EXP	DoReadUmbilicalBlockCmd
	EXP	DoWriteIOPCmd
	EXP	DoWriteUmbilicalBlockCmd
	EXP	EndFDBuffer	; FloppyTask buffer
	EXP	FDBuffer0	; FloppyTask buffer
	EXP	FDBuffer1	; FloppyTask buffer
	EXP	RxFIFO	 	; For RS232CTask
	EXP	Start
	EXP	StartFDBuffer	; FloppyTask buffer
	EXP	TxBuffer

; RS232C Task Buffers
TxBuffer:
	DS	TxBufferSize	; Tx Data Buffer

RxFIFO:
	DS	RxFifoSize	; Rx Data Buffer 
;
{  Floppy Task buffers:
Note that the Start code and the Burdock code is in the Floppy buffers. This means that the Burdock code cannot be used if the Floppy has been used. 

(Each buffer is large enough to hold a one page sector):
(The area from StartFDBuffer to EndFDBuffer can hold 4 standard Sectors)}
;
StartFDBuffer:
BlockBuffer:
	ds	0
FDBuffer0:
	ds	0
Start:
	DI			;For Initializing
	LXI	SP,UserStkStart	;Initialize user stack pointer
	MVI	A,ResetRst75+Rst75DisableMsk+Rst65DisableMsk
	CALL	DisableRST	;Disable RST 6.5 and 7.5, clear 7.5 FF (RS232C, Floppy)
	MVI	A,DisableFDC	;Disable floppy controller, Enable Waits
	OUT	FDCState
	IN	DmaStatus	;Clear the DMA status register
	XRA	A		;Clear A
	OUT	DmaMode		;Disable controller
	EI			;For mouse halting
	CMA			;Set all clock bits high
	OUT	MiscClocks1	
	LXI	H,MPStartDomino	;Initialize the Maintenance Panel
	CALL	PutMPanel	;MP ← StartDomino (500)
	OUT	MouseClr	;Clear hardware counters
	MVI	A,KBDiag	;Set KB diag mode
	CALL	SetMiscControl1Bit
	LXI	H,KBDiagWait	;Initialize delay for KBDiag signal
	CALL	Wait		;Wait 15 msec
	MVI	A,nKBDiag		;Clear KB diag mode
	CALL	ClearMiscControl1Bit	;clear bit in register

{Initialize the TOD state.}
	LXI	H,MPInitTOD
	CALL	PutMPanel	;MP ← InitTOD (501)
	CALL	GetTOD
	LXI	H,MPInitTODDone
	CALL	PutMPanel	;MP ← InitTODDone (502) and RET
	CALL	ReadKeyboard	;Initialize KeyMap in IO Page
	JMP	MainLoop

LastStartInstruction	DS	0
StartCodeCount	EQU	LastStartInstruction-Start
	ds	512-StartCodeCount
FDBuffer1:
	ds	1024
;
StartBurdockCode:
BlockPCB:
;This PortControlBlock is used to transfer data to and from the CP for the ReadBlock and WriteBlock Processor commands.
BlockAddressLo:
	DW	0
BlockAddressHi:
	DW	0
BlockByteCount:
	DW	0
	DW	BlockBuffer
TimeOutConst	equ	0A000H	;  Approx. .25 sec

DoReadIOPCmd:
{Command 5:  Do Read IOP Command. The address of the byte to read is in ProcData2. The byte read will be returned in the low byte of ProcData1.}
	LHLD	ProcData2	;HL ← memory address
	MOV	A,M		;A ← byte
	STA	ProcData1
	JMP	TransferProcessorCSB

DoWriteIOPCmd:
{Command 6:  Do Write IOP Command.  The address of the byte to write is in ProcData2. The low byte of ProcData1 contains the byte to write.}
	LHLD	ProcData2	;HL ← memory address
	LDA	ProcData1	;A ← byte to write
	MOV	M,A		;Write byte to IOP memory
	JMP	ResetProcessorCommand

DoReadUmbilicalBlockCmd:
{Command 7:  Do Read Umbilical Block Command. ProcData2 contains the number of bytes to write in the high order byte. ProcData1 and ProcData0 contain a Long Pointer to the user's buffer area. This area must be resident. Set up the PCB to transfer the data between CP virtual memory and BlockBuffer. NOTE: the FLoppy buffer is used for the DMA transfer. This means we can't be doing floppy operaions at the same time, and the buffer is limited to 1536 bytes.}

	LHLD	ProcData1
	SHLD	BlockAddressLo
	LHLD	ProcData0
	SHLD	BlockAddressHi
	LHLD	ProcData2
	SHLD	BlockCopyCount
	INX	H		;Make the count even
	MOV	A,L
	ANI	0FEH
	MOV	L,A
	SHLD	BlockByteCount
	LXI	D,BlockBuffer	;DE ← IOP Buffer address

ReadBlockLoop:
{Now wait to determine whether Burdock is there. The inner loop is approximately 49 cycles (~= 17 usec). The delay is approximately 17 * TimeOutConst usec.}

	LXI	H,TimeOutConst	;  [10]  Time-out constant
WaitToReadByte:
	IN	AltoPPIC
	ANI	IntBMask	;[7]
	JNZ	ReadByte	;[7]  nz => Byte is ready
	DCX	H		;[6]
	MOV	A,H		;[4]
	ORA	L		;[4]
	JNZ	WaitToReadByte	;[10]
	JMP	SetUmbilicalReturnCode

ReadByte:
	IN	AltoPPIB
	STAX	D		;Store byte in buffer
	INX	D		;Increment buffer address
	LHLD	BlockCopyCount
	DCX	H
	SHLD	BlockCopyCount
	MOV	A,H
	ORA	L
	JNZ	ReadBlockLoop

	LXI	H,BlockPCB
	CALL	StartCPWriteDma	;Send block to CP

WaitForUmbilicalBlockTransfer:
{Wait for the transfer to complete. It would take extra code to pass control to the next task. Since we only use this for Burdock, it won't hurt to wait for the DMA.}
	CALL	CheckCPDmaComplete
	JZ	WaitForUmbilicalBlockTransfer
	JMP	SetUmbilicalReturnCode


DoWriteUmbilicalBlockCmd:
{Command 7:  Do Write Umbilical Block Command. ProcData2 contains the number of bytes to write in the high order byte. ProcData1 and ProcData0 contain a Long Pointer to the user's buffer area. This area must be resident. Set up the PCB to transfer the data between CP virtual memory and BlockBuffer. NOTE: the FLoppy buffer is used for the DMA transfer. This means we can't be doing floppy operaions at the same time, and the buffer is limited to 1536 bytes.}

	LHLD	ProcData1
	SHLD	BlockAddressLo
	LHLD	ProcData0
	SHLD	BlockAddressHi
	LHLD	ProcData2
	SHLD	BlockCopyCount
	INX	H		;Make the count even
	MOV	A,L
	ANI	0FEH
	MOV	L,A
	SHLD	BlockByteCount
	LXI	H,BlockPCB
	CALL	StartCPReadDma	;Read block from CP

WaitForWriteBlock:
{Wait for the transfer to complete. It would take extra code to pass control to the next task. Since we only use this for Burdock, it won't hurt to wait for the DMA.}
	CALL	CheckCPDmaComplete
	JZ	WaitForWriteBlock

	LXI	D,BlockBuffer	;DE ← IOP Buffer address

WriteBlockLoop:
	LDAX	D		;A ← next byte from buffer
	OUT	AltoPPIA	;Write data
{Now wait to determine whether Burdock is there. The inner loop is approximately 49 cycles (~= 17 usec). The delay is approximately 17 * TimeOutConst usec.}

	LXI	H,TimeOutConst	;  [10]  Time-out constant
WaitAckLoop:
	IN	AltoPPIC	;[11] Read Channel B interrupt
	ANI	IntAMask	;[7]
	JNZ	NextByte	;[7]  nz => Burdock took byte
	DCX	H		;[6]
	MOV	A,H		;[4]
	ORA	L		;[4]
	JNZ	WaitAckLoop	;[10]

SetUmbilicalReturnCode:
	LHLD	BlockCopyCount	;Will be zero if	
	SHLD	ProcData0	;all bytes transferred
	JMP	TransferProcessorCSB

NextByte:
	INX	D		;Increment buffer address
	DB	opLXIH		;HL ← BlockCopyCount
BlockCopyCount:
	DW	0
	DCX	H
	SHLD	BlockCopyCount
	MOV	A,H
	ORA	L
	JNZ	WriteBlockLoop
	JMP	SetUmbilicalReturnCode

LastBurdockInstruction:	DS	0
BurdockInstructionCount	EQU	LastBurdockInstruction-StartBurdockCode
	ds	512-BurdockInstructionCount
;
EndFDBuffer:
	ds	0


;-----------------------------------------------------
NextLoc:
	ds	1		;  Next free location
	END	Buffer