; D0Asm.Asm -- Midas/D0 resident interface procedures
;	Last edited: 1 March 1982

.get "masmcommon.d"
.get "d0regmem.d"

; OS
.bext Zero

; MCMD
.bext ErrorAbort

; MDATA
.bext BadAText,MDATAtab,MADDRtab,MCTimeOut

; MASM
.bextz OddParity,MSave2,MCount

; D0TABLES
.bextz NMEMS,MEMLEN

; D0I0
.bext DVx,MIMtab

; Defined here
.bext GFrameX,CertifyAV,ConvertAV
.bext recvbyte,recvword,sendbyte,sendword
.bext ReadPrinter,WritePrinter,d0recvbyte,d0recvword,d0sendbyte,d0sendword
.bext stReadOnly,stPassive,stUndAdr,stNotIMA,stNotInVM,stRunning

.bextz MADDRH,MADDRL,utilout,utilin

.txtm B

.zrel

MADDRL:		0
MADDRH:		0
utilout:	177016
utilin:		177030

.srel

GFrameX:	.GFrameX
CertifyAV:	.CertifyAV
ConvertAV:	.ConvertAV
recvbyte:	.recvbyte
recvword:	.recvword
sendbyte:	.sendbyte
sendword:	.sendword
ReadPrinter:	.ReadPrinter
WritePrinter:	.WritePrinter
d0recvbyte:	.d0recvbyte
d0recvword:	.d0recvword
d0sendbyte:	.d0sendbyte
d0sendword:	.d0sendword
stReadOnly:	.stReadOnly
stPassive:	.stPassive
stUndAdr:	.stUndAdr
stNotIMA:	.stNotIMA
stNotInVM:	.stNotInVM
stRunning:	.stRunning

.nrel

.stReadOnly:	.txt "Read-only"
.stPassive:	.txt "Illegal to write while Passive"
.stUndAdr:	.txt "Undefined address"
.stNotIMA:	.txt "??Not IM address??"
.stNotInVM:	.txt "??Not in VM??"
.stRunning:	.txt "Illegal to write while running"

; Subroutine using new GetFrame instruction--replaces GetFrame procedure
.GFrameX:
	GtFrame
	77400		; CallSwat() if stack overflow

; **Beginning of code for CertifyAV**
; Special kludge to default address eq memory length to a reasonable value.
; Have 1/ Length and 0/ AddrVec!1
CertX:	sub# 1 0 szr
	jmp CertBad	; Error if address # memory length
	jsr CertX1
	 jmp CertBad	; IM
	 jmp CertBad	; IMX
	 jmp CertBad	; RM
	 jmp CnvTask	; T
	 jmp CnvTask	; TPC
	 jmp CertBad	; VM
	 jmp CertBad	; MAP
	 jmp CertBad	; BP
	 jmp CertBad	; MIM
	 jmp CertBad	; MDATA
	 jmp CertBad	; MADDR
CertX1:	lda 0 5 2
	add 0 3
	jmp 0 3

; T 20 and TPC 20 = T(CTASK) and TPC(CTASK).
CnvTask:
	lda 3 @lvDVx
	lda 0 7 3 ; Offset of CTASK
	cycle 4
	lda 1 cav17
	and 1 0
	sta 0 MADDRL	; MADDRL = CTASK
	jmp CertOK

lvDVx:	DVx
cav17:	17

; CertifyAV(AVec,MemX) returns true if AVec is a legal address in MemX,
; else false
.CertifyAV:
	sta 3 1 2
	jsr @GetFrame
	 10
	jsr @StArgs
	lda 1 5 2	; MemX
	lda 3 NMEMS
	subl# 1 3 szc	; skip if legal MemX
	 77400		; else CallSwat
	lda 3 4 2	; AVec
	lda 0 1 3
	sta 0 MADDRL	; MADDRL = AVec!1
	lda 0 0 3
	sta 0 MADDRH	; MADDRH = AVec!0
	lda 3 MEMLEN
	add 1 3
	add 1 3
	lda 1 0 3	; MEMLEN!(MemX+MemX)
	sub# 1 0 szr	; Skip if high parts equal
	 jmp Cert1
	lda 1 1 3	; MEMLEN!(MemX+MemX+1)
	lda 0 MADDRL
Cert1:	adcz# 0 1 snc	; Skip if Usc(Addr,Length) < 0
	 jmp CertX	; Check address eq length kludges
CertOK:	mkminusone 0 0 skp
CertBad:
	mkzero 0 0
	jsr @Return

; Subroutine to check for valid AVec passed to GetMemData and PutMemData
; ConvertAV(AVec,MemX) returns MemX if address is ok, else -1
.ConvertAV:
	sta 3 1 2	; Save return
	jsr @GetFrame
	 10
	jsr @StArgs
	lda 0 4 2	; AVec
	lda 1 5 2	; MemX
	jsr .CertifyAV
	 2
	mov# 0 0 snr
	jmp ConM1
	lda 1 5 2	; MemX
	jsr CAV1
	 ConIM-.
	 ConIMX-.
	 ConRM-.
	 ConT-.
	 ConTPC-.
	 ConVM-.
	 ConMAP-.
	 ConBP-.
	 ConMIM-.
	 ConMDATA-.
	 ConMADDR-.

CAV1:	add 1 3
	lda 1 0 3	; Self-relative pointer
	add 1 3
	lda 0 MADDRL
	mov 0 1
	jmp 0 3		; Dispatch to setup routine

lvMDATAtab:	MDATAtab
lvMADDRtab:	MADDRtab
lvMIMtab:	MIMtab

ConMIM:			; MIMtab+3*address
	lda 3 @lvMIMtab
	jmp .+2
ConMDATA:		; MDATAtab+3*address
	lda 3 @lvMDATAtab
	add 1 1 skp
ConMADDR:		; MADDRtab+2*address
	lda 3 @lvMADDRtab
	add 3 0
	add 1 0
	sta 0 MADDRL
ConIMX:
ConIM:
ConRM:
ConT:
ConTPC:
ConBP:
ConVM:
ConMAP:
ConXit:	lda 0 5 2
	jsr @Return


; Unimplemented
	jsr ConUI1
	.txt "Unimplemented memory"
ConM1:	lda 3 @lvBadAText
ConUI1:	mov 3 0
	jsrii lvErrorAbort
	 1
	77400		; Swat

lvBadAText:	BadAText
lvErrorAbort:	ErrorAbort

.recvword:
	sta 3 1 2
	jsr @GetFrame
	 10
	jsr @StArgs
	jsr .recvbyte
	 0
	sta 0 4 2
	jsr .recvbyte
	 0
	lda 1 rw377
	and 1 0
	lda 3 4 2
	ands 3 1
	add 1 0
	jsr @Return

rw377:	377

.recvbyte:
	inc 3 3
	sta 3 1 2	; Save return
	lda 0 cn1400	; output off, select PO[4:7]
	sta 0 @utilout
	lda 3 cm100
	lda 1 c10000	; look for PO[07]
rclp1:	lda 0 @utilin
	and# 0 1 snr
	 jmp lp1end	; PO[07] is low - D0 is sending
	inc 3 3 szr
	 jmp rclp1
; D0 not sending--not an error since recvbyte is called while the D0
; is running, to see if it stopped.
	lda 0 c252
	jmp @1 2

lp1end:	lda 0 cn3400	; select PD[4:7]
	sta 0 @utilout
	lda 0 @utilin
	lda 3 c170000
	and 3 0
	cycle 4
	lda 1 cn2400	; select PD[0:3]
	sta 1 @utilout
	lda 1 @utilin	; read it
	ands 3 1
	add 1 0
	sta 0 2 2	; save complete byte
	lda 0 cn540	; send write ack with boot bit high
	sta 0 @utilout
	lda 1 cn40540
	sta 1 @utilout
	sta 0 @utilout
	lda 0 cn1540	; look for PO[4:7]
	sta 0 @utilout
	lda 3 cm100
	lda 1 c10000
rclp2:	lda 0 @utilin
	and# 0 1 szr
	 jmp lp2end	; PO[7] is high - D0 has stopped sending
	inc 3 3 szr
	 jmp rclp2
	lda 3 @lvMCTimeOut	; D0 is hung up sending
	isz 0 3		; Count failures in COMM-ER0 word 0
	 jmp @1 2
	jmp @1 2

lp2end: lda 0 cn440	; Drop write ack - D0 should go about its business
	sta 0 @utilout
	lda 1 cn40440
	sta 1 @utilout
	sta 0 @utilout
	lda 0 2 2
	jmp @1 2

.sendword:
	sta 3 2 2
	sta 0 pwd
	movs 0 0
	jsr .sendbyte
	 1
	lda 0 pwd
	lda 3 2 2
.sendbyte:
	sta 3 1 2
	lda 1 cn1440	; look for PO[4:7] - output off
	sta 1 @utilout
	lda 1 c377
	and 1 0		; mask out high bits
	com 0 0
	sta 0 pbyte
	lda 3 cm100
	lda 1 c10000
xlp0:	lda 0 @utilin
	and# 0 1 szr
	 jmp d0rdy
	inc 3 3 szr
	 jmp xlp0
	lda 3 @lvMCTimeOut	; D0 is hung up sending
	isz 1 3		; Count failures in COMM-ER0 2nd word
	 jmp .+1
d0rdy:	lda 0 pbyte	; strobe byte into PD register
	sta 0 @utilout
	movzl 0 1
	movzr 1 1
	sta 1 @utilout
	sta 0 @utilout

	lda 0 cn240	; set mux to look at PD[0:3] and set strobe into PD register
	sta 0 @utilout
	lda 1 cn40240
	sta 1 @utilout
	sta 0 @utilout

	lda 3 cm100
xlp1:	lda 0 @utilin
	movl 0 0 szc
	 jmp endxlp1	; PD[00] was 1 - D0 claims it got the data
	inc 3 3 szr
	 jmp xlp1
	lda 3 @lvMCTimeOut	; D0 never responded
	isz 2 3		; Count failures in COMM-ER1 1st word
	 jmp .+1
endxlp1:
	lda 0 cn40	; drop strobe
	sta 0 @utilout
	lda 0 cn40040
	sta 0 @utilout
	lda 0 cn440	; open bus
	sta 0 @utilout

	lda 3 cm100	; wait for D0 to drop ack
xlp2:	lda 0 @utilin
	movl 0 0 snc
	 jmp xret
	inc 3 3 szr
	 jmp xlp2
	lda 3 @lvMCTimeOut	; D0 never removed ack
	isz 3 3		; Count failures in COMM-ER1 2nd word
	 jmp .+1
xret:	lda 3 1 2
	jmp 1 3


lvMCTimeOut:	MCTimeOut
cn1400:		176377
cm100:		177600
c10000:		10000
c252:		252
cn2400:		175377
c170000:	170000
cn3400:		174377
cn540:		177237
cn40540:	137237
cn1540:		176237
cn440:		177337
cn40440:	137337
pbyte:		0

cn1440:		176337
cn240:		177537
cn40240:	137537
cn40:		177737
cn40040:	137737
pwd:		0
c377:		377

; Bits in rprinter interpreted as follows:
;	0	Debuggee acks debugger writes during normal operation
;	3	Debuggee acks debugger writes during booting
;	4	Debuggee's direction bit: 0 = from debuggee (debuggee's
;		outputs enabled); 1 = to debuggee
;	10:17	data byte
; Bits in wprinter interpreted as follows:
;	0	Write strobe
;	1	Acknowledge debuggee write
;	2	Boot debuggee' (always 1 unless booting)
;	3	Mouse halt request
;	7	Debugger's direction bit: 0 = from debugger; 1 = to debugger

.d0recvword:
	sta 3 1 2
	jsr @GetFrame
	 10
	jsr @StArgs
	jsr .d0recvbyte
	 0
	sta 0 4 2
	jsr .d0recvbyte
	 0
	lda 1 c377
	and 1 0
	lda 3 4 2
	ands 3 1
	add 1 0
	jsr @Return

; Must enter with debugger's direction bit set to 1--since this is only
; changed when writes are done, it will be.
.d0recvbyte:
	inc 3 3
	sta 3 1 2	; Save return
	lda 3 cm100
	lda 1 c4000	; look for PO[07]
d0rb1:	rprinter
	and# 0 1 snr
	 jmp d0rb2	; PO[07] is low - D0 is sending
	inc 3 3 szr
	 jmp d0rb1
; D0 not sending--not an error since d0recvbyte is called while the D0
; is running, to see if it stopped.
	lda 0 c252
	jmp @1 2

d0rb2:	lda 3 c377
	and 3 0
	sta 0 2 2	; save complete byte
	lda 0 c60400
	wprinter	; send write ack with boot bit high
	lda 3 cm100
d0rb3:	rprinter	; ...and wait for debuggee to stop sending
	and# 0 1 szr
	 jmp d0rb4	; #4000 is high--D0 has stopped sending
	inc 3 3 szr
	 jmp d0rb3
	lda 3 @lvMCTimeOut	; D0 is hung up sending
	isz 0 3		; Count failures in COMM-ER0 word 0
	 jmp .+1
d0rb4:	lda 0 c20400	; Drop write ack--D0 should go about its business
	wprinter
	lda 0 2 2
	jmp @1 2

.d0sendword:
	sta 3 2 2
	sta 0 pwd
	movs 0 0
	jsr .d0sendbyte
	 1
	lda 0 pwd
	lda 3 2 2
.d0sendbyte:
	sta 3 1 2
	lda 1 c377
	and 1 0		; Mask out high bits
	lda 1 c20000
	add 1 0		; Byte to be sent + boot' bit
	sta 0 pbyte
	lda 3 cm100
	lda 1 c4000
d0sb0:	rprinter
	and# 0 1 szr	; Skip if debugee is sending
	 jmp d0sb1
	inc 3 3 szr
	 jmp d0sb0
	lda 3 @lvMCTimeOut	; D0 is hung up sending
	isz 1 3		; Count failures in COMM-ER0 2nd word
	 jmp .+1
d0sb1:	lda 0 pbyte	; Strobe byte into PD register
	wprinter	; Byte without strobe
	lda 1 c100000
	add 1 0
	wprinter	; Byte with write strobe
	lda 3 cm100
d0sb2:	rprinter	; Loop until debuggee acknowledges
	movl 0 0 szc
	 jmp d0sb3	; #100000--debuggee claims it got the data
	inc 3 3 szr
	 jmp d0sb2
	lda 3 @lvMCTimeOut	; D0 never responded
	isz 2 3		; Count failures in COMM-ER1 1st word
	 jmp .+1
d0sb3:	lda 0 c20400	; Drop strobe, clear data, open bus
	wprinter

	lda 3 cm100	; Wait for debuggee to drop ack
d0sb4:	rprinter
	movl 0 0 snc	; Wait for debuggee's acknowledge to turn off
	 jmp d0sbx
	inc 3 3 szr
	 jmp d0sb4
	lda 3 @lvMCTimeOut	; Debuggee never removed ack
	isz 3 3		; Count failures in COMM-ER1 2nd word
	 jmp .+1
d0sbx:	lda 3 1 2
	jmp 1 3


c4000:		4000
c60400:		60400
c20400:		20400
c20000:		20000
c100000:	100000

.ReadPrinter:
	rprinter
	jmp 1 3

.WritePrinter:
	wprinter
	jmp 1 3

.end