Resent-Date: Wed, 2 Dec 1998 19:39:24 +0100 (MET)
From: micha@schmitzm.hip.berkeley.edu (Michael Schmitz)
Subject: Re: Mac patches for 2.1.130
In-Reply-To: <d31zmihq30.fsf@valhall.cern.ch> from Jes Sorensen at "Dec 2, 98 10:04:51 am"
To: Jes.Sorensen@cern.ch (Jes Sorensen)
Date: Wed, 2 Dec 1998 08:41:54 -0800 (PST)
Cc: MSchmitz@lbl.gov, linux-m68k@lists.linux-m68k.org, ddkilzer@earthlink.net,
        linux-mac68k@baltimore.wwaves.com
Reply-To: mschmitz@lbl.gov
Resent-From: linux-m68k@phil.uni-sb.de

> Michael> Ok, without further ado: I've attached the minimal set of
> Michael> patches for reasonable Mac support in 2.1.130.
> 
> uudecode complains about the file.

Argh... I hate the crap mail setup (new and improved: Netscrap 4.5
and IMAP) I'm forced to use at work. I attached the file with encoding
set to uuencode because there's no way to include a file anymore. It was 
so much easier with VMSmail :-)

Anyway: here it goes again, this time with Linux/m68k ...

	Michael

--- linux-2.1.130/arch/m68k/kernel/head.S.org	Sat Nov 28 17:25:17 1998
+++ linux-2.1.130/arch/m68k/kernel/head.S	Sat Nov 28 17:30:51 1998
@@ -7,9 +7,11 @@
 **
 ** 68040 fixes by Michael Rausch
 ** 68060 fixes by Roman Hodek
+** MMU cleanup by Randy Thelen
 **
 ** Atari support by Andreas Schwab, using ideas of Robert de Vries
 ** and Bjoern Brauel
+** VME Support by Richard Hirst
 **
 ** 94/11/14 Andreas Schwab: put kernel at PAGESIZE
 ** 94/11/18 Andreas Schwab: remove identity mapping of STRAM for Atari
@@ -18,13 +20,15 @@
 ** 96/04/26 Guenther Kelleter: fixed identity mapping for Falcon with
 ** 			      Magnum- and FX-alternate ram
 ** 98/04/25 Phil Blundell: added HP300 support
+** 1998/08/30 David Kilzer: Added support for fbcon_font_desc structures
+**            for linux-2.1.115
 **
 ** This file is subject to the terms and conditions of the GNU General Public
 ** License. See the file README.legal in the main directory of this archive
 ** for more details.
 **
 */
-
+	
 /*
  * Linux startup code.
  *
@@ -34,37 +38,225 @@
  * Put us in supervisor state.
  *
  * The kernel setup code takes the following steps:
- *   Raise interrupt level
- *   Set up initial kernel memory mapping.
- *	This sets up a mapping of the 4M of memory the kernel
- *	is located in.	It also does a mapping of any initial
- *	machine specific areas.
- * Note that the kernel is located at virtual address 0x1000 == _start
- *   Enable cache memories
- *   Jump to kernel startup
- *
- * Register d6 contains the CPU flags and d4 the machine type
- * from the boot_info information for most of this file.
- * The upper word of d6 contains a bit for '040 or '060, since these two
- * are quite similar for initial mm setup. Another bit in d6 allows
- * distinction of the '060. The lower word of d6 contains the cache mode
- * that should be applied to pages containing descriptors. This mode is
- * non-cached/non-serialized for the '040 and cacheable/write-through for
- * the '060.
- *
- * General register usage:
- *   a6 - start of unused memory
- *	  new pages can be allocated from here
- *   a5 - mmu root table
- *   a4 - mmu pointer table
- *   a3 - mmu page tables
- *   a2 - points to the page table entry for a6
- *	  cache status can be changed (used for '0[46]0)
- *	  you must increase a2 if alloc a new page
- *   d7 - used for debug output and some macros
- *   d6 - cpu type and cache mode
- *   d5 - physical start address of kernel
- *   d4 - machine type
+ * .  Raise interrupt level
+ * .  Set up initial kernel memory mapping.
+ *    .  This sets up a mapping of the 4M of memory the kernel is located in.
+ *    .  It also does a mapping of any initial machine specific areas.
+ * .  Enable the MMU
+ * .  Enable cache memories
+ * .  Jump to kernel startup
+ *
+ * Much of the file restructuring was to accomplish:
+ * 1) Reduce register dependency through-out the file.
+ * 2) Increase use of subroutines to perform functions
+ * 3) Increase readability of the code
+ *
+ * Of course, readability is a subjective issue, so it will never be
+ * argued that that goal was accomplished.  It was merely a goal.
+ * A key way to help make code more readable is to give good 
+ * documentation.  So, the first thing you will find is exaustive
+ * write-ups on the structure of the file, and the features of the
+ * functional subroutines.
+ *
+ * General Structure:
+ * ------------------
+ *	Without a doubt the single largest chunk of head.S is spent
+ * mapping the kernel and I/O physical space into the logical range
+ * for the kernel.  
+ *	There are new subroutines and data structures to make MMU
+ * support cleaner and easier to understand.
+ * 	First, you will find a routine call "mmu_map" which maps
+ * a logical to a physical region for some length given a cache
+ * type on behalf of the caller.  This routine makes writing the
+ * actual per-machine specific code very simple.
+ *	A central part of the code, but not a subroutine in itself,
+ * is the mmu_init code which is broken down into mapping the kernel
+ * (the same for all machines) and mapping machine-specific I/O
+ * regions.
+ *	Also, there will be a description of engaging the MMU and
+ * caches.
+ *	You will notice that there is a chunk of code which
+ * can emit the entire MMU mapping of the machine.  This is present
+ * only in debug modes and can be very helpful.
+ *	Further, there is a new console driver in head.S that is
+ * also only engaged in debug mode.  Currently, it's only supported
+ * on the Macintosh class of machines.  However, it is hoped that
+ * others will plug-in support for specific machines.
+ * 
+ * ######################################################################
+ * 
+ * mmu_map
+ * -------
+ *	mmu_map was written for two key reasons.  First, it was clear
+ * that it was very difficult to read the previous code for mapping
+ * regions of memory.  Second, the Macintosh required such extensive
+ * memory allocations that it didn't make sense to propogate the 
+ * existing code any further.
+ *	mmu_map requires some parameters:
+ * 
+ *	mmu_map (logical, physical, length, cache_type)
+ * 
+ *	While this essentially describes the function in the abstract, you'll
+ * find more indepth description of other parameters at the implementation site.
+ * 
+ * mmu_get_page_table
+ * ------------------
+ * mmu_get_pointer_table
+ * ---------------------
+ *	These routines are used by mmu_map to get fresh tables.  They
+ * will allocate a new page of memory and consume page tables from that page
+ * until the page has been exausted.  Unfortunately, the kernel code uses
+ * a wacky and not very efficient mechanism for re-using pages of memory
+ * allocated for page tables.  Therefore, while this code does set the kpt
+ * global to a correct value upon initial usage, it doesn't help.
+ * 
+ * mmu_clear_root_table
+ * --------------------
+ * mmu_clear_pointer_table
+ * -----------------------
+ * mmu_clear_page_table
+ * --------------------
+ *	Given a pointer to a table, these routines will clear it.
+ * Sometimes writing well factored code can be a source of pride.
+ * 
+ * ######################################################################
+ * 
+ * mmu_init
+ * --------
+ *	Here is where the MMU is initialized for the various platforms.
+ * First, the kernel is mapped for all platforms at the address computed
+ * as the current address (which is known to be physical) and mapped down
+ * to logical 0x01000.  Then there is logic on a per-machine basis.
+ * 
+ * ######################################################################
+ * 
+ * mmu_engage
+ * ----------
+ *	The MMU engagement code is quite extensive and there is ample
+ * description of the algorithm in all it's gory detail at the site of the
+ * evil deed.  However, allow me to state that magic takes place there.
+ * 
+ * ######################################################################
+ * 
+ * mmu_print
+ * ---------
+ *	This algorithm will print out the page tables of the system as
+ * appropriate for an 030 or an 040.  This is useful for debugging purposes
+ * and as such is enclosed in #ifdef MMU_PRINT/#endif clauses.
+ * 
+ * ######################################################################
+ * 
+ * Lconsole_init
+ * -------------
+ *	The console is also able to be turned off.  The console in head.S
+ * is specifically for debugging and can be very useful.  It is surrounded by
+ * #ifdef CONSOLE/#endif clauses so it doesn't have to ship in known-good
+ * kernels.  It's basic algorithm is to determine the size of the screen
+ * (in height/width and bit depth) and then use that information for
+ * displaying an 8x8 font or an 8x16 (widthxheight).  I prefer the 8x8 for
+ * debugging so I can see more good data.  But it was trivial to add support
+ * for both fonts, so I included it.
+ *	Also, the algorithm for plotting pixels is abstracted so that in
+ * theory other platforms could add support for different kinds of frame
+ * buffers.  This could be very useful.
+ * 
+ * Lconsole_put_penguin
+ * --------------------
+ *	An important part of any Linux bring up is the penguin and there's
+ * nothing like getting the Penguin on the screen!  This algorithm will work
+ * on any machine for which there is a console_plot_pixel.
+ * 
+ * console_scroll
+ * --------------
+ *	My hope is that the scroll algorithm does the right thing on the
+ * various platforms, but it wouldn't be hard to add the test conditions
+ * and new code if it doesn't.
+ * 
+ * console_putc
+ * -------------
+ * 
+ * ######################################################################
+ * 
+ *	The only register that is passed through out the system are:
+ * .  A7 -- Stack Pointer (duh)
+ * .  A6 -- Top of Kernel,  available pages are taken from here
+ * .  A5 -- Ptr to Root Table
+ * .  D5 -- Ptr to __start (physical)
+ *	Many other registers are used as passed parameters into
+ * functions or used within functions.
+ *
+ *	Reducing the register usage from a dozen to a few greatly simplified
+ * head.S.
+ *
+ * ######################################################################
+ * 
+ * options
+ * -------
+ *	There are many options availble in a build of this file.  I've
+ * taken the time to describe them here to save you the time of searching
+ * for them and trying to understand what they mean.
+ * 
+ * CONFIG_xxx:	These are the obvious machine configuration defines created
+ * during configuration.  These are defined in include/linux/autoconf.h.
+ *
+ * CONSOLE:	There is support for head.S console in this file.  This
+ * console can talk to a Mac frame buffer, but could easily be extrapolated
+ * to extend it to support other platforms.
+ * 
+ * TEST_MMU:	This is a test harness for running on any given machine but
+ * getting an MMU dump for another class of machine.  The classes of machines
+ * that can be tested are any of the makes (Atari, Amiga, Mac, VME, etc.)
+ * and any of the models (030, 040, 060, etc.).
+ *
+ *	NOTE:	TEST_MMU is NOT permanent!  It is scheduled to be removed
+ *		When head.S boots on Atari, Amiga, Macintosh, and VME
+ *		machines.  At that point the underlying logic will be
+ *		believed to be solid enough to be trusted, and TEST_MMU
+ *		can be dropped.  Do note that that will clean up the
+ *		head.S code significantly as large blocks of #if/#else
+ *		clauses can be removed.
+ * 
+ * MMU_NOCACHE_KERNEL:	On the Macintosh platform there was an inquiry into
+ * determing why devices don't appear to work.  A test case was to remove
+ * the cacheability of the kernel bits.
+ * 
+ * MMU_PRINT:	There is a routine built into head.S that can display the
+ * MMU data structures.  It outputs its result through the Lserial_putc
+ * interface.  So where ever that winds up driving data, that's where the
+ * mmu struct will appear.  On the Macintosh that's typically the console.
+ * 
+ * SERIAL_DEBUG:	There are a series of putc() macro statements
+ * scattered through out the code to give progress of status to the
+ * person sitting at the console.  This constant determines whether those
+ * are used.
+ * 
+ * DEBUG:	This is the standard DEBUG flag that can be set for building
+ *		the kernel.  It has the effect adding additional tests into
+ *		the code.
+ * 
+ * MMU_PRINT_PAGE_USAGE:
+ *		Print the number of pages used by the MMU tables.
+ * 
+ * FONT_6x11:
+ * FONT_8x8:
+ * FONT_8x16:
+ *		In theory these could be determined at run time or handed
+ *		over by the booter.  But, let's be real, it's a fine hard
+ *		coded value.  (But, you will notice the code is run-time
+ *		flexible!)  A pointer to the font's struct fbcon_font_desc
+ *		is kept locally in Lconsole_font.  It is used to determine
+ *		font size information dynamically.
+ * 
+ * Atari constants:
+ * USE_PRINTER:	Use the printer port for serial debug.
+ * USE_SCC_B:	Use the SCC port A (Serial2) for serial debug.
+ * USE_SCC_A:	Use the SCC port B (Modem2) for serial debug.
+ * USE_MFP:	Use the ST-MFP port (Modem1) for serial debug. 
+ * 
+ * Macintosh constants:
+ * MAC_SERIAL_DEBUG:	Turns on serial debug output for the Macintosh.
+ * MAC_USE_SCC_A:	Use the SCC port A (modem) for serial debug.
+ * MAC_USE_SCC_B:	Use the SCC port B (printer) for serial debug (default).
  */
 
 #include <linux/config.h>
@@ -72,11 +264,67 @@
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
+#if defined(CONFIG_MAC)
+#include <video/font.h>		/* offsets for struct fbcon_font_desc */
+#endif
+
+#if defined(CONFIG_MAC)
+
+/*
+ * Macintosh console support
+ */
+#define CONSOLE
+
+/*
+ * Macintosh serial debug support; outputs boot info to the printer 
+ *   and/or modem serial ports
+ */
+#undef MAC_SERIAL_DEBUG
+
+/*
+ * Macintosh serial debug port selection; define one or both; 
+ *   requires MAC_SERIAL_DEBUG to be defined
+ */
+#undef  MAC_USE_SCC_A		/* Macintosh modem serial port */
+#define MAC_USE_SCC_B		/* Macintosh printer serial port */
 
-.globl SYMBOL_NAME(kernel_pg_dir), SYMBOL_NAME(kpt)
+#endif	/* CONFIG_MAC */
+
+#undef MMU_PRINT
+#undef MMU_NOCACHE_KERNEL
+#define SERIAL_DEBUG
+#undef DEBUG
+#undef MMU_PRINT_PAGE_USAGE
+
+/*
+ * For the head.S console, there are three supported fonts, 6x11, 8x16 and 8x8.
+ * The 8x8 font is harder to read but fits more on the screen.
+ */
+#define FONT_8x8 	/* default */
+/* #define FONT_8x16	/* 2nd choice */
+/* #define FONT_6x11	/* 3rd choice */
+	
+.globl SYMBOL_NAME(kernel_pg_dir)
+.globl SYMBOL_NAME(kpt)
 .globl SYMBOL_NAME(availmem)
 .globl SYMBOL_NAME(m68k_pgtable_cachemode)
-.globl SYMBOL_NAME(kernel_pmd_table), SYMBOL_NAME(swapper_pg_dir)
+.globl SYMBOL_NAME(kernel_pmd_table)
+.globl SYMBOL_NAME(swapper_pg_dir)
+
+#if defined(CONFIG_ATARI)
+.globl SYMBOL_NAME(atari_mch_type)
+#endif
+
+#if defined(CONFIG_MAC)
+.globl SYMBOL_NAME(mac_booter_data)
+.globl SYMBOL_NAME(compat_bi)
+.globl SYMBOL_NAME(mac_videobase)
+.globl SYMBOL_NAME(mac_videodepth)
+.globl SYMBOL_NAME(mac_rowbytes)
+#ifdef MAC_SERIAL_DEBUG
+.globl SYMBOL_NAME(mac_sccbase)
+#endif	/* MAC_SERIAL_DEBUG */
+#endif
 
 #if defined(CONFIG_MVME16x)
 .globl SYMBOL_NAME(mvme_bdid_ptr)
@@ -98,6 +346,10 @@
 D6F_040  = 1<<D6B_0460
 D6F_060  = (1<<D6B_0460)+(1<<D6B_060)
 
+CPUTYPE_040	= 1	/* indicates an 040 */
+CPUTYPE_060	= 2	/* indicates an 060 */
+CPUTYPE_0460	= 3	/* if either above are set, this is set */
+
 /* Translation control register */
 TC_ENABLE = 0x8000
 TC_PAGE8K = 0x4000
@@ -144,6 +396,7 @@
 
 /* Miscellaneous definitions */
 PAGESIZE	= 4096
+PAGESHIFT	= 12
 
 ROOT_TABLE_SIZE	= 128
 PTR_TABLE_SIZE	= 128
@@ -155,20 +408,99 @@
 TABLENR_4MB	= 16	/* # of page tables needed to page 4 MB */
 TABLENR_16MB	= 64	/* same for 16 MB */
 
-#define putc(ch) moveq &ch,%d7; jbsr Lserial_putc
-#define putr() putc(13); putc(10)
-#define putn(nr) movel nr,%d7; jbsr Lserial_putnum
-
-#define is_not_amiga(lab) moveq &MACH_AMIGA,%d7; cmpl %d4,%d7; jne lab
-#define is_not_atari(lab) moveq &MACH_ATARI,%d7; cmpl %d4,%d7; jne lab
-#define is_not_mvme16x(lab) moveq &MACH_MVME16x,%d7; cmpl %d4,%d7; jne lab
-#define is_not_bvme6000(lab) moveq &MACH_BVME6000,%d7; cmpl %d4,%d7; jne lab
-#define is_not_hp300(lab) moveq &MACH_HP300,%d7	;  cmpl %d4,%d7; jne lab
-
-#define is_040_or_060(lab) btst &D6B_0460,%d6; jne lab
-#define is_not_040_or_060(lab) btst &D6B_0460,%d6; jeq lab
-#define is_060(lab) btst &D6B_060,%d6; jne lab
-#define is_not_060(lab) btst &D6B_060,%d6; jeq lab
+#if !defined(CONSOLE) && !defined(DEBUG) && defined(SERIAL_DEBUG)
+#  define putc_trace(c)			  \
+		movel	%d7,%sp@-	; \
+		moveb	&c,%d7		; \
+		jbsr	Lserial_putc	; \
+		movel	%sp@+,%d7	;
+#  define putc(c)
+#  define puts(x)
+#  define putr()			  \
+		movel	%d7,%sp@-	; \
+		moveb	#13,%d7		; \
+		jbsr	Lserial_putc	; \
+		moveb	#10,%d7		; \
+		jbsr	Lserial_putc	; \
+		movel	%sp@+,%d7	;
+#  define putn(nr)
+#elif defined(DEBUG) || defined(CONSOLE)
+#  define putc_trace(c)			  \
+		movel	%d7,%sp@-	; \
+		moveb	&c,%d7		; \
+		jbsr	Lserial_putc	; \
+		movel	%sp@+,%d7	;
+#  define putc(c)	putc_trace(c)
+#  define puts(x)			  \
+		movel	%a0,%sp@-	; \
+		lea	%pc@(897f),%a0	; \
+		jbsr	Lserial_puts	; \
+		movel	%sp@+,%a0	; \
+		jbra	898f		; \
+	897:	.string	x		; \
+		.byte	0		; \
+		.even			; \
+	898:
+#  define putr()			  \
+		movel	%d7,%sp@-	; \
+		moveb	#13,%d7		; \
+		jbsr	Lserial_putc	; \
+		moveb	#10,%d7		; \
+		jbsr	Lserial_putc	; \
+		movel	%sp@+,%d7	;
+#  define putn(nr)			  \
+		movel	%d7,%sp@-	; \
+		movel	nr,%d7		; \
+		jbsr	Lserial_putnum	; \
+		movel	%sp@+,%d7	;
+#else /* ! DEBUG && ! SERIAL_DEBUG */
+#  define putc_trace(c)
+#  define putc(c)
+#  define puts(x)
+#  define putr()
+#  define putn(nr)	
+#endif
+
+/*
+ * mmu_map() register usage
+ *
+ * Here a symbolic names for the mmu_map() parameters.
+ */
+#define MAP_PHYS	%a1
+#define MAP_LOG		%a0
+#define MAP_CACHE	%d1
+#define MAP_LENGTH	%d0
+
+#define MMU_MAP(log,phys,leng,cache)	movel	log,MAP_LOG; \
+					movel	phys,MAP_PHYS; \
+					movel	leng,MAP_LENGTH; \
+					movel	cache,MAP_CACHE; \
+					jbsr	mmu_map
+	
+#define MMU_MAP_EQ(addr,leng,cache)	movel	addr,MAP_LOG; \
+					movel	MAP_LOG,MAP_PHYS; \
+					movel	leng,MAP_LENGTH; \
+					movel	cache,MAP_CACHE; \
+					jbsr	mmu_map
+	
+#define MMU_MAP_TT(addr,leng,cache)	movel	addr,MAP_LOG; \
+					movel	MAP_LOG,MAP_PHYS; \
+					movel	leng,MAP_LENGTH; \
+					movel	cache,MAP_CACHE; \
+					jbsr	mmu_map_tt
+	
+#define is_not_amiga(lab) cmpl &MACH_AMIGA,%pc@(m68k_machtype); jne lab
+#define is_not_atari(lab) cmpl &MACH_ATARI,%pc@(m68k_machtype); jne lab
+#define is_not_mac(lab) cmpl &MACH_MAC,%pc@(m68k_machtype); jne lab
+#define is_not_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jne lab
+#define is_not_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jne lab
+#define is_not_hp300(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); jne lab
+	
+#define is_040_or_060(lab)	btst &CPUTYPE_0460,%pc@(Lcputype+3); jne lab
+#define is_not_040_or_060(lab)	btst &CPUTYPE_0460,%pc@(Lcputype+3); jeq lab
+#define is_040(lab)		btst &CPUTYPE_040,%pc@(Lcputype+3); jne lab
+#define is_060(lab)		btst &CPUTYPE_060,%pc@(Lcputype+3); jne lab
+#define is_not_060(lab)		btst &CPUTYPE_060,%pc@(Lcputype+3); jeq lab
 
 /* On the HP300 we use the on-board LEDs for debug output before
    the console is running.  Writing a 1 bit turns the corresponding LED
@@ -192,6 +524,7 @@
 	.long	MACH_ATARI, ATARI_BOOTI_VERSION
 	.long	MACH_MVME16x, MVME16x_BOOTI_VERSION
 	.long	MACH_BVME6000, BVME6000_BOOTI_VERSION
+	.long	MACH_MAC, MAC_BOOTI_VERSION
 	.long	0
 1:	jra	SYMBOL_NAME(_start)
 
@@ -207,17 +540,17 @@
 /*
  * Setup initial stack pointer
  */
-	lea	%pc@(SYMBOL_NAME(_stext):w),%sp
-
+	lea	%pc@(SYMBOL_NAME(_stext)),%sp
+	
 /*
  * Record the CPU and machine type.
  */
 
 	movew	#BI_MACHTYPE,%d0
 	jbsr	Lget_bi_record
-	movel	%a0@,%d4
+	movel	%a0@,%d0
 	lea	%pc@(SYMBOL_NAME(m68k_machtype)),%a0
-	movel	%d4,%a0@
+	movel	%d0,%a0@
 	movew	#BI_FPUTYPE,%d0
 	jbsr	Lget_bi_record
 	movel	%a0@,%d0
@@ -234,39 +567,165 @@
 	lea	%pc@(SYMBOL_NAME(m68k_cputype)),%a0
 	movel	%d0,%a0@
 
+#if defined(CONFIG_MAC)
+/*
+ * For Macintosh, we need to determine the display parameters early (at least 
+ * while debugging it).
+ */
+
+	is_not_mac(Ltest_notmac)
+
+	movew	#BI_MAC_VADDR,%d0
+	jbsr	Lget_bi_record
+	movel	%a0@,%d0
+	lea	%pc@(SYMBOL_NAME(mac_videobase)),%a0
+	movel	%d0,%a0@
+
+	movew	#BI_MAC_VDEPTH,%d0
+	jbsr	Lget_bi_record
+	movel	%a0@,%d0
+	lea	%pc@(SYMBOL_NAME(mac_videodepth)),%a0
+	movel	%d0,%a0@
+
+	movew	#BI_MAC_VDIM,%d0
+	jbsr	Lget_bi_record
+	movel	%a0@,%d0
+	lea	%pc@(SYMBOL_NAME(mac_dimensions)),%a0
+	movel	%d0,%a0@
+
+	movew	#BI_MAC_VROW,%d0
+	jbsr	Lget_bi_record
+	movel	%a0@,%d0
+	lea	%pc@(SYMBOL_NAME(mac_rowbytes)),%a0
+	movel	%d0,%a0@
+
+#ifdef MAC_SERIAL_DEBUG
+	movew	#BI_MAC_SCCBASE,%d0
+	jbsr	Lget_bi_record
+	movel	%a0@,%d0
+	lea	%pc@(SYMBOL_NAME(mac_sccbase)),%a0
+	movel	%d0,%a0@
+#endif /* MAC_SERIAL_DEBUG */
+
+#if 0
+	/*
+	 * Clear the screen
+	 */
+	lea	%pc@(SYMBOL_NAME(mac_videobase)),%a0
+	movel	%a0@,%a1
+	lea	%pc@(SYMBOL_NAME(mac_dimensions)),%a0
+	movel	%a0@,%d1
+	swap	%d1		/* #rows is high bytes */
+	andl	#0xFFFF,%d1	/* rows */
+	subl	#10,%d1
+	lea	%pc@(SYMBOL_NAME(mac_rowbytes)),%a0
+loopy2:
+	movel	%a0@,%d0
+	subql	#1,%d0
+loopx2:
+	moveb	#0x55, %a1@+
+	dbra	%d0,loopx2
+	dbra	%d1,loopy2
+#endif
+	/*
+	 * clobbered %d0,so restore it
+	 */
+	lea	%pc@(SYMBOL_NAME(m68k_cputype)),%a0
+	movel	%a0@,%d0
+
+Ltest_notmac:
+#endif /* CONFIG_MAC */
+
+
+/*
+ * There are ultimately two pieces of information we want for all kinds of
+ * processors CpuType and CacheBits.  The CPUTYPE was passed in from booter
+ * and is converted here from a booter type definition to a separate bit
+ * number which allows for the standard is_0x0 macro tests.
+ */
+	/*
+	 * Test the BootInfo cputype for 060
+	 */
+	/*
+	 * Assume it's an 020/030
+	 */
+	clrl	%d6
+	
 	btst	#CPUB_68060,%d0
 	jeq	1f
-	/* '060: d6 := BIT0460|BIT060, cache mode 0x60 (no-cache/non-ser) */
-	movel	#D6F_060+_PAGE_CACHE040W,%d6
-	jra	2f
-1:	btst	#CPUB_68040,%d0
-	jeq	1f
-	/* '040: d6 := BIT0460, cache mode 0x00 (write-through) */
-	movel	#D6F_040+_PAGE_CACHE040W,%d6
+	bset	#CPUTYPE_060,%d6
+	bset	#CPUTYPE_0460,%d6
 	jra	2f
-1:	/* '020 or '030: d6 := no CPU bit, cache mode unused */
-	moveq	#0,%d6
-
-2:	lea	%pc@(SYMBOL_NAME(m68k_pgtable_cachemode)),%a0
-	moveq	#0,%d0
-	movew	%d6,%d0
-	movel	%d0,%a0@		/* save cache mode for page tables */
+	
+1:	/*
+	 * Test the BootInfo cputype for 040
+	 */
+	btst	#CPUB_68040,%d0
+	jeq	2f
+	bset	#CPUTYPE_040,%d6
+	bset	#CPUTYPE_0460,%d6
+	
+2:
+	/*
+	 * Record the cpu type
+	 */
+	lea	%pc@(Lcputype),%a0
+	movel	%d6,%a0@
+	
+	/*
+	 * NOTE:
+	 *
+	 * Now the macros are valid:
+	 *	is_040_or_060
+	 *	is_not_040_or_060
+	 *	is_040
+	 *	is_060
+	 *	is_not_060
+	 */
+	
+	/*
+	 * Determine the cache mode for pages holding MMU tables
+	 */
+	is_not_040_or_060(Lcachetype020)
+	
+	/*
+	 * '040 or '060
+	 * d6 := cacheable write-through 
+	 * NOTE: The 68040 manual strongly recommends non-cached for MMU tables,
+	 * but we have been using write-through since at least 2.0.29 so I
+	 * guess it is OK.
+	 */
 
+#if defined(CONFIG_060_WRITETHROUGH)
 	/*
 	 * If this is a 68060 board using drivers with cache coherency
 	 * problems, then supervisor memory accesses need to be write-through
-         * also; otherwise, we want copyback.
+	 * also; otherwise, we want copyback.
 	 */
 
-#if defined(CONFIG_060_WRITETHROUGH)
-	is_not_060(Lset_norm)
-	jra	1f
-Lset_norm:
-	move.w	#_PAGE_CACHE040,%d0
-1:
+	movel	#_PAGE_CACHE040W,%d6
+	is_060(Lset_sup)
+	move.w	#_PAGE_CACHE040,%d6
+Lset_sup:
   	lea	%pc@(SYMBOL_NAME(m68k_supervisor_cachemode)),%a0
-	movel	%d0,%a0@
-#endif
+	movel	%d6,%a0@
+#endif /* CONFIG_060_WRITETHROUGH */
+
+	movel	#_PAGE_CACHE040W,%d6
+	jbra	Lsave_cachetype
+
+Lcachetype020:
+	/*
+	 * '020 or '030
+	 * d6 := cache bits unused (after mapping the kernel!)
+	 */
+	moveql	#0,%d6
+Lsave_cachetype:
+	/*
+	 * Save cache mode for page tables
+	 */
+	lea	%pc@(SYMBOL_NAME(m68k_pgtable_cachemode)),%a0
+	movel	%d6,%a0@
 
 /*
  * raise interrupt level
@@ -302,10 +761,9 @@
 	tstl	%d0
 	jbmi	1f
 	movel	%a0@,%d3
+	lea	%pc@(SYMBOL_NAME(atari_mch_type)),%a0
+	movel	%d3,%a0@
 1:	
-	/* %d3 is not clobbered until Atari page tables are set up,
-	 * where it is used again. */
-
 	/* On the Hades, the iobase must be set up before opening the
 	 * serial port. There are no I/O regs at 0x00ffxxxx at all. */
 	moveq	#0,%d0
@@ -314,20 +772,40 @@
 	movel	#0xff000000,%d0		/* Hades I/O base addr: 0xff000000 */
 1:	lea     %pc@(Liobase),%a0
 	movel   %d0,%a0@
+	
 Lnotypetest:
 #endif
 
 /*
  * Initialize serial port
  */
+	jbsr	Lserial_init
 
-	jbsr Lserial_init
+/*
+ * Initialize console
+ */
+#ifdef CONFIG_MAC
+	is_not_mac(Lnocon)
+#ifdef CONSOLE
+	jbsr	Lconsole_init
+#ifdef CONSOLE_PENGUIN
+	jbsr	Lconsole_put_penguin
+#endif	/* CONSOLE_PENGUIN */
+	jbsr	Lconsole_put_stats
+#endif	/* CONSOLE */
+Lnocon:
+#endif	/* CONFIG_MAC */
 
 	putr()
-	putc('A')
+	putc_trace('A')
 
 /*
- * Get address at end of bootinfo and mask off at a page boundary.
+ * Get address at end of bootinfo and
+ * round up to a page boundary.
+ * Note: This hack uses two 'features' of the bi_record:
+ *  (1)  When the item searched for isn't found, a0 points
+ *       to the end of the structure;
+ *  (2)  #0 is an invalid (and never present) bi_record element.
  */
 	moveq	#0,%d0
 	jbsr	Lget_bi_record
@@ -336,246 +814,121 @@
 	andl	#-PAGESIZE,%d0
 	movel	%d0,%a6
 
-	putc('B')
-
-/*
- * Save physical start address of kernel
- */
-	lea	%pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
-	movel	%a0,%d5
-
 /*
- * initialize the kernel root table.
+ * %a6 now contains the address to the 
+ * next free block beyond the kernel
  */
-	lea	%pc@(SYMBOL_NAME(kernel_pg_dir):w),%a5
-	movel	%a5,%a0
-	moveq	#ROOT_TABLE_SIZE-1,%d1
-1:	clrl	%a0@+
-	dbra	%d1,1b
-
-	/*
-	 * Initialize root table descriptor pointing to the kernel pointer
-	 * table.
-	 */
-	lea	%pc@(Lavail_pmd_table:w),%a4
-	moveq	#_PAGE_TABLE,%d0
-	addl	%a4,%d0
-	movel	%d0,%a5@
 
-	putc('C')
+	putc_trace('B')
 
 /*
- * Initialize the pointer tables referred to above.  They either point
- * to page tables in the case of the 680[46]0 or contain early
- * termination page descriptors in the case of the 68851 or 68030.
- *
- * Each pointer table entry points to a 64 entry page table.  16 of these
- * page tables are grouped to form a single 1024 entry page table which
- * fits in a single 4096 byte page.
- *
- * Some register usages:
- *    a0 -> pointer table descriptor address
- *    a1 -> pointer table descriptor
- *    d1 -> counter
- *    d2 -> pointer table descriptor increment (varies according to CPU)
+ * Save physical start address of kernel
  */
+	lea	%pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
+	movel	%a0,%d5
 
-	/* clear the kernel pointer table */
-	movel	%a4,%a0
-	moveq	#PTR_TABLE_SIZE-1,%d1
-1:	clrl	%a0@+
-	dbra	%d1,1b
-
-	movel	%a4,%a0
-	moveq	#15,%d1
-
-	/*
-	 * base value of pointer table descriptor is either
-	 * the address of the first page table (680[46]0)
-	 * or the base address of physical memory (68030).
-	 */
-	is_040_or_060(1f)
-
-	/* 680[23]0 */
-	movel	%d5,%a1				/* base address */
-	addql	#_PAGE_PRESENT,%a1		/* descriptor type */
-	movel	#PAGE_TABLE_SIZE*PAGESIZE,%d2	/* increment */
-	jra	2f
-
-1:	/* 680[46]0 */
-	movel	%a6,%a3			/* base address */
-	addw	#PAGESIZE,%a6		/* allocate page for 16 page tables */
-	lea	%pc@(SYMBOL_NAME(kpt)),%a1
-	movel	%a3,%a1@		/* save address of page table */
-	movel	%a3,%a1
-	addw	#_PAGE_TABLE+_PAGE_ACCESSED,%a1	/* descriptor type */
-	movel	#PAGE_TABLE_SIZE<<2,%d2 /* increment */
-
-2:	movel	%a1,%a0@+
-	addl	%d2,%a1
-	dbra	%d1,2b
+	putc_trace('C')
 
-	putc('D')
+	leds(0x4)
 
 /*
- * If we are running on a 680[46]0, we have a kernel page table and
- * must initialize it.	Make the entries point to the first
- * 4M of physical memory (the memory we are residing in).
- * Set the cache mode bits to Cacheable, Copyback.  Set the Global bits
- * in the descriptors also.
+ *	mmu_init
+ *	
+ *	This block of code does what's necessary to map in the various kinds
+ *	of machines for execution of Linux.  First, it's clear there
+ *	has to be a root table, so that is cleared.  Then, the kernel
+ *	has to be mapped, so the kernel is mapped low.  Then, it's on
+ *	to machine specific code where specific address ranges are
+ *	mapped depending on current I/O configurations.
+ *	
+ *	Begin:
+ *		%a6 is an input to this routine.  %a6 must point to
+ *			the first available byte of memory on a virgin page.
+ *		%d5 is the start of the kernel's physical address
+ *	
+ *	End:
+ *		%a5 will point to the root table.
+ *		%a6 will (likely) have been modified during this
+ *			call.
+ *	
+ *	
+ *	
  */
-	is_not_040_or_060(Lnot040)
-
-	putc('F')
-
-	movel	%a3,%a0
-	movel	%d5,%a1
-#if defined(CONFIG_060_WRITETHROUGH)
-	addw	#_PAGE_GLOBAL040+_PAGE_PRESENT+_PAGE_ACCESSED,%a1
-	addl	m68k_supervisor_cachemode,%a1
-#else
-	addw    #_PAGE_GLOBAL040+_PAGE_CACHE040+_PAGE_PRESENT+_PAGE_ACCESSED,%a1
-#endif
-	movew	#(PAGE_TABLE_SIZE*TABLENR_4MB)-1,%d1
-	movel	#PAGESIZE,%d2
-1:	movel	%a1,%a0@+
-	addl	%d2,%a1
-	dbra	%d1,1b
-
-	/*
-	 * on the 68040, pages used to hold mmu tables should
-	 * be initialized as noncachable; the '060 allows write-through.
-	 * Do this for the root table page (which also contains
-	 * all pointer tables utilized thus far) and the
-	 * kernel page table.
-	 */
-	movel	%a5,%d0
-	subl	%d5,%d0
-	moveq	#PAGE_INDEX_SHIFT,%d2
-	lsrl	%d2,%d0
-	lea	%a3@(%d0:l:4),%a2
-	movel	%a2@,%d1
-	andw	#_CACHEMASK040,%d1
-	orw	%d6,%d1
-	movel	%d1,%a2@
-
-	movel	%a3,%d0
-	subl	%d5,%d0
-	lsrl	%d2,%d0
-	lea	%a3@(%d0:l:4),%a2
-	movel	%a2@,%d1
-	andw	#_CACHEMASK040,%d1
-	orw	%d6,%d1
-	movel	%d1,%a2@+
-	/*
-	 * %a2 points now to the page table entry for available pages at %a6,
-	 * hence caching modes for new pages can easily set unless increasing
-	 * of %a2 are forgotten.
-	 */
-Lnot040:
+mmu_init:
 
-	leds(0x4)
+	putc_trace('D')
 	
 /*
- * Do any machine specific page table initializations.
+ * initialize the kernel root table.
  */
-#ifdef CONFIG_AMIGA
-	is_not_amiga(Lnotami)
+	lea	%pc@(SYMBOL_NAME(kernel_pg_dir)),%a5
+	jbsr	mmu_clear_root_table
+	
+	putc_trace('E')
+	
+	lea	%pc@(SYMBOL_NAME(Lavail_pmd_table)),%a4
+	jbsr	mmu_clear_pointer_table
 
+	putc_trace('F')
+	
 /*
- * Setup a mapping of the first 16M of physical address space at virtual
- * address 0x80000000, using early termination page descriptors for the
- * 68030, and proper page tables for the 680[46]0.  Set this area as
- * non-cacheable.
+ * map the first 4 MB of kernel code & data
  */
 
-	putc('H')
-
-	is_040_or_060(Lspami68040)
-
-	/*
-	 * for the 68030, just setup a translation to map in the first
-	 * 32M of physical address space at virtual address 0x80000000
-         * using an early termination page descriptor.
-	 */
-
-	putc('I')
-
-	movel	#_PAGE_NOCACHE030+_PAGE_PRESENT+_PAGE_ACCESSED,%d0
-	movel	%d0,%a5@(0x40<<2)
-
-	jra	Lmapphys
-
-Lspami68040:
+#if defined(CONFIG_060_WRITETHROUGH)
+	movel	%pc@(m68k_supervisor_cachemode),%d2
+	addil	#_PAGE_GLOBAL040+_PAGE_ACCESSED,%d2
+	MMU_MAP(#0,%d5,#4*1024*1024,%d2)
+#else
+	MMU_MAP(#0,%d5,#4*1024*1024,#_PAGE_GLOBAL040+_PAGE_CACHE040+_PAGE_ACCESSED)
+#endif
 
-	/*
-	 * for the 680[46]0, use another pointer table, and allocate 4 more
-	 * page tables.  Initialize the pointer table to point to the
-	 * page tables.  Then initialize the page tables to point to
-	 * the first 16M of memory, with no caching (noncachable/serialized).
-	 */
+	/* Clear the pointer table to use, and page table to use */
+	moveq	#0,%d0
+	movel	%d0,%a4
+	movel	%d0,%a3
 
-	/* clear the amiga pointer table */
-	lea	%a4@(PTR_TABLE_SIZE<<2),%a4
-	moveq	#PTR_TABLE_SIZE-1,%d1
-1:	clrl	%a0@+
-	dbra	%d1,1b
+	putc_trace('G')
 
-	/* allocate 4 pages for 64 page tables */
-	movel	%a6,%a3
-	addw	#4*PAGESIZE,%a6
+#if defined(CONFIG_AMIGA)
 
-	/* initialize the pointer table */
-	movel	%a4,%a0
-	movel	%a3,%a1
-	addw	#_PAGE_TABLE+_PAGE_ACCESSED,%a1	/* base descriptor */
-	movel	#PAGE_TABLE_SIZE<<2,%d2 /* increment */
-	moveq	#TABLENR_16MB-1,%d1
+mmu_init_amiga:
+	
+	is_not_amiga(mmu_init_not_amiga)
+/* 
+ * mmu_init_amiga
+ */
 
-1:	movel	%a1,%a0@+
-	addl	%d2,%a1
-	dbra	%d1,1b
+	putc_trace('H')
 
-	/* ensure that the root table points to the pointer table */
-	movel	%a4,%a0
-	addw	#_PAGE_TABLE+_PAGE_ACCESSED,%a0
-	movel	%a0,%a5@(0x40<<2)
+	is_not_040_or_060(1f)
 
 	/*
-	 * initialize the page tables
-	 * descriptor bits include noncachable/serialized and global bits.
+	 * 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000
 	 */
-	movel	%a3,%a0
-	movew	#_PAGE_GLOBAL040+_PAGE_NOCACHE_S+_PAGE_PRESENT+_PAGE_ACCESSED,%a1
-	movel	#PAGESIZE,%d2
-	movew	#(PAGE_TABLE_SIZE*TABLENR_16MB)-1,%d1
-
-1:	movel	%a1,%a0@+
-	addl	%d2,%a1
-	dbra	%d1,1b
+	MMU_MAP(#0x80000000,#0,#0x01000000,#_PAGE_GLOBAL040+_PAGE_NOCACHE_S+_PAGE_ACCESSED)
+	
+	jbra	mmu_init_done
 
+1:	
 	/*
-	 * Finally, since we just allocated 4 page tables, make sure that
-	 * the virtual mapping of the 4 page tables indicates
-	 * noncachable/serialized.
+	 * 030:	Map the 32Meg range physical 0x0 upto logical 0x8000.0000
 	 */
-	moveq	#3,%d0
-1:	movel	%a2@,%d1	/* a2 already points to root table offset */
-	andw	#_CACHEMASK040,%d1
-	orw	%d6,%d1
-	movel	%d1,%a2@+
-	dbra	%d0,1b
-
-	jra	Lmapphys
-
-Lnotami:
+	MMU_MAP(#0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030+_PAGE_ACCESSED)
+	
+	jbra	mmu_init_done
+	
+mmu_init_not_amiga:
 #endif
 
-#ifdef CONFIG_ATARI
-	is_not_atari(Lnotatari)
+#if defined(CONFIG_ATARI)
 
-	move.w	#PAGESIZE,%sp
+mmu_init_atari:
 
+	is_not_atari(mmu_init_not_atari)
+	
+	putc_trace('I')
+	
 /* On the Atari, we map the I/O region (phys. 0x00ffxxxx) by mapping
    the last 16 MB of virtual address space to the first 16 MB (i.e.
    0xffxxxxxx -> 0x00xxxxxx). For this, an additional pointer table is
@@ -591,80 +944,33 @@
 
 	/* I/O base addr for non-Medusa, non-Hades: 0x00000000 */
 	moveq	#0,%d0
+	movel	%pc@(SYMBOL_NAME(atari_mch_type)),%d3
 	cmpl	#ATARI_MACH_MEDUSA,%d3
 	jbeq	2f
 	cmpl	#ATARI_MACH_HADES,%d3
 	jbne	1f
 2:	movel	#0xff000000,%d0 /* Medusa/Hades base addr: 0xff000000 */
 1:	movel	%d0,%d3
-	
-	/* Let the root table point to the new pointer table */
-	lea	%a4@(PTR_TABLE_SIZE<<2),%a4
-	movel	%a4,%a0
-	addw	#_PAGE_TABLE+_PAGE_ACCESSED,%a0
-	movel	%a0,%a5@(0x7f<<2)       /* 0xFE000000 - 0xFFFFFFFF */
-
-	/* clear lower half of the pointer table (0xfexxxxxx) */
-	movel	%a4,%a0
-	movel	#(PTR_TABLE_SIZE/2)-1,%d2
-1:	clrl	%a0@+
-	dbra	%d2,1b
 
 	is_040_or_060(Lspata68040)
 
-/* Mapping of the last 16M of virtual address space to the first 16M
-   for efficient addressing of hardware registers */
-	movel	#PAGE_TABLE_SIZE*PAGESIZE,%d1
-	movel	#(PTR_TABLE_SIZE/2)-1,%d2
-	movel	%d3,%d0
-	orw	#_PAGE_PRESENT+_PAGE_ACCESSED,%d0
-1:	movel	%d0,%a0@+
-	addl	%d1,%d0
-	dbra	%d2,1b
-	moveq	#_PAGE_NOCACHE030,%d0	/* make non-cachable */
-	addl	%d0,%a4@(0x7f<<2)	/* 0xFFFC0000-0xFFFFFFFF (I/O space) */
-/* GK: 0xFFF00000-0xFFF3FFFF (IDE-bus) has to be non-cachable too */
-	addl	%d0,%a4@(0x7c<<2)
-
-	jra	Lmapphys
+	/* Map everything non-cacheable, though not all parts really
+	 * need to disable caches (crucial only for 0xffc000..0xffffff
+	 * (standard I/O) and 0xf00000..0xf3ffff (IDE)). The remainder
+	 * isn't really used, except for sometimes peeking into the
+	 * ROMs (mirror at phys. 0x0), so caching isn't necessary for
+	 * this. */
+	MMU_MAP(#0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE030+_PAGE_ACCESSED)
 
+	jbra	mmu_init_done
+	
 Lspata68040:
-	/* allocate 4 page tables */
-	movel	%a6,%a3
-	addw	#4*PAGESIZE,%a6
-
-	/* Initialize the upper half of the pointer table (a0 is still valid) */
-	movel	%a3,%a1
-	addw	#_PAGE_TABLE+_PAGE_ACCESSED,%a1
-	movel	#PAGE_TABLE_SIZE<<2,%d2
-	moveq	#TABLENR_16MB-1,%d1
-1:	movel	%a1,%a0@+
-	addl	%d2,%a1
-	dbra 	%d1,1b
-
-	/* Initialize the page tables as noncacheable/serialized! */
-	movel	%a3,%a0
-	movel	%d3,%a1
-	addw	#_PAGE_GLOBAL040+_PAGE_NOCACHE_S+_PAGE_PRESENT+_PAGE_ACCESSED,%a1
-	movel	#PAGESIZE,%d2
-	movew	#(PAGE_TABLE_SIZE*TABLENR_16MB)-1,%d1
-1:	movel	%a1,%a0@+
-	addl	%d2,%a1
-	dbra	%d1,1b
-
-	/*
-	 * Finally, since we just allocated 4 page tables, make sure that
-	 * the virtual mapping of the 4 page tables indicates
-	 * noncachable or write-through.
-	 */
-	moveq	#3,%d0
-1:	movel	%a2@,%d1	/* a2 already points to root table offset */
-	andw	#_CACHEMASK040,%d1
-	orw	%d6,%d1
-	movel	%d1,%a2@+
-	dbra	%d0,1b
+	
+	MMU_MAP(#0xff000000,%d3,#0x01000000,#_PAGE_GLOBAL040+_PAGE_NOCACHE_S+_PAGE_ACCESSED)
+	
+	jbra	mmu_init_done
 
-Lnotatari:
+mmu_init_not_atari:
 #endif
 
 #ifdef CONFIG_HP300
@@ -675,14 +981,19 @@
    termination page descriptor.  The ROM mapping is needed because the LEDs 
    are mapped there too.  */
 
+	MMU_MAP(#0xf0000000,#0,#0x01000000,#_PAGE_NOCACHE030+_PAGE_ACCESSED)
+
+#if 0
 	movel	#_PAGE_NOCACHE030+_PAGE_PRESENT+_PAGE_ACCESSED,%d0
 	movel	%d0,%a5@(0x78<<2)
+#endif
 
 Lnothp300:
-	
+
 #endif
 
 #if defined(CONFIG_MVME16x)
+	
 	is_not_mvme16x(Lnot16x)
 
 	/* Get pointer to board ID data */
@@ -696,272 +1007,506 @@
 	 * On MVME16x we have already created kernel page tables for
 	 * 4MB of RAM at address 0, so now need to do a transparent
 	 * mapping of the top of memory space.  Make it 0.5GByte for now.
+	 * Supervisor only access, so transparent mapping doesn't
+	 * clash with User code virtual address space.
+	 * this covers IO devices, PROM and SRAM.  The PROM and SRAM
+	 * mapping is needed to allow 167Bug to run.
+	 * IO is in the range 0xfff00000 to 0xfffeffff.
+	 * PROM is 0xff800000->0xffbfffff and SRAM is
+	 * 0xffe00000->0xffe1ffff.
 	 */
 
-	movel	#0xe01f0000,%d2		/* logical address base */
-	orw	#0xa040,%d2		/* add in magic bits */
-	.long	0x4e7b2005		/* movec d2,ittr1 */
-	.long	0x4e7b2007		/* movec d2,dttr1 */
-
+	MMU_MAP_TT(#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S+_PAGE_ACCESSED)
+	
+	jbra	mmu_init_done
+	
 Lnot16x:
-#endif
+#endif	/* CONFIG_MVME162 | CONFIG_MVME167 */
 
 #if defined(CONFIG_BVME6000)
-	is_not_bvme6000(Lnotbvm)
+	
+	is_not_bvme6000(Lnot6000)
 
 	/*
 	 * On BVME6000 we have already created kernel page tables for
 	 * 4MB of RAM at address 0, so now need to do a transparent
-	 * mapping of the top of memory space.  Make it 0.5GByte for now.
+	 * mapping of the top of memory space.  Make it 0.5GByte for now,
+	 * so we can access on-board i/o areas.
+	 * Supervisor only access, so transparent mapping doesn't
+	 * clash with User code virtual address space.
 	 */
 
-	movel	#0xe01f0000,%d2		/* logical address base */
-	orw	#0xa040,%d2		/* add in magic bits */
-	.long	0x4e7b2005		/* movec d2,ittr1 */
-	.long	0x4e7b2007		/* movec d2,dttr1 */
-	.long	0x4e7b2004		/* movec d2,ittr0 */
-	.long	0x4e7b2006		/* movec d2,dttr0 */
+	MMU_MAP_TT(#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S+_PAGE_ACCESSED)
+	
+	jbra	mmu_init_done
+	
+Lnot6000:
+#endif /* CONFIG_BVME6000 */
+
+/* 
+ * mmu_init_mac
+ * 
+ * The Macintosh mappings are less clear.
+ * 
+ * Even as of this writing, it is unclear how the
+ * Macintosh mappings will be done.  However, as
+ * the first author of this code I'm proposing the
+ * following model:
+ * 
+ * Map the kernel (that's already done),
+ * Map the I/O (on most machines that's the
+ * 0x5000.0000 ... 0x5200.0000 range,
+ * Map the video frame buffer using as few pages
+ * as absolutely (this requirement mostly stems from
+ * the fact that when the frame buffer is at
+ * 0x0000.0000 then we know there is valid RAM just
+ * above the screen that we don't want to waste!).
+ *
+ * By the way, if the frame buffer is at 0x0000.0000
+ * then the Macintosh is known as an RBV based Mac.
+ * 
+ * By the way 2, the code currently maps in a bunch of
+ * regions.  But I'd like to cut that out.  (And move most
+ * of the mappings up into the kernel proper ... or only
+ * map what's necessary.)
+ */
+
+#if defined(CONFIG_MAC)
+
+mmu_init_mac:
+	
+	is_not_mac(mmu_init_not_mac)
+
+	putc_trace('J')
+	
+	lea	%pc@(SYMBOL_NAME(mac_videobase)),%a0
+	lea	%pc@(Lconsole_video_virtual),%a1
+	movel	%a0@,%a1@
 
-Lnotbvm:
+	is_not_040_or_060(1f)
+	
+	movel	#_PAGE_GLOBAL040+_PAGE_NOCACHE_S+_PAGE_ACCESSED,MAP_CACHE
+	jbra	2f
+1:		
+	movel	#_PAGE_NOCACHE030+_PAGE_ACCESSED,MAP_CACHE
+2:	
+	/*
+	 * Mac Note: screen address of logical 0xF000.0000 -> <screen physical>
+	 */
+
+	/* Calculate screen size */
+	clrl	%d0
+	lea	%pc@(SYMBOL_NAME(mac_dimensions)),%a0
+	movew	%a0@,%d0 		/* d0 = screen height in pixels */
+
+	lea	%pc@(SYMBOL_NAME(mac_rowbytes)),%a0
+	mulul	%a0@,%d0		/* scan line bytes x num scan lines */
+	lea	%pc@(SYMBOL_NAME(mac_videobase)),%a0
+	movel	%a0@,%d2		/* grab screen offset from start of a page */
+	andl	#PAGESIZE-1,%d2		/* ... offset from start of page ... */
+	addl	%d2,%d0			/* add it to N bytes needed for screen for mapping purposes! */
+	addl	#PAGESIZE-1,%d0		/* Round up to page alignment */
+	andl	#-PAGESIZE,%d0		/* d0 is now the number of 4K pages for the screen */
+
+	movel	%a0@,%d2
+	andl	#PAGESIZE-1,%d2
+	addl	#0xF0000000,%d2
+	lea	%pc@(Lconsole_video_virtual),%a1
+	movel	%d2,%a1@		/* Update the console_video address */
+	movel	%a0@,%d2
+	andl	#-PAGESIZE,%d2
+
+	MMU_MAP(#0xF0000000,%d2,MAP_LENGTH,MAP_CACHE)
+	MMU_MAP_EQ(#0x40800000,#0x02000000,MAP_CACHE)	/* ROM ? */
+	MMU_MAP_EQ(#0x50000000,#0x02000000,MAP_CACHE)
+	MMU_MAP_EQ(#0x60000000,#0x00400000,MAP_CACHE)
+	MMU_MAP_EQ(#0x9C000000,#0x00400000,MAP_CACHE)
+	MMU_MAP_TT(#0xF8000000,#0x08000000,MAP_CACHE)
+	
+	jbra	mmu_init_done
+	
+mmu_init_not_mac:
 #endif
 
+mmu_init_done:		
+	
+	putc_trace('K')
+	leds(0x8)
+
 /*
- * Setup a transparent mapping of the physical memory we are executing in.
+ * mmu_fixup
+ * 
+ * On the 040 class machines, all pages that are used for the
+ * mmu have to be fixed up. According to Motorola, pages holding mmu
+ * tables should be non-cacheable on a '040 and write-through on a
+ * '060. But analysis of the reasons for this, and practical
+ * experience, showed that write-through also works on a '040.
  *
- * Only do this if the physical memory is not in the first 16M Meg, or not on
- * an Amiga since the first 16M is already identity mapped on the Amiga.
+ * So, we'll walk through the MMU table to determine which pages were
+ * allocated.  An alternative would be to "know" what pages were
+ * allocated above.  But that's fraught with maintenance problems.
+ * It's easier to walk the table.
+ * 
  */
-Lmapphys:
-	putc('J')
-	leds(0x8)
+#if defined(CONFIG_M68040) || defined(CONFIG_M68060)
 
-#ifdef CONFIG_AMIGA
-	is_not_amiga(Lmapphysnotamiga)
+mmu_fixup:
+	
+	is_not_040_or_060(mmu_fixup_done)
+	
+#if defined(MMU_NOCACHE_KERNEL)
+	jbra	mmu_fixup_done
+#endif
+	
+	moveml	%d0-%d5/%a0,%sp@-
+	
+	movel	%a5,%a0
+	jbsr	mmu_fixup_page_mmu_cache
+	
+	movel	#ROOT_TABLE_SIZE-1,%d5
+1:	
+	movel	%a5@(%d5*4),%d2
+	movel	%d2,%d0
+	andb	#_PAGE_TABLE,%d0
+	jbeq	4f
 
-/*
- * The virtual address of the start of the kernel is 0x1000. We transparently
- * translate the memory where we running in and can enable then the MMU. Hence
- * we have now two locations of the kernel in memory and can jump to the final
- * place. Except if the physical location is in the first 16MB, translation
- * will overlap later virtual location, but as we already mapped the first
- * 16MB to 0x80000000, we can jump there after translation and MMU is enabled
- * and then we can switch off translation and go to the final place.
- * On 020/030 we must emulate transparant translation, since 020 doesn't know
- * it, but due to early termination pointer this is easy to do.
- * When MMU is enabled, stack pointer and Lcustom will become again valid and
- * stack points to the unused first page.
- */
+	movel	%d2,%a0
+	jbsr	mmu_fixup_page_mmu_cache
+	
+	andl	#_TABLE_MASK,%d2
+	movel	%d2,%a4
+	movel	#PTR_TABLE_SIZE-1,%d4
 
-/*
- * Setup Supervisor Root Pointer register to point to page directory,
- * setup translation register contents and enable translation.
- */
-	putc('K')
+2:
+	movel	%a4@(%d4*4),%d2
+	movel	%d2,%d0
+	andb	#_PAGE_TABLE,%d0
+	jbeq	3f
 
-	movew	#PAGESIZE,%sp
+	movel	%d2,%a0
+	jbsr	mmu_fixup_page_mmu_cache
+	
+3:
+	dbra	%d4,2b
 
-	/* fixup the Amiga custom register location before printing */
-	lea	%pc@(Lcustom),%a0
-	movel	#0x80000000,%a0@
+4:
+	dbra	%d5,1b
 
-	is_040_or_060(Lamimmu68040)
+	moveml	%sp@+,%d0-%d5/%a0
 
-	moveq	#ROOT_INDEX_SHIFT,%d2
-	movel	%d5,%d0
-	lsrl	%d2,%d0
-	movel	%d0,%d1
-	lsll	%d2,%d1
-	orw	#_PAGE_PRESENT+_PAGE_ACCESSED,%d1
-	lsll	#2,%d0
-	movel	%a5@(%d0:w),%d2
-	movel	%d1,%a5@(%d0:w)
-	lea	%pc@(Lmmu),%a3
-	/* no limit, 4byte descriptors */
-	movel	#0x80000002,%a3@
-	movel	%a5,%a3@(4)
-	pmove	%a3@,%srp
-	pmove	%a3@,%crp
-	pflusha
-	/*
-	 * enable,super root enable,4096 byte pages,7 bit root index,
-	 * 7 bit pointer index, 6 bit page table index.
+	jbra	mmu_fixup_done
+
+mmu_fixup_page_mmu_cache:
+	moveml	%a0/%d0-%d5,%sp@-
+
+	/* Calculate the offset in the root table 
 	 */
-	movel	#0x82c07760,%a3@
-	pmove	%a3@,%tc	/* enable the MMU */
-	tstl	%d0
-	jne	1f
-	jmp	%pc@(2f+0x80000000)
-1:	jmp	2f:w
-2:	movel	%d2,%a5@(%d0:w)
-	pflusha
-	jmp	LdoneMMUenable:w
+	movel	%a0,%d5
+	andil	#0xfe000000,%d5
+	roll	#7,%d5
 
-Lamimmu68040:
+	/* Calculate the offset in the pointer table 
+	 */
+	movel	%a0,%d4
+	andil	#0x01fc0000,%d4
+	lsrl	#2,%d4
+	swap	%d4
+	
+	/* Calculate the offset in the page table
+	 */
+	movel	%a0,%d3
+	andil	#0x0003f000,%d3
+	lsll	#4,%d3
+	swap	%d3
 
-	.chip	68040
-	lea	2f:w,%a0
-	movel	%d5,%d0
-	andl	#0xff000000,%d0
-	jne	1f
-	lea	%pc@(2f+0x80000000),%a0
-1:	orw	#TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
-	movec	%d0,%itt0
-	movec	%a5,%urp
-	movec	%a5,%srp
-	pflusha
-	movel	#TC_ENABLE+TC_PAGE4K,%d0
 	/*
-	 * this value is also ok for the 68060, we don`t use the cache
-	 * mode/protection defaults
+	 * Find the page table entry (PTE) for the page
 	 */
-	movec	%d0,%tc		/* enable the MMU */
-	jmp	%a0@
-2:	moveq	#0,%d0
-	movec	%d0,%itt0
-	jmp	LdoneMMUenable:w
-	.chip	68k
-
-Lmapphysnotamiga:
+	movel	%a5@(%d5*4),%d0
+	andil	#_TABLE_MASK,%d0
+	movel	%d0,%a0
+	movel	%a0@(%d4*4),%d0
+	andil	#0xffffff00,%d0
+	movel	%d0,%a0
+	movel	%a0@(%d3*4),%d0
+	/*
+	 * Set cache mode to cacheable write through
+	 */
+	andil	#_CACHEMASK040,%d0
+	orl	%pc@(SYMBOL_NAME(m68k_pgtable_cachemode)),%d0
+	movel	%d0,%a0@(%d3*4)
+	
+	moveml	%sp@+,%a0/%d0-%d5
+	rts
+	
+mmu_fixup_done:
+#endif /* CONFIG_M68040 && CONFIG_M68060 */
+	
+#if defined(MMU_PRINT)
+	jbsr	mmu_print
 #endif
 
-#ifdef CONFIG_ATARI
-	is_not_atari(Lmapphysnotatari)
-
-/*
- * If the kernel physical address is different from its virtual address, we
- * will temporarily set up an identity mapping of the 16MB chunk with
- * transparent translation where the kernel is executing.
+/* 
+ * mmu_engage
+ * 
+ * This chunk of code performs the gruesome task of engaging the MMU.
+ * The reason its gruesome is because when the MMU becomes engaged it
+ * maps logical addresses to physical addresses.  The Program Counter
+ * register is then passed through the MMU before the next instruction
+ * is fetched (the instruction following the engage MMU instruction).
+ * This may mean one of two things:
+ * 1. The Program Counter falls within the logical address space of
+ *    the kernel of which there are two sub-possibilities:
+ *    A. The PC maps to the correct instruction (logical PC == physical
+ *       code location), or
+ *    B. The PC does not map through and the processor will read some
+ *       data (or instruction) which is not the logically next instr.
+ *    As you can imagine, A is good and B is bad.
+ * Alternatively,
+ * 2. The Program Counter does not map through the MMU.  The processor
+ *    will take a Bus Error.
+ * Clearly, 2 is bad.
+ * It doesn't take a wiz kid to figure you want 1.A.
+ * This code creates that possibility.
+ * There are two possible 1.A. states (we now ignore the other above states):
+ * A. The kernel is located at physical memory addressed the same as
+ *    the logical memory for the kernel, i.e., 0x01000.
+ * B. The kernel is located some where else.  e.g., 0x0400.0000
+ * 
+ *    Under some conditions the Macintosh can look like A or B.
+ * [A friend and I once noted that Apple hardware engineers should be
+ * wacked twice each day: once when they show up at work (as in, Whack!,
+ * "This is for the screwy hardware we know you're going to design today."),
+ * and also at the end of the day (as in, Whack! "I don't know what
+ * you designed today, but I'm sure it wasn't good."). -- rst]
+ * 
+ * This code works on the following premise:
+ * If the kernel start (%d5) is within the first 16 Meg of RAM,
+ * then create a mapping for the kernel at logical 0x8000.0000 to
+ * the physical location of the pc.  And, create a transparent
+ * translation register for the first 16 Meg.  Then, after the MMU
+ * is engaged, the PC can be moved up into the 0x8000.0000 range
+ * and then the transparent translation can be turned off and then
+ * the PC can jump to the correct logical location and it will be
+ * home (finally).  This is essentially the code that the Amiga used
+ * to use.  Now, it's generalized for all processors.  Which means
+ * that a fresh (but temporary) mapping has to be created.  The mapping
+ * is made in page 0 (an as of yet unused location -- except for the
+ * stack!).  This temporary mapping will only require 1 pointer table
+ * and a single page table (it can map 256K).
+ *
+ * OK, alternatively, imagine that the Program Counter is not within
+ * the first 16 Meg.  Then, just use Transparent Translation registers
+ * to do the right thing.
+ *
+ * Last, if _start is already at 0x01000, then there's nothing special
+ * to do (in other words, in a degenerate case of the first case above,
+ * do nothing).
+ *
+ * Let's do it.
+ * 
+ * 
  */
-	putc('L')
 
-	/* fixup the  Atari iobase register location before printing */
+	putc_trace('L')
+	
+#if defined(CONFIG_MAC)
+	is_not_mac(1f)
+	lea	%pc@(Lconsole_video_virtual),%a1
+	lea	%pc@(SYMBOL_NAME(mac_videobase)),%a3
+	movel	%a1@,%a3@
+1:
+#endif
+	
+#if defined(CONFIG_AMIGA)
+	is_not_amiga(1f)
+	/* fixup the Amiga custom register location before printing */
+	lea	%pc@(Lcustom),%a0
+	movel	#0x80000000,%a0@
+1:	
+#endif
+
+#if defined(CONFIG_ATARI)
+	is_not_atari(1f)
+	/* fixup the Atari iobase register location before printing */
 	lea	%pc@(Liobase),%a0
 	movel	#0xff000000,%a0@
+1:	
+#endif
+	
+#if defined(CONFIG_HP300)
+	is_not_hp300(1f)
+	/*
+	 * Fix up the custom register to point to the new location of the LEDs.
+	 */
+	lea	%pc@(Lcustom),%a1
+	movel	#0xf0000000,%a1@
+1:	
+#endif
+	
+	/*
+	 * Test for the simplest case:
+	 *    _start == 0x01000 
+	 *       %d5 == 0x00000
+	 */
+	lea	mmu_engage_done:w,%a0
+	tstl	%d5
+	jbeq	mmu_engage_core
 
-	is_040_or_060(Latarimmu68040)
-
-	.chip	68030
-	lea	%pc@(Lmmu),%a3
+	/*
+	 * Prepare a transparent translation register
+	 * for the region the kernel is in.
+	 */
 	movel	%d5,%d0
-	jne	1f
-	lea	LdoneMMUenable:w,%a0
-	jra	3f
-1:	lea	4f:w,%a0
-	andl	#0xff000000,%d0 /* logical address base */
-	jeq	2f
+	andl	#0xff000000,%d0
+
+#if defined(CONFIG_M68040) || defined(CONFIG_M68060)
+	is_not_040_or_060(1f)
+	lea	mmu_engage_040_disable_itt0,%a0
+	
+	orw	#TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
+	.chip	68040
+	movec	%d0,%itt0
+	.chip	68k
+	jbra	2f
+1:
+#endif
+#if defined(CONFIG_M68020) || defined(CONFIG_M68030)
+	lea	mmu_engage_030_disable_tt0,%a0
+	
 	orw	#TTR_ENABLE+TTR_CI+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d0
+	lea	%pc@(Lmmu),%a3
 	movel	%d0,%a3@
+	.chip	68030
 	pmove	%a3@,%tt0
-	jra	3f
-	/* tt0 doesn't work if physical and virtual address of kernel is in
-	 * the same 16M area (Falcon with Magnum/FX, kernel in alternate ram)
-	 * Transparent translation through kernel pointer table
-	 * Requires that this code until after MMU enabling lies in
-	 * the 256K page around %d5
-	 */
-2:	movel	%a5@,%d1
-	andw	#0xfff0,%d1
-	movel	%d1,%a1
-	movel	%d5,%d1
-	moveq	#PTR_INDEX_SHIFT,%d0
-	lsrl	%d0,%d1
-	lea	%a1@(%d1:l:4),%a1
-	movel	%d5,%d1
-	orw	#_PAGE_PRESENT+_PAGE_ACCESSED,%d1
-	movel	%a1@,%d2
-	movel	%d1,%a1@
-	lea	5f:w,%a0
-	/* no limit, 4byte descriptors */
-3:	movel	#0x80000002,%a3@
-	movel	%a5,%a3@(4)
-	pmove	%a3@,%srp
-	pmove	%a3@,%crp
-	pflusha
-	/*
-	 * enable,super root enable,4096 byte pages,7 bit root index,
-	 * 7 bit pointer index, 6 bit page table index.
-	 */
-	movel	#0x82c07760,%a3@
-	pmove	%a3@,%tc	/* enable the MMU */
-	jmp	%a0@
-4:	clrl	%a3@
-	pmove	%a3@,%tt0
-	jra	LdoneMMUenable
-5:	movel	%d2,%a1@
-	jra	LdoneMMUenable
 	.chip	68k
+#endif
 
-Latarimmu68040:
-	.chip	68040
+	/*
+	 * Test for being able to use just a
+	 * transparent translation register:
+	 *    _start >= 0x0100.1000
+	 *       %d5 >= 0x0100.0000
+	 */
+2:
 	movel	%d5,%d0
-	jne	1f
-	lea	LdoneMMUenable:w,%a0
-	jra	2f
-1:	lea	3f:w,%a0
-	andl	#0xff000000,%d0 /* logical address base */
-	orw	#TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
-	movec	%d0,%itt0
-2:	nop
-	pflusha
-	movec	%a5,%srp
-	movec	%a5,%urp
-	movel	#TC_ENABLE+TC_PAGE4K,%d0
+	andil	#0xff000000,%d0
+	jbne	mmu_engage_core
+
 	/*
-	 * this value is also ok for the 68060, we don`t use the cache
-	 * mode/protection defaults
+	 * I hate this case: 
+	 *   %d5 > 0, and
+	 *   %d5 < 0x0100.0000
+	 * Here's where we have to create a temporary mapping
+	 * at 0x8000.0000 and do all the right stuff magic.
+	 * This bites.  -- rst
 	 */
-	movec	%d0,%tc		/* enable the MMU */
-	jmp	%a0@
-3:	moveq	#0,%d0
-	movec	%d0,%itt0
-	jra	LdoneMMUenable
-	.chip	68k
 
-Lmapphysnotatari:
-#endif
+#define TMP_MAP		0x80000000
+#define TMP_MAP_OFFS	(TMP_MAP>>(ROOT_INDEX_SHIFT-2))
 
-#if defined(CONFIG_MVME16x)
-	is_not_mvme16x(Lmapphysnot16x)
 	/*
-	 * save physaddr of phys mem in register a3
+	 * Build a really small Ptr table at %d5
 	 */
-	moveq	#'L',%d7
-	jbsr	Lserial_putc
-
-	.word	0xf4d8		/* CINVA I/D    */
-	.word	0xf518		/* pflusha      */
-	.long	0x4e7bd807	/* movec a5,srp */
-	.long	0x4e7bd806	/* movec a5,urp */
-	movel	#(TC_ENABLE+TC_PAGE4K),%d0
-	.long	0x4e7b0003	/* movec d0,tc  (enable the MMU) */
-	jra	LdoneMMUenable	/* branch to continuation of startup */
+	movel	%d5,%a4
+	jbsr	mmu_clear_pointer_table
+	
+	movel	%d5,%d0
+	addl	#0x100,%d0
+	orw	#_PAGE_TABLE+_PAGE_ACCESSED,%d0
+	movel	%d0,%a4@
+	
+	/*
+	 * Build a really small Page table at %d5 + 0x100
+	 * (Maps the first 16K of the kernel @ 0x8000.0000)
+	 */
+	movel	%d5,%a3
+	addaw	#0x100,%a3
+	jbsr	mmu_clear_page_table
+	
+	movel	#PAGESIZE,%d1
+	movel	%d5,%d0
+	orw	#_PAGE_PRESENT+_PAGE_ACCESSED,%d0
+	movel	%d0,%a3@+
+	addl	%d1,%d0
+	movel	%d0,%a3@+
+	addl	%d1,%d0
+	movel	%d0,%a3@+
+	addl	%d1,%d0
+	movel	%d0,%a3@
 
-Lmapphysnot16x:
+	/*
+	 * Alter the Root table to use our really small entries
+	 */
+	lea	%a5@(TMP_MAP_OFFS),%a0
+	movel	%a0@,%d2		/* save entry */
+	movel	%d5,%d0
+	orw	#_PAGE_TABLE+_PAGE_ACCESSED,%d0
+	movel	%d0,%a0@		/* insert temp. entry */
 
+#if defined(CONFIG_M68040) || defined(CONFIG_M68060)
+	is_not_040_or_060(1f)
+	lea	mmu_engage_040_disable_8000,%a0
+	addal	#TMP_MAP,%a0
+	jbra	mmu_engage_core
+1:
 #endif
+#if defined(CONFIG_M68020) || defined(CONFIG_M68030)
+	lea	mmu_engage_030_disable_8000,%a0
+	addal	#TMP_MAP,%a0
+#endif
+	
+mmu_engage_core:
+	
+#if defined(CONFIG_M68040) || defined(CONFIG_M68060)
+	is_not_040_or_060(2f)
 
-#if defined(CONFIG_HP300)
-	is_not_hp300(Lmapphysnothp300)
+mmu_engage_040:
+	.chip	68040
+	nop
+	cinva	%bc
+	nop
+	pflusha
+	nop
+	movec	%a5,%srp
+	movec	%a5,%urp
+	movel	#TC_ENABLE+TC_PAGE4K,%d0
+	movec	%d0,%tc		/* enable the MMU */
+	lea	SYMBOL_NAME(kernel_pg_dir),%a5
+	jmp	%a0@		/* Go to clean up code */
 
-/*
- * Physical RAM is at 0xff000000.  We want to map the kernel at 0x00000000.
- * In order to avoid disaster when we enable the MMU we need to make a
- * transparent mapping of the RAM we're executing out of as well.
- */
+mmu_engage_040_disable_itt0:
+	moveq	#0,%d0
+	movec	%d0,%itt0
+	jmp	mmu_engage_done:w
+
+mmu_engage_040_disable_8000:
 	/*
-	 * save physaddr of phys mem in register a3
+	 * This code is running at 0x8000.0000+ right now
 	 */
+	moveq	#0,%d0
+	movec	%d0,%itt0
+	jmp	1f:w	/* Jump down into logical space into the kernel! */
+1:
+	/* Now we're back on the ground! */
+	movel	%d2,%a5@(TMP_MAP_OFFS) /* Restore the old 0x8000.0000 mapping */
+	nop
+	pflusha
+	nop
+	jmp	mmu_engage_done:w
+	.chip	68k
+
+2:
+#endif
 
+#if defined(CONFIG_M68020) || defined(CONFIG_M68030)
+mmu_engage_030:
 	.chip	68030
 	lea	%pc@(Lmmu),%a3
-	movel	%d5,%d0
-	andl	#0xff000000,%d0 /* logical address base */
-	orw	#TTR_ENABLE+TTR_CI+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d0
-	movel	%d0,%a3@
-	pmove	%a3@,%tt0
-	/* no limit, 4byte descriptors */
 	movel	#0x80000002,%a3@
 	movel	%a5,%a3@(4)
+	movel	#0x0808,%d1
+	movec	%d1,%cacr
 	pmove	%a3@,%srp
 	pmove	%a3@,%crp
 	pflusha
@@ -971,117 +1516,171 @@
 	 */
 	movel	#0x82c07760,%a3@
 	pmove	%a3@,%tc	/* enable the MMU */
-	jmp	1f
-1:	
-	.chip	68k
+	lea	SYMBOL_NAME(kernel_pg_dir),%a5
+	jmp	%a0@		/* Go to the appropriate clean up code */
 
-	/*
-	 * Fix up the custom register to point to the new location of the LEDs.
-	 */
-	lea	%pc@(Lcustom),%a1
-	movel	#0xf0000000,%a1@
-
-	/*
-	 * Energise the FPU and caches.
-	 */
-	orl	#0x64, 0xf05f400c 
+mmu_engage_030_disable_tt0:
+	clrl	%a3@
+	pmove	%a3@,%tt0
+	jmp	mmu_engage_done:w
 	
-Lmapphysnothp300:
-
+mmu_engage_030_disable_8000:
+	clrl	%a3@
+	pmove	%a3@,%tt0
+	jmp	1f:w	/* Jump down into logical space into the kernel! */
+1:
+	/* Now we're back on the ground! */
+	movel	%d2,%a5@(TMP_MAP_OFFS)	/* Restore the old 0x8000.0000 mapping */
+	pflusha
+	jmp	mmu_engage_done:w
+	.chip	68k
 #endif
+	
+mmu_engage_done:
 
-#if defined(CONFIG_BVME6000)
-	is_not_bvme6000(Lmapphysnotbvm)
-	/*
-	 * save physaddr of phys mem in register a3
-	 */
-	moveq	#'L',%d7
-	jbsr	Lserial_putc
-
-	.word	0xf4d8		/* CINVA I/D    */
-	.word	0xf518		/* pflusha      */
-	.long	0x4e7bd807	/* movec a5,srp */
-	.long	0x4e7bd806	/* movec a5,urp */
-	movel	#(TC_ENABLE+TC_PAGE4K),%d0
+#if defined(CONFIG_HP300)
+	is_not_hp300(1f)
 	/*
-	 * this value is also ok for the 68060, we don`t use the cache
-	 * mode/protection defaults
+	 * Energise the FPU and caches.
 	 */
-	.long	0x4e7b0003	/* movec d0,tc  (enable the MMU) */
-	jra	LdoneMMUenable	/* branch to continuation of startup */
-
-Lmapphysnotbvm:
-
+	movel	#0x60, 0xf05f400c
+1:	
 #endif
-
-LdoneMMUenable:
-
+	movew	#PAGESIZE,%sp
+	
 /*
  * Fixup the addresses for the kernel pointer table and availmem.
  * Convert them from physical addresses to virtual addresses.
  */
 
-	putc('M')
+	putc_trace('M')
 	leds(0x10)
 
-	/*
-	 * d5 contains physaddr of kernel start
+	/* d5 contains physaddr of kernel start
 	 */
-	subl	%d5,SYMBOL_NAME(kpt)
+	lea	SYMBOL_NAME(kpt),%a0
+	subl	%d5,%a0@
 
-	/*
-	 * do the same conversion on the first available memory
+	/* do the same conversion on the first available memory
 	 * address (in a6).
 	 */
+	lea	SYMBOL_NAME(availmem),%a0
 	subl	%d5,%a6
-	movel	%a6,SYMBOL_NAME(availmem) /* first available memory address */
-
-	putc('N')
-
+	movel	%a6,%a0@
+	
 /*
  * Enable caches
  */
-	is_040_or_060(Lcache680460)
 
-	movel	#CC3_ENABLE_DB+CC3_CLR_D+CC3_ENABLE_D+CC3_ENABLE_IB+CC3_CLR_I+CC3_ENABLE_I,%d0
-	movec	%d0,%cacr
-	jra	1f
+#if defined(CONFIG_M68040) || defined(CONFIG_M68060)
+	is_not_040_or_060(Lcache_not_680460)
 
 Lcache680460:
 	.chip	68040
+	nop
 	cpusha	%bc
-	.chip	68k
-
+	nop
+	
 	is_060(Lcache68060)
 
 	movel	#CC6_ENABLE_D+CC6_ENABLE_I,%d0
 	/* MMU stuff works in copyback mode now, so enable the cache */
 	movec	%d0,%cacr
-	jra	1f
+	jra	Lcache_done
 
 Lcache68060:
-	.chip	68060
 	movel	#CC6_ENABLE_D+CC6_ENABLE_I+CC6_ENABLE_SB+CC6_PUSH_DPI+CC6_ENABLE_B+CC6_CLRA_B,%d0
 	/* MMU stuff works in copyback mode now, so enable the cache */
 	movec	%d0,%cacr
 	/* enable superscalar dispatch in PCR */
 	moveq	#1,%d0
+	.chip	68060
 	movec	%d0,%pcr
+
+	jbra	Lcache_done
+Lcache_not_680460:
+#endif
+#if defined(CONFIG_M68020) || defined(CONFIG_M68030)
+Lcache68030:
+	.chip	68030
+	movel	#CC3_ENABLE_DB+CC3_CLR_D+CC3_ENABLE_D+CC3_ENABLE_IB+CC3_CLR_I+CC3_ENABLE_I,%d0
+	movec	%d0,%cacr
+
+	jra	Lcache_done
+#endif
 	.chip	68k
-1:
+Lcache_done:
 
+	putc_trace('P')
+
+#if defined(MMU_PRINT_PAGE_USAGE)
+	/*
+	 * Print out the number of pages used by MMU above the kernel
+	 */
+	puts("MMU #")
+	lea	%pc@(SYMBOL_NAME(_end)),%a0
+	addw	#PAGESIZE-1,%a0
+	movel	%a0,%d0
+	andl	#-PAGESIZE,%d0
+	movel	%a6,%d1
+	subl	%d0,%d1		/* d1 :	= d1 - d0 */
+	putn(%d1)
+	putr()
+
+	puts("Page #")
+	putn(%pc@(Lmmu_num_page_tables))
+	putr()
+	
+
+	puts("Ptr #")
+	putn(%pc@(Lmmu_num_pointer_tables))
+	putr()
+
+	puts("Total #")
+	movel	%pc@(Lmmu_num_page_tables),%d0
+	addl	%pc@(Lmmu_num_pointer_tables),%d0
+	putn(%d0)
+	putr()
+
+	puts("Halting.")	
+1:
+	jbra	1b
+#endif /* MMU_PRINT_PAGE_USAGE */
+	
 /*
  * Setup initial stack pointer
- * We need to get current loaded up with our first task...
  */
 	lea	SYMBOL_NAME(init_task_union),%a2
-	lea	8192(%a2),%sp
+	lea	0x2000(%a2),%sp
 
 /* jump to the kernel start */
 	putr()
 	leds(0x55)
 
-	subl	%a6,%a6 /* clear a6 for gdb */
+#if defined(DEBUG)
+	puts("     kpt:")
+	lea	%pc@(SYMBOL_NAME(kpt)),%a0
+	movel	%a0,%d7		/* get start addr. */
+	jbsr	Lserial_putnum
+	putr()
+
+	puts("    *kpt:")
+	lea	%pc@(SYMBOL_NAME(kpt)),%a0
+	movel	%a0@,%d7	/* get start addr. */
+	jbsr	Lserial_putnum
+	putr()
+#endif
+
+#if 0
+	movel	#0xFFFF,%d1
+2:
+	movel	#0xFFFFFFFF,%d0
+1:
+	dbra	%d0,1b
+	dbra	%d1,2b
+#endif
+
+	subl	%a6,%a6		/* clear a6 for gdb */
 	jbsr	SYMBOL_NAME(start_kernel)
 
 /*
@@ -1106,18 +1705,1093 @@
 	lea	%a0@(BIR_size),%a0
 	rts
 
+
+/*
+ *	MMU Initialization Begins Here
+ *
+ *	The structure of the MMU tables on the 68k machines
+ *	is thus:
+ *	Root Table
+ *		Logical addresses are translated through
+ *	a hierarchical translation mechanism where the high-order
+ *	seven bits of the logical address (LA) are used as an
+ *	index into the "root table."  Each entry in the root
+ *	table has a bit which specifies if it's a valid pointer to a
+ *	pointer table.  Each entry defines a 32KMeg range of memory.
+ *	If an entry is invalid then that logical range of 32M is
+ *	invalid and references to that range of memory (when the MMU
+ *	is enabled) will fault.  If the entry is valid, then it does
+ *	one of two things.  On 040/060 class machines, it points to
+ *	a pointer table which then describes more finely the memory
+ *	within that 32M range.  On 020/030 class machines, a technique
+ *	called "early terminating descriptors" are used.  This technique
+ *	allows an entire 32Meg to be described by a single entry in the
+ *	root table.  Thus, this entry in the root table, contains the
+ *	physical address of the memory or I/O at the logical address
+ *	which the entry represents and it also contains the necessary
+ *	cache bits for this region.
+ *
+ *	Pointer Tables
+ *		Per the Root Table, there will be one or more
+ *	pointer tables.  Each pointer table defines a 32M range.
+ *	Not all of the 32M range need be defined.  Again, the next
+ *	seven bits of the logical address are used an index into
+ *	the pointer table to point to page tables (if the pointer
+ *	is valid).  There will undoubtedly be more than one
+ *	pointer table for the kernel because each pointer table
+ *	defines a range of only 32M.  Valid pointer table entries
+ *	point to page tables, or are early terminating entries
+ *	themselves.
+ *
+ *	Page Tables
+ *		Per the Pointer Tables, each page table entry points
+ *	to the physical page in memory that supports the logical
+ *	address that translates to the particular index.
+ *
+ *	In short, the Logical Address gets translated as follows:
+ *		bits 31..26 - index into the Root Table
+ *		bits 25..18 - index into the Pointer Table
+ *		bits 17..12 - index into the Page Table
+ *		bits 11..0  - offset into a particular 4K page
+ *	
+ *	The algorithms which follows do one thing: they abstract
+ *	the MMU hardware.  For example, there are three kinds of
+ *	cache settings that are relevant.  Either, memory is
+ *	being mapped in which case it is either Kernel Code (or
+ *	the RamDisk) or it is MMU data.  On the 030, the MMU data
+ *	option also describes the kernel.  Or, I/O is being mapped
+ *	in which case it has its own kind of cache bits.  There
+ *	are constants which abstract these notions from the code that
+ *	actually makes the call to map some range of memory.
+ *	
+ *	
+ *	
+ */
+
+#if defined(MMU_PRINT)
+/*
+ *	mmu_print
+ *	
+ *	This algorithm will print out the current MMU mappings.
+ *	
+ *	Input:
+ *		%a5 points to the root table.  Everything else is calculated
+ *			from this.
+ */
+
+#define mmu_next_valid		0
+#define mmu_start_logical	4
+#define mmu_next_logical	8
+#define mmu_start_physical	12
+#define mmu_next_physical	16
+
+#define MMU_PRINT_INVALID		-1
+#define MMU_PRINT_VALID			1
+#define MMU_PRINT_UNINITED		0
+
+#define	putZc(z,n)		jbne 1f; putc(z); jbra 2f ; 1: putc(n); 2:
+
+mmu_print:
+	moveml	%a0-%a6/%d0-%d7,%sp@-
+
+	lea	%pc@(Lmmu_print_data),%a0
+	movel	#MMU_PRINT_UNINITED,%a0@(mmu_next_valid)
+	
+	is_not_040_or_060(mmu_030_print)
+	
+mmu_040_print:
+	putr()
+	puts("MMU040")
+	putr()
+	putr()
+	puts("rp:")
+	movel	%a5,%d7
+	jbsr	Lserial_putnum
+	putr()
+	puts("tc:")
+	movel	%d5,%d7
+	jbsr	Lserial_putnum
+	putr()
+	putr()
+#if 0
+	/*
+	 * The following #if/#endif block is a tight algorithm for dumping the 040
+	 * MMU Map in gory detail.  It really isn't that practical unless the
+	 * MMU Map algorithm appears to go awry and you need to debug it at the
+	 * entry per entry level.
+	 */
+	movel	#ROOT_TABLE_SIZE-1,%d5
+	movel	%a5@+,%d7		/* Burn an entry to skip the kernel mappings, they work */
+1:	tstl	%d5
+	jbeq	mmu_print_done
+	subq	#1,%d5
+	movel	%a5@+,%d7
+	btst	#1,%d7
+	jbeq	1b
+
+2:	jbsr	Lserial_putnum
+	andil	#0xFFFFFE00,%d7
+	movel	%d7,%a4
+	movel	#PTR_TABLE_SIZE,%d4
+	putc(' ')
+3:	tstl	%d4
+	jbeq	11f
+	subq	#1,%d4
+	movel	%a4@+,%d7
+	btst	#1,%d7
+	jbeq	3b
+
+4:	jbsr	Lserial_putnum
+	andil	#0xFFFFFF00,%d7
+	movel	%d7,%a3
+	movel	#PAGE_TABLE_SIZE,%d3
+5:	movel	#8,%d2
+6:	tstl	%d3
+	jbeq	31f
+	subq	#1,%d3
+	movel	%a3@+,%d6
+	btst	#0,%d6
+	jbeq	6b
+7:	tstl	%d2
+	jbeq	8f
+	subq	#1,%d2
+	putc(' ')
+	jbra	91f
+8:	putr()
+	movel	#8+1+8+1+1,%d2
+9:	putc(' ')
+	dbra	%d2,9b
+	movel	#7,%d2
+91:	movel	%d6,%d7
+	jbsr	Lserial_putnum
+	jbra	6b
+
+31:	putr()
+	movel	#8+1,%d2
+32:	putc(' ')
+	dbra	%d2,32b
+	jbra	3b
+
+11:	putr()
+	jbra	1b
+#endif /* MMU 040 Dumping code that's gory and detailed */
+			
+	movel	%a5,%d0			/* a5 -> root table ptr */
+	andil	#0xfffffe00,%d0		/* I forget why this is here ? */
+	movel	%d0,%a0			/* a0 has the address of the root table ptr */
+	movel	#0x00000000,%a4		/* logical address */
+	moveql	#0,%d0
+40:
+	/* Increment the logical address and preserve in d5 */
+	movel	%a4,%d5
+	addil	#PAGESIZE<<13,%d5
+	movel	%a0@+,%d6
+	btst	#1,%d6
+	jbne	41f
+	jbsr	mmu_print_tuple_invalidate
+	jbra	48f
+41:	
+	movel	#0,%d1
+	andil	#0xfffffe00,%d6
+	movel	%d6,%a1
+42:
+	movel	%a4,%d5
+	addil	#PAGESIZE<<6,%d5
+	movel	%a1@+,%d6
+	btst	#1,%d6
+	jbne	43f
+	jbsr	mmu_print_tuple_invalidate
+	jbra	47f
+43:		
+	movel	#0,%d2
+	andil	#0xffffff00,%d6
+	movel	%d6,%a2
+44:	
+	movel	%a4,%d5
+	addil	#PAGESIZE,%d5
+	movel	%a2@+,%d6
+	btst	#0,%d6
+	jbne	45f
+	jbsr	mmu_print_tuple_invalidate
+	jbra	46f
+45:
+	moveml	%d0-%d1,%sp@-
+	movel	%a4,%d0
+	movel	%d6,%d1
+	andil	#0xfffff4e0,%d1
+	lea	%pc@(mmu_040_print_flags),%a6
+	jbsr	mmu_print_tuple
+	moveml	%sp@+,%d0-%d1
+46:
+	movel	%d5,%a4
+	addq	#1,%d2
+	cmpib	#64,%d2
+	jbne	44b
+47:
+	movel	%d5,%a4
+	addq	#1,%d1
+	cmpib	#128,%d1
+	jbne	42b
+48:
+	movel	%d5,%a4			/* move to the next logical address */	
+	addq	#1,%d0
+	cmpib	#128,%d0
+	jbne	40b
+
+	.long	0x4e7a0007		/* movec dtt1,%d0 */
+	movel	%d0,%d1
+	andiw	#0x8000,%d1		/* is it valid ? */
+	jbeq	49f			/* No, bail out */
+
+	movel	%d0,%d1
+	andil	#0xff000000,%d1		/* Get the address */
+	putn(%d1)
+	puts("==")
+	putn(%d1)
+
+	movel	%d0,%d6
+	jbsr	mmu_040_print_flags_tt
+	
+49:
+	jbra	mmu_print_done
+
+mmu_040_print_flags:
+	btstl	#10,%d6
+	putZc(' ','G')	/* global bit */
+	btstl	#7,%d6
+	putZc(' ','S')	/* supervisor bit */
+mmu_040_print_flags_tt:	
+	btstl	#6,%d6
+	jbne	3f
+	putc('C')
+	btstl	#5,%d6
+	putZc('w','c')	/* write through or copy-back */
+	jbra	4f
+3:
+	putc('N')
+	btstl	#5,%d6
+	putZc('s',' ')	/* serialized non-cacheable, or non-cacheable */
+4:		
+	rts
+	
+mmu_030_print_flags:
+	btstl	#6,%d6
+	putZc('C','I')	/* write through or copy-back */
+	rts
+	
+mmu_030_print:	
+	putr()
+	puts("rp:")
+	movel	%a5,%d7
+	jbsr	Lserial_putnum
+	putr()
+	puts("tc:")
+	movel	%d5,%d7
+	jbsr	Lserial_putnum
+	putr()
+	putr()
+	puts("MMU030")
+	putr()
+	movel	%a5,%d0
+	andil	#0xfffffff0,%d0
+	movel	%d0,%a0
+	movel	#0x00000000,%a4		/* logical address */
+	movel	#0,%d0
+30:
+	movel	%a4,%d5
+	addil	#PAGESIZE<<13,%d5
+	movel	%a0@+,%d6
+	btst	#1,%d6			/* is it a ptr? */
+	jbne	31f			/* yes */
+	btst	#0,%d6			/* is it early terminating? */
+	jbeq	1f			/* no */
+	jbsr	mmu_030_print_helper
+	jbra	38f
+1:	
+	jbsr	mmu_print_tuple_invalidate
+	jbra	38f
+31:	
+	movel	#0,%d1
+	andil	#0xfffffff0,%d6
+	movel	%d6,%a1
+32:
+	movel	%a4,%d5
+	addil	#PAGESIZE<<6,%d5
+	movel	%a1@+,%d6
+	btst	#1,%d6
+	jbne	33f
+	btst	#0,%d6
+	jbeq	1f			/* no */
+	jbsr	mmu_030_print_helper
+	jbra	37f
+1:	
+	jbsr	mmu_print_tuple_invalidate
+	jbra	37f
+33:		
+	movel	#0,%d2
+	andil	#0xfffffff0,%d6
+	movel	%d6,%a2
+34:	
+	movel	%a4,%d5
+	addil	#PAGESIZE,%d5
+	movel	%a2@+,%d6
+	btst	#0,%d6
+	jbne	35f
+	jbsr	mmu_print_tuple_invalidate
+	jbra	36f
+35:
+	jbsr	mmu_030_print_helper
+36:
+	movel	%d5,%a4
+	addq	#1,%d2
+	cmpib	#64,%d2
+	jbne	34b
+37:
+	movel	%d5,%a4
+	addq	#1,%d1
+	cmpib	#128,%d1
+	jbne	32b
+38:
+	movel	%d5,%a4			/* move to the next logical address */	
+	addq	#1,%d0
+	cmpib	#128,%d0
+	jbne	30b
+
+mmu_print_done:
+	putr()
+	putr()
+	
+	moveml	%sp@+,%a0-%a6/%d0-%d7
+	rts
+
+mmu_030_print_helper:
+	moveml	%d0-%d1,%sp@-
+	movel	%a4,%d0
+	movel	%d6,%d1
+	lea	%pc@(mmu_030_print_flags),%a6
+	jbsr	mmu_print_tuple
+	moveml	%sp@+,%d0-%d1
+	rts
+	
+mmu_print_tuple_invalidate:
+	moveml	%a0/%d7,%sp@-
+
+	lea	%pc@(Lmmu_print_data),%a0
+	tstl	%a0@(mmu_next_valid)
+	jbmi	mmu_print_tuple_invalidate_exit
+	
+	movel	#MMU_PRINT_INVALID,%a0@(mmu_next_valid)
+
+	movel	%a4,%d7
+	jbsr	Lserial_putnum
+	
+	puts("##")
+	putr()
+	
+mmu_print_tuple_invalidate_exit:
+	moveml	%sp@+,%a0/%d7
+	rts
+
+		
+mmu_print_tuple:
+	moveml	%d0-%d7/%a0,%sp@-
+
+	lea	%pc@(Lmmu_print_data),%a0
+	
+	tstl	%a0@(mmu_next_valid)
+	jbmi	mmu_print_tuple_print
+	jbeq	mmu_print_tuple_print
+	jbpl	mmu_print_tuple_test
+
+mmu_print_tuple_test:
+	cmpl	%a0@(mmu_next_physical),%d1
+	jbeq	mmu_print_tuple_increment
+	
+mmu_print_tuple_print:
+	movel	%d0,%d7
+	jbsr	Lserial_putnum
+	
+	puts("->")
+	
+	movel	%d1,%d7
+	jbsr	Lserial_putnum
+
+	movel	%d1,%d6
+	jbsr	%a6@
+	
+mmu_print_tuple_record:
+	movel	#MMU_PRINT_VALID,%a0@(mmu_next_valid)
+	
+	movel	%d1,%a0@(mmu_next_physical)
+
+mmu_print_tuple_increment:
+	movel	%d5,%d7
+	subl	%a4,%d7
+	addl	%d7,%a0@(mmu_next_physical)
+	
+mmu_print_tuple_exit:	
+	moveml	%sp@+,%d0-%d7/%a0
+	rts
+
+mmu_print_machine_cpu_types:
+	puts("machine: ")
+	
+	is_not_amiga(1f)
+	puts("amiga")
+	jbra	9f
+1:	
+	is_not_atari(2f)
+	puts("atari")
+	jbra	9f
+2:	
+	is_not_mac(3f)
+	puts("macintosh")
+	jbra	9f
+3:	puts("unknown")
+9:	putr()
+
+	puts("cputype: 0")		
+	is_not_060(1f)
+	putc('6')
+	jbra	9f
+1:	
+	is_not_040_or_060(2f)
+	putc('4')
+	jbra	9f
+2:	putc('3')
+9:	putc('0')
+	putr()
+		
+	rts
+#endif /* MMU_PRINT */
+
+/*
+ *	mmu_clear_root_table
+ *
+ *	%a5 = pointer to the root table
+ *	
+ *	This routine will clear out the kernel root table
+ *
+ *	The root table points to 128 pointer tables.  Because the
+ *	root table describes 32 bits of logical memory, (and there
+ *	are 7 bits of indexing in the root table) there is 25 bits
+ *	of logical address space described by each entry in the
+ *	root table.  2^25 is 32Meg, another way to look at that is
+ *	4Gig / 128 = 32Meg.  Any entry which does not have bit 1 set
+ *	is not a valid entry.  In that case, a reference into that
+ *	memory range will cause a memory exception (bus error).
+ *
+ */
+mmu_clear_root_table:
+	movel	%d0,%sp@-
+	
+	moveq	#ROOT_TABLE_SIZE-1,%d0
+1:	clrl	%a5@(%d0*4)
+	dbra	%d0,1b
+
+	movel	%sp@+,%d0
+	rts
+
+/*
+ *	mmu_clear_pointer_table
+ *
+ *	%a4 = pointer to a pointer table
+ *
+ *	This routine will clear out a pointer table.
+ *	It does NOT link the pointer table into the root table
+ *	(that linkage is done by mapping memory!)
+ */
+mmu_clear_pointer_table:	
+	movel	%d0,%sp@-
+	
+	moveq	#PTR_TABLE_SIZE-1,%d0
+1:	clrl	%a4@(%d0*4)
+	dbra	%d0,1b
+
+	movel	%sp@+,%d0
+	rts
+
+/*
+ *	mmu_clear_page_table
+ *
+ *	%a3 = pointer to a page table
+ *
+ *	This routine will clear out a page table.
+ *	It does NOT link the page table into the pointer table
+ *	(that linkage is done by mapping memory!)
+ */
+mmu_clear_page_table:	
+	movel	%d0,%sp@-
+	
+	moveq	#PAGE_TABLE_SIZE-1,%d0
+1:	clrl	%a3@(%d0*4)
+	dbra	%d0,1b
+
+	movel	%sp@+,%d0
+	rts
+
+/*
+ *	mmu_map
+ *
+ *	%a6 = address of free memory above kernel (page aligned)
+ *	%a5 = pointer to the root table
+ *	%a4 = pointer to a pointer table
+ *	%a1 = physical address of mapping
+ *	%a0 = logical address to map
+ *	%d1 = memory type
+ *	%d0 = length of the mapping
+ *
+ *	This routine will map a range of memory using a pointer
+ *	table and allocating the pages on the fly from the kernel.
+ *	The pointer table does not have to be already linked into
+ *	the root table, this routine will do that if necessary.
+ *
+ *	NOTE
+ *	This routine will assert failure and use the Lserial_putc
+ *	routines in the case of a run-time error.  For example,
+ *	if the address to be mapped requires two pointer tables
+ *	this routine will fail and the boot process will terminate.
+ *	A higher level routine would have to be written to call
+ *	this routine multiple times (with different parameters)
+ *	if a single mapping might straddle multiple pointer tables.
+ *
+ *	NOTE-2
+ *	This routine will use early terminating descriptors
+ *	where possible for the 68020+68851 and 68030 type
+ *	processors.
+ */
+mmu_map:
+	moveml	%d0-%d7/%a0-%a5,%sp@-
+
+	/* Calculate the offset in the root table 
+	 */
+	movel	MAP_LOG,%d5
+	andil	#0xfe000000,%d5
+	roll	#7,%d5
+
+	/* Calculate the offset in the pointer table 
+	 */
+	movel	MAP_LOG,%d4
+	andil	#0x01fc0000,%d4
+	lsrl	#2,%d4
+	swap	%d4
+	
+	/* Calculate the offset in the page table (used on 040's + 060's)
+	 */
+	movel	MAP_LOG,%d3
+	andil	#0x0003f000,%d3
+	lsll	#4,%d3
+	swap	%d3
+
+	/*
+	 *	The code that follows implements the following rules
+	 *	with respect to the pointer table for this memory mapping
+	 *	1) If the memory to be mapped lies within an already
+	 *	   mapped region, there will be a pointer table listed
+	 *	   in the root table.  This pointer table must be used.
+	 *	2) If the caller does not supply a pointer table, a table
+	 *	   will be allocated from above the kernel.
+	 *	3) Else, the caller must have passed the address to memory
+	 *	   that will be used as the pointer table for this mapping.
+	 */
+mmu_map_check_root_entry:
+	/* Is another pointer table already mapped into this root entry?
+	 */
+	movel	%a5@(%d5*4),%d2
+	jbeq	mmu_map_check_make_new_pointer_table
+
+	/* If there is an entry already, we must use it
+	 * to preserve existing MMU mapping data!
+	 */
+	andil	#_TABLE_MASK,%d2
+	movel	%d2,%a4
+	jbra	3f
+	
+mmu_map_check_make_new_pointer_table:	
+1:
+	/* Should we get a pointer table from memory on behalf of the caller?
+	 */
+	tstl	%a4
+	jbne	2f
+
+	jbsr	mmu_get_pointer_table
+
+2:
+	/* Put the pointer table into the root table
+	 */	
+	movel	%a4,%d2
+	orw	#_PAGE_TABLE+_PAGE_ACCESSED,%d2
+	movel	%d2,%a5@(%d5*4)
+
+3:
+#if defined(CONFIG_M68020) || defined(CONFIG_M68030)
+	/* Split up here, 030's have different logic than 040's
+	 */
+	
+	is_not_040_or_060(mmu_map_030)
+	
+#endif /* CONFIG_M68020 || CONFIG_M68030 */
+
+/*
+ *	MMU 040 & 060 Support
+ *
+ *	The MMU usage for the 040 and 060 is different enough from
+ *	the 030 and 68851 that there is separate code.  This comment
+ *	block describes the data structures and algorithms built by
+ *	this code.
+ *	
+ *	The 040 does not support early terminating descriptors, as
+ *	the 030 does.  Therefore, a third level of table is needed
+ *	for the 040, and that would be the page table.  In Linux,
+ *	page tables are allocated directly from the memory above the
+ *	kernel.  Register A6 points to the memory above kernel and
+ *	it is from that pool that page tables are allocated.
+ *	
+ *	For each page table that is allocated from above the kernel,
+ *	that page table's address has to be put into the pointer table.
+ *	Then, each page table has to be fully prepared.  Page tables,
+ *	by the way, describe a full 256K of memory.  That coincides with
+ *	the fact that a single entry in the pointer table describes
+ *	a 256K of memory because a pointer table entry points to a
+ *	complete page table.  There are 64 entries in the page table,
+ *	and each entry in the page table points to a physical page of
+ *	memory.  Each page is 4K.
+ *	
+ *	Also, there is a label "kpt" which holds the pointer to the
+ *	page table that describes the kernel.  This is only true on
+ *	the 040 and 060 cpu's.  This algorithm, because it's general
+ *	and allows the mapping of arbitrary regions of memory, assumes
+ *	that the first memory mapping is the one which maps the kernel.
+ *	So it's that page table that gets stored at kpt.
+ *	
+ *	Also, it is an error to attempt to map two regions that
+ *	fall within the same 256K range.  For that to work, this routine
+ *	would need to be modified.
+ *	
+ *	
+ *	Last:
+ *	This body of code is present even on 030 systems as this logic
+ *	is used when a block on an 030 machine is not large enough
+ *	to use an entire early terminating page descriptor.  (This
+ *	can happen on the Macintosh when the video begins life at
+ *	physical address 0.)
+ */
+mmu_map_040:
+	/* Enhance the physical address to make a valid page descriptor
+	 */
+	movel	MAP_PHYS,%d2
+	orw	#_PAGE_PRESENT,%d2
+	orw	MAP_CACHE,%d2
+	movel	%d2,MAP_PHYS
+
+	/* Convert address range length into # of pages
+	 */
+	movel	#PAGESHIFT,%d2
+	lsrl	%d2,MAP_LENGTH
+
+mmu_040_loop:
+	/* See if there is an existing page table pointer to use
+	 */
+	movel	%a4@(%d4*4),%d2
+	andil	#_TABLE_MASK,%d2
+	movel	%d2,%a3
+	tstl	%a3
+	jbne	mmu_fill_040_pagetable
+
+	jbsr	mmu_get_page_table
+
+	/* Now, begin assigning physical pages into the page table
+	 */
+mmu_fill_040_pagetable:
+	movel	MAP_PHYS,%a3@(%d3*4)
+
+	/* Decrement page count
+	 */
+	subq	#1,MAP_LENGTH
+	jbeq	mmu_map_done
+
+	/* Increase mapping addresses
+	 */
+	addl	#PAGESIZE,MAP_PHYS
+	addl	#PAGESIZE,MAP_LOG
+
+	/* Have we exhausted this page table?
+	 */
+	addq	#1,%d3
+	cmpil	#PAGE_TABLE_SIZE,%d3
+	jbne	mmu_fill_040_pagetable
+
+	/* Have we exhausted this pointer table?
+	 */
+	clrl	%d3
+	addq	#1,%d4
+	cmpil	#PTR_TABLE_SIZE,%d4
+	jbne	mmu_040_loop
+
+	/* We've exhausted this pointer table... get a new one
+	 */
+	jbsr	mmu_get_pointer_table
+	clrl	%d4	/* %d4 is ptr table index */
+	
+	jbra	mmu_040_loop
+
+/*
+ * mmu_map_revert
+ *
+ * Control gets here if mmu_map_040_tt is called and the conditions
+ * are not correct to employ tt translations.
+ */
+mmu_map_revert:
+	puts("MMU Note- attempting to use mmu_map_tt when not appropriate")
+	putr()
+	jbra	mmu_map
+
+/*
+ * mmu_map_tt
+ * 
+ * This is a specific function which works on all 680x0 machines.
+ * On 040 & 060 it will attempt to use Transparent Translation registers (tt1).
+ * On 020 & 030 it will call the standard mmu_map which will use early
+ * terminating descriptors.
+ */
+mmu_map_tt:
+	is_not_040_or_060(mmu_map)
+
+#if defined(CONFIG_M68040) || defined(CONFIG_M68060)
+mmu_map_040_tt:
+	moveml	%d0-%d7/%a0-%a4,%sp@-
+#if defined(DEBUG)
+	/*
+	 * Test for Transparent Translation working conditions
+	 */
+	cmpl	MAP_PHYS,MAP_LOG
+	jbne	mmu_map_revert
+
+	movel	MAP_PHYS,%d2
+	andil	#0x00ffffff,%d2
+	jbne	mmu_map_revert
+
+	/* Length must be a power of two
+	 */
+	movel	#0x01000000,%d2
+3:	
+	cmpl	%d2,MAP_LENGTH
+	jbeq	5f
+	lsll	#1,%d2
+	jbne	3b		/* Will terminate when %d2 == 0 */
+	
+	jbra	mmu_map_revert
+5:	
+#endif /* DEBUG */
+
+	subil	#0x01000000,MAP_LENGTH
+	lsrl	#8,MAP_LENGTH
+	movel	MAP_PHYS,%d2
+	orl	MAP_LENGTH,%d2
+	oriw	#0xa000,%d2	/* Enable | Supervisor Only */
+	orb	MAP_CACHE,%d2
+
+	.chip	68040
+	movec	%d2,%itt1
+	movec	%d2,%dtt1
+	.chip	68k
+
+	moveml	%sp@+,%d0-%d7/%a0-%a4
+	rts
+#endif /* CONFIG_M68040 || CONFIG_M68060) */
+
+#if defined(CONFIG_M68020) || defined(CONFIG_M68030)		
+mmu_map_030:
+	/*
+	 * If not a multiple of 256K, use page descriptors.
+	 */
+	movel	MAP_LENGTH,%d2
+	andl	#(PAGE_TABLE_SIZE*PAGESIZE)-1,%d2
+	jbne	mmu_map_040
+
+	/* Enhance the MMU mode to make an early terminating descriptor
+	 */
+	movel	MAP_PHYS,%d2
+	orw	#_PAGE_PRESENT,%d2
+	orw	MAP_CACHE,%d2
+	movel	%d2,MAP_PHYS
+
+	/* Convert # of pages into # of 256K entries
+	 */
+	movel	#PTR_INDEX_SHIFT,%d2
+	lsrl	%d2,MAP_LENGTH
+
+	cmpil	#PTR_TABLE_SIZE,MAP_LENGTH
+	jbcc	mmu_030_root_loop
+		
+	/* Since %a5 and %a4 point to a valid root table and
+	 * a valid pointer table, all we need to do is map.
+	 */
+mmu_030_ptr_loop:
+	/* Map logical to physical
+	 */
+	movel	MAP_PHYS,%a4@(%d4*4)
+
+	/* Decrement number of 256K chunks to map
+	 */
+	subq	#1,MAP_LENGTH
+	jbeq	mmu_map_done
+
+	/* Increment mapping addresses
+	 */
+	addl	#PAGE_TABLE_SIZE*PAGESIZE,MAP_LOG
+	addl	#PAGE_TABLE_SIZE*PAGESIZE,MAP_PHYS
+
+	/* Increment pointer table offset
+	 */
+	addq	#1,%d4
+	cmpl	#PTR_TABLE_SIZE,%d4
+	jbne	mmu_030_ptr_loop
+	
+	/* We've exhausted this pointer table... get a new one
+	 */
+	jbsr	mmu_get_pointer_table
+	clrl	%d4	/* ptr table index */
+	
+	jbra	mmu_030_ptr_loop
+
+mmu_030_root_loop:
+	/* Early terminating descriptor 32M entry
+	 */
+	movel	MAP_PHYS,%a5@(%d5*4)
+
+	/* Decrement number of 32M chunks to map
+	 */
+	subl	#PTR_TABLE_SIZE,MAP_LENGTH
+	jbeq	mmu_map_done
+	cmpl	#PTR_TABLE_SIZE,MAP_LENGTH
+	jbcs	mmu_030_ptr_loop
+
+	/* Increment mapping addresses
+	 */
+	addl	#PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE,MAP_LOG
+	addl	#PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE,MAP_PHYS
+	
+	/* Increment root table offset
+	 */
+	addq	#1,%d5
+	cmpl	#ROOT_TABLE_SIZE,%d5
+	jbne	mmu_030_root_loop
+#if defined(DEBUG)
+	/* We're trying to map past 0xFFFF.FFFF
+	 */
+	moveq	#7,%d7
+	jbra	mmu_err
+#endif /* DEBUG */
+#endif /* CONFIG_M68020 || CONFIG_M68030 */
+	
+mmu_map_done:
+	moveml	%sp@+,%d0-%d7/%a0-%a5
+	rts
+
+#if defined(DEBUG)
+mmu_err:
+	movel	%d7,%d3
+	putr()
+	puts("Error: ")
+
+	movel	%d3,%d7
+	jbsr	Lserial_putnum
+
+	puts("Logical Address #0x")
+	putn(MAP_LOG)
+	putr()
+
+	puts("Physical Address #0x")
+	putn(MAP_PHYS)
+	putr()
+
+	puts("Length #0x")
+	putn(MAP_LENGTH)
+	putr()
+
+
+	puts("Cache bits #0x")
+	putn(MAP_CACHE)
+	putr()
+
+#if defined(MMU_PRINT)
+	jbsr	mmu_print
+#endif
+	
+1:
+	jbra	1b
+#endif	/* DEBUG */
+
+/*
+ *	mmu_get_page_table
+ *	
+ *	This routine will get page table from above the kernel.
+ *	What's most interesting about this routine is that it is
+ *	capable of getting up to 16 page tables out of a page of
+ *	memory.  While this is the same algorithm used by the kernel
+ *	later on, it is also what is used down here.
+ */
+mmu_get_page_table:
+	moveml	%a0-%a2/%d0-%d2,%sp@-
+
+	/* Keep track of the number of pointer tables we use
+	 */
+	lea	%pc@(Lmmu_num_page_tables),%a2
+	addql	#1,%a2@
+	
+	/* See if there is a page table in our cache of page tables
+	 */
+	lea	%pc@(SYMBOL_NAME(Lmmu_cached_page_tables)),%a2
+	movel	%a2@,%d2
+	jbne	1f
+
+	/* The first time through this algorithm, we've got to get a page
+	 */
+	movel	%a6,%d2
+	addw	#PAGESIZE,%a6	/* allocate page for 16 page tables */
+
+1:	/* There is an unused page table in our cache... use it
+	 */
+	movel	%d2,%a3
+	addil	#PAGE_TABLE_SIZE*4,%d2
+	movel	%d2,%a2@
+
+	/* Basically this is (PAGESIZE-1)-(PAGE_TABLE_SIZE*4-1), but
+	 * the two -1 can be eliminated.
+	 * The condition is true if the current page table is at the
+	 * start of the next page. */
+	andil	#PAGESIZE-PAGE_TABLE_SIZE*4,%d2
+	jbne	2f
+
+	/* Get the page table from above the kernel memory
+	 */	
+	movel	%a6,%a2@
+	addw	#PAGESIZE,%a6	/* allocate page for 16 page tables */
+	
+2:
+	lea	%pc@(SYMBOL_NAME(kpt)),%a2
+	tstl	%a2@
+	jbne	3f
+	movel	%a3,%a2@
+	
+3:	jbsr	mmu_clear_page_table
+
+	/* Log this page table (%a3) in the pointer table (%a4)
+	 */
+	movel	%a3,%d2
+	orw	#_PAGE_TABLE+_PAGE_ACCESSED,%d2
+	movel	%d2,%a4@(%d4*4)
+	
+	moveml	%sp@+,%a0-%a2/%d0-%d2
+	rts
+	
+/*
+ *	mmu_get_pointer_table
+ *	
+ *	This routine will get page table from above the kernel.
+ *	What's most interesting about this routine is that it is
+ *	capable of getting up to 8 page tables out of a page of
+ *	memory.  While this is the same algorithm used by the kernel
+ *	later on, it is also what is used down here.
+ */
+mmu_get_pointer_table:
+	moveml	%a0-%a2/%d0-%d2,%sp@-
+
+	/* Keep track of the number of pointer tables we use
+	 */
+	lea	%pc@(Lmmu_num_pointer_tables),%a2
+	addql	#1,%a2@
+	
+	/* See if there is a pointer table in our cache of pointer tables
+	 */
+	lea	%pc@(Lmmu_cached_pointer_tables),%a2
+	movel	%a2@,%d2
+	jbne	1f
+
+	/* The first time through this algorithm, we've got to get a page
+	 */
+	movel	%a6,%d2
+	addw	#PAGESIZE,%a6	/* allocate page for 8 ptr tables */
+
+1:	/* There is an unused pointer table in our cache... use it
+	 */
+	movel	%d2,%a4
+	addil	#PTR_TABLE_SIZE*4,%d2
+	movel	%d2,%a2@
+
+	/* Did we just hand out the last ptr table in the cache page?
+	 */
+	andil	#PAGESIZE-PTR_TABLE_SIZE*4,%d2
+	jbne	2f
+
+	/* Get a new cache-of-ptr-tables page from above the kernel memory
+	 */	
+	movel	%a6,%a2@
+	addw	#PAGESIZE,%a6	/* allocate page for 8 ptr tables */
+2:
+	jbsr	mmu_clear_pointer_table
+
+	/* Log this pointer table (%a4) in the root table (%a5)
+	 */
+	movel	%a4,%d2
+	orw	#_PAGE_TABLE+_PAGE_ACCESSED,%d2
+	movel	%d2,%a5@(%d5*4)
+	
+	moveml	%sp@+,%a0-%a2/%d0-%d2
+	rts
+	
+
 /*
  * Debug output support
  * Atarians have a choice between the parallel port, the serial port
  * from the MFP or a serial port of the SCC
  */
 
-#ifdef CONFIG_ATARI
+#if defined(CONFIG_MAC)
+
+scc_initable_mac:
+	.byte	9,12		/* Reset */
+	.byte	4,0x44		/* x16, 1 stopbit, no parity */
+	.byte	3,0xc0		/* receiver: 8 bpc */
+	.byte	5,0xe2		/* transmitter: 8 bpc, assert dtr/rts */
+	.byte	9,0		/* no interrupts */
+	.byte	10,0		/* NRZ */
+	.byte	11,0x50		/* use baud rate generator */
+	.byte	12,10,13,0	/* 9600 baud */
+	.byte	14,1		/* Baud rate generator enable */
+	.byte	3,0xc1		/* enable receiver */
+	.byte	5,0xea		/* enable transmitter */
+	.byte	-1
+	.even
+#endif
+
+#if defined(CONFIG_ATARI)
 /* #define USE_PRINTER */
-/* #define USE_SCC */
+/* #define USE_SCC_B */
+/* #define USE_SCC_A */
 #define USE_MFP
 
-#ifdef USE_PRINTER
+#if defined(USE_SCC_A) || defined(USE_SCC_B)
+#define USE_SCC
+/* Initialisation table for SCC */
+scc_initable:
+	.byte	9,12		/* Reset */
+	.byte	4,0x44		/* x16, 1 stopbit, no parity */
+	.byte	3,0xc0		/* receiver: 8 bpc */
+	.byte	5,0xe2		/* transmitter: 8 bpc, assert dtr/rts */
+	.byte	9,0		/* no interrupts */
+	.byte	10,0		/* NRZ */
+	.byte	11,0x50		/* use baud rate generator */
+	.byte	12,24,13,0	/* 9600 baud */
+	.byte	14,2,14,3	/* use master clock for BRG, enable */
+	.byte	3,0xc1		/* enable receiver */
+	.byte	5,0xea		/* enable transmitter */
+	.byte	-1
+	.even
+#endif
+
+#if defined(USE_PRINTER)
 
 LPSG_SELECT	= 0xff8800
 LPSG_READ	= 0xff8800
@@ -1129,10 +2803,15 @@
 LSTMFP_DDR	= 0xfffa05
 LSTMFP_IERB	= 0xfffa09
 
-#elif defined(USE_SCC)
+#elif defined(USE_SCC_B)
  
-LSCC_CTRL_B	= 0xff8c85
-LSCC_DATA_B	= 0xff8c87
+LSCC_CTRL	= 0xff8c85
+LSCC_DATA	= 0xff8c87
+
+#elif defined(USE_SCC_A)
+
+LSCC_CTRL	= 0xff8c81
+LSCC_DATA	= 0xff8c83
 
 /* Initialisation table for SCC */
 scc_initable:
@@ -1159,45 +2838,54 @@
 LMFP_UDR     = 0xfffa2f
 
 #endif
-#endif
-
-#if defined (CONFIG_BVME6000)
-BVME_SCC_CTRL_A = 0xffb0000b
-BVME_SCC_DATA_A = 0xffb0000f
-#endif
+#endif	/* CONFIG_ATARI */
 
 /*
  * Serial port output support.
  */
-LSERPER		= 0xdff032
-LSERDAT		= 0xdff030
-LSERDATR	= 0xdff018
-LSERIAL_CNTRL	= 0xbfd000
-LSERIAL_DTR	= 7
+LSERPER      = 0xdff032
+LSERDAT      = 0xdff030
+LSERDATR     = 0xdff018
+LNTSC_PERIOD = 371
+LPAL_PERIOD  = 368
+LNTSC_ECLOCK = 7159090
+LSERIAL_CNTRL = 0xbfd000
+LSERIAL_DTR   = 7
 
 /*
  * Initialize serial port hardware for 9600/8/1
- * a0 thrashed
- * Amiga d0 trashed
- * Atari d0 trashed (a1 in case of SCC)
  */
 	.even
 Lserial_init:
+	/*
+ 	 *	Some of the register usage that follows
+	 *	CONFIG_AMIGA
+	 *		a0 = pointer to boot info record
+	 *		d0 = boot info offset
+	 *	CONFIG_ATARI
+	 *		a0 = address of SCC
+	 *		a1 = Liobase address/address of scc_initable
+	 *		d0 = init data for serial port
+	 *	CONFIG_MAC
+	 *		a0 = address of SCC
+	 *		a1 = address of scc_initable_mac
+	 *		d0 = init data for serial port
+	 */
+	moveml	%a0-%a1/%d0,%sp@-
+
 #ifdef CONFIG_AMIGA
-	cmpil	#MACH_AMIGA,%d4
-	jne	1f
-	bclr	#LSERIAL_DTR,LSERIAL_CNTRL
-	movew	#BI_AMIGA_SERPER,%d0
-	jbsr	Lget_bi_record
-	movew	%a0@,LSERPER
-	jra	9f
+	is_not_amiga(1f)
+        bclr    #LSERIAL_DTR,LSERIAL_CNTRL
+        movew   #BI_AMIGA_SERPER,%d0
+        jbsr    Lget_bi_record
+        movew   %a0@,LSERPER
+        jra     9f
 1:
 #endif
-#ifdef CONFIG_ATARI
-	cmpil   #MACH_ATARI,%d4
-	jne	4f
+#if defined(CONFIG_ATARI)
+	is_not_atari(4f)
 	movel	%pc@(Liobase),%a1
-#ifdef USE_PRINTER
+#if defined(USE_PRINTER)
 	bclr	#0,%a1@(LSTMFP_IERB)
 	bclr	#0,%a1@(LSTMFP_DDR)
 	moveb	#LPSG_CONTROL,%a1@(LPSG_SELECT)
@@ -1209,7 +2897,7 @@
 	bset	#5,%d0
 	moveb	%d0,%a1@(LPSG_WRITE)
 #elif defined(USE_SCC)
-	lea	%a1@(LSCC_CTRL_B),%a0
+	lea	%a1@(LSCC_CTRL),%a0
 	lea	%pc@(scc_initable:w),%a1
 2:	moveb	%a1@+,%d0
 	jmi	3f
@@ -1225,48 +2913,70 @@
 	orb	#1,%a1@(LMFP_TDCDR)
 	bset	#1,%a1@(LMFP_TSR)
 #endif
-4:
+	jra	9f
+4:	
 #endif
+#if defined(CONFIG_MAC)
+	is_not_mac(Lserial_init_not_mac)
+#ifdef MAC_SERIAL_DEBUG
+#if !defined(MAC_USE_SCC_A) && !defined(MAC_USE_SCC_B)
+#define MAC_USE_SCC_B
+#endif
+#define mac_scc_cha_b_ctrl_offset	0x0
+#define mac_scc_cha_a_ctrl_offset	0x2
+#define mac_scc_cha_b_data_offset	0x4
+#define mac_scc_cha_a_data_offset	0x6
+
+#ifdef MAC_USE_SCC_A
+	/* Initialize channel A */
+	movel	%pc@(SYMBOL_NAME(mac_sccbase)),%a0
+	lea	%pc@(scc_initable_mac:w),%a1
+5:	moveb	%a1@+,%d0
+	jmi	6f
+	moveb	%d0,%a0@(mac_scc_cha_a_ctrl_offset)
+	moveb	%a1@+,%a0@(mac_scc_cha_a_ctrl_offset)
+	jra	5b
+6:
+#endif	/* MAC_USE_SCC_A */
+
+#ifdef MAC_USE_SCC_B
+	/* Initialize channel B */
+#ifndef MAC_USE_SCC_A	/* Load mac_sccbase only if needed */
+	movel	%pc@(SYMBOL_NAME(mac_sccbase)),%a0
+#endif	/* MAC_USE_SCC_A */
+	lea	%pc@(scc_initable_mac:w),%a1
+7:	moveb	%a1@+,%d0
+	jmi	8f
+	moveb	%d0,%a0@(mac_scc_cha_b_ctrl_offset)
+	moveb	%a1@+,%a0@(mac_scc_cha_b_ctrl_offset)
+	jra	7b
+8:
+#endif	/* MAC_USE_SCC_B */
+#endif	/* MAC_SERIAL_DEBUG */
+
+	jra	9f
+Lserial_init_not_mac:
+#endif	/* CONFIG_MAC */
+
 9:
+ 	moveml	%sp@+,%a0-%a1/%d0
 	rts
 
-#ifdef CONFIG_HP300
-/* Set LEDs to %d7 */
-	.even
-Lset_leds:
-	moveml	%a0/%a1,%sp@-
-	movel	%pc@(Lcustom),%a1
-	moveb	%d7,%a1@(0x1ffff)
-	moveml	%sp@+,%a0/%a1
-	rts
-#endif
-	
 /*
  * Output character in d7 on serial port.
  * d7 thrashed.
  */
 Lserial_putc:
+	cmpib	#'\n',%d7
+	jbne	1f
+	
+	putc(13)	/* A little safe recursion is good for the soul */
+	moveb	#'\n',%d7
+1:	
 	moveml	%a0/%a1,%sp@-
-#if defined(CONFIG_MVME16x)
-	cmpil	#MACH_MVME16x,%d4
-	jne	2f
-	moveb	%d7,%sp@-
-	.long	0x4e4f0020
-	jra	9f
-2:
-#endif
-#ifdef CONFIG_BVME6000
-	cmpil	#MACH_BVME6000,%d4
-	jne	2f
-1:	btst	#2,BVME_SCC_CTRL_A
-	jeq	1b
-	moveb	%d7,BVME_SCC_DATA_A
-	jra	9f
-2:
-#endif
-#ifdef CONFIG_AMIGA
-	cmpil	#MACH_AMIGA,%d4
-	jne	2f
+
+#if defined(CONFIG_AMIGA)
+	is_not_amiga(2f)
 	andw	#0x00ff,%d7
 	oriw	#0x0100,%d7
 	movel	%pc@(Lcustom),%a1
@@ -1274,14 +2984,45 @@
 1:	movew	%a1@(LSERDATR),%d7
 	andw	#0x2000,%d7
 	jeq	1b
-	jra	9f
+	jra	Lserial_putc_done
 2:
 #endif
-#ifdef CONFIG_ATARI
-	cmpil   #MACH_ATARI,%d4
-	jne	4f
+
+#if defined(CONFIG_MAC)
+	is_not_mac(5f)
+
+#if defined(CONSOLE)
+	jbsr	Lconsole_putc
+#endif /* CONSOLE */
+
+#if defined(MAC_SERIAL_DEBUG)
+
+#ifdef MAC_USE_SCC_A
+	movel	%pc@(SYMBOL_NAME(mac_sccbase)),%a1
+3:	btst	#2,%a1@(mac_scc_cha_a_ctrl_offset)
+	jeq	3b
+	moveb	%d7,%a1@(mac_scc_cha_a_data_offset)
+#endif	/* MAC_USE_SCC_A */
+
+#ifdef MAC_USE_SCC_B
+#ifndef MAC_USE_SCC_A	/* Load mac_sccbase only if needed */
+	movel	%pc@(SYMBOL_NAME(mac_sccbase)),%a1
+#endif	/* MAC_USE_SCC_A */
+4:	btst	#2,%a1@(mac_scc_cha_b_ctrl_offset)
+	jeq	4b
+	moveb	%d7,%a1@(mac_scc_cha_b_data_offset)
+#endif	/* MAC_USE_SCC_B */
+
+#endif	/* MAC_SERIAL_DEBUG */
+
+	jra	Lserial_putc_done
+5:	
+#endif	/* CONFIG_MAC */
+
+#if defined(CONFIG_ATARI)
+	is_not_atari(4f)
 	movel	%pc@(Liobase),%a1
-#ifdef USE_PRINTER
+#if defined(USE_PRINTER)
 3:	btst	#0,%a1@(LSTMFP_GPIP)
 	jne	3b
 	moveb	#LPSG_IO_B,%a1@(LPSG_SELECT)
@@ -1295,17 +3036,45 @@
 	bset	#5,%d7
 	moveb	%d7,%a1@(LPSG_WRITE)
 #elif defined(USE_SCC)
-3:	btst	#2,%a1@(LSCC_CTRL_B)
+3:	btst	#2,%a1@(LSCC_CTRL)
 	jeq	3b
-	moveb	%d7,%a1@(LSCC_DATA_B)
+	moveb	%d7,%a1@(LSCC_DATA)
 #elif defined(USE_MFP)
 3:	btst	#7,%a1@(LMFP_TSR)
 	jeq	3b
 	moveb	%d7,%a1@(LMFP_UDR)
 #endif
+	jra	Lserial_putc_done
 4:
+#endif	/* CONFIG_ATARI */
+
+#if defined(CONFIG_MVME16x)
+	is_not_mvme16x(2f)
+	/*
+	 * The VME 16x class has PROM support for serial output
+	 * of some kind;  the TRAP table is still valid.
+	 */
+	moveml	%d0-%d7/%a2-%a6,%sp@-
+	moveb	%d7,%sp@-
+	.long	0x4e4f0020	/* TRAP 0x020 */
+	moveml	%sp@+,%d0-%d7/%a2-%a6
+	jbra	Lserial_putc_done
+2:
+#endif CONFIG_MVME162 | CONFIG_MVME167
+
+#if defined(CONFIG_BVME6000)
+	is_not_bvme6000(2f)
+	/*
+	 * The BVME6000 machine has a serial port ...
+	 */
+1:	btst	#2,BVME_SCC_CTRL_A
+	jeq	1b
+	moveb	%d7,BVME_SCC_DATA_A
+	jbra	Lserial_putc_done
+2:	
 #endif
-9:
+
+Lserial_putc_done:
 	moveml	%sp@+,%a0/%a1
 	rts
 
@@ -1346,28 +3115,557 @@
 	moveml	%sp@+,%d0-%d2/%d7
 	rts
 
+#if defined(CONFIG_MAC)
+/*
+ *	mac_serial_print
+ *
+ *	This routine takes its parameters on the stack.  It then
+ *	turns around and calls the internal routine.  This routine
+ *	is used until the Linux console driver initializes itself.
+ *
+ *	The calling parameters are:
+ *		void mac_serial_print(const char *str);
+ *
+ *	This routine does NOT understand variable arguments only
+ *	simple strings!
+ */
+ENTRY(mac_serial_print)
+	movel	%a0,%sp@-
+#if 1
+	move	%sr,%sp@-
+	ori	#0x0700,%sr
+#endif
+	movel	%sp@(10),%a0		/* fetch parameter */
+	jbsr	Lserial_puts
+#if 1
+	move	%sp@+,%sr
+#endif
+	movel	%sp@+,%a0
+	rts
+#endif /* CONFIG_MAC */
+
+#if defined(CONSOLE)
+/*
+ *	For continuity, see the data alignment
+ *	to which this structure is tied.
+ */
+#define Lconsole_struct_cur_column	0
+#define Lconsole_struct_cur_row		4
+#define Lconsole_struct_num_columns	8
+#define Lconsole_struct_num_rows	12
+#define Lconsole_struct_left_edge	16
+#define Lconsole_struct_penguin_putc	20
+
+Lconsole_init:
+	/*
+ 	 *	Some of the register usage that follows
+	 *		a0 = pointer to boot_info
+	 *		a1 = pointer to screen
+	 *		a2 = pointer to Lconsole_globals
+	 *		d3 = pixel width of screen
+	 *		d4 = pixel height of screen
+	 *		(d3,d4) ~= (x,y) of a point just below
+	 *			and to the right of the screen
+	 *			NOT on the screen!
+	 *		d5 = number of bytes per scan line
+	 *		d6 = number of bytes on the entire screen
+	 */
+	moveml	%a0-%a4/%d0-%d7,%sp@-
+	
+	lea	%pc@(SYMBOL_NAME(Lconsole_globals)),%a2
+	lea	%pc@(SYMBOL_NAME(mac_videobase)),%a0
+	movel	%a0@,%a1
+	lea	%pc@(SYMBOL_NAME(mac_rowbytes)),%a0
+	movel	%a0@,%d5
+	lea	%pc@(SYMBOL_NAME(mac_dimensions)),%a0
+	movel	%a0@,%d3	/* -> low byte */
+	movel	%d3,%d4
+	swap	%d4		/* -> high byte */
+	andl	#0xffff,%d3	/* d3 = screen width in pixels */
+	andl	#0xffff,%d4	/* d4 = screen height in pixels */
+
+	movel	%d5,%d6
+	subl	#20,%d6
+	mulul	%d4,%d6		/* scan line bytes x num scan lines */
+	divul	#8,%d6		/* we'll clear 8 bytes at a time */
+	subq	#1,%d6
+	
+console_clear_loop:
+	movel	#0xffffffff,%a1@+	/* Mac_black */
+	movel	#0xffffffff,%a1@+	/* Mac_black */
+	dbra	%d6,console_clear_loop
+
+	/* Calculate font size */
+
+#if   defined(FONT_8x8)
+	lea	%pc@(SYMBOL_NAME(font_vga_8x8)), %a0
+#elif defined(FONT_8x16)
+	lea	%pc@(SYMBOL_NAME(font_vga_8x16)),%a0
+#elif defined(FONT_6x11)
+	lea	%pc@(SYMBOL_NAME(font_vga_6x11)),%a0
+#else	/*   (FONT_8x8) default */
+	lea	%pc@(SYMBOL_NAME(font_vga_8x8)), %a0
+#endif
+
+	/*
+	 *	At this point we make a shift in register usage
+	 *	a1 = address of Lconsole_font pointer
+	 */
+	lea	%pc@(SYMBOL_NAME(Lconsole_font)),%a1
+	movel	%a0,%a1@	/* store pointer to struct fbcon_font_desc in Lconsole_font */
+
+	/*
+	 *	Calculate global maxs
+	 *	Note - we can use either an 
+	 *	8 x 16 or 8 x 8 character font
+	 *	6 x 11 also supported
+	 */
+		/* ASSERT: a0 = contents of Lconsole_font */
+	movel	%d3,%d0			/* screen width in pixels */
+	divul	%a0@(FBCON_FONT_DESC_width),%d0		/* d0 = max num chars per row */
+
+	movel	%d4,%d1			 /* screen height in pixels */
+	divul	%a0@(FBCON_FONT_DESC_height),%d1	 /* d1 = max num rows */
+
+	movel	%d0,%a2@(Lconsole_struct_num_columns)
+	movel	%d1,%a2@(Lconsole_struct_num_rows)
+
+	/*
+	 *	Clear the current row and column
+	 */
+	clrl	%a2@(Lconsole_struct_cur_column)
+	clrl	%a2@(Lconsole_struct_cur_row)
+	clrl	%a2@(Lconsole_struct_left_edge)
+
+	/*
+	 * Initialization is complete
+	 */
+	moveml	%sp@+,%a0-%a4/%d0-%d7
+	rts
+
+Lconsole_put_stats:
+	/*
+ 	 *	Some of the register usage that follows
+	 *		a0 = pointer to boot_info
+	 *		d7 = value of boot_info fields
+	 */
+	moveml	%a0/%d7,%sp@-
+
+	putr()
+	puts("MacLinux")
+	putr()
+	putr()
+
+#if defined(SERIAL_DEBUG)
+	puts(" vidaddr:")
+	lea	%pc@(SYMBOL_NAME(mac_videobase)),%a0
+	movel	%a0@,%d7			/* video addr. */
+	jbsr	Lserial_putnum			/* This redirects to console */
+	putr()
+
+	puts("  _stext:")
+	lea	%pc@(SYMBOL_NAME(_stext)),%a0
+	movel	%a0,%d7		/* get start addr. */
+	jbsr	Lserial_putnum
+	putr()
+
+	puts("bootinfo:")	
+	lea	%pc@(SYMBOL_NAME(_end)),%a0
+	movel	%a0, %d7	/* write start addr. */
+	jbsr	Lserial_putnum
+	putr()
+
+	puts("     kpt:")
+	lea	%pc@(SYMBOL_NAME(kpt)),%a0
+	movel	%a0,%d7		/* get start addr. */
+	jbsr	Lserial_putnum
+	putr()
+
+	puts("    *kpt:")
+	lea	%pc@(SYMBOL_NAME(kpt)),%a0
+	movel	%a0@,%d7	/* get start addr. */
+	jbsr	Lserial_putnum
+	putr()
+
+	puts("cpuid:")
+	lea	%pc@(SYMBOL_NAME(Lcputype)),%a0
+	movel	%a0@,%d7
+	jbsr	Lserial_putnum
+	putr()
+
+#  if defined(MMU_PRINT)
+	jbsr	mmu_print_machine_cpu_types
+#  endif /* MMU_PRINT */
+#endif /* SERIAL_DEBUG */
+	
+	moveml	%sp@+,%a0/%d7
+	rts
+
+#ifdef CONSOLE_PENGUIN
+Lconsole_put_penguin:
+	/*
+	 *	Get 'that_penguin' onto the screen in the upper right corner
+	 *	penguin is 64 x 74 pixels, align against right edge of screen
+	 */
+	moveml	%a0-%a1/%d0-%d7,%sp@-
+
+	lea	%pc@(SYMBOL_NAME(mac_dimensions)),%a0
+	movel	%a0@,%d0
+	andil	#0xffff,%d0
+	subil	#64,%d0		/* snug up against the right edge */
+	clrl	%d1		/* start at the top */
+	movel	#73,%d7
+	lea	%pc@(SYMBOL_NAME(that_penguin)),%a1
+console_penguin_row:
+	movel	#31,%d6
+console_penguin_pixel_pair:
+	moveb	%a1@,%d2
+	lsrb	#4,%d2
+	jbsr	console_plot_pixel
+	addq	#1,%d0
+	moveb	%a1@+,%d2
+	jbsr	console_plot_pixel
+	addq	#1,%d0
+	dbra	%d6,console_penguin_pixel_pair
+
+	subil	#64,%d0
+	addq	#1,%d1
+	dbra	%d7,console_penguin_row
+
+	moveml	%sp@+,%a0-%a1/%d0-%d7
+	rts
+#endif
+
+console_scroll:
+	moveml	%a0-%a4/%d0-%d7,%sp@-
+
+	/*
+	 * Calculate source and destination addresses
+	 *	output	a1 = dest
+	 *		a2 = source
+	 */	
+	lea	%pc@(SYMBOL_NAME(mac_videobase)),%a0
+	movel	%a0@,%a1
+	movel	%a1,%a2
+	lea	%pc@(SYMBOL_NAME(mac_rowbytes)),%a0
+	movel	%a0@,%d5
+	movel	%pc@(SYMBOL_NAME(Lconsole_font)),%a0
+	mulul	%a0@(FBCON_FONT_DESC_height),%d5	/* account for # scan lines per character */
+	addal	%d5,%a2
+
+	/*
+	 * Get dimensions
+	 */
+	lea	%pc@(SYMBOL_NAME(mac_dimensions)),%a0
+	movel	%a0@,%d3
+	movel	%d3,%d4
+	swap	%d4
+	andl	#0xffff,%d3	/* d3 = screen width in pixels */
+	andl	#0xffff,%d4	/* d4 = screen height in pixels */
+
+	/*
+	 * Calculate number of bytes to move
+	 */
+	lea	%pc@(SYMBOL_NAME(mac_rowbytes)),%a0
+	movel	%a0@,%d6
+	movel	%pc@(SYMBOL_NAME(Lconsole_font)),%a0
+	subl	%a0@(FBCON_FONT_DESC_height),%d4	/* we're not scrolling the top row! */
+	mulul	%d4,%d6		/* scan line bytes x num scan lines */
+	divul	#32,%d6		/* we'll move 8 longs at a time */
+	subq	#1,%d6
+	
+console_scroll_loop:
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	dbra	%d6,console_scroll_loop
+
+	lea	%pc@(SYMBOL_NAME(mac_rowbytes)),%a0
+	movel	%a0@,%d6
+	movel	%pc@(SYMBOL_NAME(Lconsole_font)),%a0
+	mulul	%a0@(FBCON_FONT_DESC_height),%d6	/* scan line bytes x font height */
+	divul	#32,%d6			/* we'll move 8 words at a time */
+	subq	#1,%d6
+
+	moveq	#-1,%d0
+console_scroll_clear_loop:
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	dbra	%d6,console_scroll_clear_loop
+	
+	moveml	%sp@+,%a0-%a4/%d0-%d7
+	rts
+	
+
+	
+Lconsole_putc:	
+/*
+ * Output character in d7 on console.
+ */
+	moveml	%a0/%a1/%d0-%d7,%sp@-
+	
+	lea	%pc@(Lconsole_globals),%a0
+
+	cmpib	#10,%d7
+	jne	console_not_lf
+	movel	%a0@(Lconsole_struct_cur_row),%d0
+	addil	#1,%d0
+	movel	%d0,%a0@(Lconsole_struct_cur_row)
+	movel	%a0@(Lconsole_struct_num_rows),%d1
+	cmpl	%d1,%d0
+	jcs	1f
+	subil	#1,%d0
+	movel	%d0,%a0@(Lconsole_struct_cur_row)
+	jbsr	console_scroll
+1:
+	jra	console_exit
+	
+console_not_lf:
+	cmpib	#13,%d7
+	jne	console_not_cr
+	clrl	%a0@(Lconsole_struct_cur_column)
+	jra	console_exit
+
+console_not_cr:
+	cmpib	#1,%d7
+	jne	console_not_home
+	clrl	%a0@(Lconsole_struct_cur_row)
+	clrl	%a0@(Lconsole_struct_cur_column)
+	jra	console_exit
+	
+/*
+ *	At this point we know that the %d7 character is going to be
+ *	rendered on the screen.  Register usage is -
+ *		a0 = pointer to console globals
+ *		a1 = font data
+ *		d0 = cursor column
+ *		d1 = cursor row to draw the character
+ *		d7 = character number
+ */
+console_not_home:
+	movel	%a0@(Lconsole_struct_cur_column),%d0
+	addil	#1,%a0@(Lconsole_struct_cur_column)
+	movel	%a0@(Lconsole_struct_num_columns),%d1	
+	cmpl	%d1,%d0
+	jcs	1f
+	movel	%d7,%sp@-
+	putr()		/* recursion is OK! */
+	movel	%sp@+,%d7
+1:	
+	movel	%a0@(Lconsole_struct_cur_row),%d1
+	
+	/*
+	 *	At this point we make a shift in register usage
+ 	 *	a0 = address of pointer to font data (fbcon_font_desc)
+	 */
+	movel	%pc@(SYMBOL_NAME(Lconsole_font)),%a0
+	movel	%a0@(FBCON_FONT_DESC_data),%a1	/* Load fbcon_font_desc.data into a1 */
+	andl	#0x000000ff,%d7
+		/* ASSERT: a0 = contents of Lconsole_font */
+	mulul	%a0@(FBCON_FONT_DESC_height),%d7	/* d7 = index into font data */
+	addl	%d7,%a1			/* a1 = points to char image */
+	
+	/*
+	 *	At this point we make a shift in register usage
+	 *	d0 = pixel coordinate, x
+	 *	d1 = pixel coordinate, y
+	 *	d2 = (bit 0) 1/0 for white/black (!) pixel on screen
+	 *	d3 = font scan line data (8 pixels)
+	 *	d6 = count down for the font's pixel width (8)
+	 *	d7 = count down for the font's pixel count in height
+	 */
+		/* ASSERT: a0 = contents of Lconsole_font */
+	mulul	%a0@(FBCON_FONT_DESC_width),%d0
+	mulul	%a0@(FBCON_FONT_DESC_height),%d1
+	movel	%a0@(FBCON_FONT_DESC_height),%d7	/* Load fbcon_font_desc.height into d7 */
+	subq	#1,%d7
+console_read_char_scanline:
+	moveb	%a1@+,%d3
+
+		/* ASSERT: a0 = contents of Lconsole_font */
+	movel	%a0@(FBCON_FONT_DESC_width),%d6	/* Load fbcon_font_desc.width into d6 */
+	subql	#1,%d6
+
+console_do_font_scanline:
+	lslb	#1,%d3
+	scsb	%d2		/* convert 1 bit into a byte */
+	jbsr	console_plot_pixel
+	addq	#1,%d0
+	dbra	%d6,console_do_font_scanline
+	
+		/* ASSERT: a0 = contents of Lconsole_font */
+	subl	%a0@(FBCON_FONT_DESC_width),%d0
+	addq	#1,%d1
+	dbra	%d7,console_read_char_scanline
+	
+console_exit:		
+	moveml	%sp@+,%a0/%a1/%d0-%d7
+	rts
+
+console_plot_pixel:
+	/*
+	 *	Input:
+	 *		d0 = x coordinate
+	 *		d1 = y coordinate
+	 *		d2 = (bit 0) 1/0 for white/black (!)
+	 *	All registers are preserved
+	 */
+	moveml	%a0-%a1/%d0-%d4,%sp@-
+	
+	lea	%pc@(SYMBOL_NAME(mac_videobase)),%a0
+	movel	%a0@,%a1
+	lea	%pc@(SYMBOL_NAME(mac_videodepth)),%a0
+	movel	%a0@,%d3
+	lea	%pc@(SYMBOL_NAME(mac_rowbytes)),%a0
+	mulul	%a0@,%d1
+
+	/*
+	 *	Register usage:
+	 *		d0 = x coord becomes byte offset into frame buffer
+	 *		d1 = y coord
+	 *		d2 = black or white (0/1)
+	 *		d3 = video depth
+	 *		d4 = temp of x (d0) for many bit depths
+	 *		d5 = unused
+	 *		d6 = unused
+	 *		d7 = unused
+	 */
+test_1bit:
+	cmpb	#1,%d3
+	jbne	test_2bit
+	movel	%d0,%d4		/* we need the low order 3 bits! */
+	divul	#8,%d0
+	addal	%d0,%a1
+	addal	%d1,%a1
+	andb	#7,%d4
+	eorb	#7,%d4		/* reverse the x-coordinate w/ screen-bit # */
+	andb	#1,%d2
+	jbne	white_1
+	bsetb	%d4,%a1@
+	jbra	console_plot_pixel_exit
+white_1:
+	bclrb	%d4,%a1@
+	jbra	console_plot_pixel_exit
+
+test_2bit:
+	cmpb	#2,%d3
+	jbne	test_4bit
+	movel	%d0,%d4		/* we need the low order 2 bits! */
+	divul	#4,%d0
+	addal	%d0,%a1
+	addal	%d1,%a1
+	andb	#3,%d4
+	eorb	#3,%d4		/* reverse the x-coordinate w/ screen-bit # */
+	lsll	#1,%d4		/* ! */
+	andb	#1,%d2
+	jbne	white_2
+	bsetb	%d4,%a1@
+	addq	#1,%d4
+	bsetb	%d4,%a1@
+	jbra	console_plot_pixel_exit
+white_2:
+	bclrb	%d4,%a1@
+	addq	#1,%d4
+	bclrb	%d4,%a1@
+	jbra	console_plot_pixel_exit
+
+test_4bit:
+	cmpb	#4,%d3
+	jbne	test_8bit
+	movel	%d0,%d4		/* we need the low order bit! */
+	divul	#2,%d0
+	addal	%d0,%a1
+	addal	%d1,%a1
+	andb	#1,%d4
+	eorb	#1,%d4
+	lsll	#2,%d4		/* ! */
+	andb	#1,%d2
+	jbne	white_4
+	bsetb	%d4,%a1@
+	addq	#1,%d4
+	bsetb	%d4,%a1@
+	addq	#1,%d4
+	bsetb	%d4,%a1@
+	addq	#1,%d4
+	bsetb	%d4,%a1@
+	jbra	console_plot_pixel_exit
+white_4:
+	bclrb	%d4,%a1@
+	addq	#1,%d4
+	bclrb	%d4,%a1@
+	addq	#1,%d4
+	bclrb	%d4,%a1@
+	addq	#1,%d4
+	bclrb	%d4,%a1@
+	jbra	console_plot_pixel_exit
+
+test_8bit:
+	cmpb	#8,%d3
+	jbne	test_16bit
+	addal	%d0,%a1
+	addal	%d1,%a1
+	andb	#1,%d2
+	jbne	white_8
+	moveb	#0xff,%a1@
+	jbra	console_plot_pixel_exit
+white_8:
+	clrb	%a1@
+	jbra	console_plot_pixel_exit
+
+test_16bit:
+	cmpb	#16,%d3
+	jbne	console_plot_pixel_exit
+	addal	%d0,%a1
+	addal	%d0,%a1
+	addal	%d1,%a1
+	andb	#1,%d2
+	jbne	white_16
+	clrw	%a1@
+	jbra	console_plot_pixel_exit
+white_16:
+	movew	#0x0fff,%a1@
+	jbra	console_plot_pixel_exit
+
+console_plot_pixel_exit:
+	moveml	%sp@+,%a0-%a1/%d0-%d4
+	rts
+#endif /* CONSOLE */
+
 #if 0
+/*
+ * This is some old code lying around.  I don't believe
+ * it's used or important anymore.  My guess is it contributed
+ * to getting to this point, but it's done for now.
+ * It was still in the 2.1.77 head.S, so it's still here.
+ * (And still not used!)
+ */
 Lshowtest:
 	moveml	%a0/%d7,%sp@-
-	putc('A')
-	putc('=')
+	puts("A=")
 	putn(%a1)
 
-	ptestr	#5,%a1@,#7,%a0
+	.long	0xf0119f15		| ptestr	#5,%a1@,#7,%a0
 
-	putc('D')
-	putc('A')
-	putc('=')
+	puts("DA=")
 	putn(%a0)
 
-	putc('D')
-	putc('=')
+	puts("D=")
 	putn(%a0@)
 
-	putc('S')
-	putc('=')
+	puts("S=")
 	lea	%pc@(Lmmu),%a0
-	pmove	%psr,%a0@
+	.long	0xf0106200		| pmove		%psr,%a0@
 	clrl	%d7
 	movew	%a0@,%d7
 	jbsr	Lserial_putnum
@@ -1375,13 +3673,92 @@
 	putr()
 	moveml	%sp@+,%a0/%d7
 	rts
-#endif
+#endif	/* 0 */
+	
 	.data
-	.even
+	.align	4
+	
+#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA)
 Lcustom:
 Liobase:
 	.long 0
-Lmmu:	.quad 0
+#endif
+
+#if defined(CONFIG_M68020) || defined(CONFIG_M68030)
+Lmmu:
+	.quad 0
+#endif
+
+#ifdef CONFIG_MAC
+Lconsole_video_virtual:
+	.long	0
+#endif	/* CONFIG_MAC */
+
+#if defined(CONSOLE)
+Lconsole_globals:
+	.long	0		/* cursor column */
+	.long	0		/* cursor row */
+	.long	0		/* max num columns */
+	.long	0		/* max num rows */
+	.long	0		/* left edge */
+	.long	0		/* mac putc */
+Lconsole_font:
+	.long	0		/* pointer to console font (struct fbcon_font_desc) */
+#endif /* CONSOLE */
+
+#if defined(MMU_PRINT)
+Lmmu_print_data:
+	.long	0		/* valid flag */
+	.long	0		/* start logical */
+	.long	0		/* next logical */
+	.long	0		/* start physical */
+	.long	0		/* next physical */
+#endif /* MMU_PRINT */
+
+Lcputype:
+	.long	0
+
+Lmmu_cached_page_tables:
+	.long	0
+
+Lmmu_cached_pointer_tables:
+	.long	0
+
+Lmmu_num_page_tables:
+	.long	0
+
+Lmmu_num_pointer_tables:
+	.long	0
+
+#if defined (CONFIG_BVME6000)
+BVME_SCC_CTRL_A	= 0xffb0000b
+BVME_SCC_DATA_A	= 0xffb0000f
+#endif
+
+#if 0
+#if defined(CONFIG_ATARI)
+SYMBOL_NAME_LABEL(atari_mch_type)
+	 .long 0
+#endif
+#endif
+
+#if defined(CONFIG_MAC)
+SYMBOL_NAME_LABEL(mac_booter_data)
+       .long 0
+SYMBOL_NAME_LABEL(mac_videobase)
+       .long 0
+SYMBOL_NAME_LABEL(mac_videodepth)
+       .long 0
+SYMBOL_NAME_LABEL(mac_dimensions)
+       .long 0
+SYMBOL_NAME_LABEL(mac_rowbytes)
+       .long 0
+#ifdef MAC_SERIAL_DEBUG
+SYMBOL_NAME_LABEL(mac_sccbase)
+       .long 0
+#endif /* MAC_SERIAL_DEBUG */
+#endif
+
 SYMBOL_NAME_LABEL(kpt)
 	.long 0
 SYMBOL_NAME_LABEL(availmem)
--- linux-2.1.130/arch/m68k/mac/debug.c.org	Tue Dec  1 00:25:58 1998
+++ linux-2.1.130/arch/m68k/mac/debug.c	Tue Dec  1 01:41:10 1998
@@ -36,6 +36,9 @@
 extern unsigned long mac_videodepth;
 extern unsigned long mac_rowbytes;
 
+extern void mac_serial_print(char *);
+
+#define DEBUG_HEADS
 #define DEBUG_SCREEN
 #define DEBUG_SERIAL
 
@@ -129,121 +132,6 @@
 #endif
 }
 
-/*
- * Penguin - used by head.S console; obsolete
- */
-char that_penguin[]={
-#include "that_penguin.h"
-};
-
-#ifdef DEBUG_SCREEN
-/* 
- * B/W version of penguin, unfinished - any takers??
- */
-static char bw_penguin[]={
-#include "bw_penguin.h"
-};
-#endif
-
-void mac_debugging_penguin(int peng)
-{
-#ifdef DEBUG_SCREEN
-	unsigned char *pengoffset;
-	unsigned char *pptr;
-	unsigned char *bwpdptr=bw_penguin;
-	int i;
-#endif
-
-#ifdef DEBUG_SERIAL
-	printk("Penguin: #%d !\n", peng);
-#endif
-
-#ifdef DEBUG_SCREEN
-	if (!MACH_IS_MAC) 
-		return;
-
-	if (mac_videodepth ==1) 
-		pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes)
-			   +5*peng;
-	else
-		pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes)
-			   +20*peng;
-	
-	pptr=pengoffset;
-	
-	for(i=0;i<36;i++)
-	{
-		memcpy(pptr,bwpdptr,4);
-		bwpdptr+=4;
-		pptr+=mac_rowbytes;
-	}
-#endif
-}
-
-#ifdef DEBUG_SCREEN
-/*
- * B/W version of flaming Mac, unfinished (see above).
- */
-static char bw_kaboom_map[]={
-#include "bw_mac.h"
-};
-#endif
-
-#ifdef DEBUG_SCREEN
-static void mac_boom_boom(void)
-{
-	static unsigned char *boomoffset=NULL;
-	unsigned char *pptr;
-	unsigned char *bwpdptr=bw_kaboom_map;
-	int i;
-	
-#ifdef DEBUG_SERIAL
-	printk("BOOM !\n");
-#endif
-
-	if (!MACH_IS_MAC) 
-		return;
-
-	if(!boomoffset)
-		if (mac_videodepth == 1) {
-			boomoffset=(unsigned char *)(mac_videobase+160*mac_rowbytes);
-		} else {
-			boomoffset=(unsigned char *)(mac_videobase+256*mac_rowbytes);
-		}
-	else
-		if (mac_videodepth == 1)
-			boomoffset+=5;
-		else
-			boomoffset+=32;	
-
-	pptr=boomoffset;
-	
-	for(i=0;i<36;i++)
-	{
-		memcpy(pptr,bwpdptr,4);
-		bwpdptr+=4;
-		pptr+=mac_rowbytes;
-	}
-}
-#endif
-
-void mac_boom(int booms)
-{
-#ifdef DEBUG_SCREEN
-	int i;
-#endif
-
-	if (!MACH_IS_MAC) 
-		return;
-
-#ifdef DEBUG_SCREEN
-	for(i=0;i<booms;i++)
-		mac_boom_boom();
-	while(1);
-#endif
-}
-
-
 #ifdef DEBUG_SERIAL
 /*
  * TODO: serial debug code
@@ -284,6 +172,29 @@
 	NULL
 };
 
+/*
+ * Crude hack to get console output to the screen before the framebuffer
+ * is initialized (happens a lot later in 2.1!).
+ * We just use the console routines declared in head.S, this will interfere
+ * with regular framebuffer console output and should be used exclusively
+ * to debug kernel problems manifesting before framebuffer init (aka WSOD)
+ *
+ * To keep this hack from interfering with the regular console driver, either
+ * deregister this driver before/on framebuffer console init, or silence this
+ * function after the fbcon driver is running (will lose console messages!?).
+ * To debug real early bugs, need to write a 'mac_register_console_hack()'
+ * that is called from start_kernel() before setup_arch() and just registers
+ * this driver if Mac.
+ */
+
+void mac_debug_console_write (struct console *co, const char *str,
+			      unsigned int count)
+{
+	mac_serial_print(str);
+}
+
+
+
 /* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/
 
 #define uSEC 1
@@ -500,9 +411,16 @@
 #endif
 	scc_port = 1;
     }
+#endif
+#ifdef DEBUG_HEADS
+    if (   !strcmp( m68k_debug_device, "scn"  )
+        || !strcmp( m68k_debug_device, "con" )) {
+	/* display, using head.S console routines */
+	mac_console_driver.write = mac_debug_console_write;
+    }
+#endif
     if (mac_console_driver.write)
 	register_console(&mac_console_driver);
-#endif
 }
 
 /*
--- linux-2.1.130/arch/m68k/mac/mackeyb.c.org	Sat Nov 28 18:30:02 1998
+++ linux-2.1.130/arch/m68k/mac/mackeyb.c	Sat Nov 28 18:58:53 1998
@@ -1,5 +1,12 @@
 /*
- *  linux/arch/m68k/mac/mackeyb.c
+ * linux/arch/m68k/mac/mackeyb.c
+ *
+ * Keyboard driver for Macintosh computers.
+ *
+ * Adapted from drivers/macintosh/key_mac.c and arch/m68k/atari/akakeyb.c 
+ * (see that file for its authors and contributors).
+ *
+ * Copyright (C) 1997 Michael Schmitz.
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
@@ -59,8 +66,15 @@
 static void mac_leds_done(struct adb_request *);
 static void keyboard_input(unsigned char *, int, struct pt_regs *);
 static void mouse_input(unsigned char *, int, struct pt_regs *);
-/* Hook for mouse driver */
-void (*adb_mouse_interrupt_hook) (char *, int);
+
+#ifdef CONFIG_ADBMOUSE
+/* XXX: Hook for mouse driver */
+void (*adb_mouse_interrupt_hook)(unsigned char *, int);
+int adb_emulate_buttons = 0;
+int adb_button2_keycode = 0x7d;	/* right control key */
+int adb_button3_keycode = 0x7c; /* right option key */
+#endif
+
 /* The mouse driver - for debugging */
 extern void adb_mouse_interrupt(char *, int);
 /* end keyb */
@@ -275,9 +289,11 @@
  	kbd = kbd_table + fg_console;
 	up_flag = (keycode & 0x80);
         keycode &= 0x7f;
+
 	if (!repeat)
 		del_timer(&repeat_timer);
 
+#ifdef CONFIG_ADBMOUSE
 	/*
 	 * XXX: Add mouse button 2+3 fake codes here if mouse open.
 	 *	As we only report up/down events, keep track of faked buttons.
@@ -289,7 +305,8 @@
 	 *	(wanted: command and alt/option, or KP= and KP( ...)
 	 *	Debug version; might be rewritten to be faster on normal keys.
 	 */
-	if (adb_mouse_interrupt_hook || console_loglevel >= 8) {
+	if (adb_emulate_buttons 
+	    && (adb_mouse_interrupt_hook || console_loglevel >= 8)) {
 		unsigned char button, button2, button3, fake_event;
 		static unsigned char button2state=0, button3state=0; /* up */
 		/* faked ADB packet */
@@ -297,21 +314,20 @@
 
 		button = 0;
 		fake_event = 0;
-		switch (keycode) {	/* which 'button' ? */
-			case 0x7c:	/* R-option */
-				button2 = (!up_flag);		/* new state */
-				if (button2 != button2state)	/* change ? */
-					button = 2; 
-				button2state = button2;		/* save state */
-				fake_event = 2;
-				break; 
-			case 0x7d:	/* R-control */
-				button3 = (!up_flag);		/* new state */
-				if (button3 != button3state)	/* change ? */ 
-					button = 3; 
-				button3state = button3; 	/* save state */
-				fake_event = 3;
-				break; 
+		if (keycode == adb_button2_keycode) {	/* which 'button' ? */
+			/* R-option */
+			button2 = (!up_flag);		/* new state */
+			if (button2 != button2state)	/* change ? */
+				button = 2; 
+			button2state = button2;		/* save state */
+			fake_event = 2;
+		} else if (keycode == adb_button3_keycode) {
+			/* R-control */
+			button3 = (!up_flag);		/* new state */
+			if (button3 != button3state)	/* change ? */ 
+				button = 3; 
+			button3state = button3; 	/* save state */
+			fake_event = 3;
 		}
 #ifdef DEBUG_ADBMOUSE
 		if (fake_event && console_loglevel >= 8)
@@ -340,6 +356,7 @@
 		if (fake_event)
 			return;
 	}
+#endif /* CONFIG_ADBMOUSE */
 
 	/*
 	 * Convert R-shift/control/option to L version.
@@ -365,16 +382,18 @@
 		 * transition into a key-down transition.
 		 * MSch: need to turn each caps-lock event into a down-up
 		 * double event (keyboard code assumes caps-lock is a toggle)
+		 * 981127: fix LED behavior (kudos atong!)
 		 */
-#if 0
-		if (keycode == 0x39 && up_flag && vc_kbd_led(kbd, VC_CAPSLOCK))
-			up_flag = 0;
-#else
-		if (keycode == 0x39) {
+		switch (keycode) {
+		case 0x39:
 			handle_scancode(keycode);	/* down */
 			up_flag = 0x80;			/* see below ... */
+		 	mark_bh(KEYBOARD_BH);
+			break;
+		 case 0x47:
+		 	mark_bh(KEYBOARD_BH);
+		 	break;
 		}
-#endif
 	}
 
 	handle_scancode(keycode + up_flag);
--- linux-2.1.130/arch/m68k/mac/config.c.org	Tue Dec  1 00:21:40 1998
+++ linux-2.1.130/arch/m68k/mac/config.c	Tue Dec  1 01:28:25 1998
@@ -100,17 +100,15 @@
 extern void mac_debugging_long(int, long);
 
 #ifdef CONFIG_MAGIC_SYSRQ
-
-/* XXX FIXME: Atari scancodes still */
 static char mac_sysrq_xlate[128] =
-	"\000\0331234567890-=\177\t"				/* 0x00 - 0x0f */
-	"qwertyuiop[]\r\000as"					/* 0x10 - 0x1f */
-	"dfghjkl;'`\000\\zxcv"					/* 0x20 - 0x2f */
-	"bnm,./\000\000\000 \000\201\202\203\204\205"		/* 0x30 - 0x3f */
-	"\206\207\210\211\212\000\000\000\000\000-\000\000\000+\000"/* 0x40 - 0x4f */
-	"\000\000\000\177\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
-	"\000\000\000()/*789456123"				/* 0x60 - 0x6f */
-	"0.\r\000\000\000\000\000\000\000\000\000\000\000\000\000";	/* 0x70 - 0x7f */
+	"\000sdfghzxcv\000bqwer"				/* 0x00 - 0x0f */
+	"yt123465=97-80)o"					/* 0x10 - 0x1f */
+	"u(ip\rlj'k;\\,/nm."					/* 0x20 - 0x2f */
+	"\t `\000\033\000\000\000\000\000\000\000\000\000\000\000"	/* 0x30 - 0x3f */
+	"\000.\000*\000+\000\000\000\000\000/\r\000-\000"	/* 0x40 - 0x4f */
+	"\000\00001234567a89\000\000\000"			/* 0x50 - 0x5f */
+	"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"  /* 0x60 - 0x6f */
+	"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */
 #endif
 
 extern void (*kd_mksound)(unsigned int, unsigned int);
@@ -336,7 +334,7 @@
 #endif
     kd_mksound		 = mac_mksound;
 #ifdef CONFIG_MAGIC_SYSRQ
-    mach_sysrq_key = 98;          /* HELP */
+    mach_sysrq_key = 114;         /* HELP */
     mach_sysrq_shift_state = 8;   /* Alt */
     mach_sysrq_shift_mask = 0xff; /* all modifiers except CapsLock */
     mach_sysrq_xlate = mac_sysrq_xlate;
@@ -399,10 +397,10 @@
 	 *	
 	 */
 	 
-	{	MAC_MODEL_II,	"II",		MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_NUBUS},
-	{	MAC_MODEL_IIX,	"IIx",		MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_NUBUS},
-	{	MAC_MODEL_IICX,	"IIcx",		MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_NUBUS},
-	{	MAC_MODEL_SE30, "SE/30",	MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_NUBUS},
+	{	MAC_MODEL_II,	"II",		MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_IIX,	"IIx",		MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_IICX,	"IIcx",		MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_SE30, "SE/30",	MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	
 	/*
 	 *	Weirdified MacII hardware - all subtley different. Gee thanks
@@ -461,11 +459,11 @@
 	 *	Performa - more LC type machines
 	 */
 
-	{	MAC_MODEL_P460,  "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci,   MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_P460,  "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci,   MAC_SCSI_OLD,    MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_P475,  "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE, MAC_NUBUS},
 	{	MAC_MODEL_P475F, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE, MAC_NUBUS},
 	{	MAC_MODEL_P520,  "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_P550,  "Performa 550", MAC_ADB_CUDA, MAC_VIA_IIci,   MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_P550,  "Performa 550", MAC_ADB_CUDA, MAC_VIA_IIci,   MAC_SCSI_OLD,    MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_P575,  "Performa 575", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_P588,  "Performa 588", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_TV,    "TV",           MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD,	MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
@@ -551,7 +549,7 @@
 			m++;
 		}
 		if(m->ident==-1)
-			mac_boom(5);
+			panic("mac model config data corrupt!\n");
 	}
 
 	/*
--- linux-2.1.130/arch/m68k/mac/macints.c.org	Tue Dec  1 00:28:59 1998
+++ linux-2.1.130/arch/m68k/mac/macints.c	Tue Dec  1 00:29:10 1998
@@ -163,7 +163,7 @@
 static unsigned long *mac_irqs[8];
 
 /*
- * VIA2 / RBV register base pointers
+ * VIA/RBV/OSS/PSC register base pointers
  */
 
 volatile unsigned char *via2_regp=(volatile unsigned char *)VIA2_BAS;
@@ -247,7 +247,7 @@
 
 		/* yes, this is messy - the IIfx deserves a class of his own */
 		if (macintosh_config->ident == MAC_MODEL_IIFX) {
-			/* no real VIA2, the OSS seems _very_different */	
+			/* no real VIA2, the OSS seems _very_ different */	
 			via2_is_oss = 1;
 			/* IIfx has OSS, at a different base address than RBV */
 			rbv_regp = (unsigned char *) OSS_BAS;
@@ -459,7 +459,7 @@
 	if (irq == IRQ_IDX(IRQ_MAC_SCSI)) {
 		/*
 		 * Set vPCR for SCSI interrupts. (what about RBV here?)
-		 * 980429 MS: RBV is ok, OSS seems to be differentt
+		 * 980429 MS: RBV is ok, OSS seems to be different
 		 */
 		if (!via2_is_oss)
 			if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
@@ -602,7 +602,10 @@
 
 /*
  * In opposite to {en,dis}able_irq, requests between turn{off,on}_irq are not
- * "stored". This is done with the VIA interrupt enable register
+ * "stored". This is done with the VIA interrupt enable register on VIAs.
+ *
+ * Note: Using these functions on non-VIA/OSS/PSC ints will panic, or at least 
+ * have undesired side effects.
  */
 
 void mac_turnon_irq( unsigned int irq )
@@ -615,14 +618,14 @@
 	if (!via) 
 		return;
 
-	if (srcidx == SRC_VIA2 && via2_is_rbv)
+	if (srcidx == SRC_VIA2 && via2_is_rbv)		/* RBV as VIA2 */
 	        via_write(via, rIER, via_read(via, rIER)|0x80|(1<<(irqidx)));
-	else if (srcidx == SRC_VIA2 && via2_is_oss)
+	else if (srcidx == SRC_VIA2 && via2_is_oss)	/* OSS */
 		via_write(oss_regp, oss_map[irqidx]+8, 2);
-	else if (srcidx > SRC_VIA2)
+	else if (srcidx > SRC_VIA2)			/* hope AVs have VIA2 */
 	        via_write(via, (0x104 + 0x10*srcidx), 
 	        	via_read(via, (0x104 + 0x10*srcidx))|0x80|(1<<(irqidx)));
-	else
+	else						/* VIA1+2 */
 	        via_write(via, vIER, via_read(via, vIER)|0x80|(1<<(irqidx)));
 
 }
@@ -637,9 +640,9 @@
 	if (!via) 
 		return;
 
-	if (srcidx == SRC_VIA2 && via2_is_rbv)
+	if (srcidx == SRC_VIA2 && via2_is_rbv)		/* RBV as VIA2 */
 		via_write(via, rIER, (via_read(via, rIER)&(1<<irqidx)));
-	else if (srcidx == SRC_VIA2 && via2_is_oss)
+	else if (srcidx == SRC_VIA2 && via2_is_oss)	/* OSS */
 		via_write(oss_regp, oss_map[irqidx]+8, 0);
 	/*
 	 *	VIA2 is fixed. The stuff above VIA2 is for later
@@ -648,7 +651,7 @@
 	else if (srcidx > SRC_VIA2)
 	        via_write(via, (0x104 + 0x10*srcidx), 
 	        	via_read(via, (0x104 + 0x10*srcidx))|(1<<(irqidx)));
-	else
+	else						/* VIA1+2 */
 		via_write(via, vIER, (via_read(via, vIER)&(1<<irqidx)));
 }
 
@@ -785,7 +788,7 @@
 void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 #ifdef DEBUG_VIA
-	printk("Unexpected IRQ %d\n", irq);
+	printk("Unexpected IRQ %d on device %p\n", irq, dev_id);
 #endif
 }
 
@@ -1310,7 +1313,7 @@
 	if(events==0)
 	{
 #ifdef DEBUG_VIA
-		printk("rbv_irq: nothing pending, flags %x mask %x!\n",
+		printk("psc_irq: nothing pending, flags %x mask %x!\n",
 			via_read(via, pIFR), via_read(via,pIER));
 #endif
 		mac_irqs[srcidx][7]++;
@@ -1319,7 +1322,7 @@
 
 #ifdef DEBUG_VIA	
 	/*
-	 * limited verbosity for RBV interrupts (add more if needed)
+	 * limited verbosity for PSC interrupts (add more if needed)
 	 */
 	if ( srcidx == 1 && events != 1<<3 && events != 1<<1 )		/* SCSI IRQ */
 		printk("psc_irq: irq %d srcidx+1 %d events %x !\n", irq, srcidx+1, events);
@@ -1506,6 +1509,10 @@
 		else
 			map = ~via_read(via2_regp, vBufA);
 		
+#ifdef DEBUG_NUBUS_INT
+		printk("nubus_irq: map %x mask %x\n", map, nubus_active);
+#endif
+
 		if( (map = (map&nubus_active)) ==0 ) {
 #ifdef DEBUG_NUBUS_INT
 			printk("nubus_irq: nothing pending, map %x mask %x\n", 
@@ -1514,9 +1521,6 @@
 			nubus_irqs[7]++;
 			break;
 		}
-#ifdef DEBUG_NUBUS_INT
-		printk("nubus_irq: map %x mask %x\n", map, nubus_active);
-#endif
 
 		if(ct++>2)
 		{
--- linux-2.1.130/arch/m68k/mac/via6522.c.org	Tue Dec  1 00:32:08 1998
+++ linux-2.1.130/arch/m68k/mac/via6522.c	Tue Dec  1 00:32:12 1998
@@ -304,10 +304,11 @@
 		unsigned long flags;
 		unsigned long *reset_hook;
 
-		save_flags(flags);
-		cli();
-
 		/* need ROMBASE in booter */
+		/* indeed, plus need to MAP THE ROM !! */
+
+		if (mac_bi_data.rombase == 0)
+			mac_bi_data.rombase = 0x40800000;
 
 		/* works on some */
 		rom_reset = (void *) (mac_bi_data.rombase + 0xa);
@@ -318,12 +319,22 @@
 		printk("ROM reset hook: %p\n", *reset_hook);
 		rom_reset = *reset_hook;
 #endif
+		if (macintosh_config->ident == MAC_MODEL_SE30) {
+			/*
+			 * MSch: Machines known to crash on ROM reset ...
+			 */
+			printk("System halted.\n");
+			while(1);
+		} else {
+			save_flags(flags);
+			cli();
 
-		rom_reset();
+			rom_reset();
 
-		restore_flags(flags);
+			restore_flags(flags);
+		}
 
-		/* We never make it this far... */
+		/* We never make it this far... it usually panics above. */
 		printk ("Restart failed.  Please restart manually.\n");
 
 		/* XXX - delay do we need to spin here ? */
--- linux-2.1.130/drivers/char/mac_SCC.c.org	Tue Dec  1 00:18:03 1998
+++ linux-2.1.130/drivers/char/mac_SCC.c	Tue Dec  1 00:19:46 1998
@@ -198,18 +198,6 @@
 };
 
 /*
- * tmp_buf is used as a temporary buffer by serial_write.  We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char tmp_buf[4096]; /* This is cheating */
-static struct semaphore tmp_buf_sem = MUTEX;
-
-/*
  * This is used to figure out the divisor speeds and the timeouts
  */
 static int baud_table[] = {
@@ -771,7 +759,7 @@
 
 	/* If console serial line, then enable interrupts. */
 	if (info->private->is_cons) {
-		printk("mac_SCC: console line %lx; enabling interrupt!\n", info);
+		printk("mac_SCC: console line %d; enabling interrupt!\n", info->line);
 		write_zsreg(info->private->zs_channel, R1,
 			    (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB));
 		write_zsreg(info->private->zs_channel, R9, (NV | MIE));
@@ -784,7 +772,7 @@
 	 * client attached to us asynchronously.
 	 */
 	if (info->private->kgdb_channel) {
-		printk("mac_SCC: kgdb line %lx; enabling interrupt!\n", info);
+		printk("mac_SCC: kgdb line %d; enabling interrupt!\n", info->line);
 		kgdb_chaninit(info, 1, info->private->zs_baud);
 	}
 	/* Report settings (in m68kserial.c) */
@@ -1141,8 +1129,6 @@
 static void SCC_get_serial_info(struct m68k_async_struct * info,
 			   struct serial_struct * retinfo)
 {
-	struct serial_struct tmp;
-  
 	retinfo->baud_base = info->baud_base;
 	retinfo->custom_divisor = info->custom_divisor;
 }
@@ -1190,8 +1176,7 @@
 static int SCC_set_modem_info(struct m68k_async_struct *info, 
 			      int new_dtr, int new_rts)
 {
-	int error;
-	unsigned int arg, bits;
+	unsigned int bits;
 
 	bits = (new_rts ? RTS: 0) + (new_dtr ? DTR: 0);
 	info->private->curregs[5] = (info->private->curregs[5] & ~(DTR | RTS)) | bits;
@@ -1231,7 +1216,6 @@
 	            unsigned long arg)
 {
 	int error;
-	int retval;
 
 	switch (cmd) {
 		case TIOCSERGETLSR: /* Get line status register */
@@ -1315,9 +1299,9 @@
 				ZS_CONTROL+ZS_MOVE*n;
 		zs_channels[n].data = (volatile unsigned char *)ZS_DATA+ZS_MOVE*n;
 #else
-		zs_channels[n].control = (volatile unsigned char *)
+		zs_channels[n].control = (volatile unsigned char *) /* 2, 0 */
 			(mac_bi_data.sccbase+ZS_CH_A_FIRST)+ZS_MOVE*n;
-		zs_channels[n].data = (volatile unsigned char *)
+		zs_channels[n].data = (volatile unsigned char *) /* 6, 4 */
 			(mac_bi_data.sccbase+ZS_CH_A_FIRST+ZS_DATA_MOVE)+ZS_MOVE*n;
 #endif
 		zs_soft[n].private = &zs_soft_private[n];
@@ -1405,8 +1389,8 @@
 rs_cons_check(struct m68k_async_struct *ss, int channel)
 {
 	int i, o, io;
-	static consout_registered = 0;
-	static msg_printed = 0;
+	static int consout_registered = 0;
+	static int msg_printed = 0;
 
 	i = o = io = 0;
 
@@ -1458,10 +1442,9 @@
 /* rs_init inits the driver */
 int mac_SCC_init(void)
 {
-	int channel, line, nr = 0, i;
+	int channel, line, nr = 0;
 	unsigned long flags;
 	struct serial_struct req;
-	struct m68k_async_struct *info;
 
 	printk("Mac68K Z8530 serial driver version 1.01\n");
 
@@ -1486,7 +1469,7 @@
 	for (channel = 0; channel < zs_channels_found; ++channel) {
 		req.line = channel;
 		req.type = SER_SCC_MAC;
-		req.port = zs_soft[channel].private->zs_channel->control;
+		req.port = (int) zs_soft[channel].private->zs_channel->control;
 
 		if ((line = register_serial( &req )) >= 0) {
 			SCC_init_port( &rs_table[line], req.type, line );
--- linux-2.1.130/drivers/scsi/mac_scsinew.c.org	Sat Nov 28 20:16:45 1998
+++ linux-2.1.130/drivers/scsi/mac_scsinew.c	Sat Nov 28 20:18:32 1998
@@ -1,7 +1,7 @@
 /*
  * Generic Macintosh NCR5380 driver
  *
- * Copyright 1998, Michael Schmitz
+ * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov>
  *
  * derived in part from:
  */
@@ -136,14 +136,11 @@
 /*
  * Function : mac_scsi_setup(char *str, int *ints)
  *
- * Purpose : LILO command line initialization of the overrides array,
+ * Purpose : booter command line initialization of the overrides array,
  *
  * Inputs : str - unused, ints - array of integer parameters with ints[0]
  *	equal to the number of ints.
  *
- * Currently unused in the new driver; need to add settable parameters to the 
- * detect function.
- *
  */
 
 void mac_scsi_setup(char *str, int *ints) {
@@ -244,6 +241,26 @@
 
     tpnt->proc_dir = &proc_scsi_mac5380;
 
+    /* setup variables */
+    tpnt->can_queue =
+      (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
+    tpnt->cmd_per_lun =
+      (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
+    tpnt->sg_tablesize = 
+      (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
+
+    if (setup_hostid >= 0)
+      tpnt->this_id = setup_hostid;
+    else {
+      /* use 7 as default */
+      tpnt->this_id = 7;
+    }
+
+#ifdef SUPPORT_TAGS
+	if (setup_use_tagged_queuing < 0)
+		setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
+#endif
+
 #if 0	/* loop over multiple adapters (Powerbooks ??) */
     for (count = 0; count < mac_num_scsi; count++) {
 #endif
@@ -291,7 +308,7 @@
 	else
 	    printk (" %d", instance->irq);
 	printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
-	    CAN_QUEUE, CMD_PER_LUN, MACSCSI_PUBLIC_RELEASE);
+	    instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
 	printk("\nscsi%d:", instance->host_no);
 	NCR5380_print_options(instance);
 	printk("\n");
@@ -662,8 +679,9 @@
 			NCR5380_print_status(default_instance);
 			restore_flags(flags);
 	}
-
+#if 0
 	polled_scsi_on = 1;
+#endif
 }
 /*
  * Helper function for interrupt trouble. More ugly side effects here.
--- linux-2.1.130/drivers/scsi/mac_scsinew.h.org	Sat Nov 28 20:19:50 1998
+++ linux-2.1.130/drivers/scsi/mac_scsinew.h	Sat Nov 28 20:21:42 1998
@@ -54,6 +54,14 @@
 #define CAN_QUEUE 16
 #endif
 
+#ifndef SG_TABLESIZE
+#define SG_TABLESIZE SG_NONE
+#endif
+
+#ifndef USE_TAGGED_QUEUING
+#define	USE_TAGGED_QUEUING 0
+#endif
+
 #include <scsi/scsicam.h>
 
 #define MAC_NCR5380 {						\
--- linux-2.1.130/drivers/scsi/mac_esp.c.org	Sat Nov 28 20:50:56 1998
+++ linux-2.1.130/drivers/scsi/mac_esp.c	Sat Nov 28 20:51:45 1998
@@ -1,9 +1,10 @@
-
 /*
  * 68k mac 53c9[46] scsi driver
  *
  * copyright (c) 1998, David Weis weisd3458@uni.edu
  *
+ * debugging on Quadra 800 and 660AV Michael Schmitz, Dave Kilzer 7/98
+ *
  * based loosely on cyber_esp.c
  */
 
@@ -15,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
+#include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/malloc.h>
 #include <linux/blk.h>
@@ -63,6 +65,17 @@
 
 static int esp_initialized = 0;
 
+static int setup_num_esps = -1;
+static int setup_disconnect = -1;
+static int setup_nosync = -1;
+static int setup_can_queue = -1;
+static int setup_cmd_per_lun = -1;
+static int setup_sg_tablesize = -1;
+#ifdef SUPPORT_TAGS
+static int setup_use_tagged_queuing = -1;
+#endif
+static int setup_hostid = -1;
+
 /*
  * Experimental ESP inthandler; check macints.c to make sure dev_id is 
  * set up properly!
@@ -124,6 +137,100 @@
 	printk("mac_esp: got drq\n");
 }
 
+#define DRIVER_SETUP
+
+/*
+ * Function : mac_scsi_setup(char *str, int *ints)
+ *
+ * Purpose : booter command line initialization of the overrides array,
+ *
+ * Inputs : str - unused, ints - array of integer parameters with ints[0]
+ *	equal to the number of ints.
+ *
+ * Currently unused in the new driver; need to add settable parameters to the 
+ * detect function.
+ *
+ */
+
+void mac_esp_setup(char *str, int *ints) {
+#ifdef DRIVER_SETUP
+	/* Format of mac53c9x parameter is:
+	 *   mac53c9x=<num_esps>,<disconnect>,<nosync>,<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
+	 * Negative values mean don't change.
+	 */
+	
+	/* Grmbl... the standard parameter parsing can't handle negative numbers
+	 * :-( So let's do it ourselves!
+	 */
+
+	int i = ints[0]+1, fact;
+
+	while( str && (isdigit(*str) || *str == '-') && i <= 10) {
+		if (*str == '-')
+			fact = -1, ++str;
+		else
+			fact = 1;
+		ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
+		if ((str = strchr( str, ',' )) != NULL)
+			++str;
+	}
+	ints[0] = i-1;
+	
+	if (ints[0] < 1) {
+		printk( "mac_esp_setup: no arguments!\n" );
+		return;
+	}
+
+	if (ints[0] >= 1) {
+		if (ints[1] > 0)
+			/* no limits on this, just > 0 */
+		if (ints[1] >= 0 && ints[1] <= 2)
+			setup_num_esps = ints[1];
+		else if (ints[1] > 2)
+			printk( "mac_esp_setup: invalid number of hosts %d !\n", ints[1] );
+	}
+	if (ints[0] >= 2) {
+		if (ints[2] > 0)
+			setup_disconnect = ints[2];
+	}
+	if (ints[0] >= 3) {
+		if (ints[3] >= 0) {
+			setup_nosync = ints[3];
+		}
+	}
+	if (ints[0] >= 4) {
+		if (ints[4] > 0)
+			/* no limits on this, just > 0 */
+			setup_can_queue = ints[4];
+	}
+	if (ints[0] >= 5) {
+		if (ints[5] > 0)
+			setup_cmd_per_lun = ints[5];
+	}
+	if (ints[0] >= 6) {
+		if (ints[6] >= 0) {
+			setup_sg_tablesize = ints[6];
+			/* Must be <= SG_ALL (255) */
+			if (setup_sg_tablesize > SG_ALL)
+				setup_sg_tablesize = SG_ALL;
+		}
+	}
+	if (ints[0] >= 7) {
+		/* Must be between 0 and 7 */
+		if (ints[7] >= 0 && ints[7] <= 7)
+			setup_hostid = ints[7];
+		else if (ints[7] > 7)
+			printk( "mac_esp_setup: invalid host ID %d !\n", ints[7] );
+	}
+#ifdef SUPPORT_TAGS
+	if (ints[0] >= 8) {
+		if (ints[8] >= 0)
+			setup_use_tagged_queuing = !!ints[8];
+	}
+#endif
+#endif
+}
+
 /*
  * ESP address 'detection'
  */
@@ -189,6 +296,36 @@
 		chipspresent ++;
 	}
 
+	/* number of ESPs present ? */
+	if (setup_num_esps >= 0) {
+	  if (chipspresent >= setup_num_esps)
+	    chipspresent = setup_num_esps;
+	  else
+	    printk("mac_esp_detect: num_hosts detected %d setup %d \n",
+		   chipspresent, setup_num_esps);
+	}
+
+	/* TODO: add disconnect / nosync flags */
+
+	/* setup variables */
+	tpnt->can_queue =
+	  (setup_can_queue > 0) ? setup_can_queue : 7;
+	tpnt->cmd_per_lun =
+	  (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : 1;
+	tpnt->sg_tablesize = 
+	  (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_ALL;
+
+	if (setup_hostid >= 0)
+	  tpnt->this_id = setup_hostid;
+	else {
+	  /* use 7 as default */
+	  tpnt->this_id = 7;
+	}
+
+#ifdef SUPPORT_TAGS
+	if (setup_use_tagged_queuing < 0)
+		setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
+#endif
 
 	for (chipnum = 0; chipnum < chipspresent; chipnum ++) {
 		struct NCR_ESP * esp;
@@ -253,7 +390,7 @@
 
 
 		if (quick) {
-			/* use fast versions i guess... */
+			/* 'quick' means there's handshake glue logic like in the 5380 case */
 			esp->dma_setup = &dma_setup_quick;
 		} else {
 			esp->dma_setup = &dma_setup;
--- linux-2.1.130/drivers/scsi/NCR53C9x.c.org	Sat Nov 28 20:56:14 1998
+++ linux-2.1.130/drivers/scsi/NCR53C9x.c	Sat Nov 28 20:55:22 1998
@@ -1045,7 +1045,7 @@
 
 	if(SDptr->sync) {
 		/* this targets sync is known */
-#ifdef CONFIG_SCSI_SUNESP
+#if defined(CONFIG_SCSI_SUNESP) || defined(CONFIG_SCSI_MAC_ESP)
 do_sync_known:
 #endif
 		if(SDptr->disconnect)
@@ -1101,6 +1101,19 @@
 			goto do_sync_known;
 		}
 #endif
+
+#ifdef CONFIG_SCSI_MAC_ESP
+		/* Never allow synchronous transfers (disconnect OK) on
+		 * Macintosh. Well, maybe later when we figured out how to 
+		 * do DMA on the machines that support it ...
+		 */
+		SDptr->disconnect = 1;
+		SDptr->sync_max_offset = 0;
+		SDptr->sync_min_period = 0;
+		SDptr->sync = 1;
+		esp->snip = 0;
+		goto do_sync_known;
+#endif
 		/* We've talked to this guy before,
 		 * but never negotiated.  Let's try,
 		 * need to attempt WIDE first, before
@@ -1111,7 +1124,6 @@
 			   (SDptr->type != TYPE_ROM ||
 			    strncmp(SDptr->vendor, "TOSHIBA", 7))) {
 				build_wide_nego_msg(esp, 16);
-				esp->config3[SCptr->target] |= ESP_CONFIG3_EWIDE;
 				SDptr->wide = 1;
 				esp->wnip = 1;
 				goto after_nego_msg_built;
@@ -1163,11 +1175,7 @@
 		 *           thank you very much. ;-)
 		 */
 		if(((SDptr->scsi_level < 3) && (SDptr->type != TYPE_TAPE)) ||
-#if 1 /* Until I find out why HME barfs with disconnects enabled... */
-		   toshiba_cdrom_hwbug_wkaround || SDptr->borken || esp->erev == fashme) {
-#else
 		   toshiba_cdrom_hwbug_wkaround || SDptr->borken) {
-#endif
 			printk(KERN_INFO "esp%d: Disabling DISCONNECT for target %d "
 			       "lun %d\n", esp->esp_id, SCptr->target, SCptr->lun);
 			SDptr->disconnect = 0;
@@ -1208,6 +1216,12 @@
 	if(esp->do_pio_cmds){
 		int j = 0;
 
+		/* 
+		 * It seems this is required, at least to clean up
+		 * after failed commands when using PIO mode ...
+		 */
+		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+
 		for(;j<i;j++)
 			eregs->esp_fdata = esp->esp_command[j];
 		the_esp_command &= ~ESP_CMD_DMA;
@@ -1890,24 +1904,192 @@
 	esp_advance_phase(SCptr, thisphase);
 	ESPDATA(("newphase<%s> ", (thisphase == in_datain) ? "DATAIN" : "DATAOUT"));
 	hmuch = esp->dma_can_transfer(esp, SCptr);
-	ESPDATA(("hmuch<%d> ", hmuch));
-	esp->current_transfer_size = hmuch;
-	if(esp->erev == fashme) {
-		/* Touchy chip, this stupid HME scsi adapter... */
-		esp_setcount(eregs, hmuch, 1);
-		esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
 
-		if(thisphase == in_datain)
-			esp->dma_init_read(esp, (__u32)((unsigned long)SCptr->SCp.ptr), hmuch);
-		else
-			esp->dma_init_write(esp, (__u32)((unsigned long)SCptr->SCp.ptr), hmuch);
-	} else {
+	if (hmuch) {	/* DMA */
+		ESPDATA(("hmuch<%d> ", hmuch));
+		esp->current_transfer_size = hmuch;
+		if(esp->erev == fashme) {
+			/* Touchy chip, this stupid HME scsi adapter... */
+			esp_setcount(eregs, hmuch, 1);
+			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
+
+			if(thisphase == in_datain)
+				esp->dma_init_read(esp, (__u32)((unsigned long)SCptr->SCp.ptr), hmuch);
+			else
+				esp->dma_init_write(esp, (__u32)((unsigned long)SCptr->SCp.ptr), hmuch);
+		} else {
+			esp_setcount(eregs, hmuch, 0);
+			esp->dma_setup(esp, 
+				       (__u32)((unsigned long)SCptr->SCp.ptr), 
+				       hmuch, (thisphase == in_datain));
+			ESPDATA(("DMA|TI --> do_intr_end\n"));
+			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
+		}
+		return do_intr_end;
+	} else {	/* PIO :-(( This sucks ... */
+		int oldphase, i = 0; /* or where we left off last time ?? esp->current_data ?? */
+		int fifocnt = 0;
+
+		oldphase = eregs->esp_status & ESP_STAT_PMASK;
+
+		/*
+		 * polled transfer; ugly, can we make this happen in a DRQ 
+		 * interrupt handler ??
+		 * requires keeping track of state information in host or 
+		 * command struct!
+		 * Problem: I've never seen a DRQ happen on Mac, not even
+		 * with ESP_CMD_DMA ...
+		 */
+
+		/* figure out how much needs to be transfered */
+		hmuch = SCptr->SCp.this_residual;
+		ESPDATA(("hmuch<%d> pio ", hmuch));
+		esp->current_transfer_size = hmuch;
+
+		/* tell the ESP ... */
 		esp_setcount(eregs, hmuch, 0);
-		esp->dma_setup(esp, 
-			       (__u32)((unsigned long)SCptr->SCp.ptr), 
-			       hmuch, (thisphase == in_datain));
-		ESPDATA(("DMA|TI --> do_intr_end\n"));
-		esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
+
+		/* loop */
+		while (hmuch) {
+			int j, fifo_stuck = 0, newphase;
+			unsigned long flags, timeout;
+#if 0
+			if ( i % 10 )
+				ESPDATA(("\r"));
+			else
+				ESPDATA(( /*"\n"*/ "\r"));
+#endif
+			save_flags(flags);
+#if 0
+			cli();
+#endif
+			if(thisphase == in_datain) {
+				/* 'go' ... */ 
+				esp_cmd(esp, eregs, ESP_CMD_TI);
+
+				/* wait for data */
+				timeout = 1000000;
+				while (!((esp->sreg=eregs->esp_status) & ESP_STAT_INTR) && --timeout)
+					udelay(2);
+				if (timeout == 0)
+					printk("DRQ datain timeout! \n");
+
+				newphase = esp->sreg & ESP_STAT_PMASK;
+
+				/* see how much we got ... */
+				fifocnt = (eregs->esp_fflags & ESP_FF_FBYTES);
+
+				if (!fifocnt)
+					fifo_stuck++;
+				else
+					fifo_stuck = 0;
+
+				ESPDATA(("\rgot %d st %x ph %x", fifocnt, esp->sreg, newphase));
+
+				/* read fifo */
+				for(j=0;j<fifocnt;j++)
+					SCptr->SCp.ptr[i++] = eregs->esp_fdata;
+
+				ESPDATA(("(%d) ", i));
+
+				/* how many to go ?? */
+				hmuch -= fifocnt;
+
+				/* break if status phase !! */
+				if(newphase == ESP_STATP) {
+					/* clear int. */
+					esp->ireg = eregs->esp_intrpt;
+					break;
+				}
+			} else {
+#define MAX_FIFO 8
+				/* how much will fit ? */
+				int this_count = MAX_FIFO - fifocnt;
+				if (this_count > hmuch)
+					this_count = hmuch;
+
+				/* fill fifo */
+				for(j=0;j<this_count;j++)
+					eregs->esp_fdata = SCptr->SCp.ptr[i++];
+
+				/* how many left if this goes out ?? */
+				hmuch -= this_count;
+
+				/* 'go' ... */ 
+				esp_cmd(esp, eregs, ESP_CMD_TI);
+
+				/* wait for 'got it' */
+				timeout = 1000000;
+				while (!((esp->sreg=eregs->esp_status) & ESP_STAT_INTR) && --timeout)
+					udelay(2);
+				if (timeout == 0)
+					printk("DRQ dataout timeout!  \n");
+
+				newphase = esp->sreg & ESP_STAT_PMASK;
+
+				/* need to check how much was sent ?? */
+				fifocnt = (eregs->esp_fflags & ESP_FF_FBYTES);
+
+				ESPDATA(("\rsent %d st %x ph %x", this_count - fifocnt, esp->sreg, newphase));
+
+				ESPDATA(("(%d) ", i));
+
+				/* break if status phase !! */
+				if(newphase == ESP_STATP) {
+					/* clear int. */
+					esp->ireg = eregs->esp_intrpt;
+					break;
+				}
+
+			}
+
+			/* clear int. */
+			esp->ireg = eregs->esp_intrpt;
+
+			ESPDATA(("ir %x ... ", esp->ireg));
+
+			if (hmuch == 0)
+				ESPDATA(("done! \n"));
+
+			restore_flags(flags);
+
+			/* check new bus phase */
+			if (newphase != oldphase && i < esp->current_transfer_size) {
+				/* something happened; disconnect ?? */
+				ESPDATA(("phase change, dropped out with %d done ... ", i));
+				break;
+			}
+
+			/* check int. status */
+			if (esp->ireg & ESP_INTR_DC) {
+				/* disconnect */
+				ESPDATA(("disconnect; %d transfered ... ", i));
+				break;
+			} else if (esp->ireg & ESP_INTR_FDONE) {
+				/* function done */
+				ESPDATA(("function done; %d transfered ... ", i));
+				break;
+			}
+
+			/* XXX fixme: bail out on stall */
+			if (fifo_stuck > 10) {
+				/* we're stuck */
+				ESPDATA(("fifo stall; %d transfered ... ", i));
+				break;
+			}
+		}
+
+		ESPDATA(("\n"));
+		/* check successful completion ?? */
+
+		if (thisphase == in_dataout)
+			hmuch += fifocnt; /* stuck?? adjust data pointer ...*/
+
+		/* tell do_data_finale how much was transfered */
+		esp->current_transfer_size -= hmuch;
+
+		/* still not completely sure on this one ... */		
+		return /*do_intr_end*/ do_work_bus /*do_phase_determine*/ ;
 	}
 	return do_intr_end;
 }
@@ -2029,6 +2211,10 @@
 		ESPLOG(("esp%d: use_sg=%d ptr=%p this_residual=%d\n",
 			esp->esp_id,
 			SCptr->use_sg, SCptr->SCp.ptr, SCptr->SCp.this_residual));
+		ESPLOG(("esp%d: Forcing async for target %d\n", esp->esp_id, 
+			SCptr->target));
+		SCptr->device->borken = 1;
+		SCptr->device->sync = 0;
 		bytes_sent = 0;
 	}
 
@@ -2057,7 +2243,12 @@
 			advance_sg(esp, SCptr);
 		if(sreg_datainp(esp->sreg) || sreg_dataoutp(esp->sreg)) {
 			ESPDATA(("to more data\n"));
-			return esp_do_data(esp, eregs);
+			/*
+			 * required for proper termination of data transfer 
+			 * phase in PIO mode
+			 */
+			if (!((esp->sreg & ESP_STAT_PMASK) == ESP_STATP))
+				return esp_do_data(esp, eregs);
 		}
 		ESPDATA(("to new phase\n"));
 		return esp_do_phase_determine(esp, eregs);
@@ -3122,9 +3313,11 @@
 		esp_cmd(esp, eregs, (ESP_CMD_DMA | ESP_CMD_TI));
 		esp->dma_init_write(esp, esp->esp_command_dvma, i);
 	} else {
+		unsigned char tmp;
 		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-		eregs->esp_fdata = *esp->esp_scmdp++;
+		tmp = *esp->esp_scmdp++;
 		esp->esp_scmdleft--;
+		eregs->esp_fdata = tmp;
 		esp_cmd(esp, eregs, ESP_CMD_TI);
 	}
 	return do_intr_end;
@@ -3645,14 +3838,16 @@
 void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
 	struct NCR_ESP *esp;
+	unsigned long flags;
 	int again;
 
 	/* Handle all ESP interrupts showing at this IRQ level. */
+	spin_lock_irqsave(&io_request_lock, flags);
 repeat:
 	again = 0;
 	for_each_esp(esp) {
 #ifndef __mips__	    
-		if(((esp)->irq & 0xf) == irq) {
+		if(((esp)->irq & 0xff) == irq) {
 #endif		    
 			if(esp->dma_irq_p(esp)) {
 				again = 1;
@@ -3671,14 +3866,17 @@
 	}
 	if(again)
 		goto repeat;
+	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 #else
 /* For SMP we only service one ESP on the list list at our IRQ level! */
 static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
 	struct NCR_ESP *esp;
+	unsigned long flags;
 
 	/* Handle all ESP interrupts showing at this IRQ level. */
+	spin_lock_irqsave(&io_request_lock, flags);
 	for_each_esp(esp) {
 		if(((esp)->irq & 0xf) == irq) {
 			if(esp->dma_irq_p(esp)) {
@@ -3690,10 +3888,12 @@
 				ESPIRQ((")"));
 
 				esp->dma_ints_on(esp);
-				return;
+				goto out;
 			}
 		}
 	}
+out:
+	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 #endif
 
@@ -3702,7 +3902,9 @@
 static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
 	struct NCR_ESP *esp = dev_id;
+	unsigned long flags;
 
+	spin_lock_irqsave(&io_request_lock, flags);
 	if(esp->dma_irq_p(esp)) {
 		esp->dma_ints_off(dregs);
 
@@ -3712,6 +3914,7 @@
 
 		esp->dma_ints_on(esp);
 	}
+	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 
 #endif
--- linux-2.1.130/drivers/scsi/NCR53C9x.h.org	Tue Dec  1 00:10:40 1998
+++ linux-2.1.130/drivers/scsi/NCR53C9x.h	Tue Dec  1 00:12:47 1998
@@ -13,6 +13,13 @@
 
 #include <linux/config.h>
 
+/* djweis for mac driver */
+#if defined(CONFIG_MAC)
+#define PAD_SIZE 15
+#else
+#define PAD_SIZE 3
+#endif
+
 /* Macros for debugging messages */
 
 /* #define DEBUG_ESP */
@@ -115,7 +122,7 @@
 #ifdef CONFIG_JAZZ_ESP
 #define EREGS_PAD(n)
 #else
-#define EREGS_PAD(n)    unchar n[3];
+#define EREGS_PAD(n)    unchar n[PAD_SIZE];
 #endif
 
 /* The ESP SCSI controllers have their register sets in three
@@ -167,7 +174,7 @@
     /* The following is only found on the 53C9X series SCSI chips */
     volatile unchar esp_cfg3;   /* rw  Third configuration register   0x30  */
                                 EREGS_PAD(holep);
-    volatile unchar esp_hole;   /* hole in register map               0x34  */
+    volatile unchar esp_cfg4;   /* rw  Fourth configuration register  0x34  */
                                 EREGS_PAD(thpd);    
     /* The following is found on all chips except the NCR53C90 (ESP100) */
     volatile unchar esp_tchi;   /* rw  High bits of transfer count    0x38  */
--- linux-2.1.130/drivers/video/macfb.c.org	Sat Nov 28 18:05:54 1998
+++ linux-2.1.130/drivers/video/macfb.c	Sat Nov 28 18:14:03 1998
@@ -22,6 +22,7 @@
 #include <asm/macintosh.h>
 #include <linux/fb.h>
 
+#include <video/fbcon.h>
 /* conditionalize these ?? */
 #include <video/fbcon-mfb.h>
 #include <video/fbcon-cfb2.h>
@@ -154,13 +155,15 @@
 	strcpy(fix->id,"Macintosh");
 
 	/*
-	 * X works, but screen wraps ... 
+	 * fbmem.c accepts non page aligned mappings now!
 	 */
-	fix->smem_start=(char *)(mac_videobase&PAGE_MASK);
-	fix->smem_offset=(mac_videobase&~PAGE_MASK);
-	fix->smem_len=PAGE_ALIGN(mac_videosize);
+	fix->smem_start=(char *)mac_videobase;
+	fix->smem_len=mac_videosize;
 	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	if (mac_depth == 1)
+		fix->visual = FB_VISUAL_MONO01;
+	else
+		fix->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
 	fix->xpanstep=0;
 	fix->ypanstep=0;
 	fix->ywrapstep=0;
@@ -203,7 +206,7 @@
 
 	macfb_get_fix(&fix, con, 0);
 
-	display->screen_base = fix.smem_start+fix.smem_offset;
+	display->screen_base = fix.smem_start;
 	display->visual = fix.visual;
 	display->type = fix.type;
 	display->type_aux = fix.type_aux;
@@ -212,7 +215,8 @@
 	display->line_length = fix.line_length;
 	display->next_line = fix.line_length;
 	display->can_soft_blank = 0;
-	display->inverse = inverse;
+	display->inverse =
+	    (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
 
 	switch (mac_depth) {
 #ifdef FBCON_HAS_MFB
@@ -251,6 +255,140 @@
 	return 0;
 }
 
+/*
+ * Color map handling - hardcoded maps!! 
+ *
+ * 2.0 color map primitives, copied from atafb.c
+ */
+ 
+/*
+ * should be kmalloc'ed on request
+ */
+static short red256[256], green256[256], blue256[256];
+
+static short red16[]=
+	{ 0x0000,0x0000,0x0000,0x0000,0x8080,0x8080,0x8080,0xc0c0,
+	  0x8080,0x0000,0x0000,0x0000,0xffff,0xffff,0xffff,0xffff};
+static short green16[]=
+	{ 0x0000,0x0000,0x8080,0x8080,0x0000,0x0000,0x8080,0xc0c0,
+	  0x8080,0x0000,0xffff,0xffff,0x0000,0x0000,0xffff,0xffff};
+static short blue16[]=
+	{ 0x0000,0x8080,0x0000,0x8080,0x0000,0x8080,0x0000,0xc0c0,
+	  0x8080,0xffff,0x0000,0xffff,0x0000,0xffff,0x0000,0xffff};
+
+static short red4[]=
+	{ 0x0000,0x8080,0xffff,0xffff};
+static short green4[]=
+	{ 0x0000,0x8080,0x0000,0xffff};
+static short blue4[]=
+	{ 0x0000,0x8080,0x0000,0xffff};
+
+static short red2[]=
+	{ 0x0000,0xffff};
+static short green2[]=
+	{ 0x0000,0xffff};
+static short blue2[]=
+	{ 0x0000,0xffff};
+
+struct fb_cmap default_256_colors = { 0, 256, red256, green256, blue256, NULL };
+struct fb_cmap default_16_colors  = { 0, 16, red16, green16, blue16, NULL };
+struct fb_cmap default_4_colors   = { 0, 4, red4, green4, blue4, NULL };
+struct fb_cmap default_2_colors   = { 0, 2, red2, green2, blue2, NULL };
+
+static int mac_set_cmap256(struct fb_cmap* cmap)
+{
+	int i,start;
+	unsigned short *red,*green,*blue;
+	unsigned short cval[] = {0xffff, 0xcccc, 0x9999, 
+				 0x6666, 0x3333, 0x0000 };
+	unsigned short gval[] = {0x0a0a, 0x1414, 0x1e1e,
+				 0x2828, 0x3232, 0x3c3c,
+				 0x4646, 0x5050, 0x5a5a,
+				 0x6464, 0x6e6e, 0x7878,
+				 0x8282, 0x8c8c, 0x9696,
+				 0xa0a0, 0xaaaa, 0xb4b4,
+				 0xbebe, 0xc8c8, 0xd2d2,
+				 0xdcdc, 0xe6e6, 0xf0f0};
+
+	red=cmap->red;
+	green=cmap->green;
+	blue=cmap->blue;
+	start=cmap->start;
+
+	if (start < 0)
+		return -EINVAL;
+	if (cmap->len < 255)
+		return -EINVAL;
+	/* 16 ANSI colors */
+	for (i=0 ; i < 16 ; i++) {
+		*red++   = red16[i];
+		*green++ = green16[i];
+		*blue++  = blue16[i];
+	}
+	/* 216 colors (6x6x6) map) */
+	for (i=16 ; i < 232 ; i++) {
+		*red++   = cval[(i-16)/36];
+		*green++ = cval[((i-16)/6)%6];
+		*blue++  = cval[(i-16)%6];
+	}
+	/* 24 grays */
+	for (i=232 ; i < 256 ; i++) {
+		*red = *green = *blue = gval[i-232];
+		red++;
+		green++;
+		blue++;
+	}
+	return 0;
+}
+
+static struct fb_cmap * mac_get_default_cmap(int bpp)
+{
+	if (bpp == 1)
+		return &default_2_colors;
+	if (bpp == 2)
+		return &default_4_colors;
+	if (bpp == 4)
+		return &default_16_colors;
+	return &default_256_colors;
+}
+
+static void memcpy_fs(int fsfromto, void *to, void *from, int len)
+{
+    switch (fsfromto) {
+    	case 0:
+    	    memcpy(to, from, len);
+    	    return;
+    	case 1:
+    	    copy_from_user(to, from, len);
+    	    return;
+    	case 2:
+    	    copy_to_user(to, from, len);
+    	    return;
+    }
+}
+
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+{
+	int size;
+	int tooff=0, fromoff=0;
+
+	if (to->start > from->start)
+		fromoff=to->start-from->start;
+	else
+		tooff=from->start-to->start;			
+	size=to->len-tooff;
+	if (size > from->len-fromoff)
+		size=from->len-fromoff;
+	if (size < 0)
+		return;
+	size*=sizeof(unsigned short);
+	memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
+	memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
+	memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
+	if (from->transp && to->transp)
+		memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
+}
+ 
 static int macfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
 			  struct fb_info *info)
 {
@@ -267,6 +405,8 @@
 		fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel),
 		     cmap, kspc ? 0 : 2);
 #endif
+	copy_cmap(mac_get_default_cmap(fb_display[con].var.bits_per_pixel),
+	     cmap, kspc ? 0 : 2);
 	return 0;
 
 }
@@ -387,11 +527,9 @@
 	mac_videosize=mac_xbytes*mac_yres;
 	mac_videobase=mac_bi_data.videoaddr;
 
-	printk("macfb_init: xres %d yres %d bpp %d addr %x size %d \n",
+	printk("macfb_init: xres %d yres %d bpp %d addr %lx size %ld \n",
 		mac_xres, mac_yres, mac_depth, mac_videobase, mac_videosize);
 
-	mac_debugging_penguin(4);
-	
 	/*
 	 *	Fill in the available video resolution
 	 */
@@ -421,6 +559,12 @@
 	macfb_set_disp(-1);
 
 	/*
+	 *	Fill in the 8 bit color table if required
+	 */
+	if (mac_depth == 8)
+		mac_set_cmap256(&default_256_colors);
+	 	
+	/*
 	 *	Register the nubus hook
 	 */
 	 
@@ -428,7 +572,6 @@
 
 	if (register_framebuffer(&fb_info) < 0)
 	{
-		mac_boom(6);
 		return;
 	}
 
--- linux-2.1.130/init/main.c.org	Mon Nov 30 23:38:57 1998
+++ linux-2.1.130/init/main.c	Mon Nov 30 23:41:17 1998
@@ -45,6 +45,10 @@
 #  include <asm/mtrr.h>
 #endif
 
+#ifdef CONFIG_MAC
+extern void nubus_init(void);
+#endif
+
 /*
  * Versions of gcc older than that listed below may actually compile
  * and link okay, but the end product can have subtle run time bugs.
@@ -1265,6 +1269,9 @@
 #endif
 #ifdef CONFIG_DIO
 	dio_init();
+#endif
+#ifdef CONFIG_MAC
+	nubus_init();
 #endif
 
 	/* Networking initialization needs a process context */ 
 

