patch-1.3.94 linux/arch/m68k/kernel/head.S
Next file: linux/arch/m68k/kernel/ints.c
Previous file: linux/arch/m68k/kernel/entry.S
Back to the patch index
Back to the overall index
- Lines: 1207
- Date:
Fri Apr 19 02:19:14 1996
- Orig file:
v1.3.93/linux/arch/m68k/kernel/head.S
- Orig date:
Thu Jan 1 02:00:00 1970
diff -u --recursive --new-file v1.3.93/linux/arch/m68k/kernel/head.S linux/arch/m68k/kernel/head.S
@@ -0,0 +1,1206 @@
+/* -*- mode: asm -*-
+**
+** head.S -- This file contains the initial boot code for the the
+** Linux/68k kernel.
+**
+** Copyright 1993 by Hamish Macdonald
+**
+** 68040 fixes by Michael Rausch
+** 68060 fixes by Roman Hodek
+**
+** Atari support by Andreas Schwab, using ideas of Robert de Vries
+** and Bjoern Brauel
+**
+** 94/11/14 Andreas Schwab: put kernel at PAGESIZE
+** 94/11/18 Andreas Schwab: remove identity mapping of STRAM for Atari
+** ++ Bjoern & Roman: ATARI-68040 support for the Medusa
+**
+** 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.
+**
+*/
+
+/*
+ * 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.
+ * Note that the kernel is located at virtual address 0x1000 == _start
+ * Enable cache memories
+ * Jump to kernel startup
+ *
+ * Register d6 contains the CPU flags and d4 the machine type
+ * from the boot_info information for most of this file.
+ * The upper word of d6 contains a bit for '040 or '060, since these two
+ * are quite similar for initial mm setup. Another bit in d6 allows
+ * distinction of the '060. The lower word of d6 contains the cache mode
+ * that should be applied to pages containing descriptors. This mode is
+ * non-cached/non-serialized for the '040 and cacheable/write-through for
+ * the '060.
+ */
+
+#include <linux/linkage.h>
+#include <asm/bootinfo.h>
+
+.text
+.globl SYMBOL_NAME(kernel_pg_dir), SYMBOL_NAME(kpt)
+.globl SYMBOL_NAME(availmem), SYMBOL_NAME(is_medusa)
+.globl SYMBOL_NAME(m68k_pgtable_cachemode)
+.globl SYMBOL_NAME(kernel_pmd_table), SYMBOL_NAME(swapper_pg_dir)
+
+PAGESIZE = 4096
+BI_CPU = 4
+BI_MACH = 0
+BI_AMIGA_ECLK = 1234
+LF = 10
+CR = 13
+BI_BIT040 = 2 /* CPU bits in bootinfo */
+BI_BIT060 = 3
+BIT0460 = 16 /* indicates '0[46]0 in d6 */
+BIT060 = 17 /* indicates '060 in d6 */
+D6VAL_040 = 0x00010000
+D6VAL_060 = 0x00030000
+/* BIT040 = 2 */
+
+ /* Some definitions for the special registers of the 68040.
+ * (MMU, caches)
+ */
+
+/* Translation control register */
+TC_ENABLE = 0x8000
+TC_PAGE8K = 0x4000
+TC_PAGE4K = 0x0000
+
+/* Transparent translation registers */
+TTR_ENABLE = 0x8000
+
+/* Some bits used in the page and table descriptors as well as in the
+ * special registers.
+ */
+
+CM_CACHE_WT = 0x0000 /* cacheable, write-through */
+CM_CACHE_CB = 0x0020 /* cacheable, copyback */
+CM_NONCACHE_SER = 0x0040 /* noncacheable, serialized */
+CM_NONCACHE = 0x0060 /* noncacheable */
+CM_MASK = 0xffffff9f /* mask */
+
+MODIFIED = 0x0010
+WRITE_PROT = 0x0004
+USED = 0x0008
+GLOBAL = 0x0400
+SV_ONLY = 0x0080
+PAGEDESC = 0x0001
+TABLEDESC = 0x0002
+INVALID = 0x0000
+
+/* Cache enabling */
+I_HALF = 0x00002000 /* half-cache mode for I-cache ('060) */
+I_FREEZE = 0x00004000 /* freeze I-cache ('060) */
+I_ENABLE = 0x00008000 /* enable I-cache */
+BC_CLRU = 0x00200000 /* clear user entries in branch cache ('060) */
+BC_CLRA = 0x00400000 /* clear all entries in branch cache ('060) */
+BC_ENABLE = 0x00800000 /* enable branch cache ('060) */
+D_HALF = 0x08000000 /* half-cache mode for D-cache ('060) */
+PUSH_DPI = 0x10000000 /* disable CPUSH invalidation ('060) */
+SB_ENABLE = 0x20000000 /* enable store buffer ('060) */
+D_FREEZE = 0x40000000 /* freeze D-cache ('060) */
+D_ENABLE = 0x80000000 /* enable D-cache */
+
+/* Miscellaneous definitions */
+PAGE_MASK = (~(PAGESIZE-1))
+
+ROOT_TABLE_SIZE = 128
+PTR_TABLE_SIZE = 128
+PAGE_TABLE_SIZE = 64
+ROOT_INDEX_SHIFT = 25
+PAGE_INDEX_SHIFT = 12
+
+ENTRY(_stext)
+ENTRY(_start)
+ bras 1f /* Jump over bootinfo version numbers */
+/*
+ * Version numbers of the bootinfo interface
+ */
+
+ .long BOOTINFOV_MAGIC
+ .long MACH_AMIGA, AMIGA_BOOTI_VERSION
+ .long MACH_ATARI, ATARI_BOOTI_VERSION
+ .long 0
+
+1:
+
+/*
+ * raise interrupt level
+ */
+
+ movew #0x2700,%sr
+
+/*
+ * Copy bootinfo from position after BSS to final resting place
+ */
+ lea %pc@(SYMBOL_NAME(_end)),%a0
+ lea %pc@(SYMBOL_NAME(boot_info)),%a1
+ movel %pc@(SYMBOL_NAME(bisize)),%d0
+ subql #1,%d0
+1: moveb %a0@+,%a1@+
+ dbra %d0,1b
+
+/*
+ * Record the CPU and machine type.
+ */
+ lea %pc@(SYMBOL_NAME(boot_info)),%a0
+ movel %a0@(BI_MACH),%d4
+ movel %a0@(BI_CPU),%d0
+ movel %a0@(BI_CPU),%d6 /* !!!!!!!!!!!!!!!! */
+
+ btst #BI_BIT060,%d0
+ beq 1f
+ /* '060: d6 := BIT0460|BIT060, cache mode 0x60 (no-cache/non-ser) */
+ movel #(D6VAL_060+CM_NONCACHE),%d6
+ bra 2f
+1: btst #BI_BIT040,%d0
+ beq 1f
+ /* '040: d6 := BIT0460, cache mode 0x00 (write-through) */
+ movel #(D6VAL_040+CM_CACHE_WT),%d6
+ bra 2f
+1: /* '020 or '030: d6 := no CPU bit, cache mode unused */
+ moveq #0,%d6
+
+2: lea %pc@(SYMBOL_NAME(m68k_pgtable_cachemode)),%a0
+ movel %d6,%a0@ /* save cache mode for page tables */
+ andl #0x0000ffff,%a0@
+
+/*
+ * Initialize serial port
+ */
+ jbsr Lserial_init
+
+ moveq #CR,%d7
+ jbsr Lserial_putc
+ moveq #LF,%d7
+ jbsr Lserial_putc
+ moveq #'A',%d7
+ jbsr Lserial_putc
+
+/*
+ * Get address at end of kernel code/data/bss and
+ * mask off at a page boundary.
+ */
+ lea %pc@(SYMBOL_NAME(_end)),%a0
+ movel %a0,%d0
+ addl #(PAGESIZE-1),%d0
+ andl #PAGE_MASK,%d0
+ movel %d0,%a6
+
+ moveq #'B',%d7
+ jbsr Lserial_putc
+
+/*
+ * initialize the kernel root table.
+ */
+ lea %pc@(SYMBOL_NAME(kernel_pg_dir)),%a4
+ movel %a4,%a0
+ moveq #0,%d0
+ moveq #(ROOT_TABLE_SIZE-1),%d1
+1: movel %d0,%a0@+
+ dbra %d1,1b
+
+ /*
+ * Initialize root table descriptor pointing to the kernel pointer
+ * table.
+ */
+ movel %a6,%a5
+ addw #PAGESIZE,%a6
+
+ movel %a5,%a0
+ addql #TABLEDESC,%a0
+ movel %a0,%a4@
+
+ moveq #'C',%d7
+ jbsr Lserial_putc
+
+/*
+ * Initialize the pointer tables referred to above. They either point
+ * to page tables in the case of the 680[46]0 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 */
+ movel %a5,%a0
+ moveq #0,%d0
+ moveq #(PTR_TABLE_SIZE-1),%d1
+1: movel %d0,%a0@+
+ dbra %d1,1b
+
+ movel %a5,%a0
+ moveq #15,%d1
+
+ /*
+ * base value of pointer table descriptor is either
+ * the address of the first page table (680[46]0)
+ * or the base address of physical memory (68030).
+ */
+ btst #BIT0460,%d6
+ bne 1f
+
+ /* 680[23]0 */
+ lea %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a1 /* base address */
+ addql #PAGEDESC,%a1 /* descriptor type */
+ movel #0x40000,%d2 /* increment */
+ bra 2f
+
+1: /* 680[46]0 */
+ movel %a6,%a1 /* base address */
+ addw #PAGESIZE,%a6 /* allocate the page table */
+ lea %pc@(SYMBOL_NAME(kpt)),%a3
+ movel %a1,%a3@ /* save address of page table */
+ addql #TABLEDESC,%a1 /* descriptor type */
+ movel #256,%d2 /* increment */
+
+2: movel %a1,%a0@+
+ addl %d2,%a1
+ dbra %d1,2b
+
+ moveq #'D',%d7
+ jbsr Lserial_putc
+
+/*
+ * If we are running on a 680[46]0, we have a kernel page table and
+ * must initialize it. Make the entries point to the first
+ * 4M of physical memory (the memory we are residing in).
+ * Set the cache mode bits to Cacheable, Copyback. Set the Global bits
+ * in the descriptors also.
+ */
+
+ btst #BIT0460,%d6
+ jeq Lnot040
+
+ moveq #'F',%d7
+ jbsr Lserial_putc
+
+ movel %pc@(SYMBOL_NAME(kpt)),%a0
+ lea %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a1
+
+ addw #(GLOBAL+CM_CACHE_CB+PAGEDESC),%a1
+ movew #((PAGESIZE/4)-1),%d1
+ movel #PAGESIZE,%d2
+
+1: movel %a1,%a0@+
+ addl %d2,%a1
+ dbra %d1,1b
+
+ /*
+ * on the 68040, pages used to hold mmu tables should
+ * be initialized as noncachable; the '060 allows write-through.
+ * Do this for the root table page (which also contains
+ * all pointer tables utilitized thus far) and the
+ * kernel page table.
+ */
+ lea %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
+ movel %a4,%d0 /* address of root table */
+ subl %a0,%d0 /* determine offset of root table page */
+ moveq #PAGE_INDEX_SHIFT,%d1 /* determine offset into kernel page table */
+ lsrl %d1,%d0 /* i.e. page number of the address offset */
+ movel %pc@(SYMBOL_NAME(kpt)),%a0
+ lea %a0@(%d0:l:4),%a0
+ movel %a0@,%d1
+ andl #CM_MASK,%d1
+ orw %d6,%d1
+ movel %d1,%a0@+
+
+ movel %a0@,%d1 /* do the same for the kernel page table */
+ bclr #5,%d1 /* the kernel page table resides in the */
+ bset #6,%d1 /* page after the page containing the */
+ movel %d1,%a0@ /* root table */
+
+Lnot040:
+/*
+ * Do any machine specific page table initializations.
+ */
+ moveq #MACH_AMIGA,%d0
+ cmpl %d4,%d0
+ bne Lnotami
+
+/*
+ * On the Amiga:
+ * Our current stack (in CHIP ram) may become invalid after the remapping
+ * of the kernel virtual address space, so set it to point to PAGE_SIZE.
+ * This will be in CHIP ram until after the remapping, and in the unused
+ * first page (temporarily) after that.
+ *
+ * Setup a mapping of the first 16M of physical address space at virtual
+ * address 0x80000000, using early termination page descriptors for the
+ * 68030, and proper page tables for the 680[46]0. Set this area as
+ * non-cacheable.
+ */
+
+ moveq #'H',%d7
+ jbsr Lserial_putc
+
+ move.w #PAGESIZE,%sp
+
+ btst #BIT0460,%d6
+ bne Lspami68040
+
+
+ /*
+ * for the 68030, just setup a translation to map in the first
+ * 32M of physical address space at virtual address 0x80000000
+ * using an early termination page descriptor.
+ */
+
+ moveq #'I',%d7
+ jbsr Lserial_putc
+
+ moveq #0x41,%d0
+ movel %d0,%a4@(64*4)
+
+ bra Lmapphys
+
+Lspami68040:
+
+ /*
+ * for the 680[46]0, use another pointer table, and allocate 4 more
+ * page tables. Initialize the pointer table to point to the
+ * page tables. Then initialize the page tables to point to
+ * the first 16M of memory, with no caching (noncachable/serialized).
+ */
+
+ /* clear the amiga pointer table */
+ lea %a5@(512),%a0
+ moveq #0,%d0
+ moveq #(PTR_TABLE_SIZE-1),%d1
+1: movel %d0,%a0@+
+ dbra %d1,1b
+
+ /* allocate 4 page tables */
+ movel %a6,%a3
+ addw #(4*PAGESIZE),%a6
+
+ /* initialize the pointer table */
+ lea %a5@(512),%a0
+ movel %a3,%a1
+ addql #TABLEDESC,%a1 /* base descriptor */
+ movel #256,%d2 /* increment */
+ moveq #(PAGE_TABLE_SIZE-1),%d1
+
+1: movel %a1,%a0@+
+ addl %d2,%a1
+ dbra %d1,1b
+
+ /* ensure that the root table points to the pointer table */
+ lea %a5@(512),%a0
+ addql #TABLEDESC,%a0
+ movel %a0,%a4@(256) /* 0x80000000>>(ROOT_INDEX_SHIFT-2) doesn't
+ work */
+
+ /*
+ * initialize the page tables
+ * descriptor bits include noncachable/serialized and global bits.
+ */
+ movel %a3,%a0
+ movew #(GLOBAL+CM_NONCACHE_SER+PAGEDESC),%a1
+ movel #PAGESIZE,%d2
+ movew #PAGESIZE-1,%d1
+
+1: movel %a1,%a0@+
+ addl %d2,%a1
+ dbra %d1,1b
+
+ /*
+ * Finally, since we just allocated 4 page tables, make sure that
+ * the virtual mapping of the 4 page tables indicates
+ * noncachable/serialized.
+ */
+ movel %a3,%d0 /* ami page table start address */
+ lea %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
+ subl %a0,%d0 /* determine offset of root table page */
+ moveq #PAGE_INDEX_SHIFT,%d1 /* determine offset into kernel page table */
+ lsrl %d1,%d0
+ movel %pc@(SYMBOL_NAME(kpt)),%a0
+ movel #3,%d2
+1: lea %a0@(%d0:l:4),%a1
+ movel %a1@,%d1
+ bclr #5,%d1
+ bset #6,%d1
+ movel %d1,%a1@
+ addql #1,%d0
+ dbra %d2,1b
+
+ bra Lmapphys
+
+
+Lnotami: /* other machines specific mappings go here! */
+
+ moveq #MACH_ATARI,%d0
+ cmpl %d4,%d0
+ bne Lnotatari
+
+ move.w #PAGESIZE,%sp
+
+/* On the Atari, we map the I/O region (phys. 0x00ffxxxx) by mapping
+ the last 16 MB of virtual address space to the first 16 MB (i.e.
+ 0xffxxxxxx -> 0x00xxxxxx). For this, an additional pointer table is
+ needed. I/O ranges are marked non-cachable.
+
+ For the Medusa it is better to map the I/O region transparently
+ (i.e. 0xffxxxxxx -> 0xffxxxxxx), because some I/O registers are
+ accessible only in the high area. The test whether it is a Medusa
+ is done by writing to the byte at phys. 0x0. This should result
+ in a bus error on all other machines.
+
+ ...should, but doesn't. The Atferburner040 for the Falcon has the
+ same behaviour (0x0..0x7 are no ROM shadow). So we have to do
+ another test to distinuish Medusa and AB040. This is a
+ read attempt for 0x00ff82fe phys. that should bus error on a Falcon
+ (+AB040), but is in the range where the Medusa always asserts DTACK.
+*/
+
+ moveq #0,%d3 /* base addr for others: 0x00000000 */
+ movec %d3,%vbr
+ lea %pc@(Ltest_berr),%a0
+ movel %a0,0x8
+ movel %sp,%a0
+ moveb 0x0,%d1
+ clrb 0x0
+ nop
+ moveb %d1,0x0
+ nop
+ tstb 0x00ff82fe
+ nop
+ movel #0xff000000,%d3 /* Medusa base addr: 0xff000000 */
+Ltest_berr:
+ movel %a0,%sp
+ lea %pc@(SYMBOL_NAME(is_medusa)),%a0
+ movel %d3,%a0@
+
+ /* Let the root table point to the new pointer table */
+ lea %a5@(512),%a0
+ addl #TABLEDESC,%a0
+ movel %a0,%a4@(508) /* 0xFE000000 - 0xFFFFFFFF */
+
+ /* clear lower half of the pointer table (0xfexxxxxx) */
+ lea %a5@(512),%a0
+ movel #0,%d0
+ movel #63,%d2
+1: movel %d0,%a0@+
+ dbra %d2,1b
+
+ btst #BIT0460,%d6
+ bne Lspata68040
+
+/* Mapping of the last 16M of virtual address space to the first 16M
+ for efficient addressing of hardware registers */
+ movel #0x40000,%d1
+ movel #63,%d2
+ movel %d3,%d0
+ addl #PAGEDESC,%d0
+1: movel %d0,%a0@+
+ addl %d1,%d0
+ dbra %d2,1b
+ moveq #0x40,%d0 /* make non-cachable */
+ addl %d0,%a5@(1020) /* 0xFFFC0000-0xFFFFFFFF (I/O space) */
+/* GK: 0xFFF00000-0xFFF3FFFF (IDE-bus) has to be non-cachable too */
+ addl %d0,%a5@(1008)
+
+ bra Lmapphys
+
+Lspata68040:
+ /* allocate 4 page tables */
+ movel %a6,%a3
+ addw #(4*PAGESIZE),%a6
+
+/* Initialize the upper half of the pointer table (a0 is still valid) */
+ movel %a3,%a1
+ addql #TABLEDESC,%a1
+ movel #256,%d2
+ moveq #63,%d1
+1: movel %a1,%a0@+
+ addl %d2,%a1
+ dbra %d1,1b
+
+ /* Initialize the page tables as noncacheable/serialized! */
+ movel %a3,%a0
+ movel %d3,%a1
+ addw #(GLOBAL+CM_NONCACHE_SER+PAGEDESC),%a1
+ movel #PAGESIZE,%d2
+ movew #(PAGESIZE-1),%d1
+1: movel %a1,%a0@+
+ addl %d2,%a1
+ dbra %d1,1b
+
+ /*
+ * Finally, since we just allocated 4 page tables, make sure that
+ * the virtual mapping of the 4 page tables indicates
+ * noncachable or write-through.
+ */
+ movel %a3,%d0 /* page table start address */
+ lea %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
+ subl %a0,%d0 /* determine offset of root table page */
+ moveq #PAGE_INDEX_SHIFT,%d1 /* determine offset into
+ kernel page table */
+ lsrl %d1,%d0
+ movel %pc@(SYMBOL_NAME(kpt)),%a0
+ moveq #3,%d2
+1: lea %a0@(%d0:l:4),%a1
+ movel %a1@,%d1
+ andl #CM_MASK,%d1
+ orw %d6,%d1
+ movel %d1,%a1@
+ addql #1,%d0
+ dbra %d2,1b
+
+Lnotatari:
+
+/*
+ * Setup a transparent mapping of the physical memory we are executing in.
+ *
+ * Only do this if the physical memory is not in the first 16M Meg, or not on
+ * an Amiga since the first 16M is already identity mapped on the Amiga.
+ */
+Lmapphys:
+ moveq #'J',%d7
+ jbsr Lserial_putc
+
+ clrl %d5 /* indicate that no cleanup is required */
+
+ cmpl #MACH_AMIGA,%d4
+ bne Lmapphysnotamiga /* other machines will probably have
+ * to put in code and jump to it here
+ */
+
+/*
+ * The virtual address of the start of the kernel is 0x1000. On ALL
+ * Amigas, there is CHIP RAM in this area. Hence we will copy the MMU
+ * enabling code to CHIP RAM (to the same physical address as the kernel
+ * virtual address) and jump to it. When the MMU is enabled, we will be
+ * running from the code in the kernel virtual space, rather than the
+ * physical space.
+ */
+
+/*
+ * Setup Supervisor Root Pointer register to point to page directory,
+ * setup translation register contents and enable translation.
+ */
+ btst #BIT0460,%d6
+ bne Lamimmu68040
+
+ moveq #'K',%d7
+ jbsr Lserial_putc
+
+ lea %pc@(mmu),%a0
+ movel #0x80000002,%a0@ /* no limit, 4byte descriptors */
+ movel %a4,%a0@(4)
+ pmove %a0@,%srp
+ pmove %a0@,%crp
+ /*
+ * enable,super root enable,4096 byte pages,7 bit root index,
+ * 7 bit pointer index, 6 bit page table index.
+ */
+ movel #0x82c07760,%a0@
+
+ /* setup registers for jumping MMU enabling code */
+ lea %pc@(Ldoit030ami),%a2
+ lea Ldoit030ami,%a1
+
+ moveq #CR,%d7
+ jbsr Lserial_putc
+ moveq #LF,%d7
+ jbsr Lserial_putc
+ movel %a2,%d7
+ jbsr Lserial_putnum
+ moveq #' ',%d7
+ jbsr Lserial_putc
+ movel %a1,%d7
+ jbsr Lserial_putnum
+
+ bra LdoitAmiga
+
+#ifdef __ELF__
+ .align 16
+#else
+ .align 4
+#endif
+Ldoit030ami:
+ pmove %a0@,%tc /* enable the MMU */
+ jra LdoneMMUenable /* branch to continuation of startup */
+
+Lamimmu68040:
+ moveq #'L',%d7
+ jbsr Lserial_putc
+
+ .word 0xf4d8 /* CINVA I/D */
+ .word 0xf518 /* pflusha */
+ .long 0x4e7bc807 /* movec a5,srp */
+ .long 0x4e7bc806 /* movec a5,urp */
+ movel #(TC_ENABLE+TC_PAGE4K),%d0
+
+ /* setup registers for jumping MMU enabling code */
+ lea Ldoit040ami,%a1
+ lea %pc@(Ldoit040ami),%a2
+ bra LdoitAmiga
+
+#ifdef __ELF__
+ .align 16
+#else
+ .align 4
+#endif
+Ldoit040ami:
+ .long 0x4e7b0003 /* movec d0,tc (enable the MMU) */
+ jra LdoneMMUenable /* branch to continuation of startup */
+
+LdoitAmiga:
+ /* copy the appropriate code (two longwords) to chipmem */
+ movel %a2@,%a1@
+ movel %a2@(4),%a1@(4)
+
+ /*
+ * save physaddr of phys mem in register a3
+ */
+ lea %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a3
+
+ /* jump to the physical address in chipmem */
+ jmp %a1@
+
+Lmapphysnotamiga:
+
+ cmpl #MACH_ATARI,%d4
+ bne Lmapphysnotatari
+
+ lea %pc@(SYMBOL_NAME(_stext)-PAGESIZE),%a0
+ tstl %a0
+ jeq Lnophys2
+
+ /* The kernel physical address is different from its virtual
+ address. Temporarily set up an identity mapping of the
+ 16MB chunk where the kernel is executing. */
+
+ /* 680[46]0? */
+ btst #BIT0460,%d6
+ jeq 1f
+
+ /*
+ * For the 68040, we will use the transparent translation
+ * registers to identity map the 16M chunk that contains
+ * the physical memory.
+ */
+ movel %a0,%d2
+ andl #0xff000000,%d2 /* logical address base */
+ orw #0xc040,%d2 /* add in magic bits */
+ .long 0x4e7b2004 /* movec d2,ittr0 */
+ .long 0x4e7b2006 /* movec d2,dttr0 */
+
+ /* d5 is kept 0 to do no cleanup. This didn't work in head.S, I don't
+ * know why... The transparent translation is turned off in
+ * atari/config.c instead.
+ */
+ jra Lnophys2
+
+ /* Transparent translation for the 68030 via transparent translation
+ register */
+
+1:
+ /* cleanup is needed; note it */
+ moveq #1,%d5
+
+ movel %a0,%d2
+ andl #0xff000000,%d2 /* logical address base */
+ orw #0x8143,%d2 /* add in magic bits */
+ lea %pc@(mmu),%a0
+ movel %d2,%a0@
+ pmove %a0@,%tt0
+
+Lnophys2:
+ /*
+ * save physaddr of phys mem in register a3
+ */
+ lea %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a3
+
+ btst #BIT0460,%d6
+ jne Latarimmu68040
+
+ moveq #'K',%d7
+ jbsr Lserial_putc
+
+ lea %pc@(mmu),%a0
+ movel #0x80000002,%a0@ /* no limit, 4byte descriptors */
+ movel %a4,%a0@(4)
+ pmove %a0@,%srp
+ pmove %a0@,%crp
+ /*
+ * 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 /* enable the MMU */
+
+ /* Jump to the virtual address of continuation of startup. */
+ jmp LdoneMMUenable
+
+Latarimmu68040:
+ moveq #'L',%d7
+ jbsr Lserial_putc
+
+ .word 0xf4d8 /* CINVA I/D */
+ .word 0xf518 /* pflusha */
+ .long 0x4e7bc807 /* movec a4,srp */
+ .long 0x4e7bc806 /* movec a4,urp */
+ movel #(TC_ENABLE+TC_PAGE4K),%d0
+ /* this value is also ok for the '060, we don't use the cache
+ * mode/protection defaults */
+ .long 0x4e7b0003 /* movec d0,tc (enable the MMU) */
+ jmp LdoneMMUenable /* jump to virtual address of
+ continuation of startup */
+
+Lmapphysnotatari:
+
+
+LdoneMMUenable:
+
+/*
+ * Fixup the addresses for the kernel pointer table and availmem.
+ * Convert them from physical addresses to virtual addresses.
+ */
+
+ /*
+ * fixup the Amiga custom register location before printing
+ */
+ addl #0x80000000,Lcustom
+
+ /* The same for the Atari */
+ movel #0xff000000,Liobase
+
+ moveq #'M',%d7
+ jbsr Lserial_putc
+
+ /*
+ * a3 contains physaddr of kernel start
+ */
+ movel SYMBOL_NAME(kpt),%d1
+ subl %a3,%d1
+ movel %d1,SYMBOL_NAME(kpt)
+
+ /*
+ * do the same conversion on the first available memory
+ * address (in a6).
+ */
+ subl %a3,%a6
+
+ /* Allocate a page to be used by get_kpointer_table. */
+ movel %a6,SYMBOL_NAME(kernel_pmd_table)
+ addl #PAGESIZE,%a6
+ movel %a6,SYMBOL_NAME(availmem) /* first available memory address */
+
+ moveq #'N',%d7
+ jbsr Lserial_putc
+
+ /*
+ * Clean up the temporary physical mapping (if necessary)
+ */
+
+ tstl %d5
+ jeq Lnoclean
+
+ btst #BIT0460,%d6
+ jne Loff040
+
+ /* clean up physical identity mapping for 68020/68030 */
+ /* Is this needed for the Amiga anymore? */
+ /* it's not in 1.2.13pl6 - Jes */
+ cmpl #MACH_AMIGA,%d4
+ jeq Lclean030
+ cmpl #MACH_ATARI,%d4
+ jne Lnoclean
+
+ /* clear transparent translation register */
+ lea %pc@(mmu),%a0
+ clrl %a0@
+ pmove %a0@,%tt0
+ jra Lnoclean
+
+Lclean030:
+ movel %a0,%d2 /* a0 contains physical start address */
+ moveq #25,%d3 /* find appropriate index in root table */
+ lsrl %d3,%d2
+ moveq #0,%d0
+ movel %d0,%a4@(%d2:l:4) /* clear descriptor */
+
+ jra Lnoclean
+
+Loff040:
+ /* turn off transparent translation registers for '0[46]0 */
+ moveq #0,%d0
+ .long 0x4e7b0004 /* movec d0,ittr0 */
+ .long 0x4e7b0006 /* movec d0,dttr0 */
+
+Lnoclean:
+ moveq #'O',%d7
+ jbsr Lserial_putc
+
+
+/*
+ * Enable caches
+ */
+ btst #BIT0460,%d6
+ jne Lcache680460
+
+ movel #0x00001919,%d0
+ movec %d0,%cacr
+ jra 1f
+
+Lcache680460:
+ btst #BIT060,%d6
+ jne Lcache68060
+
+ .word 0xf4d8 /* CINVA I/D */
+ movel #I_ENABLE+D_ENABLE,%d0
+ /* MMU stuff works in copyback mode now, so enable the cache */
+ movec %d0,%cacr
+ jra 1f
+
+Lcache68060:
+ .word 0xf4d8 /* CINVA I/D */
+ movel #I_ENABLE+D_ENABLE+SB_ENABLE+PUSH_DPI+BC_ENABLE+BC_CLRA,%d0
+ /* MMU stuff works in copyback mode now, so enable the cache */
+ movec %d0,%cacr
+ /* enable superscalar dispatch in PCR */
+ moveq #1,%d0
+ .long 0x4e7b0808 /* movec d0,pcr */
+
+1:
+
+/*
+ * Setup initial stack pointer
+ */
+ lea SYMBOL_NAME(init_user_stack)+PAGESIZE,%sp
+
+/* jump to the kernel start */
+
+ jbsr SYMBOL_NAME(start_kernel)
+
+#if 0
+tmp_fault_handler:
+ lea %pc@(tfh_1st_str),%a0
+ jbsr Lserial_puts
+ move.l %sp@(2),%d7 /* PC */
+ jbsr Lserial_putnum
+ move.w %sp@(0xa),%d7
+ swap %d7
+ move.w %sp@(0x6),%d7
+ jbsr Lserial_putnum
+ lea %pc@(tfh_2nd_str),%a0
+ jbsr Lserial_puts
+ move.l %sp@(0x10),%d7 /* Fault address */
+ jbsr Lserial_putnum
+ moveq #CR,%d7
+ jbsr Lserial_putc
+ moveq #LF,%d7
+ jbsr Lserial_putc
+1: jra 1b
+
+tfh_1st_str:
+ .byte CR
+ .byte LF
+ .ascii "Access fault occurred. PC = "
+ .byte 0
+
+tfh_2nd_str:
+ .byte CR
+ .byte LF
+ .ascii "FaultAddress = "
+ .byte 0
+#endif
+
+/*
+ * Serial port output support.
+ */
+LSERPER = 0xdff032
+LSERDAT = 0xdff030
+LSERDATR = 0xdff018
+LNTSC_PERIOD = 371
+LPAL_PERIOD = 368/2 /* /2 for 19200 baud */
+LNTSC_ECLOCK = 7159090
+LSERIAL_CNTRL = 0xbfd000
+LSERIAL_DTR = 7
+
+/*
+ * Debug output support
+ * Atarians have a choice between the parallel port, the serial port
+ * from the MFP or a serial port of the SCC
+ */
+
+/* #define USE_PRINTER */
+/* #define USE_SCC */
+#define USE_MFP
+
+#ifdef USE_PRINTER
+
+LPSG_SELECT = 0xff8800
+LPSG_READ = 0xff8800
+LPSG_WRITE = 0xff8802
+LPSG_IO_A = 14
+LPSG_IO_B = 15
+LPSG_CONTROL = 7
+LSTMFP_GPIP = 0xfffa01
+LSTMFP_DDR = 0xfffa05
+LSTMFP_IERB = 0xfffa09
+
+#elif defined(USE_SCC)
+
+LSCC_CTRL_B = 0xff8c85
+LSCC_DATA_B = 0xff8c87
+
+/* Initialisation table for SCC */
+scc_initable:
+ .byte 9,12 /* Reset */
+ .byte 4,0x44 /* x16, 1 stopbit, no parity */
+ .byte 3,0xc0 /* receiver: 8 bpc */
+ .byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */
+ .byte 9,0 /* no interrupts */
+ .byte 10,0 /* NRZ */
+ .byte 11,0x50 /* use baud rate generator */
+ .byte 12,24,13,0 /* 9600 baud */
+ .byte 14,2,14,3 /* use master clock for BRG, enable */
+ .byte 3,0xc1 /* enable receiver */
+ .byte 5,0xea /* enable transmitter */
+ .byte -1
+ .even
+
+#elif defined(USE_MFP)
+
+LMFP_UCR = 0xfffa29
+LMFP_TDCDR = 0xfffa1d
+LMFP_TDDR = 0xfffa25
+LMFP_TSR = 0xfffa2d
+LMFP_UDR = 0xfffa2f
+
+#endif
+
+/*
+ * Initialize serial port hardware for 9600/8/1
+ * a0 thrashed
+ * Atari d0 trashed (a1 in case of SCC)
+ */
+ .even
+Lserial_init:
+ cmpil #MACH_AMIGA,%d4
+ jne 1f
+ bclr #LSERIAL_DTR,LSERIAL_CNTRL
+ movew #LNTSC_PERIOD,LSERPER
+ cmpl #LNTSC_ECLOCK,%a0@(BI_AMIGA_ECLK)
+ jeq 9f
+ movew #LPAL_PERIOD,LSERPER
+ jra 9f
+1: cmpil #MACH_ATARI,%d4
+ jne 9f
+#ifdef USE_PRINTER
+ bclr #0,LSTMFP_IERB
+ bclr #0,LSTMFP_DDR
+ moveb #LPSG_CONTROL,LPSG_SELECT
+ moveb #0xff,LPSG_WRITE
+ moveb #LPSG_IO_B,LPSG_SELECT
+ clrb LPSG_WRITE
+ moveb #LPSG_IO_A,LPSG_SELECT
+ moveb LPSG_READ,%d0
+ bset #5,%d0
+ moveb %d0,LPSG_WRITE
+#elif defined(USE_SCC)
+ lea LSCC_CTRL_B,%a0
+ lea %pc@(scc_initable:w),%a1
+2: moveb %a1@+,%d0
+ jmi 3f
+ moveb %d0,%a0@
+ moveb %a1@+,%a0@
+ jra 2b
+3: clrb %a0@
+#elif defined(USE_MFP)
+ bclr #1,LMFP_TSR
+ moveb #0x88,LMFP_UCR
+ andb #0x70,LMFP_TDCDR
+ moveb #2,LMFP_TDDR
+ orb #1,LMFP_TDCDR
+ bset #1,LMFP_TSR
+#endif
+9:
+ rts
+
+/*
+ * Output character in d7 on serial port.
+ * d7 thrashed.
+ */
+Lserial_putc:
+ moveml %a0/%a1,%sp@-
+ cmpil #MACH_AMIGA,%d4
+ jne 2f
+ andw #0x00ff,%d7
+ oriw #0x0100,%d7
+ movel %pc@(Lcustom),%a1
+ movew %d7,%a1@(LSERDAT)
+1: movew %a1@(LSERDATR),%d7
+ andw #0x2000,%d7
+ jeq 1b
+ jra 9f
+2: cmpil #MACH_ATARI,%d4
+ jne 9f
+ movel %pc@(Liobase),%a1
+#ifdef USE_PRINTER
+3: btst #0,%a1@(LSTMFP_GPIP)
+ jne 3b
+ moveb #LPSG_IO_B,%a1@(LPSG_SELECT)
+ moveb %d7,%a1@(LPSG_WRITE)
+ moveb #LPSG_IO_A,%a1@(LPSG_SELECT)
+ moveb %a1@(LPSG_READ),%d7
+ bclr #5,%d7
+ moveb %d7,%a1@(LPSG_WRITE)
+ nop
+ nop
+ bset #5,%d7
+ moveb %d7,%a1@(LPSG_WRITE)
+#elif defined(USE_SCC)
+3: btst #2,%a1@(LSCC_CTRL_B)
+ jeq 3b
+ moveb %d7,%a1@(LSCC_DATA_B)
+#elif defined(USE_MFP)
+3: btst #7,%a1@(LMFP_TSR)
+ jeq 3b
+ moveb %d7,%a1@(LMFP_UDR)
+#endif
+9:
+ moveml %sp@+,%a0/%a1
+ rts
+
+/*
+ * Output string pointed to by a0 to serial port.
+ * a0 trashed.
+ */
+Lserial_puts:
+ movel %d7,%sp@-
+1: moveb %a0@+,%d7
+ jeq 2f
+ jbsr Lserial_putc
+ jra 1b
+2: movel %sp@+,%d7
+ rts
+
+/*
+ * Output number in d7 in hex notation on serial port.
+ * d0-d2 trashed.
+ * d7 trashed.
+ */
+
+Lserial_putnum:
+ moveml %d0-%d2/%d7,%sp@-
+ movel %d7,%d1
+ moveq #4,%d0
+ moveq #7,%d2
+L1: roll %d0,%d1
+ moveb %d1,%d7
+ andb #0x0f,%d7
+ cmpb #0x0a,%d7
+ bccs 1f
+ addb #'0',%d7
+ jra 2f
+1: addb #'A'-10,%d7
+2: jbsr Lserial_putc
+ dbra %d2,L1
+ moveq #32,%d7
+ jbsr Lserial_putc
+ moveml %sp@+,%d0-%d2/%d7
+ rts
+#if 0
+.globl showtest
+showtest:
+ moveml %a1/%d7,%sp@-
+ moveq #'A',%d7
+ jbsr Lserial_putc
+ moveq #'=',%d7
+ jbsr Lserial_putc
+ movel %a0,%d7
+ jbsr Lserial_putnum
+
+ ptestr #5,%a0@,#7,%a1
+
+ moveq #'D',%d7
+ jbsr Lserial_putc
+ moveq #'A',%d7
+ jbsr Lserial_putc
+ moveq #'=',%d7
+ jbsr Lserial_putc
+
+ movel %a1,%d7
+ jbsr Lserial_putnum
+
+ moveq #'D',%d7
+ jbsr Lserial_putc
+ moveq #'=',%d7
+ jbsr Lserial_putc
+ movel %a1@,%d7
+ jbsr Lserial_putnum
+
+ moveq #'S',%d7
+ jbsr Lserial_putc
+ moveq #'=',%d7
+ jbsr Lserial_putc
+
+ lea %pc@(mmu),%a1
+ pmove %psr,%a1@
+ clrl %d7
+ movew %a1@,%d7
+ jbsr Lserial_putnum
+
+ moveq #CR,%d7
+ jbsr Lserial_putc
+ moveq #LF,%d7
+ jbsr Lserial_putc
+
+ moveml %sp@+,%a1/%d7
+ rts
+#endif
+
+ .align 512 /*
+ * MMU root-pointers need to be 512-byte
+ * aligned on the 680[46]0 - Jes
+ */
+
+SYMBOL_NAME_LABEL(swapper_pg_dir)
+ .skip ROOT_TABLE_SIZE * 4
+SYMBOL_NAME_LABEL(kernel_pg_dir)
+ .skip ROOT_TABLE_SIZE * 4
+
+ .data
+ .even
+Lcustom:
+ .long 0
+Liobase:
+ .long 0
+mmu: .quad 0
+SYMBOL_NAME_LABEL(kernel_pmd_table)
+ .long 0
+SYMBOL_NAME_LABEL(kpt)
+ .long 0
+SYMBOL_NAME_LABEL(availmem)
+ .long 0
+SYMBOL_NAME_LABEL(is_medusa)
+ .long 0
+SYMBOL_NAME_LABEL(m68k_pgtable_cachemode)
+ .long 0
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this