.title	'"Login Please" Program for Z80 Stations, vers. 1.2'
.ident	LGNZ80

version ==	1
revision==	2
patch	==	' '

; ++++++++++++++++++++++++++++++++++++++++++++++++++++
; +						     +
; +	"Login Please" Program for Z80 Stations      +
; +						     +
; +	  last modified>  12 Mar 84 dsb 	     +
; +						     +
; ++++++++++++++++++++++++++++++++++++++++++++++++++++

; This program is loaded by Boot Phase 2 in lieu of a
;   BIOS if the user's previous login name (presumably
;   the CPU serial number) was not found in the User
;   Name Table.  The "login please" program asks for a
;   name and password and makes another login request.
; This code is based on the old Boot Phase 1 which used
;   to ask for a name but now only does a serial-number 
;   login attempt.
;
;    To save the program in a form SYSLIB can write,
;    do this:
;
;    A>ZDTI
;
;    -F100 1000 0
;    -ILOGINZ80.HEX
;    -R1100		(F000+1100 --> 100, base of TPA)
;    note "NEXT" address to find out how much to save
;    -^C
;    A>save (nn) loginz80.11	(use version as filetype)
;
.if2,[.prntx 'Load address for this program is F000'
     .prntx 'Entry point offset is 0']	; for SYSLIB
;
;
; Revision history:
;
;	     11/03/83	Works
;    1.0     01/27/84	Gave version number, put assby
;			 instructions into source
;			Took out colon after 'Please'
;    1.1     02/02/84	Rejects if name is too short or 
;			 too long, or if password is too
;			 long, without asking master
;			Backspace and delete both work
;			 for names and passwords too.
;    1.2     03/12/84	Send Product Type 1, not 0, so 
;			 we have a chance of logging in
;			 even if not in Machine Table
;
.page

lf	==	0Ah	; <linefeed>
cr	==	0Dh	; <return>
beep	==	07h	; <bell>

	.pabs
	.phex
	.loc	0F000h


cr	==	0Dh	; <return>
lf	==	0Ah	; <linefeed>
bs	==	08h	; <backspace>
del	==	7Fh	; <delete>

;----------
; Transmit and receive bits

RxRDY	==	0	; receiver ready bit
TxRDY	==	2	; transmitter ready bit
CTS	==	5	; Clear To Send
;----------
; Timing constants

$halfms 	==	50h	; 1/2 ms delay SENDNET
$1ms		==	10h	; 1ms delay in RECNET
$16ms		==	100h	; 16ms delay in RECNET
$1sec		==	4000h	; 1sec delay in RECNET
$4sec		==	0	; 4sec delay in RECNET

  .page
;----------
; BIOS low-memory contents:
ticks	==	40h	; 1/60ths \
secs	==	41h	; seconds  \  Time since
mins	==	42h	; minutes   \  cold boot
hrs	==	43h	; hours     /
month	==	44h	; month    /
day	==	45h	; day	  /  Set by SETTIME
year	==	46h	; year	 /
NETusr	==	47h	; network user number
ticsec	==	48h	; ticks per second
LOCKstat==	49h	; HiNet lock status
LOCKadr ==	4Ah	; address of HiNet lock
RTRYflop==	4Ch	; current floppy err retry cnt
errFLOP ==	4DH	; floppy errors since cold boot
Mode	==	4Eh	; system mode bits
errNET	==	4Fh	; network or hard disk
			; errors since cold boot
;--------------
; BOOT PHASE 1 command and response:

BOOTcom ==	7000h
BOOTnam ==	BOOTcom+1
BOOTpsw ==	BOOTnam+8
BOOTprom==	BOOTpsw+6
BOOTpt	==	BOOTprom+4

BOOTmsg ==	BOOTprom 
BOOTassn==	BOOTname 
BOOTdate==	BOOTcom

BOOTresp==	BOOTcom+32
BOOTnum ==	BOOTresp+1
BOOTclk ==	BOOTnum+1
BOOTver ==	BOOTclk+7

; BOOT PHASE 2 location and length
BP2base ==	1000h	; starts here
len2strap==	400h	; comes in 1k chunks

  .page
  .sbttl	'port definitions'
;----------
; Port definitions:
DMA	==	38h	; dma port
enaDMA	==	87h	; enable DMA
rstDMA	==	0C3h	; reset DMA
readDMA ==	01	; read using DMA
writeDMA==	05	; write using DMA

CTC0	==	30h	; CTC channel 0 (port 0)
CTC1	==	31h	; CTC channel 1 (port 1)
CTC2	==	32h	; CTC channel 2 (ports 2,3)
CTC3	==	33h	; CTC channel 3 (clock)

SIO1AC	==	2Ah	; SIO-1 channel A, control
SIO1AD	==	28h	; SIO-1 channel A, data -port 0
SIO1BC	==	2Bh	; SIO-1 channel B, control
SIO1BD	==	29h	; SIO-1 channel B, data -port 1
SIO2AC	==	22h	; SIO-2 channel A, control
SIO2AD	==	20h	; SIO-2 channel A, data -port 2
SIO2BC	==	23h	; SIO-2 channel B, control
SIO2BD	==	21h	; SIO-2 channel B, data -port 3
rstEOM	==	0D0h	; reset SIO underrun flag
rstCHAN ==	18h	; reset SIO channel
rstInt	==	10h	; reset SIO interrupt latch

PIOAC	==	0Ah	; PIO channel A, control
PIOAD	==	08h	; PIO channel A, data
PIOBC	==	0Bh	; PIO channel B, control
PIOBD	==	09h	; PIO channel B, data
HARDP	==	01h	; Hard disk parallel port
CENTP	==	02h	; Centronix parallel port
PPSTROBE==	00h	; Parallel port 2 strobe

FLOPP	==	18h	; Floppy DMA channel
FLOPSR	==	10h	; Floppy status register
FLOPDR	==	11h	; Floppy data register
STOPFLOP==	03h	; Stop floppy controller

SETMAP	==	03h	; Set memory map register
OFFPROM ==	02h	; De-activate DSC/3 PROM
ONMAP	==	00h	; Activate DSC/4 memory map

timeout ==	07h	; Net dead test bit,true low
crc$ovr ==	60h	; crc and ovrun error mask
pollRCV ==	00	; REClast found a poll

 .page
	.pabs
	.phex
	.loc	0F000h
		      
LGNPLS:
	di
	lxi	SP,1000h; setup a stack
	mvi	A,(vectors>8)&0FFh
	stai		; setup interrupt register
	im2
;
; Ask for an instant logout of our old user number

	lxi	H,Nbootusr
	shld	USRadr
	lda	BOOTnum
	mov	M,A
	sta	LOUTcom+1

..p1:	lxi	D,$4sec
	call	RECMSG
	bit	timeout,a	; ensure valid poll
	jrz	..p1  
	ani	crc$ovr
	jrnz	..p1  
	lda	NETmsg
	cpi	poll
	jrnz	..p1  
 
	lxi	H,LOUTcom	; got poll so send
	lxi	B,2		; logout request
	mvi	E,$halfms	; as we have set up
	sub	A
	call	SENDNET
;
; Get response to logout request
..loutresp:
	lxi	H,LOUTresp	; get login response
	lxi	B,1
	lxi	D,$4sec
	lda	LOUTcom+1
	call	RECNET
	bit	timeout,a	; and ensure its valid
	jrz	..p1
	ani	crc$ovr
	jrnz	..p1
	lda	LOUTresp	; see if we got acked
	cpi	LOUTack
;	jrnz	..p1

; Now forget our old user number, use 253

	mvi	A,LOGusr
	sta	Nbootusr 

; Set up the login request, and make it
	call	asknm	; get name and psw
	lxi	H,03FEh ; set up serial num
	lxi	D,BOOTprom
	lxi	B,4
	ldir
			; wait for poll then log in
	call	..poll	; won't return if successful
			; If unsuccessful, something is
			; VERY wrong!
	lxi	H,DeathKnell
	rst	3	; PROM string output routine
	rst	7	; give up and go to PROM monitor

;
;-------
..poll: 	; Wait for user 253 poll then req login
	lxi	D,$4sec
	call	RECMSG
	bit	timeout,a	; ensure valid poll
	jrz	..poll
;
	ani	crc$ovr
	jrnz	..poll
;
	lda	NETmsg
	cpi	poll
	jrnz	..poll
;
	lxi	H,BOOTcom	; got poll so send
	lxi	B,1+8+6+4+1	; login request
	mvi	E,$halfms	; as we have set up
	sub	A
	call	SENDNET
;
; Get response to login request
..logresp:
	lxi	H,BOOTresp	; get login response
	lxi	B,1+1+7+4	; resp, num, time, ser #
	lxi	D,$4sec
	mvi	A,LOGusr
	call	RECNET
	bit	timeout,a	; and ensure its valid
	jrz	..poll
;
	ani	crc$ovr
	jrnz	..poll
;
	lxi	H,BOOTprom	; make sure the serial#
	lxi	D,BOOTver	; master sent is yours
	mvi	B,4
..cmp:	ldax	D
	cmp	M		; if not then this
	jrnz	..retry 	; is not for you
	djnz	..cmp
;
	lda	BOOTresp
	cpi	LOGack		; its yours,
	jrz	..login 	; is it an ack
;
	cpi	logDENY 	; or maybe a nack
	rz

..retry:
	call	..delay 	; delay and retry
	jmpr	..poll		; if neither
;
;-------
; Delay random period of time, then retry
..delay:
	ldar		; use refresh register
	ani	7	; (its a good random seed)
	inr	A	; Make it non-zero
	mov	B,A
..outer:
	lxi	H,0	; delay about 400ms per pass
..inner:
	dcx	H
	mov	A,H
	ora	L
	jrnz	..inner
;
	djnz	..outer ; low 3 bits of R = pass count
	ret
;
;-------
..login:
	lxi	H,BP2base ; get rest of boot code
	push	H
	call	..rBP2
	pop	H
	mov	B,M	  ; how many chunks coming?
	djnz	..get	  ; (we have one already)
	jmpr	..got
..get:	push	B	; loop counter
	lxi	B,len2strap
	dad	H
	push	H
	call	..rBP2	; get the next 1k chunk
	pop	H
	pop	B
	djnz	..get
..got:	jmp	BP2base+1 ; go to it

..rBP2:
	lxi	B,len2strap ; (Boot Phase 2 coming)
	lxi	D,$4sec
	lda	BOOTnum
	call	RECNET
	bit	timeout,A  ; if it doesn't arrive,
	rnz		   ; restart boot process. It is
	jmp	LGNPLS	   ; VERY IMPORTANT that this
			   ; jump to the  beginning as
			   ; the stack is out of line
			   ; and must be started over.
;-------------------
Nbootusr: .byte LOGusr
DeathKnell:
	.asciz	[cr][lf]"* Error: log-nack in Login Please program"
;
;------------------------------
INITname:		;Initialize user name and psw
	lxi	H,BOOTnam
	mvi	M,' '	; fill name and psw with blanks
	lxi	D,BOOTnam+1
	lxi	B,13
	ldir
	inx	H	; point to ser num to clear out
	inx	H
	inx	D	; 4 bytes of sernum & one of
	inx	D
	mvi	M,1	; product type
	lxi	B,4	; 5-1=4
	ldir
	ret
;--------------------------------
; Ask user for name and password
; Don't return until name >0 and <=9 chars
;  and password <=6 chars.
; Regs in:  none
; Regs out: none

asknm:
	ori	0FFh
	sta	..ok	  ; "length ok" flag

	call	INITname 
	lxi	H,NAMEmsg
	rst	3	  ; PROM string out 

	lxi	H,BOOTnam 
	mvi	E,1	  ; echo ok
	call	INMSG	  ; get name
	mov	A,B	  ; length
	ora	A	  ; 0 is too few
	jrz	..bad1
	cpi	9	  ; 9 is too many
	jrnc	..bad1
	jmpr	..psw
..bad1: xra	A
	sta	..ok	  ; length NOT ok!

..psw:	lxi	H,PSWmsg
	rst	3

	lxi	H,BOOTpsw
	mvi	E,0	  ; don't echo
	call	INMSG	  ; get pswrd
	mov	A,B	  ; see how long
	cpi	7	  ; 7 is too many
	jrc	..ret2
	xra	A
	sta	..ok
..ret2: rst	4	  ; crlf
	lda	..ok	  ; see about length
	ora	A	  ; if no good, reject now
	jrz	asknm	  ; and don't bother master
	ret		  ; if good, return

..ok:	.byte	0FFh
NAMEmsg:
	.ascii	[cr][lf]'Login Please '
	.asciz	[cr][lf]'Name: '
PSWmsg: .asciz	[cr][lf]'Password: '

;------------------------------
; In put a string from the console
; Regs in:  HL = pointer to string
;	     E = 0 for no echo of input
;	       = 1 to echo it
; Regs out: B = number of chars input
; Trashed:  all

INMSG:
	mvi	B,0	; character counter
..get:	mov	A,B	; anyone who types in more than
	cpi	60	; 60 chars doesn't know what
	rnc		; they're doing or is trying to
			; cause trouble.
	rst	1	; get a character
	cpi	cr	; end on <cr>
	rz
	cpi	bs	; backspace works!
	jrz	..bs 
	cpi	del	; delete
	jrz	..bs
	cpi	'a'	; cvt to upper case
	jrc	..store
	cpi	'z'+1
	jrnc	..store
	sui	'a'-'A'
..store:
	mov	M,A
	inx	H	; incr pointer
	inr	B	; incr count
	bit	0,E	; check echo flag
	jrnz	..get	; if ok to echo, get next
	jmpr	..erase ; if not ok to echo, erase

..bs:			; deal with a backspace
	mov	C,A	; save char
	mov	A,B	; see if any gotten yet
	ora	A
	jrz	..get	; if not, nothing to do
	dcx	H	; if yes, decrement pointer and
	mvi	M,' '	; blank the last character.
	dcr	B	; show we have one less now.
	bit	0,E	; don't deal with the screen if
	jrz	..get	; we aren't echoing anyway
	mov	A,C	; get input char back to tell
	cpi	del	; bs from delete.
	jrz	..erase ; if delete, do bs-sp-bs
	push	H
	lxi	H,back2 ; if bs, sp-bs will suffice
	jmpr	..era2	; as PROM echoes first bs
..erase:
	push	H      
	lxi	H,backmsg 
..era2: rst	3
	pop	H
	jmpr	..get

backmsg:
	.byte	bs     
back2:	.byte	' ',bs,0

.page
.sbttl	' Net I/O routines '
;-----------------------
;	---	REClast stack
; put here so running master will be happy
; and booting station will also be happy
; and running station will be happy

	.byte	76h,76h,76h,76h,76h,76h,76h,76h
	.byte	76h,76h,76h,76h,76h,76h,76h,76h
	.byte	76h,76h,76h,76h,76h,76h,76h,76h
	.byte	76h,76h,76h,76h,76h,76h,76h,76h
RECstck:

; ++++++++++++++++++++++++++++++++++++++++++++++++++++
; +						     +
; +	      Network I/O Routines		     +
; +						     +
; +   Currently (30 Oct 83) the same code as in      +
; +   BP2/Z80.ASM, where it works.  Since some	     +
; +   of this is very timing-sensitive, change	     +
; +   at your own risk and document the changes.     +
; +						     +
; ++++++++++++++++++++++++++++++++++++++++++++++++++++

; Send a message to the master
;  Regs in:   A = message to be sent
;  Regs out:  none
;  Destroyed: A, BC, DE, HL
SENDMSG:
	lxi	H,NETmsg
	mov	M,A
	lxi	B,1
	sub	A	; master number = 0
			; fall thru to SENDnet
;
;----------
; Transmit a block on the network
;  Regs in:   HL = block address
;	      BC = byte count
;	      E  = delay time (master only)
;	      A  = user number
;  Regs out:  none
;  Destroyed: A, BC, DE, HL
; SendNet is extremely time-critical, particularly
; for DSC-4's, so modify it at your own risk.
SENDNET: 

	mvi	E,$halfms; delay approx 1/2 mSecs

	inr	E	; delay so that receiver has
..spin: dcr	E	; time to prepare for message
	jrnz	..spin	

	mov	D,A	; save user number
	shld	DMANSadr; store block address
	dcx	B	; DMA chip wants real size - 1
	sbcd	DMANSsize
	mov	A,C
	ora	B
	di		; no ints while reprogramming
	jrz	..notDMA

; send a data block using DMA
..useDMA:
	lxi	H,DMATdone; setup the DMA vector
	shld	DMAvect
	mvi	A,1	; multiplex SIO1B to DMA
	out	PIOAD

	lxi	H,DMANSprog; program the DMA chip
	lxi	B,DMAN$<8+DMA
	outir

	lxi	H,SENDprog
	lxi	B,SEND$<8+SIO1BC
	outir

	mvi	b,9
	djnz	.	; force 3 leading flags

	lxi	h,sDMAflag
	mvi	M,0	; reset dma done flag
	mov	A,D
	di
	out	sio1bd	; send user number
	mvi	A,enaDMA
	out	DMA	; enable dma chip
	mvi	A,rstEOM
	out	sio1bc	; reset underrun flag (SIO)
	ei
..testDONE:
	mov	A,M	; DMATdone sets sDMAflag
	ora	A
	jrz	..testDONE
	jmpr	..fin

; send one data byte so no need to use DMA
..notDMA:
	lxi	H,SENDprog
	lxi	B,SEND$<8+SIO1BC
	outir

	mvi	B,9
	djnz	.	; force 3 leading flags

	lbcd	DMANSadr
	ldax	b
	mov	e,a	; get message byte
	mvi	c,sio1bd
	di
	outp	D	; send userno
	mvi	a,rstEOM
	out	sio1bc	; reset under run flag
..wait:
	in	sio1bc
	bit	TxRdy,a
	jrz	..wait
;
	outp	E	; send message byte

; Handle the end of the transmission
..fin:	
	mvi	B,20h	; force CRC bytes
	djnz	.	; and min 3 closing flags

	mvi	A,rstCHANNEL
	out	SIO1BC	; reset the SIO chip
	ei
	ret
  .page
  .sbttl 'RECNET'
;----------
; Receive a message from the master
;  Regs in:   none
;  Regs out:  A = xmission err status
;  NETmsg = receive message char
;  Destroyed: BC, DE, HL
RECMSG:
	lhld	USRadr
	mov	A,M	; get user number
	lxi	H,NETmsg
	lxi	B,1	; fall thru to RECnet

;----------
; Receive a block from the network
;  Regs in:   HL = block address
;	      BC = maximum byte count
;	      DE = timeout count (master only)
;	      A  = user number
;  Regs out:  A  = error status
;		   bit 7 reset	= time-out
;		   bit 6 set	= CRC error
;		   bit 5 set	= receiver overrun
;		   bit 0 set	= poll only rcv'd
;  Destroyed: A, BC, DE, HL
RECNET:
	call	RECbegin  ; program the SIO chip

;----------
; Wait for next poll from network and don't ack
; ENTRY>	none
; EXIT> 	see RECnet  
;  Destroyed: BC, HL
NACKpoll:
	ei		  ; make sure SIO can interrupt
	lxi	H,RECstat ; point to receiver status
	mvi	M,60h	  ; init RECstat to errors

;
; Wait for block received from network cable
..wait: mvi	B,8	; inner loop count
..loop: mov	A,M	; check receiver status
	bit	4,A
	rnz		; return if block received
	djnz	..loop
;
	dcx	D	; decrement timeout count
	mov	A,E
	ora	D
	jrnz	..wait	; fall through if timeout
;
	di		; prevent real SIO int
	call	REClast ; pretend we received a block
	res	pollRCV,M ; no valid poll rcv'd
	mov	A,M	; return error status
	ret

;----------
; Program the SIO chip to receive a block
RECbegin:
	sta	RECadr	; station address
	shld	DMANRadr; DMA address
	dcx	B 
	sbcd	DMANRsize; DMA rcv len = real len-1
	mov	A,C
	ora	B
	di		; no ints while prog vects!
	jrz	..prog
;
; Receive more than one byte
	lxi	H,REClast; setup the DMA vector
	shld	DMAvect
	mvi	A,1	; multiplex SIO1B to DMA
	out	PIOAD
	lxi	H,DMANRprog; program the DMA chip
	lxi	B,DMAN$<8+DMA
	outir
..prog:
	lxi	H,RECfirst; setup interrupt vectors
	shld	SIO1vect+4
	lxi	H,REClast
	shld	SIO1vect+6
	lxi	H,RECprog; program the SIO chip
	lxi	B,REC$<8+SIO1BC
	outir
	ei		; make sure interrupts enabled
	ret
  .page

USRadr:
	.word	BOOTnum

sDMAflag:
	.byte	0	; 0 = DMA not done

rcvDMAlen:
	.word	0	; actual rcv'd block length

RECstat:
	.byte	60h	; rcv status - init to timeout,
			; crc & ovr err - no poll rcv'd
  .page
  .sbttl	'SDLC interupts'
;----------
; SDLC receive interrupt on first char
RECfirst:
	push	PSW
	push	H
	in	SIO1BD	; flush user number
	lhld	DMANRsize; if len = 0, don't use DMA
	mov	A,L
	ora	H
	jrz	..noDMA
;
; use the dma chip to receive a block of data
	mvi	A,enaDMA; enable DMA
	out	DMA
	jmpr	..ret

..noDMA:
	in	sio1bd	; get message byte
	lhld	DMANRadr; get buffer address
	mov	M,A	; put message into buffer
	dad	H	; done for timing
	in	SIO1BD	; flush first crc byte

..ret:	
	pop	H
	pop	PSW
	ei
	reti
;
;----------
; SDLC receive interrupt on last char
REClast:
	push	D
	push	PSW
	push	H
	push	B

	lxi	H,1<8+rstCHAN
	in	sio1bd	; flush 1st crc byte if dma
			; 2nd if not dma
	mvi	C,sio1bc; hinet control port
	outp	H	; get ready to read reg 1
	inp	A	; read receive status
	outp	L	; reset sio1b channel
	ani	0e0h	; mask relevant bits
	set	4,A	; no timeout
	sta	RECstat
;
	lhld	DMANRsize; if len = 0, don't use DMA
	mov	A,L
	ora	H
	jrz	..pastDMA
;
	lxi	H,ckDMAlen	; program the DMA chip
	lxi	B,DMAlen$<8+DMA ; to send actual rcv'd
	outir			; data length

	lxi	H,rcvDMAlen	; store actual rcv'd
	lxi	B,2<8+DMA	; data length at
	inir			; rcvDMAlen

	mvi	A,rstDMA	; reset the DMA chip
	out	DMA

..pastDMA:

	pop	B
	pop	H
	pop	PSW
	pop	D
	ei		; ints ok now
	reti
;
;----------
; DMA transmit complete interrupt
DMATdone:
	push	PSW
	mvi	A,rstDMA; reset the DMA chip
	out	DMA	; and IEO line
	sta	sDMAflag
	pop	PSW
	ret
;----------
; Death
INTerr:
	lxi	H,intmsg
	rst	3		; put string out
	lxi	H,38h		; try to get back to
	push	H		; the PROM monitor
	reti			; (it's all we've got)
intmsg: .asciz	[cr][lf]"INT ERR"

  .page
  .sbttl	'psuedo numbers, network messages, commands'
;---------------
; ***	Pseudo-user numbers	***
BOOTusr ==	254	; boot pseudo user number
LOGusr	==	253	; login pseudo user number
MIMICusr==	252	; mimic pseudo user number
PPusr	==	251	; poll-prime pseudo user number

;----------
; Network messages and commands
poll	==	'P'	; poll from master
POLLpr	==	'U'	; poll-prime from user
pollack ==	'A'	; poll-received ack
PPack	==	'V'	; poll-prime-received ack
PPnack	==	'W'	; poll-prime received nack
datack	==	'D'	; data received ack
mesack	==	'M'	; message received ack
nack	==	'N'	; negative acknowledge
logack	==	'L'	; login acknowledge
lognack ==	'N'	; login conflict
logdeny ==	'D'	; login denied
lockack ==	0	; lock acknowledge
lockdeny==	1	; lock denied
locknack==	2	; lock error
hogack	==	'H'	; hog acknowledge
hogdeny ==	'D'	; hog denied
HSTack	==	'S'	; HD status rcve ack
DTMack	==	'T'	; date/time rcve ack
whoNET	==	10h	; who command
readNET ==	11h	; read command
writeNET==	12h	; write command
loginNET==	13h	; login command
startNET==	14h	; start spool command
AckSpStart ==	04h	; Ack spool start req
read1NET==	15h	; read 1K command
stopNET ==	16h	; stop spool command
assnNET ==	17h	; assign command
hogNET	==	18h	; hog command
lockNET ==	19h	; lock command
unlockNE==	1Ah	; unlock command
clrlockN==	1Bh	; clearlocks command
spoolNET==	1Ch	; spool command
hdstNET ==	1DH	; hard disk volume status cmd
dttmNET ==	1Eh	; date/time status
loutNET ==	1Fh	; instant logout command
LOUTack ==	'A'	; and ack thereof
  .page
  .sbttl	'sio and dma commands for network activity'

; Net logout command
LOUTcom:
	.byte	loutNET
	.byte	0	; put our user number here
LOUTresp:.byte	0

; SIO commands
SENDprog:
	.byte	    00011000b ; channel reset
	.byte	14h,00100000b ; SDLC mode
	.byte	  3,00100000b ; auto enables
	.byte	11h,11000100b ; no interrupts
	.byte	  5,11101011b ; transmitter enable
	.byte	    10000000b ; reset CRC generator
SEND$	==	.-SENDprog

RECprog:
	.byte	    00011000b ; channel reset
	.byte	  4,00100000b ; SDLC mode
	.byte	  2,SIO1vect&0FFh ; interrupt vector
	.byte	    01000000b ; reset crc check
	.byte	15h,10000000b ; transmit disable
	.byte	  3,11111100b ; receiver info
	.byte	6
RECadr: .byte	0	      ; user number
	.byte	  7,01111110b ; flag byte
	.byte	11h,11101100b ; interrupt on first byte
	.byte	23h
RECable:.byte	    11111101b ; enable receiver
REC$	==	.-RECprog

;----------
; DMA commands
DMANSprog:
	.byte	0C3h	; master reset		     2D
	.byte	0C7h	; reset port A		     2D
	.byte	0CBh	; reset port B		     2D
	.byte	79h	; write
DMANSadr:.word	0	; filled by SENDNET or RECstart
DMANSsiz:.word	0	; filled by SENDNET or RECstart
	.byte	14h	; port A inc, memory	     1B
	.byte	28h	; port B fixed, I/O	     1B
	.byte	95h	; byte mode		     2B
	.byte	SIO1BD	; port B
	.byte	12h	; interrupt at end of block
	.byte	DMAvect&0FFh ; interrupt vector
	.byte	92h	; stop at end of block
	.byte	0CFh	; load starting address      2C
	.byte	writeDMA; write
	.byte	0CFh	; load starting address      1A
	.byte	0ABh	; enable interrupts	     2D
DMAN$	==	.-DMANSprog

DMANRprog:
	.byte	0C3h	; master reset		     2D
	.byte	0C7h	; reset port A		     2D
	.byte	0CBh	; reset port B		     2D
	.byte	7Dh	; read
DMANRadr:.word	0	; filled by SENDNET or RECstart
DMANRsiz:.word	0	; filled by SENDNET or RECstart
	.byte	14h	; port A inc, memory	     1B
	.byte	28h	; port B fixed, I/O	     1B
	.byte	95h	; byte mode		     2B
	.byte	SIO1BD	; port B
	.byte	12h	; interrupt at end of block
	.byte	DMAvect&0FFh ; interrupt vector
	.byte	92h	; stop at end of block
	.byte	0CFh	; load starting address      2C
	.byte	readDMA ; read
	.byte	0CFh	; load starting address      1A
	.byte	0ABh	; enable interrupts	     2D

ckDMAlen:
	.byte	0BBh	; set read status mask	     2D
	.byte	06h	; read the byte counter      2D
	.byte	0A7h	; initiate read sequence     2D
DMAlen$ ==	.-ckDMAlen

;---------------------------------
vectors ==	(.+0FFh) & 0FF00h
SIO1vect==	vectors
CTCvect ==	SIO1vect+16 ; SIO has 8 vectors
DMAvect ==	CTCvect+8   ; CTC has 4 vectors
PIOvect ==	DMAvect+2   ; DMA has one vector
NETmsg	==	PIOvect+2   ; PIO has one vector
			    ; NETmsg may be many
			    ; bytes long.
	.end

 ; DMA has one vector
NETmsg	==	PIOvect+2   ; PIO has one vector
			    ; NETmsg