/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1986,1987,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 *
 */

/* $Header:srt0.s 12.0$ */
/* $ACIS:srt0.s 12.0$ */
/* $Source: /ibm/acis/usr/sys/standca/RCS/srt0.s,v $ */

	.data
rcsid:	.asciz	"$Header:srt0.s 12.0$"
	.text

#include "asm.h"
#define LOCORE
#include "../machine/cpu.h"
#ifdef MOD135
#include "../machine/ioim.h"
#endif MOD135

/* 
 * defining STACK forces the stack to that location
 * otherwise we try to locate it as required
 */
#ifdef STACK
#define STACKBASE STACK
#else
#define STACKBASE 0x200000
#endif STACK

 #
 # note:
 # 	r2 and r3 should be preserved so that they can be 
 #	passed thru to startup for use by rdb and then passed
 #	thru to the kernel
 #
 
 	.text
	.globl	_edata
	.globl	_start
	.globl	start
start:
	j	0f
eye_profil(start):
0:

#ifdef REL
	bali	r15, 1f
1:					
	ai	r15, r15, start-1b	# adjust for the bali etc.
	get	r5,$start		# get address (purported) of start
	.using  start,r15
#else
	mfs	scr_iar,r15 		# get address of next instruction
0:	.using	0b,r15
#endif REL 

#ifdef ATR


#define ROSEBASE 0x000081		# Where we want to address the MMU
#define IOBAR    0x800000		# I/O Base Address Reginser 
#define RAMSPEC  0x16			# Displacement of RAM Spec Reg
#define ROSSPEC  0x17			# Displacement of ROS Spec Reg
#define WS1	 0x80000
#define WS2	 0x20000
#define WS3	 0x10000
#define MEG	 20
#define MEM4MEG  0xf8
#define POST_START 0x800
#define CPU_FLAG	0xc14	/* location is 0 on ATR and not on RTPC */

 # *** Initialize The MMU 

         get   r0,$ROSEBASE		# MMU starting address div 0x10000
         get   r1,$IOBAR		# I/O Base Address Register
         iow   r0,0x80(r1)		# Initialize BAR

         slpi16 r0,16-16		# Compute actual MMU address
         geth   r4,POST_START(r0)	# RAM value lc
	 cal	r0,_ram_val
	 cas	r4,r0,r4
	 lcs	r0,0(r4)
         iow   r0,0x16(r1)		# Initialize RAM Spec Reg
         s     r0,r0			# No ROS on this card.
         iow   r0,0x17(r1)		# Initialize ROS Spec Reg

 # Set up the CPU and the CPU MODEL For Crossbow

	lis	r0,CPU_ATR
	st	r0,_cpu			# correct the cpu type
	lis	r0,CPU_ROMPC
	st	r0,_cpu_model		# store cpu model information
#endif ATR

#ifdef IBMRTPC
#ifdef ROMPC
	mfs	scr_ics,r0		# get old ics
	setsb	scr_ics,18-16		# set Interrupt On Unaligned Access
	mfs	scr_ics,r4		# get new ics
	c	r0,r4
	jeq	2f			# same - old cpu
	mts	scr_ics,r0		# restore old ics
#ifdef MOD135
/*
 * If bit 20 in register IOIM_MCC of ZIC IOIM1 == 1 then APC else MOD135.
 */
	get	r4,$IOIM1		# get base of IOIM1
	ior	r4,IOIM_MCC(r4)		# get chip configuration register
	nilz	r4,r4,0x800		# if 1 then APC, if 0 then MOD135
	jne	3f			# branch if APC
	lis	r0,CPU_MOD135		# else its a MOD135
	st	r0,_cpu_model		# store cpu model number
 # if old ZIC then apply fix
	get	r6,$IOIM1		# get base of IOIM1
	ior	r4,IOIM_GSR(r6)		# get GSR to clear it
	ior	r4,IOIM_GSR(r6)		# get GSR to see if bit 20 stuck at 1
	nilz	r4,r4,0x800		# is bit 20 set?
	jeq	2f			# no, new ZIC
	ior	r4,IOIM_GCR(r6)		# yes bit 20 set, old ZIC, apply fix
	setbl	r4,6			# turn on bit 22
	iow	r4,IOIM_GCR(r6)		# write to GCR
	j	2f
3:
#endif MOD135
	lis	r0,CPU_ROMPC
	st	r0,_cpu_model		# store cpu model information
2:
#endif ROMPC
#endif IBMRTPC
#ifdef REL
	c	r15,r5			# same ?
	beq	noreloc			# yes, no need to relocate
 # loop to relocate the code to the expected address
	cas	r6,r15,r0		# copy base into temp register
	get	r4, $_edata		# address of last location to copy
	cas	r15,r5,r0		# get final (new) value
 #
 # copy from (r6) to (r5) and keep going until r5 >= r4
 #
loop:	get	r0,0(r6)
	put	r0,0(r5)		# put into proper place
	inc	r5,4
	c	r5,r4
	bnhx	loop			# keep going til done
	inc	r6,4			# get next address
	balr	r15,r15			# transfer to copy
 # all done with the copy 
noreloc:
#endif REL


	mfs	scr_iar,r14 		# get address of next instruction
0:	.using	0b,r14

#ifdef ATR
 #
 # *** Set up addressability to the PCIF
 #
 #   +-> +--------+
 #   |	 +--------+ ROMP -> PC 64K Byte I/O Window
 #   |   +--------+ ROMP -> PC 64K Half Word I/O window
 #   |   |	  |
 #   1MB +--------+ ROMP -> PC 128K Byte  window
 #   |   |	  |
 #   |   +--------+ ROMP -> PC 128K Half Word window
 #   | 	 |	  |
 #   | 	 +--------+ ROMP -> PC 128K Full Word window
 #   | 	 |	  |
 #   +-> +--------+ ROMP -> PC 512K Full Word Window
 #       |	  | end of physical memmory

	 get	r1,_cpu
	 cis	r1,CPU_ATR
	 jne	1f			# not running on ATR

	 get	r1, $POST_START
	 lh	r1,0(r1)

  	 get	r4, $MEG
	 sl	r1, r4

	 st	r1,_pcif_addr
	 put	r1,_pcif_512_fw
	 
	 get	r4,$WS1
	 a	r1,r4  		       	# 512K later the 128K FW window starts
	 put	r1,_pcif_128_fw

	 get	r4,$WS2
	 a 	r1,r4        		# 128K later the 128K HW window lives
	 put	r1,_pcif_128_hw

	 a 	r1,r4			# Another 128K to the 128K byte window
	 put	r1,_pcif_128_b

	 a 	r1,r4			# 128K more to get to the HW i/O window
	 put	r1,_pcif_io_hw

	 get	r4,$WS3
	 a 	r1,r4			# Finally, just 64K more to the byte I/O
	 put	r1,_pcif_io_b		# window

1:

#endif ATR

	get	r1, $STACKBASE		# standalone stack base
/* following check is to insure that stack is left where wanted for bootsrt0 */
#if STACKBASE >= 0x80000
	get	r5, $_end+32768		# get end of program + more
	c	r1,r5
	jh	0f			# ok, enough room
	get	r1,$0x200000		# try 2 meg
	cau	r5,0x10(r15)		# get r15 (start+...) + 1 meg
	geth	r5,0(r5)		# see if 2 1meg cards 
	geth	r4,0(r15)
	c	r4,r5
	jne	0f			# have 2 meg of real memory
	st	r1,_mem_hole		# set flag != 0
	get	r1,$0x300000		# it's the same! put stack at 3meg
0:
#endif

	lps	0,main_go		 # transfer control to startup
startup:
	CCALL(startup,0)
	b	start			# do it again upon return

 #	.align	4
	.align	2
main_go:
	.int 	startup
	.short	0x0180			 # interrupt mask & check stop mask
	.short	0x0
	
	.globl	_mem_hole
	.align	2
_mem_hole:	.long	0		# flag = 1 if memory hole present
#ifdef ATR
	.globl _pcif_addr
	.globl _current_128_w
	.globl _current_512_w
	.globl _pcif_512_fw
	.globl _pcif_128_fw
	.globl _pcif_128_hw
	.globl _pcif_128_b
	.globl _pcif_io_b
	.globl _pcif_io_hw
_pcif_addr:	.long	0x00200000	# Address of PCIF (default at 2M)
_current_128_w:	.long	0		# current value of ROMP->PC windows.
_current_512_w:	.long	0
_pcif_512_fw:	.long	0		# Address of ROMP->PC 512K window
_pcif_128_fw:	.long	0		# Address of ROMP->PC 128K FW Window
_pcif_128_hw:	.long	0		# Address of ROMP->PC 128K HW Window
_pcif_128_b:	.long	0		# Address of ROMP->PC 128K Byte Wind
_pcif_io_b:	.long	0		# Address of ROMP->PC byte I/O window
_pcif_io_hw:	.long	0		# Address of ROMP->PC half word I/O 
_ram_val:	.byte   0
		.byte  11 		# 1 Meg = 2meg 
		.byte  13		# 2 Meg = 4meg
		.byte  14		# 3 Meg = 8meg
		.byte  14		# 4 Meg = 8meg
		.byte  15		# 5 Meg = 16meg
		.byte  15		# 6 Meg = 16meg
		.byte  15		# 7 Meg = 16meg
		.byte  15		# 8 Meg = 16meg
	.globl	_post_config
	.set	_post_config,0x800
	.globl	_cbcb_addr
	.set	_cbcb_addr,0x804
#endif ATR

		.align	2
.globl	_cpu
.globl	_cpu_model
_cpu:	.long	CPU_RTPC		# assume RTPC
_cpu_model: .long	CPU_SGP		# assume old cpu

#ifdef SYMSIZE
 	.align	2
	.globl _symtab
	.globl SYMTAB
_symtab:
	.int	SYMTAB
 	.org	start+SYMSTART		 # to a known spot
	.align	2
SYMTAB:
	.space	SYMSIZE			 # leave room for symbol table

	.text
#endif
