diff options
Diffstat (limited to 'arch/m68k/kernel/head.S')
-rw-r--r-- | arch/m68k/kernel/head.S | 3940 |
1 files changed, 3940 insertions, 0 deletions
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S new file mode 100644 index 000000000000..7cd6de17c20d --- /dev/null +++ b/arch/m68k/kernel/head.S @@ -0,0 +1,3940 @@ +/* -*- mode: asm -*- +** +** head.S -- This file contains the initial boot code for the +** Linux/68k kernel. +** +** Copyright 1993 by Hamish Macdonald +** +** 68040 fixes by Michael Rausch +** 68060 fixes by Roman Hodek +** MMU cleanup by Randy Thelen +** Final MMU cleanup by Roman Zippel +** +** Atari support by Andreas Schwab, using ideas of Robert de Vries +** and Bjoern Brauel +** VME Support by Richard Hirst +** +** 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 +** 95/11/18 Richard Hirst: Added MVME166 support +** 96/04/26 Guenther Kelleter: fixed identity mapping for Falcon with +** Magnum- and FX-alternate ram +** 98/04/25 Phil Blundell: added HP300 support +** 1998/08/30 David Kilzer: Added support for font_desc structures +** for linux-2.1.115 +** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01) +** 2004/05/13 Kars de Jong: Finalised HP300 support +** +** 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. + * . Enable the MMU + * . Enable cache memories + * . Jump to kernel startup + * + * Much of the file restructuring was to accomplish: + * 1) Remove register dependency through-out the file. + * 2) Increase use of subroutines to perform functions + * 3) Increase readability of the code + * + * Of course, readability is a subjective issue, so it will never be + * argued that that goal was accomplished. It was merely a goal. + * A key way to help make code more readable is to give good + * documentation. So, the first thing you will find is exaustive + * write-ups on the structure of the file, and the features of the + * functional subroutines. + * + * General Structure: + * ------------------ + * Without a doubt the single largest chunk of head.S is spent + * mapping the kernel and I/O physical space into the logical range + * for the kernel. + * There are new subroutines and data structures to make MMU + * support cleaner and easier to understand. + * First, you will find a routine call "mmu_map" which maps + * a logical to a physical region for some length given a cache + * type on behalf of the caller. This routine makes writing the + * actual per-machine specific code very simple. + * A central part of the code, but not a subroutine in itself, + * is the mmu_init code which is broken down into mapping the kernel + * (the same for all machines) and mapping machine-specific I/O + * regions. + * Also, there will be a description of engaging the MMU and + * caches. + * You will notice that there is a chunk of code which + * can emit the entire MMU mapping of the machine. This is present + * only in debug modes and can be very helpful. + * Further, there is a new console driver in head.S that is + * also only engaged in debug mode. Currently, it's only supported + * on the Macintosh class of machines. However, it is hoped that + * others will plug-in support for specific machines. + * + * ###################################################################### + * + * mmu_map + * ------- + * mmu_map was written for two key reasons. First, it was clear + * that it was very difficult to read the previous code for mapping + * regions of memory. Second, the Macintosh required such extensive + * memory allocations that it didn't make sense to propagate the + * existing code any further. + * mmu_map requires some parameters: + * + * mmu_map (logical, physical, length, cache_type) + * + * While this essentially describes the function in the abstract, you'll + * find more indepth description of other parameters at the implementation site. + * + * mmu_get_root_table_entry + * ------------------------ + * mmu_get_ptr_table_entry + * ----------------------- + * mmu_get_page_table_entry + * ------------------------ + * + * These routines are used by other mmu routines to get a pointer into + * a table, if necessary a new table is allocated. These routines are working + * basically like pmd_alloc() and pte_alloc() in <asm/pgtable.h>. The root + * table needs of course only to be allocated once in mmu_get_root_table_entry, + * so that here also some mmu specific initialization is done. The second page + * at the start of the kernel (the first page is unmapped later) is used for + * the kernel_pg_dir. It must be at a position known at link time (as it's used + * to initialize the init task struct) and since it needs special cache + * settings, it's the easiest to use this page, the rest of the page is used + * for further pointer tables. + * mmu_get_page_table_entry allocates always a whole page for page tables, this + * means 1024 pages and so 4MB of memory can be mapped. It doesn't make sense + * to manage page tables in smaller pieces as nearly all mappings have that + * size. + * + * ###################################################################### + * + * + * ###################################################################### + * + * mmu_engage + * ---------- + * Thanks to a small helping routine enabling the mmu got quite simple + * and there is only one way left. mmu_engage makes a complete a new mapping + * that only includes the absolute necessary to be able to jump to the final + * postion and to restore the original mapping. + * As this code doesn't need a transparent translation register anymore this + * means all registers are free to be used by machines that needs them for + * other purposes. + * + * ###################################################################### + * + * mmu_print + * --------- + * This algorithm will print out the page tables of the system as + * appropriate for an 030 or an 040. This is useful for debugging purposes + * and as such is enclosed in #ifdef MMU_PRINT/#endif clauses. + * + * ###################################################################### + * + * console_init + * ------------ + * The console is also able to be turned off. The console in head.S + * is specifically for debugging and can be very useful. It is surrounded by + * #ifdef CONSOLE/#endif clauses so it doesn't have to ship in known-good + * kernels. It's basic algorithm is to determine the size of the screen + * (in height/width and bit depth) and then use that information for + * displaying an 8x8 font or an 8x16 (widthxheight). I prefer the 8x8 for + * debugging so I can see more good data. But it was trivial to add support + * for both fonts, so I included it. + * Also, the algorithm for plotting pixels is abstracted so that in + * theory other platforms could add support for different kinds of frame + * buffers. This could be very useful. + * + * console_put_penguin + * ------------------- + * An important part of any Linux bring up is the penguin and there's + * nothing like getting the Penguin on the screen! This algorithm will work + * on any machine for which there is a console_plot_pixel. + * + * console_scroll + * -------------- + * My hope is that the scroll algorithm does the right thing on the + * various platforms, but it wouldn't be hard to add the test conditions + * and new code if it doesn't. + * + * console_putc + * ------------- + * + * ###################################################################### + * + * Register usage has greatly simplified within head.S. Every subroutine + * saves and restores all registers that it modifies (except it returns a + * value in there of course). So the only register that needs to be initialized + * is the stack pointer. + * All other init code and data is now placed in the init section, so it will + * be automatically freed at the end of the kernel initialization. + * + * ###################################################################### + * + * options + * ------- + * There are many options available in a build of this file. I've + * taken the time to describe them here to save you the time of searching + * for them and trying to understand what they mean. + * + * CONFIG_xxx: These are the obvious machine configuration defines created + * during configuration. These are defined in include/linux/autoconf.h. + * + * CONSOLE: There is support for head.S console in this file. This + * console can talk to a Mac frame buffer, but could easily be extrapolated + * to extend it to support other platforms. + * + * TEST_MMU: This is a test harness for running on any given machine but + * getting an MMU dump for another class of machine. The classes of machines + * that can be tested are any of the makes (Atari, Amiga, Mac, VME, etc.) + * and any of the models (030, 040, 060, etc.). + * + * NOTE: TEST_MMU is NOT permanent! It is scheduled to be removed + * When head.S boots on Atari, Amiga, Macintosh, and VME + * machines. At that point the underlying logic will be + * believed to be solid enough to be trusted, and TEST_MMU + * can be dropped. Do note that that will clean up the + * head.S code significantly as large blocks of #if/#else + * clauses can be removed. + * + * MMU_NOCACHE_KERNEL: On the Macintosh platform there was an inquiry into + * determing why devices don't appear to work. A test case was to remove + * the cacheability of the kernel bits. + * + * MMU_PRINT: There is a routine built into head.S that can display the + * MMU data structures. It outputs its result through the serial_putc + * interface. So where ever that winds up driving data, that's where the + * mmu struct will appear. On the Macintosh that's typically the console. + * + * SERIAL_DEBUG: There are a series of putc() macro statements + * scattered through out the code to give progress of status to the + * person sitting at the console. This constant determines whether those + * are used. + * + * DEBUG: This is the standard DEBUG flag that can be set for building + * the kernel. It has the effect adding additional tests into + * the code. + * + * FONT_6x11: + * FONT_8x8: + * FONT_8x16: + * In theory these could be determined at run time or handed + * over by the booter. But, let's be real, it's a fine hard + * coded value. (But, you will notice the code is run-time + * flexible!) A pointer to the font's struct font_desc + * is kept locally in Lconsole_font. It is used to determine + * font size information dynamically. + * + * Atari constants: + * USE_PRINTER: Use the printer port for serial debug. + * USE_SCC_B: Use the SCC port A (Serial2) for serial debug. + * USE_SCC_A: Use the SCC port B (Modem2) for serial debug. + * USE_MFP: Use the ST-MFP port (Modem1) for serial debug. + * + * Macintosh constants: + * MAC_SERIAL_DEBUG: Turns on serial debug output for the Macintosh. + * MAC_USE_SCC_A: Use the SCC port A (modem) for serial debug. + * MAC_USE_SCC_B: Use the SCC port B (printer) for serial debug (default). + */ + +#include <linux/config.h> +#include <linux/linkage.h> +#include <linux/init.h> +#include <asm/bootinfo.h> +#include <asm/setup.h> +#include <asm/entry.h> +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/offsets.h> + +#ifdef CONFIG_MAC + +#include <asm/machw.h> + +/* + * Macintosh console support + */ + +#define CONSOLE +#define CONSOLE_PENGUIN + +/* + * Macintosh serial debug support; outputs boot info to the printer + * and/or modem serial ports + */ +#undef MAC_SERIAL_DEBUG + +/* + * Macintosh serial debug port selection; define one or both; + * requires MAC_SERIAL_DEBUG to be defined + */ +#define MAC_USE_SCC_A /* Macintosh modem serial port */ +#define MAC_USE_SCC_B /* Macintosh printer serial port */ + +#endif /* CONFIG_MAC */ + +#undef MMU_PRINT +#undef MMU_NOCACHE_KERNEL +#define SERIAL_DEBUG +#undef DEBUG + +/* + * For the head.S console, there are three supported fonts, 6x11, 8x16 and 8x8. + * The 8x8 font is harder to read but fits more on the screen. + */ +#define FONT_8x8 /* default */ +/* #define FONT_8x16 */ /* 2nd choice */ +/* #define FONT_6x11 */ /* 3rd choice */ + +.globl kernel_pg_dir +.globl availmem +.globl m68k_pgtable_cachemode +.globl m68k_supervisor_cachemode +#ifdef CONFIG_MVME16x +.globl mvme_bdid +#endif +#ifdef CONFIG_Q40 +.globl q40_mem_cptr +#endif + +CPUTYPE_040 = 1 /* indicates an 040 */ +CPUTYPE_060 = 2 /* indicates an 060 */ +CPUTYPE_0460 = 3 /* if either above are set, this is set */ +CPUTYPE_020 = 4 /* indicates an 020 */ + +/* Translation control register */ +TC_ENABLE = 0x8000 +TC_PAGE8K = 0x4000 +TC_PAGE4K = 0x0000 + +/* Transparent translation registers */ +TTR_ENABLE = 0x8000 /* enable transparent translation */ +TTR_ANYMODE = 0x4000 /* user and kernel mode access */ +TTR_KERNELMODE = 0x2000 /* only kernel mode access */ +TTR_USERMODE = 0x0000 /* only user mode access */ +TTR_CI = 0x0400 /* inhibit cache */ +TTR_RW = 0x0200 /* read/write mode */ +TTR_RWM = 0x0100 /* read/write mask */ +TTR_FCB2 = 0x0040 /* function code base bit 2 */ +TTR_FCB1 = 0x0020 /* function code base bit 1 */ +TTR_FCB0 = 0x0010 /* function code base bit 0 */ +TTR_FCM2 = 0x0004 /* function code mask bit 2 */ +TTR_FCM1 = 0x0002 /* function code mask bit 1 */ +TTR_FCM0 = 0x0001 /* function code mask bit 0 */ + +/* Cache Control registers */ +CC6_ENABLE_D = 0x80000000 /* enable data cache (680[46]0) */ +CC6_FREEZE_D = 0x40000000 /* freeze data cache (68060) */ +CC6_ENABLE_SB = 0x20000000 /* enable store buffer (68060) */ +CC6_PUSH_DPI = 0x10000000 /* disable CPUSH invalidation (68060) */ +CC6_HALF_D = 0x08000000 /* half-cache mode for data cache (68060) */ +CC6_ENABLE_B = 0x00800000 /* enable branch cache (68060) */ +CC6_CLRA_B = 0x00400000 /* clear all entries in branch cache (68060) */ +CC6_CLRU_B = 0x00200000 /* clear user entries in branch cache (68060) */ +CC6_ENABLE_I = 0x00008000 /* enable instruction cache (680[46]0) */ +CC6_FREEZE_I = 0x00004000 /* freeze instruction cache (68060) */ +CC6_HALF_I = 0x00002000 /* half-cache mode for instruction cache (68060) */ +CC3_ALLOC_WRITE = 0x00002000 /* write allocate mode(68030) */ +CC3_ENABLE_DB = 0x00001000 /* enable data burst (68030) */ +CC3_CLR_D = 0x00000800 /* clear data cache (68030) */ +CC3_CLRE_D = 0x00000400 /* clear entry in data cache (68030) */ +CC3_FREEZE_D = 0x00000200 /* freeze data cache (68030) */ +CC3_ENABLE_D = 0x00000100 /* enable data cache (68030) */ +CC3_ENABLE_IB = 0x00000010 /* enable instruction burst (68030) */ +CC3_CLR_I = 0x00000008 /* clear instruction cache (68030) */ +CC3_CLRE_I = 0x00000004 /* clear entry in instruction cache (68030) */ +CC3_FREEZE_I = 0x00000002 /* freeze instruction cache (68030) */ +CC3_ENABLE_I = 0x00000001 /* enable instruction cache (68030) */ + +/* Miscellaneous definitions */ +PAGESIZE = 4096 +PAGESHIFT = 12 + +ROOT_TABLE_SIZE = 128 +PTR_TABLE_SIZE = 128 +PAGE_TABLE_SIZE = 64 +ROOT_INDEX_SHIFT = 25 +PTR_INDEX_SHIFT = 18 +PAGE_INDEX_SHIFT = 12 + +#ifdef DEBUG +/* When debugging use readable names for labels */ +#ifdef __STDC__ +#define L(name) .head.S.##name +#else +#define L(name) .head.S./**/name +#endif +#else +#ifdef __STDC__ +#define L(name) .L##name +#else +#define L(name) .L/**/name +#endif +#endif + +/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */ +#ifndef __INITDATA +#define __INITDATA .data +#define __FINIT .previous +#endif + +/* Several macros to make the writing of subroutines easier: + * - func_start marks the beginning of the routine which setups the frame + * register and saves the registers, it also defines another macro + * to automatically restore the registers again. + * - func_return marks the end of the routine and simply calls the prepared + * macro to restore registers and jump back to the caller. + * - func_define generates another macro to automatically put arguments + * onto the stack call the subroutine and cleanup the stack again. + */ + +/* Within subroutines these macros can be used to access the arguments + * on the stack. With STACK some allocated memory on the stack can be + * accessed and ARG0 points to the return address (used by mmu_engage). + */ +#define STACK %a6@(stackstart) +#define ARG0 %a6@(4) +#define ARG1 %a6@(8) +#define ARG2 %a6@(12) +#define ARG3 %a6@(16) +#define ARG4 %a6@(20) + +.macro func_start name,saveregs,stack=0 +L(\name): + linkw %a6,#-\stack + moveml \saveregs,%sp@- +.set stackstart,-\stack + +.macro func_return_\name + moveml %sp@+,\saveregs + unlk %a6 + rts +.endm +.endm + +.macro func_return name + func_return_\name +.endm + +.macro func_call name + jbsr L(\name) +.endm + +.macro move_stack nr,arg1,arg2,arg3,arg4 +.if \nr + move_stack "(\nr-1)",\arg2,\arg3,\arg4 + movel \arg1,%sp@- +.endif +.endm + +.macro func_define name,nr=0 +.macro \name arg1,arg2,arg3,arg4 + move_stack \nr,\arg1,\arg2,\arg3,\arg4 + func_call \name +.if \nr + lea %sp@(\nr*4),%sp +.endif +.endm +.endm + +func_define mmu_map,4 +func_define mmu_map_tt,4 +func_define mmu_fixup_page_mmu_cache,1 +func_define mmu_temp_map,2 +func_define mmu_engage +func_define mmu_get_root_table_entry,1 +func_define mmu_get_ptr_table_entry,2 +func_define mmu_get_page_table_entry,2 +func_define mmu_print +func_define get_new_page +#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO) +func_define set_leds +#endif + +.macro mmu_map_eq arg1,arg2,arg3 + mmu_map \arg1,\arg1,\arg2,\arg3 +.endm + +.macro get_bi_record record + pea \record + func_call get_bi_record + addql #4,%sp +.endm + +func_define serial_putc,1 +func_define console_putc,1 + +func_define console_init +func_define console_put_stats +func_define console_put_penguin +func_define console_plot_pixel,3 +func_define console_scroll + +.macro putc ch +#if defined(CONSOLE) || defined(SERIAL_DEBUG) + pea \ch +#endif +#ifdef CONSOLE + func_call console_putc +#endif +#ifdef SERIAL_DEBUG + func_call serial_putc +#endif +#if defined(CONSOLE) || defined(SERIAL_DEBUG) + addql #4,%sp +#endif +.endm + +.macro dputc ch +#ifdef DEBUG + putc \ch +#endif +.endm + +func_define putn,1 + +.macro dputn nr +#ifdef DEBUG + putn \nr +#endif +.endm + +.macro puts string +#if defined(CONSOLE) || defined(SERIAL_DEBUG) + __INITDATA +.Lstr\@: + .string "\string" + __FINIT + pea %pc@(.Lstr\@) + func_call puts + addql #4,%sp +#endif +.endm + +.macro dputs string +#ifdef DEBUG + puts "\string" +#endif +.endm + +#define is_not_amiga(lab) cmpl &MACH_AMIGA,%pc@(m68k_machtype); jne lab +#define is_not_atari(lab) cmpl &MACH_ATARI,%pc@(m68k_machtype); jne lab +#define is_not_mac(lab) cmpl &MACH_MAC,%pc@(m68k_machtype); jne lab +#define is_not_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jne lab +#define is_not_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jne lab +#define is_not_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jne lab +#define is_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jeq lab +#define is_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jeq lab +#define is_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jeq lab +#define is_not_hp300(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); jne lab +#define is_not_apollo(lab) cmpl &MACH_APOLLO,%pc@(m68k_machtype); jne lab +#define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab +#define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab + +#define hasnt_leds(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); \ + jeq 42f; \ + cmpl &MACH_APOLLO,%pc@(m68k_machtype); \ + jne lab ;\ + 42:\ + +#define is_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jne lab +#define is_not_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jeq lab +#define is_040(lab) btst &CPUTYPE_040,%pc@(L(cputype)+3); jne lab +#define is_060(lab) btst &CPUTYPE_060,%pc@(L(cputype)+3); jne lab +#define is_not_060(lab) btst &CPUTYPE_060,%pc@(L(cputype)+3); jeq lab +#define is_020(lab) btst &CPUTYPE_020,%pc@(L(cputype)+3); jne lab +#define is_not_020(lab) btst &CPUTYPE_020,%pc@(L(cputype)+3); jeq lab + +/* On the HP300 we use the on-board LEDs for debug output before + the console is running. Writing a 1 bit turns the corresponding LED + _off_ - on the 340 bit 7 is towards the back panel of the machine. */ +.macro leds mask +#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO) + hasnt_leds(.Lled\@) + pea \mask + func_call set_leds + addql #4,%sp +.Lled\@: +#endif +.endm + +.text +ENTRY(_stext) +/* + * Version numbers of the bootinfo interface + * The area from _stext to _start will later be used as kernel pointer table + */ + bras 1f /* Jump over bootinfo version numbers */ + + .long BOOTINFOV_MAGIC + .long MACH_AMIGA, AMIGA_BOOTI_VERSION + .long MACH_ATARI, ATARI_BOOTI_VERSION + .long MACH_MVME147, MVME147_BOOTI_VERSION + .long MACH_MVME16x, MVME16x_BOOTI_VERSION + .long MACH_BVME6000, BVME6000_BOOTI_VERSION + .long MACH_MAC, MAC_BOOTI_VERSION + .long MACH_Q40, Q40_BOOTI_VERSION + .long MACH_HP300, HP300_BOOTI_VERSION + .long 0 +1: jra __start + +.equ kernel_pg_dir,_stext + +.equ .,_stext+PAGESIZE + +ENTRY(_start) + jra __start +__INIT +ENTRY(__start) +/* + * Setup initial stack pointer + */ + lea %pc@(_stext),%sp + +/* + * Record the CPU and machine type. + */ + get_bi_record BI_MACHTYPE + lea %pc@(m68k_machtype),%a1 + movel %a0@,%a1@ + + get_bi_record BI_FPUTYPE + lea %pc@(m68k_fputype),%a1 + movel %a0@,%a1@ + + get_bi_record BI_MMUTYPE + lea %pc@(m68k_mmutype),%a1 + movel %a0@,%a1@ + + get_bi_record BI_CPUTYPE + lea %pc@(m68k_cputype),%a1 + movel %a0@,%a1@ + + leds 0x1 + +#ifdef CONFIG_MAC +/* + * For Macintosh, we need to determine the display parameters early (at least + * while debugging it). + */ + + is_not_mac(L(test_notmac)) + + get_bi_record BI_MAC_VADDR + lea %pc@(L(mac_videobase)),%a1 + movel %a0@,%a1@ + + get_bi_record BI_MAC_VDEPTH + lea %pc@(L(mac_videodepth)),%a1 + movel %a0@,%a1@ + + get_bi_record BI_MAC_VDIM + lea %pc@(L(mac_dimensions)),%a1 + movel %a0@,%a1@ + + get_bi_record BI_MAC_VROW + lea %pc@(L(mac_rowbytes)),%a1 + movel %a0@,%a1@ + +#ifdef MAC_SERIAL_DEBUG + get_bi_record BI_MAC_SCCBASE + lea %pc@(L(mac_sccbase)),%a1 + movel %a0@,%a1@ +#endif /* MAC_SERIAL_DEBUG */ + +#if 0 + /* + * Clear the screen + */ + lea %pc@(L(mac_videobase)),%a0 + movel %a0@,%a1 + lea %pc@(L(mac_dimensions)),%a0 + movel %a0@,%d1 + swap %d1 /* #rows is high bytes */ + andl #0xFFFF,%d1 /* rows */ + subl #10,%d1 + lea %pc@(L(mac_rowbytes)),%a0 +loopy2: + movel %a0@,%d0 + subql #1,%d0 +loopx2: + moveb #0x55, %a1@+ + dbra %d0,loopx2 + dbra %d1,loopy2 +#endif + +L(test_notmac): +#endif /* CONFIG_MAC */ + + +/* + * There are ultimately two pieces of information we want for all kinds of + * processors CpuType and CacheBits. The CPUTYPE was passed in from booter + * and is converted here from a booter type definition to a separate bit + * number which allows for the standard is_0x0 macro tests. + */ + movel %pc@(m68k_cputype),%d0 + /* + * Assume it's an 030 + */ + clrl %d1 + + /* + * Test the BootInfo cputype for 060 + */ + btst #CPUB_68060,%d0 + jeq 1f + bset #CPUTYPE_060,%d1 + bset #CPUTYPE_0460,%d1 + jra 3f +1: + /* + * Test the BootInfo cputype for 040 + */ + btst #CPUB_68040,%d0 + jeq 2f + bset #CPUTYPE_040,%d1 + bset #CPUTYPE_0460,%d1 + jra 3f +2: + /* + * Test the BootInfo cputype for 020 + */ + btst #CPUB_68020,%d0 + jeq 3f + bset #CPUTYPE_020,%d1 + jra 3f +3: + /* + * Record the cpu type + */ + lea %pc@(L(cputype)),%a0 + movel %d1,%a0@ + + /* + * NOTE: + * + * Now the macros are valid: + * is_040_or_060 + * is_not_040_or_060 + * is_040 + * is_060 + * is_not_060 + */ + + /* + * Determine the cache mode for pages holding MMU tables + * and for supervisor mode, unused for '020 and '030 + */ + clrl %d0 + clrl %d1 + + is_not_040_or_060(L(save_cachetype)) + + /* + * '040 or '060 + * d1 := cacheable write-through + * NOTE: The 68040 manual strongly recommends non-cached for MMU tables, + * but we have been using write-through since at least 2.0.29 so I + * guess it is OK. + */ +#ifdef CONFIG_060_WRITETHROUGH + /* + * If this is a 68060 board using drivers with cache coherency + * problems, then supervisor memory accesses need to be write-through + * also; otherwise, we want copyback. + */ + + is_not_060(1f) + movel #_PAGE_CACHE040W,%d0 + jra L(save_cachetype) +#endif /* CONFIG_060_WRITETHROUGH */ +1: + movew #_PAGE_CACHE040,%d0 + + movel #_PAGE_CACHE040W,%d1 + +L(save_cachetype): + /* Save cache mode for supervisor mode and page tables + */ + lea %pc@(m68k_supervisor_cachemode),%a0 + movel %d0,%a0@ + lea %pc@(m68k_pgtable_cachemode),%a0 + movel %d1,%a0@ + +/* + * raise interrupt level + */ + movew #0x2700,%sr + +/* + If running on an Atari, determine the I/O base of the + serial port and test if we are running on a Medusa or Hades. + This test is necessary here, because on the Hades the serial + port is only accessible in the high I/O memory 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 Afterburner040 for the Falcon has the + same behaviour (0x0..0x7 are no ROM shadow). So we have to do + another test to distinguish 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. + + The test for the Hades is done by reading address 0xb0000000. This + should give a bus error on the Medusa. + */ + +#ifdef CONFIG_ATARI + is_not_atari(L(notypetest)) + + /* get special machine type (Medusa/Hades/AB40) */ + moveq #0,%d3 /* default if tag doesn't exist */ + get_bi_record BI_ATARI_MCH_TYPE + tstl %d0 + jbmi 1f + movel %a0@,%d3 + lea %pc@(atari_mch_type),%a0 + movel %d3,%a0@ +1: + /* On the Hades, the iobase must be set up before opening the + * serial port. There are no I/O regs at 0x00ffxxxx at all. */ + moveq #0,%d0 + cmpl #ATARI_MACH_HADES,%d3 + jbne 1f + movel #0xff000000,%d0 /* Hades I/O base addr: 0xff000000 */ +1: lea %pc@(L(iobase)),%a0 + movel %d0,%a0@ + +L(notypetest): +#endif + +#ifdef CONFIG_VME + is_mvme147(L(getvmetype)) + is_bvme6000(L(getvmetype)) + is_not_mvme16x(L(gvtdone)) + + /* See if the loader has specified the BI_VME_TYPE tag. Recent + * versions of VMELILO and TFTPLILO do this. We have to do this + * early so we know how to handle console output. If the tag + * doesn't exist then we use the Bug for output on MVME16x. + */ +L(getvmetype): + get_bi_record BI_VME_TYPE + tstl %d0 + jbmi 1f + movel %a0@,%d3 + lea %pc@(vme_brdtype),%a0 + movel %d3,%a0@ +1: +#ifdef CONFIG_MVME16x + is_not_mvme16x(L(gvtdone)) + + /* Need to get the BRD_ID info to differentiate between 162, 167, + * etc. This is available as a BI_VME_BRDINFO tag with later + * versions of VMELILO and TFTPLILO, otherwise we call the Bug. + */ + get_bi_record BI_VME_BRDINFO + tstl %d0 + jpl 1f + + /* Get pointer to board ID data from Bug */ + movel %d2,%sp@- + trap #15 + .word 0x70 /* trap 0x70 - .BRD_ID */ + movel %sp@+,%a0 +1: + lea %pc@(mvme_bdid),%a1 + /* Structure is 32 bytes long */ + movel %a0@+,%a1@+ + movel %a0@+,%a1@+ + movel %a0@+,%a1@+ + movel %a0@+,%a1@+ + movel %a0@+,%a1@+ + movel %a0@+,%a1@+ + movel %a0@+,%a1@+ + movel %a0@+,%a1@+ +#endif + +L(gvtdone): + +#endif + +#ifdef CONFIG_HP300 + is_not_hp300(L(nothp)) + + /* Get the address of the UART for serial debugging */ + get_bi_record BI_HP300_UART_ADDR + tstl %d0 + jbmi 1f + movel %a0@,%d3 + lea %pc@(L(uartbase)),%a0 + movel %d3,%a0@ + get_bi_record BI_HP300_UART_SCODE + tstl %d0 + jbmi 1f + movel %a0@,%d3 + lea %pc@(L(uart_scode)),%a0 + movel %d3,%a0@ +1: +L(nothp): +#endif + +/* + * Initialize serial port + */ + jbsr L(serial_init) + +/* + * Initialize console + */ +#ifdef CONFIG_MAC + is_not_mac(L(nocon)) +#ifdef CONSOLE + console_init +#ifdef CONSOLE_PENGUIN + console_put_penguin +#endif /* CONSOLE_PENGUIN */ + console_put_stats +#endif /* CONSOLE */ +L(nocon): +#endif /* CONFIG_MAC */ + + + putc '\n' + putc 'A' + leds 0x2 + dputn %pc@(L(cputype)) + dputn %pc@(m68k_supervisor_cachemode) + dputn %pc@(m68k_pgtable_cachemode) + dputc '\n' + +/* + * Save physical start address of kernel + */ + lea %pc@(L(phys_kernel_start)),%a0 + lea %pc@(_stext),%a1 + subl #_stext,%a1 + addl #PAGE_OFFSET,%a1 + movel %a1,%a0@ + + putc 'B' + + leds 0x4 + +/* + * mmu_init + * + * This block of code does what's necessary to map in the various kinds + * of machines for execution of Linux. + * First map the first 4 MB of kernel code & data + */ + + mmu_map #PAGE_OFFSET,%pc@(L(phys_kernel_start)),#4*1024*1024,\ + %pc@(m68k_supervisor_cachemode) + + putc 'C' + +#ifdef CONFIG_AMIGA + +L(mmu_init_amiga): + + is_not_amiga(L(mmu_init_not_amiga)) +/* + * mmu_init_amiga + */ + + putc 'D' + + is_not_040_or_060(1f) + + /* + * 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000 + */ + mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S + /* + * Map the Zorro III I/O space with transparent translation + * for frame buffer memory etc. + */ + mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE_S + + jbra L(mmu_init_done) + +1: + /* + * 030: Map the 32Meg range physical 0x0 upto logical 0x8000.0000 + */ + mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030 + mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030 + + jbra L(mmu_init_done) + +L(mmu_init_not_amiga): +#endif + +#ifdef CONFIG_ATARI + +L(mmu_init_atari): + + is_not_atari(L(mmu_init_not_atari)) + + putc 'E' + +/* 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. + + On the Hades all I/O registers are only accessible in the high + area. +*/ + + /* I/O base addr for non-Medusa, non-Hades: 0x00000000 */ + moveq #0,%d0 + movel %pc@(atari_mch_type),%d3 + cmpl #ATARI_MACH_MEDUSA,%d3 + jbeq 2f + cmpl #ATARI_MACH_HADES,%d3 + jbne 1f +2: movel #0xff000000,%d0 /* Medusa/Hades base addr: 0xff000000 */ +1: movel %d0,%d3 + + is_040_or_060(L(spata68040)) + + /* Map everything non-cacheable, though not all parts really + * need to disable caches (crucial only for 0xff8000..0xffffff + * (standard I/O) and 0xf00000..0xf3ffff (IDE)). The remainder + * isn't really used, except for sometimes peeking into the + * ROMs (mirror at phys. 0x0), so caching isn't necessary for + * this. */ + mmu_map #0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE030 + + jbra L(mmu_init_done) + +L(spata68040): + + mmu_map #0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE_S + + jbra L(mmu_init_done) + +L(mmu_init_not_atari): +#endif + +#ifdef CONFIG_Q40 + is_not_q40(L(notq40)) + /* + * add transparent mapping for 0xff00 0000 - 0xffff ffff + * non-cached serialized etc.. + * this includes master chip, DAC, RTC and ISA ports + * 0xfe000000-0xfeffffff is for screen and ROM + */ + + putc 'Q' + + mmu_map_tt #0,#0xfe000000,#0x01000000,#_PAGE_CACHE040W + mmu_map_tt #1,#0xff000000,#0x01000000,#_PAGE_NOCACHE_S + + jbra L(mmu_init_done) + +L(notq40): +#endif + +#ifdef CONFIG_HP300 + is_not_hp300(L(nothp300)) + + /* On the HP300, we map the ROM, INTIO and DIO regions (phys. 0x00xxxxxx) + * by mapping 32MB (on 020/030) or 16 MB (on 040) from 0xf0xxxxxx -> 0x00xxxxxx). + * The ROM mapping is needed because the LEDs are mapped there too. + */ + + is_040(1f) + + /* + * 030: Map the 32Meg range physical 0x0 upto logical 0xf000.0000 + */ + mmu_map #0xf0000000,#0,#0x02000000,#_PAGE_NOCACHE030 + + jbra L(mmu_init_done) + +1: + /* + * 040: Map the 16Meg range physical 0x0 upto logical 0xf000.0000 + */ + mmu_map #0xf0000000,#0,#0x01000000,#_PAGE_NOCACHE_S + + jbra L(mmu_init_done) + +L(nothp300): +#endif /* CONFIG_HP300 */ + +#ifdef CONFIG_MVME147 + + is_not_mvme147(L(not147)) + + /* + * On MVME147 we have already created kernel page tables for + * 4MB of RAM at address 0, so now need to do a transparent + * mapping of the top of memory space. Make it 0.5GByte for now, + * so we can access on-board i/o areas. + */ + + mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE030 + + jbra L(mmu_init_done) + +L(not147): +#endif /* CONFIG_MVME147 */ + +#ifdef CONFIG_MVME16x + + is_not_mvme16x(L(not16x)) + + /* + * On MVME16x we have already created kernel page tables for + * 4MB of RAM at address 0, so now need to do a transparent + * mapping of the top of memory space. Make it 0.5GByte for now. + * Supervisor only access, so transparent mapping doesn't + * clash with User code virtual address space. + * this covers IO devices, PROM and SRAM. The PROM and SRAM + * mapping is needed to allow 167Bug to run. + * IO is in the range 0xfff00000 to 0xfffeffff. + * PROM is 0xff800000->0xffbfffff and SRAM is + * 0xffe00000->0xffe1ffff. + */ + + mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S + + jbra L(mmu_init_done) + +L(not16x): +#endif /* CONFIG_MVME162 | CONFIG_MVME167 */ + +#ifdef CONFIG_BVME6000 + + is_not_bvme6000(L(not6000)) + + /* + * On BVME6000 we have already created kernel page tables for + * 4MB of RAM at address 0, so now need to do a transparent + * mapping of the top of memory space. Make it 0.5GByte for now, + * so we can access on-board i/o areas. + * Supervisor only access, so transparent mapping doesn't + * clash with User code virtual address space. + */ + + mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S + + jbra L(mmu_init_done) + +L(not6000): +#endif /* CONFIG_BVME6000 */ + +/* + * mmu_init_mac + * + * The Macintosh mappings are less clear. + * + * Even as of this writing, it is unclear how the + * Macintosh mappings will be done. However, as + * the first author of this code I'm proposing the + * following model: + * + * Map the kernel (that's already done), + * Map the I/O (on most machines that's the + * 0x5000.0000 ... 0x5300.0000 range, + * Map the video frame buffer using as few pages< |