/* -*- mode: asm -*-1**2** head.S -- This file contains the initial boot code for the3** Linux/68k kernel.4**5** Copyright 1993 by Hamish Macdonald6**7** 68040 fixes by Michael Rausch8** 68060 fixes by Roman Hodek9** MMU cleanup by Randy Thelen10** Final MMU cleanup by Roman Zippel11**12** Atari support by Andreas Schwab, using ideas of Robert de Vries13** and Bjoern Brauel14** VME Support by Richard Hirst15**16** 94/11/14 Andreas Schwab: put kernel at PAGESIZE17** 94/11/18 Andreas Schwab: remove identity mapping of STRAM for Atari18** ++ Bjoern & Roman: ATARI-68040 support for the Medusa19** 95/11/18 Richard Hirst: Added MVME166 support20** 96/04/26 Guenther Kelleter: fixed identity mapping for Falcon with21** Magnum- and FX-alternate ram22** 98/04/25 Phil Blundell: added HP300 support23** 1998/08/30 David Kilzer: Added support for font_desc structures24** for linux-2.1.11525** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01)26** 2004/05/13 Kars de Jong: Finalised HP300 support27**28** This file is subject to the terms and conditions of the GNU General Public29** License. See the file README.legal in the main directory of this archive30** for more details.31**32*/3334/*35* Linux startup code.36*37* At this point, the boot loader has:38* Disabled interrupts39* Disabled caches40* Put us in supervisor state.41*42* The kernel setup code takes the following steps:43* . Raise interrupt level44* . Set up initial kernel memory mapping.45* . This sets up a mapping of the 4M of memory the kernel is located in.46* . It also does a mapping of any initial machine specific areas.47* . Enable the MMU48* . Enable cache memories49* . Jump to kernel startup50*51* Much of the file restructuring was to accomplish:52* 1) Remove register dependency through-out the file.53* 2) Increase use of subroutines to perform functions54* 3) Increase readability of the code55*56* Of course, readability is a subjective issue, so it will never be57* argued that that goal was accomplished. It was merely a goal.58* A key way to help make code more readable is to give good59* documentation. So, the first thing you will find is exaustive60* write-ups on the structure of the file, and the features of the61* functional subroutines.62*63* General Structure:64* ------------------65* Without a doubt the single largest chunk of head.S is spent66* mapping the kernel and I/O physical space into the logical range67* for the kernel.68* There are new subroutines and data structures to make MMU69* support cleaner and easier to understand.70* First, you will find a routine call "mmu_map" which maps71* a logical to a physical region for some length given a cache72* type on behalf of the caller. This routine makes writing the73* actual per-machine specific code very simple.74* A central part of the code, but not a subroutine in itself,75* is the mmu_init code which is broken down into mapping the kernel76* (the same for all machines) and mapping machine-specific I/O77* regions.78* Also, there will be a description of engaging the MMU and79* caches.80* You will notice that there is a chunk of code which81* can emit the entire MMU mapping of the machine. This is present82* only in debug modes and can be very helpful.83* Further, there is a new console driver in head.S that is84* also only engaged in debug mode. Currently, it's only supported85* on the Macintosh class of machines. However, it is hoped that86* others will plug-in support for specific machines.87*88* ######################################################################89*90* mmu_map91* -------92* mmu_map was written for two key reasons. First, it was clear93* that it was very difficult to read the previous code for mapping94* regions of memory. Second, the Macintosh required such extensive95* memory allocations that it didn't make sense to propagate the96* existing code any further.97* mmu_map requires some parameters:98*99* mmu_map (logical, physical, length, cache_type)100*101* While this essentially describes the function in the abstract, you'll102* find more indepth description of other parameters at the implementation site.103*104* mmu_get_root_table_entry105* ------------------------106* mmu_get_ptr_table_entry107* -----------------------108* mmu_get_page_table_entry109* ------------------------110*111* These routines are used by other mmu routines to get a pointer into112* a table, if necessary a new table is allocated. These routines are working113* basically like pmd_alloc() and pte_alloc() in <asm/pgtable.h>. The root114* table needs of course only to be allocated once in mmu_get_root_table_entry,115* so that here also some mmu specific initialization is done. The second page116* at the start of the kernel (the first page is unmapped later) is used for117* the kernel_pg_dir. It must be at a position known at link time (as it's used118* to initialize the init task struct) and since it needs special cache119* settings, it's the easiest to use this page, the rest of the page is used120* for further pointer tables.121* mmu_get_page_table_entry allocates always a whole page for page tables, this122* means 1024 pages and so 4MB of memory can be mapped. It doesn't make sense123* to manage page tables in smaller pieces as nearly all mappings have that124* size.125*126* ######################################################################127*128*129* ######################################################################130*131* mmu_engage132* ----------133* Thanks to a small helping routine enabling the mmu got quite simple134* and there is only one way left. mmu_engage makes a complete a new mapping135* that only includes the absolute necessary to be able to jump to the final136* position and to restore the original mapping.137* As this code doesn't need a transparent translation register anymore this138* means all registers are free to be used by machines that needs them for139* other purposes.140*141* ######################################################################142*143* mmu_print144* ---------145* This algorithm will print out the page tables of the system as146* appropriate for an 030 or an 040. This is useful for debugging purposes147* and as such is enclosed in #ifdef MMU_PRINT/#endif clauses.148*149* ######################################################################150*151* console_init152* ------------153* The console is also able to be turned off. The console in head.S154* is specifically for debugging and can be very useful. It is surrounded by155* #ifdef CONSOLE/#endif clauses so it doesn't have to ship in known-good156* kernels. It's basic algorithm is to determine the size of the screen157* (in height/width and bit depth) and then use that information for158* displaying an 8x8 font or an 8x16 (widthxheight). I prefer the 8x8 for159* debugging so I can see more good data. But it was trivial to add support160* for both fonts, so I included it.161* Also, the algorithm for plotting pixels is abstracted so that in162* theory other platforms could add support for different kinds of frame163* buffers. This could be very useful.164*165* console_put_penguin166* -------------------167* An important part of any Linux bring up is the penguin and there's168* nothing like getting the Penguin on the screen! This algorithm will work169* on any machine for which there is a console_plot_pixel.170*171* console_scroll172* --------------173* My hope is that the scroll algorithm does the right thing on the174* various platforms, but it wouldn't be hard to add the test conditions175* and new code if it doesn't.176*177* console_putc178* -------------179*180* ######################################################################181*182* Register usage has greatly simplified within head.S. Every subroutine183* saves and restores all registers that it modifies (except it returns a184* value in there of course). So the only register that needs to be initialized185* is the stack pointer.186* All other init code and data is now placed in the init section, so it will187* be automatically freed at the end of the kernel initialization.188*189* ######################################################################190*191* options192* -------193* There are many options available in a build of this file. I've194* taken the time to describe them here to save you the time of searching195* for them and trying to understand what they mean.196*197* CONFIG_xxx: These are the obvious machine configuration defines created198* during configuration. These are defined in autoconf.h.199*200* CONSOLE: There is support for head.S console in this file. This201* console can talk to a Mac frame buffer, but could easily be extrapolated202* to extend it to support other platforms.203*204* TEST_MMU: This is a test harness for running on any given machine but205* getting an MMU dump for another class of machine. The classes of machines206* that can be tested are any of the makes (Atari, Amiga, Mac, VME, etc.)207* and any of the models (030, 040, 060, etc.).208*209* NOTE: TEST_MMU is NOT permanent! It is scheduled to be removed210* When head.S boots on Atari, Amiga, Macintosh, and VME211* machines. At that point the underlying logic will be212* believed to be solid enough to be trusted, and TEST_MMU213* can be dropped. Do note that that will clean up the214* head.S code significantly as large blocks of #if/#else215* clauses can be removed.216*217* MMU_NOCACHE_KERNEL: On the Macintosh platform there was an inquiry into218* determing why devices don't appear to work. A test case was to remove219* the cacheability of the kernel bits.220*221* MMU_PRINT: There is a routine built into head.S that can display the222* MMU data structures. It outputs its result through the serial_putc223* interface. So where ever that winds up driving data, that's where the224* mmu struct will appear. On the Macintosh that's typically the console.225*226* SERIAL_DEBUG: There are a series of putc() macro statements227* scattered through out the code to give progress of status to the228* person sitting at the console. This constant determines whether those229* are used.230*231* DEBUG: This is the standard DEBUG flag that can be set for building232* the kernel. It has the effect adding additional tests into233* the code.234*235* FONT_6x11:236* FONT_8x8:237* FONT_8x16:238* In theory these could be determined at run time or handed239* over by the booter. But, let's be real, it's a fine hard240* coded value. (But, you will notice the code is run-time241* flexible!) A pointer to the font's struct font_desc242* is kept locally in Lconsole_font. It is used to determine243* font size information dynamically.244*245* Atari constants:246* USE_PRINTER: Use the printer port for serial debug.247* USE_SCC_B: Use the SCC port A (Serial2) for serial debug.248* USE_SCC_A: Use the SCC port B (Modem2) for serial debug.249* USE_MFP: Use the ST-MFP port (Modem1) for serial debug.250*251* Macintosh constants:252* MAC_SERIAL_DEBUG: Turns on serial debug output for the Macintosh.253* MAC_USE_SCC_A: Use the SCC port A (modem) for serial debug.254* MAC_USE_SCC_B: Use the SCC port B (printer) for serial debug (default).255*/256257#include <linux/linkage.h>258#include <linux/init.h>259#include <asm/bootinfo.h>260#include <asm/setup.h>261#include <asm/entry.h>262#include <asm/pgtable.h>263#include <asm/page.h>264#include <asm/asm-offsets.h>265266#ifdef CONFIG_MAC267268#include <asm/machw.h>269270/*271* Macintosh console support272*/273274#ifdef CONFIG_FRAMEBUFFER_CONSOLE275#define CONSOLE276#define CONSOLE_PENGUIN277#endif278279/*280* Macintosh serial debug support; outputs boot info to the printer281* and/or modem serial ports282*/283#undef MAC_SERIAL_DEBUG284285/*286* Macintosh serial debug port selection; define one or both;287* requires MAC_SERIAL_DEBUG to be defined288*/289#define MAC_USE_SCC_A /* Macintosh modem serial port */290#define MAC_USE_SCC_B /* Macintosh printer serial port */291292#endif /* CONFIG_MAC */293294#undef MMU_PRINT295#undef MMU_NOCACHE_KERNEL296#define SERIAL_DEBUG297#undef DEBUG298299/*300* For the head.S console, there are three supported fonts, 6x11, 8x16 and 8x8.301* The 8x8 font is harder to read but fits more on the screen.302*/303#define FONT_8x8 /* default */304/* #define FONT_8x16 */ /* 2nd choice */305/* #define FONT_6x11 */ /* 3rd choice */306307.globl kernel_pg_dir308.globl availmem309.globl m68k_pgtable_cachemode310.globl m68k_supervisor_cachemode311#ifdef CONFIG_MVME16x312.globl mvme_bdid313#endif314#ifdef CONFIG_Q40315.globl q40_mem_cptr316#endif317318CPUTYPE_040 = 1 /* indicates an 040 */319CPUTYPE_060 = 2 /* indicates an 060 */320CPUTYPE_0460 = 3 /* if either above are set, this is set */321CPUTYPE_020 = 4 /* indicates an 020 */322323/* Translation control register */324TC_ENABLE = 0x8000325TC_PAGE8K = 0x4000326TC_PAGE4K = 0x0000327328/* Transparent translation registers */329TTR_ENABLE = 0x8000 /* enable transparent translation */330TTR_ANYMODE = 0x4000 /* user and kernel mode access */331TTR_KERNELMODE = 0x2000 /* only kernel mode access */332TTR_USERMODE = 0x0000 /* only user mode access */333TTR_CI = 0x0400 /* inhibit cache */334TTR_RW = 0x0200 /* read/write mode */335TTR_RWM = 0x0100 /* read/write mask */336TTR_FCB2 = 0x0040 /* function code base bit 2 */337TTR_FCB1 = 0x0020 /* function code base bit 1 */338TTR_FCB0 = 0x0010 /* function code base bit 0 */339TTR_FCM2 = 0x0004 /* function code mask bit 2 */340TTR_FCM1 = 0x0002 /* function code mask bit 1 */341TTR_FCM0 = 0x0001 /* function code mask bit 0 */342343/* Cache Control registers */344CC6_ENABLE_D = 0x80000000 /* enable data cache (680[46]0) */345CC6_FREEZE_D = 0x40000000 /* freeze data cache (68060) */346CC6_ENABLE_SB = 0x20000000 /* enable store buffer (68060) */347CC6_PUSH_DPI = 0x10000000 /* disable CPUSH invalidation (68060) */348CC6_HALF_D = 0x08000000 /* half-cache mode for data cache (68060) */349CC6_ENABLE_B = 0x00800000 /* enable branch cache (68060) */350CC6_CLRA_B = 0x00400000 /* clear all entries in branch cache (68060) */351CC6_CLRU_B = 0x00200000 /* clear user entries in branch cache (68060) */352CC6_ENABLE_I = 0x00008000 /* enable instruction cache (680[46]0) */353CC6_FREEZE_I = 0x00004000 /* freeze instruction cache (68060) */354CC6_HALF_I = 0x00002000 /* half-cache mode for instruction cache (68060) */355CC3_ALLOC_WRITE = 0x00002000 /* write allocate mode(68030) */356CC3_ENABLE_DB = 0x00001000 /* enable data burst (68030) */357CC3_CLR_D = 0x00000800 /* clear data cache (68030) */358CC3_CLRE_D = 0x00000400 /* clear entry in data cache (68030) */359CC3_FREEZE_D = 0x00000200 /* freeze data cache (68030) */360CC3_ENABLE_D = 0x00000100 /* enable data cache (68030) */361CC3_ENABLE_IB = 0x00000010 /* enable instruction burst (68030) */362CC3_CLR_I = 0x00000008 /* clear instruction cache (68030) */363CC3_CLRE_I = 0x00000004 /* clear entry in instruction cache (68030) */364CC3_FREEZE_I = 0x00000002 /* freeze instruction cache (68030) */365CC3_ENABLE_I = 0x00000001 /* enable instruction cache (68030) */366367/* Miscellaneous definitions */368PAGESIZE = 4096369PAGESHIFT = 12370371ROOT_TABLE_SIZE = 128372PTR_TABLE_SIZE = 128373PAGE_TABLE_SIZE = 64374ROOT_INDEX_SHIFT = 25375PTR_INDEX_SHIFT = 18376PAGE_INDEX_SHIFT = 12377378#ifdef DEBUG379/* When debugging use readable names for labels */380#ifdef __STDC__381#define L(name) .head.S.##name382#else383#define L(name) .head.S./**/name384#endif385#else386#ifdef __STDC__387#define L(name) .L##name388#else389#define L(name) .L/**/name390#endif391#endif392393/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */394#ifndef __INITDATA395#define __INITDATA .data396#define __FINIT .previous397#endif398399/* Several macros to make the writing of subroutines easier:400* - func_start marks the beginning of the routine which setups the frame401* register and saves the registers, it also defines another macro402* to automatically restore the registers again.403* - func_return marks the end of the routine and simply calls the prepared404* macro to restore registers and jump back to the caller.405* - func_define generates another macro to automatically put arguments406* onto the stack call the subroutine and cleanup the stack again.407*/408409/* Within subroutines these macros can be used to access the arguments410* on the stack. With STACK some allocated memory on the stack can be411* accessed and ARG0 points to the return address (used by mmu_engage).412*/413#define STACK %a6@(stackstart)414#define ARG0 %a6@(4)415#define ARG1 %a6@(8)416#define ARG2 %a6@(12)417#define ARG3 %a6@(16)418#define ARG4 %a6@(20)419420.macro func_start name,saveregs,stack=0421L(\name):422linkw %a6,#-\stack423moveml \saveregs,%sp@-424.set stackstart,-\stack425426.macro func_return_\name427moveml %sp@+,\saveregs428unlk %a6429rts430.endm431.endm432433.macro func_return name434func_return_\name435.endm436437.macro func_call name438jbsr L(\name)439.endm440441.macro move_stack nr,arg1,arg2,arg3,arg4442.if \nr443move_stack "(\nr-1)",\arg2,\arg3,\arg4444movel \arg1,%sp@-445.endif446.endm447448.macro func_define name,nr=0449.macro \name arg1,arg2,arg3,arg4450move_stack \nr,\arg1,\arg2,\arg3,\arg4451func_call \name452.if \nr453lea %sp@(\nr*4),%sp454.endif455.endm456.endm457458func_define mmu_map,4459func_define mmu_map_tt,4460func_define mmu_fixup_page_mmu_cache,1461func_define mmu_temp_map,2462func_define mmu_engage463func_define mmu_get_root_table_entry,1464func_define mmu_get_ptr_table_entry,2465func_define mmu_get_page_table_entry,2466func_define mmu_print467func_define get_new_page468#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)469func_define set_leds470#endif471472.macro mmu_map_eq arg1,arg2,arg3473mmu_map \arg1,\arg1,\arg2,\arg3474.endm475476.macro get_bi_record record477pea \record478func_call get_bi_record479addql #4,%sp480.endm481482func_define serial_putc,1483func_define console_putc,1484485func_define console_init486func_define console_put_stats487func_define console_put_penguin488func_define console_plot_pixel,3489func_define console_scroll490491.macro putc ch492#if defined(CONSOLE) || defined(SERIAL_DEBUG)493pea \ch494#endif495#ifdef CONSOLE496func_call console_putc497#endif498#ifdef SERIAL_DEBUG499func_call serial_putc500#endif501#if defined(CONSOLE) || defined(SERIAL_DEBUG)502addql #4,%sp503#endif504.endm505506.macro dputc ch507#ifdef DEBUG508putc \ch509#endif510.endm511512func_define putn,1513514.macro dputn nr515#ifdef DEBUG516putn \nr517#endif518.endm519520.macro puts string521#if defined(CONSOLE) || defined(SERIAL_DEBUG)522__INITDATA523.Lstr\@:524.string "\string"525__FINIT526pea %pc@(.Lstr\@)527func_call puts528addql #4,%sp529#endif530.endm531532.macro dputs string533#ifdef DEBUG534puts "\string"535#endif536.endm537538#define is_not_amiga(lab) cmpl &MACH_AMIGA,%pc@(m68k_machtype); jne lab539#define is_not_atari(lab) cmpl &MACH_ATARI,%pc@(m68k_machtype); jne lab540#define is_not_mac(lab) cmpl &MACH_MAC,%pc@(m68k_machtype); jne lab541#define is_not_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jne lab542#define is_not_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jne lab543#define is_not_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jne lab544#define is_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jeq lab545#define is_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jeq lab546#define is_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jeq lab547#define is_not_hp300(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); jne lab548#define is_not_apollo(lab) cmpl &MACH_APOLLO,%pc@(m68k_machtype); jne lab549#define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab550#define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab551552#define hasnt_leds(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); \553jeq 42f; \554cmpl &MACH_APOLLO,%pc@(m68k_machtype); \555jne lab ;\55642:\557558#define is_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jne lab559#define is_not_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jeq lab560#define is_040(lab) btst &CPUTYPE_040,%pc@(L(cputype)+3); jne lab561#define is_060(lab) btst &CPUTYPE_060,%pc@(L(cputype)+3); jne lab562#define is_not_060(lab) btst &CPUTYPE_060,%pc@(L(cputype)+3); jeq lab563#define is_020(lab) btst &CPUTYPE_020,%pc@(L(cputype)+3); jne lab564#define is_not_020(lab) btst &CPUTYPE_020,%pc@(L(cputype)+3); jeq lab565566/* On the HP300 we use the on-board LEDs for debug output before567the console is running. Writing a 1 bit turns the corresponding LED568_off_ - on the 340 bit 7 is towards the back panel of the machine. */569.macro leds mask570#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)571hasnt_leds(.Lled\@)572pea \mask573func_call set_leds574addql #4,%sp575.Lled\@:576#endif577.endm578579__HEAD580ENTRY(_stext)581/*582* Version numbers of the bootinfo interface583* The area from _stext to _start will later be used as kernel pointer table584*/585bras 1f /* Jump over bootinfo version numbers */586587.long BOOTINFOV_MAGIC588.long MACH_AMIGA, AMIGA_BOOTI_VERSION589.long MACH_ATARI, ATARI_BOOTI_VERSION590.long MACH_MVME147, MVME147_BOOTI_VERSION591.long MACH_MVME16x, MVME16x_BOOTI_VERSION592.long MACH_BVME6000, BVME6000_BOOTI_VERSION593.long MACH_MAC, MAC_BOOTI_VERSION594.long MACH_Q40, Q40_BOOTI_VERSION595.long MACH_HP300, HP300_BOOTI_VERSION596.long 05971: jra __start598599.equ kernel_pg_dir,_stext600601.equ .,_stext+PAGESIZE602603ENTRY(_start)604jra __start605__INIT606ENTRY(__start)607/*608* Setup initial stack pointer609*/610lea %pc@(_stext),%sp611612/*613* Record the CPU and machine type.614*/615get_bi_record BI_MACHTYPE616lea %pc@(m68k_machtype),%a1617movel %a0@,%a1@618619get_bi_record BI_FPUTYPE620lea %pc@(m68k_fputype),%a1621movel %a0@,%a1@622623get_bi_record BI_MMUTYPE624lea %pc@(m68k_mmutype),%a1625movel %a0@,%a1@626627get_bi_record BI_CPUTYPE628lea %pc@(m68k_cputype),%a1629movel %a0@,%a1@630631leds 0x1632633#ifdef CONFIG_MAC634/*635* For Macintosh, we need to determine the display parameters early (at least636* while debugging it).637*/638639is_not_mac(L(test_notmac))640641get_bi_record BI_MAC_VADDR642lea %pc@(L(mac_videobase)),%a1643movel %a0@,%a1@644645get_bi_record BI_MAC_VDEPTH646lea %pc@(L(mac_videodepth)),%a1647movel %a0@,%a1@648649get_bi_record BI_MAC_VDIM650lea %pc@(L(mac_dimensions)),%a1651movel %a0@,%a1@652653get_bi_record BI_MAC_VROW654lea %pc@(L(mac_rowbytes)),%a1655movel %a0@,%a1@656657#ifdef MAC_SERIAL_DEBUG658get_bi_record BI_MAC_SCCBASE659lea %pc@(L(mac_sccbase)),%a1660movel %a0@,%a1@661#endif /* MAC_SERIAL_DEBUG */662663#if 0664/*665* Clear the screen666*/667lea %pc@(L(mac_videobase)),%a0668movel %a0@,%a1669lea %pc@(L(mac_dimensions)),%a0670movel %a0@,%d1671swap %d1 /* #rows is high bytes */672andl #0xFFFF,%d1 /* rows */673subl #10,%d1674lea %pc@(L(mac_rowbytes)),%a0675loopy2:676movel %a0@,%d0677subql #1,%d0678loopx2:679moveb #0x55, %a1@+680dbra %d0,loopx2681dbra %d1,loopy2682#endif683684L(test_notmac):685#endif /* CONFIG_MAC */686687688/*689* There are ultimately two pieces of information we want for all kinds of690* processors CpuType and CacheBits. The CPUTYPE was passed in from booter691* and is converted here from a booter type definition to a separate bit692* number which allows for the standard is_0x0 macro tests.693*/694movel %pc@(m68k_cputype),%d0695/*696* Assume it's an 030697*/698clrl %d1699700/*701* Test the BootInfo cputype for 060702*/703btst #CPUB_68060,%d0704jeq 1f705bset #CPUTYPE_060,%d1706bset #CPUTYPE_0460,%d1707jra 3f7081:709/*710* Test the BootInfo cputype for 040711*/712btst #CPUB_68040,%d0713jeq 2f714bset #CPUTYPE_040,%d1715bset #CPUTYPE_0460,%d1716jra 3f7172:718/*719* Test the BootInfo cputype for 020720*/721btst #CPUB_68020,%d0722jeq 3f723bset #CPUTYPE_020,%d1724jra 3f7253:726/*727* Record the cpu type728*/729lea %pc@(L(cputype)),%a0730movel %d1,%a0@731732/*733* NOTE:734*735* Now the macros are valid:736* is_040_or_060737* is_not_040_or_060738* is_040739* is_060740* is_not_060741*/742743/*744* Determine the cache mode for pages holding MMU tables745* and for supervisor mode, unused for '020 and '030746*/747clrl %d0748clrl %d1749750is_not_040_or_060(L(save_cachetype))751752/*753* '040 or '060754* d1 := cacheable write-through755* NOTE: The 68040 manual strongly recommends non-cached for MMU tables,756* but we have been using write-through since at least 2.0.29 so I757* guess it is OK.758*/759#ifdef CONFIG_060_WRITETHROUGH760/*761* If this is a 68060 board using drivers with cache coherency762* problems, then supervisor memory accesses need to be write-through763* also; otherwise, we want copyback.764*/765766is_not_060(1f)767movel #_PAGE_CACHE040W,%d0768jra L(save_cachetype)769#endif /* CONFIG_060_WRITETHROUGH */7701:771movew #_PAGE_CACHE040,%d0772773movel #_PAGE_CACHE040W,%d1774775L(save_cachetype):776/* Save cache mode for supervisor mode and page tables777*/778lea %pc@(m68k_supervisor_cachemode),%a0779movel %d0,%a0@780lea %pc@(m68k_pgtable_cachemode),%a0781movel %d1,%a0@782783/*784* raise interrupt level785*/786movew #0x2700,%sr787788/*789If running on an Atari, determine the I/O base of the790serial port and test if we are running on a Medusa or Hades.791This test is necessary here, because on the Hades the serial792port is only accessible in the high I/O memory area.793794The test whether it is a Medusa is done by writing to the byte at795phys. 0x0. This should result in a bus error on all other machines.796797...should, but doesn't. The Afterburner040 for the Falcon has the798same behaviour (0x0..0x7 are no ROM shadow). So we have to do799another test to distinguish Medusa and AB040. This is a800read attempt for 0x00ff82fe phys. that should bus error on a Falcon801(+AB040), but is in the range where the Medusa always asserts DTACK.802803The test for the Hades is done by reading address 0xb0000000. This804should give a bus error on the Medusa.805*/806807#ifdef CONFIG_ATARI808is_not_atari(L(notypetest))809810/* get special machine type (Medusa/Hades/AB40) */811moveq #0,%d3 /* default if tag doesn't exist */812get_bi_record BI_ATARI_MCH_TYPE813tstl %d0814jbmi 1f815movel %a0@,%d3816lea %pc@(atari_mch_type),%a0817movel %d3,%a0@8181:819/* On the Hades, the iobase must be set up before opening the820* serial port. There are no I/O regs at 0x00ffxxxx at all. */821moveq #0,%d0822cmpl #ATARI_MACH_HADES,%d3823jbne 1f824movel #0xff000000,%d0 /* Hades I/O base addr: 0xff000000 */8251: lea %pc@(L(iobase)),%a0826movel %d0,%a0@827828L(notypetest):829#endif830831#ifdef CONFIG_VME832is_mvme147(L(getvmetype))833is_bvme6000(L(getvmetype))834is_not_mvme16x(L(gvtdone))835836/* See if the loader has specified the BI_VME_TYPE tag. Recent837* versions of VMELILO and TFTPLILO do this. We have to do this838* early so we know how to handle console output. If the tag839* doesn't exist then we use the Bug for output on MVME16x.840*/841L(getvmetype):842get_bi_record BI_VME_TYPE843tstl %d0844jbmi 1f845movel %a0@,%d3846lea %pc@(vme_brdtype),%a0847movel %d3,%a0@8481:849#ifdef CONFIG_MVME16x850is_not_mvme16x(L(gvtdone))851852/* Need to get the BRD_ID info to differentiate between 162, 167,853* etc. This is available as a BI_VME_BRDINFO tag with later854* versions of VMELILO and TFTPLILO, otherwise we call the Bug.855*/856get_bi_record BI_VME_BRDINFO857tstl %d0858jpl 1f859860/* Get pointer to board ID data from Bug */861movel %d2,%sp@-862trap #15863.word 0x70 /* trap 0x70 - .BRD_ID */864movel %sp@+,%a08651:866lea %pc@(mvme_bdid),%a1867/* Structure is 32 bytes long */868movel %a0@+,%a1@+869movel %a0@+,%a1@+870movel %a0@+,%a1@+871movel %a0@+,%a1@+872movel %a0@+,%a1@+873movel %a0@+,%a1@+874movel %a0@+,%a1@+875movel %a0@+,%a1@+876#endif877878L(gvtdone):879880#endif881882#ifdef CONFIG_HP300883is_not_hp300(L(nothp))884885/* Get the address of the UART for serial debugging */886get_bi_record BI_HP300_UART_ADDR887tstl %d0888jbmi 1f889movel %a0@,%d3890lea %pc@(L(uartbase)),%a0891movel %d3,%a0@892get_bi_record BI_HP300_UART_SCODE893tstl %d0894jbmi 1f895movel %a0@,%d3896lea %pc@(L(uart_scode)),%a0897movel %d3,%a0@8981:899L(nothp):900#endif901902/*903* Initialize serial port904*/905jbsr L(serial_init)906907/*908* Initialize console909*/910#ifdef CONFIG_MAC911is_not_mac(L(nocon))912#ifdef CONSOLE913console_init914#ifdef CONSOLE_PENGUIN915console_put_penguin916#endif /* CONSOLE_PENGUIN */917console_put_stats918#endif /* CONSOLE */919L(nocon):920#endif /* CONFIG_MAC */921922923putc '\n'924putc 'A'925leds 0x2926dputn %pc@(L(cputype))927dputn %pc@(m68k_supervisor_cachemode)928dputn %pc@(m68k_pgtable_cachemode)929dputc '\n'930931/*932* Save physical start address of kernel933*/934lea %pc@(L(phys_kernel_start)),%a0935lea %pc@(_stext),%a1936subl #_stext,%a1937addl #PAGE_OFFSET,%a1938movel %a1,%a0@939940putc 'B'941942leds 0x4943944/*945* mmu_init946*947* This block of code does what's necessary to map in the various kinds948* of machines for execution of Linux.949* First map the first 4 MB of kernel code & data950*/951952mmu_map #PAGE_OFFSET,%pc@(L(phys_kernel_start)),#4*1024*1024,\953%pc@(m68k_supervisor_cachemode)954955putc 'C'956957#ifdef CONFIG_AMIGA958959L(mmu_init_amiga):960961is_not_amiga(L(mmu_init_not_amiga))962/*963* mmu_init_amiga964*/965966putc 'D'967968is_not_040_or_060(1f)969970/*971* 040: Map the 16Meg range physical 0x0 up to logical 0x8000.0000972*/973mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S974/*975* Map the Zorro III I/O space with transparent translation976* for frame buffer memory etc.977*/978mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE_S979980jbra L(mmu_init_done)9819821:983/*984* 030: Map the 32Meg range physical 0x0 up to logical 0x8000.0000985*/986mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030987mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030988989jbra L(mmu_init_done)990991L(mmu_init_not_amiga):992#endif993994#ifdef CONFIG_ATARI995996L(mmu_init_atari):997998is_not_atari(L(mmu_init_not_atari))9991000putc 'E'10011002/* On the Atari, we map the I/O region (phys. 0x00ffxxxx) by mapping1003the last 16 MB of virtual address space to the first 16 MB (i.e.10040xffxxxxxx -> 0x00xxxxxx). For this, an additional pointer table is1005needed. I/O ranges are marked non-cachable.10061007For the Medusa it is better to map the I/O region transparently1008(i.e. 0xffxxxxxx -> 0xffxxxxxx), because some I/O registers are1009accessible only in the high area.10101011On the Hades all I/O registers are only accessible in the high1012area.1013*/10141015/* I/O base addr for non-Medusa, non-Hades: 0x00000000 */1016moveq #0,%d01017movel %pc@(atari_mch_type),%d31018cmpl #ATARI_MACH_MEDUSA,%d31019jbeq 2f1020cmpl #ATARI_MACH_HADES,%d31021jbne 1f10222: movel #0xff000000,%d0 /* Medusa/Hades base addr: 0xff000000 */10231: movel %d0,%d310241025is_040_or_060(L(spata68040))10261027/* Map everything non-cacheable, though not all parts really1028* need to disable caches (crucial only for 0xff8000..0xffffff1029* (standard I/O) and 0xf00000..0xf3ffff (IDE)). The remainder1030* isn't really used, except for sometimes peeking into the1031* ROMs (mirror at phys. 0x0), so caching isn't necessary for1032* this. */1033mmu_map #0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE03010341035jbra L(mmu_init_done)10361037L(spata68040):10381039mmu_map #0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE_S10401041jbra L(mmu_init_done)10421043L(mmu_init_not_atari):1044#endif10451046#ifdef CONFIG_Q401047is_not_q40(L(notq40))1048/*1049* add transparent mapping for 0xff00 0000 - 0xffff ffff1050* non-cached serialized etc..1051* this includes master chip, DAC, RTC and ISA ports1052* 0xfe000000-0xfeffffff is for screen and ROM1053*/10541055putc 'Q'10561057mmu_map_tt #0,#0xfe000000,#0x01000000,#_PAGE_CACHE040W1058mmu_map_tt #1,#0xff000000,#0x01000000,#_PAGE_NOCACHE_S10591060jbra L(mmu_init_done)10611062L(notq40):1063#endif10641065#ifdef CONFIG_HP3001066is_not_hp300(L(nothp300))10671068/* On the HP300, we map the ROM, INTIO and DIO regions (phys. 0x00xxxxxx)1069* by mapping 32MB (on 020/030) or 16 MB (on 040) from 0xf0xxxxxx -> 0x00xxxxxx).1070* The ROM mapping is needed because the LEDs are mapped there too.1071*/10721073is_040(1f)10741075/*1076* 030: Map the 32Meg range physical 0x0 up to logical 0xf000.00001077*/1078mmu_map #0xf0000000,#0,#0x02000000,#_PAGE_NOCACHE03010791080jbra L(mmu_init_done)108110821:1083/*1084* 040: Map the 16Meg range physical 0x0 up to logical 0xf000.00001085*/1086mmu_map #0xf0000000,#0,#0x01000000,#_PAGE_NOCACHE_S10871088jbra L(mmu_init_done)10891090L(nothp300):1091#endif /* CONFIG_HP300 */10921093#ifdef CONFIG_MVME14710941095is_not_mvme147(L(not147))10961097/*1098* On MVME147 we have already created kernel page tables for1099* 4MB of RAM at address 0, so now need to do a transparent1100* mapping of the top of memory space. Make it 0.5GByte for now,1101* so we can access on-board i/o areas.1102*/11031104mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE03011051106jbra L(mmu_init_done)11071108L(not147):1109#endif /* CONFIG_MVME147 */11101111#ifdef CONFIG_MVME16x11121113is_not_mvme16x(L(not16x))11141115/*1116* On MVME16x we have already created kernel page tables for1117* 4MB of RAM at address 0, so now need to do a transparent1118* mapping of the top of memory space. Make it 0.5GByte for now.1119* Supervisor only access, so transparent mapping doesn't1120* clash with User code virtual address space.1121* this covers IO devices, PROM and SRAM. The PROM and SRAM1122* mapping is needed to allow 167Bug to run.1123* IO is in the range 0xfff00000 to 0xfffeffff.1124* PROM is 0xff800000->0xffbfffff and SRAM is1125* 0xffe00000->0xffe1ffff.1126*/11271128mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S11291130jbra L(mmu_init_done)11311132L(not16x):1133#endif /* CONFIG_MVME162 | CONFIG_MVME167 */11341135#ifdef CONFIG_BVME600011361137is_not_bvme6000(L(not6000))11381139/*1140* On BVME6000 we have already created kernel page tables for1141* 4MB of RAM at address 0, so now need to do a transparent1142* mapping of the top of memory space. Make it 0.5GByte for now,1143* so we can access on-board i/o areas.1144* Supervisor only access, so transparent mapping doesn't1145* clash with User code virtual address space.1146*/11471148mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S11491150jbra L(mmu_init_done)11511152L(not6000):1153#endif /* CONFIG_BVME6000 */11541155/*1156* mmu_init_mac1157*1158* The Macintosh mappings are less clear.1159*1160* Even as of this writing, it is unclear how the1161* Macintosh mappings will be done. However, as1162* the first author of this code I'm proposing the1163* following model:1164*1165* Map the kernel (that's already done),1166* Map the I/O (on most machines that's the1167* 0x5000.0000 ... 0x5300.0000 range,1168* Map the video frame buffer using as few pages1169* as absolutely (this requirement mostly stems from1170* the fact that when the frame buffer is at1171* 0x0000.0000 then we know there is valid RAM just1172* above the screen that we don't want to waste!).1173*1174* By the way, if the frame buffer is at 0x0000.00001175* then the Macintosh is known as an RBV based Mac.1176*1177* By the way 2, the code currently maps in a bunch of1178* regions. But I'd like to cut that out. (And move most1179* of the mappings up into the kernel proper ... or only1180* map what's necessary.)1181*/11821183#ifdef CONFIG_MAC11841185L(mmu_init_mac):11861187is_not_mac(L(mmu_init_not_mac))11881189putc 'F'11901191is_not_040_or_060(1f)11921193moveq #_PAGE_NOCACHE_S,%d31194jbra 2f11951:1196moveq #_PAGE_NOCACHE030,%d311972:1198/*1199* Mac Note: screen address of logical 0xF000.0000 -> <screen physical>1200* we simply map the 4MB that contains the videomem1201*/12021203movel #VIDEOMEMMASK,%d01204andl %pc@(L(mac_videobase)),%d012051206mmu_map #VIDEOMEMBASE,%d0,#VIDEOMEMSIZE,%d31207/* ROM from 4000 0000 to 4200 0000 (only for mac_reset()) */1208mmu_map_eq #0x40000000,#0x02000000,%d31209/* IO devices (incl. serial port) from 5000 0000 to 5300 0000 */1210mmu_map_eq #0x50000000,#0x03000000,%d31211/* Nubus slot space (video at 0xF0000000, rom at 0xF0F80000) */1212mmu_map_tt #1,#0xf8000000,#0x08000000,%d312131214jbra L(mmu_init_done)12151216L(mmu_init_not_mac):1217#endif12181219#ifdef CONFIG_SUN3X1220is_not_sun3x(L(notsun3x))12211222/* oh, the pain.. We're gonna want the prom code after1223* starting the MMU, so we copy the mappings, translating1224* from 8k -> 4k pages as we go.1225*/12261227/* copy maps from 0xfee00000 to 0xff000000 */1228movel #0xfee00000, %d01229moveq #ROOT_INDEX_SHIFT, %d11230lsrl %d1,%d01231mmu_get_root_table_entry %d012321233movel #0xfee00000, %d01234moveq #PTR_INDEX_SHIFT, %d11235lsrl %d1,%d01236andl #PTR_TABLE_SIZE-1, %d01237mmu_get_ptr_table_entry %a0,%d012381239movel #0xfee00000, %d01240moveq #PAGE_INDEX_SHIFT, %d11241lsrl %d1,%d01242andl #PAGE_TABLE_SIZE-1, %d01243mmu_get_page_table_entry %a0,%d012441245/* this is where the prom page table lives */1246movel 0xfefe00d4, %a11247movel %a1@, %a112481249movel #((0x200000 >> 13)-1), %d1125012511:1252movel %a1@+, %d31253movel %d3,%a0@+1254addl #0x1000,%d31255movel %d3,%a0@+12561257dbra %d1,1b12581259/* setup tt1 for I/O */1260mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S1261jbra L(mmu_init_done)12621263L(notsun3x):1264#endif12651266#ifdef CONFIG_APOLLO1267is_not_apollo(L(notapollo))12681269putc 'P'1270mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE03012711272L(notapollo):1273jbra L(mmu_init_done)1274#endif12751276L(mmu_init_done):12771278putc 'G'1279leds 0x812801281/*1282* mmu_fixup1283*1284* On the 040 class machines, all pages that are used for the1285* mmu have to be fixed up. According to Motorola, pages holding mmu1286* tables should be non-cacheable on a '040 and write-through on a1287* '060. But analysis of the reasons for this, and practical1288* experience, showed that write-through also works on a '040.1289*1290* Allocated memory so far goes from kernel_end to memory_start that1291* is used for all kind of tables, for that the cache attributes1292* are now fixed.1293*/1294L(mmu_fixup):12951296is_not_040_or_060(L(mmu_fixup_done))12971298#ifdef MMU_NOCACHE_KERNEL1299jbra L(mmu_fixup_done)1300#endif13011302/* first fix the page at the start of the kernel, that1303* contains also kernel_pg_dir.1304*/1305movel %pc@(L(phys_kernel_start)),%d01306subl #PAGE_OFFSET,%d01307lea %pc@(_stext),%a01308subl %d0,%a01309mmu_fixup_page_mmu_cache %a013101311movel %pc@(L(kernel_end)),%a01312subl %d0,%a01313movel %pc@(L(memory_start)),%a11314subl %d0,%a11315bra 2f13161:1317mmu_fixup_page_mmu_cache %a01318addw #PAGESIZE,%a013192:1320cmpl %a0,%a11321jgt 1b13221323L(mmu_fixup_done):13241325#ifdef MMU_PRINT1326mmu_print1327#endif13281329/*1330* mmu_engage1331*1332* This chunk of code performs the gruesome task of engaging the MMU.1333* The reason its gruesome is because when the MMU becomes engaged it1334* maps logical addresses to physical addresses. The Program Counter1335* register is then passed through the MMU before the next instruction1336* is fetched (the instruction following the engage MMU instruction).1337* This may mean one of two things:1338* 1. The Program Counter falls within the logical address space of1339* the kernel of which there are two sub-possibilities:1340* A. The PC maps to the correct instruction (logical PC == physical1341* code location), or1342* B. The PC does not map through and the processor will read some1343* data (or instruction) which is not the logically next instr.1344* As you can imagine, A is good and B is bad.1345* Alternatively,1346* 2. The Program Counter does not map through the MMU. The processor1347* will take a Bus Error.1348* Clearly, 2 is bad.1349* It doesn't take a wiz kid to figure you want 1.A.1350* This code creates that possibility.1351* There are two possible 1.A. states (we now ignore the other above states):1352* A. The kernel is located at physical memory addressed the same as1353* the logical memory for the kernel, i.e., 0x01000.1354* B. The kernel is located some where else. e.g., 0x0400.00001355*1356* Under some conditions the Macintosh can look like A or B.1357* [A friend and I once noted that Apple hardware engineers should be1358* wacked twice each day: once when they show up at work (as in, Whack!,1359* "This is for the screwy hardware we know you're going to design today."),1360* and also at the end of the day (as in, Whack! "I don't know what1361* you designed today, but I'm sure it wasn't good."). -- rst]1362*1363* This code works on the following premise:1364* If the kernel start (%d5) is within the first 16 Meg of RAM,1365* then create a mapping for the kernel at logical 0x8000.0000 to1366* the physical location of the pc. And, create a transparent1367* translation register for the first 16 Meg. Then, after the MMU1368* is engaged, the PC can be moved up into the 0x8000.0000 range1369* and then the transparent translation can be turned off and then1370* the PC can jump to the correct logical location and it will be1371* home (finally). This is essentially the code that the Amiga used1372* to use. Now, it's generalized for all processors. Which means1373* that a fresh (but temporary) mapping has to be created. The mapping1374* is made in page 0 (an as of yet unused location -- except for the1375* stack!). This temporary mapping will only require 1 pointer table1376* and a single page table (it can map 256K).1377*1378* OK, alternatively, imagine that the Program Counter is not within1379* the first 16 Meg. Then, just use Transparent Translation registers1380* to do the right thing.1381*1382* Last, if _start is already at 0x01000, then there's nothing special1383* to do (in other words, in a degenerate case of the first case above,1384* do nothing).1385*1386* Let's do it.1387*1388*1389*/13901391putc 'H'13921393mmu_engage13941395/*1396* After this point no new memory is allocated and1397* the start of available memory is stored in availmem.1398* (The bootmem allocator requires now the physicall address.)1399*/14001401movel L(memory_start),availmem14021403#ifdef CONFIG_AMIGA1404is_not_amiga(1f)1405/* fixup the Amiga custom register location before printing */1406clrl L(custom)14071:1408#endif14091410#ifdef CONFIG_ATARI1411is_not_atari(1f)1412/* fixup the Atari iobase register location before printing */1413movel #0xff000000,L(iobase)14141:1415#endif14161417#ifdef CONFIG_MAC1418is_not_mac(1f)1419movel #~VIDEOMEMMASK,%d01420andl L(mac_videobase),%d01421addl #VIDEOMEMBASE,%d01422movel %d0,L(mac_videobase)1423#if defined(CONSOLE)1424movel %pc@(L(phys_kernel_start)),%d01425subl #PAGE_OFFSET,%d01426subl %d0,L(console_font)1427subl %d0,L(console_font_data)1428#endif1429#ifdef MAC_SERIAL_DEBUG1430orl #0x50000000,L(mac_sccbase)1431#endif14321:1433#endif14341435#ifdef CONFIG_HP3001436is_not_hp300(2f)1437/*1438* Fix up the iobase register to point to the new location of the LEDs.1439*/1440movel #0xf0000000,L(iobase)14411442/*1443* Energise the FPU and caches.1444*/1445is_040(1f)1446movel #0x60,0xf05f400c1447jbra 2f14481449/*1450* 040: slightly different, apparently.1451*/14521: movew #0,0xf05f400e1453movew #0x64,0xf05f400e14542:1455#endif14561457#ifdef CONFIG_SUN3X1458is_not_sun3x(1f)14591460/* enable copro */1461oriw #0x4000,0x6100000014621:1463#endif14641465#ifdef CONFIG_APOLLO1466is_not_apollo(1f)14671468/*1469* Fix up the iobase before printing1470*/1471movel #0x80000000,L(iobase)14721:1473#endif14741475putc 'I'1476leds 0x1014771478/*1479* Enable caches1480*/14811482is_not_040_or_060(L(cache_not_680460))14831484L(cache680460):1485.chip 680401486nop1487cpusha %bc1488nop14891490is_060(L(cache68060))14911492movel #CC6_ENABLE_D+CC6_ENABLE_I,%d01493/* MMU stuff works in copyback mode now, so enable the cache */1494movec %d0,%cacr1495jra L(cache_done)14961497L(cache68060):1498movel #CC6_ENABLE_D+CC6_ENABLE_I+CC6_ENABLE_SB+CC6_PUSH_DPI+CC6_ENABLE_B+CC6_CLRA_B,%d01499/* MMU stuff works in copyback mode now, so enable the cache */1500movec %d0,%cacr1501/* enable superscalar dispatch in PCR */1502moveq #1,%d01503.chip 680601504movec %d0,%pcr15051506jbra L(cache_done)1507L(cache_not_680460):1508L(cache68030):1509.chip 680301510movel #CC3_ENABLE_DB+CC3_CLR_D+CC3_ENABLE_D+CC3_ENABLE_IB+CC3_CLR_I+CC3_ENABLE_I,%d01511movec %d0,%cacr15121513jra L(cache_done)1514.chip 68k1515L(cache_done):15161517putc 'J'15181519/*1520* Setup initial stack pointer1521*/1522lea init_task,%curptr1523lea init_thread_union+THREAD_SIZE,%sp15241525putc 'K'15261527subl %a6,%a6 /* clear a6 for gdb */15281529/*1530* The new 64bit printf support requires an early exception initialization.1531*/1532jbsr base_trap_init15331534/* jump to the kernel start */15351536putc '\n'1537leds 0x5515381539jbsr start_kernel15401541/*1542* Find a tag record in the bootinfo structure1543* The bootinfo structure is located right after the kernel bss1544* Returns: d0: size (-1 if not found)1545* a0: data pointer (end-of-records if not found)1546*/1547func_start get_bi_record,%d115481549movel ARG1,%d01550lea %pc@(_end),%a015511: tstw %a0@(BIR_TAG)1552jeq 3f1553cmpw %a0@(BIR_TAG),%d01554jeq 2f1555addw %a0@(BIR_SIZE),%a01556jra 1b15572: moveq #0,%d01558movew %a0@(BIR_SIZE),%d01559lea %a0@(BIR_DATA),%a01560jra 4f15613: moveq #-1,%d01562lea %a0@(BIR_SIZE),%a015634:1564func_return get_bi_record156515661567/*1568* MMU Initialization Begins Here1569*1570* The structure of the MMU tables on the 68k machines1571* is thus:1572* Root Table1573* Logical addresses are translated through1574* a hierarchical translation mechanism where the high-order1575* seven bits of the logical address (LA) are used as an1576* index into the "root table." Each entry in the root1577* table has a bit which specifies if it's a valid pointer to a1578* pointer table. Each entry defines a 32KMeg range of memory.1579* If an entry is invalid then that logical range of 32M is1580* invalid and references to that range of memory (when the MMU1581* is enabled) will fault. If the entry is valid, then it does1582* one of two things. On 040/060 class machines, it points to1583* a pointer table which then describes more finely the memory1584* within that 32M range. On 020/030 class machines, a technique1585* called "early terminating descriptors" are used. This technique1586* allows an entire 32Meg to be described by a single entry in the1587* root table. Thus, this entry in the root table, contains the1588* physical address of the memory or I/O at the logical address1589* which the entry represents and it also contains the necessary1590* cache bits for this region.1591*1592* Pointer Tables1593* Per the Root Table, there will be one or more1594* pointer tables. Each pointer table defines a 32M range.1595* Not all of the 32M range need be defined. Again, the next1596* seven bits of the logical address are used an index into1597* the pointer table to point to page tables (if the pointer1598* is valid). There will undoubtedly be more than one1599* pointer table for the kernel because each pointer table1600* defines a range of only 32M. Valid pointer table entries1601* point to page tables, or are early terminating entries1602* themselves.1603*1604* Page Tables1605* Per the Pointer Tables, each page table entry points1606* to the physical page in memory that supports the logical1607* address that translates to the particular index.1608*1609* In short, the Logical Address gets translated as follows:1610* bits 31..26 - index into the Root Table1611* bits 25..18 - index into the Pointer Table1612* bits 17..12 - index into the Page Table1613* bits 11..0 - offset into a particular 4K page1614*1615* The algorithms which follows do one thing: they abstract1616* the MMU hardware. For example, there are three kinds of1617* cache settings that are relevant. Either, memory is1618* being mapped in which case it is either Kernel Code (or1619* the RamDisk) or it is MMU data. On the 030, the MMU data1620* option also describes the kernel. Or, I/O is being mapped1621* in which case it has its own kind of cache bits. There1622* are constants which abstract these notions from the code that1623* actually makes the call to map some range of memory.1624*1625*1626*1627*/16281629#ifdef MMU_PRINT1630/*1631* mmu_print1632*1633* This algorithm will print out the current MMU mappings.1634*1635* Input:1636* %a5 points to the root table. Everything else is calculated1637* from this.1638*/16391640#define mmu_next_valid 01641#define mmu_start_logical 41642#define mmu_next_logical 81643#define mmu_start_physical 121644#define mmu_next_physical 1616451646#define MMU_PRINT_INVALID -11647#define MMU_PRINT_VALID 11648#define MMU_PRINT_UNINITED 016491650#define putZc(z,n) jbne 1f; putc z; jbra 2f; 1: putc n; 2:16511652func_start mmu_print,%a0-%a6/%d0-%d716531654movel %pc@(L(kernel_pgdir_ptr)),%a51655lea %pc@(L(mmu_print_data)),%a01656movel #MMU_PRINT_UNINITED,%a0@(mmu_next_valid)16571658is_not_040_or_060(mmu_030_print)16591660mmu_040_print:1661puts "\nMMU040\n"1662puts "rp:"1663putn %a51664putc '\n'1665#if 01666/*1667* The following #if/#endif block is a tight algorithm for dumping the 0401668* MMU Map in gory detail. It really isn't that practical unless the1669* MMU Map algorithm appears to go awry and you need to debug it at the1670* entry per entry level.1671*/1672movel #ROOT_TABLE_SIZE,%d51673#if 01674movel %a5@+,%d7 | Burn an entry to skip the kernel mappings,1675subql #1,%d5 | they (might) work1676#endif16771: tstl %d51678jbeq mmu_print_done1679subq #1,%d51680movel %a5@+,%d71681btst #1,%d71682jbeq 1b168316842: putn %d71685andil #0xFFFFFE00,%d71686movel %d7,%a41687movel #PTR_TABLE_SIZE,%d41688putc ' '16893: tstl %d41690jbeq 11f1691subq #1,%d41692movel %a4@+,%d71693btst #1,%d71694jbeq 3b169516964: putn %d71697andil #0xFFFFFF00,%d71698movel %d7,%a31699movel #PAGE_TABLE_SIZE,%d317005: movel #8,%d217016: tstl %d31702jbeq 31f1703subq #1,%d31704movel %a3@+,%d61705btst #0,%d61706jbeq 6b17077: tstl %d21708jbeq 8f1709subq #1,%d21710putc ' '1711jbra 91f17128: putc '\n'1713movel #8+1+8+1+1,%d217149: putc ' '1715dbra %d2,9b1716movel #7,%d2171791: putn %d61718jbra 6b1719172031: putc '\n'1721movel #8+1,%d2172232: putc ' '1723dbra %d2,32b1724jbra 3b1725172611: putc '\n'1727jbra 1b1728#endif /* MMU 040 Dumping code that's gory and detailed */17291730lea %pc@(kernel_pg_dir),%a51731movel %a5,%a0 /* a0 has the address of the root table ptr */1732movel #0x00000000,%a4 /* logical address */1733moveql #0,%d0173440:1735/* Increment the logical address and preserve in d5 */1736movel %a4,%d51737addil #PAGESIZE<<13,%d51738movel %a0@+,%d61739btst #1,%d61740jbne 41f1741jbsr mmu_print_tuple_invalidate1742jbra 48f174341:1744movel #0,%d11745andil #0xfffffe00,%d61746movel %d6,%a1174742:1748movel %a4,%d51749addil #PAGESIZE<<6,%d51750movel %a1@+,%d61751btst #1,%d61752jbne 43f1753jbsr mmu_print_tuple_invalidate1754jbra 47f175543:1756movel #0,%d21757andil #0xffffff00,%d61758movel %d6,%a2175944:1760movel %a4,%d51761addil #PAGESIZE,%d51762movel %a2@+,%d61763btst #0,%d61764jbne 45f1765jbsr mmu_print_tuple_invalidate1766jbra 46f176745:1768moveml %d0-%d1,%sp@-1769movel %a4,%d01770movel %d6,%d11771andil #0xfffff4e0,%d11772lea %pc@(mmu_040_print_flags),%a61773jbsr mmu_print_tuple1774moveml %sp@+,%d0-%d1177546:1776movel %d5,%a41777addq #1,%d21778cmpib #64,%d21779jbne 44b178047:1781movel %d5,%a41782addq #1,%d11783cmpib #128,%d11784jbne 42b178548:1786movel %d5,%a4 /* move to the next logical address */1787addq #1,%d01788cmpib #128,%d01789jbne 40b17901791.chip 680401792movec %dtt1,%d01793movel %d0,%d11794andiw #0x8000,%d1 /* is it valid ? */1795jbeq 1f /* No, bail out */17961797movel %d0,%d11798andil #0xff000000,%d1 /* Get the address */1799putn %d11800puts "=="1801putn %d118021803movel %d0,%d61804jbsr mmu_040_print_flags_tt18051:1806movec %dtt0,%d01807movel %d0,%d11808andiw #0x8000,%d1 /* is it valid ? */1809jbeq 1f /* No, bail out */18101811movel %d0,%d11812andil #0xff000000,%d1 /* Get the address */1813putn %d11814puts "=="1815putn %d118161817movel %d0,%d61818jbsr mmu_040_print_flags_tt18191:1820.chip 68k18211822jbra mmu_print_done18231824mmu_040_print_flags:1825btstl #10,%d61826putZc(' ','G') /* global bit */1827btstl #7,%d61828putZc(' ','S') /* supervisor bit */1829mmu_040_print_flags_tt:1830btstl #6,%d61831jbne 3f1832putc 'C'1833btstl #5,%d61834putZc('w','c') /* write through or copy-back */1835jbra 4f18363:1837putc 'N'1838btstl #5,%d61839putZc('s',' ') /* serialized non-cacheable, or non-cacheable */18404:1841rts18421843mmu_030_print_flags:1844btstl #6,%d61845putZc('C','I') /* write through or copy-back */1846rts18471848mmu_030_print:1849puts "\nMMU030\n"1850puts "\nrp:"1851putn %a51852putc '\n'1853movel %a5,%d01854andil #0xfffffff0,%d01855movel %d0,%a01856movel #0x00000000,%a4 /* logical address */1857movel #0,%d0185830:1859movel %a4,%d51860addil #PAGESIZE<<13,%d51861movel %a0@+,%d61862btst #1,%d6 /* is it a table ptr? */1863jbne 31f /* yes */1864btst #0,%d6 /* is it early terminating? */1865jbeq 1f /* no */1866jbsr mmu_030_print_helper1867jbra 38f18681:1869jbsr mmu_print_tuple_invalidate1870jbra 38f187131:1872movel #0,%d11873andil #0xfffffff0,%d61874movel %d6,%a1187532:1876movel %a4,%d51877addil #PAGESIZE<<6,%d51878movel %a1@+,%d61879btst #1,%d6 /* is it a table ptr? */1880jbne 33f /* yes */1881btst #0,%d6 /* is it a page descriptor? */1882jbeq 1f /* no */1883jbsr mmu_030_print_helper1884jbra 37f18851:1886jbsr mmu_print_tuple_invalidate1887jbra 37f188833:1889movel #0,%d21890andil #0xfffffff0,%d61891movel %d6,%a2189234:1893movel %a4,%d51894addil #PAGESIZE,%d51895movel %a2@+,%d61896btst #0,%d61897jbne 35f1898jbsr mmu_print_tuple_invalidate1899jbra 36f190035:1901jbsr mmu_030_print_helper190236:1903movel %d5,%a41904addq #1,%d21905cmpib #64,%d21906jbne 34b190737:1908movel %d5,%a41909addq #1,%d11910cmpib #128,%d11911jbne 32b191238:1913movel %d5,%a4 /* move to the next logical address */1914addq #1,%d01915cmpib #128,%d01916jbne 30b19171918mmu_print_done:1919puts "\n\n"19201921func_return mmu_print192219231924mmu_030_print_helper:1925moveml %d0-%d1,%sp@-1926movel %a4,%d01927movel %d6,%d11928lea %pc@(mmu_030_print_flags),%a61929jbsr mmu_print_tuple1930moveml %sp@+,%d0-%d11931rts19321933mmu_print_tuple_invalidate:1934moveml %a0/%d7,%sp@-19351936lea %pc@(L(mmu_print_data)),%a01937tstl %a0@(mmu_next_valid)1938jbmi mmu_print_tuple_invalidate_exit19391940movel #MMU_PRINT_INVALID,%a0@(mmu_next_valid)19411942putn %a419431944puts "##\n"19451946mmu_print_tuple_invalidate_exit:1947moveml %sp@+,%a0/%d71948rts194919501951mmu_print_tuple:1952moveml %d0-%d7/%a0,%sp@-19531954lea %pc@(L(mmu_print_data)),%a019551956tstl %a0@(mmu_next_valid)1957jble mmu_print_tuple_print19581959cmpl %a0@(mmu_next_physical),%d11960jbeq mmu_print_tuple_increment19611962mmu_print_tuple_print:1963putn %d01964puts "->"1965putn %d119661967movel %d1,%d61968jbsr %a6@19691970mmu_print_tuple_record:1971movel #MMU_PRINT_VALID,%a0@(mmu_next_valid)19721973movel %d1,%a0@(mmu_next_physical)19741975mmu_print_tuple_increment:1976movel %d5,%d71977subl %a4,%d71978addl %d7,%a0@(mmu_next_physical)19791980mmu_print_tuple_exit:1981moveml %sp@+,%d0-%d7/%a01982rts19831984mmu_print_machine_cpu_types:1985puts "machine: "19861987is_not_amiga(1f)1988puts "amiga"1989jbra 9f19901:1991is_not_atari(2f)1992puts "atari"1993jbra 9f19942:1995is_not_mac(3f)1996puts "macintosh"1997jbra 9f19983: puts "unknown"19999: putc '\n'20002001puts "cputype: 0"2002is_not_060(1f)2003putc '6'2004jbra 9f20051:2006is_not_040_or_060(2f)2007putc '4'2008jbra 9f20092: putc '3'20109: putc '0'2011putc '\n'20122013rts2014#endif /* MMU_PRINT */20152016/*2017* mmu_map_tt2018*2019* This is a specific function which works on all 680x0 machines.2020* On 030, 040 & 060 it will attempt to use Transparent Translation2021* registers (tt1).2022* On 020 it will call the standard mmu_map which will use early2023* terminating descriptors.2024*/2025func_start mmu_map_tt,%d0/%d1/%a0,420262027dputs "mmu_map_tt:"2028dputn ARG12029dputn ARG22030dputn ARG32031dputn ARG42032dputc '\n'20332034is_020(L(do_map))20352036/* Extract the highest bit set2037*/2038bfffo ARG3{#0,#32},%d12039cmpw #8,%d12040jcc L(do_map)20412042/* And get the mask2043*/2044moveq #-1,%d02045lsrl %d1,%d02046lsrl #1,%d020472048/* Mask the address2049*/2050movel %d0,%d12051notl %d12052andl ARG2,%d120532054/* Generate the upper 16bit of the tt register2055*/2056lsrl #8,%d02057orl %d0,%d12058clrw %d120592060is_040_or_060(L(mmu_map_tt_040))20612062/* set 030 specific bits (read/write access for supervisor mode2063* (highest function code set, lower two bits masked))2064*/2065orw #TTR_ENABLE+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d12066movel ARG4,%d02067btst #6,%d02068jeq 1f2069orw #TTR_CI,%d1207020711: lea STACK,%a02072dputn %d12073movel %d1,%a0@2074.chip 680302075tstl ARG12076jne 1f2077pmove %a0@,%tt02078jra 2f20791: pmove %a0@,%tt120802: .chip 68k2081jra L(mmu_map_tt_done)20822083/* set 040 specific bits2084*/2085L(mmu_map_tt_040):2086orw #TTR_ENABLE+TTR_KERNELMODE,%d12087orl ARG4,%d12088dputn %d120892090.chip 680402091tstl ARG12092jne 1f2093movec %d1,%itt02094movec %d1,%dtt02095jra 2f20961: movec %d1,%itt12097movec %d1,%dtt120982: .chip 68k20992100jra L(mmu_map_tt_done)21012102L(do_map):2103mmu_map_eq ARG2,ARG3,ARG421042105L(mmu_map_tt_done):21062107func_return mmu_map_tt21082109/*2110* mmu_map2111*2112* This routine will map a range of memory using a pointer2113* table and allocating the pages on the fly from the kernel.2114* The pointer table does not have to be already linked into2115* the root table, this routine will do that if necessary.2116*2117* NOTE2118* This routine will assert failure and use the serial_putc2119* routines in the case of a run-time error. For example,2120* if the address is already mapped.2121*2122* NOTE-22123* This routine will use early terminating descriptors2124* where possible for the 68020+68851 and 68030 type2125* processors.2126*/2127func_start mmu_map,%d0-%d4/%a0-%a421282129dputs "\nmmu_map:"2130dputn ARG12131dputn ARG22132dputn ARG32133dputn ARG42134dputc '\n'21352136/* Get logical address and round it down to 256KB2137*/2138movel ARG1,%d02139andl #-(PAGESIZE*PAGE_TABLE_SIZE),%d02140movel %d0,%a321412142/* Get the end address2143*/2144movel ARG1,%a42145addl ARG3,%a42146subql #1,%a421472148/* Get physical address and round it down to 256KB2149*/2150movel ARG2,%d02151andl #-(PAGESIZE*PAGE_TABLE_SIZE),%d02152movel %d0,%a221532154/* Add page attributes to the physical address2155*/2156movel ARG4,%d02157orw #_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d02158addw %d0,%a221592160dputn %a22161dputn %a32162dputn %a421632164is_not_040_or_060(L(mmu_map_030))21652166addw #_PAGE_GLOBAL040,%a22167/*2168* MMU 040 & 060 Support2169*2170* The MMU usage for the 040 and 060 is different enough from2171* the 030 and 68851 that there is separate code. This comment2172* block describes the data structures and algorithms built by2173* this code.2174*2175* The 040 does not support early terminating descriptors, as2176* the 030 does. Therefore, a third level of table is needed2177* for the 040, and that would be the page table. In Linux,2178* page tables are allocated directly from the memory above the2179* kernel.2180*2181*/21822183L(mmu_map_040):2184/* Calculate the offset into the root table2185*/2186movel %a3,%d02187moveq #ROOT_INDEX_SHIFT,%d12188lsrl %d1,%d02189mmu_get_root_table_entry %d021902191/* Calculate the offset into the pointer table2192*/2193movel %a3,%d02194moveq #PTR_INDEX_SHIFT,%d12195lsrl %d1,%d02196andl #PTR_TABLE_SIZE-1,%d02197mmu_get_ptr_table_entry %a0,%d021982199/* Calculate the offset into the page table2200*/2201movel %a3,%d02202moveq #PAGE_INDEX_SHIFT,%d12203lsrl %d1,%d02204andl #PAGE_TABLE_SIZE-1,%d02205mmu_get_page_table_entry %a0,%d022062207/* The page table entry must not no be busy2208*/2209tstl %a0@2210jne L(mmu_map_error)22112212/* Do the mapping and advance the pointers2213*/2214movel %a2,%a0@22152:2216addw #PAGESIZE,%a22217addw #PAGESIZE,%a322182219/* Ready with mapping?2220*/2221lea %a3@(-1),%a02222cmpl %a0,%a42223jhi L(mmu_map_040)2224jra L(mmu_map_done)22252226L(mmu_map_030):2227/* Calculate the offset into the root table2228*/2229movel %a3,%d02230moveq #ROOT_INDEX_SHIFT,%d12231lsrl %d1,%d02232mmu_get_root_table_entry %d022332234/* Check if logical address 32MB aligned,2235* so we can try to map it once2236*/2237movel %a3,%d02238andl #(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE-1)&(-ROOT_TABLE_SIZE),%d02239jne 1f22402241/* Is there enough to map for 32MB at once2242*/2243lea %a3@(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE-1),%a12244cmpl %a1,%a42245jcs 1f22462247addql #1,%a122482249/* The root table entry must not no be busy2250*/2251tstl %a0@2252jne L(mmu_map_error)22532254/* Do the mapping and advance the pointers2255*/2256dputs "early term1"2257dputn %a22258dputn %a32259dputn %a12260dputc '\n'2261movel %a2,%a0@22622263movel %a1,%a32264lea %a2@(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE),%a22265jra L(mmu_mapnext_030)22661:2267/* Calculate the offset into the pointer table2268*/2269movel %a3,%d02270moveq #PTR_INDEX_SHIFT,%d12271lsrl %d1,%d02272andl #PTR_TABLE_SIZE-1,%d02273mmu_get_ptr_table_entry %a0,%d022742275/* The pointer table entry must not no be busy2276*/2277tstl %a0@2278jne L(mmu_map_error)22792280/* Do the mapping and advance the pointers2281*/2282dputs "early term2"2283dputn %a22284dputn %a32285dputc '\n'2286movel %a2,%a0@22872288addl #PAGE_TABLE_SIZE*PAGESIZE,%a22289addl #PAGE_TABLE_SIZE*PAGESIZE,%a322902291L(mmu_mapnext_030):2292/* Ready with mapping?2293*/2294lea %a3@(-1),%a02295cmpl %a0,%a42296jhi L(mmu_map_030)2297jra L(mmu_map_done)22982299L(mmu_map_error):23002301dputs "mmu_map error:"2302dputn %a22303dputn %a32304dputc '\n'23052306L(mmu_map_done):23072308func_return mmu_map23092310/*2311* mmu_fixup2312*2313* On the 040 class machines, all pages that are used for the2314* mmu have to be fixed up.2315*/23162317func_start mmu_fixup_page_mmu_cache,%d0/%a023182319dputs "mmu_fixup_page_mmu_cache"2320dputn ARG123212322/* Calculate the offset into the root table2323*/2324movel ARG1,%d02325moveq #ROOT_INDEX_SHIFT,%d12326lsrl %d1,%d02327mmu_get_root_table_entry %d023282329/* Calculate the offset into the pointer table2330*/2331movel ARG1,%d02332moveq #PTR_INDEX_SHIFT,%d12333lsrl %d1,%d02334andl #PTR_TABLE_SIZE-1,%d02335mmu_get_ptr_table_entry %a0,%d023362337/* Calculate the offset into the page table2338*/2339movel ARG1,%d02340moveq #PAGE_INDEX_SHIFT,%d12341lsrl %d1,%d02342andl #PAGE_TABLE_SIZE-1,%d02343mmu_get_page_table_entry %a0,%d023442345movel %a0@,%d02346andil #_CACHEMASK040,%d02347orl %pc@(m68k_pgtable_cachemode),%d02348movel %d0,%a0@23492350dputc '\n'23512352func_return mmu_fixup_page_mmu_cache23532354/*2355* mmu_temp_map2356*2357* create a temporary mapping to enable the mmu,2358* this we don't need any transparation translation tricks.2359*/23602361func_start mmu_temp_map,%d0/%d1/%a0/%a123622363dputs "mmu_temp_map"2364dputn ARG12365dputn ARG22366dputc '\n'23672368lea %pc@(L(temp_mmap_mem)),%a123692370/* Calculate the offset in the root table2371*/2372movel ARG2,%d02373moveq #ROOT_INDEX_SHIFT,%d12374lsrl %d1,%d02375mmu_get_root_table_entry %d023762377/* Check if the table is temporary allocated, so we have to reuse it2378*/2379movel %a0@,%d02380cmpl %pc@(L(memory_start)),%d02381jcc 1f23822383/* Temporary allocate a ptr table and insert it into the root table2384*/2385movel %a1@,%d02386addl #PTR_TABLE_SIZE*4,%a1@2387orw #_PAGE_TABLE+_PAGE_ACCESSED,%d02388movel %d0,%a0@2389dputs " (new)"23901:2391dputn %d02392/* Mask the root table entry for the ptr table2393*/2394andw #-ROOT_TABLE_SIZE,%d02395movel %d0,%a023962397/* Calculate the offset into the pointer table2398*/2399movel ARG2,%d02400moveq #PTR_INDEX_SHIFT,%d12401lsrl %d1,%d02402andl #PTR_TABLE_SIZE-1,%d02403lea %a0@(%d0*4),%a02404dputn %a024052406/* Check if a temporary page table is already allocated2407*/2408movel %a0@,%d02409jne 1f24102411/* Temporary allocate a page table and insert it into the ptr table2412*/2413movel %a1@,%d02414/* The 512 should be PAGE_TABLE_SIZE*4, but that violates the2415alignment restriction for pointer tables on the '0[46]0. */2416addl #512,%a1@2417orw #_PAGE_TABLE+_PAGE_ACCESSED,%d02418movel %d0,%a0@2419dputs " (new)"24201:2421dputn %d02422/* Mask the ptr table entry for the page table2423*/2424andw #-PTR_TABLE_SIZE,%d02425movel %d0,%a024262427/* Calculate the offset into the page table2428*/2429movel ARG2,%d02430moveq #PAGE_INDEX_SHIFT,%d12431lsrl %d1,%d02432andl #PAGE_TABLE_SIZE-1,%d02433lea %a0@(%d0*4),%a02434dputn %a024352436/* Insert the address into the page table2437*/2438movel ARG1,%d02439andw #-PAGESIZE,%d02440orw #_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d02441movel %d0,%a0@2442dputn %d024432444dputc '\n'24452446func_return mmu_temp_map24472448func_start mmu_engage,%d0-%d2/%a0-%a324492450moveq #ROOT_TABLE_SIZE-1,%d02451/* Temporarily use a different root table. */2452lea %pc@(L(kernel_pgdir_ptr)),%a02453movel %a0@,%a22454movel %pc@(L(memory_start)),%a12455movel %a1,%a0@2456movel %a2,%a024571:2458movel %a0@+,%a1@+2459dbra %d0,1b24602461lea %pc@(L(temp_mmap_mem)),%a02462movel %a1,%a0@24632464movew #PAGESIZE-1,%d024651:2466clrl %a1@+2467dbra %d0,1b24682469lea %pc@(1b),%a02470movel #1b,%a12471/* Skip temp mappings if phys == virt */2472cmpl %a0,%a12473jeq 1f24742475mmu_temp_map %a0,%a02476mmu_temp_map %a0,%a124772478addw #PAGESIZE,%a02479addw #PAGESIZE,%a12480mmu_temp_map %a0,%a02481mmu_temp_map %a0,%a124821:2483movel %pc@(L(memory_start)),%a32484movel %pc@(L(phys_kernel_start)),%d224852486is_not_040_or_060(L(mmu_engage_030))24872488L(mmu_engage_040):2489.chip 680402490nop2491cinva %bc2492nop2493pflusha2494nop2495movec %a3,%srp2496movel #TC_ENABLE+TC_PAGE4K,%d02497movec %d0,%tc /* enable the MMU */2498jmp 1f:l24991: nop2500movec %a2,%srp2501nop2502cinva %bc2503nop2504pflusha2505.chip 68k2506jra L(mmu_engage_cleanup)25072508L(mmu_engage_030_temp):2509.space 122510L(mmu_engage_030):2511.chip 680302512lea %pc@(L(mmu_engage_030_temp)),%a02513movel #0x80000002,%a0@2514movel %a3,%a0@(4)2515movel #0x0808,%d02516movec %d0,%cacr2517pmove %a0@,%srp2518pflusha2519/*2520* enable,super root enable,4096 byte pages,7 bit root index,2521* 7 bit pointer index, 6 bit page table index.2522*/2523movel #0x82c07760,%a0@(8)2524pmove %a0@(8),%tc /* enable the MMU */2525jmp 1f:l25261: movel %a2,%a0@(4)2527movel #0x0808,%d02528movec %d0,%cacr2529pmove %a0@,%srp2530pflusha2531.chip 68k25322533L(mmu_engage_cleanup):2534subl #PAGE_OFFSET,%d22535subl %d2,%a22536movel %a2,L(kernel_pgdir_ptr)2537subl %d2,%fp2538subl %d2,%sp2539subl %d2,ARG025402541func_return mmu_engage25422543func_start mmu_get_root_table_entry,%d0/%a125442545#if 02546dputs "mmu_get_root_table_entry:"2547dputn ARG12548dputs " ="2549#endif25502551movel %pc@(L(kernel_pgdir_ptr)),%a02552tstl %a02553jne 2f25542555dputs "\nmmu_init:"25562557/* Find the start of free memory, get_bi_record does this for us,2558* as the bootinfo structure is located directly behind the kernel2559* and and we simply search for the last entry.2560*/2561get_bi_record BI_LAST2562addw #PAGESIZE-1,%a02563movel %a0,%d02564andw #-PAGESIZE,%d025652566dputn %d025672568lea %pc@(L(memory_start)),%a02569movel %d0,%a0@2570lea %pc@(L(kernel_end)),%a02571movel %d0,%a0@25722573/* we have to return the first page at _stext since the init code2574* in mm/init.c simply expects kernel_pg_dir there, the rest of2575* page is used for further ptr tables in get_ptr_table.2576*/2577lea %pc@(_stext),%a02578lea %pc@(L(mmu_cached_pointer_tables)),%a12579movel %a0,%a1@2580addl #ROOT_TABLE_SIZE*4,%a1@25812582lea %pc@(L(mmu_num_pointer_tables)),%a12583addql #1,%a1@25842585/* clear the page2586*/2587movel %a0,%a12588movew #PAGESIZE/4-1,%d025891:2590clrl %a1@+2591dbra %d0,1b25922593lea %pc@(L(kernel_pgdir_ptr)),%a12594movel %a0,%a1@25952596dputn %a02597dputc '\n'25982:2599movel ARG1,%d02600lea %a0@(%d0*4),%a026012602#if 02603dputn %a02604dputc '\n'2605#endif26062607func_return mmu_get_root_table_entry2608260926102611func_start mmu_get_ptr_table_entry,%d0/%a126122613#if 02614dputs "mmu_get_ptr_table_entry:"2615dputn ARG12616dputn ARG22617dputs " ="2618#endif26192620movel ARG1,%a02621movel %a0@,%d02622jne 2f26232624/* Keep track of the number of pointer tables we use2625*/2626dputs "\nmmu_get_new_ptr_table:"2627lea %pc@(L(mmu_num_pointer_tables)),%a02628movel %a0@,%d02629addql #1,%a0@26302631/* See if there is a free pointer table in our cache of pointer tables2632*/2633lea %pc@(L(mmu_cached_pointer_tables)),%a12634andw #7,%d02635jne 1f26362637/* Get a new pointer table page from above the kernel memory2638*/2639get_new_page2640movel %a0,%a1@26411:2642/* There is an unused pointer table in our cache... use it2643*/2644movel %a1@,%d02645addl #PTR_TABLE_SIZE*4,%a1@26462647dputn %d02648dputc '\n'26492650/* Insert the new pointer table into the root table2651*/2652movel ARG1,%a02653orw #_PAGE_TABLE+_PAGE_ACCESSED,%d02654movel %d0,%a0@26552:2656/* Extract the pointer table entry2657*/2658andw #-PTR_TABLE_SIZE,%d02659movel %d0,%a02660movel ARG2,%d02661lea %a0@(%d0*4),%a026622663#if 02664dputn %a02665dputc '\n'2666#endif26672668func_return mmu_get_ptr_table_entry266926702671func_start mmu_get_page_table_entry,%d0/%a126722673#if 02674dputs "mmu_get_page_table_entry:"2675dputn ARG12676dputn ARG22677dputs " ="2678#endif26792680movel ARG1,%a02681movel %a0@,%d02682jne 2f26832684/* If the page table entry doesn't exist, we allocate a complete new2685* page and use it as one continues big page table which can cover2686* 4MB of memory, nearly almost all mappings have that alignment.2687*/2688get_new_page2689addw #_PAGE_TABLE+_PAGE_ACCESSED,%a026902691/* align pointer table entry for a page of page tables2692*/2693movel ARG1,%d02694andw #-(PAGESIZE/PAGE_TABLE_SIZE),%d02695movel %d0,%a126962697/* Insert the page tables into the pointer entries2698*/2699moveq #PAGESIZE/PAGE_TABLE_SIZE/4-1,%d027001:2701movel %a0,%a1@+2702lea %a0@(PAGE_TABLE_SIZE*4),%a02703dbra %d0,1b27042705/* Now we can get the initialized pointer table entry2706*/2707movel ARG1,%a02708movel %a0@,%d027092:2710/* Extract the page table entry2711*/2712andw #-PAGE_TABLE_SIZE,%d02713movel %d0,%a02714movel ARG2,%d02715lea %a0@(%d0*4),%a027162717#if 02718dputn %a02719dputc '\n'2720#endif27212722func_return mmu_get_page_table_entry27232724/*2725* get_new_page2726*2727* Return a new page from the memory start and clear it.2728*/2729func_start get_new_page,%d0/%a127302731dputs "\nget_new_page:"27322733/* allocate the page and adjust memory_start2734*/2735lea %pc@(L(memory_start)),%a02736movel %a0@,%a12737addl #PAGESIZE,%a0@27382739/* clear the new page2740*/2741movel %a1,%a02742movew #PAGESIZE/4-1,%d027431:2744clrl %a1@+2745dbra %d0,1b27462747dputn %a02748dputc '\n'27492750func_return get_new_page2751275227532754/*2755* Debug output support2756* Atarians have a choice between the parallel port, the serial port2757* from the MFP or a serial port of the SCC2758*/27592760#ifdef CONFIG_MAC27612762L(scc_initable_mac):2763.byte 9,12 /* Reset */2764.byte 4,0x44 /* x16, 1 stopbit, no parity */2765.byte 3,0xc0 /* receiver: 8 bpc */2766.byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */2767.byte 9,0 /* no interrupts */2768.byte 10,0 /* NRZ */2769.byte 11,0x50 /* use baud rate generator */2770.byte 12,10,13,0 /* 9600 baud */2771.byte 14,1 /* Baud rate generator enable */2772.byte 3,0xc1 /* enable receiver */2773.byte 5,0xea /* enable transmitter */2774.byte -12775.even2776#endif27772778#ifdef CONFIG_ATARI2779/* #define USE_PRINTER */2780/* #define USE_SCC_B */2781/* #define USE_SCC_A */2782#define USE_MFP27832784#if defined(USE_SCC_A) || defined(USE_SCC_B)2785#define USE_SCC2786/* Initialisation table for SCC */2787L(scc_initable):2788.byte 9,12 /* Reset */2789.byte 4,0x44 /* x16, 1 stopbit, no parity */2790.byte 3,0xc0 /* receiver: 8 bpc */2791.byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */2792.byte 9,0 /* no interrupts */2793.byte 10,0 /* NRZ */2794.byte 11,0x50 /* use baud rate generator */2795.byte 12,24,13,0 /* 9600 baud */2796.byte 14,2,14,3 /* use master clock for BRG, enable */2797.byte 3,0xc1 /* enable receiver */2798.byte 5,0xea /* enable transmitter */2799.byte -12800.even2801#endif28022803#ifdef USE_PRINTER28042805LPSG_SELECT = 0xff88002806LPSG_READ = 0xff88002807LPSG_WRITE = 0xff88022808LPSG_IO_A = 142809LPSG_IO_B = 152810LPSG_CONTROL = 72811LSTMFP_GPIP = 0xfffa012812LSTMFP_DDR = 0xfffa052813LSTMFP_IERB = 0xfffa0928142815#elif defined(USE_SCC_B)28162817LSCC_CTRL = 0xff8c852818LSCC_DATA = 0xff8c8728192820#elif defined(USE_SCC_A)28212822LSCC_CTRL = 0xff8c812823LSCC_DATA = 0xff8c8328242825#elif defined(USE_MFP)28262827LMFP_UCR = 0xfffa292828LMFP_TDCDR = 0xfffa1d2829LMFP_TDDR = 0xfffa252830LMFP_TSR = 0xfffa2d2831LMFP_UDR = 0xfffa2f28322833#endif2834#endif /* CONFIG_ATARI */28352836/*2837* Serial port output support.2838*/28392840/*2841* Initialize serial port hardware for 9600/8/12842*/2843func_start serial_init,%d0/%d1/%a0/%a12844/*2845* Some of the register usage that follows2846* CONFIG_AMIGA2847* a0 = pointer to boot info record2848* d0 = boot info offset2849* CONFIG_ATARI2850* a0 = address of SCC2851* a1 = Liobase address/address of scc_initable2852* d0 = init data for serial port2853* CONFIG_MAC2854* a0 = address of SCC2855* a1 = address of scc_initable_mac2856* d0 = init data for serial port2857*/28582859#ifdef CONFIG_AMIGA2860#define SERIAL_DTR 72861#define SERIAL_CNTRL CIABBASE+C_PRA28622863is_not_amiga(1f)2864lea %pc@(L(custom)),%a02865movel #-ZTWOBASE,%a0@2866bclr #SERIAL_DTR,SERIAL_CNTRL-ZTWOBASE2867get_bi_record BI_AMIGA_SERPER2868movew %a0@,CUSTOMBASE+C_SERPER-ZTWOBASE2869| movew #61,CUSTOMBASE+C_SERPER-ZTWOBASE28701:2871#endif2872#ifdef CONFIG_ATARI2873is_not_atari(4f)2874movel %pc@(L(iobase)),%a12875#if defined(USE_PRINTER)2876bclr #0,%a1@(LSTMFP_IERB)2877bclr #0,%a1@(LSTMFP_DDR)2878moveb #LPSG_CONTROL,%a1@(LPSG_SELECT)2879moveb #0xff,%a1@(LPSG_WRITE)2880moveb #LPSG_IO_B,%a1@(LPSG_SELECT)2881clrb %a1@(LPSG_WRITE)2882moveb #LPSG_IO_A,%a1@(LPSG_SELECT)2883moveb %a1@(LPSG_READ),%d02884bset #5,%d02885moveb %d0,%a1@(LPSG_WRITE)2886#elif defined(USE_SCC)2887lea %a1@(LSCC_CTRL),%a02888lea %pc@(L(scc_initable)),%a128892: moveb %a1@+,%d02890jmi 3f2891moveb %d0,%a0@2892moveb %a1@+,%a0@2893jra 2b28943: clrb %a0@2895#elif defined(USE_MFP)2896bclr #1,%a1@(LMFP_TSR)2897moveb #0x88,%a1@(LMFP_UCR)2898andb #0x70,%a1@(LMFP_TDCDR)2899moveb #2,%a1@(LMFP_TDDR)2900orb #1,%a1@(LMFP_TDCDR)2901bset #1,%a1@(LMFP_TSR)2902#endif2903jra L(serial_init_done)29044:2905#endif2906#ifdef CONFIG_MAC2907is_not_mac(L(serial_init_not_mac))2908#ifdef MAC_SERIAL_DEBUG2909#if !defined(MAC_USE_SCC_A) && !defined(MAC_USE_SCC_B)2910#define MAC_USE_SCC_B2911#endif2912#define mac_scc_cha_b_ctrl_offset 0x02913#define mac_scc_cha_a_ctrl_offset 0x22914#define mac_scc_cha_b_data_offset 0x42915#define mac_scc_cha_a_data_offset 0x629162917#ifdef MAC_USE_SCC_A2918/* Initialize channel A */2919movel %pc@(L(mac_sccbase)),%a02920lea %pc@(L(scc_initable_mac)),%a129215: moveb %a1@+,%d02922jmi 6f2923moveb %d0,%a0@(mac_scc_cha_a_ctrl_offset)2924moveb %a1@+,%a0@(mac_scc_cha_a_ctrl_offset)2925jra 5b29266:2927#endif /* MAC_USE_SCC_A */29282929#ifdef MAC_USE_SCC_B2930/* Initialize channel B */2931#ifndef MAC_USE_SCC_A /* Load mac_sccbase only if needed */2932movel %pc@(L(mac_sccbase)),%a02933#endif /* MAC_USE_SCC_A */2934lea %pc@(L(scc_initable_mac)),%a129357: moveb %a1@+,%d02936jmi 8f2937moveb %d0,%a0@(mac_scc_cha_b_ctrl_offset)2938moveb %a1@+,%a0@(mac_scc_cha_b_ctrl_offset)2939jra 7b29408:2941#endif /* MAC_USE_SCC_B */2942#endif /* MAC_SERIAL_DEBUG */29432944jra L(serial_init_done)2945L(serial_init_not_mac):2946#endif /* CONFIG_MAC */29472948#ifdef CONFIG_Q402949is_not_q40(2f)2950/* debug output goes into SRAM, so we don't do it unless requested2951- check for '%LX$' signature in SRAM */2952lea %pc@(q40_mem_cptr),%a12953move.l #0xff020010,%a1@ /* must be inited - also used by debug=mem */2954move.l #0xff020000,%a12955cmp.b #'%',%a1@2956bne 2f /*nodbg*/2957addq.w #4,%a12958cmp.b #'L',%a1@2959bne 2f /*nodbg*/2960addq.w #4,%a12961cmp.b #'X',%a1@2962bne 2f /*nodbg*/2963addq.w #4,%a12964cmp.b #'$',%a1@2965bne 2f /*nodbg*/2966/* signature OK */2967lea %pc@(L(q40_do_debug)),%a12968tas %a1@2969/*nodbg: q40_do_debug is 0 by default*/29702:2971#endif29722973#ifdef CONFIG_APOLLO2974/* We count on the PROM initializing SIO1 */2975#endif29762977#ifdef CONFIG_HP3002978/* We count on the boot loader initialising the UART */2979#endif29802981L(serial_init_done):2982func_return serial_init29832984/*2985* Output character on serial port.2986*/2987func_start serial_putc,%d0/%d1/%a0/%a129882989movel ARG1,%d02990cmpib #'\n',%d02991jbne 1f29922993/* A little safe recursion is good for the soul */2994serial_putc #'\r'29951:29962997#ifdef CONFIG_AMIGA2998is_not_amiga(2f)2999andw #0x00ff,%d03000oriw #0x0100,%d03001movel %pc@(L(custom)),%a03002movew %d0,%a0@(CUSTOMBASE+C_SERDAT)30031: movew %a0@(CUSTOMBASE+C_SERDATR),%d03004andw #0x2000,%d03005jeq 1b3006jra L(serial_putc_done)30072:3008#endif30093010#ifdef CONFIG_MAC3011is_not_mac(5f)30123013#ifdef MAC_SERIAL_DEBUG30143015#ifdef MAC_USE_SCC_A3016movel %pc@(L(mac_sccbase)),%a130173: btst #2,%a1@(mac_scc_cha_a_ctrl_offset)3018jeq 3b3019moveb %d0,%a1@(mac_scc_cha_a_data_offset)3020#endif /* MAC_USE_SCC_A */30213022#ifdef MAC_USE_SCC_B3023#ifndef MAC_USE_SCC_A /* Load mac_sccbase only if needed */3024movel %pc@(L(mac_sccbase)),%a13025#endif /* MAC_USE_SCC_A */30264: btst #2,%a1@(mac_scc_cha_b_ctrl_offset)3027jeq 4b3028moveb %d0,%a1@(mac_scc_cha_b_data_offset)3029#endif /* MAC_USE_SCC_B */30303031#endif /* MAC_SERIAL_DEBUG */30323033jra L(serial_putc_done)30345:3035#endif /* CONFIG_MAC */30363037#ifdef CONFIG_ATARI3038is_not_atari(4f)3039movel %pc@(L(iobase)),%a13040#if defined(USE_PRINTER)30413: btst #0,%a1@(LSTMFP_GPIP)3042jne 3b3043moveb #LPSG_IO_B,%a1@(LPSG_SELECT)3044moveb %d0,%a1@(LPSG_WRITE)3045moveb #LPSG_IO_A,%a1@(LPSG_SELECT)3046moveb %a1@(LPSG_READ),%d03047bclr #5,%d03048moveb %d0,%a1@(LPSG_WRITE)3049nop3050nop3051bset #5,%d03052moveb %d0,%a1@(LPSG_WRITE)3053#elif defined(USE_SCC)30543: btst #2,%a1@(LSCC_CTRL)3055jeq 3b3056moveb %d0,%a1@(LSCC_DATA)3057#elif defined(USE_MFP)30583: btst #7,%a1@(LMFP_TSR)3059jeq 3b3060moveb %d0,%a1@(LMFP_UDR)3061#endif3062jra L(serial_putc_done)30634:3064#endif /* CONFIG_ATARI */30653066#ifdef CONFIG_MVME1473067is_not_mvme147(2f)30681: btst #2,M147_SCC_CTRL_A3069jeq 1b3070moveb %d0,M147_SCC_DATA_A3071jbra L(serial_putc_done)30722:3073#endif30743075#ifdef CONFIG_MVME16x3076is_not_mvme16x(2f)3077/*3078* If the loader gave us a board type then we can use that to3079* select an appropriate output routine; otherwise we just use3080* the Bug code. If we have to use the Bug that means the Bug3081* workspace has to be valid, which means the Bug has to use3082* the SRAM, which is non-standard.3083*/3084moveml %d0-%d7/%a2-%a6,%sp@-3085movel vme_brdtype,%d13086jeq 1f | No tag - use the Bug3087cmpi #VME_TYPE_MVME162,%d13088jeq 6f3089cmpi #VME_TYPE_MVME172,%d13090jne 5f3091/* 162/172; it's an SCC */30926: btst #2,M162_SCC_CTRL_A3093nop3094nop3095nop3096jeq 6b3097moveb #8,M162_SCC_CTRL_A3098nop3099nop3100nop3101moveb %d0,M162_SCC_CTRL_A3102jra 3f31035:3104/* 166/167/177; it's a CD2401 */3105moveb #0,M167_CYCAR3106moveb M167_CYIER,%d23107moveb #0x02,M167_CYIER31087:3109btst #5,M167_PCSCCTICR3110jeq 7b3111moveb M167_PCTPIACKR,%d13112moveb M167_CYLICR,%d13113jeq 8f3114moveb #0x08,M167_CYTEOIR3115jra 7b31168:3117moveb %d0,M167_CYTDR3118moveb #0,M167_CYTEOIR3119moveb %d2,M167_CYIER3120jra 3f31211:3122moveb %d0,%sp@-3123trap #153124.word 0x0020 /* TRAP 0x020 */31253:3126moveml %sp@+,%d0-%d7/%a2-%a63127jbra L(serial_putc_done)31282:3129#endif /* CONFIG_MVME16x */31303131#ifdef CONFIG_BVME60003132is_not_bvme6000(2f)3133/*3134* The BVME6000 machine has a serial port ...3135*/31361: btst #2,BVME_SCC_CTRL_A3137jeq 1b3138moveb %d0,BVME_SCC_DATA_A3139jbra L(serial_putc_done)31402:3141#endif31423143#ifdef CONFIG_SUN3X3144is_not_sun3x(2f)3145movel %d0,-(%sp)3146movel 0xFEFE0018,%a13147jbsr (%a1)3148addq #4,%sp3149jbra L(serial_putc_done)31502:3151#endif31523153#ifdef CONFIG_Q403154is_not_q40(2f)3155tst.l %pc@(L(q40_do_debug)) /* only debug if requested */3156beq 2f3157lea %pc@(q40_mem_cptr),%a13158move.l %a1@,%a03159move.b %d0,%a0@3160addq.l #4,%a03161move.l %a0,%a1@3162jbra L(serial_putc_done)31632:3164#endif31653166#ifdef CONFIG_APOLLO3167is_not_apollo(2f)3168movl %pc@(L(iobase)),%a13169moveb %d0,%a1@(LTHRB0)31701: moveb %a1@(LSRB0),%d03171andb #0x4,%d03172beq 1b3173jbra L(serial_putc_done)31742:3175#endif31763177#ifdef CONFIG_HP3003178is_not_hp300(3f)3179movl %pc@(L(iobase)),%a13180addl %pc@(L(uartbase)),%a13181movel %pc@(L(uart_scode)),%d1 /* Check the scode */3182jmi 3f /* Unset? Exit */3183cmpi #256,%d1 /* APCI scode? */3184jeq 2f31851: moveb %a1@(DCALSR),%d1 /* Output to DCA */3186andb #0x20,%d13187beq 1b3188moveb %d0,%a1@(DCADATA)3189jbra L(serial_putc_done)31902: moveb %a1@(APCILSR),%d1 /* Output to APCI */3191andb #0x20,%d13192beq 2b3193moveb %d0,%a1@(APCIDATA)3194jbra L(serial_putc_done)31953:3196#endif31973198L(serial_putc_done):3199func_return serial_putc32003201/*3202* Output a string.3203*/3204func_start puts,%d0/%a032053206movel ARG1,%a03207jra 2f32081:3209#ifdef CONSOLE3210console_putc %d03211#endif3212#ifdef SERIAL_DEBUG3213serial_putc %d03214#endif32152: moveb %a0@+,%d03216jne 1b32173218func_return puts32193220/*3221* Output number in hex notation.3222*/32233224func_start putn,%d0-%d232253226putc ' '32273228movel ARG1,%d03229moveq #7,%d132301: roll #4,%d03231move %d0,%d23232andb #0x0f,%d23233addb #'0',%d23234cmpb #'9',%d23235jls 2f3236addb #'A'-('9'+1),%d232372:3238#ifdef CONSOLE3239console_putc %d23240#endif3241#ifdef SERIAL_DEBUG3242serial_putc %d23243#endif3244dbra %d1,1b32453246func_return putn32473248#ifdef CONFIG_MAC3249/*3250* mac_serial_print3251*3252* This routine takes its parameters on the stack. It then3253* turns around and calls the internal routine. This routine3254* is used until the Linux console driver initializes itself.3255*3256* The calling parameters are:3257* void mac_serial_print(const char *str);3258*3259* This routine does NOT understand variable arguments only3260* simple strings!3261*/3262ENTRY(mac_serial_print)3263moveml %d0/%a0,%sp@-3264#if 13265move %sr,%sp@-3266ori #0x0700,%sr3267#endif3268movel %sp@(10),%a0 /* fetch parameter */3269jra 2f32701: serial_putc %d032712: moveb %a0@+,%d03272jne 1b3273#if 13274move %sp@+,%sr3275#endif3276moveml %sp@+,%d0/%a03277rts3278#endif /* CONFIG_MAC */32793280#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)3281func_start set_leds,%d0/%a03282movel ARG1,%d03283#ifdef CONFIG_HP3003284is_not_hp300(1f)3285movel %pc@(L(iobase)),%a03286moveb %d0,%a0@(0x1ffff)3287jra 2f3288#endif32891:3290#ifdef CONFIG_APOLLO3291movel %pc@(L(iobase)),%a03292lsll #8,%d03293eorw #0xff00,%d03294moveb %d0,%a0@(LCPUCTRL)3295#endif32962:3297func_return set_leds3298#endif32993300#ifdef CONSOLE3301/*3302* For continuity, see the data alignment3303* to which this structure is tied.3304*/3305#define Lconsole_struct_cur_column 03306#define Lconsole_struct_cur_row 43307#define Lconsole_struct_num_columns 83308#define Lconsole_struct_num_rows 123309#define Lconsole_struct_left_edge 163310#define Lconsole_struct_penguin_putc 2033113312func_start console_init,%a0-%a4/%d0-%d73313/*3314* Some of the register usage that follows3315* a0 = pointer to boot_info3316* a1 = pointer to screen3317* a2 = pointer to Lconsole_globals3318* d3 = pixel width of screen3319* d4 = pixel height of screen3320* (d3,d4) ~= (x,y) of a point just below3321* and to the right of the screen3322* NOT on the screen!3323* d5 = number of bytes per scan line3324* d6 = number of bytes on the entire screen3325*/33263327lea %pc@(L(console_globals)),%a23328movel %pc@(L(mac_videobase)),%a13329movel %pc@(L(mac_rowbytes)),%d53330movel %pc@(L(mac_dimensions)),%d3 /* -> low byte */3331movel %d3,%d43332swap %d4 /* -> high byte */3333andl #0xffff,%d3 /* d3 = screen width in pixels */3334andl #0xffff,%d4 /* d4 = screen height in pixels */33353336movel %d5,%d63337| subl #20,%d63338mulul %d4,%d6 /* scan line bytes x num scan lines */3339divul #8,%d6 /* we'll clear 8 bytes at a time */3340moveq #-1,%d0 /* Mac_black */3341subq #1,%d633423343L(console_clear_loop):3344movel %d0,%a1@+3345movel %d0,%a1@+3346dbra %d6,L(console_clear_loop)33473348/* Calculate font size */33493350#if defined(FONT_8x8) && defined(CONFIG_FONT_8x8)3351lea %pc@(font_vga_8x8),%a03352#elif defined(FONT_8x16) && defined(CONFIG_FONT_8x16)3353lea %pc@(font_vga_8x16),%a03354#elif defined(FONT_6x11) && defined(CONFIG_FONT_6x11)3355lea %pc@(font_vga_6x11),%a03356#elif defined(CONFIG_FONT_8x8) /* default */3357lea %pc@(font_vga_8x8),%a03358#else /* no compiled-in font */3359lea 0,%a03360#endif33613362/*3363* At this point we make a shift in register usage3364* a1 = address of console_font pointer3365*/3366lea %pc@(L(console_font)),%a13367movel %a0,%a1@ /* store pointer to struct fbcon_font_desc in console_font */3368tstl %a03369jeq 1f3370lea %pc@(L(console_font_data)),%a43371movel %a0@(FONT_DESC_DATA),%d03372subl #L(console_font),%a13373addl %a1,%d03374movel %d0,%a4@33753376/*3377* Calculate global maxs3378* Note - we can use either an3379* 8 x 16 or 8 x 8 character font3380* 6 x 11 also supported3381*/3382/* ASSERT: a0 = contents of Lconsole_font */3383movel %d3,%d0 /* screen width in pixels */3384divul %a0@(FONT_DESC_WIDTH),%d0 /* d0 = max num chars per row */33853386movel %d4,%d1 /* screen height in pixels */3387divul %a0@(FONT_DESC_HEIGHT),%d1 /* d1 = max num rows */33883389movel %d0,%a2@(Lconsole_struct_num_columns)3390movel %d1,%a2@(Lconsole_struct_num_rows)33913392/*3393* Clear the current row and column3394*/3395clrl %a2@(Lconsole_struct_cur_column)3396clrl %a2@(Lconsole_struct_cur_row)3397clrl %a2@(Lconsole_struct_left_edge)33983399/*3400* Initialization is complete3401*/34021:3403func_return console_init34043405func_start console_put_stats,%a0/%d73406/*3407* Some of the register usage that follows3408* a0 = pointer to boot_info3409* d7 = value of boot_info fields3410*/3411puts "\nMacLinux\n\n"34123413#ifdef SERIAL_DEBUG3414puts " vidaddr:"3415putn %pc@(L(mac_videobase)) /* video addr. */34163417puts "\n _stext:"3418lea %pc@(_stext),%a03419putn %a034203421puts "\nbootinfo:"3422lea %pc@(_end),%a03423putn %a034243425puts "\ncpuid:"3426putn %pc@(L(cputype))3427putc '\n'34283429#ifdef MAC_SERIAL_DEBUG3430putn %pc@(L(mac_sccbase))3431putc '\n'3432#endif3433# if defined(MMU_PRINT)3434jbsr mmu_print_machine_cpu_types3435# endif /* MMU_PRINT */3436#endif /* SERIAL_DEBUG */34373438func_return console_put_stats34393440#ifdef CONSOLE_PENGUIN3441func_start console_put_penguin,%a0-%a1/%d0-%d73442/*3443* Get 'that_penguin' onto the screen in the upper right corner3444* penguin is 64 x 74 pixels, align against right edge of screen3445*/3446lea %pc@(L(mac_dimensions)),%a03447movel %a0@,%d03448andil #0xffff,%d03449subil #64,%d0 /* snug up against the right edge */3450clrl %d1 /* start at the top */3451movel #73,%d73452lea %pc@(L(that_penguin)),%a13453L(console_penguin_row):3454movel #31,%d63455L(console_penguin_pixel_pair):3456moveb %a1@,%d23457lsrb #4,%d23458console_plot_pixel %d0,%d1,%d23459addq #1,%d03460moveb %a1@+,%d23461console_plot_pixel %d0,%d1,%d23462addq #1,%d03463dbra %d6,L(console_penguin_pixel_pair)34643465subil #64,%d03466addq #1,%d13467dbra %d7,L(console_penguin_row)34683469func_return console_put_penguin34703471/* include penguin bitmap */3472L(that_penguin):3473#include "../mac/mac_penguin.S"3474#endif34753476/*3477* Calculate source and destination addresses3478* output a1 = dest3479* a2 = source3480*/34813482func_start console_scroll,%a0-%a4/%d0-%d73483lea %pc@(L(mac_videobase)),%a03484movel %a0@,%a13485movel %a1,%a23486lea %pc@(L(mac_rowbytes)),%a03487movel %a0@,%d53488movel %pc@(L(console_font)),%a03489tstl %a03490jeq 1f3491mulul %a0@(FONT_DESC_HEIGHT),%d5 /* account for # scan lines per character */3492addal %d5,%a234933494/*3495* Get dimensions3496*/3497lea %pc@(L(mac_dimensions)),%a03498movel %a0@,%d33499movel %d3,%d43500swap %d43501andl #0xffff,%d3 /* d3 = screen width in pixels */3502andl #0xffff,%d4 /* d4 = screen height in pixels */35033504/*3505* Calculate number of bytes to move3506*/3507lea %pc@(L(mac_rowbytes)),%a03508movel %a0@,%d63509movel %pc@(L(console_font)),%a03510subl %a0@(FONT_DESC_HEIGHT),%d4 /* we're not scrolling the top row! */3511mulul %d4,%d6 /* scan line bytes x num scan lines */3512divul #32,%d6 /* we'll move 8 longs at a time */3513subq #1,%d635143515L(console_scroll_loop):3516movel %a2@+,%a1@+3517movel %a2@+,%a1@+3518movel %a2@+,%a1@+3519movel %a2@+,%a1@+3520movel %a2@+,%a1@+3521movel %a2@+,%a1@+3522movel %a2@+,%a1@+3523movel %a2@+,%a1@+3524dbra %d6,L(console_scroll_loop)35253526lea %pc@(L(mac_rowbytes)),%a03527movel %a0@,%d63528movel %pc@(L(console_font)),%a03529mulul %a0@(FONT_DESC_HEIGHT),%d6 /* scan line bytes x font height */3530divul #32,%d6 /* we'll move 8 words at a time */3531subq #1,%d635323533moveq #-1,%d03534L(console_scroll_clear_loop):3535movel %d0,%a1@+3536movel %d0,%a1@+3537movel %d0,%a1@+3538movel %d0,%a1@+3539movel %d0,%a1@+3540movel %d0,%a1@+3541movel %d0,%a1@+3542movel %d0,%a1@+3543dbra %d6,L(console_scroll_clear_loop)354435451:3546func_return console_scroll354735483549func_start console_putc,%a0/%a1/%d0-%d735503551is_not_mac(L(console_exit))3552tstl %pc@(L(console_font))3553jeq L(console_exit)35543555/* Output character in d7 on console.3556*/3557movel ARG1,%d73558cmpib #'\n',%d73559jbne 1f35603561/* A little safe recursion is good for the soul */3562console_putc #'\r'35631:3564lea %pc@(L(console_globals)),%a035653566cmpib #10,%d73567jne L(console_not_lf)3568movel %a0@(Lconsole_struct_cur_row),%d03569addil #1,%d03570movel %d0,%a0@(Lconsole_struct_cur_row)3571movel %a0@(Lconsole_struct_num_rows),%d13572cmpl %d1,%d03573jcs 1f3574subil #1,%d03575movel %d0,%a0@(Lconsole_struct_cur_row)3576console_scroll35771:3578jra L(console_exit)35793580L(console_not_lf):3581cmpib #13,%d73582jne L(console_not_cr)3583clrl %a0@(Lconsole_struct_cur_column)3584jra L(console_exit)35853586L(console_not_cr):3587cmpib #1,%d73588jne L(console_not_home)3589clrl %a0@(Lconsole_struct_cur_row)3590clrl %a0@(Lconsole_struct_cur_column)3591jra L(console_exit)35923593/*3594* At this point we know that the %d7 character is going to be3595* rendered on the screen. Register usage is -3596* a0 = pointer to console globals3597* a1 = font data3598* d0 = cursor column3599* d1 = cursor row to draw the character3600* d7 = character number3601*/3602L(console_not_home):3603movel %a0@(Lconsole_struct_cur_column),%d03604addql #1,%a0@(Lconsole_struct_cur_column)3605movel %a0@(Lconsole_struct_num_columns),%d13606cmpl %d1,%d03607jcs 1f3608console_putc #'\n' /* recursion is OK! */36091:3610movel %a0@(Lconsole_struct_cur_row),%d136113612/*3613* At this point we make a shift in register usage3614* a0 = address of pointer to font data (fbcon_font_desc)3615*/3616movel %pc@(L(console_font)),%a03617movel %pc@(L(console_font_data)),%a1 /* Load fbcon_font_desc.data into a1 */3618andl #0x000000ff,%d73619/* ASSERT: a0 = contents of Lconsole_font */3620mulul %a0@(FONT_DESC_HEIGHT),%d7 /* d7 = index into font data */3621addl %d7,%a1 /* a1 = points to char image */36223623/*3624* At this point we make a shift in register usage3625* d0 = pixel coordinate, x3626* d1 = pixel coordinate, y3627* d2 = (bit 0) 1/0 for white/black (!) pixel on screen3628* d3 = font scan line data (8 pixels)3629* d6 = count down for the font's pixel width (8)3630* d7 = count down for the font's pixel count in height3631*/3632/* ASSERT: a0 = contents of Lconsole_font */3633mulul %a0@(FONT_DESC_WIDTH),%d03634mulul %a0@(FONT_DESC_HEIGHT),%d13635movel %a0@(FONT_DESC_HEIGHT),%d7 /* Load fbcon_font_desc.height into d7 */3636subq #1,%d73637L(console_read_char_scanline):3638moveb %a1@+,%d336393640/* ASSERT: a0 = contents of Lconsole_font */3641movel %a0@(FONT_DESC_WIDTH),%d6 /* Load fbcon_font_desc.width into d6 */3642subql #1,%d636433644L(console_do_font_scanline):3645lslb #1,%d33646scsb %d2 /* convert 1 bit into a byte */3647console_plot_pixel %d0,%d1,%d23648addq #1,%d03649dbra %d6,L(console_do_font_scanline)36503651/* ASSERT: a0 = contents of Lconsole_font */3652subl %a0@(FONT_DESC_WIDTH),%d03653addq #1,%d13654dbra %d7,L(console_read_char_scanline)36553656L(console_exit):3657func_return console_putc36583659/*3660* Input:3661* d0 = x coordinate3662* d1 = y coordinate3663* d2 = (bit 0) 1/0 for white/black (!)3664* All registers are preserved3665*/3666func_start console_plot_pixel,%a0-%a1/%d0-%d436673668movel %pc@(L(mac_videobase)),%a13669movel %pc@(L(mac_videodepth)),%d33670movel ARG1,%d03671movel ARG2,%d13672mulul %pc@(L(mac_rowbytes)),%d13673movel ARG3,%d236743675/*3676* Register usage:3677* d0 = x coord becomes byte offset into frame buffer3678* d1 = y coord3679* d2 = black or white (0/1)3680* d3 = video depth3681* d4 = temp of x (d0) for many bit depths3682*/3683L(test_1bit):3684cmpb #1,%d33685jbne L(test_2bit)3686movel %d0,%d4 /* we need the low order 3 bits! */3687divul #8,%d03688addal %d0,%a13689addal %d1,%a13690andb #7,%d43691eorb #7,%d4 /* reverse the x-coordinate w/ screen-bit # */3692andb #1,%d23693jbne L(white_1)3694bsetb %d4,%a1@3695jbra L(console_plot_pixel_exit)3696L(white_1):3697bclrb %d4,%a1@3698jbra L(console_plot_pixel_exit)36993700L(test_2bit):3701cmpb #2,%d33702jbne L(test_4bit)3703movel %d0,%d4 /* we need the low order 2 bits! */3704divul #4,%d03705addal %d0,%a13706addal %d1,%a13707andb #3,%d43708eorb #3,%d4 /* reverse the x-coordinate w/ screen-bit # */3709lsll #1,%d4 /* ! */3710andb #1,%d23711jbne L(white_2)3712bsetb %d4,%a1@3713addq #1,%d43714bsetb %d4,%a1@3715jbra L(console_plot_pixel_exit)3716L(white_2):3717bclrb %d4,%a1@3718addq #1,%d43719bclrb %d4,%a1@3720jbra L(console_plot_pixel_exit)37213722L(test_4bit):3723cmpb #4,%d33724jbne L(test_8bit)3725movel %d0,%d4 /* we need the low order bit! */3726divul #2,%d03727addal %d0,%a13728addal %d1,%a13729andb #1,%d43730eorb #1,%d43731lsll #2,%d4 /* ! */3732andb #1,%d23733jbne L(white_4)3734bsetb %d4,%a1@3735addq #1,%d43736bsetb %d4,%a1@3737addq #1,%d43738bsetb %d4,%a1@3739addq #1,%d43740bsetb %d4,%a1@3741jbra L(console_plot_pixel_exit)3742L(white_4):3743bclrb %d4,%a1@3744addq #1,%d43745bclrb %d4,%a1@3746addq #1,%d43747bclrb %d4,%a1@3748addq #1,%d43749bclrb %d4,%a1@3750jbra L(console_plot_pixel_exit)37513752L(test_8bit):3753cmpb #8,%d33754jbne L(test_16bit)3755addal %d0,%a13756addal %d1,%a13757andb #1,%d23758jbne L(white_8)3759moveb #0xff,%a1@3760jbra L(console_plot_pixel_exit)3761L(white_8):3762clrb %a1@3763jbra L(console_plot_pixel_exit)37643765L(test_16bit):3766cmpb #16,%d33767jbne L(console_plot_pixel_exit)3768addal %d0,%a13769addal %d0,%a13770addal %d1,%a13771andb #1,%d23772jbne L(white_16)3773clrw %a1@3774jbra L(console_plot_pixel_exit)3775L(white_16):3776movew #0x0fff,%a1@3777jbra L(console_plot_pixel_exit)37783779L(console_plot_pixel_exit):3780func_return console_plot_pixel3781#endif /* CONSOLE */37823783#if 03784/*3785* This is some old code lying around. I don't believe3786* it's used or important anymore. My guess is it contributed3787* to getting to this point, but it's done for now.3788* It was still in the 2.1.77 head.S, so it's still here.3789* (And still not used!)3790*/3791L(showtest):3792moveml %a0/%d7,%sp@-3793puts "A="3794putn %a137953796.long 0xf0119f15 | ptestr #5,%a1@,#7,%a037973798puts "DA="3799putn %a038003801puts "D="3802putn %a0@38033804puts "S="3805lea %pc@(L(mmu)),%a03806.long 0xf0106200 | pmove %psr,%a0@3807clrl %d73808movew %a0@,%d73809putn %d738103811putc '\n'3812moveml %sp@+,%a0/%d73813rts3814#endif /* 0 */38153816__INITDATA3817.align 438183819#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || \3820defined(CONFIG_HP300) || defined(CONFIG_APOLLO)3821L(custom):3822L(iobase):3823.long 03824#endif38253826#if defined(CONSOLE)3827L(console_globals):3828.long 0 /* cursor column */3829.long 0 /* cursor row */3830.long 0 /* max num columns */3831.long 0 /* max num rows */3832.long 0 /* left edge */3833.long 0 /* mac putc */3834L(console_font):3835.long 0 /* pointer to console font (struct font_desc) */3836L(console_font_data):3837.long 0 /* pointer to console font data */3838#endif /* CONSOLE */38393840#if defined(MMU_PRINT)3841L(mmu_print_data):3842.long 0 /* valid flag */3843.long 0 /* start logical */3844.long 0 /* next logical */3845.long 0 /* start physical */3846.long 0 /* next physical */3847#endif /* MMU_PRINT */38483849L(cputype):3850.long 03851L(mmu_cached_pointer_tables):3852.long 03853L(mmu_num_pointer_tables):3854.long 03855L(phys_kernel_start):3856.long 03857L(kernel_end):3858.long 03859L(memory_start):3860.long 03861L(kernel_pgdir_ptr):3862.long 03863L(temp_mmap_mem):3864.long 038653866#if defined (CONFIG_MVME147)3867M147_SCC_CTRL_A = 0xfffe30023868M147_SCC_DATA_A = 0xfffe30033869#endif38703871#if defined (CONFIG_MVME16x)3872M162_SCC_CTRL_A = 0xfff450053873M167_CYCAR = 0xfff450ee3874M167_CYIER = 0xfff450113875M167_CYLICR = 0xfff450263876M167_CYTEOIR = 0xfff450853877M167_CYTDR = 0xfff450f83878M167_PCSCCTICR = 0xfff4201e3879M167_PCTPIACKR = 0xfff420253880#endif38813882#if defined (CONFIG_BVME6000)3883BVME_SCC_CTRL_A = 0xffb0000b3884BVME_SCC_DATA_A = 0xffb0000f3885#endif38863887#if defined(CONFIG_MAC)3888L(mac_booter_data):3889.long 03890L(mac_videobase):3891.long 03892L(mac_videodepth):3893.long 03894L(mac_dimensions):3895.long 03896L(mac_rowbytes):3897.long 03898#ifdef MAC_SERIAL_DEBUG3899L(mac_sccbase):3900.long 03901#endif /* MAC_SERIAL_DEBUG */3902#endif39033904#if defined (CONFIG_APOLLO)3905LSRB0 = 0x104123906LTHRB0 = 0x104163907LCPUCTRL = 0x101003908#endif39093910#if defined(CONFIG_HP300)3911DCADATA = 0x113912DCALSR = 0x1b3913APCIDATA = 0x003914APCILSR = 0x143915L(uartbase):3916.long 03917L(uart_scode):3918.long -13919#endif39203921__FINIT3922.data3923.align 439243925availmem:3926.long 03927m68k_pgtable_cachemode:3928.long 03929m68k_supervisor_cachemode:3930.long 03931#if defined(CONFIG_MVME16x)3932mvme_bdid:3933.long 0,0,0,0,0,0,0,03934#endif3935#if defined(CONFIG_Q40)3936q40_mem_cptr:3937.long 03938L(q40_do_debug):3939.long 03940#endif394139423943