/*	$NetBSD: srt0.S,v 1.17 2011/02/08 20:20:14 rmind Exp $	*/

/*
 * Copyright (c) 1988 University of Utah.
 * Copyright (c) 1982, 1990, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * the Systems Programming Group of the University of Utah Computer
 * Science Department.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * from: Utah $Hdr: srt0.c 1.18 92/12/21$
 *
 *	@(#)srt0.c	8.1 (Berkeley) 6/10/93
 */

/*
 * Startup code for standalone system
 */

/* For machineid and mmuid constants */
#include <machine/hp300spu.h>

/* For _C_LABEL() and friends. */
#include <machine/asm.h>

	STACK =	   0xfffff000		/* below the ROM page */
	BOOTTYPE = 0xfffffdc0
	LOWRAM =   0xfffffdce
	SYSFLAG =  0xfffffed2		/* system flags */
	MSUS =	   0xfffffedc		/* MSUS (?) structure */
	VECTORS =  0xfffffee0		/* beginning of jump vectors */
	NMIRESET = 0xffffff9c		/* reset vector */
	BUSERR =   0xfffffffc
	MAXADDR =  0xfffff000
	NBPG =	   4096
	MMUCMD =   0x005f400c		/* MMU command/status register */

	.data
GLOBAL(bootdev)
	.long	0

GLOBAL(howto)
	.long	0

GLOBAL(lowram)
	.long	0

GLOBAL(machineid)
	.long	0

GLOBAL(mmuid)
	.long	0

	.text
ASENTRY_NOPROFILE(begin)
	movl	#STACK,%sp
	moveq	#47,%d0			/* # of vectors - 1 */
	movl	#VECTORS+2,%a0		/* addr part of first vector */
1:
	movl	#_ASM_LABEL(__trap),%a0@ /* make it direct to __trap */
	addql	#6,%a0			/* move to next vector addr */
	dbf	%d0,1b			/* go til done */
#ifdef ITECONSOLE
	movl	#NMIRESET,%a0		/* NMI keyboard reset addr */
	movl	#nmi,%a0@		/* catch in reset routine */
#else
	/*
	 * Built without ITE console support; leave the ROM's NMI
	 * vector in place, so the system will still reset if a
	 * keyboard NMI is issued.
	 */
#endif

/*
 * Determine our SPU type and look for internal HP-IB
 */
	lea	_C_LABEL(machineid),%a0
	movl	#0x808,%d0
	movc	%d0,%cacr		/* clear and disable on-chip cache(s) */
	movl	#0x200,%d0		/* data freeze bit */
	movc	%d0,%cacr		/*   only exists on 68030 */
	movc	%cacr,%d0		/* read it back */
	tstl	%d0			/* zero? */
	jeq	not68030		/* yes, we have 68020/68040 */

	/*
	 * 68030 models
	 */

	movl	#0x808,%d0
	movc	%d0,%cacr		/* clear data freeze bit again */

	movl	#0x80,MMUCMD		/* set magic cookie */
	movl	MMUCMD,%d0		/* read it back */
	btst	#7,%d0			/* cookie still on? */
	jeq	not370			/* no, 360, 362 or 375 */
	movl	#HP_370,%a0@		/* consider a 370 for now */
	movl	#0,MMUCMD		/* clear magic cookie */
	movl	MMUCMD,%d0		/* read it back */
	btst	#7,%d0			/* still on? */
	jeq	ihpibcheck		/* no, a 370 */
	movl	#HP_340,%a0@		/* yes, must be a 340 */
	jra	ihpibcheck

not370:
	movl	#HP_360,%a0@		/* type is at least a 360 */
	movl	#0,MMUCMD		/* clear magic cookie2 */
	movl	MMUCMD,%d0		/* read it back */
	btst	#16,%d0			/* still on? */
	jeq	isa36x			/* no, a 360 or a 362 */
	lea	_C_LABEL(mmuid),%a0
	lsrl	#MMUID_SHIFT,%d0	/* save MMU ID */
	andl	#MMUID_MASK,%d0
	movl	%d0,%a0@
	lea	_C_LABEL(machineid),%a0
	cmpb	#MMUID_345,%d0		/* are we a 345? */
	jeq	isa345
	cmpb	#MMUID_375,%d0		/* how about a 375? */
	jeq	isa375
	movl	#HP_400,%a0@		/* must be a 400 */
	jra	ihpibcheck
isa36x:
	movl	#0x01000000,%sp@-	/* check DIOII_BASE (scode 132) */
	jbsr	_C_LABEL(badaddr)
	addql	#4,%sp
	tstl	%d0
	jne	ihpibcheck		/* no device, assume 360 */
	movl	#0x01000000,%a0
	movb	%a0@(0x01),%d0		/* check device ID at DIO_IDOFF */
	cmpb	#0x39,%d0		/* framebuffer? */
	jne	ihpibcheck		/* no, assume 360 */
	movb	%a0@(0x15),%d0		/* check sec ID at DIO_SECIDOFF */
	cmpb	#0x11,%d0		/* VRX sti on 362? */
	jne	ihpibcheck		/* no, assume 360 */
	lea	_C_LABEL(machineid),%a0
	movl	#HP_362,%a0@
	jra	ihpibcheck
isa345:
	movl	#HP_345,%a0@
	jra	ihpibcheck
isa375:
	movl	#HP_375,%a0@
	jra	ihpibcheck

	/*
	 * End of 68030 section
	 */

not68030:
	bset	#31,%d0			/* data cache enable bit */
	movc	%d0,%cacr		/*   only exists on 68040 */
	movc	%cacr,%d0		/* read it back */
	tstl	%d0			/* zero? */
	beq	is68020			/* yes, we have 68020 */

	/*
	 * 68040 models
	 */

	moveq	#0,%d0			/* now turn it back off */
	movec	%d0,%cacr		/*   before we access any data */

	.long	0x4e7b0004		/* movc %d0,%itt0 */
	.long	0x4e7b0005		/* movc %d0,%itt1 */
	.long	0x4e7b0006		/* movc %d0,%dtt0 */
	.long	0x4e7b0007		/* movc %d0,%dtt1 */
	.word	0xf4d8			/* cinva bc */

	lea	_C_LABEL(mmuid),%a0
	movl	MMUCMD,%d0		/* get MMU ID */
	lsrl	#MMUID_SHIFT,%d0
	andl	#MMUID_MASK,%d0
	movl	%d0,%a0@		/* save it */
	lea	_C_LABEL(machineid),%a0
	cmpb	#MMUID_425_T,%d0	/* are we a 425t? */
	jeq	isa425
	cmpb	#MMUID_425_S,%d0	/* how about 425s? */
	jeq	isa425
	cmpb	#MMUID_425_E,%d0	/* or maybe a 425e? */
	jeq	isa425
	cmpb	#MMUID_433_T,%d0	/* or a 433t? */
	jeq	isa433
	cmpb	#MMUID_433_S,%d0	/* or a 433s? */
	jeq	isa433
	cmpb	#MMUID_385,%d0		/* or a 385? */
	jeq	isa385
	cmpb	#MMUID_382,%d0		/* or a 382? */
	jeq	isa382
	movl	#HP_380,%a0@		/* guess we are a 380 */
	jra	ihpibcheck
isa425:
	movl	#HP_425,%a0@
	jra	ihpibcheck
isa433:
	movl	#HP_433,%a0@
	jra	ihpibcheck
isa385:
	movl	#HP_385,%a0@
	jra	ihpibcheck
isa382:
	movl	#HP_382,%a0@
	jra	ihpibcheck

	/*
	 * End 68040 section
	 */

	/*
	 * 68020 models
	 */

is68020:
	movl	#HP_330,%a0@		/* consider a 330 for now */
	movl	#1,MMUCMD		/* a 68020, write HP MMU location */
	movl	MMUCMD,%d0		/* read it back */
	btst	#0,%d0			/* zero? */
	jeq	ihpibcheck		/* yes, a 330 */
	movl	#HP_320,%a0@		/* no, consider a 320 for now */
	movl	#0x80,MMUCMD		/* set magic cookie */
	movl	MMUCMD,%d0		/* read it back */
	btst	#7,%d0			/* cookie still on? */
	jeq	ihpibcheck		/* no, just a 320 */
	movl	#HP_350,%a0@		/* yes, a 350 */

	/*
	 * End 68020 section
	 */

ihpibcheck:
	movl	#0,MMUCMD		/* make sure MMU is off */
	btst	#5,SYSFLAG		/* do we have an internal HP-IB? */
	jeq	boottype		/* yes, continue */
	clrl	_C_LABEL(internalhpib)	/* no, clear the internal address */
/*
 * If this is a reboot, extract howto/bootdev stored by kernel
 */
boottype:
	cmpw	#12,BOOTTYPE		/* is this a reboot (REQ_REBOOT)? */
	jne	notreboot		/* no, skip */
	lea	MAXADDR,%a0		/* find last page */
	movl	%a0@+,%d7		/* and extract howto, bootdev */
	movl	%a0@+,%d6		/*   from where doboot() left them */
	jra	boot1
/*
 * At this point we do not know which logical device the MSUS select
 * code refers to so we cannot construct bootdev.  So we just punt
 * and let configure() construct it.
 */
notreboot:
	moveq	#0,%d6			/* make sure bootdev is invalid */
	cmpw	#18,BOOTTYPE		/* does the user want to interact? */
	jeq	askme			/* yes, go to it */
	moveq	#0,%d7			/* default to RB_AUTOBOOT */
	jra	boot1
askme:
	moveq	#3,%d7			/* default to RB_SINGLE|RB_ASKNAME */
boot1:
	movl	%d6,_C_LABEL(bootdev)	/* save bootdev and howto */
	movl	%d7,_C_LABEL(howto)	/*   globally so all can access */
	movl	LOWRAM,%d0		/* read lowram value from bootrom */
	/*
	 * Must preserve the scratch area for the BOOT ROM.
	 * Round up to the next 8k boundary.
	 */
	addl	#((2*NBPG)-1),%d0
	andl	#-(2*NBPG),%d0
	movl	%d0,_C_LABEL(lowram)	/* stash that value */
start:
	movl	#_C_LABEL(edata),%a2	/* start of BSS */
	movl	#_C_LABEL(end),%a3	/* end */
1:
	clrb	%a2@+			/* clear BSS */
	cmpl	%a2,%a3			/* done? */
	bne	1b			/* no, keep going */
	jsr	_C_LABEL(configure)	/* configure critical devices */
	jsr	_C_LABEL(main)		/* lets go */
GLOBAL(_rtt)
	movl	#3,_C_LABEL(howto)	/* restarts get RB_SINGLE|RB_ASKNAME */
	jmp	start

/*
 * probe a location and see if it causes a bus error
 */
ENTRY_NOPROFILE(badaddr)
	movl	BUSERR,_C_LABEL(_bsave)	/* save ROM bus error handler address */
	movl	%sp,_C_LABEL(_ssave)	/* and current stack pointer */
	movl	#catchbad,BUSERR	/* plug in our handler */
	movl	%sp@(4),%a0		/* address to probe */
	movw	%a0@,%d1		/* do it */
	movl	_C_LABEL(_bsave),BUSERR	/* if we got here, it did not fault */
	clrl	%d0			/* return that this was not a bad */
					/*   addr */
	rts

catchbad:
	movl	_C_LABEL(_bsave),BUSERR	/* got a bus error, so restore */
					/*   old handler */
	movl	_C_LABEL(_ssave),%sp	/* manually restore stack */
	moveq	#1,%d0			/* indicate that we got a fault */
	rts				/* return to caller of badaddr() */

	.data
GLOBAL(_bsave)
	.long	0

GLOBAL(_ssave)
	.long	0

ASENTRY_NOPROFILE(__trap)
	moveml	#0xFFFF,%sp@-		/* save registers */
	movl	%sp,%sp@-		/* push pointer to frame */
	jsr	_C_LABEL(trap)		/* call C routine to deal with it */
	tstl	%d0
	jeq	Lstop
	addql	#4,%sp
	moveml	%sp@+,#0x7FFF
	addql	#8,%sp
	rte
Lstop:
	stop	#0x2700			/* stop cold */

#ifdef ITECONSOLE
ASENTRY_NOPROFILE(nmi)
	movw	#18,BOOTTYPE		/* mark as system switch */
	jsr	_C_LABEL(kbdnmi)	/* clear the interrupt, and */
					/*   reset the system */
	stop	#0			/* SCREEEECH! */
#endif

ENTRY_NOPROFILE(call_req_reboot)
	jmp	0x1A4			/* call ROM reboot function */
	rts				/* XXX: just in case? */

ENTRY_NOPROFILE(romout)
	movl	%sp@(4),%d0		/* line number */
	movl	%sp@(8),%a0		/* string */
	jsr	0x150			/* do it */
	rts

/*
 * _transfer(entry, howto, opendev, conscode, lowram, esym)
 *
 *	Transfer control to the kernel.  We also set up registers
 *	as older kernels expect.
 */
ENTRY_NOPROFILE(_transfer)
	movl	%sp@(8),%d7		/* howto */
	movl	%sp@(12),%d6		/* opendev (compat) */
	movl	%sp@(16),%d5		/* conscode (compat) */
	movl	%sp@(20),%a5		/* lowram */
	movl	%sp@(24),%a4		/* esym (compat) */

	movl	%sp@(4),%a0		/* load entry point */
	jbsr	%a0@			/* GO! */
