.title	'Boot Phase 2 for Z80 Stations, vers. 1.1'
.ident	BP2Z80
;-------------------------------------------------------
; H I N E T   S T A T I O N   B O O T  -  P H A S E  2 ;
;	 For all Z80-based DMS products except 816     ;
;						       ;
;	    last changed:  12 Mar 84 dsb	       ;
;						       ;
;------------------------------------------------------;

version ==	1
revision==	1
patch	==	'a'

;
;
; Revision history:
;
;	10/26/83    Works  
; 1.0	01/27/84    No changes to assembled code, 
;		     but gave it a version number &
;		     better assby instructions
; 1.1	03/09/84    Recognizes high bit of honor flag
;		     to mean machine isn't in Machine
;		     Table, and tries to decide whether
;		     console is serial or || by looking
;		     at PROM code.
;		    For this to work, this code must be 
;		     kept workable on all the products
;		     that use the broadcast Boot Phase 1 
;		     e.g. DSC-4's, 1280's, 3/C's etc,
;		     since Boot Phase 1 will claim that
;		     they are all ZSBC-3 type computers
;		     unless there is a Machine Table 
;		     entry that says otherwise.
; 1.1a	03/12/84    Fixed display bug
;

.page
; Read BIOS or alternative program into memory at the
; place it wants to be loaded.	That place had better
; not be on top of this code!  By running this code
; at 1000h we assume it will be out of the way of the
; incoming BIOS. 
;
; To make the object file from the .HEX file:
;
; A>ZDTI
; -F100 5000 0
; -IBP2/Z80.HEX
; -RF100		(F100 + 1000 --> 100, base of TPA)
; note how much to save
; -^C
; A>save (NN) bp2/z80.10	(filetype = version number)
;
; What to tell SYSLIB when putting the object file on:
;
.if2,[
	.prntx 'Load address for this program is 1000'
	.prntx 'Entry point offset is 1'
     ]
;
.page
;	   partns,IOBYTE,nxtin,type-ahead,honor,loadlist
lendef	==    32   +1	   +1	   +31	   +1	  +128

;------------------------------------------------------
; Character constants

Null	==	00	; pad char
cntlC	==	03h	; <control-C>
bell	==	07h	; <bell>
backsp	==	08h	; <backspace>
lf	==	0Ah	; <linefeed>
cr	==	0Dh	; <return>
cntlP	==	10h	; <control-P>
cntlQ	==	11h	; <control-Q>
ctlR	==	12h	; <control-R>
cntlS	==	13h	; <control-S>
ctlT	==	14h	; <control-T>
cntlZ	==	1Ah	; <control-Z>
Esc	==	1bh	; <control-[>
rubout	==	7Fh	; <rubout>

;----------
; 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

; honor flag meanings
AOK	==	0	; the BIOS we wanted
DEFAULT ==	1	; not quite the BIOS we wanted
LGN	==	2	; a Login Please program
OSM	==	3	; an OS Menu
UGH	==	4	; disaster

MACHDEF ==	7	; test bit 7 to find out whether
			; machine table search succeeded

; Default IObytes if we have to guess
SerIObyte ==	0F4h
ParIObyte ==	0F6h

  .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
;----------
; BIOS high-memory contents:

DEFmode ==	0FFF0h	; default mode bits
FLOPmdl ==	0FFF1h	; 0 for Shugart 800, 1 for 850
hertz	==	0FFF2h	; clock hertz rate
baud1	==	0FFF3h	; port 1
			; default 500K baud
baud23	==	0FFF5h	; ports 2,3
			; default 9600 baud

IOBYTE	==	0FFF7h	; 56 or 54h
COLDbas ==	0FFF8h	; cold boot start loc
CPMbase ==	0FFFAh	; CP/M base address
			; then two bytes of version
serial	==	0FFFEh	; PROM serial number
;--------------
; 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+15

  .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
lencom	==	15	; standard net command length

  .page
	.pabs
	.phex
	.loc	1000h
NET2strap:
	.byte	(BP2len$+1023)/1024
	jmp	BP2start
DSKSdef:
	.blkb	lendef	; default disk configuration
IOBdef	==	DSKSdef+32
honor	==	DSKSdef+65
loadlist==	DSKSdef+66

	.loc	honor	; initialize honor flag to
	.byte	UGH	; "disaster" status in case
	.reloc		; an unconfigured BP2 ever
			; gets sent to a station

BP2start:
; 
; First see whether the Master found our machine in
; the machine table.  If not, the high bit of the honor 
; flag will be set meaning we have to try to figure out
; a proper IOBYTE.
 
	lda	honor
	bit	MACHDEF,A
	cnz	FixMach
	res	MACHDEF,A
	sta	honor
 
; See how well our login request succeeded.
; Honor flag = 0 for AOK, 1 for second choice,
;  2 for "login please", 3 for "OS menu",
;  4 for "disaster" (i.e. load list is bad)

	cpi	AOK
	jrz	..on	    ; ok, put no message
	lxi	H,bp2DEF; default
	cpi	DEFAULT
	jrz	..prt
	cpi	LGN
	jrz	..on	    ; login please, no msg
	lxi	H,bp2OSM; OS menu
	cpi	OSM
	jrz	..prt
	lxi	H,bp2UGH; disaster
	cpi	UGH
	jrz	..die
	lxi	H,bp2HUH; wha...
..die:	rst	3		; PROM string outputt
	rst	7		; put back into the monitor
..prt:	rst	3
..on:

; Establish a safe area for interrupt vectors and so forth.
; We don't trust where Boot Phase 1 might have had them.
;
	di
	lxi	D,INTerr
	lxi	H,vectors
	mvi	B,14
..fill: mov	M,E
	inx	H
	mov	M,D
	inx	H
	djnz	..fill
	mvi	A,(vectors>8)&0FFh
	stai
	im2

; Get the BIOS (or other program) from the Net.

	lxi	H,loadlist+1 ; disk, track, sector
	lxi	D,BOOTrd+3   ; net read request
	lxi	B,4	     ; move the address
	ldir
	lhld	loadlist+7   ; load address
	shld	OSbase
..cboot:
	lda	loadlist+5	; low byte of length
	cpi	8		; (allow up to 32k files)
	jrc	..128		; if <1k, do 128-byte read
	lda	BOOTsec 	; examine sector
	ani	7		; if not on a 1k boundary,
	cpi	1
	jrnz	..128		; do a 128-byte read
	mvi	A,read1NET	; but if ok, do a 1k read.
	jmpr	..read
..128:	mvi	A,readNET	
..read: sta	BOOTrd

	lxi	D,$4sec
	call	RECMSG

	lda	RECstat ; check rec status
	bit	timeout,a
	jrz	..cboot ; retry if timeout
 
	ani	crc$ovr
	jrnz	..cboot ; or crc or overrun
 
	lda	NETmsg	; get net cmd
	cpi	poll	; wait for poll
	jrnz	..cboot ; ignore anything but a poll.
 
	lxi	H,BOOTrd
	lxi	B,lencom
	mvi	E,$halfms
	sub	A
	call	SENDNET ; send read request to master
;
; Do the network read

	lhld	loadlist+7	; load address (current)
	lxi	D,$4sec
	lxi	B,1024		; read at most 1k bytes
	lda	BOOTnum
	call	RECNET		; get the chunk.
	bit	timeout,a
	jrz	..bioserr
 
	ani	crc$ovr
	jrnz	..bioserr
	   
	mvi	E,$halfms
	mvi	A,datack
	call	SENDMSG 	; acknowledge reception
;
; Prepare for next sector
	lda	BOOTrd		; remind how much we read
	lxi	B,128
	lxi	D,1
	cpi	read1NET
	jrnz	..updt
	lxi	B,1024
	lxi	D,8
..updt: lhld	loadlist+7	; update load address
	dad	B
	shld	loadlist+7
	ora	A		; clear carry
	lhld	loadlist+5	; length left to read
	dsbc	D		; decrement it down
	shld	loadlist+5
	jrz	..done		; if it becomes 0, we are done.

	lda	BOOTsec
	add	E		; increment sector
	cpi	129		; off end  of track?
	jrc	..nsec
	lhld	BOOTtrk
	inx	H
	shld	BOOTtrk
	ani	127		; get back into range
..nsec: sta	BOOTsec
	jmp	..cboot 	; get next chunk
 
..bioserr:			; here if bad read
	mvi	E,$halfms
	mvi	A,nack		; nack it
	call	sendmsg
	jmp	..cboot 	; and try it again

; Jump to program we've just loaded.
..done: 
	lda	honor	  ; if it's a BIOS, do some
	cpi	DEFAULT+1 ; preliminaries
	jrnc	..go

	lxi	H,BOOTclk ; store current time
	lxi	D,ticks   ; in low core, i.e. muck up
	lxi	B,7	  ; the PROM.  We can do this
	ldir		  ; since we know we've got a
			  ; BIOS ready to go.	
	lixd	03FEh	  ; cold-boot code wants PROM
	liyd	0400h	  ; ser num in index registers	

..go:	lhld	OSbase	  ; preserved load address
	lded	loadlist+11 ; unmolested entry offset
	dad	D	  ; get start address
	pchl		  ; go to it


.page
;--------------------------------
; We are working on an unregistered machine.  Having no
; Machine Table entry, we have no valid IOBYTE.  Attempt
; to discern the console type by looking at the PROM,
; and warn the user to make a machine table entry.
;
; Regs in:  A = honor flag
; Regs out: same 
; Trashed:  all others

FixMach:
	cpi	LGN + (1<MACHDEF)  ; no need on
	rz			   ; "login please"	

	push	PSW	; save honor flag
	rst	4
	lxi	H,FixIO1
	rst	3

	lxi	H,8	 ; PROM conin is rst 1
	lxi	D,ParCon ; Contains this code if ||
	mvi	B,lParCon
..cmp:	ldax	D
	cmp	M
	jrnz	..ser 
	inx	H
	inx	D
	djnz	..cmp

	mvi	A,ParIObyte
	lxi	H,ParMsg
	jmpr	..put
..ser:	mvi	A,SerIObyte
	lxi	H,SerMsg
..put:	sta	IOBdef
	rst	3	  ; say what we decided
	rst	4
	lxi	H,PrtMsg
	rst	3
	rst	4
	rst	4
	lxi	H,FixIO2  ; admonish user to put this
	rst	3	  ; machine in the table

	call	PRTSER	  ; help out by printing the
	rst	4	  ; ser num; restore honor
	pop	PSW	  ; flag, and return.
	ret	

ParCon: in	PIOAD	  ; pattern to match
lParCon ==	.-ParCon  ; length to match
.page
;---------------
; Print the serial number.
; Regs in:  none
; Regs out: none
; Trashed:  all

PRTSER:
	lxi	H,03FEh ; ser num location
	mvi	B,4
..prt:	call	PRTBYT
	inx	H
	djnz	..prt
	ret

;--------------  
; Print a byte.
; Regs in:  HL = .(byte to print)
; Regs out: same
; Trashed:  all the rest

PRTBYT: 	    
	mov	A,M
	rrc
	rrc
	rrc
	rrc
	call	..pnib
	mov	A,M

..pnib: push	H
	ani	0Fh
	adi	'0'
	cpi	'9'+1
	jrc	..go
	adi	'A'-('9'+1)
..go:	rst	2	     ; PROM byte output
	pop	H
	ret
.page
;----------
; Boot commands
BOOTrd:
	.byte	readNET ; read 128 or 1k at a time
	.byte	0	; destination
	.byte	0	; source
	.byte	0	; disk	(0 for sure)
BOOTtrk:.word	08	; track
BOOTsec:.byte	121	; sector
BOOTvol:.byte	0	; volume is always 0
	.byte	0,0,0,0 ; a few more for good measure


  .page
  .sbttl	'SENDNET'

;----------
; 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 to acknowledge polls from the master
;  Regs in:   none
;  Regs out:  none
;ACKpoll:
;	sub	A	; acknowledge polls
;	sta	ACKflag

;---------------------
; starts the poll acking sequence
;begACK:
;	lxi	H,NETmsg; put poll here
;	lxi	B,1	; receive one byte
;	lda	NETusr	; addressed to us

;----------
; 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
	lxi	H,38h
	push	H
	reti
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
  .page
  .sbttl	'sio and dma commands for network activity'
; 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

RECstck ==	0F00h

.page
.sbttl	'Messages'    

bp2DEF: .asciz	[cr][lf][lf][07h]"* DEFAULT BIOS *"[cr][lf]
bp2OSM: .asciz	[cr][lf]"*NO APPROPRIATE BIOS CAN BE FOUND*"
bp2UGH: .asciz	[cr][lf]"*BAD LOAD LIST*"
bp2HUH: .asciz	[cr][lf]"*BAD STATUS*"
FixIO1: .ascii	"This machine has not been entered in"
	.ascii	" the Machine Table."[cr][lf]
	.ascii	"You will therefore receive a default "
	.ascii	"operating system"[cr][lf]"with limited"
	.ascii	" capabilities.  Your default device"
	.ascii	[cr][lf]"assignments will be:"[cr][lf]
	.asciz	[lf]"Console -- "
SerMsg: .asciz	"Serial Port 0 (CON:)"
ParMsg: .asciz	"Parallel Port 1 (BAT:)"
PrtMsg: .asciz	"Printer -- Spooler "
FixIO2: .ascii	"Enter this machine into the Machine"
	.ascii	" Table at your earliest"[cr][lf]
	.ascii	"convenience so that you can choose "
	.ascii	"your BIOS and your"[cr][lf]"peripheral"
	.asciz	" devices.  The serial number is: "

OSbase: .word	0

BP2len$ ==	.-NET2strap
;---------------------------------
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 