/* SPDX-License-Identifier: GPL-2.0-or-later1** -*- mode: asm -*-2**3** head.S -- This file contains the initial boot code for the4** Linux/68k kernel.5**6** Copyright 1993 by Hamish Macdonald7**8** 68040 fixes by Michael Rausch9** 68060 fixes by Roman Hodek10** MMU cleanup by Randy Thelen11** Final MMU cleanup by Roman Zippel12**13** Atari support by Andreas Schwab, using ideas of Robert de Vries14** and Bjoern Brauel15** VME Support by Richard Hirst16**17** 94/11/14 Andreas Schwab: put kernel at PAGESIZE18** 94/11/18 Andreas Schwab: remove identity mapping of STRAM for Atari19** ++ Bjoern & Roman: ATARI-68040 support for the Medusa20** 95/11/18 Richard Hirst: Added MVME166 support21** 96/04/26 Guenther Kelleter: fixed identity mapping for Falcon with22** Magnum- and FX-alternate ram23** 98/04/25 Phil Blundell: added HP300 support24** 1998/08/30 David Kilzer: Added support for font_desc structures25** for linux-2.1.11526** 1999/02/11 Richard Zidlicky: added Q40 support (initial version 99/01/01)27** 2004/05/13 Kars de Jong: Finalised HP300 support28*/2930/*31* Linux startup code.32*33* At this point, the boot loader has:34* Disabled interrupts35* Disabled caches36* Put us in supervisor state.37*38* The kernel setup code takes the following steps:39* . Raise interrupt level40* . Set up initial kernel memory mapping.41* . This sets up a mapping of the 4M of memory the kernel is located in.42* . It also does a mapping of any initial machine specific areas.43* . Enable the MMU44* . Enable cache memories45* . Jump to kernel startup46*47* Much of the file restructuring was to accomplish:48* 1) Remove register dependency through-out the file.49* 2) Increase use of subroutines to perform functions50* 3) Increase readability of the code51*52* Of course, readability is a subjective issue, so it will never be53* argued that that goal was accomplished. It was merely a goal.54* A key way to help make code more readable is to give good55* documentation. So, the first thing you will find is exhaustive56* write-ups on the structure of the file, and the features of the57* functional subroutines.58*59* General Structure:60* ------------------61* Without a doubt the single largest chunk of head.S is spent62* mapping the kernel and I/O physical space into the logical range63* for the kernel.64* There are new subroutines and data structures to make MMU65* support cleaner and easier to understand.66* First, you will find a routine call "mmu_map" which maps67* a logical to a physical region for some length given a cache68* type on behalf of the caller. This routine makes writing the69* actual per-machine specific code very simple.70* A central part of the code, but not a subroutine in itself,71* is the mmu_init code which is broken down into mapping the kernel72* (the same for all machines) and mapping machine-specific I/O73* regions.74* Also, there will be a description of engaging the MMU and75* caches.76* You will notice that there is a chunk of code which77* can emit the entire MMU mapping of the machine. This is present78* only in debug modes and can be very helpful.79* Further, there is a new console driver in head.S that is80* also only engaged in debug mode. Currently, it's only supported81* on the Macintosh class of machines. However, it is hoped that82* others will plug-in support for specific machines.83*84* ######################################################################85*86* mmu_map87* -------88* mmu_map was written for two key reasons. First, it was clear89* that it was very difficult to read the previous code for mapping90* regions of memory. Second, the Macintosh required such extensive91* memory allocations that it didn't make sense to propagate the92* existing code any further.93* mmu_map requires some parameters:94*95* mmu_map (logical, physical, length, cache_type)96*97* While this essentially describes the function in the abstract, you'll98* find more indepth description of other parameters at the implementation site.99*100* mmu_get_root_table_entry101* ------------------------102* mmu_get_ptr_table_entry103* -----------------------104* mmu_get_page_table_entry105* ------------------------106*107* These routines are used by other mmu routines to get a pointer into108* a table, if necessary a new table is allocated. These routines are working109* basically like pmd_alloc() and pte_alloc() in <asm/pgtable.h>. The root110* table needs of course only to be allocated once in mmu_get_root_table_entry,111* so that here also some mmu specific initialization is done. The second page112* at the start of the kernel (the first page is unmapped later) is used for113* the kernel_pg_dir. It must be at a position known at link time (as it's used114* to initialize the init task struct) and since it needs special cache115* settings, it's the easiest to use this page, the rest of the page is used116* for further pointer tables.117* mmu_get_page_table_entry allocates always a whole page for page tables, this118* means 1024 pages and so 4MB of memory can be mapped. It doesn't make sense119* to manage page tables in smaller pieces as nearly all mappings have that120* size.121*122* ######################################################################123*124*125* ######################################################################126*127* mmu_engage128* ----------129* Thanks to a small helping routine enabling the mmu got quite simple130* and there is only one way left. mmu_engage makes a complete a new mapping131* that only includes the absolute necessary to be able to jump to the final132* position and to restore the original mapping.133* As this code doesn't need a transparent translation register anymore this134* means all registers are free to be used by machines that needs them for135* other purposes.136*137* ######################################################################138*139* mmu_print140* ---------141* This algorithm will print out the page tables of the system as142* appropriate for an 030 or an 040. This is useful for debugging purposes143* and as such is enclosed in #ifdef MMU_PRINT/#endif clauses.144*145* ######################################################################146*147* console_init148* ------------149* The console is also able to be turned off. The console in head.S150* is specifically for debugging and can be very useful. It is surrounded by151* #ifdef / #endif clauses so it doesn't have to ship in known-good152* kernels. It's basic algorithm is to determine the size of the screen153* (in height/width and bit depth) and then use that information for154* displaying an 8x8 font or an 8x16 (widthxheight). I prefer the 8x8 for155* debugging so I can see more good data. But it was trivial to add support156* for both fonts, so I included it.157* Also, the algorithm for plotting pixels is abstracted so that in158* theory other platforms could add support for different kinds of frame159* buffers. This could be very useful.160*161* console_put_penguin162* -------------------163* An important part of any Linux bring up is the penguin and there's164* nothing like getting the Penguin on the screen! This algorithm will work165* on any machine for which there is a console_plot_pixel.166*167* console_scroll168* --------------169* My hope is that the scroll algorithm does the right thing on the170* various platforms, but it wouldn't be hard to add the test conditions171* and new code if it doesn't.172*173* console_putc174* -------------175*176* ######################################################################177*178* Register usage has greatly simplified within head.S. Every subroutine179* saves and restores all registers that it modifies (except it returns a180* value in there of course). So the only register that needs to be initialized181* is the stack pointer.182* All other init code and data is now placed in the init section, so it will183* be automatically freed at the end of the kernel initialization.184*185* ######################################################################186*187* options188* -------189* There are many options available in a build of this file. I've190* taken the time to describe them here to save you the time of searching191* for them and trying to understand what they mean.192*193* CONFIG_xxx: These are the obvious machine configuration defines created194* during configuration. These are defined in autoconf.h.195*196* CONSOLE_DEBUG: Only supports a Mac frame buffer but could easily be197* extended to support other platforms.198*199* TEST_MMU: This is a test harness for running on any given machine but200* getting an MMU dump for another class of machine. The classes of machines201* that can be tested are any of the makes (Atari, Amiga, Mac, VME, etc.)202* and any of the models (030, 040, 060, etc.).203*204* NOTE: TEST_MMU is NOT permanent! It is scheduled to be removed205* When head.S boots on Atari, Amiga, Macintosh, and VME206* machines. At that point the underlying logic will be207* believed to be solid enough to be trusted, and TEST_MMU208* can be dropped. Do note that that will clean up the209* head.S code significantly as large blocks of #if/#else210* clauses can be removed.211*212* MMU_NOCACHE_KERNEL: On the Macintosh platform there was an inquiry into213* determing why devices don't appear to work. A test case was to remove214* the cacheability of the kernel bits.215*216* MMU_PRINT: There is a routine built into head.S that can display the217* MMU data structures. It outputs its result through the serial_putc218* interface. So where ever that winds up driving data, that's where the219* mmu struct will appear.220*221* SERIAL_DEBUG: There are a series of putc() macro statements222* scattered through out the code to give progress of status to the223* person sitting at the console. This constant determines whether those224* are used.225*226* DEBUG: This is the standard DEBUG flag that can be set for building227* the kernel. It has the effect adding additional tests into228* the code.229*230* FONT_6x11:231* FONT_8x8:232* FONT_8x16:233* In theory these could be determined at run time or handed234* over by the booter. But, let's be real, it's a fine hard235* coded value. (But, you will notice the code is run-time236* flexible!) A pointer to the font's struct font_desc237* is kept locally in Lconsole_font. It is used to determine238* font size information dynamically.239*240* Atari constants:241* USE_PRINTER: Use the printer port for serial debug.242* USE_SCC_B: Use the SCC port A (Serial2) for serial debug.243* USE_SCC_A: Use the SCC port B (Modem2) for serial debug.244* USE_MFP: Use the ST-MFP port (Modem1) for serial debug.245*246* Macintosh constants:247* MAC_USE_SCC_A: Use SCC port A (modem) for serial debug.248* MAC_USE_SCC_B: Use SCC port B (printer) for serial debug.249*/250251#include <linux/linkage.h>252#include <linux/init.h>253#include <linux/pgtable.h>254#include <asm/bootinfo.h>255#include <asm/bootinfo-amiga.h>256#include <asm/bootinfo-atari.h>257#include <asm/bootinfo-hp300.h>258#include <asm/bootinfo-mac.h>259#include <asm/bootinfo-q40.h>260#include <asm/bootinfo-virt.h>261#include <asm/bootinfo-vme.h>262#include <asm/setup.h>263#include <asm/entry.h>264#include <asm/page.h>265#include <asm/asm-offsets.h>266#ifdef CONFIG_MAC267# include <asm/machw.h>268#endif269270#ifdef CONFIG_EARLY_PRINTK271# define SERIAL_DEBUG272# if defined(CONFIG_MAC) && defined(CONFIG_FONT_SUPPORT)273# define CONSOLE_DEBUG274# endif275#endif276277#undef MMU_PRINT278#undef MMU_NOCACHE_KERNEL279#undef DEBUG280281/*282* For the head.S console, there are three supported fonts, 6x11, 8x16 and 8x8.283* The 8x8 font is harder to read but fits more on the screen.284*/285#define FONT_8x8 /* default */286/* #define FONT_8x16 */ /* 2nd choice */287/* #define FONT_6x11 */ /* 3rd choice */288289.globl kernel_pg_dir290.globl availmem291.globl m68k_init_mapped_size292.globl m68k_pgtable_cachemode293.globl m68k_supervisor_cachemode294#ifdef CONFIG_MVME16x295.globl mvme_bdid296#endif297#ifdef CONFIG_Q40298.globl q40_mem_cptr299#endif300301CPUTYPE_040 = 1 /* indicates an 040 */302CPUTYPE_060 = 2 /* indicates an 060 */303CPUTYPE_0460 = 3 /* if either above are set, this is set */304CPUTYPE_020 = 4 /* indicates an 020 */305306/* Translation control register */307TC_ENABLE = 0x8000308TC_PAGE8K = 0x4000309TC_PAGE4K = 0x0000310311/* Transparent translation registers */312TTR_ENABLE = 0x8000 /* enable transparent translation */313TTR_ANYMODE = 0x4000 /* user and kernel mode access */314TTR_KERNELMODE = 0x2000 /* only kernel mode access */315TTR_USERMODE = 0x0000 /* only user mode access */316TTR_CI = 0x0400 /* inhibit cache */317TTR_RW = 0x0200 /* read/write mode */318TTR_RWM = 0x0100 /* read/write mask */319TTR_FCB2 = 0x0040 /* function code base bit 2 */320TTR_FCB1 = 0x0020 /* function code base bit 1 */321TTR_FCB0 = 0x0010 /* function code base bit 0 */322TTR_FCM2 = 0x0004 /* function code mask bit 2 */323TTR_FCM1 = 0x0002 /* function code mask bit 1 */324TTR_FCM0 = 0x0001 /* function code mask bit 0 */325326/* Cache Control registers */327CC6_ENABLE_D = 0x80000000 /* enable data cache (680[46]0) */328CC6_FREEZE_D = 0x40000000 /* freeze data cache (68060) */329CC6_ENABLE_SB = 0x20000000 /* enable store buffer (68060) */330CC6_PUSH_DPI = 0x10000000 /* disable CPUSH invalidation (68060) */331CC6_HALF_D = 0x08000000 /* half-cache mode for data cache (68060) */332CC6_ENABLE_B = 0x00800000 /* enable branch cache (68060) */333CC6_CLRA_B = 0x00400000 /* clear all entries in branch cache (68060) */334CC6_CLRU_B = 0x00200000 /* clear user entries in branch cache (68060) */335CC6_ENABLE_I = 0x00008000 /* enable instruction cache (680[46]0) */336CC6_FREEZE_I = 0x00004000 /* freeze instruction cache (68060) */337CC6_HALF_I = 0x00002000 /* half-cache mode for instruction cache (68060) */338CC3_ALLOC_WRITE = 0x00002000 /* write allocate mode(68030) */339CC3_ENABLE_DB = 0x00001000 /* enable data burst (68030) */340CC3_CLR_D = 0x00000800 /* clear data cache (68030) */341CC3_CLRE_D = 0x00000400 /* clear entry in data cache (68030) */342CC3_FREEZE_D = 0x00000200 /* freeze data cache (68030) */343CC3_ENABLE_D = 0x00000100 /* enable data cache (68030) */344CC3_ENABLE_IB = 0x00000010 /* enable instruction burst (68030) */345CC3_CLR_I = 0x00000008 /* clear instruction cache (68030) */346CC3_CLRE_I = 0x00000004 /* clear entry in instruction cache (68030) */347CC3_FREEZE_I = 0x00000002 /* freeze instruction cache (68030) */348CC3_ENABLE_I = 0x00000001 /* enable instruction cache (68030) */349350/* Miscellaneous definitions */351PAGESIZE = 4096352PAGESHIFT = 12353354ROOT_TABLE_SIZE = 128355PTR_TABLE_SIZE = 128356PAGE_TABLE_SIZE = 64357ROOT_INDEX_SHIFT = 25358PTR_INDEX_SHIFT = 18359PAGE_INDEX_SHIFT = 12360361#ifdef DEBUG362/* When debugging use readable names for labels */363#ifdef __STDC__364#define L(name) .head.S.##name365#else366#define L(name) .head.S./**/name367#endif368#else369#ifdef __STDC__370#define L(name) .L##name371#else372#define L(name) .L/**/name373#endif374#endif375376/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */377#ifndef __INITDATA378#define __INITDATA .data379#define __FINIT .previous380#endif381382/* Several macros to make the writing of subroutines easier:383* - func_start marks the beginning of the routine which setups the frame384* register and saves the registers, it also defines another macro385* to automatically restore the registers again.386* - func_return marks the end of the routine and simply calls the prepared387* macro to restore registers and jump back to the caller.388* - func_define generates another macro to automatically put arguments389* onto the stack call the subroutine and cleanup the stack again.390*/391392/* Within subroutines these macros can be used to access the arguments393* on the stack. With STACK some allocated memory on the stack can be394* accessed and ARG0 points to the return address (used by mmu_engage).395*/396#define STACK %a6@(stackstart)397#define ARG0 %a6@(4)398#define ARG1 %a6@(8)399#define ARG2 %a6@(12)400#define ARG3 %a6@(16)401#define ARG4 %a6@(20)402403.macro func_start name,saveregs,stack=0404L(\name):405linkw %a6,#-\stack406moveml \saveregs,%sp@-407.set stackstart,-\stack408409.macro func_return_\name410moveml %sp@+,\saveregs411unlk %a6412rts413.endm414.endm415416.macro func_return name417func_return_\name418.endm419420.macro func_call name421jbsr L(\name)422.endm423424.macro move_stack nr,arg1,arg2,arg3,arg4425.if \nr426move_stack "(\nr-1)",\arg2,\arg3,\arg4427movel \arg1,%sp@-428.endif429.endm430431.macro func_define name,nr=0432.macro \name arg1,arg2,arg3,arg4433move_stack \nr,\arg1,\arg2,\arg3,\arg4434func_call \name435.if \nr436lea %sp@(\nr*4),%sp437.endif438.endm439.endm440441func_define mmu_map,4442func_define mmu_map_tt,4443func_define mmu_fixup_page_mmu_cache,1444func_define mmu_temp_map,2445func_define mmu_engage446func_define mmu_get_root_table_entry,1447func_define mmu_get_ptr_table_entry,2448func_define mmu_get_page_table_entry,2449func_define mmu_print450func_define get_new_page451#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)452func_define set_leds453#endif454455.macro mmu_map_eq arg1,arg2,arg3456mmu_map \arg1,\arg1,\arg2,\arg3457.endm458459.macro get_bi_record record460pea \record461func_call get_bi_record462addql #4,%sp463.endm464465func_define serial_putc,1466func_define console_putc,1467468func_define console_init469func_define console_put_penguin470func_define console_plot_pixel,3471func_define console_scroll472473.macro putc ch474#if defined(CONSOLE_DEBUG) || defined(SERIAL_DEBUG)475pea \ch476#endif477#ifdef CONSOLE_DEBUG478func_call console_putc479#endif480#ifdef SERIAL_DEBUG481func_call serial_putc482#endif483#if defined(CONSOLE_DEBUG) || defined(SERIAL_DEBUG)484addql #4,%sp485#endif486.endm487488.macro dputc ch489#ifdef DEBUG490putc \ch491#endif492.endm493494func_define putn,1495496.macro dputn nr497#ifdef DEBUG498putn \nr499#endif500.endm501502.macro puts string503#if defined(CONSOLE_DEBUG) || defined(SERIAL_DEBUG)504__INITDATA505.Lstr\@:506.string "\string"507__FINIT508pea %pc@(.Lstr\@)509func_call puts510addql #4,%sp511#endif512.endm513514.macro dputs string515#ifdef DEBUG516puts "\string"517#endif518.endm519520#define is_not_amiga(lab) cmpl &MACH_AMIGA,%pc@(m68k_machtype); jne lab521#define is_not_atari(lab) cmpl &MACH_ATARI,%pc@(m68k_machtype); jne lab522#define is_not_mac(lab) cmpl &MACH_MAC,%pc@(m68k_machtype); jne lab523#define is_not_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jne lab524#define is_not_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jne lab525#define is_not_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jne lab526#define is_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jeq lab527#define is_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jeq lab528#define is_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jeq lab529#define is_not_hp300(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); jne lab530#define is_not_apollo(lab) cmpl &MACH_APOLLO,%pc@(m68k_machtype); jne lab531#define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab532#define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab533#define is_not_virt(lab) cmpl &MACH_VIRT,%pc@(m68k_machtype); jne lab534535#define hasnt_leds(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); \536jeq 42f; \537cmpl &MACH_APOLLO,%pc@(m68k_machtype); \538jne lab ;\53942:\540541#define is_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jne lab542#define is_not_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jeq lab543#define is_040(lab) btst &CPUTYPE_040,%pc@(L(cputype)+3); jne lab544#define is_060(lab) btst &CPUTYPE_060,%pc@(L(cputype)+3); jne lab545#define is_not_060(lab) btst &CPUTYPE_060,%pc@(L(cputype)+3); jeq lab546#define is_020(lab) btst &CPUTYPE_020,%pc@(L(cputype)+3); jne lab547#define is_not_020(lab) btst &CPUTYPE_020,%pc@(L(cputype)+3); jeq lab548549/* On the HP300 we use the on-board LEDs for debug output before550the console is running. Writing a 1 bit turns the corresponding LED551_off_ - on the 340 bit 7 is towards the back panel of the machine. */552.macro leds mask553#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)554hasnt_leds(.Lled\@)555pea \mask556func_call set_leds557addql #4,%sp558.Lled\@:559#endif560.endm561562__HEAD563ENTRY(_stext)564/*565* Version numbers of the bootinfo interface566* The area from _stext to _start will later be used as kernel pointer table567*/568bras 1f /* Jump over bootinfo version numbers */569570.long BOOTINFOV_MAGIC571.long MACH_AMIGA, AMIGA_BOOTI_VERSION572.long MACH_ATARI, ATARI_BOOTI_VERSION573.long MACH_MVME147, MVME147_BOOTI_VERSION574.long MACH_MVME16x, MVME16x_BOOTI_VERSION575.long MACH_BVME6000, BVME6000_BOOTI_VERSION576.long MACH_MAC, MAC_BOOTI_VERSION577.long MACH_Q40, Q40_BOOTI_VERSION578.long MACH_HP300, HP300_BOOTI_VERSION579.long 05801: jra __start581582.equ kernel_pg_dir,_stext583584.equ .,_stext+PAGESIZE585586ENTRY(_start)587jra __start588__INIT589ENTRY(__start)590/*591* Setup initial stack pointer592*/593lea %pc@(_stext),%sp594595/*596* Record the CPU and machine type.597*/598get_bi_record BI_MACHTYPE599lea %pc@(m68k_machtype),%a1600movel %a0@,%a1@601602get_bi_record BI_FPUTYPE603lea %pc@(m68k_fputype),%a1604movel %a0@,%a1@605606get_bi_record BI_MMUTYPE607lea %pc@(m68k_mmutype),%a1608movel %a0@,%a1@609610get_bi_record BI_CPUTYPE611lea %pc@(m68k_cputype),%a1612movel %a0@,%a1@613614leds 0x1615616#ifdef CONFIG_MAC617/*618* For Macintosh, we need to determine the display parameters early (at least619* while debugging it).620*/621622is_not_mac(L(test_notmac))623624get_bi_record BI_MAC_VADDR625lea %pc@(L(mac_videobase)),%a1626movel %a0@,%a1@627628get_bi_record BI_MAC_VDEPTH629lea %pc@(L(mac_videodepth)),%a1630movel %a0@,%a1@631632get_bi_record BI_MAC_VDIM633lea %pc@(L(mac_dimensions)),%a1634movel %a0@,%a1@635636get_bi_record BI_MAC_VROW637lea %pc@(L(mac_rowbytes)),%a1638movel %a0@,%a1@639640get_bi_record BI_MAC_SCCBASE641lea %pc@(L(mac_sccbase)),%a1642movel %a0@,%a1@643644L(test_notmac):645#endif /* CONFIG_MAC */646647#ifdef CONFIG_VIRT648is_not_virt(L(test_notvirt))649650get_bi_record BI_VIRT_GF_TTY_BASE651lea %pc@(L(virt_gf_tty_base)),%a1652movel %a0@,%a1@653L(test_notvirt):654#endif /* CONFIG_VIRT */655656/*657* There are ultimately two pieces of information we want for all kinds of658* processors CpuType and CacheBits. The CPUTYPE was passed in from booter659* and is converted here from a booter type definition to a separate bit660* number which allows for the standard is_0x0 macro tests.661*/662movel %pc@(m68k_cputype),%d0663/*664* Assume it's an 030665*/666clrl %d1667668/*669* Test the BootInfo cputype for 060670*/671btst #CPUB_68060,%d0672jeq 1f673bset #CPUTYPE_060,%d1674bset #CPUTYPE_0460,%d1675jra 3f6761:677/*678* Test the BootInfo cputype for 040679*/680btst #CPUB_68040,%d0681jeq 2f682bset #CPUTYPE_040,%d1683bset #CPUTYPE_0460,%d1684jra 3f6852:686/*687* Test the BootInfo cputype for 020688*/689btst #CPUB_68020,%d0690jeq 3f691bset #CPUTYPE_020,%d1692jra 3f6933:694/*695* Record the cpu type696*/697lea %pc@(L(cputype)),%a0698movel %d1,%a0@699700/*701* NOTE:702*703* Now the macros are valid:704* is_040_or_060705* is_not_040_or_060706* is_040707* is_060708* is_not_060709*/710711/*712* Determine the cache mode for pages holding MMU tables713* and for supervisor mode, unused for '020 and '030714*/715clrl %d0716clrl %d1717718is_not_040_or_060(L(save_cachetype))719720/*721* '040 or '060722* d1 := cacheable write-through723* NOTE: The 68040 manual strongly recommends non-cached for MMU tables,724* but we have been using write-through since at least 2.0.29 so I725* guess it is OK.726*/727#ifdef CONFIG_060_WRITETHROUGH728/*729* If this is a 68060 board using drivers with cache coherency730* problems, then supervisor memory accesses need to be write-through731* also; otherwise, we want copyback.732*/733734is_not_060(1f)735movel #_PAGE_CACHE040W,%d0736jra L(save_cachetype)737#endif /* CONFIG_060_WRITETHROUGH */7381:739movew #_PAGE_CACHE040,%d0740741movel #_PAGE_CACHE040W,%d1742743L(save_cachetype):744/* Save cache mode for supervisor mode and page tables745*/746lea %pc@(m68k_supervisor_cachemode),%a0747movel %d0,%a0@748lea %pc@(m68k_pgtable_cachemode),%a0749movel %d1,%a0@750751/*752* raise interrupt level753*/754movew #0x2700,%sr755756/*757If running on an Atari, determine the I/O base of the758serial port and test if we are running on a Medusa or Hades.759This test is necessary here, because on the Hades the serial760port is only accessible in the high I/O memory area.761762The test whether it is a Medusa is done by writing to the byte at763phys. 0x0. This should result in a bus error on all other machines.764765...should, but doesn't. The Afterburner040 for the Falcon has the766same behaviour (0x0..0x7 are no ROM shadow). So we have to do767another test to distinguish Medusa and AB040. This is a768read attempt for 0x00ff82fe phys. that should bus error on a Falcon769(+AB040), but is in the range where the Medusa always asserts DTACK.770771The test for the Hades is done by reading address 0xb0000000. This772should give a bus error on the Medusa.773*/774775#ifdef CONFIG_ATARI776is_not_atari(L(notypetest))777778/* get special machine type (Medusa/Hades/AB40) */779moveq #0,%d3 /* default if tag doesn't exist */780get_bi_record BI_ATARI_MCH_TYPE781tstl %d0782jbmi 1f783movel %a0@,%d3784lea %pc@(atari_mch_type),%a0785movel %d3,%a0@7861:787/* On the Hades, the iobase must be set up before opening the788* serial port. There are no I/O regs at 0x00ffxxxx at all. */789moveq #0,%d0790cmpl #ATARI_MACH_HADES,%d3791jbne 1f792movel #0xff000000,%d0 /* Hades I/O base addr: 0xff000000 */7931: lea %pc@(L(iobase)),%a0794movel %d0,%a0@795796L(notypetest):797#endif798799#ifdef CONFIG_VME800is_mvme147(L(getvmetype))801is_bvme6000(L(getvmetype))802is_not_mvme16x(L(gvtdone))803804/* See if the loader has specified the BI_VME_TYPE tag. Recent805* versions of VMELILO and TFTPLILO do this. We have to do this806* early so we know how to handle console output. If the tag807* doesn't exist then we use the Bug for output on MVME16x.808*/809L(getvmetype):810get_bi_record BI_VME_TYPE811tstl %d0812jbmi 1f813movel %a0@,%d3814lea %pc@(vme_brdtype),%a0815movel %d3,%a0@8161:817#ifdef CONFIG_MVME16x818is_not_mvme16x(L(gvtdone))819820/* Need to get the BRD_ID info to differentiate between 162, 167,821* etc. This is available as a BI_VME_BRDINFO tag with later822* versions of VMELILO and TFTPLILO, otherwise we call the Bug.823*/824get_bi_record BI_VME_BRDINFO825tstl %d0826jpl 1f827828/* Get pointer to board ID data from Bug */829movel %d2,%sp@-830trap #15831.word 0x70 /* trap 0x70 - .BRD_ID */832movel %sp@+,%a08331:834lea %pc@(mvme_bdid),%a1835/* Structure is 32 bytes long */836movel %a0@+,%a1@+837movel %a0@+,%a1@+838movel %a0@+,%a1@+839movel %a0@+,%a1@+840movel %a0@+,%a1@+841movel %a0@+,%a1@+842movel %a0@+,%a1@+843movel %a0@+,%a1@+844#endif845846L(gvtdone):847848#endif849850#ifdef CONFIG_HP300851is_not_hp300(L(nothp))852853/* Get the address of the UART for serial debugging */854get_bi_record BI_HP300_UART_ADDR855tstl %d0856jbmi 1f857movel %a0@,%d3858lea %pc@(L(uartbase)),%a0859movel %d3,%a0@860get_bi_record BI_HP300_UART_SCODE861tstl %d0862jbmi 1f863movel %a0@,%d3864lea %pc@(L(uart_scode)),%a0865movel %d3,%a0@8661:867L(nothp):868#endif869870/*871* Initialize serial port872*/873jbsr L(serial_init)874875/*876* Initialize console877*/878#ifdef CONFIG_MAC879is_not_mac(L(nocon))880# ifdef CONSOLE_DEBUG881console_init882# ifdef CONFIG_LOGO883console_put_penguin884# endif /* CONFIG_LOGO */885# endif /* CONSOLE_DEBUG */886L(nocon):887#endif /* CONFIG_MAC */888889890putc '\n'891putc 'A'892leds 0x2893dputn %pc@(L(cputype))894dputn %pc@(m68k_supervisor_cachemode)895dputn %pc@(m68k_pgtable_cachemode)896dputc '\n'897898/*899* Save physical start address of kernel900*/901lea %pc@(L(phys_kernel_start)),%a0902lea %pc@(_stext),%a1903subl #_stext,%a1904addl #PAGE_OFFSET,%a1905movel %a1,%a0@906907putc 'B'908909leds 0x4910911/*912* mmu_init913*914* This block of code does what's necessary to map in the various kinds915* of machines for execution of Linux.916* First map the first 4, 8, or 16 MB of kernel code & data917*/918919get_bi_record BI_MEMCHUNK920movel %a0@(4),%d0921movel #16*1024*1024,%d1922cmpl %d0,%d1923jls 1f924lsrl #1,%d1925cmpl %d0,%d1926jls 1f927lsrl #1,%d19281:929lea %pc@(m68k_init_mapped_size),%a0930movel %d1,%a0@931mmu_map #PAGE_OFFSET,%pc@(L(phys_kernel_start)),%d1,\932%pc@(m68k_supervisor_cachemode)933934putc 'C'935936#ifdef CONFIG_AMIGA937938L(mmu_init_amiga):939940is_not_amiga(L(mmu_init_not_amiga))941/*942* mmu_init_amiga943*/944945putc 'D'946947is_not_040_or_060(1f)948949/*950* 040: Map the 16Meg range physical 0x0 up to logical 0x8000.0000951*/952mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S953/*954* Map the Zorro III I/O space with transparent translation955* for frame buffer memory etc.956*/957mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE_S958959jbra L(mmu_init_done)9609611:962/*963* 030: Map the 32Meg range physical 0x0 up to logical 0x8000.0000964*/965mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030966mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030967968jbra L(mmu_init_done)969970L(mmu_init_not_amiga):971#endif972973#ifdef CONFIG_ATARI974975L(mmu_init_atari):976977is_not_atari(L(mmu_init_not_atari))978979putc 'E'980981/* On the Atari, we map the I/O region (phys. 0x00ffxxxx) by mapping982the last 16 MB of virtual address space to the first 16 MB (i.e.9830xffxxxxxx -> 0x00xxxxxx). For this, an additional pointer table is984needed. I/O ranges are marked non-cachable.985986For the Medusa it is better to map the I/O region transparently987(i.e. 0xffxxxxxx -> 0xffxxxxxx), because some I/O registers are988accessible only in the high area.989990On the Hades all I/O registers are only accessible in the high991area.992*/993994/* I/O base addr for non-Medusa, non-Hades: 0x00000000 */995moveq #0,%d0996movel %pc@(atari_mch_type),%d3997cmpl #ATARI_MACH_MEDUSA,%d3998jbeq 2f999cmpl #ATARI_MACH_HADES,%d31000jbne 1f10012: movel #0xff000000,%d0 /* Medusa/Hades base addr: 0xff000000 */10021: movel %d0,%d310031004is_040_or_060(L(spata68040))10051006/* Map everything non-cacheable, though not all parts really1007* need to disable caches (crucial only for 0xff8000..0xffffff1008* (standard I/O) and 0xf00000..0xf3ffff (IDE)). The remainder1009* isn't really used, except for sometimes peeking into the1010* ROMs (mirror at phys. 0x0), so caching isn't necessary for1011* this. */1012mmu_map #0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE03010131014jbra L(mmu_init_done)10151016L(spata68040):10171018mmu_map #0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE_S10191020jbra L(mmu_init_done)10211022L(mmu_init_not_atari):1023#endif10241025#ifdef CONFIG_Q401026is_not_q40(L(notq40))1027/*1028* add transparent mapping for 0xff00 0000 - 0xffff ffff1029* non-cached serialized etc..1030* this includes master chip, DAC, RTC and ISA ports1031* 0xfe000000-0xfeffffff is for screen and ROM1032*/10331034putc 'Q'10351036mmu_map_tt #0,#0xfe000000,#0x01000000,#_PAGE_CACHE040W1037mmu_map_tt #1,#0xff000000,#0x01000000,#_PAGE_NOCACHE_S10381039jbra L(mmu_init_done)10401041L(notq40):1042#endif10431044#ifdef CONFIG_HP3001045is_not_hp300(L(nothp300))10461047/* On the HP300, we map the ROM, INTIO and DIO regions (phys. 0x00xxxxxx)1048* by mapping 32MB (on 020/030) or 16 MB (on 040) from 0xf0xxxxxx -> 0x00xxxxxx).1049* The ROM mapping is needed because the LEDs are mapped there too.1050*/10511052is_040(1f)10531054/*1055* 030: Map the 32Meg range physical 0x0 up to logical 0xf000.00001056*/1057mmu_map #0xf0000000,#0,#0x02000000,#_PAGE_NOCACHE03010581059jbra L(mmu_init_done)106010611:1062/*1063* 040: Map the 16Meg range physical 0x0 up to logical 0xf000.00001064*/1065mmu_map #0xf0000000,#0,#0x01000000,#_PAGE_NOCACHE_S10661067jbra L(mmu_init_done)10681069L(nothp300):1070#endif /* CONFIG_HP300 */10711072#ifdef CONFIG_MVME14710731074is_not_mvme147(L(not147))10751076/*1077* On MVME147 we have already created kernel page tables for1078* 4MB of RAM at address 0, so now need to do a transparent1079* mapping of the top of memory space. Make it 0.5GByte for now,1080* so we can access on-board i/o areas.1081*/10821083mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE03010841085jbra L(mmu_init_done)10861087L(not147):1088#endif /* CONFIG_MVME147 */10891090#ifdef CONFIG_MVME16x10911092is_not_mvme16x(L(not16x))10931094/*1095* On MVME16x we have already created kernel page tables for1096* 4MB of RAM at address 0, so now need to do a transparent1097* mapping of the top of memory space. Make it 0.5GByte for now.1098* Supervisor only access, so transparent mapping doesn't1099* clash with User code virtual address space.1100* this covers IO devices, PROM and SRAM. The PROM and SRAM1101* mapping is needed to allow 167Bug to run.1102* IO is in the range 0xfff00000 to 0xfffeffff.1103* PROM is 0xff800000->0xffbfffff and SRAM is1104* 0xffe00000->0xffe1ffff.1105*/11061107mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S11081109jbra L(mmu_init_done)11101111L(not16x):1112#endif /* CONFIG_MVME162 | CONFIG_MVME167 */11131114#ifdef CONFIG_BVME600011151116is_not_bvme6000(L(not6000))11171118/*1119* On BVME6000 we have already created kernel page tables for1120* 4MB of RAM at address 0, so now need to do a transparent1121* mapping of the top of memory space. Make it 0.5GByte for now,1122* so we can access on-board i/o areas.1123* Supervisor only access, so transparent mapping doesn't1124* clash with User code virtual address space.1125*/11261127mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S11281129jbra L(mmu_init_done)11301131L(not6000):1132#endif /* CONFIG_BVME6000 */11331134/*1135* mmu_init_mac1136*1137* The Macintosh mappings are less clear.1138*1139* Even as of this writing, it is unclear how the1140* Macintosh mappings will be done. However, as1141* the first author of this code I'm proposing the1142* following model:1143*1144* Map the kernel (that's already done),1145* Map the I/O (on most machines that's the1146* 0x5000.0000 ... 0x5300.0000 range,1147* Map the video frame buffer using as few pages1148* as absolutely (this requirement mostly stems from1149* the fact that when the frame buffer is at1150* 0x0000.0000 then we know there is valid RAM just1151* above the screen that we don't want to waste!).1152*1153* By the way, if the frame buffer is at 0x0000.00001154* then the Macintosh is known as an RBV based Mac.1155*1156* By the way 2, the code currently maps in a bunch of1157* regions. But I'd like to cut that out. (And move most1158* of the mappings up into the kernel proper ... or only1159* map what's necessary.)1160*/11611162#ifdef CONFIG_MAC11631164L(mmu_init_mac):11651166is_not_mac(L(mmu_init_not_mac))11671168putc 'F'11691170is_not_040_or_060(1f)11711172moveq #_PAGE_NOCACHE_S,%d31173jbra 2f11741:1175moveq #_PAGE_NOCACHE030,%d311762:1177/*1178* Mac Note: screen address of logical 0xF000.0000 -> <screen physical>1179* we simply map the 4MB that contains the videomem1180*/11811182movel #VIDEOMEMMASK,%d01183andl %pc@(L(mac_videobase)),%d011841185mmu_map #VIDEOMEMBASE,%d0,#VIDEOMEMSIZE,%d31186/* ROM from 4000 0000 to 4200 0000 (only for mac_reset()) */1187mmu_map_eq #0x40000000,#0x02000000,%d31188/* IO devices (incl. serial port) from 5000 0000 to 5300 0000 */1189mmu_map_eq #0x50000000,#0x03000000,%d31190/* Nubus slot space (video at 0xF0000000, rom at 0xF0F80000) */1191mmu_map_tt #1,#0xf8000000,#0x08000000,%d311921193jbra L(mmu_init_done)11941195L(mmu_init_not_mac):1196#endif11971198#ifdef CONFIG_SUN3X1199is_not_sun3x(L(notsun3x))12001201/* oh, the pain.. We're gonna want the prom code after1202* starting the MMU, so we copy the mappings, translating1203* from 8k -> 4k pages as we go.1204*/12051206/* copy maps from 0xfee00000 to 0xff000000 */1207movel #0xfee00000, %d01208moveq #ROOT_INDEX_SHIFT, %d11209lsrl %d1,%d01210mmu_get_root_table_entry %d012111212movel #0xfee00000, %d01213moveq #PTR_INDEX_SHIFT, %d11214lsrl %d1,%d01215andl #PTR_TABLE_SIZE-1, %d01216mmu_get_ptr_table_entry %a0,%d012171218movel #0xfee00000, %d01219moveq #PAGE_INDEX_SHIFT, %d11220lsrl %d1,%d01221andl #PAGE_TABLE_SIZE-1, %d01222mmu_get_page_table_entry %a0,%d012231224/* this is where the prom page table lives */1225movel 0xfefe00d4, %a11226movel %a1@, %a112271228movel #((0x200000 >> 13)-1), %d1122912301:1231movel %a1@+, %d31232movel %d3,%a0@+1233addl #0x1000,%d31234movel %d3,%a0@+12351236dbra %d1,1b12371238/* setup tt1 for I/O */1239mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S1240jbra L(mmu_init_done)12411242L(notsun3x):1243#endif12441245#ifdef CONFIG_VIRT1246is_not_virt(L(novirt))1247mmu_map_tt #1,#0xFF000000,#0x01000000,#_PAGE_NOCACHE_S1248jbra L(mmu_init_done)1249L(novirt):1250#endif12511252#ifdef CONFIG_APOLLO1253is_not_apollo(L(notapollo))12541255putc 'P'1256mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE03012571258L(notapollo):1259jbra L(mmu_init_done)1260#endif12611262L(mmu_init_done):12631264putc 'G'1265leds 0x812661267/*1268* mmu_fixup1269*1270* On the 040 class machines, all pages that are used for the1271* mmu have to be fixed up. According to Motorola, pages holding mmu1272* tables should be non-cacheable on a '040 and write-through on a1273* '060. But analysis of the reasons for this, and practical1274* experience, showed that write-through also works on a '040.1275*1276* Allocated memory so far goes from kernel_end to memory_start that1277* is used for all kind of tables, for that the cache attributes1278* are now fixed.1279*/1280L(mmu_fixup):12811282is_not_040_or_060(L(mmu_fixup_done))12831284#ifdef MMU_NOCACHE_KERNEL1285jbra L(mmu_fixup_done)1286#endif12871288/* first fix the page at the start of the kernel, that1289* contains also kernel_pg_dir.1290*/1291movel %pc@(L(phys_kernel_start)),%d01292subl #PAGE_OFFSET,%d01293lea %pc@(_stext),%a01294subl %d0,%a01295mmu_fixup_page_mmu_cache %a012961297movel %pc@(L(kernel_end)),%a01298subl %d0,%a01299movel %pc@(L(memory_start)),%a11300subl %d0,%a11301bra 2f13021:1303mmu_fixup_page_mmu_cache %a01304addw #PAGESIZE,%a013052:1306cmpl %a0,%a11307jgt 1b13081309L(mmu_fixup_done):13101311#ifdef MMU_PRINT1312mmu_print1313#endif13141315/*1316* mmu_engage1317*1318* This chunk of code performs the gruesome task of engaging the MMU.1319* The reason it's gruesome is because when the MMU becomes engaged it1320* maps logical addresses to physical addresses. The Program Counter1321* register is then passed through the MMU before the next instruction1322* is fetched (the instruction following the engage MMU instruction).1323* This may mean one of two things:1324* 1. The Program Counter falls within the logical address space of1325* the kernel of which there are two sub-possibilities:1326* A. The PC maps to the correct instruction (logical PC == physical1327* code location), or1328* B. The PC does not map through and the processor will read some1329* data (or instruction) which is not the logically next instr.1330* As you can imagine, A is good and B is bad.1331* Alternatively,1332* 2. The Program Counter does not map through the MMU. The processor1333* will take a Bus Error.1334* Clearly, 2 is bad.1335* It doesn't take a wiz kid to figure you want 1.A.1336* This code creates that possibility.1337* There are two possible 1.A. states (we now ignore the other above states):1338* A. The kernel is located at physical memory addressed the same as1339* the logical memory for the kernel, i.e., 0x01000.1340* B. The kernel is located some where else. e.g., 0x0400.00001341*1342* Under some conditions the Macintosh can look like A or B.1343* [A friend and I once noted that Apple hardware engineers should be1344* wacked twice each day: once when they show up at work (as in, Whack!,1345* "This is for the screwy hardware we know you're going to design today."),1346* and also at the end of the day (as in, Whack! "I don't know what1347* you designed today, but I'm sure it wasn't good."). -- rst]1348*1349* This code works on the following premise:1350* If the kernel start (%d5) is within the first 16 Meg of RAM,1351* then create a mapping for the kernel at logical 0x8000.0000 to1352* the physical location of the pc. And, create a transparent1353* translation register for the first 16 Meg. Then, after the MMU1354* is engaged, the PC can be moved up into the 0x8000.0000 range1355* and then the transparent translation can be turned off and then1356* the PC can jump to the correct logical location and it will be1357* home (finally). This is essentially the code that the Amiga used1358* to use. Now, it's generalized for all processors. Which means1359* that a fresh (but temporary) mapping has to be created. The mapping1360* is made in page 0 (an as of yet unused location -- except for the1361* stack!). This temporary mapping will only require 1 pointer table1362* and a single page table (it can map 256K).1363*1364* OK, alternatively, imagine that the Program Counter is not within1365* the first 16 Meg. Then, just use Transparent Translation registers1366* to do the right thing.1367*1368* Last, if _start is already at 0x01000, then there's nothing special1369* to do (in other words, in a degenerate case of the first case above,1370* do nothing).1371*1372* Let's do it.1373*1374*1375*/13761377putc 'H'13781379mmu_engage13801381/*1382* After this point no new memory is allocated and1383* the start of available memory is stored in availmem.1384* (The bootmem allocator requires now the physical address.)1385*/13861387movel L(memory_start),availmem13881389#ifdef CONFIG_AMIGA1390is_not_amiga(1f)1391/* fixup the Amiga custom register location before printing */1392clrl L(custom)13931:1394#endif13951396#ifdef CONFIG_ATARI1397is_not_atari(1f)1398/* fixup the Atari iobase register location before printing */1399movel #0xff000000,L(iobase)14001:1401#endif14021403#ifdef CONFIG_MAC1404is_not_mac(1f)1405movel #~VIDEOMEMMASK,%d01406andl L(mac_videobase),%d01407addl #VIDEOMEMBASE,%d01408movel %d0,L(mac_videobase)1409#ifdef CONSOLE_DEBUG1410movel %pc@(L(phys_kernel_start)),%d01411subl #PAGE_OFFSET,%d01412subl %d0,L(console_font)1413subl %d0,L(console_font_data)1414#endif1415orl #0x50000000,L(mac_sccbase)14161:1417#endif14181419#ifdef CONFIG_HP3001420is_not_hp300(2f)1421/*1422* Fix up the iobase register to point to the new location of the LEDs.1423*/1424movel #0xf0000000,L(iobase)14251426/*1427* Energise the FPU and caches.1428*/1429is_040(1f)1430movel #0x60,0xf05f400c1431jbra 2f14321433/*1434* 040: slightly different, apparently.1435*/14361: movew #0,0xf05f400e1437movew #0x64,0xf05f400e14382:1439#endif14401441#ifdef CONFIG_SUN3X1442is_not_sun3x(1f)14431444/* enable copro */1445oriw #0x4000,0x6100000014461:1447#endif14481449#ifdef CONFIG_APOLLO1450is_not_apollo(1f)14511452/*1453* Fix up the iobase before printing1454*/1455movel #0x80000000,L(iobase)14561:1457#endif14581459putc 'I'1460leds 0x1014611462/*1463* Enable caches1464*/14651466is_not_040_or_060(L(cache_not_680460))14671468L(cache680460):1469.chip 680401470nop1471cpusha %bc1472nop14731474is_060(L(cache68060))14751476movel #CC6_ENABLE_D+CC6_ENABLE_I,%d01477/* MMU stuff works in copyback mode now, so enable the cache */1478movec %d0,%cacr1479jra L(cache_done)14801481L(cache68060):1482movel #CC6_ENABLE_D+CC6_ENABLE_I+CC6_ENABLE_SB+CC6_PUSH_DPI+CC6_ENABLE_B+CC6_CLRA_B,%d01483/* MMU stuff works in copyback mode now, so enable the cache */1484movec %d0,%cacr1485/* enable superscalar dispatch in PCR */1486moveq #1,%d01487.chip 680601488movec %d0,%pcr14891490jbra L(cache_done)1491L(cache_not_680460):1492L(cache68030):1493.chip 680301494movel #CC3_ENABLE_DB+CC3_CLR_D+CC3_ENABLE_D+CC3_ENABLE_IB+CC3_CLR_I+CC3_ENABLE_I,%d01495movec %d0,%cacr14961497jra L(cache_done)1498.chip 68k1499L(cache_done):15001501putc 'J'15021503/*1504* Setup initial stack pointer1505*/1506lea init_task,%curptr1507lea init_thread_union+THREAD_SIZE,%sp15081509putc 'K'15101511subl %a6,%a6 /* clear a6 for gdb */15121513/*1514* The new 64bit printf support requires an early exception initialization.1515*/1516jbsr base_trap_init15171518/* jump to the kernel start */15191520putc '\n'1521leds 0x5515221523jbsr start_kernel15241525/*1526* Find a tag record in the bootinfo structure1527* The bootinfo structure is located right after the kernel1528* Returns: d0: size (-1 if not found)1529* a0: data pointer (end-of-records if not found)1530*/1531func_start get_bi_record,%d115321533movel ARG1,%d01534lea %pc@(_end),%a015351: tstw %a0@(BIR_TAG)1536jeq 3f1537cmpw %a0@(BIR_TAG),%d01538jeq 2f1539addw %a0@(BIR_SIZE),%a01540jra 1b15412: moveq #0,%d01542movew %a0@(BIR_SIZE),%d01543lea %a0@(BIR_DATA),%a01544jra 4f15453: moveq #-1,%d01546lea %a0@(BIR_SIZE),%a015474:1548func_return get_bi_record154915501551/*1552* MMU Initialization Begins Here1553*1554* The structure of the MMU tables on the 68k machines1555* is thus:1556* Root Table1557* Logical addresses are translated through1558* a hierarchical translation mechanism where the high-order1559* seven bits of the logical address (LA) are used as an1560* index into the "root table." Each entry in the root1561* table has a bit which specifies if it's a valid pointer to a1562* pointer table. Each entry defines a 32Meg range of memory.1563* If an entry is invalid then that logical range of 32M is1564* invalid and references to that range of memory (when the MMU1565* is enabled) will fault. If the entry is valid, then it does1566* one of two things. On 040/060 class machines, it points to1567* a pointer table which then describes more finely the memory1568* within that 32M range. On 020/030 class machines, a technique1569* called "early terminating descriptors" are used. This technique1570* allows an entire 32Meg to be described by a single entry in the1571* root table. Thus, this entry in the root table, contains the1572* physical address of the memory or I/O at the logical address1573* which the entry represents and it also contains the necessary1574* cache bits for this region.1575*1576* Pointer Tables1577* Per the Root Table, there will be one or more1578* pointer tables. Each pointer table defines a 32M range.1579* Not all of the 32M range need be defined. Again, the next1580* seven bits of the logical address are used an index into1581* the pointer table to point to page tables (if the pointer1582* is valid). There will undoubtedly be more than one1583* pointer table for the kernel because each pointer table1584* defines a range of only 32M. Valid pointer table entries1585* point to page tables, or are early terminating entries1586* themselves.1587*1588* Page Tables1589* Per the Pointer Tables, each page table entry points1590* to the physical page in memory that supports the logical1591* address that translates to the particular index.1592*1593* In short, the Logical Address gets translated as follows:1594* bits 31..26 - index into the Root Table1595* bits 25..18 - index into the Pointer Table1596* bits 17..12 - index into the Page Table1597* bits 11..0 - offset into a particular 4K page1598*1599* The algorithms which follow do one thing: they abstract1600* the MMU hardware. For example, there are three kinds of1601* cache settings that are relevant. Either, memory is1602* being mapped in which case it is either Kernel Code (or1603* the RamDisk) or it is MMU data. On the 030, the MMU data1604* option also describes the kernel. Or, I/O is being mapped1605* in which case it has its own kind of cache bits. There1606* are constants which abstract these notions from the code that1607* actually makes the call to map some range of memory.1608*1609*1610*1611*/16121613#ifdef MMU_PRINT1614/*1615* mmu_print1616*1617* This algorithm will print out the current MMU mappings.1618*1619* Input:1620* %a5 points to the root table. Everything else is calculated1621* from this.1622*/16231624#define mmu_next_valid 01625#define mmu_start_logical 41626#define mmu_next_logical 81627#define mmu_start_physical 121628#define mmu_next_physical 1616291630#define MMU_PRINT_INVALID -11631#define MMU_PRINT_VALID 11632#define MMU_PRINT_UNINITED 016331634#define putZc(z,n) jbne 1f; putc z; jbra 2f; 1: putc n; 2:16351636func_start mmu_print,%a0-%a6/%d0-%d716371638movel %pc@(L(kernel_pgdir_ptr)),%a51639lea %pc@(L(mmu_print_data)),%a01640movel #MMU_PRINT_UNINITED,%a0@(mmu_next_valid)16411642is_not_040_or_060(mmu_030_print)16431644mmu_040_print:1645puts "\nMMU040\n"1646puts "rp:"1647putn %a51648putc '\n'1649#if 01650/*1651* The following #if/#endif block is a tight algorithm for dumping the 0401652* MMU Map in gory detail. It really isn't that practical unless the1653* MMU Map algorithm appears to go awry and you need to debug it at the1654* entry per entry level.1655*/1656movel #ROOT_TABLE_SIZE,%d51657#if 01658movel %a5@+,%d7 | Burn an entry to skip the kernel mappings,1659subql #1,%d5 | they (might) work1660#endif16611: tstl %d51662jbeq mmu_print_done1663subq #1,%d51664movel %a5@+,%d71665btst #1,%d71666jbeq 1b166716682: putn %d71669andil #0xFFFFFE00,%d71670movel %d7,%a41671movel #PTR_TABLE_SIZE,%d41672putc ' '16733: tstl %d41674jbeq 11f1675subq #1,%d41676movel %a4@+,%d71677btst #1,%d71678jbeq 3b167916804: putn %d71681andil #0xFFFFFF00,%d71682movel %d7,%a31683movel #PAGE_TABLE_SIZE,%d316845: movel #8,%d216856: tstl %d31686jbeq 31f1687subq #1,%d31688movel %a3@+,%d61689btst #0,%d61690jbeq 6b16917: tstl %d21692jbeq 8f1693subq #1,%d21694putc ' '1695jbra 91f16968: putc '\n'1697movel #8+1+8+1+1,%d216989: putc ' '1699dbra %d2,9b1700movel #7,%d2170191: putn %d61702jbra 6b1703170431: putc '\n'1705movel #8+1,%d2170632: putc ' '1707dbra %d2,32b1708jbra 3b1709171011: putc '\n'1711jbra 1b1712#endif /* MMU 040 Dumping code that's gory and detailed */17131714lea %pc@(kernel_pg_dir),%a51715movel %a5,%a0 /* a0 has the address of the root table ptr */1716movel #0x00000000,%a4 /* logical address */1717moveql #0,%d0171840:1719/* Increment the logical address and preserve in d5 */1720movel %a4,%d51721addil #PAGESIZE<<13,%d51722movel %a0@+,%d61723btst #1,%d61724jbne 41f1725jbsr mmu_print_tuple_invalidate1726jbra 48f172741:1728movel #0,%d11729andil #0xfffffe00,%d61730movel %d6,%a1173142:1732movel %a4,%d51733addil #PAGESIZE<<6,%d51734movel %a1@+,%d61735btst #1,%d61736jbne 43f1737jbsr mmu_print_tuple_invalidate1738jbra 47f173943:1740movel #0,%d21741andil #0xffffff00,%d61742movel %d6,%a2174344:1744movel %a4,%d51745addil #PAGESIZE,%d51746movel %a2@+,%d61747btst #0,%d61748jbne 45f1749jbsr mmu_print_tuple_invalidate1750jbra 46f175145:1752moveml %d0-%d1,%sp@-1753movel %a4,%d01754movel %d6,%d11755andil #0xfffff4e0,%d11756lea %pc@(mmu_040_print_flags),%a61757jbsr mmu_print_tuple1758moveml %sp@+,%d0-%d1175946:1760movel %d5,%a41761addq #1,%d21762cmpib #64,%d21763jbne 44b176447:1765movel %d5,%a41766addq #1,%d11767cmpib #128,%d11768jbne 42b176948:1770movel %d5,%a4 /* move to the next logical address */1771addq #1,%d01772cmpib #128,%d01773jbne 40b17741775.chip 680401776movec %dtt1,%d01777movel %d0,%d11778andiw #0x8000,%d1 /* is it valid ? */1779jbeq 1f /* No, bail out */17801781movel %d0,%d11782andil #0xff000000,%d1 /* Get the address */1783putn %d11784puts "=="1785putn %d117861787movel %d0,%d61788jbsr mmu_040_print_flags_tt17891:1790movec %dtt0,%d01791movel %d0,%d11792andiw #0x8000,%d1 /* is it valid ? */1793jbeq 1f /* No, bail out */17941795movel %d0,%d11796andil #0xff000000,%d1 /* Get the address */1797putn %d11798puts "=="1799putn %d118001801movel %d0,%d61802jbsr mmu_040_print_flags_tt18031:1804.chip 68k18051806jbra mmu_print_done18071808mmu_040_print_flags:1809btstl #10,%d61810putZc(' ','G') /* global bit */1811btstl #7,%d61812putZc(' ','S') /* supervisor bit */1813mmu_040_print_flags_tt:1814btstl #6,%d61815jbne 3f1816putc 'C'1817btstl #5,%d61818putZc('w','c') /* write through or copy-back */1819jbra 4f18203:1821putc 'N'1822btstl #5,%d61823putZc('s',' ') /* serialized non-cacheable, or non-cacheable */18244:1825rts18261827mmu_030_print_flags:1828btstl #6,%d61829putZc('C','I') /* write through or copy-back */1830rts18311832mmu_030_print:1833puts "\nMMU030\n"1834puts "\nrp:"1835putn %a51836putc '\n'1837movel %a5,%d01838andil #0xfffffff0,%d01839movel %d0,%a01840movel #0x00000000,%a4 /* logical address */1841movel #0,%d0184230:1843movel %a4,%d51844addil #PAGESIZE<<13,%d51845movel %a0@+,%d61846btst #1,%d6 /* is it a table ptr? */1847jbne 31f /* yes */1848btst #0,%d6 /* is it early terminating? */1849jbeq 1f /* no */1850jbsr mmu_030_print_helper1851jbra 38f18521:1853jbsr mmu_print_tuple_invalidate1854jbra 38f185531:1856movel #0,%d11857andil #0xfffffff0,%d61858movel %d6,%a1185932:1860movel %a4,%d51861addil #PAGESIZE<<6,%d51862movel %a1@+,%d61863btst #1,%d6 /* is it a table ptr? */1864jbne 33f /* yes */1865btst #0,%d6 /* is it a page descriptor? */1866jbeq 1f /* no */1867jbsr mmu_030_print_helper1868jbra 37f18691:1870jbsr mmu_print_tuple_invalidate1871jbra 37f187233:1873movel #0,%d21874andil #0xfffffff0,%d61875movel %d6,%a2187634:1877movel %a4,%d51878addil #PAGESIZE,%d51879movel %a2@+,%d61880btst #0,%d61881jbne 35f1882jbsr mmu_print_tuple_invalidate1883jbra 36f188435:1885jbsr mmu_030_print_helper188636:1887movel %d5,%a41888addq #1,%d21889cmpib #64,%d21890jbne 34b189137:1892movel %d5,%a41893addq #1,%d11894cmpib #128,%d11895jbne 32b189638:1897movel %d5,%a4 /* move to the next logical address */1898addq #1,%d01899cmpib #128,%d01900jbne 30b19011902mmu_print_done:1903puts "\n"19041905func_return mmu_print190619071908mmu_030_print_helper:1909moveml %d0-%d1,%sp@-1910movel %a4,%d01911movel %d6,%d11912lea %pc@(mmu_030_print_flags),%a61913jbsr mmu_print_tuple1914moveml %sp@+,%d0-%d11915rts19161917mmu_print_tuple_invalidate:1918moveml %a0/%d7,%sp@-19191920lea %pc@(L(mmu_print_data)),%a01921tstl %a0@(mmu_next_valid)1922jbmi mmu_print_tuple_invalidate_exit19231924movel #MMU_PRINT_INVALID,%a0@(mmu_next_valid)19251926putn %a419271928puts "##\n"19291930mmu_print_tuple_invalidate_exit:1931moveml %sp@+,%a0/%d71932rts193319341935mmu_print_tuple:1936moveml %d0-%d7/%a0,%sp@-19371938lea %pc@(L(mmu_print_data)),%a019391940tstl %a0@(mmu_next_valid)1941jble mmu_print_tuple_print19421943cmpl %a0@(mmu_next_physical),%d11944jbeq mmu_print_tuple_increment19451946mmu_print_tuple_print:1947putn %d01948puts "->"1949putn %d119501951movel %d1,%d61952jbsr %a6@19531954mmu_print_tuple_record:1955movel #MMU_PRINT_VALID,%a0@(mmu_next_valid)19561957movel %d1,%a0@(mmu_next_physical)19581959mmu_print_tuple_increment:1960movel %d5,%d71961subl %a4,%d71962addl %d7,%a0@(mmu_next_physical)19631964mmu_print_tuple_exit:1965moveml %sp@+,%d0-%d7/%a01966rts19671968mmu_print_machine_cpu_types:1969puts "machine: "19701971is_not_amiga(1f)1972puts "amiga"1973jbra 9f19741:1975is_not_atari(2f)1976puts "atari"1977jbra 9f19782:1979is_not_mac(3f)1980puts "macintosh"1981jbra 9f19823: puts "unknown"19839: putc '\n'19841985puts "cputype: 0"1986is_not_060(1f)1987putc '6'1988jbra 9f19891:1990is_not_040_or_060(2f)1991putc '4'1992jbra 9f19932: putc '3'19949: putc '0'1995putc '\n'19961997rts1998#endif /* MMU_PRINT */19992000/*2001* mmu_map_tt2002*2003* This is a specific function which works on all 680x0 machines.2004* On 030, 040 & 060 it will attempt to use Transparent Translation2005* registers (tt1).2006* On 020 it will call the standard mmu_map which will use early2007* terminating descriptors.2008*/2009func_start mmu_map_tt,%d0/%d1/%a0,420102011dputs "mmu_map_tt:"2012dputn ARG12013dputn ARG22014dputn ARG32015dputn ARG42016dputc '\n'20172018is_020(L(do_map))20192020/* Extract the highest bit set2021*/2022bfffo ARG3{#0,#32},%d12023cmpw #8,%d12024jcc L(do_map)20252026/* And get the mask2027*/2028moveq #-1,%d02029lsrl %d1,%d02030lsrl #1,%d020312032/* Mask the address2033*/2034movel %d0,%d12035notl %d12036andl ARG2,%d120372038/* Generate the upper 16bit of the tt register2039*/2040lsrl #8,%d02041orl %d0,%d12042clrw %d120432044is_040_or_060(L(mmu_map_tt_040))20452046/* set 030 specific bits (read/write access for supervisor mode2047* (highest function code set, lower two bits masked))2048*/2049orw #TTR_ENABLE+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d12050movel ARG4,%d02051btst #6,%d02052jeq 1f2053orw #TTR_CI,%d1205420551: lea STACK,%a02056dputn %d12057movel %d1,%a0@2058.chip 680302059tstl ARG12060jne 1f2061pmove %a0@,%tt02062jra 2f20631: pmove %a0@,%tt120642: .chip 68k2065jra L(mmu_map_tt_done)20662067/* set 040 specific bits2068*/2069L(mmu_map_tt_040):2070orw #TTR_ENABLE+TTR_KERNELMODE,%d12071orl ARG4,%d12072dputn %d120732074.chip 680402075tstl ARG12076jne 1f2077movec %d1,%itt02078movec %d1,%dtt02079jra 2f20801: movec %d1,%itt12081movec %d1,%dtt120822: .chip 68k20832084jra L(mmu_map_tt_done)20852086L(do_map):2087mmu_map_eq ARG2,ARG3,ARG420882089L(mmu_map_tt_done):20902091func_return mmu_map_tt20922093/*2094* mmu_map2095*2096* This routine will map a range of memory using a pointer2097* table and allocate the pages on the fly from the kernel.2098* The pointer table does not have to be already linked into2099* the root table, this routine will do that if necessary.2100*2101* NOTE2102* This routine will assert failure and use the serial_putc2103* routines in the case of a run-time error. For example,2104* if the address is already mapped.2105*2106* NOTE-22107* This routine will use early terminating descriptors2108* where possible for the 68020+68851 and 68030 type2109* processors.2110*/2111func_start mmu_map,%d0-%d4/%a0-%a421122113dputs "\nmmu_map:"2114dputn ARG12115dputn ARG22116dputn ARG32117dputn ARG42118dputc '\n'21192120/* Get logical address and round it down to 256KB2121*/2122movel ARG1,%d02123andl #-(PAGESIZE*PAGE_TABLE_SIZE),%d02124movel %d0,%a321252126/* Get the end address2127*/2128movel ARG1,%a42129addl ARG3,%a42130subql #1,%a421312132/* Get physical address and round it down to 256KB2133*/2134movel ARG2,%d02135andl #-(PAGESIZE*PAGE_TABLE_SIZE),%d02136movel %d0,%a221372138/* Add page attributes to the physical address2139*/2140movel ARG4,%d02141orw #_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d02142addw %d0,%a221432144dputn %a22145dputn %a32146dputn %a421472148is_not_040_or_060(L(mmu_map_030))21492150addw #_PAGE_GLOBAL040,%a22151/*2152* MMU 040 & 060 Support2153*2154* The MMU usage for the 040 and 060 is different enough from2155* the 030 and 68851 that there is separate code. This comment2156* block describes the data structures and algorithms built by2157* this code.2158*2159* The 040 does not support early terminating descriptors, as2160* the 030 does. Therefore, a third level of table is needed2161* for the 040, and that would be the page table. In Linux,2162* page tables are allocated directly from the memory above the2163* kernel.2164*2165*/21662167L(mmu_map_040):2168/* Calculate the offset into the root table2169*/2170movel %a3,%d02171moveq #ROOT_INDEX_SHIFT,%d12172lsrl %d1,%d02173mmu_get_root_table_entry %d021742175/* Calculate the offset into the pointer table2176*/2177movel %a3,%d02178moveq #PTR_INDEX_SHIFT,%d12179lsrl %d1,%d02180andl #PTR_TABLE_SIZE-1,%d02181mmu_get_ptr_table_entry %a0,%d021822183/* Calculate the offset into the page table2184*/2185movel %a3,%d02186moveq #PAGE_INDEX_SHIFT,%d12187lsrl %d1,%d02188andl #PAGE_TABLE_SIZE-1,%d02189mmu_get_page_table_entry %a0,%d021902191/* The page table entry must not no be busy2192*/2193tstl %a0@2194jne L(mmu_map_error)21952196/* Do the mapping and advance the pointers2197*/2198movel %a2,%a0@21992:2200addw #PAGESIZE,%a22201addw #PAGESIZE,%a322022203/* Ready with mapping?2204*/2205lea %a3@(-1),%a02206cmpl %a0,%a42207jhi L(mmu_map_040)2208jra L(mmu_map_done)22092210L(mmu_map_030):2211/* Calculate the offset into the root table2212*/2213movel %a3,%d02214moveq #ROOT_INDEX_SHIFT,%d12215lsrl %d1,%d02216mmu_get_root_table_entry %d022172218/* Check if logical address 32MB aligned,2219* so we can try to map it once2220*/2221movel %a3,%d02222andl #(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE-1)&(-ROOT_TABLE_SIZE),%d02223jne 1f22242225/* Is there enough to map for 32MB at once2226*/2227lea %a3@(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE-1),%a12228cmpl %a1,%a42229jcs 1f22302231addql #1,%a122322233/* The root table entry must not no be busy2234*/2235tstl %a0@2236jne L(mmu_map_error)22372238/* Do the mapping and advance the pointers2239*/2240dputs "early term1"2241dputn %a22242dputn %a32243dputn %a12244dputc '\n'2245movel %a2,%a0@22462247movel %a1,%a32248lea %a2@(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE),%a22249jra L(mmu_mapnext_030)22501:2251/* Calculate the offset into the pointer table2252*/2253movel %a3,%d02254moveq #PTR_INDEX_SHIFT,%d12255lsrl %d1,%d02256andl #PTR_TABLE_SIZE-1,%d02257mmu_get_ptr_table_entry %a0,%d022582259/* The pointer table entry must not no be busy2260*/2261tstl %a0@2262jne L(mmu_map_error)22632264/* Do the mapping and advance the pointers2265*/2266dputs "early term2"2267dputn %a22268dputn %a32269dputc '\n'2270movel %a2,%a0@22712272addl #PAGE_TABLE_SIZE*PAGESIZE,%a22273addl #PAGE_TABLE_SIZE*PAGESIZE,%a322742275L(mmu_mapnext_030):2276/* Ready with mapping?2277*/2278lea %a3@(-1),%a02279cmpl %a0,%a42280jhi L(mmu_map_030)2281jra L(mmu_map_done)22822283L(mmu_map_error):22842285dputs "mmu_map error:"2286dputn %a22287dputn %a32288dputc '\n'22892290L(mmu_map_done):22912292func_return mmu_map22932294/*2295* mmu_fixup2296*2297* On the 040 class machines, all pages that are used for the2298* mmu have to be fixed up.2299*/23002301func_start mmu_fixup_page_mmu_cache,%d0/%a023022303dputs "mmu_fixup_page_mmu_cache"2304dputn ARG123052306/* Calculate the offset into the root table2307*/2308movel ARG1,%d02309moveq #ROOT_INDEX_SHIFT,%d12310lsrl %d1,%d02311mmu_get_root_table_entry %d023122313/* Calculate the offset into the pointer table2314*/2315movel ARG1,%d02316moveq #PTR_INDEX_SHIFT,%d12317lsrl %d1,%d02318andl #PTR_TABLE_SIZE-1,%d02319mmu_get_ptr_table_entry %a0,%d023202321/* Calculate the offset into the page table2322*/2323movel ARG1,%d02324moveq #PAGE_INDEX_SHIFT,%d12325lsrl %d1,%d02326andl #PAGE_TABLE_SIZE-1,%d02327mmu_get_page_table_entry %a0,%d023282329movel %a0@,%d02330andil #_CACHEMASK040,%d02331orl %pc@(m68k_pgtable_cachemode),%d02332movel %d0,%a0@23332334dputc '\n'23352336func_return mmu_fixup_page_mmu_cache23372338/*2339* mmu_temp_map2340*2341* create a temporary mapping to enable the mmu,2342* this we don't need any transparation translation tricks.2343*/23442345func_start mmu_temp_map,%d0/%d1/%a0/%a123462347dputs "mmu_temp_map"2348dputn ARG12349dputn ARG22350dputc '\n'23512352lea %pc@(L(temp_mmap_mem)),%a123532354/* Calculate the offset in the root table2355*/2356movel ARG2,%d02357moveq #ROOT_INDEX_SHIFT,%d12358lsrl %d1,%d02359mmu_get_root_table_entry %d023602361/* Check if the table is temporary allocated, so we have to reuse it2362*/2363movel %a0@,%d02364cmpl %pc@(L(memory_start)),%d02365jcc 1f23662367/* Temporary allocate a ptr table and insert it into the root table2368*/2369movel %a1@,%d02370addl #PTR_TABLE_SIZE*4,%a1@2371orw #_PAGE_TABLE+_PAGE_ACCESSED,%d02372movel %d0,%a0@2373dputs " (new)"23741:2375dputn %d02376/* Mask the root table entry for the ptr table2377*/2378andw #-ROOT_TABLE_SIZE,%d02379movel %d0,%a023802381/* Calculate the offset into the pointer table2382*/2383movel ARG2,%d02384moveq #PTR_INDEX_SHIFT,%d12385lsrl %d1,%d02386andl #PTR_TABLE_SIZE-1,%d02387lea %a0@(%d0*4),%a02388dputn %a023892390/* Check if a temporary page table is already allocated2391*/2392movel %a0@,%d02393jne 1f23942395/* Temporary allocate a page table and insert it into the ptr table2396*/2397movel %a1@,%d02398/* The 512 should be PAGE_TABLE_SIZE*4, but that violates the2399alignment restriction for pointer tables on the '0[46]0. */2400addl #512,%a1@2401orw #_PAGE_TABLE+_PAGE_ACCESSED,%d02402movel %d0,%a0@2403dputs " (new)"24041:2405dputn %d02406/* Mask the ptr table entry for the page table2407*/2408andw #-PTR_TABLE_SIZE,%d02409movel %d0,%a024102411/* Calculate the offset into the page table2412*/2413movel ARG2,%d02414moveq #PAGE_INDEX_SHIFT,%d12415lsrl %d1,%d02416andl #PAGE_TABLE_SIZE-1,%d02417lea %a0@(%d0*4),%a02418dputn %a024192420/* Insert the address into the page table2421*/2422movel ARG1,%d02423andw #-PAGESIZE,%d02424orw #_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d02425movel %d0,%a0@2426dputn %d024272428dputc '\n'24292430func_return mmu_temp_map24312432func_start mmu_engage,%d0-%d2/%a0-%a324332434moveq #ROOT_TABLE_SIZE-1,%d02435/* Temporarily use a different root table. */2436lea %pc@(L(kernel_pgdir_ptr)),%a02437movel %a0@,%a22438movel %pc@(L(memory_start)),%a12439movel %a1,%a0@2440movel %a2,%a024411:2442movel %a0@+,%a1@+2443dbra %d0,1b24442445lea %pc@(L(temp_mmap_mem)),%a02446movel %a1,%a0@24472448movew #PAGESIZE-1,%d024491:2450clrl %a1@+2451dbra %d0,1b24522453lea %pc@(1b),%a02454movel #1b,%a12455/* Skip temp mappings if phys == virt */2456cmpl %a0,%a12457jeq 1f24582459mmu_temp_map %a0,%a02460mmu_temp_map %a0,%a124612462addw #PAGESIZE,%a02463addw #PAGESIZE,%a12464mmu_temp_map %a0,%a02465mmu_temp_map %a0,%a124661:2467movel %pc@(L(memory_start)),%a32468movel %pc@(L(phys_kernel_start)),%d224692470is_not_040_or_060(L(mmu_engage_030))24712472L(mmu_engage_040):2473.chip 680402474nop2475cinva %bc2476nop2477pflusha2478nop2479movec %a3,%srp2480movel #TC_ENABLE+TC_PAGE4K,%d02481movec %d0,%tc /* enable the MMU */2482jmp 1f:l24831: nop2484movec %a2,%srp2485nop2486cinva %bc2487nop2488pflusha2489.chip 68k2490jra L(mmu_engage_cleanup)24912492L(mmu_engage_030_temp):2493.space 122494L(mmu_engage_030):2495.chip 680302496lea %pc@(L(mmu_engage_030_temp)),%a02497movel #0x80000002,%a0@2498movel %a3,%a0@(4)2499movel #0x0808,%d02500movec %d0,%cacr2501pmove %a0@,%srp2502pflusha2503/*2504* enable,super root enable,4096 byte pages,7 bit root index,2505* 7 bit pointer index, 6 bit page table index.2506*/2507movel #0x82c07760,%a0@(8)2508pmove %a0@(8),%tc /* enable the MMU */2509jmp 1f:l25101: movel %a2,%a0@(4)2511movel #0x0808,%d02512movec %d0,%cacr2513pmove %a0@,%srp2514pflusha2515.chip 68k25162517L(mmu_engage_cleanup):2518subl #PAGE_OFFSET,%d22519subl %d2,%a22520movel %a2,L(kernel_pgdir_ptr)2521subl %d2,%fp2522subl %d2,%sp2523subl %d2,ARG025242525func_return mmu_engage25262527func_start mmu_get_root_table_entry,%d0/%a125282529#if 02530dputs "mmu_get_root_table_entry:"2531dputn ARG12532dputs " ="2533#endif25342535movel %pc@(L(kernel_pgdir_ptr)),%a02536tstl %a02537jne 2f25382539dputs "\nmmu_init:"25402541/* Find the start of free memory, get_bi_record does this for us,2542* as the bootinfo structure is located directly behind the kernel2543* we simply search for the last entry.2544*/2545get_bi_record BI_LAST2546addw #PAGESIZE-1,%a02547movel %a0,%d02548andw #-PAGESIZE,%d025492550dputn %d025512552lea %pc@(L(memory_start)),%a02553movel %d0,%a0@2554lea %pc@(L(kernel_end)),%a02555movel %d0,%a0@25562557/* we have to return the first page at _stext since the init code2558* in mm/init.c simply expects kernel_pg_dir there, the rest of2559* page is used for further ptr tables in get_ptr_table.2560*/2561lea %pc@(_stext),%a02562lea %pc@(L(mmu_cached_pointer_tables)),%a12563movel %a0,%a1@2564addl #ROOT_TABLE_SIZE*4,%a1@25652566lea %pc@(L(mmu_num_pointer_tables)),%a12567addql #1,%a1@25682569/* clear the page2570*/2571movel %a0,%a12572movew #PAGESIZE/4-1,%d025731:2574clrl %a1@+2575dbra %d0,1b25762577lea %pc@(L(kernel_pgdir_ptr)),%a12578movel %a0,%a1@25792580dputn %a02581dputc '\n'25822:2583movel ARG1,%d02584lea %a0@(%d0*4),%a025852586#if 02587dputn %a02588dputc '\n'2589#endif25902591func_return mmu_get_root_table_entry2592259325942595func_start mmu_get_ptr_table_entry,%d0/%a125962597#if 02598dputs "mmu_get_ptr_table_entry:"2599dputn ARG12600dputn ARG22601dputs " ="2602#endif26032604movel ARG1,%a02605movel %a0@,%d02606jne 2f26072608/* Keep track of the number of pointer tables we use2609*/2610dputs "\nmmu_get_new_ptr_table:"2611lea %pc@(L(mmu_num_pointer_tables)),%a02612movel %a0@,%d02613addql #1,%a0@26142615/* See if there is a free pointer table in our cache of pointer tables2616*/2617lea %pc@(L(mmu_cached_pointer_tables)),%a12618andw #7,%d02619jne 1f26202621/* Get a new pointer table page from above the kernel memory2622*/2623get_new_page2624movel %a0,%a1@26251:2626/* There is an unused pointer table in our cache... use it2627*/2628movel %a1@,%d02629addl #PTR_TABLE_SIZE*4,%a1@26302631dputn %d02632dputc '\n'26332634/* Insert the new pointer table into the root table2635*/2636movel ARG1,%a02637orw #_PAGE_TABLE+_PAGE_ACCESSED,%d02638movel %d0,%a0@26392:2640/* Extract the pointer table entry2641*/2642andw #-PTR_TABLE_SIZE,%d02643movel %d0,%a02644movel ARG2,%d02645lea %a0@(%d0*4),%a026462647#if 02648dputn %a02649dputc '\n'2650#endif26512652func_return mmu_get_ptr_table_entry265326542655func_start mmu_get_page_table_entry,%d0/%a126562657#if 02658dputs "mmu_get_page_table_entry:"2659dputn ARG12660dputn ARG22661dputs " ="2662#endif26632664movel ARG1,%a02665movel %a0@,%d02666jne 2f26672668/* If the page table entry doesn't exist, we allocate a complete new2669* page and use it as one continuous big page table which can cover2670* 4MB of memory, nearly almost all mappings have that alignment.2671*/2672get_new_page2673addw #_PAGE_TABLE+_PAGE_ACCESSED,%a026742675/* align pointer table entry for a page of page tables2676*/2677movel ARG1,%d02678andw #-(PAGESIZE/PAGE_TABLE_SIZE),%d02679movel %d0,%a126802681/* Insert the page tables into the pointer entries2682*/2683moveq #PAGESIZE/PAGE_TABLE_SIZE/4-1,%d026841:2685movel %a0,%a1@+2686lea %a0@(PAGE_TABLE_SIZE*4),%a02687dbra %d0,1b26882689/* Now we can get the initialized pointer table entry2690*/2691movel ARG1,%a02692movel %a0@,%d026932:2694/* Extract the page table entry2695*/2696andw #-PAGE_TABLE_SIZE,%d02697movel %d0,%a02698movel ARG2,%d02699lea %a0@(%d0*4),%a027002701#if 02702dputn %a02703dputc '\n'2704#endif27052706func_return mmu_get_page_table_entry27072708/*2709* get_new_page2710*2711* Return a new page from the memory start and clear it.2712*/2713func_start get_new_page,%d0/%a127142715dputs "\nget_new_page:"27162717/* allocate the page and adjust memory_start2718*/2719lea %pc@(L(memory_start)),%a02720movel %a0@,%a12721addl #PAGESIZE,%a0@27222723/* clear the new page2724*/2725movel %a1,%a02726movew #PAGESIZE/4-1,%d027271:2728clrl %a1@+2729dbra %d0,1b27302731dputn %a02732dputc '\n'27332734func_return get_new_page2735273627372738/*2739* Debug output support2740* Atarians have a choice between the parallel port, the serial port2741* from the MFP or a serial port of the SCC2742*/27432744#ifdef CONFIG_MAC2745/* You may define either or both of these. */2746#define MAC_USE_SCC_A /* Modem port */2747#define MAC_USE_SCC_B /* Printer port */27482749#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)2750/* Initialisation table for SCC with 3.6864 MHz PCLK */2751L(scc_initable_mac):2752.byte 4,0x44 /* x16, 1 stopbit, no parity */2753.byte 3,0xc0 /* receiver: 8 bpc */2754.byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */2755.byte 10,0 /* NRZ */2756.byte 11,0x50 /* use baud rate generator */2757.byte 12,1,13,0 /* 38400 baud */2758.byte 14,1 /* Baud rate generator enable */2759.byte 3,0xc1 /* enable receiver */2760.byte 5,0xea /* enable transmitter */2761.byte -12762.even2763#endif2764#endif /* CONFIG_MAC */27652766#ifdef CONFIG_ATARI2767/* #define USE_PRINTER */2768/* #define USE_SCC_B */2769/* #define USE_SCC_A */2770#define USE_MFP27712772#if defined(USE_SCC_A) || defined(USE_SCC_B)2773/* Initialisation table for SCC with 7.9872 MHz PCLK */2774/* PCLK == 8.0539 gives baud == 9680.1 */2775L(scc_initable_atari):2776.byte 4,0x44 /* x16, 1 stopbit, no parity */2777.byte 3,0xc0 /* receiver: 8 bpc */2778.byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */2779.byte 10,0 /* NRZ */2780.byte 11,0x50 /* use baud rate generator */2781.byte 12,24,13,0 /* 9600 baud */2782.byte 14,2,14,3 /* use master clock for BRG, enable */2783.byte 3,0xc1 /* enable receiver */2784.byte 5,0xea /* enable transmitter */2785.byte -12786.even2787#endif27882789#ifdef USE_PRINTER27902791LPSG_SELECT = 0xff88002792LPSG_READ = 0xff88002793LPSG_WRITE = 0xff88022794LPSG_IO_A = 142795LPSG_IO_B = 152796LPSG_CONTROL = 72797LSTMFP_GPIP = 0xfffa012798LSTMFP_DDR = 0xfffa052799LSTMFP_IERB = 0xfffa0928002801#elif defined(USE_SCC_B)28022803LSCC_CTRL = 0xff8c852804LSCC_DATA = 0xff8c8728052806#elif defined(USE_SCC_A)28072808LSCC_CTRL = 0xff8c812809LSCC_DATA = 0xff8c8328102811#elif defined(USE_MFP)28122813LMFP_UCR = 0xfffa292814LMFP_TDCDR = 0xfffa1d2815LMFP_TDDR = 0xfffa252816LMFP_TSR = 0xfffa2d2817LMFP_UDR = 0xfffa2f28182819#endif2820#endif /* CONFIG_ATARI */28212822/*2823* Serial port output support.2824*/28252826/*2827* Initialize serial port hardware2828*/2829func_start serial_init,%d0/%d1/%a0/%a12830/*2831* Some of the register usage that follows2832* CONFIG_AMIGA2833* a0 = pointer to boot info record2834* d0 = boot info offset2835* CONFIG_ATARI2836* a0 = address of SCC2837* a1 = Liobase address/address of scc_initable_atari2838* d0 = init data for serial port2839* CONFIG_MAC2840* a0 = address of SCC2841* a1 = address of scc_initable_mac2842* d0 = init data for serial port2843*/28442845#ifdef CONFIG_AMIGA2846#define SERIAL_DTR 72847#define SERIAL_CNTRL CIABBASE+C_PRA28482849is_not_amiga(1f)2850lea %pc@(L(custom)),%a02851movel #-ZTWOBASE,%a0@2852bclr #SERIAL_DTR,SERIAL_CNTRL-ZTWOBASE2853get_bi_record BI_AMIGA_SERPER2854movew %a0@,CUSTOMBASE+C_SERPER-ZTWOBASE2855| movew #61,CUSTOMBASE+C_SERPER-ZTWOBASE28561:2857#endif28582859#ifdef CONFIG_ATARI2860is_not_atari(4f)2861movel %pc@(L(iobase)),%a12862#if defined(USE_PRINTER)2863bclr #0,%a1@(LSTMFP_IERB)2864bclr #0,%a1@(LSTMFP_DDR)2865moveb #LPSG_CONTROL,%a1@(LPSG_SELECT)2866moveb #0xff,%a1@(LPSG_WRITE)2867moveb #LPSG_IO_B,%a1@(LPSG_SELECT)2868clrb %a1@(LPSG_WRITE)2869moveb #LPSG_IO_A,%a1@(LPSG_SELECT)2870moveb %a1@(LPSG_READ),%d02871bset #5,%d02872moveb %d0,%a1@(LPSG_WRITE)2873#elif defined(USE_SCC_A) || defined(USE_SCC_B)2874lea %a1@(LSCC_CTRL),%a02875/* Reset SCC register pointer */2876moveb %a0@,%d02877/* Reset SCC device: write register pointer then register value */2878moveb #9,%a0@2879moveb #0xc0,%a0@2880/* Wait for 5 PCLK cycles, which is about 63 CPU cycles */2881/* 5 / 7.9872 MHz = approx. 0.63 us = 63 / 100 MHz */2882movel #32,%d028832:2884subq #1,%d02885jne 2b2886/* Initialize channel */2887lea %pc@(L(scc_initable_atari)),%a128882: moveb %a1@+,%d02889jmi 3f2890moveb %d0,%a0@2891moveb %a1@+,%a0@2892jra 2b28933: clrb %a0@2894#elif defined(USE_MFP)2895bclr #1,%a1@(LMFP_TSR)2896moveb #0x88,%a1@(LMFP_UCR)2897andb #0x70,%a1@(LMFP_TDCDR)2898moveb #2,%a1@(LMFP_TDDR)2899orb #1,%a1@(LMFP_TDCDR)2900bset #1,%a1@(LMFP_TSR)2901#endif2902jra L(serial_init_done)29034:2904#endif29052906#ifdef CONFIG_MAC2907is_not_mac(L(serial_init_not_mac))2908#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)2909#define mac_scc_cha_b_ctrl_offset 0x02910#define mac_scc_cha_a_ctrl_offset 0x22911#define mac_scc_cha_b_data_offset 0x42912#define mac_scc_cha_a_data_offset 0x62913movel %pc@(L(mac_sccbase)),%a02914/* Reset SCC register pointer */2915moveb %a0@(mac_scc_cha_a_ctrl_offset),%d02916/* Reset SCC device: write register pointer then register value */2917moveb #9,%a0@(mac_scc_cha_a_ctrl_offset)2918moveb #0xc0,%a0@(mac_scc_cha_a_ctrl_offset)2919/* Wait for 5 PCLK cycles, which is about 68 CPU cycles */2920/* 5 / 3.6864 MHz = approx. 1.36 us = 68 / 50 MHz */2921movel #35,%d029225:2923subq #1,%d02924jne 5b2925#endif2926#ifdef MAC_USE_SCC_A2927/* Initialize channel A */2928lea %pc@(L(scc_initable_mac)),%a129295: moveb %a1@+,%d02930jmi 6f2931moveb %d0,%a0@(mac_scc_cha_a_ctrl_offset)2932moveb %a1@+,%a0@(mac_scc_cha_a_ctrl_offset)2933jra 5b29346:2935#endif /* MAC_USE_SCC_A */2936#ifdef MAC_USE_SCC_B2937/* Initialize channel B */2938lea %pc@(L(scc_initable_mac)),%a129397: moveb %a1@+,%d02940jmi 8f2941moveb %d0,%a0@(mac_scc_cha_b_ctrl_offset)2942moveb %a1@+,%a0@(mac_scc_cha_b_ctrl_offset)2943jra 7b29448:2945#endif /* MAC_USE_SCC_B */2946jra L(serial_init_done)2947L(serial_init_not_mac):2948#endif /* CONFIG_MAC */29492950#ifdef CONFIG_Q402951is_not_q40(2f)2952/* debug output goes into SRAM, so we don't do it unless requested2953- check for '%LX$' signature in SRAM */2954lea %pc@(q40_mem_cptr),%a12955move.l #0xff020010,%a1@ /* must be inited - also used by debug=mem */2956move.l #0xff020000,%a12957cmp.b #'%',%a1@2958bne 2f /*nodbg*/2959addq.w #4,%a12960cmp.b #'L',%a1@2961bne 2f /*nodbg*/2962addq.w #4,%a12963cmp.b #'X',%a1@2964bne 2f /*nodbg*/2965addq.w #4,%a12966cmp.b #'$',%a1@2967bne 2f /*nodbg*/2968/* signature OK */2969lea %pc@(L(q40_do_debug)),%a12970tas %a1@2971/*nodbg: q40_do_debug is 0 by default*/29722:2973#endif29742975#ifdef CONFIG_MVME16x2976is_not_mvme16x(L(serial_init_not_mvme16x))2977moveb #0x10,M167_PCSCCMICR2978moveb #0x10,M167_PCSCCTICR2979moveb #0x10,M167_PCSCCRICR2980jra L(serial_init_done)2981L(serial_init_not_mvme16x):2982#endif29832984#ifdef CONFIG_APOLLO2985/* We count on the PROM initializing SIO1 */2986#endif29872988#ifdef CONFIG_HP3002989/* We count on the boot loader initialising the UART */2990#endif29912992L(serial_init_done):2993func_return serial_init29942995/*2996* Output character on serial port.2997*/2998func_start serial_putc,%d0/%d1/%a0/%a129993000movel ARG1,%d03001cmpib #'\n',%d03002jbne 1f30033004/* A little safe recursion is good for the soul */3005serial_putc #'\r'30061:30073008#ifdef CONFIG_AMIGA3009is_not_amiga(2f)3010andw #0x00ff,%d03011oriw #0x0100,%d03012movel %pc@(L(custom)),%a03013movew %d0,%a0@(CUSTOMBASE+C_SERDAT)30141: movew %a0@(CUSTOMBASE+C_SERDATR),%d03015andw #0x2000,%d03016jeq 1b3017jra L(serial_putc_done)30182:3019#endif30203021#ifdef CONFIG_MAC3022is_not_mac(5f)3023#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)3024movel %pc@(L(mac_sccbase)),%a13025#endif3026#ifdef MAC_USE_SCC_A30273: btst #2,%a1@(mac_scc_cha_a_ctrl_offset)3028jeq 3b3029moveb %d0,%a1@(mac_scc_cha_a_data_offset)3030#endif /* MAC_USE_SCC_A */3031#ifdef MAC_USE_SCC_B30324: btst #2,%a1@(mac_scc_cha_b_ctrl_offset)3033jeq 4b3034moveb %d0,%a1@(mac_scc_cha_b_data_offset)3035#endif /* MAC_USE_SCC_B */3036jra L(serial_putc_done)30375:3038#endif /* CONFIG_MAC */30393040#ifdef CONFIG_ATARI3041is_not_atari(4f)3042movel %pc@(L(iobase)),%a13043#if defined(USE_PRINTER)30443: btst #0,%a1@(LSTMFP_GPIP)3045jne 3b3046moveb #LPSG_IO_B,%a1@(LPSG_SELECT)3047moveb %d0,%a1@(LPSG_WRITE)3048moveb #LPSG_IO_A,%a1@(LPSG_SELECT)3049moveb %a1@(LPSG_READ),%d03050bclr #5,%d03051moveb %d0,%a1@(LPSG_WRITE)3052nop3053nop3054bset #5,%d03055moveb %d0,%a1@(LPSG_WRITE)3056#elif defined(USE_SCC_A) || defined(USE_SCC_B)30573: btst #2,%a1@(LSCC_CTRL)3058jeq 3b3059moveb %d0,%a1@(LSCC_DATA)3060#elif defined(USE_MFP)30613: btst #7,%a1@(LMFP_TSR)3062jeq 3b3063moveb %d0,%a1@(LMFP_UDR)3064#endif3065jra L(serial_putc_done)30664:3067#endif /* CONFIG_ATARI */30683069#ifdef CONFIG_MVME1473070is_not_mvme147(2f)30711: btst #2,M147_SCC_CTRL_A3072jeq 1b3073moveb %d0,M147_SCC_DATA_A3074jbra L(serial_putc_done)30752:3076#endif30773078#ifdef CONFIG_MVME16x3079is_not_mvme16x(2f)3080/*3081* If the loader gave us a board type then we can use that to3082* select an appropriate output routine; otherwise we just use3083* the Bug code. If we have to use the Bug that means the Bug3084* workspace has to be valid, which means the Bug has to use3085* the SRAM, which is non-standard.3086*/3087moveml %d0-%d7/%a2-%a6,%sp@-3088movel vme_brdtype,%d13089jeq 1f | No tag - use the Bug3090cmpi #VME_TYPE_MVME162,%d13091jeq 6f3092cmpi #VME_TYPE_MVME172,%d13093jne 5f3094/* 162/172; it's an SCC */30956: btst #2,M162_SCC_CTRL_A3096nop3097nop3098nop3099jeq 6b3100moveb #8,M162_SCC_CTRL_A3101nop3102nop3103nop3104moveb %d0,M162_SCC_CTRL_A3105jra 3f31065:3107/* 166/167/177; it's a CD2401 */3108moveb #0,M167_CYCAR3109moveb M167_CYIER,%d23110moveb #0x02,M167_CYIER31117:3112btst #5,M167_PCSCCTICR3113jeq 7b3114moveb M167_PCTPIACKR,%d13115moveb M167_CYLICR,%d13116jeq 8f3117moveb #0x08,M167_CYTEOIR3118jra 7b31198:3120moveb %d0,M167_CYTDR3121moveb #0,M167_CYTEOIR3122moveb %d2,M167_CYIER3123jra 3f31241:3125moveb %d0,%sp@-3126trap #153127.word 0x0020 /* TRAP 0x020 */31283:3129moveml %sp@+,%d0-%d7/%a2-%a63130jbra L(serial_putc_done)31312:3132#endif /* CONFIG_MVME16x */31333134#ifdef CONFIG_BVME60003135is_not_bvme6000(2f)3136/*3137* The BVME6000 machine has a serial port ...3138*/31391: btst #2,BVME_SCC_CTRL_A3140jeq 1b3141moveb %d0,BVME_SCC_DATA_A3142jbra L(serial_putc_done)31432:3144#endif31453146#ifdef CONFIG_SUN3X3147is_not_sun3x(2f)3148movel %d0,-(%sp)3149movel 0xFEFE0018,%a13150jbsr (%a1)3151addq #4,%sp3152jbra L(serial_putc_done)31532:3154#endif31553156#ifdef CONFIG_Q403157is_not_q40(2f)3158tst.l %pc@(L(q40_do_debug)) /* only debug if requested */3159beq 2f3160lea %pc@(q40_mem_cptr),%a13161move.l %a1@,%a03162move.b %d0,%a0@3163addq.l #4,%a03164move.l %a0,%a1@3165jbra L(serial_putc_done)31662:3167#endif31683169#ifdef CONFIG_APOLLO3170is_not_apollo(2f)3171movl %pc@(L(iobase)),%a13172moveb %d0,%a1@(LTHRB0)31731: moveb %a1@(LSRB0),%d03174andb #0x4,%d03175beq 1b3176jbra L(serial_putc_done)31772:3178#endif31793180#ifdef CONFIG_HP3003181is_not_hp300(3f)3182movl %pc@(L(iobase)),%a13183addl %pc@(L(uartbase)),%a13184movel %pc@(L(uart_scode)),%d1 /* Check the scode */3185jmi 3f /* Unset? Exit */3186cmpi #256,%d1 /* APCI scode? */3187jeq 2f31881: moveb %a1@(DCALSR),%d1 /* Output to DCA */3189andb #0x20,%d13190beq 1b3191moveb %d0,%a1@(DCADATA)3192jbra L(serial_putc_done)31932: moveb %a1@(APCILSR),%d1 /* Output to APCI */3194andb #0x20,%d13195beq 2b3196moveb %d0,%a1@(APCIDATA)3197jbra L(serial_putc_done)31983:3199#endif32003201#ifdef CONFIG_VIRT3202is_not_virt(1f)32033204movel L(virt_gf_tty_base),%a13205movel %d0,%a1@(GF_PUT_CHAR)32061:3207#endif32083209L(serial_putc_done):3210func_return serial_putc32113212/*3213* Output a string.3214*/3215func_start puts,%d0/%a032163217movel ARG1,%a03218jra 2f32191:3220#ifdef CONSOLE_DEBUG3221console_putc %d03222#endif3223#ifdef SERIAL_DEBUG3224serial_putc %d03225#endif32262: moveb %a0@+,%d03227jne 1b32283229func_return puts32303231/*3232* Output number in hex notation.3233*/32343235func_start putn,%d0-%d232363237putc ' '32383239movel ARG1,%d03240moveq #7,%d132411: roll #4,%d03242move %d0,%d23243andb #0x0f,%d23244addb #'0',%d23245cmpb #'9',%d23246jls 2f3247addb #'A'-('9'+1),%d232482:3249#ifdef CONSOLE_DEBUG3250console_putc %d23251#endif3252#ifdef SERIAL_DEBUG3253serial_putc %d23254#endif3255dbra %d1,1b32563257func_return putn32583259#ifdef CONFIG_EARLY_PRINTK3260/*3261* This routine takes its parameters on the stack. It then3262* turns around and calls the internal routines. This routine3263* is used by the boot console.3264*3265* The function signature is -3266* void debug_cons_nputs(struct console *c, const char *s, unsigned int n)3267*3268* This routine does NOT understand variable arguments only3269* simple strings!3270*/3271ENTRY(debug_cons_nputs)3272moveml %d0/%d1/%a0,%sp@-3273movew %sr,%sp@-3274ori #0x0700,%sr3275movel %sp@(22),%a0 /* char *s */3276movel %sp@(26),%d1 /* unsigned int n */3277jra 2f32781:3279#ifdef CONSOLE_DEBUG3280console_putc %d03281#endif3282#ifdef SERIAL_DEBUG3283serial_putc %d03284#endif3285subq #1,%d132862: jeq 3f3287moveb %a0@+,%d03288jne 1b32893:3290movew %sp@+,%sr3291moveml %sp@+,%d0/%d1/%a03292rts3293#endif /* CONFIG_EARLY_PRINTK */32943295#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)3296func_start set_leds,%d0/%a03297movel ARG1,%d03298#ifdef CONFIG_HP3003299is_not_hp300(1f)3300movel %pc@(L(iobase)),%a03301moveb %d0,%a0@(0x1ffff)3302jra 2f3303#endif33041:3305#ifdef CONFIG_APOLLO3306movel %pc@(L(iobase)),%a03307lsll #8,%d03308eorw #0xff00,%d03309moveb %d0,%a0@(LCPUCTRL)3310#endif33112:3312func_return set_leds3313#endif33143315#ifdef CONSOLE_DEBUG3316/*3317* For continuity, see the data alignment3318* to which this structure is tied.3319*/3320#define Lconsole_struct_cur_column 03321#define Lconsole_struct_cur_row 43322#define Lconsole_struct_num_columns 83323#define Lconsole_struct_num_rows 123324#define Lconsole_struct_left_edge 1633253326func_start console_init,%a0-%a4/%d0-%d73327/*3328* Some of the register usage that follows3329* a0 = pointer to boot_info3330* a1 = pointer to screen3331* a2 = pointer to console_globals3332* d3 = pixel width of screen3333* d4 = pixel height of screen3334* (d3,d4) ~= (x,y) of a point just below3335* and to the right of the screen3336* NOT on the screen!3337* d5 = number of bytes per scan line3338* d6 = number of bytes on the entire screen3339*/33403341lea %pc@(L(console_globals)),%a23342movel %pc@(L(mac_videobase)),%a13343movel %pc@(L(mac_rowbytes)),%d53344movel %pc@(L(mac_dimensions)),%d3 /* -> low byte */3345movel %d3,%d43346swap %d4 /* -> high byte */3347andl #0xffff,%d3 /* d3 = screen width in pixels */3348andl #0xffff,%d4 /* d4 = screen height in pixels */33493350movel %d5,%d63351| subl #20,%d63352mulul %d4,%d6 /* scan line bytes x num scan lines */3353divul #8,%d6 /* we'll clear 8 bytes at a time */3354moveq #-1,%d0 /* Mac_black */3355subq #1,%d633563357L(console_clear_loop):3358movel %d0,%a1@+3359movel %d0,%a1@+3360dbra %d6,L(console_clear_loop)33613362/* Calculate font size */33633364#if defined(FONT_8x8) && defined(CONFIG_FONT_8x8)3365lea %pc@(font_vga_8x8),%a03366#elif defined(FONT_8x16) && defined(CONFIG_FONT_8x16)3367lea %pc@(font_vga_8x16),%a03368#elif defined(FONT_6x11) && defined(CONFIG_FONT_6x11)3369lea %pc@(font_vga_6x11),%a03370#elif defined(CONFIG_FONT_8x8) /* default */3371lea %pc@(font_vga_8x8),%a03372#else /* no compiled-in font */3373lea 0,%a03374#endif33753376/*3377* At this point we make a shift in register usage3378* a1 = address of console_font pointer3379*/3380lea %pc@(L(console_font)),%a13381movel %a0,%a1@ /* store pointer to struct fbcon_font_desc in console_font */3382tstl %a03383jeq 1f3384lea %pc@(L(console_font_data)),%a43385movel %a0@(FONT_DESC_DATA),%d03386subl #L(console_font),%a13387addl %a1,%d03388movel %d0,%a4@33893390/*3391* Calculate global maxs3392* Note - we can use either an3393* 8 x 16 or 8 x 8 character font3394* 6 x 11 also supported3395*/3396/* ASSERT: a0 = contents of Lconsole_font */3397movel %d3,%d0 /* screen width in pixels */3398divul %a0@(FONT_DESC_WIDTH),%d0 /* d0 = max num chars per row */33993400movel %d4,%d1 /* screen height in pixels */3401divul %a0@(FONT_DESC_HEIGHT),%d1 /* d1 = max num rows */3402subql #1,%d1 /* row range is 0 to num - 1 */34033404movel %d0,%a2@(Lconsole_struct_num_columns)3405movel %d1,%a2@(Lconsole_struct_num_rows)34063407/*3408* Clear the current row and column3409*/3410clrl %a2@(Lconsole_struct_cur_column)3411clrl %a2@(Lconsole_struct_cur_row)3412clrl %a2@(Lconsole_struct_left_edge)34133414/*3415* Initialization is complete3416*/34171:3418func_return console_init34193420#ifdef CONFIG_LOGO3421func_start console_put_penguin,%a0-%a1/%d0-%d73422/*3423* Get 'that_penguin' onto the screen in the upper right corner3424* penguin is 64 x 74 pixels, align against right edge of screen3425*/3426lea %pc@(L(mac_dimensions)),%a03427movel %a0@,%d03428andil #0xffff,%d03429subil #64,%d0 /* snug up against the right edge */3430clrl %d1 /* start at the top */3431movel #73,%d73432lea %pc@(L(that_penguin)),%a13433L(console_penguin_row):3434movel #31,%d63435L(console_penguin_pixel_pair):3436moveb %a1@,%d23437lsrb #4,%d23438console_plot_pixel %d0,%d1,%d23439addq #1,%d03440moveb %a1@+,%d23441console_plot_pixel %d0,%d1,%d23442addq #1,%d03443dbra %d6,L(console_penguin_pixel_pair)34443445subil #64,%d03446addq #1,%d13447dbra %d7,L(console_penguin_row)34483449func_return console_put_penguin34503451/* include penguin bitmap */3452L(that_penguin):3453#include "../mac/mac_penguin.S"3454#endif34553456/*3457* Calculate source and destination addresses3458* output a1 = dest3459* a2 = source3460*/34613462func_start console_scroll,%a0-%a4/%d0-%d73463lea %pc@(L(mac_videobase)),%a03464movel %a0@,%a13465movel %a1,%a23466lea %pc@(L(mac_rowbytes)),%a03467movel %a0@,%d53468movel %pc@(L(console_font)),%a03469tstl %a03470jeq 1f3471mulul %a0@(FONT_DESC_HEIGHT),%d5 /* account for # scan lines per character */3472addal %d5,%a234733474/*3475* Get dimensions3476*/3477lea %pc@(L(mac_dimensions)),%a03478movel %a0@,%d33479movel %d3,%d43480swap %d43481andl #0xffff,%d3 /* d3 = screen width in pixels */3482andl #0xffff,%d4 /* d4 = screen height in pixels */34833484/*3485* Calculate number of bytes to move3486*/3487lea %pc@(L(mac_rowbytes)),%a03488movel %a0@,%d63489movel %pc@(L(console_font)),%a03490subl %a0@(FONT_DESC_HEIGHT),%d4 /* we're not scrolling the top row! */3491mulul %d4,%d6 /* scan line bytes x num scan lines */3492divul #32,%d6 /* we'll move 8 longs at a time */3493subq #1,%d634943495L(console_scroll_loop):3496movel %a2@+,%a1@+3497movel %a2@+,%a1@+3498movel %a2@+,%a1@+3499movel %a2@+,%a1@+3500movel %a2@+,%a1@+3501movel %a2@+,%a1@+3502movel %a2@+,%a1@+3503movel %a2@+,%a1@+3504dbra %d6,L(console_scroll_loop)35053506lea %pc@(L(mac_rowbytes)),%a03507movel %a0@,%d63508movel %pc@(L(console_font)),%a03509mulul %a0@(FONT_DESC_HEIGHT),%d6 /* scan line bytes x font height */3510divul #32,%d6 /* we'll move 8 words at a time */3511subq #1,%d635123513moveq #-1,%d03514L(console_scroll_clear_loop):3515movel %d0,%a1@+3516movel %d0,%a1@+3517movel %d0,%a1@+3518movel %d0,%a1@+3519movel %d0,%a1@+3520movel %d0,%a1@+3521movel %d0,%a1@+3522movel %d0,%a1@+3523dbra %d6,L(console_scroll_clear_loop)352435251:3526func_return console_scroll352735283529func_start console_putc,%a0/%a1/%d0-%d735303531is_not_mac(L(console_exit))3532tstl %pc@(L(console_font))3533jeq L(console_exit)35343535lea %pc@(L(console_globals)),%a035363537/* Output character in d7 on console.3538*/3539movel ARG1,%d73540cmpib #'\n',%d73541jne L(console_not_lf)35423543clrl %a0@(Lconsole_struct_cur_column) /* implicit \r */35443545movel %a0@(Lconsole_struct_cur_row),%d03546movel %a0@(Lconsole_struct_num_rows),%d13547cmpl %d1,%d03548jcs 1f3549console_scroll3550jra L(console_exit)35511:3552addql #1,%d03553movel %d0,%a0@(Lconsole_struct_cur_row)3554jra L(console_exit)35553556L(console_not_lf):3557cmpib #'\r',%d73558jne L(console_not_lf_not_cr)3559clrl %a0@(Lconsole_struct_cur_column)3560jra L(console_exit)35613562/*3563* At this point we know that the %d7 character is going to be3564* rendered on the screen. Register usage is -3565* a0 = pointer to console globals3566* a1 = font data3567* d0 = cursor column3568* d1 = cursor row to draw the character3569* d7 = character number3570*/3571L(console_not_lf_not_cr):3572movel %a0@(Lconsole_struct_cur_column),%d03573movel %a0@(Lconsole_struct_cur_row),%d135743575/*3576* At this point we make a shift in register usage3577* a0 = address of pointer to font data (fbcon_font_desc)3578*/3579movel %pc@(L(console_font)),%a03580movel %pc@(L(console_font_data)),%a1 /* Load fbcon_font_desc.data into a1 */3581andl #0x000000ff,%d73582/* ASSERT: a0 = contents of Lconsole_font */3583mulul %a0@(FONT_DESC_HEIGHT),%d7 /* d7 = index into font data */3584addl %d7,%a1 /* a1 = points to char image */35853586/*3587* At this point we make a shift in register usage3588* d0 = pixel coordinate, x3589* d1 = pixel coordinate, y3590* d2 = (bit 0) 1/0 for white/black (!) pixel on screen3591* d3 = font scan line data (8 pixels)3592* d6 = count down for the font's pixel width (8)3593* d7 = count down for the font's pixel count in height3594*/3595/* ASSERT: a0 = contents of Lconsole_font */3596mulul %a0@(FONT_DESC_WIDTH),%d03597mulul %a0@(FONT_DESC_HEIGHT),%d13598movel %a0@(FONT_DESC_HEIGHT),%d7 /* Load fbcon_font_desc.height into d7 */3599subq #1,%d73600L(console_read_char_scanline):3601moveb %a1@+,%d336023603/* ASSERT: a0 = contents of Lconsole_font */3604movel %a0@(FONT_DESC_WIDTH),%d6 /* Load fbcon_font_desc.width into d6 */3605subql #1,%d636063607L(console_do_font_scanline):3608lslb #1,%d33609scsb %d2 /* convert 1 bit into a byte */3610console_plot_pixel %d0,%d1,%d23611addq #1,%d03612dbra %d6,L(console_do_font_scanline)36133614/* ASSERT: a0 = contents of Lconsole_font */3615subl %a0@(FONT_DESC_WIDTH),%d03616addq #1,%d13617dbra %d7,L(console_read_char_scanline)36183619/*3620* Register usage in the code below:3621* a0 = pointer to console globals3622* d0 = cursor column3623* d1 = cursor column limit3624*/36253626lea %pc@(L(console_globals)),%a036273628movel %a0@(Lconsole_struct_cur_column),%d03629addql #1,%d03630movel %d0,%a0@(Lconsole_struct_cur_column) /* Update cursor pos */3631movel %a0@(Lconsole_struct_num_columns),%d13632cmpl %d1,%d03633jcs L(console_exit)3634console_putc #'\n' /* Line wrap using tail recursion */36353636L(console_exit):3637func_return console_putc36383639/*3640* Input:3641* d0 = x coordinate3642* d1 = y coordinate3643* d2 = (bit 0) 1/0 for white/black (!)3644* All registers are preserved3645*/3646func_start console_plot_pixel,%a0-%a1/%d0-%d436473648movel %pc@(L(mac_videobase)),%a13649movel %pc@(L(mac_videodepth)),%d33650movel ARG1,%d03651movel ARG2,%d13652mulul %pc@(L(mac_rowbytes)),%d13653movel ARG3,%d236543655/*3656* Register usage:3657* d0 = x coord becomes byte offset into frame buffer3658* d1 = y coord3659* d2 = black or white (0/1)3660* d3 = video depth3661* d4 = temp of x (d0) for many bit depths3662*/3663L(test_1bit):3664cmpb #1,%d33665jbne L(test_2bit)3666movel %d0,%d4 /* we need the low order 3 bits! */3667divul #8,%d03668addal %d0,%a13669addal %d1,%a13670andb #7,%d43671eorb #7,%d4 /* reverse the x-coordinate w/ screen-bit # */3672andb #1,%d23673jbne L(white_1)3674bsetb %d4,%a1@3675jbra L(console_plot_pixel_exit)3676L(white_1):3677bclrb %d4,%a1@3678jbra L(console_plot_pixel_exit)36793680L(test_2bit):3681cmpb #2,%d33682jbne L(test_4bit)3683movel %d0,%d4 /* we need the low order 2 bits! */3684divul #4,%d03685addal %d0,%a13686addal %d1,%a13687andb #3,%d43688eorb #3,%d4 /* reverse the x-coordinate w/ screen-bit # */3689lsll #1,%d4 /* ! */3690andb #1,%d23691jbne L(white_2)3692bsetb %d4,%a1@3693addq #1,%d43694bsetb %d4,%a1@3695jbra L(console_plot_pixel_exit)3696L(white_2):3697bclrb %d4,%a1@3698addq #1,%d43699bclrb %d4,%a1@3700jbra L(console_plot_pixel_exit)37013702L(test_4bit):3703cmpb #4,%d33704jbne L(test_8bit)3705movel %d0,%d4 /* we need the low order bit! */3706divul #2,%d03707addal %d0,%a13708addal %d1,%a13709andb #1,%d43710eorb #1,%d43711lsll #2,%d4 /* ! */3712andb #1,%d23713jbne L(white_4)3714bsetb %d4,%a1@3715addq #1,%d43716bsetb %d4,%a1@3717addq #1,%d43718bsetb %d4,%a1@3719addq #1,%d43720bsetb %d4,%a1@3721jbra L(console_plot_pixel_exit)3722L(white_4):3723bclrb %d4,%a1@3724addq #1,%d43725bclrb %d4,%a1@3726addq #1,%d43727bclrb %d4,%a1@3728addq #1,%d43729bclrb %d4,%a1@3730jbra L(console_plot_pixel_exit)37313732L(test_8bit):3733cmpb #8,%d33734jbne L(test_16bit)3735addal %d0,%a13736addal %d1,%a13737andb #1,%d23738jbne L(white_8)3739moveb #0xff,%a1@3740jbra L(console_plot_pixel_exit)3741L(white_8):3742clrb %a1@3743jbra L(console_plot_pixel_exit)37443745L(test_16bit):3746cmpb #16,%d33747jbne L(console_plot_pixel_exit)3748addal %d0,%a13749addal %d0,%a13750addal %d1,%a13751andb #1,%d23752jbne L(white_16)3753clrw %a1@3754jbra L(console_plot_pixel_exit)3755L(white_16):3756movew #0x0fff,%a1@3757jbra L(console_plot_pixel_exit)37583759L(console_plot_pixel_exit):3760func_return console_plot_pixel3761#endif /* CONSOLE_DEBUG */376237633764__INITDATA3765.align 437663767m68k_init_mapped_size:3768.long 037693770#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || \3771defined(CONFIG_HP300) || defined(CONFIG_APOLLO)3772L(custom):3773L(iobase):3774.long 03775#endif37763777#ifdef CONSOLE_DEBUG3778L(console_globals):3779.long 0 /* cursor column */3780.long 0 /* cursor row */3781.long 0 /* max num columns */3782.long 0 /* max num rows */3783.long 0 /* left edge */3784L(console_font):3785.long 0 /* pointer to console font (struct font_desc) */3786L(console_font_data):3787.long 0 /* pointer to console font data */3788#endif /* CONSOLE_DEBUG */37893790#if defined(MMU_PRINT)3791L(mmu_print_data):3792.long 0 /* valid flag */3793.long 0 /* start logical */3794.long 0 /* next logical */3795.long 0 /* start physical */3796.long 0 /* next physical */3797#endif /* MMU_PRINT */37983799L(cputype):3800.long 03801L(mmu_cached_pointer_tables):3802.long 03803L(mmu_num_pointer_tables):3804.long 03805L(phys_kernel_start):3806.long 03807L(kernel_end):3808.long 03809L(memory_start):3810.long 03811L(kernel_pgdir_ptr):3812.long 03813L(temp_mmap_mem):3814.long 038153816#if defined (CONFIG_MVME147)3817M147_SCC_CTRL_A = 0xfffe30023818M147_SCC_DATA_A = 0xfffe30033819#endif38203821#if defined (CONFIG_MVME16x)3822M162_SCC_CTRL_A = 0xfff450053823M167_CYCAR = 0xfff450ee3824M167_CYIER = 0xfff450113825M167_CYLICR = 0xfff450263826M167_CYTEOIR = 0xfff450853827M167_CYTDR = 0xfff450f83828M167_PCSCCMICR = 0xfff4201d3829M167_PCSCCTICR = 0xfff4201e3830M167_PCSCCRICR = 0xfff4201f3831M167_PCTPIACKR = 0xfff420253832#endif38333834#if defined (CONFIG_BVME6000)3835BVME_SCC_CTRL_A = 0xffb0000b3836BVME_SCC_DATA_A = 0xffb0000f3837#endif38383839#if defined(CONFIG_MAC)3840L(mac_videobase):3841.long 03842L(mac_videodepth):3843.long 03844L(mac_dimensions):3845.long 03846L(mac_rowbytes):3847.long 03848L(mac_sccbase):3849.long 03850#endif /* CONFIG_MAC */38513852#if defined (CONFIG_APOLLO)3853LSRB0 = 0x104123854LTHRB0 = 0x104163855LCPUCTRL = 0x101003856#endif38573858#if defined(CONFIG_HP300)3859DCADATA = 0x113860DCALSR = 0x1b3861APCIDATA = 0x003862APCILSR = 0x143863L(uartbase):3864.long 03865L(uart_scode):3866.long -13867#endif38683869__FINIT3870.data3871.align 438723873availmem:3874.long 03875m68k_pgtable_cachemode:3876.long 03877m68k_supervisor_cachemode:3878.long 03879#if defined(CONFIG_MVME16x)3880mvme_bdid:3881.long 0,0,0,0,0,0,0,03882#endif3883#if defined(CONFIG_Q40)3884q40_mem_cptr:3885.long 03886L(q40_do_debug):3887.long 03888#endif38893890#if defined(CONFIG_VIRT)3891GF_PUT_CHAR = 0x003892L(virt_gf_tty_base):3893.long 03894#endif /* CONFIG_VIRT */389538963897