; encml.asm
; Assembler encryption (DMA)

; L. Stewart, November 2, 1982  10:36 AM
; LCS, April 30, 1983  10:46 AM, pro and epilogs added

; BLT code removed, check for 0 key in di2001.c now
; Crypt returns true for success now

$INCLUDE(Lark.d)

emode	EQU	000H	; dma mode for encryption
masmode	EQU	04AH	; channel 2, single xfer, read
slvmode	EQU	047H	; channel 3, single xfer, write
KP	EQU	2
SRCP	EQU	4
DSTP	EQU	6
COUNT	EQU	8
MODE	EQU	10

C←CODE SEGMENT

C←DATA SEGMENT

C←DATA ENDS

ASSUME CS:C←CODE, DS:C←DATA

; procedure called with BX pointing to a structure
;	word 1:  pointer to key
;	word 2:  pointer to source
;	word 3:  pointer to destination
;	word 4:  count (bytes, must be multiple of 8)
;	word 5:  -1 for encrypt, 0 for decrypt
;	word 6:  item
;	word 7:  proc  (to be called with item)
; procedure returns 0 (false) on key parity error, else -1 (true) (in BX)

←Crypt		LABEL	NEAR
	PUSH	BP
	MOV	BP,SP
	MOV	AX,[MODE+BX]
	OR	AX,AX
	JZ	decrypt
	XOR	CL,CL
	JMP	aecom
decrypt:
	MOV	CL,008H
aecom:
	MOV	AL,006H		; mask off mas and slv DMA
	OUT	dmasmsk,AL
	MOV	AL,007H
	OUT	dmasmsk,AL
	MOV	AL,emode	; once per boot should be enough!
	OUT	dmacmd,AL
	MOV	AL,CL
	OUT	encctl,AL		; clear WD2001
	OR	AL,002H
	OUT	encctl,AL		; activate WD2001
; load key
	CLD
	MOV	SI,WORD PTR [KP+BX]
	MOV	DX,encdata
	LODSW
	OUT	DX,AL
	MOV	AL,AH
	OUT	DX,AL
	LODSW
	OUT	DX,AL
	MOV	AL,AH
	OUT	DX,AL
	LODSW
	OUT	DX,AL
	MOV	AL,AH
	OUT	DX,AL
	LODSW
	OUT	DX,AL
	MOV	AL,AH
	OUT	DX,AL
	IN	AL,encctl
	AND	AL,020H		; check for KPE
	JZ	ae1
	XOR	BX,BX
	MOV	SP,BP
	POP	BP
	RET
; set up DMA
ae1:
	XOR	AL,AL
	OUT	dmacbp,AL
	MOV	AL,masmode
	OUT	dmamode,AL
	MOV	AL,slvmode
	OUT	dmamode,AL
	MOV	AX,[SRCP+BX]
	OUT	dmaad2,AL
	MOV	AL,AH
	OUT	dmaad2,AL
	MOV	AX,[DSTP+BX]
	OUT	dmaad3,AL
	MOV	AL,AH
	OUT	dmaad3,AL
	MOV	CX,[COUNT+BX]
	DEC	CX
	JNS	countOK
	XOR	BX,BX
	MOV	SP,BP
	POP	BP
	RET
countOK:
	MOV	AL,CL
	OUT	dmawc2,AL
	MOV	AL,CH
	OUT	dmawc2,AL
	MOV	AL,CL
	OUT	dmawc3,AL
	MOV	AL,CH
	OUT	dmawc3,AL
; start dma
	MOV	AL,002H		; turn on mas and slv DMA
	OUT	dmasmsk,AL
	MOV	AL,003H
	OUT	dmasmsk,AL
	MOV	BX,-1		; return true
	MOV	SP,BP
	POP	BP
	RET

; procedure tests for end of encryption, returns 0 on not done
; if encryption is complete, returns 1
←EncEnd PROC NEAR
	PUSH	BP
	MOV	BP,SP
	IN	AL,dmastat
	AND	AL,008H		; wait for slv TC
	JNZ	enccu
	XOR	BX,BX		; return 0
	MOV	SP,BP
	POP	BP
	RET
enccu:
	XOR	AL,AL
	OUT	encctl,AL	; stop encryption
	MOV	AL,006H		; mask off mas and slv DMA
	OUT	dmasmsk,AL
	MOV	AL,007H
	OUT	dmasmsk,AL
	MOV	BX,-1		; return -1
	MOV	SP,BP
	POP	BP
	RET
←EncEnd ENDP

PUBLIC  ←Crypt
PUBLIC  ←EncEnd

C←CODE ENDS
	END