/* A crt0 for use with the netbooter.  This code expects to have been
* just loaded by the VMB. */

/* Processor Registers */
.set	KSP,0		/* Kernel Stack Pointer */
.set	ISP,4		/* Interrupt Stack Pointer */
.set	SCBB,0x11	/* System Control Block Base register */
.set	MCESR,0x26	/* Machine Check Error Summary Register */
.set	SID,62		/* System ID register */
.set	MCHECK,0x4	/* Machine Check Vector */
.set	SBIFS,0x30	/* SBI fault and status */
.set	IUR,0x37	/* init unibus (Qbus on 630) register */
.set	EHSR,0x4a	/* Error handling status register */

.set	SIDmask,0x00ffffff /* Only the high byte has the processor type */
.set	SID_EXT,0x20040004 /* SID extention register physical address */
.set	uVAX2,0x08000000 /* SID for the uVAX-II */
.set	QBMAP,0x20088000 /* Start of Q-Bus mapping resigters on uVAX-II */
.set	QBMvalid,0x80000000 /* Valid bit in Q-Bus mapping register */
.set	QBMnum,0x2000	/* Number of Q-Bus mapping registers */
.set	QIOPAGE630,0x20000000
.set	QIPCR,0x1f40
.set	Q_LMEAE,0x20	/* local mem external access enable */
.set	Conmem,0x400	/* High memory to save for use by console program */
.set	bootmem,65536	/* Save memory for boot loader */
.set	ERPB_R5,0x30	/* Offset from r11 for VMB input register R5 */
.set	INTCLRREQ,0x2008000f /*VS2000 interrupt clear register */

	.globl	start
	.globl	__start
	.globl	_main
	.globl	_himem
	.globl	_load_start
	.globl	_init_cons
	.globl	_badaddr

start:
__start:
	.word	0
	nop			/* nop's are saving space */
	nop
	# test for vmb, from locore.s of the ultrix kernel
	tstl	(ap)			# arg present?
	beql	1f			# if not, skip ahead
	movl	4(ap),_vmbinfo		# save vmb pointer
	movl	ERPB_R5(r11),r11	# get boot flags
1:
	/* If is a uVAX-II, set up a straight Q-bus map. */
	mfpr	$SID,r0
	extzv	$24,$8,r0,_cpu
	bicl2	$SIDmask,r0
	movl	r0,_sid
	cmpl	r0,$uVAX2
	bneq	3f
	movl	*$SID_EXT,r0
	movab	_sid_ext,r1
	extzv	$24,$8,r0,(r1)
	clrl	r0
	cvtlb	$Q_LMEAE,QIOPAGE630+QIPCR	/* init qbus map */

3:	movab	tmpstack,r0
	mtpr	r0,$ISP
	mtpr	r0,$KSP
	/* Get off the interrupt stack */
	pushl	$0x41f0000	/* A PSL at IPL 1f */
	pushab	_JOBSA		/* The PC to return to */
	rei

_JOBSA:
	/* Size memory */
	mfpr	$SCBB,r0
	movab	mcheck,MCHECK(r0)	/* Install own mcheck vector */
	clrl	r0
1:	tstl	(r0)			/* touch memory location */
	addl2	$512,r0			/* go through memory by pages */
	brb	1b

.align	2
mcheck:	mtpr	$0,$MCESR		/* Clear machine check error */
	subl2	$Conmem,r0		/* Save memory for console program */
					/*   Only really needed on uVAX-II */
	movl	r0,_himem		/* store address of first non-existant 
					 * page */

	/* round load_start up to next 1K boundary */
	movab	_end,r0
	addl2	$1023,r0
	bicl2	$1023,r0
	movl	r0,_load_start

	/* get off interrupt stack again */
	pushl	$0x41f0000
	pushab	2f
	rei
2:
	movl	r11,_flags
	movab	tmpstack,sp
	mtpr	sp,$ISP
	mtpr	sp,$KSP
	clrl	ap
	clrl	fp
	calls	$0, _init_cons		/* initialize console */
	mfpr	$SCBB,r0		/* catch bus errors */
	movab	_catchmchk,MCHECK(r0)
	pushl	$0
	pushl	$0
	pushl	$0
	calls	$3,_main
	halt

ddtrestart:
	.word	0
	movl	4(ap),r11		/* Pick up boot argument */
	movab	tmpstack,sp
	mtpr	sp,$ISP
	mtpr	sp,$KSP
	clrl	ap
	clrl	fp
	pushl	$0
	pushl	$0
	pushl	$0
	calls	$3,_main
	halt

	.align 2
_badaddr:
	.word	0
	movl	$1,r0
	movl	4(ap),r3
	movl	8(ap),r4
	mfpr	$SCBB,r2
	movl	MCHECK(r2),r5
	movab	9f,MCHECK(r2)
	bbc	$0,r4,1f; tstb	(r3)
1:	bbc	$1,r4,1f; tstw	(r3)
1:	bbc	$2,r4,1f; tstl	(r3)
1:	clrl	r0			# made it w/o machine checks
2:	movl	r5,MCHECK(r2)
	ret
	.align	2
9:
	casel	_cpu,$1,$8
0:
	.word	8f-0b		# 1 is 780
	.word	5f-0b		# 2 is 750
	.word	5f-0b		# 3 is 730
	.word	6f-0b		# 4 is 8600
	.word	5f-0b		# 5 is 8200
	.word	1f-0b		# 6 is 8800
	.word	1f-0b		# 7 is 610
	.word	5f-0b		# 8 is 630
5:
	mtpr	$0x0,$MCESR
	brb	1f
6:
	mtpr	$0,$EHSR
	brb	1f
8:
	mtpr	$0,$SBIFS
1:
	pushl	$0x41f0000
	pushab	2b
	rei

	.align	2
_catchmchk:
	casel	_cpu,$1,$8
0:
	.word	8f-0b		# 1 is 780
	.word	5f-0b		# 2 is 750
	.word	5f-0b		# 3 is 730
	.word	6f-0b		# 4 is 8600
	.word	5f-0b		# 5 is 8200
	.word	1f-0b		# 6 is 8800
	.word	1f-0b		# 7 is 610
	.word	5f-0b		# 8 is 630
5:
	mtpr	$0x0,$MCESR
	brb	1f
6:
	mtpr	$0,$EHSR
	brb	1f
8:
	mtpr	$0,$SBIFS
1:
	pushl	$0x41f0000
	pushab	2f
	rei
	.data
L87:
	.ascii	"Buss error, core not dumped\n\0"
	.text
2:	pushab	L87
	calls	$0,_printf
L88:	brb	L88

/* Shift program from _load_start down to 0. */
	.globl	_launch
_launch:
	.word	0
/* relocate ourselves up into high memory */
1:	movl	4(ap),r9	# entry point
	movl	8(ap),r8	# count
	cmpl	$8,_cpu		# see if we're a microvax
	bneq	1f
	movl	$4,_sid_ext	# see if we're a VS2000
	bneq	2f
	calls	$0,_se_down
	brb	1f
2:	calls	$0,_qna_down
1:	movl	_load_start,r7	# relocation source
	clrl	r6		# relocation destination
	ashl	$-2,r8,r8	# make count longwords, not bytes
	movl	_vmbinfo,r10	# get &vmbinfo or himem
	tstl	r10
	bneq	1f
	movl	_himem,r10
1:
	subl2	$0x100,r10	# r10 contains (highest usable memory - 100)
	movab	1f,r0
	movab	2f,r12
	subl2	r0,r12		# r12 contains length of relocation code
	movc3	r12,1f,(r10)	# move relocation code to high mem
	movl	_flags,r11	# get bootflags
	movl	_vmbinfo,r5	# save vmbinfo pointer
	jmp	(r10)		# do relocation
1:
	movl	(r7)+,(r6)+	# relocate a word
	sobgtr	r8,1b		# again til done
	clrl	ap
	clrl	r10
	movl	r5,(r6)		# set up ap to point at vmbinfo
	movl	r6,ap
	subl2	$4,ap
	jmp	2(r9)		# to application
2:
	.data
/* A stack for the boot program */
	.align	2
	.space	0x1000
kstack:
	.space	0x100
tmpstack:
	.space	4

_himem:	.long	0	/* Address of first nonexistant memory page */
_load_start:
	.long	0	/* Address to (temporarily) load first byte at */
_flags:	.globl _flags
	.long	0
_sid:	.globl _sid
	.long	0
_sid_ext: .globl _sid_ext
	.long 	0
_cpu:	.globl	_cpu
	.long	0
_vmbinfo: .globl _vmbinfo
	.long	0
