/*
** head.S -- This file contains the initial boot code for the the
**	     ATARI Linux kernel.
**
** Copyright 1994 by Bj”rn Brauel
**
** This file is subject to the terms and conditions of the GNU General Public
** License.  See the file README.legal in the main directory of this archive
** for more details.
**
*/

#include "assyms.h"

/*
 * Linux startup code.
 *
 * At this point, the boot loader has:
 * Disabled interrupts
 * Disabled caches
 * Put us in supervisor state.
 *
 * The kernel setup code takes the following steps:
 *   Raise interrupt level
 *   Set up initial kernel memory mapping.
 *	This sets up a mapping of the 4M of memory the kernel
 *	is located in.	It also does a mapping of any initial
 *	machine specific areas.
 *   Enable cache memories
 *   Jump to kernel startup
 *
 * Register d6 contains the CPU flags from the boot_info information
 * for most of this file.
 */

.text
.globl _start, _krt, _kpt, _availmem

	.even
_start:
/*
 * raise interrupt level with MASTER bit set, copy isp to msp
 */
	movew	#0x3700,sr
	movec	isp,d0
	movel	d0,sp
 
/*
 * Initialize serial port
 */
	bsr Lserial_init

	moveq	#13,d7
	bsr	Lserial_putc
	moveq	#10,d7
	bsr	Lserial_putc
	moveq	#65,d7
	bsr	Lserial_putc

/*
 * Record the CPU type.
 */
	movel	#_boot_info,a0     /* pcrel */
	subl	#LKSTART_ADDR,a0
	addl	#LVSTART_STRAM,a0
	movel	a0@(LBI_CPU),d6

/*
 * Get address at end of kernel code/data/bss and
 * mask off at a page boundary.
 */
	movel	#_end,a0  /* pcrel */
	subl	#LKSTART_ADDR,a0
	addl	#LVSTART_STRAM,a0
	movel	a0,d0
	addl	#0x00000fff,d0
	andl	#0xfffff000,d0
	movel	d0,a6

	moveq	#66,d7
	bsr	Lserial_putc

/*
 * allocate the kernel root table and initialize it.
 */
	movel	a6,a5
	addw	#LPAGE_SIZE,a6

	/* clear the root table */
	movel	a5,a0
	moveq	#0,d0
	moveq	#127,d1
lopei:	movel	d0,a0@+
	dbra	d1,lopei

	/*
	 * Initialize root table descriptor pointing to the kernel pointer
	 * table.  The pointer table is situated in memory right after
	 * the root table.
	 */
	
	/*
	 * Coming up specific Code for ATARI 
	 */
	 
	lea	a5@,a0
	movel	#0x0000001,d0
	movel	#0x2000000,d1
	movel        #127,d2
f_rpt:	movel        d0,a0@+
	addl	d1,d0
	dbra 	d2,f_rpt
	
	lea	a5@(1024),a0
	addl	#2,a0
	movel	a0,a5@(508) 


	moveq	#67,d7
	bsr	Lserial_putc

/*
 * Initialize the pointer tables referred to above.  They either point
 * to page tables in the case of the 68040 or contain early
 * termination page descriptors in the case of the 68851 or 68030.
 *
 * Each pointer table entry points to a 64 entry page table.  16 of these
 * page tables are grouped to form a single 1024 entry page table which
 * fits in a single 4096 byte page.
 *
 * Some register usages:
 *    a0 -> pointer table descriptor address
 *    a1 -> pointer table descriptor
 *    d1 -> counter
 *    d2 -> pointer table descriptor increment (varies according to CPU)
 */

	/* clear the kernel pointer table */
	lea	a5@(512),a0
	moveq	#0,d0
	moveq	#127,d1
lopzw:	movel	d0,a0@+
	dbra	d1,lopzw

	lea	a5@(512),a0
	moveq	#127,d1

	/*
	 * base value of pointer table descriptor is either
	 * the address of the first page table (68040)
	 * or the base address of physical memory (68030).
	 */

	/* 680[23]0 */
	movel	#0,a1  /* base address */
	addql	#1,a1		/* descriptor type */
	movel	#0x40000,d2	/* increment */

lopb:	movel	a1,a0@+
	addl	d2,a1
	dbra	d1,lopb
	addl	#0x40,a5@(0x2f0)
	addl	#0x40,a5@(0x2f4)
	addl	#0x40,a5@(0x2f8)
	addl	#0x40,a5@(0x2fc)

	lea 	a5@(1024),a0
	movel	#0xfe000041,d0
	movel	#0x40000,d1
	movel        #63,d2
f_kpt:	movel        d0,a0@+
	addl	d1,d0
	dbra 	d2,f_kpt
	movel	#63,d2
	movel	#0x01,d0
f_kpt2:	movel	d0,a0@+
	addl	d1,d0
	dbra 	d2,f_kpt2
	
	lea	a5@(1536),a0
	movel	#0x01,d0
	movel	#127,d2
	movel	#0x40000,d1
f_vkpt:	movel	d0,a0@+
	addl	d1,d0
	dbra	d2,f_vkpt

	addl	#0x40,a5@(1532)
	addl	#0x40,a5@(1520)
	lea	a5@(1536),a0
	addl	#2,a0
	movel	a0,a5@(0x180)
	
	moveq	#74,d7
	bsr	Lserial_putc
/*
 * Setup Supervisor Root Pointer register to point to page directory,
 * setup translation register contents and enable translation.
 */

	moveq	#75,d7
	bsr	Lserial_putc

	movel	#Lmmu,a0  /* pcrel */
	subl	#LKSTART_ADDR,a0
	addl	#LVSTART_STRAM,a0
	movel	#0x80000002,a0@   /* no limit, 4byte descriptors */
	movel	a5,a0@(4)
	pmove	a0@,srp

	/*
	 * enable,super root enable,4096 byte pages,7 bit root index,
	 * 7 bit pointer index, 6 bit page table index.
	 */
	movel	#0x82c07760,a0@
	pmove	a0@,tc


/*
 * Fixup the addresses for the kernel pointer table and availmem.
 * Convert them from physical addresses to virtual addresses.
 */
	moveq	#77,d7
	bsr	Lserial_putc

                             
	lea	a5@(1536),a0
	subl	#LVSTART_STRAM,a0
	addl	#LKSTART_ADDR,a0
	movel	a0,_kpt


	/*
	 * do the same conversion on the first available memory
	 * address (in a6).
	 */
	lea	a6@,a0
	subl	#LVSTART_STRAM,a0
	addl	#LKSTART_ADDR,a0
	movel	a0,_availmem

	/* convert and save the root table address in memory */
	lea	a5@,a0
	subl	#LVSTART_STRAM,a0 
	addl	#LKSTART_ADDR,a0
	movel	a0,_krt

	/*
	 * Record starting address and jump into the virtual address space.
	 */
	movel	#_start,a0   /* pcrel */
	subl	#LKSTART_ADDR,a0
	addl	#LVSTART_STRAM,a0

	jmp	Lvirt

Lvirt:
	moveq	#78,d7
	bsr	Lserial_putc

	/*
	 * Clean up the temporary physical mapping.
	 */

	pflusha 		/* flush address translation cache */


	moveq	#79,d7
	bsr	Lserial_putc


/*
 * Enable caches
 */

	movel	#0x00000919,d0
	movec	d0,cacr


/*
 * Setup initial stack pointer
 */
	lea	_user_stack+LPAGE_SIZE,sp

/* jump to memory management initialization */

	moveq	#0,d0
	movel	d0,sp@- 	/* parameters to main */
	movel	d0,sp@-
	movel	d0,sp@-
	bsr	_start_kernel


/*
 * Serial port output support.
 */


/*
 * Initialize serial port hardware for 9600/8/1
 */
Lserial_init:
	rts

/*
 * Output character in d7 on serial port.
 * d7 unchanged.
 */
Lserial_putc:
	rts

/*
 * Output string pointed to by a0 to serial port.
 * a0 trashed.
 */
Lserial_puts:
	rts

/*
 * Output number in d7 in hex notation on serial port.
 * d0-d2 trashed.
 * d7 trashed.
 */
Lserial_putnum:
	rts

/* Some nops to shift main.o backwards. This is necessary because the first
 * 2 KByte of RAM are supervisor-only by hardware.
 */
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop

	.data
Lmmu:	.long 0,0
_krt:	.long 0
_kpt:	.long 0
_availmem:
	.long 0
