[kernel] r8570 - dists/trunk/linux-2.6/debian/patches/bugfix/m68k

Christian T. Steigies cts at alioth.debian.org
Fri May 11 21:15:09 UTC 2007


Author: cts
Date: Fri May 11 21:14:58 2007
New Revision: 8570

Added:
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/130-adbraw.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/133-arch.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/134-atari-fat.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/141-ide.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/143-ioext.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/149-mc68681.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/152-pci.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/357-mac89x0.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/448-ide.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/478-serial.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/577-module-arch.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/600-task_thread_info.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/611-module_fixup.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/618-discontig.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/630-extern-cleanup.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/631-thread_stack.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/633-atari_scc.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/634-atari_scsi.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/635-atari_input.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/636-atafb.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/amiga-a2065-ariadne-stats.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-aranym.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-ethernec.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-rom-isa.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-scsi-compile-fixes.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-scsi-reformat.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari_NCR5380-work.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/early-param.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/ethernec-kill-ETHERNEC_USE_POLL.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/ethernec-work.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/falconide_intr_lock-reentrant.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/hilkbd-warning.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/irq_lockdep.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/kmap_atomic-inline.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-53c700-scsi.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-as.patch
      - copied unchanged from r8467, dists/etch/linux-2.6/debian/patches/m68k-as.patch
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-generic-io.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-linux-gnu-crosscompile.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-mvme-scsi-rename.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-reformat.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-cuda-adb-fixes.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-finish_irq_cleanup.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-irq-plan-e.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-irq-prep.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-macii-adb-fixes.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-macmace-fixes.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-macsonic-via-alt-mapping.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-patch_A-mac68k_cvs_nubus_defines.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-patch_B-mac68k_cvs_DP8390_update.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-patch_d-via-alt-mapping.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-remove-unused-adb-header.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-revert-remaining-irq-damage.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-sonic-fixes.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/nfeth-virt_to_phys.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/pmu_queue_request-conflict.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/sun3-3x-cg3-bw2.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/sun3-3x-serial.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/sun3-numints.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/unnecessary-m68k_memoffset.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/via-pmu68k-dead-code.diff
   dists/trunk/linux-2.6/debian/patches/bugfix/m68k/zorro-resource_size_t-warnings.diff
Log:
add linux-m68k patches for 2.6.21


Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/130-adbraw.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/130-adbraw.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,44 @@
+To: linus, alan
+Cc: lkml
+Subject: [PATCH] ADB raw packets
+
+From: Linux/m68k legacy
+
+ADB: add support for raw packets
+
+---
+ drivers/macintosh/adb.c |    8 +++++---
+ include/linux/adb.h     |    1 +
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/macintosh/adb.c
++++ linux-m68k-2.6.21/drivers/macintosh/adb.c
+@@ -478,13 +478,15 @@ adb_request(struct adb_request *req, voi
+ 		use_sreq = 1;
+ 	} else
+ 		use_sreq = 0;
+-	req->nbytes = nbytes+1;
++	i = (flags & ADBREQ_RAW) ? 0 : 1;
++	req->nbytes = nbytes+i;
+ 	req->done = done;
+ 	req->reply_expected = flags & ADBREQ_REPLY;
+ 	req->data[0] = ADB_PACKET;
+ 	va_start(list, nbytes);
+-	for (i = 0; i < nbytes; ++i)
+-		req->data[i+1] = va_arg(list, int);
++	while (i < req->nbytes) {
++		req->data[i++] = va_arg(list, int);
++	}
+ 	va_end(list);
+ 
+ 	if (flags & ADBREQ_NOSEND)
+--- linux-m68k-2.6.21.orig/include/linux/adb.h
++++ linux-m68k-2.6.21/include/linux/adb.h
+@@ -76,6 +76,7 @@ struct adb_driver {
+ #define ADBREQ_REPLY	1	/* expect reply */
+ #define ADBREQ_SYNC	2	/* poll until done */
+ #define ADBREQ_NOSEND	4	/* build the request, but don't send it */
++#define ADBREQ_RAW	8	/* send raw packet (don't prepend ADB_PACKET) */
+ 
+ /* Messages sent thru the client_list notifier. You should NOT stop
+    the operation, at least not with this version */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/133-arch.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/133-arch.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,28 @@
+Subject: [PATCH] Local m68k changes
+
+Local m68k changes, _NEVER_ to be submitted upstream:
+  - Force ARCH to be m68k
+  - Append `-m68k' to EXTRAVERSION
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org> for m68k CVS only
+
+---
+ Makefile          |    2 +-
+ localversion.m68k |    1 +
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+--- linux-m68k-2.6.21.orig/Makefile
++++ linux-m68k-2.6.21/Makefile
+@@ -182,7 +182,7 @@ SUBARCH := $(shell uname -m | sed -e s/i
+ # Default value for CROSS_COMPILE is not to prefix executables
+ # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
+ 
+-ARCH		?= $(SUBARCH)
++ARCH		?= m68k
+ CROSS_COMPILE	?=
+ 
+ # Architecture as present in compile.h
+--- /dev/null
++++ linux-m68k-2.6.21/localversion.m68k
+@@ -0,0 +1 @@
++-m68k

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/134-atari-fat.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/134-atari-fat.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,102 @@
+To: linus, alan
+Cc: lkml
+Subject: [PATCH] Atari FAT updates
+
+From: Linux/m68k legacy
+
+Add support for the Atari-variant of the FAT filesystem
+
+---
+ fs/fat/inode.c |   46 +++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 43 insertions(+), 3 deletions(-)
+
+--- linux-m68k-2.6.21.orig/fs/fat/inode.c
++++ linux-m68k-2.6.21/fs/fat/inode.c
+@@ -17,6 +17,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/seq_file.h>
+ #include <linux/msdos_fs.h>
++#include <linux/major.h>
+ #include <linux/pagemap.h>
+ #include <linux/mpage.h>
+ #include <linux/buffer_head.h>
+@@ -852,7 +853,7 @@ enum {
+ 	Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid,
+ 	Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_nocase,
+ 	Opt_quiet, Opt_showexec, Opt_debug, Opt_immutable,
+-	Opt_dots, Opt_nodots,
++	Opt_dots, Opt_nodots, Opt_atari_no, Opt_atari_yes,
+ 	Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
+ 	Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
+ 	Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
+@@ -877,6 +878,9 @@ static match_table_t fat_tokens = {
+ 	{Opt_showexec, "showexec"},
+ 	{Opt_debug, "debug"},
+ 	{Opt_immutable, "sys_immutable"},
++	{Opt_atari_yes, "atari=yes"},
++	{Opt_atari_yes, "atari"},
++	{Opt_atari_no, "atari=no"},
+ 	{Opt_obsolate, "conv=binary"},
+ 	{Opt_obsolate, "conv=text"},
+ 	{Opt_obsolate, "conv=auto"},
+@@ -952,6 +956,13 @@ static int parse_options(char *options, 
+ 	opts->utf8 = opts->unicode_xlate = 0;
+ 	opts->numtail = 1;
+ 	opts->nocase = 0;
++	opts->atari = 0;
++
++#ifdef CONFIG_ATARI
++	if(MACH_IS_ATARI)
++	/* make Atari GEMDOS format the default if machine is an Atari */
++		opts->atari = 1;
++#endif
+ 	*debug = 0;
+ 
+ 	if (!options)
+@@ -1000,6 +1011,12 @@ static int parse_options(char *options, 
+ 		case Opt_immutable:
+ 			opts->sys_immutable = 1;
+ 			break;
++		case Opt_atari_yes:
++			opts->atari = 1;
++			break;
++		case Opt_atari_no:
++			opts->atari = 0;
++			break;
+ 		case Opt_uid:
+ 			if (match_int(&args[0], &option))
+ 				return 0;
+@@ -1336,8 +1353,31 @@ int fat_fill_super(struct super_block *s
+ 
+ 	total_clusters = (total_sectors - sbi->data_start) / sbi->sec_per_clus;
+ 
+-	if (sbi->fat_bits != 32)
+-		sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12;
++	if (!sbi->options.atari) {
++		if (sbi->fat_bits != 32)
++			sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12;
++	} else {
++		int sectors;
++		/* Atari GEMDOS partitions always have 16-bit fat */
++		if (sbi->fat_bits != 32)
++			sbi->fat_bits = 16;
++		/* If more clusters than fat entries in 16-bit fat, we assume
++		 * it's a real MSDOS partition with 12-bit fat.
++		 */
++		if (sbi->fat_bits != 32 && total_clusters+2 > sbi->
++			fat_length*SECTOR_SIZE*8/sbi->fat_bits)
++			sbi->fat_bits = 12;
++		/* if it's a floppy disk --> 12bit fat */
++		if (sbi->fat_bits != 32 && MAJOR(sb->s_dev) == FLOPPY_MAJOR)
++			sbi->fat_bits = 12;
++		/* if it's a ramdisk or loopback device and has one of the usual
++		 * floppy sizes -> 12bit FAT  */
++		sectors = total_sectors + sbi->data_start;
++		if (sbi->fat_bits != 32 && (MAJOR(sb->s_dev) == RAMDISK_MAJOR ||
++			 MAJOR(sb->s_dev) == LOOP_MAJOR) &&
++			(sectors == 720 || sectors == 1440 || sectors == 2880))
++			sbi->fat_bits = 12;
++	}
+ 
+ 	/* check that FAT table does not overflow */
+ 	fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits;

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/141-ide.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/141-ide.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,38 @@
+To: linus, alan
+Cc: lkml
+Subject: [PATCH] M68k IDE updates
+
+From: Linux/m68k legacy
+
+M68k IDE updates: Add m68k-isms to the generic ide_fix_driveid()
+
+---
+ drivers/ide/ide-iops.c |   17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- linux-m68k-2.6.21.orig/drivers/ide/ide-iops.c
++++ linux-m68k-2.6.21/drivers/ide/ide-iops.c
+@@ -313,6 +313,23 @@ void ide_fix_driveid (struct hd_driveid 
+ 	int i;
+ 	u16 *stringcast;
+ 
++#ifdef __mc68000__
++	if (!MACH_IS_AMIGA && !MACH_IS_MAC && !MACH_IS_Q40 && !MACH_IS_ATARI)
++		return;
++
++#ifdef M68K_IDE_SWAPW
++	if (M68K_IDE_SWAPW) {	/* fix bus byteorder first */
++		u_char *p = (u_char *)id;
++		u_char t;
++		for (i = 0; i < 512; i += 2) {
++			t = p[i];
++			p[i] = p[i+1];
++			p[i+1] = t;
++		}
++	}
++#endif
++#endif /* __mc68000__ */
++
+ 	id->config         = __le16_to_cpu(id->config);
+ 	id->cyls           = __le16_to_cpu(id->cyls);
+ 	id->reserved2      = __le16_to_cpu(id->reserved2);

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/143-ioext.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/143-ioext.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,1352 @@
+To: linus, alan
+Cc: lkml
+Subject: [PATCH] Amiga GVP I/O Extender PLIP
+
+From: Linux/m68k legacy
+
+Add a PLIP driver for the Amiga GVP I/O Extender's parallel port
+
+---
+ drivers/char/16c552.h     |  165 +++++++
+ drivers/char/ioext.h      |  107 ++++
+ drivers/char/plip_ioext.c | 1057 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 1329 insertions(+)
+
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/char/16c552.h
+@@ -0,0 +1,165 @@
++/*
++ * Definitions for the 16c552 DACE
++ * (dual-asynchronous-communications-element) used on the GVP
++ * IO-Extender.
++ *
++ * Basically this is two 16c550 uarts's and a parallel port, which is
++ * why the serial definitions should be valid for the 16c550 uart
++ * aswell.
++ *
++ * Data was taken from National Semiconductors duart 16c552
++ * data-sheets and the Texas Instruments DACE 16c552 data-sheets (the
++ * NS version of the chip is _non_ standard and their data-sheets did
++ * cost me several wasted hours of work).
++ *
++ * This file is (C) 1995 Jes Sorensen (jds at kom.auc.dk)
++ *
++ * Moved from drivers/char/ to include/linux/, because it's useful
++ * on more than just the one card. I'm using it on the hp300 DCA
++ * serial driver, for example.
++ *      -- Peter Maydell <pmaydell at chiark.greenend.org.uk> 05/1998
++ */
++
++#ifndef _16C552_H_
++#define _16C552_H_
++
++/* Serial stuff */
++
++struct uart_16c550 {
++	volatile u_char skip0;
++	volatile u_char RBR;
++	volatile u_char skip1;
++	volatile u_char IER;
++	volatile u_char skip2;
++	volatile u_char IIR;
++	volatile u_char skip3;
++	volatile u_char LCR;
++	volatile u_char skip4;
++	volatile u_char MCR;
++	volatile u_char skip5;
++	volatile u_char LSR;
++	volatile u_char skip6;
++	volatile u_char MSR;
++	volatile u_char skip7;
++	volatile u_char SCR;
++};
++
++#define THR RBR
++#define FCR IIR
++#define DLL RBR
++#define DLM IER
++#define AFR IIR
++
++/*
++ * Bit-defines for the various registers.
++ */
++
++
++/* IER */
++
++#define ERDAI         (1<<0)
++#define ETHREI        (1<<1)
++#define ELSI          (1<<2)
++#define EMSI          (1<<3)
++
++/* IIR - Interrupt Ident. Register */
++
++#define IRQ_PEND      (1<<0) /* NOTE: IRQ_PEND=0 implies irq pending */
++#define IRQ_ID1       (1<<1)
++#define IRQ_ID2       (1<<2)
++#define IRQ_ID3       (1<<3)
++#define FIFO_ENA0     (1<<6) /* Both these are set when FCR(1<<0)=1 */
++#define FIFO_ENA1     (1<<7)
++
++#define IRQ_RLS  (IRQ_ID1 | IRQ_ID2)
++#define IRQ_RDA  (IRQ_ID2)
++#define IRQ_CTI  (IRQ_ID2 | IRQ_ID3)
++#define IRQ_THRE (IRQ_ID1)
++#define IRQ_MS   0
++
++/* FCR - FIFO Control Register */
++
++#define FIFO_ENA      (1<<0)
++#define RCVR_FIFO_RES (1<<1)
++#define XMIT_FIFO_RES (1<<2)
++#define DMA_MODE_SEL  (1<<3)
++#define RCVR_TRIG_LSB (1<<6)
++#define RCVR_TRIG_MSB (1<<7)
++
++#define FIFO_TRIG_1   0x00
++#define FIFO_TRIG_4   RCVR_TRIG_LSB
++#define FIFO_TRIG_8   RCVR_TRIG_MSB
++#define FIFO_TRIG_14  RCVR_TRIG_LSB|RCVR_TRIG_MSB
++
++/* LCR - Line Control Register */
++
++#define WLS0          (1<<0)
++#define WLS1          (1<<1)
++#define STB           (1<<2)
++#define PEN           (1<<3)
++#define EPS           (1<<4)
++#define STICK_PARITY  (1<<5)
++#define SET_BREAK     (1<<6)
++#define DLAB          (1<<7)
++
++#define data_5bit      0x00
++#define data_6bit      0x01
++#define data_7bit      0x02
++#define data_8bit      0x03
++
++
++/* MCR - Modem Control Register */
++
++#define DTR           (1<<0)
++#define RTS           (1<<1)
++#define OUT1          (1<<2)
++#define OUT2          (1<<3)
++#define LOOP          (1<<4)
++
++/* LSR - Line Status Register */
++
++#define DR            (1<<0)
++#define OE            (1<<1)
++#define PE            (1<<2)
++#define FE            (1<<3)
++#define BI            (1<<4)
++#define THRE          (1<<5)
++#define TEMT          (1<<6)
++#define RCVR_FIFO_ERR (1<<7)
++
++/* MSR - Modem Status Register */
++
++#define DCTS          (1<<0)
++#define DDSR          (1<<1)
++#define TERI          (1<<2)
++#define DDCD          (1<<3)
++#define CTS           (1<<4)
++#define DSR           (1<<5)
++#define RING_I        (1<<6)
++#define DCD           (1<<7)
++
++/* AFR - Alternate Function Register */
++
++#define CONCUR_WRITE  (1<<0)
++#define BAUDOUT       (1<<1)
++#define RXRDY         (1<<2)
++
++/* Parallel stuff */
++
++/*
++ * Unfortunately National Semiconductors did not supply the
++ * specifications for the parallel port in the chip :-(
++ * TI succed though, so here they are :-)
++ *
++ * Defines for the bits can be found by including <linux/lp.h>
++ */
++struct IOEXT_par {
++	volatile u_char skip0;
++	volatile u_char DATA;
++	volatile u_char skip1;
++	volatile u_char STATUS;
++	volatile u_char skip2;
++	volatile u_char CTRL;
++};
++
++#endif
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/char/ioext.h
+@@ -0,0 +1,107 @@
++/*
++ * Shared data structure for GVP IO-Extender support.
++ *
++ * Merge of ioext.h and ser_ioext.h
++ */
++#ifndef _IOEXT_H_
++#define _IOEXT_H_
++
++#include <linux/netdevice.h>
++
++#include "16c552.h"
++
++#define MAX_IOEXT 5 /*
++		     * The maximum number of io-extenders is 5, as you
++		     * can't have more than 5 ZII boards in any Amiga.
++		     */
++
++#define UART_CLK 7372800
++
++#define IOEXT_BAUD_BASE (UART_CLK / 16)
++
++#define IOEXT_MAX_LINES 2
++
++#define IOEXT_PAR_PLIP  0x0001
++#define IOEXT_PAR_LP    0x0002
++
++
++/*
++ * Macros for the serial driver.
++ */
++#define curruart(info) ((struct uart_16c550 *)(info->port))
++
++#define ser_DTRon(info)  curruart(info)->MCR |=  DTR
++#define ser_RTSon(info)  curruart(info)->MCR |=  RTS
++#define ser_DTRoff(info) curruart(info)->MCR &= ~DTR
++#define ser_RTSoff(info) curruart(info)->MCR &= ~RTS
++
++
++/*
++ * CNTR defines (copied from the GVP SCSI-driver file gvp11.h
++ */
++#define GVP_BUSY	(1<<0)
++#define GVP_IRQ_PEND	(1<<1)
++#define GVP_IRQ_ENA	(1<<3)
++#define GVP_DIR_WRITE   (1<<4)
++
++
++/*
++ * CTRL defines
++ */
++#define PORT0_MIDI   (1<<0)  /* CLR = DRIVERS         SET = MIDI      */
++#define PORT1_MIDI   (1<<1)  /* CLR = DRIVERS         SET = MIDI      */
++#define PORT0_DRIVER (1<<2)  /* CLR = RS232,          SET = MIDI      */
++#define PORT1_DRIVER (1<<3)  /* CLR = RS232,          SET = MIDI      */
++#define IRQ_SEL      (1<<4)  /* CLR = INT2,           SET = INT6      */
++#define ROM_BANK_SEL (1<<5)  /* CLR = LOW 32K,        SET = HIGH 32K  */
++#define PORT0_CTRL   (1<<6)  /* CLR = RTSx or RXRDYx, SET = RTSx ONLY */
++#define PORT1_CTRL   (1<<7)  /* CLR = RTSx or RXRDYx, SET = RTSx ONLY */
++
++
++/*
++ * This is the struct describing the registers on the IO-Extender.
++ * NOTE: The board uses a dual uart (16c552), which should be equal to
++ * two 16c550 uarts.
++ */
++typedef struct {
++	char gap0[0x41];
++	volatile unsigned char CNTR;	/* GVP DMAC CNTR (status register)   */
++	char gap1[0x11e];
++	struct uart_16c550 uart0;	/* The first uart                    */
++	char gap2[0xf0];
++	struct uart_16c550 uart1;	/* The second uart                   */
++	char gap3[0xf0];
++	struct IOEXT_par par;		/* The parallel port                 */
++	char gap4[0xfb];
++	volatile unsigned char CTRL;	/* The control-register on the board */
++} IOEXT_struct;
++
++
++typedef struct {
++	int num_uarts;
++	int line[IOEXT_MAX_LINES];
++	volatile struct uart_16c550 *uart[IOEXT_MAX_LINES];
++	IOEXT_struct *board;
++	int spurious_count;
++	unsigned char par_use;		/* IOEXT_PAR_xxx */
++#if defined(CONFIG_GVPIOEXT_PLIP) || defined(CONFIG_GVPIOEXT_PLIP_MODULE)
++	struct nt_device *dev;
++#endif
++#if defined(CONFIG_GVPIOEXT_LP) || defined(CONFIG_GVPIOEXT_LP_MODULE)
++	struct lp_struct *lp_table;
++	int lp_dev;
++	int lp_interrupt;
++#endif
++} IOExtInfoType;
++
++/* Number of detected boards.  */
++extern int ioext_num;
++extern IOExtInfoType ioext_info[MAX_IOEXT];
++
++void ioext_plip_interrupt(struct net_device *dev, int *spurious_count);
++void ioext_lp_interrupt(int dev, int *spurious_count);
++
++extern struct net_device ioext_dev_plip[3];
++extern struct lp_struct ioext_lp_table[1];
++
++#endif
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/char/plip_ioext.c
+@@ -0,0 +1,1057 @@
++/*
++ * plip_ioext: A parallel port "network" driver for GVP IO-Extender.
++ *
++ * Authors:	See drivers/net/plip.c
++ *              IO-Extender version by Steve Bennett, <msteveb at ozemail.com.au>
++ *
++ * This driver is for use with a 5-bit cable (LapLink (R) cable).
++ */
++
++static const char *version = "NET3 PLIP version 2.2/m68k";
++
++#define __NO_VERSION__
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/slab.h>
++#include <linux/termios.h>
++#include <linux/tty.h>
++#include <linux/serial.h>
++
++#include <asm/setup.h>
++#include <asm/irq.h>
++#include <asm/amigahw.h>
++#include <asm/amigaints.h>
++#include <linux/zorro.h>
++
++#include <linux/kernel.h>
++#include <linux/fcntl.h>
++#include <linux/string.h>
++#include <linux/ptrace.h>
++#include <linux/if_ether.h>
++
++#include <asm/system.h>
++
++#include <linux/in.h>
++#include <linux/delay.h>
++/*#include <linux/lp_m68k.h>*/
++
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/inetdevice.h>
++#include <linux/skbuff.h>
++#include <linux/if_plip.h>
++
++#include <linux/tqueue.h>
++#include <linux/ioport.h>
++#include <linux/bitops.h>
++#include <asm/byteorder.h>
++
++#include "ioext.h"
++
++#define DEBUG 0
++
++/* Map 'struct device *' to our control structure */
++#define PLIP_DEV(DEV) (&ioext_info[(DEV)->irq])
++
++/************************************************************************
++**
++** PLIP definitions
++**
++*************************************************************************
++*/
++
++/* Use 0 for production, 1 for verification, >2 for debug */
++#ifndef NET_DEBUG
++#define NET_DEBUG 2
++#endif
++static unsigned int net_debug = NET_DEBUG;
++
++/* In micro second */
++#define PLIP_DELAY_UNIT       1
++
++/* Connection time out = PLIP_TRIGGER_WAIT * PLIP_DELAY_UNIT usec */
++#define PLIP_TRIGGER_WAIT	 500
++
++/* Nibble time out = PLIP_NIBBLE_WAIT * PLIP_DELAY_UNIT usec */
++#define PLIP_NIBBLE_WAIT        3000
++
++#define PAR_DATA(dev)     ((dev)->base_addr+0)
++#define PAR_STATUS(dev)   ((dev)->base_addr+2)
++#define PAR_CONTROL(dev)  ((dev)->base_addr+4)
++
++static void enable_par_irq(struct device *dev, int on);
++static int plip_init(struct device *dev);
++
++/* Bottom halfs */
++static void plip_kick_bh(struct device *dev);
++static void plip_bh(struct device *dev);
++
++/* Functions for DEV methods */
++static int plip_rebuild_header(struct sk_buff *skb);
++static int plip_tx_packet(struct sk_buff *skb, struct device *dev);
++static int plip_open(struct device *dev);
++static int plip_close(struct device *dev);
++static struct enet_statistics *plip_get_stats(struct device *dev);
++static int plip_config(struct device *dev, struct ifmap *map);
++static int plip_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
++
++enum plip_connection_state {
++	PLIP_CN_NONE=0,
++	PLIP_CN_RECEIVE,
++	PLIP_CN_SEND,
++	PLIP_CN_CLOSING,
++	PLIP_CN_ERROR
++};
++
++enum plip_packet_state {
++	PLIP_PK_DONE=0,
++	PLIP_PK_TRIGGER,
++	PLIP_PK_LENGTH_LSB,
++	PLIP_PK_LENGTH_MSB,
++	PLIP_PK_DATA,
++	PLIP_PK_CHECKSUM
++};
++
++enum plip_nibble_state {
++	PLIP_NB_BEGIN,
++	PLIP_NB_1,
++	PLIP_NB_2,
++};
++
++struct plip_local {
++	enum plip_packet_state state;
++	enum plip_nibble_state nibble;
++	union {
++		struct {
++#if defined(__LITTLE_ENDIAN)
++			unsigned char lsb;
++			unsigned char msb;
++#elif defined(__BIG_ENDIAN)
++			unsigned char msb;
++			unsigned char lsb;
++#else
++#error  "Please fix the endianness defines in <asm/byteorder.h>"
++#endif
++		} b;
++		unsigned short h;
++	} length;
++	unsigned short byte;
++	unsigned char  checksum;
++	unsigned char  data;
++	struct sk_buff *skb;
++};
++
++struct net_local {
++	struct enet_statistics enet_stats;
++	struct tq_struct immediate;
++	struct tq_struct deferred;
++	struct plip_local snd_data;
++	struct plip_local rcv_data;
++	unsigned long  trigger;
++	unsigned long  nibble;
++	enum plip_connection_state connection;
++	unsigned short timeout_count;
++	char is_deferred;
++	int (*orig_rebuild_header)(struct sk_buff *skb);
++};
++
++struct device ioext_dev_plip[] = {
++	{
++		"plip0",
++		0, 0, 0, 0,    /* memory */
++		0, 0,    /* base, irq */
++		0, 0, 0, NULL, plip_init
++	},
++	{
++		"plip1",
++		0, 0, 0, 0,    /* memory */
++		0, 0,    /* base, irq */
++		0, 0, 0, NULL, plip_init
++	},
++	{
++		"plip2",
++		0, 0, 0, 0,    /* memory */
++		0, 0,    /* base, irq */
++		0, 0, 0, NULL, plip_init
++	}
++};
++
++/*
++ * Check for and handle an interrupt for this PLIP device.
++ *
++ */
++void ioext_plip_interrupt(struct device *dev, int *spurious_count)
++{
++	struct net_local *nl;
++	struct plip_local *rcv;
++	unsigned char c0;
++	unsigned long flags;
++
++	nl = (struct net_local *)dev->priv;
++	rcv = &nl->rcv_data;
++
++	c0 = z_readb(PAR_STATUS(dev));
++
++	if (dev->interrupt) {
++		return;
++	}
++
++	if ((c0 & 0xf8) != 0xc0) {
++		/* Not for us */
++		++*spurious_count;
++		return;
++	}
++
++	*spurious_count = 0;
++	dev->interrupt = 1;
++
++	local_irq_save(flags);
++
++	switch (nl->connection) {
++	case PLIP_CN_CLOSING:
++		dev->tbusy = 0;
++	case PLIP_CN_NONE:
++	case PLIP_CN_SEND:
++		dev->last_rx = jiffies;
++		rcv->state = PLIP_PK_TRIGGER;
++		nl->connection = PLIP_CN_RECEIVE;
++		nl->timeout_count = 0;
++		queue_task(&nl->immediate, &tq_immediate);
++		mark_bh(IMMEDIATE_BH);
++		local_irq_restore(flags);
++#if 0
++		printk("%s: receive irq in SEND/NONE/CLOSING (%d) ok\n",
++		       dev->name, nl->connection);
++#endif
++		break;
++
++	case PLIP_CN_RECEIVE:
++		local_irq_restore(flags);
++		printk("%s: receive interrupt when receiving packet\n",
++		       dev->name);
++		break;
++
++	case PLIP_CN_ERROR:
++		local_irq_restore(flags);
++		printk("%s: receive interrupt in error state\n", dev->name);
++		break;
++	}
++}
++
++
++/* Bottom half handler for the delayed request.
++   This routine is kicked by do_timer().
++   Request `plip_bh' to be invoked. */
++static void
++plip_kick_bh(struct device *dev)
++{
++	struct net_local *nl = (struct net_local *)dev->priv;
++
++	if (nl->is_deferred) {
++		queue_task(&nl->immediate, &tq_immediate);
++		mark_bh(IMMEDIATE_BH);
++	}
++}
++
++/* Forward declarations of internal routines */
++static int plip_none(struct device *, struct net_local *,
++		     struct plip_local *, struct plip_local *);
++static int plip_receive_packet(struct device *, struct net_local *,
++			       struct plip_local *, struct plip_local *);
++static int plip_send_packet(struct device *, struct net_local *,
++			    struct plip_local *, struct plip_local *);
++static int plip_connection_close(struct device *, struct net_local *,
++				 struct plip_local *, struct plip_local *);
++static int plip_error(struct device *, struct net_local *,
++		      struct plip_local *, struct plip_local *);
++static int plip_bh_timeout_error(struct device *dev, struct net_local *nl,
++				 struct plip_local *snd,
++				 struct plip_local *rcv,
++				 int error);
++
++#define OK        0
++#define TIMEOUT   1
++#define ERROR     2
++
++typedef int (*plip_func)(struct device *dev, struct net_local *nl,
++			 struct plip_local *snd, struct plip_local *rcv);
++
++static plip_func connection_state_table[] =
++{
++	plip_none,
++	plip_receive_packet,
++	plip_send_packet,
++	plip_connection_close,
++	plip_error
++};
++
++/*
++** enable_par_irq()
++**
++** Enable or disable parallel irq for 'dev' according to 'on'.
++**
++** It is NOT possible to disable only the parallel irq.
++** So we disable the board interrupt instead. This means that
++** during reception of a PLIP packet, no serial interrupts can
++** happen. Sorry.
++*/
++static void enable_par_irq(struct device *dev, int on)
++{
++	if (on) {
++		PLIP_DEV(dev)->board->CNTR |= GVP_IRQ_ENA;
++	}
++	else {
++		PLIP_DEV(dev)->board->CNTR &= ~GVP_IRQ_ENA;
++	}
++}
++
++/* Bottom half handler of PLIP. */
++static void
++plip_bh(struct device *dev)
++{
++	struct net_local *nl = (struct net_local *)dev->priv;
++	struct plip_local *snd = &nl->snd_data;
++	struct plip_local *rcv = &nl->rcv_data;
++	plip_func f;
++	int r;
++
++	nl->is_deferred = 0;
++	f = connection_state_table[nl->connection];
++	if ((r = (*f)(dev, nl, snd, rcv)) != OK
++	    && (r = plip_bh_timeout_error(dev, nl, snd, rcv, r)) != OK) {
++		nl->is_deferred = 1;
++		queue_task(&nl->deferred, &tq_timer);
++	}
++}
++
++static int
++plip_bh_timeout_error(struct device *dev, struct net_local *nl,
++		      struct plip_local *snd, struct plip_local *rcv,
++		      int error)
++{
++	unsigned char c0;
++	unsigned long flags;
++
++	local_irq_save(flags);
++	if (nl->connection == PLIP_CN_SEND) {
++
++		if (error != ERROR) { /* Timeout */
++			nl->timeout_count++;
++			if ((snd->state == PLIP_PK_TRIGGER
++			     && nl->timeout_count <= 10)
++			    || nl->timeout_count <= 3) {
++				local_irq_restore(flags);
++				/* Try again later */
++				return TIMEOUT;
++			}
++			c0 = z_readb(PAR_STATUS(dev));
++			printk(KERN_INFO "%s: transmit timeout(%d,%02x)\n",
++			       dev->name, snd->state, c0);
++		}
++		nl->enet_stats.tx_errors++;
++		nl->enet_stats.tx_aborted_errors++;
++	} else if (nl->connection == PLIP_CN_RECEIVE) {
++		if (rcv->state == PLIP_PK_TRIGGER) {
++			/* Transmission was interrupted. */
++			local_irq_restore(flags);
++			return OK;
++		}
++		if (error != ERROR) { /* Timeout */
++			if (++nl->timeout_count <= 3) {
++				local_irq_restore(flags);
++				/* Try again later */
++				return TIMEOUT;
++			}
++			c0 = z_readb(PAR_STATUS(dev));
++			printk(KERN_INFO "%s: receive timeout(%d,%02x)\n",
++			       dev->name, rcv->state, c0);
++		}
++		nl->enet_stats.rx_dropped++;
++	}
++	rcv->state = PLIP_PK_DONE;
++	if (rcv->skb) {
++		kfree_skb(rcv->skb);
++		rcv->skb = NULL;
++	}
++	snd->state = PLIP_PK_DONE;
++	if (snd->skb) {
++		dev_kfree_skb(snd->skb);
++		snd->skb = NULL;
++	}
++	enable_par_irq(dev, 0);
++	dev->tbusy = 1;
++	nl->connection = PLIP_CN_ERROR;
++	z_writeb(0x00, PAR_DATA(dev));
++	local_irq_restore(flags);
++
++	return TIMEOUT;
++}
++
++static int
++plip_none(struct device *dev, struct net_local *nl,
++	  struct plip_local *snd, struct plip_local *rcv)
++{
++	return OK;
++}
++
++/* PLIP_RECEIVE --- receive a byte(two nibbles)
++   Returns OK on success, TIMEOUT on timeout */
++inline static int
++plip_receive(struct device *dev, unsigned short nibble_timeout,
++	     enum plip_nibble_state *ns_p, unsigned char *data_p)
++{
++	unsigned char c0, c1;
++	unsigned int cx;
++
++	switch (*ns_p) {
++	case PLIP_NB_BEGIN:
++		cx = nibble_timeout;
++		while (1) {
++			c0 = z_readb(PAR_STATUS(dev));
++			udelay(PLIP_DELAY_UNIT);
++			if ((c0 & 0x80) == 0) {
++				c1 = z_readb(PAR_STATUS(dev));
++				if (c0 == c1)
++					break;
++			}
++			if (--cx == 0)
++				return TIMEOUT;
++		}
++#if 0
++		printk("received first nybble: %02X -> %02X\n",
++		       c0, (c0 >> 3) & 0x0F);
++#endif
++		*data_p = (c0 >> 3) & 0x0f;
++		z_writeb(0x10, PAR_DATA(dev)); /* send ACK */
++		*ns_p = PLIP_NB_1;
++
++	case PLIP_NB_1:
++		cx = nibble_timeout;
++		while (1) {
++			c0 = z_readb(PAR_STATUS(dev));
++			udelay(PLIP_DELAY_UNIT);
++			if (c0 & 0x80) {
++				c1 = z_readb(PAR_STATUS(dev));
++				if (c0 == c1)
++					break;
++			}
++			if (--cx == 0)
++				return TIMEOUT;
++		}
++#if 0
++		printk("received second nybble: %02X -> %02X\n",
++		       c0, (c0 << 1) & 0xF0);
++#endif
++		*data_p |= (c0 << 1) & 0xf0;
++		z_writeb(0x00, PAR_DATA(dev)); /* send ACK */
++		*ns_p = PLIP_NB_BEGIN;
++	case PLIP_NB_2:
++		break;
++	}
++	return OK;
++}
++
++/* PLIP_RECEIVE_PACKET --- receive a packet */
++static int
++plip_receive_packet(struct device *dev, struct net_local *nl,
++		    struct plip_local *snd, struct plip_local *rcv)
++{
++	unsigned short nibble_timeout = nl->nibble;
++	unsigned char *lbuf;
++	unsigned long flags;
++
++	switch (rcv->state) {
++	case PLIP_PK_TRIGGER:
++		enable_par_irq(dev, 0);
++		dev->interrupt = 0;
++		z_writeb(0x01, PAR_DATA(dev)); /* send ACK */
++		if (net_debug > 2)
++			printk(KERN_DEBUG "%s: receive start\n", dev->name);
++		rcv->state = PLIP_PK_LENGTH_LSB;
++		rcv->nibble = PLIP_NB_BEGIN;
++
++	case PLIP_PK_LENGTH_LSB:
++		if (snd->state != PLIP_PK_DONE) {
++			if (plip_receive(dev, nl->trigger,
++					 &rcv->nibble, &rcv->length.b.lsb)) {
++				/* collision, here dev->tbusy == 1 */
++				rcv->state = PLIP_PK_DONE;
++				nl->is_deferred = 1;
++				nl->connection = PLIP_CN_SEND;
++				queue_task(&nl->deferred, &tq_timer);
++				enable_par_irq(dev, 1);
++				return OK;
++			}
++		} else {
++			if (plip_receive(dev, nibble_timeout,
++					 &rcv->nibble, &rcv->length.b.lsb))
++				return TIMEOUT;
++		}
++		rcv->state = PLIP_PK_LENGTH_MSB;
++
++	case PLIP_PK_LENGTH_MSB:
++		if (plip_receive(dev, nibble_timeout,
++				 &rcv->nibble, &rcv->length.b.msb))
++			return TIMEOUT;
++		if (rcv->length.h > dev->mtu + dev->hard_header_len
++		    || rcv->length.h < 8) {
++			printk(KERN_INFO "%s: bogus packet size %d.\n",
++			       dev->name, rcv->length.h);
++			return ERROR;
++		}
++		/* Malloc up new buffer. */
++		rcv->skb = dev_alloc_skb(rcv->length.h);
++		if (rcv->skb == NULL) {
++			printk(KERN_INFO "%s: Memory squeeze.\n", dev->name);
++			return ERROR;
++		}
++		skb_put(rcv->skb,rcv->length.h);
++		rcv->skb->dev = dev;
++		rcv->state = PLIP_PK_DATA;
++		rcv->byte = 0;
++		rcv->checksum = 0;
++
++	case PLIP_PK_DATA:
++		lbuf = rcv->skb->data;
++		do
++			if (plip_receive(dev, nibble_timeout,
++					 &rcv->nibble, &lbuf[rcv->byte]))
++				return TIMEOUT;
++		while (++rcv->byte < rcv->length.h);
++		do
++			rcv->checksum += lbuf[--rcv->byte];
++		while (rcv->byte);
++		rcv->state = PLIP_PK_CHECKSUM;
++
++	case PLIP_PK_CHECKSUM:
++		if (plip_receive(dev, nibble_timeout,
++				 &rcv->nibble, &rcv->data))
++			return TIMEOUT;
++		if (rcv->data != rcv->checksum) {
++			nl->enet_stats.rx_crc_errors++;
++			if (net_debug)
++				printk(KERN_INFO "%s: checksum error\n",
++				       dev->name);
++			return ERROR;
++		}
++		rcv->state = PLIP_PK_DONE;
++
++	case PLIP_PK_DONE:
++		/* Inform the upper layer for the arrival of a packet. */
++		rcv->skb->protocol=eth_type_trans(rcv->skb, dev);
++		netif_rx(rcv->skb);
++		nl->enet_stats.rx_packets++;
++		rcv->skb = NULL;
++		if (net_debug > 2)
++			printk(KERN_DEBUG "%s: receive end\n", dev->name);
++
++		/* Close the connection. */
++		z_writeb (0x00, PAR_DATA(dev));
++
++		local_irq_save(flags);
++		if (snd->state != PLIP_PK_DONE) {
++			nl->connection = PLIP_CN_SEND;
++			local_irq_restore(flags);
++			queue_task(&nl->immediate, &tq_immediate);
++			mark_bh(IMMEDIATE_BH);
++			enable_par_irq(dev, 1);
++			return OK;
++		} else {
++			nl->connection = PLIP_CN_NONE;
++			local_irq_restore(flags);
++			enable_par_irq(dev, 1);
++			return OK;
++		}
++	}
++	return OK;
++}
++
++/* PLIP_SEND --- send a byte (two nibbles)
++   Returns OK on success, TIMEOUT when timeout    */
++inline static int
++plip_send(struct device *dev, unsigned short nibble_timeout,
++	  enum plip_nibble_state *ns_p, unsigned char data)
++{
++	unsigned char c0;
++	unsigned int cx;
++
++	switch (*ns_p) {
++	case PLIP_NB_BEGIN:
++		z_writeb((data & 0x0f), PAR_DATA(dev));
++		*ns_p = PLIP_NB_1;
++
++	case PLIP_NB_1:
++		z_writeb(0x10 | (data & 0x0f), PAR_DATA(dev));
++		cx = nibble_timeout;
++		while (1) {
++			c0 = z_readb(PAR_STATUS(dev));
++			if ((c0 & 0x80) == 0)
++				break;
++			if (--cx == 0)
++				return TIMEOUT;
++			udelay(PLIP_DELAY_UNIT);
++		}
++		z_writeb(0x10 | (data >> 4), PAR_DATA(dev));
++		*ns_p = PLIP_NB_2;
++
++	case PLIP_NB_2:
++		z_writeb((data >> 4), PAR_DATA(dev));
++		cx = nibble_timeout;
++		while (1) {
++			c0 = z_readb(PAR_STATUS(dev));
++			if (c0 & 0x80)
++				break;
++			if (--cx == 0)
++				return TIMEOUT;
++			udelay(PLIP_DELAY_UNIT);
++		}
++		*ns_p = PLIP_NB_BEGIN;
++		return OK;
++	}
++	return OK;
++}
++
++/* PLIP_SEND_PACKET --- send a packet */
++static int
++plip_send_packet(struct device *dev, struct net_local *nl,
++		 struct plip_local *snd, struct plip_local *rcv)
++{
++	unsigned short nibble_timeout = nl->nibble;
++	unsigned char *lbuf;
++	unsigned char c0;
++	unsigned int cx;
++	unsigned long flags;
++
++	if (snd->skb == NULL || (lbuf = snd->skb->data) == NULL) {
++		printk(KERN_INFO "%s: send skb lost\n", dev->name);
++		snd->state = PLIP_PK_DONE;
++		snd->skb = NULL;
++		return ERROR;
++	}
++
++	if (snd->length.h == 0) {
++		return OK;
++	}
++
++	switch (snd->state) {
++	case PLIP_PK_TRIGGER:
++		if ((z_readb(PAR_STATUS(dev)) & 0xf8) != 0x80)
++			return TIMEOUT;
++
++		/* Trigger remote rx interrupt. */
++		z_writeb(0x08, PAR_DATA(dev));
++		cx = nl->trigger;
++		while (1) {
++			udelay(PLIP_DELAY_UNIT);
++                        local_irq_save(flags);
++			if (nl->connection == PLIP_CN_RECEIVE) {
++				local_irq_restore(flags);
++				/* interrupted */
++				nl->enet_stats.collisions++;
++				if (net_debug > 1)
++					printk(KERN_INFO "%s: collision.\n",
++					       dev->name);
++				return OK;
++			}
++			c0 = z_readb(PAR_STATUS(dev));
++			if (c0 & 0x08) {
++				enable_par_irq(dev, 0);
++				if (net_debug > 2)
++					printk(KERN_DEBUG "%s: send start\n",
++					       dev->name);
++				snd->state = PLIP_PK_LENGTH_LSB;
++				snd->nibble = PLIP_NB_BEGIN;
++				nl->timeout_count = 0;
++				local_irq_restore(flags);
++				break;
++			}
++			local_irq_restore(flags);
++			if (--cx == 0) {
++				z_writeb(0x00, PAR_DATA(dev));
++				return TIMEOUT;
++			}
++		}
++
++	case PLIP_PK_LENGTH_LSB:
++		if (plip_send(dev, nibble_timeout,
++			      &snd->nibble, snd->length.b.lsb))
++			return TIMEOUT;
++		snd->state = PLIP_PK_LENGTH_MSB;
++
++	case PLIP_PK_LENGTH_MSB:
++		if (plip_send(dev, nibble_timeout,
++			      &snd->nibble, snd->length.b.msb))
++			return TIMEOUT;
++		snd->state = PLIP_PK_DATA;
++		snd->byte = 0;
++		snd->checksum = 0;
++
++	case PLIP_PK_DATA:
++		do
++			if (plip_send(dev, nibble_timeout,
++				      &snd->nibble, lbuf[snd->byte]))
++				return TIMEOUT;
++		while (++snd->byte < snd->length.h);
++		do
++			snd->checksum += lbuf[--snd->byte];
++		while (snd->byte);
++		snd->state = PLIP_PK_CHECKSUM;
++
++	case PLIP_PK_CHECKSUM:
++		if (plip_send(dev, nibble_timeout,
++			      &snd->nibble, snd->checksum))
++			return TIMEOUT;
++
++		dev_kfree_skb(snd->skb);
++		nl->enet_stats.tx_packets++;
++		snd->state = PLIP_PK_DONE;
++
++	case PLIP_PK_DONE:
++		/* Close the connection */
++		z_writeb (0x00, PAR_DATA(dev));
++		snd->skb = NULL;
++		if (net_debug > 2)
++			printk(KERN_DEBUG "%s: send end\n", dev->name);
++		nl->connection = PLIP_CN_CLOSING;
++		nl->is_deferred = 1;
++		queue_task(&nl->deferred, &tq_timer);
++		enable_par_irq(dev, 1);
++		return OK;
++	}
++	return OK;
++}
++
++static int
++plip_connection_close(struct device *dev, struct net_local *nl,
++		      struct plip_local *snd, struct plip_local *rcv)
++{
++	unsigned long flags;
++
++        local_irq_save(flags);
++	if (nl->connection == PLIP_CN_CLOSING) {
++		nl->connection = PLIP_CN_NONE;
++		dev->tbusy = 0;
++		mark_bh(NET_BH);
++	}
++	local_irq_restore(flags);
++	return OK;
++}
++
++/* PLIP_ERROR --- wait till other end settled */
++static int
++plip_error(struct device *dev, struct net_local *nl,
++	   struct plip_local *snd, struct plip_local *rcv)
++{
++	unsigned char status;
++
++	status = z_readb(PAR_STATUS(dev));
++	if ((status & 0xf8) == 0x80) {
++		if (net_debug > 2)
++			printk(KERN_DEBUG "%s: reset interface.\n", dev->name);
++		nl->connection = PLIP_CN_NONE;
++		dev->tbusy = 0;
++		dev->interrupt = 0;
++		enable_par_irq(dev, 1);
++		mark_bh(NET_BH);
++	} else {
++		nl->is_deferred = 1;
++		queue_task(&nl->deferred, &tq_timer);
++	}
++
++	return OK;
++}
++
++/* We don't need to send arp, for plip is point-to-point. */
++static int
++plip_rebuild_header(struct sk_buff *skb)
++{
++	struct device *dev = skb->dev;
++	struct net_local *nl = (struct net_local *)dev->priv;
++	struct ethhdr *eth = (struct ethhdr *)skb->data;
++	int i;
++
++	if ((dev->flags & IFF_NOARP)==0)
++		return nl->orig_rebuild_header(skb);
++
++	if (eth->h_proto != __constant_htons(ETH_P_IP)
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++	    && eth->h_proto != __constant_htons(ETH_P_IPV6)
++#endif
++		) {
++		printk(KERN_ERR "plip_rebuild_header: Don't know how to resolve type %d addresses?\n", (int)eth->h_proto);
++		memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
++		return 0;
++	}
++
++	for (i=0; i < ETH_ALEN - sizeof(u32); i++)
++		eth->h_dest[i] = 0xfc;
++#if 0
++	*(u32 *)(eth->h_dest+i) = dst;
++#else
++	/* Do not want to include net/route.h here.
++	 * In any case, it is TOP of silliness to emulate
++	 * hardware addresses on PtP link. --ANK
++	 */
++	*(u32 *)(eth->h_dest+i) = 0;
++#endif
++	return 0;
++}
++
++static int
++plip_tx_packet(struct sk_buff *skb, struct device *dev)
++{
++	struct net_local *nl = (struct net_local *)dev->priv;
++	struct plip_local *snd = &nl->snd_data;
++	unsigned long flags;
++
++	if (dev->tbusy)
++		return 1;
++
++	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
++		printk(KERN_ERR "%s: Transmitter access conflict.\n",
++		       dev->name);
++		return 1;
++	}
++
++	if (skb->len > dev->mtu + dev->hard_header_len) {
++		printk(KERN_ERR "%s: packet too big, %d.\n",
++		       dev->name, (int)skb->len);
++		dev->tbusy = 0;
++		return 0;
++	}
++
++	if (net_debug > 2)
++		printk(KERN_DEBUG "%s: send request\n", dev->name);
++
++	local_irq_save(flags);
++	dev->trans_start = jiffies;
++	snd->skb = skb;
++	snd->length.h = skb->len;
++	snd->state = PLIP_PK_TRIGGER;
++	if (nl->connection == PLIP_CN_NONE) {
++		nl->connection = PLIP_CN_SEND;
++		nl->timeout_count = 0;
++	}
++	queue_task(&nl->immediate, &tq_immediate);
++	mark_bh(IMMEDIATE_BH);
++	local_irq_restore(flags);
++
++	return 0;
++}
++
++/* Open/initialize the board.  This is called (in the current kernel)
++   sometime after booting when the 'ifconfig' program is run.
++
++ */
++static int
++plip_open(struct device *dev)
++{
++	struct net_local *nl = (struct net_local *)dev->priv;
++	struct in_device *in_dev;
++
++#if defined(CONFIG_GVPIOEXT_LP) || defined(CONFIG_GVPIOEXT_LP_MODULE)
++	/* Yes, there is a race condition here. Fix it later */
++	if (PLIP_DEV(dev)->par_use & IOEXT_PAR_LP) {
++		/* Can't open if lp is in use */
++#if DEBUG
++		printk("par is in use by lp\n");
++#endif
++		return(-EBUSY);
++	}
++#endif
++	PLIP_DEV(dev)->par_use |= IOEXT_PAR_PLIP;
++
++#if DEBUG
++	printk("plip_open(): sending 00 to data port\n");
++#endif
++
++	/* Clear the data port. */
++	z_writeb (0x00, PAR_DATA(dev));
++
++#if DEBUG
++	printk("plip_open(): sent\n");
++#endif
++
++	/* Initialize the state machine. */
++	nl->rcv_data.state = nl->snd_data.state = PLIP_PK_DONE;
++	nl->rcv_data.skb = nl->snd_data.skb = NULL;
++	nl->connection = PLIP_CN_NONE;
++	nl->is_deferred = 0;
++
++	/* Fill in the MAC-level header.
++	   (ab)Use "dev->broadcast" to store point-to-point MAC address.
++
++	   PLIP doesn't have a real mac address, but we need to create one
++	   to be DOS compatible.  */
++	memset(dev->dev_addr,  0xfc, ETH_ALEN);
++	memset(dev->broadcast, 0xfc, ETH_ALEN);
++
++	if ((in_dev=dev->ip_ptr) != NULL) {
++		/*
++		 *	Any address will do - we take the first
++		 */
++		struct in_ifaddr *ifa=in_dev->ifa_list;
++		if (ifa != NULL) {
++			memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
++			memcpy(dev->broadcast+2, &ifa->ifa_address, 4);
++		}
++	}
++
++	dev->interrupt = 0;
++	dev->start = 1;
++	dev->tbusy = 0;
++
++	MOD_INC_USE_COUNT;
++
++	/* Enable rx interrupt. */
++	enable_par_irq(dev, 1);
++
++	return 0;
++}
++
++/* The inverse routine to plip_open (). */
++static int
++plip_close(struct device *dev)
++{
++	struct net_local *nl = (struct net_local *)dev->priv;
++	struct plip_local *snd = &nl->snd_data;
++	struct plip_local *rcv = &nl->rcv_data;
++	unsigned long flags;
++
++	dev->tbusy = 1;
++	dev->start = 0;
++        local_irq_save(flags);
++	nl->is_deferred = 0;
++	nl->connection = PLIP_CN_NONE;
++	local_irq_restore(flags);
++	z_writeb(0x00, PAR_DATA(dev));
++
++	snd->state = PLIP_PK_DONE;
++	if (snd->skb) {
++		dev_kfree_skb(snd->skb);
++		snd->skb = NULL;
++	}
++	rcv->state = PLIP_PK_DONE;
++	if (rcv->skb) {
++		kfree_skb(rcv->skb);
++		rcv->skb = NULL;
++	}
++
++	PLIP_DEV(dev)->par_use &= ~IOEXT_PAR_PLIP;
++
++	MOD_DEC_USE_COUNT;
++	return 0;
++}
++
++static struct enet_statistics *
++plip_get_stats(struct device *dev)
++{
++	struct net_local *nl = (struct net_local *)dev->priv;
++	struct enet_statistics *r = &nl->enet_stats;
++
++	return r;
++}
++
++static int
++plip_config(struct device *dev, struct ifmap *map)
++{
++	if (dev->flags & IFF_UP)
++		return -EBUSY;
++
++	printk(KERN_INFO "%s: This interface is autodetected (ignored).\n",
++	       dev->name);
++
++	return 0;
++}
++
++static int
++plip_ioctl(struct device *dev, struct ifreq *rq, int cmd)
++{
++	struct net_local *nl = (struct net_local *) dev->priv;
++	struct plipconf *pc = (struct plipconf *) &rq->ifr_data;
++
++	switch(pc->pcmd) {
++	case PLIP_GET_TIMEOUT:
++		pc->trigger = nl->trigger;
++		pc->nibble  = nl->nibble;
++		break;
++	case PLIP_SET_TIMEOUT:
++		nl->trigger = pc->trigger;
++		nl->nibble  = pc->nibble;
++		break;
++	default:
++		return -EOPNOTSUPP;
++	}
++	return 0;
++}
++
++/*
++ * Detect and initialize all IO-Extenders in this system.
++ *
++ * Both PLIP and serial devices are configured.
++ */
++int plip_init(struct device *dev)
++{
++	IOEXT_struct *board;
++	struct net_local *nl;
++
++	if (ioext_num == 0) {
++		printk(KERN_INFO "%s\n", version);
++	}
++
++	board = PLIP_DEV(dev)->board;
++	dev->base_addr = (unsigned long)&board->par.DATA;
++
++	/* Cheat and use irq to index into our table */
++	dev->irq = ioext_num;
++
++	printk(KERN_INFO "%s: IO-Extender parallel port at 0x%08lX\n", dev->name, dev->base_addr);
++
++	/* Fill in the generic fields of the device structure. */
++	ether_setup(dev);
++
++	/* Then, override parts of it */
++	dev->hard_start_xmit  = plip_tx_packet;
++	dev->open    = plip_open;
++	dev->stop    = plip_close;
++	dev->get_stats     = plip_get_stats;
++	dev->set_config    = plip_config;
++	dev->do_ioctl    = plip_ioctl;
++	dev->tx_queue_len  = 10;
++	dev->flags          = IFF_POINTOPOINT|IFF_NOARP;
++
++	/* Set the private structure */
++	dev->priv = kmalloc(sizeof (struct net_local), GFP_KERNEL);
++	if (dev->priv == NULL) {
++		printk(KERN_ERR "%s: out of memory\n", dev->name);
++		return -ENOMEM;
++	}
++	memset(dev->priv, 0, sizeof(struct net_local));
++	nl = (struct net_local *) dev->priv;
++
++	nl->orig_rebuild_header = dev->rebuild_header;
++	dev->rebuild_header   = plip_rebuild_header;
++
++	/* Initialize constants */
++	nl->trigger  = PLIP_TRIGGER_WAIT;
++	nl->nibble  = PLIP_NIBBLE_WAIT;
++
++	/* Initialize task queue structures */
++	nl->immediate.next = NULL;
++	nl->immediate.sync = 0;
++	nl->immediate.routine = (void *)(void *)plip_bh;
++	nl->immediate.data = dev;
++
++	nl->deferred.next = NULL;
++	nl->deferred.sync = 0;
++	nl->deferred.routine = (void *)(void *)plip_kick_bh;
++	nl->deferred.data = dev;
++
++	/* Don't enable interrupts yet */
++
++	return 0;
++}

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/149-mc68681.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/149-mc68681.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,146 @@
+To: linus, alan
+Cc: lkml
+Subject: [PATCH] MC68681 DUART
+
+From: Linux/m68k legacy
+
+MC68681 DUART register definitions for the Amiga MultiFace III serial driver.
+
+---
+ drivers/char/mc68681.h |  131 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 131 insertions(+)
+
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/char/mc68681.h
+@@ -0,0 +1,131 @@
++#ifndef _MC68681_H_
++#define _MC68681_H_
++
++/*
++ * This describes an MC68681 DUART. It has almost only overlayed registers, which
++ * the structure very ugly.
++ * Note that the ri-register isn't really a register of the duart but a kludge of bsc
++ * to make the ring indicator available.
++ *
++ * The data came from the MFC-31-Developer Kit (from Ralph Seidel,
++ * zodiac at darkness.gun.de) and the data sheet of Phillip's clone device (SCN68681)
++ * (from Richard Hirst, srh at gpt.co.uk)
++ *
++ * 11.11.95 copyright Joerg Dorchain (dorchain at mpi-sb.mpg.de)
++ *
++ */
++
++struct duarthalf {
++union {
++volatile u_char mr1; /* rw */
++volatile u_char mr2; /* rw */
++}  mr;
++volatile u_char ri;   /* special, read */
++union {
++volatile u_char sr;  /* read */
++volatile u_char csr; /* write */
++} sr_csr;
++u_char pad1;
++volatile u_char cr; /* write */
++u_char pad2;
++union {
++volatile u_char rhr; /* read */
++volatile u_char thr; /* write */
++} hr;
++u_char pad3;
++};
++
++struct duart {
++struct duarthalf pa;
++union {
++volatile u_char ipcr; /* read */
++volatile u_char acr;  /* write */
++} ipcr_acr;
++u_char pad1;
++union {
++volatile u_char isr; /* read */
++volatile u_char imr; /* write */
++} ir;
++u_char pad2;
++volatile u_char ctu;
++u_char pad3;
++volatile u_char ctl;
++u_char pad4;
++struct duarthalf pb;
++volatile u_char ivr;
++u_char pad5;
++union {
++volatile u_char ipr; /* read */
++volatile u_char opcr; /* write */
++} ipr_opcr;
++u_char pad6;
++union {
++volatile u_char start; /* read */
++volatile u_char sopc; /* write */
++} start_sopc;
++u_char pad7;
++union {
++volatile u_char stop; /* read */
++volatile u_char ropc; /* write */
++} stop_ropc;
++u_char pad8;
++};
++
++#define MR1_BITS 3
++#define MR1_5BITS 0
++#define MR1_6BITS 1
++#define MR1_7BITS 2
++#define MR1_8BITS 3
++
++#define MR1_PARITY_ODD 4
++
++#define MR1_PARITY 24
++#define MR1_PARITY_WITH 0
++#define MR1_PARITY_FORCE 8
++#define MR1_PARITY_NO 16
++#define MR1_PARITY_MULTIDROP 24
++
++#define MR1_ERROR_BLOCK 32
++#define MR1_FFULL_IRQ 64
++#define MR1_RxRTS_ON 128
++
++#define MR2_STOPS 15
++#define MR2_1STOP 7
++#define MR2_2STOP 15
++
++#define MR2_CTS_ON 16
++#define MR2_TxRTS_ON 32
++
++#define MR2_MODE 192
++#define MR2_NORMAL 0
++#define MR2_ECHO 64
++#define MR2_LOCALLOOP 128
++#define MR2_REMOTELOOP 192
++
++#define CR_RXCOMMAND 3
++#define CR_NONE 0
++#define CR_RX_ON 1
++#define CR_RX_OFF 2
++#define CR_TXCOMMAND 12
++#define CR_TX_ON 4
++#define CR_TX_OFF 8
++#define CR_MISC 112
++#define CR_RESET_MR 16
++#define CR_RESET_RX 32
++#define CR_RESET_TX 48
++#define CR_RESET_ERR 64
++#define CR_RESET_BREAK 80
++#define CR_START_BREAK 96
++#define CR_STOP_BREAK 112
++
++#define SR_RXRDY 1
++#define SR_FFULL 2
++#define SR_TXRDY 4
++#define SR_TXEMPT 8
++#define SR_OVERRUN 16
++#define SR_PARITY 32
++#define SR_FRAMING 64
++#define SR_BREAK 128
++
++
++#endif

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/152-pci.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/152-pci.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,21 @@
+To: linus, alan
+Cc: lkml
+Subject: [PATCH] M68k PCI
+
+First steps in making m68k PCI support compilable again
+
+---
+ arch/m68k/kernel/bios32.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/bios32.c
++++ linux-m68k-2.6.21/arch/m68k/kernel/bios32.c
+@@ -284,7 +284,7 @@ static void __init layout_bus(struct pci
+ 
+ 	DBG_DEVS(("layout_bus: starting bus %d\n", bus->number));
+ 
+-	if (!bus->devices && !bus->children)
++	if (list_empty(&bus->devices) && list_empty(&bus->children))
+ 		return;
+ 
+ 	/*

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/357-mac89x0.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/357-mac89x0.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,177 @@
+Subject: [PATCH] m68k: Mac89x0 Ethernet netif updates
+Cc: Jeff Garzik <jgarzik at pobox.com>, netdev at vger.kernel.org
+
+From: Matthias Urlichs <smurf at smurf.noris.de>
+
+Macintosh CS89x0 Ethernet: Netif updates
+Addition of netif_stop_queue() before transmission by Michael Schmitz
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/net/Kconfig   |    2 -
+ drivers/net/mac89x0.c |   90 +++++++++++++++++---------------------------------
+ 2 files changed, 33 insertions(+), 59 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/net/Kconfig
++++ linux-m68k-2.6.21/drivers/net/Kconfig
+@@ -311,7 +311,7 @@ config MAC8390
+ 
+ config MAC89x0
+ 	tristate "Macintosh CS89x0 based ethernet cards"
+-	depends on NET_ETHERNET && MAC && BROKEN
++	depends on NET_ETHERNET && MAC
+ 	---help---
+ 	  Support for CS89x0 chipset based Ethernet cards.  If you have a
+ 	  Nubus or LC-PDS network (Ethernet) card of this type, say Y and
+--- linux-m68k-2.6.21.orig/drivers/net/mac89x0.c
++++ linux-m68k-2.6.21/drivers/net/mac89x0.c
+@@ -128,7 +128,7 @@ struct net_local {
+ extern void reset_chip(struct net_device *dev);
+ #endif
+ static int net_open(struct net_device *dev);
+-static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
++static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
+ static irqreturn_t net_interrupt(int irq, void *dev_id);
+ static void set_multicast_list(struct net_device *dev);
+ static void net_rx(struct net_device *dev);
+@@ -374,56 +374,38 @@ net_open(struct net_device *dev)
+ static int
+ net_send_packet(struct sk_buff *skb, struct net_device *dev)
+ {
+-	if (dev->tbusy) {
+-		/* If we get here, some higher level has decided we are broken.
+-		   There should really be a "kick me" function call instead. */
+-		int tickssofar = jiffies - dev->trans_start;
+-		if (tickssofar < 5)
+-			return 1;
+-		if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
+-			   tx_done(dev) ? "IRQ conflict" : "network cable problem");
+-		/* Try to restart the adaptor. */
+-		dev->tbusy=0;
+-		dev->trans_start = jiffies;
+-	}
+-
+-	/* Block a timer-based transmit from overlapping.  This could better be
+-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
+-		printk("%s: Transmitter access conflict.\n", dev->name);
+-	else {
+-		struct net_local *lp = netdev_priv(dev);
+-		unsigned long flags;
+-
+-		if (net_debug > 3)
+-			printk("%s: sent %d byte packet of type %x\n",
+-			       dev->name, skb->len,
+-			       (skb->data[ETH_ALEN+ETH_ALEN] << 8)
+-			       | skb->data[ETH_ALEN+ETH_ALEN+1]);
+-
+-		/* keep the upload from being interrupted, since we
+-                   ask the chip to start transmitting before the
+-                   whole packet has been completely uploaded. */
+-		local_irq_save(flags);
+-
+-		/* initiate a transmit sequence */
+-		writereg(dev, PP_TxCMD, lp->send_cmd);
+-		writereg(dev, PP_TxLength, skb->len);
+-
+-		/* Test to see if the chip has allocated memory for the packet */
+-		if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
+-			/* Gasp!  It hasn't.  But that shouldn't happen since
+-			   we're waiting for TxOk, so return 1 and requeue this packet. */
+-			local_irq_restore(flags);
+-			return 1;
+-		}
++	struct net_local *lp = netdev_priv(dev);
++	unsigned long flags;
+ 
+-		/* Write the contents of the packet */
+-		memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1);
++	if (net_debug > 3)
++		printk("%s: sent %d byte packet of type %x\n",
++		       dev->name, skb->len,
++		       (skb->data[ETH_ALEN+ETH_ALEN] << 8)
++		       | skb->data[ETH_ALEN+ETH_ALEN+1]);
++
++	/* keep the upload from being interrupted, since we
++	   ask the chip to start transmitting before the
++	   whole packet has been completely uploaded. */
++	local_irq_save(flags);
++	netif_stop_queue(dev);
+ 
++	/* initiate a transmit sequence */
++	writereg(dev, PP_TxCMD, lp->send_cmd);
++	writereg(dev, PP_TxLength, skb->len);
++
++	/* Test to see if the chip has allocated memory for the packet */
++	if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
++		/* Gasp!  It hasn't.  But that shouldn't happen since
++		   we're waiting for TxOk, so return 1 and requeue this packet. */
+ 		local_irq_restore(flags);
+-		dev->trans_start = jiffies;
++		return 1;
+ 	}
++
++	/* Write the contents of the packet */
++	memcpy((void *)(dev->mem_start + PP_TxFrame), skb->data, skb->len+1);
++
++	local_irq_restore(flags);
++	dev->trans_start = jiffies;
+ 	dev_kfree_skb (skb);
+ 
+ 	return 0;
+@@ -441,9 +423,6 @@ static irqreturn_t net_interrupt(int irq
+ 		printk ("net_interrupt(): irq %d for unknown device.\n", irq);
+ 		return IRQ_NONE;
+ 	}
+-	if (dev->interrupt)
+-		printk("%s: Re-entering the interrupt handler.\n", dev->name);
+-	dev->interrupt = 1;
+ 
+ 	ioaddr = dev->base_addr;
+ 	lp = netdev_priv(dev);
+@@ -464,8 +443,7 @@ static irqreturn_t net_interrupt(int irq
+ 			break;
+ 		case ISQ_TRANSMITTER_EVENT:
+ 			lp->stats.tx_packets++;
+-			dev->tbusy = 0;
+-			mark_bh(NET_BH);	/* Inform upper layers. */
++			netif_wake_queue(dev);
+ 			if ((status & TX_OK) == 0) lp->stats.tx_errors++;
+ 			if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
+ 			if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
+@@ -479,8 +457,7 @@ static irqreturn_t net_interrupt(int irq
+                                    That shouldn't happen since we only ever
+                                    load one packet.  Shrug.  Do the right
+                                    thing anyway. */
+-				dev->tbusy = 0;
+-				mark_bh(NET_BH);	/* Inform upper layers. */
++				netif_wake_queue(dev);
+ 			}
+ 			if (status & TX_UNDERRUN) {
+ 				if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
+@@ -497,7 +474,6 @@ static irqreturn_t net_interrupt(int irq
+ 			break;
+ 		}
+ 	}
+-	dev->interrupt = 0;
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -532,7 +508,7 @@ net_rx(struct net_device *dev)
+ 	skb_put(skb, length);
+ 	skb->dev = dev;
+ 
+-	memcpy_fromio(skb->data, dev->mem_start + PP_RxFrame, length);
++	memcpy(skb->data, (void *)(dev->mem_start + PP_RxFrame), length);
+ 
+ 	if (net_debug > 3)printk("%s: received %d byte packet of type %x\n",
+                                  dev->name, length,
+@@ -611,8 +587,6 @@ static void set_multicast_list(struct ne
+ static int set_mac_address(struct net_device *dev, void *addr)
+ {
+ 	int i;
+-	if (dev->start)
+-		return -EBUSY;
+ 	printk("%s: Setting MAC address to ", dev->name);
+ 	for (i = 0; i < 6; i++)
+ 		printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/448-ide.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/448-ide.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,23 @@
+To: linus, akpm, B.Zolnierkiewicz at elka.pw.edu.pl
+Cc: lkml
+Subject: [PATCH] m68k IDE compiler bug
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+IDE: Avoid compiler bug in gcc 3.2 (from Roman Zippel)
+
+---
+ include/linux/ide.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-m68k-2.6.21.orig/include/linux/ide.h
++++ linux-m68k-2.6.21/include/linux/ide.h
+@@ -513,7 +513,7 @@ typedef union {
+  * sense_key	: Sense key of the last failed packet command
+  */
+ typedef union {
+-	unsigned all			:8;
++	u8 all;
+ 	struct {
+ #if defined(__LITTLE_ENDIAN_BITFIELD)
+ 		unsigned ili		:1;

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/478-serial.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/478-serial.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,30 @@
+To: linus, akpm
+Cc: lkml
+Subject: [PATCH] M68k SERIAL_PORT_DFNS only if CONFIG_ISA
+
+From: Kars de Jong <jongk at linux-m68k.org>
+
+M68k serial: Only define SERIAL_PORT_DFNS when CONFIG_ISA is defined. Otherwise
+the first 4 slots in the 8250 driver are unavailable on non-ISA machines.
+
+Signed-off-by: Kars de Jong <jongk at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+
+---
+ include/asm-m68k/serial.h |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- linux-m68k-2.6.21.orig/include/asm-m68k/serial.h
++++ linux-m68k-2.6.21/include/asm-m68k/serial.h
+@@ -25,9 +25,11 @@
+ #define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
+ #endif
+ 
++#ifdef CONFIG_ISA
+ #define SERIAL_PORT_DFNS			\
+ 	/* UART CLK   PORT IRQ     FLAGS        */			\
+ 	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
+ 	{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },	/* ttyS1 */	\
+ 	{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },	/* ttyS2 */	\
+ 	{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },	/* ttyS3 */
++#endif

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/577-module-arch.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/577-module-arch.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,37 @@
+Subject: [PATCH] Allow arch to initialize arch field of the module structure
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+This will later allow an arch to add module specific information via
+linker generated tables instead of poking directly in the module object
+structure.
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ include/linux/module.h |    3 +++
+ scripts/mod/modpost.c  |    1 +
+ 2 files changed, 4 insertions(+)
+
+--- linux-m68k-2.6.21.orig/include/linux/module.h
++++ linux-m68k-2.6.21/include/linux/module.h
+@@ -356,6 +356,9 @@ struct module
+ 	   keeping pointers to this stuff */
+ 	char *args;
+ };
++#ifndef MODULE_ARCH_INIT
++#define MODULE_ARCH_INIT {}
++#endif
+ 
+ /* FIXME: It'd be nice to isolate modules during init, too, so they
+    aren't used before they (may) fail.  But presently too much code
+--- linux-m68k-2.6.21.orig/scripts/mod/modpost.c
++++ linux-m68k-2.6.21/scripts/mod/modpost.c
+@@ -1249,6 +1249,7 @@ static void add_header(struct buffer *b,
+ 		buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"
+ 			      " .exit = cleanup_module,\n"
+ 			      "#endif\n");
++	buf_printf(b, " .arch = MODULE_ARCH_INIT,\n");
+ 	buf_printf(b, "};\n");
+ }
+ 

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/600-task_thread_info.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/600-task_thread_info.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,43 @@
+Subject: [PATCH] Wrap access to thread_info
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+Wrap direct thread_info access
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ kernel/mutex.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- linux-m68k-2.6.21.orig/kernel/mutex.c
++++ linux-m68k-2.6.21/kernel/mutex.c
+@@ -133,7 +133,7 @@ __mutex_lock_common(struct mutex *lock, 
+ 
+ 	debug_mutex_lock_common(lock, &waiter);
+ 	mutex_acquire(&lock->dep_map, subclass, 0, _RET_IP_);
+-	debug_mutex_add_waiter(lock, &waiter, task->thread_info);
++	debug_mutex_add_waiter(lock, &waiter, task_thread_info(task));
+ 
+ 	/* add waiting tasks to the end of the waitqueue (FIFO): */
+ 	list_add_tail(&waiter.list, &lock->wait_list);
+@@ -159,7 +159,7 @@ __mutex_lock_common(struct mutex *lock, 
+ 		 */
+ 		if (unlikely(state == TASK_INTERRUPTIBLE &&
+ 						signal_pending(task))) {
+-			mutex_remove_waiter(lock, &waiter, task->thread_info);
++			mutex_remove_waiter(lock, &waiter, task_thread_info(task));
+ 			mutex_release(&lock->dep_map, 1, _RET_IP_);
+ 			spin_unlock_mutex(&lock->wait_lock, flags);
+ 
+@@ -175,8 +175,8 @@ __mutex_lock_common(struct mutex *lock, 
+ 	}
+ 
+ 	/* got the lock - rejoice! */
+-	mutex_remove_waiter(lock, &waiter, task->thread_info);
+-	debug_mutex_set_owner(lock, task->thread_info);
++	mutex_remove_waiter(lock, &waiter, task_thread_info(task));
++	debug_mutex_set_owner(lock, task_thread_info(task));
+ 
+ 	/* set it to 0 if there are no waiters left: */
+ 	if (likely(list_empty(&lock->wait_list)))

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/611-module_fixup.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/611-module_fixup.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,214 @@
+Subject: [PATCH] m68k: runtime patching infrastructure
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+Add the basic infrastructure to allow runtime patching of kernel and
+modules to optimize a few functions with parameters, which are only
+calculated once during bootup and are otherwise constant.
+Use this for the conversion between virtual and physical addresses.
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/Makefile                |    1 +
+ arch/m68k/kernel/module.c         |   24 +++++++++++++++++++++++-
+ arch/m68k/kernel/module.lds       |    7 +++++++
+ arch/m68k/kernel/vmlinux-std.lds  |    5 +++++
+ arch/m68k/kernel/vmlinux-sun3.lds |    5 +++++
+ arch/m68k/mm/motorola.c           |    3 +++
+ include/asm-m68k/module.h         |   33 ++++++++++++++++++++++++++++++++-
+ include/asm-m68k/page.h           |   29 ++++++++++++++++++++++++++---
+ 8 files changed, 102 insertions(+), 5 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/Makefile
++++ linux-m68k-2.6.21/arch/m68k/Makefile
+@@ -19,6 +19,7 @@ COMPILE_ARCH = $(shell uname -m)
+ # override top level makefile
+ AS += -m68020
+ LDFLAGS := -m m68kelf
++LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
+ ifneq ($(COMPILE_ARCH),$(ARCH))
+ 	# prefix for cross-compiling binaries
+ 	CROSS_COMPILE = m68k-linux-gnu-
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/module.c
++++ linux-m68k-2.6.21/arch/m68k/kernel/module.c
+@@ -1,3 +1,9 @@
++/*
++ * 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
++ * for more details.
++ */
++
+ #include <linux/moduleloader.h>
+ #include <linux/elf.h>
+ #include <linux/vmalloc.h>
+@@ -116,10 +122,26 @@ int apply_relocate_add(Elf32_Shdr *sechd
+ 	return 0;
+ }
+ 
++void module_fixup(struct module *mod, struct m68k_fixup_info *start,
++		  struct m68k_fixup_info *end)
++{
++	struct m68k_fixup_info *fixup;
++
++	for (fixup = start; fixup < end; fixup++) {
++		switch (fixup->type) {
++		case m68k_fixup_memoffset:
++			*(u32 *)fixup->addr = m68k_memoffset;
++			break;
++		}
++	}
++}
++
+ int module_finalize(const Elf_Ehdr *hdr,
+ 		    const Elf_Shdr *sechdrs,
+-		    struct module *me)
++		    struct module *mod)
+ {
++	module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
++
+ 	return 0;
+ }
+ 
+--- /dev/null
++++ linux-m68k-2.6.21/arch/m68k/kernel/module.lds
+@@ -0,0 +1,7 @@
++SECTIONS {
++	.m68k_fixup : {
++		__start_fixup = .;
++		*(.m68k_fixup)
++		__stop_fixup = .;
++	}
++}
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/vmlinux-std.lds
++++ linux-m68k-2.6.21/arch/m68k/kernel/vmlinux-std.lds
+@@ -60,6 +60,11 @@ SECTIONS
+   __con_initcall_start = .;
+   .con_initcall.init : { *(.con_initcall.init) }
+   __con_initcall_end = .;
++  .m68k_fixup : {
++	__start_fixup = .;
++	*(.m68k_fixup)
++	__stop_fixup = .;
++  }
+   SECURITY_INIT
+ #ifdef CONFIG_BLK_DEV_INITRD
+   . = ALIGN(8192);
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/vmlinux-sun3.lds
++++ linux-m68k-2.6.21/arch/m68k/kernel/vmlinux-sun3.lds
+@@ -54,6 +54,11 @@ __init_begin = .;
+ 	__con_initcall_start = .;
+ 	.con_initcall.init : { *(.con_initcall.init) }
+ 	__con_initcall_end = .;
++	.m68k_fixup : {
++		__start_fixup = .;
++		*(.m68k_fixup)
++		__stop_fixup = .;
++	}
+ 	SECURITY_INIT
+ #ifdef CONFIG_BLK_DEV_INITRD
+ 	. = ALIGN(8192);
+--- linux-m68k-2.6.21.orig/arch/m68k/mm/motorola.c
++++ linux-m68k-2.6.21/arch/m68k/mm/motorola.c
+@@ -222,6 +222,9 @@ void __init paging_init(void)
+ 			pgprot_val(protection_map[i]) |= _PAGE_CACHE040;
+ 	}
+ 
++	module_fixup(NULL, __start_fixup, __stop_fixup);
++	flush_icache();
++
+ 	/*
+ 	 * Map the physical memory available into the kernel virtual
+ 	 * address space.  It may allocate some memory for page
+--- linux-m68k-2.6.21.orig/include/asm-m68k/module.h
++++ linux-m68k-2.6.21/include/asm-m68k/module.h
+@@ -1,7 +1,38 @@
+ #ifndef _ASM_M68K_MODULE_H
+ #define _ASM_M68K_MODULE_H
+-struct mod_arch_specific { };
++
++struct mod_arch_specific {
++	struct m68k_fixup_info *fixup_start, *fixup_end;
++};
++
++#define MODULE_ARCH_INIT {				\
++	.fixup_start		= __start_fixup,	\
++	.fixup_end		= __stop_fixup,		\
++}
++
+ #define Elf_Shdr Elf32_Shdr
+ #define Elf_Sym Elf32_Sym
+ #define Elf_Ehdr Elf32_Ehdr
++
++
++enum m68k_fixup_type {
++	m68k_fixup_memoffset,
++};
++
++struct m68k_fixup_info {
++	enum m68k_fixup_type type;
++	void *addr;
++};
++
++#define m68k_fixup(type, addr)			\
++	"	.section \".m68k_fixup\",\"aw\"\n"	\
++	"	.long " #type "," #addr "\n"	\
++	"	.previous\n"
++
++extern struct m68k_fixup_info __start_fixup[], __stop_fixup[];
++
++struct module;
++extern void module_fixup(struct module *mod, struct m68k_fixup_info *start,
++			 struct m68k_fixup_info *end);
++
+ #endif /* _ASM_M68K_MODULE_H */
+--- linux-m68k-2.6.21.orig/include/asm-m68k/page.h
++++ linux-m68k-2.6.21/include/asm-m68k/page.h
+@@ -27,6 +27,8 @@
+ 
+ #ifndef __ASSEMBLY__
+ 
++#include <asm/module.h>
++
+ #define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
+ #define free_user_page(page, addr)	free_page(addr)
+ 
+@@ -114,14 +116,35 @@ typedef struct { unsigned long pgprot; }
+ 
+ #ifndef __ASSEMBLY__
+ 
++extern unsigned long m68k_memoffset;
++
+ #ifndef CONFIG_SUN3
+ 
+ #define WANT_PAGE_VIRTUAL
+ #ifdef CONFIG_SINGLE_MEMORY_CHUNK
+-extern unsigned long m68k_memoffset;
+ 
+-#define __pa(vaddr)		((unsigned long)(vaddr)+m68k_memoffset)
+-#define __va(paddr)		((void *)((unsigned long)(paddr)-m68k_memoffset))
++static inline unsigned long ___pa(void *vaddr)
++{
++	unsigned long paddr;
++	asm (
++		"1:	addl #0,%0\n"
++		m68k_fixup(%c2, 1b+2)
++		: "=r" (paddr)
++		: "0" (vaddr), "i" (m68k_fixup_memoffset));
++	return paddr;
++}
++#define __pa(vaddr)    ___pa((void *)(vaddr))
++static inline void *__va(unsigned long paddr)
++{
++	void *vaddr;
++	asm (
++		"1:	subl #0,%0\n"
++		m68k_fixup(%c2, 1b+2)
++		: "=r" (vaddr)
++		: "0" (paddr), "i" (m68k_fixup_memoffset));
++	return vaddr;
++}
++
+ #else
+ #define __pa(vaddr)		virt_to_phys((void *)(vaddr))
+ #define __va(paddr)		phys_to_virt((unsigned long)(paddr))

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/618-discontig.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/618-discontig.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,868 @@
+To: linus, akpm
+Cc: lkml
+Subject: [PATCH] m68k: Discontinuous memory support
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+Fix support for discontinuous memory
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/Kconfig                   |   13 +++
+ arch/m68k/kernel/module.c           |    3 
+ arch/m68k/kernel/setup.c            |   37 ++---------
+ arch/m68k/mm/init.c                 |  119 +++++++++++++++++++++++-------------
+ arch/m68k/mm/memory.c               |   73 ----------------------
+ arch/m68k/mm/motorola.c             |  102 +++++++++++++++++++++---------
+ arch/m68k/sun3/config.c             |    2 
+ include/asm-m68k/mmzone.h           |    9 ++
+ include/asm-m68k/module.h           |    1 
+ include/asm-m68k/motorola_pgtable.h |   10 +--
+ include/asm-m68k/page.h             |   52 ++++++++++++---
+ include/asm-m68k/pgalloc.h          |    3 
+ include/asm-m68k/pgtable.h          |   17 -----
+ include/asm-m68k/sun3_pgtable.h     |    4 -
+ include/asm-m68k/virtconvert.h      |   48 +++-----------
+ mm/page_alloc.c                     |    2 
+ 16 files changed, 247 insertions(+), 248 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/Kconfig
++++ linux-m68k-2.6.21/arch/m68k/Kconfig
+@@ -355,8 +355,9 @@ config RMW_INSNS
+ 	  adventurous.
+ 
+ config SINGLE_MEMORY_CHUNK
+-	bool "Use one physical chunk of memory only"
+-	depends on ADVANCED && !SUN3
++	bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
++	default y if SUN3
++	select NEED_MULTIPLE_NODES
+ 	help
+ 	  Ignore all but the first contiguous chunk of physical memory for VM
+ 	  purposes.  This will save a few bytes kernel size and may speed up
+@@ -377,6 +378,14 @@ config 060_WRITETHROUGH
+ 	  is hardwired on.  The 53c710 SCSI driver is known to suffer from
+ 	  this problem.
+ 
++config ARCH_DISCONTIGMEM_ENABLE
++	def_bool !SINGLE_MEMORY_CHUNK
++
++config NODES_SHIFT
++	int
++	default "3"
++	depends on !SINGLE_MEMORY_CHUNK
++
+ source "mm/Kconfig"
+ 
+ endmenu
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/module.c
++++ linux-m68k-2.6.21/arch/m68k/kernel/module.c
+@@ -132,6 +132,9 @@ void module_fixup(struct module *mod, st
+ 		case m68k_fixup_memoffset:
+ 			*(u32 *)fixup->addr = m68k_memoffset;
+ 			break;
++		case m68k_fixup_vnode_shift:
++			*(u16 *)fixup->addr += m68k_virt_to_node_shift;
++			break;
+ 		}
+ 	}
+ }
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/setup.c
++++ linux-m68k-2.6.21/arch/m68k/kernel/setup.c
+@@ -60,14 +60,12 @@ extern unsigned long availmem;
+ int m68k_num_memory;
+ int m68k_realnum_memory;
+ EXPORT_SYMBOL(m68k_realnum_memory);
+-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
+ unsigned long m68k_memoffset;
+ EXPORT_SYMBOL(m68k_memoffset);
+-#endif
+ struct mem_info m68k_memory[NUM_MEMINFO];
+ EXPORT_SYMBOL(m68k_memory);
+ 
+-static struct mem_info m68k_ramdisk;
++struct mem_info m68k_ramdisk;
+ 
+ static char m68k_command_line[CL_SIZE];
+ 
+@@ -208,9 +206,6 @@ static void __init m68k_parse_bootinfo(c
+ void __init setup_arch(char **cmdline_p)
+ {
+ 	extern int _etext, _edata, _end;
+-#ifndef CONFIG_SUN3
+-	unsigned long endmem, startmem;
+-#endif
+ 	int i;
+ 
+ 	/* The bootinfo is located right after the kernel bss */
+@@ -320,30 +315,16 @@ void __init setup_arch(char **cmdline_p)
+ 		panic("No configuration setup");
+ 	}
+ 
+-#ifndef CONFIG_SUN3
+-	startmem= m68k_memory[0].addr;
+-	endmem = startmem + m68k_memory[0].size;
+-	high_memory = (void *)PAGE_OFFSET;
+-	for (i = 0; i < m68k_num_memory; i++) {
+-		m68k_memory[i].size &= MASK_256K;
+-		if (m68k_memory[i].addr < startmem)
+-			startmem = m68k_memory[i].addr;
+-		if (m68k_memory[i].addr+m68k_memory[i].size > endmem)
+-			endmem = m68k_memory[i].addr+m68k_memory[i].size;
+-		high_memory += m68k_memory[i].size;
+-	}
+-
+-	availmem += init_bootmem_node(NODE_DATA(0), availmem >> PAGE_SHIFT,
+-				      startmem >> PAGE_SHIFT, endmem >> PAGE_SHIFT);
+-
+-	for (i = 0; i < m68k_num_memory; i++)
+-		free_bootmem(m68k_memory[i].addr, m68k_memory[i].size);
+-
+-	reserve_bootmem(m68k_memory[0].addr, availmem - m68k_memory[0].addr);
++	paging_init();
+ 
++#ifndef CONFIG_SUN3
++	for (i = 1; i < m68k_num_memory; i++)
++		free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
++				  m68k_memory[i].size);
+ #ifdef CONFIG_BLK_DEV_INITRD
+ 	if (m68k_ramdisk.size) {
+-		reserve_bootmem(m68k_ramdisk.addr, m68k_ramdisk.size);
++		reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
++				     m68k_ramdisk.addr, m68k_ramdisk.size);
+ 		initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
+ 		initrd_end = initrd_start + m68k_ramdisk.size;
+ 		printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
+@@ -362,8 +343,6 @@ void __init setup_arch(char **cmdline_p)
+ 
+ #endif /* !CONFIG_SUN3 */
+ 
+-	paging_init();
+-
+ /* set ISA defs early as possible */
+ #if defined(CONFIG_ISA) && defined(MULTI_ISA)
+ #if defined(CONFIG_Q40)
+--- linux-m68k-2.6.21.orig/arch/m68k/mm/init.c
++++ linux-m68k-2.6.21/arch/m68k/mm/init.c
+@@ -7,6 +7,7 @@
+  *  to motorola.c and sun3mmu.c
+  */
+ 
++#include <linux/module.h>
+ #include <linux/signal.h>
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+@@ -31,6 +32,37 @@
+ 
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ 
++static bootmem_data_t __initdata bootmem_data[MAX_NUMNODES];
++
++pg_data_t pg_data_map[MAX_NUMNODES];
++EXPORT_SYMBOL(pg_data_map);
++
++int m68k_virt_to_node_shift;
++
++#ifndef CONFIG_SINGLE_MEMORY_CHUNK
++pg_data_t *pg_data_table[65];
++EXPORT_SYMBOL(pg_data_table);
++#endif
++
++void m68k_setup_node(int node)
++{
++#ifndef CONFIG_SINGLE_MEMORY_CHUNK
++	struct mem_info *info = m68k_memory + node;
++	int i, end;
++
++	i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
++	end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
++	for (; i <= end; i++) {
++		if (pg_data_table[i])
++			printk("overlap at %u for chunk %u\n", i, node);
++		pg_data_table[i] = pg_data_map + node;
++	}
++#endif
++	pg_data_map[node].bdata = bootmem_data + node;
++	node_set_online(node);
++}
++
++
+ /*
+  * ZERO_PAGE is a special page that is used for zero-initialized
+  * data and COW.
+@@ -40,52 +72,51 @@ void *empty_zero_page;
+ 
+ void show_mem(void)
+ {
+-    unsigned long i;
+-    int free = 0, total = 0, reserved = 0, shared = 0;
+-    int cached = 0;
+-
+-    printk("\nMem-info:\n");
+-    show_free_areas();
+-    printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+-    i = max_mapnr;
+-    while (i-- > 0) {
+-	total++;
+-	if (PageReserved(mem_map+i))
+-	    reserved++;
+-	else if (PageSwapCache(mem_map+i))
+-	    cached++;
+-	else if (!page_count(mem_map+i))
+-	    free++;
+-	else
+-	    shared += page_count(mem_map+i) - 1;
+-    }
+-    printk("%d pages of RAM\n",total);
+-    printk("%d free pages\n",free);
+-    printk("%d reserved pages\n",reserved);
+-    printk("%d pages shared\n",shared);
+-    printk("%d pages swap cached\n",cached);
++	pg_data_t *pgdat;
++	int free = 0, total = 0, reserved = 0, shared = 0;
++	int cached = 0;
++	int i;
++
++	printk("\nMem-info:\n");
++	show_free_areas();
++	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
++	for_each_online_pgdat(pgdat) {
++		for (i = 0; i < pgdat->node_spanned_pages; i++) {
++			struct page *page = pgdat->node_mem_map + i;
++			total++;
++			if (PageReserved(page))
++				reserved++;
++			else if (PageSwapCache(page))
++				cached++;
++			else if (!page_count(page))
++				free++;
++			else
++				shared += page_count(page) - 1;
++		}
++	}
++	printk("%d pages of RAM\n",total);
++	printk("%d free pages\n",free);
++	printk("%d reserved pages\n",reserved);
++	printk("%d pages shared\n",shared);
++	printk("%d pages swap cached\n",cached);
+ }
+ 
+ extern void init_pointer_table(unsigned long ptable);
+ 
+ /* References to section boundaries */
+ 
+-extern char _text, _etext, _edata, __bss_start, _end;
+-extern char __init_begin, __init_end;
++extern char _text[], _etext[];
++extern char __init_begin[], __init_end[];
+ 
+ extern pmd_t *zero_pgtable;
+ 
+ void __init mem_init(void)
+ {
++	pg_data_t *pgdat;
+ 	int codepages = 0;
+ 	int datapages = 0;
+ 	int initpages = 0;
+-	unsigned long tmp;
+-#ifndef CONFIG_SUN3
+ 	int i;
+-#endif
+-
+-	max_mapnr = num_physpages = (((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT);
+ 
+ #ifdef CONFIG_ATARI
+ 	if (MACH_IS_ATARI)
+@@ -93,19 +124,25 @@ void __init mem_init(void)
+ #endif
+ 
+ 	/* this will put all memory onto the freelists */
+-	totalram_pages = free_all_bootmem();
+-
+-	for (tmp = PAGE_OFFSET ; tmp < (unsigned long)high_memory; tmp += PAGE_SIZE) {
+-		if (PageReserved(virt_to_page(tmp))) {
+-			if (tmp >= (unsigned long)&_text
+-			    && tmp < (unsigned long)&_etext)
++	totalram_pages = num_physpages = 0;
++	for_each_online_pgdat(pgdat) {
++		num_physpages += pgdat->node_present_pages;
++
++		totalram_pages += free_all_bootmem_node(pgdat);
++		for (i = 0; i < pgdat->node_spanned_pages; i++) {
++			struct page *page = pgdat->node_mem_map + i;
++			char *addr = page_to_virt(page);
++
++			if (!PageReserved(page))
++				continue;
++			if (addr >= _text &&
++			    addr < _etext)
+ 				codepages++;
+-			else if (tmp >= (unsigned long) &__init_begin
+-				 && tmp < (unsigned long) &__init_end)
++			else if (addr >= __init_begin &&
++				 addr < __init_end)
+ 				initpages++;
+ 			else
+ 				datapages++;
+-			continue;
+ 		}
+ 	}
+ 
+@@ -124,7 +161,7 @@ void __init mem_init(void)
+ 
+ 	printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
+ 	       (unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
+-	       max_mapnr << (PAGE_SHIFT-10),
++	       totalram_pages << (PAGE_SHIFT-10),
+ 	       codepages << (PAGE_SHIFT-10),
+ 	       datapages << (PAGE_SHIFT-10),
+ 	       initpages << (PAGE_SHIFT-10));
+--- linux-m68k-2.6.21.orig/arch/m68k/mm/memory.c
++++ linux-m68k-2.6.21/arch/m68k/mm/memory.c
+@@ -127,67 +127,6 @@ int free_pointer_table (pmd_t *ptable)
+ 	return 0;
+ }
+ 
+-#ifdef DEBUG_INVALID_PTOV
+-int mm_inv_cnt = 5;
+-#endif
+-
+-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+-/*
+- * The following two routines map from a physical address to a kernel
+- * virtual address and vice versa.
+- */
+-unsigned long mm_vtop(unsigned long vaddr)
+-{
+-	int i=0;
+-	unsigned long voff = (unsigned long)vaddr - PAGE_OFFSET;
+-
+-	do {
+-		if (voff < m68k_memory[i].size) {
+-#ifdef DEBUGPV
+-			printk ("VTOP(%p)=%lx\n", vaddr,
+-				m68k_memory[i].addr + voff);
+-#endif
+-			return m68k_memory[i].addr + voff;
+-		}
+-		voff -= m68k_memory[i].size;
+-	} while (++i < m68k_num_memory);
+-
+-	/* As a special case allow `__pa(high_memory)'.  */
+-	if (voff == 0)
+-		return m68k_memory[i-1].addr + m68k_memory[i-1].size;
+-
+-	return -1;
+-}
+-EXPORT_SYMBOL(mm_vtop);
+-
+-unsigned long mm_ptov (unsigned long paddr)
+-{
+-	int i = 0;
+-	unsigned long poff, voff = PAGE_OFFSET;
+-
+-	do {
+-		poff = paddr - m68k_memory[i].addr;
+-		if (poff < m68k_memory[i].size) {
+-#ifdef DEBUGPV
+-			printk ("PTOV(%lx)=%lx\n", paddr, poff + voff);
+-#endif
+-			return poff + voff;
+-		}
+-		voff += m68k_memory[i].size;
+-	} while (++i < m68k_num_memory);
+-
+-#ifdef DEBUG_INVALID_PTOV
+-	if (mm_inv_cnt > 0) {
+-		mm_inv_cnt--;
+-		printk("Invalid use of phys_to_virt(0x%lx) at 0x%p!\n",
+-			paddr, __builtin_return_address(0));
+-	}
+-#endif
+-	return -1;
+-}
+-EXPORT_SYMBOL(mm_ptov);
+-#endif
+-
+ /* invalidate page in both caches */
+ static inline void clear040(unsigned long paddr)
+ {
+@@ -354,15 +293,3 @@ void cache_push (unsigned long paddr, in
+ }
+ EXPORT_SYMBOL(cache_push);
+ 
+-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+-int mm_end_of_chunk (unsigned long addr, int len)
+-{
+-	int i;
+-
+-	for (i = 0; i < m68k_num_memory; i++)
+-		if (m68k_memory[i].addr + m68k_memory[i].size == addr + len)
+-			return 1;
+-	return 0;
+-}
+-EXPORT_SYMBOL(mm_end_of_chunk);
+-#endif
+--- linux-m68k-2.6.21.orig/arch/m68k/mm/motorola.c
++++ linux-m68k-2.6.21/arch/m68k/mm/motorola.c
+@@ -43,6 +43,12 @@ unsigned long mm_cachebits;
+ EXPORT_SYMBOL(mm_cachebits);
+ #endif
+ 
++/* size of memory already mapped in head.S */
++#define INIT_MAPPED_SIZE	(4UL<<20)
++
++extern unsigned long availmem;
++extern struct mem_info m68k_ramdisk;
++
+ static pte_t * __init kernel_page_table(void)
+ {
+ 	pte_t *ptablep;
+@@ -98,19 +104,20 @@ static pmd_t * __init kernel_ptr_table(v
+ 	return last_pgtable;
+ }
+ 
+-static unsigned long __init
+-map_chunk (unsigned long addr, long size)
++static void __init map_node(int node)
+ {
+ #define PTRTREESIZE (256*1024)
+ #define ROOTTREESIZE (32*1024*1024)
+-	static unsigned long virtaddr = PAGE_OFFSET;
+-	unsigned long physaddr;
++	unsigned long physaddr, virtaddr, size;
+ 	pgd_t *pgd_dir;
+ 	pmd_t *pmd_dir;
+ 	pte_t *pte_dir;
+ 
+-	physaddr = (addr | m68k_supervisor_cachemode |
+-		    _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
++	size = m68k_memory[node].size;
++	physaddr = m68k_memory[node].addr;
++	virtaddr = (unsigned long)phys_to_virt(physaddr);
++	physaddr |= m68k_supervisor_cachemode |
++		    _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY;
+ 	if (CPU_IS_040_OR_060)
+ 		physaddr |= _PAGE_GLOBAL040;
+ 
+@@ -190,8 +197,6 @@ map_chunk (unsigned long addr, long size
+ #ifdef DEBUG
+ 	printk("\n");
+ #endif
+-
+-	return virtaddr;
+ }
+ 
+ /*
+@@ -200,15 +205,16 @@ map_chunk (unsigned long addr, long size
+  */
+ void __init paging_init(void)
+ {
+-	int chunk;
+-	unsigned long mem_avail = 0;
+ 	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
++	unsigned long min_addr, max_addr;
++	unsigned long addr, size, end;
++	int i;
+ 
+ #ifdef DEBUG
+ 	{
+ 		extern unsigned long availmem;
+-		printk ("start of paging_init (%p, %lx, %lx, %lx)\n",
+-			kernel_pg_dir, availmem, start_mem, end_mem);
++		printk ("start of paging_init (%p, %lx)\n",
++			kernel_pg_dir, availmem);
+ 	}
+ #endif
+ 
+@@ -222,27 +228,62 @@ void __init paging_init(void)
+ 			pgprot_val(protection_map[i]) |= _PAGE_CACHE040;
+ 	}
+ 
++	min_addr = m68k_memory[0].addr;
++	max_addr = min_addr + m68k_memory[0].size;
++	for (i = 1; i < m68k_num_memory;) {
++		if (m68k_memory[i].addr < min_addr) {
++			printk("Ignoring memory chunk at 0x%lx:0x%lx before the first chunk\n",
++				m68k_memory[i].addr, m68k_memory[i].size);
++			printk("Fix your bootloader or use a memfile to make use of this area!\n");
++			m68k_num_memory--;
++			memmove(m68k_memory + i, m68k_memory + i + 1,
++				(m68k_num_memory - i) * sizeof(struct mem_info));
++			continue;
++		}
++		addr = m68k_memory[i].addr + m68k_memory[i].size;
++		if (addr > max_addr)
++			max_addr = addr;
++		i++;
++	}
++	m68k_memoffset = min_addr - PAGE_OFFSET;
++	m68k_virt_to_node_shift = fls(max_addr - min_addr - 1) - 6;
++
+ 	module_fixup(NULL, __start_fixup, __stop_fixup);
+ 	flush_icache();
+ 
++	high_memory = phys_to_virt(max_addr);
++
++	min_low_pfn = availmem >> PAGE_SHIFT;
++	max_low_pfn = max_addr >> PAGE_SHIFT;
++
++	for (i = 0; i < m68k_num_memory; i++) {
++		addr = m68k_memory[i].addr;
++		end = addr + m68k_memory[i].size;
++		m68k_setup_node(i);
++		availmem = PAGE_ALIGN(availmem);
++		availmem += init_bootmem_node(NODE_DATA(i),
++					      availmem >> PAGE_SHIFT,
++					      addr >> PAGE_SHIFT,
++					      end >> PAGE_SHIFT);
++	}
++
+ 	/*
+ 	 * Map the physical memory available into the kernel virtual
+-	 * address space.  It may allocate some memory for page
+-	 * tables and thus modify availmem.
++	 * address space. First initialize the bootmem allocator with
++	 * the memory we already mapped, so map_node() has something
++	 * to allocate.
+ 	 */
++	addr = m68k_memory[0].addr;
++	size = m68k_memory[0].size;
++	free_bootmem_node(NODE_DATA(0), availmem, min(INIT_MAPPED_SIZE, size) - (availmem - addr));
++	map_node(0);
++	if (size > INIT_MAPPED_SIZE)
++		free_bootmem_node(NODE_DATA(0), addr + INIT_MAPPED_SIZE, size - INIT_MAPPED_SIZE);
+ 
+-	for (chunk = 0; chunk < m68k_num_memory; chunk++) {
+-		mem_avail = map_chunk (m68k_memory[chunk].addr,
+-				       m68k_memory[chunk].size);
+-
+-	}
++	for (i = 1; i < m68k_num_memory; i++)
++		map_node(i);
+ 
+ 	flush_tlb_all();
+-#ifdef DEBUG
+-	printk ("memory available is %ldKB\n", mem_avail >> 10);
+-	printk ("start_mem is %#lx\nvirtual_end is %#lx\n",
+-		start_mem, end_mem);
+-#endif
+ 
+ 	/*
+ 	 * initialize the bad page table and bad page to point
+@@ -259,14 +300,11 @@ void __init paging_init(void)
+ #ifdef DEBUG
+ 	printk ("before free_area_init\n");
+ #endif
+-	zones_size[ZONE_DMA] = (mach_max_dma_address < (unsigned long)high_memory ?
+-				(mach_max_dma_address+1) : (unsigned long)high_memory);
+-	zones_size[ZONE_NORMAL] = (unsigned long)high_memory - zones_size[0];
+-
+-	zones_size[ZONE_DMA] = (zones_size[ZONE_DMA] - PAGE_OFFSET) >> PAGE_SHIFT;
+-	zones_size[ZONE_NORMAL] >>= PAGE_SHIFT;
+-
+-	free_area_init(zones_size);
++	for (i = 0; i < m68k_num_memory; i++) {
++		zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
++		free_area_init_node(i, pg_data_map + i, zones_size,
++				    m68k_memory[i].addr >> PAGE_SHIFT, NULL);
++	}
+ }
+ 
+ extern char __init_begin, __init_end;
+--- linux-m68k-2.6.21.orig/arch/m68k/sun3/config.c
++++ linux-m68k-2.6.21/arch/m68k/sun3/config.c
+@@ -21,6 +21,7 @@
+ #include <asm/contregs.h>
+ #include <asm/movs.h>
+ #include <asm/pgtable.h>
++#include <asm/pgalloc.h>
+ #include <asm/sun3-head.h>
+ #include <asm/sun3mmu.h>
+ #include <asm/rtc.h>
+@@ -127,6 +128,7 @@ void __init sun3_bootmem_alloc(unsigned 
+ 	high_memory = (void *)memory_end;
+ 	availmem = memory_start;
+ 
++	m68k_setup_node(0);
+ 	availmem += init_bootmem_node(NODE_DATA(0), start_page, 0, num_pages);
+ 	availmem = (availmem + (PAGE_SIZE-1)) & PAGE_MASK;
+ 
+--- /dev/null
++++ linux-m68k-2.6.21/include/asm-m68k/mmzone.h
+@@ -0,0 +1,9 @@
++#ifndef _ASM_M68K_MMZONE_H_
++#define _ASM_M68K_MMZONE_H_
++
++extern pg_data_t pg_data_map[];
++
++#define NODE_DATA(nid)		(&pg_data_map[nid])
++#define NODE_MEM_MAP(nid)	(NODE_DATA(nid)->node_mem_map)
++
++#endif /* _ASM_M68K_MMZONE_H_ */
+--- linux-m68k-2.6.21.orig/include/asm-m68k/module.h
++++ linux-m68k-2.6.21/include/asm-m68k/module.h
+@@ -17,6 +17,7 @@ struct mod_arch_specific {
+ 
+ enum m68k_fixup_type {
+ 	m68k_fixup_memoffset,
++	m68k_fixup_vnode_shift,
+ };
+ 
+ struct m68k_fixup_info {
+--- linux-m68k-2.6.21.orig/include/asm-m68k/motorola_pgtable.h
++++ linux-m68k-2.6.21/include/asm-m68k/motorola_pgtable.h
+@@ -130,7 +130,7 @@ static inline void pgd_set(pgd_t *pgdp, 
+ #define pte_present(pte)	(pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROTNONE))
+ #define pte_clear(mm,addr,ptep)		({ pte_val(*(ptep)) = 0; })
+ 
+-#define pte_page(pte)		(mem_map + ((unsigned long)(__va(pte_val(pte)) - PAGE_OFFSET) >> PAGE_SHIFT))
++#define pte_page(pte)		virt_to_page(__va(pte_val(pte)))
+ #define pte_pfn(pte)		(pte_val(pte) >> PAGE_SHIFT)
+ #define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+ 
+@@ -143,7 +143,7 @@ static inline void pgd_set(pgd_t *pgdp, 
+ 	while (--__i >= 0)			\
+ 		*__ptr++ = 0;			\
+ })
+-#define pmd_page(pmd)		(mem_map + ((unsigned long)(__va(pmd_val(pmd)) - PAGE_OFFSET) >> PAGE_SHIFT))
++#define pmd_page(pmd)		virt_to_page(__va(pmd_val(pmd)))
+ 
+ 
+ #define pgd_none(pgd)		(!pgd_val(pgd))
+@@ -223,10 +223,10 @@ static inline pte_t *pte_offset_kernel(p
+ 	return (pte_t *)__pmd_page(*pmdp) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+ }
+ 
+-#define pte_offset_map(pmdp,address) ((pte_t *)kmap(pmd_page(*pmdp)) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
++#define pte_offset_map(pmdp,address) ((pte_t *)__pmd_page(*pmdp) + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+ #define pte_offset_map_nested(pmdp, address) pte_offset_map(pmdp, address)
+-#define pte_unmap(pte) kunmap(pte)
+-#define pte_unmap_nested(pte) kunmap(pte)
++#define pte_unmap(pte)		((void)0)
++#define pte_unmap_nested(pte)	((void)0)
+ 
+ /*
+  * Allocate and free page tables. The xxx_kernel() versions are
+--- linux-m68k-2.6.21.orig/include/asm-m68k/page.h
++++ linux-m68k-2.6.21/include/asm-m68k/page.h
+@@ -121,7 +121,6 @@ extern unsigned long m68k_memoffset;
+ #ifndef CONFIG_SUN3
+ 
+ #define WANT_PAGE_VIRTUAL
+-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
+ 
+ static inline unsigned long ___pa(void *vaddr)
+ {
+@@ -133,7 +132,7 @@ static inline unsigned long ___pa(void *
+ 		: "0" (vaddr), "i" (m68k_fixup_memoffset));
+ 	return paddr;
+ }
+-#define __pa(vaddr)    ___pa((void *)(vaddr))
++#define __pa(vaddr)	___pa((void *)(vaddr))
+ static inline void *__va(unsigned long paddr)
+ {
+ 	void *vaddr;
+@@ -145,11 +144,6 @@ static inline void *__va(unsigned long p
+ 	return vaddr;
+ }
+ 
+-#else
+-#define __pa(vaddr)		virt_to_phys((void *)(vaddr))
+-#define __va(paddr)		phys_to_virt((unsigned long)(paddr))
+-#endif
+-
+ #else	/* !CONFIG_SUN3 */
+ /* This #define is a horrible hack to suppress lots of warnings. --m */
+ #define __pa(x) ___pa((unsigned long)(x))
+@@ -184,11 +178,47 @@ static inline void *__va(unsigned long x
+ #define virt_to_pfn(kaddr)	(__pa(kaddr) >> PAGE_SHIFT)
+ #define pfn_to_virt(pfn)	__va((pfn) << PAGE_SHIFT)
+ 
+-#define virt_to_page(kaddr)	(mem_map + (((unsigned long)(kaddr)-PAGE_OFFSET) >> PAGE_SHIFT))
+-#define page_to_virt(page)	((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
++extern int m68k_virt_to_node_shift;
++
++#ifdef CONFIG_SINGLE_MEMORY_CHUNK
++#define __virt_to_node(addr)	(&pg_data_map[0])
++#else
++extern struct pglist_data *pg_data_table[];
++
++static inline __attribute_const__ int __virt_to_node_shift(void)
++{
++	int shift;
++
++	asm (
++		"1:	moveq	#0,%0\n"
++		m68k_fixup(%c1, 1b)
++		: "=d" (shift)
++		: "i" (m68k_fixup_vnode_shift));
++	return shift;
++}
++
++#define __virt_to_node(addr)	(pg_data_table[(unsigned long)(addr) >> __virt_to_node_shift()])
++#endif
+ 
+-#define pfn_to_page(pfn)	virt_to_page(pfn_to_virt(pfn))
+-#define page_to_pfn(page)	virt_to_pfn(page_to_virt(page))
++#define virt_to_page(addr) ({						\
++	pfn_to_page(virt_to_pfn(addr));					\
++})
++#define page_to_virt(page) ({						\
++	pfn_to_virt(page_to_pfn(page));					\
++})
++
++#define pfn_to_page(pfn) ({						\
++	unsigned long __pfn = (pfn);					\
++	struct pglist_data *pgdat;					\
++	pgdat = __virt_to_node((unsigned long)pfn_to_virt(__pfn));	\
++	pgdat->node_mem_map + (__pfn - pgdat->node_start_pfn);		\
++})
++#define page_to_pfn(_page) ({						\
++	struct page *__p = (_page);					\
++	struct pglist_data *pgdat;					\
++	pgdat = &pg_data_map[page_to_nid(__p)];				\
++	((__p) - pgdat->node_mem_map) + pgdat->node_start_pfn;		\
++})
+ 
+ #define virt_addr_valid(kaddr)	((void *)(kaddr) >= (void *)PAGE_OFFSET && (void *)(kaddr) < high_memory)
+ #define pfn_valid(pfn)		virt_addr_valid(pfn_to_virt(pfn))
+--- linux-m68k-2.6.21.orig/include/asm-m68k/pgalloc.h
++++ linux-m68k-2.6.21/include/asm-m68k/pgalloc.h
+@@ -8,11 +8,12 @@
+ #include <asm/virtconvert.h>
+ 
+ 
+-
+ #ifdef CONFIG_SUN3
+ #include <asm/sun3_pgalloc.h>
+ #else
+ #include <asm/motorola_pgalloc.h>
+ #endif
+ 
++extern void m68k_setup_node(int node);
++
+ #endif /* M68K_PGALLOC_H */
+--- linux-m68k-2.6.21.orig/include/asm-m68k/pgtable.h
++++ linux-m68k-2.6.21/include/asm-m68k/pgtable.h
+@@ -107,22 +107,7 @@ extern void *empty_zero_page;
+ /* 64-bit machines, beware!  SRB. */
+ #define SIZEOF_PTR_LOG2			       2
+ 
+-/*
+- * Check if the addr/len goes up to the end of a physical
+- * memory chunk.  Used for DMA functions.
+- */
+-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
+-/*
+- * It makes no sense to consider whether we cross a memory boundary if
+- * we support just one physical chunk of memory.
+- */
+-static inline int mm_end_of_chunk(unsigned long addr, int len)
+-{
+-	return 0;
+-}
+-#else
+-int mm_end_of_chunk (unsigned long addr, int len);
+-#endif
++#define mm_end_of_chunk(addr, len)	0
+ 
+ extern void kernel_set_cachemode(void *addr, unsigned long size, int cmode);
+ 
+--- linux-m68k-2.6.21.orig/include/asm-m68k/sun3_pgtable.h
++++ linux-m68k-2.6.21/include/asm-m68k/sun3_pgtable.h
+@@ -132,8 +132,8 @@ static inline void pte_clear (struct mm_
+ #define pfn_pte(pfn, pgprot) \
+ ({ pte_t __pte; pte_val(__pte) = pfn | pgprot_val(pgprot); __pte; })
+ 
+-#define pte_page(pte)		(mem_map+((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT))
+-#define pmd_page(pmd)		(mem_map+((__pmd_page(pmd) - PAGE_OFFSET) >> PAGE_SHIFT))
++#define pte_page(pte)		virt_to_page(__pte_page(pte))
++#define pmd_page(pmd)		virt_to_page(__pmd_page(pmd))
+ 
+ 
+ static inline int pmd_none2 (pmd_t *pmd) { return !pmd_val (*pmd); }
+--- linux-m68k-2.6.21.orig/include/asm-m68k/virtconvert.h
++++ linux-m68k-2.6.21/include/asm-m68k/virtconvert.h
+@@ -8,56 +8,34 @@
+ #ifdef __KERNEL__
+ 
+ #include <linux/compiler.h>
++#include <linux/mmzone.h>
+ #include <asm/setup.h>
+ #include <asm/page.h>
+ 
+-#ifdef CONFIG_AMIGA
+-#include <asm/amigahw.h>
+-#endif
+-
+ /*
+  * Change virtual addresses to physical addresses and vv.
+  */
+-#ifndef CONFIG_SUN3
+-extern unsigned long mm_vtop(unsigned long addr) __attribute_const__;
+-extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
+-#else
+-static inline unsigned long mm_vtop(unsigned long vaddr)
+-{
+-	return __pa(vaddr);
+-}
+-
+-static inline unsigned long mm_ptov(unsigned long paddr)
+-{
+-	return (unsigned long)__va(paddr);
+-}
+-#endif
+-
+-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
+-static inline unsigned long virt_to_phys(void *vaddr)
+-{
+-	return (unsigned long)vaddr - PAGE_OFFSET + m68k_memory[0].addr;
+-}
+-
+-static inline void * phys_to_virt(unsigned long paddr)
+-{
+-	return (void *)(paddr - m68k_memory[0].addr + PAGE_OFFSET);
+-}
+-#else
+ static inline unsigned long virt_to_phys(void *address)
+ {
+-	return mm_vtop((unsigned long)address);
++	return __pa(address);
+ }
+ 
+ static inline void *phys_to_virt(unsigned long address)
+ {
+-	return (void *) mm_ptov(address);
++	return __va(address);
+ }
+-#endif
+ 
+ /* Permanent address of a page. */
+-#define __page_address(page)	(PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
+-#define page_to_phys(page)	virt_to_phys((void *)__page_address(page))
++#ifdef CONFIG_SINGLE_MEMORY_CHUNK
++#define page_to_phys(page) \
++	__pa(PAGE_OFFSET + (((page) - pg_data_map[0].node_mem_map) << PAGE_SHIFT))
++#else
++#define page_to_phys(page) ({						\
++	struct pglist_data *pgdat;					\
++	pgdat = pg_data_table[page_to_nid(page)];			\
++	page_to_pfn(page) << PAGE_SHIFT;				\
++})
++#endif
+ 
+ /*
+  * IO bus memory addresses are 1:1 with the physical address,
+--- linux-m68k-2.6.21.orig/mm/page_alloc.c
++++ linux-m68k-2.6.21/mm/page_alloc.c
+@@ -2713,7 +2713,7 @@ static void __init alloc_node_mem_map(st
+ 			map = alloc_bootmem_node(pgdat, size);
+ 		pgdat->node_mem_map = map + (pgdat->node_start_pfn - start);
+ 	}
+-#ifdef CONFIG_FLATMEM
++#ifndef CONFIG_NEED_MULTIPLE_NODES
+ 	/*
+ 	 * With no DISCONTIG, the global mem_map is just set as node 0's
+ 	 */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/630-extern-cleanup.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/630-extern-cleanup.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,34 @@
+To: linus, akpm
+Cc: lkml
+Subject: [PATCH] m68k: Kill superfluous externs
+
+Kill a few superfluous extern declarations.
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/mm/motorola.c |    7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/mm/motorola.c
++++ linux-m68k-2.6.21/arch/m68k/mm/motorola.c
+@@ -47,7 +47,6 @@ EXPORT_SYMBOL(mm_cachebits);
+ #define INIT_MAPPED_SIZE	(4UL<<20)
+ 
+ extern unsigned long availmem;
+-extern struct mem_info m68k_ramdisk;
+ 
+ static pte_t * __init kernel_page_table(void)
+ {
+@@ -211,11 +210,7 @@ void __init paging_init(void)
+ 	int i;
+ 
+ #ifdef DEBUG
+-	{
+-		extern unsigned long availmem;
+-		printk ("start of paging_init (%p, %lx)\n",
+-			kernel_pg_dir, availmem);
+-	}
++	printk ("start of paging_init (%p, %lx)\n", kernel_pg_dir, availmem);
+ #endif
+ 
+ 	/* Fix the cache mode in the page descriptors for the 680[46]0.  */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/631-thread_stack.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/631-thread_stack.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,117 @@
+To: linus, akpm
+Cc: lkml
+Subject: [PATCH] Thread stack abstractions
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+Thread stack abstractions:
+  - Move thread_info into task_struct
+  - Adapt thread_info initialization
+  - Abstract thread_info access
+  - Thread_info field becomes stack
+  - Change get_task_struct/put_task_struct into inline functions
+  - Move task_struct into <linux/task_struct.h>
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+
+---
+ include/asm-m68k/thread_info.h |   12 ++++++------
+ include/linux/init_task.h      |    2 +-
+ include/linux/sched.h          |    3 ++-
+ kernel/fork.c                  |   10 +++++-----
+ 4 files changed, 14 insertions(+), 13 deletions(-)
+
+--- linux-m68k-2.6.21.orig/include/asm-m68k/thread_info.h
++++ linux-m68k-2.6.21/include/asm-m68k/thread_info.h
+@@ -26,24 +26,24 @@ struct thread_info {
+ 
+ /* THREAD_SIZE should be 8k, so handle differently for 4k and 8k machines */
+ #if PAGE_SHIFT == 13 /* 8k machines */
+-#define alloc_thread_info(tsk)   ((struct thread_info *)__get_free_pages(GFP_KERNEL,0))
+-#define free_thread_info(ti)  free_pages((unsigned long)(ti),0)
++#define alloc_thread_stack(tsk) ((void *)__get_free_pages(GFP_KERNEL,0))
++#define free_thread_stack(ti)  free_pages((unsigned long)(ti),0)
+ #else /* otherwise assume 4k pages */
+-#define alloc_thread_info(tsk)   ((struct thread_info *)__get_free_pages(GFP_KERNEL,1))
+-#define free_thread_info(ti)  free_pages((unsigned long)(ti),1)
++#define alloc_thread_stack(tsk) ((void *)__get_free_pages(GFP_KERNEL,1))
++#define free_thread_stack(ti)  free_pages((unsigned long)(ti),1)
+ #endif /* PAGE_SHIFT == 13 */
+ 
+ #define init_thread_info	(init_task.thread.info)
+ #define init_stack		(init_thread_union.stack)
+ 
+ #define task_thread_info(tsk)	(&(tsk)->thread.info)
+-#define task_stack_page(tsk)	((void *)(tsk)->thread_info)
++#define task_stack_page(tsk)	((void *)(tsk)->stack)
+ #define current_thread_info()	task_thread_info(current)
+ 
+ #define __HAVE_THREAD_FUNCTIONS
+ 
+ #define setup_thread_stack(p, org) ({			\
+-	*(struct task_struct **)(p)->thread_info = (p);	\
++	*(struct task_struct **)(p)->stack = (p);	\
+ 	task_thread_info(p)->task = (p);		\
+ })
+ 
+--- linux-m68k-2.6.21.orig/include/linux/init_task.h
++++ linux-m68k-2.6.21/include/linux/init_task.h
+@@ -95,7 +95,7 @@ extern struct group_info init_groups;
+ #define INIT_TASK(tsk)	\
+ {									\
+ 	.state		= 0,						\
+-	.thread_info	= &init_thread_info,				\
++	.stack		= &init_stack,					\
+ 	.usage		= ATOMIC_INIT(2),				\
+ 	.flags		= 0,						\
+ 	.lock_depth	= -1,						\
+--- linux-m68k-2.6.21.orig/include/linux/sched.h
++++ linux-m68k-2.6.21/include/linux/sched.h
+@@ -799,7 +799,8 @@ struct prio_array;
+ 
+ struct task_struct {
+ 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
+-	struct thread_info *thread_info;
++	//struct thread_info *thread_info;
++	void *stack;
+ 	atomic_t usage;
+ 	unsigned long flags;	/* per process flags, defined below */
+ 	unsigned long ptrace;
+--- linux-m68k-2.6.21.orig/kernel/fork.c
++++ linux-m68k-2.6.21/kernel/fork.c
+@@ -106,7 +106,7 @@ static struct kmem_cache *mm_cachep;
+ 
+ void free_task(struct task_struct *tsk)
+ {
+-	free_thread_info(tsk->thread_info);
++	free_thread_stack(tsk->stack);
+ 	rt_mutex_debug_task_free(tsk);
+ 	free_task_struct(tsk);
+ }
+@@ -161,7 +161,7 @@ void __init fork_init(unsigned long memp
+ static struct task_struct *dup_task_struct(struct task_struct *orig)
+ {
+ 	struct task_struct *tsk;
+-	struct thread_info *ti;
++	void *stack;
+ 
+ 	prepare_to_copy(orig);
+ 
+@@ -169,14 +169,14 @@ static struct task_struct *dup_task_stru
+ 	if (!tsk)
+ 		return NULL;
+ 
+-	ti = alloc_thread_info(tsk);
+-	if (!ti) {
++	stack = alloc_thread_stack(tsk);
++	if (!stack) {
+ 		free_task_struct(tsk);
+ 		return NULL;
+ 	}
+ 
+ 	*tsk = *orig;
+-	tsk->thread_info = ti;
++	tsk->stack = stack;
+ 	setup_thread_stack(tsk, orig);
+ 
+ #ifdef CONFIG_CC_STACKPROTECTOR

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/633-atari_scc.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/633-atari_scc.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,1739 @@
+To: linus, akpm
+Cc: lkml
+Subject: [PATCH] m68k: Atari SCC serial driver
+
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+
+Atari SCC serial driver - this one works less well in 2.6 than it did in 2.4,
+most likely due to the way flip buffer push is handled now - i.e. no
+immediate push of received characters to the line disc. if the handler
+runs in interrupt context, and the bottom half for pushing is run as
+delayed task. 9 out of 10 ping packets end up in the bit bucket this way.
+I haven't figured out how to prevent overruns yet, and getting this right
+will require a bit more testing.
+
+Anyway, the basics are working, and maybe someone can figure out a better
+way to push characters up to the ldisc.
+
+Signed-off-by: Michael Schmitz <schmitz at debian.org>
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/char/Makefile    |    1 
+ drivers/char/atari_scc.c | 1701 +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 1702 insertions(+)
+
+--- linux-m68k-2.6.21.orig/drivers/char/Makefile
++++ linux-m68k-2.6.21/drivers/char/Makefile
+@@ -29,6 +29,7 @@ obj-$(CONFIG_DIGIEPCA)		+= epca.o
+ obj-$(CONFIG_SPECIALIX)		+= specialix.o
+ obj-$(CONFIG_MOXA_INTELLIO)	+= moxa.o
+ obj-$(CONFIG_A2232)		+= ser_a2232.o generic_serial.o
++obj-$(CONFIG_ATARI_SCC)		+= atari_scc.o generic_serial.o
+ obj-$(CONFIG_ATARI_DSP56K)	+= dsp56k.o
+ obj-$(CONFIG_MOXA_SMARTIO)	+= mxser.o
+ obj-$(CONFIG_MOXA_SMARTIO_NEW)	+= mxser_new.o
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/char/atari_scc.c
+@@ -0,0 +1,1701 @@
++/*
++ * drivers/char/atari_scc.c: Atari TT/Falcon Am8530 SCC serial ports implementation.
++ *
++ * Copyright 2005 Michael Schmitz
++ *
++ * Based on:
++ *   drivers/char/vme_scc.c: MVME147, MVME162, BVME6000 SCC serial ports
++ *   implementation.
++ *   Copyright 1999 Richard Hirst <richard at sleepie.demon.co.uk>
++ *
++ * which, in turn, was
++ *
++ * Based on atari_SCC.c which was
++ *   Copyright 1994-95 Roman Hodek <Roman.Hodek at informatik.uni-erlangen.de>
++ *   Partially based on PC-Linux serial.c by Linus Torvalds and Theodore Ts'o
++ *
++ * 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
++ * for more details.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/kdev_t.h>
++#include <asm/io.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/ioport.h>
++#include <linux/interrupt.h>
++#include <linux/errno.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/mm.h>
++#include <linux/serial.h>
++#include <linux/fcntl.h>
++#include <linux/major.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/miscdevice.h>
++#include <linux/console.h>
++#include <linux/init.h>
++#include <asm/setup.h>
++#include <asm/uaccess.h>
++#include <asm/bootinfo.h>
++
++#include <asm/atarihw.h>
++#include <asm/atariints.h>
++
++#include <linux/generic_serial.h>
++#include "scc.h"
++
++#define CONFIG_TT_SCC     1
++#define CONFIG_FALCON_SCC 1
++
++#define CHANNEL_A	0
++#define CHANNEL_B	1
++
++#define SCC_MINOR_BASE	64
++
++/* Shadows for all SCC write registers */
++static unsigned char scc_shadow[2][16];
++
++/* Location to access for SCC register access delay */
++static volatile unsigned char *scc_del = NULL;
++
++/* To keep track of STATUS_REG state for detection of Ext/Status int source */
++static unsigned char scc_last_status_reg[2];
++
++/***************************** Prototypes *****************************/
++
++/* Function prototypes */
++static void scc_disable_tx_interrupts(void *ptr);
++static void scc_enable_tx_interrupts(void *ptr);
++static void scc_disable_rx_interrupts(void *ptr);
++static void scc_enable_rx_interrupts(void *ptr);
++static int scc_get_CD(void *ptr);
++static void scc_shutdown_port(void *ptr);
++static int scc_set_real_termios(void *ptr);
++static void scc_hungup(void *ptr);
++static void scc_close(void *ptr);
++static int scc_chars_in_buffer(void *ptr);
++static int scc_open(struct tty_struct *tty, struct file *filp);
++static int scc_ioctl(struct tty_struct *tty, struct file *filp,
++		     unsigned int cmd, unsigned long arg);
++static void scc_throttle(struct tty_struct *tty);
++static void scc_unthrottle(struct tty_struct *tty);
++static irqreturn_t scc_tx_int(int irq, void *data);
++static irqreturn_t scc_rx_int(int irq, void *data);
++static irqreturn_t scc_stat_int(int irq, void *data);
++static irqreturn_t scc_spcond_int(int irq, void *data);
++static void scc_setsignals(struct scc_port *port, int dtr, int rts);
++static void scc_break_ctl(struct tty_struct *tty, int break_state);
++
++static struct tty_driver *scc_driver;
++
++struct scc_port scc_ports[2];
++
++int scc_initialized = 0;
++
++/*
++ * Flags to indicate one of the serial ports has already been initialized by the
++ * serial debug driver. We may want to hold off reinitializing ...
++ */
++
++/* Flag that Modem1 port is already initialized and used */
++extern int atari_SCC_init_done;
++/* Can be set somewhere, if a SCC master reset has already be done and should
++ * not be repeated; used by kgdb */
++extern int atari_SCC_reset_done;
++
++/*---------------------------------------------------------------------------
++ * Interface from generic_serial.c back here
++ *--------------------------------------------------------------------------*/
++
++static struct real_driver scc_real_driver = {
++	.disable_tx_interrupts	= scc_disable_tx_interrupts,
++	.enable_tx_interrupts	= scc_enable_tx_interrupts,
++	.disable_rx_interrupts	= scc_disable_rx_interrupts,
++	.enable_rx_interrupts	= scc_enable_rx_interrupts,
++	.get_CD			= scc_get_CD,
++	.shutdown_port		= scc_shutdown_port,
++	.set_real_termios	= scc_set_real_termios,
++	.chars_in_buffer	= scc_chars_in_buffer,
++	.close			= scc_close,
++	.hungup			= scc_hungup,
++};
++
++static struct tty_operations scc_ops = {
++	.open			= scc_open,
++	.close			= gs_close,
++	.write			= gs_write,
++	.put_char		= gs_put_char,
++	.flush_chars		= gs_flush_chars,
++	.write_room		= gs_write_room,
++	.chars_in_buffer	= gs_chars_in_buffer,
++	.flush_buffer		= gs_flush_buffer,
++	.ioctl			= scc_ioctl,
++	.throttle		= scc_throttle,
++	.unthrottle		= scc_unthrottle,
++	.set_termios		= gs_set_termios,
++	.stop			= gs_stop,
++	.start			= gs_start,
++	.hangup			= gs_hangup,
++	.break_ctl		= scc_break_ctl,
++};
++
++/* BRG values for the standard speeds and the various clock sources */
++
++typedef struct {
++	unsigned clksrc;		/* clock source to use or -1 for not possible */
++	unsigned div;			/* divisor: 1, 2 and 4 correspond to
++					 * direct 1:16, 1:32 and 1:64 modes,
++					 * divisors >= 4 yield a BRG value of
++					 * div/2-2 (in 1:16 mode)
++					 */
++} BAUD_ENTRY;
++
++/* A pointer for each channel to the current baud table */
++static BAUD_ENTRY *scc_baud_table[2];
++
++/* Baud table format:
++ *
++ * Each entry consists of the clock source (CLK_RTxC, CLK_TRxC or
++ * CLK_PCLK) and a divisor. The following rules apply to the divisor:
++ *
++ *   - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use
++ *               the BRG)
++ *
++ *   - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible)
++ *
++ *   - CLK_PCLK: >= 4 and even (no direct modes, only BRG)
++ *
++ */
++
++/* This table is used if RTxC = 3.672 MHz. This is the case for TT's
++ * channel A and for both channels on the Mega STE/Falcon. (TRxC is unused)
++ */
++
++static BAUD_ENTRY bdtab_norm[20] = {
++	/* B0      */ { 0, 0 },
++	/* B50     */ { CLK_RTxC, 4590 },
++	/* B75     */ { CLK_RTxC, 3060 },
++	/* B110    */ { CLK_PCLK, 4576 },
++	/* B134    */ { CLK_PCLK, 3756 },
++	/* B150    */ { CLK_RTxC, 1530 },
++	/* B200    */ { CLK_PCLK, 2516 },
++	/* B300    */ { CLK_PCLK, 1678 },
++	/* B600    */ { CLK_PCLK, 838 },
++	/* B1200   */ { CLK_PCLK, 420 },
++	/* B1800   */ { CLK_PCLK, 280 },
++	/* B2400   */ { CLK_PCLK, 210 },
++	/* B4800   */ { CLK_RTxC, 48 },
++	/* B9600   */ { CLK_RTxC, 24 },
++	/* B19200  */ { CLK_RTxC, 12 },
++	/* B38400  */ { CLK_RTxC, 6 },   /* #15 spd_extra */
++	/* B57600  */ { CLK_RTxC, 4 },   /* #16 spd_hi */
++	/* B115200 */ { CLK_RTxC, 2 },   /* #17 spd_vhi */
++	/* B230400 */ { CLK_RTxC, 1 },   /* #18 spd_shi */
++	/* B460800 */ { 0, 0 }           /* #19 spd_warp: Impossible */
++};
++
++/* This is a special table for the TT channel B with 307.2 kHz at RTxC
++ * and 2.4576 MHz at TRxC
++ */
++static BAUD_ENTRY bdtab_TTChB[20] = {
++	/* B0      */ { 0, 0 },
++	/* B50     */ { CLK_RTxC, 384 },
++	/* B75     */ { CLK_RTxC, 256 },
++	/* B110    */ { CLK_PCLK, 4576 },
++	/* B134    */ { CLK_PCLK, 3756 },
++	/* B150    */ { CLK_RTxC, 128 },
++	/* B200    */ { CLK_RTxC, 96 },
++	/* B300    */ { CLK_RTxC, 64 },
++	/* B600    */ { CLK_RTxC, 32 },
++	/* B1200   */ { CLK_RTxC, 16 },
++	/* B1800   */ { CLK_PCLK, 280 },
++	/* B2400   */ { CLK_RTxC, 8 },
++	/* B4800   */ { CLK_RTxC, 4 },
++	/* B9600   */ { CLK_RTxC, 2 },
++	/* B19200  */ { CLK_RTxC, 1 },
++	/* B38400  */ { CLK_TRxC, 4 },
++	/* B57600  */ { CLK_TRxC, 2 }, /* 57600 is not possible, use 76800 instead */
++	/* B115200 */ { CLK_TRxC, 1 }, /* 115200 is not possible, use 153600 instead */
++	/* B230400 */ { 0, 0 },        /* #18 spd_shi: Impossible  */
++	/* B460800 */ { 0, 0 }         /* #19 spd_warp: Impossible */
++};
++
++
++/*----------------------------------------------------------------------------
++ * atari_scc_init() and support functions
++ *---------------------------------------------------------------------------*/
++
++static int scc_init_drivers(void)
++{
++	int error;
++
++	scc_driver = alloc_tty_driver(2);
++	if (!scc_driver)
++		return -ENOMEM;
++	scc_driver->owner = THIS_MODULE;
++	scc_driver->driver_name = "scc";
++	scc_driver->name = "ttyS";
++	scc_driver->major = TTY_MAJOR;
++	scc_driver->minor_start = SCC_MINOR_BASE;
++	scc_driver->type = TTY_DRIVER_TYPE_SERIAL;
++	scc_driver->subtype = SERIAL_TYPE_NORMAL;
++	scc_driver->init_termios = tty_std_termios;
++	scc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
++	scc_driver->flags = TTY_DRIVER_REAL_RAW;
++
++	tty_set_operations(scc_driver, &scc_ops);
++
++	if ((error = tty_register_driver(scc_driver))) {
++		printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n",
++		       error);
++		put_tty_driver(scc_driver);
++		return 1;
++	}
++
++	return 0;
++}
++
++
++/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1).
++ */
++
++static void scc_init_portstructs(void)
++{
++	struct scc_port *port;
++	int i;
++
++	for (i = 0; i < 2; i++) {
++		port = scc_ports + i;
++		port->gs.magic = SCC_MAGIC;
++		port->gs.close_delay = HZ/2;
++		port->gs.closing_wait = 30 * HZ;
++		port->gs.rd = &scc_real_driver;
++#ifdef NEW_WRITE_LOCKING
++		port->gs.port_write_sem = MUTEX;
++#endif
++		init_waitqueue_head(&port->gs.open_wait);
++		init_waitqueue_head(&port->gs.close_wait);
++	}
++}
++
++
++#ifdef CONFIG_TT_SCC
++static int atari_tt_scc_init(void)
++{
++	struct scc_port *port;
++
++	printk(KERN_INFO "SCC: Atari TT Serial Driver\n");
++	/* FIXME channel A may be switchable between modem and LAN port */
++	/* Init channel A */
++	if (atari_SCC_init_done)
++		printk(KERN_INFO "SCC: already initialized, expect trouble!\n");
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: init channel A\n");
++#endif
++	port = &scc_ports[0];
++	port->channel = CHANNEL_A;
++	port->ctrlp = (volatile unsigned char *)&scc.cha_a_ctrl;
++	port->datap = port->ctrlp + 1;
++	port->port_a = &scc_ports[0];
++	port->port_b = &scc_ports[1];
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: request channel A irqs, port = %p\n", port);
++#endif
++	request_irq(IRQ_SCCA_TX, scc_tx_int, IRQ_TYPE_PRIO, "SCC-A TX", port);
++	request_irq(IRQ_SCCA_STAT, scc_stat_int, IRQ_TYPE_PRIO,
++		    "SCC-A status", port);
++	request_irq(IRQ_SCCA_RX, scc_rx_int, IRQ_TYPE_PRIO, "SCC-A RX", port);
++	request_irq(IRQ_SCCA_SPCOND, scc_spcond_int, IRQ_TYPE_PRIO,
++		    "SCC-A special cond", port);
++	{
++		SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: read SCC status\n");
++#endif
++		/* on the first access, read status register to reset internal pointers */
++		SCCread(STATUS_REG);
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: reset SCC\n");
++#endif
++		/* FIXME: master reset, once only */
++		SCCwrite(MASTER_INT_CTRL, MIC_HARD_RESET);
++		udelay(40);
++
++		/* disable interrupts for this channel */
++		SCCwrite(INT_AND_DMA_REG, 0);
++		/* Set the interrupt vector ; 0x60 for all Atari models */
++		SCCwrite(INT_VECTOR_REG, 0x60);
++		/* Interrupt parameters: vector includes status, status low */
++		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
++		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
++
++		/* disable interrupts for this channel */
++		SCCwrite(INT_AND_DMA_REG, 0);
++	}
++
++	if (!atari_SCC_init_done) {
++		/* Init channel B */
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: init channel B\n");
++#endif
++		port = &scc_ports[1];
++		port->channel = CHANNEL_B;
++		port->ctrlp = (volatile unsigned char *)&scc.cha_b_ctrl;
++		port->datap = port->ctrlp + 1;
++		port->port_a = &scc_ports[0];
++		port->port_b = &scc_ports[1];
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: request channel B irqs, port = %p\n", port);
++#endif
++		request_irq(IRQ_SCCB_TX, scc_tx_int, IRQ_TYPE_PRIO,
++			    "SCC-B TX", port);
++		request_irq(IRQ_SCCB_STAT, scc_stat_int, IRQ_TYPE_PRIO,
++			    "SCC-B status", port);
++		request_irq(IRQ_SCCB_RX, scc_rx_int, IRQ_TYPE_PRIO,
++			    "SCC-B RX", port);
++		request_irq(IRQ_SCCB_SPCOND, scc_spcond_int, IRQ_TYPE_PRIO,
++			    "SCC-B special cond", port);
++		{
++			SCC_ACCESS_INIT(port);
++
++			/* disable interrupts for this channel */
++			SCCwrite(INT_AND_DMA_REG, 0);
++		}
++/* not implemented yet */
++#if 0
++		request_irq(IRQ_TT_MFP_RI, scc_ri_int, IRQ_TYPE_SLOW,
++			    "TT-MFP ring indicator (modem 2)", port);
++#endif
++
++	}
++
++	/* once only: initalize MFP timer C for RTxC */
++	tt_mfp.tim_ct_cd = (tt_mfp.tim_ct_cd & ~0x70) | 0x10;
++	tt_mfp.tim_dt_c = 1;
++	atari_turnoff_irq(IRQ_TT_MFP_TIMC);
++
++	/* set baud tables */
++	scc_baud_table[CHANNEL_A] = bdtab_norm;
++	scc_baud_table[CHANNEL_B] = bdtab_TTChB;
++
++	/* Initialise the tty driver structures and register */
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: scc_init_portstructs()\n");
++#endif
++	scc_init_portstructs();
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: scc_init_drivers()\n");
++#endif
++	scc_init_drivers();
++
++	return 0;
++}
++#endif
++
++
++#ifdef CONFIG_FALCON_SCC
++static int atari_falcon_scc_init(void)
++{
++	struct scc_port *port;
++
++	printk(KERN_INFO "SCC: Atari Falcon Serial Driver\n");
++	if (atari_SCC_init_done)
++		printk(KERN_INFO "SCC: already initialized, expect trouble!\n");
++
++	/* Init channel A */
++	port = &scc_ports[0];
++	port->channel = CHANNEL_A;
++	port->ctrlp = (volatile unsigned char *)&scc.cha_a_ctrl;
++	port->datap = port->ctrlp + 2;
++	port->port_a = &scc_ports[0];
++	port->port_b = &scc_ports[1];
++	request_irq(IRQ_SCCA_TX, scc_tx_int, IRQ_TYPE_PRIO, "SCC-A TX", port);
++	request_irq(IRQ_SCCA_STAT, scc_stat_int, IRQ_TYPE_PRIO,
++		    "SCC-A status", port);
++	request_irq(IRQ_SCCA_RX, scc_rx_int, IRQ_TYPE_PRIO, "SCC-A RX", port);
++	request_irq(IRQ_SCCA_SPCOND, scc_spcond_int, IRQ_TYPE_PRIO,
++		    "SCC-A special cond", port);
++	{
++		SCC_ACCESS_INIT(port);
++
++		/* on the first access, read status register to reset internal pointers */
++		SCCread(STATUS_REG);
++
++		/* FIXME: master reset, once only */
++		SCCwrite(MASTER_INT_CTRL, MIC_HARD_RESET);
++		udelay(40);
++
++		/* disable interrupts for this channel */
++		SCCwrite(INT_AND_DMA_REG, 0);
++		/* Set the interrupt vector */
++		SCCwrite(INT_VECTOR_REG, 0x60);
++		/* Interrupt parameters: vector includes status, status low */
++		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
++		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
++	}
++
++	/* conditionalize if port in use by console ?? */
++	/* Init channel B */
++	port = &scc_ports[1];
++	port->channel = CHANNEL_B;
++	port->ctrlp = (volatile unsigned char *)&scc.cha_b_ctrl;
++	port->datap = port->ctrlp + 2;
++	port->port_a = &scc_ports[0];
++	port->port_b = &scc_ports[1];
++	request_irq(IRQ_SCCB_TX, scc_tx_int, IRQ_TYPE_PRIO, "SCC-B TX", port);
++	request_irq(IRQ_SCCB_STAT, scc_stat_int, IRQ_TYPE_PRIO,
++		    "SCC-B status", port);
++	request_irq(IRQ_SCCB_RX, scc_rx_int, IRQ_TYPE_PRIO, "SCC-B RX", port);
++	request_irq(IRQ_SCCB_SPCOND, scc_spcond_int, IRQ_TYPE_PRIO,
++		    "SCC-B special cond", port);
++
++	{
++		SCC_ACCESS_INIT(port);	/* Either channel will do */
++
++		/* disable interrupts for this channel */
++		SCCwrite(INT_AND_DMA_REG, 0);
++	}
++
++	/* set baud tables */
++	scc_baud_table[CHANNEL_A] = bdtab_norm;
++	scc_baud_table[CHANNEL_B] = bdtab_norm;
++
++	/* Initialise the tty driver structures and register */
++	scc_init_portstructs();
++	scc_init_drivers();
++
++	return 0;
++}
++#endif
++
++
++#ifdef CONFIG_ST_SCC
++static int atari_st_scc_init(void)
++{
++	struct scc_port *port;
++
++	int escc = ATARIHW_PRESENT(ST_ESCC);
++
++	printk(KERN_INFO "SCC: Atari MegaST/E Serial Driver\n");
++	/* FIXME: ports reversed logic */
++	/* Init channel A */
++	port = &scc_ports[1];
++	port->channel = CHANNEL_A;
++	port->ctrlp = (volatile unsigned char *)(escc ? &st_escc.cha_a_ctrl : &scc.cha_a_ctrl);
++	port->datap = port->ctrlp + 4;
++	port->port_a = &scc_ports[1];
++	port->port_b = &scc_ports[0];
++	request_irq(IRQ_SCCA_TX, scc_tx_int, IRQ_TYPE_PRIO, "SCC-A TX", port);
++	request_irq(IRQ_SCCA_STAT, scc_stat_int, IRQ_TYPE_PRIO,
++		    "SCC-A status", port);
++	request_irq(IRQ_SCCA_RX, scc_rx_int, IRQ_TYPE_PRIO, "SCC-A RX", port);
++	request_irq(SCCA_SPCOND, scc_spcond_int, IRQ_TYPE_PRIO,
++		    "SCC-A special cond", port);
++	{
++		SCC_ACCESS_INIT(port);
++
++		/* on the first access, read status register to reset internal pointers */
++		SCCread(STATUS_REG);
++
++		/* FIXME: master reset, once only */
++		SCCwrite(MASTER_INT_CTRL, MIC_HARD_RESET);
++		udelay(40);
++
++		/* disable interrupts for this channel */
++		SCCwrite(INT_AND_DMA_REG, 0);
++		/* Set the interrupt vector */
++		SCCwrite(INT_VECTOR_REG, BVME_IRQ_SCC_BASE);
++		/* Interrupt parameters: vector includes status, status low */
++		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
++		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
++	}
++
++	/* Init channel B */
++	port = &scc_ports[0];
++	port->channel = CHANNEL_B;
++	port->ctrlp = (volatile unsigned char *)(escc ? &st_escc.cha_b_ctrl : &scc.cha_b_ctrl);
++	port->datap = port->ctrlp + 4;
++	port->port_a = &scc_ports[0];
++	port->port_b = &scc_ports[1];
++	request_irq(IRQ_SCCB_TX, scc_tx_int, IRQ_TYPE_PRIO, "SCC-B TX", port);
++	request_irq(IRQ_SCCB_STAT, scc_stat_int, IRQ_TYPE_PRIO,
++		    "SCC-B status", port);
++	request_irq(IRQ_SCCB_RX, scc_rx_int, IRQ_TYPE_PRIO, "SCC-B RX", port);
++	request_irq(IRQ_SCCB_SPCOND, scc_spcond_int, IRQ_TYPE_PRIO,
++		    "SCC-B special cond", port);
++
++	{
++		SCC_ACCESS_INIT(port);	/* Either channel will do */
++
++		/* disable interrupts for this channel */
++		SCCwrite(INT_AND_DMA_REG, 0);
++	}
++
++	/* set baud tables */
++	scc_baud_table[CHANNEL_A] = bdtab_norm;
++	scc_baud_table[CHANNEL_B] = bdtab_norm;
++
++	/* Initialise the tty driver structures and register */
++	scc_init_portstructs();
++	scc_init_drivers();
++
++	return 0;
++}
++#endif
++
++
++int atari_scc_init(void)
++{
++	int res = -ENODEV;
++	static int called = 0;
++
++	if (called)
++		return res;
++	called = 1;
++
++	if (!(ATARIHW_PRESENT(SCC) || ATARIHW_PRESENT(ST_ESCC)))
++		return -ENODEV;
++
++	scc_del = &mfp.par_dt_reg;
++
++#ifdef CONFIG_TT_SCC
++	if (MACH_IS_TT)
++		res = atari_tt_scc_init();
++#endif
++#ifdef CONFIG_FALCON_SCC
++	if (MACH_IS_FALCON)
++		res = atari_falcon_scc_init();
++#endif
++#ifdef CONFIG_ST_SCC
++	if (MACH_IS_ST)
++		res = atari_st_scc_init();
++#endif
++	return res;
++}
++
++void atari_scc_cleanup(void)
++{
++	struct scc_port *port;
++
++	tty_unregister_driver(scc_driver);
++	port = &scc_ports[0];
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: free channel A irqs, port = %p\n", port);
++#endif
++	free_irq(IRQ_SCCA_TX, port);
++	free_irq(IRQ_SCCA_STAT, port);
++	free_irq(IRQ_SCCA_RX, port);
++	free_irq(IRQ_SCCA_SPCOND, port);
++
++	port = &scc_ports[1];
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: free channel A irqs, port = %p\n", port);
++#endif
++	free_irq(IRQ_SCCB_TX, port);
++	free_irq(IRQ_SCCB_STAT, port);
++	free_irq(IRQ_SCCB_RX, port);
++	free_irq(IRQ_SCCB_SPCOND, port);
++
++}
++
++module_init(atari_scc_init);
++module_exit(atari_scc_cleanup);
++
++/*---------------------------------------------------------------------------
++ * Interrupt handlers
++ *--------------------------------------------------------------------------*/
++
++static irqreturn_t scc_rx_int(int irq, void *data)
++{
++	unsigned char ch;
++	struct scc_port *port = data;
++	struct tty_struct *tty = port->gs.tty;
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: rx_int ...\n");
++#endif
++	ch = SCCread_NB(RX_DATA_REG);
++	if (!tty) {
++		printk(KERN_WARNING "scc_rx_int with NULL tty!\n");
++		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++		return IRQ_HANDLED;
++	}
++	tty_insert_flip_char(tty, ch, 0);
++#if 0
++	if (tty->flip.count < TTY_FLIPBUF_SIZE) {
++		*tty->flip.char_buf_ptr = ch;
++		*tty->flip.flag_buf_ptr = 0;
++		tty->flip.flag_buf_ptr++;
++		tty->flip.char_buf_ptr++;
++		tty->flip.count++;
++	}
++#endif
++	/* Check if another character is already ready; in that case, the
++	 * spcond_int() function must be used, because this character may have an
++	 * error condition that isn't signalled by the interrupt vector used!
++	 */
++	if (SCCread(INT_PENDING_REG) &
++	    (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) {
++		scc_spcond_int(irq, data);
++		return IRQ_HANDLED;
++	}
++
++	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++
++	tty_flip_buffer_push(tty);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: rx_int done\n");
++#endif
++	return IRQ_HANDLED;
++}
++
++
++static irqreturn_t scc_spcond_int(int irq, void *data)
++{
++	struct scc_port *port = data;
++	struct tty_struct *tty = port->gs.tty;
++	unsigned char stat, ch, err;
++	int int_pending_mask = port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX;
++
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: spcond_int ...\n");
++#endif
++	if (!tty) {
++		printk(KERN_WARNING "scc_spcond_int with NULL tty!\n");
++		SCCwrite(COMMAND_REG, CR_ERROR_RESET);
++		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++		return IRQ_HANDLED;
++	}
++	do {
++		stat = SCCread(SPCOND_STATUS_REG);
++		ch = SCCread_NB(RX_DATA_REG);
++
++		if (stat & SCSR_RX_OVERRUN)
++			err = TTY_OVERRUN;
++		else if (stat & SCSR_PARITY_ERR)
++			err = TTY_PARITY;
++		else if (stat & SCSR_CRC_FRAME_ERR)
++			err = TTY_FRAME;
++		else
++			err = 0;
++
++		tty_insert_flip_char(tty, ch, err);
++#if 0
++		if (tty->flip.count < TTY_FLIPBUF_SIZE) {
++			*tty->flip.char_buf_ptr = ch;
++			*tty->flip.flag_buf_ptr = err;
++			tty->flip.flag_buf_ptr++;
++			tty->flip.char_buf_ptr++;
++			tty->flip.count++;
++		}
++#endif
++		/* ++TeSche: *All* errors have to be cleared manually,
++		 * else the condition persists for the next chars
++		 */
++		if (err)
++			SCCwrite(COMMAND_REG, CR_ERROR_RESET);
++
++	} while (SCCread(INT_PENDING_REG) & int_pending_mask);
++
++	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++
++	tty_flip_buffer_push(tty);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: spcond_int done\n");
++#endif
++	return IRQ_HANDLED;
++}
++
++/* not implemented yet */
++#if 0
++static void scc_ri_int(int irq, void *data)
++{
++	struct scc_port *port = data;
++	/* update input line counter */
++	port->icount.rng++;
++	wake_up_interruptible(&port->delta_msr_wait);
++}
++#endif
++
++static irqreturn_t scc_tx_int(int irq, void *data)
++{
++	struct scc_port *port = data;
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: tx_int irq %d port %p ...\n", irq, data);
++#endif
++	if (!port->gs.tty) {
++		printk(KERN_WARNING "scc_tx_int with NULL tty!\n");
++		SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
++		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
++		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++		return IRQ_HANDLED;
++	}
++	while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) {
++		if (port->x_char) {
++#ifdef DEBUG
++			printk(KERN_INFO "SCC: tx_int writing char %c\n",
++			       port->x_char);
++#endif
++			SCCwrite(TX_DATA_REG, port->x_char);
++			port->x_char = 0;
++		} else if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
++			   port->gs.tty->hw_stopped) {
++#ifdef DEBUG
++			printk(KERN_INFO "SCC: nothing to do!\n");
++#endif
++			break;
++		} else {
++#ifdef DEBUG
++			printk(KERN_INFO "SCC: tx_int writing buf %c\n",
++			       port->gs.xmit_buf[port->gs.xmit_tail]);
++#endif
++			SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]);
++			port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1);
++			if (--port->gs.xmit_cnt <= 0)
++				break;
++		}
++	}
++	if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
++	    port->gs.tty->hw_stopped) {
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: nothing to do, disabling int\n");
++#endif
++		/* disable tx interrupts */
++		SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
++		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);	/* disable tx_int on next tx underrun? */
++		port->gs.flags &= ~GS_TX_INTEN;
++	}
++	if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) {
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: waking up tty!\n");
++#endif
++		tty_wakeup(port->gs.tty);
++	}
++
++	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: tx_int done\n");
++#endif
++	return IRQ_HANDLED;
++}
++
++
++static irqreturn_t scc_stat_int(int irq, void *data)
++{
++	struct scc_port *port = data;
++	unsigned channel = port->channel;
++	unsigned char last_sr, sr, changed;
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: stat_int ...\n");
++#endif
++	last_sr = scc_last_status_reg[channel];
++	sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG);
++	changed = last_sr ^ sr;
++
++	if (changed & SR_DCD) {
++		port->c_dcd = !!(sr & SR_DCD);
++		if (!(port->gs.flags & ASYNC_CHECK_CD))
++			;	/* Don't report DCD changes */
++		else if (port->c_dcd) {
++			/* Are we blocking in open? */
++			wake_up_interruptible(&port->gs.open_wait);
++		} else {
++			if (port->gs.tty)
++				tty_hangup(port->gs.tty);
++		}
++	}
++
++	// FIXME: CTS and DSR status changes?
++
++	SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);
++	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: stat_int done\n");
++#endif
++	return IRQ_HANDLED;
++}
++
++
++/*---------------------------------------------------------------------------
++ * generic_serial.c callback funtions
++ *--------------------------------------------------------------------------*/
++
++static void scc_disable_tx_interrupts(void *ptr)
++{
++	struct scc_port *port = ptr;
++	unsigned long flags;
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: disable_tx_int ...\n");
++#endif
++	local_irq_save(flags);
++	SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
++	port->gs.flags &= ~GS_TX_INTEN;
++	local_irq_restore(flags);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: disable_tx_int done!\n");
++#endif
++}
++
++
++static void scc_enable_tx_interrupts(void *ptr)
++{
++	struct scc_port *port = ptr;
++	unsigned long flags;
++
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: enable_tx_int ...\n");
++#endif
++	local_irq_save(flags);
++	SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);
++	/* restart the transmitter */
++	scc_tx_int(0, port);
++	local_irq_restore(flags);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: enable_tx_int done!\n");
++#endif
++}
++
++
++static void scc_disable_rx_interrupts(void *ptr)
++{
++	struct scc_port *port = ptr;
++	unsigned long flags;
++
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: disable_rx_int ...\n");
++#endif
++	local_irq_save(flags);
++	SCCmod(INT_AND_DMA_REG,
++	       ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0);
++	local_irq_restore(flags);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: disable_rx_int done!\n");
++#endif
++}
++
++
++static void scc_enable_rx_interrupts(void *ptr)
++{
++	struct scc_port *port = ptr;
++	unsigned long flags;
++
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: enable_rx_int ...\n");
++#endif
++	local_irq_save(flags);
++	SCCmod(INT_AND_DMA_REG, 0xff,
++	       IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL);
++	local_irq_restore(flags);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: enable_rx_int done!\n");
++#endif
++}
++
++
++static int scc_get_CD(void *ptr)
++{
++	struct scc_port *port = ptr;
++	unsigned channel = port->channel;
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: get_CD!\n");
++#endif
++	return !!(scc_last_status_reg[channel] & SR_DCD);
++}
++
++
++static void scc_shutdown_port(void *ptr)
++{
++	struct scc_port *port = ptr;
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: shutdown_port ...\n");
++#endif
++	port->gs.flags &= ~GS_ACTIVE;
++	if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL)
++		scc_setsignals(port, 0, 0);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: shutdown_port done!\n");
++#endif
++}
++
++
++static int scc_set_real_termios(void *ptr)
++{
++	/* the SCC has char sizes 5,7,6,8 in that order! */
++	static int chsize_map[4] = { 0, 2, 1, 3 };
++	unsigned int cflag, baud, baudbits, baudidx, brgmode;
++	unsigned int clkmode, clksrc, div, chsize, channel, brgval = 0;
++	unsigned long flags;
++	struct scc_port *port = ptr;
++	SCC_ACCESS_INIT(port);
++
++	if (!port->gs.tty || !port->gs.tty->termios)
++		return 0;
++
++	channel = port->channel;
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: termios for channel %p\n", channel);
++#endif
++	cflag = port->gs.tty->termios->c_cflag;
++	baud = port->gs.baud;
++	baudbits = cflag & CBAUD;
++	chsize = (cflag & CSIZE) >> 4;
++
++	if (baud == 0) {
++		/* speed == 0 -> drop DTR */
++		local_irq_save(flags);
++		SCCmod(TX_CTRL_REG, ~TCR_DTR, 0);
++		local_irq_restore(flags);
++		return 0;
++	} else if ((MACH_IS_TT && (baud < 50 || baud > 115200)) ||
++		   (MACH_IS_FALCON && (baud < 50 || baud > 230400))) {
++		printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud);
++		return 0;
++	}
++
++	if (cflag & CLOCAL)
++		port->gs.flags &= ~ASYNC_CHECK_CD;
++	else
++		port->gs.flags |= ASYNC_CHECK_CD;
++
++	// calculate brgval for Atari; enable direct modes!
++
++	/* convert baud rate from gs.baud to table index, set custom divisor eventually */
++
++	div     = 0;
++	clksrc  = 0;
++	baudidx = 0;
++
++	switch (baud) {
++	case 50:
++		baudidx = 1;
++		break;
++	case 75:
++		baudidx = 2;
++		break;
++	case 110:
++		baudidx = 3;
++		break;
++	case 134:
++		baudidx = 4;
++		break;
++	case 150:
++		baudidx = 5;
++		break;
++	case 200:
++		baudidx = 6;
++		break;
++	case 300:
++		baudidx = 7;
++		break;
++	case 600:
++		baudidx = 8;
++		break;
++	case 1200:
++		baudidx = 9;
++		break;
++	case 1800:
++		baudidx = 10;
++		break;
++	case 2400:
++		baudidx = 11;
++		break;
++	case 4800:
++		baudidx = 12;
++		break;
++	case 9600:
++		baudidx = 13;
++		break;
++	case 19200:
++		baudidx = 14;
++		break;
++	case 38400:
++		baudidx = 15;
++		break;
++	case 57600:
++		baudidx = 16;
++		break;
++	case 115200:
++		baudidx = 17;
++		break;
++	case 230400:
++		baudidx = 18;
++		break;
++	default:
++		baudidx = 15;
++		break;
++	}
++
++	/* do we have a custom divisor ?? */
++	if (!div) {
++		if (baudidx > 19)
++			baudidx = 19;
++		clksrc = scc_baud_table[channel][baudidx].clksrc;
++		div = scc_baud_table[channel][baudidx].div;
++		if (!div) {
++			printk(" SCC_change_speed: divisor = 0 !!!");
++			return 0;
++		}
++	}
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: termios baud %d baudbits %d baudidx %d \n clksrc %d div %d\n",
++		baud, baudbits, baudidx, clksrc, div);
++#endif
++	/* compute the SCC's clock source, clock mode, BRG mode and BRG
++	 * value from clksrc and div
++	 */
++	if (div <= 4) {
++		clkmode = (div == 1 ? A1CR_CLKMODE_x16 :
++			   div == 2 ? A1CR_CLKMODE_x32 :
++				      A1CR_CLKMODE_x64);
++		clksrc  = (clksrc == CLK_RTxC
++			   ? CCR_TXCLK_RTxC | CCR_RXCLK_RTxC
++			   : CCR_TXCLK_TRxC | CCR_RXCLK_TRxC);
++		brgmode = 0; /* off */
++		brgval  = 0;
++	} else {
++		brgval  = div/2 - 2;
++		brgmode = (DCR_BRG_ENAB |
++			   (clksrc == CLK_PCLK ? DCR_BRG_USE_PCLK : 0));
++		clkmode = A1CR_CLKMODE_x16;
++		clksrc  = CCR_TXCLK_BRG | CCR_RXCLK_BRG;
++	}
++
++	//printk(KERN_INFO "SCC: termios baud %d baudbits %d baudidx %d \n clksrc %d clkmode %d div %d brgval %d brgmode %d\n",
++	//	baud, baudbits, baudidx, clksrc, clkmode, div, brgval, brgmode);
++
++	/* Now we have all parameters and can go to set them: */
++	local_irq_save(flags);
++
++#ifdef DEBUG
++	printk("  brgval=%d brgmode=%02x clkmode=%02x clksrc=%02x\n",
++		brgval, brgmode, clkmode, clksrc);
++#endif
++	/* receiver's character size and auto-enables */
++#if 0	// auto-enable considered harmful ...
++	SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE),
++	       (chsize_map[chsize] << 6) |
++	       ((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0));
++#else
++	/* receiver's character size */
++	SCCmod(RX_CTRL_REG, ~RCR_CHSIZE_MASK, chsize_map[chsize] << 6);
++#endif
++#ifdef DEBUG
++	printk("  RX_CTRL_REG <- %02x\n", SCCread( RX_CTRL_REG ));
++#endif
++
++	// clock mode changes depending on baud rate
++	/* parity and stop bits (both, Tx and Rx) and clock mode */
++	SCCmod(AUX1_CTRL_REG,
++		~(A1CR_PARITY_MASK | A1CR_MODE_MASK | A1CR_CLKMODE_MASK),
++		((cflag & PARENB
++		  ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN)
++		  : A1CR_PARITY_NONE)
++		 | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1)
++		 | clkmode));
++
++#ifdef DEBUG
++	printk("  AUX1_CTRL_REG <- %02x\n", SCCread(AUX1_CTRL_REG));
++#endif
++	/* sender's character size, set DTR for valid baud rate */
++	SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR);
++#ifdef DEBUG
++	printk("  TX_CTRL_REG <- %02x\n", SCCread(TX_CTRL_REG));
++#endif
++
++	// clock sources change for TT !!
++	/* clock sources never change */
++	/* clock sources */
++	SCCmod(CLK_CTRL_REG, ~(CCR_TXCLK_MASK | CCR_RXCLK_MASK), clksrc);
++#ifdef DEBUG
++	printk("  CLK_CTRL_REG <- %02x\n", SCCread(CLK_CTRL_REG));
++#endif
++
++	/* disable BRG before changing the value */
++	SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0);
++	/* BRG value */
++	SCCwrite(TIMER_LOW_REG, brgval & 0xff);
++	SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff);
++	/* BRG enable, and clock source never changes */
++	//SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);
++	SCCmod(DPLL_CTRL_REG, ~(DCR_BRG_ENAB | DCR_BRG_USE_PCLK), brgmode);
++#ifdef DEBUG
++	printk("  TIMER_LOW_REG <- %02x\n", SCCread(TIMER_LOW_REG));
++	printk("  TIMER_HIGH_REG <- %02x\n", SCCread(TIMER_HIGH_REG));
++#endif
++#ifdef DEBUG
++	printk("  DPLL_CTRL_REG <- %02x\n", SCCread(DPLL_CTRL_REG));
++#endif
++
++	local_irq_restore(flags);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: done termios for channel %d\n", channel);
++#endif
++	return 0;
++}
++
++
++static int scc_chars_in_buffer(void *ptr)
++{
++	struct scc_port *port = ptr;
++#ifdef DEBUG
++	int rv;
++#endif
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	rv = (SCCread(SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0  : 1;
++	printk(KERN_INFO "SCC: chars_in_buffer: %d\n", rv);
++	return rv;
++#else
++	return (SCCread(SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0  : 1;
++#endif
++}
++
++
++/* Comment taken from sx.c (2.4.0):
++   I haven't the foggiest why the decrement use count has to happen
++   here. The whole linux serial drivers stuff needs to be redesigned.
++   My guess is that this is a hack to minimize the impact of a bug
++   elsewhere. Thinking about it some more. (try it sometime) Try
++   running minicom on a serial port that is driven by a modularized
++   driver. Have the modem hangup. Then remove the driver module. Then
++   exit minicom.  I expect an "oops".  -- REW */
++
++static void scc_hungup(void *ptr)
++{
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: hungup ...\n");
++#endif
++	scc_disable_tx_interrupts(ptr);
++	scc_disable_rx_interrupts(ptr);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: hungup done\n");
++#endif
++}
++
++
++static void scc_close(void *ptr)
++{
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: close ...\n");
++#endif
++	scc_disable_tx_interrupts(ptr);
++	scc_disable_rx_interrupts(ptr);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: close done\n");
++#endif
++}
++
++
++/*---------------------------------------------------------------------------
++ * Internal support functions
++ *--------------------------------------------------------------------------*/
++
++static void scc_setsignals(struct scc_port *port, int dtr, int rts)
++{
++	unsigned long flags;
++	unsigned char t;
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: setsignals dtr %d rts %d...\n", dtr, rts);
++#endif
++	local_irq_save(flags);
++	t = SCCread(TX_CTRL_REG);
++	if (dtr >= 0)
++		t = dtr? (t | TCR_DTR): (t & ~TCR_DTR);
++	if (rts >= 0)
++		t = rts? (t | TCR_RTS): (t & ~TCR_RTS);
++	SCCwrite(TX_CTRL_REG, t);
++	local_irq_restore(flags);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: setsignals done\n");
++#endif
++}
++
++
++static void scc_send_xchar(struct tty_struct *tty, char ch)
++{
++	struct scc_port *port = (struct scc_port *)tty->driver_data;
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: send_xchar ...\n");
++#endif
++	port->x_char = ch;
++	if (ch)
++		scc_enable_tx_interrupts(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: send_xchar done\n");
++#endif
++}
++
++
++/*---------------------------------------------------------------------------
++ * Driver entrypoints referenced from above
++ *--------------------------------------------------------------------------*/
++
++static int scc_open(struct tty_struct *tty, struct file *filp)
++{
++	int line = tty->index;
++	int retval;
++	struct scc_port *port = &scc_ports[line];
++	int i, channel = port->channel;
++	unsigned long flags;
++	SCC_ACCESS_INIT(port);
++
++	static const struct {
++		unsigned reg, val;
++	} scc_init_tab[] = {
++		/* no parity, 1 stop bit, async, 1:16 */
++		{ AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x64 },
++		/* parity error is special cond, ints disabled, no DMA */
++		{ INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
++		/* Rx 8 bits/char, no auto enable, Rx off */
++		{ RX_CTRL_REG, RCR_CHSIZE_8 },
++		/* DTR off, Tx 8 bits/char, RTS off, Tx off */
++		{ TX_CTRL_REG, TCR_CHSIZE_8 },
++		/* special features off */
++		{ AUX2_CTRL_REG, 0 },
++		/* RTxC is XTAL, TRxC is input, both clocks = RTxC */
++		{ CLK_CTRL_REG, CCR_TRxCOUT_XTAL | CCR_TXCLK_RTxC | CCR_RXCLK_RTxC },
++		{ DPLL_CTRL_REG, 0 },
++		/* Start Rx */
++		{ RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
++		/* Start Tx */
++		{ TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
++		/* Ext/Stat ints: CTS, DCD, SYNC (DSR) */
++		{ INT_CTRL_REG, ICR_ENAB_DCD_INT | ICR_ENAB_CTS_INT | ICR_ENAB_SYNC_INT },
++		/* Reset Ext/Stat ints */
++		{ COMMAND_REG, CR_EXTSTAT_RESET },
++		/* ...again */
++		{ COMMAND_REG, CR_EXTSTAT_RESET },
++		/* Rx int always, TX int off, Ext/Stat int on */
++		{ INT_AND_DMA_REG, IDR_EXTSTAT_INT_ENAB |
++		  IDR_PARERR_AS_SPCOND | IDR_RX_INT_ALL }
++	};
++
++	if (atari_SCC_init_done && line == 1)
++		return -ENODEV;
++
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: open port ...\n");
++#endif
++	if (!(port->gs.flags & ASYNC_INITIALIZED)) {
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: init port ...\n");
++#endif
++		local_irq_save(flags);
++
++		SCCmod(MASTER_INT_CTRL, 0x3f,
++		       channel == 0 ? MIC_CH_A_RESET : MIC_CH_B_RESET);
++		udelay(40);		/* extra delay after a reset */
++
++		for (i = 0; i < sizeof(scc_init_tab)/sizeof(*scc_init_tab); ++i)
++			SCCwrite(scc_init_tab[i].reg, scc_init_tab[i].val);
++
++
++		/* remember status register for detection of DCD and CTS changes */
++		scc_last_status_reg[channel] = SCCread(STATUS_REG);
++
++		port->c_dcd = 0;	/* Prevent initial 1->0 interrupt */
++		scc_setsignals(port, 1, 1);
++		local_irq_restore(flags);
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: init port done!\n");
++#endif
++	}
++
++	tty->driver_data = port;
++	port->gs.tty = tty;
++	port->gs.count++;
++#ifdef DEBUG
++	printk(KERN_WARNING "SCC: gs init port ...\n");
++#endif
++	retval = gs_init_port(&port->gs);
++	if (retval) {
++		port->gs.count--;
++		return retval;
++	}
++#ifdef DEBUG
++	printk(KERN_WARNING "SCC: gs init port done!\n");
++#endif
++	port->gs.flags |= GS_ACTIVE;
++
++#ifdef DEBUG
++	printk(KERN_WARNING "SCC: gs wait ready ...\n");
++#endif
++	retval = gs_block_til_ready(port, filp);
++#ifdef DEBUG
++	printk(KERN_WARNING "SCC: gs wait ready done!\n");
++#endif
++	if (retval) {
++		port->gs.count--;
++		return retval;
++	}
++
++	port->c_dcd = scc_get_CD(port);
++
++#ifdef DEBUG
++	printk(KERN_WARNING "SCC: enable rx ints ...\n");
++#endif
++	scc_enable_rx_interrupts(port);
++#ifdef DEBUG
++	printk(KERN_WARNING "SCC: enable rx ints done!\n");
++
++	printk(KERN_INFO "SCC: open port done!\n");
++#endif
++	return 0;
++}
++
++
++static void scc_throttle(struct tty_struct *tty)
++{
++	struct scc_port *port = (struct scc_port *)tty->driver_data;
++	unsigned long flags;
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: throttle ...\n");
++#endif
++	if (tty->termios->c_cflag & CRTSCTS) {
++		local_irq_save(flags);
++		SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);
++		local_irq_restore(flags);
++	}
++	if (I_IXOFF(tty))
++		scc_send_xchar(tty, STOP_CHAR(tty));
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: throttle done!\n");
++#endif
++}
++
++
++static void scc_unthrottle(struct tty_struct *tty)
++{
++	struct scc_port *port = (struct scc_port *)tty->driver_data;
++	unsigned long flags;
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: unthrottle ...\n");
++#endif
++	if (tty->termios->c_cflag & CRTSCTS) {
++		local_irq_save(flags);
++		SCCmod(TX_CTRL_REG, 0xff, TCR_RTS);
++		local_irq_restore(flags);
++	}
++	if (I_IXOFF(tty))
++		scc_send_xchar(tty, START_CHAR(tty));
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: unthrottle done!\n");
++#endif
++}
++
++
++static int scc_ioctl(struct tty_struct *tty, struct file *file,
++		     unsigned int cmd, unsigned long arg)
++{
++	struct scc_port *port = (struct scc_port *)tty->driver_data;
++	int retval;
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: ioctl! cmd %d, arg %p \n", cmd, arg);
++#endif
++	//if (serial_paranoia_check(info, tty->device, "zs_ioctl"))
++	//	return -ENODEV;
++
++	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
++	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
++	    (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
++		if (tty->flags & (1 << TTY_IO_ERROR))
++			return -EIO;
++	}
++
++	switch (cmd) {
++	case TCSBRK:	/* SVID version: non-zero arg --> no break */
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: ioctl TCSBRK\n");
++#endif
++		retval = tty_check_change(tty);
++		if (retval)
++			return retval;
++		tty_wait_until_sent(tty, 0);
++		//if (!arg)
++		//	send_break(info, HZ/4);	/* 1/4 second */
++		return 0;
++	case TCSBRKP:	/* support for POSIX tcsendbreak() */
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: ioctl TCSBRKP\n");
++#endif
++		retval = tty_check_change(tty);
++		if (retval)
++			return retval;
++		tty_wait_until_sent(tty, 0);
++		//send_break(info, arg ? arg*(HZ/10) : HZ/4);
++		return 0;
++	case TIOCGSOFTCAR:
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: ioctl TIOCGSOFTCAR\n");
++#endif
++		if (put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg))
++			return -EFAULT;
++		return 0;
++	case TIOCSSOFTCAR:
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: ioctl TIOCSSOFTCAR\n");
++#endif
++		if (get_user(arg, (unsigned long *)arg))
++			return -EFAULT;
++		tty->termios->c_cflag =
++			((tty->termios->c_cflag & ~CLOCAL) |
++			 (arg ? CLOCAL : 0));
++		return 0;
++	case TIOCMGET:
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: ioctl TIOCMGET\n");
++#endif
++		//return get_modem_info(info, (unsigned int *)arg);
++		return 0;
++	case TIOCMBIS:
++	case TIOCMBIC:
++	case TIOCMSET:
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: ioctl TIOCMSET\n");
++#endif
++		//return set_modem_info(info, cmd, (unsigned int *)arg);
++		return 0;
++	case TIOCGSERIAL:
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: ioctl TIOCGSERIAL\n");
++#endif
++		return 0;
++		//return get_serial_info(info,
++		//		       (struct serial_struct *)arg);
++	case TIOCSSERIAL:
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: ioctl TIOCSSERIAL\n");
++#endif
++		return 0;
++		//return set_serial_info(info,
++		//		       (struct serial_struct *)arg);
++	case TIOCSERGETLSR: /* Get line status register */
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: ioctl TIOCSERGETLSR\n");
++#endif
++		return 0;
++		//return get_lsr_info(info, (unsigned int *)arg);
++
++	case TIOCSERGSTRUCT:
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: ioctl TIOCSERGSTRUCT\n");
++#endif
++		return 0;
++		if (copy_to_user((struct scc_port *)arg,
++				 port, sizeof(struct scc_port)))
++			return -EFAULT;
++		return 0;
++
++	default:
++#ifdef DEBUG
++		printk(KERN_INFO "SCC: ioctl default\n");
++#endif
++		return -ENOIOCTLCMD;
++	}
++	return 0;
++}
++
++
++static void scc_break_ctl(struct tty_struct *tty, int break_state)
++{
++	struct scc_port *port = (struct scc_port *)tty->driver_data;
++	unsigned long flags;
++	SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: break ctl ...\n");
++#endif
++	local_irq_save(flags);
++	SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, break_state ? TCR_SEND_BREAK : 0);
++	local_irq_restore(flags);
++#ifdef DEBUG
++	printk(KERN_INFO "SCC: break ctl done!\n");
++#endif
++}
++
++
++/*---------------------------------------------------------------------------
++ * Serial console stuff...
++ *--------------------------------------------------------------------------*/
++#if 1
++#define scc_delay() \
++	asm volatile ("tstb %0" : : "m" (*scc_del) : "cc")
++
++#define SCC_WRITE(reg,val)				\
++	do {						\
++		scc.cha_b_ctrl = (reg);			\
++		scc_delay();				\
++		scc.cha_b_ctrl = (val);			\
++		scc_delay();				\
++	} while (0)
++
++/* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
++ * delay of ~ 60us. */
++#define LONG_DELAY()					\
++	do {						\
++		int i;					\
++		for (i = 100; i > 0; --i)		\
++			scc_delay();			\
++	} while (0)
++
++static void atari_init_scc_port(int cflag)
++{
++	extern int atari_SCC_reset_done;
++	static int clksrc_table[9] =
++		/* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
++		{ 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
++	static int brgsrc_table[9] =
++		/* reg 14: 0 = RTxC, 2 = PCLK */
++		{ 2, 2, 2, 2, 2, 2, 0, 2, 2 };
++	static int clkmode_table[9] =
++		/* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */
++		{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 };
++	static int div_table[9] =
++		/* reg12 (BRG low) */
++		{ 208, 138, 103, 50, 24, 11, 1, 0, 0 };
++
++	int baud = cflag & CBAUD;
++	int clksrc, clkmode, div, reg3, reg5;
++
++	scc_del = &mfp.par_dt_reg;
++
++	if (cflag & CBAUDEX)
++		baud += B38400;
++	if (baud < B1200 || baud > B38400+2)
++		baud = B9600;		/* use default 9600bps for non-implemented rates */
++	baud -= B1200;			/* tables starts at 1200bps */
++
++	clksrc  = clksrc_table[baud];
++	clkmode = clkmode_table[baud];
++	div     = div_table[baud];
++	if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
++		/* special treatment for TT, where rates >= 38400 are done via TRxC */
++		clksrc = 0x28; /* TRxC */
++		clkmode = baud == 6 ? 0xc0 :
++			  baud == 7 ? 0x80 : /* really 76800bps */
++				      0x40;  /* really 153600bps */
++		div = 0;
++	}
++
++	reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40;
++	reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */;
++
++	(void)scc.cha_b_ctrl;		/* reset reg pointer */
++	SCC_WRITE(9, 0xc0);		/* reset */
++	LONG_DELAY();			/* extra delay after WR9 access */
++	SCC_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
++		  0x04 /* 1 stopbit */ |
++		  clkmode);
++	SCC_WRITE(3, reg3);
++	SCC_WRITE(5, reg5);
++	SCC_WRITE(9, 0);		/* no interrupts */
++	LONG_DELAY();			/* extra delay after WR9 access */
++	SCC_WRITE(10, 0);		/* NRZ mode */
++	SCC_WRITE(11, clksrc);		/* main clock source */
++	SCC_WRITE(12, div);		/* BRG value */
++	SCC_WRITE(13, 0);		/* BRG high byte */
++	SCC_WRITE(14, brgsrc_table[baud]);
++	SCC_WRITE(14, brgsrc_table[baud] | (div ? 1 : 0));
++	SCC_WRITE(3, reg3 | 1);
++	SCC_WRITE(5, reg5 | 8);
++
++	atari_SCC_reset_done = 1;
++	atari_SCC_init_done = 1;
++}
++
++static void scc_ch_write(char ch)
++{
++	volatile char *p = NULL;
++
++	if (MACH_IS_TT || MACH_IS_FALCON)
++		p = (volatile char *)&scc.cha_b_ctrl;
++
++	if (MACH_IS_ST)
++		p = (volatile char *)&scc.cha_b_ctrl;
++
++	if (MACH_IS_STE)
++		p = (volatile char *)&st_escc.cha_b_ctrl;
++
++	do {
++		scc_delay();
++	}
++	while (!(*p & 4));
++	// scc_delay();
++	// *p = 8;
++	scc_delay();
++	*(p+1) = ch;
++}
++
++/* The console must be locked when we get here. */
++
++static void scc_console_write(struct console *co, const char *str, unsigned count)
++{
++	unsigned long flags;
++
++	//printk("scc_console_write: %s\n", str);
++	local_irq_save(flags);
++
++	while (count--) {
++		if (*str == '\n')
++			scc_ch_write('\r');
++		scc_ch_write(*str++);
++	}
++	local_irq_restore(flags);
++	//printk("scc_console_write done!\n");
++}
++
++static struct tty_driver *scc_console_device(struct console *c, int *index)
++{
++	*index = c->index;
++	return scc_driver;
++}
++
++
++static int __init scc_console_setup(struct console *co, char *options)
++{
++	printk("scc_console_setup: initializing SCC port B\n");
++	atari_init_scc_port(B9600|CS8);
++	printk("scc_console_setup: done!\n");
++	return 0;
++}
++
++
++static struct console sercons = {
++	.name		= "ttyS",
++	.write		= scc_console_write,
++	.device		= scc_console_device,
++	.setup		= scc_console_setup,
++	.flags		= CON_PRINTBUFFER,
++	.index		= -1,
++};
++
++
++static int __init vme_scc_console_init(void)
++{
++	if (MACH_IS_TT || MACH_IS_ST || MACH_IS_FALCON)
++		register_console(&sercons);
++	return 0;
++}
++
++console_initcall(vme_scc_console_init);
++#endif
++
++/***************************** End of Functions *********************/
++
++MODULE_AUTHOR("Michael Schmitz");
++MODULE_DESCRIPTION("Atari Amd8350 SCC serial driver");
++MODULE_LICENSE("GPL");

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/634-atari_scsi.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/634-atari_scsi.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,228 @@
+Cc: James E.J. Bottomley <James.Bottomley at SteelEye.com>,
+    linux-scsi at vger.kernel.org
+Subject: [PATCH] m68k: Atari SCSI revival
+
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+
+SCSI should be working on a TT (but someone should really try!) but causes
+trouble on a Falcon (as in: it ate a filesystem of mine) at least when
+used concurrently with IDE. I have the notion it's because locking of the
+ST-DMA interrupt by IDE is broken in 2.6 (the IDE driver always complains
+about trying to release an already-released ST-DMA). Needs more work, but
+that's on the IDE or m68k interrupt side rather than SCSI.
+
+Signed-off-by: Michael Schmitz <schmitz at debian.org>
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/scsi/Kconfig         |    2 -
+ drivers/scsi/atari_NCR5380.c |   52 ++++++++++++++++++++++++++++++++++++++-----
+ drivers/scsi/atari_scsi.c    |   10 +++-----
+ drivers/scsi/atari_scsi.h    |   30 +++++++++++++++++++++---
+ 4 files changed, 77 insertions(+), 17 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/scsi/Kconfig
++++ linux-m68k-2.6.21/drivers/scsi/Kconfig
+@@ -1649,7 +1649,7 @@ config OKTAGON_SCSI
+ 
+ config ATARI_SCSI
+ 	tristate "Atari native SCSI support"
+-	depends on ATARI && SCSI && BROKEN
++	depends on ATARI && SCSI
+ 	select SCSI_SPI_ATTRS
+ 	---help---
+ 	  If you have an Atari with built-in NCR5380 SCSI controller (TT,
+--- linux-m68k-2.6.21.orig/drivers/scsi/atari_NCR5380.c
++++ linux-m68k-2.6.21/drivers/scsi/atari_NCR5380.c
+@@ -264,7 +264,7 @@ static struct scsi_host_template *the_te
+ 	(struct NCR5380_hostdata *)(in)->hostdata
+ #define	HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata)
+ 
+-#define	NEXT(cmd)	((Scsi_Cmnd *)((cmd)->host_scribble))
++#define	NEXT(cmd)	((cmd)->host_scribble)
+ #define	NEXTADDR(cmd)	((Scsi_Cmnd **)&((cmd)->host_scribble))
+ 
+ #define	HOSTNO		instance->host_no
+@@ -716,7 +716,7 @@ static void NCR5380_print_status (struct
+ 	printk("NCR5380_print_status: no memory for print buffer\n");
+ 	return;
+     }
+-    len = NCR5380_proc_info(pr_bfr, &start, 0, PAGE_SIZE, HOSTNO, 0);
++    len = NCR5380_proc_info(instance, pr_bfr, &start, 0, PAGE_SIZE, 0);
+     pr_bfr[len] = 0;
+     printk("\n%s\n", pr_bfr);
+     free_page((unsigned long) pr_bfr);
+@@ -878,6 +878,46 @@ static int NCR5380_init (struct Scsi_Hos
+ }
+ 
+ /* 
++ * our own old-style timeout update
++ */
++/*
++ * The strategy is to cause the timer code to call scsi_times_out()
++ * when the soonest timeout is pending.
++ * The arguments are used when we are queueing a new command, because
++ * we do not want to subtract the time used from this time, but when we
++ * set the timer, we want to take this value into account.
++ */
++
++int atari_scsi_update_timeout(Scsi_Cmnd * SCset, int timeout)
++{
++    int rtn;
++
++    /*
++     * We are using the new error handling code to actually register/deregister
++     * timers for timeout.
++     */
++
++    if (!timer_pending(&SCset->eh_timeout)) {
++	rtn = 0;
++    } else {
++	rtn = SCset->eh_timeout.expires - jiffies;
++    }
++
++    if (timeout == 0) {
++        del_timer(&SCset->eh_timeout);
++        SCset->eh_timeout.data = (unsigned long) NULL;
++        SCset->eh_timeout.expires = 0;
++    } else {
++        if (SCset->eh_timeout.data != (unsigned long) NULL) 
++            del_timer(&SCset->eh_timeout);
++        SCset->eh_timeout.data = (unsigned long) SCset;
++        SCset->eh_timeout.expires = jiffies + timeout;
++        add_timer(&SCset->eh_timeout);
++    }
++	return rtn;
++}
++
++/* 
+  * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd, 
+  *	void (*done)(Scsi_Cmnd *)) 
+  *
+@@ -902,7 +942,7 @@ int NCR5380_queue_command (Scsi_Cmnd *cm
+     Scsi_Cmnd *tmp;
+     int oldto;
+     unsigned long flags;
+-    extern int update_timeout(Scsi_Cmnd * SCset, int timeout);
++    // extern int update_timeout(Scsi_Cmnd * SCset, int timeout);
+ 
+ #if (NDEBUG & NDEBUG_NO_WRITE)
+     switch (cmd->cmnd[0]) {
+@@ -978,9 +1018,9 @@ int NCR5380_queue_command (Scsi_Cmnd *cm
+      * alter queues and touch the lock.
+      */
+     if (!IS_A_TT()) {
+-	oldto = update_timeout(cmd, 0);
++	oldto = atari_scsi_update_timeout(cmd, 0);
+ 	falcon_get_lock();
+-	update_timeout(cmd, oldto);
++	atari_scsi_update_timeout(cmd, oldto);
+     }
+     if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
+ 	LIST(cmd, hostdata->issue_queue);
+@@ -1435,7 +1475,7 @@ static int NCR5380_select (struct Scsi_H
+     local_irq_restore(flags);
+ 
+     /* Wait for arbitration logic to complete */
+-#if NCR_TIMEOUT
++#if defined(NCR_TIMEOUT)
+     {
+       unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
+ 
+--- linux-m68k-2.6.21.orig/drivers/scsi/atari_scsi.c
++++ linux-m68k-2.6.21/drivers/scsi/atari_scsi.c
+@@ -395,7 +395,7 @@ static irqreturn_t scsi_tt_intr (int irq
+ 
+ #endif /* REAL_DMA */
+ 	
+-	NCR5380_intr (0, 0, 0);
++	NCR5380_intr(0, 0);
+ 
+ #if 0
+ 	/* To be sure the int is not masked */
+@@ -461,7 +461,7 @@ static irqreturn_t scsi_falcon_intr (int
+ 
+ #endif /* REAL_DMA */
+ 
+-	NCR5380_intr (0, 0, 0);
++	NCR5380_intr(0, 0);
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -557,11 +557,11 @@ static void falcon_get_lock( void )
+ 
+ 	local_irq_save(flags);
+ 
+-	while( !in_interrupt() && falcon_got_lock && stdma_others_waiting() )
++	while (!in_irq() && falcon_got_lock && stdma_others_waiting())
+ 		sleep_on( &falcon_fairness_wait );
+ 
+ 	while (!falcon_got_lock) {
+-		if (in_interrupt())
++		if (in_irq())
+ 			panic( "Falcon SCSI hasn't ST-DMA lock in interrupt" );
+ 		if (!falcon_trying_lock) {
+ 			falcon_trying_lock = 1;
+@@ -763,7 +763,6 @@ int atari_scsi_detect (struct scsi_host_
+ 	return( 1 );
+ }
+ 
+-#ifdef MODULE
+ int atari_scsi_release (struct Scsi_Host *sh)
+ {
+ 	if (IS_A_TT())
+@@ -772,7 +771,6 @@ int atari_scsi_release (struct Scsi_Host
+ 		atari_stram_free (atari_dma_buffer);
+ 	return 1;
+ }
+-#endif
+ 
+ void __init atari_scsi_setup(char *str, int *ints)
+ {
+--- linux-m68k-2.6.21.orig/drivers/scsi/atari_scsi.h
++++ linux-m68k-2.6.21/drivers/scsi/atari_scsi.h
+@@ -21,11 +21,7 @@
+ int atari_scsi_detect (struct scsi_host_template *);
+ const char *atari_scsi_info (struct Scsi_Host *);
+ int atari_scsi_reset (Scsi_Cmnd *, unsigned int);
+-#ifdef MODULE
+ int atari_scsi_release (struct Scsi_Host *);
+-#else
+-#define atari_scsi_release NULL
+-#endif
+ 
+ /* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. Higher
+  * values should work, too; try it! (but cmd_per_lun costs memory!) */
+@@ -63,6 +59,32 @@ int atari_scsi_release (struct Scsi_Host
+ #define	NCR5380_dma_xfer_len(i,cmd,phase) \
+ 	atari_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1)
+ 
++/* former generic SCSI error handling stuff */
++
++#define SCSI_ABORT_SNOOZE 0
++#define SCSI_ABORT_SUCCESS 1
++#define SCSI_ABORT_PENDING 2
++#define SCSI_ABORT_BUSY 3
++#define SCSI_ABORT_NOT_RUNNING 4
++#define SCSI_ABORT_ERROR 5
++
++#define SCSI_RESET_SNOOZE 0
++#define SCSI_RESET_PUNT 1
++#define SCSI_RESET_SUCCESS 2
++#define SCSI_RESET_PENDING 3
++#define SCSI_RESET_WAKEUP 4
++#define SCSI_RESET_NOT_RUNNING 5
++#define SCSI_RESET_ERROR 6
++
++#define SCSI_RESET_SYNCHRONOUS		0x01
++#define SCSI_RESET_ASYNCHRONOUS		0x02
++#define SCSI_RESET_SUGGEST_BUS_RESET	0x04
++#define SCSI_RESET_SUGGEST_HOST_RESET	0x08
++
++#define SCSI_RESET_BUS_RESET 0x100
++#define SCSI_RESET_HOST_RESET 0x200
++#define SCSI_RESET_ACTION   0xff
++
+ /* Debugging printk definitions:
+  *
+  *  ARB  -> arbitration

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/635-atari_input.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/635-atari_input.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,1162 @@
+Cc: Dmitry Torokhov <dmitry.torokhov at gmail.com>,
+    linux-input at atrey.karlin.mff.cuni.cz
+Subject: [PATCH] m68k: Atari keyboard and mouse support.
+
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+
+Atari keyboard and mouse support.
+(reformating and Kconfig fixes by Roman Zippel)
+
+Signed-off-by: Michael Schmitz <schmitz at debian.org>
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/Kconfig                |    3 
+ arch/m68k/atari/Makefile         |    1 
+ arch/m68k/atari/atakeyb.c        |  730 +++++++++++++++++++++++++++++++++++++++
+ drivers/input/keyboard/Kconfig   |   11 
+ drivers/input/keyboard/Makefile  |    1 
+ drivers/input/keyboard/atakbd.c  |  134 +++++++
+ drivers/input/mouse/Kconfig      |   11 
+ drivers/input/mouse/Makefile     |    1 
+ drivers/input/mouse/atarimouse.c |  160 ++++++++
+ include/asm-m68k/atarikb.h       |    6 
+ include/linux/input.h            |    1 
+ 11 files changed, 1059 insertions(+)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/Kconfig
++++ linux-m68k-2.6.21/arch/m68k/Kconfig
+@@ -409,6 +409,9 @@ config STRAM_PROC
+ 	help
+ 	  Say Y here to report ST-RAM usage statistics in /proc/stram.
+ 
++config ATARI_KBD_CORE
++	bool
++
+ config HEARTBEAT
+ 	bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
+ 	default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
+--- linux-m68k-2.6.21.orig/arch/m68k/atari/Makefile
++++ linux-m68k-2.6.21/arch/m68k/atari/Makefile
+@@ -8,3 +8,4 @@ obj-y		:= config.o time.o debug.o ataint
+ ifeq ($(CONFIG_PCI),y)
+ obj-$(CONFIG_HADES)	+= hades-pci.o
+ endif
++obj-$(CONFIG_ATARI_KBD_CORE)	+= atakeyb.o
+--- /dev/null
++++ linux-m68k-2.6.21/arch/m68k/atari/atakeyb.c
+@@ -0,0 +1,730 @@
++/*
++ * linux/atari/atakeyb.c
++ *
++ * Atari Keyboard driver for 680x0 Linux
++ *
++ * 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
++ * for more details.
++ */
++
++/*
++ * Atari support by Robert de Vries
++ * enhanced by Bjoern Brauel and Roman Hodek
++ */
++
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/errno.h>
++#include <linux/keyboard.h>
++#include <linux/delay.h>
++#include <linux/timer.h>
++#include <linux/kd.h>
++#include <linux/random.h>
++#include <linux/init.h>
++#include <linux/kbd_kern.h>
++
++#include <asm/atariints.h>
++#include <asm/atarihw.h>
++#include <asm/atarikb.h>
++#include <asm/atari_joystick.h>
++#include <asm/irq.h>
++
++static void atakeyb_rep(unsigned long ignore);
++extern unsigned int keymap_count;
++
++/* Hook for MIDI serial driver */
++void (*atari_MIDI_interrupt_hook) (void);
++/* Hook for mouse driver */
++void (*atari_mouse_interrupt_hook) (char *);
++/* Hook for keyboard inputdev  driver */
++void (*atari_input_keyboard_interrupt_hook) (unsigned char, char);
++/* Hook for mouse inputdev  driver */
++void (*atari_input_mouse_interrupt_hook) (char *);
++
++/* variables for IKBD self test: */
++
++/* state: 0: off; >0: in progress; >1: 0xf1 received */
++static volatile int ikbd_self_test;
++/* timestamp when last received a char */
++static volatile unsigned long self_test_last_rcv;
++/* bitmap of keys reported as broken */
++static unsigned long broken_keys[128/(sizeof(unsigned long)*8)] = { 0, };
++
++#define BREAK_MASK	(0x80)
++
++/*
++ * ++roman: The following changes were applied manually:
++ *
++ *  - The Alt (= Meta) key works in combination with Shift and
++ *    Control, e.g. Alt+Shift+a sends Meta-A (0xc1), Alt+Control+A sends
++ *    Meta-Ctrl-A (0x81) ...
++ *
++ *  - The parentheses on the keypad send '(' and ')' with all
++ *    modifiers (as would do e.g. keypad '+'), but they cannot be used as
++ *    application keys (i.e. sending Esc O c).
++ *
++ *  - HELP and UNDO are mapped to be F21 and F24, resp, that send the
++ *    codes "\E[M" and "\E[P". (This is better than the old mapping to
++ *    F11 and F12, because these codes are on Shift+F1/2 anyway.) This
++ *    way, applications that allow their own keyboard mappings
++ *    (e.g. tcsh, X Windows) can be configured to use them in the way
++ *    the label suggests (providing help or undoing).
++ *
++ *  - Console switching is done with Alt+Fx (consoles 1..10) and
++ *    Shift+Alt+Fx (consoles 11..20).
++ *
++ *  - The misc. special function implemented in the kernel are mapped
++ *    to the following key combinations:
++ *
++ *      ClrHome          -> Home/Find
++ *      Shift + ClrHome  -> End/Select
++ *      Shift + Up       -> Page Up
++ *      Shift + Down     -> Page Down
++ *      Alt + Help       -> show system status
++ *      Shift + Help     -> show memory info
++ *      Ctrl + Help      -> show registers
++ *      Ctrl + Alt + Del -> Reboot
++ *      Alt + Undo       -> switch to last console
++ *      Shift + Undo     -> send interrupt
++ *      Alt + Insert     -> stop/start output (same as ^S/^Q)
++ *      Alt + Up         -> Scroll back console (if implemented)
++ *      Alt + Down       -> Scroll forward console (if implemented)
++ *      Alt + CapsLock   -> NumLock
++ *
++ * ++Andreas:
++ *
++ *  - Help mapped to K_HELP
++ *  - Undo mapped to K_UNDO (= K_F246)
++ *  - Keypad Left/Right Parenthesis mapped to new K_PPAREN[LR]
++ */
++
++static u_short ataplain_map[NR_KEYS] __initdata = {
++	0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
++	0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009,
++	0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
++	0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
++	0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
++	0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
++	0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf200,
++	0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
++	0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
++	0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
++	0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
++	0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
++	0xf200, 0xf1ff, 0xf11b, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
++	0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
++	0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
++	0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
++};
++
++typedef enum kb_state_t {
++	KEYBOARD, AMOUSE, RMOUSE, JOYSTICK, CLOCK, RESYNC
++} KB_STATE_T;
++
++#define	IS_SYNC_CODE(sc)	((sc) >= 0x04 && (sc) <= 0xfb)
++
++typedef struct keyboard_state {
++	unsigned char buf[6];
++	int len;
++	KB_STATE_T state;
++} KEYBOARD_STATE;
++
++KEYBOARD_STATE kb_state;
++
++#define	DEFAULT_KEYB_REP_DELAY	(HZ/4)
++#define	DEFAULT_KEYB_REP_RATE	(HZ/25)
++
++/* These could be settable by some ioctl() in future... */
++static unsigned int key_repeat_delay = DEFAULT_KEYB_REP_DELAY;
++static unsigned int key_repeat_rate = DEFAULT_KEYB_REP_RATE;
++
++static unsigned char rep_scancode;
++static struct timer_list atakeyb_rep_timer = {
++	.function = atakeyb_rep,
++};
++
++static void atakeyb_rep(unsigned long ignore)
++{
++	/* Disable keyboard for the time we call handle_scancode(), else a race
++	 * in the keyboard tty queue may happen */
++	atari_disable_irq(IRQ_MFP_ACIA);
++	del_timer(&atakeyb_rep_timer);
++
++	/* A keyboard int may have come in before we disabled the irq, so
++	 * double-check whether rep_scancode is still != 0 */
++	if (rep_scancode) {
++		init_timer(&atakeyb_rep_timer);
++		atakeyb_rep_timer.expires = jiffies + key_repeat_rate;
++		add_timer(&atakeyb_rep_timer);
++
++		//handle_scancode(rep_scancode, 1);
++		if (atari_input_keyboard_interrupt_hook)
++			atari_input_keyboard_interrupt_hook(rep_scancode, 1);
++	}
++
++	atari_enable_irq(IRQ_MFP_ACIA);
++}
++
++
++/* ++roman: If a keyboard overrun happened, we can't tell in general how much
++ * bytes have been lost and in which state of the packet structure we are now.
++ * This usually causes keyboards bytes to be interpreted as mouse movements
++ * and vice versa, which is very annoying. It seems better to throw away some
++ * bytes (that are usually mouse bytes) than to misinterpret them. Therefor I
++ * introduced the RESYNC state for IKBD data. In this state, the bytes up to
++ * one that really looks like a key event (0x04..0xf2) or the start of a mouse
++ * packet (0xf8..0xfb) are thrown away, but at most 2 bytes. This at least
++ * speeds up the resynchronization of the event structure, even if maybe a
++ * mouse movement is lost. However, nothing is perfect. For bytes 0x01..0x03,
++ * it's really hard to decide whether they're mouse or keyboard bytes. Since
++ * overruns usually occur when moving the Atari mouse rapidly, they're seen as
++ * mouse bytes here. If this is wrong, only a make code of the keyboard gets
++ * lost, which isn't too bad. Loosing a break code would be disastrous,
++ * because then the keyboard repeat strikes...
++ */
++
++static irqreturn_t atari_keyboard_interrupt(int irq, void *dummy)
++{
++	u_char acia_stat;
++	int scancode;
++	int break_flag;
++
++repeat:
++	if (acia.mid_ctrl & ACIA_IRQ)
++		if (atari_MIDI_interrupt_hook)
++			atari_MIDI_interrupt_hook();
++	acia_stat = acia.key_ctrl;
++	/* check out if the interrupt came from this ACIA */
++	if (!((acia_stat | acia.mid_ctrl) & ACIA_IRQ))
++		return IRQ_HANDLED;
++
++	if (acia_stat & ACIA_OVRN) {
++		/* a very fast typist or a slow system, give a warning */
++		/* ...happens often if interrupts were disabled for too long */
++		printk(KERN_DEBUG "Keyboard overrun\n");
++		scancode = acia.key_data;
++		/* Turn off autorepeating in case a break code has been lost */
++		del_timer(&atakeyb_rep_timer);
++		rep_scancode = 0;
++		if (ikbd_self_test)
++			/* During self test, don't do resyncing, just process the code */
++			goto interpret_scancode;
++		else if (IS_SYNC_CODE(scancode)) {
++			/* This code seem already to be the start of a new packet or a
++			 * single scancode */
++			kb_state.state = KEYBOARD;
++			goto interpret_scancode;
++		} else {
++			/* Go to RESYNC state and skip this byte */
++			kb_state.state = RESYNC;
++			kb_state.len = 1;	/* skip max. 1 another byte */
++			goto repeat;
++		}
++	}
++
++	if (acia_stat & ACIA_RDRF) {
++		/* received a character */
++		scancode = acia.key_data;	/* get it or reset the ACIA, I'll get it! */
++		tasklet_schedule(&keyboard_tasklet);
++	interpret_scancode:
++		switch (kb_state.state) {
++		case KEYBOARD:
++			switch (scancode) {
++			case 0xF7:
++				kb_state.state = AMOUSE;
++				kb_state.len = 0;
++				break;
++
++			case 0xF8:
++			case 0xF9:
++			case 0xFA:
++			case 0xFB:
++				kb_state.state = RMOUSE;
++				kb_state.len = 1;
++				kb_state.buf[0] = scancode;
++				break;
++
++			case 0xFC:
++				kb_state.state = CLOCK;
++				kb_state.len = 0;
++				break;
++
++			case 0xFE:
++			case 0xFF:
++				kb_state.state = JOYSTICK;
++				kb_state.len = 1;
++				kb_state.buf[0] = scancode;
++				break;
++
++			case 0xF1:
++				/* during self-test, note that 0xf1 received */
++				if (ikbd_self_test) {
++					++ikbd_self_test;
++					self_test_last_rcv = jiffies;
++					break;
++				}
++				/* FALL THROUGH */
++
++			default:
++				break_flag = scancode & BREAK_MASK;
++				scancode &= ~BREAK_MASK;
++				if (ikbd_self_test) {
++					/* Scancodes sent during the self-test stand for broken
++					 * keys (keys being down). The code *should* be a break
++					 * code, but nevertheless some AT keyboard interfaces send
++					 * make codes instead. Therefore, simply ignore
++					 * break_flag...
++					 */
++					int keyval = plain_map[scancode], keytyp;
++
++					set_bit(scancode, broken_keys);
++					self_test_last_rcv = jiffies;
++					keyval = plain_map[scancode];
++					keytyp = KTYP(keyval) - 0xf0;
++					keyval = KVAL(keyval);
++
++					printk(KERN_WARNING "Key with scancode %d ", scancode);
++					if (keytyp == KT_LATIN || keytyp == KT_LETTER) {
++						if (keyval < ' ')
++							printk("('^%c') ", keyval + '@');
++						else
++							printk("('%c') ", keyval);
++					}
++					printk("is broken -- will be ignored.\n");
++					break;
++				} else if (test_bit(scancode, broken_keys))
++					break;
++
++#if 0	// FIXME; hangs at boot
++				if (break_flag) {
++					del_timer(&atakeyb_rep_timer);
++					rep_scancode = 0;
++				} else {
++					del_timer(&atakeyb_rep_timer);
++					rep_scancode = scancode;
++					atakeyb_rep_timer.expires = jiffies + key_repeat_delay;
++					add_timer(&atakeyb_rep_timer);
++				}
++#endif
++
++				// handle_scancode(scancode, !break_flag);
++				if (atari_input_keyboard_interrupt_hook)
++					atari_input_keyboard_interrupt_hook((unsigned char)scancode, !break_flag);
++				break;
++			}
++			break;
++
++		case AMOUSE:
++			kb_state.buf[kb_state.len++] = scancode;
++			if (kb_state.len == 5) {
++				kb_state.state = KEYBOARD;
++				/* not yet used */
++				/* wake up someone waiting for this */
++			}
++			break;
++
++		case RMOUSE:
++			kb_state.buf[kb_state.len++] = scancode;
++			if (kb_state.len == 3) {
++				kb_state.state = KEYBOARD;
++				if (atari_mouse_interrupt_hook)
++					atari_mouse_interrupt_hook(kb_state.buf);
++			}
++			break;
++
++		case JOYSTICK:
++			kb_state.buf[1] = scancode;
++			kb_state.state = KEYBOARD;
++#ifdef FIXED_ATARI_JOYSTICK
++			atari_joystick_interrupt(kb_state.buf);
++#endif
++			break;
++
++		case CLOCK:
++			kb_state.buf[kb_state.len++] = scancode;
++			if (kb_state.len == 6) {
++				kb_state.state = KEYBOARD;
++				/* wake up someone waiting for this.
++				   But will this ever be used, as Linux keeps its own time.
++				   Perhaps for synchronization purposes? */
++				/* wake_up_interruptible(&clock_wait); */
++			}
++			break;
++
++		case RESYNC:
++			if (kb_state.len <= 0 || IS_SYNC_CODE(scancode)) {
++				kb_state.state = KEYBOARD;
++				goto interpret_scancode;
++			}
++			kb_state.len--;
++			break;
++		}
++	}
++
++#if 0
++	if (acia_stat & ACIA_CTS)
++		/* cannot happen */;
++#endif
++
++	if (acia_stat & (ACIA_FE | ACIA_PE)) {
++		printk("Error in keyboard communication\n");
++	}
++
++	/* handle_scancode() can take a lot of time, so check again if
++	 * some character arrived
++	 */
++	goto repeat;
++}
++
++/*
++ * I write to the keyboard without using interrupts, I poll instead.
++ * This takes for the maximum length string allowed (7) at 7812.5 baud
++ * 8 data 1 start 1 stop bit: 9.0 ms
++ * If this takes too long for normal operation, interrupt driven writing
++ * is the solution. (I made a feeble attempt in that direction but I
++ * kept it simple for now.)
++ */
++void ikbd_write(const char *str, int len)
++{
++	u_char acia_stat;
++
++	if ((len < 1) || (len > 7))
++		panic("ikbd: maximum string length exceeded");
++	while (len) {
++		acia_stat = acia.key_ctrl;
++		if (acia_stat & ACIA_TDRE) {
++			acia.key_data = *str++;
++			len--;
++		}
++	}
++}
++
++/* Reset (without touching the clock) */
++void ikbd_reset(void)
++{
++	static const char cmd[2] = { 0x80, 0x01 };
++
++	ikbd_write(cmd, 2);
++
++	/*
++	 * if all's well code 0xF1 is returned, else the break codes of
++	 * all keys making contact
++	 */
++}
++
++/* Set mouse button action */
++void ikbd_mouse_button_action(int mode)
++{
++	char cmd[2] = { 0x07, mode };
++
++	ikbd_write(cmd, 2);
++}
++
++/* Set relative mouse position reporting */
++void ikbd_mouse_rel_pos(void)
++{
++	static const char cmd[1] = { 0x08 };
++
++	ikbd_write(cmd, 1);
++}
++
++/* Set absolute mouse position reporting */
++void ikbd_mouse_abs_pos(int xmax, int ymax)
++{
++	char cmd[5] = { 0x09, xmax>>8, xmax&0xFF, ymax>>8, ymax&0xFF };
++
++	ikbd_write(cmd, 5);
++}
++
++/* Set mouse keycode mode */
++void ikbd_mouse_kbd_mode(int dx, int dy)
++{
++	char cmd[3] = { 0x0A, dx, dy };
++
++	ikbd_write(cmd, 3);
++}
++
++/* Set mouse threshold */
++void ikbd_mouse_thresh(int x, int y)
++{
++	char cmd[3] = { 0x0B, x, y };
++
++	ikbd_write(cmd, 3);
++}
++
++/* Set mouse scale */
++void ikbd_mouse_scale(int x, int y)
++{
++	char cmd[3] = { 0x0C, x, y };
++
++	ikbd_write(cmd, 3);
++}
++
++/* Interrogate mouse position */
++void ikbd_mouse_pos_get(int *x, int *y)
++{
++	static const char cmd[1] = { 0x0D };
++
++	ikbd_write(cmd, 1);
++
++	/* wait for returning bytes */
++}
++
++/* Load mouse position */
++void ikbd_mouse_pos_set(int x, int y)
++{
++	char cmd[6] = { 0x0E, 0x00, x>>8, x&0xFF, y>>8, y&0xFF };
++
++	ikbd_write(cmd, 6);
++}
++
++/* Set Y=0 at bottom */
++void ikbd_mouse_y0_bot(void)
++{
++	static const char cmd[1] = { 0x0F };
++
++	ikbd_write(cmd, 1);
++}
++
++/* Set Y=0 at top */
++void ikbd_mouse_y0_top(void)
++{
++	static const char cmd[1] = { 0x10 };
++
++	ikbd_write(cmd, 1);
++}
++
++/* Resume */
++void ikbd_resume(void)
++{
++	static const char cmd[1] = { 0x11 };
++
++	ikbd_write(cmd, 1);
++}
++
++/* Disable mouse */
++void ikbd_mouse_disable(void)
++{
++	static const char cmd[1] = { 0x12 };
++
++	ikbd_write(cmd, 1);
++}
++
++/* Pause output */
++void ikbd_pause(void)
++{
++	static const char cmd[1] = { 0x13 };
++
++	ikbd_write(cmd, 1);
++}
++
++/* Set joystick event reporting */
++void ikbd_joystick_event_on(void)
++{
++	static const char cmd[1] = { 0x14 };
++
++	ikbd_write(cmd, 1);
++}
++
++/* Set joystick interrogation mode */
++void ikbd_joystick_event_off(void)
++{
++	static const char cmd[1] = { 0x15 };
++
++	ikbd_write(cmd, 1);
++}
++
++/* Joystick interrogation */
++void ikbd_joystick_get_state(void)
++{
++	static const char cmd[1] = { 0x16 };
++
++	ikbd_write(cmd, 1);
++}
++
++#if 0
++/* This disables all other ikbd activities !!!! */
++/* Set joystick monitoring */
++void ikbd_joystick_monitor(int rate)
++{
++	static const char cmd[2] = { 0x17, rate };
++
++	ikbd_write(cmd, 2);
++
++	kb_state.state = JOYSTICK_MONITOR;
++}
++#endif
++
++/* some joystick routines not in yet (0x18-0x19) */
++
++/* Disable joysticks */
++void ikbd_joystick_disable(void)
++{
++	static const char cmd[1] = { 0x1A };
++
++	ikbd_write(cmd, 1);
++}
++
++/* Time-of-day clock set */
++void ikbd_clock_set(int year, int month, int day, int hour, int minute, int second)
++{
++	char cmd[7] = { 0x1B, year, month, day, hour, minute, second };
++
++	ikbd_write(cmd, 7);
++}
++
++/* Interrogate time-of-day clock */
++void ikbd_clock_get(int *year, int *month, int *day, int *hour, int *minute, int second)
++{
++	static const char cmd[1] = { 0x1C };
++
++	ikbd_write(cmd, 1);
++}
++
++/* Memory load */
++void ikbd_mem_write(int address, int size, char *data)
++{
++	panic("Attempt to write data into keyboard memory");
++}
++
++/* Memory read */
++void ikbd_mem_read(int address, char data[6])
++{
++	char cmd[3] = { 0x21, address>>8, address&0xFF };
++
++	ikbd_write(cmd, 3);
++
++	/* receive data and put it in data */
++}
++
++/* Controller execute */
++void ikbd_exec(int address)
++{
++	char cmd[3] = { 0x22, address>>8, address&0xFF };
++
++	ikbd_write(cmd, 3);
++}
++
++/* Status inquiries (0x87-0x9A) not yet implemented */
++
++/* Set the state of the caps lock led. */
++void atari_kbd_leds(unsigned int leds)
++{
++	char cmd[6] = {32, 0, 4, 1, 254 + ((leds & 4) != 0), 0};
++
++	ikbd_write(cmd, 6);
++}
++
++/*
++ * The original code sometimes left the interrupt line of
++ * the ACIAs low forever. I hope, it is fixed now.
++ *
++ * Martin Rogge, 20 Aug 1995
++ */
++
++static int atari_keyb_done = 0;
++
++int __init atari_keyb_init(void)
++{
++	if (atari_keyb_done)
++		return 0;
++
++	/* setup key map */
++	memcpy(key_maps[0], ataplain_map, sizeof(plain_map));
++
++	kb_state.state = KEYBOARD;
++	kb_state.len = 0;
++
++	request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt, IRQ_TYPE_SLOW,
++		    "keyboard/mouse/MIDI", atari_keyboard_interrupt);
++
++	atari_turnoff_irq(IRQ_MFP_ACIA);
++	do {
++		/* reset IKBD ACIA */
++		acia.key_ctrl = ACIA_RESET |
++				(atari_switches & ATARI_SWITCH_IKBD) ? ACIA_RHTID : 0;
++		(void)acia.key_ctrl;
++		(void)acia.key_data;
++
++		/* reset MIDI ACIA */
++		acia.mid_ctrl = ACIA_RESET |
++				(atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0;
++		(void)acia.mid_ctrl;
++		(void)acia.mid_data;
++
++		/* divide 500kHz by 64 gives 7812.5 baud */
++		/* 8 data no parity 1 start 1 stop bit */
++		/* receive interrupt enabled */
++		/* RTS low (except if switch selected), transmit interrupt disabled */
++		acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RIE) |
++				((atari_switches & ATARI_SWITCH_IKBD) ?
++				 ACIA_RHTID : ACIA_RLTID);
++
++		acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S |
++				(atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0;
++
++	/* make sure the interrupt line is up */
++	} while ((mfp.par_dt_reg & 0x10) == 0);
++
++	/* enable ACIA Interrupts */
++	mfp.active_edge &= ~0x10;
++	atari_turnon_irq(IRQ_MFP_ACIA);
++
++	ikbd_self_test = 1;
++	ikbd_reset();
++	/* wait for a period of inactivity (here: 0.25s), then assume the IKBD's
++	 * self-test is finished */
++	self_test_last_rcv = jiffies;
++	while (time_before(jiffies, self_test_last_rcv + HZ/4))
++		barrier();
++	/* if not incremented: no 0xf1 received */
++	if (ikbd_self_test == 1)
++		printk(KERN_ERR "WARNING: keyboard self test failed!\n");
++	ikbd_self_test = 0;
++
++	ikbd_mouse_disable();
++	ikbd_joystick_disable();
++
++#ifdef FIXED_ATARI_JOYSTICK
++	atari_joystick_init();
++#endif
++
++	// flag init done
++	atari_keyb_done = 1;
++	return 0;
++}
++
++
++int atari_kbdrate(struct kbd_repeat *k)
++{
++	if (k->delay > 0) {
++		/* convert from msec to jiffies */
++		key_repeat_delay = (k->delay * HZ + 500) / 1000;
++		if (key_repeat_delay < 1)
++			key_repeat_delay = 1;
++	}
++	if (k->period > 0) {
++		key_repeat_rate = (k->period * HZ + 500) / 1000;
++		if (key_repeat_rate < 1)
++			key_repeat_rate = 1;
++	}
++
++	k->delay  = key_repeat_delay * 1000 / HZ;
++	k->period = key_repeat_rate  * 1000 / HZ;
++
++	return 0;
++}
++
++int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
++{
++#ifdef CONFIG_MAGIC_SYSRQ
++	/* ALT+HELP pressed? */
++	if ((keycode == 98) && ((shift_state & 0xff) == 8))
++		*keycodep = 0xff;
++	else
++#endif
++		*keycodep = keycode;
++	return 1;
++}
+--- linux-m68k-2.6.21.orig/drivers/input/keyboard/Kconfig
++++ linux-m68k-2.6.21/drivers/input/keyboard/Kconfig
+@@ -164,6 +164,17 @@ config KEYBOARD_AMIGA
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called amikbd.
+ 
++config KEYBOARD_ATARI
++	tristate "Atari keyboard"
++	depends on ATARI
++	select ATARI_KBD_CORE
++	help
++	  Say Y here if you are running Linux on any Atari and have a keyboard
++	  attached.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called atakbd.
++
+ config KEYBOARD_HIL_OLD
+ 	tristate "HP HIL keyboard support (simple driver)"
+ 	depends on GSC || HP300
+--- linux-m68k-2.6.21.orig/drivers/input/keyboard/Makefile
++++ linux-m68k-2.6.21/drivers/input/keyboard/Makefile
+@@ -9,6 +9,7 @@ obj-$(CONFIG_KEYBOARD_SUNKBD)		+= sunkbd
+ obj-$(CONFIG_KEYBOARD_LKKBD)		+= lkkbd.o
+ obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
+ obj-$(CONFIG_KEYBOARD_AMIGA)		+= amikbd.o
++obj-$(CONFIG_KEYBOARD_ATARI)		+= atakbd.o
+ obj-$(CONFIG_KEYBOARD_LOCOMO)		+= locomokbd.o
+ obj-$(CONFIG_KEYBOARD_NEWTON)		+= newtonkbd.o
+ obj-$(CONFIG_KEYBOARD_STOWAWAY)		+= stowaway.o
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/input/keyboard/atakbd.c
+@@ -0,0 +1,134 @@
++/*
++ *  atakbd.c
++ *
++ *  Copyright (c) 2005 Michael Schmitz
++ *
++ * Based on amikbd.c, which is
++ *
++ *  Copyright (c) 2000-2001 Vojtech Pavlik
++ *
++ *  Based on the work of:
++ *	Hamish Macdonald
++ */
++
++/*
++ * Atari keyboard driver for Linux/m68k
++ *
++ * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c
++ * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard
++ * interrupt is shared with the MIDI ACIA so MIDI data also get handled there).
++ * This driver only deals with handing key events off to the input layer.
++ */
++
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Should you need to contact me, the author, you can do so either by
++ * e-mail - mail your message to <vojtech at ucw.cz>, or by paper mail:
++ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++
++#include <asm/atariints.h>
++#include <asm/atarihw.h>
++#include <asm/atarikb.h>
++#include <asm/irq.h>
++
++MODULE_AUTHOR("Michael Schmitz <schmitz at biophys.uni-duesseldorf.de>");
++MODULE_DESCRIPTION("Atari keyboard driver");
++MODULE_LICENSE("GPL");
++
++static unsigned char atakbd_keycode[0x72];
++
++static struct input_dev *atakbd_dev;
++
++static void atakbd_interrupt(unsigned char scancode, char down)
++{
++
++	if (scancode < 0x72) {		/* scancodes < 0xf2 are keys */
++
++		// report raw events here?
++
++		scancode = atakbd_keycode[scancode];
++
++		if (scancode == KEY_CAPSLOCK) {	/* CapsLock is a toggle switch key on Amiga */
++			input_report_key(atakbd_dev, scancode, 1);
++			input_report_key(atakbd_dev, scancode, 0);
++			input_sync(atakbd_dev);
++		} else {
++			input_report_key(atakbd_dev, scancode, down);
++			input_sync(atakbd_dev);
++		}
++	} else				/* scancodes >= 0xf2 are mouse data, most likely */
++		printk(KERN_INFO "atakbd: unhandled scancode %x\n", scancode);
++
++	return;
++}
++
++static int __init atakbd_init(void)
++{
++	int i;
++
++	if (!ATARIHW_PRESENT(ST_MFP))
++		return -EIO;
++
++	// TODO: request_mem_region if not done in arch code
++
++	if (!(atakbd_dev = input_allocate_device()))
++		return -ENOMEM;
++
++	// need to init core driver if not already done so
++	if (atari_keyb_init())
++		return -ENODEV;
++
++	atakbd_dev->name = "Atari Keyboard";
++	atakbd_dev->phys = "atakbd/input0";
++	atakbd_dev->id.bustype = BUS_ATARI;
++	atakbd_dev->id.vendor = 0x0001;
++	atakbd_dev->id.product = 0x0001;
++	atakbd_dev->id.version = 0x0100;
++
++	atakbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
++	atakbd_dev->keycode = atakbd_keycode;
++	atakbd_dev->keycodesize = sizeof(unsigned char);
++	atakbd_dev->keycodemax = ARRAY_SIZE(atakbd_keycode);
++
++	for (i = 1; i < 0x72; i++) {
++		atakbd_keycode[i] = i;
++		set_bit(atakbd_keycode[i], atakbd_dev->keybit);
++	}
++
++	input_register_device(atakbd_dev);
++
++	atari_input_keyboard_interrupt_hook = atakbd_interrupt;
++
++	printk(KERN_INFO "input: %s at IKBD ACIA\n", atakbd_dev->name);
++
++	return 0;
++}
++
++static void __exit atakbd_exit(void)
++{
++	atari_input_keyboard_interrupt_hook = NULL;
++	input_unregister_device(atakbd_dev);
++}
++
++module_init(atakbd_init);
++module_exit(atakbd_exit);
+--- linux-m68k-2.6.21.orig/drivers/input/mouse/Kconfig
++++ linux-m68k-2.6.21/drivers/input/mouse/Kconfig
+@@ -96,6 +96,17 @@ config MOUSE_AMIGA
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called amimouse.
+ 
++config MOUSE_ATARI
++	tristate "Atari mouse"
++	depends on ATARI
++	select ATARI_KBD_CORE
++	help
++	  Say Y here if you have an Atari and want its native mouse
++	  supported by the kernel.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called atarimouse.
++
+ config MOUSE_RISCPC
+ 	tristate "Acorn RiscPC mouse"
+ 	depends on ARCH_ACORN
+--- linux-m68k-2.6.21.orig/drivers/input/mouse/Makefile
++++ linux-m68k-2.6.21/drivers/input/mouse/Makefile
+@@ -5,6 +5,7 @@
+ # Each configuration option enables a list of files.
+ 
+ obj-$(CONFIG_MOUSE_AMIGA)	+= amimouse.o
++obj-$(CONFIG_MOUSE_ATARI)	+= atarimouse.o
+ obj-$(CONFIG_MOUSE_RISCPC)	+= rpcmouse.o
+ obj-$(CONFIG_MOUSE_INPORT)	+= inport.o
+ obj-$(CONFIG_MOUSE_LOGIBM)	+= logibm.o
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/input/mouse/atarimouse.c
+@@ -0,0 +1,160 @@
++/*
++ *  Atari mouse driver for Linux/m68k
++ *
++ *  Copyright (c) 2005 Michael Schmitz
++ *
++ *  Based on:
++ *  Amiga mouse driver for Linux/m68k
++ *
++ *  Copyright (c) 2000-2002 Vojtech Pavlik
++ *
++ */
++/*
++ * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c
++ * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard
++ * interrupt is shared with the MIDI ACIA so MIDI data also get handled there).
++ * This driver only deals with handing key events off to the input layer.
++ *
++ * Largely based on the old:
++ *
++ * Atari Mouse Driver for Linux
++ * by Robert de Vries (robert at and.nl) 19Jul93
++ *
++ * 16 Nov 1994 Andreas Schwab
++ * Compatibility with busmouse
++ * Support for three button mouse (shamelessly stolen from MiNT)
++ * third button wired to one of the joystick directions on joystick 1
++ *
++ * 1996/02/11 Andreas Schwab
++ * Module support
++ * Allow multiple open's
++ *
++ * Converted to use new generic busmouse code.  5 Apr 1998
++ *   Russell King <rmk at arm.uk.linux.org>
++ */
++
++
++/*
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/input.h>
++#include <linux/interrupt.h>
++
++#include <asm/irq.h>
++#include <asm/setup.h>
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <asm/atarihw.h>
++#include <asm/atarikb.h>
++#include <asm/atariints.h>
++
++MODULE_AUTHOR("Michael Schmitz <schmitz at biophys.uni-duesseldorf.de>");
++MODULE_DESCRIPTION("Atari mouse driver");
++MODULE_LICENSE("GPL");
++
++static int mouse_threshold[2] = {2,2};
++
++#ifdef __MODULE__
++MODULE_PARM(mouse_threshold, "2i");
++#endif
++#ifdef FIXED_ATARI_JOYSTICK
++extern int atari_mouse_buttons;
++#endif
++static int atamouse_used = 0;
++
++static struct input_dev *atamouse_dev;
++
++static void atamouse_interrupt(char *buf)
++{
++	int buttons, dx, dy;
++
++/*	ikbd_mouse_disable(); */
++
++	buttons = (buf[0] & 1) | ((buf[0] & 2) << 1);
++#ifdef FIXED_ATARI_JOYSTICK
++	buttons |= atari_mouse_buttons & 2;
++	atari_mouse_buttons = buttons;
++#endif
++/*	ikbd_mouse_rel_pos(); */
++
++	/* only relative events get here */
++	dx =  buf[1];
++	dy = -buf[2];
++
++	input_report_rel(atamouse_dev, REL_X, dx);
++	input_report_rel(atamouse_dev, REL_Y, dy);
++
++	input_report_key(atamouse_dev, BTN_LEFT,   buttons & 0x1);
++	input_report_key(atamouse_dev, BTN_MIDDLE, buttons & 0x2);
++	input_report_key(atamouse_dev, BTN_RIGHT,  buttons & 0x4);
++
++	input_sync(atamouse_dev);
++
++	return;
++}
++
++static int atamouse_open(struct input_dev *dev)
++{
++	if (atamouse_used++)
++		return 0;
++
++#ifdef FIXED_ATARI_JOYSTICK
++	atari_mouse_buttons = 0;
++#endif
++	ikbd_mouse_y0_top();
++	ikbd_mouse_thresh(mouse_threshold[0], mouse_threshold[1]);
++	ikbd_mouse_rel_pos();
++	atari_input_mouse_interrupt_hook = atamouse_interrupt;
++	return 0;
++}
++
++static void atamouse_close(struct input_dev *dev)
++{
++	if (!--atamouse_used) {
++		ikbd_mouse_disable();
++		atari_mouse_interrupt_hook = NULL;
++	}
++}
++
++static int __init atamouse_init(void)
++{
++	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP))
++		return -ENODEV;
++
++	if (!(atamouse_dev = input_allocate_device()))
++		return -ENOMEM;
++
++	if (!(atari_keyb_init()))
++		return -ENODEV;
++
++	atamouse_dev->name = "Atari mouse";
++	atamouse_dev->phys = "atamouse/input0";
++	atamouse_dev->id.bustype = BUS_ATARI;
++	atamouse_dev->id.vendor = 0x0001;
++	atamouse_dev->id.product = 0x0002;
++	atamouse_dev->id.version = 0x0100;
++
++	atamouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
++	atamouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
++	atamouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
++	atamouse_dev->open = atamouse_open;
++	atamouse_dev->close = atamouse_close;
++
++	input_register_device(atamouse_dev);
++
++	printk(KERN_INFO "input: %s at keyboard ACIA\n", atamouse_dev->name);
++	return 0;
++}
++
++static void __exit atamouse_exit(void)
++{
++	input_unregister_device(atamouse_dev);
++}
++
++module_init(atamouse_init);
++module_exit(atamouse_exit);
+--- linux-m68k-2.6.21.orig/include/asm-m68k/atarikb.h
++++ linux-m68k-2.6.21/include/asm-m68k/atarikb.h
+@@ -36,5 +36,11 @@ void ikbd_joystick_disable(void);
+ extern void (*atari_MIDI_interrupt_hook) (void);
+ /* Hook for mouse driver */
+ extern void (*atari_mouse_interrupt_hook) (char *);
++/* Hook for keyboard inputdev  driver */
++extern void (*atari_input_keyboard_interrupt_hook) (unsigned char, char);
++/* Hook for mouse inputdev  driver */
++extern void (*atari_input_mouse_interrupt_hook) (char *);
++
++int atari_keyb_init(void);
+ 
+ #endif /* _LINUX_ATARIKB_H */
+--- linux-m68k-2.6.21.orig/include/linux/input.h
++++ linux-m68k-2.6.21/include/linux/input.h
+@@ -676,6 +676,7 @@ struct input_absinfo {
+ #define BUS_I2C			0x18
+ #define BUS_HOST		0x19
+ #define BUS_GSC			0x1A
++#define BUS_ATARI		0x1B
+ 
+ /*
+  * Values describing the status of a force-feedback effect

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/636-atafb.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/636-atafb.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,5530 @@
+Cc: Antonino Daplas <adaplas at gmail.com>,
+    James Simmons <jsimmons at infradead.org>,
+    linux-fbdev-devel at lists.sourceforge.net
+Subject: [PATCH] m68k: Atari fb revival
+
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+
+Update the atari fb to 2.6 by Michael Schmitz,
+Reformatting and rewrite of bit plane functions by Roman Zippel,
+A few more fixes by Geert Uytterhoeven.
+
+Signed-off-by: Michael Schmitz <schmitz at debian.org>
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/video/Kconfig          |    5 
+ drivers/video/Makefile         |    3 
+ drivers/video/atafb.c          | 2799 +++++++++++++++++++++--------------------
+ drivers/video/atafb.h          |   36 
+ drivers/video/atafb_iplan2p2.c |  293 ++++
+ drivers/video/atafb_iplan2p4.c |  308 ++++
+ drivers/video/atafb_iplan2p8.c |  345 +++++
+ drivers/video/atafb_mfb.c      |  112 +
+ drivers/video/atafb_utils.h    |  400 +++++
+ 9 files changed, 2986 insertions(+), 1315 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/video/Kconfig
++++ linux-m68k-2.6.21/drivers/video/Kconfig
+@@ -389,7 +389,10 @@ config FB_ARC
+ 
+ config FB_ATARI
+ 	bool "Atari native chipset support"
+-	depends on (FB = y) && ATARI && BROKEN
++	depends on (FB = y) && ATARI
++	select FB_CFB_FILLRECT
++	select FB_CFB_COPYAREA
++	select FB_CFB_IMAGEBLIT
+ 	help
+ 	  This is the frame buffer device driver for the builtin graphics
+ 	  chipset found in Ataris.
+--- linux-m68k-2.6.21.orig/drivers/video/Makefile
++++ linux-m68k-2.6.21/drivers/video/Makefile
+@@ -63,7 +63,8 @@ obj-$(CONFIG_FB_TCX)              += tcx
+ obj-$(CONFIG_FB_LEO)              += leo.o sbuslib.o
+ obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o
+ obj-$(CONFIG_FB_ACORN)            += acornfb.o
+-obj-$(CONFIG_FB_ATARI)            += atafb.o
++obj-$(CONFIG_FB_ATARI)            += atafb.o c2p.o atafb_mfb.o \
++                                     atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
+ obj-$(CONFIG_FB_MAC)              += macfb.o
+ obj-$(CONFIG_FB_HGA)              += hgafb.o
+ obj-$(CONFIG_FB_IGA)              += igafb.o
+--- linux-m68k-2.6.21.orig/drivers/video/atafb.c
++++ linux-m68k-2.6.21/drivers/video/atafb.c
+@@ -2,7 +2,7 @@
+  * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
+  *
+  *  Copyright (C) 1994 Martin Schaller & Roman Hodek
+- *  
++ *
+  * 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
+  * for more details.
+@@ -70,14 +70,8 @@
+ #include <linux/fb.h>
+ #include <asm/atarikb.h>
+ 
+-#include <video/fbcon.h>
+-#include <video/fbcon-cfb8.h>
+-#include <video/fbcon-cfb16.h>
+-#include <video/fbcon-iplan2p2.h>
+-#include <video/fbcon-iplan2p4.h>
+-#include <video/fbcon-iplan2p8.h>
+-#include <video/fbcon-mfb.h>
+-
++#include "c2p.h"
++#include "atafb.h"
+ 
+ #define SWITCH_ACIA 0x01		/* modes for switch on OverScan */
+ #define SWITCH_SND6 0x40
+@@ -87,22 +81,48 @@
+ 
+ #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
+ 
++	/*
++	 * Interface to the world
++	 */
++
++static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
++static int atafb_set_par(struct fb_info *info);
++static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
++			   unsigned int blue, unsigned int transp,
++			   struct fb_info *info);
++static int atafb_blank(int blank, struct fb_info *info);
++static int atafb_pan_display(struct fb_var_screeninfo *var,
++			     struct fb_info *info);
++static void atafb_fillrect(struct fb_info *info,
++			   const struct fb_fillrect *rect);
++static void atafb_copyarea(struct fb_info *info,
++			   const struct fb_copyarea *region);
++static void atafb_imageblit(struct fb_info *info, const struct fb_image *image);
++static int atafb_ioctl(struct fb_info *info, unsigned int cmd,
++		       unsigned long arg);
+ 
+-static int default_par=0;	/* default resolution (0=none) */
+ 
+-static unsigned long default_mem_req=0;
++static int default_par;		/* default resolution (0=none) */
+ 
+-static int hwscroll=-1;
++static unsigned long default_mem_req;
++
++static int hwscroll = -1;
+ 
+ static int use_hwscroll = 1;
+ 
+-static int sttt_xres=640,st_yres=400,tt_yres=480;
+-static int sttt_xres_virtual=640,sttt_yres_virtual=400;
+-static int ovsc_offset=0, ovsc_addlen=0;
++static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
++static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
++static int ovsc_offset, ovsc_addlen;
++
++	/*
++	 * Hardware parameters for current mode
++	 */
+ 
+ static struct atafb_par {
+ 	void *screen_base;
+ 	int yres_virtual;
++	u_long next_line;
++	u_long next_plane;
+ #if defined ATAFB_TT || defined ATAFB_STE
+ 	union {
+ 		struct {
+@@ -138,7 +158,7 @@ static struct atafb_par {
+ /* Don't calculate an own resolution, and thus don't change the one found when
+  * booting (currently used for the Falcon to keep settings for internal video
+  * hardware extensions (e.g. ScreenBlaster)  */
+-static int DontCalcRes = 0; 
++static int DontCalcRes = 0;
+ 
+ #ifdef ATAFB_FALCON
+ #define HHT hw.falcon.hht
+@@ -163,83 +183,84 @@ static int DontCalcRes = 0; 
+ #define VMO_PREMASK		0x0c
+ #endif
+ 
+-static struct fb_info fb_info;
++static struct fb_info fb_info = {
++	.fix = {
++		.id	= "Atari ",
++		.visual	= FB_VISUAL_PSEUDOCOLOR,
++		.accel	= FB_ACCEL_NONE,
++	}
++};
+ 
+ static void *screen_base;	/* base address of screen */
+ static void *real_screen_base;	/* (only for Overscan) */
+ 
+ static int screen_len;
+ 
+-static int current_par_valid=0; 
+-
+-static int mono_moni=0;
++static int current_par_valid;
+ 
+-static struct display disp;
++static int mono_moni;
+ 
+ 
+ #ifdef ATAFB_EXT
+-/* external video handling */
+ 
+-static unsigned			external_xres;
+-static unsigned			external_xres_virtual;
+-static unsigned			external_yres;
+-/* not needed - atafb will never support panning/hardwarescroll with external
+- * static unsigned		external_yres_virtual;	
+-*/
++/* external video handling */
++static unsigned int external_xres;
++static unsigned int external_xres_virtual;
++static unsigned int external_yres;
+ 
+-static unsigned			external_depth;
+-static int				external_pmode;
+-static void *external_addr = 0;
+-static unsigned long	external_len;
+-static unsigned long	external_vgaiobase = 0;
+-static unsigned int		external_bitspercol = 6;
+-
+-/* 
+-JOE <joe at amber.dinoco.de>: 
+-added card type for external driver, is only needed for
+-colormap handling.
+-*/
++/*
++ * not needed - atafb will never support panning/hardwarescroll with external
++ * static unsigned int external_yres_virtual;
++ */
++static unsigned int external_depth;
++static int external_pmode;
++static void *external_addr;
++static unsigned long external_len;
++static unsigned long external_vgaiobase;
++static unsigned int external_bitspercol = 6;
+ 
++/*
++ * JOE <joe at amber.dinoco.de>:
++ * added card type for external driver, is only needed for
++ * colormap handling.
++ */
+ enum cardtype { IS_VGA, IS_MV300 };
+ static enum cardtype external_card_type = IS_VGA;
+ 
+ /*
+-The MV300 mixes the color registers. So we need an array of munged
+-indices in order to access the correct reg.
+-*/
+-static int MV300_reg_1bit[2]={0,1};
+-static int MV300_reg_4bit[16]={
+-0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
+-static int MV300_reg_8bit[256]={
+-0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 
+-8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 
+-4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 
+-12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 
+-2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, 
+-10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 
+-6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 
+-14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, 
+-1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 
+-9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 
+-5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 
+-13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 
+-3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, 
+-11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 
+-7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, 
+-15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 }; 
++ * The MV300 mixes the color registers. So we need an array of munged
++ * indices in order to access the correct reg.
++ */
++static int MV300_reg_1bit[2] = {
++	0, 1
++};
++static int MV300_reg_4bit[16] = {
++	0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
++};
++static int MV300_reg_8bit[256] = {
++	0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
++	8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
++	4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
++	12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
++	2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
++	10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
++	6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
++	14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
++	1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
++	9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
++	5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
++	13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
++	3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
++	11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
++	7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
++	15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
++};
+ 
+ static int *MV300_reg = MV300_reg_8bit;
+-
+-/*
+-And on the MV300 it's difficult to read out the hardware palette. So we
+-just keep track of the set colors in our own array here, and use that!
+-*/
+-
+-static struct { unsigned char red,green,blue,pad; } ext_color[256];
+ #endif /* ATAFB_EXT */
+ 
+ 
+-static int inverse=0;
++static int inverse;
+ 
+ extern int fontheight_8x8;
+ extern int fontwidth_8x8;
+@@ -249,96 +270,154 @@ extern int fontheight_8x16;
+ extern int fontwidth_8x16;
+ extern unsigned char fontdata_8x16[];
+ 
++/*
++ * struct fb_ops {
++ *	* open/release and usage marking
++ *	struct module *owner;
++ *	int (*fb_open)(struct fb_info *info, int user);
++ *	int (*fb_release)(struct fb_info *info, int user);
++ *
++ *	* For framebuffers with strange non linear layouts or that do not
++ *	* work with normal memory mapped access
++ *	ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
++ *	ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
++ *
++ *	* checks var and eventually tweaks it to something supported,
++ *	* DOES NOT MODIFY PAR *
++ *	int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
++ *
++ *	* set the video mode according to info->var *
++ *	int (*fb_set_par)(struct fb_info *info);
++ *
++ *	* set color register *
++ *	int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
++ *			    unsigned int blue, unsigned int transp, struct fb_info *info);
++ *
++ *	* set color registers in batch *
++ *	int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
++ *
++ *	* blank display *
++ *	int (*fb_blank)(int blank, struct fb_info *info);
++ *
++ *	* pan display *
++ *	int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
++ *
++ *	*** The meat of the drawing engine ***
++ *	* Draws a rectangle *
++ *	void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
++ *	* Copy data from area to another *
++ *	void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
++ *	* Draws a image to the display *
++ *	void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
++ *
++ *	* Draws cursor *
++ *	int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
++ *
++ *	* Rotates the display *
++ *	void (*fb_rotate)(struct fb_info *info, int angle);
++ *
++ *	* wait for blit idle, optional *
++ *	int (*fb_sync)(struct fb_info *info);
++ *
++ *	* perform fb specific ioctl (optional) *
++ *	int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
++ *			unsigned long arg);
++ *
++ *	* Handle 32bit compat ioctl (optional) *
++ *	int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
++ *			unsigned long arg);
++ *
++ *	* perform fb specific mmap *
++ *	int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
++ *
++ *	* save current hardware state *
++ *	void (*fb_save_state)(struct fb_info *info);
++ *
++ *	* restore saved state *
++ *	void (*fb_restore_state)(struct fb_info *info);
++ * } ;
++ */
++
++
+ /* ++roman: This structure abstracts from the underlying hardware (ST(e),
+  * TT, or Falcon.
+  *
+- * int (*detect)( void )
++ * int (*detect)(void)
+  *   This function should detect the current video mode settings and
+  *   store them in atafb_predefined[0] for later reference by the
+  *   user. Return the index+1 of an equivalent predefined mode or 0
+  *   if there is no such.
+- * 
+- * int (*encode_fix)( struct fb_fix_screeninfo *fix,
+- *                    struct atafb_par *par )
++ *
++ * int (*encode_fix)(struct fb_fix_screeninfo *fix,
++ *                   struct atafb_par *par)
+  *   This function should fill in the 'fix' structure based on the
+  *   values in the 'par' structure.
+- *   
+- * int (*decode_var)( struct fb_var_screeninfo *var,
+- *                    struct atafb_par *par )
++ * !!! Obsolete, perhaps !!!
++ *
++ * int (*decode_var)(struct fb_var_screeninfo *var,
++ *                   struct atafb_par *par)
+  *   Get the video params out of 'var'. If a value doesn't fit, round
+  *   it up, if it's too big, return EINVAL.
+- *   Round up in the following order: bits_per_pixel, xres, yres, 
+- *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, 
++ *   Round up in the following order: bits_per_pixel, xres, yres,
++ *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
+  *   horizontal timing, vertical timing.
+  *
+- * int (*encode_var)( struct fb_var_screeninfo *var,
+- *                    struct atafb_par *par );
++ * int (*encode_var)(struct fb_var_screeninfo *var,
++ *                   struct atafb_par *par);
+  *   Fill the 'var' structure based on the values in 'par' and maybe
+  *   other values read out of the hardware.
+- *   
+- * void (*get_par)( struct atafb_par *par )
++ *
++ * void (*get_par)(struct atafb_par *par)
+  *   Fill the hardware's 'par' structure.
+- *   
+- * void (*set_par)( struct atafb_par *par )
++ *   !!! Used only by detect() !!!
++ *
++ * void (*set_par)(struct atafb_par *par)
+  *   Set the hardware according to 'par'.
+- *   
+- * int (*getcolreg)( unsigned regno, unsigned *red,
+- *                   unsigned *green, unsigned *blue,
+- *                   unsigned *transp, struct fb_info *info )
+- *   Read a single color register and split it into
+- *   colors/transparent. Return != 0 for invalid regno.
+  *
+  * void (*set_screen_base)(void *s_base)
+  *   Set the base address of the displayed frame buffer. Only called
+  *   if yres_virtual > yres or xres_virtual > xres.
+  *
+- * int (*blank)( int blank_mode )
+- *   Blank the screen if blank_mode!=0, else unblank. If blank==NULL then
++ * int (*blank)(int blank_mode)
++ *   Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
+  *   the caller blanks by setting the CLUT to all black. Return 0 if blanking
+  *   succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
+  *   doesn't support it. Implements VESA suspend and powerdown modes on
+  *   hardware that supports disabling hsync/vsync:
+- *       blank_mode==2: suspend vsync, 3:suspend hsync, 4: powerdown.
++ *       blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
+  */
+ 
+ static struct fb_hwswitch {
+-	int  (*detect)( void );
+-	int  (*encode_fix)( struct fb_fix_screeninfo *fix,
+-						struct atafb_par *par );
+-	int  (*decode_var)( struct fb_var_screeninfo *var,
+-						struct atafb_par *par );
+-	int  (*encode_var)( struct fb_var_screeninfo *var,
+-						struct atafb_par *par );
+-	void (*get_par)( struct atafb_par *par );
+-	void (*set_par)( struct atafb_par *par );
+-	int  (*getcolreg)( unsigned regno, unsigned *red,
+-					   unsigned *green, unsigned *blue,
+-					   unsigned *transp, struct fb_info *info );
++	int (*detect)(void);
++	int (*encode_fix)(struct fb_fix_screeninfo *fix,
++			  struct atafb_par *par);
++	int (*decode_var)(struct fb_var_screeninfo *var,
++			  struct atafb_par *par);
++	int (*encode_var)(struct fb_var_screeninfo *var,
++			  struct atafb_par *par);
++	void (*get_par)(struct atafb_par *par);
++	void (*set_par)(struct atafb_par *par);
+ 	void (*set_screen_base)(void *s_base);
+-	int  (*blank)( int blank_mode );
+-	int  (*pan_display)( struct fb_var_screeninfo *var,
+-						 struct atafb_par *par);
++	int (*blank)(int blank_mode);
++	int (*pan_display)(struct fb_var_screeninfo *var,
++			   struct fb_info *info);
+ } *fbhw;
+ 
+-static char *autodetect_names[] = {"autodetect", NULL};
+-static char *stlow_names[] = {"stlow", NULL};
+-static char *stmid_names[] = {"stmid", "default5", NULL};
+-static char *sthigh_names[] = {"sthigh", "default4", NULL};
+-static char *ttlow_names[] = {"ttlow", NULL};
+-static char *ttmid_names[]= {"ttmid", "default1", NULL};
+-static char *tthigh_names[]= {"tthigh", "default2", NULL};
+-static char *vga2_names[] = {"vga2", NULL};
+-static char *vga4_names[] = {"vga4", NULL};
+-static char *vga16_names[] = {"vga16", "default3", NULL};
+-static char *vga256_names[] = {"vga256", NULL};
+-static char *falh2_names[] = {"falh2", NULL};
+-static char *falh16_names[] = {"falh16", NULL};
++static char *autodetect_names[] = { "autodetect", NULL };
++static char *stlow_names[] = { "stlow", NULL };
++static char *stmid_names[] = { "stmid", "default5", NULL };
++static char *sthigh_names[] = { "sthigh", "default4", NULL };
++static char *ttlow_names[] = { "ttlow", NULL };
++static char *ttmid_names[] = { "ttmid", "default1", NULL };
++static char *tthigh_names[] = { "tthigh", "default2", NULL };
++static char *vga2_names[] = { "vga2", NULL };
++static char *vga4_names[] = { "vga4", NULL };
++static char *vga16_names[] = { "vga16", "default3", NULL };
++static char *vga256_names[] = { "vga256", NULL };
++static char *falh2_names[] = { "falh2", NULL };
++static char *falh16_names[] = { "falh16", NULL };
+ 
+ static char **fb_var_names[] = {
+-	/* Writing the name arrays directly in this array (via "(char *[]){...}")
+-	 * crashes gcc 2.5.8 (sigsegv) if the inner array
+-	 * contains more than two items. I've also seen that all elements
+-	 * were identical to the last (my cross-gcc) :-(*/
+ 	autodetect_names,
+ 	stlow_names,
+ 	stmid_names,
+@@ -353,18 +432,17 @@ static char **fb_var_names[] = {
+ 	falh2_names,
+ 	falh16_names,
+ 	NULL
+-	/* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */
+ };
+ 
+ static struct fb_var_screeninfo atafb_predefined[] = {
+- 	/*
+- 	 * yres_virtual==0 means use hw-scrolling if possible, else yres
+- 	 */
+- 	{ /* autodetect */
+-	  0, 0, 0, 0, 0, 0, 0, 0,   		/* xres-grayscale */
+-	  {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, 	/* red green blue tran*/
++	/*
++	 * yres_virtual == 0 means use hw-scrolling if possible, else yres
++	 */
++	{ /* autodetect */
++	  0, 0, 0, 0, 0, 0, 0, 0,		/* xres-grayscale */
++	  {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},	/* red green blue tran*/
+ 	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+- 	{ /* st low */
++	{ /* st low */
+ 	  320, 200, 320, 0, 0, 0, 4, 0,
+ 	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
+ 	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+@@ -414,27 +492,100 @@ static struct fb_var_screeninfo atafb_pr
+ 	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ };
+ 
+-static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined);
++static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
+ 
++static struct fb_videomode atafb_modedb[] __initdata = {
++	/*
++	 *  Atari Video Modes
++	 *
++	 *  If you change these, make sure to update DEFMODE_* as well!
++	 */
+ 
+-static int
+-get_video_mode(char *vname)
++	/*
++	 *  ST/TT Video Modes
++	 */
++
++	{
++		/* 320x200, 15 kHz, 60 Hz (ST low) */
++		"st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
++		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
++	}, {
++		/* 640x200, 15 kHz, 60 Hz (ST medium) */
++		"st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
++		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
++	}, {
++		/* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
++		"st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
++		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
++	}, {
++		/* 320x480, 15 kHz, 60 Hz (TT low) */
++		"tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
++		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
++	}, {
++		/* 640x480, 29 kHz, 57 Hz (TT medium) */
++		"tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
++		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
++	}, {
++		/* 1280x960, 29 kHz, 60 Hz (TT high) */
++		"tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
++		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
++	},
++
++	/*
++	 *  VGA Video Modes
++	 */
++
++	{
++		/* 640x480, 31 kHz, 60 Hz (VGA) */
++		"vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
++		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
++	}, {
++		/* 640x400, 31 kHz, 70 Hz (VGA) */
++		"vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
++		FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
++	},
++
++	/*
++	 *  Falcon HiRes Video Modes
++	 */
++
++	{
++		/* 896x608, 31 kHz, 60 Hz (Falcon High) */
++		"falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
++		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
++	},
++};
++
++#define NUM_TOTAL_MODES  ARRAY_SIZE(atafb_modedb)
++
++static char *mode_option __initdata = NULL;
++
++ /* default modes */
++
++#define DEFMODE_TT	5		/* "tt-high" for TT */
++#define DEFMODE_F30	7		/* "vga70" for Falcon */
++#define DEFMODE_STE	2		/* "st-high" for ST/E */
++#define DEFMODE_EXT	6		/* "vga" for external */
++
++
++static int get_video_mode(char *vname)
+ {
+-    char ***name_list;
+-    char **name;
+-    int i;
+-    name_list=fb_var_names;
+-    for (i = 0 ; i < num_atafb_predefined ; i++) {
+-	name=*(name_list++);
+-	if (! name || ! *name)
+-	    break;
+-	while (*name) {
+-	    if (! strcmp(vname, *name))
+-		return i+1;
+-	    name++;
++	char ***name_list;
++	char **name;
++	int i;
++
++	name_list = fb_var_names;
++	for (i = 0; i < num_atafb_predefined; i++) {
++		name = *name_list++;
++		if (!name || !*name)
++			break;
++		while (*name) {
++			if (!strcmp(vname, *name))
++				return i + 1;
++			name++;
++		}
+ 	}
+-    }
+-    return 0;
++	return 0;
+ }
+ 
+ 
+@@ -443,93 +594,84 @@ get_video_mode(char *vname)
+ 
+ #ifdef ATAFB_TT
+ 
+-static int tt_encode_fix( struct fb_fix_screeninfo *fix,
+-						  struct atafb_par *par )
+-
++static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
+ {
+ 	int mode;
+ 
+-	strcpy(fix->id,"Atari Builtin");
++	strcpy(fix->id, "Atari Builtin");
+ 	fix->smem_start = (unsigned long)real_screen_base;
+ 	fix->smem_len = screen_len;
+-	fix->type=FB_TYPE_INTERLEAVED_PLANES;
+-	fix->type_aux=2;
+-	fix->visual=FB_VISUAL_PSEUDOCOLOR;
++	fix->type = FB_TYPE_INTERLEAVED_PLANES;
++	fix->type_aux = 2;
++	fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ 	mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
+ 	if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
+-		fix->type=FB_TYPE_PACKED_PIXELS;
+-		fix->type_aux=0;
++		fix->type = FB_TYPE_PACKED_PIXELS;
++		fix->type_aux = 0;
+ 		if (mode == TT_SHIFTER_TTHIGH)
+-			fix->visual=FB_VISUAL_MONO01;
++			fix->visual = FB_VISUAL_MONO01;
+ 	}
+-	fix->xpanstep=0;
+-	fix->ypanstep=1;
+-	fix->ywrapstep=0;
++	fix->xpanstep = 0;
++	fix->ypanstep = 1;
++	fix->ywrapstep = 0;
+ 	fix->line_length = 0;
+ 	fix->accel = FB_ACCEL_ATARIBLITT;
+ 	return 0;
+ }
+ 
+-
+-static int tt_decode_var( struct fb_var_screeninfo *var,
+-						  struct atafb_par *par )
++static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
+ {
+-	int xres=var->xres;
+-	int yres=var->yres;
+-	int bpp=var->bits_per_pixel;
++	int xres = var->xres;
++	int yres = var->yres;
++	int bpp = var->bits_per_pixel;
+ 	int linelen;
+ 	int yres_virtual = var->yres_virtual;
+ 
+ 	if (mono_moni) {
+-		if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2)
++		if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
+ 			return -EINVAL;
+-		par->hw.tt.mode=TT_SHIFTER_TTHIGH;
+-		xres=sttt_xres*2;
+-		yres=tt_yres*2;
+-		bpp=1;
++		par->hw.tt.mode = TT_SHIFTER_TTHIGH;
++		xres = sttt_xres * 2;
++		yres = tt_yres * 2;
++		bpp = 1;
+ 	} else {
+ 		if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
+ 			return -EINVAL;
+ 		if (bpp > 4) {
+-			if (xres > sttt_xres/2 || yres > tt_yres)
++			if (xres > sttt_xres / 2 || yres > tt_yres)
+ 				return -EINVAL;
+-			par->hw.tt.mode=TT_SHIFTER_TTLOW;
+-			xres=sttt_xres/2;
+-			yres=tt_yres;
+-			bpp=8;
+-		}
+-		else if (bpp > 2) {
++			par->hw.tt.mode = TT_SHIFTER_TTLOW;
++			xres = sttt_xres / 2;
++			yres = tt_yres;
++			bpp = 8;
++		} else if (bpp > 2) {
+ 			if (xres > sttt_xres || yres > tt_yres)
+ 				return -EINVAL;
+-			if (xres > sttt_xres/2 || yres > st_yres/2) {
+-				par->hw.tt.mode=TT_SHIFTER_TTMID;
+-				xres=sttt_xres;
+-				yres=tt_yres;
+-				bpp=4;
++			if (xres > sttt_xres / 2 || yres > st_yres / 2) {
++				par->hw.tt.mode = TT_SHIFTER_TTMID;
++				xres = sttt_xres;
++				yres = tt_yres;
++				bpp = 4;
++			} else {
++				par->hw.tt.mode = TT_SHIFTER_STLOW;
++				xres = sttt_xres / 2;
++				yres = st_yres / 2;
++				bpp = 4;
+ 			}
+-			else {
+-				par->hw.tt.mode=TT_SHIFTER_STLOW;
+-				xres=sttt_xres/2;
+-				yres=st_yres/2;
+-				bpp=4;
+-			}
+-		}
+-		else if (bpp > 1) {
+-			if (xres > sttt_xres || yres > st_yres/2)
++		} else if (bpp > 1) {
++			if (xres > sttt_xres || yres > st_yres / 2)
+ 				return -EINVAL;
+-			par->hw.tt.mode=TT_SHIFTER_STMID;
+-			xres=sttt_xres;
+-			yres=st_yres/2;
+-			bpp=2;
+-		}
+-		else if (var->xres > sttt_xres || var->yres > st_yres) {
++			par->hw.tt.mode = TT_SHIFTER_STMID;
++			xres = sttt_xres;
++			yres = st_yres / 2;
++			bpp = 2;
++		} else if (var->xres > sttt_xres || var->yres > st_yres) {
+ 			return -EINVAL;
+-		}
+-		else {
+-			par->hw.tt.mode=TT_SHIFTER_STHIGH;
+-			xres=sttt_xres;
+-			yres=st_yres;
+-			bpp=1;
++		} else {
++			par->hw.tt.mode = TT_SHIFTER_STHIGH;
++			xres = sttt_xres;
++			yres = st_yres;
++			bpp = 1;
+ 		}
+ 	}
+ 	if (yres_virtual <= 0)
+@@ -537,10 +679,10 @@ static int tt_decode_var( struct fb_var_
+ 	else if (yres_virtual < yres)
+ 		yres_virtual = yres;
+ 	if (var->sync & FB_SYNC_EXT)
+-		par->hw.tt.sync=0;
++		par->hw.tt.sync = 0;
+ 	else
+-		par->hw.tt.sync=1;
+-	linelen=xres*bpp/8;
++		par->hw.tt.sync = 1;
++	linelen = xres * bpp / 8;
+ 	if (yres_virtual * linelen > screen_len && screen_len)
+ 		return -EINVAL;
+ 	if (yres * linelen > screen_len && screen_len)
+@@ -552,154 +694,123 @@ static int tt_decode_var( struct fb_var_
+ 	return 0;
+ }
+ 
+-static int tt_encode_var( struct fb_var_screeninfo *var,
+-						  struct atafb_par *par )
++static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
+ {
+ 	int linelen;
+ 	memset(var, 0, sizeof(struct fb_var_screeninfo));
+-	var->red.offset=0;
+-	var->red.length=4;
+-	var->red.msb_right=0;
+-	var->grayscale=0;
+-
+-	var->pixclock=31041;
+-	var->left_margin=120;		/* these may be incorrect 	*/
+-	var->right_margin=100;
+-	var->upper_margin=8;
+-	var->lower_margin=16;
+-	var->hsync_len=140;
+-	var->vsync_len=30;
++	var->red.offset = 0;
++	var->red.length = 4;
++	var->red.msb_right = 0;
++	var->grayscale = 0;
++
++	var->pixclock = 31041;
++	var->left_margin = 120;		/* these may be incorrect */
++	var->right_margin = 100;
++	var->upper_margin = 8;
++	var->lower_margin = 16;
++	var->hsync_len = 140;
++	var->vsync_len = 30;
+ 
+-	var->height=-1;
+-	var->width=-1;
++	var->height = -1;
++	var->width = -1;
+ 
+ 	if (par->hw.tt.sync & 1)
+-		var->sync=0;
++		var->sync = 0;
+ 	else
+-		var->sync=FB_SYNC_EXT;
++		var->sync = FB_SYNC_EXT;
+ 
+ 	switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
+ 	case TT_SHIFTER_STLOW:
+-		var->xres=sttt_xres/2;
+-		var->xres_virtual=sttt_xres_virtual/2;
+-		var->yres=st_yres/2;
+-		var->bits_per_pixel=4;
++		var->xres = sttt_xres / 2;
++		var->xres_virtual = sttt_xres_virtual / 2;
++		var->yres = st_yres / 2;
++		var->bits_per_pixel = 4;
+ 		break;
+ 	case TT_SHIFTER_STMID:
+-		var->xres=sttt_xres;
+-		var->xres_virtual=sttt_xres_virtual;
+-		var->yres=st_yres/2;
+-		var->bits_per_pixel=2;
++		var->xres = sttt_xres;
++		var->xres_virtual = sttt_xres_virtual;
++		var->yres = st_yres / 2;
++		var->bits_per_pixel = 2;
+ 		break;
+ 	case TT_SHIFTER_STHIGH:
+-		var->xres=sttt_xres;
+-		var->xres_virtual=sttt_xres_virtual;
+-		var->yres=st_yres;
+-		var->bits_per_pixel=1;
++		var->xres = sttt_xres;
++		var->xres_virtual = sttt_xres_virtual;
++		var->yres = st_yres;
++		var->bits_per_pixel = 1;
+ 		break;
+ 	case TT_SHIFTER_TTLOW:
+-		var->xres=sttt_xres/2;
+-		var->xres_virtual=sttt_xres_virtual/2;
+-		var->yres=tt_yres;
+-		var->bits_per_pixel=8;
++		var->xres = sttt_xres / 2;
++		var->xres_virtual = sttt_xres_virtual / 2;
++		var->yres = tt_yres;
++		var->bits_per_pixel = 8;
+ 		break;
+ 	case TT_SHIFTER_TTMID:
+-		var->xres=sttt_xres;
+-		var->xres_virtual=sttt_xres_virtual;
+-		var->yres=tt_yres;
+-		var->bits_per_pixel=4;
++		var->xres = sttt_xres;
++		var->xres_virtual = sttt_xres_virtual;
++		var->yres = tt_yres;
++		var->bits_per_pixel = 4;
+ 		break;
+ 	case TT_SHIFTER_TTHIGH:
+-		var->red.length=0;
+-		var->xres=sttt_xres*2;
+-		var->xres_virtual=sttt_xres_virtual*2;
+-		var->yres=tt_yres*2;
+-		var->bits_per_pixel=1;
++		var->red.length = 0;
++		var->xres = sttt_xres * 2;
++		var->xres_virtual = sttt_xres_virtual * 2;
++		var->yres = tt_yres * 2;
++		var->bits_per_pixel = 1;
+ 		break;
+-	}		
+-	var->blue=var->green=var->red;
+-	var->transp.offset=0;
+-	var->transp.length=0;
+-	var->transp.msb_right=0;
+-	linelen=var->xres_virtual * var->bits_per_pixel / 8;
+-	if (! use_hwscroll)
+-		var->yres_virtual=var->yres;
++	}
++	var->blue = var->green = var->red;
++	var->transp.offset = 0;
++	var->transp.length = 0;
++	var->transp.msb_right = 0;
++	linelen = var->xres_virtual * var->bits_per_pixel / 8;
++	if (!use_hwscroll)
++		var->yres_virtual = var->yres;
+ 	else if (screen_len) {
+ 		if (par->yres_virtual)
+ 			var->yres_virtual = par->yres_virtual;
+ 		else
+-			/* yres_virtual==0 means use maximum */
++			/* yres_virtual == 0 means use maximum */
+ 			var->yres_virtual = screen_len / linelen;
+ 	} else {
+ 		if (hwscroll < 0)
+ 			var->yres_virtual = 2 * var->yres;
+ 		else
+-			var->yres_virtual=var->yres+hwscroll * 16;
++			var->yres_virtual = var->yres + hwscroll * 16;
+ 	}
+-	var->xoffset=0;
++	var->xoffset = 0;
+ 	if (screen_base)
+-		var->yoffset=(par->screen_base - screen_base)/linelen;
++		var->yoffset = (par->screen_base - screen_base) / linelen;
+ 	else
+-		var->yoffset=0;
+-	var->nonstd=0;
+-	var->activate=0;
+-	var->vmode=FB_VMODE_NONINTERLACED;
++		var->yoffset = 0;
++	var->nonstd = 0;
++	var->activate = 0;
++	var->vmode = FB_VMODE_NONINTERLACED;
+ 	return 0;
+ }
+ 
+-
+-static void tt_get_par( struct atafb_par *par )
++static void tt_get_par(struct atafb_par *par)
+ {
+ 	unsigned long addr;
+-	par->hw.tt.mode=shifter_tt.tt_shiftmode;
+-	par->hw.tt.sync=shifter.syncmode;
++	par->hw.tt.mode = shifter_tt.tt_shiftmode;
++	par->hw.tt.sync = shifter.syncmode;
+ 	addr = ((shifter.bas_hi & 0xff) << 16) |
+ 	       ((shifter.bas_md & 0xff) << 8)  |
+ 	       ((shifter.bas_lo & 0xff));
+ 	par->screen_base = phys_to_virt(addr);
+ }
+ 
+-static void tt_set_par( struct atafb_par *par )
++static void tt_set_par(struct atafb_par *par)
+ {
+-	shifter_tt.tt_shiftmode=par->hw.tt.mode;
+-	shifter.syncmode=par->hw.tt.sync;
++	shifter_tt.tt_shiftmode = par->hw.tt.mode;
++	shifter.syncmode = par->hw.tt.sync;
+ 	/* only set screen_base if really necessary */
+ 	if (current_par.screen_base != par->screen_base)
+ 		fbhw->set_screen_base(par->screen_base);
+ }
+ 
+-
+-static int tt_getcolreg(unsigned regno, unsigned *red,
+-			unsigned *green, unsigned *blue,
+-			unsigned *transp, struct fb_info *info)
+-{
+-	int t, col;
+-
+-	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
+-		regno += 254;
+-	if (regno > 255)
+-		return 1;
+-	t = tt_palette[regno];
+-	col = t & 15;
+-	col |= col << 4;
+-	col |= col << 8;
+-	*blue = col;
+-	col = (t >> 4) & 15;
+-	col |= col << 4;
+-	col |= col << 8;
+-	*green = col;
+-	col = (t >> 8) & 15;
+-	col |= col << 4;
+-	col |= col << 8;
+-	*red = col;
+-	*transp = 0;
+-	return 0;
+-}
+-
+-
+-static int tt_setcolreg(unsigned regno, unsigned red,
+-			unsigned green, unsigned blue,
+-			unsigned transp, struct fb_info *info)
++static int tt_setcolreg(unsigned int regno, unsigned int red,
++			unsigned int green, unsigned int blue,
++			unsigned int transp, struct fb_info *info)
+ {
+ 	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
+ 		regno += 254;
+@@ -708,15 +819,14 @@ static int tt_setcolreg(unsigned regno, 
+ 	tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
+ 			     (blue >> 12));
+ 	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
+-		TT_SHIFTER_STHIGH && regno == 254)
++	    TT_SHIFTER_STHIGH && regno == 254)
+ 		tt_palette[0] = 0;
+ 	return 0;
+ }
+ 
+-						  
+-static int tt_detect( void )
+-
+-{	struct atafb_par par;
++static int tt_detect(void)
++{
++	struct atafb_par par;
+ 
+ 	/* Determine the connected monitor: The DMA sound must be
+ 	 * disabled before reading the MFP GPIP, because the Sound
+@@ -726,9 +836,9 @@ static int tt_detect( void )
+ 	 * announced that the Eagle is TT compatible, but only the PCM is
+ 	 * missing...
+ 	 */
+-	if (ATARIHW_PRESENT(PCM_8BIT)) { 
++	if (ATARIHW_PRESENT(PCM_8BIT)) {
+ 		tt_dmasnd.ctrl = DMASND_CTRL_OFF;
+-		udelay(20);	/* wait a while for things to settle down */
++		udelay(20);		/* wait a while for things to settle down */
+ 	}
+ 	mono_moni = (mfp.par_dt_reg & 0x80) == 0;
+ 
+@@ -755,19 +865,24 @@ static struct pixel_clock {
+ 	unsigned long f;	/* f/[Hz] */
+ 	unsigned long t;	/* t/[ps] (=1/f) */
+ 	int right, hsync, left;	/* standard timing in clock cycles, not pixel */
+-		/* hsync initialized in falcon_detect() */
++	/* hsync initialized in falcon_detect() */
+ 	int sync_mask;		/* or-mask for hw.falcon.sync to set this clock */
+ 	int control_mask;	/* ditto, for hw.falcon.vid_control */
+-}
+-f25  = {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25},
+-f32  = {32000000, 31250, 18, 0, 42, 0x0, 0},
+-fext = {       0,     0, 18, 0, 42, 0x1, 0};
++} f25 = {
++	25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
++}, f32 = {
++	32000000, 31250, 18, 0, 42, 0x0, 0
++}, fext = {
++	0, 0, 18, 0, 42, 0x1, 0
++};
+ 
+ /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
+-static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}};
++static int vdl_prescale[4][3] = {
++	{ 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
++};
+ 
+ /* Default hsync timing [mon_type] in picoseconds */
+-static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000};
++static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
+ 
+ #ifdef FBCON_HAS_CFB16
+ static u16 fbcon_cfb16_cmap[16];
+@@ -775,12 +890,12 @@ static u16 fbcon_cfb16_cmap[16];
+ 
+ static inline int hxx_prescale(struct falcon_hw *hw)
+ {
+-	return hw->ste_mode ? 16 :
+-		   vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
++	return hw->ste_mode ? 16
++			    : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
+ }
+ 
+-static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
+-							  struct atafb_par *par )
++static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
++			     struct atafb_par *par)
+ {
+ 	strcpy(fix->id, "Atari Builtin");
+ 	fix->smem_start = (unsigned long)real_screen_base;
+@@ -796,8 +911,7 @@ static int falcon_encode_fix( struct fb_
+ 		fix->type_aux = 0;
+ 		/* no smooth scrolling with longword aligned video mem */
+ 		fix->xpanstep = 32;
+-	}
+-	else if (par->hw.falcon.f_shift & 0x100) {
++	} else if (par->hw.falcon.f_shift & 0x100) {
+ 		fix->type = FB_TYPE_PACKED_PIXELS;
+ 		fix->type_aux = 0;
+ 		/* Is this ok or should it be DIRECTCOLOR? */
+@@ -809,9 +923,8 @@ static int falcon_encode_fix( struct fb_
+ 	return 0;
+ }
+ 
+-
+-static int falcon_decode_var( struct fb_var_screeninfo *var,
+-							  struct atafb_par *par )
++static int falcon_decode_var(struct fb_var_screeninfo *var,
++			     struct atafb_par *par)
+ {
+ 	int bpp = var->bits_per_pixel;
+ 	int xres = var->xres;
+@@ -823,17 +936,19 @@ static int falcon_decode_var( struct fb_
+ 	int linelen;
+ 	int interlace = 0, doubleline = 0;
+ 	struct pixel_clock *pclock;
+-	int plen; /* width of pixel in clock cycles */
++	int plen;			/* width of pixel in clock cycles */
+ 	int xstretch;
+ 	int prescale;
+ 	int longoffset = 0;
+ 	int hfreq, vfreq;
++	int hdb_off, hde_off, base_off;
++	int gstart, gend1, gend2, align;
+ 
+ /*
+ 	Get the video params out of 'var'. If a value doesn't fit, round
+ 	it up, if it's too big, return EINVAL.
+-	Round up in the following order: bits_per_pixel, xres, yres, 
+-	xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, 
++	Round up in the following order: bits_per_pixel, xres, yres,
++	xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
+ 	horizontal timing, vertical timing.
+ 
+ 	There is a maximum of screen resolution determined by pixelclock
+@@ -843,11 +958,11 @@ static int falcon_decode_var( struct fb_
+ 	Frequency range for multisync monitors is given via command line.
+ 	For TV and SM124 both frequencies are fixed.
+ 
+-	X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0)
++	X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
+ 	Y % 16 == 0 to fit 8x16 font
+ 	Y % 8 == 0 if Y<400
+ 
+-	Currently interlace and doubleline mode in var are ignored. 
++	Currently interlace and doubleline mode in var are ignored.
+ 	On SM124 and TV only the standard resolutions can be used.
+ */
+ 
+@@ -855,43 +970,38 @@ static int falcon_decode_var( struct fb_
+ 	if (!xres || !yres || !bpp)
+ 		return -EINVAL;
+ 
+-	if (mon_type == F_MON_SM && bpp != 1) {
++	if (mon_type == F_MON_SM && bpp != 1)
+ 		return -EINVAL;
+-	}
+-	else if (bpp <= 1) {
++
++	if (bpp <= 1) {
+ 		bpp = 1;
+ 		par->hw.falcon.f_shift = 0x400;
+ 		par->hw.falcon.st_shift = 0x200;
+-	}
+-	else if (bpp <= 2) {
++	} else if (bpp <= 2) {
+ 		bpp = 2;
+ 		par->hw.falcon.f_shift = 0x000;
+ 		par->hw.falcon.st_shift = 0x100;
+-	}
+-	else if (bpp <= 4) {
++	} else if (bpp <= 4) {
+ 		bpp = 4;
+ 		par->hw.falcon.f_shift = 0x000;
+ 		par->hw.falcon.st_shift = 0x000;
+-	}
+-	else if (bpp <= 8) {
++	} else if (bpp <= 8) {
+ 		bpp = 8;
+ 		par->hw.falcon.f_shift = 0x010;
+-	}
+-	else if (bpp <= 16) {
+-		bpp = 16; /* packed pixel mode */
+-		par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
+-	}
+-	else
++	} else if (bpp <= 16) {
++		bpp = 16;		/* packed pixel mode */
++		par->hw.falcon.f_shift = 0x100;	/* hicolor, no overlay */
++	} else
+ 		return -EINVAL;
+ 	par->hw.falcon.bpp = bpp;
+ 
+ 	if (mon_type == F_MON_SM || DontCalcRes) {
+ 		/* Skip all calculations. VGA/TV/SC1224 only supported. */
+ 		struct fb_var_screeninfo *myvar = &atafb_predefined[0];
+-		
++
+ 		if (bpp > myvar->bits_per_pixel ||
+-			var->xres > myvar->xres ||
+-			var->yres > myvar->yres)
++		    var->xres > myvar->xres ||
++		    var->yres > myvar->yres)
+ 			return -EINVAL;
+ 		fbhw->get_par(par);	/* Current par will be new par */
+ 		goto set_screen_base;	/* Don't forget this */
+@@ -910,8 +1020,8 @@ static int falcon_decode_var( struct fb_
+ 		yres = 400;
+ 
+ 	/* 2 planes must use STE compatibility mode */
+-	par->hw.falcon.ste_mode = bpp==2;
+-	par->hw.falcon.mono = bpp==1;
++	par->hw.falcon.ste_mode = bpp == 2;
++	par->hw.falcon.mono = bpp == 1;
+ 
+ 	/* Total and visible scanline length must be a multiple of one longword,
+ 	 * this and the console fontwidth yields the alignment for xres and
+@@ -967,8 +1077,7 @@ static int falcon_decode_var( struct fb_
+ 		left_margin = hsync_len = 128 / plen;
+ 		right_margin = 0;
+ 		/* TODO set all margins */
+-	}
+-	else
++	} else
+ #endif
+ 	if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
+ 		plen = 2 * xstretch;
+@@ -1002,26 +1111,24 @@ static int falcon_decode_var( struct fb_
+ 				vsync_len *= 2;
+ 			}
+ 		}
+-	}
+-	else
+-	{	/* F_MON_VGA */
++	} else {			/* F_MON_VGA */
+ 		if (bpp == 16)
+-			xstretch = 2; /* Double pixel width only for hicolor */
++			xstretch = 2;	/* Double pixel width only for hicolor */
+ 		/* Default values are used for vert./hor. timing if no pixelclock given. */
+ 		if (var->pixclock == 0) {
+ 			int linesize;
+ 
+ 			/* Choose master pixelclock depending on hor. timing */
+ 			plen = 1 * xstretch;
+-			if ((plen * xres + f25.right+f25.hsync+f25.left) *
++			if ((plen * xres + f25.right + f25.hsync + f25.left) *
+ 			    fb_info.monspecs.hfmin < f25.f)
+ 				pclock = &f25;
+-			else if ((plen * xres + f32.right+f32.hsync+f32.left) * 
+-			    fb_info.monspecs.hfmin < f32.f)
++			else if ((plen * xres + f32.right + f32.hsync +
++				  f32.left) * fb_info.monspecs.hfmin < f32.f)
+ 				pclock = &f32;
+-			else if ((plen * xres + fext.right+fext.hsync+fext.left) * 
+-			    fb_info.monspecs.hfmin < fext.f
+-			         && fext.f)
++			else if ((plen * xres + fext.right + fext.hsync +
++				  fext.left) * fb_info.monspecs.hfmin < fext.f &&
++			         fext.f)
+ 				pclock = &fext;
+ 			else
+ 				return -EINVAL;
+@@ -1033,22 +1140,24 @@ static int falcon_decode_var( struct fb_
+ 			upper_margin = 31;
+ 			lower_margin = 11;
+ 			vsync_len = 3;
+-		}
+-		else {
++		} else {
+ 			/* Choose largest pixelclock <= wanted clock */
+ 			int i;
+ 			unsigned long pcl = ULONG_MAX;
+ 			pclock = 0;
+-			for (i=1; i <= 4; i *= 2) {
+-				if (f25.t*i >= var->pixclock && f25.t*i < pcl) {
++			for (i = 1; i <= 4; i *= 2) {
++				if (f25.t * i >= var->pixclock &&
++				    f25.t * i < pcl) {
+ 					pcl = f25.t * i;
+ 					pclock = &f25;
+ 				}
+-				if (f32.t*i >= var->pixclock && f32.t*i < pcl) {
++				if (f32.t * i >= var->pixclock &&
++				    f32.t * i < pcl) {
+ 					pcl = f32.t * i;
+ 					pclock = &f32;
+ 				}
+-				if (fext.t && fext.t*i >= var->pixclock && fext.t*i < pcl) {
++				if (fext.t && fext.t * i >= var->pixclock &&
++				    fext.t * i < pcl) {
+ 					pcl = fext.t * i;
+ 					pclock = &fext;
+ 				}
+@@ -1070,8 +1179,7 @@ static int falcon_decode_var( struct fb_
+ 				upper_margin = (upper_margin + 1) / 2;
+ 				lower_margin = (lower_margin + 1) / 2;
+ 				vsync_len = (vsync_len + 1) / 2;
+-			}
+-			else if (var->vmode & FB_VMODE_DOUBLE) {
++			} else if (var->vmode & FB_VMODE_DOUBLE) {
+ 				/* External unit is [double lines per frame] */
+ 				upper_margin *= 2;
+ 				lower_margin *= 2;
+@@ -1079,7 +1187,7 @@ static int falcon_decode_var( struct fb_
+ 			}
+ 		}
+ 		if (pclock == &fext)
+-			longoffset = 1; /* VIDEL doesn't synchronize on short offset */
++			longoffset = 1;	/* VIDEL doesn't synchronize on short offset */
+ 	}
+ 	/* Is video bus bandwidth (32MB/s) too low for this resolution? */
+ 	/* this is definitely wrong if bus clock != 32MHz */
+@@ -1098,7 +1206,7 @@ static int falcon_decode_var( struct fb_
+ 	 * between interlace and non-interlace without messing around
+ 	 * with these.
+ 	 */
+-  again:
++again:
+ 	/* Set base_offset 128 and video bus width */
+ 	par->hw.falcon.vid_control = mon_type | f030_bus_width;
+ 	if (!longoffset)
+@@ -1112,37 +1220,34 @@ static int falcon_decode_var( struct fb_
+ 	/* External or internal clock */
+ 	par->hw.falcon.sync = pclock->sync_mask | 0x2;
+ 	/* Pixellength and prescale */
+-	par->hw.falcon.vid_mode = (2/plen) << 2;
++	par->hw.falcon.vid_mode = (2 / plen) << 2;
+ 	if (doubleline)
+ 		par->hw.falcon.vid_mode |= VMO_DOUBLE;
+ 	if (interlace)
+ 		par->hw.falcon.vid_mode |= VMO_INTER;
+ 
+ 	/*********************
+-	Horizontal timing: unit = [master clock cycles]
+-	unit of hxx-registers: [master clock cycles * prescale]
+-	Hxx-registers are 9 bit wide
+-
+-	1 line = ((hht + 2) * 2 * prescale) clock cycles
+-
+-	graphic output = hdb & 0x200 ?
+-	       ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff:
+-	       ( hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
+-	(this must be a multiple of plen*128/bpp, on VGA pixels
+-	 to the right may be cut off with a bigger right margin)
+-
+-	start of graphics relative to start of 1st halfline = hdb & 0x200 ?
+-	       (hdb - hht - 2) * prescale + hdboff :
+-	       hdb * prescale + hdboff
+-
+-	end of graphics relative to start of 1st halfline =
+-	       (hde + hht + 2) * prescale + hdeoff
+-	*********************/
++	 * Horizontal timing: unit = [master clock cycles]
++	 * unit of hxx-registers: [master clock cycles * prescale]
++	 * Hxx-registers are 9 bit wide
++	 *
++	 * 1 line = ((hht + 2) * 2 * prescale) clock cycles
++	 *
++	 * graphic output = hdb & 0x200 ?
++	 *        ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
++	 *        (hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
++	 * (this must be a multiple of plen*128/bpp, on VGA pixels
++	 *  to the right may be cut off with a bigger right margin)
++	 *
++	 * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
++	 *        (hdb - hht - 2) * prescale + hdboff :
++	 *        hdb * prescale + hdboff
++	 *
++	 * end of graphics relative to start of 1st halfline =
++	 *        (hde + hht + 2) * prescale + hdeoff
++	 *********************/
+ 	/* Calculate VIDEL registers */
+-	{
+-	int hdb_off, hde_off, base_off;
+-	int gstart, gend1, gend2, align;
+-
++{
+ 	prescale = hxx_prescale(&par->hw.falcon);
+ 	base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
+ 
+@@ -1154,8 +1259,7 @@ static int falcon_decode_var( struct fb_
+ 		align = 1;
+ 		hde_off = 0;
+ 		hdb_off = (base_off + 16 * plen) + prescale;
+-	}
+-	else {
++	} else {
+ 		align = 128 / bpp;
+ 		hde_off = ((128 / bpp + 2) * plen);
+ 		if (par->hw.falcon.ste_mode)
+@@ -1164,23 +1268,24 @@ static int falcon_decode_var( struct fb_
+ 			hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
+ 	}
+ 
+-	gstart = (prescale/2 + plen * left_margin) / prescale;
++	gstart = (prescale / 2 + plen * left_margin) / prescale;
+ 	/* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
+-	gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale;
++	gend1 = gstart + ((xres + align - 1) / align) * align * plen / prescale;
+ 	/* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
+ 	gend2 = gstart + xres * plen / prescale;
+ 	par->HHT = plen * (left_margin + xres + right_margin) /
+ 			   (2 * prescale) - 2;
+ /*	par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
+ 
+-	par->HDB = gstart - hdb_off/prescale;
++	par->HDB = gstart - hdb_off / prescale;
+ 	par->HBE = gstart;
+-	if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200;
+-	par->HDE = gend1 - par->HHT - 2 - hde_off/prescale;
++	if (par->HDB < 0)
++		par->HDB += par->HHT + 2 + 0x200;
++	par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
+ 	par->HBB = gend2 - par->HHT - 2;
+ #if 0
+ 	/* One more Videl constraint: data fetch of two lines must not overlap */
+-	if ((par->HDB & 0x200)  &&  (par->HDB & ~0x200) - par->HDE <= 5) {
++	if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
+ 		/* if this happens increase margins, decrease hfreq. */
+ 	}
+ #endif
+@@ -1189,11 +1294,11 @@ static int falcon_decode_var( struct fb_
+ 	par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
+ 	if (par->HSS < par->HBB)
+ 		par->HSS = par->HBB;
+-	}
++}
+ 
+ 	/*  check hor. frequency */
+-	hfreq = pclock->f / ((par->HHT+2)*prescale*2);
+-	if (hfreq > fb_info.monspecs.hfmax && mon_type!=F_MON_VGA) {
++	hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
++	if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
+ 		/* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
+ 		/* Too high -> enlarge margin */
+ 		left_margin += 1;
+@@ -1213,12 +1318,14 @@ static int falcon_decode_var( struct fb_
+ 	par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
+ 	par->VDB = par->VBE;
+ 	par->VDE = yres;
+-	if (!interlace) par->VDE <<= 1;
+-	if (doubleline) par->VDE <<= 1;  /* VDE now half lines per (half-)frame */
++	if (!interlace)
++		par->VDE <<= 1;
++	if (doubleline)
++		par->VDE <<= 1;		/* VDE now half lines per (half-)frame */
+ 	par->VDE += par->VDB;
+ 	par->VBB = par->VDE;
+ 	par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
+-	par->VSS = par->VFT+1 - (vsync_len * 2 - 1);
++	par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
+ 	/* vbb,vss,vft must be even in interlace mode */
+ 	if (interlace) {
+ 		par->VBB++;
+@@ -1229,55 +1336,53 @@ static int falcon_decode_var( struct fb_
+ 	/* V-frequency check, hope I didn't create any loop here. */
+ 	/* Interlace and doubleline are mutually exclusive. */
+ 	vfreq = (hfreq * 2) / (par->VFT + 1);
+-	if      (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
++	if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
+ 		/* Too high -> try again with doubleline */
+ 		doubleline = 1;
+ 		goto again;
+-	}
+-	else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
++	} else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
+ 		/* Too low -> try again with interlace */
+ 		interlace = 1;
+ 		goto again;
+-	}
+-	else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
++	} else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
+ 		/* Doubleline too low -> clear doubleline and enlarge margins */
+ 		int lines;
+ 		doubleline = 0;
+-		for (lines=0;
+-		     (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax;
++		for (lines = 0;
++		     (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
++		     fb_info.monspecs.vfmax;
+ 		     lines++)
+ 			;
+ 		upper_margin += lines;
+ 		lower_margin += lines;
+ 		goto again;
+-	}
+-	else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
++	} else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
+ 		/* Doubleline too high -> enlarge margins */
+ 		int lines;
+-		for (lines=0;
+-		     (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
+-		     lines+=2)
++		for (lines = 0;
++		     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
++		     fb_info.monspecs.vfmax;
++		     lines += 2)
+ 			;
+ 		upper_margin += lines;
+ 		lower_margin += lines;
+ 		goto again;
+-	}
+-	else if (vfreq > fb_info.monspecs.vfmax && interlace) {
++	} else if (vfreq > fb_info.monspecs.vfmax && interlace) {
+ 		/* Interlace, too high -> enlarge margins */
+ 		int lines;
+-		for (lines=0;
+-		     (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
++		for (lines = 0;
++		     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
++		     fb_info.monspecs.vfmax;
+ 		     lines++)
+ 			;
+ 		upper_margin += lines;
+ 		lower_margin += lines;
+ 		goto again;
+-	}
+-	else if (vfreq < fb_info.monspecs.vfmin ||
+-		 vfreq > fb_info.monspecs.vfmax)
++	} else if (vfreq < fb_info.monspecs.vfmin ||
++		   vfreq > fb_info.monspecs.vfmax)
+ 		return -EINVAL;
+ 
+-  set_screen_base:
++set_screen_base:
+ 	linelen = xres_virtual * bpp / 8;
+ 	if (yres_virtual * linelen > screen_len && screen_len)
+ 		return -EINVAL;
+@@ -1289,11 +1394,20 @@ static int falcon_decode_var( struct fb_
+ 	par->screen_base = screen_base + var->yoffset * linelen;
+ 	par->hw.falcon.xoffset = 0;
+ 
++	// FIXME!!! sort of works, no crash
++	//par->next_line = linelen;
++	//par->next_plane = yres_virtual * linelen;
++	par->next_line = linelen;
++	par->next_plane = 2;
++	// crashes
++	//par->next_plane = linelen;
++	//par->next_line  = yres_virtual * linelen;
++
+ 	return 0;
+ }
+ 
+-static int falcon_encode_var( struct fb_var_screeninfo *var,
+-							  struct atafb_par *par )
++static int falcon_encode_var(struct fb_var_screeninfo *var,
++			     struct atafb_par *par)
+ {
+ /* !!! only for VGA !!! */
+ 	int linelen;
+@@ -1306,10 +1420,10 @@ static int falcon_encode_var( struct fb_
+ 	var->pixclock = hw->sync & 0x1 ? fext.t :
+ 	                hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
+ 
+-	var->height=-1;
+-	var->width=-1;
++	var->height = -1;
++	var->width = -1;
+ 
+-	var->sync=0;
++	var->sync = 0;
+ 	if (hw->vid_control & VCO_HSYPOS)
+ 		var->sync |= FB_SYNC_HOR_HIGH_ACT;
+ 	if (hw->vid_control & VCO_VSYPOS)
+@@ -1320,7 +1434,7 @@ static int falcon_encode_var( struct fb_
+ 		var->vmode |= FB_VMODE_INTERLACED;
+ 	if (hw->vid_mode & VMO_DOUBLE)
+ 		var->vmode |= FB_VMODE_DOUBLE;
+-	
++
+ 	/* visible y resolution:
+ 	 * Graphics display starts at line VDB and ends at line
+ 	 * VDE. If interlace mode off unit of VC-registers is
+@@ -1332,14 +1446,15 @@ static int falcon_encode_var( struct fb_
+ 	if (var->vmode & FB_VMODE_DOUBLE)
+ 		var->yres >>= 1;
+ 
+-	/* to get bpp, we must examine f_shift and st_shift.
++	/*
++	 * to get bpp, we must examine f_shift and st_shift.
+ 	 * f_shift is valid if any of bits no. 10, 8 or 4
+ 	 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
+ 	 * if bit 10 set then bit 8 and bit 4 don't care...
+ 	 * If all these bits are 0 get display depth from st_shift
+ 	 * (as for ST and STE)
+ 	 */
+-	if (hw->f_shift & 0x400)		/* 2 colors */
++	if (hw->f_shift & 0x400)	/* 2 colors */
+ 		var->bits_per_pixel = 1;
+ 	else if (hw->f_shift & 0x100)	/* hicolor */
+ 		var->bits_per_pixel = 16;
+@@ -1349,7 +1464,7 @@ static int falcon_encode_var( struct fb_
+ 		var->bits_per_pixel = 4;
+ 	else if (hw->st_shift == 0x100)
+ 		var->bits_per_pixel = 2;
+-	else /* if (hw->st_shift == 0x200) */
++	else				/* if (hw->st_shift == 0x200) */
+ 		var->bits_per_pixel = 1;
+ 
+ 	var->xres = hw->line_width * 16 / var->bits_per_pixel;
+@@ -1358,42 +1473,42 @@ static int falcon_encode_var( struct fb_
+ 		var->xres_virtual += 16;
+ 
+ 	if (var->bits_per_pixel == 16) {
+-		var->red.offset=11;
+-		var->red.length=5;
+-		var->red.msb_right=0;
+-		var->green.offset=5;
+-		var->green.length=6;
+-		var->green.msb_right=0;
+-		var->blue.offset=0;
+-		var->blue.length=5;
+-		var->blue.msb_right=0;
+-	}
+-	else {
+-		var->red.offset=0;
++		var->red.offset = 11;
++		var->red.length = 5;
++		var->red.msb_right = 0;
++		var->green.offset = 5;
++		var->green.length = 6;
++		var->green.msb_right = 0;
++		var->blue.offset = 0;
++		var->blue.length = 5;
++		var->blue.msb_right = 0;
++	} else {
++		var->red.offset = 0;
+ 		var->red.length = hw->ste_mode ? 4 : 6;
+-		var->red.msb_right=0;
+-		var->grayscale=0;
+-		var->blue=var->green=var->red;
+-	}
+-	var->transp.offset=0;
+-	var->transp.length=0;
+-	var->transp.msb_right=0;
++		if (var->red.length > var->bits_per_pixel)
++			var->red.length = var->bits_per_pixel;
++		var->red.msb_right = 0;
++		var->grayscale = 0;
++		var->blue = var->green = var->red;
++	}
++	var->transp.offset = 0;
++	var->transp.length = 0;
++	var->transp.msb_right = 0;
+ 
+ 	linelen = var->xres_virtual * var->bits_per_pixel / 8;
+ 	if (screen_len) {
+ 		if (par->yres_virtual)
+ 			var->yres_virtual = par->yres_virtual;
+ 		else
+-			/* yres_virtual==0 means use maximum */
++			/* yres_virtual == 0 means use maximum */
+ 			var->yres_virtual = screen_len / linelen;
+-	}
+-	else {
++	} else {
+ 		if (hwscroll < 0)
+ 			var->yres_virtual = 2 * var->yres;
+ 		else
+-			var->yres_virtual=var->yres+hwscroll * 16;
++			var->yres_virtual = var->yres + hwscroll * 16;
+ 	}
+-	var->xoffset=0; /* TODO change this */
++	var->xoffset = 0;		/* TODO change this */
+ 
+ 	/* hdX-offsets */
+ 	prescale = hxx_prescale(hw);
+@@ -1402,8 +1517,7 @@ static int falcon_encode_var( struct fb_
+ 	if (hw->f_shift & 0x100) {
+ 		hde_off = 0;
+ 		hdb_off = (base_off + 16 * plen) + prescale;
+-	}
+-	else {
++	} else {
+ 		hde_off = ((128 / var->bits_per_pixel + 2) * plen);
+ 		if (hw->ste_mode)
+ 			hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
+@@ -1415,8 +1529,8 @@ static int falcon_encode_var( struct fb_
+ 
+ 	/* Right margin includes hsync */
+ 	var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
+-					   (hw->hdb & 0x200 ? 2+hw->hht : 0));
+-	if (hw->ste_mode || mon_type!=F_MON_VGA)
++					   (hw->hdb & 0x200 ? 2 + hw->hht : 0));
++	if (hw->ste_mode || mon_type != F_MON_VGA)
+ 		var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
+ 	else
+ 		/* can't use this in ste_mode, because hbb is +1 off */
+@@ -1424,15 +1538,14 @@ static int falcon_encode_var( struct fb_
+ 	var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
+ 
+ 	/* Lower margin includes vsync */
+-	var->upper_margin = hw->vdb / 2 ;  /* round down to full lines */
+-	var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */
+-	var->vsync_len    = (hw->vft+1 - hw->vss + 1) / 2; /* round up */
++	var->upper_margin = hw->vdb / 2;	/* round down to full lines */
++	var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2;	/* round up */
++	var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2;	/* round up */
+ 	if (var->vmode & FB_VMODE_INTERLACED) {
+ 		var->upper_margin *= 2;
+ 		var->lower_margin *= 2;
+ 		var->vsync_len *= 2;
+-	}
+-	else if (var->vmode & FB_VMODE_DOUBLE) {
++	} else if (var->vmode & FB_VMODE_DOUBLE) {
+ 		var->upper_margin = (var->upper_margin + 1) / 2;
+ 		var->lower_margin = (var->lower_margin + 1) / 2;
+ 		var->vsync_len = (var->vsync_len + 1) / 2;
+@@ -1447,20 +1560,19 @@ static int falcon_encode_var( struct fb_
+ 	var->lower_margin -= var->vsync_len;
+ 
+ 	if (screen_base)
+-		var->yoffset=(par->screen_base - screen_base)/linelen;
++		var->yoffset = (par->screen_base - screen_base) / linelen;
+ 	else
+-		var->yoffset=0;
+-	var->nonstd=0;	/* what is this for? */
+-	var->activate=0;
++		var->yoffset = 0;
++	var->nonstd = 0;		/* what is this for? */
++	var->activate = 0;
+ 	return 0;
+ }
+ 
+-
+-static int f_change_mode = 0;
++static int f_change_mode;
+ static struct falcon_hw f_new_mode;
+-static int f_pan_display = 0;
++static int f_pan_display;
+ 
+-static void falcon_get_par( struct atafb_par *par )
++static void falcon_get_par(struct atafb_par *par)
+ {
+ 	unsigned long addr;
+ 	struct falcon_hw *hw = &par->hw.falcon;
+@@ -1492,12 +1604,12 @@ static void falcon_get_par( struct atafb
+ 	par->screen_base = phys_to_virt(addr);
+ 
+ 	/* derived parameters */
+-	hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100;
++	hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
+ 	hw->mono = (hw->f_shift & 0x400) ||
+-	           ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200);
++	           ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
+ }
+ 
+-static void falcon_set_par( struct atafb_par *par )
++static void falcon_set_par(struct atafb_par *par)
+ {
+ 	f_change_mode = 0;
+ 
+@@ -1519,8 +1631,7 @@ static void falcon_set_par( struct atafb
+ 	f_change_mode = 1;
+ }
+ 
+-
+-static irqreturn_t falcon_vbl_switcher( int irq, void *dummy )
++static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
+ {
+ 	struct falcon_hw *hw = &f_new_mode;
+ 
+@@ -1529,11 +1640,10 @@ static irqreturn_t falcon_vbl_switcher( 
+ 
+ 		if (hw->sync & 0x1) {
+ 			/* Enable external pixelclock. This code only for ScreenWonder */
+-			*(volatile unsigned short*)0xffff9202 = 0xffbf;
+-		}
+-		else {
++			*(volatile unsigned short *)0xffff9202 = 0xffbf;
++		} else {
+ 			/* Turn off external clocks. Read sets all output bits to 1. */
+-			*(volatile unsigned short*)0xffff9202;
++			*(volatile unsigned short *)0xffff9202;
+ 		}
+ 		shifter.syncmode = hw->sync;
+ 
+@@ -1550,15 +1660,14 @@ static irqreturn_t falcon_vbl_switcher( 
+ 		videl.vde = hw->vde;
+ 		videl.vss = hw->vss;
+ 
+-		videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
++		videl.f_shift = 0;	/* write enables Falcon palette, 0: 4 planes */
+ 		if (hw->ste_mode) {
+-			videl.st_shift = hw->st_shift; /* write enables STE palette */
+-		}
+-		else {
++			videl.st_shift = hw->st_shift;	/* write enables STE palette */
++		} else {
+ 			/* IMPORTANT:
+-			 * set st_shift 0, so we can tell the screen-depth if f_shift==0.
++			 * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
+ 			 * Writing 0 to f_shift enables 4 plane Falcon mode but
+-			 * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible
++			 * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
+ 			 * with Falcon palette.
+ 			 */
+ 			videl.st_shift = 0;
+@@ -1580,12 +1689,13 @@ static irqreturn_t falcon_vbl_switcher( 
+ 	return IRQ_HANDLED;
+ }
+ 
+-
+-static int falcon_pan_display( struct fb_var_screeninfo *var,
+-							   struct atafb_par *par )
++static int falcon_pan_display(struct fb_var_screeninfo *var,
++			      struct fb_info *info)
+ {
++	struct atafb_par *par = (struct atafb_par *)info->par;
++
+ 	int xoffset;
+-	int bpp = fb_display[fb_info.currcon].var.bits_per_pixel;
++	int bpp = info->var.bits_per_pixel;
+ 
+ 	if (bpp == 1)
+ 		var->xoffset = up(var->xoffset, 32);
+@@ -1596,45 +1706,24 @@ static int falcon_pan_display( struct fb
+ 		var->xoffset = up(var->xoffset, 2);
+ 	}
+ 	par->hw.falcon.line_offset = bpp *
+-	       	(fb_display[fb_info.currcon].var.xres_virtual - fb_display[fb_info.currcon].var.xres) / 16;
++		(info->var.xres_virtual - info->var.xres) / 16;
+ 	if (par->hw.falcon.xoffset)
+ 		par->hw.falcon.line_offset -= bpp;
+ 	xoffset = var->xoffset - par->hw.falcon.xoffset;
+ 
+ 	par->screen_base = screen_base +
+-	        (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + xoffset) * bpp / 8;
++	        (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
+ 	if (fbhw->set_screen_base)
+-		fbhw->set_screen_base (par->screen_base);
++		fbhw->set_screen_base(par->screen_base);
+ 	else
+-		return -EINVAL; /* shouldn't happen */
++		return -EINVAL;		/* shouldn't happen */
+ 	f_pan_display = 1;
+ 	return 0;
+ }
+ 
+-
+-static int falcon_getcolreg( unsigned regno, unsigned *red,
+-				 unsigned *green, unsigned *blue,
+-				 unsigned *transp, struct fb_info *info )
+-{	unsigned long col;
+-	
+-	if (regno > 255)
+-		return 1;
+-	/* This works in STE-mode (with 4bit/color) since f030_col-registers
+-	 * hold up to 6bit/color.
+-	 * Even with hicolor r/g/b=5/6/5 bit!
+-	 */
+-	col = f030_col[regno];
+-	*red = (col >> 16) & 0xff00;
+-	*green = (col >> 8) & 0xff00;
+-	*blue = (col << 8) & 0xff00;
+-	*transp = 0;
+-	return 0;
+-}
+-
+-
+-static int falcon_setcolreg( unsigned regno, unsigned red,
+-							 unsigned green, unsigned blue,
+-							 unsigned transp, struct fb_info *info )
++static int falcon_setcolreg(unsigned int regno, unsigned int red,
++			    unsigned int green, unsigned int blue,
++			    unsigned int transp, struct fb_info *info)
+ {
+ 	if (regno > 255)
+ 		return 1;
+@@ -1655,13 +1744,12 @@ static int falcon_setcolreg( unsigned re
+ 	return 0;
+ }
+ 
+-
+-static int falcon_blank( int blank_mode )
++static int falcon_blank(int blank_mode)
+ {
+-/* ++guenther: we can switch off graphics by changing VDB and VDE,
+- * so VIDEL doesn't hog the bus while saving.
+- * (this may affect usleep()).
+- */
++	/* ++guenther: we can switch off graphics by changing VDB and VDE,
++	 * so VIDEL doesn't hog the bus while saving.
++	 * (this may affect usleep()).
++	 */
+ 	int vdb, vss, hbe, hss;
+ 
+ 	if (mon_type == F_MON_SM)	/* this doesn't work on SM124 */
+@@ -1694,14 +1782,13 @@ static int falcon_blank( int blank_mode 
+ 	return 0;
+ }
+ 
+- 
+-static int falcon_detect( void )
++static int falcon_detect(void)
+ {
+ 	struct atafb_par par;
+ 	unsigned char fhw;
+ 
+ 	/* Determine connected monitor and set monitor parameters */
+-	fhw = *(unsigned char*)0xffff8006;
++	fhw = *(unsigned char *)0xffff8006;
+ 	mon_type = fhw >> 6 & 0x3;
+ 	/* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
+ 	f030_bus_width = fhw << 6 & 0x80;
+@@ -1715,7 +1802,7 @@ static int falcon_detect( void )
+ 	case F_MON_SC:
+ 	case F_MON_TV:
+ 		/* PAL...NTSC */
+-		fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
++		fb_info.monspecs.vfmin = 49;	/* not 50, since TOS defaults to 49.9x Hz */
+ 		fb_info.monspecs.vfmax = 60;
+ 		fb_info.monspecs.hfmin = 15620;
+ 		fb_info.monspecs.hfmax = 15755;
+@@ -1740,13 +1827,12 @@ static int falcon_detect( void )
+ 
+ #ifdef ATAFB_STE
+ 
+-static int stste_encode_fix( struct fb_fix_screeninfo *fix,
+-							 struct atafb_par *par )
+-
++static int stste_encode_fix(struct fb_fix_screeninfo *fix,
++			    struct atafb_par *par)
+ {
+ 	int mode;
+ 
+-	strcpy(fix->id,"Atari Builtin");
++	strcpy(fix->id, "Atari Builtin");
+ 	fix->smem_start = (unsigned long)real_screen_base;
+ 	fix->smem_len = screen_len;
+ 	fix->type = FB_TYPE_INTERLEAVED_PLANES;
+@@ -1771,43 +1857,40 @@ static int stste_encode_fix( struct fb_f
+ 	return 0;
+ }
+ 
+-
+-static int stste_decode_var( struct fb_var_screeninfo *var,
+-						  struct atafb_par *par )
++static int stste_decode_var(struct fb_var_screeninfo *var,
++			    struct atafb_par *par)
+ {
+-	int xres=var->xres;
+-	int yres=var->yres;
+-	int bpp=var->bits_per_pixel;
++	int xres = var->xres;
++	int yres = var->yres;
++	int bpp = var->bits_per_pixel;
+ 	int linelen;
+ 	int yres_virtual = var->yres_virtual;
+ 
+ 	if (mono_moni) {
+ 		if (bpp > 1 || xres > sttt_xres || yres > st_yres)
+ 			return -EINVAL;
+-		par->hw.st.mode=ST_HIGH;
+-		xres=sttt_xres;
+-		yres=st_yres;
+-		bpp=1;
++		par->hw.st.mode = ST_HIGH;
++		xres = sttt_xres;
++		yres = st_yres;
++		bpp = 1;
+ 	} else {
+ 		if (bpp > 4 || xres > sttt_xres || yres > st_yres)
+ 			return -EINVAL;
+ 		if (bpp > 2) {
+-			if (xres > sttt_xres/2 || yres > st_yres/2)
++			if (xres > sttt_xres / 2 || yres > st_yres / 2)
+ 				return -EINVAL;
+-			par->hw.st.mode=ST_LOW;
+-			xres=sttt_xres/2;
+-			yres=st_yres/2;
+-			bpp=4;
+-		}
+-		else if (bpp > 1) {
+-			if (xres > sttt_xres || yres > st_yres/2)
++			par->hw.st.mode = ST_LOW;
++			xres = sttt_xres / 2;
++			yres = st_yres / 2;
++			bpp = 4;
++		} else if (bpp > 1) {
++			if (xres > sttt_xres || yres > st_yres / 2)
+ 				return -EINVAL;
+-			par->hw.st.mode=ST_MID;
+-			xres=sttt_xres;
+-			yres=st_yres/2;
+-			bpp=2;
+-		}
+-		else
++			par->hw.st.mode = ST_MID;
++			xres = sttt_xres;
++			yres = st_yres / 2;
++			bpp = 2;
++		} else
+ 			return -EINVAL;
+ 	}
+ 	if (yres_virtual <= 0)
+@@ -1815,10 +1898,10 @@ static int stste_decode_var( struct fb_v
+ 	else if (yres_virtual < yres)
+ 		yres_virtual = yres;
+ 	if (var->sync & FB_SYNC_EXT)
+-		par->hw.st.sync=(par->hw.st.sync & ~1) | 1;
++		par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
+ 	else
+-		par->hw.st.sync=(par->hw.st.sync & ~1);
+-	linelen=xres*bpp/8;
++		par->hw.st.sync = (par->hw.st.sync & ~1);
++	linelen = xres * bpp / 8;
+ 	if (yres_virtual * linelen > screen_len && screen_len)
+ 		return -EINVAL;
+ 	if (yres * linelen > screen_len && screen_len)
+@@ -1826,93 +1909,91 @@ static int stste_decode_var( struct fb_v
+ 	if (var->yoffset + yres > yres_virtual && yres_virtual)
+ 		return -EINVAL;
+ 	par->yres_virtual = yres_virtual;
+-	par->screen_base=screen_base+ var->yoffset*linelen;
++	par->screen_base = screen_base + var->yoffset * linelen;
+ 	return 0;
+ }
+ 
+-static int stste_encode_var( struct fb_var_screeninfo *var,
+-						  struct atafb_par *par )
++static int stste_encode_var(struct fb_var_screeninfo *var,
++			    struct atafb_par *par)
+ {
+ 	int linelen;
+ 	memset(var, 0, sizeof(struct fb_var_screeninfo));
+-	var->red.offset=0;
++	var->red.offset = 0;
+ 	var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
+-	var->red.msb_right=0;
+-	var->grayscale=0;
++	var->red.msb_right = 0;
++	var->grayscale = 0;
+ 
+-	var->pixclock=31041;
+-	var->left_margin=120;		/* these are incorrect */
+-	var->right_margin=100;
+-	var->upper_margin=8;
+-	var->lower_margin=16;
+-	var->hsync_len=140;
+-	var->vsync_len=30;
++	var->pixclock = 31041;
++	var->left_margin = 120;		/* these are incorrect */
++	var->right_margin = 100;
++	var->upper_margin = 8;
++	var->lower_margin = 16;
++	var->hsync_len = 140;
++	var->vsync_len = 30;
+ 
+-	var->height=-1;
+-	var->width=-1;
++	var->height = -1;
++	var->width = -1;
+ 
+ 	if (!(par->hw.st.sync & 1))
+-		var->sync=0;
++		var->sync = 0;
+ 	else
+-		var->sync=FB_SYNC_EXT;
++		var->sync = FB_SYNC_EXT;
+ 
+ 	switch (par->hw.st.mode & 3) {
+ 	case ST_LOW:
+-		var->xres=sttt_xres/2;
+-		var->yres=st_yres/2;
+-		var->bits_per_pixel=4;
++		var->xres = sttt_xres / 2;
++		var->yres = st_yres / 2;
++		var->bits_per_pixel = 4;
+ 		break;
+ 	case ST_MID:
+-		var->xres=sttt_xres;
+-		var->yres=st_yres/2;
+-		var->bits_per_pixel=2;
++		var->xres = sttt_xres;
++		var->yres = st_yres / 2;
++		var->bits_per_pixel = 2;
+ 		break;
+ 	case ST_HIGH:
+-		var->xres=sttt_xres;
+-		var->yres=st_yres;
+-		var->bits_per_pixel=1;
++		var->xres = sttt_xres;
++		var->yres = st_yres;
++		var->bits_per_pixel = 1;
+ 		break;
+-	}		
+-	var->blue=var->green=var->red;
+-	var->transp.offset=0;
+-	var->transp.length=0;
+-	var->transp.msb_right=0;
+-	var->xres_virtual=sttt_xres_virtual;
+-	linelen=var->xres_virtual * var->bits_per_pixel / 8;
+-	ovsc_addlen=linelen*(sttt_yres_virtual - st_yres);
+-	
+-	if (! use_hwscroll)
+-		var->yres_virtual=var->yres;
++	}
++	var->blue = var->green = var->red;
++	var->transp.offset = 0;
++	var->transp.length = 0;
++	var->transp.msb_right = 0;
++	var->xres_virtual = sttt_xres_virtual;
++	linelen = var->xres_virtual * var->bits_per_pixel / 8;
++	ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
++
++	if (!use_hwscroll)
++		var->yres_virtual = var->yres;
+ 	else if (screen_len) {
+ 		if (par->yres_virtual)
+ 			var->yres_virtual = par->yres_virtual;
+ 		else
+-			/* yres_virtual==0 means use maximum */
++			/* yres_virtual == 0 means use maximum */
+ 			var->yres_virtual = screen_len / linelen;
+-	}
+-	else {
++	} else {
+ 		if (hwscroll < 0)
+ 			var->yres_virtual = 2 * var->yres;
+ 		else
+-			var->yres_virtual=var->yres+hwscroll * 16;
++			var->yres_virtual = var->yres + hwscroll * 16;
+ 	}
+-	var->xoffset=0;
++	var->xoffset = 0;
+ 	if (screen_base)
+-		var->yoffset=(par->screen_base - screen_base)/linelen;
++		var->yoffset = (par->screen_base - screen_base) / linelen;
+ 	else
+-		var->yoffset=0;
+-	var->nonstd=0;
+-	var->activate=0;
+-	var->vmode=FB_VMODE_NONINTERLACED;
++		var->yoffset = 0;
++	var->nonstd = 0;
++	var->activate = 0;
++	var->vmode = FB_VMODE_NONINTERLACED;
+ 	return 0;
+ }
+ 
+-
+-static void stste_get_par( struct atafb_par *par )
++static void stste_get_par(struct atafb_par *par)
+ {
+ 	unsigned long addr;
+-	par->hw.st.mode=shifter_tt.st_shiftmode;
+-	par->hw.st.sync=shifter.syncmode;
++	par->hw.st.mode = shifter_tt.st_shiftmode;
++	par->hw.st.sync = shifter.syncmode;
+ 	addr = ((shifter.bas_hi & 0xff) << 16) |
+ 	       ((shifter.bas_md & 0xff) << 8);
+ 	if (ATARIHW_PRESENT(EXTD_SHIFTER))
+@@ -1920,55 +2001,18 @@ static void stste_get_par( struct atafb_
+ 	par->screen_base = phys_to_virt(addr);
+ }
+ 
+-static void stste_set_par( struct atafb_par *par )
++static void stste_set_par(struct atafb_par *par)
+ {
+-	shifter_tt.st_shiftmode=par->hw.st.mode;
+-	shifter.syncmode=par->hw.st.sync;
++	shifter_tt.st_shiftmode = par->hw.st.mode;
++	shifter.syncmode = par->hw.st.sync;
+ 	/* only set screen_base if really necessary */
+ 	if (current_par.screen_base != par->screen_base)
+ 		fbhw->set_screen_base(par->screen_base);
+ }
+ 
+-
+-static int stste_getcolreg(unsigned regno, unsigned *red,
+-			   unsigned *green, unsigned *blue,
+-			   unsigned *transp, struct fb_info *info)
+-{
+-	unsigned col, t;
+-	
+-	if (regno > 15)
+-		return 1;
+-	col = shifter_tt.color_reg[regno];
+-	if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
+-		t = ((col >> 7) & 0xe) | ((col >> 11) & 1);
+-		t |= t << 4;
+-		*red = t | (t << 8);
+-		t = ((col >> 3) & 0xe) | ((col >> 7) & 1);
+-		t |= t << 4;
+-		*green = t | (t << 8);
+-		t = ((col << 1) & 0xe) | ((col >> 3) & 1);
+-		t |= t << 4;
+-		*blue = t | (t << 8);
+-	}
+-	else {
+-		t = (col >> 7) & 0xe;
+-		t |= t << 4;
+-		*red = t | (t << 8);
+-		t = (col >> 3) & 0xe;
+-		t |= t << 4;
+-		*green = t | (t << 8);
+-		t = (col << 1) & 0xe;
+-		t |= t << 4;
+-		*blue = t | (t << 8);
+-	}
+-	*transp = 0;
+-	return 0;
+-}
+-
+-
+-static int stste_setcolreg(unsigned regno, unsigned red,
+-			   unsigned green, unsigned blue,
+-			   unsigned transp, struct fb_info *info)
++static int stste_setcolreg(unsigned int regno, unsigned int red,
++			   unsigned int green, unsigned int blue,
++			   unsigned int transp, struct fb_info *info)
+ {
+ 	if (regno > 15)
+ 		return 1;
+@@ -1988,10 +2032,9 @@ static int stste_setcolreg(unsigned regn
+ 	return 0;
+ }
+ 
+-						  
+-static int stste_detect( void )
+-
+-{	struct atafb_par par;
++static int stste_detect(void)
++{
++	struct atafb_par par;
+ 
+ 	/* Determine the connected monitor: The DMA sound must be
+ 	 * disabled before reading the MFP GPIP, because the Sound
+@@ -1999,7 +2042,7 @@ static int stste_detect( void )
+ 	 */
+ 	if (ATARIHW_PRESENT(PCM_8BIT)) {
+ 		tt_dmasnd.ctrl = DMASND_CTRL_OFF;
+-		udelay(20);	/* wait a while for things to settle down */
++		udelay(20);		/* wait a while for things to settle down */
+ 	}
+ 	mono_moni = (mfp.par_dt_reg & 0x80) == 0;
+ 
+@@ -2014,12 +2057,12 @@ static int stste_detect( void )
+ static void stste_set_screen_base(void *s_base)
+ {
+ 	unsigned long addr;
+-	addr= virt_to_phys(s_base);
++	addr = virt_to_phys(s_base);
+ 	/* Setup Screen Memory */
+-	shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
+-  	shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
++	shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
++	shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
+ 	if (ATARIHW_PRESENT(EXTD_SHIFTER))
+-		shifter.bas_lo=(unsigned char)  (addr & 0x0000ff);
++		shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
+ }
+ 
+ #endif /* ATAFB_STE */
+@@ -2045,51 +2088,49 @@ static void stste_set_screen_base(void *
+ /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
+ static void st_ovsc_switch(void)
+ {
+-    unsigned long flags;
+-    register unsigned char old, new;
++	unsigned long flags;
++	register unsigned char old, new;
+ 
+-    if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
+-	return;
+-    local_irq_save(flags);
++	if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
++		return;
++	local_irq_save(flags);
+ 
+-    mfp.tim_ct_b = 0x10;
+-    mfp.active_edge |= 8;
+-    mfp.tim_ct_b = 0;
+-    mfp.tim_dt_b = 0xf0;
+-    mfp.tim_ct_b = 8;
+-    while (mfp.tim_dt_b > 1)	/* TOS does it this way, don't ask why */
+-	;
+-    new = mfp.tim_dt_b;
+-    do {
+-	udelay(LINE_DELAY);
+-	old = new;
++	mfp.tim_ct_b = 0x10;
++	mfp.active_edge |= 8;
++	mfp.tim_ct_b = 0;
++	mfp.tim_dt_b = 0xf0;
++	mfp.tim_ct_b = 8;
++	while (mfp.tim_dt_b > 1)	/* TOS does it this way, don't ask why */
++		;
+ 	new = mfp.tim_dt_b;
+-    } while (old != new);
+-    mfp.tim_ct_b = 0x10;
+-    udelay(SYNC_DELAY);
+-
+-    if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
+-	acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
+-    if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
+-	acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
+-    if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
+-	sound_ym.rd_data_reg_sel = 14;
+-	sound_ym.wd_data = sound_ym.rd_data_reg_sel |
+-			   ((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
+-			   ((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
+-    }
+-    local_irq_restore(flags);
++	do {
++		udelay(LINE_DELAY);
++		old = new;
++		new = mfp.tim_dt_b;
++	} while (old != new);
++	mfp.tim_ct_b = 0x10;
++	udelay(SYNC_DELAY);
++
++	if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
++		acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
++	if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
++		acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
++	if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
++		sound_ym.rd_data_reg_sel = 14;
++		sound_ym.wd_data = sound_ym.rd_data_reg_sel |
++				   ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
++				   ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
++	}
++	local_irq_restore(flags);
+ }
+ 
+ /* ------------------- External Video ---------------------- */
+ 
+ #ifdef ATAFB_EXT
+ 
+-static int ext_encode_fix( struct fb_fix_screeninfo *fix,
+-						   struct atafb_par *par )
+-
++static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
+ {
+-	strcpy(fix->id,"Unknown Extern");
++	strcpy(fix->id, "Unknown Extern");
+ 	fix->smem_start = (unsigned long)external_addr;
+ 	fix->smem_len = PAGE_ALIGN(external_len);
+ 	if (external_depth == 1) {
+@@ -2099,31 +2140,29 @@ static int ext_encode_fix( struct fb_fix
+ 		fix->visual =
+ 			(external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
+ 			 external_pmode == FB_TYPE_PACKED_PIXELS) ?
+-				FB_VISUAL_MONO10 :
+-					FB_VISUAL_MONO01;
+-	}
+-	else {
++				FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
++	} else {
+ 		/* Use STATIC if we don't know how to access color registers */
+ 		int visual = external_vgaiobase ?
+ 					 FB_VISUAL_PSEUDOCOLOR :
+ 					 FB_VISUAL_STATIC_PSEUDOCOLOR;
+ 		switch (external_pmode) {
+-		    case -1:              /* truecolor */
+-			fix->type=FB_TYPE_PACKED_PIXELS;
+-			fix->visual=FB_VISUAL_TRUECOLOR;
++		case -1:		/* truecolor */
++			fix->type = FB_TYPE_PACKED_PIXELS;
++			fix->visual = FB_VISUAL_TRUECOLOR;
+ 			break;
+-		    case FB_TYPE_PACKED_PIXELS:
+-			fix->type=FB_TYPE_PACKED_PIXELS;
+-			fix->visual=visual;
++		case FB_TYPE_PACKED_PIXELS:
++			fix->type = FB_TYPE_PACKED_PIXELS;
++			fix->visual = visual;
+ 			break;
+-		    case FB_TYPE_PLANES:
+-			fix->type=FB_TYPE_PLANES;
+-			fix->visual=visual;
++		case FB_TYPE_PLANES:
++			fix->type = FB_TYPE_PLANES;
++			fix->visual = visual;
+ 			break;
+-		    case FB_TYPE_INTERLEAVED_PLANES:
+-			fix->type=FB_TYPE_INTERLEAVED_PLANES;
+-			fix->type_aux=2;
+-			fix->visual=visual;
++		case FB_TYPE_INTERLEAVED_PLANES:
++			fix->type = FB_TYPE_INTERLEAVED_PLANES;
++			fix->type_aux = 2;
++			fix->visual = visual;
+ 			break;
+ 		}
+ 	}
+@@ -2134,137 +2173,112 @@ static int ext_encode_fix( struct fb_fix
+ 	return 0;
+ }
+ 
+-
+-static int ext_decode_var( struct fb_var_screeninfo *var,
+-						   struct atafb_par *par )
++static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
+ {
+ 	struct fb_var_screeninfo *myvar = &atafb_predefined[0];
+-	
++
+ 	if (var->bits_per_pixel > myvar->bits_per_pixel ||
+-		var->xres > myvar->xres ||
+-		var->xres_virtual > myvar->xres_virtual ||
+-		var->yres > myvar->yres ||
+-		var->xoffset > 0 ||
+-		var->yoffset > 0)
++	    var->xres > myvar->xres ||
++	    var->xres_virtual > myvar->xres_virtual ||
++	    var->yres > myvar->yres ||
++	    var->xoffset > 0 ||
++	    var->yoffset > 0)
+ 		return -EINVAL;
+ 	return 0;
+ }
+ 
+-
+-static int ext_encode_var( struct fb_var_screeninfo *var,
+-						   struct atafb_par *par )
++static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
+ {
+ 	memset(var, 0, sizeof(struct fb_var_screeninfo));
+-	var->red.offset=0;
+-	var->red.length=(external_pmode == -1) ? external_depth/3 : 
++	var->red.offset = 0;
++	var->red.length = (external_pmode == -1) ? external_depth / 3 :
+ 			(external_vgaiobase ? external_bitspercol : 0);
+-	var->red.msb_right=0;
+-	var->grayscale=0;
++	var->red.msb_right = 0;
++	var->grayscale = 0;
+ 
+-	var->pixclock=31041;
+-	var->left_margin=120;		/* these are surely incorrect 	*/
+-	var->right_margin=100;
+-	var->upper_margin=8;
+-	var->lower_margin=16;
+-	var->hsync_len=140;
+-	var->vsync_len=30;
++	var->pixclock = 31041;
++	var->left_margin = 120;		/* these are surely incorrect */
++	var->right_margin = 100;
++	var->upper_margin = 8;
++	var->lower_margin = 16;
++	var->hsync_len = 140;
++	var->vsync_len = 30;
+ 
+-	var->height=-1;
+-	var->width=-1;
++	var->height = -1;
++	var->width = -1;
+ 
+-	var->sync=0;
++	var->sync = 0;
+ 
+ 	var->xres = external_xres;
+ 	var->yres = external_yres;
+ 	var->xres_virtual = external_xres_virtual;
+ 	var->bits_per_pixel = external_depth;
+-	
+-	var->blue=var->green=var->red;
+-	var->transp.offset=0;
+-	var->transp.length=0;
+-	var->transp.msb_right=0;
+-	var->yres_virtual=var->yres;
+-	var->xoffset=0;
+-	var->yoffset=0;
+-	var->nonstd=0;
+-	var->activate=0;
+-	var->vmode=FB_VMODE_NONINTERLACED;
++
++	var->blue = var->green = var->red;
++	var->transp.offset = 0;
++	var->transp.length = 0;
++	var->transp.msb_right = 0;
++	var->yres_virtual = var->yres;
++	var->xoffset = 0;
++	var->yoffset = 0;
++	var->nonstd = 0;
++	var->activate = 0;
++	var->vmode = FB_VMODE_NONINTERLACED;
+ 	return 0;
+ }
+ 
+-
+-static void ext_get_par( struct atafb_par *par )
++static void ext_get_par(struct atafb_par *par)
+ {
+ 	par->screen_base = external_addr;
+ }
+ 
+-static void ext_set_par( struct atafb_par *par )
++static void ext_set_par(struct atafb_par *par)
+ {
+ }
+ 
+ #define OUTB(port,val) \
+-	*((unsigned volatile char *) ((port)+external_vgaiobase))=(val)
++	*((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
+ #define INB(port) \
+ 	(*((unsigned volatile char *) ((port)+external_vgaiobase)))
+-#define DACDelay 				\
++#define DACDelay				\
+ 	do {					\
+-		unsigned char tmp=INB(0x3da);	\
+-		tmp=INB(0x3da);			\
++		unsigned char tmp = INB(0x3da);	\
++		tmp = INB(0x3da);			\
+ 	} while (0)
+ 
+-static int ext_getcolreg( unsigned regno, unsigned *red,
+-						  unsigned *green, unsigned *blue,
+-						  unsigned *transp, struct fb_info *info )
++static int ext_setcolreg(unsigned int regno, unsigned int red,
++			 unsigned int green, unsigned int blue,
++			 unsigned int transp, struct fb_info *info)
+ {
+-	if (! external_vgaiobase)
++	unsigned char colmask = (1 << external_bitspercol) - 1;
++
++	if (!external_vgaiobase)
+ 		return 1;
+ 
+-	    *red   = ext_color[regno].red;
+-	    *green = ext_color[regno].green;
+-	    *blue  = ext_color[regno].blue;
+-	    *transp=0;
+-	    return 0;
+-}
+-	
+-static int ext_setcolreg( unsigned regno, unsigned red,
+-						  unsigned green, unsigned blue,
+-						  unsigned transp, struct fb_info *info )
++	switch (external_card_type) {
++	case IS_VGA:
++		OUTB(0x3c8, regno);
++		DACDelay;
++		OUTB(0x3c9, red & colmask);
++		DACDelay;
++		OUTB(0x3c9, green & colmask);
++		DACDelay;
++		OUTB(0x3c9, blue & colmask);
++		DACDelay;
++		return 0;
+ 
+-{	unsigned char colmask = (1 << external_bitspercol) - 1;
++	case IS_MV300:
++		OUTB((MV300_reg[regno] << 2) + 1, red);
++		OUTB((MV300_reg[regno] << 2) + 1, green);
++		OUTB((MV300_reg[regno] << 2) + 1, blue);
++		return 0;
+ 
+-	if (! external_vgaiobase)
++	default:
+ 		return 1;
+-
+-	ext_color[regno].red = red;
+-	ext_color[regno].green = green;
+-	ext_color[regno].blue = blue;
+-
+-	switch (external_card_type) {
+-	  case IS_VGA:
+-	    OUTB(0x3c8, regno);
+-	    DACDelay;
+-	    OUTB(0x3c9, red & colmask);
+-	    DACDelay;
+-	    OUTB(0x3c9, green & colmask);
+-	    DACDelay;
+-	    OUTB(0x3c9, blue & colmask);
+-	    DACDelay;
+-	    return 0;
+-
+-	  case IS_MV300:
+-	    OUTB((MV300_reg[regno] << 2)+1, red);
+-	    OUTB((MV300_reg[regno] << 2)+1, green);
+-	    OUTB((MV300_reg[regno] << 2)+1, blue);
+-	    return 0;
+-
+-	  default:
+-	    return 1;
+-	  }
++	}
+ }
+-	
+-
+-static int ext_detect( void )
+ 
++static int ext_detect(void)
+ {
+ 	struct fb_var_screeninfo *myvar = &atafb_predefined[0];
+ 	struct atafb_par dummy_par;
+@@ -2284,213 +2298,182 @@ static int ext_detect( void )
+ static void set_screen_base(void *s_base)
+ {
+ 	unsigned long addr;
+-	addr= virt_to_phys(s_base);
++
++	addr = virt_to_phys(s_base);
+ 	/* Setup Screen Memory */
+-	shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
+-  	shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
+-  	shifter.bas_lo=(unsigned char)  (addr & 0x0000ff);
++	shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
++	shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
++	shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
+ }
+ 
+-
+-static int pan_display( struct fb_var_screeninfo *var,
+-                        struct atafb_par *par )
++static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+ {
++	struct atafb_par *par = (struct atafb_par *)info->par;
++
+ 	if (!fbhw->set_screen_base ||
+-		(!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
++	    (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
+ 		return -EINVAL;
+ 	var->xoffset = up(var->xoffset, 16);
+ 	par->screen_base = screen_base +
+-	        (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + var->xoffset)
+-	        * fb_display[fb_info.currcon].var.bits_per_pixel / 8;
+-	fbhw->set_screen_base (par->screen_base);
++	        (var->yoffset * info->var.xres_virtual + var->xoffset)
++	        * info->var.bits_per_pixel / 8;
++	fbhw->set_screen_base(par->screen_base);
+ 	return 0;
+ }
+ 
+-
+ /* ------------ Interfaces to hardware functions ------------ */
+ 
+-
+ #ifdef ATAFB_TT
+ static struct fb_hwswitch tt_switch = {
+-	tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var,
+-	tt_get_par, tt_set_par, tt_getcolreg, 
+-	set_screen_base, NULL, pan_display
++	.detect		= tt_detect,
++	.encode_fix	= tt_encode_fix,
++	.decode_var	= tt_decode_var,
++	.encode_var	= tt_encode_var,
++	.get_par	= tt_get_par,
++	.set_par	= tt_set_par,
++	.set_screen_base = set_screen_base,
++	.pan_display	= pan_display,
+ };
+ #endif
+ 
+ #ifdef ATAFB_FALCON
+ static struct fb_hwswitch falcon_switch = {
+-	falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var,
+-	falcon_get_par, falcon_set_par, falcon_getcolreg,
+-	set_screen_base, falcon_blank, falcon_pan_display
++	.detect		= falcon_detect,
++	.encode_fix	= falcon_encode_fix,
++	.decode_var	= falcon_decode_var,
++	.encode_var	= falcon_encode_var,
++	.get_par	= falcon_get_par,
++	.set_par	= falcon_set_par,
++	.set_screen_base = set_screen_base,
++	.blank		= falcon_blank,
++	.pan_display	= falcon_pan_display,
+ };
+ #endif
+ 
+ #ifdef ATAFB_STE
+ static struct fb_hwswitch st_switch = {
+-	stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var,
+-	stste_get_par, stste_set_par, stste_getcolreg,
+-	stste_set_screen_base, NULL, pan_display
++	.detect		= stste_detect,
++	.encode_fix	= stste_encode_fix,
++	.decode_var	= stste_decode_var,
++	.encode_var	= stste_encode_var,
++	.get_par	= stste_get_par,
++	.set_par	= stste_set_par,
++	.set_screen_base = stste_set_screen_base,
++	.pan_display	= pan_display
+ };
+ #endif
+ 
+ #ifdef ATAFB_EXT
+ static struct fb_hwswitch ext_switch = {
+-	ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var,
+-	ext_get_par, ext_set_par, ext_getcolreg, NULL, NULL, NULL
++	.detect		= ext_detect,
++	.encode_fix	= ext_encode_fix,
++	.decode_var	= ext_decode_var,
++	.encode_var	= ext_encode_var,
++	.get_par	= ext_get_par,
++	.set_par	= ext_set_par,
+ };
+ #endif
+ 
+-
+-
+-static void atafb_get_par( struct atafb_par *par )
++static void ata_get_par(struct atafb_par *par)
+ {
+-	if (current_par_valid) {
+-		*par=current_par;
+-	}
++	if (current_par_valid)
++		*par = current_par;
+ 	else
+ 		fbhw->get_par(par);
+ }
+ 
+-
+-static void atafb_set_par( struct atafb_par *par )
++static void ata_set_par(struct atafb_par *par)
+ {
+ 	fbhw->set_par(par);
+-	current_par=*par;
+-	current_par_valid=1;
++	current_par = *par;
++	current_par_valid = 1;
+ }
+ 
+ 
+-
+ /* =========================================================== */
+ /* ============== Hardware Independent Functions ============= */
+ /* =========================================================== */
+ 
+-
+ /* used for hardware scrolling */
+ 
+-static int
+-fb_update_var(int con, struct fb_info *info)
+-{
+-	int off=fb_display[con].var.yoffset*fb_display[con].var.xres_virtual*
+-			fb_display[con].var.bits_per_pixel>>3;
+-
+-	current_par.screen_base=screen_base + off;
+-
+-	if (fbhw->set_screen_base)
+-		fbhw->set_screen_base(current_par.screen_base);
+-	return 0;
+-}
+-
+-static int
+-do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
++static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
+ {
+-	int err,activate;
++	int err, activate;
+ 	struct atafb_par par;
+-	if ((err=fbhw->decode_var(var, &par)))
++
++	err = fbhw->decode_var(var, &par);
++	if (err)
+ 		return err;
+-	activate=var->activate;
++	activate = var->activate;
+ 	if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
+-		atafb_set_par(&par);
++		ata_set_par(&par);
+ 	fbhw->encode_var(var, &par);
+-	var->activate=activate;
++	var->activate = activate;
+ 	return 0;
+ }
+ 
+-static int
+-atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
++static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
+ {
+ 	struct atafb_par par;
+-	if (con == -1)
+-		atafb_get_par(&par);
+-	else {
+-	  int err;
+-		if ((err=fbhw->decode_var(&fb_display[con].var,&par)))
+-		  return err;
+-	}
++	int err;
++	// Get fix directly (case con == -1 before)??
++	err = fbhw->decode_var(&info->var, &par);
++	if (err)
++		return err;
+ 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ 	return fbhw->encode_fix(fix, &par);
+ }
+-	
+-static int
+-atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
++
++static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
+ {
+ 	struct atafb_par par;
+-	if (con == -1) {
+-		atafb_get_par(&par);
+-		fbhw->encode_var(var, &par);
+-	}
+-	else
+-		*var=fb_display[con].var;
++
++	ata_get_par(&par);
++	fbhw->encode_var(var, &par);
++
+ 	return 0;
+ }
+ 
+-static void
+-atafb_set_disp(int con, struct fb_info *info)
++// No longer called by fbcon!
++// Still called by set_var internally
++
++static void atafb_set_disp(struct fb_info *info)
+ {
+-	struct fb_fix_screeninfo fix;
+-	struct fb_var_screeninfo var;
+-	struct display *display;
++	atafb_get_var(&info->var, info);
++	atafb_get_fix(&info->fix, info);
+ 
+-	if (con >= 0)
+-		display = &fb_display[con];
+-	else
+-		display = &disp;	/* used during initialization */
++	info->screen_base = (void *)info->fix.smem_start;
+ 
+-	atafb_get_fix(&fix, con, info);
+-	atafb_get_var(&var, con, info);
+-	if (con == -1)
+-		con=0;
+-	info->screen_base = (void *)fix.smem_start;
+-	display->visual = fix.visual;
+-	display->type = fix.type;
+-	display->type_aux = fix.type_aux;
+-	display->ypanstep = fix.ypanstep;
+-	display->ywrapstep = fix.ywrapstep;
+-	display->line_length = fix.line_length;
+-	if (fix.visual != FB_VISUAL_PSEUDOCOLOR &&
+-		fix.visual != FB_VISUAL_DIRECTCOLOR)
+-		display->can_soft_blank = 0;
+-	else
+-		display->can_soft_blank = 1;
+-	display->inverse =
+-	    (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
+-	switch (fix.type) {
+-	    case FB_TYPE_INTERLEAVED_PLANES:
+-		switch (var.bits_per_pixel) {
+-#ifdef FBCON_HAS_IPLAN2P2
+-		    case 2:
+-			display->dispsw = &fbcon_iplan2p2;
++	switch (info->fix.type) {
++	case FB_TYPE_INTERLEAVED_PLANES:
++		switch (info->var.bits_per_pixel) {
++		case 2:
++			// display->dispsw = &fbcon_iplan2p2;
+ 			break;
+-#endif
+-#ifdef FBCON_HAS_IPLAN2P4
+-		    case 4:
+-			display->dispsw = &fbcon_iplan2p4;
++		case 4:
++			// display->dispsw = &fbcon_iplan2p4;
+ 			break;
+-#endif
+-#ifdef FBCON_HAS_IPLAN2P8
+-		    case 8:
+-			display->dispsw = &fbcon_iplan2p8;
++		case 8:
++			// display->dispsw = &fbcon_iplan2p8;
+ 			break;
+-#endif
+ 		}
+ 		break;
+-	    case FB_TYPE_PACKED_PIXELS:
+-		switch (var.bits_per_pixel) {
++	case FB_TYPE_PACKED_PIXELS:
++		switch (info->var.bits_per_pixel) {
+ #ifdef FBCON_HAS_MFB
+-		    case 1:
+-			display->dispsw = &fbcon_mfb;
++		case 1:
++			// display->dispsw = &fbcon_mfb;
+ 			break;
+ #endif
+ #ifdef FBCON_HAS_CFB8
+-		    case 8:
+-			display->dispsw = &fbcon_cfb8;
++		case 8:
++			// display->dispsw = &fbcon_cfb8;
+ 			break;
+ #endif
+ #ifdef FBCON_HAS_CFB16
+-		    case 16:
+-			display->dispsw = &fbcon_cfb16;
+-			display->dispsw_data = fbcon_cfb16_cmap;
++		case 16:
++			// display->dispsw = &fbcon_cfb16;
++			// display->dispsw_data = fbcon_cfb16_cmap;
+ 			break;
+ #endif
+ 		}
+@@ -2498,74 +2481,203 @@ atafb_set_disp(int con, struct fb_info *
+ 	}
+ }
+ 
++static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
++			   u_int transp, struct fb_info *info)
++{
++	red >>= 8;
++	green >>= 8;
++	blue >>= 8;
++
++	return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info);
++}
++
+ static int
+-atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
++atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+ {
+-	int err,oldxres,oldyres,oldbpp,oldxres_virtual,
+-	    oldyres_virtual,oldyoffset;
+-	if ((err=do_fb_set_var(var, con==info->currcon)))
+-		return err;
+-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+-		oldxres=fb_display[con].var.xres;
+-		oldyres=fb_display[con].var.yres;
+-		oldxres_virtual=fb_display[con].var.xres_virtual;
+-		oldyres_virtual=fb_display[con].var.yres_virtual;
+-		oldbpp=fb_display[con].var.bits_per_pixel;
+-		oldyoffset=fb_display[con].var.yoffset;
+-		fb_display[con].var=*var;
+-		if (oldxres != var->xres || oldyres != var->yres 
+-		    || oldxres_virtual != var->xres_virtual
+-		    || oldyres_virtual != var->yres_virtual
+-		    || oldbpp != var->bits_per_pixel
+-		    || oldyoffset != var->yoffset) {
+-			atafb_set_disp(con, info);
+-			(*fb_info.changevar)(con);
+-			fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
+-			do_install_cmap(con, info);
+-		}
++	int xoffset = var->xoffset;
++	int yoffset = var->yoffset;
++	int err;
++
++	if (var->vmode & FB_VMODE_YWRAP) {
++		if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset)
++			return -EINVAL;
++	} else {
++		if (xoffset + info->var.xres > info->var.xres_virtual ||
++		    yoffset + info->var.yres > info->var.yres_virtual)
++			return -EINVAL;
+ 	}
+-	var->activate=0;
++
++	if (fbhw->pan_display) {
++		err = fbhw->pan_display(var, info);
++		if (err)
++			return err;
++	} else
++		return -EINVAL;
++
++	info->var.xoffset = xoffset;
++	info->var.yoffset = yoffset;
++
++	if (var->vmode & FB_VMODE_YWRAP)
++		info->var.vmode |= FB_VMODE_YWRAP;
++	else
++		info->var.vmode &= ~FB_VMODE_YWRAP;
++
+ 	return 0;
+ }
+ 
++/*
++ * generic drawing routines; imageblit needs updating for image depth > 1
++ */
++
++#if BITS_PER_LONG == 32
++#define BYTES_PER_LONG	4
++#define SHIFT_PER_LONG	5
++#elif BITS_PER_LONG == 64
++#define BYTES_PER_LONG	8
++#define SHIFT_PER_LONG	6
++#else
++#define Please update me
++#endif
+ 
+ 
+-static int
+-atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
++static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+ {
+-	if (con == info->currcon) /* current console ? */
+-		return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
++	struct atafb_par *par = (struct atafb_par *)info->par;
++	int x2, y2;
++	u32 width, height;
++
++	if (!rect->width || !rect->height)
++		return;
++
++	/*
++	 * We could use hardware clipping but on many cards you get around
++	 * hardware clipping by writing to framebuffer directly.
++	 * */
++	x2 = rect->dx + rect->width;
++	y2 = rect->dy + rect->height;
++	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
++	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
++	width = x2 - rect->dx;
++	height = y2 - rect->dy;
++
++	if (info->var.bits_per_pixel == 1)
++		atafb_mfb_fillrect(info, par->next_line, rect->color,
++				   rect->dy, rect->dx, height, width);
++	else if (info->var.bits_per_pixel == 2)
++		atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
++					rect->dy, rect->dx, height, width);
++	else if (info->var.bits_per_pixel == 4)
++		atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
++					rect->dy, rect->dx, height, width);
+ 	else
+-		if (fb_display[con].cmap.len) /* non default colormap ? */
+-			fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+-		else
+-			fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
+-				     cmap, kspc ? 0 : 2);
+-	return 0;
++		atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
++					rect->dy, rect->dx, height, width);
++
++	return;
+ }
+ 
+-static int
+-atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
++static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+ {
+-	int xoffset = var->xoffset;
+-	int yoffset = var->yoffset;
+-	int err;
++	struct atafb_par *par = (struct atafb_par *)info->par;
++	int x2, y2;
++	u32 dx, dy, sx, sy, width, height;
++	int rev_copy = 0;
++
++	/* clip the destination */
++	x2 = area->dx + area->width;
++	y2 = area->dy + area->height;
++	dx = area->dx > 0 ? area->dx : 0;
++	dy = area->dy > 0 ? area->dy : 0;
++	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
++	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
++	width = x2 - dx;
++	height = y2 - dy;
++
++	/* update sx,sy */
++	sx = area->sx + (dx - area->dx);
++	sy = area->sy + (dy - area->dy);
++
++	/* the source must be completely inside the virtual screen */
++	if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
++	    (sy + height) > info->var.yres_virtual)
++		return;
+ 
+-	if (   xoffset < 0 || xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual
+-	    || yoffset < 0 || yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
+-		return -EINVAL;
++	if (dy > sy || (dy == sy && dx > sx)) {
++		dy += height;
++		sy += height;
++		rev_copy = 1;
++	}
++
++	if (info->var.bits_per_pixel == 1)
++		atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
++	else if (info->var.bits_per_pixel == 2)
++		atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
++	else if (info->var.bits_per_pixel == 4)
++		atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
++	else
++		atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
++
++	return;
++}
+ 
+-	if (con == info->currcon) {
+-		if (fbhw->pan_display) {
+-			if ((err = fbhw->pan_display(var, &current_par)))
+-				return err;
++static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
++{
++	struct atafb_par *par = (struct atafb_par *)info->par;
++	int x2, y2;
++	unsigned long *dst;
++	int dst_idx;
++	const char *src;
++	u32 dx, dy, width, height, pitch;
++
++	/*
++	 * We could use hardware clipping but on many cards you get around
++	 * hardware clipping by writing to framebuffer directly like we are
++	 * doing here.
++	 */
++	x2 = image->dx + image->width;
++	y2 = image->dy + image->height;
++	dx = image->dx;
++	dy = image->dy;
++	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
++	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
++	width = x2 - dx;
++	height = y2 - dy;
++
++	if (image->depth == 1) {
++		// used for font data
++		dst = (unsigned long *)
++			((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
++		dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
++		dst_idx += dy * par->next_line * 8 + dx;
++		src = image->data;
++		pitch = (image->width + 7) / 8;
++		while (height--) {
++
++			if (info->var.bits_per_pixel == 1)
++				atafb_mfb_linefill(info, par->next_line,
++						   dy, dx, width, src,
++						   image->bg_color, image->fg_color);
++			else if (info->var.bits_per_pixel == 2)
++				atafb_iplan2p2_linefill(info, par->next_line,
++							dy, dx, width, src,
++							image->bg_color, image->fg_color);
++			else if (info->var.bits_per_pixel == 4)
++				atafb_iplan2p4_linefill(info, par->next_line,
++							dy, dx, width, src,
++							image->bg_color, image->fg_color);
++			else
++				atafb_iplan2p8_linefill(info, par->next_line,
++							dy, dx, width, src,
++							image->bg_color, image->fg_color);
++			dy++;
++			src += pitch;
+ 		}
+-		else
+-			return -EINVAL;
++	} else {
++		// only used for logo; broken
++		c2p(info->screen_base, image->data, dx, dy, width, height,
++		    par->next_line, par->next_plane, image->width,
++		    info->var.bits_per_pixel);
+ 	}
+-	fb_display[con].var.xoffset = var->xoffset;
+-	fb_display[con].var.yoffset = var->yoffset;
+-	return 0;
+ }
+ 
+ static int
+@@ -2584,7 +2696,7 @@ atafb_ioctl(struct fb_info *info, unsign
+ 		if (copy_from_user((void *)&current_par, (void *)arg,
+ 				   sizeof(struct atafb_par)))
+ 			return -EFAULT;
+-		atafb_set_par(&current_par);
++		ata_set_par(&current_par);
+ 		return 0;
+ #endif
+ 	}
+@@ -2598,42 +2710,82 @@ atafb_ioctl(struct fb_info *info, unsign
+  * 3 = suspend hsync
+  * 4 = off
+  */
+-static int 
+-atafb_blank(int blank, struct fb_info *info)
++static int atafb_blank(int blank, struct fb_info *info)
+ {
+ 	unsigned short black[16];
+ 	struct fb_cmap cmap;
+ 	if (fbhw->blank && !fbhw->blank(blank))
+ 		return 1;
+ 	if (blank) {
+-		memset(black, 0, 16*sizeof(unsigned short));
+-		cmap.red=black;
+-		cmap.green=black;
+-		cmap.blue=black;
+-		cmap.transp=NULL;
+-		cmap.start=0;
+-		cmap.len=16;
+-		fb_set_cmap(&cmap, 1, info);
++		memset(black, 0, 16 * sizeof(unsigned short));
++		cmap.red = black;
++		cmap.green = black;
++		cmap.blue = black;
++		cmap.transp = NULL;
++		cmap.start = 0;
++		cmap.len = 16;
++		fb_set_cmap(&cmap, info);
+ 	}
++#if 0
+ 	else
+-		do_install_cmap(info->currcon, info);
++		do_install_cmap(info);
++#endif
++	return 0;
++}
++
++	/*
++	 * New fbcon interface ...
++	 */
++
++	 /* check var by decoding var into hw par, rounding if necessary,
++	  * then encoding hw par back into new, validated var */
++static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
++{
++	int err;
++	struct atafb_par par;
++
++	/* Validate wanted screen parameters */
++	// if ((err = ata_decode_var(var, &par)))
++	err = fbhw->decode_var(var, &par);
++	if (err)
++		return err;
++
++	/* Encode (possibly rounded) screen parameters */
++	fbhw->encode_var(var, &par);
+ 	return 0;
+ }
+ 
++	/* actually set hw par by decoding var, then setting hardware from
++	 * hw par just decoded */
++static int atafb_set_par(struct fb_info *info)
++{
++	struct atafb_par *par = (struct atafb_par *)info->par;
++
++	/* Decode wanted screen parameters */
++	fbhw->decode_var(&info->var, par);
++	fbhw->encode_fix(&info->fix, par);
++
++	/* Set new videomode */
++	ata_set_par(par);
++
++	return 0;
++}
++
++
+ static struct fb_ops atafb_ops = {
+ 	.owner =	THIS_MODULE,
+-	.fb_get_fix =	atafb_get_fix,
+-	.fb_get_var =	atafb_get_var,
+-	.fb_set_var =	atafb_set_var,
+-	.fb_get_cmap =	atafb_get_cmap,
+-	.fb_set_cmap =	gen_set_cmap,
+-	.fb_pan_display =atafb_pan_display,
++	.fb_check_var	= atafb_check_var,
++	.fb_set_par	= atafb_set_par,
++	.fb_setcolreg	= atafb_setcolreg,
+ 	.fb_blank =	atafb_blank,
++	.fb_pan_display	= atafb_pan_display,
++	.fb_fillrect	= atafb_fillrect,
++	.fb_copyarea	= atafb_copyarea,
++	.fb_imageblit	= atafb_imageblit,
+ 	.fb_ioctl =	atafb_ioctl,
+ };
+ 
+-static void
+-check_default_par( int detected_mode )
++static void check_default_par(int detected_mode)
+ {
+ 	char default_name[10];
+ 	int i;
+@@ -2642,199 +2794,41 @@ check_default_par( int detected_mode )
+ 
+ 	/* First try the user supplied mode */
+ 	if (default_par) {
+-		var=atafb_predefined[default_par-1];
++		var = atafb_predefined[default_par - 1];
+ 		var.activate = FB_ACTIVATE_TEST;
+-		if (do_fb_set_var(&var,1))
+-			default_par=0;		/* failed */
++		if (do_fb_set_var(&var, 1))
++			default_par = 0;	/* failed */
+ 	}
+ 	/* Next is the autodetected one */
+-	if (! default_par) {
+-		var=atafb_predefined[detected_mode-1]; /* autodetect */
++	if (!default_par) {
++		var = atafb_predefined[detected_mode - 1]; /* autodetect */
+ 		var.activate = FB_ACTIVATE_TEST;
+-		if (!do_fb_set_var(&var,1))
+-			default_par=detected_mode;
++		if (!do_fb_set_var(&var, 1))
++			default_par = detected_mode;
+ 	}
+ 	/* If that also failed, try some default modes... */
+-	if (! default_par) {
++	if (!default_par) {
+ 		/* try default1, default2... */
+-		for (i=1 ; i < 10 ; i++) {
+-			sprintf(default_name,"default%d",i);
+-			default_par=get_video_mode(default_name);
+-			if (! default_par)
++		for (i = 1; i < 10; i++) {
++			sprintf(default_name,"default%d", i);
++			default_par = get_video_mode(default_name);
++			if (!default_par)
+ 				panic("can't set default video mode");
+-			var=atafb_predefined[default_par-1];
++			var = atafb_predefined[default_par - 1];
+ 			var.activate = FB_ACTIVATE_TEST;
+-			if (! do_fb_set_var(&var,1))
++			if (!do_fb_set_var(&var,1))
+ 				break;	/* ok */
+ 		}
+ 	}
+-	min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8;
++	min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
+ 	if (default_mem_req < min_mem)
+-		default_mem_req=min_mem;
+-}
+-
+-static int
+-atafb_switch(int con, struct fb_info *info)
+-{
+-	/* Do we have to save the colormap ? */
+-	if (fb_display[info->currcon].cmap.len)
+-		fb_get_cmap(&fb_display[info->currcon].cmap, 1, fbhw->getcolreg,
+-			    info);
+-	do_fb_set_var(&fb_display[con].var,1);
+-	info->currcon=con;
+-	/* Install new colormap */
+-	do_install_cmap(con, info);
+-	return 0;
+-}
+-
+-int __init atafb_init(void)
+-{
+-	int pad;
+-	int detected_mode;
+-	unsigned long mem_req;
+-
+-	if (!MACH_IS_ATARI)
+-	        return -ENXIO;
+-
+-	do {
+-#ifdef ATAFB_EXT
+-		if (external_addr) {
+-			fbhw = &ext_switch;
+-			atafb_ops.fb_setcolreg = &ext_setcolreg;
+-			break;
+-		}
+-#endif
+-#ifdef ATAFB_TT
+-		if (ATARIHW_PRESENT(TT_SHIFTER)) {
+-			fbhw = &tt_switch;
+-			atafb_ops.fb_setcolreg = &tt_setcolreg;
+-			break;
+-		}
+-#endif
+-#ifdef ATAFB_FALCON
+-		if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
+-			fbhw = &falcon_switch;
+-			atafb_ops.fb_setcolreg = &falcon_setcolreg;
+-			request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
+-			            "framebuffer/modeswitch", falcon_vbl_switcher);
+-			break;
+-		}
+-#endif
+-#ifdef ATAFB_STE
+-		if (ATARIHW_PRESENT(STND_SHIFTER) ||
+-		    ATARIHW_PRESENT(EXTD_SHIFTER)) {
+-			fbhw = &st_switch;
+-			atafb_ops.fb_setcolreg = &stste_setcolreg;
+-			break;
+-		}
+-		fbhw = &st_switch;
+-		atafb_ops.fb_setcolreg = &stste_setcolreg;
+-		printk("Cannot determine video hardware; defaulting to ST(e)\n");
+-#else /* ATAFB_STE */
+-		/* no default driver included */
+-		/* Nobody will ever see this message :-) */
+-		panic("Cannot initialize video hardware");
+-#endif
+-	} while (0);
+-
+-	/* Multisync monitor capabilities */
+-	/* Atari-TOS defaults if no boot option present */
+-	if (fb_info.monspecs.hfmin == 0) {
+-	    fb_info.monspecs.hfmin = 31000;
+-	    fb_info.monspecs.hfmax = 32000;
+-	    fb_info.monspecs.vfmin = 58;
+-	    fb_info.monspecs.vfmax = 62;
+-	}
+-
+-	detected_mode = fbhw->detect();
+-	check_default_par(detected_mode);
+-#ifdef ATAFB_EXT
+-	if (!external_addr) {
+-#endif /* ATAFB_EXT */
+-		mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
+-		mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
+-		screen_base = atari_stram_alloc(mem_req, "atafb");
+-		if (!screen_base)
+-			panic("Cannot allocate screen memory");
+-		memset(screen_base, 0, mem_req);
+-		pad = -(unsigned long)screen_base & (PAGE_SIZE-1);
+-		screen_base+=pad;
+-		real_screen_base=screen_base+ovsc_offset;
+-		screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
+-		st_ovsc_switch();
+-		if (CPU_IS_040_OR_060) {
+-			/* On a '040+, the cache mode of video RAM must be set to
+-			 * write-through also for internal video hardware! */
+-			cache_push(virt_to_phys(screen_base), screen_len);
+-			kernel_set_cachemode(screen_base, screen_len,
+-					     IOMAP_WRITETHROUGH);
+-		}
+-#ifdef ATAFB_EXT
+-	}
+-	else {
+-		/* Map the video memory (physical address given) to somewhere
+-		 * in the kernel address space.
+-		 */
+-		external_addr =
+-		  ioremap_writethrough((unsigned long)external_addr,
+-				       external_len);
+-		if (external_vgaiobase)
+-			external_vgaiobase =
+-			  (unsigned long)ioremap(external_vgaiobase, 0x10000);
+-		screen_base      =
+-		real_screen_base = external_addr;
+-		screen_len       = external_len & PAGE_MASK;
+-		memset (screen_base, 0, external_len);
+-	}
+-#endif /* ATAFB_EXT */
+-
+-	strcpy(fb_info.modename, "Atari Builtin ");
+-	fb_info.changevar = NULL;
+-	fb_info.fbops = &atafb_ops;
+-	fb_info.disp = &disp;
+-	fb_info.currcon = -1;
+-	fb_info.switch_con = &atafb_switch;
+-	fb_info.updatevar = &fb_update_var;
+-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+-	do_fb_set_var(&atafb_predefined[default_par-1], 1);
+-	strcat(fb_info.modename, fb_var_names[default_par-1][0]);
+-
+-	atafb_get_var(&disp.var, -1, &fb_info);
+-	atafb_set_disp(-1, &fb_info);
+-	do_install_cmap(0, &fb_info);
+-
+-	if (register_framebuffer(&fb_info) < 0) {
+-#ifdef ATAFB_EXT
+-		if (external_addr) {
+-			iounmap(external_addr);
+-			external_addr = NULL;
+-		}
+-		if (external_vgaiobase) {
+-			iounmap((void*)external_vgaiobase);
+-			external_vgaiobase = 0;
+-		}
+-#endif
+-		return -EINVAL;
+-	}
+-
+-	printk("Determined %dx%d, depth %d\n",
+-	       disp.var.xres, disp.var.yres, disp.var.bits_per_pixel);
+-	if ((disp.var.xres != disp.var.xres_virtual) ||
+-	    (disp.var.yres != disp.var.yres_virtual))
+-	   printk("   virtual %dx%d\n",
+-			  disp.var.xres_virtual, disp.var.yres_virtual);
+-	printk("fb%d: %s frame buffer device, using %dK of video memory\n",
+-	       fb_info.node, fb_info.modename, screen_len>>10);
+-
+-	/* TODO: This driver cannot be unloaded yet */
+-	return 0;
++		default_mem_req = min_mem;
+ }
+ 
+-
+ #ifdef ATAFB_EXT
+ static void __init atafb_setup_ext(char *spec)
+ {
+-	int		xres, xres_virtual, yres, depth, planes;
++	int xres, xres_virtual, yres, depth, planes;
+ 	unsigned long addr, len;
+ 	char *p;
+ 
+@@ -2848,27 +2842,31 @@ static void __init atafb_setup_ext(char 
+ 	 *
+ 	 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
+ 	 */
+-	if (!(p = strsep(&spec, ";")) || !*p)
+-	    return;
++	p = strsep(&spec, ";");
++	if (!p || !*p)
++		return;
+ 	xres_virtual = xres = simple_strtoul(p, NULL, 10);
+ 	if (xres <= 0)
+-	    return;
++		return;
+ 
+-	if (!(p = strsep(&spec, ";")) || !*p)
+-	    return;
++	p = strsep(&spec, ";");
++	if (!p || !*p)
++		return;
+ 	yres = simple_strtoul(p, NULL, 10);
+ 	if (yres <= 0)
+-	    return;
++		return;
+ 
+-	if (!(p = strsep(&spec, ";")) || !*p)
+-	    return;
++	p = strsep(&spec, ";");
++	if (!p || !*p)
++		return;
+ 	depth = simple_strtoul(p, NULL, 10);
+ 	if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
+-		depth != 16 && depth != 24)
+-	    return;
++	    depth != 16 && depth != 24)
++		return;
+ 
+-	if (!(p = strsep(&spec, ";")) || !*p)
+-	    return;
++	p = strsep(&spec, ";");
++	if (!p || !*p)
++		return;
+ 	if (*p == 'i')
+ 		planes = FB_TYPE_INTERLEAVED_PLANES;
+ 	else if (*p == 'p')
+@@ -2876,25 +2874,27 @@ static void __init atafb_setup_ext(char 
+ 	else if (*p == 'n')
+ 		planes = FB_TYPE_PLANES;
+ 	else if (*p == 't')
+-		planes = -1; /* true color */
++		planes = -1;		/* true color */
+ 	else
+ 		return;
+ 
+-
+-	if (!(p = strsep(&spec, ";")) || !*p)
++	p = strsep(&spec, ";");
++	if (!p || !*p)
+ 		return;
+ 	addr = simple_strtoul(p, NULL, 0);
+ 
+-	if (!(p = strsep(&spec, ";")) || !*p)
+-		len = xres*yres*depth/8;
++	p = strsep(&spec, ";");
++	if (!p || !*p)
++		len = xres * yres * depth / 8;
+ 	else
+ 		len = simple_strtoul(p, NULL, 0);
+ 
+-	if ((p = strsep(&spec, ";")) && *p) {
+-		external_vgaiobase=simple_strtoul(p, NULL, 0);
+-	}
++	p = strsep(&spec, ";");
++	if (p && *p)
++		external_vgaiobase = simple_strtoul(p, NULL, 0);
+ 
+-	if ((p = strsep(&spec, ";")) && *p) {
++	p = strsep(&spec, ";");
++	if (p && *p) {
+ 		external_bitspercol = simple_strtoul(p, NULL, 0);
+ 		if (external_bitspercol > 8)
+ 			external_bitspercol = 8;
+@@ -2902,59 +2902,61 @@ static void __init atafb_setup_ext(char 
+ 			external_bitspercol = 1;
+ 	}
+ 
+-	if ((p = strsep(&spec, ";")) && *p) {
++	p = strsep(&spec, ";");
++	if (p && *p) {
+ 		if (!strcmp(p, "vga"))
+ 			external_card_type = IS_VGA;
+ 		if (!strcmp(p, "mv300"))
+ 			external_card_type = IS_MV300;
+ 	}
+ 
+-	if ((p = strsep(&spec, ";")) && *p) {
++	p = strsep(&spec, ";");
++	if (p && *p) {
+ 		xres_virtual = simple_strtoul(p, NULL, 10);
+ 		if (xres_virtual < xres)
+ 			xres_virtual = xres;
+-		if (xres_virtual*yres*depth/8 > len)
+-			len=xres_virtual*yres*depth/8;
++		if (xres_virtual * yres * depth / 8 > len)
++			len = xres_virtual * yres * depth / 8;
+ 	}
+ 
+-	external_xres  = xres;
+-	external_xres_virtual  = xres_virtual;
+-	external_yres  = yres;
++	external_xres = xres;
++	external_xres_virtual = xres_virtual;
++	external_yres = yres;
+ 	external_depth = depth;
+ 	external_pmode = planes;
+-	external_addr  = (void *)addr;
+-	external_len   = len;
++	external_addr = (void *)addr;
++	external_len = len;
+ 
+-	if (external_card_type == IS_MV300)
+-	  switch (external_depth) {
+-	    case 1:
+-	      MV300_reg = MV300_reg_1bit;
+-	      break;
+-	    case 4:
+-	      MV300_reg = MV300_reg_4bit;
+-	      break;
+-	    case 8:
+-	      MV300_reg = MV300_reg_8bit;
+-	      break;
+-	    }
++	if (external_card_type == IS_MV300) {
++		switch (external_depth) {
++		case 1:
++			MV300_reg = MV300_reg_1bit;
++			break;
++		case 4:
++			MV300_reg = MV300_reg_4bit;
++			break;
++		case 8:
++			MV300_reg = MV300_reg_8bit;
++			break;
++		}
++	}
+ }
+ #endif /* ATAFB_EXT */
+ 
+-
+ static void __init atafb_setup_int(char *spec)
+ {
+ 	/* Format to config extended internal video hardware like OverScan:
+-	"internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
+-	Explanation:
+-	<xres>: x-resolution 
+-	<yres>: y-resolution
+-	The following are only needed if you have an overscan which
+-	needs a black border:
+-	<xres_max>: max. length of a line in pixels your OverScan hardware would allow
+-	<yres_max>: max. number of lines your OverScan hardware would allow
+-	<offset>: Offset from physical beginning to visible beginning
+-		  of screen in bytes
+-	*/
++	 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
++	 * Explanation:
++	 * <xres>: x-resolution
++	 * <yres>: y-resolution
++	 * The following are only needed if you have an overscan which
++	 * needs a black border:
++	 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
++	 * <yres_max>: max. number of lines your OverScan hardware would allow
++	 * <offset>: Offset from physical beginning to visible beginning
++	 *	  of screen in bytes
++	 */
+ 	int xres;
+ 	char *p;
+ 
+@@ -2963,23 +2965,19 @@ static void __init atafb_setup_int(char 
+ 	xres = simple_strtoul(p, NULL, 10);
+ 	if (!(p = strsep(&spec, ";")) || !*p)
+ 		return;
+-	sttt_xres=xres;
+-	tt_yres=st_yres=simple_strtoul(p, NULL, 10);
+-	if ((p=strsep(&spec, ";")) && *p) {
+-		sttt_xres_virtual=simple_strtoul(p, NULL, 10);
+-	}
+-	if ((p=strsep(&spec, ";")) && *p) {
+-		sttt_yres_virtual=simple_strtoul(p, NULL, 0);
+-	}
+-	if ((p=strsep(&spec, ";")) && *p) {
+-		ovsc_offset=simple_strtoul(p, NULL, 0);
+-	}
++	sttt_xres = xres;
++	tt_yres = st_yres = simple_strtoul(p, NULL, 10);
++	if ((p = strsep(&spec, ";")) && *p)
++		sttt_xres_virtual = simple_strtoul(p, NULL, 10);
++	if ((p = strsep(&spec, ";")) && *p)
++		sttt_yres_virtual = simple_strtoul(p, NULL, 0);
++	if ((p = strsep(&spec, ";")) && *p)
++		ovsc_offset = simple_strtoul(p, NULL, 0);
+ 
+ 	if (ovsc_offset || (sttt_yres_virtual != st_yres))
+-		use_hwscroll=0;
++		use_hwscroll = 0;
+ }
+ 
+-
+ #ifdef ATAFB_FALCON
+ static void __init atafb_setup_mcap(char *spec)
+ {
+@@ -3018,7 +3016,6 @@ static void __init atafb_setup_mcap(char
+ }
+ #endif /* ATAFB_FALCON */
+ 
+-
+ static void __init atafb_setup_user(char *spec)
+ {
+ 	/* Format of user defined video mode is: <xres>;<yres>;<depth>
+@@ -3026,81 +3023,257 @@ static void __init atafb_setup_user(char
+ 	char *p;
+ 	int xres, yres, depth, temp;
+ 
+-	if (!(p = strsep(&spec, ";")) || !*p)
++	p = strsep(&spec, ";");
++	if (!p || !*p)
+ 		return;
+ 	xres = simple_strtoul(p, NULL, 10);
+-	if (!(p = strsep(&spec, ";")) || !*p)
++	p = strsep(&spec, ";");
++	if (!p || !*p)
+ 		return;
+ 	yres = simple_strtoul(p, NULL, 10);
+-	if (!(p = strsep(&spec, "")) || !*p)
++	p = strsep(&spec, "");
++	if (!p || !*p)
+ 		return;
+ 	depth = simple_strtoul(p, NULL, 10);
+-	if ((temp=get_video_mode("user0"))) {
+-		default_par=temp;
+-		atafb_predefined[default_par-1].xres = xres;
+-		atafb_predefined[default_par-1].yres = yres;
+-		atafb_predefined[default_par-1].bits_per_pixel = depth;
++	temp = get_video_mode("user0");
++	if (temp) {
++		default_par = temp;
++		atafb_predefined[default_par - 1].xres = xres;
++		atafb_predefined[default_par - 1].yres = yres;
++		atafb_predefined[default_par - 1].bits_per_pixel = depth;
+ 	}
+ }
+ 
+-int __init atafb_setup( char *options )
++int __init atafb_setup(char *options)
+ {
+-    char *this_opt;
+-    int temp;
+-
+-    fb_info.fontname[0] = '\0';
++	char *this_opt;
++	int temp;
+ 
+-    if (!options || !*options)
++	if (!options || !*options)
+ 		return 0;
+-    
+-    while ((this_opt = strsep(&options, ",")) != NULL) {	 
+-	if (!*this_opt) continue;
+-	if ((temp=get_video_mode(this_opt)))
+-		default_par=temp;
+-	else if (! strcmp(this_opt, "inverse"))
+-		inverse=1;
+-	else if (!strncmp(this_opt, "font:", 5))
+-	   strcpy(fb_info.fontname, this_opt+5);
+-	else if (! strncmp(this_opt, "hwscroll_",9)) {
+-		hwscroll=simple_strtoul(this_opt+9, NULL, 10);
+-		if (hwscroll < 0)
+-			hwscroll = 0;
+-		if (hwscroll > 200)
+-			hwscroll = 200;
+-	}
++
++	while ((this_opt = strsep(&options, ",")) != NULL) {
++		if (!*this_opt)
++			continue;
++		if ((temp = get_video_mode(this_opt))) {
++			default_par = temp;
++			mode_option = this_opt;
++		} else if (!strcmp(this_opt, "inverse"))
++			inverse = 1;
++		else if (!strncmp(this_opt, "hwscroll_", 9)) {
++			hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
++			if (hwscroll < 0)
++				hwscroll = 0;
++			if (hwscroll > 200)
++				hwscroll = 200;
++		}
+ #ifdef ATAFB_EXT
+-	else if (!strcmp(this_opt,"mv300")) {
+-		external_bitspercol = 8;
+-		external_card_type = IS_MV300;
++		else if (!strcmp(this_opt, "mv300")) {
++			external_bitspercol = 8;
++			external_card_type = IS_MV300;
++		} else if (!strncmp(this_opt, "external:", 9))
++			atafb_setup_ext(this_opt + 9);
++#endif
++		else if (!strncmp(this_opt, "internal:", 9))
++			atafb_setup_int(this_opt + 9);
++#ifdef ATAFB_FALCON
++		else if (!strncmp(this_opt, "eclock:", 7)) {
++			fext.f = simple_strtoul(this_opt + 7, NULL, 10);
++			/* external pixelclock in kHz --> ps */
++			fext.t = 1000000000 / fext.f;
++			fext.f *= 1000;
++		} else if (!strncmp(this_opt, "monitorcap:", 11))
++			atafb_setup_mcap(this_opt + 11);
++#endif
++		else if (!strcmp(this_opt, "keep"))
++			DontCalcRes = 1;
++		else if (!strncmp(this_opt, "R", 1))
++			atafb_setup_user(this_opt + 1);
+ 	}
+-	else if (!strncmp(this_opt,"external:",9))
+-		atafb_setup_ext(this_opt+9);
++	return 0;
++}
++
++int __init atafb_init(void)
++{
++	int pad;
++	int detected_mode;
++	unsigned int defmode = 0;
++	unsigned long mem_req;
++
++#ifndef MODULE
++	char *option = NULL;
++
++	if (fb_get_options("atafb", &option))
++		return -ENODEV;
++	atafb_setup(option);
++#endif
++	printk("atafb_init: start\n");
++
++	if (!MACH_IS_ATARI)
++		return -ENXIO;
++
++	do {
++#ifdef ATAFB_EXT
++		if (external_addr) {
++			printk("atafb_init: initializing external hw\n");
++			fbhw = &ext_switch;
++			atafb_ops.fb_setcolreg = &ext_setcolreg;
++			defmode = DEFMODE_EXT;
++			break;
++		}
++#endif
++#ifdef ATAFB_TT
++		if (ATARIHW_PRESENT(TT_SHIFTER)) {
++			printk("atafb_init: initializing TT hw\n");
++			fbhw = &tt_switch;
++			atafb_ops.fb_setcolreg = &tt_setcolreg;
++			defmode = DEFMODE_TT;
++			break;
++		}
+ #endif
+-	else if (!strncmp(this_opt,"internal:",9))
+-		atafb_setup_int(this_opt+9);
+ #ifdef ATAFB_FALCON
+-	else if (!strncmp(this_opt, "eclock:", 7)) {
+-		fext.f = simple_strtoul(this_opt+7, NULL, 10);
+-		/* external pixelclock in kHz --> ps */
+-		fext.t = 1000000000/fext.f;
+-		fext.f *= 1000;
+-	}
+-	else if (!strncmp(this_opt, "monitorcap:", 11))
+-		atafb_setup_mcap(this_opt+11);
+-#endif
+-	else if (!strcmp(this_opt, "keep"))
+-		DontCalcRes = 1;
+-	else if (!strncmp(this_opt, "R", 1))
+-		atafb_setup_user(this_opt+1);
+-    }
+-    return 0;
++		if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
++			printk("atafb_init: initializing Falcon hw\n");
++			fbhw = &falcon_switch;
++			atafb_ops.fb_setcolreg = &falcon_setcolreg;
++			request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
++			            "framebuffer/modeswitch", falcon_vbl_switcher);
++			defmode = DEFMODE_F30;
++			break;
++		}
++#endif
++#ifdef ATAFB_STE
++		if (ATARIHW_PRESENT(STND_SHIFTER) ||
++		    ATARIHW_PRESENT(EXTD_SHIFTER)) {
++			printk("atafb_init: initializing ST/E hw\n");
++			fbhw = &st_switch;
++			atafb_ops.fb_setcolreg = &stste_setcolreg;
++			defmode = DEFMODE_STE;
++			break;
++		}
++		fbhw = &st_switch;
++		atafb_ops.fb_setcolreg = &stste_setcolreg;
++		printk("Cannot determine video hardware; defaulting to ST(e)\n");
++#else /* ATAFB_STE */
++		/* no default driver included */
++		/* Nobody will ever see this message :-) */
++		panic("Cannot initialize video hardware");
++#endif
++	} while (0);
++
++	/* Multisync monitor capabilities */
++	/* Atari-TOS defaults if no boot option present */
++	if (fb_info.monspecs.hfmin == 0) {
++		fb_info.monspecs.hfmin = 31000;
++		fb_info.monspecs.hfmax = 32000;
++		fb_info.monspecs.vfmin = 58;
++		fb_info.monspecs.vfmax = 62;
++	}
++
++	detected_mode = fbhw->detect();
++	check_default_par(detected_mode);
++#ifdef ATAFB_EXT
++	if (!external_addr) {
++#endif /* ATAFB_EXT */
++		mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
++		mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
++		screen_base = atari_stram_alloc(mem_req, "atafb");
++		if (!screen_base)
++			panic("Cannot allocate screen memory");
++		memset(screen_base, 0, mem_req);
++		pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
++		screen_base += pad;
++		real_screen_base = screen_base + ovsc_offset;
++		screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
++		st_ovsc_switch();
++		if (CPU_IS_040_OR_060) {
++			/* On a '040+, the cache mode of video RAM must be set to
++			 * write-through also for internal video hardware! */
++			cache_push(virt_to_phys(screen_base), screen_len);
++			kernel_set_cachemode(screen_base, screen_len,
++					     IOMAP_WRITETHROUGH);
++		}
++		printk("atafb: screen_base %p real_screen_base %p screen_len %d\n",
++			screen_base, real_screen_base, screen_len);
++#ifdef ATAFB_EXT
++	} else {
++		/* Map the video memory (physical address given) to somewhere
++		 * in the kernel address space.
++		 */
++		external_addr = ioremap_writethrough((unsigned long)external_addr,
++						     external_len);
++		if (external_vgaiobase)
++			external_vgaiobase =
++			  (unsigned long)ioremap(external_vgaiobase, 0x10000);
++		screen_base =
++		real_screen_base = external_addr;
++		screen_len = external_len & PAGE_MASK;
++		memset (screen_base, 0, external_len);
++	}
++#endif /* ATAFB_EXT */
++
++//	strcpy(fb_info.mode->name, "Atari Builtin ");
++	fb_info.fbops = &atafb_ops;
++	// try to set default (detected; requested) var
++	do_fb_set_var(&atafb_predefined[default_par - 1], 1);
++	// reads hw state into current par, which may not be sane yet
++	ata_get_par(&current_par);
++	fb_info.par = &current_par;
++	// tries to read from HW which may not be initialized yet
++	// so set sane var first, then call atafb_set_par
++	atafb_get_var(&fb_info.var, &fb_info);
++	fb_info.flags = FBINFO_FLAG_DEFAULT;
++
++	if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
++			  NUM_TOTAL_MODES, &atafb_modedb[defmode],
++			  fb_info.var.bits_per_pixel)) {
++		return -EINVAL;
++	}
++
++	atafb_set_disp(&fb_info);
++
++	fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
++
++
++	printk("Determined %dx%d, depth %d\n",
++	       fb_info.var.xres, fb_info.var.yres, fb_info.var.bits_per_pixel);
++	if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
++	    (fb_info.var.yres != fb_info.var.yres_virtual))
++		printk("   virtual %dx%d\n", fb_info.var.xres_virtual,
++		       fb_info.var.yres_virtual);
++
++	if (register_framebuffer(&fb_info) < 0) {
++#ifdef ATAFB_EXT
++		if (external_addr) {
++			iounmap(external_addr);
++			external_addr = NULL;
++		}
++		if (external_vgaiobase) {
++			iounmap((void*)external_vgaiobase);
++			external_vgaiobase = 0;
++		}
++#endif
++		return -EINVAL;
++	}
++
++	// FIXME: mode needs setting!
++	//printk("fb%d: %s frame buffer device, using %dK of video memory\n",
++	//       fb_info.node, fb_info.mode->name, screen_len>>10);
++	printk("fb%d: frame buffer device, using %dK of video memory\n",
++	       fb_info.node, screen_len >> 10);
++
++	/* TODO: This driver cannot be unloaded yet */
++	return 0;
+ }
+ 
++module_init(atafb_init);
++
+ #ifdef MODULE
+ MODULE_LICENSE("GPL");
+ 
+-int init_module(void)
++int cleanup_module(void)
+ {
+-	return atafb_init();
++	unregister_framebuffer(&fb_info);
++	return atafb_deinit();
+ }
+ #endif /* MODULE */
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/video/atafb.h
+@@ -0,0 +1,36 @@
++#ifndef _VIDEO_ATAFB_H
++#define _VIDEO_ATAFB_H
++
++void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
++			int dx, int height, int width);
++void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
++			int sy, int sx, int height, int width);
++void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
++			int dy, int dx, u32 width,
++			const u8 *data, u32 bgcolor, u32 fgcolor);
++
++void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
++			     int dx, int height, int width);
++void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
++			     int sy, int sx, int height, int width);
++void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
++			     int dy, int dx, u32 width,
++			     const u8 *data, u32 bgcolor, u32 fgcolor);
++
++void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
++			     int dx, int height, int width);
++void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
++			     int sy, int sx, int height, int width);
++void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
++			     int dy, int dx, u32 width,
++			     const u8 *data, u32 bgcolor, u32 fgcolor);
++
++void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
++			     int dx, int height, int width);
++void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
++			     int sy, int sx, int height, int width);
++void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
++			     int dy, int dx, u32 width,
++			     const u8 *data, u32 bgcolor, u32 fgcolor);
++
++#endif /* _VIDEO_ATAFB_H */
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/video/atafb_iplan2p2.c
+@@ -0,0 +1,293 @@
++/*
++ *  linux/drivers/video/iplan2p2.c -- Low level frame buffer operations for
++ *				      interleaved bitplanes à la Atari (2
++ *				      planes, 2 bytes interleave)
++ *
++ *	Created 5 Apr 1997 by Geert Uytterhoeven
++ *
++ *  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 for
++ *  more details.
++ */
++
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/fb.h>
++
++#include <asm/setup.h>
++
++#include "atafb.h"
++
++#define BPL	2
++#include "atafb_utils.h"
++
++void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line,
++			     int sy, int sx, int dy, int dx,
++			     int height, int width)
++{
++	/*  bmove() has to distinguish two major cases: If both, source and
++	 *  destination, start at even addresses or both are at odd
++	 *  addresses, just the first odd and last even column (if present)
++	 *  require special treatment (memmove_col()). The rest between
++	 *  then can be copied by normal operations, because all adjacent
++	 *  bytes are affected and are to be stored in the same order.
++	 *    The pathological case is when the move should go from an odd
++	 *  address to an even or vice versa. Since the bytes in the plane
++	 *  words must be assembled in new order, it seems wisest to make
++	 *  all movements by memmove_col().
++	 */
++
++	u8 *src, *dst;
++	u32 *s, *d;
++	int w, l , i, j;
++	u_int colsize;
++	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
++
++	colsize = height;
++	if (!((sx ^ dx) & 15)) {
++		/* odd->odd or even->even */
++
++		if (upwards) {
++			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
++			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
++			if (sx & 15) {
++				memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
++				src += BPL * 2;
++				dst += BPL * 2;
++				width -= 8;
++			}
++			w = width >> 4;
++			if (w) {
++				s = (u32 *)src;
++				d = (u32 *)dst;
++				w *= BPL / 2;
++				l = next_line - w * 4;
++				for (j = height; j > 0; j--) {
++					for (i = w; i > 0; i--)
++						*d++ = *s++;
++					s = (u32 *)((u8 *)s + l);
++					d = (u32 *)((u8 *)d + l);
++				}
++			}
++			if (width & 15)
++				memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
++					      0xff00ff00, height, next_line - BPL * 2);
++		} else {
++			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
++			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
++
++			if ((sx + width) & 15) {
++				src -= BPL * 2;
++				dst -= BPL * 2;
++				memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
++				width -= 8;
++			}
++			w = width >> 4;
++			if (w) {
++				s = (u32 *)src;
++				d = (u32 *)dst;
++				w *= BPL / 2;
++				l = next_line - w * 4;
++				for (j = height; j > 0; j--) {
++					for (i = w; i > 0; i--)
++						*--d = *--s;
++					s = (u32 *)((u8 *)s - l);
++					d = (u32 *)((u8 *)d - l);
++				}
++			}
++			if (sx & 15)
++				memmove32_col(dst - (width - 16) / (8 / BPL),
++					      src - (width - 16) / (8 / BPL),
++					      0xff00ff, colsize, -next_line - BPL * 2);
++		}
++	} else {
++		/* odd->even or even->odd */
++		if (upwards) {
++			u32 *src32, *dst32;
++			u32 pval[4], v, v1, mask;
++			int i, j, w, f;
++
++			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
++			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
++
++			mask = 0xff00ff00;
++			f = 0;
++			w = width;
++			if (sx & 15) {
++				f = 1;
++				w += 8;
++			}
++			if ((sx + width) & 15)
++				f |= 2;
++			w >>= 4;
++			for (i = height; i; i--) {
++				src32 = (u32 *)src;
++				dst32 = (u32 *)dst;
++
++				if (f & 1) {
++					pval[0] = (*src32++ << 8) & mask;
++				} else {
++					pval[0] = dst32[0] & mask;
++				}
++
++				for (j = w; j > 0; j--) {
++					v = *src32++;
++					v1 = v & mask;
++					*dst32++ = pval[0] | (v1 >> 8);
++					pval[0] = (v ^ v1) << 8;
++				}
++
++				if (f & 2) {
++					dst32[0] = (dst32[0] & mask) | pval[0];
++				}
++
++				src += next_line;
++				dst += next_line;
++			}
++		} else {
++			u32 *src32, *dst32;
++			u32 pval[4], v, v1, mask;
++			int i, j, w, f;
++
++			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
++			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
++
++			mask = 0xff00ff;
++			f = 0;
++			w = width;
++			if ((dx + width) & 15)
++				f = 1;
++			if (sx & 15) {
++				f |= 2;
++				w += 8;
++			}
++			w >>= 4;
++			for (i = height; i; i--) {
++				src32 = (u32 *)src;
++				dst32 = (u32 *)dst;
++
++				if (f & 1) {
++					pval[0] = dst32[-1] & mask;
++				} else {
++					pval[0] = (*--src32 >> 8) & mask;
++				}
++
++				for (j = w; j > 0; j--) {
++					v = *--src32;
++					v1 = v & mask;
++					*--dst32 = pval[0] | (v1 << 8);
++					pval[0] = (v ^ v1) >> 8;
++				}
++
++				if (!(f & 2)) {
++					dst32[-1] = (dst32[-1] & mask) | pval[0];
++				}
++
++				src -= next_line;
++				dst -= next_line;
++			}
++		}
++	}
++}
++
++void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
++                             int sy, int sx, int height, int width)
++{
++	u32 *dest;
++	int rows, i;
++	u32 cval[4];
++
++	dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
++	if (sx & 15) {
++		u8 *dest8 = (u8 *)dest + 1;
++
++		expand8_col2mask(color, cval);
++
++		for (i = height; i; i--) {
++			fill8_col(dest8, cval);
++			dest8 += next_line;
++		}
++		dest += BPL / 2;
++		width -= 8;
++	}
++
++	expand16_col2mask(color, cval);
++	rows = width >> 4;
++	if (rows) {
++		u32 *d = dest;
++		u32 off = next_line - rows * BPL * 2;
++		for (i = height; i; i--) {
++			d = fill16_col(d, rows, cval);
++			d = (u32 *)((long)d + off);
++		}
++		dest += rows * BPL / 2;
++		width &= 15;
++	}
++
++	if (width) {
++		u8 *dest8 = (u8 *)dest;
++
++		expand8_col2mask(color, cval);
++
++		for (i = height; i; i--) {
++			fill8_col(dest8, cval);
++			dest8 += next_line;
++		}
++	}
++}
++
++void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
++                             int dy, int dx, u32 width,
++                             const u8 *data, u32 bgcolor, u32 fgcolor)
++{
++	u32 *dest;
++	const u16 *data16;
++	int rows;
++	u32 fgm[4], bgm[4], m;
++
++	dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
++	if (dx & 15) {
++		fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
++		dest += BPL / 2;
++		width -= 8;
++	}
++
++	if (width >= 16) {
++		data16 = (const u16 *)data;
++		expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
++
++		for (rows = width / 16; rows; rows--) {
++			u16 d = *data16++;
++			m = d | ((u32)d << 16);
++			*dest++ = (m & fgm[0]) ^ bgm[0];
++		}
++
++		data = (const u8 *)data16;
++		width &= 15;
++	}
++
++	if (width)
++		fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
++}
++
++#ifdef MODULE
++MODULE_LICENSE("GPL");
++
++int init_module(void)
++{
++	return 0;
++}
++
++void cleanup_module(void)
++{
++}
++#endif /* MODULE */
++
++
++    /*
++     *  Visible symbols for modules
++     */
++
++EXPORT_SYMBOL(atafb_iplan2p2_copyarea);
++EXPORT_SYMBOL(atafb_iplan2p2_fillrect);
++EXPORT_SYMBOL(atafb_iplan2p2_linefill);
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/video/atafb_iplan2p4.c
+@@ -0,0 +1,308 @@
++/*
++ *  linux/drivers/video/iplan2p4.c -- Low level frame buffer operations for
++ *				      interleaved bitplanes à la Atari (4
++ *				      planes, 2 bytes interleave)
++ *
++ *	Created 5 Apr 1997 by Geert Uytterhoeven
++ *
++ *  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 for
++ *  more details.
++ */
++
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/fb.h>
++
++#include <asm/setup.h>
++
++#include "atafb.h"
++
++#define BPL	4
++#include "atafb_utils.h"
++
++void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line,
++			     int sy, int sx, int dy, int dx,
++			     int height, int width)
++{
++	/*  bmove() has to distinguish two major cases: If both, source and
++	 *  destination, start at even addresses or both are at odd
++	 *  addresses, just the first odd and last even column (if present)
++	 *  require special treatment (memmove_col()). The rest between
++	 *  then can be copied by normal operations, because all adjacent
++	 *  bytes are affected and are to be stored in the same order.
++	 *    The pathological case is when the move should go from an odd
++	 *  address to an even or vice versa. Since the bytes in the plane
++	 *  words must be assembled in new order, it seems wisest to make
++	 *  all movements by memmove_col().
++	 */
++
++	u8 *src, *dst;
++	u32 *s, *d;
++	int w, l , i, j;
++	u_int colsize;
++	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
++
++	colsize = height;
++	if (!((sx ^ dx) & 15)) {
++		/* odd->odd or even->even */
++
++		if (upwards) {
++			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
++			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
++			if (sx & 15) {
++				memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
++				src += BPL * 2;
++				dst += BPL * 2;
++				width -= 8;
++			}
++			w = width >> 4;
++			if (w) {
++				s = (u32 *)src;
++				d = (u32 *)dst;
++				w *= BPL / 2;
++				l = next_line - w * 4;
++				for (j = height; j > 0; j--) {
++					for (i = w; i > 0; i--)
++						*d++ = *s++;
++					s = (u32 *)((u8 *)s + l);
++					d = (u32 *)((u8 *)d + l);
++				}
++			}
++			if (width & 15)
++				memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
++					      0xff00ff00, height, next_line - BPL * 2);
++		} else {
++			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
++			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
++
++			if ((sx + width) & 15) {
++				src -= BPL * 2;
++				dst -= BPL * 2;
++				memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
++				width -= 8;
++			}
++			w = width >> 4;
++			if (w) {
++				s = (u32 *)src;
++				d = (u32 *)dst;
++				w *= BPL / 2;
++				l = next_line - w * 4;
++				for (j = height; j > 0; j--) {
++					for (i = w; i > 0; i--)
++						*--d = *--s;
++					s = (u32 *)((u8 *)s - l);
++					d = (u32 *)((u8 *)d - l);
++				}
++			}
++			if (sx & 15)
++				memmove32_col(dst - (width - 16) / (8 / BPL),
++					      src - (width - 16) / (8 / BPL),
++					      0xff00ff, colsize, -next_line - BPL * 2);
++		}
++	} else {
++		/* odd->even or even->odd */
++		if (upwards) {
++			u32 *src32, *dst32;
++			u32 pval[4], v, v1, mask;
++			int i, j, w, f;
++
++			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
++			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
++
++			mask = 0xff00ff00;
++			f = 0;
++			w = width;
++			if (sx & 15) {
++				f = 1;
++				w += 8;
++			}
++			if ((sx + width) & 15)
++				f |= 2;
++			w >>= 4;
++			for (i = height; i; i--) {
++				src32 = (u32 *)src;
++				dst32 = (u32 *)dst;
++
++				if (f & 1) {
++					pval[0] = (*src32++ << 8) & mask;
++					pval[1] = (*src32++ << 8) & mask;
++				} else {
++					pval[0] = dst32[0] & mask;
++					pval[1] = dst32[1] & mask;
++				}
++
++				for (j = w; j > 0; j--) {
++					v = *src32++;
++					v1 = v & mask;
++					*dst32++ = pval[0] | (v1 >> 8);
++					pval[0] = (v ^ v1) << 8;
++					v = *src32++;
++					v1 = v & mask;
++					*dst32++ = pval[1] | (v1 >> 8);
++					pval[1] = (v ^ v1) << 8;
++				}
++
++				if (f & 2) {
++					dst32[0] = (dst32[0] & mask) | pval[0];
++					dst32[1] = (dst32[1] & mask) | pval[1];
++				}
++
++				src += next_line;
++				dst += next_line;
++			}
++		} else {
++			u32 *src32, *dst32;
++			u32 pval[4], v, v1, mask;
++			int i, j, w, f;
++
++			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
++			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
++
++			mask = 0xff00ff;
++			f = 0;
++			w = width;
++			if ((dx + width) & 15)
++				f = 1;
++			if (sx & 15) {
++				f |= 2;
++				w += 8;
++			}
++			w >>= 4;
++			for (i = height; i; i--) {
++				src32 = (u32 *)src;
++				dst32 = (u32 *)dst;
++
++				if (f & 1) {
++					pval[0] = dst32[-1] & mask;
++					pval[1] = dst32[-2] & mask;
++				} else {
++					pval[0] = (*--src32 >> 8) & mask;
++					pval[1] = (*--src32 >> 8) & mask;
++				}
++
++				for (j = w; j > 0; j--) {
++					v = *--src32;
++					v1 = v & mask;
++					*--dst32 = pval[0] | (v1 << 8);
++					pval[0] = (v ^ v1) >> 8;
++					v = *--src32;
++					v1 = v & mask;
++					*--dst32 = pval[1] | (v1 << 8);
++					pval[1] = (v ^ v1) >> 8;
++				}
++
++				if (!(f & 2)) {
++					dst32[-1] = (dst32[-1] & mask) | pval[0];
++					dst32[-2] = (dst32[-2] & mask) | pval[1];
++				}
++
++				src -= next_line;
++				dst -= next_line;
++			}
++		}
++	}
++}
++
++void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
++                             int sy, int sx, int height, int width)
++{
++	u32 *dest;
++	int rows, i;
++	u32 cval[4];
++
++	dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
++	if (sx & 15) {
++		u8 *dest8 = (u8 *)dest + 1;
++
++		expand8_col2mask(color, cval);
++
++		for (i = height; i; i--) {
++			fill8_col(dest8, cval);
++			dest8 += next_line;
++		}
++		dest += BPL / 2;
++		width -= 8;
++	}
++
++	expand16_col2mask(color, cval);
++	rows = width >> 4;
++	if (rows) {
++		u32 *d = dest;
++		u32 off = next_line - rows * BPL * 2;
++		for (i = height; i; i--) {
++			d = fill16_col(d, rows, cval);
++			d = (u32 *)((long)d + off);
++		}
++		dest += rows * BPL / 2;
++		width &= 15;
++	}
++
++	if (width) {
++		u8 *dest8 = (u8 *)dest;
++
++		expand8_col2mask(color, cval);
++
++		for (i = height; i; i--) {
++			fill8_col(dest8, cval);
++			dest8 += next_line;
++		}
++	}
++}
++
++void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
++                             int dy, int dx, u32 width,
++                             const u8 *data, u32 bgcolor, u32 fgcolor)
++{
++	u32 *dest;
++	const u16 *data16;
++	int rows;
++	u32 fgm[4], bgm[4], m;
++
++	dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
++	if (dx & 15) {
++		fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
++		dest += BPL / 2;
++		width -= 8;
++	}
++
++	if (width >= 16) {
++		data16 = (const u16 *)data;
++		expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
++
++		for (rows = width / 16; rows; rows--) {
++			u16 d = *data16++;
++			m = d | ((u32)d << 16);
++			*dest++ = (m & fgm[0]) ^ bgm[0];
++			*dest++ = (m & fgm[1]) ^ bgm[1];
++		}
++
++		data = (const u8 *)data16;
++		width &= 15;
++	}
++
++	if (width)
++		fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
++}
++
++#ifdef MODULE
++MODULE_LICENSE("GPL");
++
++int init_module(void)
++{
++	return 0;
++}
++
++void cleanup_module(void)
++{
++}
++#endif /* MODULE */
++
++
++    /*
++     *  Visible symbols for modules
++     */
++
++EXPORT_SYMBOL(atafb_iplan2p4_copyarea);
++EXPORT_SYMBOL(atafb_iplan2p4_fillrect);
++EXPORT_SYMBOL(atafb_iplan2p4_linefill);
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/video/atafb_iplan2p8.c
+@@ -0,0 +1,345 @@
++/*
++ *  linux/drivers/video/iplan2p8.c -- Low level frame buffer operations for
++ *				      interleaved bitplanes à la Atari (8
++ *				      planes, 2 bytes interleave)
++ *
++ *	Created 5 Apr 1997 by Geert Uytterhoeven
++ *
++ *  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 for
++ *  more details.
++ */
++
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/fb.h>
++
++#include <asm/setup.h>
++
++#include "atafb.h"
++
++#define BPL	8
++#include "atafb_utils.h"
++
++
++/* Copies a 8 plane column from 's', height 'h', to 'd'. */
++
++/* This expands a 8 bit color into two longs for two movepl (8 plane)
++ * operations.
++ */
++
++void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line,
++			     int sy, int sx, int dy, int dx,
++			     int height, int width)
++{
++	/*  bmove() has to distinguish two major cases: If both, source and
++	 *  destination, start at even addresses or both are at odd
++	 *  addresses, just the first odd and last even column (if present)
++	 *  require special treatment (memmove_col()). The rest between
++	 *  then can be copied by normal operations, because all adjacent
++	 *  bytes are affected and are to be stored in the same order.
++	 *    The pathological case is when the move should go from an odd
++	 *  address to an even or vice versa. Since the bytes in the plane
++	 *  words must be assembled in new order, it seems wisest to make
++	 *  all movements by memmove_col().
++	 */
++
++	u8 *src, *dst;
++	u32 *s, *d;
++	int w, l , i, j;
++	u_int colsize;
++	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
++
++	colsize = height;
++	if (!((sx ^ dx) & 15)) {
++		/* odd->odd or even->even */
++
++		if (upwards) {
++			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
++			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
++			if (sx & 15) {
++				memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
++				src += BPL * 2;
++				dst += BPL * 2;
++				width -= 8;
++			}
++			w = width >> 4;
++			if (w) {
++				s = (u32 *)src;
++				d = (u32 *)dst;
++				w *= BPL / 2;
++				l = next_line - w * 4;
++				for (j = height; j > 0; j--) {
++					for (i = w; i > 0; i--)
++						*d++ = *s++;
++					s = (u32 *)((u8 *)s + l);
++					d = (u32 *)((u8 *)d + l);
++				}
++			}
++			if (width & 15)
++				memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
++					      0xff00ff00, height, next_line - BPL * 2);
++		} else {
++			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
++			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
++
++			if ((sx + width) & 15) {
++				src -= BPL * 2;
++				dst -= BPL * 2;
++				memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
++				width -= 8;
++			}
++			w = width >> 4;
++			if (w) {
++				s = (u32 *)src;
++				d = (u32 *)dst;
++				w *= BPL / 2;
++				l = next_line - w * 4;
++				for (j = height; j > 0; j--) {
++					for (i = w; i > 0; i--)
++						*--d = *--s;
++					s = (u32 *)((u8 *)s - l);
++					d = (u32 *)((u8 *)d - l);
++				}
++			}
++			if (sx & 15)
++				memmove32_col(dst - (width - 16) / (8 / BPL),
++					      src - (width - 16) / (8 / BPL),
++					      0xff00ff, colsize, -next_line - BPL * 2);
++		}
++	} else {
++		/* odd->even or even->odd */
++		if (upwards) {
++			u32 *src32, *dst32;
++			u32 pval[4], v, v1, mask;
++			int i, j, w, f;
++
++			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
++			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
++
++			mask = 0xff00ff00;
++			f = 0;
++			w = width;
++			if (sx & 15) {
++				f = 1;
++				w += 8;
++			}
++			if ((sx + width) & 15)
++				f |= 2;
++			w >>= 4;
++			for (i = height; i; i--) {
++				src32 = (u32 *)src;
++				dst32 = (u32 *)dst;
++
++				if (f & 1) {
++					pval[0] = (*src32++ << 8) & mask;
++					pval[1] = (*src32++ << 8) & mask;
++					pval[2] = (*src32++ << 8) & mask;
++					pval[3] = (*src32++ << 8) & mask;
++				} else {
++					pval[0] = dst32[0] & mask;
++					pval[1] = dst32[1] & mask;
++					pval[2] = dst32[2] & mask;
++					pval[3] = dst32[3] & mask;
++				}
++
++				for (j = w; j > 0; j--) {
++					v = *src32++;
++					v1 = v & mask;
++					*dst32++ = pval[0] | (v1 >> 8);
++					pval[0] = (v ^ v1) << 8;
++					v = *src32++;
++					v1 = v & mask;
++					*dst32++ = pval[1] | (v1 >> 8);
++					pval[1] = (v ^ v1) << 8;
++					v = *src32++;
++					v1 = v & mask;
++					*dst32++ = pval[2] | (v1 >> 8);
++					pval[2] = (v ^ v1) << 8;
++					v = *src32++;
++					v1 = v & mask;
++					*dst32++ = pval[3] | (v1 >> 8);
++					pval[3] = (v ^ v1) << 8;
++				}
++
++				if (f & 2) {
++					dst32[0] = (dst32[0] & mask) | pval[0];
++					dst32[1] = (dst32[1] & mask) | pval[1];
++					dst32[2] = (dst32[2] & mask) | pval[2];
++					dst32[3] = (dst32[3] & mask) | pval[3];
++				}
++
++				src += next_line;
++				dst += next_line;
++			}
++		} else {
++			u32 *src32, *dst32;
++			u32 pval[4], v, v1, mask;
++			int i, j, w, f;
++
++			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
++			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
++
++			mask = 0xff00ff;
++			f = 0;
++			w = width;
++			if ((dx + width) & 15)
++				f = 1;
++			if (sx & 15) {
++				f |= 2;
++				w += 8;
++			}
++			w >>= 4;
++			for (i = height; i; i--) {
++				src32 = (u32 *)src;
++				dst32 = (u32 *)dst;
++
++				if (f & 1) {
++					pval[0] = dst32[-1] & mask;
++					pval[1] = dst32[-2] & mask;
++					pval[2] = dst32[-3] & mask;
++					pval[3] = dst32[-4] & mask;
++				} else {
++					pval[0] = (*--src32 >> 8) & mask;
++					pval[1] = (*--src32 >> 8) & mask;
++					pval[2] = (*--src32 >> 8) & mask;
++					pval[3] = (*--src32 >> 8) & mask;
++				}
++
++				for (j = w; j > 0; j--) {
++					v = *--src32;
++					v1 = v & mask;
++					*--dst32 = pval[0] | (v1 << 8);
++					pval[0] = (v ^ v1) >> 8;
++					v = *--src32;
++					v1 = v & mask;
++					*--dst32 = pval[1] | (v1 << 8);
++					pval[1] = (v ^ v1) >> 8;
++					v = *--src32;
++					v1 = v & mask;
++					*--dst32 = pval[2] | (v1 << 8);
++					pval[2] = (v ^ v1) >> 8;
++					v = *--src32;
++					v1 = v & mask;
++					*--dst32 = pval[3] | (v1 << 8);
++					pval[3] = (v ^ v1) >> 8;
++				}
++
++				if (!(f & 2)) {
++					dst32[-1] = (dst32[-1] & mask) | pval[0];
++					dst32[-2] = (dst32[-2] & mask) | pval[1];
++					dst32[-3] = (dst32[-3] & mask) | pval[2];
++					dst32[-4] = (dst32[-4] & mask) | pval[3];
++				}
++
++				src -= next_line;
++				dst -= next_line;
++			}
++		}
++	}
++}
++
++void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
++                             int sy, int sx, int height, int width)
++{
++	u32 *dest;
++	int rows, i;
++	u32 cval[4];
++
++	dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
++	if (sx & 15) {
++		u8 *dest8 = (u8 *)dest + 1;
++
++		expand8_col2mask(color, cval);
++
++		for (i = height; i; i--) {
++			fill8_col(dest8, cval);
++			dest8 += next_line;
++		}
++		dest += BPL / 2;
++		width -= 8;
++	}
++
++	expand16_col2mask(color, cval);
++	rows = width >> 4;
++	if (rows) {
++		u32 *d = dest;
++		u32 off = next_line - rows * BPL * 2;
++		for (i = height; i; i--) {
++			d = fill16_col(d, rows, cval);
++			d = (u32 *)((long)d + off);
++		}
++		dest += rows * BPL / 2;
++		width &= 15;
++	}
++
++	if (width) {
++		u8 *dest8 = (u8 *)dest;
++
++		expand8_col2mask(color, cval);
++
++		for (i = height; i; i--) {
++			fill8_col(dest8, cval);
++			dest8 += next_line;
++		}
++	}
++}
++
++void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
++			     int dy, int dx, u32 width,
++			     const u8 *data, u32 bgcolor, u32 fgcolor)
++{
++	u32 *dest;
++	const u16 *data16;
++	int rows;
++	u32 fgm[4], bgm[4], m;
++
++	dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
++	if (dx & 15) {
++		fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
++		dest += BPL / 2;
++		width -= 8;
++	}
++
++	if (width >= 16) {
++		data16 = (const u16 *)data;
++		expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
++
++		for (rows = width / 16; rows; rows--) {
++			u16 d = *data16++;
++			m = d | ((u32)d << 16);
++			*dest++ = (m & fgm[0]) ^ bgm[0];
++			*dest++ = (m & fgm[1]) ^ bgm[1];
++			*dest++ = (m & fgm[2]) ^ bgm[2];
++			*dest++ = (m & fgm[3]) ^ bgm[3];
++		}
++
++		data = (const u8 *)data16;
++		width &= 15;
++	}
++
++	if (width)
++		fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
++}
++
++#ifdef MODULE
++MODULE_LICENSE("GPL");
++
++int init_module(void)
++{
++	return 0;
++}
++
++void cleanup_module(void)
++{
++}
++#endif /* MODULE */
++
++
++    /*
++     *  Visible symbols for modules
++     */
++
++EXPORT_SYMBOL(atafb_iplan2p8_copyarea);
++EXPORT_SYMBOL(atafb_iplan2p8_fillrect);
++EXPORT_SYMBOL(atafb_iplan2p8_linefill);
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/video/atafb_mfb.c
+@@ -0,0 +1,112 @@
++/*
++ *  linux/drivers/video/mfb.c -- Low level frame buffer operations for
++ *				 monochrome
++ *
++ *	Created 5 Apr 1997 by Geert Uytterhoeven
++ *
++ *  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 for
++ *  more details.
++ */
++
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/fb.h>
++
++#include "atafb.h"
++#include "atafb_utils.h"
++
++
++    /*
++     *  Monochrome
++     */
++
++void atafb_mfb_copyarea(struct fb_info *info, u_long next_line,
++			int sy, int sx, int dy, int dx,
++			int height, int width)
++{
++	u8 *src, *dest;
++	u_int rows;
++
++	if (sx == 0 && dx == 0 && width == next_line) {
++		src = (u8 *)info->screen_base + sy * (width >> 3);
++		dest = (u8 *)info->screen_base + dy * (width >> 3);
++		fb_memmove(dest, src, height * (width >> 3));
++	} else if (dy <= sy) {
++		src = (u8 *)info->screen_base + sy * next_line + (sx >> 3);
++		dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3);
++		for (rows = height; rows--;) {
++			fb_memmove(dest, src, width >> 3);
++			src += next_line;
++			dest += next_line;
++		}
++	} else {
++		src = (u8 *)info->screen_base + (sy + height - 1) * next_line + (sx >> 3);
++		dest = (u8 *)info->screen_base + (dy + height - 1) * next_line + (dx >> 3);
++		for (rows = height; rows--;) {
++			fb_memmove(dest, src, width >> 3);
++			src -= next_line;
++			dest -= next_line;
++		}
++	}
++}
++
++void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
++			int sy, int sx, int height, int width)
++{
++	u8 *dest;
++	u_int rows;
++
++	dest = (u8 *)info->screen_base + sy * next_line + (sx >> 3);
++
++	if (sx == 0 && width == next_line) {
++		if (color)
++			fb_memset255(dest, height * (width >> 3));
++		else
++			fb_memclear(dest, height * (width >> 3));
++	} else {
++		for (rows = height; rows--; dest += next_line) {
++			if (color)
++				fb_memset255(dest, width >> 3);
++			else
++				fb_memclear_small(dest, width >> 3);
++		}
++	}
++}
++
++void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
++			int dy, int dx, u32 width,
++			const u8 *data, u32 bgcolor, u32 fgcolor)
++{
++	u8 *dest;
++	u_int rows;
++
++	dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3);
++
++	for (rows = width / 8; rows--; /* check margins */ ) {
++		// use fast_memmove or fb_memmove
++		*dest++ = *data++;
++	}
++}
++
++#ifdef MODULE
++MODULE_LICENSE("GPL");
++
++int init_module(void)
++{
++	return 0;
++}
++
++void cleanup_module(void)
++{
++}
++#endif /* MODULE */
++
++
++    /*
++     *  Visible symbols for modules
++     */
++
++EXPORT_SYMBOL(atafb_mfb_copyarea);
++EXPORT_SYMBOL(atafb_mfb_fillrect);
++EXPORT_SYMBOL(atafb_mfb_linefill);
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/video/atafb_utils.h
+@@ -0,0 +1,400 @@
++#ifndef _VIDEO_ATAFB_UTILS_H
++#define _VIDEO_ATAFB_UTILS_H
++
++/* ================================================================= */
++/*                      Utility Assembler Functions                  */
++/* ================================================================= */
++
++/* ====================================================================== */
++
++/* Those of a delicate disposition might like to skip the next couple of
++ * pages.
++ *
++ * These functions are drop in replacements for memmove and
++ * memset(_, 0, _). However their five instances add at least a kilobyte
++ * to the object file. You have been warned.
++ *
++ * Not a great fan of assembler for the sake of it, but I think
++ * that these routines are at least 10 times faster than their C
++ * equivalents for large blits, and that's important to the lowest level of
++ * a graphics driver. Question is whether some scheme with the blitter
++ * would be faster. I suspect not for simple text system - not much
++ * asynchrony.
++ *
++ * Code is very simple, just gruesome expansion. Basic strategy is to
++ * increase data moved/cleared at each step to 16 bytes to reduce
++ * instruction per data move overhead. movem might be faster still
++ * For more than 15 bytes, we try to align the write direction on a
++ * longword boundary to get maximum speed. This is even more gruesome.
++ * Unaligned read/write used requires 68020+ - think this is a problem?
++ *
++ * Sorry!
++ */
++
++
++/* ++roman: I've optimized Robert's original versions in some minor
++ * aspects, e.g. moveq instead of movel, let gcc choose the registers,
++ * use movem in some places...
++ * For other modes than 1 plane, lots of more such assembler functions
++ * were needed (e.g. the ones using movep or expanding color values).
++ */
++
++/* ++andreas: more optimizations:
++   subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
++   addal is faster than addaw
++   movep is rather expensive compared to ordinary move's
++   some functions rewritten in C for clarity, no speed loss */
++
++static inline void *fb_memclear_small(void *s, size_t count)
++{
++	if (!count)
++		return 0;
++
++	asm volatile ("\n"
++		"	lsr.l	#1,%1 ; jcc 1f ; move.b %2,-(%0)\n"
++		"1:	lsr.l	#1,%1 ; jcc 1f ; move.w %2,-(%0)\n"
++		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0)\n"
++		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n"
++		"1:"
++		: "=a" (s), "=d" (count)
++		: "d" (0), "0" ((char *)s + count), "1" (count));
++	asm volatile ("\n"
++		"	subq.l  #1,%1\n"
++		"	jcs	3f\n"
++		"	move.l	%2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n"
++		"2:	movem.l	%2/%%d4/%%d5/%%d6,-(%0)\n"
++		"	dbra	%1,2b\n"
++		"3:"
++		: "=a" (s), "=d" (count)
++		: "d" (0), "0" (s), "1" (count)
++		: "d4", "d5", "d6"
++		);
++
++	return 0;
++}
++
++
++static inline void *fb_memclear(void *s, size_t count)
++{
++	if (!count)
++		return 0;
++
++	if (count < 16) {
++		asm volatile ("\n"
++			"	lsr.l	#1,%1 ; jcc 1f ; clr.b (%0)+\n"
++			"1:	lsr.l	#1,%1 ; jcc 1f ; clr.w (%0)+\n"
++			"1:	lsr.l	#1,%1 ; jcc 1f ; clr.l (%0)+\n"
++			"1:	lsr.l	#1,%1 ; jcc 1f ; clr.l (%0)+ ; clr.l (%0)+\n"
++			"1:"
++			: "=a" (s), "=d" (count)
++			: "0" (s), "1" (count));
++	} else {
++		long tmp;
++		asm volatile ("\n"
++			"	move.l	%1,%2\n"
++			"	lsr.l	#1,%2 ; jcc 1f ; clr.b (%0)+ ; subq.w #1,%1\n"
++			"	lsr.l	#1,%2 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
++			"	clr.w	(%0)+  ; subq.w  #2,%1 ; jra 2f\n"
++			"1:	lsr.l	#1,%2 ; jcc 2f\n"
++			"	clr.w	(%0)+  ; subq.w  #2,%1\n"
++			"2:	move.w	%1,%2; lsr.l #2,%1 ; jeq 6f\n"
++			"	lsr.l	#1,%1 ; jcc 3f ; clr.l (%0)+\n"
++			"3:	lsr.l	#1,%1 ; jcc 4f ; clr.l (%0)+ ; clr.l (%0)+\n"
++			"4:	subq.l	#1,%1 ; jcs 6f\n"
++			"5:	clr.l	(%0)+; clr.l (%0)+ ; clr.l (%0)+ ; clr.l (%0)+\n"
++			"	dbra	%1,5b ; clr.w %1; subq.l #1,%1; jcc 5b\n"
++			"6:	move.w	%2,%1; btst #1,%1 ; jeq 7f ; clr.w (%0)+\n"
++			"7:	btst	#0,%1 ; jeq 8f ; clr.b (%0)+\n"
++			"8:"
++			: "=a" (s), "=d" (count), "=d" (tmp)
++			: "0" (s), "1" (count));
++	}
++
++	return 0;
++}
++
++
++static inline void *fb_memset255(void *s, size_t count)
++{
++	if (!count)
++		return 0;
++
++	asm volatile ("\n"
++		"	lsr.l	#1,%1 ; jcc 1f ; move.b %2,-(%0)\n"
++		"1:	lsr.l	#1,%1 ; jcc 1f ; move.w %2,-(%0)\n"
++		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0)\n"
++		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n"
++		"1:"
++		: "=a" (s), "=d" (count)
++		: "d" (-1), "0" ((char *)s+count), "1" (count));
++	asm volatile ("\n"
++		"	subq.l	#1,%1 ; jcs 3f\n"
++		"	move.l	%2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n"
++		"2:	movem.l	%2/%%d4/%%d5/%%d6,-(%0)\n"
++		"	dbra	%1,2b\n"
++		"3:"
++		: "=a" (s), "=d" (count)
++		: "d" (-1), "0" (s), "1" (count)
++		: "d4", "d5", "d6");
++
++	return 0;
++}
++
++
++static inline void *fb_memmove(void *d, const void *s, size_t count)
++{
++	if (d < s) {
++		if (count < 16) {
++			asm volatile ("\n"
++				"	lsr.l	#1,%2 ; jcc 1f ; move.b (%1)+,(%0)+\n"
++				"1:	lsr.l	#1,%2 ; jcc 1f ; move.w (%1)+,(%0)+\n"
++				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l (%1)+,(%0)+\n"
++				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n"
++				"1:"
++				: "=a" (d), "=a" (s), "=d" (count)
++				: "0" (d), "1" (s), "2" (count));
++		} else {
++			long tmp;
++			asm volatile ("\n"
++				"	move.l	%0,%3\n"
++				"	lsr.l	#1,%3 ; jcc 1f ; move.b (%1)+,(%0)+ ; subqw #1,%2\n"
++				"	lsr.l	#1,%3 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
++				"	move.w	(%1)+,(%0)+  ; subqw  #2,%2 ; jra 2f\n"
++				"1:	lsr.l   #1,%3 ; jcc 2f\n"
++				"	move.w	(%1)+,(%0)+  ; subqw  #2,%2\n"
++				"2:	move.w	%2,%-; lsr.l #2,%2 ; jeq 6f\n"
++				"	lsr.l	#1,%2 ; jcc 3f ; move.l (%1)+,(%0)+\n"
++				"3:	lsr.l	#1,%2 ; jcc 4f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n"
++				"4:	subq.l	#1,%2 ; jcs 6f\n"
++				"5:	move.l	(%1)+,(%0)+; move.l (%1)+,(%0)+\n"
++				"	move.l	(%1)+,(%0)+; move.l (%1)+,(%0)+\n"
++				"	dbra	%2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n"
++				"6:	move.w	%+,%2; btst #1,%2 ; jeq 7f ; move.w (%1)+,(%0)+\n"
++				"7:	btst	#0,%2 ; jeq 8f ; move.b (%1)+,(%0)+\n"
++				"8:"
++				: "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
++				: "0" (d), "1" (s), "2" (count));
++		}
++	} else {
++		if (count < 16) {
++			asm volatile ("\n"
++				"	lsr.l	#1,%2 ; jcc 1f ; move.b -(%1),-(%0)\n"
++				"1:	lsr.l	#1,%2 ; jcc 1f ; move.w -(%1),-(%0)\n"
++				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l -(%1),-(%0)\n"
++				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n"
++				"1:"
++				: "=a" (d), "=a" (s), "=d" (count)
++				: "0" ((char *) d + count), "1" ((char *) s + count), "2" (count));
++		} else {
++			long tmp;
++
++			asm volatile ("\n"
++				"	move.l	%0,%3\n"
++				"	lsr.l	#1,%3 ; jcc 1f ; move.b -(%1),-(%0) ; subqw #1,%2\n"
++				"	lsr.l	#1,%3 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
++				"	move.w	-(%1),-(%0) ; subqw  #2,%2 ; jra 2f\n"
++				"1:	lsr.l	#1,%3 ; jcc 2f\n"
++				"	move.w	-(%1),-(%0) ; subqw  #2,%2\n"
++				"2:	move.w	%2,%-; lsr.l #2,%2 ; jeq 6f\n"
++				"	lsr.l	#1,%2 ; jcc 3f ; move.l -(%1),-(%0)\n"
++				"3:	lsr.l	#1,%2 ; jcc 4f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n"
++				"4:	subq.l	#1,%2 ; jcs 6f\n"
++				"5:	move.l	-(%1),-(%0); move.l -(%1),-(%0)\n"
++				"	move.l	-(%1),-(%0); move.l -(%1),-(%0)\n"
++				"	dbra	%2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n"
++				"6:	move.w	%+,%2; btst #1,%2 ; jeq 7f ; move.w -(%1),-(%0)\n"
++				"7:	btst	#0,%2 ; jeq 8f ; move.b -(%1),-(%0)\n"
++				"8:"
++				: "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
++				: "0" ((char *) d + count), "1" ((char *) s + count), "2" (count));
++		}
++	}
++
++	return 0;
++}
++
++
++/* ++andreas: Simple and fast version of memmove, assumes size is
++   divisible by 16, suitable for moving the whole screen bitplane */
++static inline void fast_memmove(char *dst, const char *src, size_t size)
++{
++	if (!size)
++		return;
++	if (dst < src)
++		asm volatile ("\n"
++			"1:	movem.l	(%0)+,%%d0/%%d1/%%a0/%%a1\n"
++			"	movem.l	%%d0/%%d1/%%a0/%%a1,%1@\n"
++			"	addq.l	#8,%1; addq.l #8,%1\n"
++			"	dbra	%2,1b\n"
++			"	clr.w	%2; subq.l #1,%2\n"
++			"	jcc	1b"
++			: "=a" (src), "=a" (dst), "=d" (size)
++			: "0" (src), "1" (dst), "2" (size / 16 - 1)
++			: "d0", "d1", "a0", "a1", "memory");
++	else
++		asm volatile ("\n"
++			"1:	subq.l	#8,%0; subq.l #8,%0\n"
++			"	movem.l	%0@,%%d0/%%d1/%%a0/%%a1\n"
++			"	movem.l	%%d0/%%d1/%%a0/%%a1,-(%1)\n"
++			"	dbra	%2,1b\n"
++			"	clr.w	%2; subq.l #1,%2\n"
++			"	jcc 1b"
++			: "=a" (src), "=a" (dst), "=d" (size)
++			: "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
++			: "d0", "d1", "a0", "a1", "memory");
++}
++
++#ifdef BPL
++
++/*
++ * This expands a up to 8 bit color into two longs
++ * for movel operations.
++ */
++static const u32 four2long[] = {
++	0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
++	0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
++	0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
++	0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff,
++};
++
++static inline void expand8_col2mask(u8 c, u32 m[])
++{
++	m[0] = four2long[c & 15];
++#if BPL > 4
++	m[1] = four2long[c >> 4];
++#endif
++}
++
++static inline void expand8_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[])
++{
++	fgm[0] = four2long[fg & 15] ^ (bgm[0] = four2long[bg & 15]);
++#if BPL > 4
++	fgm[1] = four2long[fg >> 4] ^ (bgm[1] = four2long[bg >> 4]);
++#endif
++}
++
++/*
++ * set an 8bit value to a color
++ */
++static inline void fill8_col(u8 *dst, u32 m[])
++{
++	u32 tmp = m[0];
++	dst[0] = tmp;
++	dst[2] = (tmp >>= 8);
++#if BPL > 2
++	dst[4] = (tmp >>= 8);
++	dst[6] = tmp >> 8;
++#endif
++#if BPL > 4
++	tmp = m[1];
++	dst[8] = tmp;
++	dst[10] = (tmp >>= 8);
++	dst[12] = (tmp >>= 8);
++	dst[14] = tmp >> 8;
++#endif
++}
++
++/*
++ * set an 8bit value according to foreground/background color
++ */
++static inline void fill8_2col(u8 *dst, u8 fg, u8 bg, u32 mask)
++{
++	u32 fgm[2], bgm[2], tmp;
++
++	expand8_2col2mask(fg, bg, fgm, bgm);
++
++	mask |= mask << 8;
++#if BPL > 2
++	mask |= mask << 16;
++#endif
++	tmp = (mask & fgm[0]) ^ bgm[0];
++	dst[0] = tmp;
++	dst[2] = (tmp >>= 8);
++#if BPL > 2
++	dst[4] = (tmp >>= 8);
++	dst[6] = tmp >> 8;
++#endif
++#if BPL > 4
++	tmp = (mask & fgm[1]) ^ bgm[1];
++	dst[8] = tmp;
++	dst[10] = (tmp >>= 8);
++	dst[12] = (tmp >>= 8);
++	dst[14] = tmp >> 8;
++#endif
++}
++
++static const u32 two2word[] = {
++	0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
++};
++
++static inline void expand16_col2mask(u8 c, u32 m[])
++{
++	m[0] = two2word[c & 3];
++#if BPL > 2
++	m[1] = two2word[(c >> 2) & 3];
++#endif
++#if BPL > 4
++	m[2] = two2word[(c >> 4) & 3];
++	m[3] = two2word[c >> 6];
++#endif
++}
++
++static inline void expand16_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[])
++{
++	bgm[0] = two2word[bg & 3];
++	fgm[0] = two2word[fg & 3] ^ bgm[0];
++#if BPL > 2
++	bgm[1] = two2word[(bg >> 2) & 3];
++	fgm[1] = two2word[(fg >> 2) & 3] ^ bgm[1];
++#endif
++#if BPL > 4
++	bgm[2] = two2word[(bg >> 4) & 3];
++	fgm[2] = two2word[(fg >> 4) & 3] ^ bgm[2];
++	bgm[3] = two2word[bg >> 6];
++	fgm[3] = two2word[fg >> 6] ^ bgm[3];
++#endif
++}
++
++static inline u32 *fill16_col(u32 *dst, int rows, u32 m[])
++{
++	while (rows) {
++		*dst++ = m[0];
++#if BPL > 2
++		*dst++ = m[1];
++#endif
++#if BPL > 4
++		*dst++ = m[2];
++		*dst++ = m[3];
++#endif
++		rows--;
++	}
++	return dst;
++}
++
++static inline void memmove32_col(void *dst, void *src, u32 mask, u32 h, u32 bytes)
++{
++	u32 *s, *d, v;
++
++        s = src;
++        d = dst;
++        do {
++                v = (*s++ & mask) | (*d  & ~mask);
++                *d++ = v;
++#if BPL > 2
++                v = (*s++ & mask) | (*d  & ~mask);
++                *d++ = v;
++#endif
++#if BPL > 4
++                v = (*s++ & mask) | (*d  & ~mask);
++                *d++ = v;
++                v = (*s++ & mask) | (*d  & ~mask);
++                *d++ = v;
++#endif
++                d = (u32 *)((u8 *)d + bytes);
++                s = (u32 *)((u8 *)s + bytes);
++        } while (--h);
++}
++
++#endif
++
++#endif /* _VIDEO_ATAFB_UTILS_H */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/amiga-a2065-ariadne-stats.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/amiga-a2065-ariadne-stats.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,42 @@
+Subject: [PATCH] m68k: Amiga A2065 and Ariadne TX statistics
+Cc: Jeff Garzik <jgarzik at pobox.com>, netdev at vger.kernel.org
+
+Add missing code to the Amiga A2065 and Ariadne drivers to update
+net_device_stats.tx_bytes.
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/net/a2065.c   |    4 +---
+ drivers/net/ariadne.c |    1 +
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/net/a2065.c
++++ linux-m68k-2.6.21/drivers/net/a2065.c
+@@ -563,7 +563,6 @@ static int lance_start_xmit (struct sk_b
+ 	volatile struct lance_init_block *ib = lp->init_block;
+ 	int entry, skblen, len;
+ 	int status = 0;
+-	static int outs;
+ 	unsigned long flags;
+ 
+ 	skblen = skb->len;
+@@ -608,8 +607,7 @@ static int lance_start_xmit (struct sk_b
+ 	/* Now, give the packet to the lance */
+ 	ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
+ 	lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
+-
+-	outs++;
++	lp->stats.tx_bytes += skblen;
+ 
+ 	if (TX_BUFFS_AVAIL <= 0)
+ 		netif_stop_queue(dev);
+--- linux-m68k-2.6.21.orig/drivers/net/ariadne.c
++++ linux-m68k-2.6.21/drivers/net/ariadne.c
+@@ -677,6 +677,7 @@ static int ariadne_start_xmit(struct sk_
+ 	priv->cur_tx -= TX_RING_SIZE;
+ 	priv->dirty_tx -= TX_RING_SIZE;
+     }
++    priv->stats.tx_bytes += len;
+ 
+     /* Trigger an immediate send poll. */
+     lance->RAP = CSR0;		/* PCnet-ISA Controller Status */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-aranym.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-aranym.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,542 @@
+Subject: [PATCH] m68k: Atari ARAnyM support
+
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+
+This isn't really my kettle of fish, but I post it anyway unless Petr
+complains :-)
+
+This is what makes it possible for me to test 2.6 builds on the
+emulator...
+
+Should be signed off by Petr, really.
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/Kconfig          |   15 ++
+ arch/m68k/Makefile         |    1 
+ arch/m68k/emu/Makefile     |    7 +
+ arch/m68k/emu/natfeat.c    |  113 +++++++++++++++++
+ arch/m68k/emu/nfeth.c      |  292 +++++++++++++++++++++++++++++++++++++++++++++
+ arch/m68k/kernel/setup.c   |    5 
+ drivers/net/Kconfig        |    8 +
+ include/asm-m68k/natfeat.h |   22 +++
+ 8 files changed, 463 insertions(+)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/Kconfig
++++ linux-m68k-2.6.21/arch/m68k/Kconfig
+@@ -260,6 +260,21 @@ config Q40
+ 	  Q60. Select your CPU below.  For 68LC060 don't forget to enable FPU
+ 	  emulation.
+ 
++config NATFEAT
++	bool "ARAnyM emulator support"
++	depends on ATARI
++	help
++	  This option enables support for ARAnyM native features, such as
++	  access to a disk image as /dev/hda. Useful with the ARANYM option.
++
++config NFETH
++	tristate "NatFeat Ethernet support"
++	depends on NET_ETHERNET && NATFEAT
++	help
++	  Say Y to include support for the ARAnyM NatFeat network device
++	  which will emulate a regular ethernet device while presenting an
++	  ethertap device to the host system.
++
+ comment "Processor type"
+ 
+ config M68020
+--- linux-m68k-2.6.21.orig/arch/m68k/Makefile
++++ linux-m68k-2.6.21/arch/m68k/Makefile
+@@ -75,6 +75,7 @@ core-$(CONFIG_MVME16x)		+= arch/m68k/mvm
+ core-$(CONFIG_BVME6000)		+= arch/m68k/bvme6000/
+ core-$(CONFIG_SUN3X)		+= arch/m68k/sun3x/	arch/m68k/sun3/
+ core-$(CONFIG_SUN3)		+= arch/m68k/sun3/	arch/m68k/sun3/prom/
++core-$(CONFIG_NATFEAT)		+= arch/m68k/emu/
+ core-$(CONFIG_M68040)		+= arch/m68k/fpsp040/
+ core-$(CONFIG_M68060)		+= arch/m68k/ifpsp060/
+ core-$(CONFIG_M68KFPU_EMU)	+= arch/m68k/math-emu/
+--- /dev/null
++++ linux-m68k-2.6.21/arch/m68k/emu/Makefile
+@@ -0,0 +1,7 @@
++#
++# Makefile for Linux arch/m68k/emu source directory
++#
++
++obj-y			+= natfeat.o
++
++obj-$(CONFIG_NFETH)	+= nfeth.o
+--- /dev/null
++++ linux-m68k-2.6.21/arch/m68k/emu/natfeat.c
+@@ -0,0 +1,113 @@
++/*
++ * natfeat.c - ARAnyM hardware support via Native Features (natfeats)
++ *
++ * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team
++ *
++ * Reworked for Linux by Roman Zippel <zippel at linux-m68k.org>
++ *
++ * This software may be used and distributed according to the terms of
++ * the GNU General Public License (GPL), incorporated herein by reference.
++ */
++
++#include <linux/types.h>
++#include <linux/console.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <asm/io.h>
++#include <asm/machdep.h>
++#include <asm/natfeat.h>
++
++asm ("\n"
++"	.global nf_get_id,nf_call\n"
++"nf_get_id:\n"
++"	.short	0x7300\n"
++"	rts\n"
++"nf_call:\n"
++"	.short	0x7301\n"
++"	rts\n"
++"1:	moveq.l	#0,%d0\n"
++"	rts\n"
++"	.section __ex_table,\"a\"\n"
++"	.long	nf_get_id,1b\n"
++"	.long	nf_call,1b\n"
++"	.previous");
++
++static int stderr_id;
++
++static void nf_write(struct console *co, const char *str, unsigned int count)
++{
++	char buf[68];
++
++	buf[64] = 0;
++	while (count > 64) {
++		memcpy(buf, str, 64);
++		nf_call(stderr_id, buf);
++		str += 64;
++		count -= 64;
++	}
++	memcpy(buf, str, count);
++	buf[count] = 0;
++	nf_call(stderr_id, buf);
++}
++
++void nfprint(const char *fmt, ...)
++{
++	static char buf[256];
++	va_list ap;
++	int n;
++
++	va_start(ap, fmt);
++	n = vsnprintf(buf, 256, fmt, ap);
++	nf_call(nf_get_id("NF_STDERR"), buf);
++	va_end(ap);
++}
++
++static struct console nf_console_driver = {
++	.name	= "debug",
++	.write	= nf_write,
++	.flags	= CON_PRINTBUFFER,
++	.index	= -1,
++};
++
++static int __init nf_debug_setup(char *arg)
++{
++	if (strcmp(arg, "emu"))
++		return 0;
++
++	stderr_id = nf_get_id("NF_STDERR");
++	if (stderr_id)
++		register_console(&nf_console_driver);
++	return 0;
++}
++
++early_param("debug", nf_debug_setup);
++
++static void nf_poweroff(void)
++{
++	long id = nf_get_id("NF_SHUTDOWN");
++
++	if (id)
++		nf_call(id);
++}
++
++void nf_init(void)
++{
++	unsigned long id, version;
++	char buf[256];
++
++	id = nf_get_id("NF_VERSION");
++	if (!id)
++		return;
++	version = nf_call(id);
++
++	id = nf_get_id("NF_NAME");
++	if (!id)
++		return;
++	nf_call(id, buf, 256);
++	buf[255] = 0;
++
++	printk("NatFeats found (%s, %lu.%lu)\n", buf,
++		version >> 16, version & 0xffff);
++
++	mach_power_off = nf_poweroff;
++}
+--- /dev/null
++++ linux-m68k-2.6.21/arch/m68k/emu/nfeth.c
+@@ -0,0 +1,292 @@
++/*
++ * atari_nfeth.c - ARAnyM ethernet card driver for GNU/Linux
++ *
++ * Copyright (c) 2005 Milan Jurik, Petr Stehlik of ARAnyM dev team
++ *
++ * Based on ARAnyM driver for FreeMiNT written by Standa Opichal
++ *
++ * This software may be used and distributed according to the terms of
++ * the GNU General Public License (GPL), incorporated herein by reference.
++ */
++
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/module.h>
++#include <net/ieee80211.h>
++#include <asm/natfeat.h>
++
++enum {
++	GET_VERSION = 0,	/* no parameters, return NFAPI_VERSION in d0 */
++	XIF_INTLEVEL,		/* no parameters, return Interrupt Level in d0 */
++	XIF_IRQ,		/* acknowledge interrupt from host */
++	XIF_START,		/* (ethX), called on 'ifup', start receiver thread */
++	XIF_STOP,		/* (ethX), called on 'ifdown', stop the thread */
++	XIF_READLENGTH,		/* (ethX), return size of network data block to read */
++	XIF_READBLOCK,		/* (ethX, buffer, size), read block of network data */
++	XIF_WRITEBLOCK,		/* (ethX, buffer, size), write block of network data */
++	XIF_GET_MAC,		/* (ethX, buffer, size), return MAC HW addr in buffer */
++	XIF_GET_IPHOST,		/* (ethX, buffer, size), return IP address of host */
++	XIF_GET_IPATARI,	/* (ethX, buffer, size), return IP address of atari */
++	XIF_GET_NETMASK		/* (ethX, buffer, size), return IP netmask */
++};
++
++#define DRV_NAME	"nfeth"
++#define DRV_VERSION	"0.3"
++#define DRV_RELDATE	"10/12/2005"
++
++#define MAX_UNIT	8
++
++/* These identify the driver base version and may not be removed. */
++static char version[] __devinitdata =
++KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " S.Opichal, M.Jurik, P.Stehlik\n"
++KERN_INFO "  http://aranym.atari.org/\n";
++
++MODULE_AUTHOR("Milan Jurik");
++MODULE_DESCRIPTION("Atari NFeth driver");
++MODULE_LICENSE("GPL");
++/*
++MODULE_PARM(nfeth_debug, "i");
++MODULE_PARM_DESC(nfeth_debug, "nfeth_debug level (1-2)");
++*/
++
++#undef DEBUG
++
++static long nfEtherID;
++static int nfEtherIRQ;
++
++struct nfeth_private {
++	int ethX;
++	struct net_device_stats	stats;
++	spinlock_t lock;
++};
++
++static struct net_device *nfeth_dev[MAX_UNIT];
++
++int nfeth_open(struct net_device *dev);
++int nfeth_stop(struct net_device *dev);
++irqreturn_t nfeth_interrupt(int irq, void *dev_id);
++int nfeth_xmit(struct sk_buff *skb, struct net_device *dev);
++
++int nfeth_open(struct net_device *dev)
++{
++	struct nfeth_private *priv = netdev_priv(dev);
++	int res;
++
++	res = nf_call(nfEtherID + XIF_START, priv->ethX);
++
++	/* Clean statistics */
++	memset(&priv->stats, 0, sizeof(struct net_device_stats));
++	spin_lock_init(&priv->lock);
++
++#ifdef DEBUG
++	printk(DRV_NAME ": open %d\n", res);
++#endif
++
++	/* Ready for data */
++	netif_start_queue(dev);
++
++	return 0;
++}
++
++int nfeth_stop(struct net_device *dev)
++{
++	struct nfeth_private *priv = netdev_priv(dev);
++
++	/* No more data */
++	netif_stop_queue(dev);
++
++	nf_call(nfEtherID + XIF_STOP, priv->ethX);
++
++	return 0;
++}
++
++/*
++ * Read a packet out of the adapter and pass it to the upper layers
++ */
++static inline void recv_packet(struct net_device *dev)
++{
++	struct nfeth_private *priv = netdev_priv(dev);
++	int handled = 0;
++	unsigned short pktlen;
++	struct sk_buff *skb;
++
++	/* read packet length (excluding 32 bit crc) */
++	pktlen = nf_call(nfEtherID + XIF_READLENGTH, priv->ethX);
++
++#ifdef DEBUG
++	printk(DRV_NAME ": recv_packet: %i\n", pktlen);
++#endif
++
++	if (!pktlen) {
++#ifdef DEBUG
++		printk(DRV_NAME ": recv_packet: pktlen == 0\n");
++#endif
++		priv->stats.rx_errors++;
++		return;
++	}
++
++	skb = dev_alloc_skb(pktlen + 2);
++	if (!skb) {
++#ifdef DEBUG
++		printk(DRV_NAME ": recv_packet: out of mem (buf_alloc failed)\n");
++#endif
++		priv->stats.rx_dropped++;
++		return;
++	}
++
++	skb->dev = dev;
++	skb_reserve(skb, 2);		/* 16 Byte align  */
++	skb_put(skb, pktlen);		/* make room */
++	nf_call(nfEtherID + XIF_READBLOCK, priv->ethX, virt_to_phys(skb->data), pktlen);
++
++	skb->protocol = eth_type_trans(skb, dev);
++	netif_rx(skb);
++	dev->last_rx = jiffies;
++	priv->stats.rx_packets++;
++	priv->stats.rx_bytes += pktlen;
++
++	/* and enqueue packet */
++	handled = 1;
++	return;
++}
++
++irqreturn_t nfeth_interrupt(int irq, void *dev_id)
++{
++	int i, m, mask;
++
++	mask = nf_call(nfEtherID + XIF_IRQ, 0);
++	for (i = 0, m = 1; i < MAX_UNIT; m <<= 1, i++) {
++		if (mask & m && nfeth_dev[i]) {
++			recv_packet(nfeth_dev[i]);
++			nf_call(nfEtherID + XIF_IRQ, m);
++		}
++	}
++	return IRQ_HANDLED;
++}
++
++int nfeth_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++	int len;
++	char *data, shortpkt[ETH_ZLEN];
++	struct nfeth_private *priv = netdev_priv(dev);
++
++	data = skb->data;
++	len = skb->len;
++	if (len < ETH_ZLEN) {
++		memset(shortpkt, 0, ETH_ZLEN);
++		memcpy(shortpkt, data, len);
++		data = shortpkt;
++		len = ETH_ZLEN;
++	}
++
++	dev->trans_start = jiffies;
++
++#ifdef DEBUG
++	printk(DRV_NAME ": send %d bytes\n", len);
++#endif
++	nf_call(nfEtherID + XIF_WRITEBLOCK, priv->ethX, virt_to_phys(data), len);
++
++	priv->stats.tx_packets++;
++	priv->stats.tx_bytes += len;
++
++	dev_kfree_skb(skb);
++	return 0;
++}
++
++static void nfeth_tx_timeout(struct net_device *dev)
++{
++	struct nfeth_private *priv = netdev_priv(dev);
++	priv->stats.tx_errors++;
++	netif_wake_queue(dev);
++}
++
++static struct net_device_stats *nfeth_get_stats(struct net_device *dev)
++{
++	struct nfeth_private *priv = netdev_priv(dev);
++	return &priv->stats;
++}
++
++struct net_device * __init nfeth_probe(int unit)
++{
++	struct net_device *dev;
++	struct nfeth_private *priv;
++	char mac[ETH_ALEN], host_ip[32], local_ip[32];
++	int err;
++
++	if (!nf_call(nfEtherID + XIF_GET_MAC, unit, mac, ETH_ALEN))
++		return NULL;
++
++	dev = alloc_etherdev(sizeof(struct nfeth_private));
++	if (!dev)
++		return NULL;
++
++	SET_MODULE_OWNER(dev);
++	dev->irq = nfEtherIRQ;
++	dev->open = nfeth_open;
++	dev->stop = nfeth_stop;
++	dev->hard_start_xmit = nfeth_xmit;
++	dev->tx_timeout = nfeth_tx_timeout;
++	dev->get_stats = nfeth_get_stats;
++	dev->flags |= NETIF_F_NO_CSUM;
++	memcpy(dev->dev_addr, mac, ETH_ALEN);
++
++	priv = netdev_priv(dev);
++	priv->ethX = unit;
++
++	err = register_netdev(dev);
++	if (err) {
++		free_netdev(dev);
++		return NULL;
++	}
++
++	nf_call(nfEtherID + XIF_GET_IPHOST, unit,
++		host_ip, sizeof(host_ip));
++	nf_call(nfEtherID + XIF_GET_IPATARI, unit,
++		local_ip, sizeof(local_ip));
++
++	printk(KERN_INFO "%s: nfeth addr:%s (%s) HWaddr:" MAC_FMT "\n",
++	       dev->name, host_ip, local_ip, MAC_ARG(mac));
++
++	return dev;
++}
++
++int __init nfeth_init(void)
++{
++	long ver;
++	int i;
++
++	nfEtherID = nf_get_id("ETHERNET");
++	if (!nfEtherID)
++		return -ENODEV;
++
++	ver = nf_call(nfEtherID + GET_VERSION);
++	printk("nfeth API %lu\n", ver);
++
++	nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL);
++	if (request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED,
++			"eth emu", nfeth_interrupt)) {
++		printk("nfeth: request for irq %d failed", nfEtherIRQ);
++		return -ENODEV;
++	}
++
++	for (i = 0; i < MAX_UNIT; i++)
++		nfeth_dev[i] = nfeth_probe(i);
++
++	return 0;
++}
++
++void __exit nfeth_cleanup(void)
++{
++	int i;
++
++	for (i = 0; i < MAX_UNIT; i++) {
++		if (nfeth_dev[i]) {
++			unregister_netdev(nfeth_dev[0]);
++			free_netdev(nfeth_dev[0]);
++		}
++	}
++	free_irq(nfEtherIRQ, nfeth_interrupt);
++}
++
++module_init(nfeth_init);
++module_exit(nfeth_cleanup);
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/setup.c
++++ linux-m68k-2.6.21/arch/m68k/kernel/setup.c
+@@ -39,6 +39,7 @@
+ #ifdef CONFIG_SUN3X
+ #include <asm/dvma.h>
+ #endif
++#include <asm/natfeat.h>
+ 
+ unsigned long m68k_machtype;
+ unsigned long m68k_cputype;
+@@ -313,6 +314,10 @@ void __init setup_arch(char **cmdline_p)
+ 		panic("No configuration setup");
+ 	}
+ 
++#ifdef CONFIG_NATFEAT
++	nf_init();
++#endif
++
+ 	paging_init();
+ 
+ #ifndef CONFIG_SUN3
+--- linux-m68k-2.6.21.orig/drivers/net/Kconfig
++++ linux-m68k-2.6.21/drivers/net/Kconfig
+@@ -398,6 +398,14 @@ config ATARI_PAMSNET
+ 	  ACSI port ("ACSI node"). The driver works (has to work...) with a
+ 	  polled I/O scheme, so it's rather slow :-(
+ 
++config ATARI_ETHERNEC
++	tristate "Atari EtherNEC Ethernet support"
++	depends on NET_ETHERNET && ATARI && ATARI_ROM_ISA
++	help
++	  Say Y to include support for the EtherNEC network adapter for the
++	  ROM port. The driver works by polling instead of interrupts, so it
++	  is quite slow.
++
+ config SUN3LANCE
+ 	tristate "Sun3/Sun3x on-board LANCE support"
+ 	depends on NET_ETHERNET && (SUN3 || SUN3X)
+--- /dev/null
++++ linux-m68k-2.6.21/include/asm-m68k/natfeat.h
+@@ -0,0 +1,22 @@
++/*
++ * ARAnyM hardware support via Native Features (natfeats)
++ *
++ * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team
++ *
++ * This software may be used and distributed according to the terms of
++ * the GNU General Public License (GPL), incorporated herein by reference.
++ */
++
++#ifndef _NATFEAT_H
++#define _NATFEAT_H
++
++long nf_get_id(const char *feature_name);
++long nf_call(long id, ...);
++
++void nf_init(void);
++void nf_shutdown(void);
++
++void nfprint(const char *fmt, ...)
++	__attribute__ ((format (printf, 1, 2)));
++
++# endif /* _NATFEAT_H */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-ethernec.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-ethernec.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,1106 @@
+Subject: [PATCH] m68k: Atari EtherNEC driver
+Cc: Jeff Garzik <jgarzik at pobox.com>, netdev at vger.kernel.org
+
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+
+Atari EtherNEC driver
+
+Signed-off-by: Michael Schmitz <schmitz at debian.org>
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/net/Makefile         |    1 
+ drivers/net/Space.c          |    4 
+ drivers/net/atari_ethernec.c | 1057 +++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 1062 insertions(+)
+
+--- linux-m68k-2.6.21.orig/drivers/net/Makefile
++++ linux-m68k-2.6.21/drivers/net/Makefile
+@@ -177,6 +177,7 @@ obj-$(CONFIG_DECLANCE) += declance.o
+ obj-$(CONFIG_ATARILANCE) += atarilance.o
+ obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o
+ obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o
++obj-$(CONFIG_ATARI_ETHERNEC) += atari_ethernec.o 8390.o
+ obj-$(CONFIG_A2065) += a2065.o
+ obj-$(CONFIG_HYDRA) += hydra.o
+ obj-$(CONFIG_ARIADNE) += ariadne.o
+--- linux-m68k-2.6.21.orig/drivers/net/Space.c
++++ linux-m68k-2.6.21/drivers/net/Space.c
+@@ -72,6 +72,7 @@ extern struct net_device *SK_init(int un
+ extern struct net_device *seeq8005_probe(int unit);
+ extern struct net_device *smc_init(int unit);
+ extern struct net_device *atarilance_probe(int unit);
++extern struct net_device *atari_ethernec_probe(int unit);
+ extern struct net_device *sun3lance_probe(int unit);
+ extern struct net_device *sun3_82586_probe(int unit);
+ extern struct net_device *apne_probe(int unit);
+@@ -255,6 +256,9 @@ static struct devprobe2 m68k_probes[] __
+ #ifdef CONFIG_ATARILANCE	/* Lance-based Atari ethernet boards */
+ 	{atarilance_probe, 0},
+ #endif
++#ifdef CONFIG_ATARI_ETHERNEC	/* NE2000 based ROM port ethernet cards */
++	{atari_ethernec_probe, 0},
++#endif
+ #ifdef CONFIG_SUN3LANCE         /* sun3 onboard Lance chip */
+ 	{sun3lance_probe, 0},
+ #endif
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/net/atari_ethernec.c
+@@ -0,0 +1,1057 @@
++/*
++ * atari_ethernec.c: Atari cartridge port ethernet adapter
++ * (C) 2006 Michael Schmitz
++ *
++ * Modified after:
++ */
++
++/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
++/*
++    Written 1992-94 by Donald Becker.
++
++    Copyright 1993 United States Government as represented by the
++    Director, National Security Agency.
++
++    This software may be used and distributed according to the terms
++    of the GNU General Public License, incorporated herein by reference.
++
++    The author may be reached as becker at scyld.com, or C/O
++    Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
++
++    This driver should work with many programmed-I/O 8390-based ethernet
++    boards.  Currently it supports the NE1000, NE2000, many clones,
++    and some Cabletron products.
++
++    Changelog:
++
++    Paul Gortmaker	: use ENISR_RDC to monitor Tx PIO uploads, made
++			  sanity checks and bad clone support optional.
++    Paul Gortmaker	: new reset code, reset card after probe at boot.
++    Paul Gortmaker	: multiple card support for module users.
++    Paul Gortmaker	: Support for PCI ne2k clones, similar to lance.c
++    Paul Gortmaker	: Allow users with bad cards to avoid full probe.
++    Paul Gortmaker	: PCI probe changes, more PCI cards supported.
++    rjohnson at analogic.com : Changed init order so an interrupt will only
++    occur after memory is allocated for dev->priv. Deallocated memory
++    last in cleanup_modue()
++    Richard Guenther    : Added support for ISAPnP cards
++    Paul Gortmaker	: Discontinued PCI support - use ne2k-pci.c instead.
++    Hayato Fujiwara	: Add m32r support.
++
++*/
++
++/*
++ * From the driver distribution kit by Thomas Redelberger:
++ *
++ * Hardware circuit description (see directory ETHERNEC for schematics)
++ *
++ * As there is no reset line on the CP, a resistor and a capacitor are
++ * used to reset the NE card on power up.
++ *
++ * Reading from the NE card is done by a read cycle on the CP at address
++ * /ROM4 + 512*ISA address as the ISA address lines A0-A4 are connected
++ * to CP A9-A13. /ROM4 going low will start the ISA read cycle, enable
++ * the ISA bus buffers of the NE card and start decoding of the ISA IO
++ * address by the NE card. /ROM4 going high ends the cycle and the
++ * processor latches the data.
++ *
++ * Because the CP is read only writing to the NE card must be done with
++ * the trick to read from addresses that stand for the data. Dummy reads
++ * at /ROM3 base address + data*2 + ISA address*512 effect this. You
++ * might wonder why everything appears to be shifted up one bit. There is
++ * no CP "A0" address line. There are the signals /UDS and /LDS instead
++ * typical for the 68000 family. The original design which generated an
++ * "A0" worked on an ST and an STE but did not on a Falcon.
++ *
++ * The falling edge of /ROM3 enables the CP address lines A1-A8 onto the
++ * data bus and starts the ISA write cycle. The rising edge will end the
++ * ISA write cycle and the NE latches the data. The processor will also
++ * see and just read this same data but that is harmless.
++ * Elmar Hilgart reported that the bus buffer IC shall be an TTL F-type
++ * to keep up with the fast cycles on the Falcon.
++ *
++ * Base addresses:
++ * rom4            EQU     $00fa0000       ; ROM4 base address
++ * rom3            EQU     $00fb0000       ; ROM3 base address
++ *
++ */
++
++/* Routines for the NatSemi-based designs (NE[12]000). */
++
++static const char version1[] =
++"ne.c:v1.10 9/23/94 Donald Becker (becker at scyld.com)\n";
++static const char version2[] =
++"atari_ethernec.c 11/10/06 Michael Schmitz (schmitz at debian.org)\n";
++
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/wait.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/isapnp.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/jiffies.h>
++
++#include <asm/system.h>
++#include <asm/atarihw.h>
++#include <asm/atariints.h>
++#include <asm/io.h>
++
++#include "8390.h"
++
++#define DRV_NAME "ethernec"
++
++/* Some defines that people can play with if so inclined. */
++
++/* Do we support clones that don't adhere to 14,15 of the SAprom ? */
++#define SUPPORT_NE_BAD_CLONES
++
++/* Do we perform extra sanity checks on stuff ? */
++/* #define NE_SANITY_CHECK */
++
++/* Do we implement the read before write bugfix ? */
++/* #define NE_RW_BUGFIX */
++
++/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
++/* #define PACKETBUF_MEMSIZE	0x40 */
++
++/* A zero-terminated list of I/O addresses to be probed at boot. */
++#ifndef MODULE
++static unsigned int netcard_portlist[] __initdata = {
++	0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
++};
++#endif
++
++static struct isapnp_device_id isapnp_clone_list[] __initdata = {
++	{	ISAPNP_CARD_ID('A','X','E',0x2011),
++		ISAPNP_VENDOR('A','X','E'), ISAPNP_FUNCTION(0x2011),
++		(long) "NetGear EA201" },
++	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
++		ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216),
++		(long) "NN NE2000" },
++	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
++		ISAPNP_VENDOR('P','N','P'), ISAPNP_FUNCTION(0x80d6),
++		(long) "Generic PNP" },
++	{ }	/* terminate list */
++};
++
++MODULE_DEVICE_TABLE(isapnp, isapnp_clone_list);
++
++#ifdef SUPPORT_NE_BAD_CLONES
++/* A list of bad clones that we none-the-less recognize. */
++static struct { const char *name8, *name16; unsigned char SAprefix[4];}
++bad_clone_list[] __initdata = {
++	{"DE100", "DE200", {0x00, 0xDE, 0x01,}},
++	{"DE120", "DE220", {0x00, 0x80, 0xc8,}},
++	{"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh?  */
++	{"EtherNext UTP8", "EtherNext UTP16", {0x00, 0x00, 0x79}},
++	{"NE1000","NE2000-invalid", {0x00, 0x00, 0xd8}}, /* Ancient real NE1000. */
++	{"NN1000", "NN2000",  {0x08, 0x03, 0x08}}, /* Outlaw no-name clone. */
++	{"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}},  /* Outlaw 4-Dimension cards. */
++	{"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */
++	{"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
++	{"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
++	{"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
++	{"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
++	{"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
++#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
++	{"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}},  /* Toshiba built-in */
++#endif
++	{"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
++	{NULL,}
++};
++#endif
++
++/* ---- No user-serviceable parts below ---- */
++
++#define NE_BASE	 (dev->base_addr)
++#define NE_CMD		0x00
++#define NE_DATAPORT	0x10	/* NatSemi-defined port window offset. */
++#define NE_RESET	0x1f	/* Issue a read to reset, a write to clear. */
++#define NE_IO_EXTENT	0x20
++
++#define NE1SM_START_PG	0x20	/* First page of TX buffer */
++#define NE1SM_STOP_PG	0x40	/* Last page +1 of RX ring */
++#define NESM_START_PG	0x40	/* First page of TX buffer */
++#define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
++
++#if defined(CONFIG_PLAT_MAPPI)
++#  define DCR_VAL 0x4b
++#elif defined(CONFIG_PLAT_OAKS32R)  || \
++   defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938) || \
++   defined(CONFIG_ATARI_ETHERNEC) || defined(CONFIG_ATARI_ETHERNEC_MODULE)
++#  define DCR_VAL 0x48		/* 8-bit mode */
++#else
++#  define DCR_VAL 0x49
++#endif
++
++#if defined(CONFIG_ATARI_ETHERNEC) || defined(CONFIG_ATARI_ETHERNEC_MODULE)
++#  define ETHERNEC_RTL_8019_BASE 0x300
++#  define ETHERNEC_RTL_8019_IRQ IRQ_MFP_TIMD
++#endif
++
++static int ne_probe1(struct net_device *dev, int ioaddr);
++static int ne_probe_isapnp(struct net_device *dev);
++
++static int ne_open(struct net_device *dev);
++static int ne_close(struct net_device *dev);
++
++static void ne_reset_8390(struct net_device *dev);
++static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
++			    int ring_page);
++static void ne_block_input(struct net_device *dev, int count,
++			   struct sk_buff *skb, int ring_offset);
++static void ne_block_output(struct net_device *dev, const int count,
++			    const unsigned char *buf, const int start_page);
++
++
++/*
++ * The Atari ROM port has no interrupt line, so we poll the card instead.
++ */
++
++static int use_poll;
++
++/*
++ * This is used by cleanup, to prevent the module from being unloaded while
++ * intrpt_routine is still in the task queue
++ */
++static wait_queue_head_t WaitQ;
++
++static struct work_struct tqueue;
++
++#ifdef ETHERNEC_USE_POLL
++static struct {
++	struct work_struct poll_queue;
++	struct timer_list poll_timer;
++	struct net_device *dev;
++} poll_ops;
++#endif
++
++static struct net_device *poll_dev = NULL;
++
++static void atari_ethernec_int(unsigned long dev_addr)
++{
++	struct net_device *dev = poll_dev;
++
++	if (!dev) {
++		/* If cleanup wants us to die */
++		if (waitqueue_active(&WaitQ))
++			wake_up(&WaitQ);	/* Now cleanup_module can return */
++		else
++			/* Put ourselves back in the task queue */
++			schedule_delayed_work(&tqueue, 1);
++		return;
++	}
++
++	if (netif_running(dev))
++		ei_interrupt(dev->irq, dev);
++
++	/* If cleanup wants us to die */
++	if (waitqueue_active(&WaitQ))
++		wake_up(&WaitQ);	/* Now cleanup_module can return */
++	else
++		/* Put ourselves back in the task queue */
++		schedule_delayed_work(&tqueue, 0); /* reduced delay from 1 */
++}
++
++#ifdef ETHERNEC_USE_POLL
++static void atari_ethernec_poll_handler(unsigned long dev_addr)
++{
++	struct net_device *dev = poll_dev;
++
++	if (!dev || !dev->poll_controller)
++		return;
++
++	if (netif_running(dev))
++		dev->poll_controller(dev);
++
++	schedule_work(&poll_ops.poll_queue);
++	mod_timer(&poll_ops.poll_timer, jiffies + HZ / 100);
++}
++#endif
++
++static void atari_ethernec_start_poll(struct net_device *dev)
++{
++	poll_dev = dev;
++
++	init_waitqueue_head(&WaitQ);
++
++	INIT_WORK(&tqueue, (void (*)(void *))atari_ethernec_int, dev);
++	schedule_delayed_work(&tqueue, 1);
++#ifdef ETHERNEC_USE_POLL
++	if (!poll_ops.poll_queue.func ||
++	    poll_ops.poll_queue.func == ei_interrupt) {
++		if (!poll_ops.poll_queue.func)
++			INIT_WORK(&poll_ops.poll_queue, ei_interrupt, dev);
++
++		init_timer(&poll_ops.poll_timer);
++		poll_ops.poll_timer.function = atari_ethernec_poll_handler;
++		poll_ops.poll_timer.expires = jiffies + HZ / 5;
++		poll_ops.poll_timer.data = (unsigned long)dev;
++		add_timer(&poll_ops.poll_timer);
++	}
++#endif
++}
++
++static void atari_ethernec_stop_poll(struct net_device *dev)
++{
++	poll_dev = NULL;
++
++	if (dev)
++		sleep_on(&WaitQ);
++
++#ifdef ETHERNEC_USE_POLL
++	if (poll_ops.poll_queue.func == ei_interrupt)
++		del_timer_sync(&poll_ops.poll_timer);
++#endif
++}
++
++
++/*  Probe for various non-shared-memory ethercards.
++
++   NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
++   buffer memory space.  NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
++   the SAPROM, while other supposed NE2000 clones must be detected by their
++   SA prefix.
++
++   Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
++   mode results in doubled values, which can be detected and compensated for.
++
++   The probe is also responsible for initializing the card and filling
++   in the 'dev' and 'ei_status' structures.
++
++   We use the minimum memory size for some ethercard product lines, iff we can't
++   distinguish models.  You can increase the packet buffer size by setting
++   PACKETBUF_MEMSIZE.  Reported Cabletron packet buffer locations are:
++	E1010   starts at 0x100 and ends at 0x2000.
++	E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
++	E2010	 starts at 0x100 and ends at 0x4000.
++	E2010-x starts at 0x100 and ends at 0xffff.
++*/
++
++static int __init do_ne_probe(struct net_device *dev)
++{
++	unsigned int base_addr = dev->base_addr;
++	int rv;
++#ifndef MODULE
++	int orig_irq = dev->irq;
++#endif
++
++	SET_MODULE_OWNER(dev);
++
++	/* First check any supplied i/o locations. User knows best. <cough> */
++	if (base_addr > 0x1ff) {	/* Check a single specified location. */
++		rv = ne_probe1(dev, base_addr);
++		if (!rv && use_poll) {
++			/* Seems we have a valid device here; set up polling routine */
++			poll_dev = dev;
++			atari_ethernec_start_poll(dev);
++		}
++		return rv;
++	} else if (base_addr != 0)	/* Don't probe at all. */
++		return -ENXIO;
++
++	/* Then look for any installed ISAPnP clones */
++	if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
++		return 0;
++
++#ifndef MODULE
++	/* Last resort. The semi-risky ISA auto-probe. */
++	for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
++		int ioaddr = netcard_portlist[base_addr];
++		dev->irq = orig_irq;
++		rv = ne_probe1(dev, ioaddr);
++		if (rv == 0) {
++			if (use_poll) {
++				poll_dev = dev;
++				atari_ethernec_start_poll(dev);
++			}
++			return 0;
++		}
++	}
++#endif
++
++	return -ENODEV;
++}
++
++#ifndef MODULE
++struct net_device * __init atari_ethernec_probe(int unit)
++{
++	struct net_device *dev = alloc_ei_netdev();
++	int err;
++
++	if (!dev)
++		return ERR_PTR(-ENOMEM);
++
++	sprintf(dev->name, "eth%d", unit);
++	netdev_boot_setup_check(dev);
++
++#if defined(CONFIG_ATARI_ETHERNEC)
++	dev->base_addr = ETHERNEC_RTL_8019_BASE;
++	dev->irq = ETHERNEC_RTL_8019_IRQ;
++#endif
++	err = do_ne_probe(dev);
++	if (err)
++		goto out;
++
++	/* Seems we have a valid device here; set up polling routine */
++	return dev;
++out:
++	free_netdev(dev);
++	return ERR_PTR(err);
++}
++#endif
++
++static int __init ne_probe_isapnp(struct net_device *dev)
++{
++	int i;
++
++	for (i = 0; isapnp_clone_list[i].vendor != 0; i++) {
++		struct pnp_dev *idev = NULL;
++
++		while ((idev = pnp_find_dev(NULL,
++					    isapnp_clone_list[i].vendor,
++					    isapnp_clone_list[i].function,
++					    idev))) {
++			/* Avoid already found cards from previous calls */
++			if (pnp_device_attach(idev) < 0)
++				continue;
++			if (pnp_activate_dev(idev) < 0) {
++				pnp_device_detach(idev);
++				continue;
++			}
++			/* if no io and irq, search for next */
++			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
++				pnp_device_detach(idev);
++				continue;
++			}
++			/* found it */
++			dev->base_addr = pnp_port_start(idev, 0);
++			dev->irq = pnp_irq(idev, 0);
++			printk(KERN_INFO "atari_ethernec.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
++			       (char *) isapnp_clone_list[i].driver_data,
++			       dev->base_addr, dev->irq);
++			if (ne_probe1(dev, dev->base_addr) != 0) {	/* Shouldn't happen. */
++				printk(KERN_ERR "atari_ethernec.c: Probe of ISAPnP card at %#lx failed.\n",
++				       dev->base_addr);
++				pnp_device_detach(idev);
++				return -ENXIO;
++			}
++			ei_status.priv = (unsigned long)idev;
++			break;
++		}
++		if (!idev)
++			continue;
++		return 0;
++	}
++
++	return -ENODEV;
++}
++
++static int __init ne_probe1(struct net_device *dev, int ioaddr)
++{
++	int i;
++	unsigned char SA_prom[32];
++	int wordlength = 2;
++	const char *name = NULL;
++	int start_page, stop_page;
++	int neX000, ctron, copam, bad_card;
++	int reg0, ret;
++	static unsigned version_printed;
++
++	if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
++		return -EBUSY;
++
++	reg0 = inb_p(ioaddr);
++	if (reg0 == 0xFF) {
++		ret = -ENODEV;
++		goto err_out;
++	}
++
++	/* Do a preliminary verification that we have a 8390. */
++	{
++		int regd;
++		outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
++		regd = inb_p(ioaddr + 0x0d);
++		outb_p(0xff, ioaddr + 0x0d);
++		outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
++		inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
++		if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
++			outb_p(reg0, ioaddr);
++			outb_p(regd, ioaddr + 0x0d);	/* Restore the old values. */
++			ret = -ENODEV;
++			goto err_out;
++		}
++	}
++
++	if (ei_debug && version_printed++ == 0)
++		printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
++
++	/* A user with a poor card that fails to ack the reset, or that
++	   does not have a valid 0x57,0x57 signature can still use this
++	   without having to recompile. Specifying an i/o address along
++	   with an otherwise unused dev->mem_end value of "0xBAD" will
++	   cause the driver to skip these parts of the probe. */
++
++	bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
++
++	/* Reset card. Who knows what dain-bramaged state it was left in. */
++
++	{
++		unsigned long reset_start_time = jiffies;
++
++		/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
++		outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
++
++		while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0) {
++			if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) {
++				if (bad_card) {
++					printk(" (warning: no reset ack)");
++					break;
++				} else {
++					// MSch: ARAnyM exits here
++					printk(" not found (no reset ack).\n");
++					ret = -ENODEV;
++					goto err_out;
++				}
++			}
++		}
++
++		outb_p(0xff, ioaddr + EN0_ISR);		/* Ack all intr. */
++	}
++
++	/* Read the 16 bytes of station address PROM.
++	   We must first initialize registers, similar to NS8390_init(eifdev, 0).
++	   We can't reliably read the SAPROM address without this.
++	   (I learned the hard way!). */
++	{
++		struct {unsigned char value, offset; } program_seq[] =
++		{
++			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
++			{0x48,	EN0_DCFG},	/* Set byte-wide (0x48) access. */
++			{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
++			{0x00,	EN0_RCNTHI},
++			{0x00,	EN0_IMR},	/* Mask completion irq. */
++			{0xFF,	EN0_ISR},
++			{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
++			{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
++			{32,	EN0_RCNTLO},
++			{0x00,	EN0_RCNTHI},
++			{0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */
++			{0x00,	EN0_RSARHI},
++			{E8390_RREAD+E8390_START, E8390_CMD},
++		};
++
++		for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
++			outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
++
++	}
++	for (i = 0; i < 32 /*sizeof(SA_prom)*/; i += 2) {
++		SA_prom[i] = inb(ioaddr + NE_DATAPORT);
++		SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
++		if (SA_prom[i] != SA_prom[i+1])
++			wordlength = 1;
++	}
++
++	if (wordlength == 2) {
++		for (i = 0; i < 16; i++)
++			SA_prom[i] = SA_prom[i+i];
++		/* We must set the 8390 for word mode. */
++		outb_p(DCR_VAL, ioaddr + EN0_DCFG);
++		start_page = NESM_START_PG;
++
++		/*
++		 * Realtek RTL8019AS datasheet says that the PSTOP register
++		 * shouldn't exceed 0x60 in 8-bit mode.
++		 * This chip can be identified by reading the signature from
++		 * the  remote byte count registers (otherwise write-only)...
++		 */
++		if ((DCR_VAL & 0x01) == 0 &&		/* 8-bit mode */
++		    inb(ioaddr + EN0_RCNTLO) == 0x50 &&
++		    inb(ioaddr + EN0_RCNTHI) == 0x70)
++			stop_page = 0x60;
++		else
++			stop_page = NESM_STOP_PG;
++	} else {
++		start_page = NE1SM_START_PG;
++		stop_page  = NE1SM_STOP_PG;
++	}
++
++#if  defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R)
++	neX000 = ((SA_prom[14] == 0x57 && SA_prom[15] == 0x57)
++		|| (SA_prom[14] == 0x42 && SA_prom[15] == 0x42));
++#else
++	neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57);
++#endif
++	ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
++	copam =  (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
++
++	/* Set up the rest of the parameters. */
++	if (neX000 || bad_card || copam) {
++		name = (wordlength == 2) ? "NE2000" : "NE1000";
++	} else if (ctron) {
++		name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
++		start_page = 0x01;
++		stop_page = (wordlength == 2) ? 0x40 : 0x20;
++	} else {
++#ifdef SUPPORT_NE_BAD_CLONES
++		/* Ack!  Well, there might be a *bad* NE*000 clone there.
++		   Check for total bogus addresses. */
++		for (i = 0; bad_clone_list[i].name8; i++) {
++			if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
++			    SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
++			    SA_prom[2] == bad_clone_list[i].SAprefix[2]) {
++				if (wordlength == 2) {
++					name = bad_clone_list[i].name16;
++				} else {
++					name = bad_clone_list[i].name8;
++				}
++				break;
++			}
++		}
++		if (bad_clone_list[i].name8 == NULL) {
++			printk(" not found (invalid signature %2.2x %2.2x).\n",
++			       SA_prom[14], SA_prom[15]);
++			ret = -ENXIO;
++			goto err_out;
++		}
++#else
++		printk(" not found.\n");
++		ret = -ENXIO;
++		goto err_out;
++#endif
++	}
++
++	if (dev->irq < 2) {
++		unsigned long cookie = probe_irq_on();
++		outb_p(0x50, ioaddr + EN0_IMR);	/* Enable one interrupt. */
++		outb_p(0x00, ioaddr + EN0_RCNTLO);
++		outb_p(0x00, ioaddr + EN0_RCNTHI);
++		outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
++		mdelay(10);		/* wait 10ms for interrupt to propagate */
++		outb_p(0x00, ioaddr + EN0_IMR);		/* Mask it again. */
++		dev->irq = probe_irq_off(cookie);
++		if (ei_debug > 2)
++			printk(" autoirq is %d\n", dev->irq);
++	} else if (dev->irq == 2)
++		/* Fixup for users that don't know that IRQ 2 is really IRQ 9,
++		   or don't know which one to set. */
++		dev->irq = 9;
++
++	/*
++	 * use timer based polling!
++	 */
++	if (! dev->irq) {
++		printk(" failed to detect IRQ line. Assuming irq %d\n",
++		       ETHERNEC_RTL_8019_IRQ);
++		dev->irq = ETHERNEC_RTL_8019_IRQ;
++		/* timer routine set up in atari_ethernec_probe() */
++		if (dev->irq == IRQ_MFP_TIMD) {
++			/* set Timer D data Register */
++			mfp.tim_dt_d = 123;	/* 200 Hz */
++			/* start timer D, div = 1:100 */
++			mfp.tim_ct_cd = (mfp.tim_ct_cd & 0xf0) | 0x6;
++		}
++		ret = request_irq(dev->irq, ei_interrupt, 0, name, dev);
++		if (ret) {
++			printk(" unable to get IRQ %d (errno=%d), polling instead.\n",
++			       dev->irq, ret);
++			use_poll = 1;
++		}
++	} else {
++
++		/* Snarf the interrupt now.  There's no point in waiting since we cannot
++		   share and the board will usually be enabled. */
++		ret = request_irq(dev->irq, ei_interrupt, 0, name, dev);
++		if (ret) {
++			printk(" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
++			goto err_out;
++		}
++	}
++	dev->base_addr = ioaddr;
++
++#ifdef CONFIG_PLAT_MAPPI
++	outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
++		ioaddr + E8390_CMD); /* 0x61 */
++	for (i = 0; i < ETHER_ADDR_LEN; i++) {
++		dev->dev_addr[i] = SA_prom[i] = inb_p(ioaddr + EN1_PHYS_SHIFT(i));
++		printk(" %2.2x", SA_prom[i]);
++	}
++#else
++	for (i = 0; i < ETHER_ADDR_LEN; i++) {
++		printk(" %2.2x", SA_prom[i]);
++		dev->dev_addr[i] = SA_prom[i];
++	}
++#endif
++
++	printk("\n%s: %s found at %#x, using IRQ %d.\n",
++		dev->name, name, ioaddr, dev->irq);
++
++	ei_status.name = name;
++	ei_status.tx_start_page = start_page;
++	ei_status.stop_page = stop_page;
++
++	/* Use 16-bit mode only if this wasn't overridden by DCR_VAL */
++	ei_status.word16 = (wordlength == 2 && (DCR_VAL & 0x01));
++
++	ei_status.rx_start_page = start_page + TX_PAGES;
++#ifdef PACKETBUF_MEMSIZE
++	/* Allow the packet buffer size to be overridden by know-it-alls. */
++	ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
++#endif
++
++	ei_status.reset_8390 = &ne_reset_8390;
++	ei_status.block_input = &ne_block_input;
++	ei_status.block_output = &ne_block_output;
++	ei_status.get_8390_hdr = &ne_get_8390_hdr;
++	ei_status.priv = 0;
++	dev->open = &ne_open;
++	dev->stop = &ne_close;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++	dev->poll_controller = ei_poll;
++#endif
++	NS8390_init(dev, 0);
++
++	ret = register_netdev(dev);
++	if (ret)
++		goto out_irq;
++	return 0;
++
++out_irq:
++	free_irq(dev->irq, dev);
++err_out:
++	release_region(ioaddr, NE_IO_EXTENT);
++	return ret;
++}
++
++static int ne_open(struct net_device *dev)
++{
++	ei_open(dev);
++	return 0;
++}
++
++static int ne_close(struct net_device *dev)
++{
++	if (ei_debug > 1)
++		printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
++	ei_close(dev);
++	return 0;
++}
++
++/* Hard reset the card.  This used to pause for the same period that a
++   8390 reset command required, but that shouldn't be necessary. */
++
++static void ne_reset_8390(struct net_device *dev)
++{
++	unsigned long reset_start_time = jiffies;
++
++	if (ei_debug > 1)
++		printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
++
++	/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
++	outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
++
++	ei_status.txing = 0;
++	ei_status.dmaing = 0;
++
++	/* This check _should_not_ be necessary, omit eventually. */
++	while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) {
++		if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
++			printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n",
++			       dev->name);
++			break;
++		}
++	}
++	outb_p(ENISR_RESET, NE_BASE + EN0_ISR);	/* Ack intr. */
++}
++
++/* Grab the 8390 specific header. Similar to the block_input routine, but
++   we don't need to be concerned with ring wrap as the header will be at
++   the start of a page, so we optimize accordingly. */
++
++static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
++{
++	int nic_base = dev->base_addr;
++
++	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
++
++	if (ei_status.dmaing)
++	{
++		printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
++			"[DMAstat:%d][irqlock:%d].\n",
++			dev->name, ei_status.dmaing, ei_status.irqlock);
++		return;
++	}
++
++	ei_status.dmaing |= 0x01;
++	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
++	outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
++	outb_p(0, nic_base + EN0_RCNTHI);
++	outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */
++	outb_p(ring_page, nic_base + EN0_RSARHI);
++	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
++
++	if (ei_status.word16)
++		insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
++	else
++		insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
++
++	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
++	ei_status.dmaing &= ~0x01;
++
++	le16_to_cpus(&hdr->count);
++}
++
++/* Block input and output, similar to the Crynwr packet driver.  If you
++   are porting to a new ethercard, look at the packet driver source for hints.
++   The NEx000 doesn't share the on-board packet memory -- you have to put
++   the packet out through the "remote DMA" dataport using outb. */
++
++static void ne_block_input(struct net_device *dev, int count,
++			   struct sk_buff *skb, int ring_offset)
++{
++#ifdef NE_SANITY_CHECK
++	int xfer_count = count;
++#endif
++	int nic_base = dev->base_addr;
++	char *buf = skb->data;
++
++	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
++	if (ei_status.dmaing) {
++		printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
++			"[DMAstat:%d][irqlock:%d].\n",
++			dev->name, ei_status.dmaing, ei_status.irqlock);
++		return;
++	}
++	ei_status.dmaing |= 0x01;
++	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
++	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
++	outb_p(count >> 8, nic_base + EN0_RCNTHI);
++	outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
++	outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
++	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
++
++	if (ei_status.word16) {
++		insw(NE_BASE + NE_DATAPORT,buf,count>>1);
++		if (count & 0x01) {
++			buf[count-1] = inb(NE_BASE + NE_DATAPORT);
++#ifdef NE_SANITY_CHECK
++			xfer_count++;
++#endif
++		}
++	} else {
++		insb(NE_BASE + NE_DATAPORT, buf, count);
++	}
++
++#ifdef NE_SANITY_CHECK
++	/* This was for the ALPHA version only, but enough people have
++	   been encountering problems so it is still here.  If you see
++	   this message you either 1) have a slightly incompatible clone
++	   or 2) have noise/speed problems with your bus. */
++
++	if (ei_debug > 1) {
++		/* DMA termination address check... */
++		int addr, tries = 20;
++		do {
++			/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
++			   -- it's broken for Rx on some cards! */
++			int high = inb_p(nic_base + EN0_RSARHI);
++			int low = inb_p(nic_base + EN0_RSARLO);
++			addr = (high << 8) + low;
++			if (((ring_offset + xfer_count) & 0xff) == low)
++				break;
++		} while (--tries > 0);
++		if (tries <= 0)
++			printk(KERN_WARNING "%s: RX transfer address mismatch,"
++				"%#4.4x (expected) vs. %#4.4x (actual).\n",
++				dev->name, ring_offset + xfer_count, addr);
++	}
++#endif
++	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
++	ei_status.dmaing &= ~0x01;
++}
++
++static void ne_block_output(struct net_device *dev, int count,
++			    const unsigned char *buf, const int start_page)
++{
++	int nic_base = NE_BASE;
++	unsigned long dma_start;
++#ifdef NE_SANITY_CHECK
++	int retries = 0;
++#endif
++
++	/* Round the count up for word writes.  Do we need to do this?
++	   What effect will an odd byte count have on the 8390?
++	   I should check someday. */
++
++	if (ei_status.word16 && (count & 0x01))
++		count++;
++
++	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
++	if (ei_status.dmaing) {
++		printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
++			"[DMAstat:%d][irqlock:%d]\n",
++			dev->name, ei_status.dmaing, ei_status.irqlock);
++		return;
++	}
++	ei_status.dmaing |= 0x01;
++	/* We should already be in page 0, but to be safe... */
++	outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
++
++#ifdef NE_SANITY_CHECK
++retry:
++#endif
++
++#ifdef NE8390_RW_BUGFIX
++	/* Handle the read-before-write bug the same way as the
++	   Crynwr packet driver -- the NatSemi method doesn't work.
++	   Actually this doesn't always work either, but if you have
++	   problems with your NEx000 this is better than nothing! */
++
++	outb_p(0x42, nic_base + EN0_RCNTLO);
++	outb_p(0x00,   nic_base + EN0_RCNTHI);
++	outb_p(0x42, nic_base + EN0_RSARLO);
++	outb_p(0x00, nic_base + EN0_RSARHI);
++	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
++	/* Make certain that the dummy read has occurred. */
++	udelay(6);
++#endif
++
++	outb_p(ENISR_RDC, nic_base + EN0_ISR);
++
++	/* Now the normal output. */
++	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
++	outb_p(count >> 8,   nic_base + EN0_RCNTHI);
++	outb_p(0x00, nic_base + EN0_RSARLO);
++	outb_p(start_page, nic_base + EN0_RSARHI);
++
++	outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
++	if (ei_status.word16)
++		outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
++	else
++		outsb(NE_BASE + NE_DATAPORT, buf, count);
++
++	dma_start = jiffies;
++
++#ifdef NE_SANITY_CHECK
++	/* This was for the ALPHA version only, but enough people have
++	   been encountering problems so it is still here. */
++
++	if (ei_debug > 1) {
++		/* DMA termination address check... */
++		int addr, tries = 20;
++		do {
++			int high = inb_p(nic_base + EN0_RSARHI);
++			int low = inb_p(nic_base + EN0_RSARLO);
++			addr = (high << 8) + low;
++			if ((start_page << 8) + count == addr)
++				break;
++		} while (--tries > 0);
++
++		if (tries <= 0) {
++			printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
++				"%#4.4x (expected) vs. %#4.4x (actual).\n",
++				dev->name, (start_page << 8) + count, addr);
++			if (retries++ == 0)
++				goto retry;
++		}
++	}
++#endif
++
++	while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
++		if (time_after(jiffies, dma_start + 2*HZ/100)) {		/* 20ms */
++			printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
++			ne_reset_8390(dev);
++			NS8390_init(dev, 1);
++			break;
++		}
++	}
++
++	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
++	ei_status.dmaing &= ~0x01;
++	return;
++}
++
++
++#ifdef MODULE
++#define MAX_NE_CARDS	4	/* Max number of NE cards per module */
++static struct net_device *dev_ne[MAX_NE_CARDS];
++static int io[MAX_NE_CARDS];
++static int irq[MAX_NE_CARDS];
++static int bad[MAX_NE_CARDS];	/* 0xbad = bad sig or no reset ack */
++
++module_param_array(io, int, NULL, 0);
++module_param_array(irq, int, NULL, 0);
++module_param_array(bad, int, NULL, 0);
++module_param(use_poll, int, 0);
++MODULE_PARM_DESC(io, "I/O base address(es),required");
++MODULE_PARM_DESC(irq, "IRQ number(s)");
++MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
++MODULE_PARM_DESC(use_poll, "Use timer interrupt to poll driver");
++MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
++MODULE_LICENSE("GPL");
++
++/* This is set up so that no ISA autoprobe takes place. We can't guarantee
++that the ne2k probe is the last 8390 based probe to take place (as it
++is at boot) and so the probe will get confused by any other 8390 cards.
++ISA device autoprobes on a running machine are not recommended anyway. */
++
++int __init init_module(void)
++{
++	int this_dev, found = 0;
++
++	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
++		struct net_device *dev = alloc_ei_netdev();
++		if (!dev)
++			break;
++		dev->irq = irq[this_dev];
++		dev->mem_end = bad[this_dev];
++		dev->base_addr = io[this_dev];
++		if (do_ne_probe(dev) == 0) {
++			dev_ne[found++] = dev;
++			continue;
++		}
++		free_netdev(dev);
++		if (found)
++			break;
++		if (io[this_dev] != 0)
++			printk(KERN_WARNING "atari_ethernec.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
++		else
++			printk(KERN_NOTICE "atari_ethernec.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
++		return -ENXIO;
++	}
++	if (found)
++		return 0;
++	return -ENODEV;
++}
++
++static void cleanup_card(struct net_device *dev)
++{
++	struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
++	if (idev)
++		pnp_device_detach(idev);
++	free_irq(dev->irq, dev);
++	release_region(dev->base_addr, NE_IO_EXTENT);
++}
++
++void cleanup_module(void)
++{
++	int this_dev;
++
++	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
++		struct net_device *dev = dev_ne[this_dev];
++		if (dev) {
++			if (use_poll)
++				atari_ethernec_stop_poll(dev);
++			unregister_netdev(dev);
++			cleanup_card(dev);
++			free_netdev(dev);
++		}
++	}
++}
++#endif /* MODULE */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-rom-isa.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-rom-isa.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,340 @@
+Subject: [PATCH] m68k: Atari ROM port ISA adapter support
+
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+
+Atari ROM port ISA adapter support
+
+Signed-off-by: Michael Schmitz <schmitz at debian.org>
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/Kconfig         |   10 ++++
+ include/asm-m68k/io.h     |  101 ++++++++++++++++++++++++++++++++++++++++++++--
+ include/asm-m68k/raw_io.h |   98 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 205 insertions(+), 4 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/Kconfig
++++ linux-m68k-2.6.21/arch/m68k/Kconfig
+@@ -143,6 +143,16 @@ config PCI
+ 	  information about which PCI hardware does work under Linux and which
+ 	  doesn't.
+ 
++config ATARI_ROM_ISA
++	bool "Atari ROM port ISA adapter support"
++	depends on ATARI
++	help
++	  This option enables support for the ROM port ISA adapter used to
++	  operate ISA cards on Atari. Only 8  bit cards are supported, and
++	  no interrupt lines are connected.
++	  The only driver currently using this adapter is the EtherNEC
++	  driver for RTL8019AS based NE2000 compatible network cards.
++
+ config MAC
+ 	bool "Macintosh support"
+ 	depends on !MMU_SUN3
+--- linux-m68k-2.6.21.orig/include/asm-m68k/io.h
++++ linux-m68k-2.6.21/include/asm-m68k/io.h
+@@ -82,9 +82,21 @@ extern unsigned long gg2_isa_base;
+ #endif
+ #endif /* AMIGA_PCMCIA */
+ 
++#ifdef CONFIG_ATARI_ROM_ISA
+ 
++#define enec_isa_read_base  0xfffa0000
++#define enec_isa_write_base 0xfffb0000
+ 
+-#ifdef CONFIG_ISA
++#define ENEC_ISA_IO_B(ioaddr)	(enec_isa_read_base+((((unsigned long)(ioaddr))&0x1F)<<9))
++#define ENEC_ISA_IO_W(ioaddr)	(enec_isa_read_base+((((unsigned long)(ioaddr))&0x1F)<<9))
++#define ENEC_ISA_MEM_B(madr)	(enec_isa_read_base+((((unsigned long)(madr))&0x1F)<<9))
++#define ENEC_ISA_MEM_W(madr)	(enec_isa_read_base+((((unsigned long)(madr))&0x1F)<<9))
++
++#define MULTI_ISA 0
++#endif /* ATARI */
++
++
++#if defined(CONFIG_ISA) || defined(CONFIG_ATARI_ROM_ISA)
+ 
+ #if MULTI_ISA == 0
+ #undef MULTI_ISA
+@@ -93,6 +105,7 @@ extern unsigned long gg2_isa_base;
+ #define Q40_ISA (1)
+ #define GG2_ISA (2)
+ #define AG_ISA  (3)
++#define ENEC_ISA (4)
+ 
+ #if defined(CONFIG_Q40) && !defined(MULTI_ISA)
+ #define ISA_TYPE Q40_ISA
+@@ -106,6 +119,10 @@ extern unsigned long gg2_isa_base;
+ #define ISA_TYPE GG2_ISA
+ #define ISA_SEX  0
+ #endif
++#if defined(CONFIG_ATARI_ROM_ISA) && !defined(MULTI_ISA)
++#define ISA_TYPE ENEC_ISA
++#define ISA_SEX  0
++#endif
+ 
+ #ifdef MULTI_ISA
+ extern int isa_type;
+@@ -133,6 +150,9 @@ static inline u8 __iomem *isa_itb(unsign
+ #ifdef CONFIG_AMIGA_PCMCIA
+     case AG_ISA: return (u8 __iomem *)AG_ISA_IO_B(addr);
+ #endif
++#ifdef CONFIG_ATARI_ROM_ISA
++    case ENEC_ISA: return (u8 __iomem *)ENEC_ISA_IO_B(addr);
++#endif
+     default: return NULL; /* avoid warnings, just in case */
+     }
+ }
+@@ -149,6 +169,9 @@ static inline u16 __iomem *isa_itw(unsig
+ #ifdef CONFIG_AMIGA_PCMCIA
+     case AG_ISA: return (u16 __iomem *)AG_ISA_IO_W(addr);
+ #endif
++#ifdef CONFIG_ATARI_ROM_ISA
++    case ENEC_ISA: return (u16 __iomem *)ENEC_ISA_IO_W(addr);
++#endif
+     default: return NULL; /* avoid warnings, just in case */
+     }
+ }
+@@ -165,6 +188,9 @@ static inline u8 __iomem *isa_mtb(unsign
+ #ifdef CONFIG_AMIGA_PCMCIA
+     case AG_ISA: return (u8 __iomem *)addr;
+ #endif
++#ifdef CONFIG_ATARI_ROM_ISA
++    case ENEC_ISA: return (u8 __iomem *)ENEC_ISA_MEM_B(addr);
++#endif
+     default: return NULL; /* avoid warnings, just in case */
+     }
+ }
+@@ -181,6 +207,9 @@ static inline u16 __iomem *isa_mtw(unsig
+ #ifdef CONFIG_AMIGA_PCMCIA
+     case AG_ISA: return (u16 __iomem *)addr;
+ #endif
++#ifdef CONFIG_ATARI_ROM_ISA
++    case ENEC_ISA: return (u16 __iomem *)ENEC_ISA_MEM_W(addr);
++#endif
+     default: return NULL; /* avoid warnings, just in case */
+     }
+ }
+@@ -200,6 +229,19 @@ static inline u16 __iomem *isa_mtw(unsig
+ 	(ISA_SEX ? out_be16(isa_mtw((unsigned long)(p)),(val))	\
+ 		 : out_le16(isa_mtw((unsigned long)(p)),(val)))
+ 
++#if defined(CONFIG_ATARI_ROM_ISA)
++#define isa_rom_inb(port)      rom_in_8(isa_itb(port))
++#define isa_rom_inw(port)      (ISA_SEX ? rom_in_be16(isa_itw(port)) : rom_in_le16(isa_itw(port)))
++
++#define isa_rom_outb(val,port) rom_out_8(isa_itb(port),(val))
++#define isa_rom_outw(val,port) (ISA_SEX ? rom_out_be16(isa_itw(port),(val)) : rom_out_le16(isa_itw(port),(val)))
++
++#define isa_rom_writeb(val,p)  rom_out_8(isa_mtb((unsigned long)(p)),(val))
++#define isa_rom_writew(val,p)  \
++	(ISA_SEX ? rom_out_be16(isa_mtw((unsigned long)(p)),(val))	\
++		 : rom_out_le16(isa_mtw((unsigned long)(p)),(val)))
++#endif
++
+ static inline void isa_delay(void)
+ {
+   switch(ISA_TYPE)
+@@ -213,6 +255,9 @@ static inline void isa_delay(void)
+ #ifdef CONFIG_AMIGA_PCMCIA
+     case AG_ISA: break;
+ #endif
++#ifdef CONFIG_ATARI_ROM_ISA
++    case ENEC_ISA: break;
++#endif
+     default: break; /* avoid warnings */
+     }
+ }
+@@ -234,10 +279,33 @@ static inline void isa_delay(void)
+ #define isa_outsw(port, buf, nr)    \
+        (ISA_SEX ? raw_outsw(isa_itw(port), (u16 *)(buf), (nr)) :  \
+                   raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
++
++#if defined(CONFIG_ATARI_ROM_ISA)
++#define isa_rom_inb_p(p)	({ u8 _v = isa_rom_inb(p); isa_delay(); _v; })
++#define isa_rom_inw_p(p)	({ u16 _v = isa_rom_inw(p); isa_delay(); _v; })
++#define isa_rom_inl_p(p)	({ u32 _v = isa_rom_inl(p) ;isa_delay(); _v; })
++#define isa_rom_outb_p(v,p)	({ isa_rom_outb((v), (p)); isa_delay(); })
++#define isa_rom_outw_p(v,p)	({ isa_rom_outw((v), (p)); isa_delay(); })
++#define isa_rom_outl_p(v,p)	({ isa_rom_outl((v), (p)); isa_delay(); })
++
++#define isa_rom_insb(port, buf, nr) raw_rom_insb(isa_itb(port), (u8 *)(buf), (nr))
++
++#define isa_rom_insw(port, buf, nr)     \
++       (ISA_SEX ? raw_rom_insw(isa_itw(port), (u16 *)(buf), (nr)) :    \
++                  raw_rom_insw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
++
++#define isa_rom_outsb(port, buf, nr) raw_rom_outsb(isa_itb(port), (u8 *)(buf), (nr))
++
++#define isa_rom_outsw(port, buf, nr)    \
++       (ISA_SEX ? raw_rom_outsw(isa_itw(port), (u16 *)(buf), (nr)) :  \
++                  raw_rom_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
++
++#endif
++
+ #endif  /* CONFIG_ISA */
+ 
+ 
+-#if defined(CONFIG_ISA) && !defined(CONFIG_PCI)
++#if defined(CONFIG_ISA) && !defined(CONFIG_PCI) && !defined(CONFIG_ATARI_ROM_ISA)
+ #define inb     isa_inb
+ #define inb_p   isa_inb_p
+ #define outb    isa_outb
+@@ -306,7 +374,34 @@ static inline void isa_delay(void)
+ #endif
+ #endif /* CONFIG_PCI */
+ 
+-#if !defined(CONFIG_ISA) && !defined(CONFIG_PCI) && defined(CONFIG_HP300)
++#if defined(CONFIG_ATARI_ROM_ISA)
++/*
++ * kernel with both ROM port ISA and IDE compiled in, those have
++ * conflicting defs for in/out. Simply consider port < 1024
++ * ROM port ISA and everything else regular ISA for IDE. read,write not defined
++ * in this case
++ */
++#define inb(port)	((port) < 1024 ? isa_rom_inb(port) : in_8(port))
++#define inb_p(port)	((port) < 1024 ? isa_rom_inb_p(port) : in_8(port))
++#define inw(port)	((port) < 1024 ? isa_rom_inw(port) : in_le16(port))
++#define inw_p(port)	((port) < 1024 ? isa_rom_inw_p(port) : in_le16(port))
++#define inl(port)	((port) < 1024 ? isa_rom_inl(port) : in_le32(port))
++#define inl_p(port)	((port) < 1024 ? isa_rom_inl_p(port) : in_le32(port))
++
++#define outb(val,port)	((port) < 1024 ? isa_rom_outb((val), (port)) : out_8((port), (val)))
++#define outb_p(val,port) ((port) < 1024 ? isa_rom_outb_p((val), (port)) : out_8((port), (val)))
++#define outw(val,port)	((port) < 1024 ? isa_rom_outw((val), (port)) : out_le16((port), (val)))
++#define outw_p(val,port) ((port) < 1024 ? isa_rom_outw_p((val), (port)) : out_le16((port), (val)))
++#define outl(val,port)	((port) < 1024 ? isa_rom_outl((val), (port)) : out_le32((port), (val)))
++#define outl_p(val,port) ((port) < 1024 ? isa_rom_outl_p((val), (port)) : out_le32((port), (val)))
++
++#define insb    isa_rom_insb
++#define insw    isa_rom_insw
++#define outsb   isa_rom_outsb
++#define outsw   isa_rom_outsw
++#endif
++
++#if !defined(CONFIG_ISA) && !defined(CONFIG_PCI) && !defined(CONFIG_ATARI_ROM_ISA) && defined(CONFIG_HP300)
+ /*
+  * We need to define dummy functions otherwise drivers/serial/8250.c doesn't link
+  */
+--- linux-m68k-2.6.21.orig/include/asm-m68k/raw_io.h
++++ linux-m68k-2.6.21/include/asm-m68k/raw_io.h
+@@ -10,7 +10,7 @@
+ 
+ #ifdef __KERNEL__
+ 
+-#include <asm/types.h>
++#include <asm/byteorder.h>
+ 
+ 
+ /* Values for nocacheflag and cmode */
+@@ -54,6 +54,46 @@ extern void __iounmap(void *addr, unsign
+ #define raw_outw(val,port) out_be16((port),(val))
+ #define raw_outl(val,port) out_be32((port),(val))
+ 
++/*
++ * Atari ROM port (cartridge port) ISA adapter, used for the EtherNEC NE2000
++ * network card driver.
++ * The ISA adapter connects address lines A9-A13 to ISA address lines A0-A4,
++ * and hardwires the rest of the ISA addresses for a base address of 0x300.
++ *
++ * Data lines D8-D15 are connected to ISA data lines D0-D7 for reading.
++ * For writes, address lines A1-A8 are latched to ISA data lines D0-D7
++ * (meaning the bit pattern on A1-A8 can be read back as byte).
++ *
++ * Reads and writes are byte only.
++ */
++
++#if defined(CONFIG_ATARI_ROM_ISA)
++#define rom_in_8(addr) \
++	({ u16 __v = (*(__force volatile u16 *) (addr)); __v >>= 8; __v; })
++#define rom_in_be16(addr) \
++	({ u16 __v = (*(__force volatile u16 *) (addr)); __v >>= 8; __v; })
++#define rom_in_be32(addr) \
++	({ u32 __v = (*(__force volatile u32 *) (addr)); __v >>= 8; __v; })
++#define rom_in_le16(addr) \
++	({ u16 __v = le16_to_cpu(*(__force volatile u16 *) (addr)); __v >>= 8; __v; })
++#define rom_in_le32(addr) \
++	({ u32 __v = le32_to_cpu(*(__force volatile u32 *) (addr)); __v >>= 8; __v; })
++
++#define rom_out_8(addr,b)	({u8 __w, __v = (b); __w = ((*(__force volatile u8 *)  ((addr) + 0x10000 + (__v<<1)))); })
++#define rom_out_be16(addr,w)	({u16 __w, __v = (w); __w = ((*(__force volatile u16 *) ((addr) + 0x10000 + (__v<<1)))); })
++#define rom_out_be32(addr,l)	({u32 __w, __v = (l); __w = ((*(__force volatile u32 *) ((addr) + 0x10000 + (__v<<1)))); })
++#define rom_out_le16(addr,w)	({u16 __w, __v = cpu_to_le16(w); __w = ((*(__force volatile u16 *) ((addr) + 0x10000 + (__v<<1)))); })
++#define rom_out_le32(addr,l)	({u32 __w, __v = cpu_to_le32(l); __w = ((*(__force volatile u32 *) ((addr) + 0x10000 + (__v<<1)))); })
++
++#define raw_rom_inb rom_in_8
++#define raw_rom_inw rom_in_be16
++#define raw_rom_inl rom_in_be32
++
++#define raw_rom_outb(val,port) rom_out_8((port),(val))
++#define raw_rom_outw(val,port) rom_out_be16((port),(val))
++#define raw_rom_outl(val,port) rom_out_be32((port),(val))
++#endif /* CONFIG_ATARI_ROM_ISA */
++
+ static inline void raw_insb(volatile u8 __iomem *port, u8 *buf, unsigned int len)
+ {
+ 	unsigned int i;
+@@ -336,6 +376,62 @@ static inline void raw_outsw_swapw(volat
+ 		: "d0", "a0", "a1", "d6");
+ }
+ 
++
++#if defined(CONFIG_ATARI_ROM_ISA)
++static inline void raw_rom_insb(volatile u8 __iomem *port, u8 *buf, unsigned int len)
++{
++	unsigned int i;
++
++	for (i = 0; i < len; i++)
++		*buf++ = rom_in_8(port);
++}
++
++static inline void raw_rom_outsb(volatile u8 __iomem *port, const u8 *buf,
++			     unsigned int len)
++{
++	unsigned int i;
++
++	for (i = 0; i < len; i++)
++		rom_out_8(port, *buf++);
++}
++
++static inline void raw_rom_insw(volatile u16 __iomem *port, u16 *buf,
++				   unsigned int nr)
++{
++	unsigned int i;
++
++	for (i = 0; i < nr; i++)
++		*buf++ = rom_in_be16(port);
++}
++
++static inline void raw_rom_outsw(volatile u16 __iomem *port, const u16 *buf,
++				   unsigned int nr)
++{
++	unsigned int i;
++
++	for (i = 0; i < nr; i++)
++		rom_out_be16(port, *buf++);
++}
++
++static inline void raw_rom_insw_swapw(volatile u16 __iomem *port, u16 *buf,
++				   unsigned int nr)
++{
++	unsigned int i;
++
++	for (i = 0; i < nr; i++)
++		*buf++ = rom_in_le16(port);
++}
++
++static inline void raw_rom_outsw_swapw(volatile u16 __iomem *port, const u16 *buf,
++				   unsigned int nr)
++{
++	unsigned int i;
++
++	for (i = 0; i < nr; i++)
++		rom_out_le16(port, *buf++);
++}
++#endif /* CONFIG_ATARI_ROM_ISA */
++
+ #define __raw_writel raw_outl
+ 
+ #endif /* __KERNEL__ */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-scsi-compile-fixes.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-scsi-compile-fixes.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,340 @@
+Cc: James E.J. Bottomley <James.Bottomley at SteelEye.com>,
+    linux-scsi at vger.kernel.org
+Subject: [PATCH] m68k: Atari SCSI driver compile fixes
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+Atari SCSI driver compile fixes
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/scsi/atari_NCR5380.c |   33 +++++----
+ drivers/scsi/atari_scsi.c    |    6 -
+ drivers/scsi/atari_scsi.h    |  144 ++++++++-----------------------------------
+ 3 files changed, 49 insertions(+), 134 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/scsi/atari_NCR5380.c
++++ linux-m68k-2.6.21/drivers/scsi/atari_NCR5380.c
+@@ -272,8 +272,9 @@ static struct scsi_host_template *the_te
+ 	(struct NCR5380_hostdata *)(in)->hostdata
+ #define	HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata)
+ 
+-#define	NEXT(cmd)	((cmd)->host_scribble)
+-#define	NEXTADDR(cmd)	((Scsi_Cmnd **)&((cmd)->host_scribble))
++#define	NEXT(cmd)		((Scsi_Cmnd *)(cmd)->host_scribble)
++#define	SET_NEXT(cmd,next)	((cmd)->host_scribble = (void *)(next))
++#define	NEXTADDR(cmd)		((Scsi_Cmnd **)&(cmd)->host_scribble)
+ 
+ #define	HOSTNO		instance->host_no
+ #define	H_NO(cmd)	(cmd)->device->host->host_no
+@@ -479,7 +480,7 @@ static void merge_contiguous_buffers(Scs
+ 	     virt_to_phys(page_address(cmd->SCp.buffer[1].page) +
+ 			  cmd->SCp.buffer[1].offset) == endaddr;) {
+ 		MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
+-			   cmd->SCp.buffer[1].address, endaddr);
++			   page_address(cmd->SCp.buffer[1].page), endaddr);
+ #if (NDEBUG & NDEBUG_MERGING)
+ 		++cnt;
+ #endif
+@@ -1002,7 +1003,7 @@ static int NCR5380_queue_command(Scsi_Cm
+ 	 * in a queue
+ 	 */
+ 
+-	NEXT(cmd) = NULL;
++	SET_NEXT(cmd, NULL);
+ 	cmd->scsi_done = done;
+ 
+ 	cmd->result = 0;
+@@ -1034,14 +1035,14 @@ static int NCR5380_queue_command(Scsi_Cm
+ 	}
+ 	if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
+ 		LIST(cmd, hostdata->issue_queue);
+-		NEXT(cmd) = hostdata->issue_queue;
++		SET_NEXT(cmd, hostdata->issue_queue);
+ 		hostdata->issue_queue = cmd;
+ 	} else {
+ 		for (tmp = (Scsi_Cmnd *)hostdata->issue_queue;
+ 		     NEXT(tmp); tmp = NEXT(tmp))
+ 			;
+ 		LIST(cmd, tmp);
+-		NEXT(tmp) = cmd;
++		SET_NEXT(tmp, cmd);
+ 	}
+ 	local_irq_restore(flags);
+ 
+@@ -1149,12 +1150,12 @@ static void NCR5380_main(void *bl)
+ 					local_irq_disable();
+ 					if (prev) {
+ 						REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
+-						NEXT(prev) = NEXT(tmp);
++						SET_NEXT(prev, NEXT(tmp));
+ 					} else {
+ 						REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
+ 						hostdata->issue_queue = NEXT(tmp);
+ 					}
+-					NEXT(tmp) = NULL;
++					SET_NEXT(tmp, NULL);
+ 					falcon_dont_release++;
+ 
+ 					/* reenable interrupts after finding one */
+@@ -1192,7 +1193,7 @@ static void NCR5380_main(void *bl)
+ 					} else {
+ 						local_irq_disable();
+ 						LIST(tmp, hostdata->issue_queue);
+-						NEXT(tmp) = hostdata->issue_queue;
++						SET_NEXT(tmp, hostdata->issue_queue);
+ 						hostdata->issue_queue = tmp;
+ #ifdef SUPPORT_TAGS
+ 						cmd_free_tag(tmp);
+@@ -2295,7 +2296,7 @@ static void NCR5380_information_transfer
+ 
+ 						local_irq_save(flags);
+ 						LIST(cmd,hostdata->issue_queue);
+-						NEXT(cmd) = hostdata->issue_queue;
++						SET_NEXT(cmd, hostdata->issue_queue);
+ 						hostdata->issue_queue = (Scsi_Cmnd *) cmd;
+ 						local_irq_restore(flags);
+ 						QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
+@@ -2357,7 +2358,7 @@ static void NCR5380_information_transfer
+ 					local_irq_save(flags);
+ 					cmd->device->disconnect = 1;
+ 					LIST(cmd,hostdata->disconnected_queue);
+-					NEXT(cmd) = hostdata->disconnected_queue;
++					SET_NEXT(cmd, hostdata->disconnected_queue);
+ 					hostdata->connected = NULL;
+ 					hostdata->disconnected_queue = cmd;
+ 					local_irq_restore(flags);
+@@ -2632,12 +2633,12 @@ static void NCR5380_reselect(struct Scsi
+ 			falcon_dont_release++;
+ 			if (prev) {
+ 				REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
+-				NEXT(prev) = NEXT(tmp);
++				SET_NEXT(prev, NEXT(tmp));
+ 			} else {
+ 				REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp));
+ 				hostdata->disconnected_queue = NEXT(tmp);
+ 			}
+-			NEXT(tmp) = NULL;
++			SET_NEXT(tmp, NULL);
+ 			break;
+ 		}
+ 	}
+@@ -2769,7 +2770,7 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
+ 		if (cmd == tmp) {
+ 			REMOVE(5, *prev, tmp, NEXT(tmp));
+ 			(*prev) = NEXT(tmp);
+-			NEXT(tmp) = NULL;
++			SET_NEXT(tmp, NULL);
+ 			tmp->result = DID_ABORT << 16;
+ 			local_irq_restore(flags);
+ 			ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
+@@ -2844,7 +2845,7 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
+ 				if (cmd == tmp) {
+ 					REMOVE(5, *prev, tmp, NEXT(tmp));
+ 					*prev = NEXT(tmp);
+-					NEXT(tmp) = NULL;
++					SET_NEXT(tmp, NULL);
+ 					tmp->result = DID_ABORT << 16;
+ 					/* We must unlock the tag/LUN immediately here, since the
+ 					 * target goes to BUS FREE and doesn't send us another
+@@ -2965,7 +2966,7 @@ static int NCR5380_bus_reset(Scsi_Cmnd *
+ 
+ 	for (i = 0; (cmd = disconnected_queue); ++i) {
+ 		disconnected_queue = NEXT(cmd);
+-		NEXT(cmd) = NULL;
++		SET_NEXT(cmd, NULL);
+ 		cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
+ 		cmd->scsi_done(cmd);
+ 	}
+--- linux-m68k-2.6.21.orig/drivers/scsi/atari_scsi.c
++++ linux-m68k-2.6.21/drivers/scsi/atari_scsi.c
+@@ -69,9 +69,9 @@
+ 
+ #define NDEBUG (0)
+ 
+-#define NDEBUG_ABORT	0x800000
+-#define NDEBUG_TAGS	0x1000000
+-#define NDEBUG_MERGING	0x2000000
++#define NDEBUG_ABORT		0x00100000
++#define NDEBUG_TAGS		0x00200000
++#define NDEBUG_MERGING		0x00400000
+ 
+ #define AUTOSENSE
+ /* For the Atari version, use only polled IO or REAL_DMA */
+--- linux-m68k-2.6.21.orig/drivers/scsi/atari_scsi.h
++++ linux-m68k-2.6.21/drivers/scsi/atari_scsi.h
+@@ -113,144 +113,58 @@ int atari_scsi_release (struct Scsi_Host
+  *
+  */
+ 
+-#if NDEBUG & NDEBUG_ARBITRATION
++#define dprint(flg, format...)			\
++({						\
++	if (NDEBUG & (flg))			\
++		printk(KERN_DEBUG format);	\
++})
++
+ #define ARB_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define ARB_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_AUTOSENSE
++	dprint(NDEBUG_ARBITRATION, format , ## args)
+ #define ASEN_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define ASEN_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_DMA
++	dprint(NDEBUG_AUTOSENSE, format , ## args)
+ #define DMA_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define DMA_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_HANDSHAKE
++	dprint(NDEBUG_DMA, format , ## args)
+ #define HSH_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define HSH_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_INFORMATION
++	dprint(NDEBUG_HANDSHAKE, format , ## args)
+ #define INF_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define INF_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_INIT
++	dprint(NDEBUG_INFORMATION, format , ## args)
+ #define INI_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define INI_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_INTR
++	dprint(NDEBUG_INIT, format , ## args)
+ #define INT_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define INT_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_LINKED
++	dprint(NDEBUG_INTR, format , ## args)
+ #define LNK_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define LNK_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_MAIN
++	dprint(NDEBUG_LINKED, format , ## args)
+ #define MAIN_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define MAIN_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_NO_DATAOUT
++	dprint(NDEBUG_MAIN, format , ## args)
+ #define NDAT_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define NDAT_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_NO_WRITE
++	dprint(NDEBUG_NO_DATAOUT, format , ## args)
+ #define NWR_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define NWR_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_PIO
++	dprint(NDEBUG_NO_WRITE, format , ## args)
+ #define PIO_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define PIO_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_PSEUDO_DMA
++	dprint(NDEBUG_PIO, format , ## args)
+ #define PDMA_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define PDMA_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_QUEUES
++	dprint(NDEBUG_PSEUDO_DMA, format , ## args)
+ #define QU_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define QU_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_RESELECTION
++	dprint(NDEBUG_QUEUES, format , ## args)
+ #define RSL_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define RSL_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_SELECTION
++	dprint(NDEBUG_RESELECTION, format , ## args)
+ #define SEL_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define SEL_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_USLEEP
++	dprint(NDEBUG_SELECTION, format , ## args)
+ #define USL_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define USL_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_LAST_BYTE_SENT
++	dprint(NDEBUG_USLEEP, format , ## args)
+ #define LBS_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define LBS_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_RESTART_SELECT
++	dprint(NDEBUG_LAST_BYTE_SENT, format , ## args)
+ #define RSS_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define RSS_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_EXTENDED
++	dprint(NDEBUG_RESTART_SELECT, format , ## args)
+ #define EXT_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define EXT_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_ABORT
++	dprint(NDEBUG_EXTENDED, format , ## args)
+ #define ABRT_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define ABRT_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_TAGS
++	dprint(NDEBUG_ABORT, format , ## args)
+ #define TAG_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define TAG_PRINTK(format, args...)
+-#endif
+-#if NDEBUG & NDEBUG_MERGING
++	dprint(NDEBUG_TAGS, format , ## args)
+ #define MER_PRINTK(format, args...) \
+-	printk(KERN_DEBUG format , ## args)
+-#else
+-#define MER_PRINTK(format, args...)
+-#endif
++	dprint(NDEBUG_MERGING, format , ## args)
+ 
+ /* conditional macros for NCR5380_print_{,phase,status} */
+ 

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-scsi-reformat.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari-scsi-reformat.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,5903 @@
+Cc: James E.J. Bottomley <James.Bottomley at SteelEye.com>,
+    linux-scsi at vger.kernel.org
+Subject: [PATCH] m68k: Reformat the Atari SCSI driver
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+Reformat the Atari SCSI driver
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/scsi/atari_NCR5380.c | 4433 +++++++++++++++++++++----------------------
+ drivers/scsi/atari_scsi.c    |  363 +--
+ 2 files changed, 2397 insertions(+), 2399 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/scsi/atari_NCR5380.c
++++ linux-m68k-2.6.21/drivers/scsi/atari_NCR5380.c
+@@ -1,19 +1,19 @@
+-/* 
++/*
+  * NCR 5380 generic driver routines.  These should make it *trivial*
+- * 	to implement 5380 SCSI drivers under Linux with a non-trantor
++ *	to implement 5380 SCSI drivers under Linux with a non-trantor
+  *	architecture.
+  *
+  *	Note that these routines also work with NR53c400 family chips.
+  *
+  * Copyright 1993, Drew Eckhardt
+- *	Visionary Computing 
++ *	Visionary Computing
+  *	(Unix and Linux consulting and custom programming)
+- * 	drew at colorado.edu
++ *	drew at colorado.edu
+  *	+1 (303) 666-5836
+  *
+- * DISTRIBUTION RELEASE 6. 
++ * DISTRIBUTION RELEASE 6.
+  *
+- * For more information, please consult 
++ * For more information, please consult
+  *
+  * NCR 5380 Family
+  * SCSI Protocol Controller
+@@ -57,7 +57,7 @@
+  * - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA
+  *    and USLEEP, because these were messing up readability and will never be
+  *    needed for Atari SCSI.
+- * 
++ *
+  * - I've revised the NCR5380_main() calling scheme (relax the 'main_running'
+  *   stuff), and 'main' is executed in a bottom half if awoken by an
+  *   interrupt.
+@@ -69,21 +69,29 @@
+  */
+ 
+ /*
+- * Further development / testing that should be done : 
+- * 1.  Test linked command handling code after Eric is ready with 
++ * Further development / testing that should be done :
++ * 1.  Test linked command handling code after Eric is ready with
+  *     the high level code.
+  */
+ #include <scsi/scsi_dbg.h>
+ #include <scsi/scsi_transport_spi.h>
+ 
+ #if (NDEBUG & NDEBUG_LISTS)
+-#define LIST(x,y) \
+-  { printk("LINE:%d   Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); \
+-    if ((x)==(y)) udelay(5); }
+-#define REMOVE(w,x,y,z) \
+-  { printk("LINE:%d   Removing: %p->%p  %p->%p \n", __LINE__, \
+-	   (void*)(w), (void*)(x), (void*)(y), (void*)(z)); \
+-    if ((x)==(y)) udelay(5); }
++#define LIST(x, y)						\
++	do {							\
++		printk("LINE:%d   Adding %p to %p\n",		\
++		       __LINE__, (void*)(x), (void*)(y));	\
++		if ((x) == (y))					\
++			udelay(5);				\
++	} while (0)
++#define REMOVE(w, x, y, z)					\
++	do {							\
++		printk("LINE:%d   Removing: %p->%p  %p->%p \n",	\
++		       __LINE__, (void*)(w), (void*)(x),	\
++		       (void*)(y), (void*)(z));			\
++		if ((x) == (y))					\
++			udelay(5);				\
++	} while (0)
+ #else
+ #define LIST(x,y)
+ #define REMOVE(w,x,y,z)
+@@ -103,62 +111,62 @@
+  * more difficult than it has to be.
+  *
+  * Also, many of the SCSI drivers were written before the command queuing
+- * routines were implemented, meaning their implementations of queued 
++ * routines were implemented, meaning their implementations of queued
+  * commands were hacked on rather than designed in from the start.
+  *
+- * When I designed the Linux SCSI drivers I figured that 
++ * When I designed the Linux SCSI drivers I figured that
+  * while having two different SCSI boards in a system might be useful
+  * for debugging things, two of the same type wouldn't be used.
+  * Well, I was wrong and a number of users have mailed me about running
+  * multiple high-performance SCSI boards in a server.
+  *
+- * Finally, when I get questions from users, I have no idea what 
++ * Finally, when I get questions from users, I have no idea what
+  * revision of my driver they are running.
+  *
+  * This driver attempts to address these problems :
+- * This is a generic 5380 driver.  To use it on a different platform, 
++ * This is a generic 5380 driver.  To use it on a different platform,
+  * one simply writes appropriate system specific macros (ie, data
+- * transfer - some PC's will use the I/O bus, 68K's must use 
++ * transfer - some PC's will use the I/O bus, 68K's must use
+  * memory mapped) and drops this file in their 'C' wrapper.
+  *
+- * As far as command queueing, two queues are maintained for 
++ * As far as command queueing, two queues are maintained for
+  * each 5380 in the system - commands that haven't been issued yet,
+- * and commands that are currently executing.  This means that an 
+- * unlimited number of commands may be queued, letting 
+- * more commands propagate from the higher driver levels giving higher 
+- * throughput.  Note that both I_T_L and I_T_L_Q nexuses are supported, 
+- * allowing multiple commands to propagate all the way to a SCSI-II device 
++ * and commands that are currently executing.  This means that an
++ * unlimited number of commands may be queued, letting
++ * more commands propagate from the higher driver levels giving higher
++ * throughput.  Note that both I_T_L and I_T_L_Q nexuses are supported,
++ * allowing multiple commands to propagate all the way to a SCSI-II device
+  * while a command is already executing.
+  *
+- * To solve the multiple-boards-in-the-same-system problem, 
++ * To solve the multiple-boards-in-the-same-system problem,
+  * there is a separate instance structure for each instance
+  * of a 5380 in the system.  So, multiple NCR5380 drivers will
+  * be able to coexist with appropriate changes to the high level
+- * SCSI code.  
++ * SCSI code.
+  *
+  * A NCR5380_PUBLIC_REVISION macro is provided, with the release
+- * number (updated for each public release) printed by the 
+- * NCR5380_print_options command, which should be called from the 
++ * number (updated for each public release) printed by the
++ * NCR5380_print_options command, which should be called from the
+  * wrapper detect function, so that I know what release of the driver
+  * users are using.
+  *
+- * Issues specific to the NCR5380 : 
++ * Issues specific to the NCR5380 :
+  *
+- * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead 
+- * piece of hardware that requires you to sit in a loop polling for 
+- * the REQ signal as long as you are connected.  Some devices are 
+- * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect 
++ * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead
++ * piece of hardware that requires you to sit in a loop polling for
++ * the REQ signal as long as you are connected.  Some devices are
++ * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect
+  * while doing long seek operations.
+- * 
++ *
+  * The workaround for this is to keep track of devices that have
+  * disconnected.  If the device hasn't disconnected, for commands that
+- * should disconnect, we do something like 
++ * should disconnect, we do something like
+  *
+  * while (!REQ is asserted) { sleep for N usecs; poll for M usecs }
+- * 
+- * Some tweaking of N and M needs to be done.  An algorithm based 
++ *
++ * Some tweaking of N and M needs to be done.  An algorithm based
+  * on "time to data" would give the best results as long as short time
+- * to datas (ie, on the same track) were considered, however these 
++ * to datas (ie, on the same track) were considered, however these
+  * broken devices are the exception rather than the rule and I'd rather
+  * spend my time optimizing for the normal case.
+  *
+@@ -167,9 +175,9 @@
+  * At the heart of the design is a coroutine, NCR5380_main,
+  * which is started when not running by the interrupt handler,
+  * timer, and queue command function.  It attempts to establish
+- * I_T_L or I_T_L_Q nexuses by removing the commands from the 
+- * issue queue and calling NCR5380_select() if a nexus 
+- * is not established. 
++ * I_T_L or I_T_L_Q nexuses by removing the commands from the
++ * issue queue and calling NCR5380_select() if a nexus
++ * is not established.
+  *
+  * Once a nexus is established, the NCR5380_information_transfer()
+  * phase goes through the various phases as instructed by the target.
+@@ -183,10 +191,10 @@
+  * calling NCR5380_intr()  which will in turn call NCR5380_reselect
+  * to reestablish a nexus.  This will run main if necessary.
+  *
+- * On command termination, the done function will be called as 
++ * On command termination, the done function will be called as
+  * appropriate.
+  *
+- * SCSI pointers are maintained in the SCp field of SCSI command 
++ * SCSI pointers are maintained in the SCp field of SCSI command
+  * structures, being initialized after the command is connected
+  * in NCR5380_select, and set as appropriate in NCR5380_information_transfer.
+  * Note that in violation of the standard, an implicit SAVE POINTERS operation
+@@ -196,12 +204,12 @@
+ /*
+  * Using this file :
+  * This file a skeleton Linux SCSI driver for the NCR 5380 series
+- * of chips.  To use it, you write an architecture specific functions 
++ * of chips.  To use it, you write an architecture specific functions
+  * and macros and include this file in your driver.
+  *
+- * These macros control options : 
++ * These macros control options :
+  * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
+- *	for commands that return with a CHECK CONDITION status. 
++ *	for commands that return with a CHECK CONDITION status.
+  *
+  * LINKED - if defined, linked commands are supported.
+  *
+@@ -210,18 +218,18 @@
+  * SUPPORT_TAGS - if defined, SCSI-2 tagged queuing is used where possible
+  *
+  * These macros MUST be defined :
+- * 
++ *
+  * NCR5380_read(register)  - read from the specified register
+  *
+- * NCR5380_write(register, value) - write to the specific register 
++ * NCR5380_write(register, value) - write to the specific register
+  *
+  * Either real DMA *or* pseudo DMA may be implemented
+- * REAL functions : 
++ * REAL functions :
+  * NCR5380_REAL_DMA should be defined if real DMA is to be used.
+- * Note that the DMA setup functions should return the number of bytes 
++ * Note that the DMA setup functions should return the number of bytes
+  *	that they were able to program the controller for.
+  *
+- * Also note that generic i386/PC versions of these macros are 
++ * Also note that generic i386/PC versions of these macros are
+  *	available as NCR5380_i386_dma_write_setup,
+  *	NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual.
+  *
+@@ -234,14 +242,14 @@
+  * NCR5380_pread(instance, dst, count);
+  *
+  * If nothing specific to this implementation needs doing (ie, with external
+- * hardware), you must also define 
+- *  
++ * hardware), you must also define
++ *
+  * NCR5380_queue_command
+  * NCR5380_reset
+  * NCR5380_abort
+  * NCR5380_proc_info
+  *
+- * to be the global entry points into the specific driver, ie 
++ * to be the global entry points into the specific driver, ie
+  * #define NCR5380_queue_command t128_queue_command.
+  *
+  * If this is not done, the routines will be defined as static functions
+@@ -249,7 +257,7 @@
+  * accessible wrapper function.
+  *
+  * The generic driver is initialized by calling NCR5380_init(instance),
+- * after setting the appropriate host specific fields and ID.  If the 
++ * after setting the appropriate host specific fields and ID.  If the
+  * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
+  * possible) function may be used.  Before the specific driver initialization
+  * code finishes, NCR5380_print_options should be called.
+@@ -312,34 +320,34 @@ static struct scsi_host_template *the_te
+ #define TAG_NONE 0xff
+ 
+ typedef struct {
+-    DECLARE_BITMAP(allocated, MAX_TAGS);
+-    int		nr_allocated;
+-    int		queue_size;
++	DECLARE_BITMAP(allocated, MAX_TAGS);
++	int nr_allocated;
++	int queue_size;
+ } TAG_ALLOC;
+ 
+-static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */
++static TAG_ALLOC TagAlloc[8][8];	/* 8 targets and 8 LUNs */
+ 
+ 
+-static void __init init_tags( void )
++static void __init init_tags(void)
+ {
+-    int target, lun;
+-    TAG_ALLOC *ta;
+-    
+-    if (!setup_use_tagged_queuing)
+-	return;
+-    
+-    for( target = 0; target < 8; ++target ) {
+-	for( lun = 0; lun < 8; ++lun ) {
+-	    ta = &TagAlloc[target][lun];
+-	    bitmap_zero(ta->allocated, MAX_TAGS);
+-	    ta->nr_allocated = 0;
+-	    /* At the beginning, assume the maximum queue size we could
+-	     * support (MAX_TAGS). This value will be decreased if the target
+-	     * returns QUEUE_FULL status.
+-	     */
+-	    ta->queue_size = MAX_TAGS;
++	int target, lun;
++	TAG_ALLOC *ta;
++
++	if (!setup_use_tagged_queuing)
++		return;
++
++	for (target = 0; target < 8; ++target) {
++		for (lun = 0; lun < 8; ++lun) {
++			ta = &TagAlloc[target][lun];
++			bitmap_zero(ta->allocated, MAX_TAGS);
++			ta->nr_allocated = 0;
++			/* At the beginning, assume the maximum queue size we could
++			 * support (MAX_TAGS). This value will be decreased if the target
++			 * returns QUEUE_FULL status.
++			 */
++			ta->queue_size = MAX_TAGS;
++		}
+ 	}
+-    }
+ }
+ 
+ 
+@@ -348,24 +356,24 @@ static void __init init_tags( void )
+  * check that there is a free tag and the target's queue won't overflow. This
+  * function should be called with interrupts disabled to avoid race
+  * conditions.
+- */ 
++ */
+ 
+-static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged )
++static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
+ {
+-    SETUP_HOSTDATA(cmd->device->host);
++	SETUP_HOSTDATA(cmd->device->host);
+ 
+-    if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))
+-	return( 1 );
+-    if (!should_be_tagged ||
+-	!setup_use_tagged_queuing || !cmd->device->tagged_supported)
+-	return( 0 );
+-    if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >=
+-	TagAlloc[cmd->device->id][cmd->device->lun].queue_size ) {
+-	TAG_PRINTK( "scsi%d: target %d lun %d: no free tags\n",
+-		    H_NO(cmd), cmd->device->id, cmd->device->lun );
+-	return( 1 );
+-    }
+-    return( 0 );
++	if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))
++		return 1;
++	if (!should_be_tagged ||
++	    !setup_use_tagged_queuing || !cmd->device->tagged_supported)
++		return 0;
++	if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >=
++	    TagAlloc[cmd->device->id][cmd->device->lun].queue_size) {
++		TAG_PRINTK("scsi%d: target %d lun %d: no free tags\n",
++			   H_NO(cmd), cmd->device->id, cmd->device->lun);
++		return 1;
++	}
++	return 0;
+ }
+ 
+ 
+@@ -374,31 +382,30 @@ static int is_lun_busy( Scsi_Cmnd *cmd, 
+  * untagged.
+  */
+ 
+-static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged )
++static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
+ {
+-    SETUP_HOSTDATA(cmd->device->host);
++	SETUP_HOSTDATA(cmd->device->host);
+ 
+-    /* If we or the target don't support tagged queuing, allocate the LUN for
+-     * an untagged command.
+-     */
+-    if (!should_be_tagged ||
+-	!setup_use_tagged_queuing || !cmd->device->tagged_supported) {
+-	cmd->tag = TAG_NONE;
+-	hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+-	TAG_PRINTK( "scsi%d: target %d lun %d now allocated by untagged "
+-		    "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun );
+-    }
+-    else {
+-	TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+-
+-	cmd->tag = find_first_zero_bit( ta->allocated, MAX_TAGS );
+-	set_bit( cmd->tag, ta->allocated );
+-	ta->nr_allocated++;
+-	TAG_PRINTK( "scsi%d: using tag %d for target %d lun %d "
+-		    "(now %d tags in use)\n",
+-		    H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun,
+-		    ta->nr_allocated );
+-    }
++	/* If we or the target don't support tagged queuing, allocate the LUN for
++	 * an untagged command.
++	 */
++	if (!should_be_tagged ||
++	    !setup_use_tagged_queuing || !cmd->device->tagged_supported) {
++		cmd->tag = TAG_NONE;
++		hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
++		TAG_PRINTK("scsi%d: target %d lun %d now allocated by untagged "
++			   "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun);
++	} else {
++		TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
++
++		cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS);
++		set_bit(cmd->tag, ta->allocated);
++		ta->nr_allocated++;
++		TAG_PRINTK("scsi%d: using tag %d for target %d lun %d "
++			   "(now %d tags in use)\n",
++			   H_NO(cmd), cmd->tag, cmd->device->id,
++			   cmd->device->lun, ta->nr_allocated);
++	}
+ }
+ 
+ 
+@@ -406,44 +413,42 @@ static void cmd_get_tag( Scsi_Cmnd *cmd,
+  * unlock the LUN.
+  */
+ 
+-static void cmd_free_tag( Scsi_Cmnd *cmd )
++static void cmd_free_tag(Scsi_Cmnd *cmd)
+ {
+-    SETUP_HOSTDATA(cmd->device->host);
++	SETUP_HOSTDATA(cmd->device->host);
+ 
+-    if (cmd->tag == TAG_NONE) {
+-	hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+-	TAG_PRINTK( "scsi%d: target %d lun %d untagged cmd finished\n",
+-		    H_NO(cmd), cmd->device->id, cmd->device->lun );
+-    }
+-    else if (cmd->tag >= MAX_TAGS) {
+-	printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
+-		H_NO(cmd), cmd->tag );
+-    }
+-    else {
+-	TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+-	clear_bit( cmd->tag, ta->allocated );
+-	ta->nr_allocated--;
+-	TAG_PRINTK( "scsi%d: freed tag %d for target %d lun %d\n",
+-		    H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun );
+-    }
++	if (cmd->tag == TAG_NONE) {
++		hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
++		TAG_PRINTK("scsi%d: target %d lun %d untagged cmd finished\n",
++			   H_NO(cmd), cmd->device->id, cmd->device->lun);
++	} else if (cmd->tag >= MAX_TAGS) {
++		printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
++		       H_NO(cmd), cmd->tag);
++	} else {
++		TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
++		clear_bit(cmd->tag, ta->allocated);
++		ta->nr_allocated--;
++		TAG_PRINTK("scsi%d: freed tag %d for target %d lun %d\n",
++			   H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun);
++	}
+ }
+ 
+ 
+-static void free_all_tags( void )
+-{
+-    int target, lun;
+-    TAG_ALLOC *ta;
+-
+-    if (!setup_use_tagged_queuing)
+-	return;
+-    
+-    for( target = 0; target < 8; ++target ) {
+-	for( lun = 0; lun < 8; ++lun ) {
+-	    ta = &TagAlloc[target][lun];
+-	    bitmap_zero(ta->allocated, MAX_TAGS);
+-	    ta->nr_allocated = 0;
++static void free_all_tags(void)
++{
++	int target, lun;
++	TAG_ALLOC *ta;
++
++	if (!setup_use_tagged_queuing)
++		return;
++
++	for (target = 0; target < 8; ++target) {
++		for (lun = 0; lun < 8; ++lun) {
++			ta = &TagAlloc[target][lun];
++			bitmap_zero(ta->allocated, MAX_TAGS);
++			ta->nr_allocated = 0;
++		}
+ 	}
+-    }
+ }
+ 
+ #endif /* SUPPORT_TAGS */
+@@ -461,89 +466,94 @@ static void free_all_tags( void )
+  *    assumed to be already transfered into ptr/this_residual.
+  */
+ 
+-static void merge_contiguous_buffers( Scsi_Cmnd *cmd )
++static void merge_contiguous_buffers(Scsi_Cmnd *cmd)
+ {
+-    unsigned long endaddr;
++	unsigned long endaddr;
+ #if (NDEBUG & NDEBUG_MERGING)
+-    unsigned long oldlen = cmd->SCp.this_residual;
+-    int		  cnt = 1;
++	unsigned long oldlen = cmd->SCp.this_residual;
++	int cnt = 1;
+ #endif
+ 
+-    for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
+-	 cmd->SCp.buffers_residual &&
+-	 virt_to_phys(page_address(cmd->SCp.buffer[1].page)+
+-		      cmd->SCp.buffer[1].offset) == endaddr; ) {
+-	MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
+-		   cmd->SCp.buffer[1].address, endaddr);
++	for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
++	     cmd->SCp.buffers_residual &&
++	     virt_to_phys(page_address(cmd->SCp.buffer[1].page) +
++			  cmd->SCp.buffer[1].offset) == endaddr;) {
++		MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
++			   cmd->SCp.buffer[1].address, endaddr);
+ #if (NDEBUG & NDEBUG_MERGING)
+-	++cnt;
++		++cnt;
+ #endif
+-	++cmd->SCp.buffer;
+-	--cmd->SCp.buffers_residual;
+-	cmd->SCp.this_residual += cmd->SCp.buffer->length;
+-	endaddr += cmd->SCp.buffer->length;
+-    }
++		++cmd->SCp.buffer;
++		--cmd->SCp.buffers_residual;
++		cmd->SCp.this_residual += cmd->SCp.buffer->length;
++		endaddr += cmd->SCp.buffer->length;
++	}
+ #if (NDEBUG & NDEBUG_MERGING)
+-    if (oldlen != cmd->SCp.this_residual)
+-	MER_PRINTK("merged %d buffers from %p, new length %08x\n",
+-		   cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
++	if (oldlen != cmd->SCp.this_residual)
++		MER_PRINTK("merged %d buffers from %p, new length %08x\n",
++			   cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
+ #endif
+ }
+ 
+ /*
+  * Function : void initialize_SCp(Scsi_Cmnd *cmd)
+  *
+- * Purpose : initialize the saved data pointers for cmd to point to the 
++ * Purpose : initialize the saved data pointers for cmd to point to the
+  *	start of the buffer.
+  *
+  * Inputs : cmd - Scsi_Cmnd structure to have pointers reset.
+  */
+ 
+-static __inline__ void initialize_SCp(Scsi_Cmnd *cmd)
++static inline void initialize_SCp(Scsi_Cmnd *cmd)
+ {
+-    /* 
+-     * Initialize the Scsi Pointer field so that all of the commands in the 
+-     * various queues are valid.
+-     */
+-
+-    if (cmd->use_sg) {
+-	cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
+-	cmd->SCp.buffers_residual = cmd->use_sg - 1;
+-	cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page)+
+-		       cmd->SCp.buffer->offset;
+-	cmd->SCp.this_residual = cmd->SCp.buffer->length;
+-	/* ++roman: Try to merge some scatter-buffers if they are at
+-	 * contiguous physical addresses.
+-	 */
+-	merge_contiguous_buffers( cmd );
+-    } else {
+-	cmd->SCp.buffer = NULL;
+-	cmd->SCp.buffers_residual = 0;
+-	cmd->SCp.ptr = (char *) cmd->request_buffer;
+-	cmd->SCp.this_residual = cmd->request_bufflen;
+-    }
++	/*
++	 * Initialize the Scsi Pointer field so that all of the commands in the
++	 * various queues are valid.
++	 */
++
++	if (cmd->use_sg) {
++		cmd->SCp.buffer = (struct scatterlist *)cmd->request_buffer;
++		cmd->SCp.buffers_residual = cmd->use_sg - 1;
++		cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page) +
++			       cmd->SCp.buffer->offset;
++		cmd->SCp.this_residual = cmd->SCp.buffer->length;
++		/* ++roman: Try to merge some scatter-buffers if they are at
++		 * contiguous physical addresses.
++		 */
++		merge_contiguous_buffers(cmd);
++	} else {
++		cmd->SCp.buffer = NULL;
++		cmd->SCp.buffers_residual = 0;
++		cmd->SCp.ptr = (char *)cmd->request_buffer;
++		cmd->SCp.this_residual = cmd->request_bufflen;
++	}
+ }
+ 
+ #include <linux/delay.h>
+ 
+ #if NDEBUG
+ static struct {
+-    unsigned char mask;
+-    const char * name;} 
+-signals[] = {{ SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" }, 
+-    { SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD,  "CD" }, { SR_IO, "IO" }, 
+-    { SR_SEL, "SEL" }, {0, NULL}}, 
+-basrs[] = {{BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}},
+-icrs[] = {{ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"},
+-    {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"}, 
+-    {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"}, 
+-    {0, NULL}},
+-mrs[] = {{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"}, 
+-    {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR, 
+-    "MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"},
+-    {MR_MONITOR_BSY, "MODE MONITOR BSY"},
+-    {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"}, 
+-    {0, NULL}};
++	unsigned char mask;
++	const char *name;
++} signals[] = {
++	{ SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" },
++	{ SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD,  "CD" }, { SR_IO, "IO" },
++	{ SR_SEL, "SEL" }, {0, NULL}
++}, basrs[] = {
++	{BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}
++}, icrs[] = {
++	{ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"},
++	{ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"},
++	{ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"},
++	{0, NULL}
++}, mrs[] = {
++	{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"},
++	{MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR,
++	"MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"},
++	{MR_MONITOR_BSY, "MODE MONITOR BSY"},
++	{MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"},
++	{0, NULL}
++};
+ 
+ /*
+  * Function : void NCR5380_print(struct Scsi_Host *instance)
+@@ -553,45 +563,47 @@ mrs[] = {{MR_BLOCK_DMA_MODE, "MODE BLOCK
+  * Input : instance - which NCR5380
+  */
+ 
+-static void NCR5380_print(struct Scsi_Host *instance) {
+-    unsigned char status, data, basr, mr, icr, i;
+-    unsigned long flags;
+-
+-    local_irq_save(flags);
+-    data = NCR5380_read(CURRENT_SCSI_DATA_REG);
+-    status = NCR5380_read(STATUS_REG);
+-    mr = NCR5380_read(MODE_REG);
+-    icr = NCR5380_read(INITIATOR_COMMAND_REG);
+-    basr = NCR5380_read(BUS_AND_STATUS_REG);
+-    local_irq_restore(flags);
+-    printk("STATUS_REG: %02x ", status);
+-    for (i = 0; signals[i].mask ; ++i) 
+-	if (status & signals[i].mask)
+-	    printk(",%s", signals[i].name);
+-    printk("\nBASR: %02x ", basr);
+-    for (i = 0; basrs[i].mask ; ++i) 
+-	if (basr & basrs[i].mask)
+-	    printk(",%s", basrs[i].name);
+-    printk("\nICR: %02x ", icr);
+-    for (i = 0; icrs[i].mask; ++i) 
+-	if (icr & icrs[i].mask)
+-	    printk(",%s", icrs[i].name);
+-    printk("\nMODE: %02x ", mr);
+-    for (i = 0; mrs[i].mask; ++i) 
+-	if (mr & mrs[i].mask)
+-	    printk(",%s", mrs[i].name);
+-    printk("\n");
++static void NCR5380_print(struct Scsi_Host *instance)
++{
++	unsigned char status, data, basr, mr, icr, i;
++	unsigned long flags;
++
++	local_irq_save(flags);
++	data = NCR5380_read(CURRENT_SCSI_DATA_REG);
++	status = NCR5380_read(STATUS_REG);
++	mr = NCR5380_read(MODE_REG);
++	icr = NCR5380_read(INITIATOR_COMMAND_REG);
++	basr = NCR5380_read(BUS_AND_STATUS_REG);
++	local_irq_restore(flags);
++	printk("STATUS_REG: %02x ", status);
++	for (i = 0; signals[i].mask; ++i)
++		if (status & signals[i].mask)
++			printk(",%s", signals[i].name);
++	printk("\nBASR: %02x ", basr);
++	for (i = 0; basrs[i].mask; ++i)
++		if (basr & basrs[i].mask)
++			printk(",%s", basrs[i].name);
++	printk("\nICR: %02x ", icr);
++	for (i = 0; icrs[i].mask; ++i)
++		if (icr & icrs[i].mask)
++			printk(",%s", icrs[i].name);
++	printk("\nMODE: %02x ", mr);
++	for (i = 0; mrs[i].mask; ++i)
++		if (mr & mrs[i].mask)
++			printk(",%s", mrs[i].name);
++	printk("\n");
+ }
+ 
+ static struct {
+-    unsigned char value;
+-    const char *name;
++	unsigned char value;
++	const char *name;
+ } phases[] = {
+-    {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"},
+-    {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"},
+-    {PHASE_UNKNOWN, "UNKNOWN"}};
++	{PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"},
++	{PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"},
++	{PHASE_UNKNOWN, "UNKNOWN"}
++};
+ 
+-/* 
++/*
+  * Function : void NCR5380_print_phase(struct Scsi_Host *instance)
+  *
+  * Purpose : print the current SCSI phase for debugging purposes
+@@ -601,30 +613,35 @@ static struct {
+ 
+ static void NCR5380_print_phase(struct Scsi_Host *instance)
+ {
+-    unsigned char status;
+-    int i;
++	unsigned char status;
++	int i;
+ 
+-    status = NCR5380_read(STATUS_REG);
+-    if (!(status & SR_REQ)) 
+-	printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO);
+-    else {
+-	for (i = 0; (phases[i].value != PHASE_UNKNOWN) && 
+-	    (phases[i].value != (status & PHASE_MASK)); ++i); 
+-	printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name);
+-    }
++	status = NCR5380_read(STATUS_REG);
++	if (!(status & SR_REQ))
++		printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO);
++	else {
++		for (i = 0; (phases[i].value != PHASE_UNKNOWN) &&
++		     (phases[i].value != (status & PHASE_MASK)); ++i)
++			;
++		printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name);
++	}
+ }
+ 
+ #else /* !NDEBUG */
+ 
+ /* dummies... */
+-__inline__ void NCR5380_print(struct Scsi_Host *instance) { };
+-__inline__ void NCR5380_print_phase(struct Scsi_Host *instance) { };
++static inline void NCR5380_print(struct Scsi_Host *instance)
++{
++};
++static inline void NCR5380_print_phase(struct Scsi_Host *instance)
++{
++};
+ 
+ #endif
+ 
+ /*
+  * ++roman: New scheme of calling NCR5380_main()
+- * 
++ *
+  * If we're not in an interrupt, we can call our main directly, it cannot be
+  * already running. Else, we queue it on a task queue, if not 'main_running'
+  * tells us that a lower level is already executing it. This way,
+@@ -638,33 +655,33 @@ __inline__ void NCR5380_print_phase(stru
+ #include <linux/workqueue.h>
+ #include <linux/interrupt.h>
+ 
+-static volatile int main_running = 0;
+-static DECLARE_WORK(NCR5380_tqueue, (void (*)(void*))NCR5380_main, NULL);
++static volatile int main_running;
++static DECLARE_WORK(NCR5380_tqueue, (void (*)(void *))NCR5380_main, NULL);
+ 
+-static __inline__ void queue_main(void)
++static inline void queue_main(void)
+ {
+-    if (!main_running) {
+-	/* If in interrupt and NCR5380_main() not already running,
+-	   queue it on the 'immediate' task queue, to be processed
+-	   immediately after the current interrupt processing has
+-	   finished. */
+-	schedule_work(&NCR5380_tqueue);
+-    }
+-    /* else: nothing to do: the running NCR5380_main() will pick up
+-       any newly queued command. */
++	if (!main_running) {
++		/* If in interrupt and NCR5380_main() not already running,
++		   queue it on the 'immediate' task queue, to be processed
++		   immediately after the current interrupt processing has
++		   finished. */
++		schedule_work(&NCR5380_tqueue);
++	}
++	/* else: nothing to do: the running NCR5380_main() will pick up
++	   any newly queued command. */
+ }
+ 
+ 
+-static inline void NCR5380_all_init (void)
++static inline void NCR5380_all_init(void)
+ {
+-    static int done = 0;
+-    if (!done) {
+-	INI_PRINTK("scsi : NCR5380_all_init()\n");
+-	done = 1;
+-    }
++	static int done = 0;
++	if (!done) {
++		INI_PRINTK("scsi : NCR5380_all_init()\n");
++		done = 1;
++	}
+ }
+ 
+- 
++
+ /*
+  * Function : void NCR58380_print_options (struct Scsi_Host *instance)
+  *
+@@ -674,23 +691,23 @@ static inline void NCR5380_all_init (voi
+  * Inputs : instance, pointer to this instance.  Unused.
+  */
+ 
+-static void __init NCR5380_print_options (struct Scsi_Host *instance)
++static void __init NCR5380_print_options(struct Scsi_Host *instance)
+ {
+-    printk(" generic options"
+-#ifdef AUTOSENSE 
+-    " AUTOSENSE"
++	printk(" generic options"
++#ifdef AUTOSENSE
++	       " AUTOSENSE"
+ #endif
+ #ifdef REAL_DMA
+-    " REAL DMA"
++	       " REAL DMA"
+ #endif
+ #ifdef PARITY
+-    " PARITY"
++	       " PARITY"
+ #endif
+ #ifdef SUPPORT_TAGS
+-    " SCSI-2 TAGGED QUEUING"
++	       " SCSI-2 TAGGED QUEUING"
+ #endif
+-    );
+-    printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
++	       );
++	printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
+ }
+ 
+ /*
+@@ -699,27 +716,27 @@ static void __init NCR5380_print_options
+  * Purpose : print commands in the various queues, called from
+  *	NCR5380_abort and NCR5380_debug to aid debugging.
+  *
+- * Inputs : instance, pointer to this instance.  
++ * Inputs : instance, pointer to this instance.
+  */
+ 
+-static void NCR5380_print_status (struct Scsi_Host *instance)
++static void NCR5380_print_status(struct Scsi_Host *instance)
+ {
+-    char *pr_bfr;
+-    char *start;
+-    int len;
+-
+-    NCR_PRINT(NDEBUG_ANY);
+-    NCR_PRINT_PHASE(NDEBUG_ANY);
+-
+-    pr_bfr = (char *) __get_free_page(GFP_ATOMIC);
+-    if (!pr_bfr) {
+-	printk("NCR5380_print_status: no memory for print buffer\n");
+-	return;
+-    }
+-    len = NCR5380_proc_info(instance, pr_bfr, &start, 0, PAGE_SIZE, 0);
+-    pr_bfr[len] = 0;
+-    printk("\n%s\n", pr_bfr);
+-    free_page((unsigned long) pr_bfr);
++	char *pr_bfr;
++	char *start;
++	int len;
++
++	NCR_PRINT(NDEBUG_ANY);
++	NCR_PRINT_PHASE(NDEBUG_ANY);
++
++	pr_bfr = (char *)__get_free_page(GFP_ATOMIC);
++	if (!pr_bfr) {
++		printk("NCR5380_print_status: no memory for print buffer\n");
++		return;
++	}
++	len = NCR5380_proc_info(instance, pr_bfr, &start, 0, PAGE_SIZE, 0);
++	pr_bfr[len] = 0;
++	printk("\n%s\n", pr_bfr);
++	free_page((unsigned long)pr_bfr);
+ }
+ 
+ 
+@@ -738,146 +755,144 @@ static void NCR5380_print_status (struct
+ */
+ 
+ #undef SPRINTF
+-#define SPRINTF(fmt,args...) \
+-  do { if (pos + strlen(fmt) + 20 /* slop */ < buffer + length) \
+-	 pos += sprintf(pos, fmt , ## args); } while(0)
+-static
+-char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
+-
+-static
+-int NCR5380_proc_info (struct Scsi_Host *instance, char *buffer, char **start, off_t offset,
+-		       int length, int inout)
+-{
+-    char *pos = buffer;
+-    struct NCR5380_hostdata *hostdata;
+-    Scsi_Cmnd *ptr;
+-    unsigned long flags;
+-    off_t begin = 0;
+-#define check_offset()				\
+-    do {					\
+-	if (pos - buffer < offset - begin) {	\
+-	    begin += pos - buffer;		\
+-	    pos = buffer;			\
+-	}					\
+-    } while (0)
+-
+-    hostdata = (struct NCR5380_hostdata *)instance->hostdata;
+-
+-    if (inout) { /* Has data been written to the file ? */
+-	return(-ENOSYS);  /* Currently this is a no-op */
+-    }
+-    SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
+-    check_offset();
+-    local_irq_save(flags);
+-    SPRINTF("NCR5380: coroutine is%s running.\n", main_running ? "" : "n't");
+-    check_offset();
+-    if (!hostdata->connected)
+-	SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
+-    else
+-	pos = lprint_Scsi_Cmnd ((Scsi_Cmnd *) hostdata->connected,
+-				pos, buffer, length);
+-    SPRINTF("scsi%d: issue_queue\n", HOSTNO);
+-    check_offset();
+-    for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
+-	pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
++#define SPRINTF(fmt,args...)							\
++	do {									\
++		if (pos + strlen(fmt) + 20 /* slop */ < buffer + length)	\
++			pos += sprintf(pos, fmt , ## args);			\
++	} while(0)
++static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
++
++static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer,
++			     char **start, off_t offset, int length, int inout)
++{
++	char *pos = buffer;
++	struct NCR5380_hostdata *hostdata;
++	Scsi_Cmnd *ptr;
++	unsigned long flags;
++	off_t begin = 0;
++#define check_offset()					\
++	do {						\
++		if (pos - buffer < offset - begin) {	\
++			begin += pos - buffer;		\
++			pos = buffer;			\
++		}					\
++	} while (0)
++
++	hostdata = (struct NCR5380_hostdata *)instance->hostdata;
++
++	if (inout)			/* Has data been written to the file ? */
++		return -ENOSYS;		/* Currently this is a no-op */
++	SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
+ 	check_offset();
+-    }
+-
+-    SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
+-    check_offset();
+-    for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+-	 ptr = NEXT(ptr)) {
+-	pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
++	local_irq_save(flags);
++	SPRINTF("NCR5380: coroutine is%s running.\n",
++		main_running ? "" : "n't");
+ 	check_offset();
+-    }
++	if (!hostdata->connected)
++		SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
++	else
++		pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected,
++				       pos, buffer, length);
++	SPRINTF("scsi%d: issue_queue\n", HOSTNO);
++	check_offset();
++	for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
++		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
++		check_offset();
++	}
+ 
+-    local_irq_restore(flags);
+-    *start = buffer + (offset - begin);
+-    if (pos - buffer < offset - begin)
+-	return 0;
+-    else if (pos - buffer - (offset - begin) < length)
+-	return pos - buffer - (offset - begin);
+-    return length;
+-}
++	SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
++	check_offset();
++	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
++	     ptr = NEXT(ptr)) {
++		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
++		check_offset();
++	}
+ 
+-static char *
+-lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
+-{
+-    int i, s;
+-    unsigned char *command;
+-    SPRINTF("scsi%d: destination target %d, lun %d\n",
+-	    H_NO(cmd), cmd->device->id, cmd->device->lun);
+-    SPRINTF("        command = ");
+-    command = cmd->cmnd;
+-    SPRINTF("%2d (0x%02x)", command[0], command[0]);
+-    for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
+-	SPRINTF(" %02x", command[i]);
+-    SPRINTF("\n");
+-    return pos;
++	local_irq_restore(flags);
++	*start = buffer + (offset - begin);
++	if (pos - buffer < offset - begin)
++		return 0;
++	else if (pos - buffer - (offset - begin) < length)
++		return pos - buffer - (offset - begin);
++	return length;
++}
++
++static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
++{
++	int i, s;
++	unsigned char *command;
++	SPRINTF("scsi%d: destination target %d, lun %d\n",
++		H_NO(cmd), cmd->device->id, cmd->device->lun);
++	SPRINTF("        command = ");
++	command = cmd->cmnd;
++	SPRINTF("%2d (0x%02x)", command[0], command[0]);
++	for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
++		SPRINTF(" %02x", command[i]);
++	SPRINTF("\n");
++	return pos;
+ }
+ 
+ 
+-/* 
++/*
+  * Function : void NCR5380_init (struct Scsi_Host *instance)
+  *
+  * Purpose : initializes *instance and corresponding 5380 chip.
+  *
+- * Inputs : instance - instantiation of the 5380 driver.  
++ * Inputs : instance - instantiation of the 5380 driver.
+  *
+  * Notes : I assume that the host, hostno, and id bits have been
+- * 	set correctly.  I don't care about the irq and other fields. 
+- * 
++ *	set correctly.  I don't care about the irq and other fields.
++ *
+  */
+ 
+-static int NCR5380_init (struct Scsi_Host *instance, int flags)
++static int NCR5380_init(struct Scsi_Host *instance, int flags)
+ {
+-    int i;
+-    SETUP_HOSTDATA(instance);
++	int i;
++	SETUP_HOSTDATA(instance);
+ 
+-    NCR5380_all_init();
++	NCR5380_all_init();
+ 
+-    hostdata->aborted = 0;
+-    hostdata->id_mask = 1 << instance->this_id;
+-    hostdata->id_higher_mask = 0;
+-    for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
+-	if (i > hostdata->id_mask)
+-	    hostdata->id_higher_mask |= i;
+-    for (i = 0; i < 8; ++i)
+-	hostdata->busy[i] = 0;
++	hostdata->aborted = 0;
++	hostdata->id_mask = 1 << instance->this_id;
++	hostdata->id_higher_mask = 0;
++	for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
++		if (i > hostdata->id_mask)
++			hostdata->id_higher_mask |= i;
++	for (i = 0; i < 8; ++i)
++		hostdata->busy[i] = 0;
+ #ifdef SUPPORT_TAGS
+-    init_tags();
++	init_tags();
+ #endif
+ #if defined (REAL_DMA)
+-    hostdata->dma_len = 0;
++	hostdata->dma_len = 0;
+ #endif
+-    hostdata->targets_present = 0;
+-    hostdata->connected = NULL;
+-    hostdata->issue_queue = NULL;
+-    hostdata->disconnected_queue = NULL;
+-    hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;
+-
+-    if (!the_template) {
+-	the_template = instance->hostt;
+-	first_instance = instance;
+-    }
+-	
++	hostdata->targets_present = 0;
++	hostdata->connected = NULL;
++	hostdata->issue_queue = NULL;
++	hostdata->disconnected_queue = NULL;
++	hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;
++
++	if (!the_template) {
++		the_template = instance->hostt;
++		first_instance = instance;
++	}
+ 
+ #ifndef AUTOSENSE
+-    if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1))
+-	 printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n"
+-	        "        without AUTOSENSE option, contingent allegiance conditions may\n"
+-	        "        be incorrectly cleared.\n", HOSTNO);
++	if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1))
++		printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n"
++		       "        without AUTOSENSE option, contingent allegiance conditions may\n"
++		       "        be incorrectly cleared.\n", HOSTNO);
+ #endif /* def AUTOSENSE */
+ 
+-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-    NCR5380_write(MODE_REG, MR_BASE);
+-    NCR5380_write(TARGET_COMMAND_REG, 0);
+-    NCR5380_write(SELECT_ENABLE_REG, 0);
++	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++	NCR5380_write(MODE_REG, MR_BASE);
++	NCR5380_write(TARGET_COMMAND_REG, 0);
++	NCR5380_write(SELECT_ENABLE_REG, 0);
+ 
+-    return 0;
++	return 0;
+ }
+ 
+-/* 
++/*
+  * our own old-style timeout update
+  */
+ /*
+@@ -890,331 +905,328 @@ static int NCR5380_init (struct Scsi_Hos
+ 
+ int atari_scsi_update_timeout(Scsi_Cmnd * SCset, int timeout)
+ {
+-    int rtn;
++	int rtn;
+ 
+-    /*
+-     * We are using the new error handling code to actually register/deregister
+-     * timers for timeout.
+-     */
+-
+-    if (!timer_pending(&SCset->eh_timeout)) {
+-	rtn = 0;
+-    } else {
+-	rtn = SCset->eh_timeout.expires - jiffies;
+-    }
+-
+-    if (timeout == 0) {
+-        del_timer(&SCset->eh_timeout);
+-        SCset->eh_timeout.data = (unsigned long) NULL;
+-        SCset->eh_timeout.expires = 0;
+-    } else {
+-        if (SCset->eh_timeout.data != (unsigned long) NULL) 
+-            del_timer(&SCset->eh_timeout);
+-        SCset->eh_timeout.data = (unsigned long) SCset;
+-        SCset->eh_timeout.expires = jiffies + timeout;
+-        add_timer(&SCset->eh_timeout);
+-    }
++	/*
++	 * We are using the new error handling code to actually register/deregister
++	 * timers for timeout.
++	 */
++
++	if (!timer_pending(&SCset->eh_timeout))
++		rtn = 0;
++	else
++		rtn = SCset->eh_timeout.expires - jiffies;
++
++	if (timeout == 0) {
++		del_timer(&SCset->eh_timeout);
++		SCset->eh_timeout.data = (unsigned long)NULL;
++		SCset->eh_timeout.expires = 0;
++	} else {
++		if (SCset->eh_timeout.data != (unsigned long)NULL)
++			del_timer(&SCset->eh_timeout);
++		SCset->eh_timeout.data = (unsigned long)SCset;
++		SCset->eh_timeout.expires = jiffies + timeout;
++		add_timer(&SCset->eh_timeout);
++	}
+ 	return rtn;
+ }
+ 
+-/* 
+- * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd, 
+- *	void (*done)(Scsi_Cmnd *)) 
++/*
++ * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
++ *	void (*done)(Scsi_Cmnd *))
+  *
+  * Purpose :  enqueues a SCSI command
+  *
+  * Inputs : cmd - SCSI command, done - function called on completion, with
+  *	a pointer to the command descriptor.
+- * 
++ *
+  * Returns : 0
+  *
+- * Side effects : 
+- *      cmd is added to the per instance issue_queue, with minor 
+- *	twiddling done to the host specific fields of cmd.  If the 
++ * Side effects :
++ *      cmd is added to the per instance issue_queue, with minor
++ *	twiddling done to the host specific fields of cmd.  If the
+  *	main coroutine is not running, it is restarted.
+  *
+  */
+ 
+-static
+-int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
++static int NCR5380_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+ {
+-    SETUP_HOSTDATA(cmd->device->host);
+-    Scsi_Cmnd *tmp;
+-    int oldto;
+-    unsigned long flags;
+-    // extern int update_timeout(Scsi_Cmnd * SCset, int timeout);
++	SETUP_HOSTDATA(cmd->device->host);
++	Scsi_Cmnd *tmp;
++	int oldto;
++	unsigned long flags;
++	// extern int update_timeout(Scsi_Cmnd * SCset, int timeout);
+ 
+ #if (NDEBUG & NDEBUG_NO_WRITE)
+-    switch (cmd->cmnd[0]) {
+-    case WRITE_6:
+-    case WRITE_10:
+-	printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
+-	       H_NO(cmd));
+-	cmd->result = (DID_ERROR << 16);
+-	done(cmd);
+-	return 0;
+-    }
++	switch (cmd->cmnd[0]) {
++	case WRITE_6:
++	case WRITE_10:
++		printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
++		       H_NO(cmd));
++		cmd->result = (DID_ERROR << 16);
++		done(cmd);
++		return 0;
++	}
+ #endif /* (NDEBUG & NDEBUG_NO_WRITE) */
+ 
+-
+ #ifdef NCR5380_STATS
+ # if 0
+-    if (!hostdata->connected && !hostdata->issue_queue &&
+-	!hostdata->disconnected_queue) {
+-	hostdata->timebase = jiffies;
+-    }
++	if (!hostdata->connected && !hostdata->issue_queue &&
++	    !hostdata->disconnected_queue) {
++		hostdata->timebase = jiffies;
++	}
+ # endif
+ # ifdef NCR5380_STAT_LIMIT
+-    if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
++	if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
+ # endif
+-	switch (cmd->cmnd[0])
+-	{
+-	    case WRITE:
+-	    case WRITE_6:
+-	    case WRITE_10:
+-		hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
+-		hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;
+-		hostdata->pendingw++;
+-		break;
+-	    case READ:
+-	    case READ_6:
+-	    case READ_10:
+-		hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase);
+-		hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;
+-		hostdata->pendingr++;
+-		break;
+-	}
+-#endif
+-
+-    /* 
+-     * We use the host_scribble field as a pointer to the next command  
+-     * in a queue 
+-     */
+-
+-    NEXT(cmd) = NULL;
+-    cmd->scsi_done = done;
+-
+-    cmd->result = 0;
+-
+-
+-    /* 
+-     * Insert the cmd into the issue queue. Note that REQUEST SENSE 
+-     * commands are added to the head of the queue since any command will
+-     * clear the contingent allegiance condition that exists and the 
+-     * sense data is only guaranteed to be valid while the condition exists.
+-     */
+-
+-    local_irq_save(flags);
+-    /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
+-     * Otherwise a running NCR5380_main may steal the lock.
+-     * Lock before actually inserting due to fairness reasons explained in
+-     * atari_scsi.c. If we insert first, then it's impossible for this driver
+-     * to release the lock.
+-     * Stop timer for this command while waiting for the lock, or timeouts
+-     * may happen (and they really do), and it's no good if the command doesn't
+-     * appear in any of the queues.
+-     * ++roman: Just disabling the NCR interrupt isn't sufficient here,
+-     * because also a timer int can trigger an abort or reset, which would
+-     * alter queues and touch the lock.
+-     */
+-    if (!IS_A_TT()) {
+-	oldto = atari_scsi_update_timeout(cmd, 0);
+-	falcon_get_lock();
+-	atari_scsi_update_timeout(cmd, oldto);
+-    }
+-    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
+-	LIST(cmd, hostdata->issue_queue);
+-	NEXT(cmd) = hostdata->issue_queue;
+-	hostdata->issue_queue = cmd;
+-    } else {
+-	for (tmp = (Scsi_Cmnd *)hostdata->issue_queue;
+-	     NEXT(tmp); tmp = NEXT(tmp))
+-	    ;
+-	LIST(cmd, tmp);
+-	NEXT(tmp) = cmd;
+-    }
+-    local_irq_restore(flags);
+-
+-    QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),
+-	      (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
+-
+-    /* If queue_command() is called from an interrupt (real one or bottom
+-     * half), we let queue_main() do the job of taking care about main. If it
+-     * is already running, this is a no-op, else main will be queued.
+-     *
+-     * If we're not in an interrupt, we can call NCR5380_main()
+-     * unconditionally, because it cannot be already running.
+-     */
+-    if (in_interrupt() || ((flags >> 8) & 7) >= 6)
+-	queue_main();
+-    else
+-	NCR5380_main(NULL);
+-    return 0;
+-}
+-
+-/*
+- * Function : NCR5380_main (void) 
+- *
+- * Purpose : NCR5380_main is a coroutine that runs as long as more work can 
+- *	be done on the NCR5380 host adapters in a system.  Both 
+- *	NCR5380_queue_command() and NCR5380_intr() will try to start it 
++		switch (cmd->cmnd[0]) {
++		case WRITE:
++		case WRITE_6:
++		case WRITE_10:
++			hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
++			hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;
++			hostdata->pendingw++;
++			break;
++		case READ:
++		case READ_6:
++		case READ_10:
++			hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase);
++			hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;
++			hostdata->pendingr++;
++			break;
++		}
++#endif
++
++	/*
++	 * We use the host_scribble field as a pointer to the next command
++	 * in a queue
++	 */
++
++	NEXT(cmd) = NULL;
++	cmd->scsi_done = done;
++
++	cmd->result = 0;
++
++	/*
++	 * Insert the cmd into the issue queue. Note that REQUEST SENSE
++	 * commands are added to the head of the queue since any command will
++	 * clear the contingent allegiance condition that exists and the
++	 * sense data is only guaranteed to be valid while the condition exists.
++	 */
++
++	local_irq_save(flags);
++	/* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
++	 * Otherwise a running NCR5380_main may steal the lock.
++	 * Lock before actually inserting due to fairness reasons explained in
++	 * atari_scsi.c. If we insert first, then it's impossible for this driver
++	 * to release the lock.
++	 * Stop timer for this command while waiting for the lock, or timeouts
++	 * may happen (and they really do), and it's no good if the command doesn't
++	 * appear in any of the queues.
++	 * ++roman: Just disabling the NCR interrupt isn't sufficient here,
++	 * because also a timer int can trigger an abort or reset, which would
++	 * alter queues and touch the lock.
++	 */
++	if (!IS_A_TT()) {
++		oldto = atari_scsi_update_timeout(cmd, 0);
++		falcon_get_lock();
++		atari_scsi_update_timeout(cmd, oldto);
++	}
++	if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
++		LIST(cmd, hostdata->issue_queue);
++		NEXT(cmd) = hostdata->issue_queue;
++		hostdata->issue_queue = cmd;
++	} else {
++		for (tmp = (Scsi_Cmnd *)hostdata->issue_queue;
++		     NEXT(tmp); tmp = NEXT(tmp))
++			;
++		LIST(cmd, tmp);
++		NEXT(tmp) = cmd;
++	}
++	local_irq_restore(flags);
++
++	QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),
++		  (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
++
++	/* If queue_command() is called from an interrupt (real one or bottom
++	 * half), we let queue_main() do the job of taking care about main. If it
++	 * is already running, this is a no-op, else main will be queued.
++	 *
++	 * If we're not in an interrupt, we can call NCR5380_main()
++	 * unconditionally, because it cannot be already running.
++	 */
++	if (in_interrupt() || ((flags >> 8) & 7) >= 6)
++		queue_main();
++	else
++		NCR5380_main(NULL);
++	return 0;
++}
++
++/*
++ * Function : NCR5380_main (void)
++ *
++ * Purpose : NCR5380_main is a coroutine that runs as long as more work can
++ *	be done on the NCR5380 host adapters in a system.  Both
++ *	NCR5380_queue_command() and NCR5380_intr() will try to start it
+  *	in case it is not running.
+- * 
+- * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should 
++ *
++ * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should
+  *  reenable them.  This prevents reentrancy and kernel stack overflow.
+- */ 	
+-    
+-static void NCR5380_main (void *bl)
+-{
+-    Scsi_Cmnd *tmp, *prev;
+-    struct Scsi_Host *instance = first_instance;
+-    struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
+-    int done;
+-    unsigned long flags;
+-    
+-    /*
+-     * We run (with interrupts disabled) until we're sure that none of 
+-     * the host adapters have anything that can be done, at which point 
+-     * we set main_running to 0 and exit.
+-     *
+-     * Interrupts are enabled before doing various other internal 
+-     * instructions, after we've decided that we need to run through
+-     * the loop again.
+-     *
+-     * this should prevent any race conditions.
+-     * 
+-     * ++roman: Just disabling the NCR interrupt isn't sufficient here,
+-     * because also a timer int can trigger an abort or reset, which can
+-     * alter queues and touch the Falcon lock.
+-     */
+-
+-    /* Tell int handlers main() is now already executing.  Note that
+-       no races are possible here. If an int comes in before
+-       'main_running' is set here, and queues/executes main via the
+-       task queue, it doesn't do any harm, just this instance of main
+-       won't find any work left to do. */
+-    if (main_running)
+-    	return;
+-    main_running = 1;
+-
+-    local_save_flags(flags);
+-    do {
+-	local_irq_disable(); /* Freeze request queues */
+-	done = 1;
+-	
+-	if (!hostdata->connected) {
+-	    MAIN_PRINTK( "scsi%d: not connected\n", HOSTNO );
+-	    /*
+-	     * Search through the issue_queue for a command destined
+-	     * for a target that's not busy.
+-	     */
++ */
++
++static void NCR5380_main(void *bl)
++{
++	Scsi_Cmnd *tmp, *prev;
++	struct Scsi_Host *instance = first_instance;
++	struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
++	int done;
++	unsigned long flags;
++
++	/*
++	 * We run (with interrupts disabled) until we're sure that none of
++	 * the host adapters have anything that can be done, at which point
++	 * we set main_running to 0 and exit.
++	 *
++	 * Interrupts are enabled before doing various other internal
++	 * instructions, after we've decided that we need to run through
++	 * the loop again.
++	 *
++	 * this should prevent any race conditions.
++	 *
++	 * ++roman: Just disabling the NCR interrupt isn't sufficient here,
++	 * because also a timer int can trigger an abort or reset, which can
++	 * alter queues and touch the Falcon lock.
++	 */
++
++	/* Tell int handlers main() is now already executing.  Note that
++	   no races are possible here. If an int comes in before
++	   'main_running' is set here, and queues/executes main via the
++	   task queue, it doesn't do any harm, just this instance of main
++	   won't find any work left to do. */
++	if (main_running)
++		return;
++	main_running = 1;
++
++	local_save_flags(flags);
++	do {
++		local_irq_disable();	/* Freeze request queues */
++		done = 1;
++
++		if (!hostdata->connected) {
++			MAIN_PRINTK("scsi%d: not connected\n", HOSTNO);
++			/*
++			 * Search through the issue_queue for a command destined
++			 * for a target that's not busy.
++			 */
+ #if (NDEBUG & NDEBUG_LISTS)
+-	    for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL;
+-		 tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp))
+-		;
+-		/*printk("%p  ", tmp);*/
+-	    if ((tmp == prev) && tmp) printk(" LOOP\n");/* else printk("\n");*/
++			for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL;
++			     tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp))
++				;
++			/*printk("%p  ", tmp);*/
++			if ((tmp == prev) && tmp)
++				printk(" LOOP\n");
++			/* else printk("\n"); */
+ #endif
+-	    for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, 
+-		 prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) {
++			for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,
++			     prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) {
+ 
+ #if (NDEBUG & NDEBUG_LISTS)
+-		if (prev != tmp)
+-		    printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n",
+-			   tmp, tmp->device->id, hostdata->busy[tmp->device->id],
+-			   tmp->device->lun);
+-#endif
+-		/*  When we find one, remove it from the issue queue. */
+-		/* ++guenther: possible race with Falcon locking */
+-		if (
++				if (prev != tmp)
++					printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n",
++					       tmp, tmp->device->id, hostdata->busy[tmp->device->id],
++					       tmp->device->lun);
++#endif
++				/*  When we find one, remove it from the issue queue. */
++				/* ++guenther: possible race with Falcon locking */
++				if (
+ #ifdef SUPPORT_TAGS
+-		    !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)
++				    !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)
+ #else
+-		    !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))
++				    !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))
+ #endif
+-		    ) {
+-		    /* ++guenther: just to be sure, this must be atomic */
+-		    local_irq_disable();
+-		    if (prev) {
+-		        REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
+-			NEXT(prev) = NEXT(tmp);
+-		    } else {
+-		        REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
+-			hostdata->issue_queue = NEXT(tmp);
+-		    }
+-		    NEXT(tmp) = NULL;
+-		    falcon_dont_release++;
+-		    
+-		    /* reenable interrupts after finding one */
+-		    local_irq_restore(flags);
+-		    
+-		    /* 
+-		     * Attempt to establish an I_T_L nexus here. 
+-		     * On success, instance->hostdata->connected is set.
+-		     * On failure, we must add the command back to the
+-		     *   issue queue so we can keep trying.	
+-		     */
+-		    MAIN_PRINTK("scsi%d: main(): command for target %d "
+-				"lun %d removed from issue_queue\n",
+-				HOSTNO, tmp->device->id, tmp->device->lun);
+-		    /* 
+-		     * REQUEST SENSE commands are issued without tagged
+-		     * queueing, even on SCSI-II devices because the 
+-		     * contingent allegiance condition exists for the 
+-		     * entire unit.
+-		     */
+-		    /* ++roman: ...and the standard also requires that
+-		     * REQUEST SENSE command are untagged.
+-		     */
+-		    
++				    ) {
++					/* ++guenther: just to be sure, this must be atomic */
++					local_irq_disable();
++					if (prev) {
++						REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
++						NEXT(prev) = NEXT(tmp);
++					} else {
++						REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
++						hostdata->issue_queue = NEXT(tmp);
++					}
++					NEXT(tmp) = NULL;
++					falcon_dont_release++;
++
++					/* reenable interrupts after finding one */
++					local_irq_restore(flags);
++
++					/*
++					 * Attempt to establish an I_T_L nexus here.
++					 * On success, instance->hostdata->connected is set.
++					 * On failure, we must add the command back to the
++					 *   issue queue so we can keep trying.
++					 */
++					MAIN_PRINTK("scsi%d: main(): command for target %d "
++						    "lun %d removed from issue_queue\n",
++						    HOSTNO, tmp->device->id, tmp->device->lun);
++					/*
++					 * REQUEST SENSE commands are issued without tagged
++					 * queueing, even on SCSI-II devices because the
++					 * contingent allegiance condition exists for the
++					 * entire unit.
++					 */
++					/* ++roman: ...and the standard also requires that
++					 * REQUEST SENSE command are untagged.
++					 */
++
+ #ifdef SUPPORT_TAGS
+-		    cmd_get_tag( tmp, tmp->cmnd[0] != REQUEST_SENSE );
++					cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE);
+ #endif
+-		    if (!NCR5380_select(instance, tmp, 
+-			    (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : 
+-			    TAG_NEXT)) {
+-			falcon_dont_release--;
+-			/* release if target did not response! */
+-			falcon_release_lock_if_possible( hostdata );
+-			break;
+-		    } else {
+-			local_irq_disable();
+-			LIST(tmp, hostdata->issue_queue);
+-			NEXT(tmp) = hostdata->issue_queue;
+-			hostdata->issue_queue = tmp;
++					if (!NCR5380_select(instance, tmp,
++					    (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE :
++					    TAG_NEXT)) {
++						falcon_dont_release--;
++						/* release if target did not response! */
++						falcon_release_lock_if_possible(hostdata);
++						break;
++					} else {
++						local_irq_disable();
++						LIST(tmp, hostdata->issue_queue);
++						NEXT(tmp) = hostdata->issue_queue;
++						hostdata->issue_queue = tmp;
+ #ifdef SUPPORT_TAGS
+-			cmd_free_tag( tmp );
++						cmd_free_tag(tmp);
+ #endif
+-			falcon_dont_release--;
+-			local_irq_restore(flags);
+-			MAIN_PRINTK("scsi%d: main(): select() failed, "
+-				    "returned to issue_queue\n", HOSTNO);
+-			if (hostdata->connected)
+-			    break;
+-		    }
+-		} /* if target/lun/target queue is not busy */
+-	    } /* for issue_queue */
+-	} /* if (!hostdata->connected) */
+-		
+-	if (hostdata->connected 
++						falcon_dont_release--;
++						local_irq_restore(flags);
++						MAIN_PRINTK("scsi%d: main(): select() failed, "
++							    "returned to issue_queue\n", HOSTNO);
++						if (hostdata->connected)
++							break;
++					}
++				} /* if target/lun/target queue is not busy */
++			} /* for issue_queue */
++		} /* if (!hostdata->connected) */
++
++		if (hostdata->connected
+ #ifdef REAL_DMA
+-	    && !hostdata->dma_len
++		    && !hostdata->dma_len
+ #endif
+-	    ) {
+-	    local_irq_restore(flags);
+-	    MAIN_PRINTK("scsi%d: main: performing information transfer\n",
+-			HOSTNO);
+-	    NCR5380_information_transfer(instance);
+-	    MAIN_PRINTK("scsi%d: main: done set false\n", HOSTNO);
+-	    done = 0;
+-	}
+-    } while (!done);
+-
+-    /* Better allow ints _after_ 'main_running' has been cleared, else
+-       an interrupt could believe we'll pick up the work it left for
+-       us, but we won't see it anymore here... */
+-    main_running = 0;
+-    local_irq_restore(flags);
++		    ) {
++			local_irq_restore(flags);
++			MAIN_PRINTK("scsi%d: main: performing information transfer\n",
++				    HOSTNO);
++			NCR5380_information_transfer(instance);
++			MAIN_PRINTK("scsi%d: main: done set false\n", HOSTNO);
++			done = 0;
++		}
++	} while (!done);
++
++	/* Better allow ints _after_ 'main_running' has been cleared, else
++	   an interrupt could believe we'll pick up the work it left for
++	   us, but we won't see it anymore here... */
++	main_running = 0;
++	local_irq_restore(flags);
+ }
+ 
+ 
+@@ -1223,1441 +1235,1439 @@ static void NCR5380_main (void *bl)
+  * Function : void NCR5380_dma_complete (struct Scsi_Host *instance)
+  *
+  * Purpose : Called by interrupt handler when DMA finishes or a phase
+- *	mismatch occurs (which would finish the DMA transfer).  
++ *	mismatch occurs (which would finish the DMA transfer).
+  *
+  * Inputs : instance - this instance of the NCR5380.
+  *
+  */
+ 
+-static void NCR5380_dma_complete( struct Scsi_Host *instance )
++static void NCR5380_dma_complete(struct Scsi_Host *instance)
+ {
+-    SETUP_HOSTDATA(instance);
+-    int           transfered, saved_data = 0, overrun = 0, cnt, toPIO;
+-    unsigned char **data, p;
+-    volatile int  *count;
+-
+-    if (!hostdata->connected) {
+-	printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
+-	       "no connected cmd\n", HOSTNO);
+-	return;
+-    }
+-    
+-    if (atari_read_overruns) {
+-	p = hostdata->connected->SCp.phase;
+-	if (p & SR_IO) {
+-	    udelay(10);
+-	    if ((((NCR5380_read(BUS_AND_STATUS_REG)) &
+-		  (BASR_PHASE_MATCH|BASR_ACK)) ==
+-		 (BASR_PHASE_MATCH|BASR_ACK))) {
+-		saved_data = NCR5380_read(INPUT_DATA_REG);
+-		overrun = 1;
+-		DMA_PRINTK("scsi%d: read overrun handled\n", HOSTNO);
+-	    }
+-	}
+-    }
+-
+-    DMA_PRINTK("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",
+-	       HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
+-	       NCR5380_read(STATUS_REG));
+-
+-    (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+-    NCR5380_write(MODE_REG, MR_BASE);
+-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-
+-    transfered = hostdata->dma_len - NCR5380_dma_residual(instance);
+-    hostdata->dma_len = 0;
+-
+-    data = (unsigned char **) &(hostdata->connected->SCp.ptr);
+-    count = &(hostdata->connected->SCp.this_residual);
+-    *data += transfered;
+-    *count -= transfered;
+-
+-    if (atari_read_overruns) {
+-	if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
+-	    cnt = toPIO = atari_read_overruns;
+-	    if (overrun) {
+-		DMA_PRINTK("Got an input overrun, using saved byte\n");
+-		*(*data)++ = saved_data;
+-		(*count)--;
+-		cnt--;
+-		toPIO--;
+-	    }
+-	    DMA_PRINTK("Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data);
+-	    NCR5380_transfer_pio(instance, &p, &cnt, data);
+-	    *count -= toPIO - cnt;
++	SETUP_HOSTDATA(instance);
++	int transfered, saved_data = 0, overrun = 0, cnt, toPIO;
++	unsigned char **data, p;
++	volatile int *count;
++
++	if (!hostdata->connected) {
++		printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
++		       "no connected cmd\n", HOSTNO);
++		return;
++	}
++
++	if (atari_read_overruns) {
++		p = hostdata->connected->SCp.phase;
++		if (p & SR_IO) {
++			udelay(10);
++			if ((NCR5380_read(BUS_AND_STATUS_REG) &
++			     (BASR_PHASE_MATCH|BASR_ACK)) ==
++			    (BASR_PHASE_MATCH|BASR_ACK)) {
++				saved_data = NCR5380_read(INPUT_DATA_REG);
++				overrun = 1;
++				DMA_PRINTK("scsi%d: read overrun handled\n", HOSTNO);
++			}
++		}
++	}
++
++	DMA_PRINTK("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",
++		   HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
++		   NCR5380_read(STATUS_REG));
++
++	(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
++	NCR5380_write(MODE_REG, MR_BASE);
++	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++
++	transfered = hostdata->dma_len - NCR5380_dma_residual(instance);
++	hostdata->dma_len = 0;
++
++	data = (unsigned char **)&hostdata->connected->SCp.ptr;
++	count = &hostdata->connected->SCp.this_residual;
++	*data += transfered;
++	*count -= transfered;
++
++	if (atari_read_overruns) {
++		if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
++			cnt = toPIO = atari_read_overruns;
++			if (overrun) {
++				DMA_PRINTK("Got an input overrun, using saved byte\n");
++				*(*data)++ = saved_data;
++				(*count)--;
++				cnt--;
++				toPIO--;
++			}
++			DMA_PRINTK("Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data);
++			NCR5380_transfer_pio(instance, &p, &cnt, data);
++			*count -= toPIO - cnt;
++		}
+ 	}
+-    }
+ }
+ #endif /* REAL_DMA */
+ 
+ 
+ /*
+  * Function : void NCR5380_intr (int irq)
+- * 
++ *
+  * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
+- *	from the disconnected queue, and restarting NCR5380_main() 
++ *	from the disconnected queue, and restarting NCR5380_main()
+  *	as required.
+  *
+  * Inputs : int irq, irq that caused this interrupt.
+  *
+  */
+ 
+-static irqreturn_t NCR5380_intr (int irq, void *dev_id)
++static irqreturn_t NCR5380_intr(int irq, void *dev_id)
+ {
+-    struct Scsi_Host *instance = first_instance;
+-    int done = 1, handled = 0;
+-    unsigned char basr;
+-
+-    INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);
+-
+-    /* Look for pending interrupts */
+-    basr = NCR5380_read(BUS_AND_STATUS_REG);
+-    INT_PRINTK("scsi%d: BASR=%02x\n", HOSTNO, basr);
+-    /* dispatch to appropriate routine if found and done=0 */
+-    if (basr & BASR_IRQ) {
+-	NCR_PRINT(NDEBUG_INTR);
+-	if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
+-	    done = 0;
+-	    ENABLE_IRQ();
+-	    INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO);
+-	    NCR5380_reselect(instance);
+-	    (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+-	}
+-	else if (basr & BASR_PARITY_ERROR) {
+-	    INT_PRINTK("scsi%d: PARITY interrupt\n", HOSTNO);
+-	    (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+-	}
+-	else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
+-	    INT_PRINTK("scsi%d: RESET interrupt\n", HOSTNO);
+-	    (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+-	}
+-	else {
+-	    /*  
+-	     * The rest of the interrupt conditions can occur only during a
+-	     * DMA transfer
+-	     */
++	struct Scsi_Host *instance = first_instance;
++	int done = 1, handled = 0;
++	unsigned char basr;
++
++	INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);
++
++	/* Look for pending interrupts */
++	basr = NCR5380_read(BUS_AND_STATUS_REG);
++	INT_PRINTK("scsi%d: BASR=%02x\n", HOSTNO, basr);
++	/* dispatch to appropriate routine if found and done=0 */
++	if (basr & BASR_IRQ) {
++		NCR_PRINT(NDEBUG_INTR);
++		if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
++			done = 0;
++			ENABLE_IRQ();
++			INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO);
++			NCR5380_reselect(instance);
++			(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
++		} else if (basr & BASR_PARITY_ERROR) {
++			INT_PRINTK("scsi%d: PARITY interrupt\n", HOSTNO);
++			(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
++		} else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
++			INT_PRINTK("scsi%d: RESET interrupt\n", HOSTNO);
++			(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
++		} else {
++			/*
++			 * The rest of the interrupt conditions can occur only during a
++			 * DMA transfer
++			 */
+ 
+ #if defined(REAL_DMA)
+-	    /*
+-	     * We should only get PHASE MISMATCH and EOP interrupts if we have
+-	     * DMA enabled, so do a sanity check based on the current setting
+-	     * of the MODE register.
+-	     */
+-
+-	    if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) &&
+-		((basr & BASR_END_DMA_TRANSFER) || 
+-		 !(basr & BASR_PHASE_MATCH))) {
+-		    
+-		INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
+-		NCR5380_dma_complete( instance );
+-		done = 0;
+-		ENABLE_IRQ();
+-	    } else
++			/*
++			 * We should only get PHASE MISMATCH and EOP interrupts if we have
++			 * DMA enabled, so do a sanity check based on the current setting
++			 * of the MODE register.
++			 */
++
++			if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) &&
++			    ((basr & BASR_END_DMA_TRANSFER) ||
++			     !(basr & BASR_PHASE_MATCH))) {
++
++				INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
++				NCR5380_dma_complete( instance );
++				done = 0;
++				ENABLE_IRQ();
++			} else
+ #endif /* REAL_DMA */
+-	    {
++			{
+ /* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */
+-		if (basr & BASR_PHASE_MATCH)
+-		    printk(KERN_NOTICE "scsi%d: unknown interrupt, "
+-			   "BASR 0x%x, MR 0x%x, SR 0x%x\n",
+-			   HOSTNO, basr, NCR5380_read(MODE_REG),
+-			   NCR5380_read(STATUS_REG));
+-		(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+-	    }
+-	} /* if !(SELECTION || PARITY) */
+-	handled = 1;
+-    } /* BASR & IRQ */
+-    else {
+-	printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
+-	       "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
+-	       NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
+-	(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+-    }
+-    
+-    if (!done) {
+-	INT_PRINTK("scsi%d: in int routine, calling main\n", HOSTNO);
+-	/* Put a call to NCR5380_main() on the queue... */
+-	queue_main();
+-    }
+-    return IRQ_RETVAL(handled);
++				if (basr & BASR_PHASE_MATCH)
++					printk(KERN_NOTICE "scsi%d: unknown interrupt, "
++					       "BASR 0x%x, MR 0x%x, SR 0x%x\n",
++					       HOSTNO, basr, NCR5380_read(MODE_REG),
++					       NCR5380_read(STATUS_REG));
++				(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
++			}
++		} /* if !(SELECTION || PARITY) */
++		handled = 1;
++	} /* BASR & IRQ */ else {
++		printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
++		       "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
++		       NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
++		(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
++	}
++
++	if (!done) {
++		INT_PRINTK("scsi%d: in int routine, calling main\n", HOSTNO);
++		/* Put a call to NCR5380_main() on the queue... */
++		queue_main();
++	}
++	return IRQ_RETVAL(handled);
+ }
+ 
+ #ifdef NCR5380_STATS
+-static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd* cmd)
++static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd *cmd)
+ {
+ # ifdef NCR5380_STAT_LIMIT
+-    if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
++	if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
+ # endif
+-	switch (cmd->cmnd[0])
+-	{
+-	    case WRITE:
+-	    case WRITE_6:
+-	    case WRITE_10:
+-		hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase);
+-		/*hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;*/
+-		hostdata->pendingw--;
+-		break;
+-	    case READ:
+-	    case READ_6:
+-	    case READ_10:
+-		hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase);
+-		/*hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;*/
+-		hostdata->pendingr--;
+-		break;
+-	}
++		switch (cmd->cmnd[0]) {
++		case WRITE:
++		case WRITE_6:
++		case WRITE_10:
++			hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase);
++			/*hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;*/
++			hostdata->pendingw--;
++			break;
++		case READ:
++		case READ_6:
++		case READ_10:
++			hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase);
++			/*hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;*/
++			hostdata->pendingr--;
++			break;
++		}
+ }
+ #endif
+ 
+-/* 
+- * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, 
++/*
++ * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
+  *	int tag);
+  *
+  * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
+- *	including ARBITRATION, SELECTION, and initial message out for 
+- *	IDENTIFY and queue messages. 
++ *	including ARBITRATION, SELECTION, and initial message out for
++ *	IDENTIFY and queue messages.
+  *
+- * Inputs : instance - instantiation of the 5380 driver on which this 
+- * 	target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for 
+- *	new tag, TAG_NONE for untagged queueing, otherwise set to the tag for 
++ * Inputs : instance - instantiation of the 5380 driver on which this
++ *	target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for
++ *	new tag, TAG_NONE for untagged queueing, otherwise set to the tag for
+  *	the command that is presently connected.
+- * 
++ *
+  * Returns : -1 if selection could not execute for some reason,
+- *	0 if selection succeeded or failed because the target 
+- * 	did not respond.
++ *	0 if selection succeeded or failed because the target
++ *	did not respond.
+  *
+- * Side effects : 
+- * 	If bus busy, arbitration failed, etc, NCR5380_select() will exit 
++ * Side effects :
++ *	If bus busy, arbitration failed, etc, NCR5380_select() will exit
+  *		with registers as they should have been on entry - ie
+  *		SELECT_ENABLE will be set appropriately, the NCR5380
+  *		will cease to drive any SCSI bus signals.
+  *
+- *	If successful : I_T_L or I_T_L_Q nexus will be established, 
+- *		instance->connected will be set to cmd.  
+- * 		SELECT interrupt will be disabled.
++ *	If successful : I_T_L or I_T_L_Q nexus will be established,
++ *		instance->connected will be set to cmd.
++ *		SELECT interrupt will be disabled.
+  *
+- *	If failed (no target) : cmd->scsi_done() will be called, and the 
++ *	If failed (no target) : cmd->scsi_done() will be called, and the
+  *		cmd->result host byte set to DID_BAD_TARGET.
+  */
+ 
+-static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
++static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
+ {
+-    SETUP_HOSTDATA(instance);
+-    unsigned char tmp[3], phase;
+-    unsigned char *data;
+-    int len;
+-    unsigned long timeout;
+-    unsigned long flags;
+-
+-    hostdata->restart_select = 0;
+-    NCR_PRINT(NDEBUG_ARBITRATION);
+-    ARB_PRINTK("scsi%d: starting arbitration, id = %d\n", HOSTNO,
+-	       instance->this_id);
+-
+-    /* 
+-     * Set the phase bits to 0, otherwise the NCR5380 won't drive the 
+-     * data bus during SELECTION.
+-     */
++	SETUP_HOSTDATA(instance);
++	unsigned char tmp[3], phase;
++	unsigned char *data;
++	int len;
++	unsigned long timeout;
++	unsigned long flags;
++
++	hostdata->restart_select = 0;
++	NCR_PRINT(NDEBUG_ARBITRATION);
++	ARB_PRINTK("scsi%d: starting arbitration, id = %d\n", HOSTNO,
++		   instance->this_id);
++
++	/*
++	 * Set the phase bits to 0, otherwise the NCR5380 won't drive the
++	 * data bus during SELECTION.
++	 */
+ 
+-    local_irq_save(flags);
+-    if (hostdata->connected) {
+-	local_irq_restore(flags);
+-	return -1;
+-    }
+-    NCR5380_write(TARGET_COMMAND_REG, 0);
++	local_irq_save(flags);
++	if (hostdata->connected) {
++		local_irq_restore(flags);
++		return -1;
++	}
++	NCR5380_write(TARGET_COMMAND_REG, 0);
+ 
++	/*
++	 * Start arbitration.
++	 */
+ 
+-    /* 
+-     * Start arbitration.
+-     */
+-    
+-    NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
+-    NCR5380_write(MODE_REG, MR_ARBITRATE);
++	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
++	NCR5380_write(MODE_REG, MR_ARBITRATE);
+ 
+-    local_irq_restore(flags);
++	local_irq_restore(flags);
+ 
+-    /* Wait for arbitration logic to complete */
++	/* Wait for arbitration logic to complete */
+ #if defined(NCR_TIMEOUT)
+-    {
+-      unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
++	{
++		unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
+ 
+-      while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
+-	   && time_before(jiffies, timeout) && !hostdata->connected)
+-	;
+-      if (time_after_eq(jiffies, timeout))
+-      {
+-	printk("scsi : arbitration timeout at %d\n", __LINE__);
+-	NCR5380_write(MODE_REG, MR_BASE);
+-	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+-	return -1;
+-      }
+-    }
++		while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) &&
++		       time_before(jiffies, timeout) && !hostdata->connected)
++			;
++		if (time_after_eq(jiffies, timeout)) {
++			printk("scsi : arbitration timeout at %d\n", __LINE__);
++			NCR5380_write(MODE_REG, MR_BASE);
++			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
++			return -1;
++		}
++	}
+ #else /* NCR_TIMEOUT */
+-    while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
+-	 && !hostdata->connected);
++	while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) &&
++	       !hostdata->connected)
++		;
+ #endif
+ 
+-    ARB_PRINTK("scsi%d: arbitration complete\n", HOSTNO);
++	ARB_PRINTK("scsi%d: arbitration complete\n", HOSTNO);
+ 
+-    if (hostdata->connected) {
+-	NCR5380_write(MODE_REG, MR_BASE); 
+-	return -1;
+-    }
+-    /* 
+-     * The arbitration delay is 2.2us, but this is a minimum and there is 
+-     * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate
+-     * the integral nature of udelay().
+-     *
+-     */
+-
+-    udelay(3);
+-
+-    /* Check for lost arbitration */
+-    if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
+-	(NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
+-	(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
+-	hostdata->connected) {
+-	NCR5380_write(MODE_REG, MR_BASE); 
+-	ARB_PRINTK("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n",
+-		   HOSTNO);
+-	return -1;
+-    }
+-
+-     /* after/during arbitration, BSY should be asserted.
+-	IBM DPES-31080 Version S31Q works now */
+-     /* Tnx to Thomas_Roesch at m2.maus.de for finding this! (Roman) */
+-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL |
+-					 ICR_ASSERT_BSY ) ;
+-    
+-    if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
+-	hostdata->connected) {
+-	NCR5380_write(MODE_REG, MR_BASE);
+-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-	ARB_PRINTK("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n",
+-		   HOSTNO);
+-	return -1;
+-    }
+-
+-    /* 
+-     * Again, bus clear + bus settle time is 1.2us, however, this is 
+-     * a minimum so we'll udelay ceil(1.2)
+-     */
++	if (hostdata->connected) {
++		NCR5380_write(MODE_REG, MR_BASE);
++		return -1;
++	}
++	/*
++	 * The arbitration delay is 2.2us, but this is a minimum and there is
++	 * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate
++	 * the integral nature of udelay().
++	 *
++	 */
++
++	udelay(3);
++
++	/* Check for lost arbitration */
++	if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
++	    (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
++	    (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
++	    hostdata->connected) {
++		NCR5380_write(MODE_REG, MR_BASE);
++		ARB_PRINTK("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n",
++			   HOSTNO);
++		return -1;
++	}
++
++	/* after/during arbitration, BSY should be asserted.
++	   IBM DPES-31080 Version S31Q works now */
++	/* Tnx to Thomas_Roesch at m2.maus.de for finding this! (Roman) */
++	NCR5380_write(INITIATOR_COMMAND_REG,
++		      ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);
++
++	if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
++	    hostdata->connected) {
++		NCR5380_write(MODE_REG, MR_BASE);
++		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++		ARB_PRINTK("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n",
++			   HOSTNO);
++		return -1;
++	}
++
++	/*
++	 * Again, bus clear + bus settle time is 1.2us, however, this is
++	 * a minimum so we'll udelay ceil(1.2)
++	 */
+ 
+ #ifdef CONFIG_ATARI_SCSI_TOSHIBA_DELAY
+-    /* ++roman: But some targets (see above :-) seem to need a bit more... */
+-    udelay(15);
++	/* ++roman: But some targets (see above :-) seem to need a bit more... */
++	udelay(15);
+ #else
+-    udelay(2);
++	udelay(2);
+ #endif
+-    
+-    if (hostdata->connected) {
++
++	if (hostdata->connected) {
++		NCR5380_write(MODE_REG, MR_BASE);
++		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++		return -1;
++	}
++
++	ARB_PRINTK("scsi%d: won arbitration\n", HOSTNO);
++
++	/*
++	 * Now that we have won arbitration, start Selection process, asserting
++	 * the host and target ID's on the SCSI bus.
++	 */
++
++	NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id)));
++
++	/*
++	 * Raise ATN while SEL is true before BSY goes false from arbitration,
++	 * since this is the only way to guarantee that we'll get a MESSAGE OUT
++	 * phase immediately after selection.
++	 */
++
++	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY |
++		      ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL ));
+ 	NCR5380_write(MODE_REG, MR_BASE);
+-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-	return -1;
+-    }
+ 
+-    ARB_PRINTK("scsi%d: won arbitration\n", HOSTNO);
++	/*
++	 * Reselect interrupts must be turned off prior to the dropping of BSY,
++	 * otherwise we will trigger an interrupt.
++	 */
++
++	if (hostdata->connected) {
++		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++		return -1;
++	}
++
++	NCR5380_write(SELECT_ENABLE_REG, 0);
+ 
+-    /* 
+-     * Now that we have won arbitration, start Selection process, asserting 
+-     * the host and target ID's on the SCSI bus.
+-     */
+-
+-    NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id)));
+-
+-    /* 
+-     * Raise ATN while SEL is true before BSY goes false from arbitration,
+-     * since this is the only way to guarantee that we'll get a MESSAGE OUT
+-     * phase immediately after selection.
+-     */
+-
+-    NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | 
+-	ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL ));
+-    NCR5380_write(MODE_REG, MR_BASE);
+-
+-    /* 
+-     * Reselect interrupts must be turned off prior to the dropping of BSY,
+-     * otherwise we will trigger an interrupt.
+-     */
++	/*
++	 * The initiator shall then wait at least two deskew delays and release
++	 * the BSY signal.
++	 */
++	udelay(1);        /* wingel -- wait two bus deskew delay >2*45ns */
+ 
+-    if (hostdata->connected) {
+-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-	return -1;
+-    }
++	/* Reset BSY */
++	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA |
++		      ICR_ASSERT_ATN | ICR_ASSERT_SEL));
++
++	/*
++	 * Something weird happens when we cease to drive BSY - looks
++	 * like the board/chip is letting us do another read before the
++	 * appropriate propagation delay has expired, and we're confusing
++	 * a BSY signal from ourselves as the target's response to SELECTION.
++	 *
++	 * A small delay (the 'C++' frontend breaks the pipeline with an
++	 * unnecessary jump, making it work on my 386-33/Trantor T128, the
++	 * tighter 'C' code breaks and requires this) solves the problem -
++	 * the 1 us delay is arbitrary, and only used because this delay will
++	 * be the same on other platforms and since it works here, it should
++	 * work there.
++	 *
++	 * wingel suggests that this could be due to failing to wait
++	 * one deskew delay.
++	 */
++
++	udelay(1);
+ 
+-    NCR5380_write(SELECT_ENABLE_REG, 0);
++	SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->device->id);
++
++	/*
++	 * The SCSI specification calls for a 250 ms timeout for the actual
++	 * selection.
++	 */
+ 
+-    /*
+-     * The initiator shall then wait at least two deskew delays and release 
+-     * the BSY signal.
+-     */
+-    udelay(1);        /* wingel -- wait two bus deskew delay >2*45ns */
+-
+-    /* Reset BSY */
+-    NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | 
+-	ICR_ASSERT_ATN | ICR_ASSERT_SEL));
+-
+-    /* 
+-     * Something weird happens when we cease to drive BSY - looks
+-     * like the board/chip is letting us do another read before the 
+-     * appropriate propagation delay has expired, and we're confusing
+-     * a BSY signal from ourselves as the target's response to SELECTION.
+-     *
+-     * A small delay (the 'C++' frontend breaks the pipeline with an
+-     * unnecessary jump, making it work on my 386-33/Trantor T128, the
+-     * tighter 'C' code breaks and requires this) solves the problem - 
+-     * the 1 us delay is arbitrary, and only used because this delay will 
+-     * be the same on other platforms and since it works here, it should 
+-     * work there.
+-     *
+-     * wingel suggests that this could be due to failing to wait
+-     * one deskew delay.
+-     */
+-
+-    udelay(1);
+-
+-    SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->device->id);
+-
+-    /* 
+-     * The SCSI specification calls for a 250 ms timeout for the actual 
+-     * selection.
+-     */
+-
+-    timeout = jiffies + 25; 
+-
+-    /* 
+-     * XXX very interesting - we're seeing a bounce where the BSY we 
+-     * asserted is being reflected / still asserted (propagation delay?)
+-     * and it's detecting as true.  Sigh.
+-     */
++	timeout = jiffies + 25;
++
++	/*
++	 * XXX very interesting - we're seeing a bounce where the BSY we
++	 * asserted is being reflected / still asserted (propagation delay?)
++	 * and it's detecting as true.  Sigh.
++	 */
+ 
+ #if 0
+-    /* ++roman: If a target conformed to the SCSI standard, it wouldn't assert
+-     * IO while SEL is true. But again, there are some disks out the in the
+-     * world that do that nevertheless. (Somebody claimed that this announces
+-     * reselection capability of the target.) So we better skip that test and
+-     * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
+-     */
+-
+-    while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & 
+-	(SR_BSY | SR_IO)));
+-
+-    if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == 
+-	    (SR_SEL | SR_IO)) {
+-	    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-	    NCR5380_reselect(instance);
+-	    printk (KERN_ERR "scsi%d: reselection after won arbitration?\n",
+-		    HOSTNO);
+-	    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+-	    return -1;
+-    }
++	/* ++roman: If a target conformed to the SCSI standard, it wouldn't assert
++	 * IO while SEL is true. But again, there are some disks out the in the
++	 * world that do that nevertheless. (Somebody claimed that this announces
++	 * reselection capability of the target.) So we better skip that test and
++	 * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
++	 */
++
++	while (time_before(jiffies, timeout) &&
++	       !(NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO)))
++		;
++
++	if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
++		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++		NCR5380_reselect(instance);
++		printk(KERN_ERR "scsi%d: reselection after won arbitration?\n",
++		       HOSTNO);
++		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
++		return -1;
++	}
+ #else
+-    while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
++	while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY))
++		;
+ #endif
+ 
+-    /* 
+-     * No less than two deskew delays after the initiator detects the 
+-     * BSY signal is true, it shall release the SEL signal and may 
+-     * change the DATA BUS.                                     -wingel
+-     */
++	/*
++	 * No less than two deskew delays after the initiator detects the
++	 * BSY signal is true, it shall release the SEL signal and may
++	 * change the DATA BUS.                                     -wingel
++	 */
+ 
+-    udelay(1);
++	udelay(1);
+ 
+-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
++	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+ 
+-    if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
+-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-	if (hostdata->targets_present & (1 << cmd->device->id)) {
+-	    printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO);
+-	    if (hostdata->restart_select)
+-		printk(KERN_NOTICE "\trestart select\n");
+-	    NCR_PRINT(NDEBUG_ANY);
+-	    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+-	    return -1;
+-	}
+-	cmd->result = DID_BAD_TARGET << 16;
++	if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
++		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++		if (hostdata->targets_present & (1 << cmd->device->id)) {
++			printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO);
++			if (hostdata->restart_select)
++				printk(KERN_NOTICE "\trestart select\n");
++			NCR_PRINT(NDEBUG_ANY);
++			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
++			return -1;
++		}
++		cmd->result = DID_BAD_TARGET << 16;
+ #ifdef NCR5380_STATS
+-	collect_stats(hostdata, cmd);
++		collect_stats(hostdata, cmd);
+ #endif
+ #ifdef SUPPORT_TAGS
+-	cmd_free_tag( cmd );
++		cmd_free_tag(cmd);
+ #endif
+-	cmd->scsi_done(cmd);
+-	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+-	SEL_PRINTK("scsi%d: target did not respond within 250ms\n", HOSTNO);
+-	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+-	return 0;
+-    } 
++		cmd->scsi_done(cmd);
++		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
++		SEL_PRINTK("scsi%d: target did not respond within 250ms\n", HOSTNO);
++		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
++		return 0;
++	}
++
++	hostdata->targets_present |= (1 << cmd->device->id);
+ 
+-    hostdata->targets_present |= (1 << cmd->device->id);
++	/*
++	 * Since we followed the SCSI spec, and raised ATN while SEL
++	 * was true but before BSY was false during selection, the information
++	 * transfer phase should be a MESSAGE OUT phase so that we can send the
++	 * IDENTIFY message.
++	 *
++	 * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
++	 * message (2 bytes) with a tag ID that we increment with every command
++	 * until it wraps back to 0.
++	 *
++	 * XXX - it turns out that there are some broken SCSI-II devices,
++	 *	     which claim to support tagged queuing but fail when more than
++	 *	     some number of commands are issued at once.
++	 */
++
++	/* Wait for start of REQ/ACK handshake */
++	while (!(NCR5380_read(STATUS_REG) & SR_REQ))
++		;
+ 
+-    /*
+-     * Since we followed the SCSI spec, and raised ATN while SEL 
+-     * was true but before BSY was false during selection, the information
+-     * transfer phase should be a MESSAGE OUT phase so that we can send the
+-     * IDENTIFY message.
+-     * 
+-     * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
+-     * message (2 bytes) with a tag ID that we increment with every command
+-     * until it wraps back to 0.
+-     *
+-     * XXX - it turns out that there are some broken SCSI-II devices,
+-     *	     which claim to support tagged queuing but fail when more than
+-     *	     some number of commands are issued at once.
+-     */
+-
+-    /* Wait for start of REQ/ACK handshake */
+-    while (!(NCR5380_read(STATUS_REG) & SR_REQ));
+-
+-    SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n",
+-	       HOSTNO, cmd->device->id);
+-    tmp[0] = IDENTIFY(1, cmd->device->lun);
++	SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n",
++		   HOSTNO, cmd->device->id);
++	tmp[0] = IDENTIFY(1, cmd->device->lun);
+ 
+ #ifdef SUPPORT_TAGS
+-    if (cmd->tag != TAG_NONE) {
+-	tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG;
+-	tmp[2] = cmd->tag;
+-	len = 3;
+-    } else 
+-	len = 1;
++	if (cmd->tag != TAG_NONE) {
++		tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG;
++		tmp[2] = cmd->tag;
++		len = 3;
++	} else
++		len = 1;
+ #else
+-    len = 1;
+-    cmd->tag=0;
++	len = 1;
++	cmd->tag = 0;
+ #endif /* SUPPORT_TAGS */
+ 
+-    /* Send message(s) */
+-    data = tmp;
+-    phase = PHASE_MSGOUT;
+-    NCR5380_transfer_pio(instance, &phase, &len, &data);
+-    SEL_PRINTK("scsi%d: nexus established.\n", HOSTNO);
+-    /* XXX need to handle errors here */
+-    hostdata->connected = cmd;
++	/* Send message(s) */
++	data = tmp;
++	phase = PHASE_MSGOUT;
++	NCR5380_transfer_pio(instance, &phase, &len, &data);
++	SEL_PRINTK("scsi%d: nexus established.\n", HOSTNO);
++	/* XXX need to handle errors here */
++	hostdata->connected = cmd;
+ #ifndef SUPPORT_TAGS
+-    hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+-#endif    
+-
+-    initialize_SCp(cmd);
++	hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
++#endif
+ 
++	initialize_SCp(cmd);
+ 
+-    return 0;
++	return 0;
+ }
+ 
+-/* 
+- * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, 
++/*
++ * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance,
+  *      unsigned char *phase, int *count, unsigned char **data)
+  *
+  * Purpose : transfers data in given phase using polled I/O
+  *
+- * Inputs : instance - instance of driver, *phase - pointer to 
+- *	what phase is expected, *count - pointer to number of 
++ * Inputs : instance - instance of driver, *phase - pointer to
++ *	what phase is expected, *count - pointer to number of
+  *	bytes to transfer, **data - pointer to data pointer.
+- * 
++ *
+  * Returns : -1 when different phase is entered without transferring
+  *	maximum number of bytes, 0 if all bytes are transfered or exit
+  *	is in same phase.
+  *
+- * 	Also, *phase, *count, *data are modified in place.
++ *	Also, *phase, *count, *data are modified in place.
+  *
+  * XXX Note : handling for bus free may be useful.
+  */
+ 
+ /*
+- * Note : this code is not as quick as it could be, however it 
++ * Note : this code is not as quick as it could be, however it
+  * IS 100% reliable, and for the actual data transfer where speed
+  * counts, we will always do a pseudo DMA or DMA transfer.
+  */
+ 
+-static int NCR5380_transfer_pio( struct Scsi_Host *instance, 
+-				 unsigned char *phase, int *count,
+-				 unsigned char **data)
+-{
+-    register unsigned char p = *phase, tmp;
+-    register int c = *count;
+-    register unsigned char *d = *data;
+-
+-    /* 
+-     * The NCR5380 chip will only drive the SCSI bus when the 
+-     * phase specified in the appropriate bits of the TARGET COMMAND
+-     * REGISTER match the STATUS REGISTER
+-     */
+-
+-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
+-
+-    do {
+-	/* 
+-	 * Wait for assertion of REQ, after which the phase bits will be 
+-	 * valid 
+-	 */
+-	while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ));
+-
+-	HSH_PRINTK("scsi%d: REQ detected\n", HOSTNO);
+-
+-	/* Check for phase mismatch */	
+-	if ((tmp & PHASE_MASK) != p) {
+-	    PIO_PRINTK("scsi%d: phase mismatch\n", HOSTNO);
+-	    NCR_PRINT_PHASE(NDEBUG_PIO);
+-	    break;
+-	}
+-
+-	/* Do actual transfer from SCSI bus to / from memory */
+-	if (!(p & SR_IO)) 
+-	    NCR5380_write(OUTPUT_DATA_REG, *d);
+-	else 
+-	    *d = NCR5380_read(CURRENT_SCSI_DATA_REG);
+-
+-	++d;
+-
+-	/* 
+-	 * The SCSI standard suggests that in MSGOUT phase, the initiator
+-	 * should drop ATN on the last byte of the message phase
+-	 * after REQ has been asserted for the handshake but before
+-	 * the initiator raises ACK.
+-	 */
+-
+-	if (!(p & SR_IO)) {
+-	    if (!((p & SR_MSG) && c > 1)) {
+-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
+-		    ICR_ASSERT_DATA);
+-		NCR_PRINT(NDEBUG_PIO);
+-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
+-			ICR_ASSERT_DATA | ICR_ASSERT_ACK);
+-	    } else {
+-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+-		    ICR_ASSERT_DATA | ICR_ASSERT_ATN);
+-		NCR_PRINT(NDEBUG_PIO);
+-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
+-		    ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
+-	    }
+-	} else {
+-	    NCR_PRINT(NDEBUG_PIO);
+-	    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
+-	}
++static int NCR5380_transfer_pio(struct Scsi_Host *instance,
++				unsigned char *phase, int *count,
++				unsigned char **data)
++{
++	register unsigned char p = *phase, tmp;
++	register int c = *count;
++	register unsigned char *d = *data;
++
++	/*
++	 * The NCR5380 chip will only drive the SCSI bus when the
++	 * phase specified in the appropriate bits of the TARGET COMMAND
++	 * REGISTER match the STATUS REGISTER
++	 */
+ 
+-	while (NCR5380_read(STATUS_REG) & SR_REQ);
++	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
+ 
+-	HSH_PRINTK("scsi%d: req false, handshake complete\n", HOSTNO);
++	do {
++		/*
++		 * Wait for assertion of REQ, after which the phase bits will be
++		 * valid
++		 */
++		while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ))
++			;
+ 
+-/*
+- * We have several special cases to consider during REQ/ACK handshaking : 
+- * 1.  We were in MSGOUT phase, and we are on the last byte of the 
+- *	message.  ATN must be dropped as ACK is dropped.
+- *
+- * 2.  We are in a MSGIN phase, and we are on the last byte of the  
+- *	message.  We must exit with ACK asserted, so that the calling
+- *	code may raise ATN before dropping ACK to reject the message.
+- *
+- * 3.  ACK and ATN are clear and the target may proceed as normal.
+- */
+-	if (!(p == PHASE_MSGIN && c == 1)) {  
+-	    if (p == PHASE_MSGOUT && c > 1)
+-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+-	    else
+-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-	} 
+-    } while (--c);
++		HSH_PRINTK("scsi%d: REQ detected\n", HOSTNO);
+ 
+-    PIO_PRINTK("scsi%d: residual %d\n", HOSTNO, c);
++		/* Check for phase mismatch */
++		if ((tmp & PHASE_MASK) != p) {
++			PIO_PRINTK("scsi%d: phase mismatch\n", HOSTNO);
++			NCR_PRINT_PHASE(NDEBUG_PIO);
++			break;
++		}
+ 
+-    *count = c;
+-    *data = d;
+-    tmp = NCR5380_read(STATUS_REG);
+-    /* The phase read from the bus is valid if either REQ is (already)
+-     * asserted or if ACK hasn't been released yet. The latter is the case if
+-     * we're in MSGIN and all wanted bytes have been received. */
+-    if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0))
+-	*phase = tmp & PHASE_MASK;
+-    else 
+-	*phase = PHASE_UNKNOWN;
++		/* Do actual transfer from SCSI bus to / from memory */
++		if (!(p & SR_IO))
++			NCR5380_write(OUTPUT_DATA_REG, *d);
++		else
++			*d = NCR5380_read(CURRENT_SCSI_DATA_REG);
+ 
+-    if (!c || (*phase == p))
+-	return 0;
+-    else 
+-	return -1;
++		++d;
++
++		/*
++		 * The SCSI standard suggests that in MSGOUT phase, the initiator
++		 * should drop ATN on the last byte of the message phase
++		 * after REQ has been asserted for the handshake but before
++		 * the initiator raises ACK.
++		 */
++
++		if (!(p & SR_IO)) {
++			if (!((p & SR_MSG) && c > 1)) {
++				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
++				NCR_PRINT(NDEBUG_PIO);
++				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
++					      ICR_ASSERT_DATA | ICR_ASSERT_ACK);
++			} else {
++				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
++					      ICR_ASSERT_DATA | ICR_ASSERT_ATN);
++				NCR_PRINT(NDEBUG_PIO);
++				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
++					      ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
++			}
++		} else {
++			NCR_PRINT(NDEBUG_PIO);
++			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
++		}
++
++		while (NCR5380_read(STATUS_REG) & SR_REQ)
++			;
++
++		HSH_PRINTK("scsi%d: req false, handshake complete\n", HOSTNO);
++
++		/*
++		 * We have several special cases to consider during REQ/ACK handshaking :
++		 * 1.  We were in MSGOUT phase, and we are on the last byte of the
++		 *	message.  ATN must be dropped as ACK is dropped.
++		 *
++		 * 2.  We are in a MSGIN phase, and we are on the last byte of the
++		 *	message.  We must exit with ACK asserted, so that the calling
++		 *	code may raise ATN before dropping ACK to reject the message.
++		 *
++		 * 3.  ACK and ATN are clear and the target may proceed as normal.
++		 */
++		if (!(p == PHASE_MSGIN && c == 1)) {
++			if (p == PHASE_MSGOUT && c > 1)
++				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
++			else
++				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++		}
++	} while (--c);
++
++	PIO_PRINTK("scsi%d: residual %d\n", HOSTNO, c);
++
++	*count = c;
++	*data = d;
++	tmp = NCR5380_read(STATUS_REG);
++	/* The phase read from the bus is valid if either REQ is (already)
++	 * asserted or if ACK hasn't been released yet. The latter is the case if
++	 * we're in MSGIN and all wanted bytes have been received.
++	 */
++	if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0))
++		*phase = tmp & PHASE_MASK;
++	else
++		*phase = PHASE_UNKNOWN;
++
++	if (!c || (*phase == p))
++		return 0;
++	else
++		return -1;
+ }
+ 
+ /*
+  * Function : do_abort (Scsi_Host *host)
+- * 
+- * Purpose : abort the currently established nexus.  Should only be 
+- * 	called from a routine which can drop into a 
+- * 
++ *
++ * Purpose : abort the currently established nexus.  Should only be
++ *	called from a routine which can drop into a
++ *
+  * Returns : 0 on success, -1 on failure.
+  */
+ 
+-static int do_abort (struct Scsi_Host *host) 
++static int do_abort(struct Scsi_Host *host)
+ {
+-    unsigned char tmp, *msgptr, phase;
+-    int len;
+-
+-    /* Request message out phase */
+-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
++	unsigned char tmp, *msgptr, phase;
++	int len;
+ 
+-    /* 
+-     * Wait for the target to indicate a valid phase by asserting 
+-     * REQ.  Once this happens, we'll have either a MSGOUT phase 
+-     * and can immediately send the ABORT message, or we'll have some 
+-     * other phase and will have to source/sink data.
+-     * 
+-     * We really don't care what value was on the bus or what value
+-     * the target sees, so we just handshake.
+-     */
+-    
+-    while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ);
+-
+-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
+-
+-    if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
+-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | 
+-		      ICR_ASSERT_ACK);
+-	while (NCR5380_read(STATUS_REG) & SR_REQ);
++	/* Request message out phase */
+ 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+-    }
+-   
+-    tmp = ABORT;
+-    msgptr = &tmp;
+-    len = 1;
+-    phase = PHASE_MSGOUT;
+-    NCR5380_transfer_pio (host, &phase, &len, &msgptr);
+-
+-    /*
+-     * If we got here, and the command completed successfully,
+-     * we're about to go into bus free state.
+-     */
+ 
+-    return len ? -1 : 0;
++	/*
++	 * Wait for the target to indicate a valid phase by asserting
++	 * REQ.  Once this happens, we'll have either a MSGOUT phase
++	 * and can immediately send the ABORT message, or we'll have some
++	 * other phase and will have to source/sink data.
++	 *
++	 * We really don't care what value was on the bus or what value
++	 * the target sees, so we just handshake.
++	 */
++
++	while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ)
++		;
++
++	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
++
++	if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
++		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
++			      ICR_ASSERT_ACK);
++		while (NCR5380_read(STATUS_REG) & SR_REQ)
++			;
++		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
++	}
++
++	tmp = ABORT;
++	msgptr = &tmp;
++	len = 1;
++	phase = PHASE_MSGOUT;
++	NCR5380_transfer_pio(host, &phase, &len, &msgptr);
++
++	/*
++	 * If we got here, and the command completed successfully,
++	 * we're about to go into bus free state.
++	 */
++
++	return len ? -1 : 0;
+ }
+ 
+ #if defined(REAL_DMA)
+-/* 
+- * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, 
++/*
++ * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance,
+  *      unsigned char *phase, int *count, unsigned char **data)
+  *
+  * Purpose : transfers data in given phase using either real
+  *	or pseudo DMA.
+  *
+- * Inputs : instance - instance of driver, *phase - pointer to 
+- *	what phase is expected, *count - pointer to number of 
++ * Inputs : instance - instance of driver, *phase - pointer to
++ *	what phase is expected, *count - pointer to number of
+  *	bytes to transfer, **data - pointer to data pointer.
+- * 
++ *
+  * Returns : -1 when different phase is entered without transferring
+  *	maximum number of bytes, 0 if all bytes or transfered or exit
+  *	is in same phase.
+  *
+- * 	Also, *phase, *count, *data are modified in place.
++ *	Also, *phase, *count, *data are modified in place.
+  *
+  */
+ 
+ 
+-static int NCR5380_transfer_dma( struct Scsi_Host *instance, 
+-				 unsigned char *phase, int *count,
+-				 unsigned char **data)
++static int NCR5380_transfer_dma(struct Scsi_Host *instance,
++				unsigned char *phase, int *count,
++				unsigned char **data)
+ {
+-    SETUP_HOSTDATA(instance);
+-    register int c = *count;
+-    register unsigned char p = *phase;
+-    register unsigned char *d = *data;
+-    unsigned char tmp;
+-    unsigned long flags;
++	SETUP_HOSTDATA(instance);
++	register int c = *count;
++	register unsigned char p = *phase;
++	register unsigned char *d = *data;
++	unsigned char tmp;
++	unsigned long flags;
+ 
+-    if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
+-        *phase = tmp;
+-        return -1;
+-    }
++	if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
++		*phase = tmp;
++		return -1;
++	}
+ 
+-    if (atari_read_overruns && (p & SR_IO)) {
+-	c -= atari_read_overruns;
+-    }
++	if (atari_read_overruns && (p & SR_IO))
++		c -= atari_read_overruns;
+ 
+-    DMA_PRINTK("scsi%d: initializing DMA for %s, %d bytes %s %p\n",
+-	       HOSTNO, (p & SR_IO) ? "reading" : "writing",
+-	       c, (p & SR_IO) ? "to" : "from", d);
++	DMA_PRINTK("scsi%d: initializing DMA for %s, %d bytes %s %p\n",
++		   HOSTNO, (p & SR_IO) ? "reading" : "writing",
++		   c, (p & SR_IO) ? "to" : "from", d);
+ 
+-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
++	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
+ 
+ #ifdef REAL_DMA
+-    NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
++	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
+ #endif /* def REAL_DMA  */
+ 
+-    if (IS_A_TT()) {
+-	/* On the Medusa, it is a must to initialize the DMA before
+-	 * starting the NCR. This is also the cleaner way for the TT.
+-	 */
+-	local_irq_save(flags);
+-	hostdata->dma_len = (p & SR_IO) ?
+-	    NCR5380_dma_read_setup(instance, d, c) : 
+-	    NCR5380_dma_write_setup(instance, d, c);
+-	local_irq_restore(flags);
+-    }
+-    
+-    if (p & SR_IO)
+-	NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
+-    else {
+-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
+-	NCR5380_write(START_DMA_SEND_REG, 0);
+-    }
+-
+-    if (!IS_A_TT()) {
+-	/* On the Falcon, the DMA setup must be done after the last */
+-	/* NCR access, else the DMA setup gets trashed!
+-	 */
+-	local_irq_save(flags);
+-	hostdata->dma_len = (p & SR_IO) ?
+-	    NCR5380_dma_read_setup(instance, d, c) : 
+-	    NCR5380_dma_write_setup(instance, d, c);
+-	local_irq_restore(flags);
+-    }
+-    return 0;
++	if (IS_A_TT()) {
++		/* On the Medusa, it is a must to initialize the DMA before
++		 * starting the NCR. This is also the cleaner way for the TT.
++		 */
++		local_irq_save(flags);
++		hostdata->dma_len = (p & SR_IO) ?
++			NCR5380_dma_read_setup(instance, d, c) :
++			NCR5380_dma_write_setup(instance, d, c);
++		local_irq_restore(flags);
++	}
++
++	if (p & SR_IO)
++		NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
++	else {
++		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
++		NCR5380_write(START_DMA_SEND_REG, 0);
++	}
++
++	if (!IS_A_TT()) {
++		/* On the Falcon, the DMA setup must be done after the last */
++		/* NCR access, else the DMA setup gets trashed!
++		 */
++		local_irq_save(flags);
++		hostdata->dma_len = (p & SR_IO) ?
++			NCR5380_dma_read_setup(instance, d, c) :
++			NCR5380_dma_write_setup(instance, d, c);
++		local_irq_restore(flags);
++	}
++	return 0;
+ }
+ #endif /* defined(REAL_DMA) */
+ 
+ /*
+  * Function : NCR5380_information_transfer (struct Scsi_Host *instance)
+  *
+- * Purpose : run through the various SCSI phases and do as the target 
+- * 	directs us to.  Operates on the currently connected command, 
++ * Purpose : run through the various SCSI phases and do as the target
++ *	directs us to.  Operates on the currently connected command,
+  *	instance->connected.
+  *
+  * Inputs : instance, instance for which we are doing commands
+  *
+- * Side effects : SCSI things happen, the disconnected queue will be 
++ * Side effects : SCSI things happen, the disconnected queue will be
+  *	modified if a command disconnects, *instance->connected will
+  *	change.
+  *
+- * XXX Note : we need to watch for bus free or a reset condition here 
+- * 	to recover from an unexpected bus free condition.
++ * XXX Note : we need to watch for bus free or a reset condition here
++ *	to recover from an unexpected bus free condition.
+  */
+- 
+-static void NCR5380_information_transfer (struct Scsi_Host *instance)
++
++static void NCR5380_information_transfer(struct Scsi_Host *instance)
+ {
+-    SETUP_HOSTDATA(instance);
+-    unsigned long flags;
+-    unsigned char msgout = NOP;
+-    int sink = 0;
+-    int len;
++	SETUP_HOSTDATA(instance);
++	unsigned long flags;
++	unsigned char msgout = NOP;
++	int sink = 0;
++	int len;
+ #if defined(REAL_DMA)
+-    int transfersize;
+-#endif
+-    unsigned char *data;
+-    unsigned char phase, tmp, extended_msg[10], old_phase=0xff;
+-    Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
+-
+-    while (1) {
+-	tmp = NCR5380_read(STATUS_REG);
+-	/* We only have a valid SCSI phase when REQ is asserted */
+-	if (tmp & SR_REQ) {
+-	    phase = (tmp & PHASE_MASK); 
+-	    if (phase != old_phase) {
+-		old_phase = phase;
+-		NCR_PRINT_PHASE(NDEBUG_INFORMATION);
+-	    }
+-	    
+-	    if (sink && (phase != PHASE_MSGOUT)) {
+-		NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
+-
+-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | 
+-		    ICR_ASSERT_ACK);
+-		while (NCR5380_read(STATUS_REG) & SR_REQ);
+-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
+-		    ICR_ASSERT_ATN);
+-		sink = 0;
+-		continue;
+-	    }
+-
+-	    switch (phase) {
+-	    case PHASE_DATAOUT:
+-#if (NDEBUG & NDEBUG_NO_DATAOUT)
+-		printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT "
+-		       "aborted\n", HOSTNO);
+-		sink = 1;
+-		do_abort(instance);
+-		cmd->result = DID_ERROR  << 16;
+-		cmd->done(cmd);
+-		return;
++	int transfersize;
+ #endif
+-	    case PHASE_DATAIN:
+-		/* 
+-		 * If there is no room left in the current buffer in the
+-		 * scatter-gather list, move onto the next one.
+-		 */
++	unsigned char *data;
++	unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
++	Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
++
++	while (1) {
++		tmp = NCR5380_read(STATUS_REG);
++		/* We only have a valid SCSI phase when REQ is asserted */
++		if (tmp & SR_REQ) {
++			phase = (tmp & PHASE_MASK);
++			if (phase != old_phase) {
++				old_phase = phase;
++				NCR_PRINT_PHASE(NDEBUG_INFORMATION);
++			}
+ 
+-		if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
+-		    ++cmd->SCp.buffer;
+-		    --cmd->SCp.buffers_residual;
+-		    cmd->SCp.this_residual = cmd->SCp.buffer->length;
+-		    cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+
+-				   cmd->SCp.buffer->offset;
+-		    /* ++roman: Try to merge some scatter-buffers if
+-		     * they are at contiguous physical addresses.
+-		     */
+-		    merge_contiguous_buffers( cmd );
+-		    INF_PRINTK("scsi%d: %d bytes and %d buffers left\n",
+-			       HOSTNO, cmd->SCp.this_residual,
+-			       cmd->SCp.buffers_residual);
+-		}
++			if (sink && (phase != PHASE_MSGOUT)) {
++				NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
+ 
+-		/*
+-		 * The preferred transfer method is going to be 
+-		 * PSEUDO-DMA for systems that are strictly PIO,
+-		 * since we can let the hardware do the handshaking.
+-		 *
+-		 * For this to work, we need to know the transfersize
+-		 * ahead of time, since the pseudo-DMA code will sit
+-		 * in an unconditional loop.
+-		 */
++				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
++					      ICR_ASSERT_ACK);
++				while (NCR5380_read(STATUS_REG) & SR_REQ)
++					;
++				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
++					      ICR_ASSERT_ATN);
++				sink = 0;
++				continue;
++			}
+ 
+-/* ++roman: I suggest, this should be
+- *   #if def(REAL_DMA)
+- * instead of leaving REAL_DMA out.
+- */
++			switch (phase) {
++			case PHASE_DATAOUT:
++#if (NDEBUG & NDEBUG_NO_DATAOUT)
++				printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT "
++				       "aborted\n", HOSTNO);
++				sink = 1;
++				do_abort(instance);
++				cmd->result = DID_ERROR << 16;
++				cmd->done(cmd);
++				return;
++#endif
++			case PHASE_DATAIN:
++				/*
++				 * If there is no room left in the current buffer in the
++				 * scatter-gather list, move onto the next one.
++				 */
++
++				if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
++					++cmd->SCp.buffer;
++					--cmd->SCp.buffers_residual;
++					cmd->SCp.this_residual = cmd->SCp.buffer->length;
++					cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
++						   cmd->SCp.buffer->offset;
++					/* ++roman: Try to merge some scatter-buffers if
++					 * they are at contiguous physical addresses.
++					 */
++					merge_contiguous_buffers(cmd);
++					INF_PRINTK("scsi%d: %d bytes and %d buffers left\n",
++						   HOSTNO, cmd->SCp.this_residual,
++						   cmd->SCp.buffers_residual);
++				}
++
++				/*
++				 * The preferred transfer method is going to be
++				 * PSEUDO-DMA for systems that are strictly PIO,
++				 * since we can let the hardware do the handshaking.
++				 *
++				 * For this to work, we need to know the transfersize
++				 * ahead of time, since the pseudo-DMA code will sit
++				 * in an unconditional loop.
++				 */
++
++				/* ++roman: I suggest, this should be
++				 *   #if def(REAL_DMA)
++				 * instead of leaving REAL_DMA out.
++				 */
+ 
+ #if defined(REAL_DMA)
+-		if (!cmd->device->borken &&
+-		    (transfersize = NCR5380_dma_xfer_len(instance,cmd,phase)) > 31) {
+-		    len = transfersize;
+-		    cmd->SCp.phase = phase;
+-		    if (NCR5380_transfer_dma(instance, &phase,
+-			&len, (unsigned char **) &cmd->SCp.ptr)) {
+-			/*
+-			 * If the watchdog timer fires, all future
+-			 * accesses to this device will use the
+-			 * polled-IO. */ 
+-			printk(KERN_NOTICE "scsi%d: switching target %d "
+-			       "lun %d to slow handshake\n", HOSTNO,
+-			       cmd->device->id, cmd->device->lun);
+-			cmd->device->borken = 1;
+-			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
+-			    ICR_ASSERT_ATN);
+-			sink = 1;
+-			do_abort(instance);
+-			cmd->result = DID_ERROR  << 16;
+-			cmd->done(cmd);
+-			/* XXX - need to source or sink data here, as appropriate */
+-		    } else {
++				if (!cmd->device->borken &&
++				    (transfersize = NCR5380_dma_xfer_len(instance,cmd,phase)) > 31) {
++					len = transfersize;
++					cmd->SCp.phase = phase;
++					if (NCR5380_transfer_dma(instance, &phase,
++					    &len, (unsigned char **)&cmd->SCp.ptr)) {
++						/*
++						 * If the watchdog timer fires, all future
++						 * accesses to this device will use the
++						 * polled-IO. */
++						printk(KERN_NOTICE "scsi%d: switching target %d "
++							   "lun %d to slow handshake\n", HOSTNO,
++							   cmd->device->id, cmd->device->lun);
++						cmd->device->borken = 1;
++						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
++							ICR_ASSERT_ATN);
++						sink = 1;
++						do_abort(instance);
++						cmd->result = DID_ERROR << 16;
++						cmd->done(cmd);
++						/* XXX - need to source or sink data here, as appropriate */
++					} else {
+ #ifdef REAL_DMA
+-			/* ++roman: When using real DMA,
+-			 * information_transfer() should return after
+-			 * starting DMA since it has nothing more to
+-			 * do.
+-			 */
+-			return;
+-#else			
+-			cmd->SCp.this_residual -= transfersize - len;
++						/* ++roman: When using real DMA,
++						 * information_transfer() should return after
++						 * starting DMA since it has nothing more to
++						 * do.
++						 */
++						return;
++#else
++						cmd->SCp.this_residual -= transfersize - len;
+ #endif
+-		    }
+-		} else
++					}
++				} else
+ #endif /* defined(REAL_DMA) */
+-		  NCR5380_transfer_pio(instance, &phase, 
+-		    (int *) &cmd->SCp.this_residual, (unsigned char **)
+-		    &cmd->SCp.ptr);
+-		break;
+-	    case PHASE_MSGIN:
+-		len = 1;
+-		data = &tmp;
+-		NCR5380_write(SELECT_ENABLE_REG, 0); 	/* disable reselects */
+-		NCR5380_transfer_pio(instance, &phase, &len, &data);
+-		cmd->SCp.Message = tmp;
+-
+-		switch (tmp) {
+-		/*
+-		 * Linking lets us reduce the time required to get the 
+-		 * next command out to the device, hopefully this will
+-		 * mean we don't waste another revolution due to the delays
+-		 * required by ARBITRATION and another SELECTION.
+-		 *
+-		 * In the current implementation proposal, low level drivers
+-		 * merely have to start the next command, pointed to by 
+-		 * next_link, done() is called as with unlinked commands.
+-		 */
++					NCR5380_transfer_pio(instance, &phase,
++							     (int *)&cmd->SCp.this_residual,
++							     (unsigned char **)&cmd->SCp.ptr);
++				break;
++			case PHASE_MSGIN:
++				len = 1;
++				data = &tmp;
++				NCR5380_write(SELECT_ENABLE_REG, 0);	/* disable reselects */
++				NCR5380_transfer_pio(instance, &phase, &len, &data);
++				cmd->SCp.Message = tmp;
++
++				switch (tmp) {
++				/*
++				 * Linking lets us reduce the time required to get the
++				 * next command out to the device, hopefully this will
++				 * mean we don't waste another revolution due to the delays
++				 * required by ARBITRATION and another SELECTION.
++				 *
++				 * In the current implementation proposal, low level drivers
++				 * merely have to start the next command, pointed to by
++				 * next_link, done() is called as with unlinked commands.
++				 */
+ #ifdef LINKED
+-		case LINKED_CMD_COMPLETE:
+-		case LINKED_FLG_CMD_COMPLETE:
+-		    /* Accept message by clearing ACK */
+-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-		    
+-		    LNK_PRINTK("scsi%d: target %d lun %d linked command "
+-			       "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun);
+-
+-		    /* Enable reselect interrupts */
+-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+-		    /*
+-		     * Sanity check : A linked command should only terminate
+-		     * with one of these messages if there are more linked
+-		     * commands available.
+-		     */
+-
+-		    if (!cmd->next_link) {
+-			 printk(KERN_NOTICE "scsi%d: target %d lun %d "
+-				"linked command complete, no next_link\n",
+-				HOSTNO, cmd->device->id, cmd->device->lun);
+-			    sink = 1;
+-			    do_abort (instance);
+-			    return;
+-		    }
+-
+-		    initialize_SCp(cmd->next_link);
+-		    /* The next command is still part of this process; copy it
+-		     * and don't free it! */
+-		    cmd->next_link->tag = cmd->tag;
+-		    cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); 
+-		    LNK_PRINTK("scsi%d: target %d lun %d linked request "
+-			       "done, calling scsi_done().\n",
+-			       HOSTNO, cmd->device->id, cmd->device->lun);
++				case LINKED_CMD_COMPLETE:
++				case LINKED_FLG_CMD_COMPLETE:
++					/* Accept message by clearing ACK */
++					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++
++					LNK_PRINTK("scsi%d: target %d lun %d linked command "
++						   "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun);
++
++					/* Enable reselect interrupts */
++					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
++					/*
++					 * Sanity check : A linked command should only terminate
++					 * with one of these messages if there are more linked
++					 * commands available.
++					 */
++
++					if (!cmd->next_link) {
++						 printk(KERN_NOTICE "scsi%d: target %d lun %d "
++							"linked command complete, no next_link\n",
++							HOSTNO, cmd->device->id, cmd->device->lun);
++						sink = 1;
++						do_abort(instance);
++						return;
++					}
++
++					initialize_SCp(cmd->next_link);
++					/* The next command is still part of this process; copy it
++					 * and don't free it! */
++					cmd->next_link->tag = cmd->tag;
++					cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
++					LNK_PRINTK("scsi%d: target %d lun %d linked request "
++						   "done, calling scsi_done().\n",
++						   HOSTNO, cmd->device->id, cmd->device->lun);
+ #ifdef NCR5380_STATS
+-		    collect_stats(hostdata, cmd);
++					collect_stats(hostdata, cmd);
+ #endif
+-		    cmd->scsi_done(cmd);
+-		    cmd = hostdata->connected;
+-		    break;
++					cmd->scsi_done(cmd);
++					cmd = hostdata->connected;
++					break;
+ #endif /* def LINKED */
+-		case ABORT:
+-		case COMMAND_COMPLETE: 
+-		    /* Accept message by clearing ACK */
+-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-		    /* ++guenther: possible race with Falcon locking */
+-		    falcon_dont_release++;
+-		    hostdata->connected = NULL;
+-		    QU_PRINTK("scsi%d: command for target %d, lun %d "
+-			      "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
++				case ABORT:
++				case COMMAND_COMPLETE:
++					/* Accept message by clearing ACK */
++					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++					/* ++guenther: possible race with Falcon locking */
++					falcon_dont_release++;
++					hostdata->connected = NULL;
++					QU_PRINTK("scsi%d: command for target %d, lun %d "
++						  "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
+ #ifdef SUPPORT_TAGS
+-		    cmd_free_tag( cmd );
+-		    if (status_byte(cmd->SCp.Status) == QUEUE_FULL) {
+-			/* Turn a QUEUE FULL status into BUSY, I think the
+-			 * mid level cannot handle QUEUE FULL :-( (The
+-			 * command is retried after BUSY). Also update our
+-			 * queue size to the number of currently issued
+-			 * commands now.
+-			 */
+-			/* ++Andreas: the mid level code knows about
+-			   QUEUE_FULL now. */
+-			TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+-			TAG_PRINTK("scsi%d: target %d lun %d returned "
+-				   "QUEUE_FULL after %d commands\n",
+-				   HOSTNO, cmd->device->id, cmd->device->lun,
+-				   ta->nr_allocated);
+-			if (ta->queue_size > ta->nr_allocated)
+-			    ta->nr_allocated = ta->queue_size;
+-		    }
++					cmd_free_tag(cmd);
++					if (status_byte(cmd->SCp.Status) == QUEUE_FULL) {
++						/* Turn a QUEUE FULL status into BUSY, I think the
++						 * mid level cannot handle QUEUE FULL :-( (The
++						 * command is retried after BUSY). Also update our
++						 * queue size to the number of currently issued
++						 * commands now.
++						 */
++						/* ++Andreas: the mid level code knows about
++						   QUEUE_FULL now. */
++						TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
++						TAG_PRINTK("scsi%d: target %d lun %d returned "
++							   "QUEUE_FULL after %d commands\n",
++							   HOSTNO, cmd->device->id, cmd->device->lun,
++							   ta->nr_allocated);
++						if (ta->queue_size > ta->nr_allocated)
++							ta->nr_allocated = ta->queue_size;
++					}
+ #else
+-		    hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
++					hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+ #endif
+-		    /* Enable reselect interrupts */
+-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
++					/* Enable reselect interrupts */
++					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+ 
+-		    /* 
+-		     * I'm not sure what the correct thing to do here is : 
+-		     * 
+-		     * If the command that just executed is NOT a request 
+-		     * sense, the obvious thing to do is to set the result
+-		     * code to the values of the stored parameters.
+-		     * 
+-		     * If it was a REQUEST SENSE command, we need some way to
+-		     * differentiate between the failure code of the original
+-		     * and the failure code of the REQUEST sense - the obvious
+-		     * case is success, where we fall through and leave the
+-		     * result code unchanged.
+-		     * 
+-		     * The non-obvious place is where the REQUEST SENSE failed
+-		     */
+-
+-		    if (cmd->cmnd[0] != REQUEST_SENSE) 
+-			cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); 
+-		    else if (status_byte(cmd->SCp.Status) != GOOD)
+-			cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
+-		    
+-#ifdef AUTOSENSE
+-		    if ((cmd->cmnd[0] != REQUEST_SENSE) && 
+-			(status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
+-			ASEN_PRINTK("scsi%d: performing request sense\n",
+-				    HOSTNO);
+-			cmd->cmnd[0] = REQUEST_SENSE;
+-			cmd->cmnd[1] &= 0xe0;
+-			cmd->cmnd[2] = 0;
+-			cmd->cmnd[3] = 0;
+-			cmd->cmnd[4] = sizeof(cmd->sense_buffer);
+-			cmd->cmnd[5] = 0;
+-			cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
+-
+-			cmd->use_sg = 0;
+-			/* this is initialized from initialize_SCp 
+-			cmd->SCp.buffer = NULL;
+-			cmd->SCp.buffers_residual = 0;
+-			*/
+-			cmd->request_buffer = (char *) cmd->sense_buffer;
+-			cmd->request_bufflen = sizeof(cmd->sense_buffer);
++					/*
++					 * I'm not sure what the correct thing to do here is :
++					 *
++					 * If the command that just executed is NOT a request
++					 * sense, the obvious thing to do is to set the result
++					 * code to the values of the stored parameters.
++					 *
++					 * If it was a REQUEST SENSE command, we need some way to
++					 * differentiate between the failure code of the original
++					 * and the failure code of the REQUEST sense - the obvious
++					 * case is success, where we fall through and leave the
++					 * result code unchanged.
++					 *
++					 * The non-obvious place is where the REQUEST SENSE failed
++					 */
++
++					if (cmd->cmnd[0] != REQUEST_SENSE)
++						cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
++					else if (status_byte(cmd->SCp.Status) != GOOD)
++						cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
+ 
+-			local_irq_save(flags);
+-			LIST(cmd,hostdata->issue_queue);
+-			NEXT(cmd) = hostdata->issue_queue;
+-		        hostdata->issue_queue = (Scsi_Cmnd *) cmd;
+-		        local_irq_restore(flags);
+-			QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
+-				  "issue queue\n", H_NO(cmd));
+-		   } else
++#ifdef AUTOSENSE
++					if ((cmd->cmnd[0] != REQUEST_SENSE) &&
++					    (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
++						ASEN_PRINTK("scsi%d: performing request sense\n", HOSTNO);
++						cmd->cmnd[0] = REQUEST_SENSE;
++						cmd->cmnd[1] &= 0xe0;
++						cmd->cmnd[2] = 0;
++						cmd->cmnd[3] = 0;
++						cmd->cmnd[4] = sizeof(cmd->sense_buffer);
++						cmd->cmnd[5] = 0;
++						cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
++
++						cmd->use_sg = 0;
++						/* this is initialized from initialize_SCp
++						cmd->SCp.buffer = NULL;
++						cmd->SCp.buffers_residual = 0;
++						*/
++						cmd->request_buffer = (char *) cmd->sense_buffer;
++						cmd->request_bufflen = sizeof(cmd->sense_buffer);
++
++						local_irq_save(flags);
++						LIST(cmd,hostdata->issue_queue);
++						NEXT(cmd) = hostdata->issue_queue;
++						hostdata->issue_queue = (Scsi_Cmnd *) cmd;
++						local_irq_restore(flags);
++						QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
++							  "issue queue\n", H_NO(cmd));
++					} else
+ #endif /* def AUTOSENSE */
+-		   {
++					{
+ #ifdef NCR5380_STATS
+-		       collect_stats(hostdata, cmd);
++						collect_stats(hostdata, cmd);
+ #endif
+-		       cmd->scsi_done(cmd);
+-		    }
++						cmd->scsi_done(cmd);
++					}
+ 
+-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+-		    /* 
+-		     * Restore phase bits to 0 so an interrupted selection, 
+-		     * arbitration can resume.
+-		     */
+-		    NCR5380_write(TARGET_COMMAND_REG, 0);
+-		    
+-		    while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
+-			barrier();
+-
+-		    falcon_dont_release--;
+-		    /* ++roman: For Falcon SCSI, release the lock on the
+-		     * ST-DMA here if no other commands are waiting on the
+-		     * disconnected queue.
+-		     */
+-		    falcon_release_lock_if_possible( hostdata );
+-		    return;
+-		case MESSAGE_REJECT:
+-		    /* Accept message by clearing ACK */
+-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-		    /* Enable reselect interrupts */
+-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+-		    switch (hostdata->last_message) {
+-		    case HEAD_OF_QUEUE_TAG:
+-		    case ORDERED_QUEUE_TAG:
+-		    case SIMPLE_QUEUE_TAG:
+-			/* The target obviously doesn't support tagged
+-			 * queuing, even though it announced this ability in
+-			 * its INQUIRY data ?!? (maybe only this LUN?) Ok,
+-			 * clear 'tagged_supported' and lock the LUN, since
+-			 * the command is treated as untagged further on.
+-			 */
+-			cmd->device->tagged_supported = 0;
+-			hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+-			cmd->tag = TAG_NONE;
+-			TAG_PRINTK("scsi%d: target %d lun %d rejected "
+-				   "QUEUE_TAG message; tagged queuing "
+-				   "disabled\n",
+-				   HOSTNO, cmd->device->id, cmd->device->lun);
+-			break;
+-		    }
+-		    break;
+-		case DISCONNECT:
+-		    /* Accept message by clearing ACK */
+-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-		    local_irq_save(flags);
+-		    cmd->device->disconnect = 1;
+-		    LIST(cmd,hostdata->disconnected_queue);
+-		    NEXT(cmd) = hostdata->disconnected_queue;
+-		    hostdata->connected = NULL;
+-		    hostdata->disconnected_queue = cmd;
+-		    local_irq_restore(flags);
+-		    QU_PRINTK("scsi%d: command for target %d lun %d was "
+-			      "moved from connected to the "
+-			      "disconnected_queue\n", HOSTNO, 
+-			      cmd->device->id, cmd->device->lun);
+-		    /* 
+-		     * Restore phase bits to 0 so an interrupted selection, 
+-		     * arbitration can resume.
+-		     */
+-		    NCR5380_write(TARGET_COMMAND_REG, 0);
+-
+-		    /* Enable reselect interrupts */
+-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+-		    /* Wait for bus free to avoid nasty timeouts */
+-		    while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
+-		    	barrier();
+-		    return;
+-		/* 
+-		 * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
+-		 * operation, in violation of the SCSI spec so we can safely 
+-		 * ignore SAVE/RESTORE pointers calls.
+-		 *
+-		 * Unfortunately, some disks violate the SCSI spec and 
+-		 * don't issue the required SAVE_POINTERS message before
+-		 * disconnecting, and we have to break spec to remain 
+-		 * compatible.
+-		 */
+-		case SAVE_POINTERS:
+-		case RESTORE_POINTERS:
+-		    /* Accept message by clearing ACK */
+-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-		    /* Enable reselect interrupts */
+-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+-		    break;
+-		case EXTENDED_MESSAGE:
+-/* 
+- * Extended messages are sent in the following format :
+- * Byte 	
+- * 0		EXTENDED_MESSAGE == 1
+- * 1		length (includes one byte for code, doesn't 
+- *		include first two bytes)
+- * 2 		code
+- * 3..length+1	arguments
+- *
+- * Start the extended message buffer with the EXTENDED_MESSAGE
+- * byte, since spi_print_msg() wants the whole thing.  
+- */
+-		    extended_msg[0] = EXTENDED_MESSAGE;
+-		    /* Accept first byte by clearing ACK */
+-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-
+-		    EXT_PRINTK("scsi%d: receiving extended message\n", HOSTNO);
+-
+-		    len = 2;
+-		    data = extended_msg + 1;
+-		    phase = PHASE_MSGIN;
+-		    NCR5380_transfer_pio(instance, &phase, &len, &data);
+-		    EXT_PRINTK("scsi%d: length=%d, code=0x%02x\n", HOSTNO,
+-			       (int)extended_msg[1], (int)extended_msg[2]);
+-
+-		    if (!len && extended_msg[1] <= 
+-			(sizeof (extended_msg) - 1)) {
+-			/* Accept third byte by clearing ACK */
+-			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-			len = extended_msg[1] - 1;
+-			data = extended_msg + 3;
+-			phase = PHASE_MSGIN;
+-
+-			NCR5380_transfer_pio(instance, &phase, &len, &data);
+-			EXT_PRINTK("scsi%d: message received, residual %d\n",
+-				   HOSTNO, len);
+-
+-			switch (extended_msg[2]) {
+-			case EXTENDED_SDTR:
+-			case EXTENDED_WDTR:
+-			case EXTENDED_MODIFY_DATA_POINTER:
+-			case EXTENDED_EXTENDED_IDENTIFY:
+-			    tmp = 0;
+-			}
+-		    } else if (len) {
+-			printk(KERN_NOTICE "scsi%d: error receiving "
+-			       "extended message\n", HOSTNO);
+-			tmp = 0;
+-		    } else {
+-			printk(KERN_NOTICE "scsi%d: extended message "
+-			       "code %02x length %d is too long\n",
+-			       HOSTNO, extended_msg[2], extended_msg[1]);
+-			tmp = 0;
+-		    }
+-		/* Fall through to reject message */
+-
+-		/* 
+-  		 * If we get something weird that we aren't expecting, 
+- 		 * reject it.
+-		 */
+-		default:
+-		    if (!tmp) {
+-			printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
+-			spi_print_msg(extended_msg);
+-			printk("\n");
+-		    } else if (tmp != EXTENDED_MESSAGE)
+-			printk(KERN_DEBUG "scsi%d: rejecting unknown "
+-			       "message %02x from target %d, lun %d\n",
+-			       HOSTNO, tmp, cmd->device->id, cmd->device->lun);
+-		    else
+-			printk(KERN_DEBUG "scsi%d: rejecting unknown "
+-			       "extended message "
+-			       "code %02x, length %d from target %d, lun %d\n",
+-			       HOSTNO, extended_msg[1], extended_msg[0],
+-			       cmd->device->id, cmd->device->lun);
+-   
+-
+-		    msgout = MESSAGE_REJECT;
+-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
+-			ICR_ASSERT_ATN);
+-		    break;
+-		} /* switch (tmp) */
+-		break;
+-	    case PHASE_MSGOUT:
+-		len = 1;
+-		data = &msgout;
+-		hostdata->last_message = msgout;
+-		NCR5380_transfer_pio(instance, &phase, &len, &data);
+-		if (msgout == ABORT) {
++					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
++					/*
++					 * Restore phase bits to 0 so an interrupted selection,
++					 * arbitration can resume.
++					 */
++					NCR5380_write(TARGET_COMMAND_REG, 0);
++
++					while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
++						barrier();
++
++					falcon_dont_release--;
++					/* ++roman: For Falcon SCSI, release the lock on the
++					 * ST-DMA here if no other commands are waiting on the
++					 * disconnected queue.
++					 */
++					falcon_release_lock_if_possible(hostdata);
++					return;
++				case MESSAGE_REJECT:
++					/* Accept message by clearing ACK */
++					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++					/* Enable reselect interrupts */
++					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
++					switch (hostdata->last_message) {
++					case HEAD_OF_QUEUE_TAG:
++					case ORDERED_QUEUE_TAG:
++					case SIMPLE_QUEUE_TAG:
++						/* The target obviously doesn't support tagged
++						 * queuing, even though it announced this ability in
++						 * its INQUIRY data ?!? (maybe only this LUN?) Ok,
++						 * clear 'tagged_supported' and lock the LUN, since
++						 * the command is treated as untagged further on.
++						 */
++						cmd->device->tagged_supported = 0;
++						hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
++						cmd->tag = TAG_NONE;
++						TAG_PRINTK("scsi%d: target %d lun %d rejected "
++							   "QUEUE_TAG message; tagged queuing "
++							   "disabled\n",
++							   HOSTNO, cmd->device->id, cmd->device->lun);
++						break;
++					}
++					break;
++				case DISCONNECT:
++					/* Accept message by clearing ACK */
++					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++					local_irq_save(flags);
++					cmd->device->disconnect = 1;
++					LIST(cmd,hostdata->disconnected_queue);
++					NEXT(cmd) = hostdata->disconnected_queue;
++					hostdata->connected = NULL;
++					hostdata->disconnected_queue = cmd;
++					local_irq_restore(flags);
++					QU_PRINTK("scsi%d: command for target %d lun %d was "
++						  "moved from connected to the "
++						  "disconnected_queue\n", HOSTNO,
++						  cmd->device->id, cmd->device->lun);
++					/*
++					 * Restore phase bits to 0 so an interrupted selection,
++					 * arbitration can resume.
++					 */
++					NCR5380_write(TARGET_COMMAND_REG, 0);
++
++					/* Enable reselect interrupts */
++					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
++					/* Wait for bus free to avoid nasty timeouts */
++					while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
++						barrier();
++					return;
++					/*
++					 * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
++					 * operation, in violation of the SCSI spec so we can safely
++					 * ignore SAVE/RESTORE pointers calls.
++					 *
++					 * Unfortunately, some disks violate the SCSI spec and
++					 * don't issue the required SAVE_POINTERS message before
++					 * disconnecting, and we have to break spec to remain
++					 * compatible.
++					 */
++				case SAVE_POINTERS:
++				case RESTORE_POINTERS:
++					/* Accept message by clearing ACK */
++					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++					/* Enable reselect interrupts */
++					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
++					break;
++				case EXTENDED_MESSAGE:
++					/*
++					 * Extended messages are sent in the following format :
++					 * Byte
++					 * 0		EXTENDED_MESSAGE == 1
++					 * 1		length (includes one byte for code, doesn't
++					 *		include first two bytes)
++					 * 2		code
++					 * 3..length+1	arguments
++					 *
++					 * Start the extended message buffer with the EXTENDED_MESSAGE
++					 * byte, since spi_print_msg() wants the whole thing.
++					 */
++					extended_msg[0] = EXTENDED_MESSAGE;
++					/* Accept first byte by clearing ACK */
++					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++
++					EXT_PRINTK("scsi%d: receiving extended message\n", HOSTNO);
++
++					len = 2;
++					data = extended_msg + 1;
++					phase = PHASE_MSGIN;
++					NCR5380_transfer_pio(instance, &phase, &len, &data);
++					EXT_PRINTK("scsi%d: length=%d, code=0x%02x\n", HOSTNO,
++						   (int)extended_msg[1], (int)extended_msg[2]);
++
++					if (!len && extended_msg[1] <=
++					    (sizeof(extended_msg) - 1)) {
++						/* Accept third byte by clearing ACK */
++						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++						len = extended_msg[1] - 1;
++						data = extended_msg + 3;
++						phase = PHASE_MSGIN;
++
++						NCR5380_transfer_pio(instance, &phase, &len, &data);
++						EXT_PRINTK("scsi%d: message received, residual %d\n",
++							   HOSTNO, len);
++
++						switch (extended_msg[2]) {
++						case EXTENDED_SDTR:
++						case EXTENDED_WDTR:
++						case EXTENDED_MODIFY_DATA_POINTER:
++						case EXTENDED_EXTENDED_IDENTIFY:
++							tmp = 0;
++						}
++					} else if (len) {
++						printk(KERN_NOTICE "scsi%d: error receiving "
++						       "extended message\n", HOSTNO);
++						tmp = 0;
++					} else {
++						printk(KERN_NOTICE "scsi%d: extended message "
++							   "code %02x length %d is too long\n",
++							   HOSTNO, extended_msg[2], extended_msg[1]);
++						tmp = 0;
++					}
++					/* Fall through to reject message */
++
++					/*
++					 * If we get something weird that we aren't expecting,
++					 * reject it.
++					 */
++				default:
++					if (!tmp) {
++						printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
++						spi_print_msg(extended_msg);
++						printk("\n");
++					} else if (tmp != EXTENDED_MESSAGE)
++						printk(KERN_DEBUG "scsi%d: rejecting unknown "
++						       "message %02x from target %d, lun %d\n",
++						       HOSTNO, tmp, cmd->device->id, cmd->device->lun);
++					else
++						printk(KERN_DEBUG "scsi%d: rejecting unknown "
++						       "extended message "
++						       "code %02x, length %d from target %d, lun %d\n",
++						       HOSTNO, extended_msg[1], extended_msg[0],
++						       cmd->device->id, cmd->device->lun);
++
++
++					msgout = MESSAGE_REJECT;
++					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
++					break;
++				} /* switch (tmp) */
++				break;
++			case PHASE_MSGOUT:
++				len = 1;
++				data = &msgout;
++				hostdata->last_message = msgout;
++				NCR5380_transfer_pio(instance, &phase, &len, &data);
++				if (msgout == ABORT) {
+ #ifdef SUPPORT_TAGS
+-		    cmd_free_tag( cmd );
++					cmd_free_tag(cmd);
+ #else
+-		    hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
++					hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+ #endif
+-		    hostdata->connected = NULL;
+-		    cmd->result = DID_ERROR << 16;
++					hostdata->connected = NULL;
++					cmd->result = DID_ERROR << 16;
+ #ifdef NCR5380_STATS
+-		    collect_stats(hostdata, cmd);
++					collect_stats(hostdata, cmd);
+ #endif
+-		    cmd->scsi_done(cmd);
+-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+-		    falcon_release_lock_if_possible( hostdata );
+-		    return;
+-		}
+-		msgout = NOP;
+-		break;
+-	    case PHASE_CMDOUT:
+-		len = cmd->cmd_len;
+-		data = cmd->cmnd;
+-		/* 
+-		 * XXX for performance reasons, on machines with a 
+-		 * PSEUDO-DMA architecture we should probably 
+-		 * use the dma transfer function.  
+-		 */
+-		NCR5380_transfer_pio(instance, &phase, &len, 
+-		    &data);
+-		break;
+-	    case PHASE_STATIN:
+-		len = 1;
+-		data = &tmp;
+-		NCR5380_transfer_pio(instance, &phase, &len, &data);
+-		cmd->SCp.Status = tmp;
+-		break;
+-	    default:
+-		printk("scsi%d: unknown phase\n", HOSTNO);
+-		NCR_PRINT(NDEBUG_ANY);
+-	    } /* switch(phase) */
+-	} /* if (tmp * SR_REQ) */ 
+-    } /* while (1) */
++					cmd->scsi_done(cmd);
++					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
++					falcon_release_lock_if_possible(hostdata);
++					return;
++				}
++				msgout = NOP;
++				break;
++			case PHASE_CMDOUT:
++				len = cmd->cmd_len;
++				data = cmd->cmnd;
++				/*
++				 * XXX for performance reasons, on machines with a
++				 * PSEUDO-DMA architecture we should probably
++				 * use the dma transfer function.
++				 */
++				NCR5380_transfer_pio(instance, &phase, &len, &data);
++				break;
++			case PHASE_STATIN:
++				len = 1;
++				data = &tmp;
++				NCR5380_transfer_pio(instance, &phase, &len, &data);
++				cmd->SCp.Status = tmp;
++				break;
++			default:
++				printk("scsi%d: unknown phase\n", HOSTNO);
++				NCR_PRINT(NDEBUG_ANY);
++			} /* switch(phase) */
++		} /* if (tmp * SR_REQ) */
++	} /* while (1) */
+ }
+ 
+ /*
+  * Function : void NCR5380_reselect (struct Scsi_Host *instance)
+  *
+- * Purpose : does reselection, initializing the instance->connected 
+- *	field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q 
++ * Purpose : does reselection, initializing the instance->connected
++ *	field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q
+  *	nexus has been reestablished,
+- *	
++ *
+  * Inputs : instance - this instance of the NCR5380.
+  *
+  */
+ 
+ 
+-static void NCR5380_reselect (struct Scsi_Host *instance)
++static void NCR5380_reselect(struct Scsi_Host *instance)
+ {
+-    SETUP_HOSTDATA(instance);
+-    unsigned char target_mask;
+-    unsigned char lun, phase;
+-    int len;
++	SETUP_HOSTDATA(instance);
++	unsigned char target_mask;
++	unsigned char lun, phase;
++	int len;
+ #ifdef SUPPORT_TAGS
+-    unsigned char tag;
++	unsigned char tag;
+ #endif
+-    unsigned char msg[3];
+-    unsigned char *data;
+-    Scsi_Cmnd *tmp = NULL, *prev;
+-/*    unsigned long flags; */
+-
+-    /*
+-     * Disable arbitration, etc. since the host adapter obviously
+-     * lost, and tell an interrupted NCR5380_select() to restart.
+-     */
+-
+-    NCR5380_write(MODE_REG, MR_BASE);
+-    hostdata->restart_select = 1;
+-
+-    target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
+-
+-    RSL_PRINTK("scsi%d: reselect\n", HOSTNO);
+-
+-    /* 
+-     * At this point, we have detected that our SCSI ID is on the bus,
+-     * SEL is true and BSY was false for at least one bus settle delay
+-     * (400 ns).
+-     *
+-     * We must assert BSY ourselves, until the target drops the SEL
+-     * signal.
+-     */
+-
+-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
+-    
+-    while (NCR5380_read(STATUS_REG) & SR_SEL);
+-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-
+-    /*
+-     * Wait for target to go into MSGIN.
+-     */
+-
+-    while (!(NCR5380_read(STATUS_REG) & SR_REQ));
+-
+-    len = 1;
+-    data = msg;
+-    phase = PHASE_MSGIN;
+-    NCR5380_transfer_pio(instance, &phase, &len, &data);
+-
+-    if (!(msg[0] & 0x80)) {
+-	printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
+-	spi_print_msg(msg);
+-	do_abort(instance);
+-	return;
+-    }
+-    lun = (msg[0] & 0x07);
++	unsigned char msg[3];
++	unsigned char *data;
++	Scsi_Cmnd *tmp = NULL, *prev;
++/*	unsigned long flags; */
++
++	/*
++	 * Disable arbitration, etc. since the host adapter obviously
++	 * lost, and tell an interrupted NCR5380_select() to restart.
++	 */
++
++	NCR5380_write(MODE_REG, MR_BASE);
++	hostdata->restart_select = 1;
++
++	target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
++
++	RSL_PRINTK("scsi%d: reselect\n", HOSTNO);
++
++	/*
++	 * At this point, we have detected that our SCSI ID is on the bus,
++	 * SEL is true and BSY was false for at least one bus settle delay
++	 * (400 ns).
++	 *
++	 * We must assert BSY ourselves, until the target drops the SEL
++	 * signal.
++	 */
++
++	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
++
++	while (NCR5380_read(STATUS_REG) & SR_SEL)
++		;
++	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++
++	/*
++	 * Wait for target to go into MSGIN.
++	 */
++
++	while (!(NCR5380_read(STATUS_REG) & SR_REQ))
++		;
++
++	len = 1;
++	data = msg;
++	phase = PHASE_MSGIN;
++	NCR5380_transfer_pio(instance, &phase, &len, &data);
++
++	if (!(msg[0] & 0x80)) {
++		printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
++		spi_print_msg(msg);
++		do_abort(instance);
++		return;
++	}
++	lun = (msg[0] & 0x07);
+ 
+ #ifdef SUPPORT_TAGS
+-    /* If the phase is still MSGIN, the target wants to send some more
+-     * messages. In case it supports tagged queuing, this is probably a
+-     * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
+-     */
+-    tag = TAG_NONE;
+-    if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
+-	/* Accept previous IDENTIFY message by clearing ACK */
+-	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
+-	len = 2;
+-	data = msg+1;
+-	if (!NCR5380_transfer_pio(instance, &phase, &len, &data) &&
+-	    msg[1] == SIMPLE_QUEUE_TAG)
+-	    tag = msg[2];
+-	TAG_PRINTK("scsi%d: target mask %02x, lun %d sent tag %d at "
+-		   "reselection\n", HOSTNO, target_mask, lun, tag);
+-    }
+-#endif
+-    
+-    /* 
+-     * Find the command corresponding to the I_T_L or I_T_L_Q  nexus we 
+-     * just reestablished, and remove it from the disconnected queue.
+-     */
+-
+-    for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; 
+-	 tmp; prev = tmp, tmp = NEXT(tmp) ) {
+-	if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
++	/* If the phase is still MSGIN, the target wants to send some more
++	 * messages. In case it supports tagged queuing, this is probably a
++	 * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
++	 */
++	tag = TAG_NONE;
++	if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
++		/* Accept previous IDENTIFY message by clearing ACK */
++		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++		len = 2;
++		data = msg + 1;
++		if (!NCR5380_transfer_pio(instance, &phase, &len, &data) &&
++		    msg[1] == SIMPLE_QUEUE_TAG)
++			tag = msg[2];
++		TAG_PRINTK("scsi%d: target mask %02x, lun %d sent tag %d at "
++			   "reselection\n", HOSTNO, target_mask, lun, tag);
++	}
++#endif
++
++	/*
++	 * Find the command corresponding to the I_T_L or I_T_L_Q  nexus we
++	 * just reestablished, and remove it from the disconnected queue.
++	 */
++
++	for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL;
++	     tmp; prev = tmp, tmp = NEXT(tmp)) {
++		if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
+ #ifdef SUPPORT_TAGS
+-	    && (tag == tmp->tag) 
++		    && (tag == tmp->tag)
+ #endif
+-	    ) {
+-	    /* ++guenther: prevent race with falcon_release_lock */
+-	    falcon_dont_release++;
+-	    if (prev) {
+-		REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
+-		NEXT(prev) = NEXT(tmp);
+-	    } else {
+-		REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp));
+-		hostdata->disconnected_queue = NEXT(tmp);
+-	    }
+-	    NEXT(tmp) = NULL;
+-	    break;
+-	}
+-    }
+-    
+-    if (!tmp) {
+-	printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d "
++		    ) {
++			/* ++guenther: prevent race with falcon_release_lock */
++			falcon_dont_release++;
++			if (prev) {
++				REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
++				NEXT(prev) = NEXT(tmp);
++			} else {
++				REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp));
++				hostdata->disconnected_queue = NEXT(tmp);
++			}
++			NEXT(tmp) = NULL;
++			break;
++		}
++	}
++
++	if (!tmp) {
++		printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d "
+ #ifdef SUPPORT_TAGS
+-		"tag %d "
++		       "tag %d "
+ #endif
+-		"not in disconnected_queue.\n",
+-		HOSTNO, target_mask, lun
++		       "not in disconnected_queue.\n",
++		       HOSTNO, target_mask, lun
+ #ifdef SUPPORT_TAGS
+-		, tag
++		       , tag
+ #endif
+-		);
+-	/* 
+-	 * Since we have an established nexus that we can't do anything
+-	 * with, we must abort it.  
+-	 */
+-	do_abort(instance);
+-	return;
+-    }
+-
+-    /* Accept message by clearing ACK */
+-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+-
+-    hostdata->connected = tmp;
+-    RSL_PRINTK("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
+-	       HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
+-    falcon_dont_release--;
++			);
++		/*
++		 * Since we have an established nexus that we can't do anything
++		 * with, we must abort it.
++		 */
++		do_abort(instance);
++		return;
++	}
++
++	/* Accept message by clearing ACK */
++	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++
++	hostdata->connected = tmp;
++	RSL_PRINTK("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
++		   HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
++	falcon_dont_release--;
+ }
+ 
+ 
+@@ -2666,362 +2676,361 @@ static void NCR5380_reselect (struct Scs
+  *
+  * Purpose : abort a command
+  *
+- * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the 
+- * 	host byte of the result field to, if zero DID_ABORTED is 
++ * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the
++ *	host byte of the result field to, if zero DID_ABORTED is
+  *	used.
+  *
+  * Returns : 0 - success, -1 on failure.
+  *
+- * XXX - there is no way to abort the command that is currently 
+- * 	 connected, you have to wait for it to complete.  If this is 
++ * XXX - there is no way to abort the command that is currently
++ *	 connected, you have to wait for it to complete.  If this is
+  *	 a problem, we could implement longjmp() / setjmp(), setjmp()
+- * 	 called where the loop started in NCR5380_main().
++ *	 called where the loop started in NCR5380_main().
+  */
+ 
+ static
+-int NCR5380_abort (Scsi_Cmnd *cmd)
++int NCR5380_abort(Scsi_Cmnd *cmd)
+ {
+-    struct Scsi_Host *instance = cmd->device->host;
+-    SETUP_HOSTDATA(instance);
+-    Scsi_Cmnd *tmp, **prev;
+-    unsigned long flags;
+-
+-    printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO);
+-    scsi_print_command(cmd);
+-
+-    NCR5380_print_status (instance);
+-
+-    local_irq_save(flags);
+-    
+-    if (!IS_A_TT() && !falcon_got_lock)
+-	printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
+-	       HOSTNO);
+-
+-    ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
+-		NCR5380_read(BUS_AND_STATUS_REG),
+-		NCR5380_read(STATUS_REG));
++	struct Scsi_Host *instance = cmd->device->host;
++	SETUP_HOSTDATA(instance);
++	Scsi_Cmnd *tmp, **prev;
++	unsigned long flags;
++
++	printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO);
++	scsi_print_command(cmd);
++
++	NCR5380_print_status(instance);
++
++	local_irq_save(flags);
++
++	if (!IS_A_TT() && !falcon_got_lock)
++		printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
++		       HOSTNO);
++
++	ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
++		    NCR5380_read(BUS_AND_STATUS_REG),
++		    NCR5380_read(STATUS_REG));
+ 
+ #if 1
+-/* 
+- * Case 1 : If the command is the currently executing command, 
+- * we'll set the aborted flag and return control so that 
+- * information transfer routine can exit cleanly.
+- */
++	/*
++	 * Case 1 : If the command is the currently executing command,
++	 * we'll set the aborted flag and return control so that
++	 * information transfer routine can exit cleanly.
++	 */
+ 
+-    if (hostdata->connected == cmd) {
++	if (hostdata->connected == cmd) {
+ 
+-	ABRT_PRINTK("scsi%d: aborting connected command\n", HOSTNO);
+-/*
+- * We should perform BSY checking, and make sure we haven't slipped
+- * into BUS FREE.
+- */
++		ABRT_PRINTK("scsi%d: aborting connected command\n", HOSTNO);
++		/*
++		 * We should perform BSY checking, and make sure we haven't slipped
++		 * into BUS FREE.
++		 */
+ 
+-/*	NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */
+-/* 
+- * Since we can't change phases until we've completed the current 
+- * handshake, we have to source or sink a byte of data if the current
+- * phase is not MSGOUT.
+- */
++		/*	NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */
++		/*
++		 * Since we can't change phases until we've completed the current
++		 * handshake, we have to source or sink a byte of data if the current
++		 * phase is not MSGOUT.
++		 */
+ 
+-/* 
+- * Return control to the executing NCR drive so we can clear the
+- * aborted flag and get back into our main loop.
+- */ 
++		/*
++		 * Return control to the executing NCR drive so we can clear the
++		 * aborted flag and get back into our main loop.
++		 */
+ 
+-	if (do_abort(instance) == 0) {
+-	  hostdata->aborted = 1;
+-	  hostdata->connected = NULL;
+-	  cmd->result = DID_ABORT << 16;
++		if (do_abort(instance) == 0) {
++			hostdata->aborted = 1;
++			hostdata->connected = NULL;
++			cmd->result = DID_ABORT << 16;
+ #ifdef SUPPORT_TAGS
+-	  cmd_free_tag( cmd );
++			cmd_free_tag(cmd);
+ #else
+-	  hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
++			hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
++#endif
++			local_irq_restore(flags);
++			cmd->scsi_done(cmd);
++			falcon_release_lock_if_possible(hostdata);
++			return SCSI_ABORT_SUCCESS;
++		} else {
++/*			local_irq_restore(flags); */
++			printk("scsi%d: abort of connected command failed!\n", HOSTNO);
++			return SCSI_ABORT_ERROR;
++		}
++	}
+ #endif
+-	  local_irq_restore(flags);
+-	  cmd->scsi_done(cmd);
+-	  falcon_release_lock_if_possible( hostdata );
+-	  return SCSI_ABORT_SUCCESS;
+-	} else {
+-/*	  local_irq_restore(flags); */
+-	  printk("scsi%d: abort of connected command failed!\n", HOSTNO);
+-	  return SCSI_ABORT_ERROR;
+-	} 
+-   }
+-#endif
+-
+-/* 
+- * Case 2 : If the command hasn't been issued yet, we simply remove it 
+- * 	    from the issue queue.
+- */
+-    for (prev = (Scsi_Cmnd **) &(hostdata->issue_queue), 
+-	tmp = (Scsi_Cmnd *) hostdata->issue_queue;
+-	tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) )
+-	if (cmd == tmp) {
+-	    REMOVE(5, *prev, tmp, NEXT(tmp));
+-	    (*prev) = NEXT(tmp);
+-	    NEXT(tmp) = NULL;
+-	    tmp->result = DID_ABORT << 16;
+-	    local_irq_restore(flags);
+-	    ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
+-			HOSTNO);
+-	    /* Tagged queuing note: no tag to free here, hasn't been assigned
+-	     * yet... */
+-	    tmp->scsi_done(tmp);
+-	    falcon_release_lock_if_possible( hostdata );
+-	    return SCSI_ABORT_SUCCESS;
+-	}
+-
+-/* 
+- * Case 3 : If any commands are connected, we're going to fail the abort
+- *	    and let the high level SCSI driver retry at a later time or 
+- *	    issue a reset.
+- *
+- *	    Timeouts, and therefore aborted commands, will be highly unlikely
+- *          and handling them cleanly in this situation would make the common
+- *	    case of noresets less efficient, and would pollute our code.  So,
+- *	    we fail.
+- */
+ 
+-    if (hostdata->connected) {
+-	local_irq_restore(flags);
+-	ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
+-        return SCSI_ABORT_SNOOZE;
+-    }
+-
+-/*
+- * Case 4: If the command is currently disconnected from the bus, and 
+- * 	there are no connected commands, we reconnect the I_T_L or 
+- *	I_T_L_Q nexus associated with it, go into message out, and send 
+- *      an abort message.
+- *
+- * This case is especially ugly. In order to reestablish the nexus, we
+- * need to call NCR5380_select().  The easiest way to implement this 
+- * function was to abort if the bus was busy, and let the interrupt
+- * handler triggered on the SEL for reselect take care of lost arbitrations
+- * where necessary, meaning interrupts need to be enabled.
+- *
+- * When interrupts are enabled, the queues may change - so we 
+- * can't remove it from the disconnected queue before selecting it
+- * because that could cause a failure in hashing the nexus if that 
+- * device reselected.
+- * 
+- * Since the queues may change, we can't use the pointers from when we
+- * first locate it.
+- *
+- * So, we must first locate the command, and if NCR5380_select()
+- * succeeds, then issue the abort, relocate the command and remove
+- * it from the disconnected queue.
+- */
+-
+-    for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
+-	 tmp = NEXT(tmp)) 
+-        if (cmd == tmp) {
+-            local_irq_restore(flags);
+-	    ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
+-  
+-            if (NCR5380_select (instance, cmd, (int) cmd->tag)) 
+-		return SCSI_ABORT_BUSY;
+-
+-	    ABRT_PRINTK("scsi%d: nexus reestablished.\n", HOSTNO);
+-
+-	    do_abort (instance);
+-
+-	    local_irq_save(flags);
+-	    for (prev = (Scsi_Cmnd **) &(hostdata->disconnected_queue), 
+-		tmp = (Scsi_Cmnd *) hostdata->disconnected_queue;
+-		tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) )
+-		    if (cmd == tmp) {
+-		    REMOVE(5, *prev, tmp, NEXT(tmp));
+-		    *prev = NEXT(tmp);
+-		    NEXT(tmp) = NULL;
+-		    tmp->result = DID_ABORT << 16;
+-		    /* We must unlock the tag/LUN immediately here, since the
+-		     * target goes to BUS FREE and doesn't send us another
+-		     * message (COMMAND_COMPLETE or the like)
+-		     */
++	/*
++	 * Case 2 : If the command hasn't been issued yet, we simply remove it
++	 *	    from the issue queue.
++	 */
++	for (prev = (Scsi_Cmnd **)&(hostdata->issue_queue),
++	     tmp = (Scsi_Cmnd *)hostdata->issue_queue;
++	     tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) {
++		if (cmd == tmp) {
++			REMOVE(5, *prev, tmp, NEXT(tmp));
++			(*prev) = NEXT(tmp);
++			NEXT(tmp) = NULL;
++			tmp->result = DID_ABORT << 16;
++			local_irq_restore(flags);
++			ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
++				    HOSTNO);
++			/* Tagged queuing note: no tag to free here, hasn't been assigned
++			 * yet... */
++			tmp->scsi_done(tmp);
++			falcon_release_lock_if_possible(hostdata);
++			return SCSI_ABORT_SUCCESS;
++		}
++	}
++
++	/*
++	 * Case 3 : If any commands are connected, we're going to fail the abort
++	 *	    and let the high level SCSI driver retry at a later time or
++	 *	    issue a reset.
++	 *
++	 *	    Timeouts, and therefore aborted commands, will be highly unlikely
++	 *          and handling them cleanly in this situation would make the common
++	 *	    case of noresets less efficient, and would pollute our code.  So,
++	 *	    we fail.
++	 */
++
++	if (hostdata->connected) {
++		local_irq_restore(flags);
++		ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
++		return SCSI_ABORT_SNOOZE;
++	}
++
++	/*
++	 * Case 4: If the command is currently disconnected from the bus, and
++	 *	there are no connected commands, we reconnect the I_T_L or
++	 *	I_T_L_Q nexus associated with it, go into message out, and send
++	 *      an abort message.
++	 *
++	 * This case is especially ugly. In order to reestablish the nexus, we
++	 * need to call NCR5380_select().  The easiest way to implement this
++	 * function was to abort if the bus was busy, and let the interrupt
++	 * handler triggered on the SEL for reselect take care of lost arbitrations
++	 * where necessary, meaning interrupts need to be enabled.
++	 *
++	 * When interrupts are enabled, the queues may change - so we
++	 * can't remove it from the disconnected queue before selecting it
++	 * because that could cause a failure in hashing the nexus if that
++	 * device reselected.
++	 *
++	 * Since the queues may change, we can't use the pointers from when we
++	 * first locate it.
++	 *
++	 * So, we must first locate the command, and if NCR5380_select()
++	 * succeeds, then issue the abort, relocate the command and remove
++	 * it from the disconnected queue.
++	 */
++
++	for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
++	     tmp = NEXT(tmp)) {
++		if (cmd == tmp) {
++			local_irq_restore(flags);
++			ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
++
++			if (NCR5380_select(instance, cmd, (int)cmd->tag))
++				return SCSI_ABORT_BUSY;
++
++			ABRT_PRINTK("scsi%d: nexus reestablished.\n", HOSTNO);
++
++			do_abort(instance);
++
++			local_irq_save(flags);
++			for (prev = (Scsi_Cmnd **)&(hostdata->disconnected_queue),
++			     tmp = (Scsi_Cmnd *)hostdata->disconnected_queue;
++			     tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) {
++				if (cmd == tmp) {
++					REMOVE(5, *prev, tmp, NEXT(tmp));
++					*prev = NEXT(tmp);
++					NEXT(tmp) = NULL;
++					tmp->result = DID_ABORT << 16;
++					/* We must unlock the tag/LUN immediately here, since the
++					 * target goes to BUS FREE and doesn't send us another
++					 * message (COMMAND_COMPLETE or the like)
++					 */
+ #ifdef SUPPORT_TAGS
+-		    cmd_free_tag( tmp );
++					cmd_free_tag(tmp);
+ #else
+-		    hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
++					hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+ #endif
+-		    local_irq_restore(flags);
+-		    tmp->scsi_done(tmp);
+-		    falcon_release_lock_if_possible( hostdata );
+-		    return SCSI_ABORT_SUCCESS;
++					local_irq_restore(flags);
++					tmp->scsi_done(tmp);
++					falcon_release_lock_if_possible(hostdata);
++					return SCSI_ABORT_SUCCESS;
++				}
++			}
+ 		}
+ 	}
+ 
+-/*
+- * Case 5 : If we reached this point, the command was not found in any of 
+- *	    the queues.
+- *
+- * We probably reached this point because of an unlikely race condition
+- * between the command completing successfully and the abortion code,
+- * so we won't panic, but we will notify the user in case something really
+- * broke.
+- */
++	/*
++	 * Case 5 : If we reached this point, the command was not found in any of
++	 *	    the queues.
++	 *
++	 * We probably reached this point because of an unlikely race condition
++	 * between the command completing successfully and the abortion code,
++	 * so we won't panic, but we will notify the user in case something really
++	 * broke.
++	 */
+ 
+-    local_irq_restore(flags);
+-    printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
+-           KERN_INFO "        before abortion\n", HOSTNO); 
++	local_irq_restore(flags);
++	printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
++	       KERN_INFO "        before abortion\n", HOSTNO);
+ 
+-/* Maybe it is sufficient just to release the ST-DMA lock... (if
+- * possible at all) At least, we should check if the lock could be
+- * released after the abort, in case it is kept due to some bug.
+- */
+-    falcon_release_lock_if_possible( hostdata );
++	/* Maybe it is sufficient just to release the ST-DMA lock... (if
++	 * possible at all) At least, we should check if the lock could be
++	 * released after the abort, in case it is kept due to some bug.
++	 */
++	falcon_release_lock_if_possible(hostdata);
+ 
+-    return SCSI_ABORT_NOT_RUNNING;
++	return SCSI_ABORT_NOT_RUNNING;
+ }
+ 
+ 
+-/* 
++/*
+  * Function : int NCR5380_reset (Scsi_Cmnd *cmd)
+- * 
++ *
+  * Purpose : reset the SCSI bus.
+  *
+  * Returns : SCSI_RESET_WAKEUP
+  *
+- */ 
++ */
+ 
+-static int NCR5380_bus_reset( Scsi_Cmnd *cmd)
++static int NCR5380_bus_reset(Scsi_Cmnd *cmd)
+ {
+-    SETUP_HOSTDATA(cmd->device->host);
+-    int           i;
+-    unsigned long flags;
++	SETUP_HOSTDATA(cmd->device->host);
++	int i;
++	unsigned long flags;
+ #if 1
+-    Scsi_Cmnd *connected, *disconnected_queue;
++	Scsi_Cmnd *connected, *disconnected_queue;
+ #endif
+ 
+-    if (!IS_A_TT() && !falcon_got_lock)
+-	printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n",
+-	       H_NO(cmd) );
+-
+-    NCR5380_print_status (cmd->device->host);
+-
+-    /* get in phase */
+-    NCR5380_write( TARGET_COMMAND_REG,
+-		   PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
+-    /* assert RST */
+-    NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
+-    udelay (40);
+-    /* reset NCR registers */
+-    NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
+-    NCR5380_write( MODE_REG, MR_BASE );
+-    NCR5380_write( TARGET_COMMAND_REG, 0 );
+-    NCR5380_write( SELECT_ENABLE_REG, 0 );
+-    /* ++roman: reset interrupt condition! otherwise no interrupts don't get
+-     * through anymore ... */
+-    (void)NCR5380_read( RESET_PARITY_INTERRUPT_REG );
+-
+-#if 1 /* XXX Should now be done by midlevel code, but it's broken XXX */
+-      /* XXX see below                                            XXX */
+-
+-    /* MSch: old-style reset: actually abort all command processing here */
+-
+-    /* After the reset, there are no more connected or disconnected commands
+-     * and no busy units; to avoid problems with re-inserting the commands
+-     * into the issue_queue (via scsi_done()), the aborted commands are
+-     * remembered in local variables first.
+-     */
+-    local_irq_save(flags);
+-    connected = (Scsi_Cmnd *)hostdata->connected;
+-    hostdata->connected = NULL;
+-    disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
+-    hostdata->disconnected_queue = NULL;
++	if (!IS_A_TT() && !falcon_got_lock)
++		printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n",
++		       H_NO(cmd));
++
++	NCR5380_print_status(cmd->device->host);
++
++	/* get in phase */
++	NCR5380_write(TARGET_COMMAND_REG,
++		      PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG)));
++	/* assert RST */
++	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
++	udelay(40);
++	/* reset NCR registers */
++	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++	NCR5380_write(MODE_REG, MR_BASE);
++	NCR5380_write(TARGET_COMMAND_REG, 0);
++	NCR5380_write(SELECT_ENABLE_REG, 0);
++	/* ++roman: reset interrupt condition! otherwise no interrupts don't get
++	 * through anymore ... */
++	(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
++
++#if 1	/* XXX Should now be done by midlevel code, but it's broken XXX */
++	/* XXX see below                                            XXX */
++
++	/* MSch: old-style reset: actually abort all command processing here */
++
++	/* After the reset, there are no more connected or disconnected commands
++	 * and no busy units; to avoid problems with re-inserting the commands
++	 * into the issue_queue (via scsi_done()), the aborted commands are
++	 * remembered in local variables first.
++	 */
++	local_irq_save(flags);
++	connected = (Scsi_Cmnd *)hostdata->connected;
++	hostdata->connected = NULL;
++	disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
++	hostdata->disconnected_queue = NULL;
+ #ifdef SUPPORT_TAGS
+-    free_all_tags();
++	free_all_tags();
+ #endif
+-    for( i = 0; i < 8; ++i )
+-	hostdata->busy[i] = 0;
++	for (i = 0; i < 8; ++i)
++		hostdata->busy[i] = 0;
+ #ifdef REAL_DMA
+-    hostdata->dma_len = 0;
++	hostdata->dma_len = 0;
+ #endif
+-    local_irq_restore(flags);
++	local_irq_restore(flags);
+ 
+-    /* In order to tell the mid-level code which commands were aborted, 
+-     * set the command status to DID_RESET and call scsi_done() !!!
+-     * This ultimately aborts processing of these commands in the mid-level.
+-     */
+-
+-    if ((cmd = connected)) {
+-	ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
+-	cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
+-	cmd->scsi_done( cmd );
+-    }
++	/* In order to tell the mid-level code which commands were aborted,
++	 * set the command status to DID_RESET and call scsi_done() !!!
++	 * This ultimately aborts processing of these commands in the mid-level.
++	 */
+ 
+-    for (i = 0; (cmd = disconnected_queue); ++i) {
+-	disconnected_queue = NEXT(cmd);
+-	NEXT(cmd) = NULL;
+-	cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
+-	cmd->scsi_done( cmd );
+-    }
+-    if (i > 0)
+-	ABRT_PRINTK("scsi: reset aborted %d disconnected command(s)\n", i);
+-
+-/* The Falcon lock should be released after a reset...
+- */
+-/* ++guenther: moved to atari_scsi_reset(), to prevent a race between
+- * unlocking and enabling dma interrupt.
+- */
+-/*    falcon_release_lock_if_possible( hostdata );*/
+-
+-    /* since all commands have been explicitly terminated, we need to tell
+-     * the midlevel code that the reset was SUCCESSFUL, and there is no 
+-     * need to 'wake up' the commands by a request_sense
+-     */
+-    return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
++	if ((cmd = connected)) {
++		ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
++		cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
++		cmd->scsi_done(cmd);
++	}
++
++	for (i = 0; (cmd = disconnected_queue); ++i) {
++		disconnected_queue = NEXT(cmd);
++		NEXT(cmd) = NULL;
++		cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
++		cmd->scsi_done(cmd);
++	}
++	if (i > 0)
++		ABRT_PRINTK("scsi: reset aborted %d disconnected command(s)\n", i);
++
++	/* The Falcon lock should be released after a reset...
++	 */
++	/* ++guenther: moved to atari_scsi_reset(), to prevent a race between
++	 * unlocking and enabling dma interrupt.
++	 */
++/*	falcon_release_lock_if_possible( hostdata );*/
++
++	/* since all commands have been explicitly terminated, we need to tell
++	 * the midlevel code that the reset was SUCCESSFUL, and there is no
++	 * need to 'wake up' the commands by a request_sense
++	 */
++	return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
+ #else /* 1 */
+ 
+-    /* MSch: new-style reset handling: let the mid-level do what it can */
++	/* MSch: new-style reset handling: let the mid-level do what it can */
++
++	/* ++guenther: MID-LEVEL IS STILL BROKEN.
++	 * Mid-level is supposed to requeue all commands that were active on the
++	 * various low-level queues. In fact it does this, but that's not enough
++	 * because all these commands are subject to timeout. And if a timeout
++	 * happens for any removed command, *_abort() is called but all queues
++	 * are now empty. Abort then gives up the falcon lock, which is fatal,
++	 * since the mid-level will queue more commands and must have the lock
++	 * (it's all happening inside timer interrupt handler!!).
++	 * Even worse, abort will return NOT_RUNNING for all those commands not
++	 * on any queue, so they won't be retried ...
++	 *
++	 * Conclusion: either scsi.c disables timeout for all resetted commands
++	 * immediately, or we lose!  As of linux-2.0.20 it doesn't.
++	 */
++
++	/* After the reset, there are no more connected or disconnected commands
++	 * and no busy units; so clear the low-level status here to avoid
++	 * conflicts when the mid-level code tries to wake up the affected
++	 * commands!
++	 */
++
++	if (hostdata->issue_queue)
++		ABRT_PRINTK("scsi%d: reset aborted issued command(s)\n", H_NO(cmd));
++	if (hostdata->connected)
++		ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
++	if (hostdata->disconnected_queue)
++		ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd));
+ 
+-    /* ++guenther: MID-LEVEL IS STILL BROKEN.
+-     * Mid-level is supposed to requeue all commands that were active on the
+-     * various low-level queues. In fact it does this, but that's not enough
+-     * because all these commands are subject to timeout. And if a timeout
+-     * happens for any removed command, *_abort() is called but all queues
+-     * are now empty. Abort then gives up the falcon lock, which is fatal,
+-     * since the mid-level will queue more commands and must have the lock
+-     * (it's all happening inside timer interrupt handler!!).
+-     * Even worse, abort will return NOT_RUNNING for all those commands not
+-     * on any queue, so they won't be retried ...
+-     *
+-     * Conclusion: either scsi.c disables timeout for all resetted commands
+-     * immediately, or we lose!  As of linux-2.0.20 it doesn't.
+-     */
+-
+-    /* After the reset, there are no more connected or disconnected commands
+-     * and no busy units; so clear the low-level status here to avoid 
+-     * conflicts when the mid-level code tries to wake up the affected 
+-     * commands!
+-     */
+-
+-    if (hostdata->issue_queue)
+-	ABRT_PRINTK("scsi%d: reset aborted issued command(s)\n", H_NO(cmd));
+-    if (hostdata->connected) 
+-	ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
+-    if (hostdata->disconnected_queue)
+-	ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd));
+-
+-    local_irq_save(flags);
+-    hostdata->issue_queue = NULL;
+-    hostdata->connected = NULL;
+-    hostdata->disconnected_queue = NULL;
++	local_irq_save(flags);
++	hostdata->issue_queue = NULL;
++	hostdata->connected = NULL;
++	hostdata->disconnected_queue = NULL;
+ #ifdef SUPPORT_TAGS
+-    free_all_tags();
++	free_all_tags();
+ #endif
+-    for( i = 0; i < 8; ++i )
+-	hostdata->busy[i] = 0;
++	for (i = 0; i < 8; ++i)
++		hostdata->busy[i] = 0;
+ #ifdef REAL_DMA
+-    hostdata->dma_len = 0;
++	hostdata->dma_len = 0;
+ #endif
+-    local_irq_restore(flags);
++	local_irq_restore(flags);
+ 
+-    /* we did no complete reset of all commands, so a wakeup is required */
+-    return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
++	/* we did no complete reset of all commands, so a wakeup is required */
++	return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
+ #endif /* 1 */
+ }
+-
+-/* Local Variables: */
+-/* tab-width: 8     */
+-/* End:             */
+--- linux-m68k-2.6.21.orig/drivers/scsi/atari_scsi.c
++++ linux-m68k-2.6.21/drivers/scsi/atari_scsi.c
+@@ -186,38 +186,37 @@ static inline void DISABLE_IRQ(void)
+ /***************************** Prototypes *****************************/
+ 
+ #ifdef REAL_DMA
+-static int scsi_dma_is_ignored_buserr( unsigned char dma_stat );
+-static void atari_scsi_fetch_restbytes( void );
+-static long atari_scsi_dma_residual( struct Scsi_Host *instance );
+-static int falcon_classify_cmd( Scsi_Cmnd *cmd );
+-static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
+-                                         Scsi_Cmnd *cmd, int write_flag );
+-#endif
+-static irqreturn_t scsi_tt_intr( int irq, void *dummy);
+-static irqreturn_t scsi_falcon_intr( int irq, void *dummy);
+-static void falcon_release_lock_if_possible( struct NCR5380_hostdata *
+-                                             hostdata );
+-static void falcon_get_lock( void );
++static int scsi_dma_is_ignored_buserr(unsigned char dma_stat);
++static void atari_scsi_fetch_restbytes(void);
++static long atari_scsi_dma_residual(struct Scsi_Host *instance);
++static int falcon_classify_cmd(Scsi_Cmnd *cmd);
++static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
++					Scsi_Cmnd *cmd, int write_flag);
++#endif
++static irqreturn_t scsi_tt_intr(int irq, void *dummy);
++static irqreturn_t scsi_falcon_intr(int irq, void *dummy);
++static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata);
++static void falcon_get_lock(void);
+ #ifdef CONFIG_ATARI_SCSI_RESET_BOOT
+-static void atari_scsi_reset_boot( void );
++static void atari_scsi_reset_boot(void);
+ #endif
+-static unsigned char atari_scsi_tt_reg_read( unsigned char reg );
+-static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value);
+-static unsigned char atari_scsi_falcon_reg_read( unsigned char reg );
+-static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value );
++static unsigned char atari_scsi_tt_reg_read(unsigned char reg);
++static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value);
++static unsigned char atari_scsi_falcon_reg_read(unsigned char reg);
++static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value);
+ 
+ /************************* End of Prototypes **************************/
+ 
+ 
+-static struct Scsi_Host *atari_scsi_host = NULL;
+-static unsigned char (*atari_scsi_reg_read)( unsigned char reg );
+-static void (*atari_scsi_reg_write)( unsigned char reg, unsigned char value );
++static struct Scsi_Host *atari_scsi_host;
++static unsigned char (*atari_scsi_reg_read)(unsigned char reg);
++static void (*atari_scsi_reg_write)(unsigned char reg, unsigned char value);
+ 
+ #ifdef REAL_DMA
+ static unsigned long	atari_dma_residual, atari_dma_startaddr;
+ static short		atari_dma_active;
+ /* pointer to the dribble buffer */
+-static char		*atari_dma_buffer = NULL;
++static char		*atari_dma_buffer;
+ /* precalculated physical address of the dribble buffer */
+ static unsigned long	atari_dma_phys_buffer;
+ /* != 0 tells the Falcon int handler to copy data from the dribble buffer */
+@@ -233,7 +232,7 @@ static char		*atari_dma_orig_addr;
+ static unsigned long	atari_dma_stram_mask;
+ #define STRAM_ADDR(a)	(((a) & atari_dma_stram_mask) == 0)
+ /* number of bytes to cut from a transfer to handle NCR overruns */
+-static int atari_read_overruns = 0;
++static int atari_read_overruns;
+ #endif
+ 
+ static int setup_can_queue = -1;
+@@ -256,10 +255,10 @@ module_param(setup_hostid, int, 0);
+ 
+ #if defined(REAL_DMA)
+ 
+-static int scsi_dma_is_ignored_buserr( unsigned char dma_stat )
++static int scsi_dma_is_ignored_buserr(unsigned char dma_stat)
+ {
+ 	int i;
+-	unsigned long	addr = SCSI_DMA_READ_P( dma_addr ), end_addr;
++	unsigned long addr = SCSI_DMA_READ_P(dma_addr), end_addr;
+ 
+ 	if (dma_stat & 0x01) {
+ 
+@@ -267,15 +266,14 @@ static int scsi_dma_is_ignored_buserr( u
+ 		 * physical memory chunk (DMA prefetch!), but that doesn't hurt.
+ 		 * Check for this case:
+ 		 */
+-		
+-		for( i = 0; i < m68k_num_memory; ++i ) {
+-			end_addr = m68k_memory[i].addr +
+-				m68k_memory[i].size;
++
++		for (i = 0; i < m68k_num_memory; ++i) {
++			end_addr = m68k_memory[i].addr + m68k_memory[i].size;
+ 			if (end_addr <= addr && addr <= end_addr + 4)
+-				return( 1 );
++				return 1;
+ 		}
+ 	}
+-	return( 0 );
++	return 0;
+ }
+ 
+ 
+@@ -284,28 +282,27 @@ static int scsi_dma_is_ignored_buserr( u
+  * end-of-DMA, both SCSI ints are triggered simultaneously, so the NCR int has
+  * to clear the DMA int pending bit before it allows other level 6 interrupts.
+  */
+-static void scsi_dma_buserr (int irq, void *dummy)
++static void scsi_dma_buserr(int irq, void *dummy)
+ {
+-	unsigned char	dma_stat = tt_scsi_dma.dma_ctrl;
++	unsigned char dma_stat = tt_scsi_dma.dma_ctrl;
+ 
+ 	/* Don't do anything if a NCR interrupt is pending. Probably it's just
+ 	 * masked... */
+-	if (atari_irq_pending( IRQ_TT_MFP_SCSI ))
++	if (atari_irq_pending(IRQ_TT_MFP_SCSI))
+ 		return;
+-	
++
+ 	printk("Bad SCSI DMA interrupt! dma_addr=0x%08lx dma_stat=%02x dma_cnt=%08lx\n",
+ 	       SCSI_DMA_READ_P(dma_addr), dma_stat, SCSI_DMA_READ_P(dma_cnt));
+ 	if (dma_stat & 0x80) {
+-		if (!scsi_dma_is_ignored_buserr( dma_stat ))
+-			printk( "SCSI DMA bus error -- bad DMA programming!\n" );
+-	}
+-	else {
++		if (!scsi_dma_is_ignored_buserr(dma_stat))
++			printk("SCSI DMA bus error -- bad DMA programming!\n");
++	} else {
+ 		/* Under normal circumstances we never should get to this point,
+ 		 * since both interrupts are triggered simultaneously and the 5380
+ 		 * int has higher priority. When this irq is handled, that DMA
+ 		 * interrupt is cleared. So a warning message is printed here.
+ 		 */
+-		printk( "SCSI DMA intr ?? -- this shouldn't happen!\n" );
++		printk("SCSI DMA intr ?? -- this shouldn't happen!\n");
+ 	}
+ }
+ #endif
+@@ -313,7 +310,7 @@ static void scsi_dma_buserr (int irq, vo
+ #endif
+ 
+ 
+-static irqreturn_t scsi_tt_intr (int irq, void *dummy)
++static irqreturn_t scsi_tt_intr(int irq, void *dummy)
+ {
+ #ifdef REAL_DMA
+ 	int dma_stat;
+@@ -327,7 +324,7 @@ static irqreturn_t scsi_tt_intr (int irq
+ 	 * is that a bus error occurred...
+ 	 */
+ 	if (dma_stat & 0x80) {
+-		if (!scsi_dma_is_ignored_buserr( dma_stat )) {
++		if (!scsi_dma_is_ignored_buserr(dma_stat)) {
+ 			printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n",
+ 			       SCSI_DMA_READ_P(dma_addr));
+ 			printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!");
+@@ -344,8 +341,7 @@ static irqreturn_t scsi_tt_intr (int irq
+ 	 * data reg!
+ 	 */
+ 	if ((dma_stat & 0x02) && !(dma_stat & 0x40)) {
+-		atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P( dma_addr ) -
+-												atari_dma_startaddr);
++		atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr);
+ 
+ 		DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n",
+ 			   atari_dma_residual);
+@@ -353,28 +349,30 @@ static irqreturn_t scsi_tt_intr (int irq
+ 		if ((signed int)atari_dma_residual < 0)
+ 			atari_dma_residual = 0;
+ 		if ((dma_stat & 1) == 0) {
+-			/* After read operations, we maybe have to
+-			   transport some rest bytes */
++			/*
++			 * After read operations, we maybe have to
++			 * transport some rest bytes
++			 */
+ 			atari_scsi_fetch_restbytes();
+-		}
+-		else {
+-			/* There seems to be a nasty bug in some SCSI-DMA/NCR
+-			   combinations: If a target disconnects while a write
+-			   operation is going on, the address register of the
+-			   DMA may be a few bytes farer than it actually read.
+-			   This is probably due to DMA prefetching and a delay
+-			   between DMA and NCR.  Experiments showed that the
+-			   dma_addr is 9 bytes to high, but this could vary.
+-			   The problem is, that the residual is thus calculated
+-			   wrong and the next transfer will start behind where
+-			   it should.  So we round up the residual to the next
+-			   multiple of a sector size, if it isn't already a
+-			   multiple and the originally expected transfer size
+-			   was.  The latter condition is there to ensure that
+-			   the correction is taken only for "real" data
+-			   transfers and not for, e.g., the parameters of some
+-			   other command.  These shouldn't disconnect anyway.
+-			   */
++		} else {
++			/*
++			 * There seems to be a nasty bug in some SCSI-DMA/NCR
++			 * combinations: If a target disconnects while a write
++			 * operation is going on, the address register of the
++			 * DMA may be a few bytes farer than it actually read.
++			 * This is probably due to DMA prefetching and a delay
++			 * between DMA and NCR.  Experiments showed that the
++			 * dma_addr is 9 bytes to high, but this could vary.
++			 * The problem is, that the residual is thus calculated
++			 * wrong and the next transfer will start behind where
++			 * it should.  So we round up the residual to the next
++			 * multiple of a sector size, if it isn't already a
++			 * multiple and the originally expected transfer size
++			 * was.  The latter condition is there to ensure that
++			 * the correction is taken only for "real" data
++			 * transfers and not for, e.g., the parameters of some
++			 * other command.  These shouldn't disconnect anyway.
++			 */
+ 			if (atari_dma_residual & 0x1ff) {
+ 				DMA_PRINTK("SCSI DMA: DMA bug corrected, "
+ 					   "difference %ld bytes\n",
+@@ -394,18 +392,18 @@ static irqreturn_t scsi_tt_intr (int irq
+ 	}
+ 
+ #endif /* REAL_DMA */
+-	
++
+ 	NCR5380_intr(0, 0);
+ 
+ #if 0
+ 	/* To be sure the int is not masked */
+-	atari_enable_irq( IRQ_TT_MFP_SCSI );
++	atari_enable_irq(IRQ_TT_MFP_SCSI);
+ #endif
+ 	return IRQ_HANDLED;
+ }
+ 
+ 
+-static irqreturn_t scsi_falcon_intr (int irq, void *dummy)
++static irqreturn_t scsi_falcon_intr(int irq, void *dummy)
+ {
+ #ifdef REAL_DMA
+ 	int dma_stat;
+@@ -430,7 +428,7 @@ static irqreturn_t scsi_falcon_intr (int
+ 	 * bytes are stuck in the ST-DMA fifo (there's no way to reach them!)
+ 	 */
+ 	if (atari_dma_active && (dma_stat & 0x02)) {
+-		unsigned long	transferred;
++		unsigned long transferred;
+ 
+ 		transferred = SCSI_DMA_GETADR() - atari_dma_startaddr;
+ 		/* The ST-DMA address is incremented in 2-byte steps, but the
+@@ -445,8 +443,7 @@ static irqreturn_t scsi_falcon_intr (int
+ 		atari_dma_residual = HOSTDATA_DMALEN - transferred;
+ 		DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n",
+ 			   atari_dma_residual);
+-	}
+-	else
++	} else
+ 		atari_dma_residual = 0;
+ 	atari_dma_active = 0;
+ 
+@@ -467,7 +464,7 @@ static irqreturn_t scsi_falcon_intr (int
+ 
+ 
+ #ifdef REAL_DMA
+-static void atari_scsi_fetch_restbytes( void )
++static void atari_scsi_fetch_restbytes(void)
+ {
+ 	int nr;
+ 	char *src, *dst;
+@@ -505,19 +502,17 @@ static int falcon_dont_release = 0;
+  * again (but others waiting longer more probably will win).
+  */
+ 
+-static void
+-falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
++static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata)
+ {
+ 	unsigned long flags;
+-		
+-	if (IS_A_TT()) return;
+-	
++
++	if (IS_A_TT())
++		return;
++
+ 	local_irq_save(flags);
+ 
+-	if (falcon_got_lock &&
+-		!hostdata->disconnected_queue &&
+-		!hostdata->issue_queue &&
+-		!hostdata->connected) {
++	if (falcon_got_lock && !hostdata->disconnected_queue &&
++	    !hostdata->issue_queue && !hostdata->connected) {
+ 
+ 		if (falcon_dont_release) {
+ #if 0
+@@ -528,7 +523,7 @@ falcon_release_lock_if_possible( struct 
+ 		}
+ 		falcon_got_lock = 0;
+ 		stdma_release();
+-		wake_up( &falcon_fairness_wait );
++		wake_up(&falcon_fairness_wait);
+ 	}
+ 
+ 	local_irq_restore(flags);
+@@ -549,31 +544,31 @@ falcon_release_lock_if_possible( struct 
+  * Complicated, complicated.... Sigh...
+  */
+ 
+-static void falcon_get_lock( void )
++static void falcon_get_lock(void)
+ {
+ 	unsigned long flags;
+ 
+-	if (IS_A_TT()) return;
++	if (IS_A_TT())
++		return;
+ 
+ 	local_irq_save(flags);
+ 
+ 	while (!in_irq() && falcon_got_lock && stdma_others_waiting())
+-		sleep_on( &falcon_fairness_wait );
++		sleep_on(&falcon_fairness_wait);
+ 
+ 	while (!falcon_got_lock) {
+ 		if (in_irq())
+-			panic( "Falcon SCSI hasn't ST-DMA lock in interrupt" );
++			panic("Falcon SCSI hasn't ST-DMA lock in interrupt");
+ 		if (!falcon_trying_lock) {
+ 			falcon_trying_lock = 1;
+ 			stdma_lock(scsi_falcon_intr, NULL);
+ 			falcon_got_lock = 1;
+ 			falcon_trying_lock = 0;
+-			wake_up( &falcon_try_wait );
+-		}
+-		else {
+-			sleep_on( &falcon_try_wait );
++			wake_up(&falcon_try_wait);
++		} else {
++			sleep_on(&falcon_try_wait);
+ 		}
+-	}	
++	}
+ 
+ 	local_irq_restore(flags);
+ 	if (!falcon_got_lock)
+@@ -587,18 +582,18 @@ static void falcon_get_lock( void )
+  */
+ 
+ #if 0
+-int atari_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
++int atari_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+ {
+ 	/* falcon_get_lock();
+ 	 * ++guenther: moved to NCR5380_queue_command() to prevent
+ 	 * race condition, see there for an explanation.
+ 	 */
+-	return( NCR5380_queue_command( cmd, done ) );
++	return NCR5380_queue_command(cmd, done);
+ }
+ #endif
+ 
+ 
+-int atari_scsi_detect (struct scsi_host_template *host)
++int atari_scsi_detect(struct scsi_host_template *host)
+ {
+ 	static int called = 0;
+ 	struct Scsi_Host *instance;
+@@ -606,7 +601,7 @@ int atari_scsi_detect (struct scsi_host_
+ 	if (!MACH_IS_ATARI ||
+ 	    (!ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(TT_SCSI)) ||
+ 	    called)
+-		return( 0 );
++		return 0;
+ 
+ 	host->proc_name = "Atari";
+ 
+@@ -655,32 +650,33 @@ int atari_scsi_detect (struct scsi_host_
+ 	    !ATARIHW_PRESENT(EXTD_DMA) && m68k_num_memory > 1) {
+ 		atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI");
+ 		if (!atari_dma_buffer) {
+-			printk( KERN_ERR "atari_scsi_detect: can't allocate ST-RAM "
+-					"double buffer\n" );
+-			return( 0 );
++			printk(KERN_ERR "atari_scsi_detect: can't allocate ST-RAM "
++					"double buffer\n");
++			return 0;
+ 		}
+-		atari_dma_phys_buffer = virt_to_phys( atari_dma_buffer );
++		atari_dma_phys_buffer = virt_to_phys(atari_dma_buffer);
+ 		atari_dma_orig_addr = 0;
+ 	}
+ #endif
+-	instance = scsi_register (host, sizeof (struct NCR5380_hostdata));
+-	if(instance == NULL)
+-	{
++	instance = scsi_register(host, sizeof(struct NCR5380_hostdata));
++	if (instance == NULL) {
+ 		atari_stram_free(atari_dma_buffer);
+ 		atari_dma_buffer = 0;
+ 		return 0;
+ 	}
+ 	atari_scsi_host = instance;
+-       /* Set irq to 0, to avoid that the mid-level code disables our interrupt
+-        * during queue_command calls. This is completely unnecessary, and even
+-        * worse causes bad problems on the Falcon, where the int is shared with
+-        * IDE and floppy! */
++	/*
++	 * Set irq to 0, to avoid that the mid-level code disables our interrupt
++	 * during queue_command calls. This is completely unnecessary, and even
++	 * worse causes bad problems on the Falcon, where the int is shared with
++	 * IDE and floppy!
++	 */
+        instance->irq = 0;
+ 
+ #ifdef CONFIG_ATARI_SCSI_RESET_BOOT
+ 	atari_scsi_reset_boot();
+ #endif
+-	NCR5380_init (instance, 0);
++	NCR5380_init(instance, 0);
+ 
+ 	if (IS_A_TT()) {
+ 
+@@ -727,11 +723,10 @@ int atari_scsi_detect (struct scsi_host_
+ 			 * the rest data bug is fixed, this can be lowered to 1.
+ 			 */
+ 			atari_read_overruns = 4;
+-		}		
++		}
+ #endif /*REAL_DMA*/
+-	}
+-	else { /* ! IS_A_TT */
+-		
++	} else { /* ! IS_A_TT */
++
+ 		/* Nothing to do for the interrupt: the ST-DMA is initialized
+ 		 * already by atari_init_INTS()
+ 		 */
+@@ -756,19 +751,19 @@ int atari_scsi_detect (struct scsi_host_
+ 			setup_use_tagged_queuing ? "yes" : "no",
+ #endif
+ 			instance->hostt->this_id );
+-	NCR5380_print_options (instance);
+-	printk ("\n");
++	NCR5380_print_options(instance);
++	printk("\n");
+ 
+ 	called = 1;
+-	return( 1 );
++	return 1;
+ }
+ 
+-int atari_scsi_release (struct Scsi_Host *sh)
++int atari_scsi_release(struct Scsi_Host *sh)
+ {
+ 	if (IS_A_TT())
+ 		free_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr);
+ 	if (atari_dma_buffer)
+-		atari_stram_free (atari_dma_buffer);
++		atari_stram_free(atari_dma_buffer);
+ 	return 1;
+ }
+ 
+@@ -779,9 +774,9 @@ void __init atari_scsi_setup(char *str, 
+ 	 * Defaults depend on TT or Falcon, hostid determined at run time.
+ 	 * Negative values mean don't change.
+ 	 */
+-	
++
+ 	if (ints[0] < 1) {
+-		printk( "atari_scsi_setup: no arguments!\n" );
++		printk("atari_scsi_setup: no arguments!\n");
+ 		return;
+ 	}
+ 
+@@ -807,7 +802,7 @@ void __init atari_scsi_setup(char *str, 
+ 		if (ints[4] >= 0 && ints[4] <= 7)
+ 			setup_hostid = ints[4];
+ 		else if (ints[4] > 7)
+-			printk( "atari_scsi_setup: invalid host ID %d !\n", ints[4] );
++			printk("atari_scsi_setup: invalid host ID %d !\n", ints[4]);
+ 	}
+ #ifdef SUPPORT_TAGS
+ 	if (ints[0] >= 5) {
+@@ -819,7 +814,7 @@ void __init atari_scsi_setup(char *str, 
+ 
+ int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
+ {
+-	int		rv;
++	int rv;
+ 	struct NCR5380_hostdata *hostdata =
+ 		(struct NCR5380_hostdata *)cmd->device->host->hostdata;
+ 
+@@ -829,13 +824,12 @@ int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
+ 	 */
+ 	/* And abort a maybe active DMA transfer */
+ 	if (IS_A_TT()) {
+-		atari_turnoff_irq( IRQ_TT_MFP_SCSI );
++		atari_turnoff_irq(IRQ_TT_MFP_SCSI);
+ #ifdef REAL_DMA
+ 		tt_scsi_dma.dma_ctrl = 0;
+ #endif /* REAL_DMA */
+-	}
+-	else {
+-		atari_turnoff_irq( IRQ_MFP_FSCSI );
++	} else {
++		atari_turnoff_irq(IRQ_MFP_FSCSI);
+ #ifdef REAL_DMA
+ 		st_dma.dma_mode_status = 0x90;
+ 		atari_dma_active = 0;
+@@ -847,52 +841,51 @@ int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
+ 
+ 	/* Re-enable ints */
+ 	if (IS_A_TT()) {
+-		atari_turnon_irq( IRQ_TT_MFP_SCSI );
+-	}
+-	else {
+-		atari_turnon_irq( IRQ_MFP_FSCSI );
++		atari_turnon_irq(IRQ_TT_MFP_SCSI);
++	} else {
++		atari_turnon_irq(IRQ_MFP_FSCSI);
+ 	}
+ 	if ((rv & SCSI_RESET_ACTION) == SCSI_RESET_SUCCESS)
+ 		falcon_release_lock_if_possible(hostdata);
+ 
+-	return( rv );
++	return rv;
+ }
+ 
+-	
++
+ #ifdef CONFIG_ATARI_SCSI_RESET_BOOT
+ static void __init atari_scsi_reset_boot(void)
+ {
+ 	unsigned long end;
+-	
++
+ 	/*
+ 	 * Do a SCSI reset to clean up the bus during initialization. No messing
+ 	 * with the queues, interrupts, or locks necessary here.
+ 	 */
+ 
+-	printk( "Atari SCSI: resetting the SCSI bus..." );
++	printk("Atari SCSI: resetting the SCSI bus...");
+ 
+ 	/* get in phase */
+-	NCR5380_write( TARGET_COMMAND_REG,
+-		      PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
++	NCR5380_write(TARGET_COMMAND_REG,
++		      PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG)));
+ 
+ 	/* assert RST */
+-	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
++	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
+ 	/* The min. reset hold time is 25us, so 40us should be enough */
+-	udelay( 50 );
++	udelay(50);
+ 	/* reset RST and interrupt */
+-	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
+-	NCR5380_read( RESET_PARITY_INTERRUPT_REG );
++	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
++	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+ 
+ 	end = jiffies + AFTER_RESET_DELAY;
+ 	while (time_before(jiffies, end))
+ 		barrier();
+ 
+-	printk( " done\n" );
++	printk(" done\n");
+ }
+ #endif
+ 
+ 
+-const char * atari_scsi_info (struct Scsi_Host *host)
++const char *atari_scsi_info(struct Scsi_Host *host)
+ {
+ 	/* atari_scsi_detect() is verbose enough... */
+ 	static const char string[] = "Atari native SCSI";
+@@ -902,10 +895,10 @@ const char * atari_scsi_info (struct Scs
+ 
+ #if defined(REAL_DMA)
+ 
+-unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
+-				   unsigned long count, int dir )
++unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, void *data,
++				   unsigned long count, int dir)
+ {
+-	unsigned long addr = virt_to_phys( data );
++	unsigned long addr = virt_to_phys(data);
+ 
+ 	DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, "
+ 		   "dir = %d\n", instance->host_no, data, addr, count, dir);
+@@ -917,38 +910,37 @@ unsigned long atari_scsi_dma_setup( stru
+ 		 * wanted address.
+ 		 */
+ 		if (dir)
+-			memcpy( atari_dma_buffer, data, count );
++			memcpy(atari_dma_buffer, data, count);
+ 		else
+ 			atari_dma_orig_addr = data;
+ 		addr = atari_dma_phys_buffer;
+ 	}
+-	
++
+ 	atari_dma_startaddr = addr;	/* Needed for calculating residual later. */
+-  
++
+ 	/* Cache cleanup stuff: On writes, push any dirty cache out before sending
+ 	 * it to the peripheral. (Must be done before DMA setup, since at least
+ 	 * the ST-DMA begins to fill internal buffers right after setup. For
+ 	 * reads, invalidate any cache, may be altered after DMA without CPU
+ 	 * knowledge.
+-	 * 
++	 *
+ 	 * ++roman: For the Medusa, there's no need at all for that cache stuff,
+ 	 * because the hardware does bus snooping (fine!).
+ 	 */
+-	dma_cache_maintenance( addr, count, dir );
++	dma_cache_maintenance(addr, count, dir);
+ 
+ 	if (count == 0)
+ 		printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n");
+ 
+ 	if (IS_A_TT()) {
+ 		tt_scsi_dma.dma_ctrl = dir;
+-		SCSI_DMA_WRITE_P( dma_addr, addr );
+-		SCSI_DMA_WRITE_P( dma_cnt, count );
++		SCSI_DMA_WRITE_P(dma_addr, addr);
++		SCSI_DMA_WRITE_P(dma_cnt, count);
+ 		tt_scsi_dma.dma_ctrl = dir | 2;
+-	}
+-	else { /* ! IS_A_TT */
+-  
++	} else { /* ! IS_A_TT */
++
+ 		/* set address */
+-		SCSI_DMA_SETADR( addr );
++		SCSI_DMA_SETADR(addr);
+ 
+ 		/* toggle direction bit to clear FIFO and set DMA direction */
+ 		dir <<= 8;
+@@ -966,13 +958,13 @@ unsigned long atari_scsi_dma_setup( stru
+ 		atari_dma_active = 1;
+ 	}
+ 
+-	return( count );
++	return count;
+ }
+ 
+ 
+-static long atari_scsi_dma_residual( struct Scsi_Host *instance )
++static long atari_scsi_dma_residual(struct Scsi_Host *instance)
+ {
+-	return( atari_dma_residual );
++	return atari_dma_residual;
+ }
+ 
+ 
+@@ -980,13 +972,13 @@ static long atari_scsi_dma_residual( str
+ #define	CMD_SURELY_BYTE_MODE	1
+ #define	CMD_MODE_UNKNOWN		2
+ 
+-static int falcon_classify_cmd( Scsi_Cmnd *cmd )
++static int falcon_classify_cmd(Scsi_Cmnd *cmd)
+ {
+ 	unsigned char opcode = cmd->cmnd[0];
+-	
++
+ 	if (opcode == READ_DEFECT_DATA || opcode == READ_LONG ||
+-		opcode == READ_BUFFER)
+-		return( CMD_SURELY_BYTE_MODE );
++	    opcode == READ_BUFFER)
++		return CMD_SURELY_BYTE_MODE;
+ 	else if (opcode == READ_6 || opcode == READ_10 ||
+ 		 opcode == 0xa8 /* READ_12 */ || opcode == READ_REVERSE ||
+ 		 opcode == RECOVER_BUFFERED_DATA) {
+@@ -994,12 +986,11 @@ static int falcon_classify_cmd( Scsi_Cmn
+ 		 * needed here: The transfer is block-mode only if the 'fixed' bit is
+ 		 * set! */
+ 		if (cmd->device->type == TYPE_TAPE && !(cmd->cmnd[1] & 1))
+-			return( CMD_SURELY_BYTE_MODE );
++			return CMD_SURELY_BYTE_MODE;
+ 		else
+-			return( CMD_SURELY_BLOCK_MODE );
+-	}
+-	else
+-		return( CMD_MODE_UNKNOWN );
++			return CMD_SURELY_BLOCK_MODE;
++	} else
++		return CMD_MODE_UNKNOWN;
+ }
+ 
+ 
+@@ -1012,19 +1003,18 @@ static int falcon_classify_cmd( Scsi_Cmn
+  * the overrun problem, so this question is academic :-)
+  */
+ 
+-static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
+-					Scsi_Cmnd *cmd,
+-					int write_flag )
++static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
++					Scsi_Cmnd *cmd, int write_flag)
+ {
+ 	unsigned long	possible_len, limit;
+ #ifndef CONFIG_TT_DMA_EMUL
+ 	if (MACH_IS_HADES)
+ 		/* Hades has no SCSI DMA at all :-( Always force use of PIO */
+-		return( 0 );
+-#endif	
++		return 0;
++#endif
+ 	if (IS_A_TT())
+ 		/* TT SCSI DMA can transfer arbitrary #bytes */
+-		return( wanted_len );
++		return wanted_len;
+ 
+ 	/* ST DMA chip is stupid -- only multiples of 512 bytes! (and max.
+ 	 * 255*512 bytes, but this should be enough)
+@@ -1060,8 +1050,7 @@ static unsigned long atari_dma_xfer_len(
+ 		 * this).
+ 		 */
+ 		possible_len = wanted_len;
+-	}
+-	else {
++	} else {
+ 		/* Read operations: if the wanted transfer length is not a multiple of
+ 		 * 512, we cannot use DMA, since the ST-DMA cannot split transfers
+ 		 * (no interrupt on DMA finished!)
+@@ -1071,15 +1060,15 @@ static unsigned long atari_dma_xfer_len(
+ 		else {
+ 			/* Now classify the command (see above) and decide whether it is
+ 			 * allowed to do DMA at all */
+-			switch( falcon_classify_cmd( cmd )) {
+-			  case CMD_SURELY_BLOCK_MODE:
++			switch (falcon_classify_cmd(cmd)) {
++			case CMD_SURELY_BLOCK_MODE:
+ 				possible_len = wanted_len;
+ 				break;
+-			  case CMD_SURELY_BYTE_MODE:
++			case CMD_SURELY_BYTE_MODE:
+ 				possible_len = 0; /* DMA prohibited */
+ 				break;
+-			  case CMD_MODE_UNKNOWN:
+-			  default:
++			case CMD_MODE_UNKNOWN:
++			default:
+ 				/* For unknown commands assume block transfers if the transfer
+ 				 * size/allocation length is >= 1024 */
+ 				possible_len = (wanted_len < 1024) ? 0 : wanted_len;
+@@ -1087,9 +1076,9 @@ static unsigned long atari_dma_xfer_len(
+ 			}
+ 		}
+ 	}
+-	
++
+ 	/* Last step: apply the hard limit on DMA transfers */
+-	limit = (atari_dma_buffer && !STRAM_ADDR( virt_to_phys(cmd->SCp.ptr) )) ?
++	limit = (atari_dma_buffer && !STRAM_ADDR(virt_to_phys(cmd->SCp.ptr))) ?
+ 		    STRAM_BUFFER_SIZE : 255*512;
+ 	if (possible_len > limit)
+ 		possible_len = limit;
+@@ -1098,7 +1087,7 @@ static unsigned long atari_dma_xfer_len(
+ 		DMA_PRINTK("Sorry, must cut DMA transfer size to %ld bytes "
+ 			   "instead of %ld\n", possible_len, wanted_len);
+ 
+-	return( possible_len );
++	return possible_len;
+ }
+ 
+ 
+@@ -1112,23 +1101,23 @@ static unsigned long atari_dma_xfer_len(
+  * NCR5380_write call these functions via function pointers.
+  */
+ 
+-static unsigned char atari_scsi_tt_reg_read( unsigned char reg )
++static unsigned char atari_scsi_tt_reg_read(unsigned char reg)
+ {
+-	return( tt_scsi_regp[reg * 2] );
++	return tt_scsi_regp[reg * 2];
+ }
+ 
+-static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value )
++static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value)
+ {
+ 	tt_scsi_regp[reg * 2] = value;
+ }
+ 
+-static unsigned char atari_scsi_falcon_reg_read( unsigned char reg )
++static unsigned char atari_scsi_falcon_reg_read(unsigned char reg)
+ {
+ 	dma_wd.dma_mode_status= (u_short)(0x88 + reg);
+-	return( (u_char)dma_wd.fdc_acces_seccount );
++	return (u_char)dma_wd.fdc_acces_seccount;
+ }
+ 
+-static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value )
++static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value)
+ {
+ 	dma_wd.dma_mode_status = (u_short)(0x88 + reg);
+ 	dma_wd.fdc_acces_seccount = (u_short)value;

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari_NCR5380-work.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/atari_NCR5380-work.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,31 @@
+Cc: James E.J. Bottomley <James.Bottomley at SteelEye.com>,
+    linux-scsi at vger.kernel.org
+Subject: [PATCH] m68k: Atari SCSI workqueue updates
+
+Workqueue updates for the Atari SCSI driver
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/scsi/atari_NCR5380.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/scsi/atari_NCR5380.c
++++ linux-m68k-2.6.21/drivers/scsi/atari_NCR5380.c
+@@ -657,7 +657,7 @@ static inline void NCR5380_print_phase(s
+ #include <linux/interrupt.h>
+ 
+ static volatile int main_running;
+-static DECLARE_WORK(NCR5380_tqueue, (void (*)(void *))NCR5380_main, NULL);
++static DECLARE_WORK(NCR5380_tqueue, NCR5380_main);
+ 
+ static inline void queue_main(void)
+ {
+@@ -1075,7 +1075,7 @@ static int NCR5380_queue_command(Scsi_Cm
+  *  reenable them.  This prevents reentrancy and kernel stack overflow.
+  */
+ 
+-static void NCR5380_main(void *bl)
++static void NCR5380_main(struct work_struct *work)
+ {
+ 	Scsi_Cmnd *tmp, *prev;
+ 	struct Scsi_Host *instance = first_instance;

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/early-param.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/early-param.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,468 @@
+Subject: [PATCH] m68k: early parameter support
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+Add early parameter support and convert current users to it.
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/amiga/config.c |   41 ++++++++++++++++++++++-------------------
+ arch/m68k/atari/config.c |   17 +++++++++--------
+ arch/m68k/atari/debug.c  |   24 ++++++++++++++----------
+ arch/m68k/kernel/setup.c |   39 +--------------------------------------
+ arch/m68k/mac/config.c   |    8 --------
+ arch/m68k/mac/debug.c    |   20 ++++++++++----------
+ arch/m68k/q40/config.c   |   23 ++++++++++++++---------
+ arch/m68k/sun3x/prom.c   |   11 +++++++----
+ 8 files changed, 77 insertions(+), 106 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/amiga/config.c
++++ linux-m68k-2.6.21/arch/m68k/amiga/config.c
+@@ -79,8 +79,6 @@ static char *amiga_models[] __initdata =
+ 
+ static char amiga_model_name[13] = "Amiga ";
+ 
+-extern char m68k_debug_device[];
+-
+ static void amiga_sched_init(irq_handler_t handler);
+ /* amiga specific irq functions */
+ extern void amiga_init_IRQ(void);
+@@ -95,12 +93,10 @@ static unsigned int amiga_get_ss(void);
+ extern void amiga_mksound(unsigned int count, unsigned int ticks);
+ static void amiga_reset(void);
+ extern void amiga_init_sound(void);
+-static void amiga_savekmsg_init(void);
+ static void amiga_mem_console_write(struct console *co, const char *b,
+ 				    unsigned int count);
+ void amiga_serial_console_write(struct console *co, const char *s,
+ 				unsigned int count);
+-static void amiga_debug_init(void);
+ #ifdef CONFIG_HEARTBEAT
+ static void amiga_heartbeat(int on);
+ #endif
+@@ -370,7 +366,6 @@ void __init config_amiga(void)
+ {
+ 	int i;
+ 
+-	amiga_debug_init();
+ 	amiga_identify();
+ 
+ 	/* Yuk, we don't have PCI memory */
+@@ -458,17 +453,6 @@ void __init config_amiga(void)
+ 	/* initialize chipram allocator */
+ 	amiga_chip_init();
+ 
+-	/* debugging using chipram */
+-	if (!strcmp(m68k_debug_device, "mem")) {
+-		if (!AMIGAHW_PRESENT(CHIP_RAM))
+-			printk("Warning: no chipram present for debugging\n");
+-		else {
+-			amiga_savekmsg_init();
+-			amiga_console_driver.write = amiga_mem_console_write;
+-			register_console(&amiga_console_driver);
+-		}
+-	}
+-
+ 	/* our beloved beeper */
+ 	if (AMIGAHW_PRESENT(AMI_AUDIO))
+ 		amiga_init_sound();
+@@ -787,17 +771,33 @@ static void amiga_mem_console_write(stru
+ 	}
+ }
+ 
+-static void amiga_savekmsg_init(void)
++static int __init amiga_savekmsg_setup(char *arg)
+ {
+ 	static struct resource debug_res = { .name = "Debug" };
+ 
++	if (!MACH_IS_AMIGA || strcmp(arg, "mem"))
++		goto done;
++
++	if (!AMIGAHW_PRESENT(CHIP_RAM)) {
++		printk("Warning: no chipram present for debugging\n");
++		goto done;
++	}
++
+ 	savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
+ 	savekmsg->magic1 = SAVEKMSG_MAGIC1;
+ 	savekmsg->magic2 = SAVEKMSG_MAGIC2;
+ 	savekmsg->magicptr = ZTWO_PADDR(savekmsg);
+ 	savekmsg->size = 0;
++
++	amiga_console_driver.write = amiga_mem_console_write;
++	register_console(&amiga_console_driver);
++
++done:
++	return 0;
+ }
+ 
++early_param("debug", amiga_savekmsg_setup);
++
+ static void amiga_serial_putc(char c)
+ {
+ 	amiga_custom.serdat = (unsigned char)c | 0x100;
+@@ -872,15 +872,18 @@ void amiga_serial_gets(struct console *c
+ }
+ #endif
+ 
+-static void __init amiga_debug_init(void)
++static int __init amiga_debug_setup(char *arg)
+ {
+-	if (!strcmp(m68k_debug_device, "ser" )) {
++	if (MACH_IS_AMIGA && !strcmp(arg, "ser")) {
+ 		/* no initialization required (?) */
+ 		amiga_console_driver.write = amiga_serial_console_write;
+ 		register_console(&amiga_console_driver);
+ 	}
++	return 0;
+ }
+ 
++early_param("debug", amiga_debug_setup);
++
+ #ifdef CONFIG_HEARTBEAT
+ static void amiga_heartbeat(int on)
+ {
+--- linux-m68k-2.6.21.orig/arch/m68k/atari/config.c
++++ linux-m68k-2.6.21/arch/m68k/atari/config.c
+@@ -69,9 +69,6 @@ extern int atari_tt_hwclk (int, struct r
+ extern int atari_mste_set_clock_mmss (unsigned long);
+ extern int atari_tt_set_clock_mmss (unsigned long);
+ 
+-/* atari specific debug functions (in debug.c) */
+-extern void atari_debug_init(void);
+-
+ 
+ /* ++roman: This is a more elaborate test for an SCC chip, since the plain
+  * Medusa board generates DTACK at the SCC's standard addresses, but a SCC
+@@ -137,15 +134,18 @@ int __init atari_parse_bootinfo(const st
+ 
+ 
+ /* Parse the Atari-specific switches= option. */
+-void __init atari_switches_setup(const char *str, unsigned len)
++static int __init atari_switches_setup(char *str)
+ {
+-	char switches[len+1];
++	char switches[strlen(str) + 1];
+ 	char *p;
+ 	int ovsc_shift;
+ 	char *args = switches;
+ 
++	if (!MACH_IS_ATARI)
++		return 0;
++
+ 	/* copy string to local array, strsep works destructively... */
+-	strlcpy(switches, str, sizeof(switches));
++	strcpy(switches, str);
+ 	atari_switches = 0;
+ 
+ 	/* parse the options */
+@@ -170,8 +170,11 @@ void __init atari_switches_setup(const c
+ 			atari_switches |= ATARI_SWITCH_SND7 << ovsc_shift;
+ 		}
+ 	}
++	return 0;
+ }
+ 
++early_param("switches", atari_switches_setup);
++
+ 
+     /*
+      *  Setup the Atari configuration info
+@@ -183,8 +186,6 @@ void __init config_atari(void)
+ 
+ 	memset(&atari_hw_present, 0, sizeof(atari_hw_present));
+ 
+-	atari_debug_init();
+-
+ 	/* Change size of I/O space from 64KB to 4GB. */
+ 	ioport_resource.end  = 0xFFFFFFFF;
+ 
+--- linux-m68k-2.6.21.orig/arch/m68k/atari/debug.c
++++ linux-m68k-2.6.21/arch/m68k/atari/debug.c
+@@ -19,8 +19,6 @@
+ #include <asm/atarihw.h>
+ #include <asm/atariints.h>
+ 
+-extern char m68k_debug_device[];
+-
+ /* Flag that Modem1 port is already initialized and used */
+ int atari_MFP_init_done;
+ /* Flag that Modem1 port is already initialized and used */
+@@ -305,26 +303,28 @@ void atari_init_midi_port(int cflag)
+ 		     ACIA_RHTID : ACIA_RLTID);
+ }
+ 
+-void __init atari_debug_init(void)
++static int __init atari_debug_setup(char *arg)
+ {
+-	if (!strcmp(m68k_debug_device, "ser")) {
++	if (!MACH_IS_ATARI)
++		return 0;
++
++	if (!strcmp(arg, "ser"))
+ 		/* defaults to ser2 for a Falcon and ser1 otherwise */
+-		strcpy(m68k_debug_device, MACH_IS_FALCON ? "ser2" : "ser1");
+-	}
++		arg = MACH_IS_FALCON ? "ser2" : "ser1";
+ 
+-	if (!strcmp(m68k_debug_device, "ser1")) {
++	if (!strcmp(arg, "ser1")) {
+ 		/* ST-MFP Modem1 serial port */
+ 		atari_init_mfp_port(B9600|CS8);
+ 		atari_console_driver.write = atari_mfp_console_write;
+-	} else if (!strcmp(m68k_debug_device, "ser2")) {
++	} else if (!strcmp(arg, "ser2")) {
+ 		/* SCC Modem2 serial port */
+ 		atari_init_scc_port(B9600|CS8);
+ 		atari_console_driver.write = atari_scc_console_write;
+-	} else if (!strcmp(m68k_debug_device, "midi")) {
++	} else if (!strcmp(arg, "midi")) {
+ 		/* MIDI port */
+ 		atari_init_midi_port(B9600|CS8);
+ 		atari_console_driver.write = atari_midi_console_write;
+-	} else if (!strcmp(m68k_debug_device, "par")) {
++	} else if (!strcmp(arg, "par")) {
+ 		/* parallel printer */
+ 		atari_turnoff_irq(IRQ_MFP_BUSY); /* avoid ints */
+ 		sound_ym.rd_data_reg_sel = 7;	/* select mixer control */
+@@ -337,4 +337,8 @@ void __init atari_debug_init(void)
+ 	}
+ 	if (atari_console_driver.write)
+ 		register_console(&atari_console_driver);
++
++	return 0;
+ }
++
++early_param("debug", atari_debug_setup);
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/setup.c
++++ linux-m68k-2.6.21/arch/m68k/kernel/setup.c
+@@ -71,9 +71,6 @@ static struct mem_info m68k_ramdisk;
+ 
+ static char m68k_command_line[CL_SIZE];
+ 
+-char m68k_debug_device[6] = "";
+-EXPORT_SYMBOL(m68k_debug_device);
+-
+ void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
+ /* machine dependent irq functions */
+ void (*mach_init_IRQ) (void) __initdata = NULL;
+@@ -215,7 +212,6 @@ void __init setup_arch(char **cmdline_p)
+ 	unsigned long endmem, startmem;
+ #endif
+ 	int i;
+-	char *p, *q;
+ 
+ 	/* The bootinfo is located right after the kernel bss */
+ 	m68k_parse_bootinfo((const struct bi_record *)&_end);
+@@ -258,40 +254,7 @@ void __init setup_arch(char **cmdline_p)
+ 	*cmdline_p = m68k_command_line;
+ 	memcpy(boot_command_line, *cmdline_p, CL_SIZE);
+ 
+-	/* Parse the command line for arch-specific options.
+-	 * For the m68k, this is currently only "debug=xxx" to enable printing
+-	 * certain kernel messages to some machine-specific device.
+-	 */
+-	for (p = *cmdline_p; p && *p;) {
+-		i = 0;
+-		if (!strncmp(p, "debug=", 6)) {
+-			strlcpy(m68k_debug_device, p+6, sizeof(m68k_debug_device));
+-			q = strchr(m68k_debug_device, ' ');
+-			if (q)
+-				*q = 0;
+-			i = 1;
+-		}
+-#ifdef CONFIG_ATARI
+-		/* This option must be parsed very early */
+-		if (!strncmp(p, "switches=", 9)) {
+-			extern void atari_switches_setup(const char *, int);
+-			q = strchr(p + 9, ' ');
+-			atari_switches_setup(p + 9, q ? (q - (p + 9)) : strlen(p + 9));
+-			i = 1;
+-		}
+-#endif
+-
+-		if (i) {
+-			/* option processed, delete it */
+-			if ((q = strchr(p, ' ')))
+-				strcpy(p, q + 1);
+-			else
+-				*p = 0;
+-		} else {
+-			if ((p = strchr(p, ' ')))
+-				++p;
+-		}
+-	}
++	parse_early_param();
+ 
+ #ifdef CONFIG_DUMMY_CONSOLE
+ 	conswitchp = &dummy_con;
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/config.c
++++ linux-m68k-2.6.21/arch/m68k/mac/config.c
+@@ -82,10 +82,6 @@ extern void mac_mksound(unsigned int, un
+ 
+ extern void nubus_sweep_video(void);
+ 
+-/* Mac specific debug functions (in debug.c) */
+-extern void mac_debug_init(void);
+-extern void mac_debugging_long(int, long);
+-
+ static void mac_get_model(char *str);
+ 
+ static void mac_sched_init(irq_handler_t vector)
+@@ -180,9 +176,6 @@ void __init config_mac(void)
+ 	mach_halt = mac_poweroff;
+ 	mach_power_off = mac_poweroff;
+ 	mach_max_dma_address = 0xffffffff;
+-#if 0
+-	mach_debug_init	= mac_debug_init;
+-#endif
+ #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
+ 	mach_beep = mac_mksound;
+ #endif
+@@ -802,7 +795,6 @@ void mac_identify(void)
+ 	/* the serial ports set to "Faster" mode in MacOS. */
+ 
+ 	iop_preinit();
+-	mac_debug_init();
+ 
+ 	printk(KERN_INFO "Detected Macintosh model: %d \n", model);
+ 
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/debug.c
++++ linux-m68k-2.6.21/arch/m68k/mac/debug.c
+@@ -27,10 +27,6 @@
+ #include <asm/machw.h>
+ #include <asm/macints.h>
+ 
+-extern char m68k_debug_device[];
+-
+-extern struct compat_bootinfo compat_boot_info;
+-
+ extern unsigned long mac_videobase;
+ extern unsigned long mac_videodepth;
+ extern unsigned long mac_rowbytes;
+@@ -360,16 +356,18 @@ void mac_init_sccb_port(int cflag)
+ 	mac_init_scc_port(cflag, 1);
+ }
+ 
+-void __init mac_debug_init(void)
++static int __init mac_debug_setup(char *arg)
+ {
++	if (!MACH_IS_MAC)
++		return 0;
++
+ #ifdef DEBUG_SERIAL
+-	if (!strcmp(m68k_debug_device, "ser") ||
+-            !strcmp(m68k_debug_device, "ser1")) {
++	if (!strcmp(arg, "ser") || !strcmp(arg, "ser1")) {
+ 		/* Mac modem port */
+ 		mac_init_scc_port(B9600|CS8, 0);
+ 		mac_console_driver.write = mac_scca_console_write;
+ 		scc_port = 0;
+-	} else if (!strcmp(m68k_debug_device, "ser2")) {
++	} else if (!strcmp(arg, "ser2")) {
+ 		/* Mac printer port */
+ 		mac_init_scc_port(B9600|CS8, 1);
+ 		mac_console_driver.write = mac_sccb_console_write;
+@@ -377,12 +375,14 @@ void __init mac_debug_init(void)
+ 	}
+ #endif
+ #ifdef DEBUG_HEADS
+-	if (!strcmp(m68k_debug_device, "scn") ||
+-	    !strcmp(m68k_debug_device, "con")) {
++	if (!strcmp(arg, "scn") || !strcmp(arg, "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);
++	return 0;
+ }
++
++early_param("debug", mac_debug_setup);
+--- linux-m68k-2.6.21.orig/arch/m68k/q40/config.c
++++ linux-m68k-2.6.21/arch/m68k/q40/config.c
+@@ -54,7 +54,6 @@ void q40_set_vectors(void);
+ 
+ extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/);
+ 
+-extern char m68k_debug_device[];
+ static void q40_mem_console_write(struct console *co, const char *b,
+ 				  unsigned int count);
+ 
+@@ -62,6 +61,7 @@ extern int ql_ticks;
+ 
+ static struct console q40_console_driver = {
+ 	.name	= "debug",
++	.write	= q40_mem_console_write,
+ 	.flags	= CON_PRINTBUFFER,
+ 	.index	= -1,
+ };
+@@ -85,6 +85,19 @@ static void q40_mem_console_write(struct
+ 	}
+ }
+ 
++static int __init q40_debug_setup(char *arg)
++{
++	/* useful for early debugging stages - writes kernel messages into SRAM */
++	if (MACH_IS_Q40 && !strncmp(arg, "mem", 3)) {
++		/*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/
++		_cpleft = 2000 - ((long)q40_mem_cptr-0xff020000) / 4;
++		register_console(&q40_console_driver);
++	}
++	return 0;
++}
++
++early_param("debug", q40_debug_setup);
++
+ #if 0
+ void printq40(char *str)
+ {
+@@ -194,14 +207,6 @@ void __init config_q40(void)
+ 	 * all physical RAM fits into the boundary - otherwise
+ 	 * allocator may play costly and useless tricks */
+ 	mach_max_dma_address = 1024*1024*1024;
+-
+-	/* useful for early debugging stages - writes kernel messages into SRAM */
+-	if (!strncmp( m68k_debug_device,"mem", 3)) {
+-		/*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/
+-		_cpleft = 2000 - ((long)q40_mem_cptr-0xff020000) / 4;
+-		q40_console_driver.write = q40_mem_console_write;
+-		register_console(&q40_console_driver);
+-	}
+ }
+ 
+ 
+--- linux-m68k-2.6.21.orig/arch/m68k/sun3x/prom.c
++++ linux-m68k-2.6.21/arch/m68k/sun3x/prom.c
+@@ -73,8 +73,6 @@ void sun3x_reboot(void)
+ 	(*romvec->pv_reboot)("vmlinux");
+ }
+ 
+-extern char m68k_debug_device[];
+-
+ static void sun3x_prom_write(struct console *co, const char *s,
+                              unsigned int count)
+ {
+@@ -119,13 +117,18 @@ void sun3x_prom_init(void)
+ 	 * XXX this is futile since we restore the vbr first - oops
+ 	 */
+ 	vectors[VEC_TRAP14] = sun3x_prom_abort;
++}
+ 
++static int __init sun3x_debug_setup(char *arg)
++{
+ 	/* If debug=prom was specified, start the debug console */
+-
+-	if (!strcmp(m68k_debug_device, "prom"))
++	if (MACH_IS_SUN3X && !strcmp(arg, "prom"))
+ 		register_console(&sun3x_debug);
++	return 0;
+ }
+ 
++early_param("debug", sun3x_debug_setup);
++
+ /* some prom functions to export */
+ int prom_getintdefault(int node, char *property, int deflt)
+ {

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/ethernec-kill-ETHERNEC_USE_POLL.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/ethernec-kill-ETHERNEC_USE_POLL.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,76 @@
+---
+ drivers/net/atari_ethernec.c |   42 ------------------------------------------
+ 1 file changed, 42 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/net/atari_ethernec.c
++++ linux-m68k-2.6.21/drivers/net/atari_ethernec.c
+@@ -225,14 +225,6 @@ static wait_queue_head_t WaitQ;
+ 
+ static struct delayed_work tqueue;
+ 
+-#ifdef ETHERNEC_USE_POLL
+-static struct {
+-	struct work_struct poll_queue;
+-	struct timer_list poll_timer;
+-	struct net_device *dev;
+-} poll_ops;
+-#endif
+-
+ static struct net_device *poll_dev = NULL;
+ 
+ static void atari_ethernec_int(struct work_struct *work)
+@@ -260,22 +252,6 @@ static void atari_ethernec_int(struct wo
+ 		schedule_delayed_work(&tqueue, 0); /* reduced delay from 1 */
+ }
+ 
+-#ifdef ETHERNEC_USE_POLL
+-static void atari_ethernec_poll_handler(unsigned long dev_addr)
+-{
+-	struct net_device *dev = poll_dev;
+-
+-	if (!dev || !dev->poll_controller)
+-		return;
+-
+-	if (netif_running(dev))
+-		dev->poll_controller(dev);
+-
+-	schedule_work(&poll_ops.poll_queue);
+-	mod_timer(&poll_ops.poll_timer, jiffies + HZ / 100);
+-}
+-#endif
+-
+ static void atari_ethernec_start_poll(struct net_device *dev)
+ {
+ 	poll_dev = dev;
+@@ -284,19 +260,6 @@ static void atari_ethernec_start_poll(st
+ 
+ 	INIT_DELAYED_WORK(&tqueue, atari_ethernec_int);
+ 	schedule_delayed_work(&tqueue, 1);
+-#ifdef ETHERNEC_USE_POLL
+-	if (!poll_ops.poll_queue.func ||
+-	    poll_ops.poll_queue.func == ei_interrupt) {
+-		if (!poll_ops.poll_queue.func)
+-			INIT_WORK(&poll_ops.poll_queue, ei_interrupt, dev);
+-
+-		init_timer(&poll_ops.poll_timer);
+-		poll_ops.poll_timer.function = atari_ethernec_poll_handler;
+-		poll_ops.poll_timer.expires = jiffies + HZ / 5;
+-		poll_ops.poll_timer.data = (unsigned long)dev;
+-		add_timer(&poll_ops.poll_timer);
+-	}
+-#endif
+ }
+ 
+ static void atari_ethernec_stop_poll(struct net_device *dev)
+@@ -305,11 +268,6 @@ static void atari_ethernec_stop_poll(str
+ 
+ 	if (dev)
+ 		sleep_on(&WaitQ);
+-
+-#ifdef ETHERNEC_USE_POLL
+-	if (poll_ops.poll_queue.func == ei_interrupt)
+-		del_timer_sync(&poll_ops.poll_timer);
+-#endif
+ }
+ 
+ 

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/ethernec-work.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/ethernec-work.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,46 @@
+Subject: [PATCH] m68k: Atari EtherNEC workqueue updates
+
+Workqueue updates for the Atari EtherNEC driver
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/net/atari_ethernec.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/net/atari_ethernec.c
++++ linux-m68k-2.6.21/drivers/net/atari_ethernec.c
+@@ -96,6 +96,7 @@ static const char version2[] =
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/jiffies.h>
++#include <linux/workqueue.h>
+ 
+ #include <asm/system.h>
+ #include <asm/atarihw.h>
+@@ -222,7 +223,7 @@ static int use_poll;
+  */
+ static wait_queue_head_t WaitQ;
+ 
+-static struct work_struct tqueue;
++static struct delayed_work tqueue;
+ 
+ #ifdef ETHERNEC_USE_POLL
+ static struct {
+@@ -234,7 +235,7 @@ static struct {
+ 
+ static struct net_device *poll_dev = NULL;
+ 
+-static void atari_ethernec_int(unsigned long dev_addr)
++static void atari_ethernec_int(struct work_struct *work)
+ {
+ 	struct net_device *dev = poll_dev;
+ 
+@@ -281,7 +282,7 @@ static void atari_ethernec_start_poll(st
+ 
+ 	init_waitqueue_head(&WaitQ);
+ 
+-	INIT_WORK(&tqueue, (void (*)(void *))atari_ethernec_int, dev);
++	INIT_DELAYED_WORK(&tqueue, atari_ethernec_int);
+ 	schedule_delayed_work(&tqueue, 1);
+ #ifdef ETHERNEC_USE_POLL
+ 	if (!poll_ops.poll_queue.func ||

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/falconide_intr_lock-reentrant.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/falconide_intr_lock-reentrant.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,41 @@
+Subject: [PATCH] m68k: make Atari IDE lock reentrant
+
+From Roman Zippel <zippel at linux-m68k.org>
+
+Make the Atari IDE lock reentrant, as the new request is started in the
+interrupt before the last one is completely released.
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ include/asm-m68k/ide.h |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- linux-m68k-2.6.21.orig/include/asm-m68k/ide.h
++++ linux-m68k-2.6.21/include/asm-m68k/ide.h
+@@ -117,8 +117,8 @@ static __inline__ void ide_release_lock 
+ 			printk("ide_release_lock: bug\n");
+ 			return;
+ 		}
+-		falconide_intr_lock = 0;
+-		stdma_release();
++		if (!--falconide_intr_lock)
++			stdma_release();
+ 	}
+ }
+ 
+@@ -126,12 +126,12 @@ static __inline__ void
+ ide_get_lock(irq_handler_t handler, void *data)
+ {
+ 	if (MACH_IS_ATARI) {
+-		if (falconide_intr_lock == 0) {
++		if (!falconide_intr_lock) {
+ 			if (in_interrupt() > 0)
+ 				panic( "Falcon IDE hasn't ST-DMA lock in interrupt" );
+ 			stdma_lock(handler, data);
+-			falconide_intr_lock = 1;
+ 		}
++		falconide_intr_lock++;
+ 	}
+ }
+ #endif /* CONFIG_BLK_DEV_FALCON_IDE */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/hilkbd-warning.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/hilkbd-warning.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,21 @@
+Cc: parisc-linux at parisc-linux.org
+Subject: [PATCH] hilkbd: Kill compiler warning and fix comment dyslexia
+
+hilkbd: Kill compiler warning and fix comment dyslexia
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/input/keyboard/hilkbd.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-m68k-2.6.21.orig/drivers/input/keyboard/hilkbd.c
++++ linux-m68k-2.6.21/drivers/input/keyboard/hilkbd.c
+@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL v2");
+ 
+ #elif defined(CONFIG_HP300)
+ 
+- #define HILBASE		0xf0428000 /* HP300 (m86k) port address */
++ #define HILBASE		0xf0428000UL /* HP300 (m68k) port address */
+  #define HIL_DATA		0x1
+  #define HIL_CMD		0x3
+  #define HIL_IRQ		2

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/irq_lockdep.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/irq_lockdep.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,30 @@
+Subject: [PATCH] lockdep: Add missing disable/enable irq variant
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+Add missing disable/enable irq variant
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ include/linux/interrupt.h |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- linux-m68k-2.6.21.orig/include/linux/interrupt.h
++++ linux-m68k-2.6.21/include/linux/interrupt.h
+@@ -185,10 +185,14 @@ static inline int disable_irq_wake(unsig
+  * validator need to define the methods below in their asm/irq.h
+  * files, under an #ifdef CONFIG_LOCKDEP section.
+  */
+-# ifndef CONFIG_LOCKDEP
++#ifndef CONFIG_LOCKDEP
+ #  define disable_irq_nosync_lockdep(irq)	disable_irq_nosync(irq)
++#  define disable_irq_nosync_lockdep_irqsave(irq, flags) \
++						disable_irq_nosync(irq)
+ #  define disable_irq_lockdep(irq)		disable_irq(irq)
+ #  define enable_irq_lockdep(irq)		enable_irq(irq)
++#  define enable_irq_lockdep_irqrestore(irq, flags) \
++						enable_irq(irq)
+ # endif
+ 
+ #endif /* CONFIG_GENERIC_HARDIRQS */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/kmap_atomic-inline.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/kmap_atomic-inline.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,30 @@
+Subject: [PATCH] Convert non-highmem kmap_atomic() to static inline function
+
+Convert kmap_atomic() in the non-highmem case from a macro to a static
+inline function, for better type-checking and the ability to pass void
+pointers instead of struct page pointers.
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ include/linux/highmem.h |   10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- linux-m68k-2.6.21.orig/include/linux/highmem.h
++++ linux-m68k-2.6.21/include/linux/highmem.h
+@@ -42,8 +42,14 @@ static inline void *kmap(struct page *pa
+ 
+ #define kunmap(page) do { (void) (page); } while (0)
+ 
+-#define kmap_atomic(page, idx) \
+-	({ pagefault_disable(); page_address(page); })
++#include <asm/kmap_types.h>
++
++static inline void *kmap_atomic(struct page *page, enum km_type idx)
++{
++	pagefault_disable();
++	return page_address(page);
++}
++
+ #define kunmap_atomic(addr, idx)	do { pagefault_enable(); } while (0)
+ #define kmap_atomic_pfn(pfn, idx)	kmap_atomic(pfn_to_page(pfn), (idx))
+ #define kmap_atomic_to_page(ptr)	virt_to_page(ptr)

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-53c700-scsi.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-53c700-scsi.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,1155 @@
+From jongk at linux-m68k.org Tue Oct 31 22:46:33 2006
+Date: Tue, 31 Oct 2006 22:47:04 +0100
+From: Kars de Jong <jongk at linux-m68k.org>
+To: Christoph Hellwig <hch at infradead.org>
+Cc: Richard Hirst <rhirst at levanta.com>, Matthew Wilcox <matthew at wil.cx>, linux-scsi at vger.kernel.org, linux-m68k at vger.kernel.org, Geert Uytterhoeven <geert at linux-m68k.org>
+Subject: [RFC PATCH] m68k: switch to 53c700 driver
+
+On ma, 2006-10-30 at 11:13 +0000, Christoph Hellwig wrote:
+> Any updates?  Honestly, I do not plan to touch the current 53c7xx/etc
+> mess in the upoming request_buffer transition, and unless the m68k
+> folks provide the new 53c700-based driver I'll just submit a patch to
+> rip 53c7xx and users out without replacement.
+
+OK, here's the patch, without the m68k generic iomap changes.
+
+If there are no objections, I will commit it to our CVS repository so
+Geert can send it upstream (with proper Signed-Off-By: headers and
+everything).
+
+Kars.
+
+---
+ arch/m68k/configs/amiga_defconfig    |    2 
+ arch/m68k/configs/bvme6000_defconfig |    2 
+ arch/m68k/configs/mvme16x_defconfig  |    2 
+ arch/m68k/defconfig                  |    2 
+ drivers/scsi/53c700.c                |   20 +-
+ drivers/scsi/53c700.h                |    5 
+ drivers/scsi/Kconfig                 |   26 +-
+ drivers/scsi/Makefile                |   15 -
+ drivers/scsi/amiga7xx.c              |  344 +++++++++++++++++++++++++----------
+ drivers/scsi/amiga7xx.h              |   23 --
+ drivers/scsi/bvme6000.h              |   24 --
+ drivers/scsi/bvme6000_scsi.c         |  158 ++++++++++------
+ drivers/scsi/mvme16x.h               |   24 --
+ drivers/scsi/mvme16x_scsi.c          |  183 +++++++++++++-----
+ 14 files changed, 525 insertions(+), 305 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/configs/amiga_defconfig
++++ linux-m68k-2.6.21/arch/m68k/configs/amiga_defconfig
+@@ -249,7 +249,9 @@ CONFIG_CYBERSTORMII_SCSI=y
+ CONFIG_BLZ2060_SCSI=y
+ CONFIG_BLZ1230_SCSI=y
+ CONFIG_FASTLANE_SCSI=y
++CONFIG_SCSI_AMIGA7XX=y
+ CONFIG_OKTAGON_SCSI=y
++CONFIG_SCSI_NCR53C7xx_FAST=y
+ 
+ #
+ # Old CD-ROM drivers (not SCSI, not IDE)
+--- linux-m68k-2.6.21.orig/arch/m68k/configs/bvme6000_defconfig
++++ linux-m68k-2.6.21/arch/m68k/configs/bvme6000_defconfig
+@@ -185,6 +185,8 @@ CONFIG_SCSI_CONSTANTS=y
+ #
+ # CONFIG_SCSI_SATA is not set
+ # CONFIG_SCSI_DEBUG is not set
++CONFIG_BVME6000_SCSI=y
++CONFIG_SCSI_NCR53C7xx_FAST=y
+ 
+ #
+ # Multi-device support (RAID and LVM)
+--- linux-m68k-2.6.21.orig/arch/m68k/configs/mvme16x_defconfig
++++ linux-m68k-2.6.21/arch/m68k/configs/mvme16x_defconfig
+@@ -185,6 +185,8 @@ CONFIG_SCSI_CONSTANTS=y
+ #
+ # CONFIG_SCSI_SATA is not set
+ # CONFIG_SCSI_DEBUG is not set
++CONFIG_MVME16x_SCSI=y
++CONFIG_SCSI_NCR53C7xx_FAST=y
+ 
+ #
+ # Multi-device support (RAID and LVM)
+--- linux-m68k-2.6.21.orig/arch/m68k/defconfig
++++ linux-m68k-2.6.21/arch/m68k/defconfig
+@@ -186,7 +186,9 @@ CONFIG_GVP11_SCSI=y
+ # CONFIG_BLZ2060_SCSI is not set
+ # CONFIG_BLZ1230_SCSI is not set
+ # CONFIG_FASTLANE_SCSI is not set
++CONFIG_SCSI_AMIGA7XX=y
+ # CONFIG_OKTAGON_SCSI is not set
++CONFIG_SCSI_NCR53C7xx_FAST=y
+ 
+ #
+ # Multi-device support (RAID and LVM)
+--- linux-m68k-2.6.21.orig/drivers/scsi/53c700.c
++++ linux-m68k-2.6.21/drivers/scsi/53c700.c
+@@ -661,7 +661,6 @@ NCR_700_chip_setup(struct Scsi_Host *hos
+ {
+ 	struct NCR_700_Host_Parameters *hostdata = 
+ 		(struct NCR_700_Host_Parameters *)host->hostdata[0];
+-	__u32 dcntl_extra = 0;
+ 	__u8 min_period;
+ 	__u8 min_xferp = (hostdata->chip710 ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP);
+ 
+@@ -686,13 +685,14 @@ NCR_700_chip_setup(struct Scsi_Host *hos
+ 			        burst_disable = BURST_DISABLE;
+ 			        break;
+ 		}
+-		dcntl_extra = COMPAT_700_MODE;
++		hostdata->dcntl_extra |= COMPAT_700_MODE;
+ 
+-		NCR_700_writeb(dcntl_extra, host, DCNTL_REG);
++		NCR_700_writeb(hostdata->dcntl_extra, host, DCNTL_REG);
+ 		NCR_700_writeb(burst_length | hostdata->dmode_extra,
+ 			       host, DMODE_710_REG);
+-		NCR_700_writeb(burst_disable | (hostdata->differential ? 
+-						DIFF : 0), host, CTEST7_REG);
++		NCR_700_writeb(burst_disable | hostdata->ctest7_extra |
++			       (hostdata->differential ? DIFF : 0),
++			       host, CTEST7_REG);
+ 		NCR_700_writeb(BTB_TIMER_DISABLE, host, CTEST0_REG);
+ 		NCR_700_writeb(FULL_ARBITRATION | ENABLE_PARITY | PARITY
+ 			       | AUTO_ATN, host, SCNTL0_REG);
+@@ -727,13 +727,13 @@ NCR_700_chip_setup(struct Scsi_Host *hos
+ 		 * of spec: sync divider 2, async divider 3 */
+ 		DEBUG(("53c700: sync 2 async 3\n"));
+ 		NCR_700_writeb(SYNC_DIV_2_0, host, SBCL_REG);
+-		NCR_700_writeb(ASYNC_DIV_3_0 | dcntl_extra, host, DCNTL_REG);
++		NCR_700_writeb(ASYNC_DIV_3_0 | hostdata->dcntl_extra, host, DCNTL_REG);
+ 		hostdata->sync_clock = hostdata->clock/2;
+ 	} else	if(hostdata->clock > 50  && hostdata->clock <= 75) {
+ 		/* sync divider 1.5, async divider 3 */
+ 		DEBUG(("53c700: sync 1.5 async 3\n"));
+ 		NCR_700_writeb(SYNC_DIV_1_5, host, SBCL_REG);
+-		NCR_700_writeb(ASYNC_DIV_3_0 | dcntl_extra, host, DCNTL_REG);
++		NCR_700_writeb(ASYNC_DIV_3_0 | hostdata->dcntl_extra, host, DCNTL_REG);
+ 		hostdata->sync_clock = hostdata->clock*2;
+ 		hostdata->sync_clock /= 3;
+ 		
+@@ -741,18 +741,18 @@ NCR_700_chip_setup(struct Scsi_Host *hos
+ 		/* sync divider 1, async divider 2 */
+ 		DEBUG(("53c700: sync 1 async 2\n"));
+ 		NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
+-		NCR_700_writeb(ASYNC_DIV_2_0 | dcntl_extra, host, DCNTL_REG);
++		NCR_700_writeb(ASYNC_DIV_2_0 | hostdata->dcntl_extra, host, DCNTL_REG);
+ 		hostdata->sync_clock = hostdata->clock;
+ 	} else if(hostdata->clock > 25 && hostdata->clock <=37) {
+ 		/* sync divider 1, async divider 1.5 */
+ 		DEBUG(("53c700: sync 1 async 1.5\n"));
+ 		NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
+-		NCR_700_writeb(ASYNC_DIV_1_5 | dcntl_extra, host, DCNTL_REG);
++		NCR_700_writeb(ASYNC_DIV_1_5 | hostdata->dcntl_extra, host, DCNTL_REG);
+ 		hostdata->sync_clock = hostdata->clock;
+ 	} else {
+ 		DEBUG(("53c700: sync 1 async 1\n"));
+ 		NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
+-		NCR_700_writeb(ASYNC_DIV_1_0 | dcntl_extra, host, DCNTL_REG);
++		NCR_700_writeb(ASYNC_DIV_1_0 | hostdata->dcntl_extra, host, DCNTL_REG);
+ 		/* sync divider 1, async divider 1 */
+ 		hostdata->sync_clock = hostdata->clock;
+ 	}
+--- linux-m68k-2.6.21.orig/drivers/scsi/53c700.h
++++ linux-m68k-2.6.21/drivers/scsi/53c700.h
+@@ -177,6 +177,7 @@ struct NCR_700_command_slot {
+ 	__u8	state;
+ 	#define NCR_700_FLAG_AUTOSENSE	0x01
+ 	__u8	flags;
++	__u8	pad1[2];	/* Needed for m68k where min alignment is 2 bytes */
+ 	int	tag;
+ 	__u32	resume_offset;
+ 	struct scsi_cmnd *cmnd;
+@@ -196,6 +197,8 @@ struct NCR_700_Host_Parameters {
+ 	void __iomem	*base;		/* the base for the port (copied to host) */
+ 	struct device	*dev;
+ 	__u32	dmode_extra;	/* adjustable bus settings */
++	__u32	dcntl_extra;	/* adjustable bus settings */
++	__u32	ctest7_extra;	/* adjustable bus settings */
+ 	__u32	differential:1;	/* if we are differential */
+ #ifdef CONFIG_53C700_LE_ON_BE
+ 	/* This option is for HP only.  Set it if your chip is wired for
+@@ -352,6 +355,7 @@ struct NCR_700_Host_Parameters {
+ #define		SEL_TIMEOUT_DISABLE	0x10 /* 710 only */
+ #define         DFP                     0x08
+ #define         EVP                     0x04
++#define         CTEST7_TT1              0x02
+ #define		DIFF			0x01
+ #define CTEST6_REG                      0x1A
+ #define	TEMP_REG			0x1C
+@@ -385,6 +389,7 @@ struct NCR_700_Host_Parameters {
+ #define		SOFTWARE_RESET		0x01
+ #define		COMPAT_700_MODE		0x01
+ #define 	SCRPTS_16BITS		0x20
++#define		EA_710			0x20
+ #define		ASYNC_DIV_2_0		0x00
+ #define		ASYNC_DIV_1_5		0x40
+ #define		ASYNC_DIV_1_0		0x80
+--- linux-m68k-2.6.21.orig/drivers/scsi/Kconfig
++++ linux-m68k-2.6.21/drivers/scsi/Kconfig
+@@ -1000,6 +1000,11 @@ config SCSI_STEX
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called stex.
+ 
++config 53C700_BE_BUS
++	bool
++	depends on SCSI_AMIGA7XX || MVME16x_SCSI || BVME6000_SCSI
++	default y
++
+ config SCSI_SYM53C8XX_2
+ 	tristate "SYM53C8XX Version 2 SCSI support"
+ 	depends on PCI && SCSI
+@@ -1620,8 +1625,9 @@ config FASTLANE_SCSI
+ 	  one in the near future, say Y to this question. Otherwise, say N.
+ 
+ config SCSI_AMIGA7XX
+-	bool "Amiga NCR53c710 SCSI support (EXPERIMENTAL)"
+-	depends on AMIGA && SCSI && EXPERIMENTAL && BROKEN
++	tristate "Amiga NCR53c710 SCSI support (EXPERIMENTAL)"
++	depends on AMIGA && SCSI && EXPERIMENTAL
++	select SCSI_SPI_ATTRS
+ 	help
+ 	  Support for various NCR53c710-based SCSI controllers on the Amiga.
+ 	  This includes:
+@@ -1720,8 +1726,8 @@ config MVME147_SCSI
+ 	  single-board computer.
+ 
+ config MVME16x_SCSI
+-	bool "NCR53C710 SCSI driver for MVME16x"
+-	depends on MVME16x && SCSI && BROKEN
++	tristate "NCR53C710 SCSI driver for MVME16x"
++	depends on MVME16x && SCSI
+ 	select SCSI_SPI_ATTRS
+ 	help
+ 	  The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710
+@@ -1729,22 +1735,14 @@ config MVME16x_SCSI
+ 	  will want to say Y to this question.
+ 
+ config BVME6000_SCSI
+-	bool "NCR53C710 SCSI driver for BVME6000"
+-	depends on BVME6000 && SCSI && BROKEN
++	tristate "NCR53C710 SCSI driver for BVME6000"
++	depends on BVME6000 && SCSI
+ 	select SCSI_SPI_ATTRS
+ 	help
+ 	  The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710
+ 	  SCSI controller chip.  Almost everyone using one of these boards
+ 	  will want to say Y to this question.
+ 
+-config SCSI_NCR53C7xx_FAST
+-	bool "allow FAST-SCSI [10MHz]"
+-	depends on SCSI_AMIGA7XX || MVME16x_SCSI || BVME6000_SCSI
+-	help
+-	  This will enable 10MHz FAST-SCSI transfers with your host
+-	  adapter. Some systems have problems with that speed, so it's safest
+-	  to say N here.
+-
+ config SUN3_SCSI
+ 	tristate "Sun3 NCR5380 SCSI"
+ 	depends on SUN3 && SCSI
+--- linux-m68k-2.6.21.orig/drivers/scsi/Makefile
++++ linux-m68k-2.6.21/drivers/scsi/Makefile
+@@ -37,7 +37,7 @@ obj-$(CONFIG_SCSI_SAS_LIBSAS)	+= libsas/
+ 
+ obj-$(CONFIG_ISCSI_TCP) 	+= libiscsi.o	iscsi_tcp.o
+ obj-$(CONFIG_INFINIBAND_ISER) 	+= libiscsi.o
+-obj-$(CONFIG_SCSI_AMIGA7XX)	+= amiga7xx.o	53c7xx.o
++obj-$(CONFIG_SCSI_AMIGA7XX)	+= 53c700.o	amiga7xx.o
+ obj-$(CONFIG_A3000_SCSI)	+= a3000.o	wd33c93.o
+ obj-$(CONFIG_A2091_SCSI)	+= a2091.o	wd33c93.o
+ obj-$(CONFIG_GVP11_SCSI)	+= gvp11.o	wd33c93.o
+@@ -53,8 +53,8 @@ obj-$(CONFIG_ATARI_SCSI)	+= atari_scsi.o
+ obj-$(CONFIG_MAC_SCSI)		+= mac_scsi.o
+ obj-$(CONFIG_SCSI_MAC_ESP)	+= mac_esp.o	NCR53C9x.o
+ obj-$(CONFIG_SUN3_SCSI)		+= sun3_scsi.o  sun3_scsi_vme.o
+-obj-$(CONFIG_MVME16x_SCSI)	+= mvme16x_scsi.o	53c7xx.o
+-obj-$(CONFIG_BVME6000_SCSI)	+= bvme6000_scsi.o	53c7xx.o
++obj-$(CONFIG_MVME16x_SCSI)	+= 53c700.o	mvme16x_scsi.o
++obj-$(CONFIG_BVME6000_SCSI)	+= 53c700.o	bvme6000_scsi.o
+ obj-$(CONFIG_SCSI_SIM710)	+= 53c700.o	sim710.o
+ obj-$(CONFIG_SCSI_ADVANSYS)	+= advansys.o
+ obj-$(CONFIG_SCSI_PSI240I)	+= psi240i.o
+@@ -168,10 +168,8 @@ NCR_Q720_mod-objs	:= NCR_Q720.o ncr53c8x
+ oktagon_esp_mod-objs	:= oktagon_esp.o oktagon_io.o
+ 
+ # Files generated that shall be removed upon make clean
+-clean-files :=	53c7xx_d.h 53c700_d.h	\
+-		53c7xx_u.h 53c700_u.h
++clean-files :=	53c700_d.h 53c700_u.h
+ 
+-$(obj)/53c7xx.o:   $(obj)/53c7xx_d.h $(obj)/53c7xx_u.h
+ $(obj)/53c700.o $(MODVERDIR)/$(obj)/53c700.ver: $(obj)/53c700_d.h
+ 
+ # If you want to play with the firmware, uncomment
+@@ -179,11 +177,6 @@ $(obj)/53c700.o $(MODVERDIR)/$(obj)/53c7
+ 
+ ifdef GENERATE_FIRMWARE
+ 
+-$(obj)/53c7xx_d.h: $(src)/53c7xx.scr $(src)/script_asm.pl
+-	$(CPP) -traditional -DCHIP=710 - < $< | grep -v '^#' | $(PERL) -s $(src)/script_asm.pl -ncr7x0_family $@ $(@:_d.h=_u.h)
+-
+-$(obj)/53c7xx_u.h: $(obj)/53c7xx_d.h
+-
+ $(obj)/53c700_d.h: $(src)/53c700.scr $(src)/script_asm.pl
+ 	$(PERL) -s $(src)/script_asm.pl -ncr7x0_family $@ $(@:_d.h=_u.h) < $<
+ 
+--- linux-m68k-2.6.21.orig/drivers/scsi/amiga7xx.c
++++ linux-m68k-2.6.21/drivers/scsi/amiga7xx.c
+@@ -6,133 +6,287 @@
+  *
+  * Written 1997 by Alan Hourihane <alanh at fairlite.demon.co.uk>
+  * plus modifications of the 53c7xx.c driver to support the Amiga.
++ *
++ * Rewritten to use 53c700.c by Kars de Jong <jongk at linux-m68k.org>
+  */
+-#include <linux/types.h>
+-#include <linux/mm.h>
++
++#include <linux/module.h>
+ #include <linux/blkdev.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
+ #include <linux/zorro.h>
+-#include <linux/stat.h>
+-
+-#include <asm/setup.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/amigaints.h>
+ #include <asm/amigahw.h>
+-#include <asm/dma.h>
+-#include <asm/irq.h>
+-
+-#include "scsi.h"
++#include <asm/amigaints.h>
+ #include <scsi/scsi_host.h>
+-#include "53c7xx.h"
+-#include "amiga7xx.h"
++#include <scsi/scsi_device.h>
++#include <scsi/scsi_transport.h>
++#include <scsi/scsi_transport_spi.h>
++
++#include "53c700.h"
++
++MODULE_AUTHOR("Alan Hourihane <alanh at fairlite.demon.co.uk> / Kars de Jong <jongk at linux-m68k.org>");
++MODULE_DESCRIPTION("Amiga NCR53C710 driver");
++MODULE_LICENSE("GPL");
++
++static struct scsi_host_template amiga7xx_scsi_driver_template = {
++	.name		= "A4000T builtin SCSI",
++	.proc_name	= "Amiga7xx",
++	.this_id	= 7,
++	.module		= THIS_MODULE,
++};
++
++static struct platform_device *a4000t_scsi_device;
++
++#ifdef CONFIG_ZORRO
++
++static struct zorro_driver_data {
++	const char *name;
++	unsigned long offset;
++	int absolute;	/* offset is absolute address */
++} amiga7xx_driver_data[] __devinitdata = {
++	{ .name = "PowerUP 603e+", .offset = 0xf40000, .absolute = 1 },
++	{ .name = "WarpEngine 40xx", .offset = 0x40000 },
++	{ .name = "A4091", .offset = 0x800000 },
++	{ .name = "GForce 040/060", .offset = 0x40000 },
++	{ 0 }
++};
+ 
++static struct zorro_device_id amiga7xx_zorro_tbl[] __devinitdata = {
++	{
++		.id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS,
++		.driver_data = (unsigned long)&amiga7xx_driver_data[0],
++	},
++	{
++		.id = ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx,
++		.driver_data = (unsigned long)&amiga7xx_driver_data[1],
++	},
++	{
++		.id = ZORRO_PROD_CBM_A4091_1,
++		.driver_data = (unsigned long)&amiga7xx_driver_data[2],
++	},
++	{
++		.id = ZORRO_PROD_CBM_A4091_2,
++		.driver_data = (unsigned long)&amiga7xx_driver_data[2],
++	},
++	{
++		.id = ZORRO_PROD_GVP_GFORCE_040_060,
++		.driver_data = (unsigned long)&amiga7xx_driver_data[3],
++	},
++	{ 0 }
++};
+ 
+-static int amiga7xx_register_one(struct scsi_host_template *tpnt,
+-				 unsigned long address)
++static int __devinit amiga7xx_init_one(struct zorro_dev *z,
++				   const struct zorro_device_id *ent)
+ {
+-    long long options;
+-    int clock;
++	struct Scsi_Host * host = NULL;
++	struct NCR_700_Host_Parameters *hostdata;
++	struct zorro_driver_data *zdd;
++	unsigned long board, ioaddr;
++
++	board = zorro_resource_start(z);
++	zdd = (struct zorro_driver_data *)ent->driver_data;
++
++	if (zdd->absolute) {
++		ioaddr = zdd->offset;
++	} else {
++		ioaddr = board + zdd->offset;
++	}
++
++	if (!zorro_request_device(z, zdd->name)) {
++		printk(KERN_ERR "amiga7xx: cannot reserve region 0x%lx, abort\n",
++		       board);
++		return -EBUSY;
++	}
++
++	hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
++
++	if (hostdata == NULL) {
++		printk(KERN_ERR "amiga7xx: Failed to allocate host data\n");
++		goto out_release;
++	}
++
++	memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
++
++	/* Fill in the required pieces of hostdata */
++	if (ioaddr > 0x01000000)
++		hostdata->base = ioremap(ioaddr, zorro_resource_len(z));
++	else
++		hostdata->base = (void __iomem *)ZTWO_VADDR(ioaddr);
+ 
+-    if (!request_mem_region(address, 0x1000, "ncr53c710"))
+-	return 0;
++	hostdata->clock = 50;
++	hostdata->chip710 = 1;
+ 
+-    address = (unsigned long)z_ioremap(address, 0x1000);
+-    options = OPTION_MEMORY_MAPPED | OPTION_DEBUG_TEST1 | OPTION_INTFLY |
+-	      OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS |
+-	      OPTION_DISCONNECT;
+-    clock = 50000000;	/* 50 MHz SCSI Clock */
+-    ncr53c7xx_init(tpnt, 0, 710, address, 0, IRQ_AMIGA_PORTS, DMA_NONE,
+-		   options, clock);
+-    return 1;
+-}
++	/* Settings for at least WarpEngine 40xx */
++	hostdata->ctest7_extra = CTEST7_TT1;
+ 
++	amiga7xx_scsi_driver_template.name = zdd->name;
+ 
+-#ifdef CONFIG_ZORRO
++	/* and register the chip */
++	if ((host = NCR_700_detect(&amiga7xx_scsi_driver_template, hostdata, &z->dev))
++	   == NULL) {
++		printk(KERN_ERR "amiga7xx-scsi: No host detected; board configuration problem?\n");
++		goto out_free;
++	}
+ 
+-static struct {
+-    zorro_id id;
+-    unsigned long offset;
+-    int absolute;	/* offset is absolute address */
+-} amiga7xx_table[] = {
+-    { .id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS, .offset = 0xf40000,
+-      .absolute = 1 },
+-    { .id = ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx, .offset = 0x40000 },
+-    { .id = ZORRO_PROD_CBM_A4091_1, .offset = 0x800000 },
+-    { .id = ZORRO_PROD_CBM_A4091_2, .offset = 0x800000 },
+-    { .id = ZORRO_PROD_GVP_GFORCE_040_060, .offset = 0x40000 },
+-    { 0 }
+-};
++	host->this_id = 7;
++	host->base = ioaddr;
++	host->irq = IRQ_AMIGA_PORTS;
++
++	if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "amiga7xx-scsi", host)) {
++		printk(KERN_ERR "amiga7xx-scsi: request_irq failed\n");
++		goto out_put_host;
++	}
++
++	scsi_scan_host(host);
++
++	return 0;
++
++ out_put_host:
++	scsi_host_put(host);
++ out_free:
++	if (ioaddr > 0x01000000)
++		iounmap(hostdata->base);
++	kfree(hostdata);
++ out_release:
++	zorro_release_device(z);
++
++	return -ENODEV;
++}
+ 
+-static int __init amiga7xx_zorro_detect(struct scsi_host_template *tpnt)
++static __devexit void amiga7xx_remove_one(struct zorro_dev *z)
+ {
+-    int num = 0, i;
+-    struct zorro_dev *z = NULL;
+-    unsigned long address;
+-
+-    while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
+-	for (i = 0; amiga7xx_table[i].id; i++)
+-	    if (z->id == amiga7xx_table[i].id)
+-		break;
+-	if (!amiga7xx_table[i].id)
+-	    continue;
+-	if (amiga7xx_table[i].absolute)
+-	    address = amiga7xx_table[i].offset;
+-	else
+-	    address = z->resource.start + amiga7xx_table[i].offset;
+-	num += amiga7xx_register_one(tpnt, address);
+-    }
+-    return num;
++	struct Scsi_Host *host = dev_to_shost(&z->dev);
++	struct NCR_700_Host_Parameters *hostdata =
++		(struct NCR_700_Host_Parameters *)host->hostdata[0];
++
++	scsi_remove_host(host);
++
++	NCR_700_release(host);
++	kfree(hostdata);
++	free_irq(host->irq, host);
++	zorro_release_device(z);
+ }
+ 
++static struct zorro_driver amiga7xx_driver = {
++	.name	  = "amiga7xx-scsi",
++	.id_table = amiga7xx_zorro_tbl,
++	.probe	  = amiga7xx_init_one,
++	.remove	  = __devexit_p(amiga7xx_remove_one),
++};
++
+ #endif /* CONFIG_ZORRO */
+ 
++#define A4000T_SCSI_ADDR 0xdd0040
+ 
+-int __init amiga7xx_detect(struct scsi_host_template *tpnt)
++static int __devinit a4000t_probe(struct device *dev)
+ {
+-    static unsigned char called = 0;
+-    int num = 0;
++	struct Scsi_Host * host = NULL;
++	struct NCR_700_Host_Parameters *hostdata;
+ 
+-    if (called || !MACH_IS_AMIGA)
+-	return 0;
++	if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI)))
++		goto out;
+ 
+-    tpnt->proc_name = "Amiga7xx";
++	if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000, "A4000T builtin SCSI"))
++		goto out;
+ 
+-    if (AMIGAHW_PRESENT(A4000_SCSI))
+-	num += amiga7xx_register_one(tpnt, 0xdd0040);
++	hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
++	if (hostdata == NULL) {
++		printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n");
++		goto out_release;
++	}
++	memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
++
++	/* Fill in the required pieces of hostdata */
++	hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR);
++	hostdata->clock = 50;
++	hostdata->chip710 = 1;
++	hostdata->dmode_extra = DMODE_FC2;
++	hostdata->dcntl_extra = EA_710;
++
++	/* and register the chip */
++	if ((host = NCR_700_detect(&amiga7xx_scsi_driver_template, hostdata, dev))
++	   == NULL) {
++		printk(KERN_ERR "a4000t-scsi: No host detected; board configuration problem?\n");
++		goto out_free;
++	}
++
++	host->this_id = 7;
++	host->base = A4000T_SCSI_ADDR;
++	host->irq = IRQ_AMIGA_PORTS;
++
++	if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi", host)) {
++		printk(KERN_ERR "a4000t-scsi: request_irq failed\n");
++		goto out_put_host;
++	}
+ 
+-#ifdef CONFIG_ZORRO
+-    num += amiga7xx_zorro_detect(tpnt);
+-#endif
++	scsi_scan_host(host);
++
++	return 0;
+ 
+-    called = 1;
+-    return num;
++ out_put_host:
++	scsi_host_put(host);
++ out_free:
++	kfree(hostdata);
++ out_release:
++	release_mem_region(A4000T_SCSI_ADDR, 0x1000);
++ out:
++	return -ENODEV;
+ }
+ 
+-static int amiga7xx_release(struct Scsi_Host *shost)
++static __devexit int a4000t_device_remove(struct device *dev)
+ {
+-	if (shost->irq)
+-		free_irq(shost->irq, NULL);
+-	if (shost->dma_channel != 0xff)
+-		free_dma(shost->dma_channel);
+-	if (shost->io_port && shost->n_io_port)
+-		release_region(shost->io_port, shost->n_io_port);
+-	scsi_unregister(shost);
++	struct Scsi_Host *host = dev_to_shost(dev);
++	struct NCR_700_Host_Parameters *hostdata =
++		(struct NCR_700_Host_Parameters *)host->hostdata[0];
++
++	scsi_remove_host(host);
++
++	NCR_700_release(host);
++	kfree(hostdata);
++	free_irq(host->irq, host);
++	release_mem_region(A4000T_SCSI_ADDR, 0x1000);
++
+ 	return 0;
+ }
+ 
+-static struct scsi_host_template driver_template = {
+-	.name			= "Amiga NCR53c710 SCSI",
+-	.detect			= amiga7xx_detect,
+-	.release		= amiga7xx_release,
+-	.queuecommand		= NCR53c7xx_queue_command,
+-	.abort			= NCR53c7xx_abort,
+-	.reset			= NCR53c7xx_reset,
+-	.can_queue		= 24,
+-	.this_id		= 7,
+-	.sg_tablesize		= 63,
+-	.cmd_per_lun		= 3,
+-	.use_clustering		= DISABLE_CLUSTERING
++static struct device_driver a4000t_scsi_driver = {
++	.name	= "a4000t-scsi",
++	.bus	= &platform_bus_type,
++	.probe	= a4000t_probe,
++	.remove	= __devexit_p(a4000t_device_remove),
+ };
+ 
++static int __init amiga7xx_scsi_init(void)
++{
++	int err;
++
++	if ((err = driver_register(&a4000t_scsi_driver)))
++		return err;
++
++	a4000t_scsi_device = platform_device_register_simple("a4000t-scsi", -1, NULL, 0);
++
++	if (IS_ERR(a4000t_scsi_device)) {
++		driver_unregister(&a4000t_scsi_driver);
++		return PTR_ERR(a4000t_scsi_device);
++	}
++
++#ifdef CONFIG_ZORRO
++	err = zorro_register_driver(&amiga7xx_driver);
++#endif
++
++	return err;
++}
++
++static void __exit amiga7xx_scsi_exit(void)
++{
++	platform_device_unregister(a4000t_scsi_device);
++	driver_unregister(&a4000t_scsi_driver);
++#ifdef CONFIG_ZORRO
++	zorro_unregister_driver(&amiga7xx_driver);
++#endif
++}
+ 
+-#include "scsi_module.c"
++module_init(amiga7xx_scsi_init);
++module_exit(amiga7xx_scsi_exit);
+--- linux-m68k-2.6.21.orig/drivers/scsi/amiga7xx.h
++++ /dev/null
+@@ -1,23 +0,0 @@
+-#ifndef AMIGA7XX_H
+-
+-#include <linux/types.h>
+-
+-int amiga7xx_detect(struct scsi_host_template *);
+-const char *NCR53c7x0_info(void);
+-int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+-int NCR53c7xx_abort(Scsi_Cmnd *);
+-int NCR53c7x0_release (struct Scsi_Host *);
+-int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
+-void NCR53c7x0_intr(int irq, void *dev_id);
+-
+-#ifndef CMD_PER_LUN
+-#define CMD_PER_LUN 3
+-#endif
+-
+-#ifndef CAN_QUEUE
+-#define CAN_QUEUE 24
+-#endif
+-
+-#include <scsi/scsicam.h>
+-
+-#endif /* AMIGA7XX_H */
+--- linux-m68k-2.6.21.orig/drivers/scsi/bvme6000.h
++++ /dev/null
+@@ -1,24 +0,0 @@
+-#ifndef BVME6000_SCSI_H
+-#define BVME6000_SCSI_H
+-
+-#include <linux/types.h>
+-
+-int bvme6000_scsi_detect(struct scsi_host_template *);
+-const char *NCR53c7x0_info(void);
+-int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+-int NCR53c7xx_abort(Scsi_Cmnd *);
+-int NCR53c7x0_release (struct Scsi_Host *);
+-int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
+-void NCR53c7x0_intr(int irq, void *dev_id);
+-
+-#ifndef CMD_PER_LUN
+-#define CMD_PER_LUN 3
+-#endif
+-
+-#ifndef CAN_QUEUE
+-#define CAN_QUEUE 24
+-#endif
+-
+-#include <scsi/scsicam.h>
+-
+-#endif /* BVME6000_SCSI_H */
+--- linux-m68k-2.6.21.orig/drivers/scsi/bvme6000_scsi.c
++++ linux-m68k-2.6.21/drivers/scsi/bvme6000_scsi.c
+@@ -1,76 +1,132 @@
+ /*
+  * Detection routine for the NCR53c710 based BVME6000 SCSI Controllers for Linux.
+  *
+- * Based on work by Alan Hourihane
++ * Based on work by Alan Hourihane and Kars de Jong
++ *
++ * Rewritten to use 53c700.c by Richard Hirst <richard at sleepie.demon.co.uk>
+  */
+-#include <linux/types.h>
+-#include <linux/mm.h>
+-#include <linux/blkdev.h>
+-#include <linux/zorro.h>
+ 
+-#include <asm/setup.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
++#include <linux/module.h>
++#include <linux/blkdev.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
+ #include <asm/bvme6000hw.h>
+-#include <asm/irq.h>
+-
+-#include "scsi.h"
+ #include <scsi/scsi_host.h>
+-#include "53c7xx.h"
+-#include "bvme6000.h"
++#include <scsi/scsi_device.h>
++#include <scsi/scsi_transport.h>
++#include <scsi/scsi_transport_spi.h>
+ 
+-#include<linux/stat.h>
++#include "53c700.h"
+ 
++MODULE_AUTHOR("Richard Hirst <richard at sleepie.demon.co.uk>");
++MODULE_DESCRIPTION("BVME6000 NCR53C710 driver");
++MODULE_LICENSE("GPL");
+ 
+-int bvme6000_scsi_detect(struct scsi_host_template *tpnt)
++static struct scsi_host_template bvme6000_scsi_driver_template = {
++	.name			= "BVME6000 NCR53c710 SCSI",
++	.proc_name		= "BVME6000",
++	.this_id		= 7,
++	.module			= THIS_MODULE,
++};
++
++static struct platform_device *bvme6000_scsi_device;
++
++static __devinit int
++bvme6000_probe(struct device *dev)
+ {
+-    static unsigned char called = 0;
+-    int clock;
+-    long long options;
++	struct Scsi_Host * host = NULL;
++	struct NCR_700_Host_Parameters *hostdata;
+ 
+-    if (called)
+-	return 0;
+-    if (!MACH_IS_BVME6000)
+-	return 0;
++	if (!MACH_IS_BVME6000)
++		goto out;
+ 
+-    tpnt->proc_name = "BVME6000";
++	hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
++	if (hostdata == NULL) {
++		printk(KERN_ERR "bvme6000-scsi: Failed to allocate host data\n");
++		goto out;
++	}
++	memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
++
++	/* Fill in the required pieces of hostdata */
++	hostdata->base = (void __iomem *)BVME_NCR53C710_BASE;
++	hostdata->clock = 40;	/* XXX - depends on the CPU clock! */
++	hostdata->chip710 = 1;
++	hostdata->dmode_extra = DMODE_FC2;
++	hostdata->dcntl_extra = EA_710;
++	hostdata->ctest7_extra = CTEST7_TT1;
++
++	/* and register the chip */
++	if ((host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata, dev))
++	   == NULL) {
++		printk(KERN_ERR "bvme6000-scsi: No host detected; board configuration problem?\n");
++		goto out_free;
++	}
++	host->base = BVME_NCR53C710_BASE;
++	host->this_id = 7;
++	host->irq = BVME_IRQ_SCSI;
++	if (request_irq(BVME_IRQ_SCSI, NCR_700_intr, 0, "bvme6000-scsi", host)) {
++		printk(KERN_ERR "bvme6000-scsi: request_irq failed\n");
++		goto out_put_host;
++	}
+ 
+-    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
++	scsi_scan_host(host);
+ 
+-    clock = 40000000;	/* 66MHz SCSI Clock */
++	return 0;
+ 
+-    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)BVME_NCR53C710_BASE,
+-			0, BVME_IRQ_SCSI, DMA_NONE,
+-			options, clock);
+-    called = 1;
+-    return 1;
++ out_put_host:
++	scsi_host_put(host);
++ out_free:
++	kfree(hostdata);
++ out:
++	return -ENODEV;
+ }
+ 
+-static int bvme6000_scsi_release(struct Scsi_Host *shost)
++static __devexit int
++bvme6000_device_remove(struct device *dev)
+ {
+-	if (shost->irq)
+-		free_irq(shost->irq, NULL);
+-	if (shost->dma_channel != 0xff)
+-		free_dma(shost->dma_channel);
+-	if (shost->io_port && shost->n_io_port)
+-		release_region(shost->io_port, shost->n_io_port);
+-	scsi_unregister(shost);
++	struct Scsi_Host *host = dev_to_shost(dev);
++	struct NCR_700_Host_Parameters *hostdata =
++		(struct NCR_700_Host_Parameters *)host->hostdata[0];
++
++	scsi_remove_host(host);
++	NCR_700_release(host);
++	kfree(hostdata);
++	free_irq(host->irq, host);
++
+ 	return 0;
+ }
+ 
+-static struct scsi_host_template driver_template = {
+-	.name			= "BVME6000 NCR53c710 SCSI",
+-	.detect			= bvme6000_scsi_detect,
+-	.release		= bvme6000_scsi_release,
+-	.queuecommand		= NCR53c7xx_queue_command,
+-	.abort			= NCR53c7xx_abort,
+-	.reset			= NCR53c7xx_reset,
+-	.can_queue		= 24,
+-	.this_id		= 7,
+-	.sg_tablesize		= 63,
+-	.cmd_per_lun		= 3,
+-	.use_clustering		= DISABLE_CLUSTERING
++static struct device_driver bvme6000_scsi_driver = {
++	.name	= "bvme6000-scsi",
++	.bus	= &platform_bus_type,
++	.probe	= bvme6000_probe,
++	.remove	= __devexit_p(bvme6000_device_remove),
+ };
+ 
++static int __init bvme6000_scsi_init(void)
++{
++	int err;
++
++	if ((err = driver_register(&bvme6000_scsi_driver)))
++		return err;
++
++	bvme6000_scsi_device = platform_device_register_simple("bvme6000-scsi", -1, NULL, 0);
++
++	if (IS_ERR(bvme6000_scsi_device)) {
++		driver_unregister(&bvme6000_scsi_driver);
++		return PTR_ERR(bvme6000_scsi_device);
++	}
++
++	return 0;
++}
++
++static void __exit bvme6000_scsi_exit(void)
++{
++	platform_device_unregister(bvme6000_scsi_device);
++	driver_unregister(&bvme6000_scsi_driver);
++}
+ 
+-#include "scsi_module.c"
++module_init(bvme6000_scsi_init);
++module_exit(bvme6000_scsi_exit);
+--- linux-m68k-2.6.21.orig/drivers/scsi/mvme16x.h
++++ /dev/null
+@@ -1,24 +0,0 @@
+-#ifndef MVME16x_SCSI_H
+-#define MVME16x_SCSI_H
+-
+-#include <linux/types.h>
+-
+-int mvme16x_scsi_detect(struct scsi_host_template *);
+-const char *NCR53c7x0_info(void);
+-int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+-int NCR53c7xx_abort(Scsi_Cmnd *);
+-int NCR53c7x0_release (struct Scsi_Host *);
+-int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
+-void NCR53c7x0_intr(int irq, void *dev_id);
+-
+-#ifndef CMD_PER_LUN
+-#define CMD_PER_LUN 3
+-#endif
+-
+-#ifndef CAN_QUEUE
+-#define CAN_QUEUE 24
+-#endif
+-
+-#include <scsi/scsicam.h>
+-
+-#endif /* MVME16x_SCSI_H */
+--- linux-m68k-2.6.21.orig/drivers/scsi/mvme16x_scsi.c
++++ linux-m68k-2.6.21/drivers/scsi/mvme16x_scsi.c
+@@ -2,77 +2,154 @@
+  * Detection routine for the NCR53c710 based MVME16x SCSI Controllers for Linux.
+  *
+  * Based on work by Alan Hourihane
++ *
++ * Rewritten to use 53c700.c by Kars de Jong <jongk at linux-m68k.org>
+  */
+-#include <linux/types.h>
+-#include <linux/mm.h>
+-#include <linux/blkdev.h>
+ 
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
++#include <linux/module.h>
++#include <linux/blkdev.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
+ #include <asm/mvme16xhw.h>
+-#include <asm/irq.h>
+-
+-#include "scsi.h"
+ #include <scsi/scsi_host.h>
+-#include "53c7xx.h"
+-#include "mvme16x.h"
++#include <scsi/scsi_device.h>
++#include <scsi/scsi_transport.h>
++#include <scsi/scsi_transport_spi.h>
+ 
+-#include<linux/stat.h>
++#include "53c700.h"
+ 
++MODULE_AUTHOR("Kars de Jong <jongk at linux-m68k.org>");
++MODULE_DESCRIPTION("MVME16x NCR53C710 driver");
++MODULE_LICENSE("GPL");
+ 
+-int mvme16x_scsi_detect(struct scsi_host_template *tpnt)
++static struct scsi_host_template mvme16x_scsi_driver_template = {
++	.name			= "MVME16x NCR53c710 SCSI",
++	.proc_name		= "MVME16x",
++	.this_id		= 7,
++	.module			= THIS_MODULE,
++};
++
++static struct platform_device *mvme16x_scsi_device;
++
++static __devinit int
++mvme16x_probe(struct device *dev)
+ {
+-    static unsigned char called = 0;
+-    int clock;
+-    long long options;
+-
+-    if (!MACH_IS_MVME16x)
+-		return 0;
+-    if (mvme16x_config & MVME16x_CONFIG_NO_SCSICHIP) {
+-	printk ("SCSI detection disabled, SCSI chip not present\n");
+-	return 0;
+-    }
+-    if (called)
+-	return 0;
++	struct Scsi_Host * host = NULL;
++	struct NCR_700_Host_Parameters *hostdata;
++
++	if (!MACH_IS_MVME16x)
++		goto out;
+ 
+-    tpnt->proc_name = "MVME16x";
++	if (mvme16x_config & MVME16x_CONFIG_NO_SCSICHIP) {
++		printk(KERN_INFO "mvme16x-scsi: detection disabled, SCSI chip not present\n");
++		goto out;
++	}
++
++	hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
++	if (hostdata == NULL) {
++		printk(KERN_ERR "mvme16x-scsi: Failed to allocate host data\n");
++		goto out;
++	}
++	memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
++
++	/* Fill in the required pieces of hostdata */
++	hostdata->base = (void __iomem *)0xfff47000UL;
++	hostdata->clock = 50;	/* XXX - depends on the CPU clock! */
++	hostdata->chip710 = 1;
++	hostdata->dmode_extra = DMODE_FC2;
++	hostdata->dcntl_extra = EA_710;
++	hostdata->ctest7_extra = CTEST7_TT1;
++
++	/* and register the chip */
++	if ((host = NCR_700_detect(&mvme16x_scsi_driver_template, hostdata, dev))
++	   == NULL) {
++		printk(KERN_ERR "mvme16x-scsi: No host detected; board configuration problem?\n");
++		goto out_free;
++	}
++	host->this_id = 7;
++	host->base = 0xfff47000UL;
++	host->irq = MVME16x_IRQ_SCSI;
++	if (request_irq(host->irq, NCR_700_intr, 0, "mvme16x-scsi", host)) {
++		printk(KERN_ERR "mvme16x-scsi: request_irq failed\n");
++		goto out_put_host;
++	}
++
++	/* Enable scsi chip ints */
++	{
++		volatile unsigned long v;
++
++		/* Enable scsi interrupts at level 4 in PCCchip2 */
++		v = in_be32(0xfff4202c);
++		v = (v & ~0xff) | 0x10 | 4;
++		out_be32(0xfff4202c, v);
++	}
+ 
+-    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
++	scsi_scan_host(host);
+ 
+-    clock = 66000000;	/* 66MHz SCSI Clock */
++	return 0;
+ 
+-    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)0xfff47000,
+-			0, MVME16x_IRQ_SCSI, DMA_NONE,
+-			options, clock);
+-    called = 1;
+-    return 1;
++ out_put_host:
++	scsi_host_put(host);
++ out_free:
++	kfree(hostdata);
++ out:
++	return -ENODEV;
+ }
+ 
+-static int mvme16x_scsi_release(struct Scsi_Host *shost)
++static __devexit int
++mvme16x_device_remove(struct device *dev)
+ {
+-	if (shost->irq)
+-		free_irq(shost->irq, NULL);
+-	if (shost->dma_channel != 0xff)
+-		free_dma(shost->dma_channel);
+-	if (shost->io_port && shost->n_io_port)
+-		release_region(shost->io_port, shost->n_io_port);
+-	scsi_unregister(shost);
++	struct Scsi_Host *host = dev_to_shost(dev);
++	struct NCR_700_Host_Parameters *hostdata =
++		(struct NCR_700_Host_Parameters *)host->hostdata[0];
++
++	/* Disable scsi chip ints */
++	{
++		volatile unsigned long v;
++
++		v = in_be32(0xfff4202c);
++		v &= ~0x10;
++		out_be32(0xfff4202c, v);
++	}
++	scsi_remove_host(host);
++	NCR_700_release(host);
++	kfree(hostdata);
++	free_irq(host->irq, host);
++
+ 	return 0;
+ }
+ 
+-static struct scsi_host_template driver_template = {
+-	.name			= "MVME16x NCR53c710 SCSI",
+-	.detect			= mvme16x_scsi_detect,
+-	.release		= mvme16x_scsi_release,
+-	.queuecommand		= NCR53c7xx_queue_command,
+-	.abort			= NCR53c7xx_abort,
+-	.reset			= NCR53c7xx_reset,
+-	.can_queue		= 24,
+-	.this_id		= 7,
+-	.sg_tablesize		= 63,
+-	.cmd_per_lun		= 3,
+-	.use_clustering		= DISABLE_CLUSTERING
++static struct device_driver mvme16x_scsi_driver = {
++	.name	= "mvme16x-scsi",
++	.bus	= &platform_bus_type,
++	.probe	= mvme16x_probe,
++	.remove	= __devexit_p(mvme16x_device_remove),
+ };
+ 
++static int __init mvme16x_scsi_init(void)
++{
++	int err;
++
++	if ((err = driver_register(&mvme16x_scsi_driver)))
++		return err;
++
++	mvme16x_scsi_device = platform_device_register_simple("mvme16x-scsi", -1, NULL, 0);
++
++	if (IS_ERR(mvme16x_scsi_device)) {
++		driver_unregister(&mvme16x_scsi_driver);
++		return PTR_ERR(mvme16x_scsi_device);
++	}
++
++	return 0;
++}
++
++static void __exit mvme16x_scsi_exit(void)
++{
++	platform_device_unregister(mvme16x_scsi_device);
++	driver_unregister(&mvme16x_scsi_driver);
++}
+ 
+-#include "scsi_module.c"
++module_init(mvme16x_scsi_init);
++module_exit(mvme16x_scsi_exit);

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-generic-io.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-generic-io.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,234 @@
+From jongk at linux-m68k.org Fri Nov  3 10:12:53 2006
+Date: Fri, 03 Nov 2006 00:06:13 +0100
+From: Kars de Jong <jongk at linux-m68k.org>
+To: Geert Uytterhoeven <geert at linux-m68k.org>
+Cc: linux-m68k at vger.kernel.org
+Subject: [RFC PATCH] m68k: GENERIC_IOMAP support
+
+On do, 2006-11-02 at 22:34 +0100, Geert Uytterhoeven wrote:
+> > OK, here's the patch, without the m68k generic iomap changes.
+> 
+> Ah, the missing io{read,write}*() stuff :-)
+
+And here is the proposed patch to add iomap support. I think we need to
+rethink our I/O support when we want to support all our I/O buses
+properly, but that has been discussed before. I will commit my Amiga
+PCMCIA support soon, I promise!
+
+I'm personally in favour of dropping the "generic" m68k kernel support.
+Even a specific 2.6.18 kernel with only MVME167 support and the bare
+essentials is already 2.5 MBytes these days. I don't even dare to think
+of the size of a generic m68k kernel these days.
+
+Since Debian also builds "specific" kernels these days, I wonder if we
+still need "generic" installation type kernels. Dropping that support
+does make implementing some of the I/O stuff a lot easier, IMO, since it
+can then be done at compile time.
+
+On vr, 2006-11-03 at 00:06 +0100, Kars de Jong wrote:
+> On do, 2006-11-02 at 22:34 +0100, Geert Uytterhoeven wrote:
+> > > OK, here's the patch, without the m68k generic iomap changes.
+> > 
+> > Ah, the missing io{read,write}*() stuff :-)
+> 
+> And here is the proposed patch to add iomap support. I think we need to
+> rethink our I/O support when we want to support all our I/O buses
+> properly, but that has been discussed before. I will commit my Amiga
+> PCMCIA support soon, I promise!
+
+Here's the updated version of this patch. It should now work with Amiga
+and Q40 defconfig.
+
+I don't think the CONFIG_ATARI_ROM_ISA definitions are complete yet, the
+32-bit variants are missing.
+
+Kind regards,
+
+Kars.
+
+---
+ arch/m68k/Kconfig         |    4 ++
+ include/asm-m68k/io.h     |   63 +++++++++++++++++++++++++++++++++++++---------
+ include/asm-m68k/raw_io.h |    8 ++++-
+ 3 files changed, 61 insertions(+), 14 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/Kconfig
++++ linux-m68k-2.6.21/arch/m68k/Kconfig
+@@ -37,6 +37,10 @@ config TIME_LOW_RES
+ 	bool
+ 	default y
+ 
++config GENERIC_IOMAP
++	bool
++	default y
++
+ config ARCH_MAY_HAVE_PC_FDC
+ 	bool
+ 	depends on Q40 || (BROKEN && SUN3X)
+--- linux-m68k-2.6.21.orig/include/asm-m68k/io.h
++++ linux-m68k-2.6.21/include/asm-m68k/io.h
+@@ -27,6 +27,7 @@
+ #include <asm/raw_io.h>
+ #include <asm/virtconvert.h>
+ 
++#include <asm-generic/iomap.h>
+ 
+ #ifdef CONFIG_ATARI
+ #include <asm/atarihw.h>
+@@ -175,6 +176,16 @@ static inline u16 __iomem *isa_itw(unsig
+     default: return NULL; /* avoid warnings, just in case */
+     }
+ }
++static inline u32 __iomem *isa_itl(unsigned long addr)
++{
++  switch(ISA_TYPE)
++    {
++#ifdef CONFIG_AMIGA_PCMCIA
++    case AG_ISA: return (u32 *)AG_ISA_IO_W(addr);
++#endif
++    default: return 0; /* avoid warnings, just in case */
++    }
++}
+ static inline u8 __iomem *isa_mtb(unsigned long addr)
+ {
+   switch(ISA_TYPE)
+@@ -217,8 +228,10 @@ static inline u16 __iomem *isa_mtw(unsig
+ 
+ #define isa_inb(port)      in_8(isa_itb(port))
+ #define isa_inw(port)      (ISA_SEX ? in_be16(isa_itw(port)) : in_le16(isa_itw(port)))
++#define isa_inl(port)      (ISA_SEX ? in_be32(isa_itl(port)) : in_le32(isa_itl(port)))
+ #define isa_outb(val,port) out_8(isa_itb(port),(val))
+ #define isa_outw(val,port) (ISA_SEX ? out_be16(isa_itw(port),(val)) : out_le16(isa_itw(port),(val)))
++#define isa_outl(val,port) (ISA_SEX ? out_be32(isa_itl(port),(val)) : out_le32(isa_itl(port),(val)))
+ 
+ #define isa_readb(p)       in_8(isa_mtb((unsigned long)(p)))
+ #define isa_readw(p)       \
+@@ -280,6 +293,14 @@ static inline void isa_delay(void)
+        (ISA_SEX ? raw_outsw(isa_itw(port), (u16 *)(buf), (nr)) :  \
+                   raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
+ 
++#define isa_insl(port, buf, nr)     \
++       (ISA_SEX ? raw_insl(isa_itl(port), (u32 *)(buf), (nr)) :    \
++                  raw_insw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
++
++#define isa_outsl(port, buf, nr)    \
++       (ISA_SEX ? raw_outsl(isa_itl(port), (u32 *)(buf), (nr)) :  \
++                  raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
++
+ #if defined(CONFIG_ATARI_ROM_ISA)
+ #define isa_rom_inb_p(p)	({ u8 _v = isa_rom_inb(p); isa_delay(); _v; })
+ #define isa_rom_inw_p(p)	({ u16 _v = isa_rom_inw(p); isa_delay(); _v; })
+@@ -314,14 +335,16 @@ static inline void isa_delay(void)
+ #define inw_p   isa_inw_p
+ #define outw    isa_outw
+ #define outw_p  isa_outw_p
+-#define inl     isa_inw
+-#define inl_p   isa_inw_p
+-#define outl    isa_outw
+-#define outl_p  isa_outw_p
++#define inl     isa_inl
++#define inl_p   isa_inl_p
++#define outl    isa_outl
++#define outl_p  isa_outl_p
+ #define insb    isa_insb
+ #define insw    isa_insw
++#define insl    isa_insl
+ #define outsb   isa_outsb
+ #define outsw   isa_outsw
++#define outsl   isa_outsl
+ #define readb   isa_readb
+ #define readw   isa_readw
+ #define writeb  isa_writeb
+@@ -330,8 +353,6 @@ static inline void isa_delay(void)
+ 
+ #if defined(CONFIG_PCI)
+ 
+-#define inl(port)        in_le32(port)
+-#define outl(val,port)   out_le32((port),(val))
+ #define readl(addr)      in_le32(addr)
+ #define writel(val,addr) out_le32((addr),(val))
+ 
+@@ -346,10 +367,13 @@ static inline void isa_delay(void)
+ #define readl_relaxed(addr) readl(addr)
+ 
+ #ifndef CONFIG_ISA
++
+ #define inb(port)      in_8(port)
+ #define outb(val,port) out_8((port),(val))
+ #define inw(port)      in_le16(port)
+ #define outw(val,port) out_le16((port),(val))
++#define inl(port)      in_le32(port)
++#define outl(val,port) out_le32((port),(val))
+ 
+ #else
+ /*
+@@ -401,20 +425,35 @@ static inline void isa_delay(void)
+ #define outsw   isa_rom_outsw
+ #endif
+ 
+-#if !defined(CONFIG_ISA) && !defined(CONFIG_PCI) && !defined(CONFIG_ATARI_ROM_ISA) && defined(CONFIG_HP300)
++#if !defined(CONFIG_ISA) && !defined(CONFIG_PCI) && !defined(CONFIG_ATARI_ROM_ISA)
+ /*
+- * We need to define dummy functions otherwise drivers/serial/8250.c doesn't link
++ * We need to define dummy functions for GENERIC_IOMAP support.
+  */
+-#define inb(port)        0xff
+-#define inb_p(port)      0xff
+-#define outb(val,port)   do { } while (0)
+-#define outb_p(val,port) do { } while (0)
++#define inb(port)          0xff
++#define inb_p(port)        0xff
++#define outb(val,port)     do { } while (0)
++#define outb_p(val,port)   do { } while (0)
++#define inw(port)          0xffff
++#define outw(val,port)     do { } while (0)
++#define inl(port)          0xffffffffUL
++#define outl(val,port)     do { } while (0)
++
++#define insb(port,buf,nr)  do { } while (0)
++#define outsb(port,buf,nr) do { } while (0)
++#define insw(port,buf,nr)  do { } while (0)
++#define outsw(port,buf,nr) do { } while (0)
++#define insl(port,buf,nr)  do { } while (0)
++#define outsl(port,buf,nr) do { } while (0)
+ 
+ /*
+  * These should be valid on any ioremap()ed region
+  */
+ #define readb(addr)      in_8(addr)
+ #define writeb(val,addr) out_8((addr),(val))
++#define readw(addr)      in_le16(addr)
++#define writew(val,addr) out_le16((addr),(val))
++#endif /* !CONFIG_ISA && !CONFIG_PCI && !CONFIG_ATARI_ROM_ISA */
++#if !defined(CONFIG_PCI)
+ #define readl(addr)      in_le32(addr)
+ #define writel(val,addr) out_le32((addr),(val))
+ #endif
+--- linux-m68k-2.6.21.orig/include/asm-m68k/raw_io.h
++++ linux-m68k-2.6.21/include/asm-m68k/raw_io.h
+@@ -49,10 +49,16 @@ extern void __iounmap(void *addr, unsign
+ #define raw_inb in_8
+ #define raw_inw in_be16
+ #define raw_inl in_be32
++#define __raw_readb in_8
++#define __raw_readw in_be16
++#define __raw_readl in_be32
+ 
+ #define raw_outb(val,port) out_8((port),(val))
+ #define raw_outw(val,port) out_be16((port),(val))
+ #define raw_outl(val,port) out_be32((port),(val))
++#define __raw_writeb(val,addr) out_8((addr),(val))
++#define __raw_writew(val,addr) out_be16((addr),(val))
++#define __raw_writel(val,addr) out_be32((addr),(val))
+ 
+ /*
+  * Atari ROM port (cartridge port) ISA adapter, used for the EtherNEC NE2000
+@@ -432,8 +438,6 @@ static inline void raw_rom_outsw_swapw(v
+ }
+ #endif /* CONFIG_ATARI_ROM_ISA */
+ 
+-#define __raw_writel raw_outl
+-
+ #endif /* __KERNEL__ */
+ 
+ #endif /* _RAW_IO_H */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-linux-gnu-crosscompile.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-linux-gnu-crosscompile.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,20 @@
+Subject: [PATCH] m68k: CROSS_COMPILE = m68k-linux-gnu-
+
+Recent cross-compilers are called m68k-linux-gnu-gcc instead of m68k-linux-gcc
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/Makefile |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/Makefile
++++ linux-m68k-2.6.21/arch/m68k/Makefile
+@@ -21,7 +21,7 @@ AS += -m68020
+ LDFLAGS := -m m68kelf
+ ifneq ($(COMPILE_ARCH),$(ARCH))
+ 	# prefix for cross-compiling binaries
+-	CROSS_COMPILE = m68k-linux-
++	CROSS_COMPILE = m68k-linux-gnu-
+ endif
+ 
+ ifdef CONFIG_SUN3

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-mvme-scsi-rename.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-mvme-scsi-rename.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,348 @@
+Subject: [PATCH] m68k: BVME6000 and MVME16x SCSI driver rename
+
+Rename the source files for the BVME6000 and MVME16x SCSI drivers from *.c to
+*_scsi.c
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+
+---
+ drivers/scsi/Makefile        |    4 +-
+ drivers/scsi/bvme6000.c      |   76 -----------------------------------------
+ drivers/scsi/bvme6000_scsi.c |   76 +++++++++++++++++++++++++++++++++++++++++
+ drivers/scsi/mvme16x.c       |   78 -------------------------------------------
+ drivers/scsi/mvme16x_scsi.c  |   78 +++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 156 insertions(+), 156 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/scsi/Makefile
++++ linux-m68k-2.6.21/drivers/scsi/Makefile
+@@ -53,8 +53,8 @@ obj-$(CONFIG_ATARI_SCSI)	+= atari_scsi.o
+ obj-$(CONFIG_MAC_SCSI)		+= mac_scsi.o
+ obj-$(CONFIG_SCSI_MAC_ESP)	+= mac_esp.o	NCR53C9x.o
+ obj-$(CONFIG_SUN3_SCSI)		+= sun3_scsi.o  sun3_scsi_vme.o
+-obj-$(CONFIG_MVME16x_SCSI)	+= mvme16x.o	53c7xx.o
+-obj-$(CONFIG_BVME6000_SCSI)	+= bvme6000.o	53c7xx.o
++obj-$(CONFIG_MVME16x_SCSI)	+= mvme16x_scsi.o	53c7xx.o
++obj-$(CONFIG_BVME6000_SCSI)	+= bvme6000_scsi.o	53c7xx.o
+ obj-$(CONFIG_SCSI_SIM710)	+= 53c700.o	sim710.o
+ obj-$(CONFIG_SCSI_ADVANSYS)	+= advansys.o
+ obj-$(CONFIG_SCSI_PSI240I)	+= psi240i.o
+--- linux-m68k-2.6.21.orig/drivers/scsi/bvme6000.c
++++ /dev/null
+@@ -1,76 +0,0 @@
+-/*
+- * Detection routine for the NCR53c710 based BVME6000 SCSI Controllers for Linux.
+- *
+- * Based on work by Alan Hourihane
+- */
+-#include <linux/types.h>
+-#include <linux/mm.h>
+-#include <linux/blkdev.h>
+-#include <linux/zorro.h>
+-
+-#include <asm/setup.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/bvme6000hw.h>
+-#include <asm/irq.h>
+-
+-#include "scsi.h"
+-#include <scsi/scsi_host.h>
+-#include "53c7xx.h"
+-#include "bvme6000.h"
+-
+-#include<linux/stat.h>
+-
+-
+-int bvme6000_scsi_detect(struct scsi_host_template *tpnt)
+-{
+-    static unsigned char called = 0;
+-    int clock;
+-    long long options;
+-
+-    if (called)
+-	return 0;
+-    if (!MACH_IS_BVME6000)
+-	return 0;
+-
+-    tpnt->proc_name = "BVME6000";
+-
+-    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
+-
+-    clock = 40000000;	/* 66MHz SCSI Clock */
+-
+-    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)BVME_NCR53C710_BASE,
+-			0, BVME_IRQ_SCSI, DMA_NONE,
+-			options, clock);
+-    called = 1;
+-    return 1;
+-}
+-
+-static int bvme6000_scsi_release(struct Scsi_Host *shost)
+-{
+-	if (shost->irq)
+-		free_irq(shost->irq, NULL);
+-	if (shost->dma_channel != 0xff)
+-		free_dma(shost->dma_channel);
+-	if (shost->io_port && shost->n_io_port)
+-		release_region(shost->io_port, shost->n_io_port);
+-	scsi_unregister(shost);
+-	return 0;
+-}
+-
+-static struct scsi_host_template driver_template = {
+-	.name			= "BVME6000 NCR53c710 SCSI",
+-	.detect			= bvme6000_scsi_detect,
+-	.release		= bvme6000_scsi_release,
+-	.queuecommand		= NCR53c7xx_queue_command,
+-	.abort			= NCR53c7xx_abort,
+-	.reset			= NCR53c7xx_reset,
+-	.can_queue		= 24,
+-	.this_id		= 7,
+-	.sg_tablesize		= 63,
+-	.cmd_per_lun		= 3,
+-	.use_clustering		= DISABLE_CLUSTERING
+-};
+-
+-
+-#include "scsi_module.c"
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/scsi/bvme6000_scsi.c
+@@ -0,0 +1,76 @@
++/*
++ * Detection routine for the NCR53c710 based BVME6000 SCSI Controllers for Linux.
++ *
++ * Based on work by Alan Hourihane
++ */
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/blkdev.h>
++#include <linux/zorro.h>
++
++#include <asm/setup.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/bvme6000hw.h>
++#include <asm/irq.h>
++
++#include "scsi.h"
++#include <scsi/scsi_host.h>
++#include "53c7xx.h"
++#include "bvme6000.h"
++
++#include<linux/stat.h>
++
++
++int bvme6000_scsi_detect(struct scsi_host_template *tpnt)
++{
++    static unsigned char called = 0;
++    int clock;
++    long long options;
++
++    if (called)
++	return 0;
++    if (!MACH_IS_BVME6000)
++	return 0;
++
++    tpnt->proc_name = "BVME6000";
++
++    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
++
++    clock = 40000000;	/* 66MHz SCSI Clock */
++
++    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)BVME_NCR53C710_BASE,
++			0, BVME_IRQ_SCSI, DMA_NONE,
++			options, clock);
++    called = 1;
++    return 1;
++}
++
++static int bvme6000_scsi_release(struct Scsi_Host *shost)
++{
++	if (shost->irq)
++		free_irq(shost->irq, NULL);
++	if (shost->dma_channel != 0xff)
++		free_dma(shost->dma_channel);
++	if (shost->io_port && shost->n_io_port)
++		release_region(shost->io_port, shost->n_io_port);
++	scsi_unregister(shost);
++	return 0;
++}
++
++static struct scsi_host_template driver_template = {
++	.name			= "BVME6000 NCR53c710 SCSI",
++	.detect			= bvme6000_scsi_detect,
++	.release		= bvme6000_scsi_release,
++	.queuecommand		= NCR53c7xx_queue_command,
++	.abort			= NCR53c7xx_abort,
++	.reset			= NCR53c7xx_reset,
++	.can_queue		= 24,
++	.this_id		= 7,
++	.sg_tablesize		= 63,
++	.cmd_per_lun		= 3,
++	.use_clustering		= DISABLE_CLUSTERING
++};
++
++
++#include "scsi_module.c"
+--- linux-m68k-2.6.21.orig/drivers/scsi/mvme16x.c
++++ /dev/null
+@@ -1,78 +0,0 @@
+-/*
+- * Detection routine for the NCR53c710 based MVME16x SCSI Controllers for Linux.
+- *
+- * Based on work by Alan Hourihane
+- */
+-#include <linux/types.h>
+-#include <linux/mm.h>
+-#include <linux/blkdev.h>
+-
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/mvme16xhw.h>
+-#include <asm/irq.h>
+-
+-#include "scsi.h"
+-#include <scsi/scsi_host.h>
+-#include "53c7xx.h"
+-#include "mvme16x.h"
+-
+-#include<linux/stat.h>
+-
+-
+-int mvme16x_scsi_detect(struct scsi_host_template *tpnt)
+-{
+-    static unsigned char called = 0;
+-    int clock;
+-    long long options;
+-
+-    if (!MACH_IS_MVME16x)
+-		return 0;
+-    if (mvme16x_config & MVME16x_CONFIG_NO_SCSICHIP) {
+-	printk ("SCSI detection disabled, SCSI chip not present\n");
+-	return 0;
+-    }
+-    if (called)
+-	return 0;
+-
+-    tpnt->proc_name = "MVME16x";
+-
+-    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
+-
+-    clock = 66000000;	/* 66MHz SCSI Clock */
+-
+-    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)0xfff47000,
+-			0, MVME16x_IRQ_SCSI, DMA_NONE,
+-			options, clock);
+-    called = 1;
+-    return 1;
+-}
+-
+-static int mvme16x_scsi_release(struct Scsi_Host *shost)
+-{
+-	if (shost->irq)
+-		free_irq(shost->irq, NULL);
+-	if (shost->dma_channel != 0xff)
+-		free_dma(shost->dma_channel);
+-	if (shost->io_port && shost->n_io_port)
+-		release_region(shost->io_port, shost->n_io_port);
+-	scsi_unregister(shost);
+-	return 0;
+-}
+-
+-static struct scsi_host_template driver_template = {
+-	.name			= "MVME16x NCR53c710 SCSI",
+-	.detect			= mvme16x_scsi_detect,
+-	.release		= mvme16x_scsi_release,
+-	.queuecommand		= NCR53c7xx_queue_command,
+-	.abort			= NCR53c7xx_abort,
+-	.reset			= NCR53c7xx_reset,
+-	.can_queue		= 24,
+-	.this_id		= 7,
+-	.sg_tablesize		= 63,
+-	.cmd_per_lun		= 3,
+-	.use_clustering		= DISABLE_CLUSTERING
+-};
+-
+-
+-#include "scsi_module.c"
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/scsi/mvme16x_scsi.c
+@@ -0,0 +1,78 @@
++/*
++ * Detection routine for the NCR53c710 based MVME16x SCSI Controllers for Linux.
++ *
++ * Based on work by Alan Hourihane
++ */
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/blkdev.h>
++
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/mvme16xhw.h>
++#include <asm/irq.h>
++
++#include "scsi.h"
++#include <scsi/scsi_host.h>
++#include "53c7xx.h"
++#include "mvme16x.h"
++
++#include<linux/stat.h>
++
++
++int mvme16x_scsi_detect(struct scsi_host_template *tpnt)
++{
++    static unsigned char called = 0;
++    int clock;
++    long long options;
++
++    if (!MACH_IS_MVME16x)
++		return 0;
++    if (mvme16x_config & MVME16x_CONFIG_NO_SCSICHIP) {
++	printk ("SCSI detection disabled, SCSI chip not present\n");
++	return 0;
++    }
++    if (called)
++	return 0;
++
++    tpnt->proc_name = "MVME16x";
++
++    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
++
++    clock = 66000000;	/* 66MHz SCSI Clock */
++
++    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)0xfff47000,
++			0, MVME16x_IRQ_SCSI, DMA_NONE,
++			options, clock);
++    called = 1;
++    return 1;
++}
++
++static int mvme16x_scsi_release(struct Scsi_Host *shost)
++{
++	if (shost->irq)
++		free_irq(shost->irq, NULL);
++	if (shost->dma_channel != 0xff)
++		free_dma(shost->dma_channel);
++	if (shost->io_port && shost->n_io_port)
++		release_region(shost->io_port, shost->n_io_port);
++	scsi_unregister(shost);
++	return 0;
++}
++
++static struct scsi_host_template driver_template = {
++	.name			= "MVME16x NCR53c710 SCSI",
++	.detect			= mvme16x_scsi_detect,
++	.release		= mvme16x_scsi_release,
++	.queuecommand		= NCR53c7xx_queue_command,
++	.abort			= NCR53c7xx_abort,
++	.reset			= NCR53c7xx_reset,
++	.can_queue		= 24,
++	.this_id		= 7,
++	.sg_tablesize		= 63,
++	.cmd_per_lun		= 3,
++	.use_clustering		= DISABLE_CLUSTERING
++};
++
++
++#include "scsi_module.c"

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-reformat.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/m68k-reformat.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,4818 @@
+Subject: [PATCH] m68k: reformat various m68k files
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+Reformat various m68k files, so they actually look like Linux sources.
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/amiga/config.c | 1062 +++++++++++++++++++++++------------------------
+ arch/m68k/atari/config.c |  983 ++++++++++++++++++++-----------------------
+ arch/m68k/atari/debug.c  |  470 ++++++++++----------
+ arch/m68k/kernel/entry.S |    2 
+ arch/m68k/kernel/head.S  |    2 
+ arch/m68k/kernel/setup.c |  381 ++++++++--------
+ arch/m68k/mac/config.c   |  161 +++----
+ arch/m68k/mac/debug.c    |  331 +++++++-------
+ arch/m68k/q40/config.c   |  259 +++++------
+ arch/m68k/sun3x/prom.c   |  121 ++---
+ 10 files changed, 1856 insertions(+), 1916 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/amiga/config.c
++++ linux-m68k-2.6.21/arch/m68k/amiga/config.c
+@@ -22,9 +22,7 @@
+ #include <linux/vt_kern.h>
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
+-#ifdef CONFIG_ZORRO
+ #include <linux/zorro.h>
+-#endif
+ 
+ #include <asm/bootinfo.h>
+ #include <asm/setup.h>
+@@ -62,21 +60,21 @@ static char s_cdtv[] __initdata = "CDTV"
+ static char s_cd32[] __initdata = "CD32";
+ static char s_draco[] __initdata = "Draco";
+ static char *amiga_models[] __initdata = {
+-    [AMI_500-AMI_500]		= s_a500,
+-    [AMI_500PLUS-AMI_500]	= s_a500p,
+-    [AMI_600-AMI_500]		= s_a600,
+-    [AMI_1000-AMI_500]		= s_a1000,
+-    [AMI_1200-AMI_500]		= s_a1200,
+-    [AMI_2000-AMI_500]		= s_a2000,
+-    [AMI_2500-AMI_500]		= s_a2500,
+-    [AMI_3000-AMI_500]		= s_a3000,
+-    [AMI_3000T-AMI_500]		= s_a3000t,
+-    [AMI_3000PLUS-AMI_500]	= s_a3000p,
+-    [AMI_4000-AMI_500]		= s_a4000,
+-    [AMI_4000T-AMI_500]		= s_a4000t,
+-    [AMI_CDTV-AMI_500]		= s_cdtv,
+-    [AMI_CD32-AMI_500]		= s_cd32,
+-    [AMI_DRACO-AMI_500]		= s_draco,
++	[AMI_500-AMI_500]	= s_a500,
++	[AMI_500PLUS-AMI_500]	= s_a500p,
++	[AMI_600-AMI_500]	= s_a600,
++	[AMI_1000-AMI_500]	= s_a1000,
++	[AMI_1200-AMI_500]	= s_a1200,
++	[AMI_2000-AMI_500]	= s_a2000,
++	[AMI_2500-AMI_500]	= s_a2500,
++	[AMI_3000-AMI_500]	= s_a3000,
++	[AMI_3000T-AMI_500]	= s_a3000t,
++	[AMI_3000PLUS-AMI_500]	= s_a3000p,
++	[AMI_4000-AMI_500]	= s_a4000,
++	[AMI_4000T-AMI_500]	= s_a4000t,
++	[AMI_CDTV-AMI_500]	= s_cdtv,
++	[AMI_CD32-AMI_500]	= s_cd32,
++	[AMI_DRACO-AMI_500]	= s_draco,
+ };
+ 
+ static char amiga_model_name[13] = "Amiga ";
+@@ -85,17 +83,17 @@ extern char m68k_debug_device[];
+ 
+ static void amiga_sched_init(irq_handler_t handler);
+ /* amiga specific irq functions */
+-extern void amiga_init_IRQ (void);
++extern void amiga_init_IRQ(void);
+ static void amiga_get_model(char *model);
+ static int amiga_get_hardware_list(char *buffer);
+ /* amiga specific timer functions */
+-static unsigned long amiga_gettimeoffset (void);
+-static int a3000_hwclk (int, struct rtc_time *);
+-static int a2000_hwclk (int, struct rtc_time *);
+-static int amiga_set_clock_mmss (unsigned long);
+-static unsigned int amiga_get_ss (void);
+-extern void amiga_mksound( unsigned int count, unsigned int ticks );
+-static void amiga_reset (void);
++static unsigned long amiga_gettimeoffset(void);
++static int a3000_hwclk(int, struct rtc_time *);
++static int a2000_hwclk(int, struct rtc_time *);
++static int amiga_set_clock_mmss(unsigned long);
++static unsigned int amiga_get_ss(void);
++extern void amiga_mksound(unsigned int count, unsigned int ticks);
++static void amiga_reset(void);
+ extern void amiga_init_sound(void);
+ static void amiga_savekmsg_init(void);
+ static void amiga_mem_console_write(struct console *co, const char *b,
+@@ -108,9 +106,9 @@ static void amiga_heartbeat(int on);
+ #endif
+ 
+ static struct console amiga_console_driver = {
+-	.name =		"debug",
+-	.flags =	CON_PRINTBUFFER,
+-	.index =	-1,
++	.name	= "debug",
++	.flags	= CON_PRINTBUFFER,
++	.index	= -1,
+ };
+ 
+ 
+@@ -119,24 +117,24 @@ static struct console amiga_console_driv
+      */
+ 
+ static struct {
+-    struct resource _ciab, _ciaa, _custom, _kickstart;
++	struct resource _ciab, _ciaa, _custom, _kickstart;
+ } mb_resources = {
+-    ._ciab = {
+-	.name = "CIA B", .start = 0x00bfd000, .end = 0x00bfdfff
+-    },
+-    ._ciaa = {
+-	.name = "CIA A", .start = 0x00bfe000, .end = 0x00bfefff
+-    },
+-    ._custom = {
+-	.name = "Custom I/O", .start = 0x00dff000, .end = 0x00dfffff
+-    },
+-    ._kickstart = {
+-	.name = "Kickstart ROM", .start = 0x00f80000, .end = 0x00ffffff
+-    }
++	._ciab = {
++		.name = "CIA B", .start = 0x00bfd000, .end = 0x00bfdfff
++	},
++	._ciaa = {
++		.name = "CIA A", .start = 0x00bfe000, .end = 0x00bfefff
++	},
++	._custom = {
++		.name = "Custom I/O", .start = 0x00dff000, .end = 0x00dfffff
++	},
++	._kickstart = {
++		.name = "Kickstart ROM", .start = 0x00f80000, .end = 0x00ffffff
++	}
+ };
+ 
+ static struct resource rtc_resource = {
+-    .start = 0x00dc0000, .end = 0x00dcffff
++	.start = 0x00dc0000, .end = 0x00dcffff
+ };
+ 
+ static struct resource ram_resource[NUM_MEMINFO];
+@@ -148,57 +146,57 @@ static struct resource ram_resource[NUM_
+ 
+ int amiga_parse_bootinfo(const struct bi_record *record)
+ {
+-    int unknown = 0;
+-    const unsigned long *data = record->data;
++	int unknown = 0;
++	const unsigned long *data = record->data;
+ 
+-    switch (record->tag) {
++	switch (record->tag) {
+ 	case BI_AMIGA_MODEL:
+-	    amiga_model = *data;
+-	    break;
++		amiga_model = *data;
++		break;
+ 
+ 	case BI_AMIGA_ECLOCK:
+-	    amiga_eclock = *data;
+-	    break;
++		amiga_eclock = *data;
++		break;
+ 
+ 	case BI_AMIGA_CHIPSET:
+-	    amiga_chipset = *data;
+-	    break;
++		amiga_chipset = *data;
++		break;
+ 
+ 	case BI_AMIGA_CHIP_SIZE:
+-	    amiga_chip_size = *(const int *)data;
+-	    break;
++		amiga_chip_size = *(const int *)data;
++		break;
+ 
+ 	case BI_AMIGA_VBLANK:
+-	    amiga_vblank = *(const unsigned char *)data;
+-	    break;
++		amiga_vblank = *(const unsigned char *)data;
++		break;
+ 
+ 	case BI_AMIGA_PSFREQ:
+-	    amiga_psfreq = *(const unsigned char *)data;
+-	    break;
++		amiga_psfreq = *(const unsigned char *)data;
++		break;
+ 
+ 	case BI_AMIGA_AUTOCON:
+ #ifdef CONFIG_ZORRO
+-	    if (zorro_num_autocon < ZORRO_NUM_AUTO) {
+-		const struct ConfigDev *cd = (struct ConfigDev *)data;
+-		struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
+-		dev->rom = cd->cd_Rom;
+-		dev->slotaddr = cd->cd_SlotAddr;
+-		dev->slotsize = cd->cd_SlotSize;
+-		dev->resource.start = (unsigned long)cd->cd_BoardAddr;
+-		dev->resource.end = dev->resource.start+cd->cd_BoardSize-1;
+-	    } else
+-		printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
++		if (zorro_num_autocon < ZORRO_NUM_AUTO) {
++			const struct ConfigDev *cd = (struct ConfigDev *)data;
++			struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
++			dev->rom = cd->cd_Rom;
++			dev->slotaddr = cd->cd_SlotAddr;
++			dev->slotsize = cd->cd_SlotSize;
++			dev->resource.start = (unsigned long)cd->cd_BoardAddr;
++			dev->resource.end = dev->resource.start + cd->cd_BoardSize - 1;
++		} else
++			printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
+ #endif /* CONFIG_ZORRO */
+-	    break;
++		break;
+ 
+ 	case BI_AMIGA_SERPER:
+-	    /* serial port period: ignored here */
+-	    break;
++		/* serial port period: ignored here */
++		break;
+ 
+ 	default:
+-	    unknown = 1;
+-    }
+-    return(unknown);
++		unknown = 1;
++	}
++	return unknown;
+ }
+ 
+     /*
+@@ -207,159 +205,159 @@ int amiga_parse_bootinfo(const struct bi
+ 
+ static void __init amiga_identify(void)
+ {
+-  /* Fill in some default values, if necessary */
+-  if (amiga_eclock == 0)
+-    amiga_eclock = 709379;
+-
+-  memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
+-
+-  printk("Amiga hardware found: ");
+-  if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
+-    printk("[%s] ", amiga_models[amiga_model-AMI_500]);
+-    strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
+-  }
+-
+-  switch(amiga_model) {
+-  case AMI_UNKNOWN:
+-    goto Generic;
+-
+-  case AMI_600:
+-  case AMI_1200:
+-    AMIGAHW_SET(A1200_IDE);
+-    AMIGAHW_SET(PCMCIA);
+-  case AMI_500:
+-  case AMI_500PLUS:
+-  case AMI_1000:
+-  case AMI_2000:
+-  case AMI_2500:
+-    AMIGAHW_SET(A2000_CLK);	/* Is this correct for all models? */
+-    goto Generic;
+-
+-  case AMI_3000:
+-  case AMI_3000T:
+-    AMIGAHW_SET(AMBER_FF);
+-    AMIGAHW_SET(MAGIC_REKICK);
+-    /* fall through */
+-  case AMI_3000PLUS:
+-    AMIGAHW_SET(A3000_SCSI);
+-    AMIGAHW_SET(A3000_CLK);
+-    AMIGAHW_SET(ZORRO3);
+-    goto Generic;
+-
+-  case AMI_4000T:
+-    AMIGAHW_SET(A4000_SCSI);
+-    /* fall through */
+-  case AMI_4000:
+-    AMIGAHW_SET(A4000_IDE);
+-    AMIGAHW_SET(A3000_CLK);
+-    AMIGAHW_SET(ZORRO3);
+-    goto Generic;
+-
+-  case AMI_CDTV:
+-  case AMI_CD32:
+-    AMIGAHW_SET(CD_ROM);
+-    AMIGAHW_SET(A2000_CLK);             /* Is this correct? */
+-    goto Generic;
+-
+-  Generic:
+-    AMIGAHW_SET(AMI_VIDEO);
+-    AMIGAHW_SET(AMI_BLITTER);
+-    AMIGAHW_SET(AMI_AUDIO);
+-    AMIGAHW_SET(AMI_FLOPPY);
+-    AMIGAHW_SET(AMI_KEYBOARD);
+-    AMIGAHW_SET(AMI_MOUSE);
+-    AMIGAHW_SET(AMI_SERIAL);
+-    AMIGAHW_SET(AMI_PARALLEL);
+-    AMIGAHW_SET(CHIP_RAM);
+-    AMIGAHW_SET(PAULA);
+-
+-    switch(amiga_chipset) {
+-    case CS_OCS:
+-    case CS_ECS:
+-    case CS_AGA:
+-      switch (amiga_custom.deniseid & 0xf) {
+-      case 0x0c:
+-	AMIGAHW_SET(DENISE_HR);
+-	break;
+-      case 0x08:
+-	AMIGAHW_SET(LISA);
+-	break;
+-      }
+-      break;
+-    default:
+-      AMIGAHW_SET(DENISE);
+-      break;
+-    }
+-    switch ((amiga_custom.vposr>>8) & 0x7f) {
+-    case 0x00:
+-      AMIGAHW_SET(AGNUS_PAL);
+-      break;
+-    case 0x10:
+-      AMIGAHW_SET(AGNUS_NTSC);
+-      break;
+-    case 0x20:
+-    case 0x21:
+-      AMIGAHW_SET(AGNUS_HR_PAL);
+-      break;
+-    case 0x30:
+-    case 0x31:
+-      AMIGAHW_SET(AGNUS_HR_NTSC);
+-      break;
+-    case 0x22:
+-    case 0x23:
+-      AMIGAHW_SET(ALICE_PAL);
+-      break;
+-    case 0x32:
+-    case 0x33:
+-      AMIGAHW_SET(ALICE_NTSC);
+-      break;
+-    }
+-    AMIGAHW_SET(ZORRO);
+-    break;
+-
+-  case AMI_DRACO:
+-    panic("No support for Draco yet");
+-
+-  default:
+-    panic("Unknown Amiga Model");
+-  }
++	/* Fill in some default values, if necessary */
++	if (amiga_eclock == 0)
++		amiga_eclock = 709379;
++
++	memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
++
++	printk("Amiga hardware found: ");
++	if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
++		printk("[%s] ", amiga_models[amiga_model-AMI_500]);
++		strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
++	}
++
++	switch (amiga_model) {
++	case AMI_UNKNOWN:
++		goto Generic;
++
++	case AMI_600:
++	case AMI_1200:
++		AMIGAHW_SET(A1200_IDE);
++		AMIGAHW_SET(PCMCIA);
++	case AMI_500:
++	case AMI_500PLUS:
++	case AMI_1000:
++	case AMI_2000:
++	case AMI_2500:
++		AMIGAHW_SET(A2000_CLK);	/* Is this correct for all models? */
++		goto Generic;
++
++	case AMI_3000:
++	case AMI_3000T:
++		AMIGAHW_SET(AMBER_FF);
++		AMIGAHW_SET(MAGIC_REKICK);
++		/* fall through */
++	case AMI_3000PLUS:
++		AMIGAHW_SET(A3000_SCSI);
++		AMIGAHW_SET(A3000_CLK);
++		AMIGAHW_SET(ZORRO3);
++		goto Generic;
++
++	case AMI_4000T:
++		AMIGAHW_SET(A4000_SCSI);
++		/* fall through */
++	case AMI_4000:
++		AMIGAHW_SET(A4000_IDE);
++		AMIGAHW_SET(A3000_CLK);
++		AMIGAHW_SET(ZORRO3);
++		goto Generic;
++
++	case AMI_CDTV:
++	case AMI_CD32:
++		AMIGAHW_SET(CD_ROM);
++		AMIGAHW_SET(A2000_CLK);             /* Is this correct? */
++		goto Generic;
++
++	Generic:
++		AMIGAHW_SET(AMI_VIDEO);
++		AMIGAHW_SET(AMI_BLITTER);
++		AMIGAHW_SET(AMI_AUDIO);
++		AMIGAHW_SET(AMI_FLOPPY);
++		AMIGAHW_SET(AMI_KEYBOARD);
++		AMIGAHW_SET(AMI_MOUSE);
++		AMIGAHW_SET(AMI_SERIAL);
++		AMIGAHW_SET(AMI_PARALLEL);
++		AMIGAHW_SET(CHIP_RAM);
++		AMIGAHW_SET(PAULA);
++
++		switch (amiga_chipset) {
++		case CS_OCS:
++		case CS_ECS:
++		case CS_AGA:
++			switch (amiga_custom.deniseid & 0xf) {
++			case 0x0c:
++				AMIGAHW_SET(DENISE_HR);
++				break;
++			case 0x08:
++				AMIGAHW_SET(LISA);
++				break;
++			}
++			break;
++		default:
++			AMIGAHW_SET(DENISE);
++			break;
++		}
++		switch ((amiga_custom.vposr>>8) & 0x7f) {
++		case 0x00:
++			AMIGAHW_SET(AGNUS_PAL);
++			break;
++		case 0x10:
++			AMIGAHW_SET(AGNUS_NTSC);
++			break;
++		case 0x20:
++		case 0x21:
++			AMIGAHW_SET(AGNUS_HR_PAL);
++			break;
++		case 0x30:
++		case 0x31:
++			AMIGAHW_SET(AGNUS_HR_NTSC);
++			break;
++		case 0x22:
++		case 0x23:
++			AMIGAHW_SET(ALICE_PAL);
++			break;
++		case 0x32:
++		case 0x33:
++			AMIGAHW_SET(ALICE_NTSC);
++			break;
++		}
++		AMIGAHW_SET(ZORRO);
++		break;
+ 
+-#define AMIGAHW_ANNOUNCE(name, str)			\
+-  if (AMIGAHW_PRESENT(name))				\
+-    printk(str)
++	case AMI_DRACO:
++		panic("No support for Draco yet");
++
++	default:
++		panic("Unknown Amiga Model");
++	}
+ 
+-  AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
+-  AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
+-  AMIGAHW_ANNOUNCE(AMBER_FF, "AMBER_FF ");
+-  AMIGAHW_ANNOUNCE(AMI_AUDIO, "AUDIO ");
+-  AMIGAHW_ANNOUNCE(AMI_FLOPPY, "FLOPPY ");
+-  AMIGAHW_ANNOUNCE(A3000_SCSI, "A3000_SCSI ");
+-  AMIGAHW_ANNOUNCE(A4000_SCSI, "A4000_SCSI ");
+-  AMIGAHW_ANNOUNCE(A1200_IDE, "A1200_IDE ");
+-  AMIGAHW_ANNOUNCE(A4000_IDE, "A4000_IDE ");
+-  AMIGAHW_ANNOUNCE(CD_ROM, "CD_ROM ");
+-  AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "KEYBOARD ");
+-  AMIGAHW_ANNOUNCE(AMI_MOUSE, "MOUSE ");
+-  AMIGAHW_ANNOUNCE(AMI_SERIAL, "SERIAL ");
+-  AMIGAHW_ANNOUNCE(AMI_PARALLEL, "PARALLEL ");
+-  AMIGAHW_ANNOUNCE(A2000_CLK, "A2000_CLK ");
+-  AMIGAHW_ANNOUNCE(A3000_CLK, "A3000_CLK ");
+-  AMIGAHW_ANNOUNCE(CHIP_RAM, "CHIP_RAM ");
+-  AMIGAHW_ANNOUNCE(PAULA, "PAULA ");
+-  AMIGAHW_ANNOUNCE(DENISE, "DENISE ");
+-  AMIGAHW_ANNOUNCE(DENISE_HR, "DENISE_HR ");
+-  AMIGAHW_ANNOUNCE(LISA, "LISA ");
+-  AMIGAHW_ANNOUNCE(AGNUS_PAL, "AGNUS_PAL ");
+-  AMIGAHW_ANNOUNCE(AGNUS_NTSC, "AGNUS_NTSC ");
+-  AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "AGNUS_HR_PAL ");
+-  AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "AGNUS_HR_NTSC ");
+-  AMIGAHW_ANNOUNCE(ALICE_PAL, "ALICE_PAL ");
+-  AMIGAHW_ANNOUNCE(ALICE_NTSC, "ALICE_NTSC ");
+-  AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
+-  AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA ");
+-  if (AMIGAHW_PRESENT(ZORRO))
+-    printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
+-  printk("\n");
++#define AMIGAHW_ANNOUNCE(name, str)		\
++	if (AMIGAHW_PRESENT(name))		\
++		printk(str)
++
++	AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
++	AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
++	AMIGAHW_ANNOUNCE(AMBER_FF, "AMBER_FF ");
++	AMIGAHW_ANNOUNCE(AMI_AUDIO, "AUDIO ");
++	AMIGAHW_ANNOUNCE(AMI_FLOPPY, "FLOPPY ");
++	AMIGAHW_ANNOUNCE(A3000_SCSI, "A3000_SCSI ");
++	AMIGAHW_ANNOUNCE(A4000_SCSI, "A4000_SCSI ");
++	AMIGAHW_ANNOUNCE(A1200_IDE, "A1200_IDE ");
++	AMIGAHW_ANNOUNCE(A4000_IDE, "A4000_IDE ");
++	AMIGAHW_ANNOUNCE(CD_ROM, "CD_ROM ");
++	AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "KEYBOARD ");
++	AMIGAHW_ANNOUNCE(AMI_MOUSE, "MOUSE ");
++	AMIGAHW_ANNOUNCE(AMI_SERIAL, "SERIAL ");
++	AMIGAHW_ANNOUNCE(AMI_PARALLEL, "PARALLEL ");
++	AMIGAHW_ANNOUNCE(A2000_CLK, "A2000_CLK ");
++	AMIGAHW_ANNOUNCE(A3000_CLK, "A3000_CLK ");
++	AMIGAHW_ANNOUNCE(CHIP_RAM, "CHIP_RAM ");
++	AMIGAHW_ANNOUNCE(PAULA, "PAULA ");
++	AMIGAHW_ANNOUNCE(DENISE, "DENISE ");
++	AMIGAHW_ANNOUNCE(DENISE_HR, "DENISE_HR ");
++	AMIGAHW_ANNOUNCE(LISA, "LISA ");
++	AMIGAHW_ANNOUNCE(AGNUS_PAL, "AGNUS_PAL ");
++	AMIGAHW_ANNOUNCE(AGNUS_NTSC, "AGNUS_NTSC ");
++	AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "AGNUS_HR_PAL ");
++	AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "AGNUS_HR_NTSC ");
++	AMIGAHW_ANNOUNCE(ALICE_PAL, "ALICE_PAL ");
++	AMIGAHW_ANNOUNCE(ALICE_NTSC, "ALICE_NTSC ");
++	AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
++	AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA ");
++	if (AMIGAHW_PRESENT(ZORRO))
++		printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
++	printk("\n");
+ 
+ #undef AMIGAHW_ANNOUNCE
+ }
+@@ -370,119 +368,117 @@ static void __init amiga_identify(void)
+ 
+ void __init config_amiga(void)
+ {
+-  int i;
++	int i;
++
++	amiga_debug_init();
++	amiga_identify();
+ 
+-  amiga_debug_init();
+-  amiga_identify();
++	/* Yuk, we don't have PCI memory */
++	iomem_resource.name = "Memory";
++	for (i = 0; i < 4; i++)
++		request_resource(&iomem_resource, &((struct resource *)&mb_resources)[i]);
++
++	mach_sched_init      = amiga_sched_init;
++	mach_init_IRQ        = amiga_init_IRQ;
++	mach_get_model       = amiga_get_model;
++	mach_get_hardware_list = amiga_get_hardware_list;
++	mach_gettimeoffset   = amiga_gettimeoffset;
++	if (AMIGAHW_PRESENT(A3000_CLK)) {
++		mach_hwclk         = a3000_hwclk;
++		rtc_resource.name = "A3000 RTC";
++		request_resource(&iomem_resource, &rtc_resource);
++	} else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
++		mach_hwclk         = a2000_hwclk;
++		rtc_resource.name = "A2000 RTC";
++		request_resource(&iomem_resource, &rtc_resource);
++	}
+ 
+-  /* Yuk, we don't have PCI memory */
+-  iomem_resource.name = "Memory";
+-  for (i = 0; i < 4; i++)
+-    request_resource(&iomem_resource, &((struct resource *)&mb_resources)[i]);
+-
+-  mach_sched_init      = amiga_sched_init;
+-  mach_init_IRQ        = amiga_init_IRQ;
+-  mach_get_model       = amiga_get_model;
+-  mach_get_hardware_list = amiga_get_hardware_list;
+-  mach_gettimeoffset   = amiga_gettimeoffset;
+-  if (AMIGAHW_PRESENT(A3000_CLK)){
+-    mach_hwclk         = a3000_hwclk;
+-    rtc_resource.name = "A3000 RTC";
+-    request_resource(&iomem_resource, &rtc_resource);
+-  }
+-  else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */
+-    mach_hwclk         = a2000_hwclk;
+-    rtc_resource.name = "A2000 RTC";
+-    request_resource(&iomem_resource, &rtc_resource);
+-  }
+-
+-  mach_max_dma_address = 0xffffffff; /*
+-				      * default MAX_DMA=0xffffffff
+-				      * on all machines. If we don't
+-				      * do so, the SCSI code will not
+-				      * be able to allocate any mem
+-				      * for transfers, unless we are
+-				      * dealing with a Z2 mem only
+-				      * system.                  /Jes
+-				      */
+-
+-  mach_set_clock_mmss  = amiga_set_clock_mmss;
+-  mach_get_ss          = amiga_get_ss;
+-  mach_reset           = amiga_reset;
++	/*
++	 * default MAX_DMA=0xffffffff on all machines. If we don't do so, the SCSI
++	 * code will not be able to allocate any mem for transfers, unless we are
++	 * dealing with a Z2 mem only system.                  /Jes
++	 */
++	mach_max_dma_address = 0xffffffff;
++
++	mach_set_clock_mmss  = amiga_set_clock_mmss;
++	mach_get_ss          = amiga_get_ss;
++	mach_reset           = amiga_reset;
+ #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
+-  mach_beep            = amiga_mksound;
++	mach_beep            = amiga_mksound;
+ #endif
+ 
+ #ifdef CONFIG_HEARTBEAT
+-  mach_heartbeat = amiga_heartbeat;
++	mach_heartbeat = amiga_heartbeat;
+ #endif
+ 
+-  /* Fill in the clock values (based on the 700 kHz E-Clock) */
+-  amiga_masterclock = 40*amiga_eclock;	/* 28 MHz */
+-  amiga_colorclock = 5*amiga_eclock;	/* 3.5 MHz */
+-
+-  /* clear all DMA bits */
+-  amiga_custom.dmacon = DMAF_ALL;
+-  /* ensure that the DMA master bit is set */
+-  amiga_custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
+-
+-  /* don't use Z2 RAM as system memory on Z3 capable machines */
+-  if (AMIGAHW_PRESENT(ZORRO3)) {
+-    int i, j;
+-    u32 disabled_z2mem = 0;
+-    for (i = 0; i < m68k_num_memory; i++)
+-      if (m68k_memory[i].addr < 16*1024*1024) {
+-	if (i == 0) {
+-	  /* don't cut off the branch we're sitting on */
+-	  printk("Warning: kernel runs in Zorro II memory\n");
+-	  continue;
+-	}
+-	disabled_z2mem += m68k_memory[i].size;
+-	m68k_num_memory--;
+-	for (j = i; j < m68k_num_memory; j++)
+-	  m68k_memory[j] = m68k_memory[j+1];
+-	i--;
+-      }
+-    if (disabled_z2mem)
+-      printk("%dK of Zorro II memory will not be used as system memory\n",
+-	     disabled_z2mem>>10);
+-  }
+-
+-  /* request all RAM */
+-  for (i = 0; i < m68k_num_memory; i++) {
+-    ram_resource[i].name =
+-      (m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" :
+-      (m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" :
+-      "16-bit Slow RAM";
+-    ram_resource[i].start = m68k_memory[i].addr;
+-    ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1;
+-    request_resource(&iomem_resource, &ram_resource[i]);
+-  }
+-
+-  /* initialize chipram allocator */
+-  amiga_chip_init ();
+-
+-  /* debugging using chipram */
+-  if (!strcmp( m68k_debug_device, "mem" )){
+-	  if (!AMIGAHW_PRESENT(CHIP_RAM))
+-		  printk("Warning: no chipram present for debugging\n");
+-	  else {
+-		  amiga_savekmsg_init();
+-		  amiga_console_driver.write = amiga_mem_console_write;
+-		  register_console(&amiga_console_driver);
+-	  }
+-  }
+-
+-  /* our beloved beeper */
+-  if (AMIGAHW_PRESENT(AMI_AUDIO))
+-	  amiga_init_sound();
+-
+-  /*
+-   * if it is an A3000, set the magic bit that forces
+-   * a hard rekick
+-   */
+-  if (AMIGAHW_PRESENT(MAGIC_REKICK))
+-	  *(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
++	/* Fill in the clock values (based on the 700 kHz E-Clock) */
++	amiga_masterclock = 40*amiga_eclock;	/* 28 MHz */
++	amiga_colorclock = 5*amiga_eclock;	/* 3.5 MHz */
++
++	/* clear all DMA bits */
++	amiga_custom.dmacon = DMAF_ALL;
++	/* ensure that the DMA master bit is set */
++	amiga_custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
++
++	/* don't use Z2 RAM as system memory on Z3 capable machines */
++	if (AMIGAHW_PRESENT(ZORRO3)) {
++		int i, j;
++		u32 disabled_z2mem = 0;
++
++		for (i = 0; i < m68k_num_memory; i++) {
++			if (m68k_memory[i].addr < 16*1024*1024) {
++				if (i == 0) {
++					/* don't cut off the branch we're sitting on */
++					printk("Warning: kernel runs in Zorro II memory\n");
++					continue;
++				}
++				disabled_z2mem += m68k_memory[i].size;
++				m68k_num_memory--;
++				for (j = i; j < m68k_num_memory; j++)
++					m68k_memory[j] = m68k_memory[j+1];
++				i--;
++			}
++		}
++		if (disabled_z2mem)
++		printk("%dK of Zorro II memory will not be used as system memory\n",
++		disabled_z2mem>>10);
++	}
++
++	/* request all RAM */
++	for (i = 0; i < m68k_num_memory; i++) {
++		ram_resource[i].name =
++			(m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" :
++			(m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" :
++			"16-bit Slow RAM";
++		ram_resource[i].start = m68k_memory[i].addr;
++		ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1;
++		request_resource(&iomem_resource, &ram_resource[i]);
++	}
++
++	/* initialize chipram allocator */
++	amiga_chip_init();
++
++	/* debugging using chipram */
++	if (!strcmp(m68k_debug_device, "mem")) {
++		if (!AMIGAHW_PRESENT(CHIP_RAM))
++			printk("Warning: no chipram present for debugging\n");
++		else {
++			amiga_savekmsg_init();
++			amiga_console_driver.write = amiga_mem_console_write;
++			register_console(&amiga_console_driver);
++		}
++	}
++
++	/* our beloved beeper */
++	if (AMIGAHW_PRESENT(AMI_AUDIO))
++		amiga_init_sound();
++
++	/*
++	 * if it is an A3000, set the magic bit that forces
++	 * a hard rekick
++	 */
++	if (AMIGAHW_PRESENT(MAGIC_REKICK))
++		*(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
+ }
+ 
+ static unsigned short jiffy_ticks;
+@@ -490,12 +486,12 @@ static unsigned short jiffy_ticks;
+ static void __init amiga_sched_init(irq_handler_t timer_routine)
+ {
+ 	static struct resource sched_res = {
+-	    .name = "timer", .start = 0x00bfd400, .end = 0x00bfd5ff,
++		.name = "timer", .start = 0x00bfd400, .end = 0x00bfd5ff,
+ 	};
+ 	jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
+ 
+ 	if (request_resource(&mb_resources._ciab, &sched_res))
+-	    printk("Cannot allocate ciab.ta{lo,hi}\n");
++		printk("Cannot allocate ciab.ta{lo,hi}\n");
+ 	ciab.cra &= 0xC0;   /* turn off timer A, continuous mode, from Eclk */
+ 	ciab.talo = jiffy_ticks % 256;
+ 	ciab.tahi = jiffy_ticks / 256;
+@@ -513,7 +509,7 @@ static void __init amiga_sched_init(irq_
+ #define TICK_SIZE 10000
+ 
+ /* This is always executed with interrupts disabled.  */
+-static unsigned long amiga_gettimeoffset (void)
++static unsigned long amiga_gettimeoffset(void)
+ {
+ 	unsigned short hi, lo, hi2;
+ 	unsigned long ticks, offset = 0;
+@@ -585,15 +581,15 @@ static int a2000_hwclk(int op, struct rt
+ 
+ 	tod_2000.cntrl1 = TOD2000_CNTRL1_HOLD;
+ 
+-	while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--)
+-	{
+-	        tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+-	        udelay(70);
+-	        tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
++	while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) {
++		tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
++		udelay(70);
++		tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
+ 	}
+ 
+ 	if (!cnt)
+-		printk(KERN_INFO "hwclk: timed out waiting for RTC (0x%x)\n", tod_2000.cntrl1);
++		printk(KERN_INFO "hwclk: timed out waiting for RTC (0x%x)\n",
++			tod_2000.cntrl1);
+ 
+ 	if (!op) { /* read */
+ 		t->tm_sec  = tod_2000.second1     * 10 + tod_2000.second2;
+@@ -606,7 +602,7 @@ static int a2000_hwclk(int op, struct rt
+ 		if (t->tm_year <= 69)
+ 			t->tm_year += 100;
+ 
+-		if (!(tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)){
++		if (!(tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)) {
+ 			if (!(tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour == 12)
+ 				t->tm_hour = 0;
+ 			else if ((tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour != 12)
+@@ -642,7 +638,7 @@ static int a2000_hwclk(int op, struct rt
+ 	return 0;
+ }
+ 
+-static int amiga_set_clock_mmss (unsigned long nowtime)
++static int amiga_set_clock_mmss(unsigned long nowtime)
+ {
+ 	short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
+ 
+@@ -660,8 +656,7 @@ static int amiga_set_clock_mmss (unsigne
+ 
+ 		tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
+ 
+-		while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--)
+-		{
++		while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) {
+ 			tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+ 			udelay(70);
+ 			tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
+@@ -681,7 +676,7 @@ static int amiga_set_clock_mmss (unsigne
+ 	return 0;
+ }
+ 
+-static unsigned int amiga_get_ss( void )
++static unsigned int amiga_get_ss(void)
+ {
+ 	unsigned int s;
+ 
+@@ -695,71 +690,72 @@ static unsigned int amiga_get_ss( void )
+ 	return s;
+ }
+ 
+-static NORET_TYPE void amiga_reset( void )
++static NORET_TYPE void amiga_reset(void)
+     ATTRIB_NORET;
+ 
+-static void amiga_reset (void)
++static void amiga_reset(void)
+ {
+-  unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
+-  unsigned long jmp_addr = virt_to_phys(&&jmp_addr_label);
+-
+-  local_irq_disable();
+-  if (CPU_IS_040_OR_060)
+-    /* Setup transparent translation registers for mapping
+-     * of 16 MB kernel segment before disabling translation
+-     */
+-    __asm__ __volatile__
+-      ("movel    %0,%/d0\n\t"
+-       "andl     #0xff000000,%/d0\n\t"
+-       "orw      #0xe020,%/d0\n\t"   /* map 16 MB, enable, cacheable */
+-       ".chip    68040\n\t"
+-       "movec    %%d0,%%itt0\n\t"
+-       "movec    %%d0,%%dtt0\n\t"
+-       ".chip    68k\n\t"
+-       "jmp      %0@\n\t"
+-       : /* no outputs */
+-       : "a" (jmp_addr040));
+-  else
+-    /* for 680[23]0, just disable translation and jump to the physical
+-     * address of the label
+-     */
+-    __asm__ __volatile__
+-      ("pmove  %/tc,%@\n\t"
+-       "bclr   #7,%@\n\t"
+-       "pmove  %@,%/tc\n\t"
+-       "jmp    %0@\n\t"
+-       : /* no outputs */
+-       : "a" (jmp_addr));
+- jmp_addr_label040:
+-  /* disable translation on '040 now */
+-  __asm__ __volatile__
+-    ("moveq #0,%/d0\n\t"
+-     ".chip 68040\n\t"
+-     "movec %%d0,%%tc\n\t"	/* disable MMU */
+-     ".chip 68k\n\t"
+-     : /* no outputs */
+-     : /* no inputs */
+-     : "d0");
+-
+- jmp_addr_label:
+-  /* pickup reset address from AmigaOS ROM, reset devices and jump
+-   * to reset address
+-   */
+-  __asm__ __volatile__
+-    ("movew #0x2700,%/sr\n\t"
+-     "leal  0x01000000,%/a0\n\t"
+-     "subl  %/a0@(-0x14),%/a0\n\t"
+-     "movel %/a0@(4),%/a0\n\t"
+-     "subql #2,%/a0\n\t"
+-     "bra   1f\n\t"
+-     /* align on a longword boundary */
+-     __ALIGN_STR "\n"
+-     "1:\n\t"
+-     "reset\n\t"
+-     "jmp   %/a0@" : /* Just that gcc scans it for % escapes */ );
++	unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
++	unsigned long jmp_addr = virt_to_phys(&&jmp_addr_label);
+ 
+-  for (;;);
++	local_irq_disable();
++	if (CPU_IS_040_OR_060)
++		/* Setup transparent translation registers for mapping
++		 * of 16 MB kernel segment before disabling translation
++		 */
++		asm volatile ("\n"
++			"	move.l	%0,%%d0\n"
++			"	and.l	#0xff000000,%%d0\n"
++			"	or.w	#0xe020,%%d0\n"   /* map 16 MB, enable, cacheable */
++			"	.chip	68040\n"
++			"	movec	%%d0,%%itt0\n"
++			"	movec	%%d0,%%dtt0\n"
++			"	.chip	68k\n"
++			"	jmp	%0@\n"
++			: /* no outputs */
++			: "a" (jmp_addr040)
++			: "d0");
++	else
++		/* for 680[23]0, just disable translation and jump to the physical
++		 * address of the label
++		 */
++		asm volatile ("\n"
++			"	pmove	%%tc,%@\n"
++			"	bclr	#7,%@\n"
++			"	pmove	%@,%%tc\n"
++			"	jmp	%0@\n"
++			: /* no outputs */
++			: "a" (jmp_addr));
++jmp_addr_label040:
++	/* disable translation on '040 now */
++	asm volatile ("\n"
++		"	moveq	#0,%%d0\n"
++		"	.chip	68040\n"
++		"	movec	%%d0,%%tc\n"	/* disable MMU */
++		"	.chip	68k\n"
++		: /* no outputs */
++		: /* no inputs */
++		: "d0");
++
++	jmp_addr_label:
++	/* pickup reset address from AmigaOS ROM, reset devices and jump
++	 * to reset address
++	 */
++	asm volatile ("\n"
++		"	move.w	#0x2700,%sr\n"
++		"	lea	0x01000000,%a0\n"
++		"	sub.l	%a0@(-0x14),%a0\n"
++		"	move.l	%a0@(4),%a0\n"
++		"	subq.l	#2,%a0\n"
++		"	jra	1f\n"
++		/* align on a longword boundary */
++		"	" __ALIGN_STR "\n"
++		"1:\n"
++		"	reset\n"
++		"	jmp   %a0@");
+ 
++	for (;;)
++		;
+ }
+ 
+ 
+@@ -773,11 +769,11 @@ static void amiga_reset (void)
+ #define SAVEKMSG_MAGIC2		0x4B4D5347	/* 'KMSG' */
+ 
+ struct savekmsg {
+-    unsigned long magic1;		/* SAVEKMSG_MAGIC1 */
+-    unsigned long magic2;		/* SAVEKMSG_MAGIC2 */
+-    unsigned long magicptr;		/* address of magic1 */
+-    unsigned long size;
+-    char data[0];
++	unsigned long magic1;		/* SAVEKMSG_MAGIC1 */
++	unsigned long magic2;		/* SAVEKMSG_MAGIC2 */
++	unsigned long magicptr;		/* address of magic1 */
++	unsigned long size;
++	char data[0];
+ };
+ 
+ static struct savekmsg *savekmsg;
+@@ -785,100 +781,100 @@ static struct savekmsg *savekmsg;
+ static void amiga_mem_console_write(struct console *co, const char *s,
+ 				    unsigned int count)
+ {
+-    if (savekmsg->size+count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) {
+-        memcpy(savekmsg->data+savekmsg->size, s, count);
+-        savekmsg->size += count;
+-    }
++	if (savekmsg->size + count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) {
++		memcpy(savekmsg->data + savekmsg->size, s, count);
++		savekmsg->size += count;
++	}
+ }
+ 
+ static void amiga_savekmsg_init(void)
+ {
+-    static struct resource debug_res = { .name = "Debug" };
++	static struct resource debug_res = { .name = "Debug" };
+ 
+-    savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
+-    savekmsg->magic1 = SAVEKMSG_MAGIC1;
+-    savekmsg->magic2 = SAVEKMSG_MAGIC2;
+-    savekmsg->magicptr = ZTWO_PADDR(savekmsg);
+-    savekmsg->size = 0;
++	savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
++	savekmsg->magic1 = SAVEKMSG_MAGIC1;
++	savekmsg->magic2 = SAVEKMSG_MAGIC2;
++	savekmsg->magicptr = ZTWO_PADDR(savekmsg);
++	savekmsg->size = 0;
+ }
+ 
+ static void amiga_serial_putc(char c)
+ {
+-    amiga_custom.serdat = (unsigned char)c | 0x100;
+-    while (!(amiga_custom.serdatr & 0x2000))
+-	;
++	amiga_custom.serdat = (unsigned char)c | 0x100;
++	while (!(amiga_custom.serdatr & 0x2000))
++		;
+ }
+ 
+ void amiga_serial_console_write(struct console *co, const char *s,
+-				       unsigned int count)
++				unsigned int count)
+ {
+-    while (count--) {
+-	if (*s == '\n')
+-	    amiga_serial_putc('\r');
+-	amiga_serial_putc(*s++);
+-    }
++	while (count--) {
++		if (*s == '\n')
++			amiga_serial_putc('\r');
++		amiga_serial_putc(*s++);
++	}
+ }
+ 
+ #ifdef CONFIG_SERIAL_CONSOLE
+ void amiga_serial_puts(const char *s)
+ {
+-    amiga_serial_console_write(NULL, s, strlen(s));
++	amiga_serial_console_write(NULL, s, strlen(s));
+ }
+ 
+ int amiga_serial_console_wait_key(struct console *co)
+ {
+-    int ch;
++	int ch;
+ 
+-    while (!(amiga_custom.intreqr & IF_RBF))
+-	barrier();
+-    ch = amiga_custom.serdatr & 0xff;
+-    /* clear the interrupt, so that another character can be read */
+-    amiga_custom.intreq = IF_RBF;
+-    return ch;
++	while (!(amiga_custom.intreqr & IF_RBF))
++		barrier();
++	ch = amiga_custom.serdatr & 0xff;
++	/* clear the interrupt, so that another character can be read */
++	amiga_custom.intreq = IF_RBF;
++	return ch;
+ }
+ 
+ void amiga_serial_gets(struct console *co, char *s, int len)
+ {
+-    int ch, cnt = 0;
++	int ch, cnt = 0;
++
++	while (1) {
++		ch = amiga_serial_console_wait_key(co);
+ 
+-    while (1) {
+-	ch = amiga_serial_console_wait_key(co);
++		/* Check for backspace. */
++		if (ch == 8 || ch == 127) {
++			if (cnt == 0) {
++				amiga_serial_putc('\007');
++				continue;
++			}
++			cnt--;
++			amiga_serial_puts("\010 \010");
++			continue;
++		}
++
++		/* Check for enter. */
++		if (ch == 10 || ch == 13)
++			break;
++
++		/* See if line is too long. */
++		if (cnt >= len + 1) {
++			amiga_serial_putc(7);
++			cnt--;
++			continue;
++		}
+ 
+-	/* Check for backspace. */
+-	if (ch == 8 || ch == 127) {
+-	    if (cnt == 0) {
+-		amiga_serial_putc('\007');
+-		continue;
+-	    }
+-	    cnt--;
+-	    amiga_serial_puts("\010 \010");
+-	    continue;
+-	}
+-
+-	/* Check for enter. */
+-	if (ch == 10 || ch == 13)
+-	    break;
+-
+-	/* See if line is too long. */
+-	if (cnt >= len + 1) {
+-	    amiga_serial_putc(7);
+-	    cnt--;
+-	    continue;
+-	}
+-
+-	/* Store and echo character. */
+-	s[cnt++] = ch;
+-	amiga_serial_putc(ch);
+-    }
+-    /* Print enter. */
+-    amiga_serial_puts("\r\n");
+-    s[cnt] = 0;
++		/* Store and echo character. */
++		s[cnt++] = ch;
++		amiga_serial_putc(ch);
++	}
++	/* Print enter. */
++	amiga_serial_puts("\r\n");
++	s[cnt] = 0;
+ }
+ #endif
+ 
+ static void __init amiga_debug_init(void)
+ {
+-	if (!strcmp( m68k_debug_device, "ser" )) {
++	if (!strcmp(m68k_debug_device, "ser" )) {
+ 		/* no initialization required (?) */
+ 		amiga_console_driver.write = amiga_serial_console_write;
+ 		register_console(&amiga_console_driver);
+@@ -888,10 +884,10 @@ static void __init amiga_debug_init(void
+ #ifdef CONFIG_HEARTBEAT
+ static void amiga_heartbeat(int on)
+ {
+-    if (on)
+-	ciaa.pra &= ~2;
+-    else
+-	ciaa.pra |= 2;
++	if (on)
++		ciaa.pra &= ~2;
++	else
++		ciaa.pra |= 2;
+ }
+ #endif
+ 
+@@ -901,81 +897,81 @@ static void amiga_heartbeat(int on)
+ 
+ static void amiga_get_model(char *model)
+ {
+-    strcpy(model, amiga_model_name);
++	strcpy(model, amiga_model_name);
+ }
+ 
+ 
+ static int amiga_get_hardware_list(char *buffer)
+ {
+-    int len = 0;
++	int len = 0;
+ 
+-    if (AMIGAHW_PRESENT(CHIP_RAM))
+-	len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10);
+-    len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n",
+-		   amiga_psfreq, amiga_eclock);
+-    if (AMIGAHW_PRESENT(AMI_VIDEO)) {
+-	char *type;
+-	switch(amiga_chipset) {
+-	    case CS_OCS:
+-		type = "OCS";
+-		break;
+-	    case CS_ECS:
+-		type = "ECS";
+-		break;
+-	    case CS_AGA:
+-		type = "AGA";
+-		break;
+-	    default:
+-		type = "Old or Unknown";
+-		break;
++	if (AMIGAHW_PRESENT(CHIP_RAM))
++		len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10);
++	len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n",
++			amiga_psfreq, amiga_eclock);
++	if (AMIGAHW_PRESENT(AMI_VIDEO)) {
++		char *type;
++		switch (amiga_chipset) {
++		case CS_OCS:
++			type = "OCS";
++			break;
++		case CS_ECS:
++			type = "ECS";
++			break;
++		case CS_AGA:
++			type = "AGA";
++			break;
++		default:
++			type = "Old or Unknown";
++			break;
++		}
++		len += sprintf(buffer+len, "Graphics:\t%s\n", type);
+ 	}
+-	len += sprintf(buffer+len, "Graphics:\t%s\n", type);
+-    }
+ 
+ #define AMIGAHW_ANNOUNCE(name, str)			\
+-    if (AMIGAHW_PRESENT(name))				\
+-	len += sprintf (buffer+len, "\t%s\n", str)
++	if (AMIGAHW_PRESENT(name))			\
++		len += sprintf (buffer+len, "\t%s\n", str)
+ 
+-    len += sprintf (buffer + len, "Detected hardware:\n");
++	len += sprintf (buffer + len, "Detected hardware:\n");
+ 
+-    AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
+-    AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
+-    AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
+-    AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio");
+-    AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller");
+-    AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)");
+-    AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)");
+-    AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)");
+-    AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)");
+-    AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive");
+-    AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard");
+-    AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port");
+-    AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port");
+-    AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port");
+-    AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)");
+-    AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)");
+-    AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM");
+-    AMIGAHW_ANNOUNCE(PAULA, "Paula 8364");
+-    AMIGAHW_ANNOUNCE(DENISE, "Denise 8362");
+-    AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373");
+-    AMIGAHW_ANNOUNCE(LISA, "Lisa 8375");
+-    AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371");
+-    AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370");
+-    AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372");
+-    AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372");
+-    AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374");
+-    AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374");
+-    AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick");
+-    AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot");
++	AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
++	AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
++	AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
++	AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio");
++	AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller");
++	AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)");
++	AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)");
++	AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)");
++	AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)");
++	AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive");
++	AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard");
++	AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port");
++	AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port");
++	AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port");
++	AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)");
++	AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)");
++	AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM");
++	AMIGAHW_ANNOUNCE(PAULA, "Paula 8364");
++	AMIGAHW_ANNOUNCE(DENISE, "Denise 8362");
++	AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373");
++	AMIGAHW_ANNOUNCE(LISA, "Lisa 8375");
++	AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371");
++	AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370");
++	AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372");
++	AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372");
++	AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374");
++	AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374");
++	AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick");
++	AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot");
+ #ifdef CONFIG_ZORRO
+-    if (AMIGAHW_PRESENT(ZORRO))
+-	len += sprintf(buffer+len, "\tZorro II%s AutoConfig: %d Expansion "
+-				   "Device%s\n",
+-		       AMIGAHW_PRESENT(ZORRO3) ? "I" : "",
+-		       zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
++	if (AMIGAHW_PRESENT(ZORRO))
++		len += sprintf(buffer+len, "\tZorro II%s AutoConfig: %d Expansion "
++				"Device%s\n",
++				AMIGAHW_PRESENT(ZORRO3) ? "I" : "",
++				zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
+ #endif /* CONFIG_ZORRO */
+ 
+ #undef AMIGAHW_ANNOUNCE
+ 
+-    return(len);
++	return len;
+ }
+--- linux-m68k-2.6.21.orig/arch/m68k/atari/config.c
++++ linux-m68k-2.6.21/arch/m68k/atari/config.c
+@@ -50,19 +50,19 @@ int atari_dont_touch_floppy_select;
+ int atari_rtc_year_offset;
+ 
+ /* local function prototypes */
+-static void atari_reset( void );
++static void atari_reset(void);
+ static void atari_get_model(char *model);
+ static int atari_get_hardware_list(char *buffer);
+ 
+ /* atari specific irq functions */
+ extern void atari_init_IRQ (void);
+-extern void atari_mksound( unsigned int count, unsigned int ticks );
++extern void atari_mksound(unsigned int count, unsigned int ticks);
+ #ifdef CONFIG_HEARTBEAT
+-static void atari_heartbeat( int on );
++static void atari_heartbeat(int on);
+ #endif
+ 
+ /* atari specific timer functions (in time.c) */
+-extern void atari_sched_init(irq_handler_t );
++extern void atari_sched_init(irq_handler_t);
+ extern unsigned long atari_gettimeoffset (void);
+ extern int atari_mste_hwclk (int, struct rtc_time *);
+ extern int atari_tt_hwclk (int, struct rtc_time *);
+@@ -73,48 +73,6 @@ extern int atari_tt_set_clock_mmss (unsi
+ extern void atari_debug_init(void);
+ 
+ 
+-/* I've moved hwreg_present() and hwreg_present_bywrite() out into
+- * mm/hwtest.c, to avoid having multiple copies of the same routine
+- * in the kernel [I wanted them in hp300 and they were already used
+- * in the nubus code. NB: I don't have an Atari so this might (just
+- * conceivably) break something.
+- * I've preserved the #if 0 version of hwreg_present_bywrite() here
+- * for posterity.
+- *   -- Peter Maydell <pmaydell at chiark.greenend.org.uk>, 05/1998
+- */
+-
+-#if 0
+-static int __init
+-hwreg_present_bywrite(volatile void *regp, unsigned char val)
+-{
+-    int		ret;
+-    long	save_sp, save_vbr;
+-    static long tmp_vectors[3] = { [2] = (long)&&after_test };
+-
+-    __asm__ __volatile__
+-	(	"movec	%/vbr,%2\n\t"	/* save vbr value            */
+-                "movec	%4,%/vbr\n\t"	/* set up temporary vectors  */
+-		"movel	%/sp,%1\n\t"	/* save sp                   */
+-		"moveq	#0,%0\n\t"	/* assume not present        */
+-		"moveb	%5,%3@\n\t"	/* write the hardware reg    */
+-		"cmpb	%3@,%5\n\t"	/* compare it                */
+-		"seq	%0"		/* comes here only if reg    */
+-                                        /* is present                */
+-		: "=d&" (ret), "=r&" (save_sp), "=r&" (save_vbr)
+-		: "a" (regp), "r" (tmp_vectors), "d" (val)
+-                );
+-  after_test:
+-    __asm__ __volatile__
+-      (	"movel	%0,%/sp\n\t"		/* restore sp                */
+-        "movec	%1,%/vbr"			/* restore vbr               */
+-        : : "r" (save_sp), "r" (save_vbr) : "sp"
+-	);
+-
+-    return( ret );
+-}
+-#endif
+-
+-
+ /* ++roman: This is a more elaborate test for an SCC chip, since the plain
+  * Medusa board generates DTACK at the SCC's standard addresses, but a SCC
+  * board in the Medusa is possible. Also, the addresses where the ST_ESCC
+@@ -123,26 +81,34 @@ hwreg_present_bywrite(volatile void *reg
+  * should be readable without trouble (from channel A!).
+  */
+ 
+-static int __init scc_test( volatile char *ctla )
++static int __init scc_test(volatile char *ctla)
+ {
+-	if (!hwreg_present( ctla ))
+-		return( 0 );
++	if (!hwreg_present(ctla))
++		return 0;
+ 	MFPDELAY();
+ 
+-	*ctla = 2; MFPDELAY();
+-	*ctla = 0x40; MFPDELAY();
++	*ctla = 2;
++	MFPDELAY();
++	*ctla = 0x40;
++	MFPDELAY();
+ 
+-	*ctla = 2; MFPDELAY();
+-	if (*ctla != 0x40) return( 0 );
++	*ctla = 2;
++	MFPDELAY();
++	if (*ctla != 0x40)
++		return 0;
+ 	MFPDELAY();
+ 
+-	*ctla = 2; MFPDELAY();
+-	*ctla = 0x60; MFPDELAY();
++	*ctla = 2;
++	MFPDELAY();
++	*ctla = 0x60;
++	MFPDELAY();
+ 
+-	*ctla = 2; MFPDELAY();
+-	if (*ctla != 0x60) return( 0 );
++	*ctla = 2;
++	MFPDELAY();
++	if (*ctla != 0x60)
++		return 0;
+ 
+-	return( 1 );
++	return 1;
+ }
+ 
+ 
+@@ -152,59 +118,58 @@ static int __init scc_test( volatile cha
+ 
+ int __init atari_parse_bootinfo(const struct bi_record *record)
+ {
+-    int unknown = 0;
+-    const u_long *data = record->data;
++	int unknown = 0;
++	const u_long *data = record->data;
+ 
+-    switch (record->tag) {
++	switch (record->tag) {
+ 	case BI_ATARI_MCH_COOKIE:
+-	    atari_mch_cookie = *data;
+-	    break;
++		atari_mch_cookie = *data;
++		break;
+ 	case BI_ATARI_MCH_TYPE:
+-	    atari_mch_type = *data;
+-	    break;
++		atari_mch_type = *data;
++		break;
+ 	default:
+-	    unknown = 1;
+-    }
+-    return(unknown);
++		unknown = 1;
++		break;
++	}
++	return unknown;
+ }
+ 
+ 
+ /* Parse the Atari-specific switches= option. */
+-void __init atari_switches_setup( const char *str, unsigned len )
++void __init atari_switches_setup(const char *str, unsigned len)
+ {
+-    char switches[len+1];
+-    char *p;
+-    int ovsc_shift;
+-    char *args = switches;
+-
+-    /* copy string to local array, strsep works destructively... */
+-    strlcpy( switches, str, sizeof(switches) );
+-    atari_switches = 0;
+-
+-    /* parse the options */
+-    while ((p = strsep(&args, ",")) != NULL) {
+-	if (!*p) continue;
+-	ovsc_shift = 0;
+-	if (strncmp( p, "ov_", 3 ) == 0) {
+-	    p += 3;
+-	    ovsc_shift = ATARI_SWITCH_OVSC_SHIFT;
+-	}
+-
+-	if (strcmp( p, "ikbd" ) == 0) {
+-	    /* RTS line of IKBD ACIA */
+-	    atari_switches |= ATARI_SWITCH_IKBD << ovsc_shift;
+-	}
+-	else if (strcmp( p, "midi" ) == 0) {
+-	    /* RTS line of MIDI ACIA */
+-	    atari_switches |= ATARI_SWITCH_MIDI << ovsc_shift;
+-	}
+-	else if (strcmp( p, "snd6" ) == 0) {
+-	    atari_switches |= ATARI_SWITCH_SND6 << ovsc_shift;
++	char switches[len+1];
++	char *p;
++	int ovsc_shift;
++	char *args = switches;
++
++	/* copy string to local array, strsep works destructively... */
++	strlcpy(switches, str, sizeof(switches));
++	atari_switches = 0;
++
++	/* parse the options */
++	while ((p = strsep(&args, ",")) != NULL) {
++		if (!*p)
++			continue;
++		ovsc_shift = 0;
++		if (strncmp(p, "ov_", 3) == 0) {
++			p += 3;
++			ovsc_shift = ATARI_SWITCH_OVSC_SHIFT;
++		}
++
++		if (strcmp(p, "ikbd") == 0) {
++			/* RTS line of IKBD ACIA */
++			atari_switches |= ATARI_SWITCH_IKBD << ovsc_shift;
++		} else if (strcmp(p, "midi") == 0) {
++			/* RTS line of MIDI ACIA */
++			atari_switches |= ATARI_SWITCH_MIDI << ovsc_shift;
++		} else if (strcmp(p, "snd6") == 0) {
++			atari_switches |= ATARI_SWITCH_SND6 << ovsc_shift;
++		} else if (strcmp(p, "snd7") == 0) {
++			atari_switches |= ATARI_SWITCH_SND7 << ovsc_shift;
++		}
+ 	}
+-	else if (strcmp( p, "snd7" ) == 0) {
+-	    atari_switches |= ATARI_SWITCH_SND7 << ovsc_shift;
+-	}
+-    }
+ }
+ 
+ 
+@@ -214,284 +179,283 @@ void __init atari_switches_setup( const 
+ 
+ void __init config_atari(void)
+ {
+-    unsigned short tos_version;
++	unsigned short tos_version;
+ 
+-    memset(&atari_hw_present, 0, sizeof(atari_hw_present));
++	memset(&atari_hw_present, 0, sizeof(atari_hw_present));
+ 
+-    atari_debug_init();
++	atari_debug_init();
+ 
+-    ioport_resource.end  = 0xFFFFFFFF;  /* Change size of I/O space from 64KB
+-                                           to 4GB. */
++	/* Change size of I/O space from 64KB to 4GB. */
++	ioport_resource.end  = 0xFFFFFFFF;
+ 
+-    mach_sched_init      = atari_sched_init;
+-    mach_init_IRQ        = atari_init_IRQ;
+-    mach_get_model	 = atari_get_model;
+-    mach_get_hardware_list = atari_get_hardware_list;
+-    mach_gettimeoffset   = atari_gettimeoffset;
+-    mach_reset           = atari_reset;
+-    mach_max_dma_address = 0xffffff;
++	mach_sched_init      = atari_sched_init;
++	mach_init_IRQ        = atari_init_IRQ;
++	mach_get_model	 = atari_get_model;
++	mach_get_hardware_list = atari_get_hardware_list;
++	mach_gettimeoffset   = atari_gettimeoffset;
++	mach_reset           = atari_reset;
++	mach_max_dma_address = 0xffffff;
+ #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
+-    mach_beep          = atari_mksound;
++	mach_beep          = atari_mksound;
+ #endif
+ #ifdef CONFIG_HEARTBEAT
+-    mach_heartbeat = atari_heartbeat;
++	mach_heartbeat = atari_heartbeat;
+ #endif
+ 
+-    /* Set switches as requested by the user */
+-    if (atari_switches & ATARI_SWITCH_IKBD)
+-	acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID;
+-    if (atari_switches & ATARI_SWITCH_MIDI)
+-	acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
+-    if (atari_switches & (ATARI_SWITCH_SND6|ATARI_SWITCH_SND7)) {
+-	sound_ym.rd_data_reg_sel = 14;
+-	sound_ym.wd_data = sound_ym.rd_data_reg_sel |
+-			   ((atari_switches&ATARI_SWITCH_SND6) ? 0x40 : 0) |
+-			   ((atari_switches&ATARI_SWITCH_SND7) ? 0x80 : 0);
+-    }
+-
+-    /* ++bjoern:
+-     * Determine hardware present
+-     */
++	/* Set switches as requested by the user */
++	if (atari_switches & ATARI_SWITCH_IKBD)
++		acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID;
++	if (atari_switches & ATARI_SWITCH_MIDI)
++		acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
++	if (atari_switches & (ATARI_SWITCH_SND6|ATARI_SWITCH_SND7)) {
++		sound_ym.rd_data_reg_sel = 14;
++		sound_ym.wd_data = sound_ym.rd_data_reg_sel |
++				   ((atari_switches&ATARI_SWITCH_SND6) ? 0x40 : 0) |
++				   ((atari_switches&ATARI_SWITCH_SND7) ? 0x80 : 0);
++	}
+ 
+-    printk( "Atari hardware found: " );
+-    if (MACH_IS_MEDUSA || MACH_IS_HADES) {
+-        /* There's no Atari video hardware on the Medusa, but all the
+-         * addresses below generate a DTACK so no bus error occurs! */
+-    }
+-    else if (hwreg_present( f030_xreg )) {
+-	ATARIHW_SET(VIDEL_SHIFTER);
+-        printk( "VIDEL " );
+-        /* This is a temporary hack: If there is Falcon video
+-         * hardware, we assume that the ST-DMA serves SCSI instead of
+-         * ACSI. In the future, there should be a better method for
+-         * this...
+-         */
+-	ATARIHW_SET(ST_SCSI);
+-        printk( "STDMA-SCSI " );
+-    }
+-    else if (hwreg_present( tt_palette )) {
+-	ATARIHW_SET(TT_SHIFTER);
+-        printk( "TT_SHIFTER " );
+-    }
+-    else if (hwreg_present( &shifter.bas_hi )) {
+-        if (hwreg_present( &shifter.bas_lo ) &&
+-	    (shifter.bas_lo = 0x0aau, shifter.bas_lo == 0x0aau)) {
+-	    ATARIHW_SET(EXTD_SHIFTER);
+-            printk( "EXTD_SHIFTER " );
+-        }
+-        else {
+-	    ATARIHW_SET(STND_SHIFTER);
+-            printk( "STND_SHIFTER " );
+-        }
+-    }
+-    if (hwreg_present( &mfp.par_dt_reg )) {
+-	ATARIHW_SET(ST_MFP);
+-        printk( "ST_MFP " );
+-    }
+-    if (hwreg_present( &tt_mfp.par_dt_reg )) {
+-	ATARIHW_SET(TT_MFP);
+-        printk( "TT_MFP " );
+-    }
+-    if (hwreg_present( &tt_scsi_dma.dma_addr_hi )) {
+-	ATARIHW_SET(SCSI_DMA);
+-        printk( "TT_SCSI_DMA " );
+-    }
+-    if (!MACH_IS_HADES && hwreg_present( &st_dma.dma_hi )) {
+-	ATARIHW_SET(STND_DMA);
+-        printk( "STND_DMA " );
+-    }
+-    if (MACH_IS_MEDUSA || /* The ST-DMA address registers aren't readable
+-			   * on all Medusas, so the test below may fail */
+-        (hwreg_present( &st_dma.dma_vhi ) &&
+-         (st_dma.dma_vhi = 0x55) && (st_dma.dma_hi = 0xaa) &&
+-         st_dma.dma_vhi == 0x55 && st_dma.dma_hi == 0xaa &&
+-         (st_dma.dma_vhi = 0xaa) && (st_dma.dma_hi = 0x55) &&
+-         st_dma.dma_vhi == 0xaa && st_dma.dma_hi == 0x55)) {
+-	ATARIHW_SET(EXTD_DMA);
+-        printk( "EXTD_DMA " );
+-    }
+-    if (hwreg_present( &tt_scsi.scsi_data )) {
+-	ATARIHW_SET(TT_SCSI);
+-        printk( "TT_SCSI " );
+-    }
+-    if (hwreg_present( &sound_ym.rd_data_reg_sel )) {
+-	ATARIHW_SET(YM_2149);
+-        printk( "YM2149 " );
+-    }
+-    if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
+-	hwreg_present( &tt_dmasnd.ctrl )) {
+-	ATARIHW_SET(PCM_8BIT);
+-        printk( "PCM " );
+-    }
+-    if (!MACH_IS_HADES && hwreg_present( &falcon_codec.unused5 )) {
+-	ATARIHW_SET(CODEC);
+-        printk( "CODEC " );
+-    }
+-    if (hwreg_present( &dsp56k_host_interface.icr )) {
+-	ATARIHW_SET(DSP56K);
+-        printk( "DSP56K " );
+-    }
+-    if (hwreg_present( &tt_scc_dma.dma_ctrl ) &&
++	/* ++bjoern:
++	 * Determine hardware present
++	 */
++
++	printk("Atari hardware found: ");
++	if (MACH_IS_MEDUSA || MACH_IS_HADES) {
++		/* There's no Atari video hardware on the Medusa, but all the
++		 * addresses below generate a DTACK so no bus error occurs! */
++	} else if (hwreg_present(f030_xreg)) {
++		ATARIHW_SET(VIDEL_SHIFTER);
++		printk("VIDEL ");
++		/* This is a temporary hack: If there is Falcon video
++		 * hardware, we assume that the ST-DMA serves SCSI instead of
++		 * ACSI. In the future, there should be a better method for
++		 * this...
++		 */
++		ATARIHW_SET(ST_SCSI);
++		printk("STDMA-SCSI ");
++	} else if (hwreg_present(tt_palette)) {
++		ATARIHW_SET(TT_SHIFTER);
++		printk("TT_SHIFTER ");
++	} else if (hwreg_present(&shifter.bas_hi)) {
++		if (hwreg_present(&shifter.bas_lo) &&
++		    (shifter.bas_lo = 0x0aau, shifter.bas_lo == 0x0aau)) {
++			ATARIHW_SET(EXTD_SHIFTER);
++			printk("EXTD_SHIFTER ");
++		} else {
++			ATARIHW_SET(STND_SHIFTER);
++			printk("STND_SHIFTER ");
++		}
++	}
++	if (hwreg_present(&mfp.par_dt_reg)) {
++		ATARIHW_SET(ST_MFP);
++		printk("ST_MFP ");
++	}
++	if (hwreg_present(&tt_mfp.par_dt_reg)) {
++		ATARIHW_SET(TT_MFP);
++		printk("TT_MFP ");
++	}
++	if (hwreg_present(&tt_scsi_dma.dma_addr_hi)) {
++		ATARIHW_SET(SCSI_DMA);
++		printk("TT_SCSI_DMA ");
++	}
++	if (!MACH_IS_HADES && hwreg_present(&st_dma.dma_hi)) {
++		ATARIHW_SET(STND_DMA);
++		printk("STND_DMA ");
++	}
++	/*
++	 * The ST-DMA address registers aren't readable
++	 * on all Medusas, so the test below may fail
++	 */
++	if (MACH_IS_MEDUSA ||
++	    (hwreg_present(&st_dma.dma_vhi) &&
++	     (st_dma.dma_vhi = 0x55) && (st_dma.dma_hi = 0xaa) &&
++	     st_dma.dma_vhi == 0x55 && st_dma.dma_hi == 0xaa &&
++	     (st_dma.dma_vhi = 0xaa) && (st_dma.dma_hi = 0x55) &&
++	     st_dma.dma_vhi == 0xaa && st_dma.dma_hi == 0x55)) {
++		ATARIHW_SET(EXTD_DMA);
++		printk("EXTD_DMA ");
++	}
++	if (hwreg_present(&tt_scsi.scsi_data)) {
++		ATARIHW_SET(TT_SCSI);
++		printk("TT_SCSI ");
++	}
++	if (hwreg_present(&sound_ym.rd_data_reg_sel)) {
++		ATARIHW_SET(YM_2149);
++		printk("YM2149 ");
++	}
++	if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
++		hwreg_present(&tt_dmasnd.ctrl)) {
++		ATARIHW_SET(PCM_8BIT);
++		printk("PCM ");
++	}
++	if (!MACH_IS_HADES && hwreg_present(&falcon_codec.unused5)) {
++		ATARIHW_SET(CODEC);
++		printk("CODEC ");
++	}
++	if (hwreg_present(&dsp56k_host_interface.icr)) {
++		ATARIHW_SET(DSP56K);
++		printk("DSP56K ");
++	}
++	if (hwreg_present(&tt_scc_dma.dma_ctrl) &&
+ #if 0
+-	/* This test sucks! Who knows some better? */
+-	(tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
+-	(tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
++	    /* This test sucks! Who knows some better? */
++	    (tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
++	    (tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
+ #else
+-	!MACH_IS_MEDUSA && !MACH_IS_HADES
++	    !MACH_IS_MEDUSA && !MACH_IS_HADES
+ #endif
+-	) {
+-	ATARIHW_SET(SCC_DMA);
+-        printk( "SCC_DMA " );
+-    }
+-    if (scc_test( &scc.cha_a_ctrl )) {
+-	ATARIHW_SET(SCC);
+-        printk( "SCC " );
+-    }
+-    if (scc_test( &st_escc.cha_b_ctrl )) {
+-	ATARIHW_SET( ST_ESCC );
+-	printk( "ST_ESCC " );
+-    }
+-    if (MACH_IS_HADES)
+-    {
+-        ATARIHW_SET( VME );
+-        printk( "VME " );
+-    }
+-    else if (hwreg_present( &tt_scu.sys_mask )) {
+-	ATARIHW_SET(SCU);
+-	/* Assume a VME bus if there's a SCU */
+-	ATARIHW_SET( VME );
+-        printk( "VME SCU " );
+-    }
+-    if (hwreg_present( (void *)(0xffff9210) )) {
+-	ATARIHW_SET(ANALOG_JOY);
+-        printk( "ANALOG_JOY " );
+-    }
+-    if (!MACH_IS_HADES && hwreg_present( blitter.halftone )) {
+-	ATARIHW_SET(BLITTER);
+-        printk( "BLITTER " );
+-    }
+-    if (hwreg_present((void *)0xfff00039)) {
+-	ATARIHW_SET(IDE);
+-        printk( "IDE " );
+-    }
++	    ) {
++		ATARIHW_SET(SCC_DMA);
++		printk("SCC_DMA ");
++	}
++	if (scc_test(&scc.cha_a_ctrl)) {
++		ATARIHW_SET(SCC);
++		printk("SCC ");
++	}
++	if (scc_test(&st_escc.cha_b_ctrl)) {
++		ATARIHW_SET(ST_ESCC);
++		printk("ST_ESCC ");
++	}
++	if (MACH_IS_HADES) {
++		ATARIHW_SET(VME);
++		printk("VME ");
++	} else if (hwreg_present(&tt_scu.sys_mask)) {
++		ATARIHW_SET(SCU);
++		/* Assume a VME bus if there's a SCU */
++		ATARIHW_SET(VME);
++		printk("VME SCU ");
++	}
++	if (hwreg_present((void *)(0xffff9210))) {
++		ATARIHW_SET(ANALOG_JOY);
++		printk("ANALOG_JOY ");
++	}
++	if (!MACH_IS_HADES && hwreg_present(blitter.halftone)) {
++		ATARIHW_SET(BLITTER);
++		printk("BLITTER ");
++	}
++	if (hwreg_present((void *)0xfff00039)) {
++		ATARIHW_SET(IDE);
++		printk("IDE ");
++	}
+ #if 1 /* This maybe wrong */
+-    if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
+-	hwreg_present( &tt_microwire.data ) &&
+-	hwreg_present( &tt_microwire.mask ) &&
+-	(tt_microwire.mask = 0x7ff,
+-	 udelay(1),
+-	 tt_microwire.data = MW_LM1992_PSG_HIGH | MW_LM1992_ADDR,
+-	 udelay(1),
+-	 tt_microwire.data != 0)) {
+-	ATARIHW_SET(MICROWIRE);
+-	while (tt_microwire.mask != 0x7ff) ;
+-        printk( "MICROWIRE " );
+-    }
++	if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
++	    hwreg_present(&tt_microwire.data) &&
++	    hwreg_present(&tt_microwire.mask) &&
++	    (tt_microwire.mask = 0x7ff,
++	     udelay(1),
++	     tt_microwire.data = MW_LM1992_PSG_HIGH | MW_LM1992_ADDR,
++	     udelay(1),
++	     tt_microwire.data != 0)) {
++		ATARIHW_SET(MICROWIRE);
++		while (tt_microwire.mask != 0x7ff)
++			;
++		printk("MICROWIRE ");
++	}
+ #endif
+-    if (hwreg_present( &tt_rtc.regsel )) {
+-	ATARIHW_SET(TT_CLK);
+-        printk( "TT_CLK " );
+-        mach_hwclk = atari_tt_hwclk;
+-        mach_set_clock_mmss = atari_tt_set_clock_mmss;
+-    }
+-    if (!MACH_IS_HADES && hwreg_present( &mste_rtc.sec_ones)) {
+-	ATARIHW_SET(MSTE_CLK);
+-        printk( "MSTE_CLK ");
+-        mach_hwclk = atari_mste_hwclk;
+-        mach_set_clock_mmss = atari_mste_set_clock_mmss;
+-    }
+-    if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
+-	hwreg_present( &dma_wd.fdc_speed ) &&
+-	hwreg_write( &dma_wd.fdc_speed, 0 )) {
+-	    ATARIHW_SET(FDCSPEED);
+-	    printk( "FDC_SPEED ");
+-    }
+-    if (!MACH_IS_HADES && !ATARIHW_PRESENT(ST_SCSI)) {
+-	ATARIHW_SET(ACSI);
+-        printk( "ACSI " );
+-    }
+-    printk("\n");
+-
+-    if (CPU_IS_040_OR_060)
+-        /* Now it seems to be safe to turn of the tt0 transparent
+-         * translation (the one that must not be turned off in
+-         * head.S...)
+-         */
+-        __asm__ volatile ("moveq #0,%/d0\n\t"
+-                          ".chip 68040\n\t"
+-			  "movec %%d0,%%itt0\n\t"
+-			  "movec %%d0,%%dtt0\n\t"
+-			  ".chip 68k"
+-						  : /* no outputs */
+-						  : /* no inputs */
+-						  : "d0");
+-
+-    /* allocator for memory that must reside in st-ram */
+-    atari_stram_init ();
+-
+-    /* Set up a mapping for the VMEbus address region:
+-     *
+-     * VME is either at phys. 0xfexxxxxx (TT) or 0xa00000..0xdfffff
+-     * (MegaSTE) In both cases, the whole 16 MB chunk is mapped at
+-     * 0xfe000000 virt., because this can be done with a single
+-     * transparent translation. On the 68040, lots of often unused
+-     * page tables would be needed otherwise. On a MegaSTE or similar,
+-     * the highest byte is stripped off by hardware due to the 24 bit
+-     * design of the bus.
+-     */
++	if (hwreg_present(&tt_rtc.regsel)) {
++		ATARIHW_SET(TT_CLK);
++		printk("TT_CLK ");
++		mach_hwclk = atari_tt_hwclk;
++		mach_set_clock_mmss = atari_tt_set_clock_mmss;
++	}
++	if (!MACH_IS_HADES && hwreg_present(&mste_rtc.sec_ones)) {
++		ATARIHW_SET(MSTE_CLK);
++		printk("MSTE_CLK ");
++		mach_hwclk = atari_mste_hwclk;
++		mach_set_clock_mmss = atari_mste_set_clock_mmss;
++	}
++	if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
++	    hwreg_present(&dma_wd.fdc_speed) &&
++	    hwreg_write(&dma_wd.fdc_speed, 0)) {
++		ATARIHW_SET(FDCSPEED);
++		printk("FDC_SPEED ");
++	}
++	if (!MACH_IS_HADES && !ATARIHW_PRESENT(ST_SCSI)) {
++		ATARIHW_SET(ACSI);
++		printk("ACSI ");
++	}
++	printk("\n");
+ 
+-    if (CPU_IS_020_OR_030) {
+-        unsigned long	tt1_val;
+-        tt1_val = 0xfe008543;	/* Translate 0xfexxxxxx, enable, cache
+-                                 * inhibit, read and write, FDC mask = 3,
+-                                 * FDC val = 4 -> Supervisor only */
+-        __asm__ __volatile__ ( ".chip 68030\n\t"
+-				"pmove	%0@,%/tt1\n\t"
+-				".chip 68k"
+-				: : "a" (&tt1_val) );
+-    }
+-    else {
+-        __asm__ __volatile__
+-            ( "movel %0,%/d0\n\t"
+-	      ".chip 68040\n\t"
+-	      "movec %%d0,%%itt1\n\t"
+-	      "movec %%d0,%%dtt1\n\t"
+-	      ".chip 68k"
+-              :
+-              : "g" (0xfe00a040)	/* Translate 0xfexxxxxx, enable,
+-                                         * supervisor only, non-cacheable/
+-                                         * serialized, writable */
+-              : "d0" );
+-
+-    }
+-
+-    /* Fetch tos version at Physical 2 */
+-    /* We my not be able to access this address if the kernel is
+-       loaded to st ram, since the first page is unmapped.  On the
+-       Medusa this is always the case and there is nothing we can do
+-       about this, so we just assume the smaller offset.  For the TT
+-       we use the fact that in head.S we have set up a mapping
+-       0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
+-       in the last 16MB of the address space. */
+-    tos_version = (MACH_IS_MEDUSA || MACH_IS_HADES) ?
+-		  0xfff : *(unsigned short *)0xff000002;
+-    atari_rtc_year_offset = (tos_version < 0x306) ? 70 : 68;
++	if (CPU_IS_040_OR_060)
++		/* Now it seems to be safe to turn of the tt0 transparent
++		 * translation (the one that must not be turned off in
++		 * head.S...)
++		 */
++		asm volatile ("\n"
++			"	moveq	#0,%%d0\n"
++			"	.chip	68040\n"
++			"	movec	%%d0,%%itt0\n"
++			"	movec	%%d0,%%dtt0\n"
++			"	.chip	68k"
++			: /* no outputs */
++			: /* no inputs */
++			: "d0");
++
++	/* allocator for memory that must reside in st-ram */
++	atari_stram_init();
++
++	/* Set up a mapping for the VMEbus address region:
++	 *
++	 * VME is either at phys. 0xfexxxxxx (TT) or 0xa00000..0xdfffff
++	 * (MegaSTE) In both cases, the whole 16 MB chunk is mapped at
++	 * 0xfe000000 virt., because this can be done with a single
++	 * transparent translation. On the 68040, lots of often unused
++	 * page tables would be needed otherwise. On a MegaSTE or similar,
++	 * the highest byte is stripped off by hardware due to the 24 bit
++	 * design of the bus.
++	 */
++
++	if (CPU_IS_020_OR_030) {
++		unsigned long tt1_val;
++		tt1_val = 0xfe008543;	/* Translate 0xfexxxxxx, enable, cache
++					 * inhibit, read and write, FDC mask = 3,
++					 * FDC val = 4 -> Supervisor only */
++		asm volatile ("\n"
++			"	.chip	68030\n"
++			"	pmove	%0@,%/tt1\n"
++			"	.chip	68k"
++			: : "a" (&tt1_val));
++	} else {
++	        asm volatile ("\n"
++			"	.chip	68040\n"
++			"	movec	%0,%%itt1\n"
++			"	movec	%0,%%dtt1\n"
++			"	.chip	68k"
++			:
++			: "d" (0xfe00a040));	/* Translate 0xfexxxxxx, enable,
++						 * supervisor only, non-cacheable/
++						 * serialized, writable */
++
++	}
++
++	/* Fetch tos version at Physical 2 */
++	/*
++	 * We my not be able to access this address if the kernel is
++	 * loaded to st ram, since the first page is unmapped.  On the
++	 * Medusa this is always the case and there is nothing we can do
++	 * about this, so we just assume the smaller offset.  For the TT
++	 * we use the fact that in head.S we have set up a mapping
++	 * 0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
++	 * in the last 16MB of the address space.
++	 */
++	tos_version = (MACH_IS_MEDUSA || MACH_IS_HADES) ?
++			0xfff : *(unsigned short *)0xff000002;
++	atari_rtc_year_offset = (tos_version < 0x306) ? 70 : 68;
+ }
+ 
+ #ifdef CONFIG_HEARTBEAT
+-static void atari_heartbeat( int on )
++static void atari_heartbeat(int on)
+ {
+-    unsigned char tmp;
+-    unsigned long flags;
++	unsigned char tmp;
++	unsigned long flags;
+ 
+-    if (atari_dont_touch_floppy_select)
+-	return;
++	if (atari_dont_touch_floppy_select)
++		return;
+ 
+-    local_irq_save(flags);
+-    sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */
+-    tmp = sound_ym.rd_data_reg_sel;
+-    sound_ym.wd_data = on ? (tmp & ~0x02) : (tmp | 0x02);
+-    local_irq_restore(flags);
++	local_irq_save(flags);
++	sound_ym.rd_data_reg_sel = 14;	/* Select PSG Port A */
++	tmp = sound_ym.rd_data_reg_sel;
++	sound_ym.wd_data = on ? (tmp & ~0x02) : (tmp | 0x02);
++	local_irq_restore(flags);
+ }
+ #endif
+ 
+@@ -526,180 +490,171 @@ static void atari_heartbeat( int on )
+ 
+ /* ++andreas: no need for complicated code, just depend on prefetch */
+ 
+-static void atari_reset (void)
++static void atari_reset(void)
+ {
+-    long tc_val = 0;
+-    long reset_addr;
++	long tc_val = 0;
++	long reset_addr;
+ 
+-    /* On the Medusa, phys. 0x4 may contain garbage because it's no
+-       ROM.  See above for explanation why we cannot use PTOV(4). */
+-    reset_addr = MACH_IS_HADES ? 0x7fe00030 :
+-                 MACH_IS_MEDUSA || MACH_IS_AB40 ? 0xe00030 :
+-		 *(unsigned long *) 0xff000004;
+-
+-    /* reset ACIA for switch off OverScan, if it's active */
+-    if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
+-	acia.key_ctrl = ACIA_RESET;
+-    if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
+-	acia.mid_ctrl = ACIA_RESET;
+-
+-    /* processor independent: turn off interrupts and reset the VBR;
+-     * the caches must be left enabled, else prefetching the final jump
+-     * instruction doesn't work. */
+-    local_irq_disable();
+-    __asm__ __volatile__
+-	("moveq	#0,%/d0\n\t"
+-	 "movec	%/d0,%/vbr"
+-	 : : : "d0" );
+-
+-    if (CPU_IS_040_OR_060) {
+-        unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
+-	if (CPU_IS_060) {
+-	    /* 68060: clear PCR to turn off superscalar operation */
+-	    __asm__ __volatile__
+-		("moveq	#0,%/d0\n\t"
+-		 ".chip 68060\n\t"
+-		 "movec %%d0,%%pcr\n\t"
+-		 ".chip 68k"
+-		 : : : "d0" );
+-	}
+-
+-        __asm__ __volatile__
+-            ("movel    %0,%/d0\n\t"
+-             "andl     #0xff000000,%/d0\n\t"
+-             "orw      #0xe020,%/d0\n\t"   /* map 16 MB, enable, cacheable */
+-             ".chip 68040\n\t"
+-	     "movec    %%d0,%%itt0\n\t"
+-             "movec    %%d0,%%dtt0\n\t"
+-	     ".chip 68k\n\t"
+-             "jmp   %0@\n\t"
+-             : /* no outputs */
+-             : "a" (jmp_addr040)
+-             : "d0" );
+-      jmp_addr_label040:
+-        __asm__ __volatile__
+-          ("moveq #0,%/d0\n\t"
+-	   "nop\n\t"
+-	   ".chip 68040\n\t"
+-	   "cinva %%bc\n\t"
+-	   "nop\n\t"
+-	   "pflusha\n\t"
+-	   "nop\n\t"
+-	   "movec %%d0,%%tc\n\t"
+-	   "nop\n\t"
+-	   /* the following setup of transparent translations is needed on the
+-	    * Afterburner040 to successfully reboot. Other machines shouldn't
+-	    * care about a different tt regs setup, they also didn't care in
+-	    * the past that the regs weren't turned off. */
+-	   "movel #0xffc000,%%d0\n\t" /* whole insn space cacheable */
+-	   "movec %%d0,%%itt0\n\t"
+-	   "movec %%d0,%%itt1\n\t"
+-	   "orw   #0x40,%/d0\n\t" /* whole data space non-cacheable/ser. */
+-	   "movec %%d0,%%dtt0\n\t"
+-	   "movec %%d0,%%dtt1\n\t"
+-	   ".chip 68k\n\t"
+-           "jmp %0@"
+-           : /* no outputs */
+-           : "a" (reset_addr)
+-           : "d0");
+-    }
+-    else
+-        __asm__ __volatile__
+-            ("pmove %0@,%/tc\n\t"
+-             "jmp %1@"
+-             : /* no outputs */
+-             : "a" (&tc_val), "a" (reset_addr));
++	/*
++	 * On the Medusa, phys. 0x4 may contain garbage because it's no
++	 * ROM.  See above for explanation why we cannot use PTOV(4).
++	 */
++	reset_addr = MACH_IS_HADES ? 0x7fe00030 :
++		     MACH_IS_MEDUSA || MACH_IS_AB40 ? 0xe00030 :
++		     *(unsigned long *) 0xff000004;
++
++	/* reset ACIA for switch off OverScan, if it's active */
++	if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
++		acia.key_ctrl = ACIA_RESET;
++	if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
++		acia.mid_ctrl = ACIA_RESET;
++
++	/* processor independent: turn off interrupts and reset the VBR;
++	 * the caches must be left enabled, else prefetching the final jump
++	 * instruction doesn't work.
++	 */
++	local_irq_disable();
++	asm volatile ("movec	%0,%%vbr"
++			: : "d" (0));
++
++	if (CPU_IS_040_OR_060) {
++		unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
++		if (CPU_IS_060) {
++			/* 68060: clear PCR to turn off superscalar operation */
++			asm volatile ("\n"
++				"	.chip 68060\n"
++				"	movec %0,%%pcr\n"
++				"	.chip 68k"
++				: : "d" (0));
++		}
++
++		asm volatile ("\n"
++			"	move.l	%0,%%d0\n"
++			"	and.l	#0xff000000,%%d0\n"
++			"	or.w	#0xe020,%%d0\n"   /* map 16 MB, enable, cacheable */
++			"	.chip	68040\n"
++			"	movec	%%d0,%%itt0\n"
++			"	movec	%%d0,%%dtt0\n"
++			"	.chip	68k\n"
++			"	jmp	%0@"
++			: : "a" (jmp_addr040)
++			: "d0");
++	jmp_addr_label040:
++		asm volatile ("\n"
++			"	moveq	#0,%%d0\n"
++			"	nop\n"
++			"	.chip	68040\n"
++			"	cinva	%%bc\n"
++			"	nop\n"
++			"	pflusha\n"
++			"	nop\n"
++			"	movec	%%d0,%%tc\n"
++			"	nop\n"
++			/* the following setup of transparent translations is needed on the
++			 * Afterburner040 to successfully reboot. Other machines shouldn't
++			 * care about a different tt regs setup, they also didn't care in
++			 * the past that the regs weren't turned off. */
++			"	move.l	#0xffc000,%%d0\n" /* whole insn space cacheable */
++			"	movec	%%d0,%%itt0\n"
++			"	movec	%%d0,%%itt1\n"
++			"	or.w	#0x40,%/d0\n" /* whole data space non-cacheable/ser. */
++			"	movec	%%d0,%%dtt0\n"
++			"	movec	%%d0,%%dtt1\n"
++			"	.chip	68k\n"
++			"	jmp	%0@"
++			: /* no outputs */
++			: "a" (reset_addr)
++			: "d0");
++	} else
++		asm volatile ("\n"
++			"	pmove	%0@,%%tc\n"
++			"	jmp	%1@"
++			: /* no outputs */
++			: "a" (&tc_val), "a" (reset_addr));
+ }
+ 
+ 
+ static void atari_get_model(char *model)
+ {
+-    strcpy(model, "Atari ");
+-    switch (atari_mch_cookie >> 16) {
++	strcpy(model, "Atari ");
++	switch (atari_mch_cookie >> 16) {
+ 	case ATARI_MCH_ST:
+-	    if (ATARIHW_PRESENT(MSTE_CLK))
+-		strcat (model, "Mega ST");
+-	    else
+-		strcat (model, "ST");
+-	    break;
++		if (ATARIHW_PRESENT(MSTE_CLK))
++			strcat(model, "Mega ST");
++		else
++			strcat(model, "ST");
++		break;
+ 	case ATARI_MCH_STE:
+-	    if (MACH_IS_MSTE)
+-		strcat (model, "Mega STE");
+-	    else
+-		strcat (model, "STE");
+-	    break;
++		if (MACH_IS_MSTE)
++			strcat(model, "Mega STE");
++		else
++			strcat(model, "STE");
++		break;
+ 	case ATARI_MCH_TT:
+-	    if (MACH_IS_MEDUSA)
+-		/* Medusa has TT _MCH cookie */
+-		strcat (model, "Medusa");
+-	    else if (MACH_IS_HADES)
+-		strcat(model, "Hades");
+-	    else
+-		strcat (model, "TT");
+-	    break;
++		if (MACH_IS_MEDUSA)
++			/* Medusa has TT _MCH cookie */
++			strcat(model, "Medusa");
++		else if (MACH_IS_HADES)
++			strcat(model, "Hades");
++		else
++			strcat(model, "TT");
++		break;
+ 	case ATARI_MCH_FALCON:
+-	    strcat (model, "Falcon");
+-	    if (MACH_IS_AB40)
+-		strcat (model, " (with Afterburner040)");
+-	    break;
++		strcat(model, "Falcon");
++		if (MACH_IS_AB40)
++			strcat(model, " (with Afterburner040)");
++		break;
+ 	default:
+-	    sprintf (model + strlen (model), "(unknown mach cookie 0x%lx)",
+-		     atari_mch_cookie);
+-	    break;
+-    }
++		sprintf(model + strlen(model), "(unknown mach cookie 0x%lx)",
++			atari_mch_cookie);
++		break;
++	}
+ }
+ 
+ 
+ static int atari_get_hardware_list(char *buffer)
+ {
+-    int len = 0, i;
++	int len = 0, i;
+ 
+-    for (i = 0; i < m68k_num_memory; i++)
+-	len += sprintf (buffer+len, "\t%3ld MB at 0x%08lx (%s)\n",
+-			m68k_memory[i].size >> 20, m68k_memory[i].addr,
+-			(m68k_memory[i].addr & 0xff000000 ?
+-			 "alternate RAM" : "ST-RAM"));
+-
+-#define ATARIHW_ANNOUNCE(name,str)				\
+-    if (ATARIHW_PRESENT(name))			\
+-	len += sprintf (buffer + len, "\t%s\n", str)
+-
+-    len += sprintf (buffer + len, "Detected hardware:\n");
+-    ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter");
+-    ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter");
+-    ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter");
+-    ATARIHW_ANNOUNCE(VIDEL_SHIFTER, "Falcon Shifter");
+-    ATARIHW_ANNOUNCE(YM_2149, "Programmable Sound Generator");
+-    ATARIHW_ANNOUNCE(PCM_8BIT, "PCM 8 Bit Sound");
+-    ATARIHW_ANNOUNCE(CODEC, "CODEC Sound");
+-    ATARIHW_ANNOUNCE(TT_SCSI, "SCSI Controller NCR5380 (TT style)");
+-    ATARIHW_ANNOUNCE(ST_SCSI, "SCSI Controller NCR5380 (Falcon style)");
+-    ATARIHW_ANNOUNCE(ACSI, "ACSI Interface");
+-    ATARIHW_ANNOUNCE(IDE, "IDE Interface");
+-    ATARIHW_ANNOUNCE(FDCSPEED, "8/16 Mhz Switch for FDC");
+-    ATARIHW_ANNOUNCE(ST_MFP, "Multi Function Peripheral MFP 68901");
+-    ATARIHW_ANNOUNCE(TT_MFP, "Second Multi Function Peripheral MFP 68901");
+-    ATARIHW_ANNOUNCE(SCC, "Serial Communications Controller SCC 8530");
+-    ATARIHW_ANNOUNCE(ST_ESCC, "Extended Serial Communications Controller SCC 85230");
+-    ATARIHW_ANNOUNCE(ANALOG_JOY, "Paddle Interface");
+-    ATARIHW_ANNOUNCE(MICROWIRE, "MICROWIRE(tm) Interface");
+-    ATARIHW_ANNOUNCE(STND_DMA, "DMA Controller (24 bit)");
+-    ATARIHW_ANNOUNCE(EXTD_DMA, "DMA Controller (32 bit)");
+-    ATARIHW_ANNOUNCE(SCSI_DMA, "DMA Controller for NCR5380");
+-    ATARIHW_ANNOUNCE(SCC_DMA, "DMA Controller for SCC");
+-    ATARIHW_ANNOUNCE(TT_CLK, "Clock Chip MC146818A");
+-    ATARIHW_ANNOUNCE(MSTE_CLK, "Clock Chip RP5C15");
+-    ATARIHW_ANNOUNCE(SCU, "System Control Unit");
+-    ATARIHW_ANNOUNCE(BLITTER, "Blitter");
+-    ATARIHW_ANNOUNCE(VME, "VME Bus");
+-    ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
++	for (i = 0; i < m68k_num_memory; i++)
++		len += sprintf(buffer+len, "\t%3ld MB at 0x%08lx (%s)\n",
++				m68k_memory[i].size >> 20, m68k_memory[i].addr,
++				(m68k_memory[i].addr & 0xff000000 ?
++				 "alternate RAM" : "ST-RAM"));
++
++#define ATARIHW_ANNOUNCE(name, str)			\
++	if (ATARIHW_PRESENT(name))			\
++		len += sprintf(buffer + len, "\t%s\n", str)
++
++	len += sprintf(buffer + len, "Detected hardware:\n");
++	ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter");
++	ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter");
++	ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter");
++	ATARIHW_ANNOUNCE(VIDEL_SHIFTER, "Falcon Shifter");
++	ATARIHW_ANNOUNCE(YM_2149, "Programmable Sound Generator");
++	ATARIHW_ANNOUNCE(PCM_8BIT, "PCM 8 Bit Sound");
++	ATARIHW_ANNOUNCE(CODEC, "CODEC Sound");
++	ATARIHW_ANNOUNCE(TT_SCSI, "SCSI Controller NCR5380 (TT style)");
++	ATARIHW_ANNOUNCE(ST_SCSI, "SCSI Controller NCR5380 (Falcon style)");
++	ATARIHW_ANNOUNCE(ACSI, "ACSI Interface");
++	ATARIHW_ANNOUNCE(IDE, "IDE Interface");
++	ATARIHW_ANNOUNCE(FDCSPEED, "8/16 Mhz Switch for FDC");
++	ATARIHW_ANNOUNCE(ST_MFP, "Multi Function Peripheral MFP 68901");
++	ATARIHW_ANNOUNCE(TT_MFP, "Second Multi Function Peripheral MFP 68901");
++	ATARIHW_ANNOUNCE(SCC, "Serial Communications Controller SCC 8530");
++	ATARIHW_ANNOUNCE(ST_ESCC, "Extended Serial Communications Controller SCC 85230");
++	ATARIHW_ANNOUNCE(ANALOG_JOY, "Paddle Interface");
++	ATARIHW_ANNOUNCE(MICROWIRE, "MICROWIRE(tm) Interface");
++	ATARIHW_ANNOUNCE(STND_DMA, "DMA Controller (24 bit)");
++	ATARIHW_ANNOUNCE(EXTD_DMA, "DMA Controller (32 bit)");
++	ATARIHW_ANNOUNCE(SCSI_DMA, "DMA Controller for NCR5380");
++	ATARIHW_ANNOUNCE(SCC_DMA, "DMA Controller for SCC");
++	ATARIHW_ANNOUNCE(TT_CLK, "Clock Chip MC146818A");
++	ATARIHW_ANNOUNCE(MSTE_CLK, "Clock Chip RP5C15");
++	ATARIHW_ANNOUNCE(SCU, "System Control Unit");
++	ATARIHW_ANNOUNCE(BLITTER, "Blitter");
++	ATARIHW_ANNOUNCE(VME, "VME Bus");
++	ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
+ 
+-    return(len);
++	return len;
+ }
+-
+-/*
+- * Local variables:
+- *  c-indent-level: 4
+- *  tab-width: 8
+- * End:
+- */
+--- linux-m68k-2.6.21.orig/arch/m68k/atari/debug.c
++++ linux-m68k-2.6.21/arch/m68k/atari/debug.c
+@@ -30,317 +30,311 @@ int atari_SCC_init_done;
+ int atari_SCC_reset_done;
+ 
+ static struct console atari_console_driver = {
+-	.name =		"debug",
+-	.flags =	CON_PRINTBUFFER,
+-	.index =	-1,
++	.name	= "debug",
++	.flags	= CON_PRINTBUFFER,
++	.index	= -1,
+ };
+ 
+ 
+-static inline void ata_mfp_out (char c)
++static inline void ata_mfp_out(char c)
+ {
+-    while (!(mfp.trn_stat & 0x80)) /* wait for tx buf empty */
+-	barrier ();
+-    mfp.usart_dta = c;
++	while (!(mfp.trn_stat & 0x80))	/* wait for tx buf empty */
++		barrier();
++	mfp.usart_dta = c;
+ }
+ 
+-void atari_mfp_console_write (struct console *co, const char *str,
+-			      unsigned int count)
++void atari_mfp_console_write(struct console *co, const char *str,
++			     unsigned int count)
+ {
+-    while (count--) {
+-	if (*str == '\n')
+-	    ata_mfp_out( '\r' );
+-	ata_mfp_out( *str++ );
+-    }
++	while (count--) {
++		if (*str == '\n')
++			ata_mfp_out('\r');
++		ata_mfp_out(*str++);
++	}
+ }
+ 
+-static inline void ata_scc_out (char c)
++static inline void ata_scc_out(char c)
+ {
+-    do {
++	do {
++		MFPDELAY();
++	} while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
+ 	MFPDELAY();
+-    } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
+-    MFPDELAY();
+-    scc.cha_b_data = c;
++	scc.cha_b_data = c;
+ }
+ 
+-void atari_scc_console_write (struct console *co, const char *str,
+-			      unsigned int count)
++void atari_scc_console_write(struct console *co, const char *str,
++			     unsigned int count)
+ {
+-    while (count--) {
+-	if (*str == '\n')
+-	    ata_scc_out( '\r' );
+-	ata_scc_out( *str++ );
+-    }
++	while (count--) {
++		if (*str == '\n')
++			ata_scc_out('\r');
++		ata_scc_out(*str++);
++	}
+ }
+ 
+-static inline void ata_midi_out (char c)
++static inline void ata_midi_out(char c)
+ {
+-    while (!(acia.mid_ctrl & ACIA_TDRE)) /* wait for tx buf empty */
+-	barrier ();
+-    acia.mid_data = c;
++	while (!(acia.mid_ctrl & ACIA_TDRE))	/* wait for tx buf empty */
++		barrier();
++	acia.mid_data = c;
+ }
+ 
+-void atari_midi_console_write (struct console *co, const char *str,
+-			       unsigned int count)
++void atari_midi_console_write(struct console *co, const char *str,
++			      unsigned int count)
+ {
+-    while (count--) {
+-	if (*str == '\n')
+-	    ata_midi_out( '\r' );
+-	ata_midi_out( *str++ );
+-    }
++	while (count--) {
++		if (*str == '\n')
++			ata_midi_out('\r');
++		ata_midi_out(*str++);
++	}
+ }
+ 
+-static int ata_par_out (char c)
++static int ata_par_out(char c)
+ {
+-    unsigned char tmp;
+-    /* This a some-seconds timeout in case no printer is connected */
+-    unsigned long i = loops_per_jiffy > 1 ? loops_per_jiffy : 10000000/HZ;
++	unsigned char tmp;
++	/* This a some-seconds timeout in case no printer is connected */
++	unsigned long i = loops_per_jiffy > 1 ? loops_per_jiffy : 10000000/HZ;
+ 
+-    while( (mfp.par_dt_reg & 1) && --i ) /* wait for BUSY == L */
+-	;
+-    if (!i) return( 0 );
++	while ((mfp.par_dt_reg & 1) && --i) /* wait for BUSY == L */
++		;
++	if (!i)
++		return 0;
+ 
+-    sound_ym.rd_data_reg_sel = 15;  /* select port B */
+-    sound_ym.wd_data = c;           /* put char onto port */
+-    sound_ym.rd_data_reg_sel = 14;  /* select port A */
+-    tmp = sound_ym.rd_data_reg_sel;
+-    sound_ym.wd_data = tmp & ~0x20; /* set strobe L */
+-    MFPDELAY();                     /* wait a bit */
+-    sound_ym.wd_data = tmp | 0x20;  /* set strobe H */
+-    return( 1 );
++	sound_ym.rd_data_reg_sel = 15;	/* select port B */
++	sound_ym.wd_data = c;		/* put char onto port */
++	sound_ym.rd_data_reg_sel = 14;	/* select port A */
++	tmp = sound_ym.rd_data_reg_sel;
++	sound_ym.wd_data = tmp & ~0x20;	/* set strobe L */
++	MFPDELAY();			/* wait a bit */
++	sound_ym.wd_data = tmp | 0x20;	/* set strobe H */
++	return 1;
+ }
+ 
+-static void atari_par_console_write (struct console *co, const char *str,
+-				     unsigned int count)
++static void atari_par_console_write(struct console *co, const char *str,
++				    unsigned int count)
+ {
+-    static int printer_present = 1;
+-
+-    if (!printer_present)
+-	return;
++	static int printer_present = 1;
+ 
+-    while (count--) {
+-	if (*str == '\n')
+-	    if (!ata_par_out( '\r' )) {
+-		printer_present = 0;
++	if (!printer_present)
+ 		return;
+-	    }
+-	if (!ata_par_out( *str++ )) {
+-	    printer_present = 0;
+-	    return;
++
++	while (count--) {
++		if (*str == '\n') {
++			if (!ata_par_out('\r')) {
++				printer_present = 0;
++				return;
++			}
++		}
++		if (!ata_par_out(*str++)) {
++			printer_present = 0;
++			return;
++		}
+ 	}
+-    }
+ }
+ 
+ #ifdef CONFIG_SERIAL_CONSOLE
+ int atari_mfp_console_wait_key(struct console *co)
+ {
+-    while( !(mfp.rcv_stat & 0x80) ) /* wait for rx buf filled */
+-	barrier();
+-    return( mfp.usart_dta );
++	while (!(mfp.rcv_stat & 0x80))	/* wait for rx buf filled */
++		barrier();
++	return mfp.usart_dta;
+ }
+ 
+ int atari_scc_console_wait_key(struct console *co)
+ {
+-    do {
++	do {
++		MFPDELAY();
++	} while (!(scc.cha_b_ctrl & 0x01)); /* wait for rx buf filled */
+ 	MFPDELAY();
+-    } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */
+-    MFPDELAY();
+-    return( scc.cha_b_data );
++	return scc.cha_b_data;
+ }
+ 
+ int atari_midi_console_wait_key(struct console *co)
+ {
+-    while( !(acia.mid_ctrl & ACIA_RDRF) ) /* wait for rx buf filled */
+-	barrier();
+-    return( acia.mid_data );
++	while (!(acia.mid_ctrl & ACIA_RDRF)) /* wait for rx buf filled */
++		barrier();
++	return acia.mid_data;
+ }
+ #endif
+ 
+-/* The following two functions do a quick'n'dirty initialization of the MFP or
++/*
++ * The following two functions do a quick'n'dirty initialization of the MFP or
+  * SCC serial ports. They're used by the debugging interface, kgdb, and the
+- * serial console code. */
++ * serial console code.
++ */
+ #ifndef CONFIG_SERIAL_CONSOLE
+-static void __init atari_init_mfp_port( int cflag )
++static void __init atari_init_mfp_port(int cflag)
+ #else
+-void atari_init_mfp_port( int cflag )
++void atari_init_mfp_port(int cflag)
+ #endif
+ {
+-    /* timer values for 1200...115200 bps; > 38400 select 110, 134, or 150
+-     * bps, resp., and work only correct if there's a RSVE or RSSPEED */
+-    static int baud_table[9] = { 16, 11, 8, 4, 2, 1, 175, 143, 128 };
+-    int baud = cflag & CBAUD;
+-    int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x04 : 0x06) : 0;
+-    int csize = ((cflag & CSIZE) == CS7) ? 0x20 : 0x00;
+-
+-    if (cflag & CBAUDEX)
+-	baud += B38400;
+-    if (baud < B1200 || baud > B38400+2)
+-	baud = B9600; /* use default 9600bps for non-implemented rates */
+-    baud -= B1200; /* baud_table[] starts at 1200bps */
+-
+-    mfp.trn_stat &= ~0x01; /* disable TX */
+-    mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
+-    mfp.tim_ct_cd &= 0x70;  /* stop timer D */
+-    mfp.tim_dt_d = baud_table[baud];
+-    mfp.tim_ct_cd |= 0x01;  /* start timer D, 1:4 */
+-    mfp.trn_stat |= 0x01;  /* enable TX */
+-
+-    atari_MFP_init_done = 1;
+-}
+-
+-#define SCC_WRITE(reg,val)				\
+-    do {						\
+-	scc.cha_b_ctrl = (reg);				\
+-	MFPDELAY();					\
+-	scc.cha_b_ctrl = (val);				\
+-	MFPDELAY();					\
+-    } while(0)
++	/*
++	 * timer values for 1200...115200 bps; > 38400 select 110, 134, or 150
++	 * bps, resp., and work only correct if there's a RSVE or RSSPEED
++	 */
++	static int baud_table[9] = { 16, 11, 8, 4, 2, 1, 175, 143, 128 };
++	int baud = cflag & CBAUD;
++	int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x04 : 0x06) : 0;
++	int csize = ((cflag & CSIZE) == CS7) ? 0x20 : 0x00;
++
++	if (cflag & CBAUDEX)
++		baud += B38400;
++	if (baud < B1200 || baud > B38400+2)
++		baud = B9600;		/* use default 9600bps for non-implemented rates */
++	baud -= B1200;			/* baud_table[] starts at 1200bps */
++
++	mfp.trn_stat &= ~0x01;		/* disable TX */
++	mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
++	mfp.tim_ct_cd &= 0x70;		/* stop timer D */
++	mfp.tim_dt_d = baud_table[baud];
++	mfp.tim_ct_cd |= 0x01;		/* start timer D, 1:4 */
++	mfp.trn_stat |= 0x01;		/* enable TX */
++
++	atari_MFP_init_done = 1;
++}
++
++#define SCC_WRITE(reg, val)				\
++	do {						\
++		scc.cha_b_ctrl = (reg);			\
++		MFPDELAY();				\
++		scc.cha_b_ctrl = (val);			\
++		MFPDELAY();				\
++	} while (0)
+ 
+ /* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
+  * delay of ~ 60us. */
+-#define LONG_DELAY()				\
+-    do {					\
+-	int i;					\
+-	for( i = 100; i > 0; --i )		\
+-	    MFPDELAY();				\
+-    } while(0)
++#define LONG_DELAY()					\
++	do {						\
++		int i;					\
++		for (i = 100; i > 0; --i)		\
++			MFPDELAY();			\
++	} while (0)
+ 
+ #ifndef CONFIG_SERIAL_CONSOLE
+-static void __init atari_init_scc_port( int cflag )
++static void __init atari_init_scc_port(int cflag)
+ #else
+-void atari_init_scc_port( int cflag )
++void atari_init_scc_port(int cflag)
+ #endif
+ {
+-    extern int atari_SCC_reset_done;
+-    static int clksrc_table[9] =
+-	/* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
+-	{ 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
+-    static int brgsrc_table[9] =
+-	/* reg 14: 0 = RTxC, 2 = PCLK */
+-	{ 2, 2, 2, 2, 2, 2, 0, 2, 2 };
+-    static int clkmode_table[9] =
+-	/* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */
+-	{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 };
+-    static int div_table[9] =
+-	/* reg12 (BRG low) */
+-	{ 208, 138, 103, 50, 24, 11, 1, 0, 0 };
+-
+-    int baud = cflag & CBAUD;
+-    int clksrc, clkmode, div, reg3, reg5;
+-
+-    if (cflag & CBAUDEX)
+-	baud += B38400;
+-    if (baud < B1200 || baud > B38400+2)
+-	baud = B9600; /* use default 9600bps for non-implemented rates */
+-    baud -= B1200; /* tables starts at 1200bps */
+-
+-    clksrc  = clksrc_table[baud];
+-    clkmode = clkmode_table[baud];
+-    div     = div_table[baud];
+-    if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
+-	/* special treatment for TT, where rates >= 38400 are done via TRxC */
+-	clksrc = 0x28; /* TRxC */
+-	clkmode = baud == 6 ? 0xc0 :
+-		  baud == 7 ? 0x80 : /* really 76800bps */
+-			      0x40;  /* really 153600bps */
+-	div = 0;
+-    }
+-
+-    reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40;
+-    reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */;
+-
+-    (void)scc.cha_b_ctrl;	/* reset reg pointer */
+-    SCC_WRITE( 9, 0xc0 );	/* reset */
+-    LONG_DELAY();		/* extra delay after WR9 access */
+-    SCC_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
+-		  0x04 /* 1 stopbit */ |
+-		  clkmode );
+-    SCC_WRITE( 3, reg3 );
+-    SCC_WRITE( 5, reg5 );
+-    SCC_WRITE( 9, 0 );		/* no interrupts */
+-    LONG_DELAY();		/* extra delay after WR9 access */
+-    SCC_WRITE( 10, 0 );		/* NRZ mode */
+-    SCC_WRITE( 11, clksrc );	/* main clock source */
+-    SCC_WRITE( 12, div );	/* BRG value */
+-    SCC_WRITE( 13, 0 );		/* BRG high byte */
+-    SCC_WRITE( 14, brgsrc_table[baud] );
+-    SCC_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) );
+-    SCC_WRITE( 3, reg3 | 1 );
+-    SCC_WRITE( 5, reg5 | 8 );
++	extern int atari_SCC_reset_done;
++	static int clksrc_table[9] =
++		/* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
++		{ 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
++	static int brgsrc_table[9] =
++		/* reg 14: 0 = RTxC, 2 = PCLK */
++		{ 2, 2, 2, 2, 2, 2, 0, 2, 2 };
++	static int clkmode_table[9] =
++		/* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */
++		{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 };
++	static int div_table[9] =
++		/* reg12 (BRG low) */
++		{ 208, 138, 103, 50, 24, 11, 1, 0, 0 };
++
++	int baud = cflag & CBAUD;
++	int clksrc, clkmode, div, reg3, reg5;
++
++	if (cflag & CBAUDEX)
++		baud += B38400;
++	if (baud < B1200 || baud > B38400+2)
++		baud = B9600;		/* use default 9600bps for non-implemented rates */
++	baud -= B1200;			/* tables starts at 1200bps */
++
++	clksrc  = clksrc_table[baud];
++	clkmode = clkmode_table[baud];
++	div     = div_table[baud];
++	if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
++		/* special treatment for TT, where rates >= 38400 are done via TRxC */
++		clksrc = 0x28;		/* TRxC */
++		clkmode = baud == 6 ? 0xc0 :
++			  baud == 7 ? 0x80 : /* really 76800bps */
++				      0x40;  /* really 153600bps */
++		div = 0;
++	}
++
++	reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40;
++	reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */;
++
++	(void)scc.cha_b_ctrl;		/* reset reg pointer */
++	SCC_WRITE(9, 0xc0);		/* reset */
++	LONG_DELAY();			/* extra delay after WR9 access */
++	SCC_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03)
++				      : 0 | 0x04 /* 1 stopbit */ | clkmode);
++	SCC_WRITE(3, reg3);
++	SCC_WRITE(5, reg5);
++	SCC_WRITE(9, 0);		/* no interrupts */
++	LONG_DELAY();			/* extra delay after WR9 access */
++	SCC_WRITE(10, 0);		/* NRZ mode */
++	SCC_WRITE(11, clksrc);		/* main clock source */
++	SCC_WRITE(12, div);		/* BRG value */
++	SCC_WRITE(13, 0);		/* BRG high byte */
++	SCC_WRITE(14, brgsrc_table[baud]);
++	SCC_WRITE(14, brgsrc_table[baud] | (div ? 1 : 0));
++	SCC_WRITE(3, reg3 | 1);
++	SCC_WRITE(5, reg5 | 8);
+ 
+-    atari_SCC_reset_done = 1;
+-    atari_SCC_init_done = 1;
++	atari_SCC_reset_done = 1;
++	atari_SCC_init_done = 1;
+ }
+ 
+ #ifndef CONFIG_SERIAL_CONSOLE
+-static void __init atari_init_midi_port( int cflag )
++static void __init atari_init_midi_port(int cflag)
+ #else
+-void atari_init_midi_port( int cflag )
++void atari_init_midi_port(int cflag)
+ #endif
+ {
+-    int baud = cflag & CBAUD;
+-    int csize = ((cflag & CSIZE) == CS8) ? 0x10 : 0x00;
+-    /* warning 7N1 isn't possible! (instead 7O2 is used...) */
+-    int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x0c : 0x08) : 0x04;
+-    int div;
+-
+-    /* 4800 selects 7812.5, 115200 selects 500000, all other (incl. 9600 as
+-     * default) the standard MIDI speed 31250. */
+-    if (cflag & CBAUDEX)
+-	baud += B38400;
+-    if (baud == B4800)
+-	div = ACIA_DIV64; /* really 7812.5 bps */
+-    else if (baud == B38400+2 /* 115200 */)
+-	div = ACIA_DIV1; /* really 500 kbps (does that work??) */
+-    else
+-	div = ACIA_DIV16; /* 31250 bps, standard for MIDI */
++	int baud = cflag & CBAUD;
++	int csize = ((cflag & CSIZE) == CS8) ? 0x10 : 0x00;
++	/* warning 7N1 isn't possible! (instead 7O2 is used...) */
++	int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x0c : 0x08) : 0x04;
++	int div;
++
++	/* 4800 selects 7812.5, 115200 selects 500000, all other (incl. 9600 as
++	 * default) the standard MIDI speed 31250. */
++	if (cflag & CBAUDEX)
++		baud += B38400;
++	if (baud == B4800)
++		div = ACIA_DIV64;	/* really 7812.5 bps */
++	else if (baud == B38400+2 /* 115200 */)
++		div = ACIA_DIV1;	/* really 500 kbps (does that work??) */
++	else
++		div = ACIA_DIV16;	/* 31250 bps, standard for MIDI */
+ 
+-    /* RTS low, ints disabled */
+-    acia.mid_ctrl = div | csize | parity |
++	/* RTS low, ints disabled */
++	acia.mid_ctrl = div | csize | parity |
+ 		    ((atari_switches & ATARI_SWITCH_MIDI) ?
+ 		     ACIA_RHTID : ACIA_RLTID);
+ }
+ 
+ void __init atari_debug_init(void)
+ {
+-    if (!strcmp( m68k_debug_device, "ser" )) {
+-	/* defaults to ser2 for a Falcon and ser1 otherwise */
+-	strcpy( m68k_debug_device, MACH_IS_FALCON ? "ser2" : "ser1" );
+-
+-    }
+-
+-    if (!strcmp( m68k_debug_device, "ser1" )) {
+-	/* ST-MFP Modem1 serial port */
+-	atari_init_mfp_port( B9600|CS8 );
+-	atari_console_driver.write = atari_mfp_console_write;
+-    }
+-    else if (!strcmp( m68k_debug_device, "ser2" )) {
+-	/* SCC Modem2 serial port */
+-	atari_init_scc_port( B9600|CS8 );
+-	atari_console_driver.write = atari_scc_console_write;
+-    }
+-    else if (!strcmp( m68k_debug_device, "midi" )) {
+-	/* MIDI port */
+-	atari_init_midi_port( B9600|CS8 );
+-	atari_console_driver.write = atari_midi_console_write;
+-    }
+-    else if (!strcmp( m68k_debug_device, "par" )) {
+-	/* parallel printer */
+-	atari_turnoff_irq( IRQ_MFP_BUSY ); /* avoid ints */
+-	sound_ym.rd_data_reg_sel = 7;  /* select mixer control */
+-	sound_ym.wd_data = 0xff;       /* sound off, ports are output */
+-	sound_ym.rd_data_reg_sel = 15; /* select port B */
+-	sound_ym.wd_data = 0;          /* no char */
+-	sound_ym.rd_data_reg_sel = 14; /* select port A */
+-	sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
+-	atari_console_driver.write = atari_par_console_write;
+-    }
+-    if (atari_console_driver.write)
+-	register_console(&atari_console_driver);
+-}
++	if (!strcmp(m68k_debug_device, "ser")) {
++		/* defaults to ser2 for a Falcon and ser1 otherwise */
++		strcpy(m68k_debug_device, MACH_IS_FALCON ? "ser2" : "ser1");
++	}
+ 
+-/*
+- * Local variables:
+- *  c-indent-level: 4
+- *  tab-width: 8
+- * End:
+- */
++	if (!strcmp(m68k_debug_device, "ser1")) {
++		/* ST-MFP Modem1 serial port */
++		atari_init_mfp_port(B9600|CS8);
++		atari_console_driver.write = atari_mfp_console_write;
++	} else if (!strcmp(m68k_debug_device, "ser2")) {
++		/* SCC Modem2 serial port */
++		atari_init_scc_port(B9600|CS8);
++		atari_console_driver.write = atari_scc_console_write;
++	} else if (!strcmp(m68k_debug_device, "midi")) {
++		/* MIDI port */
++		atari_init_midi_port(B9600|CS8);
++		atari_console_driver.write = atari_midi_console_write;
++	} else if (!strcmp(m68k_debug_device, "par")) {
++		/* parallel printer */
++		atari_turnoff_irq(IRQ_MFP_BUSY); /* avoid ints */
++		sound_ym.rd_data_reg_sel = 7;	/* select mixer control */
++		sound_ym.wd_data = 0xff;	/* sound off, ports are output */
++		sound_ym.rd_data_reg_sel = 15;	/* select port B */
++		sound_ym.wd_data = 0;		/* no char */
++		sound_ym.rd_data_reg_sel = 14;	/* select port A */
++		sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
++		atari_console_driver.write = atari_par_console_write;
++	}
++	if (atari_console_driver.write)
++		register_console(&atari_console_driver);
++}
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/entry.S
++++ linux-m68k-2.6.21/arch/m68k/kernel/entry.S
+@@ -692,7 +692,7 @@ sys_call_table:
+ 	.long sys_tgkill	/* 265 */
+ 	.long sys_utimes
+ 	.long sys_fadvise64_64
+-	.long sys_mbind	
++	.long sys_mbind
+ 	.long sys_get_mempolicy
+ 	.long sys_set_mempolicy	/* 270 */
+ 	.long sys_mq_open
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/head.S
++++ linux-m68k-2.6.21/arch/m68k/kernel/head.S
+@@ -3195,7 +3195,7 @@ func_start	serial_putc,%d0/%d1/%a0/%a1
+ 	jbra	L(serial_putc_done)
+ 3:
+ #endif
+-	
++
+ L(serial_putc_done):
+ func_return	serial_putc
+ 
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/setup.c
++++ linux-m68k-2.6.21/arch/m68k/kernel/setup.c
+@@ -133,78 +133,78 @@ extern void config_hp300(void);
+ extern void config_q40(void);
+ extern void config_sun3x(void);
+ 
+-extern void mac_debugging_short (int, short);
+-extern void mac_debugging_long  (int, long);
+-
+ #define MASK_256K 0xfffc0000
+ 
+ extern void paging_init(void);
+ 
+ static void __init m68k_parse_bootinfo(const struct bi_record *record)
+ {
+-    while (record->tag != BI_LAST) {
+-	int unknown = 0;
+-	const unsigned long *data = record->data;
+-	switch (record->tag) {
+-	    case BI_MACHTYPE:
+-	    case BI_CPUTYPE:
+-	    case BI_FPUTYPE:
+-	    case BI_MMUTYPE:
+-		/* Already set up by head.S */
+-		break;
+-
+-	    case BI_MEMCHUNK:
+-		if (m68k_num_memory < NUM_MEMINFO) {
+-		    m68k_memory[m68k_num_memory].addr = data[0];
+-		    m68k_memory[m68k_num_memory].size = data[1];
+-		    m68k_num_memory++;
+-		} else
+-		    printk("m68k_parse_bootinfo: too many memory chunks\n");
+-		break;
+-
+-	    case BI_RAMDISK:
+-		m68k_ramdisk.addr = data[0];
+-		m68k_ramdisk.size = data[1];
+-		break;
+-
+-	    case BI_COMMAND_LINE:
+-		strlcpy(m68k_command_line, (const char *)data, sizeof(m68k_command_line));
+-		break;
+-
+-	    default:
+-		if (MACH_IS_AMIGA)
+-		    unknown = amiga_parse_bootinfo(record);
+-		else if (MACH_IS_ATARI)
+-		    unknown = atari_parse_bootinfo(record);
+-		else if (MACH_IS_MAC)
+-		    unknown = mac_parse_bootinfo(record);
+-		else if (MACH_IS_Q40)
+-		    unknown = q40_parse_bootinfo(record);
+-		else if (MACH_IS_BVME6000)
+-		    unknown = bvme6000_parse_bootinfo(record);
+-		else if (MACH_IS_MVME16x)
+-		    unknown = mvme16x_parse_bootinfo(record);
+-		else if (MACH_IS_MVME147)
+-		    unknown = mvme147_parse_bootinfo(record);
+-		else if (MACH_IS_HP300)
+-		    unknown = hp300_parse_bootinfo(record);
+-		else
+-		    unknown = 1;
+-	}
+-	if (unknown)
+-	    printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
+-		   record->tag);
+-	record = (struct bi_record *)((unsigned long)record+record->size);
+-    }
++	while (record->tag != BI_LAST) {
++		int unknown = 0;
++		const unsigned long *data = record->data;
++
++		switch (record->tag) {
++		case BI_MACHTYPE:
++		case BI_CPUTYPE:
++		case BI_FPUTYPE:
++		case BI_MMUTYPE:
++			/* Already set up by head.S */
++			break;
++
++		case BI_MEMCHUNK:
++			if (m68k_num_memory < NUM_MEMINFO) {
++				m68k_memory[m68k_num_memory].addr = data[0];
++				m68k_memory[m68k_num_memory].size = data[1];
++				m68k_num_memory++;
++			} else
++				printk("m68k_parse_bootinfo: too many memory chunks\n");
++			break;
++
++		case BI_RAMDISK:
++			m68k_ramdisk.addr = data[0];
++			m68k_ramdisk.size = data[1];
++			break;
++
++		case BI_COMMAND_LINE:
++			strlcpy(m68k_command_line, (const char *)data,
++				sizeof(m68k_command_line));
++			break;
++
++		default:
++			if (MACH_IS_AMIGA)
++				unknown = amiga_parse_bootinfo(record);
++			else if (MACH_IS_ATARI)
++				unknown = atari_parse_bootinfo(record);
++			else if (MACH_IS_MAC)
++				unknown = mac_parse_bootinfo(record);
++			else if (MACH_IS_Q40)
++				unknown = q40_parse_bootinfo(record);
++			else if (MACH_IS_BVME6000)
++				unknown = bvme6000_parse_bootinfo(record);
++			else if (MACH_IS_MVME16x)
++				unknown = mvme16x_parse_bootinfo(record);
++			else if (MACH_IS_MVME147)
++				unknown = mvme147_parse_bootinfo(record);
++			else if (MACH_IS_HP300)
++				unknown = hp300_parse_bootinfo(record);
++			else
++				unknown = 1;
++		}
++		if (unknown)
++			printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
++			       record->tag);
++		record = (struct bi_record *)((unsigned long)record +
++					      record->size);
++	}
+ 
+-    m68k_realnum_memory = m68k_num_memory;
++	m68k_realnum_memory = m68k_num_memory;
+ #ifdef CONFIG_SINGLE_MEMORY_CHUNK
+-    if (m68k_num_memory > 1) {
+-	printk("Ignoring last %i chunks of physical memory\n",
+-	       (m68k_num_memory - 1));
+-	m68k_num_memory = 1;
+-    }
+-    m68k_memoffset = m68k_memory[0].addr-PAGE_OFFSET;
++	if (m68k_num_memory > 1) {
++		printk("Ignoring last %i chunks of physical memory\n",
++		       (m68k_num_memory - 1));
++		m68k_num_memory = 1;
++	}
++	m68k_memoffset = m68k_memory[0].addr-PAGE_OFFSET;
+ #endif
+ }
+ 
+@@ -234,7 +234,7 @@ void __init setup_arch(char **cmdline_p)
+ 	/* clear the fpu if we have one */
+ 	if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
+ 		volatile int zero = 0;
+-		asm __volatile__ ("frestore %0" : : "m" (zero));
++		asm volatile ("frestore %0" : : "m" (zero));
+ 	}
+ #endif
+ 
+@@ -262,32 +262,35 @@ void __init setup_arch(char **cmdline_p)
+ 	 * For the m68k, this is currently only "debug=xxx" to enable printing
+ 	 * certain kernel messages to some machine-specific device.
+ 	 */
+-	for( p = *cmdline_p; p && *p; ) {
+-	    i = 0;
+-	    if (!strncmp( p, "debug=", 6 )) {
+-		strlcpy( m68k_debug_device, p+6, sizeof(m68k_debug_device) );
+-		if ((q = strchr( m68k_debug_device, ' ' ))) *q = 0;
+-		i = 1;
+-	    }
++	for (p = *cmdline_p; p && *p;) {
++		i = 0;
++		if (!strncmp(p, "debug=", 6)) {
++			strlcpy(m68k_debug_device, p+6, sizeof(m68k_debug_device));
++			q = strchr(m68k_debug_device, ' ');
++			if (q)
++				*q = 0;
++			i = 1;
++		}
+ #ifdef CONFIG_ATARI
+-	    /* This option must be parsed very early */
+-	    if (!strncmp( p, "switches=", 9 )) {
+-		extern void atari_switches_setup( const char *, int );
+-		atari_switches_setup( p+9, (q = strchr( p+9, ' ' )) ?
+-				           (q - (p+9)) : strlen(p+9) );
+-		i = 1;
+-	    }
+-#endif
+-
+-	    if (i) {
+-		/* option processed, delete it */
+-		if ((q = strchr( p, ' ' )))
+-		    strcpy( p, q+1 );
+-		else
+-		    *p = 0;
+-	    } else {
+-		if ((p = strchr( p, ' ' ))) ++p;
+-	    }
++		/* This option must be parsed very early */
++		if (!strncmp(p, "switches=", 9)) {
++			extern void atari_switches_setup(const char *, int);
++			q = strchr(p + 9, ' ');
++			atari_switches_setup(p + 9, q ? (q - (p + 9)) : strlen(p + 9));
++			i = 1;
++		}
++#endif
++
++		if (i) {
++			/* option processed, delete it */
++			if ((q = strchr(p, ' ')))
++				strcpy(p, q + 1);
++			else
++				*p = 0;
++		} else {
++			if ((p = strchr(p, ' ')))
++				++p;
++		}
+ 	}
+ 
+ #ifdef CONFIG_DUMMY_CONSOLE
+@@ -296,62 +299,62 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	switch (m68k_machtype) {
+ #ifdef CONFIG_AMIGA
+-	    case MACH_AMIGA:
++	case MACH_AMIGA:
+ 		config_amiga();
+ 		break;
+ #endif
+ #ifdef CONFIG_ATARI
+-	    case MACH_ATARI:
++	case MACH_ATARI:
+ 		config_atari();
+ 		break;
+ #endif
+ #ifdef CONFIG_MAC
+-	    case MACH_MAC:
++	case MACH_MAC:
+ 		config_mac();
+ 		break;
+ #endif
+ #ifdef CONFIG_SUN3
+-	    case MACH_SUN3:
++	case MACH_SUN3:
+ 		config_sun3();
+ 		break;
+ #endif
+ #ifdef CONFIG_APOLLO
+-	    case MACH_APOLLO:
++	case MACH_APOLLO:
+ 		config_apollo();
+ 		break;
+ #endif
+ #ifdef CONFIG_MVME147
+-	    case MACH_MVME147:
++	case MACH_MVME147:
+ 		config_mvme147();
+ 		break;
+ #endif
+ #ifdef CONFIG_MVME16x
+-	    case MACH_MVME16x:
++	case MACH_MVME16x:
+ 		config_mvme16x();
+ 		break;
+ #endif
+ #ifdef CONFIG_BVME6000
+-	    case MACH_BVME6000:
++	case MACH_BVME6000:
+ 		config_bvme6000();
+ 		break;
+ #endif
+ #ifdef CONFIG_HP300
+-	    case MACH_HP300:
++	case MACH_HP300:
+ 		config_hp300();
+ 		break;
+ #endif
+ #ifdef CONFIG_Q40
+-	    case MACH_Q40:
+-	        config_q40();
++	case MACH_Q40:
++		config_q40();
+ 		break;
+ #endif
+ #ifdef CONFIG_SUN3X
+-	    case MACH_SUN3X:
++	case MACH_SUN3X:
+ 		config_sun3x();
+ 		break;
+ #endif
+-	    default:
+-		panic ("No configuration setup");
++	default:
++		panic("No configuration setup");
+ 	}
+ 
+ #ifndef CONFIG_SUN3
+@@ -380,7 +383,7 @@ void __init setup_arch(char **cmdline_p)
+ 		reserve_bootmem(m68k_ramdisk.addr, m68k_ramdisk.size);
+ 		initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
+ 		initrd_end = initrd_start + m68k_ramdisk.size;
+-		printk ("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
++		printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
+ 	}
+ #endif
+ 
+@@ -402,18 +405,18 @@ void __init setup_arch(char **cmdline_p)
+ #if defined(CONFIG_ISA) && defined(MULTI_ISA)
+ #if defined(CONFIG_Q40)
+ 	if (MACH_IS_Q40) {
+-	    isa_type = Q40_ISA;
+-	    isa_sex = 0;
++		isa_type = Q40_ISA;
++		isa_sex = 0;
+ 	}
+ #elif defined(CONFIG_GG2)
+-	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)){
+-	    isa_type = GG2_ISA;
+-	    isa_sex = 0;
++	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)) {
++		isa_type = GG2_ISA;
++		isa_sex = 0;
+ 	}
+ #elif defined(CONFIG_AMIGA_PCMCIA)
+-	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)){
+-	    isa_type = AG_ISA;
+-	    isa_sex = 1;
++	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
++		isa_type = AG_ISA;
++		isa_sex = 1;
+ 	}
+ #endif
+ #endif
+@@ -421,66 +424,66 @@ void __init setup_arch(char **cmdline_p)
+ 
+ static int show_cpuinfo(struct seq_file *m, void *v)
+ {
+-    const char *cpu, *mmu, *fpu;
+-    unsigned long clockfreq, clockfactor;
++	const char *cpu, *mmu, *fpu;
++	unsigned long clockfreq, clockfactor;
+ 
+ #define LOOP_CYCLES_68020	(8)
+ #define LOOP_CYCLES_68030	(8)
+ #define LOOP_CYCLES_68040	(3)
+ #define LOOP_CYCLES_68060	(1)
+ 
+-    if (CPU_IS_020) {
+-	cpu = "68020";
+-	clockfactor = LOOP_CYCLES_68020;
+-    } else if (CPU_IS_030) {
+-	cpu = "68030";
+-	clockfactor = LOOP_CYCLES_68030;
+-    } else if (CPU_IS_040) {
+-	cpu = "68040";
+-	clockfactor = LOOP_CYCLES_68040;
+-    } else if (CPU_IS_060) {
+-	cpu = "68060";
+-	clockfactor = LOOP_CYCLES_68060;
+-    } else {
+-	cpu = "680x0";
+-	clockfactor = 0;
+-    }
++	if (CPU_IS_020) {
++		cpu = "68020";
++		clockfactor = LOOP_CYCLES_68020;
++	} else if (CPU_IS_030) {
++		cpu = "68030";
++		clockfactor = LOOP_CYCLES_68030;
++	} else if (CPU_IS_040) {
++		cpu = "68040";
++		clockfactor = LOOP_CYCLES_68040;
++	} else if (CPU_IS_060) {
++		cpu = "68060";
++		clockfactor = LOOP_CYCLES_68060;
++	} else {
++		cpu = "680x0";
++		clockfactor = 0;
++	}
+ 
+ #ifdef CONFIG_M68KFPU_EMU_ONLY
+-    fpu="none(soft float)";
++	fpu = "none(soft float)";
+ #else
+-    if (m68k_fputype & FPU_68881)
+-	fpu = "68881";
+-    else if (m68k_fputype & FPU_68882)
+-	fpu = "68882";
+-    else if (m68k_fputype & FPU_68040)
+-	fpu = "68040";
+-    else if (m68k_fputype & FPU_68060)
+-	fpu = "68060";
+-    else if (m68k_fputype & FPU_SUNFPA)
+-	fpu = "Sun FPA";
+-    else
+-	fpu = "none";
+-#endif
+-
+-    if (m68k_mmutype & MMU_68851)
+-	mmu = "68851";
+-    else if (m68k_mmutype & MMU_68030)
+-	mmu = "68030";
+-    else if (m68k_mmutype & MMU_68040)
+-	mmu = "68040";
+-    else if (m68k_mmutype & MMU_68060)
+-	mmu = "68060";
+-    else if (m68k_mmutype & MMU_SUN3)
+-	mmu = "Sun-3";
+-    else if (m68k_mmutype & MMU_APOLLO)
+-	mmu = "Apollo";
+-    else
+-	mmu = "unknown";
++	if (m68k_fputype & FPU_68881)
++		fpu = "68881";
++	else if (m68k_fputype & FPU_68882)
++		fpu = "68882";
++	else if (m68k_fputype & FPU_68040)
++		fpu = "68040";
++	else if (m68k_fputype & FPU_68060)
++		fpu = "68060";
++	else if (m68k_fputype & FPU_SUNFPA)
++		fpu = "Sun FPA";
++	else
++		fpu = "none";
++#endif
++
++	if (m68k_mmutype & MMU_68851)
++		mmu = "68851";
++	else if (m68k_mmutype & MMU_68030)
++		mmu = "68030";
++	else if (m68k_mmutype & MMU_68040)
++		mmu = "68040";
++	else if (m68k_mmutype & MMU_68060)
++		mmu = "68060";
++	else if (m68k_mmutype & MMU_SUN3)
++		mmu = "Sun-3";
++	else if (m68k_mmutype & MMU_APOLLO)
++		mmu = "Apollo";
++	else
++		mmu = "unknown";
+ 
+-    clockfreq = loops_per_jiffy*HZ*clockfactor;
++	clockfreq = loops_per_jiffy * HZ * clockfactor;
+ 
+-    seq_printf(m, "CPU:\t\t%s\n"
++	seq_printf(m, "CPU:\t\t%s\n"
+ 		   "MMU:\t\t%s\n"
+ 		   "FPU:\t\t%s\n"
+ 		   "Clocking:\t%lu.%1luMHz\n"
+@@ -490,7 +493,7 @@ static int show_cpuinfo(struct seq_file 
+ 		   clockfreq/1000000,(clockfreq/100000)%10,
+ 		   loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
+ 		   loops_per_jiffy);
+-    return 0;
++	return 0;
+ }
+ 
+ static void *c_start(struct seq_file *m, loff_t *pos)
+@@ -506,44 +509,44 @@ static void c_stop(struct seq_file *m, v
+ {
+ }
+ struct seq_operations cpuinfo_op = {
+-	.start =	c_start,
+-	.next =		c_next,
+-	.stop =		c_stop,
+-	.show =		show_cpuinfo,
++	.start	= c_start,
++	.next	= c_next,
++	.stop	= c_stop,
++	.show	= show_cpuinfo,
+ };
+ 
+ int get_hardware_list(char *buffer)
+ {
+-    int len = 0;
+-    char model[80];
+-    unsigned long mem;
+-    int i;
+-
+-    if (mach_get_model)
+-	mach_get_model(model);
+-    else
+-	strcpy(model, "Unknown m68k");
+-
+-    len += sprintf(buffer+len, "Model:\t\t%s\n", model);
+-    for (mem = 0, i = 0; i < m68k_num_memory; i++)
+-	mem += m68k_memory[i].size;
+-    len += sprintf(buffer+len, "System Memory:\t%ldK\n", mem>>10);
++	int len = 0;
++	char model[80];
++	unsigned long mem;
++	int i;
++
++	if (mach_get_model)
++		mach_get_model(model);
++	else
++		strcpy(model, "Unknown m68k");
++
++	len += sprintf(buffer + len, "Model:\t\t%s\n", model);
++	for (mem = 0, i = 0; i < m68k_num_memory; i++)
++		mem += m68k_memory[i].size;
++	len += sprintf(buffer + len, "System Memory:\t%ldK\n", mem >> 10);
+ 
+-    if (mach_get_hardware_list)
+-	len += mach_get_hardware_list(buffer+len);
++	if (mach_get_hardware_list)
++		len += mach_get_hardware_list(buffer + len);
+ 
+-    return(len);
++	return len;
+ }
+ 
+ void check_bugs(void)
+ {
+ #ifndef CONFIG_M68KFPU_EMU
+ 	if (m68k_fputype == 0) {
+-		printk( KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
+-				"WHICH IS REQUIRED BY LINUX/M68K ***\n" );
+-		printk( KERN_EMERG "Upgrade your hardware or join the FPU "
+-				"emulation project\n" );
+-		panic( "no FPU" );
++		printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
++			"WHICH IS REQUIRED BY LINUX/M68K ***\n");
++		printk(KERN_EMERG "Upgrade your hardware or join the FPU "
++			"emulation project\n");
++		panic("no FPU");
+ 	}
+ #endif /* !CONFIG_M68KFPU_EMU */
+ }
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/config.c
++++ linux-m68k-2.6.21/arch/m68k/mac/config.c
+@@ -59,15 +59,15 @@ extern struct mem_info m68k_ramdisk;
+ 
+ extern char m68k_command_line[CL_SIZE];
+ 
+-void *mac_env;		/* Loaded by the boot asm */
++void *mac_env;					/* Loaded by the boot asm */
+ 
+ /* The phys. video addr. - might be bogus on some machines */
+ unsigned long mac_orig_videoaddr;
+ 
+ /* Mac specific timer functions */
+-extern unsigned long mac_gettimeoffset (void);
+-extern int mac_hwclk (int, struct rtc_time *);
+-extern int mac_set_clock_mmss (unsigned long);
++extern unsigned long mac_gettimeoffset(void);
++extern int mac_hwclk(int, struct rtc_time *);
++extern int mac_set_clock_mmss(unsigned long);
+ extern int show_mac_interrupts(struct seq_file *, void *);
+ extern void iop_preinit(void);
+ extern void iop_init(void);
+@@ -99,51 +99,52 @@ static void mac_sched_init(irq_handler_t
+ 
+ int __init mac_parse_bootinfo(const struct bi_record *record)
+ {
+-    int unknown = 0;
+-    const u_long *data = record->data;
++	int unknown = 0;
++	const u_long *data = record->data;
+ 
+-    switch (record->tag) {
++	switch (record->tag) {
+ 	case BI_MAC_MODEL:
+-	    mac_bi_data.id = *data;
+-	    break;
++		mac_bi_data.id = *data;
++		break;
+ 	case BI_MAC_VADDR:
+-	    mac_bi_data.videoaddr = *data;
+-	    break;
++		mac_bi_data.videoaddr = *data;
++		break;
+ 	case BI_MAC_VDEPTH:
+-	    mac_bi_data.videodepth = *data;
+-	    break;
++		mac_bi_data.videodepth = *data;
++		break;
+ 	case BI_MAC_VROW:
+-	    mac_bi_data.videorow = *data;
+-	    break;
++		mac_bi_data.videorow = *data;
++		break;
+ 	case BI_MAC_VDIM:
+-	    mac_bi_data.dimensions = *data;
+-	    break;
++		mac_bi_data.dimensions = *data;
++		break;
+ 	case BI_MAC_VLOGICAL:
+-	    mac_bi_data.videological = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK);
+-	    mac_orig_videoaddr = *data;
+-	    break;
++		mac_bi_data.videological = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK);
++		mac_orig_videoaddr = *data;
++		break;
+ 	case BI_MAC_SCCBASE:
+-	    mac_bi_data.sccbase = *data;
+-	    break;
++		mac_bi_data.sccbase = *data;
++		break;
+ 	case BI_MAC_BTIME:
+-	    mac_bi_data.boottime = *data;
+-	    break;
++		mac_bi_data.boottime = *data;
++		break;
+ 	case BI_MAC_GMTBIAS:
+-	    mac_bi_data.gmtbias = *data;
+-	    break;
++		mac_bi_data.gmtbias = *data;
++		break;
+ 	case BI_MAC_MEMSIZE:
+-	    mac_bi_data.memsize = *data;
+-	    break;
++		mac_bi_data.memsize = *data;
++		break;
+ 	case BI_MAC_CPUID:
+-	    mac_bi_data.cpuid = *data;
+-	    break;
+-        case BI_MAC_ROMBASE:
+-	    mac_bi_data.rombase = *data;
+-	    break;
++		mac_bi_data.cpuid = *data;
++		break;
++	case BI_MAC_ROMBASE:
++		mac_bi_data.rombase = *data;
++		break;
+ 	default:
+-	    unknown = 1;
+-    }
+-    return(unknown);
++		unknown = 1;
++		break;
++	}
++	return unknown;
+ }
+ 
+ /*
+@@ -155,6 +156,7 @@ int __init mac_parse_bootinfo(const stru
+ static void mac_cache_card_flush(int writeback)
+ {
+ 	unsigned long flags;
++
+ 	local_irq_save(flags);
+ 	via_flush_cache();
+ 	local_irq_restore(flags);
+@@ -162,28 +164,27 @@ static void mac_cache_card_flush(int wri
+ 
+ void __init config_mac(void)
+ {
+-	if (!MACH_IS_MAC) {
+-	  printk(KERN_ERR "ERROR: no Mac, but config_mac() called!! \n");
+-	}
++	if (!MACH_IS_MAC)
++		printk(KERN_ERR "ERROR: no Mac, but config_mac() called!! \n");
+ 
+-	mach_sched_init      = mac_sched_init;
+-	mach_init_IRQ        = mac_init_IRQ;
+-	mach_get_model	 = mac_get_model;
+-	mach_gettimeoffset   = mac_gettimeoffset;
++	mach_sched_init = mac_sched_init;
++	mach_init_IRQ = mac_init_IRQ;
++	mach_get_model = mac_get_model;
++	mach_gettimeoffset = mac_gettimeoffset;
+ #warning move to adb/via init
+ #if 0
+-	mach_hwclk           = mac_hwclk;
++	mach_hwclk = mac_hwclk;
+ #endif
+-	mach_set_clock_mmss	 = mac_set_clock_mmss;
+-	mach_reset           = mac_reset;
+-	mach_halt            = mac_poweroff;
+-	mach_power_off       = mac_poweroff;
++	mach_set_clock_mmss = mac_set_clock_mmss;
++	mach_reset = mac_reset;
++	mach_halt = mac_poweroff;
++	mach_power_off = mac_poweroff;
+ 	mach_max_dma_address = 0xffffffff;
+ #if 0
+-	mach_debug_init	 = mac_debug_init;
++	mach_debug_init	= mac_debug_init;
+ #endif
+ #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
+-        mach_beep            = mac_mksound;
++	mach_beep = mac_mksound;
+ #endif
+ #ifdef CONFIG_HEARTBEAT
+ #if 0
+@@ -199,21 +200,22 @@ void __init config_mac(void)
+ 	mac_identify();
+ 	mac_report_hardware();
+ 
+-	/* AFAIK only the IIci takes a cache card.  The IIfx has onboard
+-	   cache ... someone needs to figure out how to tell if it's on or
+-	   not. */
++	/*
++	 * AFAIK only the IIci takes a cache card.  The IIfx has onboard
++	 * cache ... someone needs to figure out how to tell if it's on or
++	 * not.
++	 */
+ 
+ 	if (macintosh_config->ident == MAC_MODEL_IICI
+-	    || macintosh_config->ident == MAC_MODEL_IIFX) {
++	    || macintosh_config->ident == MAC_MODEL_IIFX)
+ 		mach_l2_flush = mac_cache_card_flush;
+-	}
+ 
+ 	/*
+ 	 * Check for machine specific fixups.
+ 	 */
+ 
+ #ifdef OLD_NUBUS_CODE
+-	 nubus_sweep_video();
++	nubus_sweep_video();
+ #endif
+ }
+ 
+@@ -233,8 +235,7 @@ void __init config_mac(void)
+ struct mac_model *macintosh_config;
+ EXPORT_SYMBOL(macintosh_config);
+ 
+-static struct mac_model mac_data_table[]=
+-{
++static struct mac_model mac_data_table[] = {
+ 	/*
+ 	 *	We'll pretend to be a Macintosh II, that's pretty safe.
+ 	 */
+@@ -784,12 +785,12 @@ void mac_identify(void)
+ 	if (!model) {
+ 		/* no bootinfo model id -> NetBSD booter was used! */
+ 		/* XXX FIXME: breaks for model > 31 */
+-		model=(mac_bi_data.cpuid>>2)&63;
+-		printk (KERN_WARNING "No bootinfo model ID, using cpuid instead (hey, use Penguin!)\n");
++		model = (mac_bi_data.cpuid >> 2) & 63;
++		printk(KERN_WARNING "No bootinfo model ID, using cpuid instead (hey, use Penguin!)\n");
+ 	}
+ 
+ 	macintosh_config = mac_data_table;
+-	for (m = macintosh_config ; m->ident != -1 ; m++) {
++	for (m = macintosh_config; m->ident != -1; m++) {
+ 		if (m->ident == model) {
+ 			macintosh_config = m;
+ 			break;
+@@ -803,25 +804,25 @@ void mac_identify(void)
+ 	iop_preinit();
+ 	mac_debug_init();
+ 
+-	printk (KERN_INFO "Detected Macintosh model: %d \n", model);
++	printk(KERN_INFO "Detected Macintosh model: %d \n", model);
+ 
+ 	/*
+ 	 * Report booter data:
+ 	 */
+-	printk (KERN_DEBUG " Penguin bootinfo data:\n");
+-	printk (KERN_DEBUG " Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n",
++	printk(KERN_DEBUG " Penguin bootinfo data:\n");
++	printk(KERN_DEBUG " Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n",
+ 		mac_bi_data.videoaddr, mac_bi_data.videorow,
+ 		mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF,
+ 		mac_bi_data.dimensions >> 16);
+-	printk (KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n",
++	printk(KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n",
+ 		mac_bi_data.videological, mac_orig_videoaddr,
+ 		mac_bi_data.sccbase);
+-	printk (KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx \n",
++	printk(KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx \n",
+ 		mac_bi_data.boottime, mac_bi_data.gmtbias);
+-	printk (KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
++	printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
+ 		mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize);
+ #if 0
+-	printk ("Ramdisk: addr 0x%lx size 0x%lx\n",
++	printk("Ramdisk: addr 0x%lx size 0x%lx\n",
+ 		m68k_ramdisk.addr, m68k_ramdisk.size);
+ #endif
+ 
+@@ -830,22 +831,22 @@ void mac_identify(void)
+ 	 */
+ 	switch (macintosh_config->scsi_type) {
+ 	case MAC_SCSI_OLD:
+-	  MACHW_SET(MAC_SCSI_80);
+-	  break;
++		MACHW_SET(MAC_SCSI_80);
++		break;
+ 	case MAC_SCSI_QUADRA:
+ 	case MAC_SCSI_QUADRA2:
+ 	case MAC_SCSI_QUADRA3:
+-	  MACHW_SET(MAC_SCSI_96);
+-	  if ((macintosh_config->ident == MAC_MODEL_Q900) ||
+-	      (macintosh_config->ident == MAC_MODEL_Q950))
+-	    MACHW_SET(MAC_SCSI_96_2);
+-	  break;
++		MACHW_SET(MAC_SCSI_96);
++		if ((macintosh_config->ident == MAC_MODEL_Q900) ||
++		    (macintosh_config->ident == MAC_MODEL_Q950))
++			MACHW_SET(MAC_SCSI_96_2);
++		break;
+ 	default:
+-	  printk(KERN_WARNING "config.c: wtf: unknown scsi, using 53c80\n");
+-	  MACHW_SET(MAC_SCSI_80);
+-	  break;
+-
++		printk(KERN_WARNING "config.c: wtf: unknown scsi, using 53c80\n");
++		MACHW_SET(MAC_SCSI_80);
++		break;
+ 	}
++
+ 	iop_init();
+ 	via_init();
+ 	oss_init();
+@@ -860,6 +861,6 @@ void mac_report_hardware(void)
+ 
+ static void mac_get_model(char *str)
+ {
+-	strcpy(str,"Macintosh ");
++	strcpy(str, "Macintosh ");
+ 	strcat(str, macintosh_config->name);
+ }
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/debug.c
++++ linux-m68k-2.6.21/arch/m68k/mac/debug.c
+@@ -52,7 +52,7 @@ extern void mac_serial_print(const char 
+  */
+ 
+ #ifdef DEBUG_SCREEN
+-static int peng=0, line=0;
++static int peng, line;
+ #endif
+ 
+ void mac_debugging_short(int pos, short num)
+@@ -74,15 +74,14 @@ void mac_debugging_short(int pos, short 
+ 	}
+ 
+ 	/* calculate current offset */
+-	pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes)
+-		    +80*peng;
++	pengoffset = (unsigned char *)mac_videobase +
++		(150+line*2) * mac_rowbytes) + 80 * peng;
+ 
+-	pptr=pengoffset;
++	pptr = pengoffset;
+ 
+-	for(i=0;i<8*sizeof(short);i++) /* # of bits */
+-	{
++	for (i = 0; i < 8 * sizeof(short); i++) { /* # of bits */
+ 		/*        value        mask for bit i, reverse order */
+-		*pptr++ = (num & ( 1 << (8*sizeof(short)-i-1) ) ? 0xFF : 0x00);
++		*pptr++ = (num & (1 << (8*sizeof(short)-i-1)) ? 0xFF : 0x00);
+ 	}
+ 
+ 	peng++;
+@@ -115,11 +114,10 @@ void mac_debugging_long(int pos, long ad
+ 	pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes)
+ 		    +80*peng;
+ 
+-	pptr=pengoffset;
++	pptr = pengoffset;
+ 
+-	for(i=0;i<8*sizeof(long);i++) /* # of bits */
+-	{
+-		*pptr++ = (addr & ( 1 << (8*sizeof(long)-i-1) ) ? 0xFF : 0x00);
++	for (i = 0; i < 8 * sizeof(long); i++) { /* # of bits */
++		*pptr++ = (addr & (1 << (8*sizeof(long)-i-1)) ? 0xFF : 0x00);
+ 	}
+ 
+ 	peng++;
+@@ -136,16 +134,15 @@ void mac_debugging_long(int pos, long ad
+  * TODO: serial debug code
+  */
+ 
+-struct mac_SCC
+- {
+-  u_char cha_b_ctrl;
+-  u_char char_dummy1;
+-  u_char cha_a_ctrl;
+-  u_char char_dummy2;
+-  u_char cha_b_data;
+-  u_char char_dummy3;
+-  u_char cha_a_data;
+- };
++struct mac_SCC {
++	u_char cha_b_ctrl;
++	u_char char_dummy1;
++	u_char cha_a_ctrl;
++	u_char char_dummy2;
++	u_char cha_b_data;
++	u_char char_dummy3;
++	u_char cha_a_data;
++};
+ 
+ # define scc (*((volatile struct mac_SCC*)mac_bi_data.sccbase))
+ 
+@@ -158,9 +155,9 @@ int mac_SCC_reset_done;
+ static int scc_port = -1;
+ 
+ static struct console mac_console_driver = {
+-	.name =		"debug",
+-	.flags =	CON_PRINTBUFFER,
+-	.index =	-1,
++	.name	= "debug",
++	.flags	= CON_PRINTBUFFER,
++	.index	= -1,
+ };
+ 
+ /*
+@@ -178,8 +175,8 @@ static struct console mac_console_driver
+  * this driver if Mac.
+  */
+ 
+-void mac_debug_console_write (struct console *co, const char *str,
+-			      unsigned int count)
++void mac_debug_console_write(struct console *co, const char *str,
++			     unsigned int count)
+ {
+ 	mac_serial_print(str);
+ }
+@@ -190,48 +187,50 @@ void mac_debug_console_write (struct con
+ 
+ #define uSEC 1
+ 
+-static inline void mac_sccb_out (char c)
++static inline void mac_sccb_out(char c)
+ {
+-    int i;
+-    do {
+-	for( i = uSEC; i > 0; --i )
++	int i;
++
++	do {
++		for (i = uSEC; i > 0; --i)
++			barrier();
++	} while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
++	for (i = uSEC; i > 0; --i)
+ 		barrier();
+-    } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
+-    for( i = uSEC; i > 0; --i )
+-	barrier();
+-    scc.cha_b_data = c;
++	scc.cha_b_data = c;
+ }
+ 
+-static inline void mac_scca_out (char c)
++static inline void mac_scca_out(char c)
+ {
+-    int i;
+-    do {
+-	for( i = uSEC; i > 0; --i )
++	int i;
++
++	do {
++		for (i = uSEC; i > 0; --i)
++			barrier();
++	} while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */
++	for (i = uSEC; i > 0; --i)
+ 		barrier();
+-    } while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */
+-    for( i = uSEC; i > 0; --i )
+-	barrier();
+-    scc.cha_a_data = c;
+-}
+-
+-void mac_sccb_console_write (struct console *co, const char *str,
+-			      unsigned int count)
+-{
+-    while (count--) {
+-	if (*str == '\n')
+-	    mac_sccb_out( '\r' );
+-	mac_sccb_out( *str++ );
+-    }
+-}
+-
+-void mac_scca_console_write (struct console *co, const char *str,
+-			      unsigned int count)
+-{
+-    while (count--) {
+-	if (*str == '\n')
+-	    mac_scca_out( '\r' );
+-	mac_scca_out( *str++ );
+-    }
++	scc.cha_a_data = c;
++}
++
++void mac_sccb_console_write(struct console *co, const char *str,
++			    unsigned int count)
++{
++	while (count--) {
++		if (*str == '\n')
++			mac_sccb_out('\r');
++		mac_sccb_out(*str++);
++	}
++}
++
++void mac_scca_console_write(struct console *co, const char *str,
++			    unsigned int count)
++{
++	while (count--) {
++		if (*str == '\n')
++			mac_scca_out('\r');
++		mac_scca_out(*str++);
++	}
+ }
+ 
+ 
+@@ -239,41 +238,41 @@ void mac_scca_console_write (struct cons
+  * SCC serial ports. They're used by the debugging interface, kgdb, and the
+  * serial console code. */
+ #define SCCB_WRITE(reg,val)				\
+-    do {						\
+-	int i;						\
+-	scc.cha_b_ctrl = (reg);				\
+-	for( i = uSEC; i > 0; --i )			\
+-		barrier();				\
+-	scc.cha_b_ctrl = (val);				\
+-	for( i = uSEC; i > 0; --i )			\
+-		barrier();				\
+-    } while(0)
++	do {						\
++		int i;					\
++		scc.cha_b_ctrl = (reg);			\
++		for (i = uSEC; i > 0; --i)		\
++			barrier();			\
++		scc.cha_b_ctrl = (val);			\
++		for (i = uSEC; i > 0; --i)		\
++			barrier();			\
++	} while(0)
+ 
+ #define SCCA_WRITE(reg,val)				\
+-    do {						\
+-	int i;						\
+-	scc.cha_a_ctrl = (reg);				\
+-	for( i = uSEC; i > 0; --i )			\
+-		barrier();				\
+-	scc.cha_a_ctrl = (val);				\
+-	for( i = uSEC; i > 0; --i )			\
+-		barrier();				\
+-    } while(0)
++	do {						\
++		int i;					\
++		scc.cha_a_ctrl = (reg);			\
++		for (i = uSEC; i > 0; --i)		\
++			barrier();			\
++		scc.cha_a_ctrl = (val);			\
++		for (i = uSEC; i > 0; --i)		\
++			barrier();			\
++	} while(0)
+ 
+ /* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
+  * delay of ~ 60us. */
+ /* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/
+-#define LONG_DELAY()				\
+-    do {					\
+-	int i;					\
+-	for( i = 60*uSEC; i > 0; --i )		\
+-	    barrier();				\
+-    } while(0)
++#define LONG_DELAY()					\
++	do {						\
++		int i;					\
++		for (i = 60*uSEC; i > 0; --i)		\
++		    barrier();				\
++	} while(0)
+ 
+ #ifndef CONFIG_SERIAL_CONSOLE
+-static void __init mac_init_scc_port( int cflag, int port )
++static void __init mac_init_scc_port(int cflag, int port)
+ #else
+-void mac_init_scc_port( int cflag, int port )
++void mac_init_scc_port(int cflag, int port)
+ #endif
+ {
+ 	extern int mac_SCC_reset_done;
+@@ -292,71 +291,71 @@ void mac_init_scc_port( int cflag, int p
+ 		/* reg12 (BRG low) */
+ 		{ 94, 62, 46, 22, 10, 4, 1, 0, 0 };
+ 
+-    int baud = cflag & CBAUD;
+-    int clksrc, clkmode, div, reg3, reg5;
++	int baud = cflag & CBAUD;
++	int clksrc, clkmode, div, reg3, reg5;
+ 
+-    if (cflag & CBAUDEX)
+-	baud += B38400;
+-    if (baud < B1200 || baud > B38400+2)
+-	baud = B9600; /* use default 9600bps for non-implemented rates */
+-    baud -= B1200; /* tables starts at 1200bps */
+-
+-    clksrc  = clksrc_table[baud];
+-    clkmode = clkmode_table[baud];
+-    div     = div_table[baud];
+-
+-    reg3 = (((cflag & CSIZE) == CS8) ? 0xc0 : 0x40);
+-    reg5 = (((cflag & CSIZE) == CS8) ? 0x60 : 0x20) | 0x82 /* assert DTR/RTS */;
+-
+-    if (port == 1) {
+-	    (void)scc.cha_b_ctrl;	/* reset reg pointer */
+-	    SCCB_WRITE( 9, 0xc0 );	/* reset */
+-	    LONG_DELAY();		/* extra delay after WR9 access */
+-	    SCCB_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
+-			  0x04 /* 1 stopbit */ |
+-			  clkmode );
+-	    SCCB_WRITE( 3, reg3 );
+-	    SCCB_WRITE( 5, reg5 );
+-	    SCCB_WRITE( 9, 0 );		/* no interrupts */
+-	    LONG_DELAY();		/* extra delay after WR9 access */
+-	    SCCB_WRITE( 10, 0 );	/* NRZ mode */
+-	    SCCB_WRITE( 11, clksrc );	/* main clock source */
+-	    SCCB_WRITE( 12, div );	/* BRG value */
+-	    SCCB_WRITE( 13, 0 );		/* BRG high byte */
+-	    SCCB_WRITE( 14, 1 );
+-	    SCCB_WRITE( 3, reg3 | 1 );
+-	    SCCB_WRITE( 5, reg5 | 8 );
+-    } else if (port == 0) {
+-	    (void)scc.cha_a_ctrl;	/* reset reg pointer */
+-	    SCCA_WRITE( 9, 0xc0 );	/* reset */
+-	    LONG_DELAY();		/* extra delay after WR9 access */
+-	    SCCA_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
++	if (cflag & CBAUDEX)
++		baud += B38400;
++	if (baud < B1200 || baud > B38400+2)
++		baud = B9600; /* use default 9600bps for non-implemented rates */
++	baud -= B1200; /* tables starts at 1200bps */
++
++	clksrc  = clksrc_table[baud];
++	clkmode = clkmode_table[baud];
++	div     = div_table[baud];
++
++	reg3 = (((cflag & CSIZE) == CS8) ? 0xc0 : 0x40);
++	reg5 = (((cflag & CSIZE) == CS8) ? 0x60 : 0x20) | 0x82 /* assert DTR/RTS */;
++
++	if (port == 1) {
++		(void)scc.cha_b_ctrl;	/* reset reg pointer */
++		SCCB_WRITE(9, 0xc0);	/* reset */
++		LONG_DELAY();		/* extra delay after WR9 access */
++		SCCB_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
++			   0x04 /* 1 stopbit */ |
++			   clkmode);
++		SCCB_WRITE(3, reg3);
++		SCCB_WRITE(5, reg5);
++		SCCB_WRITE(9, 0);	/* no interrupts */
++		LONG_DELAY();		/* extra delay after WR9 access */
++		SCCB_WRITE(10, 0);	/* NRZ mode */
++		SCCB_WRITE(11, clksrc);	/* main clock source */
++		SCCB_WRITE(12, div);	/* BRG value */
++		SCCB_WRITE(13, 0);	/* BRG high byte */
++		SCCB_WRITE(14, 1);
++		SCCB_WRITE(3, reg3 | 1);
++		SCCB_WRITE(5, reg5 | 8);
++	} else if (port == 0) {
++		(void)scc.cha_a_ctrl;	/* reset reg pointer */
++		SCCA_WRITE(9, 0xc0);	/* reset */
++		LONG_DELAY();		/* extra delay after WR9 access */
++		SCCA_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
+ 			  0x04 /* 1 stopbit */ |
+-			  clkmode );
+-	    SCCA_WRITE( 3, reg3 );
+-	    SCCA_WRITE( 5, reg5 );
+-	    SCCA_WRITE( 9, 0 );		/* no interrupts */
+-	    LONG_DELAY();		/* extra delay after WR9 access */
+-	    SCCA_WRITE( 10, 0 );	/* NRZ mode */
+-	    SCCA_WRITE( 11, clksrc );	/* main clock source */
+-	    SCCA_WRITE( 12, div );	/* BRG value */
+-	    SCCA_WRITE( 13, 0 );		/* BRG high byte */
+-	    SCCA_WRITE( 14, 1 );
+-	    SCCA_WRITE( 3, reg3 | 1 );
+-	    SCCA_WRITE( 5, reg5 | 8 );
+-    }
++			  clkmode);
++		SCCA_WRITE(3, reg3);
++		SCCA_WRITE(5, reg5);
++		SCCA_WRITE(9, 0);	/* no interrupts */
++		LONG_DELAY();		/* extra delay after WR9 access */
++		SCCA_WRITE(10, 0);	/* NRZ mode */
++		SCCA_WRITE(11, clksrc);	/* main clock source */
++		SCCA_WRITE(12, div);	/* BRG value */
++		SCCA_WRITE(13, 0);	/* BRG high byte */
++		SCCA_WRITE(14, 1);
++		SCCA_WRITE(3, reg3 | 1);
++		SCCA_WRITE(5, reg5 | 8);
++	}
+ 
+-    mac_SCC_reset_done = 1;
+-    mac_SCC_init_done = 1;
++	mac_SCC_reset_done = 1;
++	mac_SCC_init_done = 1;
+ }
+ #endif /* DEBUG_SERIAL */
+ 
+-void mac_init_scca_port( int cflag )
++void mac_init_scca_port(int cflag)
+ {
+ 	mac_init_scc_port(cflag, 0);
+ }
+ 
+-void mac_init_sccb_port( int cflag )
++void mac_init_sccb_port(int cflag)
+ {
+ 	mac_init_scc_port(cflag, 1);
+ }
+@@ -364,34 +363,26 @@ void mac_init_sccb_port( int cflag )
+ void __init mac_debug_init(void)
+ {
+ #ifdef DEBUG_SERIAL
+-    if (   !strcmp( m68k_debug_device, "ser"  )
+-        || !strcmp( m68k_debug_device, "ser1" )) {
+-	/* Mac modem port */
+-	mac_init_scc_port( B9600|CS8, 0 );
+-	mac_console_driver.write = mac_scca_console_write;
+-	scc_port = 0;
+-    }
+-    else if (!strcmp( m68k_debug_device, "ser2" )) {
+-	/* Mac printer port */
+-	mac_init_scc_port( B9600|CS8, 1 );
+-	mac_console_driver.write = mac_sccb_console_write;
+-	scc_port = 1;
+-    }
++	if (!strcmp(m68k_debug_device, "ser") ||
++            !strcmp(m68k_debug_device, "ser1")) {
++		/* Mac modem port */
++		mac_init_scc_port(B9600|CS8, 0);
++		mac_console_driver.write = mac_scca_console_write;
++		scc_port = 0;
++	} else if (!strcmp(m68k_debug_device, "ser2")) {
++		/* Mac printer port */
++		mac_init_scc_port(B9600|CS8, 1);
++		mac_console_driver.write = mac_sccb_console_write;
++		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;
+-    }
++	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);
++	if (mac_console_driver.write)
++		register_console(&mac_console_driver);
+ }
+-
+-/*
+- * Local variables:
+- *  c-indent-level: 4
+- *  tab-width: 8
+- * End:
+- */
+--- linux-m68k-2.6.21.orig/arch/m68k/q40/config.c
++++ linux-m68k-2.6.21/arch/m68k/q40/config.c
+@@ -35,35 +35,35 @@
+ #include <asm/machdep.h>
+ #include <asm/q40_master.h>
+ 
+-extern irqreturn_t q40_process_int (int level, struct pt_regs *regs);
+-extern void q40_init_IRQ (void);
++extern irqreturn_t q40_process_int(int level, struct pt_regs *regs);
++extern void q40_init_IRQ(void);
+ static void q40_get_model(char *model);
+ static int  q40_get_hardware_list(char *buffer);
+ extern void q40_sched_init(irq_handler_t handler);
+ 
+-extern unsigned long q40_gettimeoffset (void);
+-extern int q40_hwclk (int, struct rtc_time *);
+-extern unsigned int q40_get_ss (void);
+-extern int q40_set_clock_mmss (unsigned long);
++extern unsigned long q40_gettimeoffset(void);
++extern int q40_hwclk(int, struct rtc_time *);
++extern unsigned int q40_get_ss(void);
++extern int q40_set_clock_mmss(unsigned long);
+ static int q40_get_rtc_pll(struct rtc_pll_info *pll);
+ static int q40_set_rtc_pll(struct rtc_pll_info *pll);
+-extern void q40_reset (void);
++extern void q40_reset(void);
+ void q40_halt(void);
+ extern void q40_waitbut(void);
+-void q40_set_vectors (void);
++void q40_set_vectors(void);
+ 
+-extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ );
++extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/);
+ 
+ extern char m68k_debug_device[];
+ static void q40_mem_console_write(struct console *co, const char *b,
+-				    unsigned int count);
++				  unsigned int count);
+ 
+ extern int ql_ticks;
+ 
+ static struct console q40_console_driver = {
+-	.name =		"debug",
+-	.flags =	CON_PRINTBUFFER,
+-	.index =	-1,
++	.name	= "debug",
++	.flags	= CON_PRINTBUFFER,
++	.index	= -1,
+ };
+ 
+ 
+@@ -74,150 +74,157 @@ static int _cpleft;
+ static void q40_mem_console_write(struct console *co, const char *s,
+ 				  unsigned int count)
+ {
+-  char *p=(char *)s;
++	const char *p = s;
+ 
+-  if (count<_cpleft)
+-    while (count-- >0){
+-      *q40_mem_cptr=*p++;
+-      q40_mem_cptr+=4;
+-      _cpleft--;
+-    }
++	if (count < _cpleft) {
++		while (count-- > 0) {
++			*q40_mem_cptr = *p++;
++			q40_mem_cptr += 4;
++			_cpleft--;
++		}
++	}
+ }
++
+ #if 0
+ void printq40(char *str)
+ {
+-  int l=strlen(str);
+-  char *p=q40_mem_cptr;
++	int l = strlen(str);
++	char *p = q40_mem_cptr;
+ 
+-  while (l-- >0 && _cpleft-- >0)
+-    {
+-      *p=*str++;
+-      p+=4;
+-    }
+-  q40_mem_cptr=p;
++	while (l-- > 0 && _cpleft-- > 0) {
++		*p = *str++;
++		p += 4;
++	}
++	q40_mem_cptr = p;
+ }
+ #endif
+ 
+-static int halted=0;
++static int halted;
+ 
+ #ifdef CONFIG_HEARTBEAT
+ static void q40_heartbeat(int on)
+ {
+-  if (halted) return;
++	if (halted)
++		return;
+ 
+-  if (on)
+-    Q40_LED_ON();
+-  else
+-    Q40_LED_OFF();
++	if (on)
++		Q40_LED_ON();
++	else
++		Q40_LED_OFF();
+ }
+ #endif
+ 
+ void q40_reset(void)
+ {
+-        halted=1;
+-        printk ("\n\n*******************************************\n"
++        halted = 1;
++        printk("\n\n*******************************************\n"
+ 		"Called q40_reset : press the RESET button!! \n"
+ 		"*******************************************\n");
+ 	Q40_LED_ON();
+-	while(1) ;
++	while (1)
++		;
+ }
+ void q40_halt(void)
+ {
+-        halted=1;
+-        printk ("\n\n*******************\n"
+-		    "  Called q40_halt\n"
+-		    "*******************\n");
++        halted = 1;
++        printk("\n\n*******************\n"
++		   "  Called q40_halt\n"
++		   "*******************\n");
+ 	Q40_LED_ON();
+-	while(1) ;
++	while (1)
++		;
+ }
+ 
+ static void q40_get_model(char *model)
+ {
+-    sprintf(model, "Q40");
++	sprintf(model, "Q40");
+ }
+ 
+ /* No hardware options on Q40? */
+ 
+ static int q40_get_hardware_list(char *buffer)
+ {
+-    *buffer = '\0';
+-    return 0;
++	*buffer = '\0';
++	return 0;
+ }
+ 
+-static unsigned int serports[]={0x3f8,0x2f8,0x3e8,0x2e8,0};
++static unsigned int serports[] =
++{
++	0x3f8,0x2f8,0x3e8,0x2e8,0
++};
+ void q40_disable_irqs(void)
+ {
+-  unsigned i,j;
++	unsigned i, j;
+ 
+-  j=0;
+-  while((i=serports[j++])) outb(0,i+UART_IER);
+-  master_outb(0,EXT_ENABLE_REG);
+-  master_outb(0,KEY_IRQ_ENABLE_REG);
++	j = 0;
++	while ((i = serports[j++]))
++		outb(0, i + UART_IER);
++	master_outb(0, EXT_ENABLE_REG);
++	master_outb(0, KEY_IRQ_ENABLE_REG);
+ }
+ 
+ void __init config_q40(void)
+ {
+-    mach_sched_init      = q40_sched_init;
++	mach_sched_init = q40_sched_init;
+ 
+-    mach_init_IRQ        = q40_init_IRQ;
+-    mach_gettimeoffset   = q40_gettimeoffset;
+-    mach_hwclk           = q40_hwclk;
+-    mach_get_ss          = q40_get_ss;
+-    mach_get_rtc_pll     = q40_get_rtc_pll;
+-    mach_set_rtc_pll     = q40_set_rtc_pll;
+-    mach_set_clock_mmss	 = q40_set_clock_mmss;
+-
+-    mach_reset		 = q40_reset;
+-    mach_get_model       = q40_get_model;
+-    mach_get_hardware_list = q40_get_hardware_list;
++	mach_init_IRQ = q40_init_IRQ;
++	mach_gettimeoffset = q40_gettimeoffset;
++	mach_hwclk = q40_hwclk;
++	mach_get_ss = q40_get_ss;
++	mach_get_rtc_pll = q40_get_rtc_pll;
++	mach_set_rtc_pll = q40_set_rtc_pll;
++	mach_set_clock_mmss = q40_set_clock_mmss;
++
++	mach_reset = q40_reset;
++	mach_get_model = q40_get_model;
++	mach_get_hardware_list = q40_get_hardware_list;
+ 
+ #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
+-    mach_beep            = q40_mksound;
++	mach_beep = q40_mksound;
+ #endif
+ #ifdef CONFIG_HEARTBEAT
+-    mach_heartbeat = q40_heartbeat;
++	mach_heartbeat = q40_heartbeat;
+ #endif
+-    mach_halt = q40_halt;
++	mach_halt = q40_halt;
+ 
+-    /* disable a few things that SMSQ might have left enabled */
+-    q40_disable_irqs();
++	/* disable a few things that SMSQ might have left enabled */
++	q40_disable_irqs();
+ 
+-    /* no DMA at all, but ide-scsi requires it.. make sure
+-     * all physical RAM fits into the boundary - otherwise
+-     * allocator may play costly and useless tricks */
+-    mach_max_dma_address = 1024*1024*1024;
+-
+-    /* useful for early debugging stages - writes kernel messages into SRAM */
+-    if (!strncmp( m68k_debug_device,"mem",3 ))
+-      {
+-	/*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/
+-	_cpleft=2000-((long)q40_mem_cptr-0xff020000)/4;
+-	q40_console_driver.write = q40_mem_console_write;
+-	register_console(&q40_console_driver);
+-      }
++	/* no DMA at all, but ide-scsi requires it.. make sure
++	 * all physical RAM fits into the boundary - otherwise
++	 * allocator may play costly and useless tricks */
++	mach_max_dma_address = 1024*1024*1024;
++
++	/* useful for early debugging stages - writes kernel messages into SRAM */
++	if (!strncmp( m68k_debug_device,"mem", 3)) {
++		/*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/
++		_cpleft = 2000 - ((long)q40_mem_cptr-0xff020000) / 4;
++		q40_console_driver.write = q40_mem_console_write;
++		register_console(&q40_console_driver);
++	}
+ }
+ 
+ 
+ int q40_parse_bootinfo(const struct bi_record *rec)
+ {
+-  return 1;
++	return 1;
+ }
+ 
+ 
+-static inline unsigned char bcd2bin (unsigned char b)
++static inline unsigned char bcd2bin(unsigned char b)
+ {
+-	return ((b>>4)*10 + (b&15));
++	return (b >> 4) * 10 + (b & 15);
+ }
+ 
+-static inline unsigned char bin2bcd (unsigned char b)
++static inline unsigned char bin2bcd(unsigned char b)
+ {
+-	return (((b/10)*16) + (b%10));
++	return (b / 10) * 16 + (b % 10);
+ }
+ 
+ 
+-unsigned long q40_gettimeoffset (void)
++unsigned long q40_gettimeoffset(void)
+ {
+-    return 5000*(ql_ticks!=0);
++	return 5000 * (ql_ticks != 0);
+ }
+ 
+ 
+@@ -238,9 +245,9 @@ unsigned long q40_gettimeoffset (void)
+ 
+ int q40_hwclk(int op, struct rtc_time *t)
+ {
+-        if (op)
+-	{	/* Write.... */
+-	        Q40_RTC_CTRL |= Q40_RTC_WRITE;
++	if (op) {
++		/* Write.... */
++		Q40_RTC_CTRL |= Q40_RTC_WRITE;
+ 
+ 		Q40_RTC_SECS = bin2bcd(t->tm_sec);
+ 		Q40_RTC_MINS = bin2bcd(t->tm_min);
+@@ -251,25 +258,23 @@ int q40_hwclk(int op, struct rtc_time *t
+ 		if (t->tm_wday >= 0)
+ 			Q40_RTC_DOW = bin2bcd(t->tm_wday+1);
+ 
+-	        Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
+-	}
+-	else
+-	{	/* Read....  */
+-	  Q40_RTC_CTRL |= Q40_RTC_READ;
+-
+-	  t->tm_year = bcd2bin (Q40_RTC_YEAR);
+-	  t->tm_mon  = bcd2bin (Q40_RTC_MNTH)-1;
+-	  t->tm_mday = bcd2bin (Q40_RTC_DATE);
+-	  t->tm_hour = bcd2bin (Q40_RTC_HOUR);
+-	  t->tm_min  = bcd2bin (Q40_RTC_MINS);
+-	  t->tm_sec  = bcd2bin (Q40_RTC_SECS);
+-
+-	  Q40_RTC_CTRL &= ~(Q40_RTC_READ);
+-
+-	  if (t->tm_year < 70)
+-	    t->tm_year += 100;
+-	  t->tm_wday = bcd2bin(Q40_RTC_DOW)-1;
+-
++		Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
++	} else {
++		/* Read....  */
++		Q40_RTC_CTRL |= Q40_RTC_READ;
++
++		t->tm_year = bcd2bin (Q40_RTC_YEAR);
++		t->tm_mon  = bcd2bin (Q40_RTC_MNTH)-1;
++		t->tm_mday = bcd2bin (Q40_RTC_DATE);
++		t->tm_hour = bcd2bin (Q40_RTC_HOUR);
++		t->tm_min  = bcd2bin (Q40_RTC_MINS);
++		t->tm_sec  = bcd2bin (Q40_RTC_SECS);
++
++		Q40_RTC_CTRL &= ~(Q40_RTC_READ);
++
++		if (t->tm_year < 70)
++			t->tm_year += 100;
++		t->tm_wday = bcd2bin(Q40_RTC_DOW)-1;
+ 	}
+ 
+ 	return 0;
+@@ -285,29 +290,25 @@ unsigned int q40_get_ss(void)
+  * clock is out by > 30 minutes.  Logic lifted from atari code.
+  */
+ 
+-int q40_set_clock_mmss (unsigned long nowtime)
++int q40_set_clock_mmss(unsigned long nowtime)
+ {
+ 	int retval = 0;
+ 	short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
+ 
+ 	int rtc_minutes;
+ 
++	rtc_minutes = bcd2bin(Q40_RTC_MINS);
+ 
+-	rtc_minutes = bcd2bin (Q40_RTC_MINS);
+-
+-	if ((rtc_minutes < real_minutes
+-		? real_minutes - rtc_minutes
+-			: rtc_minutes - real_minutes) < 30)
+-	{
+-	        Q40_RTC_CTRL |= Q40_RTC_WRITE;
++	if ((rtc_minutes < real_minutes ?
++	     real_minutes - rtc_minutes :
++	     rtc_minutes - real_minutes) < 30) {
++		Q40_RTC_CTRL |= Q40_RTC_WRITE;
+ 		Q40_RTC_MINS = bin2bcd(real_minutes);
+ 		Q40_RTC_SECS = bin2bcd(real_seconds);
+ 		Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
+-	}
+-	else
++	} else
+ 		retval = -1;
+ 
+-
+ 	return retval;
+ }
+ 
+@@ -318,21 +319,23 @@ int q40_set_clock_mmss (unsigned long no
+ 
+ static int q40_get_rtc_pll(struct rtc_pll_info *pll)
+ {
+-	int tmp=Q40_RTC_CTRL;
++	int tmp = Q40_RTC_CTRL;
++
+ 	pll->pll_value = tmp & Q40_RTC_PLL_MASK;
+ 	if (tmp & Q40_RTC_PLL_SIGN)
+ 		pll->pll_value = -pll->pll_value;
+-	pll->pll_max=31;
+-	pll->pll_min=-31;
+-	pll->pll_posmult=512;
+-	pll->pll_negmult=256;
+-	pll->pll_clock=125829120;
++	pll->pll_max = 31;
++	pll->pll_min = -31;
++	pll->pll_posmult = 512;
++	pll->pll_negmult = 256;
++	pll->pll_clock = 125829120;
++
+ 	return 0;
+ }
+ 
+ static int q40_set_rtc_pll(struct rtc_pll_info *pll)
+ {
+-	if (!pll->pll_ctrl){
++	if (!pll->pll_ctrl) {
+ 		/* the docs are a bit unclear so I am doublesetting */
+ 		/* RTC_WRITE here ... */
+ 		int tmp = (pll->pll_value & 31) | (pll->pll_value<0 ? 32 : 0) |
+--- linux-m68k-2.6.21.orig/arch/m68k/sun3x/prom.c
++++ linux-m68k-2.6.21/arch/m68k/sun3x/prom.c
+@@ -34,43 +34,43 @@ e_vector *sun3x_prom_vbr;
+ /* Handle returning to the prom */
+ void sun3x_halt(void)
+ {
+-    unsigned long flags;
++	unsigned long flags;
+ 
+-    /* Disable interrupts while we mess with things */
+-    local_irq_save(flags);
++	/* Disable interrupts while we mess with things */
++	local_irq_save(flags);
+ 
+-    /* Restore prom vbr */
+-    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
++	/* Restore prom vbr */
++	asm volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
+ 
+-    /* Restore prom NMI clock */
+-//    sun3x_disable_intreg(5);
+-    sun3_enable_irq(7);
++	/* Restore prom NMI clock */
++//	sun3x_disable_intreg(5);
++	sun3_enable_irq(7);
+ 
+-    /* Let 'er rip */
+-    __asm__ volatile ("trap #14" : : );
++	/* Let 'er rip */
++	asm volatile ("trap #14");
+ 
+-    /* Restore everything */
+-    sun3_disable_irq(7);
+-    sun3_enable_irq(5);
++	/* Restore everything */
++	sun3_disable_irq(7);
++	sun3_enable_irq(5);
+ 
+-    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
+-    local_irq_restore(flags);
++	asm volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
++	local_irq_restore(flags);
+ }
+ 
+ void sun3x_reboot(void)
+ {
+-    /* This never returns, don't bother saving things */
+-    local_irq_disable();
++	/* This never returns, don't bother saving things */
++	local_irq_disable();
+ 
+-    /* Restore prom vbr */
+-    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
++	/* Restore prom vbr */
++	asm volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
+ 
+-    /* Restore prom NMI clock */
+-    sun3_disable_irq(5);
+-    sun3_enable_irq(7);
++	/* Restore prom NMI clock */
++	sun3_disable_irq(5);
++	sun3_enable_irq(7);
+ 
+-    /* Let 'er rip */
+-    (*romvec->pv_reboot)("vmlinux");
++	/* Let 'er rip */
++	(*romvec->pv_reboot)("vmlinux");
+ }
+ 
+ extern char m68k_debug_device[];
+@@ -78,54 +78,52 @@ extern char m68k_debug_device[];
+ static void sun3x_prom_write(struct console *co, const char *s,
+                              unsigned int count)
+ {
+-    while (count--) {
+-        if (*s == '\n')
+-            sun3x_putchar('\r');
+-        sun3x_putchar(*s++);
+-    }
++	while (count--) {
++		if (*s == '\n')
++			sun3x_putchar('\r');
++		sun3x_putchar(*s++);
++	}
+ }
+ 
+ /* debug console - write-only */
+ 
+ static struct console sun3x_debug = {
+-	.name  =	"debug",
+-	.write =	sun3x_prom_write,
+-	.flags =	CON_PRINTBUFFER,
+-	.index =	-1,
++	.name	= "debug",
++	.write	= sun3x_prom_write,
++	.flags	= CON_PRINTBUFFER,
++	.index	= -1,
+ };
+ 
+ void sun3x_prom_init(void)
+ {
+-    /* Read the vector table */
++	/* Read the vector table */
+ 
+-    sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR);
+-    sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR);
+-    sun3x_mayget = *(int (**)(void))  (SUN3X_P_MAYGET);
+-    sun3x_mayput = *(int (**)(int))   (SUN3X_P_MAYPUT);
+-    sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT);
+-    sun3x_prom_abort = *(e_vector *)  (SUN3X_P_ABORT);
+-    romvec = (struct linux_romvec *)SUN3X_PROM_BASE;
+-
+-    idprom_init();
+-
+-    if(!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) {
+-	    printk("Warning: machine reports strange type %02x\n",
+-		   idprom->id_machtype);
+-	    printk("Pretending it's a 3/80, but very afraid...\n");
+-	    idprom->id_machtype = SM_SUN3X | SM_3_80;
+-    }
+-
+-    /* point trap #14 at abort.
+-     * XXX this is futile since we restore the vbr first - oops
+-     */
+-    vectors[VEC_TRAP14] = sun3x_prom_abort;
+-
+-    /* If debug=prom was specified, start the debug console */
+-
+-    if (!strcmp(m68k_debug_device, "prom"))
+-        register_console(&sun3x_debug);
++	sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR);
++	sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR);
++	sun3x_mayget = *(int (**)(void))  (SUN3X_P_MAYGET);
++	sun3x_mayput = *(int (**)(int))   (SUN3X_P_MAYPUT);
++	sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT);
++	sun3x_prom_abort = *(e_vector *)  (SUN3X_P_ABORT);
++	romvec = (struct linux_romvec *)SUN3X_PROM_BASE;
++
++	idprom_init();
++
++	if (!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) {
++		printk("Warning: machine reports strange type %02x\n",
++			idprom->id_machtype);
++		printk("Pretending it's a 3/80, but very afraid...\n");
++		idprom->id_machtype = SM_SUN3X | SM_3_80;
++	}
++
++	/* point trap #14 at abort.
++	 * XXX this is futile since we restore the vbr first - oops
++	 */
++	vectors[VEC_TRAP14] = sun3x_prom_abort;
+ 
++	/* If debug=prom was specified, start the debug console */
+ 
++	if (!strcmp(m68k_debug_device, "prom"))
++		register_console(&sun3x_debug);
+ }
+ 
+ /* some prom functions to export */
+@@ -141,7 +139,6 @@ int prom_getbool (int node, char *prop)
+ 
+ void prom_printf(char *fmt, ...)
+ {
+-
+ }
+ 
+ void prom_halt (void)
+@@ -159,7 +156,7 @@ prom_get_idprom(char *idbuf, int num_byt
+         int i;
+ 
+ 	/* make a copy of the idprom structure */
+-	for(i = 0; i < num_bytes; i++)
++	for (i = 0; i < num_bytes; i++)
+ 		idbuf[i] = ((char *)SUN3X_IDPROM)[i];
+ 
+         return idbuf[0];

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-cuda-adb-fixes.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-cuda-adb-fixes.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,176 @@
+Subject: [PATCH 10/13] CUDA ADB fixes
+Cc: Benjamin Herrenschmidt <benh at kernel.crashing.org>,
+    linuxppc-dev at ozlabs.org
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Fix the flakiness in the CUDA ADB driver on m68k macs (keypresses getting
+wedged down or ADB just going AWOL altogether).
+
+The only IRQ used by this driver is the VIA shift register IRQ. The PowerMac
+conditional code disables the other VIA IRQ sources, so don't mess with the
+other IRQ flags in the common code -- m68k macs need them.
+
+When polling, don't disable local interrupts when we only need to disable the
+CUDA interrupt.
+
+Unless polling, don't clear the shift register IRQ flag. On m68k macs this
+creates a race that often breaks CUDA ADB.
+
+Tested on Quadra 840av and LC630 (both m68k); also Beige G3 (powerpc).
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/macintosh/via-cuda.c |   58 +++++++++++++++++++++++--------------------
+ 1 file changed, 32 insertions(+), 26 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/macintosh/via-cuda.c
++++ linux-m68k-2.6.21/drivers/macintosh/via-cuda.c
+@@ -82,6 +82,7 @@ static unsigned char cuda_rbuf[16];
+ static unsigned char *reply_ptr;
+ static int reading_reply;
+ static int data_index;
++static int cuda_irq;
+ #ifdef CONFIG_PPC
+ static struct device_node *vias;
+ #endif
+@@ -160,10 +161,8 @@ int __init find_via_cuda(void)
+     /* Clear and enable interrupts, but only on PPC. On 68K it's done  */
+     /* for us by the main VIA driver in arch/m68k/mac/via.c        */
+ 
+-#ifndef CONFIG_MAC
+     out_8(&via[IFR], 0x7f);	/* clear interrupts by writing 1s */
+     out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
+-#endif
+ 
+     /* enable autopoll */
+     cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
+@@ -181,24 +180,22 @@ int __init find_via_cuda(void)
+ 
+ static int __init via_cuda_start(void)
+ {
+-    unsigned int irq;
+-
+     if (via == NULL)
+ 	return -ENODEV;
+ 
+ #ifdef CONFIG_MAC
+-    irq = IRQ_MAC_ADB;
++    cuda_irq = IRQ_MAC_ADB;
+ #else /* CONFIG_MAC */
+-    irq = irq_of_parse_and_map(vias, 0);
+-    if (irq == NO_IRQ) {
++    cuda_irq = irq_of_parse_and_map(vias, 0);
++    if (cuda_irq == NO_IRQ) {
+ 	printk(KERN_ERR "via-cuda: can't map interrupts for %s\n",
+ 	       vias->full_name);
+ 	return -ENODEV;
+     }
+-#endif /* CONFIG_MAP */
++#endif /* CONFIG_MAC */
+ 
+-    if (request_irq(irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
+-	printk(KERN_ERR "via-cuda: can't request irq %d\n", irq);
++    if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
++	printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq);
+ 	return -EAGAIN;
+     }
+ 
+@@ -238,6 +235,7 @@ cuda_init(void)
+ 	printk(KERN_ERR "cuda_init_via() failed\n");
+ 	return -ENODEV;
+     }
++    out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
+ 
+     return via_cuda_start();
+ #endif
+@@ -263,15 +261,17 @@ cuda_init_via(void)
+     out_8(&via[B], in_8(&via[B]) | TACK | TIP);			/* negate them */
+     out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT);	/* SR data in */
+     (void)in_8(&via[SR]);						/* clear any left-over data */
+-#ifndef CONFIG_MAC
++#ifdef CONFIG_PPC
+     out_8(&via[IER], 0x7f);					/* disable interrupts from VIA */
+     (void)in_8(&via[IER]);
++#else
++    out_8(&via[IER], SR_INT);					/* disable SR interrupt from VIA */
+ #endif
+ 
+     /* delay 4ms and then clear any pending interrupt */
+     mdelay(4);
+     (void)in_8(&via[SR]);
+-    out_8(&via[IFR], in_8(&via[IFR]) & 0x7f);
++    out_8(&via[IFR], SR_INT);
+ 
+     /* sync with the CUDA - assert TACK without TIP */
+     out_8(&via[B], in_8(&via[B]) & ~TACK);
+@@ -282,7 +282,7 @@ cuda_init_via(void)
+     /* wait for the interrupt and then clear it */
+     WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)");
+     (void)in_8(&via[SR]);
+-    out_8(&via[IFR], in_8(&via[IFR]) & 0x7f);
++    out_8(&via[IFR], SR_INT);
+ 
+     /* finish the sync by negating TACK */
+     out_8(&via[B], in_8(&via[B]) | TACK);
+@@ -291,7 +291,7 @@ cuda_init_via(void)
+     WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)");
+     WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)");
+     (void)in_8(&via[SR]);
+-    out_8(&via[IFR], in_8(&via[IFR]) & 0x7f);
++    out_8(&via[IFR], SR_INT);
+     out_8(&via[B], in_8(&via[B]) | TIP);	/* should be unnecessary */
+ 
+     return 0;
+@@ -428,16 +428,12 @@ cuda_start(void)
+ void
+ cuda_poll(void)
+ {
+-    unsigned long flags;
+-
+     /* cuda_interrupt only takes a normal lock, we disable
+      * interrupts here to avoid re-entering and thus deadlocking.
+-     * An option would be to disable only the IRQ source with
+-     * disable_irq(), would that work on m68k ? --BenH
+      */
+-    local_irq_save(flags);
++    disable_irq(cuda_irq);
+     cuda_interrupt(0, NULL);
+-    local_irq_restore(flags);
++    enable_irq(cuda_irq);
+ }
+ 
+ static irqreturn_t
+@@ -448,15 +444,25 @@ cuda_interrupt(int irq, void *arg)
+     unsigned char ibuf[16];
+     int ibuf_len = 0;
+     int complete = 0;
+-    unsigned char virq;
+     
+     spin_lock(&cuda_lock);
+ 
+-    virq = in_8(&via[IFR]) & 0x7f;
+-    out_8(&via[IFR], virq);   
+-    if ((virq & SR_INT) == 0) {
+-        spin_unlock(&cuda_lock);
+-	return IRQ_NONE;
++    /* On powermacs, this handler is registered for the VIA IRQ. But it uses
++     * just the shift register IRQ -- other VIA interrupt sources are disabled.
++     * On m68k macs, the VIA IRQ sources are dispatched individually. Unless
++     * we are polling, the shift register IRQ flag has already been cleared.
++     */
++
++#ifdef CONFIG_MAC
++    if (!arg)
++#endif
++    {
++        if ((in_8(&via[IFR]) & SR_INT) == 0) {
++            spin_unlock(&cuda_lock);
++            return IRQ_NONE;
++        } else {
++            out_8(&via[IFR], SR_INT);
++        }
+     }
+     
+     status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT);

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-finish_irq_cleanup.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-finish_irq_cleanup.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,162 @@
+Subject: [PATCH 8/13] m68k: Mac IRQ cleanup
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+There are no slow IRQs on Macs since Roman Zippel's IRQ reorganisation that
+went into 2.6.16 and removed mac_irq_list[] and the do_mac_irq_list()
+dispatcher. (They were implemented in do_mac_irq_list() by lowering the IPL.)
+Hence there's no more use for mutual exclusion in the Mac interrupt
+dispatchers. Remove it.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/mac/baboon.c |   20 +++++++-------------
+ arch/m68k/mac/oss.c    |    4 ----
+ arch/m68k/mac/psc.c    |    2 --
+ arch/m68k/mac/via.c    |   10 ----------
+ 4 files changed, 7 insertions(+), 29 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/baboon.c
++++ linux-m68k-2.6.21/arch/m68k/mac/baboon.c
+@@ -22,7 +22,7 @@
+ /* #define DEBUG_BABOON */
+ /* #define DEBUG_IRQS */
+ 
+-int baboon_present,baboon_active;
++int baboon_present;
+ volatile struct baboon *baboon;
+ 
+ irqreturn_t baboon_irq(int, void *);
+@@ -45,7 +45,6 @@ void __init baboon_init(void)
+ 
+ 	baboon = (struct baboon *) BABOON_BASE;
+ 	baboon_present = 1;
+-	baboon_active = 0;
+ 
+ 	printk("Baboon detected at %p\n", baboon);
+ }
+@@ -70,9 +69,9 @@ irqreturn_t baboon_irq(int irq, void *de
+ 	unsigned char events;
+ 
+ #ifdef DEBUG_IRQS
+-	printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X active %02X\n",
++	printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X\n",
+ 		(uint) baboon->mb_control, (uint) baboon->mb_ifr,
+-		(uint) baboon->mb_status,  baboon_active);
++		(uint) baboon->mb_status);
+ #endif
+ 
+ 	if (!(events = baboon->mb_ifr & 0x07))
+@@ -81,11 +80,9 @@ irqreturn_t baboon_irq(int irq, void *de
+ 	irq_num = IRQ_BABOON_0;
+ 	irq_bit = 1;
+ 	do {
+-	        if (events & irq_bit/* & baboon_active*/) {
+-			baboon_active &= ~irq_bit;
++	        if (events & irq_bit) {
+ 			baboon->mb_ifr &= ~irq_bit;
+ 			m68k_handle_int(irq_num);
+-			baboon_active |= irq_bit;
+ 		}
+ 		irq_bit <<= 1;
+ 		irq_num++;
+@@ -99,21 +96,18 @@ irqreturn_t baboon_irq(int irq, void *de
+ }
+ 
+ void baboon_irq_enable(int irq) {
+-	int irq_idx	= IRQ_IDX(irq);
+-
+ #ifdef DEBUG_IRQUSE
+ 	printk("baboon_irq_enable(%d)\n", irq);
+ #endif
+-	baboon_active |= (1 << irq_idx);
++	/* FIXME: figure out how to mask and unmask baboon interrupt sources */
++	enable_irq(IRQ_NUBUS_C);
+ }
+ 
+ void baboon_irq_disable(int irq) {
+-	int irq_idx	= IRQ_IDX(irq);
+-
+ #ifdef DEBUG_IRQUSE
+ 	printk("baboon_irq_disable(%d)\n", irq);
+ #endif
+-	baboon_active &= ~(1 << irq_idx);
++	disable_irq(IRQ_NUBUS_C);
+ }
+ 
+ void baboon_irq_clear(int irq) {
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/oss.c
++++ linux-m68k-2.6.21/arch/m68k/mac/oss.c
+@@ -112,10 +112,8 @@ irqreturn_t oss_irq(int irq, void *dev_i
+ 		oss->irq_pending &= ~OSS_IP_SOUND;
+ 		/* FIXME: call sound handler */
+ 	} else if (events & OSS_IP_SCSI) {
+-		oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED;
+ 		oss->irq_pending &= ~OSS_IP_SCSI;
+ 		m68k_handle_int(IRQ_MAC_SCSI);
+-		oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
+ 	} else {
+ 		/* FIXME: error check here? */
+ 	}
+@@ -149,10 +147,8 @@ irqreturn_t oss_nubus_irq(int irq, void 
+ 		--i;
+ 		irq_bit >>= 1;
+ 		if (events & irq_bit) {
+-			oss->irq_level[i] = OSS_IRQLEV_DISABLED;
+ 			oss->irq_pending &= ~irq_bit;
+ 			m68k_handle_int(NUBUS_SOURCE_BASE + i);
+-			oss->irq_level[i] = OSS_IRQLEV_NUBUS;
+ 		}
+ 	} while(events & (irq_bit - 1));
+ 	return IRQ_HANDLED;
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/psc.c
++++ linux-m68k-2.6.21/arch/m68k/mac/psc.c
+@@ -147,10 +147,8 @@ irqreturn_t psc_irq(int irq, void *dev_i
+ 	irq_bit = 1;
+ 	do {
+ 		if (events & irq_bit) {
+-			psc_write_byte(pIER, irq_bit);
+ 			psc_write_byte(pIFR, irq_bit);
+ 			m68k_handle_int(irq_num);
+-			psc_write_byte(pIER, irq_bit | 0x80);
+ 		}
+ 		irq_num++;
+ 		irq_bit <<= 1;
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/via.c
++++ linux-m68k-2.6.21/arch/m68k/mac/via.c
+@@ -443,11 +443,6 @@ void __init via_nubus_init(void)
+ /*
+  * The generic VIA interrupt routines (shamelessly stolen from Alan Cox's
+  * via6522.c :-), disable/pending masks added.
+- *
+- * The new interrupt architecture in macints.c takes care of a lot of the
+- * gruntwork for us, including tallying the interrupts and calling the
+- * handlers on the linked list. All we need to do here is basically generate
+- * the machspec interrupt number after clearing the interrupt.
+  */
+ 
+ irqreturn_t via1_irq(int irq, void *dev_id)
+@@ -463,10 +458,8 @@ irqreturn_t via1_irq(int irq, void *dev_
+ 	irq_bit = 1;
+ 	do {
+ 		if (events & irq_bit) {
+-			via1[vIER] = irq_bit;
+ 			via1[vIFR] = irq_bit;
+ 			m68k_handle_int(irq_num);
+-			via1[vIER] = irq_bit | 0x80;
+ 		}
+ 		++irq_num;
+ 		irq_bit <<= 1;
+@@ -502,11 +495,8 @@ irqreturn_t via2_irq(int irq, void *dev_
+ 	irq_bit = 1;
+ 	do {
+ 		if (events & irq_bit) {
+-			via2[gIER] = irq_bit;
+ 			via2[gIFR] = irq_bit | rbv_clear;
+ 			m68k_handle_int(irq_num);
+-			if (irq_num != IRQ_MAC_NUBUS || nubus_disabled == 0)
+-				via2[gIER] = irq_bit | 0x80;
+ 		}
+ 		++irq_num;
+ 		irq_bit <<= 1;

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-irq-plan-e.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-irq-plan-e.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,270 @@
+Subject: [PATCH 7/13] m68k: Mac nubus IRQ fixes (plan E)
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Some Macs lack a slot interrupt enable register. So the existing code makes
+disabled and unregistered slot IRQ lines outputs set high. This seems to work
+on quadras, but does not work on genuine VIAs (perhaps the card still succeeds
+in pulling the line low, or perhaps because this increases the settle time on
+the port A input, meaning that the CA1 IRQ could fire before the slot line
+reads active).
+
+Because of this, the nubus_active flags were used to mask IRQs, which is
+actually worse than the problem it tries to solve. Any interrupt masked by
+nubus_active will remain asserted and prevent further transitions on CA1. And
+so the nubus gets wedged regardless of hardware (emulated VIA ASIC, real VIA
+chip or RBV).
+
+The best solution to this hardware limitation of genuine VIAs is to disable the
+umbrella SLOTS IRQ when disabling a slot on those machines. Unfortunately, this
+means all slot IRQs get disabled when any slot IRQ is disabled. But it is only
+a problem when there's more than 1 device using nubus interrupts.
+
+Another potential problem for genuine VIAs is an unregistered nubus IRQ.
+Eventually it will be possible to enable the CA1 interrupt by installing its
+handler only _after_ all nubus drivers have loaded but _before_ the kernel
+needs them, at which time this last problem can be fixed. For now it can be
+worked around:
+
+  - disable MacOS extensions
+  - don't boot MacOS (use the Emile bootloader instead)
+  - get the bootloaders to disable ROM drivers (Penguin does this for video
+    cards already, don't know about Emile)
+  - physically remove unsupported cards
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/mac/via.c |  141 +++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 80 insertions(+), 61 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/via.c
++++ linux-m68k-2.6.21/arch/m68k/mac/via.c
+@@ -64,7 +64,19 @@ static int gIER,gIFR,gBufA,gBufB;
+ #define MAC_CLOCK_LOW		(MAC_CLOCK_TICK&0xFF)
+ #define MAC_CLOCK_HIGH		(MAC_CLOCK_TICK>>8)
+ 
+-static int  nubus_active;
++/* To disable a NuBus slot on Quadras we make the slot IRQ lines outputs, set
++ * high. On RBV we just use the slot interrupt enable register. On Macs with
++ * genuine VIA chips we must use nubus_disabled to keep track of disabled slot
++ * interrupts. When any slot IRQ is disabled we mask the (edge triggered) CA1
++ * or "SLOTS" interrupt. When no slot is disabled, we unmask the CA1 interrupt.
++ * So, on genuine VIAs, having more than one NuBus IRQ can mean trouble,
++ * because closing one of those drivers can mask all of the NuBus interrupts.
++ * Also, since we can't mask the unregistered slot IRQs on genuine VIAs, it's
++ * possible to get interrupts from cards that MacOS or the ROM has configured
++ * but we have not. FWIW, "Designing Cards and Drivers for Macintosh II and
++ * Macintosh SE", page 9-8, says, a slot IRQ with no driver would crash MacOS.
++ */
++static u8 nubus_disabled;
+ 
+ void via_debug_dump(void);
+ irqreturn_t via1_irq(int, void *);
+@@ -383,9 +395,6 @@ int via_get_cache_disable(void)
+ 
+ void __init via_nubus_init(void)
+ {
+-	/* don't set nubus_active = 0 here, it kills the Baboon */
+-	/* interrupt that we've already registered.		*/
+-
+ 	/* unlock nubus transactions */
+ 
+ 	if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+@@ -399,28 +408,35 @@ void __init via_nubus_init(void)
+ 		via2[gBufB] |= 0x02;
+ 	}
+ 
+-	/* disable nubus slot interrupts. */
+-	if (rbv_present) {
++	/* Disable all the slot interrupts (where possible). */
++
++	switch (macintosh_config->via_type) {
++	case MAC_VIA_II:
++		/* Just make the port A lines inputs. */
++		switch(macintosh_config->ident) {
++		case MAC_MODEL_II:
++		case MAC_MODEL_IIX:
++		case MAC_MODEL_IICX:
++		case MAC_MODEL_SE30:
++			/* The top two bits are RAM size outputs. */
++			via2[vDirA] &= 0xC0;
++			break;
++		default:
++			via2[vDirA] &= 0x80;
++		}
++		break;
++	case MAC_VIA_IIci:
++		/* RBV. Disable all the slot interrupts. SIER works like IER. */
+ 		via2[rSIER] = 0x7F;
+-		via2[rSIER] = nubus_active | 0x80;
+-	} else {
+-		/* These are ADB bits on PMU */
++		break;
++	case MAC_VIA_QUADRA:
++		/* Disable the inactive slot interrupts by making those lines outputs. */
+ 		if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+-		   (macintosh_config->adb_type != MAC_ADB_PB2)) {
+-			switch(macintosh_config->ident)
+-			{
+-				case MAC_MODEL_II:
+-				case MAC_MODEL_IIX:
+-				case MAC_MODEL_IICX:
+-				case MAC_MODEL_SE30:
+-					via2[vBufA] |= 0x3F;
+-					via2[vDirA] = ~nubus_active | 0xc0;
+-					break;
+-				default:
+-					via2[vBufA] = 0xFF;
+-					via2[vDirA] = ~nubus_active;
+-			}
++		    (macintosh_config->adb_type != MAC_ADB_PB2)) {
++			via2[vBufA] |= 0x7F;
++			via2[vDirA] |= 0x7F;
+ 		}
++		break;
+ 	}
+ }
+ 
+@@ -489,7 +505,8 @@ irqreturn_t via2_irq(int irq, void *dev_
+ 			via2[gIER] = irq_bit;
+ 			via2[gIFR] = irq_bit | rbv_clear;
+ 			m68k_handle_int(irq_num);
+-			via2[gIER] = irq_bit | 0x80;
++			if (irq_num != IRQ_MAC_NUBUS || nubus_disabled == 0)
++				via2[gIER] = irq_bit | 0x80;
+ 		}
+ 		++irq_num;
+ 		irq_bit <<= 1;
+@@ -511,7 +528,7 @@ irqreturn_t via_nubus_irq(int irq, void 
+ 	if (rbv_present)
+ 		events &= via2[rSIER];
+ 	else
+-		events &= nubus_active;
++		events &= ~via2[vDirA];
+ 	if (!events)
+ 		return IRQ_NONE;
+ 
+@@ -533,7 +550,7 @@ irqreturn_t via_nubus_irq(int irq, void 
+ 		if (rbv_present)
+ 			events &= via2[rSIER];
+ 		else
+-			events &= nubus_active;
++			events &= ~via2[vDirA];
+ 	} while (events);
+ 	return IRQ_HANDLED;
+ }
+@@ -541,38 +558,38 @@ irqreturn_t via_nubus_irq(int irq, void 
+ void via_irq_enable(int irq) {
+ 	int irq_src	= IRQ_SRC(irq);
+ 	int irq_idx	= IRQ_IDX(irq);
+-	int irq_bit	= 1 << irq_idx;
+ 
+ #ifdef DEBUG_IRQUSE
+ 	printk(KERN_DEBUG "via_irq_enable(%d)\n", irq);
+ #endif
+ 
+ 	if (irq_src == 1) {
+-		via1[vIER] = irq_bit | 0x80;
++		via1[vIER] = IER_SET_BIT(irq_idx);
+ 	} else if (irq_src == 2) {
+-		via2[gIER] = irq_bit | 0x80;
++		if (irq != IRQ_MAC_NUBUS || nubus_disabled == 0)
++			via2[gIER] = IER_SET_BIT(irq_idx);
+ 	} else if (irq_src == 7) {
+-		nubus_active |= irq_bit;
+-		if (rbv_present) {
+-			/* enable the slot interrupt. SIER works like IER. */
++		switch (macintosh_config->via_type) {
++		case MAC_VIA_II:
++			nubus_disabled &= ~(1 << irq_idx);
++			/* Enable the CA1 interrupt when no slot is disabled. */
++			if (!nubus_disabled)
++				via2[gIER] = IER_SET_BIT(1);
++			break;
++		case MAC_VIA_IIci:
++			/* On RBV, enable the slot interrupt.
++			 * SIER works like IER.
++			 */
+ 			via2[rSIER] = IER_SET_BIT(irq_idx);
+-		} else {
+-			/* Make sure the bit is an input, to enable the irq */
+-			/* But not on PowerBooks, that's ADB... */
++			break;
++		case MAC_VIA_QUADRA:
++			/* Make the port A line an input to enable the slot irq.
++			 * But not on PowerBooks, that's ADB.
++			 */
+ 			if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+-			   (macintosh_config->adb_type != MAC_ADB_PB2)) {
+-				switch(macintosh_config->ident)
+-				{
+-					case MAC_MODEL_II:
+-					case MAC_MODEL_IIX:
+-					case MAC_MODEL_IICX:
+-					case MAC_MODEL_SE30:
+-						via2[vDirA] &= (~irq_bit | 0xc0);
+-						break;
+-					default:
+-						via2[vDirA] &= ~irq_bit;
+-				}
+-			}
++			    (macintosh_config->adb_type != MAC_ADB_PB2))
++				via2[vDirA] &= ~(1 << irq_idx);
++			break;
+ 		}
+ 	}
+ }
+@@ -580,29 +597,31 @@ void via_irq_enable(int irq) {
+ void via_irq_disable(int irq) {
+ 	int irq_src	= IRQ_SRC(irq);
+ 	int irq_idx	= IRQ_IDX(irq);
+-	int irq_bit	= 1 << irq_idx;
+ 
+ #ifdef DEBUG_IRQUSE
+ 	printk(KERN_DEBUG "via_irq_disable(%d)\n", irq);
+ #endif
+ 
+ 	if (irq_src == 1) {
+-		via1[vIER] = irq_bit & 0x7F;
++		via1[vIER] = IER_CLR_BIT(irq_idx);
+ 	} else if (irq_src == 2) {
+-		via2[gIER] = irq_bit & 0x7F;
++		via2[gIER] = IER_CLR_BIT(irq_idx);
+ 	} else if (irq_src == 7) {
+-		if (rbv_present) {
+-			/* disable the slot interrupt.  SIER works like IER. */
++		switch (macintosh_config->via_type) {
++		case MAC_VIA_II:
++			nubus_disabled |= 1 << irq_idx;
++			if (nubus_disabled)
++				via2[gIER] = IER_CLR_BIT(1);
++			break;
++		case MAC_VIA_IIci:
+ 			via2[rSIER] = IER_CLR_BIT(irq_idx);
+-		} else {
+-			/* disable the nubus irq by changing dir to output */
+-			/* except on PMU */
++			break;
++		case MAC_VIA_QUADRA:
+ 			if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+-			   (macintosh_config->adb_type != MAC_ADB_PB2)) {
+-				via2[vDirA] |= irq_bit;
+-			}
++			    (macintosh_config->adb_type != MAC_ADB_PB2))
++				via2[vDirA] |= 1 << irq_idx;
++			break;
+ 		}
+-		nubus_active &= ~irq_bit;
+ 	}
+ }
+ 
+@@ -638,7 +657,7 @@ int via_irq_pending(int irq)
+ 	} else if (irq_src == 2) {
+ 		return via2[gIFR] & irq_bit;
+ 	} else if (irq_src == 7) {
+-		/* FIXME: this can't work while a slot irq is disabled! */
++		/* Always 0 for MAC_VIA_QUADRA if the slot irq is disabled. */
+ 		return ~via2[gBufA] & irq_bit;
+ 	}
+ 	return 0;

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-irq-prep.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-irq-prep.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,375 @@
+Subject: [PATCH 6/13] m68k: Mac IRQ prep
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Make sure that there are no slot IRQs asserted before leaving the nubus
+handler. If there are and we don't then the nubus gets wedged because this
+prevents a CA1 transition, which means no more nubus IRQs.
+
+Make the interrupt dispatch loops terminate sooner.
+
+Explicitly initialise the VIA latches to make the code more easily understood.
+
+Also some cleanups.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/mac/baboon.c |   12 ++--
+ arch/m68k/mac/oss.c    |    8 ++
+ arch/m68k/mac/psc.c    |   19 +++---
+ arch/m68k/mac/via.c    |  139 ++++++++++++++++++++++++++++++-------------------
+ 4 files changed, 110 insertions(+), 68 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/baboon.c
++++ linux-m68k-2.6.21/arch/m68k/mac/baboon.c
+@@ -66,7 +66,7 @@ void __init baboon_register_interrupts(v
+ 
+ irqreturn_t baboon_irq(int irq, void *dev_id)
+ {
+-	int irq_bit,i;
++	int irq_bit, irq_num;
+ 	unsigned char events;
+ 
+ #ifdef DEBUG_IRQS
+@@ -78,14 +78,18 @@ irqreturn_t baboon_irq(int irq, void *de
+ 	if (!(events = baboon->mb_ifr & 0x07))
+ 		return IRQ_NONE;
+ 
+-	for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) {
++	irq_num = IRQ_BABOON_0;
++	irq_bit = 1;
++	do {
+ 	        if (events & irq_bit/* & baboon_active*/) {
+ 			baboon_active &= ~irq_bit;
+ 			baboon->mb_ifr &= ~irq_bit;
+-			m68k_handle_int(IRQ_BABOON_0 + i);
++			m68k_handle_int(irq_num);
+ 			baboon_active |= irq_bit;
+ 		}
+-	}
++		irq_bit <<= 1;
++		irq_num++;
++	} while(events >= irq_bit);
+ #if 0
+ 	if (baboon->mb_ifr & 0x02) macide_ack_intr(NULL);
+ 	/* for now we need to smash all interrupts */
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/oss.c
++++ linux-m68k-2.6.21/arch/m68k/mac/oss.c
+@@ -143,14 +143,18 @@ irqreturn_t oss_nubus_irq(int irq, void 
+ #endif
+ 	/* There are only six slots on the OSS, not seven */
+ 
+-	for (i = 0, irq_bit = 1 ; i < 6 ; i++, irq_bit <<= 1) {
++	i = 6;
++	irq_bit = 0x40;
++	do {
++		--i;
++		irq_bit >>= 1;
+ 		if (events & irq_bit) {
+ 			oss->irq_level[i] = OSS_IRQLEV_DISABLED;
+ 			oss->irq_pending &= ~irq_bit;
+ 			m68k_handle_int(NUBUS_SOURCE_BASE + i);
+ 			oss->irq_level[i] = OSS_IRQLEV_NUBUS;
+ 		}
+-	}
++	} while(events & (irq_bit - 1));
+ 	return IRQ_HANDLED;
+ }
+ 
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/psc.c
++++ linux-m68k-2.6.21/arch/m68k/mac/psc.c
+@@ -131,11 +131,8 @@ irqreturn_t psc_irq(int irq, void *dev_i
+ {
+ 	int pIFR	= pIFRbase + ((int) dev_id);
+ 	int pIER	= pIERbase + ((int) dev_id);
+-	int base_irq;
+-	int irq_bit,i;
+-	unsigned char events;
+-
+-	base_irq = irq << 3;
++	int irq_num;
++	unsigned char irq_bit, events;
+ 
+ #ifdef DEBUG_IRQS
+ 	printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n",
+@@ -146,14 +143,18 @@ irqreturn_t psc_irq(int irq, void *dev_i
+ 	if (!events)
+ 		return IRQ_NONE;
+ 
+-	for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) {
+-	        if (events & irq_bit) {
++	irq_num = irq << 3;
++	irq_bit = 1;
++	do {
++		if (events & irq_bit) {
+ 			psc_write_byte(pIER, irq_bit);
+ 			psc_write_byte(pIFR, irq_bit);
+-			m68k_handle_int(base_irq + i);
++			m68k_handle_int(irq_num);
+ 			psc_write_byte(pIER, irq_bit | 0x80);
+ 		}
+-	}
++		irq_num++;
++		irq_bit <<= 1;
++	} while (events >= irq_bit);
+ 	return IRQ_HANDLED;
+ }
+ 
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/via.c
++++ linux-m68k-2.6.21/arch/m68k/mac/via.c
+@@ -13,6 +13,10 @@
+  * for info.  A full-text web search on 6522 AND VIA will probably also
+  * net some usefulness. <cananian at alumni.princeton.edu> 20apr1999
+  *
++ * Additional data is here (the SY6522 was used in the Mac II etc):
++ *     http://www.6502.org/documents/datasheets/synertek/synertek_sy6522.pdf
++ *     http://www.6502.org/documents/datasheets/synertek/synertek_sy6522_programming_reference.pdf
++ *
+  * PRAM/RTC access algorithms are from the NetBSD RTC toolkit version 1.08b
+  * by Erik Vogan and adapted to Linux by Joshua M. Thompson (funaho at jurai.org)
+  *
+@@ -37,7 +41,7 @@ volatile __u8 *via1, *via2;
+ /* See note in mac_via.h about how this is possibly not useful */
+ volatile long *via_memory_bogon=(long *)&via_memory_bogon;
+ #endif
+-int  rbv_present,via_alt_mapping;
++int rbv_present, via_alt_mapping;
+ __u8 rbv_clear;
+ 
+ /*
+@@ -138,11 +142,11 @@ void __init via_init(void)
+ 
+ 	printk(KERN_INFO "VIA2 at %p is ", via2);
+ 	if (rbv_present) {
+-		printk(KERN_INFO "an RBV\n");
++		printk("an RBV\n");
+ 	} else if (oss_present) {
+-		printk(KERN_INFO "an OSS\n");
++		printk("an OSS\n");
+ 	} else {
+-		printk(KERN_INFO "a 6522 or clone\n");
++		printk("a 6522 or clone\n");
+ 	}
+ 
+ #ifdef DEBUG_VIA
+@@ -163,6 +167,7 @@ void __init via_init(void)
+ 	via1[vT2CL] = 0;
+ 	via1[vT2CH] = 0;
+ 	via1[vACR] &= 0x3F;
++	via1[vACR] &= ~0x03; /* disable port A & B latches */
+ 
+ 	/*
+ 	 * SE/30: disable video IRQ
+@@ -234,6 +239,22 @@ void __init via_init(void)
+ 		via2[vT2CL] = 0;
+ 		via2[vT2CH] = 0;
+ 		via2[vACR] &= 0x3F;
++		via2[vACR] &= ~0x03; /* disable port A & B latches */
++	}
++
++	/*
++	 * Set vPCR for SCSI interrupts (but not on RBV)
++	 */
++	if (!rbv_present) {
++		if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
++			/* CB2 (IRQ) indep. input, positive edge */
++			/* CA2 (DRQ) indep. input, positive edge */
++			via2[vPCR] = 0x66;
++		} else {
++			/* CB2 (IRQ) indep. input, negative edge */
++			/* CA2 (DRQ) indep. input, negative edge */
++			via2[vPCR] = 0x22;
++		}
+ 	}
+ }
+ 
+@@ -367,19 +388,14 @@ void __init via_nubus_init(void)
+ 
+ 	/* unlock nubus transactions */
+ 
+-	if (!rbv_present) {
++	if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
++	    (macintosh_config->adb_type != MAC_ADB_PB2)) {
+ 		/* set the line to be an output on non-RBV machines */
+-		if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+-		   (macintosh_config->adb_type != MAC_ADB_PB2)) {
++		if (!rbv_present)
+ 			via2[vDirB] |= 0x02;
+-		}
+-	}
+-
+-	/* this seems to be an ADB bit on PMU machines */
+-	/* according to MkLinux.  -- jmt               */
+ 
+-	if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+-	    (macintosh_config->adb_type != MAC_ADB_PB2)) {
++		/* this seems to be an ADB bit on PMU machines */
++		/* according to MkLinux.  -- jmt               */
+ 		via2[gBufB] |= 0x02;
+ 	}
+ 
+@@ -420,20 +436,25 @@ void __init via_nubus_init(void)
+ 
+ irqreturn_t via1_irq(int irq, void *dev_id)
+ {
+-	int irq_bit, i;
+-	unsigned char events, mask;
++	int irq_num;
++	unsigned char irq_bit, events;
+ 
+-	mask = via1[vIER] & 0x7F;
+-	if (!(events = via1[vIFR] & mask))
++	events = via1[vIFR] & via1[vIER] & 0x7F;
++	if (!events)
+ 		return IRQ_NONE;
+ 
+-	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
++	irq_num = VIA1_SOURCE_BASE;
++	irq_bit = 1;
++	do {
+ 		if (events & irq_bit) {
+ 			via1[vIER] = irq_bit;
+ 			via1[vIFR] = irq_bit;
+-			m68k_handle_int(VIA1_SOURCE_BASE + i);
++			m68k_handle_int(irq_num);
+ 			via1[vIER] = irq_bit | 0x80;
+ 		}
++		++irq_num;
++		irq_bit <<= 1;
++	} while (events >= irq_bit);
+ 
+ #if 0 /* freakin' pmu is doing weird stuff */
+ 	if (!oss_present) {
+@@ -454,20 +475,25 @@ irqreturn_t via1_irq(int irq, void *dev_
+ 
+ irqreturn_t via2_irq(int irq, void *dev_id)
+ {
+-	int irq_bit, i;
+-	unsigned char events, mask;
++	int irq_num;
++	unsigned char irq_bit, events;
+ 
+-	mask = via2[gIER] & 0x7F;
+-	if (!(events = via2[gIFR] & mask))
++	events = via2[gIFR] & via2[gIER] & 0x7F;
++	if (!events)
+ 		return IRQ_NONE;
+ 
+-	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
++	irq_num = VIA2_SOURCE_BASE;
++	irq_bit = 1;
++	do {
+ 		if (events & irq_bit) {
+ 			via2[gIER] = irq_bit;
+ 			via2[gIFR] = irq_bit | rbv_clear;
+-			m68k_handle_int(VIA2_SOURCE_BASE + i);
++			m68k_handle_int(irq_num);
+ 			via2[gIER] = irq_bit | 0x80;
+ 		}
++		++irq_num;
++		irq_bit <<= 1;
++	} while (events >= irq_bit);
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -478,19 +504,37 @@ irqreturn_t via2_irq(int irq, void *dev_
+ 
+ irqreturn_t via_nubus_irq(int irq, void *dev_id)
+ {
+-	int irq_bit, i;
+-	unsigned char events;
++	int slot_irq;
++	unsigned char slot_bit, events;
+ 
+-	if (!(events = ~via2[gBufA] & nubus_active))
++	events = ~via2[gBufA] & 0x7F;
++	if (rbv_present)
++		events &= via2[rSIER];
++	else
++		events &= nubus_active;
++	if (!events)
+ 		return IRQ_NONE;
+ 
+-	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) {
+-		if (events & irq_bit) {
+-			via_irq_disable(NUBUS_SOURCE_BASE + i);
+-			m68k_handle_int(NUBUS_SOURCE_BASE + i);
+-			via_irq_enable(NUBUS_SOURCE_BASE + i);
+-		}
+-	}
++	do {
++		slot_irq = IRQ_NUBUS_F;
++		slot_bit = 0x40;
++		do {
++			if (events & slot_bit) {
++				events &= ~slot_bit;
++				m68k_handle_int(slot_irq);
++			}
++			--slot_irq;
++			slot_bit >>= 1;
++		} while (events);
++
++ 		/* clear the CA1 interrupt and make certain there's no more. */
++		via2[gIFR] = 0x02 | rbv_clear;
++		events = ~via2[gBufA] & 0x7F;
++		if (rbv_present)
++			events &= via2[rSIER];
++		else
++			events &= nubus_active;
++	} while (events);
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -506,20 +550,6 @@ void via_irq_enable(int irq) {
+ 	if (irq_src == 1) {
+ 		via1[vIER] = irq_bit | 0x80;
+ 	} else if (irq_src == 2) {
+-		/*
+-		 * Set vPCR for SCSI interrupts (but not on RBV)
+-		 */
+-		if ((irq_idx == 0) && !rbv_present) {
+-			if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
+-				/* CB2 (IRQ) indep. input, positive edge */
+-				/* CA2 (DRQ) indep. input, positive edge */
+-				via2[vPCR] = 0x66;
+-			} else {
+-				/* CB2 (IRQ) indep. input, negative edge */
+-				/* CA2 (DRQ) indep. input, negative edge */
+-				via2[vPCR] = 0x22;
+-			}
+-		}
+ 		via2[gIER] = irq_bit | 0x80;
+ 	} else if (irq_src == 7) {
+ 		nubus_active |= irq_bit;
+@@ -557,9 +587,9 @@ void via_irq_disable(int irq) {
+ #endif
+ 
+ 	if (irq_src == 1) {
+-		via1[vIER] = irq_bit;
++		via1[vIER] = irq_bit & 0x7F;
+ 	} else if (irq_src == 2) {
+-		via2[gIER] = irq_bit;
++		via2[gIER] = irq_bit & 0x7F;
+ 	} else if (irq_src == 7) {
+ 		if (rbv_present) {
+ 			/* disable the slot interrupt.  SIER works like IER. */
+@@ -586,7 +616,9 @@ void via_irq_clear(int irq) {
+ 	} else if (irq_src == 2) {
+ 		via2[gIFR] = irq_bit | rbv_clear;
+ 	} else if (irq_src == 7) {
+-		/* FIXME: hmm.. */
++		/* FIXME: There is no way to clear an individual nubus slot
++		 * IRQ flag, other than getting the device to do it.
++		 */
+ 	}
+ }
+ 
+@@ -606,6 +638,7 @@ int via_irq_pending(int irq)
+ 	} else if (irq_src == 2) {
+ 		return via2[gIFR] & irq_bit;
+ 	} else if (irq_src == 7) {
++		/* FIXME: this can't work while a slot irq is disabled! */
+ 		return ~via2[gBufA] & irq_bit;
+ 	}
+ 	return 0;

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-macii-adb-fixes.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-macii-adb-fixes.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,873 @@
+Subject: [PATCH 9/13] m68k: Mac II ADB fixes
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Fix a crash caused by requests placed in the queue with the completed flag
+already set. This lead to some ADB_SYNC requests returning early and their
+request structs being popped off the stack while still queued. Stack corruption
+ensued or an invalid request callback pointer was invoked or both. Eliminate
+macii_retransmit() and its buggy implementation of macii_write(). Have
+macii_queue_poll() fully initialise the request queues.
+
+Fix a bug in macii_queue_poll() where the last_req pointer was not being set.
+This caused some requests to leave the queue before being completed (and would
+also corrupt the stack under certain conditions).
+
+Fix a race in macii_start that could set the state machine to "reading" while
+current_req was null.
+
+No longer send poll commands with the ADBREQ_REPLY flag -- doing that caused
+the replies to be stored in the request buffer where they were forgotten
+about.
+
+Don't autopoll by continuously sending new Talk commands. Get the controller to
+do that for us. This reduces the ADB interrupt rate on an idle bus to about 5
+per second. Only autopoll the devices that were probed.
+
+Explicitly clear the interrupt flag when polling.
+
+Use disable_irq rather than local_irq_save when polling.
+
+Remove excess local_irq_save/restore pairs.
+
+Improve bus timeout and service request detection.
+
+Remove unused code (last_reply, adb_dir etc) and unneeded code (prefix_len,
+first_byte etc).
+
+Change TIP and TACK to their correct names on this ADB controller (ST_EVEN and
+ST_ODD).
+
+Add some commentry.
+
+Add a generous quantity of sanity checks (BUG_ONs).
+
+Let m68k macs use the adb_sync boot param too.
+
+Tested on Mac II, Mac IIci, Quadra 650, Quadra 700 etc.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/kernel/setup.c      |   10 
+ drivers/macintosh/via-macii.c |  582 +++++++++++++++++-------------------------
+ 2 files changed, 251 insertions(+), 341 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/setup.c
++++ linux-m68k-2.6.21/arch/m68k/kernel/setup.c
+@@ -513,3 +513,13 @@ void check_bugs(void)
+ 	}
+ #endif /* !CONFIG_M68KFPU_EMU */
+ }
++
++#ifdef CONFIG_ADB
++static int __init adb_probe_sync_enable (char *str) {
++	extern int __adb_probe_sync;
++	__adb_probe_sync = 1;
++	return 1;
++}
++
++__setup("adb_sync", adb_probe_sync_enable);
++#endif /* CONFIG_ADB */
+--- linux-m68k-2.6.21.orig/drivers/macintosh/via-macii.c
++++ linux-m68k-2.6.21/drivers/macintosh/via-macii.c
+@@ -12,6 +12,15 @@
+  * 1999-08-02 (jmt) - Initial rewrite for Unified ADB.
+  * 2000-03-29 Tony Mantler <tonym at mac.linux-m68k.org>
+  * 				- Big overhaul, should actually work now.
++ * 2006-12-31 Finn Thain <fthain at telegraphics.com.au> - Another overhaul.
++ *
++ * Suggested reading:
++ *   Inside Macintosh, ch. 5 ADB Manager
++ *   Guide to the Macinstosh Family Hardware, ch. 8 Apple Desktop Bus
++ *   Rockwell R6522 VIA datasheet
++ *
++ * Apple's "ADB Analyzer" bus sniffer is invaluable:
++ *   ftp://ftp.apple.com/developer/Tool_Chest/Devices_-_Hardware/Apple_Desktop_Bus/
+  */
+  
+ #include <stdarg.h>
+@@ -26,7 +35,6 @@
+ #include <asm/macints.h>
+ #include <asm/machw.h>
+ #include <asm/mac_via.h>
+-#include <asm/io.h>
+ #include <asm/system.h>
+ 
+ static volatile unsigned char *via;
+@@ -51,9 +59,7 @@ static volatile unsigned char *via;
+ #define ANH		(15*RS)		/* A-side data, no handshake */
+ 
+ /* Bits in B data register: all active low */
+-#define TREQ		0x08		/* Transfer request (input) */
+-#define TACK		0x10		/* Transfer acknowledge (output) */
+-#define TIP		0x20		/* Transfer in progress (output) */
++#define CTLR_IRQ	0x08		/* Controller rcv status (input) */
+ #define ST_MASK		0x30		/* mask for selecting ADB state bits */
+ 
+ /* Bits in ACR */
+@@ -65,8 +71,6 @@ static volatile unsigned char *via;
+ #define IER_SET		0x80		/* set bits in IER */
+ #define IER_CLR		0		/* clear bits in IER */
+ #define SR_INT		0x04		/* Shift register full/empty */
+-#define SR_DATA		0x08		/* Shift register data */
+-#define SR_CLOCK	0x10		/* Shift register clock */
+ 
+ /* ADB transaction states according to GMHW */
+ #define ST_CMD		0x00		/* ADB state: command byte */
+@@ -77,7 +81,6 @@ static volatile unsigned char *via;
+ static int  macii_init_via(void);
+ static void macii_start(void);
+ static irqreturn_t macii_interrupt(int irq, void *arg);
+-static void macii_retransmit(int);
+ static void macii_queue_poll(void);
+ 
+ static int macii_probe(void);
+@@ -103,29 +106,37 @@ static enum macii_state {
+ 	sending,
+ 	reading,
+ 	read_done,
+-	awaiting_reply
+ } macii_state;
+ 
+-static int need_poll;
+-static int command_byte;
+-static int last_reply;
+-static int last_active;
+-
+-static struct adb_request *current_req;
+-static struct adb_request *last_req;
+-static struct adb_request *retry_req;
+-static unsigned char reply_buf[16];
+-static unsigned char *reply_ptr;
+-static int reply_len;
+-static int reading_reply;
+-static int data_index;
+-static int first_byte;
+-static int prefix_len;
+-static int status = ST_IDLE|TREQ;
+-static int last_status;
+-static int driver_running;
+-
+-/* debug level 10 required for ADB logging (should be && debug_adb, ideally) */
++static struct adb_request *current_req; /* first request struct in the queue */
++static struct adb_request *last_req;     /* last request struct in the queue */
++static unsigned char reply_buf[16];        /* storage for autopolled replies */
++static unsigned char *reply_ptr;      /* next byte in req->data or reply_buf */
++static int reading_reply;        /* store reply in reply_buf else req->reply */
++static int data_index;      /* index of the next byte to send from req->data */
++static int reply_len; /* number of bytes received in reply_buf or req->reply */
++static int status;          /* VIA's ADB status bits captured upon interrupt */
++static int last_status;              /* status bits as at previous interrupt */
++static int srq_asserted;     /* have to poll for the device that asserted it */
++static int command_byte;         /* the most recent command byte transmitted */
++static int autopoll_devs;      /* bits set are device addresses to be polled */
++
++/* Sanity check for request queue. Doesn't check for cycles. */
++static int request_is_queued(struct adb_request *req) {
++	struct adb_request *cur;
++	unsigned long flags;
++	local_irq_save(flags);
++	cur = current_req;
++	while (cur) {
++		if (cur == req) {
++			local_irq_restore(flags);
++			return 1;
++		}
++		cur = cur->next;
++	}
++	local_irq_restore(flags);
++	return 0;
++}
+ 
+ /* Check for MacII style ADB */
+ static int macii_probe(void)
+@@ -147,15 +158,16 @@ int macii_init(void)
+ 	local_irq_save(flags);
+ 	
+ 	err = macii_init_via();
+-	if (err) return err;
++	if (err) goto out;
+ 
+ 	err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",
+ 			  macii_interrupt);
+-	if (err) return err;
++	if (err) goto out;
+ 
+ 	macii_state = idle;
++out:
+ 	local_irq_restore(flags);
+-	return 0;
++	return err;
+ }
+ 
+ /* initialize the hardware */	
+@@ -163,12 +175,12 @@ static int macii_init_via(void)
+ {
+ 	unsigned char x;
+ 
+-	/* Set the lines up. We want TREQ as input TACK|TIP as output */
+-	via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ;
++	/* We want CTLR_IRQ as input and ST_EVEN | ST_ODD as output lines. */
++	via[DIRB] = (via[DIRB] | ST_EVEN | ST_ODD) & ~CTLR_IRQ;
+ 
+ 	/* Set up state: idle */
+ 	via[B] |= ST_IDLE;
+-	last_status = via[B] & (ST_MASK|TREQ);
++	last_status = via[B] & (ST_MASK|CTLR_IRQ);
+ 
+ 	/* Shift register on input */
+ 	via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT;
+@@ -179,81 +191,72 @@ static int macii_init_via(void)
+ 	return 0;
+ }
+ 
+-/* Send an ADB poll (Talk Register 0 command, tagged on the front of the request queue) */
++/* Send an ADB poll (Talk Register 0 command prepended to the request queue) */
+ static void macii_queue_poll(void)
+ {
+-	static int device = 0;
+-	static int in_poll=0;
++	/* No point polling the active device as it will never assert SRQ, so
++	 * poll the next device in the autopoll list. This could leave us
++	 * stuck in a polling loop if an unprobed device is asserting SRQ.
++	 * In theory, that could only happen if a device was plugged in after
++	 * probing started. Unplugging it again will break the cycle.
++	 * (Simply polling the next higher device often ends up polling almost
++	 * every device (after wrapping around), which takes too long.)
++	 */
++	int device_mask;
++	int next_device;
+ 	static struct adb_request req;
+-	unsigned long flags;
+-	
+-	if (in_poll) printk("macii_queue_poll: double poll!\n");
+ 
+-	in_poll++;
+-	if (++device > 15) device = 1;
+-
+-	adb_request(&req, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1,
+-		    ADB_READREG(device, 0));
+-
+-	local_irq_save(flags);
++	if (!autopoll_devs) return;
+ 
++	device_mask = (1 << (((command_byte & 0xF0) >> 4) + 1)) - 1;
++	if (autopoll_devs & ~device_mask)
++		next_device = ffs(autopoll_devs & ~device_mask) - 1;
++	else
++		next_device = ffs(autopoll_devs) - 1;
++
++	BUG_ON(request_is_queued(&req));
++
++	adb_request(&req, NULL, ADBREQ_NOSEND, 1,
++	            ADB_READREG(next_device, 0));
++
++	req.sent = 0;
++	req.complete = 0;
++	req.reply_len = 0;
+ 	req.next = current_req;
+-	current_req = &req;
+-
+-	local_irq_restore(flags);
+-	macii_start();
+-	in_poll--;
+-}
+-
+-/* Send an ADB retransmit (Talk, appended to the request queue) */
+-static void macii_retransmit(int device)
+-{
+-	static int in_retransmit = 0;
+-	static struct adb_request rt;
+-	unsigned long flags;
+-	
+-	if (in_retransmit) printk("macii_retransmit: double retransmit!\n");
+-
+-	in_retransmit++;
+-
+-	adb_request(&rt, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1,
+-		    ADB_READREG(device, 0));
+-
+-	local_irq_save(flags);
+ 
+ 	if (current_req != NULL) {
+-		last_req->next = &rt;
+-		last_req = &rt;
++		current_req = &req;
+ 	} else {
+-		current_req = &rt;
+-		last_req = &rt;
++		current_req = &req;
++		last_req = &req;
+ 	}
+-
+-	if (macii_state == idle) macii_start();
+-
+-	local_irq_restore(flags);
+-	in_retransmit--;
+ }
+ 
+ /* Send an ADB request; if sync, poll out the reply 'till it's done */
+ static int macii_send_request(struct adb_request *req, int sync)
+ {
+-	int i;
++	int err;
++	unsigned long flags;
+ 
+-	i = macii_write(req);
+-	if (i) return i;
++	BUG_ON(request_is_queued(req));
+ 
+-	if (sync) {
+-		while (!req->complete) macii_poll();
++	local_irq_save(flags);
++	err = macii_write(req);
++	local_irq_restore(flags);
++
++	if (!err && sync) {
++		while (!req->complete) {
++			macii_poll();
++		}
++		BUG_ON(request_is_queued(req));
+ 	}
+-	return 0;
++
++	return err;
+ }
+ 
+-/* Send an ADB request */
++/* Send an ADB request (append to request queue) */
+ static int macii_write(struct adb_request *req)
+ {
+-	unsigned long flags;
+-
+ 	if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) {
+ 		req->complete = 1;
+ 		return -EINVAL;
+@@ -264,8 +267,6 @@ static int macii_write(struct adb_reques
+ 	req->complete = 0;
+ 	req->reply_len = 0;
+ 
+-	local_irq_save(flags);
+-
+ 	if (current_req != NULL) {
+ 		last_req->next = req;
+ 		last_req = req;
+@@ -274,28 +275,52 @@ static int macii_write(struct adb_reques
+ 		last_req = req;
+ 		if (macii_state == idle) macii_start();
+ 	}
+-
+-	local_irq_restore(flags);
+ 	return 0;
+ }
+ 
+ /* Start auto-polling */
+ static int macii_autopoll(int devs)
+ {
+-	/* Just ping a random default address */
+-	if (!(current_req || retry_req))
+-		macii_retransmit( (last_active < 16 && last_active > 0) ? last_active : 3);
+-	return 0;
++	static struct adb_request req;
++	unsigned long flags;
++	int err = 0;
++
++	/* bit 1 == device 1, and so on. */
++	autopoll_devs = devs & 0xFFFE;
++
++	if (!autopoll_devs) return 0;
++
++	local_irq_save(flags);
++
++	if (current_req == NULL) {
++		/* Send a Talk Reg 0. The controller will repeatedly transmit
++		 * this as long as it is idle.
++		 */
++		adb_request(&req, NULL, ADBREQ_NOSEND, 1,
++		            ADB_READREG(ffs(autopoll_devs) - 1, 0));
++		err = macii_write(&req);
++	}
++
++	local_irq_restore(flags);
++	return err;
++}
++
++static inline int need_autopoll(void) {
++	/* Was the last command Talk Reg 0
++	 * and is the target on the autopoll list?
++	 */
++	if ((command_byte & 0x0F) == 0x0C &&
++	    ((1 << ((command_byte & 0xF0) >> 4)) & autopoll_devs))
++		return 0;
++	return 1;
+ }
+ 
+ /* Prod the chip without interrupts */
+ static void macii_poll(void)
+ {
+-	unsigned long flags;
+-
+-	local_irq_save(flags);
+-	if (via[IFR] & SR_INT) macii_interrupt(0, NULL);
+-	local_irq_restore(flags);
++	disable_irq(IRQ_MAC_ADB);
++	macii_interrupt(0, NULL);
++	enable_irq(IRQ_MAC_ADB);
+ }
+ 
+ /* Reset the bus */
+@@ -303,73 +328,34 @@ static int macii_reset_bus(void)
+ {
+ 	static struct adb_request req;
+ 	
++	if (request_is_queued(&req))
++		return 0;
++
+ 	/* Command = 0, Address = ignored */
+ 	adb_request(&req, NULL, 0, 1, ADB_BUSRESET);
+ 
++	/* Don't want any more requests during the Global Reset low time. */
++	udelay(3000);
++
+ 	return 0;
+ }
+ 
+ /* Start sending ADB packet */
+ static void macii_start(void)
+ {
+-	unsigned long flags;
+ 	struct adb_request *req;
+ 
+ 	req = current_req;
+-	if (!req) return;
+-	
+-	/* assert macii_state == idle */
+-	if (macii_state != idle) {
+-		printk("macii_start: called while driver busy (%p %x %x)!\n",
+-			req, macii_state, (uint) via1[B] & (ST_MASK|TREQ));
+-		return;
+-	}
+ 
+-	local_irq_save(flags);
+-	
+-	/* 
+-	 * IRQ signaled ?? (means ADB controller wants to send, or might 
+-	 * be end of packet if we were reading)
+-	 */
+-#if 0 /* FIXME: This is broke broke broke, for some reason */
+-	if ((via[B] & TREQ) == 0) {
+-		printk("macii_start: weird poll stuff. huh?\n");
+-		/*
+-		 *	FIXME - we need to restart this on a timer
+-		 *	or a collision at boot hangs us.
+-		 *	Never set macii_state to idle here, or macii_start 
+-		 *	won't be called again from send_request!
+-		 *	(need to re-check other cases ...)
+-		 */
+-		/*
+-		 * if the interrupt handler set the need_poll
+-		 * flag, it's hopefully a SRQ poll or re-Talk
+-		 * so we try to send here anyway
+-		 */
+-		if (!need_poll) {
+-			if (console_loglevel == 10)
+-				printk("macii_start: device busy - retry %p state %d status %x!\n", 
+-					req, macii_state,
+-					(uint) via[B] & (ST_MASK|TREQ));
+-			retry_req = req;
+-			/* set ADB status here ? */
+-			local_irq_restore(flags);
+-			return;
+-		} else {
+-			need_poll = 0;
+-		}
+-	}
+-#endif
+-	/*
+-	 * Another retry pending? (sanity check)
++	BUG_ON(req == NULL);
++
++	BUG_ON(macii_state != idle);
++
++	/* Now send it. Be careful though, that first byte of the request
++	 * is actually ADB_PACKET; the real data begins at index 1!
++	 * And req->nbytes is the number of bytes of real data plus one.
+ 	 */
+-	if (retry_req) {
+-		retry_req = NULL;
+-	}
+ 
+-	/* Now send it. Be careful though, that first byte of the request */
+-	/* is actually ADB_PACKET; the real data begins at index 1!	  */
+-	
+ 	/* store command byte */
+ 	command_byte = req->data[1];
+ 	/* Output mode */
+@@ -381,115 +367,97 @@ static void macii_start(void)
+ 
+ 	macii_state = sending;
+ 	data_index = 2;
+-
+-	local_irq_restore(flags);
+ }
+ 
+ /*
+- * The notorious ADB interrupt handler - does all of the protocol handling, 
+- * except for starting new send operations. Relies heavily on the ADB 
+- * controller sending and receiving data, thereby generating SR interrupts
+- * for us. This means there has to be always activity on the ADB bus, otherwise
+- * the whole process dies and has to be re-kicked by sending TALK requests ...
+- * CUDA-based Macs seem to solve this with the autopoll option, for MacII-type
+- * ADB the problem isn't solved yet (retransmit of the latest active TALK seems
+- * a good choice; either on timeout or on a timer interrupt).
++ * The notorious ADB interrupt handler - does all of the protocol handling.
++ * Relies on the ADB controller sending and receiving data, thereby
++ * generating shift register interrupts (SR_INT) for us. This means there has
++ * to be activity on the ADB bus. The chip will poll to achieve this.
+  *
+  * The basic ADB state machine was left unchanged from the original MacII code
+  * by Alan Cox, which was based on the CUDA driver for PowerMac. 
+- * The syntax of the ADB status lines seems to be totally different on MacII, 
+- * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle for
+- * sending, and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. Start 
+- * and end of a receive packet are signaled by asserting /IRQ on the interrupt
+- * line. Timeouts are signaled by a sequence of 4 0xFF, with /IRQ asserted on 
+- * every other byte. SRQ is probably signaled by 3 or more 0xFF tacked on the 
+- * end of a packet. (Thanks to Guido Koerber for eavesdropping on the ADB 
+- * protocol with a logic analyzer!!)
+- *
+- * Note: As of 21/10/97, the MacII ADB part works including timeout detection
+- * and retransmit (Talk to the last active device).
++ * The syntax of the ADB status lines is totally different on MacII,
++ * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle
++ * for sending and Idle -> Even -> Odd -> Even ->...-> Idle for receiving.
++ * Start and end of a receive packet are signalled by asserting /IRQ on the
++ * interrupt line (/IRQ means the CTLR_IRQ bit in port B; not to be confused
++ * with the VIA shift register interrupt. /IRQ never actually interrupts the
++ * processor, it's just an ordinary input.)
+  */
+ static irqreturn_t macii_interrupt(int irq, void *arg)
+ {
+-	int x, adbdir;
+-	unsigned long flags;
++	int x;
++	static int entered;
+ 	struct adb_request *req;
+ 
+-	last_status = status;
+-
+-	/* prevent races due to SCSI enabling ints */
+-	local_irq_save(flags);
+-
+-	if (driver_running) {
+-		local_irq_restore(flags);
+-		return IRQ_NONE;
++	if (!arg) {
++		/* Clear the SR IRQ flag when polling. */
++		if (via[IFR] & SR_INT)
++			via[IFR] = SR_INT;
++		else
++			return IRQ_NONE;
+ 	}
+ 
+-	driver_running = 1;
+-	
+-	status = via[B] & (ST_MASK|TREQ);
+-	adbdir = via[ACR] & SR_OUT;
++	BUG_ON(entered++);
++
++	last_status = status;
++	status = via[B] & (ST_MASK|CTLR_IRQ);
+ 
+ 	switch (macii_state) {
+ 		case idle:
++			if (reading_reply) {
++				reply_ptr = current_req->reply;
++			} else {
++				BUG_ON(current_req != NULL);
++				reply_ptr = reply_buf;
++			}
++
+ 			x = via[SR];
+-			first_byte = x;
+-			/* set ADB state = even for first data byte */
+-			via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
+ 
+-			reply_buf[0] = first_byte; /* was command_byte?? */
+-			reply_ptr = reply_buf + 1;
+-			reply_len = 1;
+-			prefix_len = 1;
+-			reading_reply = 0;
+-			
+-			macii_state = reading;
+-			break;
++			if ((status & CTLR_IRQ) && (x == 0xFF)) {
++				/* Bus timeout without SRQ sequence:
++				 *     data is "FF" while CTLR_IRQ is "H"
++				 */
++				reply_len = 0;
++				srq_asserted = 0;
++				macii_state = read_done;
++			} else {
++				macii_state = reading;
++				*reply_ptr = x;
++				reply_len = 1;
++			}
+ 
+-		case awaiting_reply:
+-			/* handshake etc. for II ?? */
+-			x = via[SR];
+-			first_byte = x;
+ 			/* set ADB state = even for first data byte */
+ 			via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
+-
+-			current_req->reply[0] = first_byte;
+-			reply_ptr = current_req->reply + 1;
+-			reply_len = 1;
+-			prefix_len = 1;
+-			reading_reply = 1;
+-
+-			macii_state = reading;			
+ 			break;
+ 
+ 		case sending:
+ 			req = current_req;
+ 			if (data_index >= req->nbytes) {
+-				/* print an error message if a listen command has no data */
+-				if (((command_byte & 0x0C) == 0x08)
+-				 /* && (console_loglevel == 10) */
+-				    && (data_index == 2))
+-					printk("MacII ADB: listen command with no data: %x!\n", 
+-						command_byte);
+-				/* reset to shift in */
+-				via[ACR] &= ~SR_OUT;
+-				x = via[SR];
+-				/* set ADB state idle - might get SRQ */
+-				via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
+-
+ 				req->sent = 1;
++				macii_state = idle;
+ 
+ 				if (req->reply_expected) {
+-					macii_state = awaiting_reply;
++					reading_reply = 1;
+ 				} else {
+ 					req->complete = 1;
+ 					current_req = req->next;
+ 					if (req->done) (*req->done)(req);
+-					macii_state = idle;
+-					if (current_req || retry_req)
++
++					if (current_req)
+ 						macii_start();
+ 					else
+-						macii_retransmit((command_byte & 0xF0) >> 4);
++						if (need_autopoll())
++							macii_autopoll(autopoll_devs);
++				}
++
++				if (macii_state == idle) {
++					/* reset to shift in */
++					via[ACR] &= ~SR_OUT;
++					x = via[SR];
++					/* set ADB state idle - might get SRQ */
++					via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
+ 				}
+ 			} else {
+ 				via[SR] = req->data[data_index++];
+@@ -505,147 +473,79 @@ static irqreturn_t macii_interrupt(int i
+ 			break;
+ 
+ 		case reading:
++			x = via[SR];
++			BUG_ON((status & ST_MASK) == ST_CMD ||
++			       (status & ST_MASK) == ST_IDLE);
+ 
+-			/* timeout / SRQ handling for II hw */
+-			if( (first_byte == 0xFF && (reply_len-prefix_len)==2 
+-			     && memcmp(reply_ptr-2,"\xFF\xFF",2)==0) || 
+-			    ((reply_len-prefix_len)==3 
+-			     && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0))
+-			{
+-				/*
+-				 * possible timeout (in fact, most probably a 
+-				 * timeout, since SRQ can't be signaled without
+-				 * transfer on the bus).
+-				 * The last three bytes seen were FF, together 
+-				 * with the starting byte (in case we started
+-				 * on 'idle' or 'awaiting_reply') this probably
+-				 * makes four. So this is mostl likely #5!
+-				 * The timeout signal is a pattern 1 0 1 0 0..
+-				 * on /INT, meaning we missed it :-(
+-				 */
+-				x = via[SR];
+-				if (x != 0xFF) printk("MacII ADB: mistaken timeout/SRQ!\n");
++			/* Bus timeout with SRQ sequence:
++			 *     data is "XX FF"      while CTLR_IRQ is "L L"
++			 * End of packet without SRQ sequence:
++			 *     data is "XX...YY 00" while CTLR_IRQ is "L...H L"
++			 * End of packet SRQ sequence:
++			 *     data is "XX...YY 00" while CTLR_IRQ is "L...L L"
++			 * (where XX is the first response byte and
++			 * YY is the last byte of valid response data.)
++			 */
+ 
+-				if ((status & TREQ) == (last_status & TREQ)) {
+-					/* Not a timeout. Unsolicited SRQ? weird. */
+-					/* Terminate the SRQ packet and poll */
+-					need_poll = 1;
++			srq_asserted = 0;
++			if (!(status & CTLR_IRQ)) {
++				if (x == 0xFF) {
++					if (!(last_status & CTLR_IRQ)) {
++						macii_state = read_done;
++						reply_len = 0;
++						srq_asserted = 1;
++					}
++				} else if (x == 0x00) {
++					macii_state = read_done;
++					if (!(last_status & CTLR_IRQ))
++						srq_asserted = 1;
+ 				}
+-				/* There's no packet to get, so reply is blank */
+-				via[B] ^= ST_MASK;
+-				reply_ptr -= (reply_len-prefix_len);
+-				reply_len = prefix_len;
+-				macii_state = read_done;
+-				break;
+-			} /* end timeout / SRQ handling for II hw. */
++			}
+ 
+-			if((reply_len-prefix_len)>3
+-				&& memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
+-			{
+-				/* SRQ tacked on data packet */
+-				/* Terminate the packet (SRQ never ends) */
+-				x = via[SR];
+-				macii_state = read_done;
+-				reply_len -= 3;
+-				reply_ptr -= 3;
+-				need_poll = 1;
+-				/* need to continue; next byte not seen else */
+-			} else {
+-				/* Sanity check */
+-				if (reply_len > 15) reply_len = 0;
+-				/* read byte */
+-				x = via[SR];
+-				*reply_ptr = x;
++			if (macii_state == reading) {
++				BUG_ON(reply_len > 15);
+ 				reply_ptr++;
++				*reply_ptr = x;
+ 				reply_len++;
+ 			}
+-			/* The usual handshake ... */
+ 
+-			/*
+-			 * NetBSD hints that the next to last byte 
+-			 * is sent with IRQ !! 
+-			 * Guido found out it's the last one (0x0),
+-			 * but IRQ should be asserted already.
+-			 * Problem with timeout detection: First
+-			 * transition to /IRQ might be second 
+-			 * byte of timeout packet! 
+-			 * Timeouts are signaled by 4x FF.
+-			 */
+-			if (((status & TREQ) == 0) && (x == 0x00)) { /* != 0xFF */
+-				/* invert state bits, toggle ODD/EVEN */
+-				via[B] ^= ST_MASK;
+-
+-				/* adjust packet length */
+-				reply_len--;
+-				reply_ptr--;
+-				macii_state = read_done;
+-			} else {
+-				/* not caught: ST_CMD */
+-				/* required for re-entry 'reading'! */
+-				if ((status & ST_MASK) == ST_IDLE) {
+-					/* (in)sanity check - set even */
+-					via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
+-				} else {
+-					/* invert state bits */
+-					via[B] ^= ST_MASK;
+-				}
+-			}
++			/* invert state bits, toggle ODD/EVEN */
++			via[B] ^= ST_MASK;
+ 			break;
+ 
+ 		case read_done:
+ 			x = via[SR];
++
+ 			if (reading_reply) {
++				reading_reply = 0;
+ 				req = current_req;
+-				req->reply_len = reply_ptr - req->reply;
++				req->reply_len = reply_len;
+ 				req->complete = 1;
+ 				current_req = req->next;
+ 				if (req->done) (*req->done)(req);
+-			} else {
+-				adb_input(reply_buf, reply_ptr - reply_buf, 0);
+-			}
++			} else if (reply_len && autopoll_devs)
++				adb_input(reply_buf, reply_len, 0);
+ 
+-			/*
+-			 * remember this device ID; it's the latest we got a 
+-			 * reply from!
+-			 */
+-			last_reply = command_byte;
+-			last_active = (command_byte & 0xF0) >> 4;
++			macii_state = idle;
+ 
+ 			/* SRQ seen before, initiate poll now */
+-			if (need_poll) {
+-				macii_state = idle;
++			if (srq_asserted)
+ 				macii_queue_poll();
+-				need_poll = 0;
+-				break;
+-			}
+-			
+-			/* set ADB state to idle */
+-			via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
+-			
+-			/* /IRQ seen, so the ADB controller has data for us */
+-			if ((via[B] & TREQ) != 0) {
+-				macii_state = reading;
+ 
+-				reply_buf[0] = command_byte;
+-				reply_ptr = reply_buf + 1;
+-				reply_len = 1;
+-				prefix_len = 1;
+-				reading_reply = 0;
+-			} else {
+-				/* no IRQ, send next packet or wait */
+-				macii_state = idle;
+-				if (current_req)
+-					macii_start();
+-				else
+-					macii_retransmit(last_active);
+-			}
++			if (current_req)
++				macii_start();
++			else
++				if (need_autopoll())
++					macii_autopoll(autopoll_devs);
++
++			if (macii_state == idle)
++				via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
+ 			break;
+ 
+ 		default:
+ 		break;
+ 	}
+-	/* reset mutex and interrupts */
+-	driver_running = 0;
+-	local_irq_restore(flags);
++
++	entered--;
+ 	return IRQ_HANDLED;
+ }

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-macmace-fixes.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-macmace-fixes.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,951 @@
+Subject: [PATCH 11/13] m68k: macmace fixes
+Cc: Jeff Garzik <jgarzik at pobox.com>, netdev at vger.kernel.org
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Fix a race condition in the transmit code, where the dma interrupt could update
+the free tx buffer count concurrently and wedge the tx queue.
+
+Fix the misuse of the rx frame status and rx frame length registers: no more
+"fifo overrun" errors caused by the OFLOW bit being tested in the frame length
+register (instead of the status register), and no more missed packets due to
+incorrect length taken from status register (instead of the frame length
+register).
+
+Fix a panic (skb_over_panic BUG) caused by allocating and then copying an
+incoming packet while the packet length register was changing.
+
+Cut-and-paste the reset code from the powermac mace driver (mace.c), so the NIC
+functions when MacOS does not initialise it (important for anyone wanting to
+use the Emile boot loader).
+
+Cut-and-paste the error counting and timeout recovery code from mace.c.
+
+Fix over allocation of rx buffer memory (it's page order, not page count).
+
+Converted to driver model.
+
+Converted to DMA API.
+
+Since I've run out of ways to make it fail, and since it performs well now,
+promote the driver from EXPERIMENTAL status. Tested on both quadra 840av and
+660av.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/net/Kconfig   |    4 
+ drivers/net/Space.c   |    4 
+ drivers/net/macmace.c |  591 ++++++++++++++++++++++++++++++--------------------
+ 3 files changed, 364 insertions(+), 235 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/net/Kconfig
++++ linux-m68k-2.6.21/drivers/net/Kconfig
+@@ -337,8 +337,8 @@ config MACSONIC
+ 	  be called macsonic.
+ 
+ config MACMACE
+-	bool "Macintosh (AV) onboard MACE ethernet (EXPERIMENTAL)"
+-	depends on NET_ETHERNET && MAC && EXPERIMENTAL
++	bool "Macintosh (AV) onboard MACE ethernet"
++	depends on NET_ETHERNET && MAC
+ 	select CRC32
+ 	help
+ 	  Support for the onboard AMD 79C940 MACE Ethernet controller used in
+--- linux-m68k-2.6.21.orig/drivers/net/Space.c
++++ linux-m68k-2.6.21/drivers/net/Space.c
+@@ -83,7 +83,6 @@ extern struct net_device *bagetlance_pro
+ extern struct net_device *mvme147lance_probe(int unit);
+ extern struct net_device *tc515_probe(int unit);
+ extern struct net_device *lance_probe(int unit);
+-extern struct net_device *mace_probe(int unit);
+ extern struct net_device *mac8390_probe(int unit);
+ extern struct net_device *mac89x0_probe(int unit);
+ extern struct net_device *mc32_probe(int unit);
+@@ -274,9 +273,6 @@ static struct devprobe2 m68k_probes[] __
+ #ifdef CONFIG_MVME147_NET	/* MVME147 internal Ethernet */
+ 	{mvme147lance_probe, 0},
+ #endif
+-#ifdef CONFIG_MACMACE		/* Mac 68k Quadra AV builtin Ethernet */
+-	{mace_probe, 0},
+-#endif
+ #ifdef CONFIG_MAC8390           /* NuBus NS8390-based cards */
+ 	{mac8390_probe, 0},
+ #endif
+--- linux-m68k-2.6.21.orig/drivers/net/macmace.c
++++ linux-m68k-2.6.21/drivers/net/macmace.c
+@@ -12,6 +12,11 @@
+  *	Copyright (C) 1998 Alan Cox <alan at redhat.com>
+  *
+  *	Modified heavily by Joshua M. Thompson based on Dave Huang's NetBSD driver
++ *
++ *	Copyright (C) 2007 Finn Thain
++ *
++ *	Converted to DMA API, converted to unified driver model,
++ *	sync'd some routines with mace.c and fixed various bugs.
+  */
+ 
+ 
+@@ -23,8 +28,9 @@
+ #include <linux/string.h>
+ #include <linux/crc32.h>
+ #include <linux/bitrev.h>
++#include <linux/dma-mapping.h>
++#include <linux/platform_device.h>
+ #include <asm/io.h>
+-#include <asm/pgtable.h>
+ #include <asm/irq.h>
+ #include <asm/macintosh.h>
+ #include <asm/macints.h>
+@@ -32,13 +38,20 @@
+ #include <asm/page.h>
+ #include "mace.h"
+ 
+-#define N_TX_RING	1
+-#define N_RX_RING	8
+-#define N_RX_PAGES	((N_RX_RING * 0x0800 + PAGE_SIZE - 1) / PAGE_SIZE)
++static char mac_mace_string[] = "macmace";
++static struct platform_device *mac_mace_device;
++
++#define N_TX_BUFF_ORDER	0
++#define N_TX_RING	(1 << N_TX_BUFF_ORDER)
++#define N_RX_BUFF_ORDER	3
++#define N_RX_RING	(1 << N_RX_BUFF_ORDER)
++
+ #define TX_TIMEOUT	HZ
+ 
+-/* Bits in transmit DMA status */
+-#define TX_DMA_ERR	0x80
++#define MACE_BUFF_SIZE	0x800
++
++/* Chip rev needs workaround on HW & multicast addr change */
++#define BROKEN_ADDRCHG_REV	0x0941
+ 
+ /* The MACE is simply wired down on a Mac68K box */
+ 
+@@ -47,40 +60,46 @@
+ 
+ struct mace_data {
+ 	volatile struct mace *mace;
+-	volatile unsigned char *tx_ring;
+-	volatile unsigned char *tx_ring_phys;
+-	volatile unsigned char *rx_ring;
+-	volatile unsigned char *rx_ring_phys;
++	unsigned char *tx_ring;
++	dma_addr_t tx_ring_phys;
++	unsigned char *rx_ring;
++	dma_addr_t rx_ring_phys;
+ 	int dma_intr;
+ 	struct net_device_stats stats;
+ 	int rx_slot, rx_tail;
+ 	int tx_slot, tx_sloti, tx_count;
++	int chipid;
++	struct device *device;
+ };
+ 
+ struct mace_frame {
+-	u16	len;
+-	u16	status;
+-	u16	rntpc;
+-	u16	rcvcc;
+-	u32	pad1;
+-	u32	pad2;
++	u8	rcvcnt;
++	u8	pad1;
++	u8	rcvsts;
++	u8	pad2;
++	u8	rntpc;
++	u8	pad3;
++	u8	rcvcc;
++	u8	pad4;
++	u32	pad5;
++	u32	pad6;
+ 	u8	data[1];
+ 	/* And frame continues.. */
+ };
+ 
+ #define PRIV_BYTES	sizeof(struct mace_data)
+ 
+-extern void psc_debug_dump(void);
+-
+ static int mace_open(struct net_device *dev);
+ static int mace_close(struct net_device *dev);
+ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
+ static struct net_device_stats *mace_stats(struct net_device *dev);
+ static void mace_set_multicast(struct net_device *dev);
+ static int mace_set_address(struct net_device *dev, void *addr);
++static void mace_reset(struct net_device *dev);
+ static irqreturn_t mace_interrupt(int irq, void *dev_id);
+ static irqreturn_t mace_dma_intr(int irq, void *dev_id);
+ static void mace_tx_timeout(struct net_device *dev);
++static void __mace_set_address(struct net_device *dev, void *addr);
+ 
+ /*
+  * Load a receive DMA channel with a base address and ring length
+@@ -88,7 +107,7 @@ static void mace_tx_timeout(struct net_d
+ 
+ static void mace_load_rxdma_base(struct net_device *dev, int set)
+ {
+-	struct mace_data *mp = (struct mace_data *) dev->priv;
++	struct mace_data *mp = netdev_priv(dev);
+ 
+ 	psc_write_word(PSC_ENETRD_CMD + set, 0x0100);
+ 	psc_write_long(PSC_ENETRD_ADDR + set, (u32) mp->rx_ring_phys);
+@@ -103,7 +122,7 @@ static void mace_load_rxdma_base(struct 
+ 
+ static void mace_rxdma_reset(struct net_device *dev)
+ {
+-	struct mace_data *mp = (struct mace_data *) dev->priv;
++	struct mace_data *mp = netdev_priv(dev);
+ 	volatile struct mace *mace = mp->mace;
+ 	u8 maccc = mace->maccc;
+ 
+@@ -130,7 +149,7 @@ static void mace_rxdma_reset(struct net_
+ 
+ static void mace_txdma_reset(struct net_device *dev)
+ {
+-	struct mace_data *mp = (struct mace_data *) dev->priv;
++	struct mace_data *mp = netdev_priv(dev);
+ 	volatile struct mace *mace = mp->mace;
+ 	u8 maccc;
+ 
+@@ -168,7 +187,7 @@ static void mace_dma_off(struct net_devi
+  * model of Macintrash has a MACE (AV macintoshes)
+  */
+ 
+-struct net_device *mace_probe(int unit)
++static int __devinit mace_probe(struct platform_device *pdev)
+ {
+ 	int j;
+ 	struct mace_data *mp;
+@@ -179,24 +198,28 @@ struct net_device *mace_probe(int unit)
+ 	int err;
+ 
+ 	if (found || macintosh_config->ether_type != MAC_ETHER_MACE)
+-		return ERR_PTR(-ENODEV);
++		return -ENODEV;
+ 
+ 	found = 1;	/* prevent 'finding' one on every device probe */
+ 
+ 	dev = alloc_etherdev(PRIV_BYTES);
+ 	if (!dev)
+-		return ERR_PTR(-ENOMEM);
++		return -ENOMEM;
+ 
+-	if (unit >= 0)
+-		sprintf(dev->name, "eth%d", unit);
++	mp = netdev_priv(dev);
++
++	mp->device = &pdev->dev;
++	SET_NETDEV_DEV(dev, &pdev->dev);
++ 	SET_MODULE_OWNER(dev);
+ 
+-	mp = (struct mace_data *) dev->priv;
+ 	dev->base_addr = (u32)MACE_BASE;
+ 	mp->mace = (volatile struct mace *) MACE_BASE;
+ 
+ 	dev->irq = IRQ_MAC_MACE;
+ 	mp->dma_intr = IRQ_MAC_MACE_DMA;
+ 
++	mp->chipid = mp->mace->chipid_hi << 8 | mp->mace->chipid_lo;
++
+ 	/*
+ 	 * The PROM contains 8 bytes which total 0xFF when XOR'd
+ 	 * together. Due to the usual peculiar apple brain damage
+@@ -217,7 +240,7 @@ struct net_device *mace_probe(int unit)
+ 
+ 	if (checksum != 0xFF) {
+ 		free_netdev(dev);
+-		return ERR_PTR(-ENODEV);
++		return -ENODEV;
+ 	}
+ 
+ 	memset(&mp->stats, 0, sizeof(mp->stats));
+@@ -237,22 +260,98 @@ struct net_device *mace_probe(int unit)
+ 
+ 	err = register_netdev(dev);
+ 	if (!err)
+-		return dev;
++		return 0;
+ 
+ 	free_netdev(dev);
+-	return ERR_PTR(err);
++	return err;
++}
++
++/*
++ * Reset the chip.
++ */
++
++static void mace_reset(struct net_device *dev)
++{
++	struct mace_data *mp = netdev_priv(dev);
++	volatile struct mace *mb = mp->mace;
++	int i;
++
++	/* soft-reset the chip */
++	i = 200;
++	while (--i) {
++		mb->biucc = SWRST;
++		if (mb->biucc & SWRST) {
++			udelay(10);
++			continue;
++		}
++		break;
++	}
++	if (!i) {
++		printk(KERN_ERR "macmace: cannot reset chip!\n");
++		return;
++	}
++
++	mb->maccc = 0;	/* turn off tx, rx */
++	mb->imr = 0xFF;	/* disable all intrs for now */
++	i = mb->ir;
++
++	mb->biucc = XMTSP_64;
++	mb->utr = RTRD;
++	mb->fifocc = XMTFW_8 | RCVFW_64 | XMTFWU | RCVFWU;
++
++	mb->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */
++	mb->rcvfc = 0;
++
++	/* load up the hardware address */
++	__mace_set_address(dev, dev->dev_addr);
++
++	/* clear the multicast filter */
++	if (mp->chipid == BROKEN_ADDRCHG_REV)
++		mb->iac = LOGADDR;
++	else {
++		mb->iac = ADDRCHG | LOGADDR;
++		while ((mb->iac & ADDRCHG) != 0)
++			;
++	}
++	for (i = 0; i < 8; ++i)
++		mb->ladrf = 0;
++
++	/* done changing address */
++	if (mp->chipid != BROKEN_ADDRCHG_REV)
++		mb->iac = 0;
++
++	mb->plscc = PORTSEL_AUI;
+ }
+ 
+ /*
+  * Load the address on a mace controller.
+  */
+ 
+-static int mace_set_address(struct net_device *dev, void *addr)
++static void __mace_set_address(struct net_device *dev, void *addr)
+ {
+-	unsigned char *p = addr;
+-	struct mace_data *mp = (struct mace_data *) dev->priv;
++	struct mace_data *mp = netdev_priv(dev);
+ 	volatile struct mace *mb = mp->mace;
++	unsigned char *p = addr;
+ 	int i;
++
++	/* load up the hardware address */
++	if (mp->chipid == BROKEN_ADDRCHG_REV)
++		mb->iac = PHYADDR;
++	else {
++		mb->iac = ADDRCHG | PHYADDR;
++		while ((mb->iac & ADDRCHG) != 0)
++			;
++	}
++	for (i = 0; i < 6; ++i)
++		mb->padr = dev->dev_addr[i] = p[i];
++	if (mp->chipid != BROKEN_ADDRCHG_REV)
++		mb->iac = 0;
++}
++
++static int mace_set_address(struct net_device *dev, void *addr)
++{
++	struct mace_data *mp = netdev_priv(dev);
++	volatile struct mace *mb = mp->mace;
+ 	unsigned long flags;
+ 	u8 maccc;
+ 
+@@ -260,15 +359,10 @@ static int mace_set_address(struct net_d
+ 
+ 	maccc = mb->maccc;
+ 
+-	/* load up the hardware address */
+-	mb->iac = ADDRCHG | PHYADDR;
+-	while ((mb->iac & ADDRCHG) != 0);
+-
+-	for (i = 0; i < 6; ++i) {
+-		mb->padr = dev->dev_addr[i] = p[i];
+-	}
++	__mace_set_address(dev, addr);
+ 
+ 	mb->maccc = maccc;
++
+ 	local_irq_restore(flags);
+ 
+ 	return 0;
+@@ -281,31 +375,11 @@ static int mace_set_address(struct net_d
+ 
+ static int mace_open(struct net_device *dev)
+ {
+-	struct mace_data *mp = (struct mace_data *) dev->priv;
++	struct mace_data *mp = netdev_priv(dev);
+ 	volatile struct mace *mb = mp->mace;
+-#if 0
+-	int i;
+ 
+-	i = 200;
+-	while (--i) {
+-		mb->biucc = SWRST;
+-		if (mb->biucc & SWRST) {
+-			udelay(10);
+-			continue;
+-		}
+-		break;
+-	}
+-	if (!i) {
+-		printk(KERN_ERR "%s: software reset failed!!\n", dev->name);
+-		return -EAGAIN;
+-	}
+-#endif
+-
+-	mb->biucc = XMTSP_64;
+-	mb->fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU | XMTBRST | RCVBRST;
+-	mb->xmtfc = AUTO_PAD_XMIT;
+-	mb->plscc = PORTSEL_AUI;
+-	/* mb->utr = RTRD; */
++	/* reset the chip */
++	mace_reset(dev);
+ 
+ 	if (request_irq(dev->irq, mace_interrupt, 0, dev->name, dev)) {
+ 		printk(KERN_ERR "%s: can't get irq %d\n", dev->name, dev->irq);
+@@ -319,25 +393,21 @@ static int mace_open(struct net_device *
+ 
+ 	/* Allocate the DMA ring buffers */
+ 
+-	mp->rx_ring = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, N_RX_PAGES);
+-	mp->tx_ring = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, 0);
+-
+-	if (mp->tx_ring==NULL || mp->rx_ring==NULL) {
+-		if (mp->rx_ring) free_pages((u32) mp->rx_ring, N_RX_PAGES);
+-		if (mp->tx_ring) free_pages((u32) mp->tx_ring, 0);
+-		free_irq(dev->irq, dev);
+-		free_irq(mp->dma_intr, dev);
+-		printk(KERN_ERR "%s: unable to allocate DMA buffers\n", dev->name);
+-		return -ENOMEM;
++	mp->tx_ring = dma_alloc_coherent(mp->device,
++			N_TX_RING * MACE_BUFF_SIZE,
++			&mp->tx_ring_phys, GFP_KERNEL);
++	if (mp->tx_ring == NULL) {
++		printk(KERN_ERR "%s: unable to allocate DMA tx buffers\n", dev->name);
++		goto out1;
+ 	}
+ 
+-	mp->rx_ring_phys = (unsigned char *) virt_to_bus((void *)mp->rx_ring);
+-	mp->tx_ring_phys = (unsigned char *) virt_to_bus((void *)mp->tx_ring);
+-
+-	/* We want the Rx buffer to be uncached and the Tx buffer to be writethrough */
+-
+-	kernel_set_cachemode((void *)mp->rx_ring, N_RX_PAGES * PAGE_SIZE, IOMAP_NOCACHE_NONSER);
+-	kernel_set_cachemode((void *)mp->tx_ring, PAGE_SIZE, IOMAP_WRITETHROUGH);
++	mp->rx_ring = dma_alloc_coherent(mp->device,
++			N_RX_RING * MACE_BUFF_SIZE,
++			&mp->rx_ring_phys, GFP_KERNEL);
++	if (mp->rx_ring == NULL) {
++		printk(KERN_ERR "%s: unable to allocate DMA rx buffers\n", dev->name);
++		goto out2;
++	}
+ 
+ 	mace_dma_off(dev);
+ 
+@@ -348,34 +418,22 @@ static int mace_open(struct net_device *
+ 	psc_write_word(PSC_ENETWR_CTL, 0x0400);
+ 	psc_write_word(PSC_ENETRD_CTL, 0x0400);
+ 
+-#if 0
+-	/* load up the hardware address */
+-
+-	mb->iac = ADDRCHG | PHYADDR;
+-
+-	while ((mb->iac & ADDRCHG) != 0);
+-
+-	for (i = 0; i < 6; ++i)
+-		mb->padr = dev->dev_addr[i];
+-
+-	/* clear the multicast filter */
+-	mb->iac = ADDRCHG | LOGADDR;
+-
+-	while ((mb->iac & ADDRCHG) != 0);
+-
+-	for (i = 0; i < 8; ++i)
+-		mb->ladrf = 0;
+-
+-	mb->plscc = PORTSEL_GPSI + ENPLSIO;
+-
+-	mb->maccc = ENXMT | ENRCV;
+-	mb->imr = RCVINT;
+-#endif
+-
+ 	mace_rxdma_reset(dev);
+ 	mace_txdma_reset(dev);
+ 
++	/* turn it on! */
++	mb->maccc = ENXMT | ENRCV;
++	/* enable all interrupts except receive interrupts */
++	mb->imr = RCVINT;
+ 	return 0;
++
++out2:
++	dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE,
++	                  mp->tx_ring, mp->tx_ring_phys);
++out1:
++	free_irq(dev->irq, dev);
++	free_irq(mp->dma_intr, dev);
++	return -ENOMEM;
+ }
+ 
+ /*
+@@ -384,19 +442,13 @@ static int mace_open(struct net_device *
+ 
+ static int mace_close(struct net_device *dev)
+ {
+-	struct mace_data *mp = (struct mace_data *) dev->priv;
++	struct mace_data *mp = netdev_priv(dev);
+ 	volatile struct mace *mb = mp->mace;
+ 
+ 	mb->maccc = 0;		/* disable rx and tx	 */
+ 	mb->imr = 0xFF;		/* disable all irqs	 */
+ 	mace_dma_off(dev);	/* disable rx and tx dma */
+ 
+-	free_irq(dev->irq, dev);
+-	free_irq(IRQ_MAC_MACE_DMA, dev);
+-
+-	free_pages((u32) mp->rx_ring, N_RX_PAGES);
+-	free_pages((u32) mp->tx_ring, 0);
+-
+ 	return 0;
+ }
+ 
+@@ -406,15 +458,20 @@ static int mace_close(struct net_device 
+ 
+ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
+ {
+-	struct mace_data *mp = (struct mace_data *) dev->priv;
++	struct mace_data *mp = netdev_priv(dev);
++	unsigned long flags;
+ 
+-	/* Stop the queue if the buffer is full */
++	/* Stop the queue since there's only the one buffer */
+ 
++	local_irq_save(flags);
++	netif_stop_queue(dev);
+ 	if (!mp->tx_count) {
+-		netif_stop_queue(dev);
+-		return 1;
++		printk(KERN_ERR "macmace: tx queue running but no free buffers.\n");
++		local_irq_restore(flags);
++		return NETDEV_TX_BUSY;
+ 	}
+ 	mp->tx_count--;
++	local_irq_restore(flags);
+ 
+ 	mp->stats.tx_packets++;
+ 	mp->stats.tx_bytes += skb->len;
+@@ -433,23 +490,26 @@ static int mace_xmit_start(struct sk_buf
+ 
+ 	dev_kfree_skb(skb);
+ 
+-	return 0;
++	dev->trans_start = jiffies;
++	return NETDEV_TX_OK;
+ }
+ 
+ static struct net_device_stats *mace_stats(struct net_device *dev)
+ {
+-	struct mace_data *p = (struct mace_data *) dev->priv;
+-	return &p->stats;
++	struct mace_data *mp = netdev_priv(dev);
++	return &mp->stats;
+ }
+ 
+ static void mace_set_multicast(struct net_device *dev)
+ {
+-	struct mace_data *mp = (struct mace_data *) dev->priv;
++	struct mace_data *mp = netdev_priv(dev);
+ 	volatile struct mace *mb = mp->mace;
+ 	int i, j;
+ 	u32 crc;
+ 	u8 maccc;
++	unsigned long flags;
+ 
++	local_irq_save(flags);
+ 	maccc = mb->maccc;
+ 	mb->maccc &= ~PROM;
+ 
+@@ -474,116 +534,122 @@ static void mace_set_multicast(struct ne
+ 			}
+ 		}
+ 
+-		mb->iac = ADDRCHG | LOGADDR;
+-		while (mb->iac & ADDRCHG);
+-
+-		for (i = 0; i < 8; ++i) {
+-			mb->ladrf = multicast_filter[i];
++		if (mp->chipid == BROKEN_ADDRCHG_REV)
++			mb->iac = LOGADDR;
++		else {
++			mb->iac = ADDRCHG | LOGADDR;
++			while ((mb->iac & ADDRCHG) != 0)
++				;
+ 		}
++		for (i = 0; i < 8; ++i)
++			mb->ladrf = multicast_filter[i];
++		if (mp->chipid != BROKEN_ADDRCHG_REV)
++			mb->iac = 0;
+ 	}
+ 
+ 	mb->maccc = maccc;
++	local_irq_restore(flags);
+ }
+ 
+-/*
+- * Miscellaneous interrupts are handled here. We may end up
+- * having to bash the chip on the head for bad errors
+- */
+-
+ static void mace_handle_misc_intrs(struct mace_data *mp, int intr)
+ {
+ 	volatile struct mace *mb = mp->mace;
+ 	static int mace_babbles, mace_jabbers;
+ 
+-	if (intr & MPCO) {
++	if (intr & MPCO)
+ 		mp->stats.rx_missed_errors += 256;
+-	}
+-	mp->stats.rx_missed_errors += mb->mpc;	/* reading clears it */
+-
+-	if (intr & RNTPCO) {
++	mp->stats.rx_missed_errors += mb->mpc;   /* reading clears it */
++	if (intr & RNTPCO)
+ 		mp->stats.rx_length_errors += 256;
+-	}
+-	mp->stats.rx_length_errors += mb->rntpc;	/* reading clears it */
+-
+-	if (intr & CERR) {
++	mp->stats.rx_length_errors += mb->rntpc; /* reading clears it */
++	if (intr & CERR)
+ 		++mp->stats.tx_heartbeat_errors;
+-	}
+-	if (intr & BABBLE) {
+-		if (mace_babbles++ < 4) {
+-			printk(KERN_DEBUG "mace: babbling transmitter\n");
+-		}
+-	}
+-	if (intr & JABBER) {
+-		if (mace_jabbers++ < 4) {
+-			printk(KERN_DEBUG "mace: jabbering transceiver\n");
+-		}
+-	}
++	if (intr & BABBLE)
++		if (mace_babbles++ < 4)
++			printk(KERN_DEBUG "macmace: babbling transmitter\n");
++	if (intr & JABBER)
++		if (mace_jabbers++ < 4)
++			printk(KERN_DEBUG "macmace: jabbering transceiver\n");
+ }
+ 
+-/*
+- *	A transmit error has occurred. (We kick the transmit side from
+- *	the DMA completion)
+- */
+-
+-static void mace_xmit_error(struct net_device *dev)
++static irqreturn_t mace_interrupt(int irq, void *dev_id)
+ {
+-	struct mace_data *mp = (struct mace_data *) dev->priv;
++	struct net_device *dev = (struct net_device *) dev_id;
++	struct mace_data *mp = netdev_priv(dev);
+ 	volatile struct mace *mb = mp->mace;
+-	u8 xmtfs, xmtrc;
++	int intr, fs;
++	unsigned int flags;
++
++	/* don't want the dma interrupt handler to fire */
++	local_irq_save(flags);
+ 
+-	xmtfs = mb->xmtfs;
+-	xmtrc = mb->xmtrc;
++	intr = mb->ir; /* read interrupt register */
++	mace_handle_misc_intrs(mp, intr);
+ 
+-	if (xmtfs & XMTSV) {
+-		if (xmtfs & UFLO) {
+-			printk("%s: DMA underrun.\n", dev->name);
+-			mp->stats.tx_errors++;
+-			mp->stats.tx_fifo_errors++;
+-			mace_txdma_reset(dev);
++	if (intr & XMTINT) {
++		fs = mb->xmtfs;
++		if ((fs & XMTSV) == 0) {
++			printk(KERN_ERR "macmace: xmtfs not valid! (fs=%x)\n", fs);
++			mace_reset(dev);
++			/*
++			 * XXX mace likes to hang the machine after a xmtfs error.
++			 * This is hard to reproduce, reseting *may* help
++			 */
+ 		}
+-		if (xmtfs & RTRY) {
+-			mp->stats.collisions++;
++		/* dma should have finished */
++		if (!mp->tx_count) {
++			printk(KERN_DEBUG "macmace: tx ring ran out? (fs=%x)\n", fs);
++		}
++		/* Update stats */
++		if (fs & (UFLO|LCOL|LCAR|RTRY)) {
++			++mp->stats.tx_errors;
++			if (fs & LCAR)
++				++mp->stats.tx_carrier_errors;
++			else if (fs & (UFLO|LCOL|RTRY)) {
++				++mp->stats.tx_aborted_errors;
++				if (mb->xmtfs & UFLO) {
++					printk(KERN_ERR "%s: DMA underrun.\n", dev->name);
++					mp->stats.tx_fifo_errors++;
++					mace_txdma_reset(dev);
++				}
++			}
+ 		}
+ 	}
+-}
+ 
+-/*
+- *	A receive interrupt occurred.
+- */
++	if (mp->tx_count)
++		netif_wake_queue(dev);
+ 
+-static void mace_recv_interrupt(struct net_device *dev)
+-{
+-/*	struct mace_data *mp = (struct mace_data *) dev->priv; */
+-//	volatile struct mace *mb = mp->mace;
+-}
++	local_irq_restore(flags);
+ 
+-/*
+- * Process the chip interrupt
+- */
++	return IRQ_HANDLED;
++}
+ 
+-static irqreturn_t mace_interrupt(int irq, void *dev_id)
++static void mace_tx_timeout(struct net_device *dev)
+ {
+-	struct net_device *dev = (struct net_device *) dev_id;
+-	struct mace_data *mp = (struct mace_data *) dev->priv;
++	struct mace_data *mp = netdev_priv(dev);
+ 	volatile struct mace *mb = mp->mace;
+-	u8 ir;
++	unsigned long flags;
+ 
+-	ir = mb->ir;
+-	mace_handle_misc_intrs(mp, ir);
++	local_irq_save(flags);
+ 
+-	if (ir & XMTINT) {
+-		mace_xmit_error(dev);
+-	}
+-	if (ir & RCVINT) {
+-		mace_recv_interrupt(dev);
+-	}
+-	return IRQ_HANDLED;
+-}
++	/* turn off both tx and rx and reset the chip */
++	mb->maccc = 0;
++	printk(KERN_ERR "macmace: transmit timeout - resetting\n");
++	mace_txdma_reset(dev);
++	mace_reset(dev);
+ 
+-static void mace_tx_timeout(struct net_device *dev)
+-{
+-/*	struct mace_data *mp = (struct mace_data *) dev->priv; */
+-//	volatile struct mace *mb = mp->mace;
++	/* restart rx dma */
++	mace_rxdma_reset(dev);
++
++	mp->tx_count = N_TX_RING;
++	netif_wake_queue(dev);
++
++	/* turn it on! */
++	mb->maccc = ENXMT | ENRCV;
++	/* enable all interrupts except receive interrupts */
++	mb->imr = RCVINT;
++
++	local_irq_restore(flags);
+ }
+ 
+ /*
+@@ -592,41 +658,40 @@ static void mace_tx_timeout(struct net_d
+ 
+ static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf)
+ {
+-	struct mace_data *mp = (struct mace_data *) dev->priv;
++	struct mace_data *mp = netdev_priv(dev);
+ 	struct sk_buff *skb;
++	unsigned int frame_status = mf->rcvsts;
+ 
+-	if (mf->status & RS_OFLO) {
+-		printk("%s: fifo overflow.\n", dev->name);
+-		mp->stats.rx_errors++;
+-		mp->stats.rx_fifo_errors++;
+-	}
+-	if (mf->status&(RS_CLSN|RS_FRAMERR|RS_FCSERR))
++	if (frame_status & (RS_OFLO | RS_CLSN | RS_FRAMERR | RS_FCSERR)) {
+ 		mp->stats.rx_errors++;
++		if (frame_status & RS_OFLO) {
++			printk(KERN_DEBUG "%s: fifo overflow.\n", dev->name);
++			mp->stats.rx_fifo_errors++;
++		}
++		if (frame_status & RS_CLSN)
++			mp->stats.collisions++;
++		if (frame_status & RS_FRAMERR)
++			mp->stats.rx_frame_errors++;
++		if (frame_status & RS_FCSERR)
++			mp->stats.rx_crc_errors++;
++	} else {
++		unsigned int frame_length = mf->rcvcnt + ((frame_status & 0x0F) << 8 );
+ 
+-	if (mf->status&RS_CLSN) {
+-		mp->stats.collisions++;
+-	}
+-	if (mf->status&RS_FRAMERR) {
+-		mp->stats.rx_frame_errors++;
+-	}
+-	if (mf->status&RS_FCSERR) {
+-		mp->stats.rx_crc_errors++;
+-	}
++		skb = dev_alloc_skb(frame_length + 2);
++		if (!skb) {
++			mp->stats.rx_dropped++;
++			return;
++		}
++		skb_reserve(skb, 2);
++		memcpy(skb_put(skb, frame_length), mf->data, frame_length);
+ 
+-	skb = dev_alloc_skb(mf->len+2);
+-	if (!skb) {
+-		mp->stats.rx_dropped++;
+-		return;
++		skb->dev = dev;
++		skb->protocol = eth_type_trans(skb, dev);
++		netif_rx(skb);
++		dev->last_rx = jiffies;
++		mp->stats.rx_packets++;
++		mp->stats.rx_bytes += frame_length;
+ 	}
+-	skb_reserve(skb,2);
+-	memcpy(skb_put(skb, mf->len), mf->data, mf->len);
+-
+-	skb->dev = dev;
+-	skb->protocol = eth_type_trans(skb, dev);
+-	netif_rx(skb);
+-	dev->last_rx = jiffies;
+-	mp->stats.rx_packets++;
+-	mp->stats.rx_bytes += mf->len;
+ }
+ 
+ /*
+@@ -636,7 +701,7 @@ static void mace_dma_rx_frame(struct net
+ static irqreturn_t mace_dma_intr(int irq, void *dev_id)
+ {
+ 	struct net_device *dev = (struct net_device *) dev_id;
+-	struct mace_data *mp = (struct mace_data *) dev->priv;
++	struct mace_data *mp = netdev_priv(dev);
+ 	int left, head;
+ 	u16 status;
+ 	u32 baka;
+@@ -663,7 +728,8 @@ static irqreturn_t mace_dma_intr(int irq
+ 		/* Loop through the ring buffer and process new packages */
+ 
+ 		while (mp->rx_tail < head) {
+-			mace_dma_rx_frame(dev, (struct mace_frame *) (mp->rx_ring + (mp->rx_tail * 0x0800)));
++			mace_dma_rx_frame(dev, (struct mace_frame*) (mp->rx_ring
++				+ (mp->rx_tail * MACE_BUFF_SIZE)));
+ 			mp->rx_tail++;
+ 		}
+ 
+@@ -690,9 +756,76 @@ static irqreturn_t mace_dma_intr(int irq
+ 		psc_write_word(PSC_ENETWR_CMD + mp->tx_sloti, 0x0100);
+ 		mp->tx_sloti ^= 0x10;
+ 		mp->tx_count++;
+-		netif_wake_queue(dev);
+ 	}
+ 	return IRQ_HANDLED;
+ }
+ 
+ MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Macintosh MACE ethernet driver");
++
++static int __devexit mac_mace_device_remove (struct platform_device *pdev)
++{
++	struct net_device *dev = platform_get_drvdata(pdev);
++	struct mace_data *mp = netdev_priv(dev);
++
++	unregister_netdev(dev);
++
++	free_irq(dev->irq, dev);
++	free_irq(IRQ_MAC_MACE_DMA, dev);
++
++	dma_free_coherent(mp->device, N_RX_RING * MACE_BUFF_SIZE,
++	                  mp->rx_ring, mp->rx_ring_phys);
++	dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE,
++	                  mp->tx_ring, mp->tx_ring_phys);
++
++	free_netdev(dev);
++
++	return 0;
++}
++
++static struct platform_driver mac_mace_driver = {
++	.probe  = mace_probe,
++	.remove = __devexit_p(mac_mace_device_remove),
++	.driver	= {
++		.name = mac_mace_string,
++	},
++};
++
++static int __init mac_mace_init_module(void)
++{
++	int err;
++
++	if ((err = platform_driver_register(&mac_mace_driver))) {
++		printk(KERN_ERR "Driver registration failed\n");
++		return err;
++	}
++
++	mac_mace_device = platform_device_alloc(mac_mace_string, 0);
++	if (!mac_mace_device)
++		goto out_unregister;
++
++	if (platform_device_add(mac_mace_device)) {
++		platform_device_put(mac_mace_device);
++		mac_mace_device = NULL;
++	}
++
++	return 0;
++
++out_unregister:
++	platform_driver_unregister(&mac_mace_driver);
++
++	return -ENOMEM;
++}
++
++static void __exit mac_mace_cleanup_module(void)
++{
++	platform_driver_unregister(&mac_mace_driver);
++
++	if (mac_mace_device) {
++		platform_device_unregister(mac_mace_device);
++		mac_mace_device = NULL;
++	}
++}
++
++module_init(mac_mace_init_module);
++module_exit(mac_mace_cleanup_module);

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-macsonic-via-alt-mapping.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-macsonic-via-alt-mapping.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,194 @@
+Subject: [PATCH 13/13] SONIC interrupt handling
+Cc: Thomas Bogendoerfer <tsbogend at alpha.franken.de>,
+    Jeff Garzik <jgarzik at pobox.com>, netdev at vger.kernel.org,
+    linux-mips at linux-mips.org
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Install the built-in macsonic interrupt handler on both IRQs when using 
+via_alt_mapping. Otherwise the rare interrupt that still comes from the 
+nubus slot will wedge the nubus.
+
+$ cat /proc/interrupts
+auto       2:      89176 via2
+auto       3:     744367 sonic
+auto       4:          0 scc
+auto       6:     318363 via1
+auto       7:          0 NMI
+mac        9:     119413 framebuffer vbl
+mac       10:       1971 ADB
+mac       14:     198517 timer
+mac       17:      89104 nubus
+mac       19:         72 Mac ESP SCSI
+mac       56:        629 sonic
+mac       62:    1142593 ide0
+
+Version 1 of this patch had a bug where a nubus sonic card would register 
+two interrupt handlers. Only a built-in sonic needs both.
+  
+Versions 2 and 3 needed some cleanups, as Raylynn Knight and Christoph 
+Hellwig pointed out (thanks).
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+---
+ drivers/net/jazzsonic.c |   23 +++++++++++++++++++----
+ drivers/net/macsonic.c  |   46 ++++++++++++++++++++++++++++++++++++++++++----
+ drivers/net/sonic.c     |   25 -------------------------
+ 3 files changed, 61 insertions(+), 33 deletions(-)
+
+--- linux-m68k-2.6.22-rc1.orig/drivers/net/jazzsonic.c
++++ linux-m68k-2.6.22-rc1/drivers/net/jazzsonic.c
+@@ -88,6 +88,23 @@ static unsigned short known_revisions[] 
+ 	0xffff			/* end of list */
+ };
+ 
++static int jazzsonic_open(struct net_device* dev)
++{
++	if (request_irq(dev->irq, &sonic_interrupt, IRQF_DISABLED, "sonic", dev)) {
++		printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
++		return -EAGAIN;
++	}
++	return sonic_open(dev);
++}
++
++static int jazzsonic_close(struct net_device* dev)
++{
++	int err;
++	err = sonic_close(dev);
++	free_irq(dev->irq, dev);
++	return err;
++}
++
+ static int __init sonic_probe1(struct net_device *dev)
+ {
+ 	static unsigned version_printed;
+@@ -169,8 +186,8 @@ static int __init sonic_probe1(struct ne
+ 	lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+ 	                     * SONIC_BUS_SCALE(lp->dma_bitmode));
+ 
+-	dev->open = sonic_open;
+-	dev->stop = sonic_close;
++	dev->open = jazzsonic_open;
++	dev->stop = jazzsonic_close;
+ 	dev->hard_start_xmit = sonic_send_packet;
+ 	dev->get_stats = sonic_get_stats;
+ 	dev->set_multicast_list = &sonic_multicast_list;
+@@ -260,8 +277,6 @@ MODULE_DESCRIPTION("Jazz SONIC ethernet 
+ module_param(sonic_debug, int, 0);
+ MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
+ 
+-#define SONIC_IRQ_FLAG IRQF_DISABLED
+-
+ #include "sonic.c"
+ 
+ static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
+--- linux-m68k-2.6.22-rc1.orig/drivers/net/macsonic.c
++++ linux-m68k-2.6.22-rc1/drivers/net/macsonic.c
+@@ -130,6 +130,46 @@ static inline void bit_reverse_addr(unsi
+ 		addr[i] = bitrev8(addr[i]);
+ }
+ 
++static irqreturn_t macsonic_interrupt(int irq, void *dev_id)
++{
++	irqreturn_t result;
++	unsigned long flags;
++
++	local_irq_save(flags);
++	result = sonic_interrupt(irq, dev_id);
++	local_irq_restore(flags);
++	return result;
++}
++
++static int macsonic_open(struct net_device* dev)
++{
++	if (request_irq(dev->irq, &sonic_interrupt, IRQ_FLG_FAST, "sonic", dev)) {
++		printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
++		return -EAGAIN;
++	}
++	/* Under the A/UX interrupt scheme, the onboard SONIC interrupt comes
++	 * in at priority level 3. However, we sometimes get the level 2 inter-
++	 * rupt as well, which must prevent re-entrance of the sonic handler.
++	 */
++	if (dev->irq == IRQ_AUTO_3)
++		if (request_irq(IRQ_NUBUS_9, &macsonic_interrupt, IRQ_FLG_FAST, "sonic", dev)) {
++			printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, IRQ_NUBUS_9);
++			free_irq(dev->irq, dev);
++			return -EAGAIN;
++		}
++	return sonic_open(dev);
++}
++
++static int macsonic_close(struct net_device* dev)
++{
++	int err;
++	err = sonic_close(dev);
++	free_irq(dev->irq, dev);
++	if (dev->irq == IRQ_AUTO_3)
++		free_irq(IRQ_NUBUS_9, dev);
++	return err;
++}
++
+ int __init macsonic_init(struct net_device* dev)
+ {
+ 	struct sonic_local* lp = netdev_priv(dev);
+@@ -160,8 +200,8 @@ int __init macsonic_init(struct net_devi
+ 	lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+ 	                     * SONIC_BUS_SCALE(lp->dma_bitmode));
+ 
+-	dev->open = sonic_open;
+-	dev->stop = sonic_close;
++	dev->open = macsonic_open;
++	dev->stop = macsonic_close;
+ 	dev->hard_start_xmit = sonic_send_packet;
+ 	dev->get_stats = sonic_get_stats;
+ 	dev->set_multicast_list = &sonic_multicast_list;
+@@ -572,8 +612,6 @@ MODULE_DESCRIPTION("Macintosh SONIC ethe
+ module_param(sonic_debug, int, 0);
+ MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");
+ 
+-#define SONIC_IRQ_FLAG IRQ_FLG_FAST
+-
+ #include "sonic.c"
+ 
+ static int __devexit mac_sonic_device_remove (struct platform_device *pdev)
+--- linux-m68k-2.6.22-rc1.orig/drivers/net/sonic.c
++++ linux-m68k-2.6.22-rc1/drivers/net/sonic.c
+@@ -50,29 +50,6 @@ static int sonic_open(struct net_device 
+ 	if (sonic_debug > 2)
+ 		printk("sonic_open: initializing sonic driver.\n");
+ 
+-	/*
+-	 * We don't need to deal with auto-irq stuff since we
+-	 * hardwire the sonic interrupt.
+-	 */
+-/*
+- * XXX Horrible work around:  We install sonic_interrupt as fast interrupt.
+- * This means that during execution of the handler interrupt are disabled
+- * covering another bug otherwise corrupting data.  This doesn't mean
+- * this glue works ok under all situations.
+- *
+- * Note (dhd): this also appears to prevent lockups on the Macintrash
+- * when more than one Ethernet card is installed (knock on wood)
+- *
+- * Note (fthain): whether the above is still true is anyones guess. Certainly
+- * the buffer handling algorithms will not tolerate re-entrance without some
+- * mutual exclusion added. Anyway, the memcpy has now been eliminated from the
+- * rx code to make this a faster "fast interrupt".
+- */
+-	if (request_irq(dev->irq, &sonic_interrupt, SONIC_IRQ_FLAG, "sonic", dev)) {
+-		printk(KERN_ERR "\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
+-		return -EAGAIN;
+-	}
+-
+ 	for (i = 0; i < SONIC_NUM_RRS; i++) {
+ 		struct sk_buff *skb = dev_alloc_skb(SONIC_RBSIZE + 2);
+ 		if (skb == NULL) {
+@@ -169,8 +146,6 @@ static int sonic_close(struct net_device
+ 		}
+ 	}
+ 
+-	free_irq(dev->irq, dev);	/* release the IRQ */
+-
+ 	return 0;
+ }
+ 

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-patch_A-mac68k_cvs_nubus_defines.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-patch_A-mac68k_cvs_nubus_defines.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,222 @@
+Subject: [PATCH 3/13] NuBus header update
+Cc: nubus-pmac-users at lists.sourceforge.net
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Sync the nubus defines with the latest code in the mac68k repo. Some of these
+are needed for DP8390 driver update in the next patch.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/net/macsonic.c |    2 
+ include/linux/nubus.h  |  126 +++++++++++++++++++++++++++++--------------------
+ 2 files changed, 76 insertions(+), 52 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/net/macsonic.c
++++ linux-m68k-2.6.21/drivers/net/macsonic.c
+@@ -402,7 +402,7 @@ int __init macsonic_ident(struct nubus_d
+ 	    ndev->dr_sw == NUBUS_DRSW_DAYNA)
+ 		return MACSONIC_DAYNA;
+ 
+-	if (ndev->dr_hw == NUBUS_DRHW_SONIC_LC &&
++	if (ndev->dr_hw == NUBUS_DRHW_APPLE_SONIC_LC &&
+ 	    ndev->dr_sw == 0) { /* huh? */
+ 		return MACSONIC_APPLE16;
+ 	}
+--- linux-m68k-2.6.21.orig/include/linux/nubus.h
++++ linux-m68k-2.6.21/include/linux/nubus.h
+@@ -28,18 +28,18 @@ enum nubus_category {
+ };
+ 
+ enum nubus_type_network {
+-	NUBUS_TYPE_ETHERNET 	 = 0x0001,
+-	NUBUS_TYPE_RS232    	 = 0x0002
++	NUBUS_TYPE_ETHERNET      = 0x0001,
++	NUBUS_TYPE_RS232         = 0x0002
+ };
+ 
+ enum nubus_type_display {
+-	NUBUS_TYPE_VIDEO 	 = 0x0001
++	NUBUS_TYPE_VIDEO         = 0x0001
+ };
+ 
+ enum nubus_type_cpu {
+-	NUBUS_TYPE_68020 	 = 0x0003,
+-	NUBUS_TYPE_68030 	 = 0x0004,
+-	NUBUS_TYPE_68040 	 = 0x0005
++	NUBUS_TYPE_68020         = 0x0003,
++	NUBUS_TYPE_68030         = 0x0004,
++	NUBUS_TYPE_68040         = 0x0005
+ };
+ 
+ /* Known <Cat,Type,SW,HW> tuples: (according to TattleTech and Slots)
+@@ -56,6 +56,7 @@ enum nubus_type_cpu {
+  *
+  *  SONIC comm-slot/on-board and DuoDock Ethernet: <4,1,1,272>
+  *  SONIC LC-PDS Ethernet (Dayna, but like Apple 16-bit, sort of): <4,1,1,271>
++ *  Apple SONIC LC-PDS Ethernet ("Apple Ethernet LC Twisted-Pair Card"): <4,1,0,281>
+  *  Sonic Systems Ethernet A-Series Card: <4,1,268,256>
+  *  Asante MacCon NuBus-A: <4,1,260,256> (alpha-1.0,1.1 revision)
+  *   ROM on the above card: <2,1,0,0>
+@@ -80,24 +81,26 @@ enum nubus_type_cpu {
+ /* Add known DrSW values here */
+ enum nubus_drsw {
+ 	/* NUBUS_CAT_DISPLAY */
+-	NUBUS_DRSW_APPLE       	= 0x0001,
+-	NUBUS_DRSW_APPLE_HIRES 	= 0x0013, /* MacII HiRes card driver */
++	NUBUS_DRSW_APPLE        = 0x0001,
++	NUBUS_DRSW_APPLE_HIRES  = 0x0013, /* MacII HiRes card driver */
+ 	
+ 	/* NUBUS_CAT_NETWORK */
+-	NUBUS_DRSW_CABLETRON   	= 0x0001,
+-	NUBUS_DRSW_SONIC_LC    	= 0x0001,
+-	NUBUS_DRSW_KINETICS    	= 0x0103,
+-	NUBUS_DRSW_ASANTE      	= 0x0104,
+-	NUBUS_DRSW_DAYNA       	= 0x010b,
+-	NUBUS_DRSW_FARALLON    	= 0x010c,
+-	NUBUS_DRSW_APPLE_SN    	= 0x010f,
+-	NUBUS_DRSW_DAYNA2	= 0x0115,
++	NUBUS_DRSW_3COM         = 0x0000,
++	NUBUS_DRSW_CABLETRON    = 0x0001,
++	NUBUS_DRSW_SONIC_LC     = 0x0001,
++	NUBUS_DRSW_KINETICS     = 0x0103,
++	NUBUS_DRSW_ASANTE       = 0x0104,
++	NUBUS_DRSW_TECHWORKS    = 0x0109,
++	NUBUS_DRSW_DAYNA        = 0x010b,
++	NUBUS_DRSW_FARALLON     = 0x010c,
++	NUBUS_DRSW_APPLE_SN     = 0x010f,
++	NUBUS_DRSW_DAYNA2       = 0x0115,
+ 	NUBUS_DRSW_FOCUS        = 0x011a,
+ 	NUBUS_DRSW_ASANTE_CS    = 0x011d, /* use asante SMC9194 driver */
+-	NUBUS_DRSW_DAYNA_LC	= 0x011e,
++	NUBUS_DRSW_DAYNA_LC     = 0x011e,
+ 
+ 	/* NUBUS_CAT_CPU */
+-	NUBUS_DRSW_NONE        	= 0x0000,
++	NUBUS_DRSW_NONE         = 0x0000,
+ };
+ 
+ /* DrHW: Uniquely identifies the hardware interface to a board (or at
+@@ -107,27 +110,48 @@ enum nubus_drsw {
+ /* Add known DrHW values here */
+ enum nubus_drhw {
+ 	/* NUBUS_CAT_DISPLAY */
+-	NUBUS_DRHW_APPLE_TFB	= 0x0001, /* Toby frame buffer card */
+-	NUBUS_DRHW_APPLE_HRVC	= 0x0013, /* Mac II High Res Video card */
+-	NUBUS_DRHW_APPLE_RBV1   = 0x0018, /* IIci RBV video */
+-	NUBUS_DRHW_APPLE_MDC    = 0x0019, /* Macintosh Display Card */
+-	NUBUS_DRHW_APPLE_SONORA = 0x0022, /* Sonora built-in video */
+-	NUBUS_DRHW_APPLE_JET 	= 0x0029, /* Jet framebuffer (DuoDock) */
++	NUBUS_DRHW_APPLE_TFB      = 0x0001, /* Toby frame buffer card */
++	NUBUS_DRHW_APPLE_WVC      = 0x0006, /* Apple Workstation Video Card */
++	NUBUS_DRHW_SIGMA_CLRMAX   = 0x0007, /* Sigma Design ColorMax */
++	NUBUS_DRHW_APPLE_SE30     = 0x0009, /* Apple SE/30 video */
++	NUBUS_DRHW_APPLE_HRVC     = 0x0013, /* Mac II High-Res Video Card */
++	NUBUS_DRHW_APPLE_PVC      = 0x0017, /* Mac II Portrait Video Card */
++	NUBUS_DRHW_APPLE_RBV1     = 0x0018, /* IIci RBV video */
++	NUBUS_DRHW_APPLE_MDC      = 0x0019, /* Macintosh Display Card */
++	NUBUS_DRHW_APPLE_SONORA   = 0x0022, /* Sonora built-in video */
++	NUBUS_DRHW_APPLE_24AC     = 0x002b, /* Mac 24AC Video Card */
+ 	NUBUS_DRHW_APPLE_VALKYRIE = 0x002e,
+-	NUBUS_DRHW_THUNDER24	= 0x02cb, /* SuperMac Thunder/24 */
++	NUBUS_DRHW_APPLE_JET      = 0x0029, /* Jet framebuffer (DuoDock) */
++	NUBUS_DRHW_SMAC_GFX       = 0x0105, /* SuperMac GFX */
++	NUBUS_DRHW_RASTER_CB264   = 0x013B, /* RasterOps ColorBoard 264 */
++	NUBUS_DRHW_MICRON_XCEED   = 0x0146, /* Micron Exceed color */
++	NUBUS_DRHW_RDIUS_GSC      = 0x0153, /* Radius GS/C */
++	NUBUS_DRHW_SMAC_SPEC8     = 0x017B, /* SuperMac Spectrum/8 */
++	NUBUS_DRHW_SMAC_SPEC24    = 0x017C, /* SuperMac Spectrum/24 */
++	NUBUS_DRHW_RASTER_CB364   = 0x026F, /* RasterOps ColorBoard 364 */
++	NUBUS_DRHW_RDIUS_DCGX     = 0x027C, /* Radius DirectColor/GX */
++	NUBUS_DRHW_RDIUS_PC8      = 0x0291, /* Radius PrecisionColor 8 */
++	NUBUS_DRHW_LAPIS_PCS8     = 0x0292, /* Lapis ProColorServer 8 */
++	NUBUS_DRHW_RASTER_24LXI   = 0x02A0, /* RasterOps 8/24 XLi */
++	NUBUS_DRHW_RASTER_PBPGT   = 0x02A5, /* RasterOps PaintBoard Prism GT */
++	NUBUS_DRHW_EMACH_FSX      = 0x02AE, /* E-Machines Futura SX */
++	NUBUS_DRHW_SMAC_THUND24   = 0x02CB, /* SuperMac Thunder/24 */
++	NUBUS_DRHW_RDIUS_PC24XP   = 0x0406, /* Radius PrecisionColor 24Xp */
++	NUBUS_DRHW_RDIUS_PC24X    = 0x040A, /* Radius PrecisionColor 24X */
++	NUBUS_DRHW_RDIUS_PC8XJ    = 0x040B, /* Radius PrecisionColor 8XJ */
+ 	
+ 	/* NUBUS_CAT_NETWORK */
+-	NUBUS_DRHW_INTERLAN     = 0x0100,
+-	NUBUS_DRHW_SMC9194      = 0x0101,
+-	NUBUS_DRHW_KINETICS     = 0x0106,
+-	NUBUS_DRHW_CABLETRON    = 0x0109,
+-	NUBUS_DRHW_ASANTE_LC    = 0x010f,
+-	NUBUS_DRHW_SONIC        = 0x0110,
+-	NUBUS_DRHW_SONIC_NB	= 0x0118,
+-	NUBUS_DRHW_SONIC_LC	= 0x0119,
+-	
+-	/* NUBUS_CAT_COMMUNICATIONS */
+-	NUBUS_DRHW_DOVEFAX	= 0x0100,
++	NUBUS_DRHW_INTERLAN       = 0x0100,
++	NUBUS_DRHW_SMC9194        = 0x0101,
++	NUBUS_DRHW_KINETICS       = 0x0106,
++	NUBUS_DRHW_CABLETRON      = 0x0109,
++	NUBUS_DRHW_ASANTE_LC      = 0x010f,
++	NUBUS_DRHW_SONIC          = 0x0110,
++	NUBUS_DRHW_TECHWORKS      = 0x0112,
++	NUBUS_DRHW_APPLE_SONIC_NB = 0x0118,
++	NUBUS_DRHW_APPLE_SONIC_LC = 0x0119,
++	NUBUS_DRHW_FOCUS          = 0x011c,
++	NUBUS_DRHW_SONNET         = 0x011d,
+ };
+ 
+ /* Resource IDs: These are the identifiers for the various weird and
+@@ -153,17 +177,17 @@ enum nubus_res_id {
+ 
+ /* Category-specific resources. */
+ enum nubus_board_res_id {
+-	NUBUS_RESID_BOARDID	 = 0x0020,
++	NUBUS_RESID_BOARDID      = 0x0020,
+ 	NUBUS_RESID_PRAMINITDATA = 0x0021,
+-	NUBUS_RESID_PRIMARYINIT	 = 0x0022,
++	NUBUS_RESID_PRIMARYINIT  = 0x0022,
+ 	NUBUS_RESID_TIMEOUTCONST = 0x0023,
+-	NUBUS_RESID_VENDORINFO	 = 0x0024,
+-	NUBUS_RESID_BOARDFLAGS	 = 0x0025,
+-	NUBUS_RESID_SECONDINIT	 = 0x0026,
++	NUBUS_RESID_VENDORINFO   = 0x0024,
++	NUBUS_RESID_BOARDFLAGS   = 0x0025,
++	NUBUS_RESID_SECONDINIT   = 0x0026,
+ 
+ 	/* Not sure why Apple put these next two in here */
+-	NUBUS_RESID_VIDNAMES 	 = 0x0041,
+-	NUBUS_RESID_VIDMODES 	 = 0x007e
++	NUBUS_RESID_VIDNAMES     = 0x0041,
++	NUBUS_RESID_VIDMODES     = 0x007e
+ };
+ 
+ /* Fields within the vendor info directory */
+@@ -185,13 +209,13 @@ enum nubus_cpu_res_id {
+ };
+ 
+ enum nubus_display_res_id {
+-	NUBUS_RESID_GAMMADIR	= 0x0040,
+-	NUBUS_RESID_FIRSTMODE	= 0x0080,
+-	NUBUS_RESID_SECONDMODE	= 0x0081,
+-	NUBUS_RESID_THIRDMODE	= 0x0082,
+-	NUBUS_RESID_FOURTHMODE	= 0x0083,
+-	NUBUS_RESID_FIFTHMODE	= 0x0084,
+-	NUBUS_RESID_SIXTHMODE	= 0x0085
++	NUBUS_RESID_GAMMADIR    = 0x0040,
++	NUBUS_RESID_FIRSTMODE   = 0x0080,
++	NUBUS_RESID_SECONDMODE  = 0x0081,
++	NUBUS_RESID_THIRDMODE   = 0x0082,
++	NUBUS_RESID_FOURTHMODE  = 0x0083,
++	NUBUS_RESID_FIFTHMODE   = 0x0084,
++	NUBUS_RESID_SIXTHMODE   = 0x0085
+ };
+ 
+ struct nubus_dir
+@@ -214,7 +238,7 @@ struct nubus_board {
+ 	struct nubus_board* next;
+ 	struct nubus_dev* first_dev;
+ 	
+-        /* Only 9-E actually exist, though 0-8 are also theoretically
++	/* Only 9-E actually exist, though 0-8 are also theoretically
+ 	   possible, and 0 is a special case which represents the
+ 	   motherboard and onboard peripherals (Ethernet, video) */
+ 	int slot;

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-patch_B-mac68k_cvs_DP8390_update.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-patch_B-mac68k_cvs_DP8390_update.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,398 @@
+Subject: [PATCH 4/13] m68k: Mac DP8390 update
+Cc: Jeff Garzik <jgarzik at pobox.com>, netdev at vger.kernel.org
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Fix the support for C/NET nubus ethernet cards etc. Sync up the DP8390 driver
+with the latest code in the mac68k repo.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/net/mac8390.c |  245 +++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 175 insertions(+), 70 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/net/mac8390.c
++++ linux-m68k-2.6.21/drivers/net/mac8390.c
+@@ -14,6 +14,8 @@
+ /* 2001-05-15: support for Cabletron ported from old daynaport driver
+  * and fixed access to Sonic Sys card which masquerades as a Farallon
+  * by rayk at knightsmanor.org */
++/* 2002-12-30: Try to support more cards, some clues from NetBSD driver */
++/* 2003-12-26: Make sure Asante cards always work. */
+ 
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+@@ -61,25 +63,21 @@ static char version[] =
+ #define DAYNA_8390_BASE		0x80000
+ #define DAYNA_8390_MEM		0x00000
+ 
+-#define KINETICS_8390_BASE	0x80000
+-#define KINETICS_8390_MEM	0x00000
+-
+ #define CABLETRON_8390_BASE	0x90000
+ #define CABLETRON_8390_MEM	0x00000
+ 
++#define INTERLAN_8390_BASE	0xE0000
++#define INTERLAN_8390_MEM	0xD0000
++
+ enum mac8390_type {
+ 	MAC8390_NONE = -1,
+ 	MAC8390_APPLE,
+ 	MAC8390_ASANTE,
+-	MAC8390_FARALLON,  /* Apple, Asante, and Farallon are all compatible */
++	MAC8390_FARALLON,
+ 	MAC8390_CABLETRON,
+ 	MAC8390_DAYNA,
+ 	MAC8390_INTERLAN,
+ 	MAC8390_KINETICS,
+-	MAC8390_FOCUS,
+-	MAC8390_SONICSYS,
+-	MAC8390_DAYNA2,
+-	MAC8390_DAYNA3,
+ };
+ 
+ static const char * cardname[] = {
+@@ -90,10 +88,6 @@ static const char * cardname[] = {
+ 	"dayna",
+ 	"interlan",
+ 	"kinetics",
+-	"focus",
+-	"sonic systems",
+-	"dayna2",
+-	"dayna_lc",
+ };
+ 
+ static int word16[] = {
+@@ -104,10 +98,6 @@ static int word16[] = {
+ 	0, /* dayna */
+ 	1, /* interlan */
+ 	0, /* kinetics */
+-	1, /* focus (??) */
+-	1, /* sonic systems  */
+-	1, /* dayna2 */
+-	1, /* dayna-lc */
+ };
+ 
+ /* on which cards do we use NuBus resources? */
+@@ -119,10 +109,12 @@ static int useresources[] = {
+ 	0, /* dayna */
+ 	0, /* interlan */
+ 	0, /* kinetics */
+-	0, /* focus (??) */
+-	1, /* sonic systems */
+-	1, /* dayna2 */
+-	1, /* dayna-lc */
++};
++
++enum mac8390_access {
++	ACCESS_UNKNOWN = 0,
++	ACCESS_32,
++	ACCESS_16,
+ };
+ 
+ extern enum mac8390_type mac8390_ident(struct nubus_dev * dev);
+@@ -134,8 +126,9 @@ static int mac8390_initdev(struct net_de
+ static int mac8390_open(struct net_device * dev);
+ static int mac8390_close(struct net_device * dev);
+ static void mac8390_no_reset(struct net_device *dev);
++static void interlan_reset(struct net_device *dev);
+ 
+-/* Sane (32-bit chunk memory read/write) - Apple/Asante/Farallon do this*/
++/* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/
+ static void sane_get_8390_hdr(struct net_device *dev,
+ 			      struct e8390_pkt_hdr *hdr, int ring_page);
+ static void sane_block_input(struct net_device * dev, int count,
+@@ -172,23 +165,93 @@ static void word_memcpy_fromcard(void *t
+ 
+ enum mac8390_type __init mac8390_ident(struct nubus_dev * dev)
+ {
+-	if (dev->dr_sw == NUBUS_DRSW_ASANTE)
+-		return MAC8390_ASANTE;
+-	if (dev->dr_sw == NUBUS_DRSW_FARALLON)
+-		return MAC8390_FARALLON;
+-	if (dev->dr_sw == NUBUS_DRSW_KINETICS)
+-		return MAC8390_KINETICS;
+-	if (dev->dr_sw == NUBUS_DRSW_DAYNA)
+-		return MAC8390_DAYNA;
+-	if (dev->dr_sw == NUBUS_DRSW_DAYNA2)
+-		return MAC8390_DAYNA2;
+-	if (dev->dr_sw == NUBUS_DRSW_DAYNA_LC)
+-		return MAC8390_DAYNA3;
+-	if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
+-		return MAC8390_CABLETRON;
++	switch (dev->dr_sw) {
++		case NUBUS_DRSW_3COM:
++			switch (dev->dr_hw) {
++				case NUBUS_DRHW_APPLE_SONIC_NB:
++				case NUBUS_DRHW_APPLE_SONIC_LC:
++				case NUBUS_DRHW_SONNET:
++					return MAC8390_NONE;
++					break;
++				default:
++					return MAC8390_APPLE;
++					break;
++			}
++			break;
++
++		case NUBUS_DRSW_APPLE:
++			switch (dev->dr_hw) {
++				case NUBUS_DRHW_ASANTE_LC:
++					return MAC8390_NONE;
++					break;
++				case NUBUS_DRHW_CABLETRON:
++					return MAC8390_CABLETRON;
++					break;
++				default:
++					return MAC8390_APPLE;
++					break;
++			}
++			break;
++
++		case NUBUS_DRSW_ASANTE:
++			return MAC8390_ASANTE;
++			break;
++
++		case NUBUS_DRSW_TECHWORKS:
++		case NUBUS_DRSW_DAYNA2:
++		case NUBUS_DRSW_DAYNA_LC:
++			if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
++				return MAC8390_CABLETRON;
++			else
++				return MAC8390_APPLE;
++			break;
++
++		case NUBUS_DRSW_FARALLON:
++			return MAC8390_FARALLON;
++			break;
++
++		case NUBUS_DRSW_KINETICS:
++			switch (dev->dr_hw) {
++				case NUBUS_DRHW_INTERLAN:
++					return MAC8390_INTERLAN;
++					break;
++				default:
++					return MAC8390_KINETICS;
++					break;
++			}
++			break;
++
++		case NUBUS_DRSW_DAYNA:
++			// These correspond to Dayna Sonic cards
++			// which use the macsonic driver
++			if (dev->dr_hw == NUBUS_DRHW_SMC9194 ||
++				dev->dr_hw == NUBUS_DRHW_INTERLAN )
++				return MAC8390_NONE;
++			else
++				return MAC8390_DAYNA;
++			break;
++	}
+ 	return MAC8390_NONE;
+ }
+ 
++enum mac8390_access __init mac8390_testio(volatile unsigned long membase)
++{
++	unsigned long outdata = 0xA5A0B5B0;
++	unsigned long indata =  0x00000000;
++	/* Try writing 32 bits */
++	memcpy((char *)membase, (char *)&outdata, 4);
++	/* Now compare them */
++	if (memcmp((char *)&outdata, (char *)membase, 4) == 0)
++		return ACCESS_32;
++	/* Write 16 bit output */
++	word_memcpy_tocard((char *)membase, (char *)&outdata, 4);
++	/* Now read it back */
++	word_memcpy_fromcard((char *)&indata, (char *)membase, 4);
++	if (outdata == indata)
++		return ACCESS_16;
++	return ACCESS_UNKNOWN;
++}
++
+ int __init mac8390_memsize(unsigned long membase)
+ {
+ 	unsigned long flags;
+@@ -287,14 +350,6 @@ struct net_device * __init mac8390_probe
+ 			continue;
+ 		} else {
+ 			nubus_get_rsrc_mem(dev->dev_addr, &ent, 6);
+-			/* Some Sonic Sys cards masquerade as Farallon */
+-			if (cardtype == MAC8390_FARALLON &&
+-					dev->dev_addr[0] == 0x0 &&
+-					dev->dev_addr[1] == 0x40 &&
+-					dev->dev_addr[2] == 0x10) {
+-				/* This is really Sonic Sys card */
+-				cardtype = MAC8390_SONICSYS;
+-			}
+ 		}
+ 
+ 		if (useresources[cardtype] == 1) {
+@@ -334,6 +389,17 @@ struct net_device * __init mac8390_probe
+ 						dev->mem_start +
+ 						mac8390_memsize(dev->mem_start);
+ 					break;
++				case MAC8390_INTERLAN:
++					dev->base_addr =
++						(int)(ndev->board->slot_addr +
++						INTERLAN_8390_BASE);
++					dev->mem_start =
++						(int)(ndev->board->slot_addr +
++						INTERLAN_8390_MEM);
++					dev->mem_end =
++						dev->mem_start +
++						mac8390_memsize(dev->mem_start);
++					break;
+ 				case MAC8390_CABLETRON:
+ 					dev->base_addr =
+ 						(int)(ndev->board->slot_addr +
+@@ -356,8 +422,8 @@ struct net_device * __init mac8390_probe
+ 
+ 				default:
+ 					printk(KERN_ERR "Card type %s is"
+-							" unsupported, sorry\n",
+-					       cardname[cardtype]);
++					       " unsupported, sorry\n",
++					       ndev->board->name);
+ 					continue;
+ 			}
+ 		}
+@@ -438,7 +504,7 @@ static int __init mac8390_initdev(struct
+ 		24,    26,     28,     30
+ 	};
+ 
+-	int access_bitmode;
++	int access_bitmode = 0;
+ 
+ 	/* Now fill in our stuff */
+ 	dev->open = &mac8390_open;
+@@ -468,29 +534,47 @@ static int __init mac8390_initdev(struct
+ 
+ 	/* Fill in model-specific information and functions */
+ 	switch(type) {
+-	case MAC8390_SONICSYS:
+-		/* 16 bit card, register map is reversed */
+-		ei_status.reset_8390 = &mac8390_no_reset;
+-		ei_status.block_input = &slow_sane_block_input;
+-		ei_status.block_output = &slow_sane_block_output;
+-		ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+-		ei_status.reg_offset = back4_offsets;
+-		access_bitmode = 0;
+-		break;
+ 	case MAC8390_FARALLON:
+ 	case MAC8390_APPLE:
++		switch(mac8390_testio(dev->mem_start)) {
++			case ACCESS_UNKNOWN:
++				printk("Don't know how to access card memory!\n");
++				return -ENODEV;
++				break;
++
++			case ACCESS_16:
++				/* 16 bit card, register map is reversed */
++				ei_status.reset_8390 = &mac8390_no_reset;
++				ei_status.block_input = &slow_sane_block_input;
++				ei_status.block_output = &slow_sane_block_output;
++				ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
++				ei_status.reg_offset = back4_offsets;
++				break;
++
++			case ACCESS_32:
++				/* 32 bit card, register map is reversed */
++				ei_status.reset_8390 = &mac8390_no_reset;
++				ei_status.block_input = &sane_block_input;
++				ei_status.block_output = &sane_block_output;
++				ei_status.get_8390_hdr = &sane_get_8390_hdr;
++				ei_status.reg_offset = back4_offsets;
++				access_bitmode = 1;
++				break;
++		}
++		break;
++
+ 	case MAC8390_ASANTE:
+-	case MAC8390_DAYNA2:
+-	case MAC8390_DAYNA3:
+-		/* 32 bit card, register map is reversed */
+-		/* sane */
++		/* Some Asante cards pass the 32 bit test
++		 * but overwrite system memory when run at 32 bit.
++		 * so we run them all at 16 bit.
++		 */
+ 		ei_status.reset_8390 = &mac8390_no_reset;
+-		ei_status.block_input = &sane_block_input;
+-		ei_status.block_output = &sane_block_output;
+-		ei_status.get_8390_hdr = &sane_get_8390_hdr;
++		ei_status.block_input = &slow_sane_block_input;
++		ei_status.block_output = &slow_sane_block_output;
++		ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+ 		ei_status.reg_offset = back4_offsets;
+-		access_bitmode = 1;
+ 		break;
++
+ 	case MAC8390_CABLETRON:
+ 		/* 16 bit card, register map is short forward */
+ 		ei_status.reset_8390 = &mac8390_no_reset;
+@@ -498,21 +582,30 @@ static int __init mac8390_initdev(struct
+ 		ei_status.block_output = &slow_sane_block_output;
+ 		ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+ 		ei_status.reg_offset = fwrd2_offsets;
+-		access_bitmode = 0;
+ 		break;
++
+ 	case MAC8390_DAYNA:
+ 	case MAC8390_KINETICS:
+-		/* 16 bit memory */
++		/* 16 bit memory, register map is forward */
+ 		/* dayna and similar */
+ 		ei_status.reset_8390 = &mac8390_no_reset;
+ 		ei_status.block_input = &dayna_block_input;
+ 		ei_status.block_output = &dayna_block_output;
+ 		ei_status.get_8390_hdr = &dayna_get_8390_hdr;
+ 		ei_status.reg_offset = fwrd4_offsets;
+-		access_bitmode = 0;
+ 		break;
++
++	case MAC8390_INTERLAN:
++		/* 16 bit memory, register map is forward */
++		ei_status.reset_8390 = &interlan_reset;
++		ei_status.block_input = &slow_sane_block_input;
++		ei_status.block_output = &slow_sane_block_output;
++		ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
++	        ei_status.reg_offset = fwrd4_offsets;
++	        break;
++
+ 	default:
+-		printk(KERN_ERR "Card type %s is unsupported, sorry\n", cardname[type]);
++		printk(KERN_ERR "Card type %s is unsupported, sorry\n", ndev->board->name);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -530,9 +623,9 @@ static int __init mac8390_initdev(struct
+ 				printk(":");
+ 		}
+ 	}
+-	printk(" IRQ %d, shared memory at %#lx-%#lx,  %d-bit access.\n",
+-		   dev->irq, dev->mem_start, dev->mem_end-1,
+-		   access_bitmode?32:16);
++	printk(" IRQ %d, %d KB shared memory at %#lx,  %d-bit access.\n",
++		   dev->irq, (int)((dev->mem_end - dev->mem_start)/0x1000) * 4,
++		   dev->mem_start, access_bitmode?32:16);
+ 	return 0;
+ }
+ 
+@@ -561,6 +654,18 @@ static void mac8390_no_reset(struct net_
+ 	return;
+ }
+ 
++static void interlan_reset(struct net_device *dev)
++{
++	unsigned char *target=nubus_slot_addr(IRQ2SLOT(dev->irq));
++	if (ei_debug > 1)
++		printk("Need to reset the NS8390 t=%lu...", jiffies);
++	ei_status.txing = 0;
++	target[0xC0000] = 0;
++	if (ei_debug > 1)
++		printk("reset complete\n");
++	return;
++}
++
+ /* dayna_memcpy_fromio/dayna_memcpy_toio */
+ /* directly from daynaport.c by Alan Cox */
+ static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count)

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-patch_d-via-alt-mapping.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-patch_d-via-alt-mapping.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,30 @@
+Subject: [PATCH 2/13] m68k: Mac interrupt priorities
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Add some more machines that support A/UX interrupt priorities. There are
+probably others as well, but I've only tested these ones so far.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/mac/via.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/via.c
++++ linux-m68k-2.6.21/arch/m68k/mac/via.c
+@@ -193,8 +193,14 @@ void __init via_init(void)
+ 	/* that the IIfx emulates this alternate mapping using the OSS. */
+ 
+ 	switch(macintosh_config->ident) {
++		case MAC_MODEL_P475:
++		case MAC_MODEL_P475F:
++		case MAC_MODEL_P575:
++		case MAC_MODEL_Q605:
++		case MAC_MODEL_Q605_ACC:
+ 		case MAC_MODEL_C610:
+ 		case MAC_MODEL_Q610:
++		case MAC_MODEL_Q630:
+ 		case MAC_MODEL_C650:
+ 		case MAC_MODEL_Q650:
+ 		case MAC_MODEL_Q700:

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-remove-unused-adb-header.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-remove-unused-adb-header.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,92 @@
+Subject: [PATCH 1/13] m68k: remove unused adb.h
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+The asm-m68k/adb.h header is unused. Some definitions are wrong and the rest
+are duplicated in linux/adb.h. Remove it.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+
+---
+ include/asm-m68k/adb.h |   75 -------------------------------------------------
+ 1 file changed, 75 deletions(-)
+
+--- linux-m68k-2.6.21.orig/include/asm-m68k/adb.h
++++ /dev/null
+@@ -1,75 +0,0 @@
+-/*
+- * Definitions for talking to ADB and CUDA.  The CUDA is a microcontroller
+- * which controls the ADB, system power, RTC, and various other things on
+- * later Macintoshes
+- *
+- * Copyright (C) 1996 Paul Mackerras.
+- */
+-
+-/* First byte sent to or received from CUDA */
+-#define ADB_PACKET	0
+-#define CUDA_PACKET	1
+-#define ERROR_PACKET	2
+-#define TIMER_PACKET	3
+-#define POWER_PACKET	4
+-#define MACIIC_PACKET	5
+-
+-/* ADB commands (2nd byte) */
+-#define ADB_BUSRESET		0
+-#define ADB_FLUSH(id)		(1 + ((id) << 4))
+-#define ADB_WRITEREG(id, reg)	(8 + (reg) + ((id) << 4))
+-#define ADB_READREG(id, reg)	(0xc + (reg) + ((id) << 4))
+-
+-/* ADB default device IDs (upper 4 bits of 2nd byte) */
+-#define ADB_DONGLE	1	/* "software execution control" devices */
+-#define ADB_KEYBOARD	2
+-#define ADB_MOUSE	3
+-#define ADB_TABLET	4
+-#define ADB_MODEM	5
+-#define ADB_MISC	7	/* maybe a monitor */
+-
+-/* CUDA commands (2nd byte) */
+-#define CUDA_WARM_START		0
+-#define CUDA_AUTOPOLL		1
+-#define CUDA_GET_6805_ADDR	2
+-#define CUDA_GET_TIME		3
+-#define CUDA_GET_PRAM		7
+-#define CUDA_SET_6805_ADDR	8
+-#define CUDA_SET_TIME		9
+-#define CUDA_POWERDOWN		0xa
+-#define CUDA_POWERUP_TIME	0xb
+-#define CUDA_SET_PRAM		0xc
+-#define CUDA_MS_RESET		0xd
+-#define CUDA_SEND_DFAC		0xe
+-#define CUDA_RESET_SYSTEM	0x11
+-#define CUDA_SET_IPL		0x12
+-#define CUDA_SET_AUTO_RATE	0x14
+-#define CUDA_GET_AUTO_RATE	0x16
+-#define CUDA_SET_DEVICE_LIST	0x19
+-#define CUDA_GET_DEVICE_LIST	0x1a
+-#define CUDA_GET_SET_IIC	0x22
+-
+-#ifdef __KERNEL__
+-
+-struct adb_request {
+-    unsigned char data[16];
+-    int nbytes;
+-    unsigned char reply[16];
+-    int reply_len;
+-    unsigned char reply_expected;
+-    unsigned char sent;
+-    unsigned char got_reply;
+-    void (*done)(struct adb_request *);
+-    void *arg;
+-    struct adb_request *next;
+-};
+-
+-void via_adb_init(void);
+-int adb_request(struct adb_request *req,
+-		 void (*done)(struct adb_request *), int nbytes, ...);
+-int adb_send_request(struct adb_request *req);
+-void adb_poll(void);
+-int adb_register(int default_id,
+-		 void (*handler)(unsigned char *, int, struct pt_regs *));
+-
+-#endif	/* __KERNEL */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-revert-remaining-irq-damage.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-revert-remaining-irq-damage.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,80 @@
+Subject: [PATCH 5/13] m68k: reverse Mac IRQ damage
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Reverse the last of a monumental brown-paper-bag commit that went into the 2.3
+kernel.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/mac/baboon.c |    2 +-
+ arch/m68k/mac/oss.c    |    6 +++---
+ arch/m68k/mac/psc.c    |    2 +-
+ arch/m68k/mac/via.c    |    2 +-
+ 4 files changed, 6 insertions(+), 6 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/baboon.c
++++ linux-m68k-2.6.21/arch/m68k/mac/baboon.c
+@@ -81,9 +81,9 @@ irqreturn_t baboon_irq(int irq, void *de
+ 	for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) {
+ 	        if (events & irq_bit/* & baboon_active*/) {
+ 			baboon_active &= ~irq_bit;
++			baboon->mb_ifr &= ~irq_bit;
+ 			m68k_handle_int(IRQ_BABOON_0 + i);
+ 			baboon_active |= irq_bit;
+-			baboon->mb_ifr &= ~irq_bit;
+ 		}
+ 	}
+ #if 0
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/oss.c
++++ linux-m68k-2.6.21/arch/m68k/mac/oss.c
+@@ -109,12 +109,12 @@ irqreturn_t oss_irq(int irq, void *dev_i
+ 	/* FIXME: how do you clear a pending IRQ?    */
+ 
+ 	if (events & OSS_IP_SOUND) {
+-		/* FIXME: call sound handler */
+ 		oss->irq_pending &= ~OSS_IP_SOUND;
++		/* FIXME: call sound handler */
+ 	} else if (events & OSS_IP_SCSI) {
+ 		oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED;
+-		m68k_handle_int(IRQ_MAC_SCSI);
+ 		oss->irq_pending &= ~OSS_IP_SCSI;
++		m68k_handle_int(IRQ_MAC_SCSI);
+ 		oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
+ 	} else {
+ 		/* FIXME: error check here? */
+@@ -146,8 +146,8 @@ irqreturn_t oss_nubus_irq(int irq, void 
+ 	for (i = 0, irq_bit = 1 ; i < 6 ; i++, irq_bit <<= 1) {
+ 		if (events & irq_bit) {
+ 			oss->irq_level[i] = OSS_IRQLEV_DISABLED;
+-			m68k_handle_int(NUBUS_SOURCE_BASE + i);
+ 			oss->irq_pending &= ~irq_bit;
++			m68k_handle_int(NUBUS_SOURCE_BASE + i);
+ 			oss->irq_level[i] = OSS_IRQLEV_NUBUS;
+ 		}
+ 	}
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/psc.c
++++ linux-m68k-2.6.21/arch/m68k/mac/psc.c
+@@ -149,8 +149,8 @@ irqreturn_t psc_irq(int irq, void *dev_i
+ 	for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) {
+ 	        if (events & irq_bit) {
+ 			psc_write_byte(pIER, irq_bit);
+-			m68k_handle_int(base_irq + i);
+ 			psc_write_byte(pIFR, irq_bit);
++			m68k_handle_int(base_irq + i);
+ 			psc_write_byte(pIER, irq_bit | 0x80);
+ 		}
+ 	}
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/via.c
++++ linux-m68k-2.6.21/arch/m68k/mac/via.c
+@@ -430,8 +430,8 @@ irqreturn_t via1_irq(int irq, void *dev_
+ 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
+ 		if (events & irq_bit) {
+ 			via1[vIER] = irq_bit;
+-			m68k_handle_int(VIA1_SOURCE_BASE + i);
+ 			via1[vIFR] = irq_bit;
++			m68k_handle_int(VIA1_SOURCE_BASE + i);
+ 			via1[vIER] = irq_bit | 0x80;
+ 		}
+ 

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-sonic-fixes.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/mac68k-sonic-fixes.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,106 @@
+Subject: [PATCH 12/13] SONIC: small fix and cleanup
+Cc: Thomas Bogendoerfer <tsbogend at alpha.franken.de>,
+    Jeff Garzik <jgarzik at pobox.com>, netdev at vger.kernel.org,
+    linux-mips at linux-mips.org
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Fix a potential problem in the timeout handling: don't free the DMA buffers
+before resetting the chip.
+
+Also a trivial cleanup. Bring macsonic and jazzsonic into sync.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/net/jazzsonic.c |    4 ++--
+ drivers/net/macsonic.c  |   17 ++++++++---------
+ drivers/net/sonic.c     |    7 ++++++-
+ 3 files changed, 16 insertions(+), 12 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/net/jazzsonic.c
++++ linux-m68k-2.6.21/drivers/net/jazzsonic.c
+@@ -269,11 +269,11 @@ static int __devexit jazz_sonic_device_r
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct sonic_local* lp = netdev_priv(dev);
+ 
+-	unregister_netdev (dev);
++	unregister_netdev(dev);
+ 	dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+ 	                  lp->descriptors, lp->descriptors_laddr);
+ 	release_region (dev->base_addr, SONIC_MEM_SIZE);
+-	free_netdev (dev);
++	free_netdev(dev);
+ 
+ 	return 0;
+ }
+--- linux-m68k-2.6.21.orig/drivers/net/macsonic.c
++++ linux-m68k-2.6.21/drivers/net/macsonic.c
+@@ -522,7 +522,7 @@ int __init mac_nubus_sonic_probe(struct 
+ 	return macsonic_init(dev);
+ }
+ 
+-static int __init mac_sonic_probe(struct platform_device *device)
++static int __init mac_sonic_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct sonic_local *lp;
+@@ -534,8 +534,8 @@ static int __init mac_sonic_probe(struct
+ 		return -ENOMEM;
+ 
+ 	lp = netdev_priv(dev);
+-	lp->device = &device->dev;
+-	SET_NETDEV_DEV(dev, &device->dev);
++	lp->device = &pdev->dev;
++	SET_NETDEV_DEV(dev, &pdev->dev);
+  	SET_MODULE_OWNER(dev);
+ 
+ 	/* This will catch fatal stuff like -ENOMEM as well as success */
+@@ -576,15 +576,15 @@ MODULE_PARM_DESC(sonic_debug, "macsonic 
+ 
+ #include "sonic.c"
+ 
+-static int __devexit mac_sonic_device_remove (struct platform_device *device)
++static int __devexit mac_sonic_device_remove (struct platform_device *pdev)
+ {
+-	struct net_device *dev = platform_get_drvdata(device);
++	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct sonic_local* lp = netdev_priv(dev);
+ 
+-	unregister_netdev (dev);
++	unregister_netdev(dev);
+ 	dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+ 	                  lp->descriptors, lp->descriptors_laddr);
+-	free_netdev (dev);
++	free_netdev(dev);
+ 
+ 	return 0;
+ }
+@@ -607,9 +607,8 @@ static int __init mac_sonic_init_module(
+ 	}
+ 
+ 	mac_sonic_device = platform_device_alloc(mac_sonic_string, 0);
+-	if (!mac_sonic_device) {
++	if (!mac_sonic_device)
+ 		goto out_unregister;
+-	}
+ 
+ 	if (platform_device_add(mac_sonic_device)) {
+ 		platform_device_put(mac_sonic_device);
+--- linux-m68k-2.6.21.orig/drivers/net/sonic.c
++++ linux-m68k-2.6.21/drivers/net/sonic.c
+@@ -179,8 +179,13 @@ static void sonic_tx_timeout(struct net_
+ {
+ 	struct sonic_local *lp = netdev_priv(dev);
+ 	int i;
+-	/* Stop the interrupts for this */
++	/*
++	 * put the Sonic into software-reset mode and
++	 * disable all interrupts before releasing DMA buffers
++	 */
+ 	SONIC_WRITE(SONIC_IMR, 0);
++	SONIC_WRITE(SONIC_ISR, 0x7fff);
++	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+ 	/* We could resend the original skbs. Easier to re-initialise. */
+ 	for (i = 0; i < SONIC_NUM_TDS; i++) {
+ 		if(lp->tx_laddr[i]) {

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/nfeth-virt_to_phys.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/nfeth-virt_to_phys.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,19 @@
+Subject: [PATCH] m68k: ARAnyM virtual Ethernet missing include
+
+Add missing #include <asm/virtconvert.h> (needed for virt_to_phys())
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/emu/nfeth.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/emu/nfeth.c
++++ linux-m68k-2.6.21/arch/m68k/emu/nfeth.c
+@@ -14,6 +14,7 @@
+ #include <linux/module.h>
+ #include <net/ieee80211.h>
+ #include <asm/natfeat.h>
++#include <asm/virtconvert.h>
+ 
+ enum {
+ 	GET_VERSION = 0,	/* no parameters, return NFAPI_VERSION in d0 */

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/pmu_queue_request-conflict.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/pmu_queue_request-conflict.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,32 @@
+Subject: m68k: pmu_queue_request() declaration conflict
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Fixes a "static qualifier follows non-static qualifier" error from gcc 4.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/macintosh/via-pmu68k.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/macintosh/via-pmu68k.c
++++ linux-m68k-2.6.21/drivers/macintosh/via-pmu68k.c
+@@ -111,7 +111,6 @@ static int pmu_send_request(struct adb_r
+ static int pmu_autopoll(int devs);
+ void pmu_poll(void);
+ static int pmu_reset_bus(void);
+-static int pmu_queue_request(struct adb_request *req);
+ 
+ static void pmu_start(void);
+ static void send_byte(int x);
+@@ -475,7 +474,7 @@ pmu_request(struct adb_request *req, voi
+ 	return pmu_queue_request(req);
+ }
+ 
+-static int 
++int
+ pmu_queue_request(struct adb_request *req)
+ {
+ 	unsigned long flags;

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/sun3-3x-cg3-bw2.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/sun3-3x-cg3-bw2.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,887 @@
+From: David Miller <davem at davemloft.net>
+To: sammy at sammy.net
+Cc: linux-m68k at vger.kernel.org
+Subject: Re: [PATCH] cg3/bw2: add Sun3/Sun3x support
+
+From: Sam Creasey <sammy at sammy.net>
+Date: Tue, 3 Apr 2007 10:32:35 -0400
+
+> This patch (re) introduces support for the CG3 driver on Sun3, and for
+> BW2 on Sun3x.  It applies cleanly to both the m68k CVS tree and the
+> vanilla tree.
+>
+> Signed-off-by: Sam Creasey <sammy at sammy.net>
+
+If you guys want to share driver code with the Sparc port, please do
+it properly.
+
+I am not applying a pile of ifdef's that basically duplicate half of
+the existing driver.
+
+What you can do instead is to build a fake openprom device tree and
+register those devices with the generic device subsystem, and then the
+driver will mostly just work out of the box.  It should be easy to
+duplicate the arch/sparc64/kernel/prom.c and of_device.c code you
+use as well as the driver interfaces in include/asm-sparc64/prom.h
+and of_device.h
+
+This way you don't need to shit all over the drivers adding hardcoded
+register addresses and ad-hoc probing code.  For special behaviors,
+you can add openprom node properties that the driver can test for at
+run time to guide behavior, again instead of ifdefs.
+
+---------------------------------------------------------------------------
+
+From sammy at sammy.net Tue Apr  3 16:47:32 2007
+Date: Tue, 3 Apr 2007 10:32:35 -0400
+From: Sam Creasey <sammy at sammy.net>
+To: linux-m68k at vger.kernel.org, David S. Miller <davem at davemloft.net>
+Subject: [PATCH] cg3/bw2: add Sun3/Sun3x support
+
+This patch (re) introduces support for the CG3 driver on Sun3, and for
+BW2 on Sun3x.  It applies cleanly to both the m68k CVS tree and the
+vanilla tree.
+
+Signed-off-by: Sam Creasey <sammy at sammy.net>
+
+---
+ drivers/video/Kconfig   |   14 ++
+ drivers/video/Makefile  |    1 
+ drivers/video/bw2.c     |  232 ++++++++++++++++++++++++++++++++++++++++++++++--
+ drivers/video/cg3.c     |  212 ++++++++++++++++++++++++++++++++++++++++++-
+ drivers/video/p4lib.c   |  107 ++++++++++++++++++++++
+ drivers/video/p4lib.h   |   56 +++++++++++
+ drivers/video/sbuslib.c |   13 ++
+ 7 files changed, 616 insertions(+), 19 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/video/Kconfig
++++ linux-m68k-2.6.21/drivers/video/Kconfig
+@@ -600,6 +600,16 @@ config FB_GBE_MEM
+ 	  This is the amount of memory reserved for the framebuffer,
+ 	  which can be any value between 1MB and 8MB.
+ 
++config FB_SUN3
++	bool "Sun3 framebuffer support"
++	depends on (FB = y) && (SUN3 || SUN3X)
++	help
++	  Support framebuffer devices on Sun3/3x.  Note that if you say yes
++	  here, any framebuffer drivers you select MUST be installed in the
++	  target system, or be disabled on the command line. (e.g. if you
++	  don't have a bw2, include video=bw2fb:off.  If you don't have
++	  a cg3, include video=cg3fb:off.)
++
+ config FB_SBUS
+ 	bool "SBUS and UPA framebuffers"
+ 	depends on (FB = y) && SPARC
+@@ -608,7 +618,7 @@ config FB_SBUS
+ 
+ config FB_BW2
+ 	bool "BWtwo support"
+-	depends on (FB = y) && (SPARC && FB_SBUS)
++	depends on (FB = y) && ((SPARC && FB_SBUS) || (SUN3X && FB_SUN3))
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+@@ -617,7 +627,7 @@ config FB_BW2
+ 
+ config FB_CG3
+ 	bool "CGthree support"
+-	depends on (FB = y) && (SPARC && FB_SBUS)
++	depends on (FB = y) && ((SPARC && FB_SBUS) || (SUN3 && FB_SUN3))
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+--- linux-m68k-2.6.21.orig/drivers/video/Makefile
++++ linux-m68k-2.6.21/drivers/video/Makefile
+@@ -106,6 +106,7 @@ obj-$(CONFIG_FB_VESA)             += ves
+ obj-$(CONFIG_FB_IMAC)             += imacfb.o
+ obj-$(CONFIG_FB_VGA16)            += vga16fb.o vgastate.o
+ obj-$(CONFIG_FB_OF)               += offb.o
++obj-$(CONFIG_FB_SUN3)             += p4lib.o
+ 
+ # the test framebuffer is last
+ obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
+--- linux-m68k-2.6.21.orig/drivers/video/bw2.c
++++ linux-m68k-2.6.21/drivers/video/bw2.c
+@@ -20,18 +20,29 @@
+ 
+ #include <asm/io.h>
+ #include <asm/oplib.h>
++#ifndef CONFIG_FB_SUN3
+ #include <asm/prom.h>
+ #include <asm/of_device.h>
++#endif
+ #include <asm/fbio.h>
+ 
+ #include "sbuslib.h"
+ 
++#ifdef CONFIG_FB_SUN3
++#ifdef CONFIG_SUN3
++#include <asm/sun3mmu.h>
++#endif
++#include <asm/machines.h>
++#include <asm/idprom.h>
++#include <asm/sbus.h>
++#include "p4lib.h"
++#endif
+ /*
+  * Local functions.
+  */
+-
++#ifndef CONFIG_FB_SUN3
+ static int bw2_blank(int, struct fb_info *);
+-
++#endif
+ static int bw2_mmap(struct fb_info *, struct vm_area_struct *);
+ static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long);
+ 
+@@ -41,7 +52,11 @@ static int bw2_ioctl(struct fb_info *, u
+ 
+ static struct fb_ops bw2_ops = {
+ 	.owner			= THIS_MODULE,
++#ifdef CONFIG_FB_SUN3
++	.fb_blank		= NULL,
++#else
+ 	.fb_blank		= bw2_blank,
++#endif
+ 	.fb_fillrect		= cfb_fillrect,
+ 	.fb_copyarea		= cfb_copyarea,
+ 	.fb_imageblit		= cfb_imageblit,
+@@ -53,7 +68,18 @@ static struct fb_ops bw2_ops = {
+ };
+ 
+ /* OBio addresses for the bwtwo registers */
++#ifdef CONFIG_FB_SUN3
++/* sun3 series */
++#define BWTWO_OBMEM_ADDR    0x1f000000
++#define BWTWO_OBMEM_ADDR_50 0x00100000
++#define BWTWO_OBMEM_ADDR_P4 0x1f300000
++#define BWTWO_OBMEM_ADDR_3X 0x50300000
++/* is this true for 3/50? */
++#define BWTWO_FB_OFFSET 0x100000
++#define BWTWO_OBMEM_HIGHRES_60 0x1f1c0000
++#else
+ #define BWTWO_REGISTER_OFFSET 0x400000
++#endif
+ 
+ struct bt_regs {
+ 	u32 addr;
+@@ -108,8 +134,11 @@ struct bw2_regs {
+ 
+ struct bw2_par {
+ 	spinlock_t		lock;
++#ifdef CONFIG_FB_SUN3
++	volatile u32           *regs;
++#else
+ 	struct bw2_regs		__iomem *regs;
+-
++#endif
+ 	u32			flags;
+ #define BW2_FLAG_BLANKED	0x00000001
+ 
+@@ -118,6 +147,7 @@ struct bw2_par {
+ 	unsigned long		fbsize;
+ };
+ 
++#ifndef CONFIG_FB_SUN3
+ /**
+  *      bw2_blank - Optional function.  Blanks the display.
+  *      @blank_mode: the blank mode we want.
+@@ -156,6 +186,7 @@ bw2_blank(int blank, struct fb_info *inf
+ 
+ 	return 0;
+ }
++#endif
+ 
+ static struct sbus_mmap_map bw2_mmap_map[] = {
+ 	{
+@@ -198,6 +229,17 @@ static void __devinit bw2_init_fix(struc
+ 	info->fix.accel = FB_ACCEL_SUN_BWTWO;
+ }
+ 
++struct all_info {
++	struct fb_info info;
++	struct bw2_par par;
++};
++/* CONFIG_FB_SUN3 has a different implementation for the remaining
++    functions, since:
++    1) No OpenProm
++    2) Fixed frequency
++    3) No support for multiple BWtwo's */
++#ifndef CONFIG_FB_SUN3
++
+ static u8 bw2regs_1600[] __devinitdata = {
+ 	0x14, 0x8b,	0x15, 0x28,	0x16, 0x03,	0x17, 0x13,
+ 	0x18, 0x7b,	0x19, 0x05,	0x1a, 0x34,	0x1b, 0x2e,
+@@ -279,11 +321,6 @@ static void __devinit bw2_do_default_mod
+ 	}
+ }
+ 
+-struct all_info {
+-	struct fb_info info;
+-	struct bw2_par par;
+-};
+-
+ static int __devinit bw2_init_one(struct of_device *op)
+ {
+ 	struct device_node *dp = op->node;
+@@ -397,6 +434,185 @@ static void __exit bw2_exit(void)
+ 	return of_unregister_driver(&bw2_driver);
+ }
+ 
++#else /* !CONFIG_FB_SUN3 */
++
++static struct all_info *bw2_all = NULL;
++
++static void bw2_do_default_mode(struct bw2_par *par, struct fb_info *info,
++				int *linebytes)
++{
++	int highres = 0;
++
++	if(idprom->id_machtype == (SM_SUN3|SM_3_260))
++		/* the 3/260 is allegedly always highres */
++		highres = 1;
++	if(idprom->id_machtype == (SM_SUN3|SM_3_60)) {
++#ifdef CONFIG_SUN3
++		/* we won't hit this unless running on a sun3 anyway */
++		volatile u32 *reg;
++		u32 il
++
++		reg = sun3_ioremap(BW2_OBMEM_HIGHRES_60, sizeof(u32),
++				   SUN3_PAGE_TYPE_MEMORY);
++		i = *reg;
++		iounmap(reg);
++		if((i != -1) && (i& 0x80) == 0)
++			highres = 1;
++#endif
++	}
++
++	if(highres) {
++		info->var.xres = info->var.xres_virtual = 1600;
++		info->var.yres = info->var.yres_virtual = 1280;
++		*linebytes = 1600 / 8;
++	}
++}
++
++
++static int __devinit bw2_init_one(unsigned long phys_addr)
++{
++	struct all_info *all;
++	int linebytes, err, id;
++	all = kzalloc(sizeof(*all), GFP_KERNEL);
++	if (!all)
++		return -ENOMEM;
++
++	spin_lock_init(&all->par.lock);
++
++	all->par.physbase = phys_addr;
++
++#ifdef CONFIG_SUN3
++	all->par.regs = sun3_ioremap(phys_addr, sizeof(u32),
++				     SUN3_PAGE_TYPE_MEMORY);
++#else
++	all->par.regs = ioremap_nocache(phys_addr, sizeof(u32));
++#endif
++	/* look for the p4 register, or assume we're OBIO if it's not found */
++	id = p4fb_get_id(all->par.regs);
++	printk("bwtwo: p4id %08x\n", id);
++
++	/* mutable memory address, probably save to say we've got an onboard fb */
++	if(id == -1) {
++		iounmap((void *)all->par.regs);
++		/* only currently supported on sun3.  Perhaps someday sun4. */
++		if((idprom->id_machtype & SM_ARCH_MASK) != SM_SUN3) {
++			kfree(all);
++			return -ENODEV;
++		}
++
++		p4fb_fill_var(&all->info.var, NULL, 1);
++		bw2_do_default_mode(&all->par, &all->info, &linebytes);
++	} else {
++		if(id != P4_ID_BW2) {
++			kfree(all);
++			iounmap((void *)all->par.regs);
++			return -ENODEV;
++		}
++
++		p4fb_fill_var(&all->info.var, (volatile u32 *)all->par.regs, 1);
++	}
++
++	linebytes = all->info.var.xres / 8;
++
++	all->info.var.red.length = all->info.var.green.length =
++		all->info.var.blue.length = all->info.var.bits_per_pixel;
++	all->info.var.red.offset = all->info.var.green.offset =
++		all->info.var.blue.offset = 0;
++
++	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
++
++	all->info.flags = FBINFO_DEFAULT;
++	all->info.fbops = &bw2_ops;
++
++	if(id == -1) {
++#ifdef CONFIG_SUN3
++		all->info.screen_base = sun3_ioremap(phys_addr,
++						     all->par.fbsize,
++						     SUN3_PAGE_TYPE_MEMORY);
++#else
++		all->info.screen_base = ioremap(phys_addr,
++						all->par.fbsize);
++#endif
++	} else {
++#ifdef CONFIG_SUN3
++		all->info.screen_base = sun3_ioremap(phys_addr + BWTWO_FB_OFFSET,
++						     all->par.fbsize,
++						     SUN3_PAGE_TYPE_MEMORY);
++#else
++		all->info.screen_base = ioremap(phys_addr + BWTWO_FB_OFFSET,
++						all->par.fbsize);
++#endif
++	}
++
++	p4fb_video_enable(all->par.regs);
++
++	all->info.par = &all->par;
++
++	bw2_init_fix(&all->info, linebytes);
++
++	err= register_framebuffer(&all->info);
++	if (err < 0) {
++		iounmap((void *)all->par.regs);
++		iounmap((void *)all->info.screen_base);
++		kfree(all);
++		return err;
++	}
++
++	bw2_all = all;
++
++	printk("%s: bwtwo at %lx\n",
++	       all->info.fix.id, all->par.physbase);
++
++	return 0;
++}
++
++static int __init bw2_init(void)
++{
++	if(fb_get_options("bw2fb", NULL))
++		return -ENODEV;
++
++	if(bw2_all != NULL)
++		return -ENODEV;
++
++	/* currently only sun3/80 P4 is supported/tested */
++	switch(idprom->id_machtype) {
++	case SM_SUN3X|SM_3_80:
++	case SM_SUN3X|SM_3_460:
++		return bw2_init_one(BWTWO_OBMEM_ADDR_3X);
++
++	case SM_SUN3|SM_3_50:
++		return bw2_init_one(BWTWO_OBMEM_ADDR_50);
++
++	case SM_SUN3|SM_3_160:
++	case SM_SUN3|SM_3_260:
++	case SM_SUN3|SM_3_110:
++	case SM_SUN3|SM_3_60:
++		return bw2_init_one(BWTWO_OBMEM_ADDR);
++	default:
++		break;
++	}
++
++	return -ENODEV;
++}
++
++static void __exit bw2_exit(void)
++{
++	struct all_info *all = bw2_all;
++	if(bw2_all == NULL)
++		return;
++
++	unregister_framebuffer(&all->info);
++
++	iounmap((void *)all->par.regs);
++	iounmap((void *)all->info.screen_base);
++
++	kfree(all);
++
++	bw2_all = NULL;
++
++	return;
++}
++#endif /* CONFIG_FB_SUN3 */
+ 
+ module_init(bw2_init);
+ module_exit(bw2_exit);
+--- linux-m68k-2.6.21.orig/drivers/video/cg3.c
++++ linux-m68k-2.6.21/drivers/video/cg3.c
+@@ -20,12 +20,24 @@
+ 
+ #include <asm/io.h>
+ #include <asm/oplib.h>
++#ifndef CONFIG_FB_SUN3
+ #include <asm/prom.h>
+ #include <asm/of_device.h>
++#endif
+ #include <asm/fbio.h>
+ 
+ #include "sbuslib.h"
+ 
++#ifdef CONFIG_FB_SUN3
++#ifdef CONFIG_SUN3
++#include <asm/sun3mmu.h>
++#endif
++#include <asm/machines.h>
++#include <asm/idprom.h>
++#include <asm/sbus.h>
++#include "p4lib.h"
++#endif
++
+ /*
+  * Local functions.
+  */
+@@ -108,8 +120,16 @@ struct cg3_regs {
+ };
+ 
+ /* Offset of interesting structures in the OBIO space */
+-#define CG3_REGS_OFFSET	     0x400000UL
+-#define CG3_RAM_OFFSET	     0x800000UL
++#ifdef CONFIG_SUN3
++#define CGFOUR_OBMEM_ADDR_60  0x1f000000
++#define CGFOUR_OBMEM_ADDR_110 0x1f300000
++#define CG3_REGS_OFFSET       (-0x100000)
++#define CG3_RAM_OFFSET        0x500000UL
++#else
++#define CG3_REGS_OFFSET	      0x400000UL
++#define CG3_RAM_OFFSET	      0x800000UL
++#endif
++
+ 
+ struct cg3_par {
+ 	spinlock_t		lock;
+@@ -250,6 +270,18 @@ static int cg3_ioctl(struct fb_info *inf
+  *  Initialisation
+  */
+ 
++struct all_info {
++	struct fb_info info;
++	struct cg3_par par;
++};
++
++
++/* CONFIG_FB_SUN3 has a different implementation for the remaining
++   functions, since:
++   1) No OpenProm
++   2) Fixed frequency
++   3) No support for multiple CGthree's */
++#ifndef CONFIG_FB_SUN3
+ static void __devinit cg3_init_fix(struct fb_info *info, int linebytes,
+ 				   struct device_node *dp)
+ {
+@@ -351,12 +383,8 @@ static void __devinit cg3_do_default_mod
+ 		regp = (u8 __iomem *)&par->regs->cmap.control;
+ 		sbus_writeb(p[1], regp);
+ 	}
+-}
+ 
+-struct all_info {
+-	struct fb_info info;
+-	struct cg3_par par;
+-};
++}
+ 
+ static int __devinit cg3_init_one(struct of_device *op)
+ {
+@@ -426,8 +454,8 @@ static int __devinit cg3_init_one(struct
+ 
+ 	dev_set_drvdata(&op->dev, all);
+ 
+-	printk("%s: cg3 at %lx:%lx\n",
+-	       dp->full_name, all->par.which_io, all->par.physbase);
++	printk("%s: cg3 at %lx\n",
++	       dp->full_name, all->par.physbase);
+ 
+ 	return 0;
+ }
+@@ -488,6 +516,172 @@ static void __exit cg3_exit(void)
+ 	of_unregister_driver(&cg3_driver);
+ }
+ 
++#else /* !CONFIG_FB_SUN3 */
++static void
++cg3_init_fix(struct fb_info *info, int linebytes)
++{
++
++	strcpy(info->fix.id, "SUN3 CG3");
++
++	info->fix.type = FB_TYPE_PACKED_PIXELS;
++	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
++
++	info->fix.line_length = linebytes;
++
++	info->fix.accel = FB_ACCEL_SUN_CGTHREE;
++}
++static void cg3_do_default_mode(struct cg3_par *par)
++{
++	/* kick up the sun3 -- 66hz prom mode only */
++	/* this also turns off the overlay in case it's really a cg4 */
++
++	par->regs->cmap.addr = 4;
++	par->regs->cmap.control = 0xff;
++	par->regs->cmap.addr = 5;
++	par->regs->cmap.control = 0;
++	par->regs->cmap.addr = 6;
++	par->regs->cmap.control = 0x40;
++	par->regs->cmap.addr = 7;
++	par->regs->cmap.control = 0;
++
++}
++
++/* The Sun3 version of this driver only supports one cgthree.
++   This really isn't an issue, because it also only supports
++   the 3/60 OBIO cg3, and not vme cards (of which there could be more
++   than one) */
++static struct all_info *cg3_all = NULL;
++
++static int __devinit cg3_init_one(unsigned long phys_addr)
++{
++	struct all_info *all;
++	int linebytes, err;
++	volatile u32 *p4reg = NULL;
++
++	all = kzalloc(sizeof(*all), GFP_KERNEL);
++	if (!all)
++		return -ENOMEM;
++
++	spin_lock_init(&all->par.lock);
++
++	all->par.physbase = phys_addr;
++
++#if 0
++	/* it would be nice to use p4 registers here, but it appears
++	 * some P4 framebuffers don't actually have useful data.
++	 * So we just plod along regardless */
++	p4reg = sun3_ioremap(all->par.physbase, sizeof(u32),
++			     SUN3_PAGE_TYPE_MEMORY);
++	id = p4fb_get_id(p4reg);
++	printk("cg3: p4id %08x\n", *p4reg);
++
++	if(id != P4_ID_CG4) {
++		iounmap((void *)p4reg);
++		kfree(all);
++		return -ENODEV;
++	}
++
++#endif
++	p4fb_fill_var(&all->info.var, p4reg, 8);
++	if(p4reg != NULL)
++		iounmap((void *)p4reg);
++
++	all->info.var.red.length = 8;
++	all->info.var.green.length = 8;
++	all->info.var.blue.length = 8;
++	linebytes = all->info.var.xres;
++
++	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
++
++	all->par.regs = (struct cg3_regs *)
++		sun3_ioremap(all->par.physbase + CG3_REGS_OFFSET,
++			     sizeof(struct cg3_regs), SUN3_PAGE_TYPE_MEMORY);
++
++
++	all->info.flags = FBINFO_DEFAULT;
++	all->info.fbops = &cg3_ops;
++	all->info.screen_base = (char *)
++		sun3_ioremap(all->par.physbase + CG3_RAM_OFFSET,
++			     all->par.fbsize, SUN3_PAGE_TYPE_MEMORY);
++	all->info.par = &all->par;
++
++	cg3_blank(0, &all->info);
++
++	cg3_do_default_mode(&all->par);
++
++	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
++		kfree(all);
++		return -ENOMEM;
++	}
++
++	fb_set_cmap(&all->info.cmap, &all->info);
++
++	cg3_init_fix(&all->info, linebytes);
++
++	err = register_framebuffer(&all->info);
++	if (err < 0) {
++		fb_dealloc_cmap(&all->info.cmap);
++		iounmap(all->par.regs);
++		iounmap(all->info.screen_base);
++		kfree(all);
++		return err;
++	}
++
++	cg3_all = all;
++
++	printk("%s: cg3 at %lx\n",
++	       all->info.fix.id, all->par.physbase);
++
++	return 0;
++}
++
++static int __init cg3_init(void)
++{
++	if (fb_get_options("cg3fb", NULL))
++		return -ENODEV;
++
++	if(cg3_all != NULL)
++		return -ENODEV;
++
++	/* currently only sun3/60 P4 is supported/tested */
++	switch(idprom->id_machtype) {
++	case SM_SUN3|SM_3_60:
++		return cg3_init_one(CGFOUR_OBMEM_ADDR_60);
++
++	case SM_SUN3|SM_3_110:
++		/* 3/110 is a guess, no 3/110 to test on */
++		return cg3_init_one(CGFOUR_OBMEM_ADDR_110);
++
++	default:
++		break;
++	}
++
++	return -ENODEV;
++}
++
++static void __exit cg3_exit(void)
++{
++	struct all_info *all = cg3_all;
++
++	if(cg3_all == NULL)
++		return;
++
++	unregister_framebuffer(&all->info);
++	fb_dealloc_cmap(&all->info.cmap);
++
++	iounmap(all->par.regs);
++	iounmap(all->info.screen_base);
++
++	kfree(all);
++
++	cg3_all = NULL;
++
++	return;
++
++}
++
++#endif /* CONFIG_FB_SUN3 */
++
+ module_init(cg3_init);
+ module_exit(cg3_exit);
+ 
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/video/p4lib.c
+@@ -0,0 +1,107 @@
++/* p4lib.c: Helper library for Sun P4 framebuffer drivers
++ *
++ * Copyright (C) 2007 Sam Creasey (sammy at sammy.net)
++ */
++
++#include <linux/compat.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++
++#include <linux/fb.h>
++
++#include "p4lib.h"
++
++int p4fb_get_id(volatile u32 *p4reg)
++{
++
++#ifdef CONFIG_SUN3
++	/* this code makes the 3x cry, and it can't have onboard fb anyway */
++	u32 x, old;
++
++	/* attempt to read the id bit back from the p4 register, if
++	 * we're able to modify the value, conclude there's no p4
++	 * device there.  This should enable us to determine if we're
++	 * dealing with, for example, a builtin bw2 or a p4 bw2. */
++
++	old = *p4reg;
++	x = old & ~P4_CTRL_RESET;
++
++	*p4reg = x ^ P4_ID_MASK;
++	if((*p4reg ^ x) & P4_ID_MASK) {
++		/* we managed to change the type bits, not a p4 port */
++		*p4reg = old;
++		return -1;
++	}
++#endif
++	return ((*p4reg) & P4_ID_MASK) >> P4_ID_SHIFT;
++}
++
++int p4fb_get_res(volatile u32 *p4reg)
++{
++	return ((*p4reg) & P4_RES_MASK) >> P4_RES_SHIFT;
++}
++
++void p4fb_video_enable(volatile u32 *p4reg)
++{
++	u32 x;
++
++	x = *p4reg;
++	x &= ~(P4_CTRL_VIDEO_EN | P4_CTRL_INT);
++	x |= P4_CTRL_VIDEO_EN;
++	*p4reg = x;
++
++}
++
++/* This function basically assumes that p4fb_get_id returns a sane
++ * value for this card/instance.  If this was not true, calling with
++ * NULL for p4reg will return the defaults */
++void p4fb_fill_var(struct fb_var_screeninfo *var, volatile u32 *p4reg, int bpp)
++{
++	memset(var, 0, sizeof(*var));
++
++	if(p4reg == NULL) {
++		var->xres = 1152;
++		var->yres = 900;
++	} else {
++		switch(p4fb_get_res(p4reg)) {
++		case P4_RES_1600X1280:
++			var->xres = 1600;
++			var->yres = 1280;
++			break;
++		case P4_RES_1152X900:
++			var->xres = 1152;
++			var->yres = 900;
++			break;
++		case P4_RES_1024X1024:
++			var->xres = 1024;
++			var->yres = 1024;
++			break;
++		case P4_RES_1280X1024:
++			var->xres = 1280;
++			var->yres = 1024;
++			break;
++		case P4_RES_1440X1440:
++			var->xres = 1440;
++			var->yres = 1400;
++			break;
++		case P4_RES_640X480:
++			var->xres = 640;
++			var->yres = 480;
++			break;
++		default:
++			/* this may or may not be the right thing to
++			 * do here, but plod on anyway */
++			var->xres = 1152;
++			var->yres = 900;
++			break;
++		}
++	}
++
++	var->xres_virtual = var->xres;
++	var->yres_virtual = var->yres;
++	var->bits_per_pixel = bpp;
++}
++
++EXPORT_SYMBOL(p4fb_get_id);
++EXPORT_SYMBOL(p4fb_get_res);
++EXPORT_SYMBOL(p4fb_fill_var);
+--- /dev/null
++++ linux-m68k-2.6.21/drivers/video/p4lib.h
+@@ -0,0 +1,56 @@
++/* p4lib.h: helper functions for p4 framebuffers */
++
++#ifndef _P4LIB_H
++#define _P4LIB_H
++
++/* register defintions applicable to p4 framebuffers found on some
++   Sun3/3x machines (and some Sun4 machines, though these are not
++   currently supported or tested).  These machines have a single 32bit
++   register at the start of the p4 address space.
++
++   The format of this register is as follows:
++
++   bit 31    : unused
++   bits 30-28: type
++   bits 27-24: resolution
++   bits 23-8:  unused
++   bits 7-0:   status/control
++
++   The CG8 may break this format, if that turns out to be true, I'll
++   fix once I have a CG8 to test against...
++*/
++
++/* control register, lower 8bits */
++#define P4_CTRL_DIAG     0x80  /* ??? */
++#define P4_CTRL_RBCLR    0x40  /* ??? */
++#define P4_CTRL_VIDEO_EN 0x20  /* enable video */
++#define P4_CTRL_SYNC     0x10  /* ??? */
++#define P4_CTRL_VTRACE   0x08  /* ??? */
++#define P4_CTRL_INT      0x04  /* read: int pending, write: clear int */
++#define P4_CTRL_INT_EN   0x02  /* enable interrupts */
++#define P4_CTRL_RESET    0x01  /* reset */
++
++/* framebuffer identification -- bits 31-28 */
++#define P4_ID_MASK  0x70000000
++#define P4_ID_SHIFT 24
++#define P4_ID_BW2   0x00
++#define P4_ID_CG4   0x40 /* supported in linux as a cg3 */
++#define P4_ID_CG6   0x60
++
++/* framebuffer resolution - bits 27-24 */
++#define P4_RES_MASK      0x0f000000
++#define P4_RES_SHIFT     24
++#define P4_RES_1600X1280 0x00
++#define P4_RES_1152X900  0x01 /* only tested resolution */
++#define P4_RES_1024X1024 0x02
++#define P4_RES_1280X1024 0x03
++#define P4_RES_1440X1440 0x04
++#define P4_RES_640X480   0x05
++
++/* actual helper functions */
++extern int p4fb_get_id(volatile u32 *p4reg);
++extern int p4fb_get_res(volatile u32 *p4reg);
++extern void p4fb_video_enable(volatile u32 *p4reg);
++extern void p4fb_fill_var(struct fb_var_screeninfo *var, volatile u32 *p4reg, int bpp);
++
++#endif /* P4LIB_H */
+--- linux-m68k-2.6.21.orig/drivers/video/sbuslib.c
++++ linux-m68k-2.6.21/drivers/video/sbuslib.c
+@@ -13,6 +13,10 @@
+ #include <asm/oplib.h>
+ #include <asm/fbio.h>
+ 
++#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
++#include <asm/uaccess.h>
++#endif
++
+ #include "sbuslib.h"
+ 
+ void sbusfb_fill_var(struct fb_var_screeninfo *var, int prom_node, int bpp)
+@@ -21,6 +25,7 @@ void sbusfb_fill_var(struct fb_var_scree
+ 
+ 	var->xres = prom_getintdefault(prom_node, "width", 1152);
+ 	var->yres = prom_getintdefault(prom_node, "height", 900);
++
+ 	var->xres_virtual = var->xres;
+ 	var->yres_virtual = var->yres;
+ 	var->bits_per_pixel = bpp;
+@@ -80,12 +85,20 @@ int sbusfb_mmap_helper(struct sbus_mmap_
+ 		}
+ 		if (page + map_size > size)
+ 			map_size = size - page;
++#if !defined(CONFIG_FB_SUN3)
+ 		r = io_remap_pfn_range(vma,
+ 					vma->vm_start + page,
+ 					MK_IOSPACE_PFN(iospace,
+ 						map_offset >> PAGE_SHIFT),
+ 					map_size,
+ 					vma->vm_page_prot);
++#else
++		r = io_remap_pfn_range(vma,
++					vma->vm_start + page,
++					map_offset, map_size,
++					vma->vm_page_prot);
++#endif
++
+ 		if (r)
+ 			return -EAGAIN;
+ 		page += map_size;

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/sun3-3x-serial.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/sun3-3x-serial.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,486 @@
+From: David Miller <davem at davemloft.net>
+To: sammy at sammy.net
+Cc: linux-m68k at vger.kernel.org
+Subject: Re: [PATCH] Sun3/3x Serial driver support
+
+From: Sam Creasey <sammy at sammy.net>
+Date: Tue, 3 Apr 2007 10:43:42 -0400
+
+> Adds serial support for sun3/3x machines.  This patch has basically
+> been around for years, but my own laziness has kept me from committing
+> upstream.
+>
+> Signed-off-by: Sam Creasey <sammy at sammy.net>
+
+Same thing here, please build a proper openprom device tree in
+the sun3 port and then you'll need to make few, if any,
+changes to the sparc drivers.
+
+I've made these drivers as portable as possible, frankly, and
+if you cook up proper in-kernel device objects, you'll need
+to do no porting at all.
+
+---------------------------------------------------------------------------
+
+From sammy at sammy.net Tue Apr  3 16:47:31 2007
+Date: Tue, 3 Apr 2007 10:43:42 -0400
+From: Sam Creasey <sammy at sammy.net>
+To: linux-m68k at vger.kernel.org, David S. Miller <davem at davemloft.net>
+Subject: [PATCH] Sun3/3x Serial driver support
+
+Adds serial support for sun3/3x machines.  This patch has basically
+been around for years, but my own laziness has kept me from committing
+upstream.
+
+Signed-off-by: Sam Creasey <sammy at sammy.net>
+
+---
+ drivers/serial/Kconfig    |    4 
+ drivers/serial/suncore.c  |    4 
+ drivers/serial/sunzilog.c |  200 +++++++++++++++++++++++++++++++++++++++++++---
+ 3 files changed, 195 insertions(+), 13 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/serial/Kconfig
++++ linux-m68k-2.6.21/drivers/serial/Kconfig
+@@ -543,14 +543,14 @@ config SERIAL_UARTLITE_CONSOLE
+ 
+ config SERIAL_SUNCORE
+ 	bool
+-	depends on SPARC
++	depends on SPARC || SUN3 || SUN3X
+ 	select SERIAL_CORE
+ 	select SERIAL_CORE_CONSOLE
+ 	default y
+ 
+ config SERIAL_SUNZILOG
+ 	tristate "Sun Zilog8530 serial support"
+-	depends on SPARC
++	depends on SPARC || SUN3 || SUN3X
+ 	help
+ 	  This driver supports the Zilog8530 serial ports found on many Sparc
+ 	  systems.  Say Y or M if you want to be able to these serial ports.
+--- linux-m68k-2.6.21.orig/drivers/serial/suncore.c
++++ linux-m68k-2.6.21/drivers/serial/suncore.c
+@@ -29,6 +29,7 @@ EXPORT_SYMBOL(sunserial_current_minor);
+ void
+ sunserial_console_termios(struct console *con)
+ {
++#if !defined(CONFIG_SUN3) && !defined (CONFIG_SUN3X)
+ 	char mode[16], buf[16], *s;
+ 	char *mode_prop = "ttyX-mode";
+ 	char *cd_prop = "ttyX-ignore-cd";
+@@ -162,6 +163,9 @@ no_options:
+ 	}
+ 
+ 	con->cflag = cflag;
++#else /* CONFIG_SUN3(X) */
++	con->cflag = CREAD | HUPCL | CLOCAL | B9600 | CS8;
++#endif
+ }
+ 
+ EXPORT_SYMBOL(sunserial_console_termios);
+--- linux-m68k-2.6.21.orig/drivers/serial/sunzilog.c
++++ linux-m68k-2.6.21/drivers/serial/sunzilog.c
+@@ -35,13 +35,30 @@
+ 
+ #include <asm/io.h>
+ #include <asm/irq.h>
+-#include <asm/prom.h>
+-#include <asm/of_device.h>
+ 
+ #if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+ #define SUPPORT_SYSRQ
+ #endif
+ 
++#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
++#include <asm/oplib.h>
++#include <asm/sbus.h>
++#define readb sbus_readb
++#define writeb sbus_writeb
++
++#else
++#include <asm/prom.h>
++#include <asm/of_device.h>
++#endif
++
++#ifdef CONFIG_SUN3
++#include <asm/sun3mmu.h>
++#endif
++
++#ifdef CONFIG_SUN3X
++#include <asm/sun3xprom.h>
++#endif
++
+ #include <linux/serial_core.h>
+ 
+ #include "suncore.h"
+@@ -415,7 +432,15 @@ static void sunzilog_status_handle(struc
+ 				if (!(status & BRK_ABRT))
+ 					break;
+ 			}
+-			sun_do_break();
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
++ 			sun_do_break();
++#else
++#ifdef CONFIG_SUN3
++			prom_reboot("");
++#else
++			sun3x_reboot();
++#endif
++#endif
+ 			return;
+ 		}
+ 	}
+@@ -523,6 +548,13 @@ static irqreturn_t sunzilog_interrupt(in
+ 		struct tty_struct *tty;
+ 		unsigned char r3;
+ 
++#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
++		if(!channel) {
++			up = up->next;
++			continue;
++		}
++#endif
++
+ 		spin_lock(&up->port.lock);
+ 		r3 = read_zsreg(channel, R3);
+ 
+@@ -1193,6 +1225,7 @@ static struct console sunzilog_console_o
+ 
+ static inline struct console *SUNZILOG_CONSOLE(void)
+ {
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ 	int i;
+ 
+ 	if (con_is_present())
+@@ -1209,6 +1242,10 @@ static inline struct console *SUNZILOG_C
+ 
+ 	sunzilog_console_ops.index = i;
+ 	sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS;
++#else
++	sunzilog_console_ops.index = 0;
++	sunzilog_port_table[0].flags |= SUNZILOG_FLAG_IS_CONS;
++#endif
+ 
+ 	return &sunzilog_console_ops;
+ }
+@@ -1266,6 +1303,8 @@ static void __init sunzilog_register_ser
+ }
+ #endif
+ 
++static int zilog_irq = -1;
++
+ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
+ {
+ 	struct zilog_channel __iomem *channel;
+@@ -1276,9 +1315,16 @@ static void __devinit sunzilog_init_hw(s
+ 
+ 	spin_lock_irqsave(&up->port.lock, flags);
+ 	if (ZS_IS_CHANNEL_A(up)) {
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ 		write_zsreg(channel, R9, FHWRES);
+ 		ZSDELAY_LONG();
++#endif
+ 		(void) read_zsreg(channel, R0);
++#ifdef CONFIG_SUN3
++			/* should sun3x run here? */
++			/* program the int vector */
++			write_zsreg(channel, R2, 0x18+zilog_irq);
++#endif
+ 	}
+ 
+ 	if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
+@@ -1293,7 +1339,11 @@ static void __devinit sunzilog_init_hw(s
+ 		up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
+ 		up->curregs[R3] = RxENAB | Rx8;
+ 		up->curregs[R5] = TxENAB | Tx8;
++#ifdef CONFIG_SUN3
++		up->curregs[R9] = MIE;
++#else
+ 		up->curregs[R9] = NV | MIE;
++#endif
+ 		up->curregs[R10] = NRZ;
+ 		up->curregs[R11] = TCBR | RCBR;
+ 		baud = 9600;
+@@ -1314,9 +1364,75 @@ static void __devinit sunzilog_init_hw(s
+ #endif
+ }
+ 
+-static int zilog_irq = -1;
++#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
++static struct zilog_layout * __init get_zs(int chip)
++{
++	unsigned int vaddr = 0;
+ 
++	if (chip < 0 || chip >= NUM_SUNZILOG) {
++		prom_printf("SunZilog: Illegal chip number %d in get_zs.\n", chip);
++		prom_halt();
++	}
++
++#ifndef CONFIG_SUN3X
++	/* sun3 OBIO version */
++	/* Grrr, these have to be hardcoded aieee */
++	switch(chip) {
++	case 0:
++		for(vaddr = 0xfe00000; vaddr < (0xfe00000 +
++						SUN3_PMEG_SIZE); vaddr += SUN3_PTE_SIZE) {
++			unsigned long iopte;
++
++			iopte = sun3_get_pte(vaddr);
++			if(!(iopte & SUN3_PAGE_TYPE_IO)) /* this an io page? */
++				continue;
++
++			if(((iopte & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT) ==
++			   0x20000) {
++				break;
++			}
++		}
++		break;
++	case 1:
++		for(vaddr = 0xfe00000; vaddr < (0xfe00000 +
++						SUN3_PMEG_SIZE); vaddr += SUN3_PTE_SIZE) {
++
++			unsigned long iopte;
++
++			iopte = sun3_get_pte(vaddr);
++			if(!(iopte & SUN3_PAGE_TYPE_IO)) /* this an io page? */
++				continue;
++
++			if(((iopte & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT) ==
++			   0) {
++				break;
++			}
++		}
++		break;
++	};
++#else
++	/* sun3x is a wee bit cleaner. :) */
++	switch(chip) {
++	case 0:
++		vaddr = SUN3X_ZS2;
++		break;
++
++	case 1:
++		vaddr = SUN3X_ZS1;
++		break;
++	}
++#endif
++
++	if(!vaddr)
++		panic("get_zs whee no serial chip mappable");
++
++	return (struct zilog_layout *)(unsigned long) vaddr;
++}
++
++static int __devinit zs_probe(void)
++#else
+ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match)
++#endif
+ {
+ 	static int inst;
+ 	struct uart_sunzilog_port *up;
+@@ -1325,51 +1441,70 @@ static int __devinit zs_probe(struct of_
+ 	int err;
+ 
+ 	keyboard_mouse = 0;
++#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
++	sunzilog_chip_regs[inst] = get_zs(inst);
++	if(inst)
++		keyboard_mouse = 1;
++#else
+ 	if (of_find_property(op->node, "keyboard", NULL))
+ 		keyboard_mouse = 1;
+ 
+ 	sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
+ 					      sizeof(struct zilog_layout),
+ 					      "zs");
++#endif /* CONFIG_SUN3 || CONFIG_SUN3X */
++
+ 	if (!sunzilog_chip_regs[inst])
+ 		return -ENOMEM;
+ 
+ 	rp = sunzilog_chip_regs[inst];
+ 
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ 	if (zilog_irq == -1)
+ 		zilog_irq = op->irqs[0];
++#endif
+ 
+ 	up = &sunzilog_port_table[inst * 2];
+ 
+ 	/* Channel A */
+-	up[0].port.mapbase = op->resource[0].start + 0x00;
+ 	up[0].port.membase = (void __iomem *) &rp->channelA;
+-	up[0].port.iotype = UPIO_MEM;
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
++	up[0].port.mapbase = op->resource[0].start + 0x00;
+ 	up[0].port.irq = op->irqs[0];
++	up[0].port.dev = &op->dev;
++#else
++	up[0].port.mapbase = (unsigned long)up[0].port.membase;
++	up[0].port.irq = zilog_irq;
++#endif
++	up[0].port.iotype = UPIO_MEM;
+ 	up[0].port.uartclk = ZS_CLOCK;
+ 	up[0].port.fifosize = 1;
+ 	up[0].port.ops = &sunzilog_pops;
+ 	up[0].port.type = PORT_SUNZILOG;
+ 	up[0].port.flags = 0;
+ 	up[0].port.line = (inst * 2) + 0;
+-	up[0].port.dev = &op->dev;
+ 	up[0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
+ 	if (keyboard_mouse)
+ 		up[0].flags |= SUNZILOG_FLAG_CONS_KEYB;
+ 	sunzilog_init_hw(&up[0]);
+ 
+ 	/* Channel B */
+-	up[1].port.mapbase = op->resource[0].start + 0x04;
+ 	up[1].port.membase = (void __iomem *) &rp->channelB;
+-	up[1].port.iotype = UPIO_MEM;
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
++	up[1].port.mapbase = op->resource[0].start + 0x04;
+ 	up[1].port.irq = op->irqs[0];
++	up[1].port.dev = &op->dev;
++#else
++	up[1].port.mapbase = (unsigned long)up[1].port.membase;
++	up[1].port.irq = zilog_irq;
++#endif
++	up[1].port.iotype = UPIO_MEM;
+ 	up[1].port.uartclk = ZS_CLOCK;
+ 	up[1].port.fifosize = 1;
+ 	up[1].port.ops = &sunzilog_pops;
+ 	up[1].port.type = PORT_SUNZILOG;
+ 	up[1].port.flags = 0;
+ 	up[1].port.line = (inst * 2) + 1;
+-	up[1].port.dev = &op->dev;
+ 	up[1].flags |= 0;
+ 	if (keyboard_mouse)
+ 		up[1].flags |= SUNZILOG_FLAG_CONS_MOUSE;
+@@ -1378,33 +1513,50 @@ static int __devinit zs_probe(struct of_
+ 	if (!keyboard_mouse) {
+ 		err = uart_add_one_port(&sunzilog_reg, &up[0].port);
+ 		if (err) {
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ 			of_iounmap(&op->resource[0],
+ 				   rp, sizeof(struct zilog_layout));
++#endif
+ 			return err;
+ 		}
+ 		err = uart_add_one_port(&sunzilog_reg, &up[1].port);
+ 		if (err) {
+ 			uart_remove_one_port(&sunzilog_reg, &up[0].port);
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ 			of_iounmap(&op->resource[0],
+ 				   rp, sizeof(struct zilog_layout));
++#endif
+ 			return err;
+ 		}
+ 	} else {
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ 		printk(KERN_INFO "%s: Keyboard at MMIO %lx (irq = %d) "
+ 		       "is a zs\n",
+ 		       op->dev.bus_id, up[0].port.mapbase, op->irqs[0]);
+ 		printk(KERN_INFO "%s: Mouse at MMIO %lx (irq = %d) "
+ 		       "is a zs\n",
+ 		       op->dev.bus_id, up[1].port.mapbase, op->irqs[0]);
++#else
++		printk(KERN_INFO "zs%d: Keyboard at MMIO %lx (irq = %d) "
++		       "is a zs\n",
++		       inst, up[0].port.mapbase, zilog_irq);
++		printk(KERN_INFO "zs%d: Mouse at MMIO %lx (irq = %d) "
++		       "is a zs\n",
++		       inst, up[1].port.mapbase, zilog_irq);
++#endif
+ 	}
+ 
++
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ 	dev_set_drvdata(&op->dev, &up[0]);
++#endif
+ 
+ 	inst++;
+ 
+ 	return 0;
+ }
+ 
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
+ {
+ 	if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
+@@ -1445,13 +1597,17 @@ static struct of_platform_driver zs_driv
+ 	.probe		= zs_probe,
+ 	.remove		= __devexit_p(zs_remove),
+ };
++#endif /* !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X) */
+ 
+ static int __init sunzilog_init(void)
+ {
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ 	struct device_node *dp;
++#endif
+ 	int err, uart_count;
+ 	int num_keybms;
+ 
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ 	NUM_SUNZILOG = 0;
+ 	num_keybms = 0;
+ 	for_each_node_by_name(dp, "zs") {
+@@ -1459,6 +1615,10 @@ static int __init sunzilog_init(void)
+ 		if (of_find_property(dp, "keyboard", NULL))
+ 			num_keybms++;
+ 	}
++#else
++	NUM_SUNZILOG = 2;
++	num_keybms = 1;
++#endif
+ 
+ 	uart_count = 0;
+ 	if (NUM_SUNZILOG) {
+@@ -1481,6 +1641,7 @@ static int __init sunzilog_init(void)
+ 
+ 		sunserial_current_minor += uart_count;
+ 	}
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ 
+ 	err = of_register_driver(&zs_driver, &of_bus_type);
+ 	if (err)
+@@ -1492,12 +1653,28 @@ static int __init sunzilog_init(void)
+ 		if (err)
+ 			goto out_unregister_driver;
+ 	}
++#else
++
++	zilog_irq = 6;
++	err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_DISABLED,
++			  "zs", sunzilog_irq_chain);
++	if (err)
++		goto out_unregister_uart;
++
++	/* probe for two zs instances on sun3/3x */
++	zs_probe();
++	zs_probe();
++
++
++#endif
+ 
+ out:
+ 	return err;
+ 
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ out_unregister_driver:
+ 	of_unregister_driver(&zs_driver);
++#endif
+ 
+ out_unregister_uart:
+ 	if (NUM_SUNZILOG) {
+@@ -1512,8 +1689,9 @@ out_free_tables:
+ 
+ static void __exit sunzilog_exit(void)
+ {
++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+ 	of_unregister_driver(&zs_driver);
+-
++#endif
+ 	if (zilog_irq != -1) {
+ 		free_irq(zilog_irq, sunzilog_irq_chain);
+ 		zilog_irq = -1;

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/sun3-numints.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/sun3-numints.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,23 @@
+Subject: [PATCH] m68k: Correct number of interrupts for Sun3
+
+From: Sam Creasey <sammy at sammy.net>
+
+Only attempt to initialize the amount of interrupts a sun3 actually has...
+
+Signed-off-by: Sam Creasey <sammy at sammy.net>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/sun3/sun3ints.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/sun3/sun3ints.c
++++ linux-m68k-2.6.21/arch/m68k/sun3/sun3ints.c
+@@ -103,7 +103,7 @@ void sun3_init_IRQ(void)
+ 
+ 	m68k_setup_auto_interrupt(sun3_inthandle);
+ 	m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
+-	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
++	m68k_setup_user_interrupt(VEC_USER, 128, NULL);
+ 
+ 	request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL);
+ 	request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL);

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/unnecessary-m68k_memoffset.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/unnecessary-m68k_memoffset.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,30 @@
+Subject: [PATCH] m68k: Remove unnecessary m68k_memoffset export and init
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+Remove an unnecessary m68k_memoffset export and initialization
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/kernel/setup.c |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/setup.c
++++ linux-m68k-2.6.21/arch/m68k/kernel/setup.c
+@@ -61,7 +61,6 @@ int m68k_num_memory;
+ int m68k_realnum_memory;
+ EXPORT_SYMBOL(m68k_realnum_memory);
+ unsigned long m68k_memoffset;
+-EXPORT_SYMBOL(m68k_memoffset);
+ struct mem_info m68k_memory[NUM_MEMINFO];
+ EXPORT_SYMBOL(m68k_memory);
+ 
+@@ -199,7 +198,6 @@ static void __init m68k_parse_bootinfo(c
+ 		       (m68k_num_memory - 1));
+ 		m68k_num_memory = 1;
+ 	}
+-	m68k_memoffset = m68k_memory[0].addr-PAGE_OFFSET;
+ #endif
+ }
+ 

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/via-pmu68k-dead-code.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/via-pmu68k-dead-code.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,263 @@
+Subject: [PATCH] remove dead code in via-pmu68k
+Cc: Benjamin Herrenschmidt <benh at kernel.crashing.org>
+
+From: Johannes Berg <johannes at sipsolutions.net>
+
+When suspend is ever implemented for pmu68k it really should follow the
+generic pm_ops concept and not mirror the platform-specific /dev/pmu
+device with ioctls on it. Hence, this patch removes the unused code there;
+should the implementers need it they can look at via-pmu.c and/or the
+history of the file.
+
+Signed-off-by: Johannes Berg <johannes at sipsolutions.net
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/macintosh/via-pmu68k.c |  240 -----------------------------------------
+ 1 file changed, 240 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/macintosh/via-pmu68k.c
++++ linux-m68k-2.6.21/drivers/macintosh/via-pmu68k.c
+@@ -818,243 +818,3 @@ pmu_present(void)
+ {
+ 	return (pmu_kind != PMU_UNKNOWN);
+ }
+-
+-#if 0 /* needs some work for 68K */
+-
+-/*
+- * This struct is used to store config register values for
+- * PCI devices which may get powered off when we sleep.
+- */
+-static struct pci_save {
+-	u16	command;
+-	u16	cache_lat;
+-	u16	intr;
+-} *pbook_pci_saves;
+-static int n_pbook_pci_saves;
+-
+-static inline void
+-pbook_pci_save(void)
+-{
+-	int npci;
+-	struct pci_dev *pd = NULL;
+-	struct pci_save *ps;
+-
+-	npci = 0;
+-	while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL)
+-		++npci;
+-	n_pbook_pci_saves = npci;
+-	if (npci == 0)
+-		return;
+-	ps = kmalloc(npci * sizeof(*ps), GFP_KERNEL);
+-	pbook_pci_saves = ps;
+-	if (ps == NULL)
+-		return;
+-
+-	pd = NULL;
+-	while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+-		pci_read_config_word(pd, PCI_COMMAND, &ps->command);
+-		pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat);
+-		pci_read_config_word(pd, PCI_INTERRUPT_LINE, &ps->intr);
+-		++ps;
+-		--npci;
+-	}
+-}
+-
+-static inline void
+-pbook_pci_restore(void)
+-{
+-	u16 cmd;
+-	struct pci_save *ps = pbook_pci_saves;
+-	struct pci_dev *pd = NULL;
+-	int j;
+-
+-	while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+-		if (ps->command == 0)
+-			continue;
+-		pci_read_config_word(pd, PCI_COMMAND, &cmd);
+-		if ((ps->command & ~cmd) == 0)
+-			continue;
+-		switch (pd->hdr_type) {
+-		case PCI_HEADER_TYPE_NORMAL:
+-			for (j = 0; j < 6; ++j)
+-				pci_write_config_dword(pd,
+-					PCI_BASE_ADDRESS_0 + j*4,
+-					pd->resource[j].start);
+-			pci_write_config_dword(pd, PCI_ROM_ADDRESS,
+-			       pd->resource[PCI_ROM_RESOURCE].start);
+-			pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
+-				ps->cache_lat);
+-			pci_write_config_word(pd, PCI_INTERRUPT_LINE,
+-				ps->intr);
+-			pci_write_config_word(pd, PCI_COMMAND, ps->command);
+-			break;
+-			/* other header types not restored at present */
+-		}
+-	}
+-}
+-
+-/*
+- * Put the powerbook to sleep.
+- */
+-#define IRQ_ENABLE	((unsigned int *)0xf3000024)
+-#define MEM_CTRL	((unsigned int *)0xf8000070)
+-
+-int powerbook_sleep(void)
+-{
+-	int ret, i, x;
+-	static int save_backlight;
+-	static unsigned int save_irqen;
+-	unsigned long msr;
+-	unsigned int hid0;
+-	unsigned long p, wait;
+-	struct adb_request sleep_req;
+-
+-	/* Notify device drivers */
+-	ret = blocking_notifier_call_chain(&sleep_notifier_list,
+-			PBOOK_SLEEP, NULL);
+-	if (ret & NOTIFY_STOP_MASK)
+-		return -EBUSY;
+-
+-	/* Sync the disks. */
+-	/* XXX It would be nice to have some way to ensure that
+-	 * nobody is dirtying any new buffers while we wait. */
+-	sys_sync();
+-
+-	/* Turn off the display backlight */
+-	save_backlight = backlight_enabled;
+-	if (save_backlight)
+-		pmu_enable_backlight(0);
+-
+-	/* Give the disks a little time to actually finish writing */
+-	for (wait = jiffies + (HZ/4); time_before(jiffies, wait); )
+-		mb();
+-
+-	/* Disable all interrupts except pmu */
+-	save_irqen = in_le32(IRQ_ENABLE);
+-	for (i = 0; i < 32; ++i)
+-		if (i != vias->intrs[0].line && (save_irqen & (1 << i)))
+-			disable_irq(i);
+-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+-
+-	/* Save the state of PCI config space for some slots */
+-	pbook_pci_save();
+-
+-	/* Set the memory controller to keep the memory refreshed
+-	   while we're asleep */
+-	for (i = 0x403f; i >= 0x4000; --i) {
+-		out_be32(MEM_CTRL, i);
+-		do {
+-			x = (in_be32(MEM_CTRL) >> 16) & 0x3ff;
+-		} while (x == 0);
+-		if (x >= 0x100)
+-			break;
+-	}
+-
+-	/* Ask the PMU to put us to sleep */
+-	pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
+-	while (!sleep_req.complete)
+-		mb();
+-	/* displacement-flush the L2 cache - necessary? */
+-	for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000)
+-		i = *(volatile int *)p;
+-	asleep = 1;
+-
+-	/* Put the CPU into sleep mode */
+-	asm volatile("mfspr %0,1008" : "=r" (hid0) :);
+-	hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;
+-	asm volatile("mtspr 1008,%0" : : "r" (hid0));
+-	local_save_flags(msr);
+-	msr |= MSR_POW | MSR_EE;
+-	local_irq_restore(msr);
+-	udelay(10);
+-
+-	/* OK, we're awake again, start restoring things */
+-	out_be32(MEM_CTRL, 0x3f);
+-	pbook_pci_restore();
+-
+-	/* wait for the PMU interrupt sequence to complete */
+-	while (asleep)
+-		mb();
+-
+-	/* reenable interrupts */
+-	for (i = 0; i < 32; ++i)
+-		if (i != vias->intrs[0].line && (save_irqen & (1 << i)))
+-			enable_irq(i);
+-
+-	/* Notify drivers */
+-	blocking_notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL);
+-
+-	/* reenable ADB autopoll */
+-	pmu_adb_autopoll(adb_dev_map);
+-
+-	/* Turn on the screen backlight, if it was on before */
+-	if (save_backlight)
+-		pmu_enable_backlight(1);
+-
+-	/* Wait for the hard disk to spin up */
+-
+-	return 0;
+-}
+-
+-/*
+- * Support for /dev/pmu device
+- */
+-static int pmu_open(struct inode *inode, struct file *file)
+-{
+-	return 0;
+-}
+-
+-static ssize_t pmu_read(struct file *file, char *buf,
+-			size_t count, loff_t *ppos)
+-{
+-	return 0;
+-}
+-
+-static ssize_t pmu_write(struct file *file, const char *buf,
+-			 size_t count, loff_t *ppos)
+-{
+-	return 0;
+-}
+-
+-static int pmu_ioctl(struct inode * inode, struct file *filp,
+-		     u_int cmd, u_long arg)
+-{
+-	int error;
+-	__u32 value;
+-
+-	switch (cmd) {
+-	    case PMU_IOC_SLEEP:
+-	    	return -ENOSYS;
+-	    case PMU_IOC_GET_BACKLIGHT:
+-		return put_user(backlight_level, (__u32 *)arg);
+-	    case PMU_IOC_SET_BACKLIGHT:
+-		error = get_user(value, (__u32 *)arg);
+-		if (!error)
+-			pmu_set_brightness(value);
+-		return error;
+-	    case PMU_IOC_GET_MODEL:
+-	    	return put_user(pmu_kind, (__u32 *)arg);
+-	}
+-	return -EINVAL;
+-}
+-
+-static const struct file_operations pmu_device_fops = {
+-	.read		= pmu_read,
+-	.write		= pmu_write,
+-	.ioctl		= pmu_ioctl,
+-	.open		= pmu_open,
+-};
+-
+-static struct miscdevice pmu_device = {
+-	PMU_MINOR, "pmu", &pmu_device_fops
+-};
+-
+-void pmu_device_init(void)
+-{
+-	if (!via)
+-		return;
+-	if (misc_register(&pmu_device) < 0)
+-		printk(KERN_ERR "via-pmu68k: cannot register misc device.\n");
+-}
+-#endif /* CONFIG_PMAC_PBOOK */
+-

Added: dists/trunk/linux-2.6/debian/patches/bugfix/m68k/zorro-resource_size_t-warnings.diff
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/m68k/zorro-resource_size_t-warnings.diff	Fri May 11 21:14:58 2007
@@ -0,0 +1,50 @@
+Subject: [PATCH] Amiga Zorro bus: kill resource_size_t warnings
+
+Kill resource_size_t warnings by casting resource_size_t to unsigned long when
+formatting Zorro bus resources, as they are always 32-bit.
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/zorro/proc.c        |    5 +++--
+ drivers/zorro/zorro-sysfs.c |    3 ++-
+ drivers/zorro/zorro.c       |    3 ++-
+ 3 files changed, 7 insertions(+), 4 deletions(-)
+
+--- linux-m68k-2.6.21.orig/drivers/zorro/proc.c
++++ linux-m68k-2.6.21/drivers/zorro/proc.c
+@@ -90,8 +90,9 @@ get_zorro_dev_info(char *buf, char **sta
+ 	for (slot = cnt = 0; slot < zorro_num_autocon && count > cnt; slot++) {
+ 		struct zorro_dev *z = &zorro_autocon[slot];
+ 		len = sprintf(buf, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot,
+-			      z->id, zorro_resource_start(z),
+-			      zorro_resource_len(z), z->rom.er_Type);
++			      z->id, (unsigned long)zorro_resource_start(z),
++			      (unsigned long)zorro_resource_len(z),
++			      z->rom.er_Type);
+ 		at += len;
+ 		if (at >= pos) {
+ 			if (!*start) {
+--- linux-m68k-2.6.21.orig/drivers/zorro/zorro-sysfs.c
++++ linux-m68k-2.6.21/drivers/zorro/zorro-sysfs.c
+@@ -42,7 +42,8 @@ static ssize_t zorro_show_resource(struc
+ 	struct zorro_dev *z = to_zorro_dev(dev);
+ 
+ 	return sprintf(buf, "0x%08lx 0x%08lx 0x%08lx\n",
+-		       zorro_resource_start(z), zorro_resource_end(z),
++		       (unsigned long)zorro_resource_start(z),
++		       (unsigned long)zorro_resource_end(z),
+ 		       zorro_resource_flags(z));
+ }
+ 
+--- linux-m68k-2.6.21.orig/drivers/zorro/zorro.c
++++ linux-m68k-2.6.21/drivers/zorro/zorro.c
+@@ -164,7 +164,8 @@ static int __init zorro_init(void)
+ 	if (request_resource(zorro_find_parent_resource(z), &z->resource))
+ 	    printk(KERN_ERR "Zorro: Address space collision on device %s "
+ 		   "[%lx:%lx]\n",
+-		   z->name, zorro_resource_start(z), zorro_resource_end(z));
++		   z->name, (unsigned long)zorro_resource_start(z),
++		   (unsigned long)zorro_resource_end(z));
+ 	sprintf(z->dev.bus_id, "%02x", i);
+ 	z->dev.parent = &zorro_bus.dev;
+ 	z->dev.bus = &zorro_bus_type;



More information about the Kernel-svn-changes mailing list