Date: Mon, 13 Jul 1998 00:39:43 +0200 (CEST)
From: Geert Uytterhoeven <Geert.Uytterhoeven@cs.kuleuven.ac.be>
To: Linux/m68k <linux-m68k@lists.linux-m68k.org>
cc: Jes Sorensen <Jes.Sorensen@cern.ch>
Subject: Re: L68K: 2.1.108
In-Reply-To: <Pine.LNX.3.96.980712204605.3853A-100000@hexe.eth.bha.privat>
Sender: owner-linux-m68k@phil.uni-sb.de

On Sun, 12 Jul 1998, Bernd Harries wrote:
> just a short preliminary result after make of 2.1.108 on a MACH_ATARI:
> 
> make[1]: Leaving directory `/usr/src/linux-2.1.108_JES/arch/m68k/fpsp040'
> ld -m m68kelf -T /usr/src/linux/arch/m68k/vmlinux.lds
> arch/m68k/kernel/head.o init/main.o init/version.o \
>         arch/m68k/kernel/kernel.o arch/m68k/mm/mm.o kernel/kernel.o
> mm/mm.o fs/fs.o ipc/ipc.o arch/m68k/atari/atari.o arch/m68k/fpsp040/fpsp.o
> \
>         fs/filesystems.a \
>         net/network.a \
>         drivers/block/block.a drivers/char/char.a drivers/misc/misc.a
> drivers/net/net.a drivers/scsi/scsi.a drivers/cdrom/cdrom.a
> drivers/video/video.a drivers/video/video.a \
>         /usr/src/linux/lib/lib.a arch/m68k/lib/lib.a \
>         -o vmlinux
> arch/m68k/atari/atari.o: In function `atari_keyb_init':
> arch/m68k/atari/atari.o(.text.init+0xe92): undefined reference to
> `mach_keyboard_type'
> drivers/block/block.a(ide.o): In function `probe_hwif':
> ide.o(.text+0x4a): undefined reference to `falconide_probe_hwif'
> make: *** [vmlinux] Error 1
> Hexe:/usr/src/linux/>

drivers/block/Makefile is severely broken w.r.t. IDE. This is fixed by the
following patch, among other things:

  - remove double occurrencies (Makefile, drivers/Makefile,
    drivers/char/mac_SCC.[ch])
  - partition table patches (by Roman Hodek and Russell King)
  - APNE driver (by Alain Malek)
  - kbd_reset_setup patches (by Geert Stappers, IIRC)
  - STRAM patches (by Andreas Schwab)
  - dummy_con fixes
  - update drivers/char/console.c and include/linux/console.h (from vger)
  - update drivers/char/fbmem.c and drivers/video (from vger):
      o promfb is dead, promcon is alive (by Eddie C. Dost and Jakub Jelinek)
      o CT65550 frame buffer device (by Paul Mackerras)
      o fbcon-cfb24 works (verified with beta atyfb)
      o 
  - TTY fixes (by Andreas Schwab)
  - Dmasound fixes (by Andreas Schwab)
  - Ext2 fix (by Andreas Schwab)
  - Make kmod work again by flushing the ATC (forgot the author of this patch)

Caveats:

  - the Penguin colors are wrong. I think it has to do with the set_palette()
    in drivers/char/fbmem.c. Same on PPC.

BTW, if anyone finds scrollback keys on his/her Amiga, scrollback should work
now with both panning and wrapping, assumed you have a virtual screen.

diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/Makefile m68k/Makefile
--- jes-2.1.108/Makefile	Fri Jul 10 19:10:58 1998
+++ m68k/Makefile	Sun Jul 12 20:44:01 1998
@@ -161,10 +161,6 @@
 DRIVERS := $(DRIVERS) drivers/video/video.a
 endif
 
-ifdef CONFIG_VT
-DRIVERS := $(DRIVERS) drivers/video/video.a
-endif
-
 ifeq ($(CONFIG_PARIDE),y)
 DRIVERS := $(DRIVERS) drivers/block/paride/paride.a
 endif
@@ -329,18 +325,19 @@
 		echo Installing modules under $$MODLIB/$$2; \
 	}; \
 	\
-	if [ -f BLOCK_MODULES ]; then inst_mod BLOCK_MODULES block; fi; \
-	if [ -f NET_MODULES   ]; then inst_mod NET_MODULES   net;   fi; \
-	if [ -f IPV4_MODULES  ]; then inst_mod IPV4_MODULES  ipv4;  fi; \
-	if [ -f IPV6_MODULES  ]; then inst_mod IPV6_MODULES  ipv6;  fi; \
-	if [ -f SCSI_MODULES  ]; then inst_mod SCSI_MODULES  scsi;  fi; \
-	if [ -f FS_MODULES    ]; then inst_mod FS_MODULES    fs;    fi; \
-	if [ -f NLS_MODULES   ]; then inst_mod NLS_MODULES   fs;    fi; \
-	if [ -f CDROM_MODULES ]; then inst_mod CDROM_MODULES cdrom; fi; \
-	if [ -f VIDEO_MODULES ]; then inst_mod VIDEO_MODULES video; fi; \
-	if [ -f HAM_MODULES   ]; then inst_mod HAM_MODULES   net;   fi; \
-	if [ -f SOUND_MODULES ]; then inst_mod SOUND_MODULES sound; fi; \
-	if [ -f FC4_MODULES   ]; then inst_mod FC4_MODULES   fc4;   fi; \
+	if [ -f BLOCK_MODULES  ]; then inst_mod BLOCK_MODULES  block;  fi; \
+	if [ -f NET_MODULES    ]; then inst_mod NET_MODULES    net;    fi; \
+	if [ -f IPV4_MODULES   ]; then inst_mod IPV4_MODULES   ipv4;   fi; \
+	if [ -f IPV6_MODULES   ]; then inst_mod IPV6_MODULES   ipv6;   fi; \
+	if [ -f SCSI_MODULES   ]; then inst_mod SCSI_MODULES   scsi;   fi; \
+	if [ -f FS_MODULES     ]; then inst_mod FS_MODULES     fs;     fi; \
+	if [ -f NLS_MODULES    ]; then inst_mod NLS_MODULES    fs;     fi; \
+	if [ -f PARTBL_MODULES ]; then inst_mod PARTBL_MODULES partbl; fi; \
+	if [ -f CDROM_MODULES  ]; then inst_mod CDROM_MODULES  cdrom;  fi; \
+	if [ -f VIDEO_MODULES  ]; then inst_mod VIDEO_MODULES  video;  fi; \
+	if [ -f HAM_MODULES    ]; then inst_mod HAM_MODULES    net;    fi; \
+	if [ -f SOUND_MODULES  ]; then inst_mod SOUND_MODULES  sound;  fi; \
+	if [ -f FC4_MODULES    ]; then inst_mod FC4_MODULES    fc4;    fi; \
 	\
 	ls *.o > .allmods; \
 	echo $$MODULES | tr ' ' '\n' | sort | comm -23 .allmods - > .misc; \
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/amiga/Makefile m68k/arch/m68k/amiga/Makefile
--- jes-2.1.108/arch/m68k/amiga/Makefile	Mon Jun  8 20:45:17 1998
+++ m68k/arch/m68k/amiga/Makefile	Thu Jul  9 20:25:31 1998
@@ -11,4 +11,8 @@
 O_OBJS   := config.o amiints.o cia.o chipram.o amisound.o
 OX_OBJS  := amiga_ksyms.o
 
+ifdef CONFIG_AMIGA_PCMCIA
+O_OBJS := $(O_OBJS) pcmcia.o
+endif
+
 include $(TOPDIR)/Rules.make
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/amiga/amiga_ksyms.c m68k/arch/m68k/amiga/amiga_ksyms.c
--- jes-2.1.108/arch/m68k/amiga/amiga_ksyms.c	Thu Jun 18 20:52:52 1998
+++ m68k/arch/m68k/amiga/amiga_ksyms.c	Thu Jul  9 20:25:31 1998
@@ -2,6 +2,7 @@
 #include <linux/types.h>
 #include <linux/zorro.h>
 #include <asm/amigahw.h>
+#include <asm/amipcmcia.h>
 
 extern volatile u_short amiga_audio_min_period;
 extern u_short amiga_audio_period;
@@ -19,3 +20,12 @@
 EXPORT_SYMBOL(amiga_chip_size);
 EXPORT_SYMBOL(amiga_audio_period);
 EXPORT_SYMBOL(amiga_audio_min_period);
+
+#ifdef CONFIG_AMIGA_PCMCIA
+  EXPORT_SYMBOL(pcmcia_reset);
+  EXPORT_SYMBOL(pcmcia_copy_tuple);
+  EXPORT_SYMBOL(pcmcia_program_voltage);
+  EXPORT_SYMBOL(pcmcia_access_speed);
+  EXPORT_SYMBOL(pcmcia_write_enable);
+  EXPORT_SYMBOL(pcmcia_write_disable);
+#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/amiga/amiints.c m68k/arch/m68k/amiga/amiints.c
--- jes-2.1.108/arch/m68k/amiga/amiints.c	Sun Feb  8 23:14:43 1998
+++ m68k/arch/m68k/amiga/amiints.c	Sun Jul 12 21:34:56 1998
@@ -32,6 +32,7 @@
 #include <asm/traps.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
+#include <asm/amipcmcia.h>
 
 extern int cia_request_irq(struct ciabase *base,int irq,
                            void (*handler)(int, void *, struct pt_regs *),
@@ -88,6 +89,10 @@
 	}
 	for (i = 0; i < AMI_IRQS; i++)
 		ami_ablecount[i] = 0;
+
+	/* turn off PCMCIA interrupts */
+	if (AMIGAHW_PRESENT(PCMCIA))
+		pcmcia_disable_irq();
 
 	/* turn off all interrupts and enable the master interrupt bit */
 	custom.intena = 0x7fff;
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/amiga/config.c m68k/arch/m68k/amiga/config.c
--- jes-2.1.108/arch/m68k/amiga/config.c	Fri Jul 10 19:11:00 1998
+++ m68k/arch/m68k/amiga/config.c	Sun Jul 12 21:34:56 1998
@@ -51,6 +51,7 @@
 /* amiga specific keyboard functions */
 extern int amiga_keyb_init(void);
 extern int amiga_kbdrate (struct kbd_repeat *);
+extern void amiga_kbd_reset_setup(char*, int);
 /* amiga specific irq functions */
 extern void amiga_init_IRQ (void);
 extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *);
@@ -341,6 +342,7 @@
   mach_sched_init      = amiga_sched_init;
   mach_keyb_init       = amiga_keyb_init;
   mach_kbdrate         = amiga_kbdrate;
+  kbd_reset_setup      = amiga_kbd_reset_setup;
   mach_init_IRQ        = amiga_init_IRQ;
   mach_default_handler = &amiga_default_handler;
   mach_request_irq     = amiga_request_irq;
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/amiga/pcmcia.c m68k/arch/m68k/amiga/pcmcia.c
--- jes-2.1.108/arch/m68k/amiga/pcmcia.c	Thu Jan  1 01:00:00 1970
+++ m68k/arch/m68k/amiga/pcmcia.c	Thu Jul  9 20:25:31 1998
@@ -0,0 +1,114 @@
+
+/*
+** asm-m68k/pcmcia.h -- Amiga Linux PCMCIA support
+**                      most information was found by disassembling card.resource
+**                      I'm still looking for an official doc !
+**
+** Copyright 1997 by Alain Malek
+**
+** 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.
+**
+** Created: 12/10/97 by Alain Malek
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <asm/amigayle.h>
+#include <asm/amipcmcia.h>
+
+/* gayle config byte for program voltage and access speed */
+static u_char cfg_byte = GAYLE_CFG_0V|GAYLE_CFG_150NS;
+
+void pcmcia_reset(void)
+{
+	unsigned long reset_start_time = jiffies;
+	unsigned char b;
+
+	gayle_reset = 0x00;
+	while (jiffies - reset_start_time < 1*HZ/100);
+	b = gayle_reset;
+}
+
+
+/* copy a tuple, including tuple header. return nb bytes copied */
+/* be carefull as this may trigger a GAYLE_IRQ_WR interrupt ! */
+
+int pcmcia_copy_tuple(unsigned char tuple_id, void *tuple, int max_len)
+{
+	unsigned char id, *dest;
+	int cnt, pos, len;
+
+	dest = tuple;
+	pos = 0;
+
+	id = gayle_attribute[pos];
+
+	while((id != CISTPL_END) && (pos < 0x10000)) {
+		len = (int)gayle_attribute[pos+2] + 2;
+		if (id == tuple_id) {
+			len = (len > max_len)?max_len:len;
+			for (cnt = 0; cnt < len; cnt++) {
+				*dest++ = gayle_attribute[pos+(cnt<<1)];
+			}
+
+			return len;
+		}
+		pos += len<<1;
+		id = gayle_attribute[pos];
+	}
+
+	return 0;
+}
+
+void pcmcia_program_voltage(int voltage)
+{
+	u_char v;
+
+	switch (voltage) {
+	case PCMCIA_0V:
+		v = GAYLE_CFG_0V;
+		break;
+	case PCMCIA_5V:
+		v = GAYLE_CFG_5V;
+		break;
+	case PCMCIA_12V:
+		v = GAYLE_CFG_12V;
+		break;
+	default:
+		v = GAYLE_CFG_0V;
+	}
+
+	cfg_byte = (cfg_byte & 0xfc) | v;
+	gayle.config = cfg_byte;
+
+}
+
+void pcmcia_access_speed(int speed)
+{
+	u_char s;
+
+	if (speed <= PCMCIA_SPEED_100NS)
+		s = GAYLE_CFG_100NS;
+	else if (speed <= PCMCIA_SPEED_150NS)
+		s = GAYLE_CFG_150NS;
+	else if (speed <= PCMCIA_SPEED_250NS)
+		s = GAYLE_CFG_250NS;
+	else
+		s = GAYLE_CFG_720NS;
+
+	cfg_byte = (cfg_byte & 0xf3) | s;
+	gayle.config = cfg_byte;
+}
+
+void pcmcia_write_enable(void)
+{
+	gayle.cardstatus = GAYLE_CS_WR|GAYLE_CS_DA;
+}
+
+void pcmcia_write_disable(void)
+{
+	gayle.cardstatus = 0;
+}
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/atari/atakeyb.c m68k/arch/m68k/atari/atakeyb.c
--- jes-2.1.108/arch/m68k/atari/atakeyb.c	Thu May 14 21:34:07 1998
+++ m68k/arch/m68k/atari/atakeyb.c	Sun Jun 14 22:18:24 1998
@@ -864,6 +864,6 @@
 }
 
 /* for "kbd-reset" cmdline param */
-__initfunc(void kbd_reset_setup(char *str, int *ints))
+__initfunc(void atari_kbd_reset_setup(char *str, int *ints))
 {
 }
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/atari/config.c m68k/arch/m68k/atari/config.c
--- jes-2.1.108/arch/m68k/atari/config.c	Fri Jul 10 19:11:00 1998
+++ m68k/arch/m68k/atari/config.c	Sun Jul 12 20:28:48 1998
@@ -59,6 +59,7 @@
 extern int atari_keyb_init(void);
 extern int atari_kbdrate (struct kbd_repeat *);
 extern void atari_kbd_leds (unsigned int);
+extern void atari_kbd_reset_setup(char*, int);
 /* atari specific irq functions */
 extern void atari_init_IRQ (void);
 extern int atari_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
@@ -249,6 +250,7 @@
     mach_keyb_init       = atari_keyb_init;
     mach_kbdrate         = atari_kbdrate;
     mach_kbd_leds        = atari_kbd_leds;
+    kbd_reset_setup      = atari_kbd_reset_setup;
     mach_init_IRQ        = atari_init_IRQ;
     mach_request_irq     = atari_request_irq;
     mach_free_irq        = atari_free_irq;
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/atari/stram.c m68k/arch/m68k/atari/stram.c
--- jes-2.1.108/arch/m68k/atari/stram.c	Mon Jun  8 20:45:18 1998
+++ m68k/arch/m68k/atari/stram.c	Mon Jun 29 21:29:20 1998
@@ -826,18 +826,23 @@
 						   unsigned long page, int isswap )
 {
 	struct vm_area_struct* vma;
+	int retval = 0;
 
 	/*
 	 * Go through process' page directory.
 	 */
 	if (!mm || mm == &init_mm)
 		return 0;
+	down(&mm->mmap_sem);
 	for( vma = mm->mmap; vma; vma = vma->vm_next ) {
 		pgd_t * pgd = pgd_offset(mm, vma->vm_start);
-		if (unswap_vma( vma, pgd, entry, page, isswap ))
-			return 1;
+		if (unswap_vma( vma, pgd, entry, page, isswap )) {
+			retval = 1;
+			break;
+		}
 	}
-	return 0;
+	up(&mm->mmap_sem);
+	return retval;
 }
 
 
@@ -1160,7 +1165,7 @@
 
 
 /* setup parameters from command line */
-void stram_swap_setup( char *str, int *ints )
+__initfunc(void stram_swap_setup(char *str, int *ints))
 {
 	if (ints[0] >= 1)
 		max_swap_size = ((ints[1] < 0 ? 0 : ints[1]) * 1024) & PAGE_MASK;
@@ -1256,7 +1261,7 @@
         block_fsync             /* fsync */
 };
 
-int stram_device_init( void )
+__initfunc(int stram_device_init(void))
 {
 
     if (!MACH_IS_ATARI)
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/config.in m68k/arch/m68k/config.in
--- jes-2.1.108/arch/m68k/config.in	Fri Jul 10 19:11:00 1998
+++ m68k/arch/m68k/config.in	Sun Jul 12 20:28:39 1998
@@ -82,6 +82,9 @@
 
 if [ "$CONFIG_AMIGA" = "y" ]; then
   bool 'Amiga Zorro (AutoConfig) bus support' CONFIG_ZORRO
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    bool 'Amiga 1200/600 PCMCIA support' CONFIG_AMIGA_PCMCIA
+  fi
 fi
 if [ "$CONFIG_ATARI" = "y" ]; then
   bool 'Support for ST-RAM as swap space' CONFIG_STRAM_SWAP
@@ -206,6 +209,9 @@
   tristate 'Ariadne support' CONFIG_ARIADNE
   tristate 'A2065 support' CONFIG_A2065
   tristate 'Hydra support' CONFIG_HYDRA
+  if [ "$CONFIG_AMIGA_PCMCIA" = "y" ]; then
+    tristate 'PCMCIA NE2000 support' CONFIG_APNE
+  fi
 fi
 if [ "$CONFIG_APOLLO" = "y" ] ; then
   tristate 'Apollo 3c505 support' CONFIG_APOLLO_ELPLUS
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/defconfig m68k/arch/m68k/defconfig
--- jes-2.1.108/arch/m68k/defconfig	Mon May  4 20:28:32 1998
+++ m68k/arch/m68k/defconfig	Thu Jul  9 20:25:31 1998
@@ -45,6 +45,7 @@
 # CONFIG_AMIGA_GSP is not set
 # CONFIG_GSP_RESOLVER is not set
 # CONFIG_GSP_A2410 is not set
+# CONFIG_AMIGA_PCMCIA is not set
 # CONFIG_HEARTBEAT is not set
 CONFIG_PROC_HARDWARE=y
 
@@ -148,6 +149,7 @@
 # CONFIG_ARIADNE is not set
 # CONFIG_A2065 is not set
 # CONFIG_HYDRA is not set
+# CONFIG_APNE is not set
 # CONFIG_ATARILANCE is not set
 # CONFIG_ATARI_BIONET is not set
 # CONFIG_ATARI_PAMSNET is not set
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/hp300/config.c m68k/arch/m68k/hp300/config.c
--- jes-2.1.108/arch/m68k/hp300/config.c	Fri Jul 10 19:11:00 1998
+++ m68k/arch/m68k/hp300/config.c	Sun Jul 12 20:37:43 1998
@@ -66,7 +66,7 @@
 #ifdef CONFIG_HEARTBEAT
   mach_heartbeat       = hp300_pulse;
 #endif
-#ifdef CONFIG_FB
+#ifdef CONFIG_DUMMY_CONSOLE
   conswitchp	       = &dummy_con;
 #endif
   mach_max_dma_address = 0xffffffff;
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/kernel/setup.c m68k/arch/m68k/kernel/setup.c
--- jes-2.1.108/arch/m68k/kernel/setup.c	Mon Jun  8 20:45:27 1998
+++ m68k/arch/m68k/kernel/setup.c	Sun Jul 12 21:34:56 1998
@@ -61,6 +61,8 @@
 int (*mach_keyb_init) (void) __initdata;
 int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
 void (*mach_kbd_leds) (unsigned int) = NULL;
+/* machine dependent "kbd-reset" setup function */
+void (*kbd_reset_setup) (char *, int) __initdata = NULL;
 /* machine dependent irq functions */
 void (*mach_init_IRQ) (void) __initdata;
 void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/mac/config.c m68k/arch/m68k/mac/config.c
--- jes-2.1.108/arch/m68k/mac/config.c	Fri Jul 10 19:11:00 1998
+++ m68k/arch/m68k/mac/config.c	Sun Jul 12 21:34:56 1998
@@ -63,6 +63,7 @@
 extern int mac_keyb_init(void);
 extern int mac_kbdrate(struct kbd_repeat *k);
 extern void mac_kbd_leds(unsigned int leds);
+extern void mac_kbd_reset_setup(char*, int);
 
 extern void (*kd_mksound)(unsigned int, unsigned int);
 extern void mac_mksound(unsigned int, unsigned int);
@@ -258,6 +259,7 @@
     mach_keyb_init       = mac_keyb_init;
     mach_kbdrate         = mac_kbdrate;
     mach_kbd_leds        = mac_kbd_leds;
+    kbd_reset_setup      = mac_kbd_reset_setup;
     mach_init_IRQ        = mac_init_IRQ;
     mach_request_irq     = mac_request_irq;
     mach_free_irq        = mac_free_irq;
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/arch/m68k/mac/mackeyb.c m68k/arch/m68k/mac/mackeyb.c
--- jes-2.1.108/arch/m68k/mac/mackeyb.c	Thu May 14 21:34:08 1998
+++ m68k/arch/m68k/mac/mackeyb.c	Sun Jun 14 22:18:24 1998
@@ -750,3 +750,8 @@
 
 	return 0;
 }
+
+/* for "kbd-reset" cmdline param */
+__initfunc(void mac_kbd_reset_setup(char *str, int *ints))
+{
+}
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/Makefile m68k/drivers/Makefile
--- jes-2.1.108/drivers/Makefile	Fri Jul 10 19:11:00 1998
+++ m68k/drivers/Makefile	Sun Jul 12 20:44:01 1998
@@ -38,11 +38,6 @@
 MOD_SUB_DIRS += video
 endif
 
-ifdef CONFIG_VT
-SUB_DIRS += video
-MOD_SUB_DIRS += video
-endif
-
 ifdef CONFIG_PPC
 SUB_DIRS += macintosh
 MOD_SUB_DIRS += macintosh
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/block/Makefile m68k/drivers/block/Makefile
--- jes-2.1.108/drivers/block/Makefile	Fri Jul 10 19:11:00 1998
+++ m68k/drivers/block/Makefile	Mon Jul 13 00:00:08 1998
@@ -20,68 +20,22 @@
 
 
 L_TARGET := block.a
-L_OBJS   := 
+L_OBJS   := genhd.o
 M_OBJS   :=
 MOD_LIST_NAME := BLOCK_MODULES
-LX_OBJS := ll_rw_blk.o genhd.o
+LX_OBJS := ll_rw_blk.o
 MX_OBJS :=
 
-IDE_OBJS :=
-
-ifeq ($(CONFIG_MSDOS_PARTITION),y)
-  L_OBJS += partbl_msdos.o
-else
-  ifeq ($(CONFIG_MSDOS_PARTITION),m)
-    M_OBJS += partbl_msdos.o
-  endif
-endif
-
-ifeq ($(CONFIG_OSF_PARTITION),y)
-  L_OBJS += partbl_osf.o
-else
-  ifeq ($(CONFIG_OSF_PARTITION),m)
-    M_OBJS += partbl_osf.o
-  endif
-endif
-
-ifeq ($(CONFIG_SUN_PARTITION),y)
-  L_OBJS += partbl_sun.o
-else
-  ifeq ($(CONFIG_SUN_PARTITION),m)
-    M_OBJS += partbl_sun.o
-  endif
-endif
-
-ifeq ($(CONFIG_AMIGA_PARTITION),y)
-  L_OBJS += partbl_amiga.o
-else
-  ifeq ($(CONFIG_AMIGA_PARTITION),m)
-    M_OBJS += partbl_amiga.o
-  endif
-endif
-
-ifeq ($(CONFIG_ATARI_PARTITION),y)
-  L_OBJS += partbl_atari.o
-else
-  ifeq ($(CONFIG_ATARI_PARTITION),m)
-    M_OBJS += partbl_atari.o
-  endif
-endif
-
-ifeq ($(CONFIG_MAC_PARTITION),y)
-  L_OBJS += partbl_mac.o
-else
-  ifeq ($(CONFIG_MAC_PARTITION),m)
-    M_OBJS += partbl_mac.o
-  endif
-endif
-
 ifeq ($(CONFIG_MAC_FLOPPY),y)
 L_OBJS += swim3.o
 endif
 
 ifeq ($(CONFIG_MAC_FLOPPY_IWM),y)
-L_OBJS += iwm.o
+ L_OBJS += iwm.o
+else
+  ifeq ($(CONFIG_MAC_FLOPPY_IWM),m)
+  M_OBJS += iwm.o
+  endif
 endif
 
 ifeq ($(CONFIG_BLK_DEV_FD),y)
@@ -108,14 +62,6 @@
   endif
 endif
 
-ifeq ($(CONFIG_MAC_FLOPPY_IWM),y)
- L_OBJS += iwm.o
-else
-  ifeq ($(CONFIG_MAC_FLOPPY_IWM),m)
-  M_OBJS += iwm.o
-  endif
-endif
-
 ifeq ($(CONFIG_ATARI_ACSI),y)
   LX_OBJS += acsi.o
 else
@@ -160,23 +106,6 @@
 L_OBJS += hd.o
 endif
 
-ifeq ($(CONFIG_BLK_DEV_IDE),y)
-  LX_OBJS += ide.o
-  ifeq ($(CONFIG_PROC_FS),y)
-    L_OBJS += ide-proc.o
-  endif
-  L_OBJS += ide-probe.o
-else
-  ifeq ($(CONFIG_BLK_DEV_IDE),m)
-  MIX_OBJS += ide.o
-  ifeq ($(CONFIG_PROC_FS),y)
-    M_OBJS += ide-proc.o
-  endif
-  M_OBJS += ide-mod.o
-  MX_OBJS += ide-probe.o
-  endif
-endif
-
 ifeq ($(CONFIG_BLK_DEV_RZ1000),y)
 IDE_OBJS += rz1000.o
 endif
@@ -229,6 +158,14 @@
 IDE_OBJS += ns87415.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_CMD646),y)
+IDE_OBJS += cmd646.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_SL82C105),y)
+IDE_OBJS += sl82c105.o
+endif
+
 ifeq ($(CONFIG_BLK_DEV_PCIDE),y)
 IDE_OBJS += pcide.o
 endif
@@ -249,14 +186,26 @@
 IDE_OBJS += buddha.o
 endif
 
-ifeq ($(CONFIG_BLK_DEV_CMD646),y)
-L_OBJS += cmd646.o
+### if CONFIG_BLK_DEV_IDE is n, IDE_OBJS will be ignored
+
+ifeq ($(CONFIG_PROC_FS),y)
+IDE_OBJS += ide-proc.o
 endif
+  
+###Collect
 
-ifeq ($(CONFIG_BLK_DEV_SL82C105),y)
-L_OBJS += sl82c105.o
+ifeq ($(CONFIG_BLK_DEV_IDE),y)
+  LX_OBJS += ide.o
+  L_OBJS += ide-probe.o $(IDE_OBJS)
+else
+  ifeq ($(CONFIG_BLK_DEV_IDE),m)
+  MIX_OBJS += ide.o $(IDE_OBJS)
+  M_OBJS += ide-mod.o ide-probe.o
+  endif
 endif
 
+############
+
 ifeq ($(CONFIG_BLK_DEV_IDEDISK),y)
 L_OBJS += ide-disk.o
 else
@@ -357,5 +306,5 @@
 
 include $(TOPDIR)/Rules.make
 
-ide-mod.o: ide.o ide-proc.o
-	$(LD) $(LD_RFLAG) -r -o $@ ide.o ide-proc.o
+ide-mod.o: ide.o $(IDE_OBJS)
+	$(LD) $(LD_RFLAG) -r -o $@ ide.o $(IDE_OBJS)
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/block/genhd.c m68k/drivers/block/genhd.c
--- jes-2.1.108/drivers/block/genhd.c	Fri Jul 10 19:11:01 1998
+++ m68k/drivers/block/genhd.c	Sun Jul 12 23:41:18 1998
@@ -17,8 +17,8 @@
  *
  *  Check partition table on IDE disks for common CHS translations
  *
- *  Moved partition table parsers into separate files and modularized them
- *  (10/08/97 Roman Hodek)
+ *  Moved partition table parsers to fs/partitions and modularized them
+ *  (10/08/97 Roman Hodek, Russell King)
  */
 
 #include <linux/config.h>
@@ -30,15 +30,16 @@
 #include <linux/string.h>
 #include <linux/blk.h>
 #include <linux/init.h>
-#ifdef CONFIG_PROC_FS
-#include <linux/proc_fs.h>
-#endif
 
 #include <asm/system.h>
 
+/* defined in fs/partitions/check.c */
+extern void partbl_init( void );
+extern void check_partition(struct gendisk *hd, kdev_t dev, int first_minor);
+
+
 struct gendisk *gendisk_head = NULL;
 
-int current_minor = 0;
 extern int *blk_size[];
 extern void rd_load(void);
 extern void initrd_load(void);
@@ -48,363 +49,6 @@
 extern int scsi_dev_init(void);
 extern int net_dev_init(void);
 
-struct partition_parser *partition_parsers = NULL;
-
-/*
- * disk_name() is used by genhd.c and md.c.
- * It formats the devicename of the indicated disk
- * into the supplied buffer, and returns a pointer
- * to that same buffer (for convenience).
- */
-char *disk_name (struct gendisk *hd, int minor, char *buf)
-{
-	unsigned int part;
-	const char *maj = hd->major_name;
-	char unit = (minor >> hd->minor_shift) + 'a';
-
-	/*
-	 * IDE devices use multiple major numbers, but the drives
-	 * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
-	 * This requires special handling here.
-	 */
-	switch (hd->major) {
-		case IDE3_MAJOR:
-			unit += 2;
-		case IDE2_MAJOR:
-			unit += 2;
-		case IDE1_MAJOR:
-			unit += 2;
-		case IDE0_MAJOR:
-			maj = "hd";
-	}
-	part = minor & ((1 << hd->minor_shift) - 1);
-	if (part)
-		sprintf(buf, "%s%c%d", maj, unit, part);
-	else
-		sprintf(buf, "%s%c", maj, unit);
-	return buf;
-}
-
-void add_partition (struct gendisk *hd, int minor, int start, int size)
-{
-	char buf[8];
-	hd->part[minor].start_sect = start;
-	hd->part[minor].nr_sects   = size;
-	printk(" %s", disk_name(hd, minor, buf));
-}
-
-unsigned int get_ptable_blocksize(kdev_t dev)
-{
-  int ret = 1024;
-
-  /*
-   * See whether the low-level driver has given us a minumum blocksize.
-   * If so, check to see whether it is larger than the default of 1024.
-   */
-  if (!blksize_size[MAJOR(dev)])
-    {
-      return ret;
-    }
-
-  /*
-   * Check for certain special power of two sizes that we allow.
-   * With anything larger than 1024, we must force the blocksize up to
-   * the natural blocksize for the device so that we don't have to try
-   * and read partial sectors.  Anything smaller should be just fine.
-   */
-  switch( blksize_size[MAJOR(dev)][MINOR(dev)] )
-    {
-    case 2048:
-      ret = 2048;
-      break;
-    case 4096:
-      ret = 4096;
-      break;
-    case 8192:
-      ret = 8192;
-      break;
-    case 1024:
-    case 512:
-    case 256:
-    case 0:
-      /*
-       * These are all OK.
-       */
-      break;
-    default:
-      panic("Strange blocksize for partition table\n");
-    }
-
-  return ret;
-
-}
-
-
-#if CONFIG_KERNELD && CONFIG_FOREIGN_PARTITIONS
-
-#include <linux/kerneld.h>
-
-#ifdef CONFIG_AMIGA_PARTITION_MODULE
-#include <linux/affs_hardblocks.h>
-static int probe_amiga_partition(struct gendisk *hd, kdev_t dev,
-				 struct buffer_head *bh_0)
-{
-	struct buffer_head *bh;
-	int blk, res;
-
-	if (*(u32 *)bh_0->b_data == cpu_to_be32(IDNAME_RIGIDDISK))
-		return 1;
-
-	/* also need to check other possible RDB blocks */
-	for (blk = 1; blk < RDB_ALLOCATION_LIMIT; blk++) {
-		if (!(bh = bread(dev,blk,512)))
-			return -1;
-		res = *(u32 *)bh->b_data == cpu_to_be32(IDNAME_RIGIDDISK);
-		brelse(bh);
-		if (res)
-			return 1;
-	}
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_ATARI_PARTITION_MODULE
-#include <linux/atari_rootsec.h>
-#include <linux/ctype.h>
-#define	VALID_PARTITION(pi,hdsiz)					     \
-    (((pi)->flg & 1) &&							     \
-     isalnum((pi)->id[0]) && isalnum((pi)->id[1]) && isalnum((pi)->id[2]) && \
-     be32_to_cpu((pi)->st) <= (hdsiz) &&				     \
-     be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz))
-static int probe_atari_partition(struct gendisk *hd, kdev_t dev,
-				 struct buffer_head *bh_0)
-{
-	struct rootsector *rs;
-	u32 hd_size;
-	int res;
-
-	rs = (struct rootsector *)bh_0->b_data;
-	hd_size = hd->part[0].nr_sects;
-	res = VALID_PARTITION( &rs->part[0], hd_size ) ||
-	      VALID_PARTITION( &rs->part[1], hd_size ) ||
-	      VALID_PARTITION( &rs->part[2], hd_size ) ||
-	      VALID_PARTITION( &rs->part[3], hd_size );
-	return res;
-}
-#endif
-
-/*
- * This table lists the magics to recognize the partition formats that are
- * availble as modules. The magics can be stored as 16 or 32 bit little-endian
- * or big-endian numbers. For the more complicated cases (Amiga and Atari), a
- * function doing the real work is called.
- */
-
-enum partbl_probe_type { BE16, BE32, LE16, LE32, FUNC };
-
-static struct partbl_probe {
-	char *name;
-	enum partbl_probe_type type;
-	u32 offset;
-	u32 magic;
-	int (*func)(struct gendisk *hd, kdev_t dev, struct buffer_head *bh_0);
-} partbl_modules[] = {
-#ifdef CONFIG_MSDOS_PARTITION_MODULE
-	{ "msdos", LE16, 510, 0xAA55, NULL },
-#endif
-#ifdef CONFIG_OSF_PARTITION_MODULE
-	{ "osf",   LE32,  64, 0x82564557, NULL },
-#endif
-#ifdef CONFIG_SUN_PARTITION_MODULE
-	{ "sun",   BE16, 508, 0xDABE, NULL },
-#endif
-#ifdef CONFIG_AMIGA_PARTITION_MODULE
-	{ "amiga", FUNC,   0,      0, probe_amiga_partition },
-#endif
-#ifdef CONFIG_ATARI_PARTITION_MODULE
-	{ "atari", FUNC,   0,      0, probe_atari_partition },
-#endif
-#ifdef CONFIG_MAC_PARTITION_MODULE
-	{ "mac",   BE16,   0, 0x4552, NULL },
-#endif
-};
-
-#define N_PARTBL_MODULES sizeof(partbl_modules)/sizeof(*partbl_modules)
-
-/*
- * Try to load all partition parsers that could apply to this device
- */
-static int try_to_load_parser(struct gendisk *hd, kdev_t dev)
-{
-	int i, hit = 0, loaded = 0;
-	char modname[24];
-	struct partbl_probe *mod;
-	struct partition_parser *p;
-	struct buffer_head *bh;
-
-	if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
-		return -1;
-
-	for( i = 0, mod = partbl_modules; i < N_PARTBL_MODULES; ++i, ++mod ) {
-		/* don't probe already loaded formats again */
-		for( p = partition_parsers; p; p = p->next )
-			if (!strcmp( mod->name, p->name))
-				goto skip;
-		
-		switch( mod->type ) {
-		    case LE16:
-			hit = le16_to_cpu(*(u16 *)(bh->b_data+mod->offset)) ==
-			      mod->magic;
-			break;
-		    case LE32:
-			hit = le32_to_cpu(*(u32 *)(bh->b_data+mod->offset)) ==
-			      mod->magic;
-			break;
-		    case BE16:
-			hit = be16_to_cpu(*(u16 *)(bh->b_data+mod->offset)) ==
-			      mod->magic;
-			break;
-		    case BE32:
-			hit = be32_to_cpu(*(u32 *)(bh->b_data+mod->offset)) ==
-			      mod->magic;
-			break;
-		    case FUNC:
-			hit = mod->func(hd, dev, bh) > 0;
-			break;
-		}
-		if (hit) {
-			strcpy(modname, "part-format-");
-			strcat(modname, mod->name);
-			request_module(modname);
-			++loaded;
-		}
-	    skip:
-	}
-	brelse(bh);
-	return loaded;
-}
-
-#endif /* CONFIG_KERNELD && CONFIG_FOREIGN_PARTITIONS */
-
-
-static void check_partition(struct gendisk *hd, kdev_t dev)
-{
-	static int first_time = 1;
-	int tries = 0;
-	unsigned long first_sector;
-	char buf[8];
-	struct partition_parser *parser;
-
-	if (first_time)
-		printk("Partition check:\n");
-	first_time = 0;
-	first_sector = hd->part[MINOR(dev)].start_sect;
-
-	/*
-	 * This is a kludge to allow the partition check to be
-	 * skipped for specific drives (e.g. IDE CD-ROM drives)
-	 */
-	if ((int)first_sector == -1) {
-		hd->part[MINOR(dev)].start_sect = 0;
-		return;
-	}
-
-#if CONFIG_KERNELD && CONFIG_FOREIGN_PARTITIONS
-    retry:
-#endif
-	printk(" %s:", disk_name(hd, MINOR(dev), buf));
-	for( parser = partition_parsers; parser; parser = parser->next ) {
-		if (parser->func(hd, dev, first_sector))
-			return;
-	}
-	++tries;
-#if CONFIG_KERNELD && CONFIG_FOREIGN_PARTITIONS
-	if (tries == 1 && try_to_load_parser(hd, dev))
-		goto retry;
-#endif
-	printk(" unknown partition table\n");
-}
-
-int register_partbl( struct partition_parser *parser )
-{
-	struct partition_parser **p;
-    
-	if (!parser)
-		return -EINVAL;
-	if (parser->next)
-		return -EBUSY;
-	for( p = &partition_parsers; *p; p = &(*p)->next )
-		if (*p == parser)
-			return -EBUSY;
-
-	/* Insert new parser at front of list, so that a user-loaded module can
-	 * (in case of some misdetection) override other parsers */
-	parser->next = partition_parsers;
-	partition_parsers = parser;
-	return 0;
-}
-
-#ifdef CONFIG_MODULES
-int unregister_partbl( struct partition_parser *parser )
-{
-	struct partition_parser **p;
-    
-	for( p = &partition_parsers; *p; p = &(*p)->next ) {
-		if (*p == parser) {
-			*p = parser->next;
-			parser->next = NULL;
-			return 0;
-		}
-	}
-	return -EINVAL;
-}
-#endif
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *proc_partbl;
-
-static int partbl_read_proc(char *buf, char **start, off_t offset,
-			    int len, int *eof, void *private)
-{
-	struct partition_parser *p;
-
-	len = 0;
-	for( p = partition_parsers; p && len < 4000; p = p->next )
-		len += sprintf(buf + len, "%s\n", p->name );
-	*start = buf + offset;
-	return len > offset ? len - offset : 0;
-}
-#endif
-
-__initfunc(static void partbl_init( void ))
-{
-	extern void msdos_partbl_init(void);
-	extern void osf_partbl_init(void);
-	extern void sun_partbl_init(void);
-	extern void amiga_partbl_init(void);
-	extern void atari_partbl_init(void);
-	extern void mac_partbl_init(void);
-    
-	if (HAVE_MAC_PARTITION)
-		mac_partbl_init();
-	if (HAVE_ATARI_PARTITION)
-		atari_partbl_init();
-	if (HAVE_AMIGA_PARTITION)
-		amiga_partbl_init();
-	if (HAVE_SUN_PARTITION)
-		sun_partbl_init();
-	if (HAVE_OSF_PARTITION)
-		osf_partbl_init();
-	if (HAVE_MSDOS_PARTITION)
-		msdos_partbl_init();
-
-#ifdef CONFIG_PROC_FS
-	proc_partbl = create_proc_entry("partition-formats", 0, 0);
-	if (proc_partbl)
-		proc_partbl->read_proc = partbl_read_proc;
-#endif
-}
-
 /* This function is used to re-read partition tables for removable disks.
    Much of the cleanup from the old partition tables should have already been
    done */
@@ -421,8 +65,7 @@
 	int end_minor	= first_minor + dev->max_p;
 
 	blk_size[dev->major] = NULL;
-	current_minor = 1 + first_minor;
-	check_partition(dev, MKDEV(dev->major, first_minor));
+	check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
 
  	/*
  	 * We need to set the sizes array before we will be able to access
@@ -448,8 +91,7 @@
 	dev->init(dev);	
 	for (drive = 0 ; drive < dev->nr_real ; drive++) {
 		int first_minor	= drive << dev->minor_shift;
-		current_minor = 1 + first_minor;
-		check_partition(dev, MKDEV(dev->major, first_minor));
+		check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
 	}
 	if (dev->sizes != NULL) {	/* optional safeguard in ll_rw_blk.c */
 		for (i = 0; i < end_minor; i++)
@@ -502,10 +144,3 @@
         md_setup_drive();
 #endif
 }
-
-/* symbols visible for partbl_* modules */
-EXPORT_SYMBOL(add_partition);
-EXPORT_SYMBOL(get_ptable_blocksize);
-EXPORT_SYMBOL(current_minor);
-EXPORT_SYMBOL(register_partbl);
-EXPORT_SYMBOL(unregister_partbl);
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/block/partbl_amiga.c m68k/drivers/block/partbl_amiga.c
--- jes-2.1.108/drivers/block/partbl_amiga.c	Sun Feb  8 22:32:52 1998
+++ m68k/drivers/block/partbl_amiga.c	Thu Jan  1 01:00:00 1970
@@ -1,121 +0,0 @@
-/*
- *  partbl_amiga.c -- Amiga RDSK partition table parser
- *
- *  Code extracted from
- *  linux/drivers/block/genhd.c
- *
- */
-
-#include <linux/module.h>
-
-#include <linux/fs.h>
-#include <linux/genhd.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/affs_hardblocks.h>
-#include <asm/byteorder.h>
-
-static __inline__ u32
-checksum_block(u32 *m, int size)
-{
-	u32 sum = 0;
-
-	while (size--)
-		sum += be32_to_cpu(*m++);
-	return sum;
-}
-
-static int
-amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
-	struct buffer_head	*bh;
-	struct RigidDiskBlock	*rdb;
-	struct PartitionBlock	*pb;
-	int			 start_sect;
-	int			 nr_sects;
-	int			 blk;
-	int			 part, res;
-
-	MOD_INC_USE_COUNT;
-	set_blocksize(dev,512);
-	res = 0;
-
-	for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
-		if(!(bh = bread(dev,blk,512))) {
-			printk("Dev %s: unable to read RDB block %d\n",
-			       kdevname(dev),blk);
-			res = -1;
-			goto rdb_done;
-		}
-		if (*(u32 *)bh->b_data == cpu_to_be32(IDNAME_RIGIDDISK)) {
-			rdb = (struct RigidDiskBlock *)bh->b_data;
-			if (checksum_block((u32 *)bh->b_data,be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
-				printk("Dev %s: RDB in block %d has bad checksum\n",
-				       kdevname(dev),blk);
-				brelse(bh);
-				continue;
-			}
-			printk(" RDSK");
-			blk = be32_to_cpu(rdb->rdb_PartitionList);
-			brelse(bh);
-			for (part = 1; blk > 0 && part <= 16; part++) {
-				if (!(bh = bread(dev,blk,512))) {
-					printk("Dev %s: unable to read partition block %d\n",
-						       kdevname(dev),blk);
-					res = -1;
-					goto rdb_done;
-				}
-				pb  = (struct PartitionBlock *)bh->b_data;
-				blk = be32_to_cpu(pb->pb_Next);
-				if (pb->pb_ID == cpu_to_be32(IDNAME_PARTITION) && checksum_block(
-				    (u32 *)pb,be32_to_cpu(pb->pb_SummedLongs) & 0x7F) == 0 ) {
-					
-					/* Tell Kernel about it */
-
-					if (!(nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
-							  be32_to_cpu(pb->pb_Environment[9])) *
-							 be32_to_cpu(pb->pb_Environment[3]) *
-							 be32_to_cpu(pb->pb_Environment[5]))) {
-						continue;
-					}
-					start_sect = be32_to_cpu(pb->pb_Environment[9]) *
-						     be32_to_cpu(pb->pb_Environment[3]) *
-						     be32_to_cpu(pb->pb_Environment[5]);
-					add_partition(hd,current_minor,start_sect,nr_sects);
-					current_minor++;
-					res = 1;
-				}
-				brelse(bh);
-			}
-			printk("\n");
-			break;
-		}
-	}
-
-rdb_done:
-	set_blocksize(dev,BLOCK_SIZE);
-	MOD_DEC_USE_COUNT;
-	return res;
-}
-
-static struct partition_parser amiga_partition_parser =
-    { NULL, "amiga", amiga_partition };
-
-#ifndef MODULE
-__initfunc(void amiga_partbl_init( void ))
-{
-	(void)register_partbl( &amiga_partition_parser );
-}
-#else
-int init_module(void)
-{
-	return register_partbl( &amiga_partition_parser );
-}
-
-void cleanup_module(void)
-{
-	(void)unregister_partbl( &amiga_partition_parser );
-}
-#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/block/partbl_atari.c m68k/drivers/block/partbl_atari.c
--- jes-2.1.108/drivers/block/partbl_atari.c	Sun Feb  8 22:32:52 1998
+++ m68k/drivers/block/partbl_atari.c	Thu Jan  1 01:00:00 1970
@@ -1,203 +0,0 @@
-/*
- *  partbl_atari.c -- Atari partition table parser
- *
- *  Code extracted from
- *  linux/drivers/block/genhd.c
- *
- */
-
-#include <linux/module.h>
-
-#include <linux/fs.h>
-#include <linux/genhd.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/init.h>
-#include <linux/atari_rootsec.h>
-#include <asm/byteorder.h>
-
-
-/* ++guenther: this should be settable by the user ("make config")?.
- * roman: doesn't use much code, better always include it :-)
- */
-#define ICD_PARTS
-
-/* check if a partition entry looks valid -- Atari format is assumed if at
- * least one of the primary entries is ok this way */
-#define	VALID_PARTITION(pi,hdsiz)					     \
-    (((pi)->flg & 1) &&							     \
-     isalnum((pi)->id[0]) && isalnum((pi)->id[1]) && isalnum((pi)->id[2]) && \
-     be32_to_cpu((pi)->st) <= (hdsiz) &&				     \
-     be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz))
-
-static int atari_partition (struct gendisk *hd, kdev_t dev,
-			    unsigned long first_sector)
-{
-  int minor = current_minor, m_lim = current_minor + hd->max_p;
-  int i;
-  struct buffer_head *bh;
-  struct rootsector *rs;
-  struct partition_info *pi;
-  u32 extensect;
-  u32 hd_size;
-#ifdef ICD_PARTS
-  int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
-#endif
-
-  MOD_INC_USE_COUNT;
-  bh = bread (dev, 0, get_ptable_blocksize(dev));
-  if (!bh)
-    {
-      printk (" unable to read block 0\n");
-      MOD_DEC_USE_COUNT;
-      return -1;
-    }
-
-  rs = (struct rootsector *) bh->b_data;
-  hd_size = hd->part[current_minor-1].nr_sects;
-  if (!VALID_PARTITION( &rs->part[0], hd_size ) &&
-      !VALID_PARTITION( &rs->part[1], hd_size ) &&
-      !VALID_PARTITION( &rs->part[2], hd_size ) &&
-      !VALID_PARTITION( &rs->part[3], hd_size )) {
-      /* if there's no valid primary partition, assume that no Atari format
-       * partition table (there's no reliable magic or the like :-() */
-      MOD_DEC_USE_COUNT;
-      return 0;
-  }
-
-  printk (" AHDI");
-  pi = &rs->part[0];
-  for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++)
-    {
-      if (pi->flg & 1)
-	/* active partition */
-	{
-	  if (memcmp (pi->id, "XGM", 3) == 0)
-	    /* extension partition */
-	    {
-	      struct rootsector *xrs;
-	      struct buffer_head *xbh;
-	      u32 partsect;
-
-#ifdef ICD_PARTS
-	      part_fmt = 1;
-#endif
-	      printk(" XGM<");
-	      partsect = extensect = be32_to_cpu(pi->st);
-	      while (1)
-		{
-		  xbh = bread (dev, partsect / 2, 1024);
-		  if (!xbh)
-		    {
-		      printk (" block %u read failed\n", partsect);
-		      brelse(bh);
-		      MOD_DEC_USE_COUNT;
-		      return -1;
-		    }
-		  if (partsect & 1)
-		    xrs = (struct rootsector *) &xbh->b_data[512];
-		  else
-		    xrs = (struct rootsector *) &xbh->b_data[0];
-
-		  /* ++roman: valid bit must be set in one of the first 3
-		   * slots */
-		  for( i = 0; i < 3; ++i )
-		      if (xrs->part[0].flg & 1)
-			  break;
-		  if (i == 3) {
-		    printk( "\nNo valid subpartition in extended "
-			    "partition!\n" );
-		    break;
-		  }
-		  
-		  add_partition(hd, minor,
-				partsect + be32_to_cpu(xrs->part[i].st),
-				be32_to_cpu(xrs->part[i].siz));
-
-		  /* the slot following must be either invalid (end of list)
-		   * or another XGM entry */
-		  if (!(xrs->part[i+1].flg & 1)) {
-		    brelse( xbh );
-		    break;
-		  }
-		  if (memcmp( xrs->part[i+1].id, "XGM", 3 ) != 0) {
-		    printk( "\nLink ID in extended partition is not XGM!\n" );
-		    brelse( xbh );
-		    break;
-		  }
-
-		  partsect = be32_to_cpu(xrs->part[i+1].st) + extensect;
-		  brelse (xbh);
-		  minor++;
-		  if (minor >= m_lim) {
-		    printk( "\nMaximum number of partitions reached!\n" );
-		    break;
-		  }
-		}
-	      printk(" >");
-	    }
-	  else
-	    {
-	      /* we don't care about other id's */
-	      add_partition (hd, minor, be32_to_cpu(pi->st),
-			     be32_to_cpu(pi->siz));
-	    }
-	}
-    }
-#ifdef ICD_PARTS
-  if ( part_fmt!=1 ) /* no extended partitions -> test ICD-format */
-  {
-    pi = &rs->icdpart[0];
-    /* sanity check: no ICD format if first partition invalid */
-    if (memcmp (pi->id, "GEM", 3) == 0 ||
-        memcmp (pi->id, "BGM", 3) == 0 ||
-        memcmp (pi->id, "LNX", 3) == 0 ||
-        memcmp (pi->id, "SWP", 3) == 0 ||
-        memcmp (pi->id, "RAW", 3) == 0 )
-    {
-      printk(" ICD<");
-      for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++)
-      {
-        /* accept only GEM,BGM,RAW,LNX,SWP partitions */
-        if (pi->flg & 1 && 
-            (memcmp (pi->id, "GEM", 3) == 0 ||
-             memcmp (pi->id, "BGM", 3) == 0 ||
-             memcmp (pi->id, "LNX", 3) == 0 ||
-             memcmp (pi->id, "SWP", 3) == 0 ||
-             memcmp (pi->id, "RAW", 3) == 0) )
-        {
-          part_fmt = 2;
-	  add_partition (hd, minor, be32_to_cpu(pi->st), be32_to_cpu(pi->siz));
-        }
-      }
-      printk(" >");
-    }
-  }
-#endif
-  brelse (bh);
-  printk ("\n");
-  MOD_DEC_USE_COUNT;
-  return 1;
-}
-
-static struct partition_parser atari_partition_parser =
-    { NULL, "atari", atari_partition };
-
-#ifndef MODULE
-__initfunc(void atari_partbl_init( void ))
-{
-	(void)register_partbl( &atari_partition_parser );
-}
-#else
-int init_module(void)
-{
-	return register_partbl( &atari_partition_parser );
-}
-
-void cleanup_module(void)
-{
-	(void)unregister_partbl( &atari_partition_parser );
-}
-#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/block/partbl_mac.c m68k/drivers/block/partbl_mac.c
--- jes-2.1.108/drivers/block/partbl_mac.c	Sun Feb  8 22:32:52 1998
+++ m68k/drivers/block/partbl_mac.c	Thu Jan  1 01:00:00 1970
@@ -1,170 +0,0 @@
-/*
- *  partbl_mac.c -- Mac partition table parser
- *
- *  Code extracted from
- *  linux/drivers/block/genhd.c
- *
- */
-
-#include <linux/module.h>
-
-#include <linux/config.h>
-#include <linux/fs.h>
-#include <linux/genhd.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/init.h>
-
-
-/*
- * Code to understand MacOS partition tables.
- */
-
-#define MAC_PARTITION_MAGIC	0x504d
-
-/* type field value for A/UX or other Unix partitions */
-#define APPLE_AUX_TYPE	"Apple_UNIX_SVR2"
-
-struct mac_partition {
-	__u16	signature;	/* expected to be MAC_PARTITION_MAGIC */
-	__u16	res1;
-	__u32	map_count;	/* # blocks in partition map */
-	__u32	start_block;	/* absolute starting block # of partition */
-	__u32	block_count;	/* number of blocks in partition */
-	char	name[32];	/* partition name */
-	char	type[32];	/* string type description */
-	__u32	data_start;	/* rel block # of first data block */
-	__u32	data_count;	/* number of data blocks */
-	__u32	status;		/* partition status bits */
-	__u32	boot_start;
-	__u32	boot_size;
-	__u32	boot_load;
-	__u32	boot_load2;
-	__u32	boot_entry;
-	__u32	boot_entry2;
-	__u32	boot_cksum;
-	char	processor[16];	/* identifies ISA of boot */
-	/* there is more stuff after this that we don't need */
-};
-
-#define MAC_STATUS_BOOTABLE	8	/* partition is bootable */
-
-#define MAC_DRIVER_MAGIC	0x4552
-
-/* Driver descriptor structure, in block 0 */
-struct mac_driver_desc {
-	__u16	signature;	/* expected to be MAC_DRIVER_MAGIC */
-	__u16	block_size;
-	__u32	block_count;
-    /* ... more stuff */
-};
-
-static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec)
-{
-	struct buffer_head *bh;
-	int blk, blocks_in_map;
-	int dev_bsize, dev_pos, pos;
-	unsigned secsize;
-#ifdef CONFIG_PMAC
-	int first_bootable = 1;
-#endif
-	struct mac_partition *part;
-	struct mac_driver_desc *md;
-
-	MOD_INC_USE_COUNT;
-	dev_bsize = get_ptable_blocksize(dev);
-	dev_pos = 0;
-	/* Get 0th block and look at the first partition map entry. */
-	if ((bh = bread(dev, 0, dev_bsize)) == 0) {
-	    printk("%s: error reading partition table\n",
-		   kdevname(dev));
-	    MOD_DEC_USE_COUNT;
-	    return -1;
-	}
-	md = (struct mac_driver_desc *) bh->b_data;
-	if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) {
-		brelse(bh);
-		MOD_DEC_USE_COUNT;
-		return 0;
-	}
-	secsize = be16_to_cpu(md->block_size);
-	if (secsize >= dev_bsize) {
-		brelse(bh);
-		dev_pos = secsize;
-		if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) {
-			printk("%s: error reading partition table\n",
-			       kdevname(dev));
-			MOD_DEC_USE_COUNT;
-			return -1;
-		}
-	}
-	part = (struct mac_partition *) (bh->b_data + secsize - dev_pos);
-	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
-		brelse(bh);
-		MOD_DEC_USE_COUNT;
-		return 0;		/* not a MacOS disk */
-	}
-	printk(" MAC");
-	blocks_in_map = be32_to_cpu(part->map_count);
-	for (blk = 1; blk <= blocks_in_map; ++blk) {
-		pos = blk * secsize;
-		if (pos >= dev_pos + dev_bsize) {
-			brelse(bh);
-			dev_pos = pos;
-			if ((bh = bread(dev, pos/dev_bsize, dev_bsize)) == 0) {
-				printk("%s: error reading partition table\n",
-				       kdevname(dev));
-				MOD_DEC_USE_COUNT;
-				return -1;
-			}
-		}
-		part = (struct mac_partition *) (bh->b_data + pos - dev_pos);
-		if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
-			break;
-		blocks_in_map = be32_to_cpu(part->map_count);
-		add_partition(hd, current_minor,
-			fsec + be32_to_cpu(part->start_block) * (secsize/512),
-			be32_to_cpu(part->block_count) * (secsize/512));
-
-#ifdef CONFIG_PMAC
-		/*
-		 * If this is the first bootable partition, tell the
-		 * setup code, in case it wants to make this the root.
-		 */
-		if (first_bootable
-		    && (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
-		    && strcasecmp(part->processor, "powerpc") == 0) {
-			note_bootable_part(dev, blk);
-			first_bootable = 0;
-		}
-#endif /* CONFIG_PMAC */
-
-		++current_minor;
-	}
-	brelse(bh);
-	printk("\n");
-	MOD_DEC_USE_COUNT;
-	return 1;
-}
-
-static struct partition_parser mac_partition_parser =
-    { NULL, "mac", mac_partition };
-
-#ifndef MODULE
-__initfunc(void mac_partbl_init( void ))
-{
-	(void)register_partbl( &mac_partition_parser );
-}
-#else
-int init_module(void)
-{
-	return register_partbl( &mac_partition_parser );
-}
-
-void cleanup_module(void)
-{
-	(void)unregister_partbl( &mac_partition_parser );
-}
-#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/block/partbl_msdos.c m68k/drivers/block/partbl_msdos.c
--- jes-2.1.108/drivers/block/partbl_msdos.c	Tue Mar 24 19:04:12 1998
+++ m68k/drivers/block/partbl_msdos.c	Thu Jan  1 01:00:00 1970
@@ -1,423 +0,0 @@
-/*
- *  partbl_msdos.c -- MSDOS partition table parser
- *
- *  Code extracted from
- *  linux/drivers/block/genhd.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
- *  in the early extended-partition checks and added DM partitions
- *
- *  Support for DiskManager v6.0x added by Mark Lord,
- *  with information provided by OnTrack.  This now works for linux fdisk
- *  and LILO, as well as loadlin and bootln.  Note that disks other than
- *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
- *
- *  More flexible handling of extended partitions - aeb, 950831
- *
- *  Check partition table on IDE disks for common CHS translations
- */
-
-#include <linux/module.h>
-
-#include <linux/config.h>
-#include <linux/fs.h>
-#include <linux/genhd.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/blk.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-
-/*
- * Many architectures don't like unaligned accesses, which is
- * frequently the case with the nr_sects and start_sect partition
- * table entries.
- */
-#include <asm/unaligned.h>
-
-#define SYS_IND(p)	(get_unaligned(&p->sys_ind))
-#define NR_SECTS(p)	({ __typeof__(p->nr_sects) __a =	\
-				get_unaligned(&p->nr_sects);	\
-				le32_to_cpu(__a); \
-			})
-
-#define START_SECT(p)	({ __typeof__(p->start_sect) __a =	\
-				get_unaligned(&p->start_sect);	\
-				le32_to_cpu(__a); \
-			})
-
-
-static inline int is_extended_partition(struct partition *p)
-{
-	return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
-		SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
-		SYS_IND(p) == LINUX_EXTENDED_PARTITION);
-}
-
-/*
- * Create devices for each logical partition in an extended partition.
- * The logical partitions form a linked list, with each entry being
- * a partition table with two entries.  The first entry
- * is the real data partition (with a start relative to the partition
- * table start).  The second is a pointer to the next logical partition
- * (with a start relative to the entire extended partition).
- * We do not create a Linux partition for the partition tables, but
- * only for the actual data partitions.
- */
-
-#define MSDOS_LABEL_MAGIC		0xAA55
-
-static void extended_partition(struct gendisk *hd, kdev_t dev)
-{
-	struct buffer_head *bh;
-	struct partition *p;
-	unsigned long first_sector, first_size, this_sector, this_size;
-	int mask = (1 << hd->minor_shift) - 1;
-	int i;
-
-	first_sector = hd->part[MINOR(dev)].start_sect;
-	first_size = hd->part[MINOR(dev)].nr_sects;
-	this_sector = first_sector;
-
-	while (1) {
-		if ((current_minor & mask) == 0)
-			return;
-		if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
-			return;
-	  /*
-	   * This block is from a device that we're about to stomp on.
-	   * So make sure nobody thinks this block is usable.
-	   */
-		bh->b_state = 0;
-
-		if ((*(unsigned short *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC))
-			goto done;
-
-		p = (struct partition *) (0x1BE + bh->b_data);
-
-		this_size = hd->part[MINOR(dev)].nr_sects;
-
-		/*
-		 * Usually, the first entry is the real data partition,
-		 * the 2nd entry is the next extended partition, or empty,
-		 * and the 3rd and 4th entries are unused.
-		 * However, DRDOS sometimes has the extended partition as
-		 * the first entry (when the data partition is empty),
-		 * and OS/2 seems to use all four entries.
-		 */
-
-		/* 
-		 * First process the data partition(s)
-		 */
-		for (i=0; i<4; i++, p++) {
-		    if (!NR_SECTS(p) || is_extended_partition(p))
-		      continue;
-
-		    /* Check the 3rd and 4th entries -
-		       these sometimes contain random garbage */
-		    if (i >= 2
-			&& START_SECT(p) + NR_SECTS(p) > this_size
-			&& (this_sector + START_SECT(p) < first_sector ||
-			    this_sector + START_SECT(p) + NR_SECTS(p) >
-			     first_sector + first_size))
-		      continue;
-
-		    add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
-		    current_minor++;
-		    if ((current_minor & mask) == 0)
-		      goto done;
-		}
-		/*
-		 * Next, process the (first) extended partition, if present.
-		 * (So far, there seems to be no reason to make
-		 *  extended_partition()  recursive and allow a tree
-		 *  of extended partitions.)
-		 * It should be a link to the next logical partition.
-		 * Create a minor for this just long enough to get the next
-		 * partition table.  The minor will be reused for the next
-		 * data partition.
-		 */
-		p -= 4;
-		for (i=0; i<4; i++, p++)
-		  if(NR_SECTS(p) && is_extended_partition(p))
-		    break;
-		if (i == 4)
-		  goto done;	 /* nothing left to do */
-
-		hd->part[current_minor].nr_sects = NR_SECTS(p);
-		hd->part[current_minor].start_sect = first_sector + START_SECT(p);
-		this_sector = first_sector + START_SECT(p);
-		dev = MKDEV(hd->major, current_minor);
-		brelse(bh);
-	}
-done:
-	brelse(bh);
-}
-
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-static void
-solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) {
-
-	struct buffer_head *bh;
-	struct solaris_x86_vtoc *v;
-	struct solaris_x86_slice *s;
-	int i;
-
-	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev))))
-		return;
-	v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
-	if(v->v_sanity != cpu_to_le32(SOLARIS_X86_VTOC_SANE)) {
-		brelse(bh);
-		return;
-	}
-	printk(" <solaris:");
-	if(v->v_version != cpu_to_le32(1)) {
-		printk("  cannot handle version %ld vtoc>", le32_to_cpu(v->v_version));
-		brelse(bh);
-		return;
-	}
-	for(i=0; i<SOLARIS_X86_NUMSLICE; i++) {
-		s = &v->v_slice[i];
-
-		if (s->s_tag == 0)
-			continue;
-		printk(" [s%d]", i);
-		/* solaris partitions are relative to current MS-DOS
-		 * one but add_partition starts relative to sector
-		 * zero of the disk.  Therefore, must add the offset
-		 * of the current partition */
-		add_partition(hd, current_minor, le32_to_cpu(s->s_start)+offset,
-					  le32_to_cpu(s->s_size));
-		current_minor++;
-	}
-	brelse(bh);
-	printk(" >");
-}
-#endif
-
-#ifdef CONFIG_BSD_DISKLABEL
-/* 
- * Create devices for BSD partitions listed in a disklabel, under a
- * dos-like partition. See extended_partition() for more information.
- */
-static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev)
-{
-	struct buffer_head *bh;
-	struct bsd_disklabel *l;
-	struct bsd_partition *p;
-	int mask = (1 << hd->minor_shift) - 1;
-
-	if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
-		return;
-	bh->b_state = 0;
-	l = (struct bsd_disklabel *) (bh->b_data+512);
-	if (l->d_magic != cpu_to_le32(BSD_DISKMAGIC)) {
-		brelse(bh);
-		return;
-	}
-
-	p = &l->d_partitions[0];
-	while (p - &l->d_partitions[0] <= BSD_MAXPARTITIONS) {
-		if ((current_minor & mask) >= (4 + hd->max_p))
-			break;
-
-		if (p->p_fstype != BSD_FS_UNUSED) {
-			add_partition(hd, current_minor, le32_to_cpu(p->p_offset),
-						  le32_to_cpu(p->p_size));
-			current_minor++;
-		}
-		p++;
-	}
-	brelse(bh);
-
-}
-#endif
-
-static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
-	int i, minor = current_minor;
-	struct buffer_head *bh;
-	struct partition *p;
-	unsigned char *data;
-	int mask = (1 << hd->minor_shift) - 1;
-#ifdef CONFIG_BLK_DEV_IDE
-	int tested_for_xlate = 0;
-
-	MOD_INC_USE_COUNT;
-read_mbr:
-#endif
-	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
-		printk(" unable to read partition table\n");
-	    MOD_DEC_USE_COUNT;
-		return -1;
-	}
-	data = bh->b_data;
-	/* In some cases we modify the geometry    */
-	/*  of the drive (below), so ensure that   */
-	/*  nobody else tries to re-use this data. */
-	bh->b_state = 0;
-#ifdef CONFIG_BLK_DEV_IDE
-check_table:
-#endif
-	if (*(unsigned short *)  (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
-		brelse(bh);
-	    MOD_DEC_USE_COUNT;
-		return 0;
-	}
-	p = (struct partition *) (0x1be + data);
-
-#ifdef CONFIG_BLK_DEV_IDE
-	if (!tested_for_xlate++) {	/* Do this only once per disk */
-		/*
-		 * Look for various forms of IDE disk geometry translation
-		 */
-		extern int ide_xlate_1024(kdev_t, int, const char *);
-		unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
-		if (SYS_IND(p) == EZD_PARTITION) {
-			/*
-			 * The remainder of the disk must be accessed using
-			 * a translated geometry that reduces the number of 
-			 * apparent cylinders to less than 1024 if possible.
-			 *
-			 * ide_xlate_1024() will take care of the necessary
-			 * adjustments to fool fdisk/LILO and partition check.
-			 */
-			if (ide_xlate_1024(dev, -1, " [EZD]")) {
-				data += 512;
-				goto check_table;
-			}
-		} else if (SYS_IND(p) == DM6_PARTITION) {
-
-			/*
-			 * Everything on the disk is offset by 63 sectors,
-			 * including a "new" MBR with its own partition table,
-			 * and the remainder of the disk must be accessed using
-			 * a translated geometry that reduces the number of 
-			 * apparent cylinders to less than 1024 if possible.
-			 *
-			 * ide_xlate_1024() will take care of the necessary
-			 * adjustments to fool fdisk/LILO and partition check.
-			 */
-			if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
-				brelse(bh);
-				goto read_mbr;	/* start over with new MBR */
-			}
-		} else if (sig <= 0x1ae &&
-			   *(unsigned short *)(data + sig) == cpu_to_le16(0x55AA) &&
-			   (1 & *(unsigned char *)(data + sig + 2))) {
-			/* DM6 signature in MBR, courtesy of OnTrack */
-			(void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
-		} else if (SYS_IND(p) == DM6_AUX1PARTITION || SYS_IND(p) == DM6_AUX3PARTITION) {
-			/*
-			 * DM6 on other than the first (boot) drive
-			 */
-			(void) ide_xlate_1024(dev, 0, " [DM6:AUX]");
-		} else {
-			/*
-			 * Examine the partition table for common translations.
-			 * This is necessary for drives for situations where
-			 * the translated geometry is unavailable from the BIOS.
-			 */
-			for (i = 0; i < 4 ; i++) {
-				struct partition *q = &p[i];
-				if (NR_SECTS(q)
-				   && (q->sector & 63) == 1
-				   && (q->end_sector & 63) == 63) {
-					unsigned int heads = q->end_head + 1;
-					if (heads == 32 || heads == 64 || heads == 128 || heads == 255) {
-
-						(void) ide_xlate_1024(dev, heads, " [PTBL]");
-						break;
-					}
-				}
-			}
-		}
-	}
-#endif	/* CONFIG_BLK_DEV_IDE */
-
-	printk(" DOS");	/* show partition type */
-	current_minor += 4;  /* first "extra" minor (for extended partitions) */
-	for (i=1 ; i<=4 ; minor++,i++,p++) {
-		if (!NR_SECTS(p))
-			continue;
-		add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
-		if (is_extended_partition(p)) {
-			printk(" <");
-			/*
-			 * If we are rereading the partition table, we need
-			 * to set the size of the partition so that we will
-			 * be able to bread the block containing the extended
-			 * partition info.
-			 */
-			hd->sizes[minor] = hd->part[minor].nr_sects 
-			  	>> (BLOCK_SIZE_BITS - 9);
-			extended_partition(hd, MKDEV(hd->major, minor));
-			printk(" >");
-			/* prevent someone doing mkfs or mkswap on an
-			   extended partition, but leave room for LILO */
-			if (hd->part[minor].nr_sects > 2)
-				hd->part[minor].nr_sects = 2;
-		}
-#ifdef CONFIG_BSD_DISKLABEL
-		if (SYS_IND(p) == BSD_PARTITION) {
-			printk(" BSD<");
-			bsd_disklabel_partition(hd, MKDEV(hd->major, minor));
-			printk(" >");
-		}
-#endif
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-
-		/* james@bpgc.com: Solaris has a nasty indicator: 0x82
-		 * which also means linux swap.  For that reason, all
-		 * of the prints are done inside the
-		 * solaris_x86_partition routine */
-
-		if(SYS_IND(p) == SOLARIS_X86_PARTITION) {
-			solaris_x86_partition(hd, MKDEV(hd->major, minor),
-					      first_sector+START_SECT(p));
-		}
-#endif
-	}
-	/*
-	 *  Check for old-style Disk Manager partition table
-	 */
-	if (*(unsigned short *) (data+0xfc) == cpu_to_le16(MSDOS_LABEL_MAGIC)) {
-		p = (struct partition *) (0x1be + data);
-		for (i = 4 ; i < 16 ; i++, current_minor++) {
-			p--;
-			if ((current_minor & mask) == 0)
-				break;
-			if (!(START_SECT(p) && NR_SECTS(p)))
-				continue;
-			add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
-		}
-	}
-	printk("\n");
-	brelse(bh);
-	MOD_DEC_USE_COUNT;
-	return 1;
-}
-
-static struct partition_parser msdos_partition_parser =
-    { NULL, "msdos", msdos_partition };
-
-#ifndef MODULE
-__initfunc(void msdos_partbl_init( void ))
-{
-	(void)register_partbl( &msdos_partition_parser );
-}
-#else
-int init_module(void)
-{
-	return register_partbl( &msdos_partition_parser );
-}
-
-void cleanup_module(void)
-{
-	(void)unregister_partbl( &msdos_partition_parser );
-}
-#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/block/partbl_osf.c m68k/drivers/block/partbl_osf.c
--- jes-2.1.108/drivers/block/partbl_osf.c	Sun Feb  8 22:32:52 1998
+++ m68k/drivers/block/partbl_osf.c	Thu Jan  1 01:00:00 1970
@@ -1,117 +0,0 @@
-/*
- *  partbl_osf.c -- partition table parser for OSF partitions (alpha)
- *
- *  Code extracted from
- *  linux/drivers/block/genhd.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/module.h>
-
-#include <linux/fs.h>
-#include <linux/genhd.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-
-static int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
-	int i;
-	int mask = (1 << hd->minor_shift) - 1;
-	struct buffer_head *bh;
-	struct disklabel {
-		u32 d_magic;
-		u16 d_type,d_subtype;
-		u8 d_typename[16];
-		u8 d_packname[16];
-		u32 d_secsize;
-		u32 d_nsectors;
-		u32 d_ntracks;
-		u32 d_ncylinders;
-		u32 d_secpercyl;
-		u32 d_secprtunit;
-		u16 d_sparespertrack;
-		u16 d_sparespercyl;
-		u32 d_acylinders;
-		u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
-		u32 d_headswitch, d_trkseek, d_flags;
-		u32 d_drivedata[5];
-		u32 d_spare[5];
-		u32 d_magic2;
-		u16 d_checksum;
-		u16 d_npartitions;
-		u32 d_bbsize, d_sbsize;
-		struct d_partition {
-			u32 p_size;
-			u32 p_offset;
-			u32 p_fsize;
-			u8  p_fstype;
-			u8  p_frag;
-			u16 p_cpg;
-		} d_partitions[8];
-	} * label;
-	struct d_partition * partition;
-#define DISKLABELMAGIC (0x82564557UL)
-
-	MOD_INC_USE_COUNT;
-	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
-		printk("unable to read partition table\n");
-	    MOD_DEC_USE_COUNT;
-		return -1;
-	}
-	label = (struct disklabel *) (bh->b_data+64);
-	partition = label->d_partitions;
-	if (label->d_magic != cpu_to_le32(DISKLABELMAGIC)) {
-#if 0
-		printk("magic: %08x\n", label->d_magic);
-#endif
-		brelse(bh);
-	    MOD_DEC_USE_COUNT;
-		return 0;
-	}
-	if (label->d_magic2 != cpu_to_le32(DISKLABELMAGIC)) {
-#if 0
-		printk("magic2: %08x\n", label->d_magic2);
-#endif
-		brelse(bh);
-	    MOD_DEC_USE_COUNT;
-		return 0;
-	}
-	printk(" OSF");
-	for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) {
-		if ((current_minor & mask) == 0)
-		        break;
-		if (partition->p_size)
-			add_partition(hd, current_minor,
-				first_sector+le32_to_cpu(partition->p_offset),
-				le32_to_cpu(partition->p_size));
-		current_minor++;
-	}
-	printk("\n");
-	brelse(bh);
-	MOD_DEC_USE_COUNT;
-	return 1;
-}
-
-static struct partition_parser osf_partition_parser =
-    { NULL, "osf",  osf_partition };
-
-#ifndef MODULE
-__initfunc(void osf_partbl_init( void ))
-{
-	(void)register_partbl( &osf_partition_parser );
-}
-#else
-int init_module(void)
-{
-	return register_partbl( &osf_partition_parser );
-}
-
-void cleanup_module(void)
-{
-	(void)unregister_partbl( &osf_partition_parser );
-}
-#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/block/partbl_sun.c m68k/drivers/block/partbl_sun.c
--- jes-2.1.108/drivers/block/partbl_sun.c	Tue Mar 24 19:04:12 1998
+++ m68k/drivers/block/partbl_sun.c	Thu Jan  1 01:00:00 1970
@@ -1,113 +0,0 @@
-/*
- *  partbl_sun.c -- Sun partition table parser
- *
- *  Code extracted from
- *  linux/drivers/block/genhd.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/module.h>
-
-#include <linux/fs.h>
-#include <linux/genhd.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-
-static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
-	int i, csum;
-	unsigned short *ush;
-	struct buffer_head *bh;
-	struct sun_disklabel {
-		unsigned char info[128];   /* Informative text string */
-		unsigned char spare[292];  /* Boot information etc. */
-		unsigned short rspeed;     /* Disk rotational speed */
-		unsigned short pcylcount;  /* Physical cylinder count */
-		unsigned short sparecyl;   /* extra sects per cylinder */
-		unsigned char spare2[4];   /* More magic... */
-		unsigned short ilfact;     /* Interleave factor */
-		unsigned short ncyl;       /* Data cylinder count */
-		unsigned short nacyl;      /* Alt. cylinder count */
-		unsigned short ntrks;      /* Tracks per cylinder */
-		unsigned short nsect;      /* Sectors per track */
-		unsigned char spare3[4];   /* Even more magic... */
-		struct sun_partition {
-			__u32 start_cylinder;
-			__u32 num_sectors;
-		} partitions[8];
-		unsigned short magic;      /* Magic number */
-		unsigned short csum;       /* Label xor'd checksum */
-	} * label;		
-	struct sun_partition *p;
-	unsigned long spc;
-#define SUN_LABEL_MAGIC          0xDABE
-
-	MOD_INC_USE_COUNT;
-	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
-		printk("Dev %s: unable to read partition table\n",
-		       kdevname(dev));
-	    MOD_DEC_USE_COUNT;
-		return -1;
-	}
-	label = (struct sun_disklabel *) bh->b_data;
-	p = label->partitions;
-	if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
-		printk("Dev %s Sun disklabel: bad magic %04x\n",
-		       kdevname(dev), be16_to_cpu(label->magic));
-		brelse(bh);
-	    MOD_DEC_USE_COUNT;
-		return 0;
-	}
-	/* Look at the checksum */
-	ush = ((unsigned short *) (label+1)) - 1;
-	for(csum = 0; ush >= ((unsigned short *) label);)
-		csum ^= *ush--;
-	if(csum) {
-		printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
-		       kdevname(dev));
-		brelse(bh);
-	    MOD_DEC_USE_COUNT;
-		return 0;
-	}
-	printk(" UFS");
-	/* All Sun disks have 8 partition entries */
-	spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
-	for(i=0; i < 8; i++, p++) {
-		unsigned long st_sector;
-		int num_sectors;
-
-		st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc;
-		num_sectors = be32_to_cpu(p->num_sectors);
-		if (num_sectors)
-			add_partition(hd, current_minor, st_sector, num_sectors);
-		current_minor++;
-	}
-	printk("\n");
-	brelse(bh);
-	MOD_DEC_USE_COUNT;
-	return 1;
-}
-
-static struct partition_parser sun_partition_parser =
-    { NULL, "sun", sun_partition };
-
-#ifndef MODULE
-__initfunc(void sun_partbl_init( void ))
-{
-	(void)register_partbl( &sun_partition_parser );
-}
-#else
-int init_module(void)
-{
-	return register_partbl( &sun_partition_parser );
-}
-
-void cleanup_module(void)
-{
-	(void)unregister_partbl( &sun_partition_parser );
-}
-#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/char/amikeyb.c m68k/drivers/char/amikeyb.c
--- jes-2.1.108/drivers/char/amikeyb.c	Thu May 14 21:34:33 1998
+++ m68k/drivers/char/amikeyb.c	Sun Jun 14 22:18:24 1998
@@ -343,6 +343,6 @@
 }
 
 /* for "kbd-reset" cmdline param */
-__initfunc(void kbd_reset_setup(char *str, int *ints))
+__initfunc(void amiga_kbd_reset_setup(char *str, int *ints))
 {
 }
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/char/console.c m68k/drivers/char/console.c
--- jes-2.1.108/drivers/char/console.c	Fri Jul 10 19:11:02 1998
+++ m68k/drivers/char/console.c	Sun Jul 12 22:54:16 1998
@@ -1155,6 +1155,7 @@
 				update_screen(par[1]-1);
 			break;
 		case 13: /* unblank the screen */
+			/* FIXME: call poke_blanked_console? */
 			unblank_screen();
 			break;
 		case 14: /* set vesa powerdown interval */
@@ -1692,6 +1693,12 @@
 	    return 0;
 	}
 
+	if (from_user) {
+		/* just to make sure that noone lurks at places he shouldn't see. */
+		if (verify_area(VERIFY_READ, buf, count))
+			return 0; /* ?? are error codes legal here ?? */
+	}
+
 	/* undraw cursor first */
 	if (DO_UPDATE)
 		hide_cursor(currcons);
@@ -1700,12 +1707,6 @@
 	if (currcons == sel_cons)
 		clear_selection();
 
-	if (from_user) {
-		/* just to make sure that noone lurks at places he shouldn't see. */
-		if (verify_area(VERIFY_READ, buf, count))
-			return 0; /* ?? are error codes legal here ?? */
-	}
-
 	disable_bh(CONSOLE_BH);
 	while (count) {
 		enable_bh(CONSOLE_BH);
@@ -1816,7 +1817,6 @@
 			}
 			continue;
 		}
-		/* FIXME: Handle tabs in a special way and use putcs for them as well */
 		FLUSH
 		do_con_trol(tty, currcons, c);
 	}
@@ -2155,18 +2155,12 @@
  * This routine initializes console interrupts, and does nothing
  * else. If you want the screen to clear, call tty_write with
  * the appropriate escape-sequence.
- *
- * FIXME: return early if we don't _have_ a video card installed.
  */
 
 struct tty_driver console_driver;
 static int console_refcount;
 
-#ifdef VGER_CONINIT
-__initfunc(void con_init(void))
-#else
 __initfunc(unsigned long con_init(unsigned long kmem_start))
-#endif
 {
 	const char *display_desc = NULL;
 	unsigned int currcons = 0;
@@ -2209,11 +2203,7 @@
 		panic("Couldn't register console driver\n");
 
 #if CONFIG_AP1000
-#ifdef VGER_CONINIT
 	return kmem_start;
-#else
-        return;
-#endif
 #endif
 
 	timer_table[BLANK_TIMER].fn = blank_screen;
@@ -2223,9 +2213,6 @@
 		timer_active |= 1<<BLANK_TIMER;
 	}
 
-#ifdef VGER_CONINIT
-	vc_allocate(0, 1);
-#else
 	/* Unfortunately, kmalloc is not running yet */
 	/* Due to kmalloc roundup allocating statically is more efficient -
 	   so provide MIN_NR_CONSOLES for people with very little memory */
@@ -2249,7 +2236,6 @@
 			vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ;
 		}
 	}
-#endif
 	currcons = fg_console = 0;
 	save_screen();
 	gotoxy(currcons,x,y);
@@ -2268,9 +2254,7 @@
 
 	init_bh(CONSOLE_BH, console_bh);
 	
-#ifndef VGER_CONINIT
 	return kmem_start;
-#endif
 }
 
 /*
@@ -2287,11 +2271,13 @@
 
 void vesa_blank(void)
 {
-    vc_cons[fg_console].d->vc_sw->con_blank(vesa_blank_mode + 1);
+    struct vc_data *c = vc_cons[fg_console].d;
+    c->vc_sw->con_blank(c, vesa_blank_mode + 1);
 }
 
 void vesa_powerdown(void)
 {
+    struct vc_data *c = vc_cons[fg_console].d;
     /*
      *  Power down if currently suspended (1 or 2),
      *  suspend if currently blanked (0),
@@ -2300,11 +2286,11 @@
      */
     switch (vesa_blank_mode) {
 	case VESA_NO_BLANKING:
-	    vc_cons[fg_console].d->vc_sw->con_blank(VESA_VSYNC_SUSPEND+1);
+	    c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1);
 	    break;
 	case VESA_VSYNC_SUSPEND:
 	case VESA_HSYNC_SUSPEND:
-	    vc_cons[fg_console].d->vc_sw->con_blank(VESA_POWERDOWN+1);
+	    c->vc_sw->con_blank(c, VESA_POWERDOWN+1);
 	    break;
     }
 }
@@ -2341,7 +2327,7 @@
 
 	currcons = fg_console;
 	save_screen();
-	sw->con_blank(1);
+	sw->con_blank(vc_cons[currcons].d, 1);
 	console_blanked = fg_console + 1;
 
 	if(!nopowersave)
@@ -2372,16 +2358,12 @@
 
 	currcons = fg_console;
 	console_blanked = 0;
-	if (sw->con_blank(0))
+	if (sw->con_blank(vc_cons[currcons].d, 0))
 		/* Low-level driver cannot restore -> do it ourselves */
 		update_screen(fg_console);
 	set_cursor(fg_console);
 }
 
-/*
- * If a blank_screen is due to a timer, then a power save is allowed.
- * If it is related to console_switching, then avoid vesa_blank().
- */
 static void blank_screen(void)
 {
 	do_blank_screen(0);
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/char/fbmem.c m68k/drivers/char/fbmem.c
--- jes-2.1.108/drivers/char/fbmem.c	Fri Jul 10 19:11:02 1998
+++ m68k/drivers/char/fbmem.c	Sun Jul 12 21:38:12 1998
@@ -83,8 +83,6 @@
 extern void hpfb_setup(char *options, int *ints);
 extern void sbusfb_init(void);
 extern void sbusfb_setup(char *options, int *ints);
-extern void promfb_init(void);
-extern void promfb_setup(char *options, int *ints);
 
 static struct {
 	const char *name;
@@ -144,9 +142,6 @@
 #endif 
 #ifdef CONFIG_FB_SBUS
 	{ "sbus", sbusfb_init, sbusfb_setup },
-#endif
-#ifdef CONFIG_FB_PROM
-	{ "prom", promfb_init, promfb_setup },
 #endif
 #ifdef CONFIG_GSP_RESOLVER
 	/* Not a real frame buffer device... */
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/char/mac_SCC.c m68k/drivers/char/mac_SCC.c
--- jes-2.1.108/drivers/char/mac_SCC.c	Thu Jun 18 20:52:55 1998
+++ m68k/drivers/char/mac_SCC.c	Sun Jul 12 21:21:20 1998
@@ -61,1549 +61,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/macints.h>
-#ifndef CONFIG_MAC
-#include <asm/prom.h>
-#endif
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/bitops.h>
-
-#include "mac_SCC.h"
-
-/*
- * It would be nice to dynamically allocate everything that
- * depends on NUM_SERIAL, so we could support any number of
- * Z8530s, but for now...
- */
-#define NUM_SERIAL	2		/* Max number of ZS chips supported */
-#define NUM_CHANNELS	(NUM_SERIAL * 2)	/* 2 channels per chip */
-
-#ifdef CONFIG_MAC
-/*
- *	All the Macintosh 68K boxes that have an MMU also have hardware
- *	recovery delays.
- */
-#define RECOVERY_DELAY
-#else
-/* On PowerMacs, the hardware takes care of the SCC recovery time,
-   but we need the eieio to make sure that the accesses occur
-   in the order we want. */
-#define RECOVERY_DELAY	eieio()
-#endif
-
-struct mac_zschannel *zs_kgdbchan;
-struct mac_zschannel zs_channels[NUM_CHANNELS];
-
-struct m68k_async_struct  zs_soft[NUM_CHANNELS];
-struct m68k_async_private zs_soft_private[NUM_CHANNELS];
-int zs_channels_found;
-struct m68k_async_struct *zs_chain;	/* list of all channels */
-
-struct tty_struct zs_ttys[NUM_CHANNELS];
-/** struct tty_struct *zs_constty; **/
-
-/* Console hooks... */
-static int zs_cons_chanout = 0;
-static int zs_cons_chanin = 0;
-struct m68k_async_struct  *zs_consinfo = 0;
-struct mac_zschannel *zs_conschan;
-
-static unsigned char kgdb_regs[16] = {
-	0, 0, 0,		/* write 0, 1, 2 */
-	(Rx8 | RxENABLE),	/* write 3 */
-	(X16CLK | SB1 | PAR_EVEN), /* write 4 */
-	(Tx8 | TxENAB),		/* write 5 */
-	0, 0, 0,		/* write 6, 7, 8 */
-	(NV),			/* write 9 */
-	(NRZ),			/* write 10 */
-	(TCBR | RCBR),		/* write 11 */
-	1, 0,			/* 38400 baud divisor, write 12 + 13 */
-	(BRENABL),		/* write 14 */
-	(DCDIE)			/* write 15 */
-};
-
-#define ZS_CLOCK         3686400 	/* Z8530 RTxC input clock rate */
-
-/* Debugging... DEBUG_INTR is bad to use when one of the zs
- * lines is your console ;(
- */
-#undef SERIAL_DEBUG_INTR
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-
-#define RS_STROBE_TIME 10
-#define RS_ISR_PASS_LIMIT 256
-
-#define _INLINE_ inline
-
-static void probe_sccs(void);
-
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
-
-/***************************** Prototypes *****************************/
-
-static void SCC_init_port( struct m68k_async_struct *info, int type, int channel );
-#if 0
-#ifdef MODULE
-static void SCC_deinit_port( struct m68k_async_struct *info, int channel );
-#endif
-#endif
-
-/* FIXME !!! Currently, only autovector interrupt used! */
-#if 0
-static void SCC_rx_int (int irq, void *data, struct pt_regs *fp);
-static void SCC_spcond_int (int irq, void *data, struct pt_regs *fp);
-static void SCC_tx_int (int irq, void *data, struct pt_regs *fp);
-static void SCC_stat_int (int irq, void *data, struct pt_regs *fp);
-static void SCC_ri_int (int irq, void *data, struct pt_regs *fp);
-#endif
-
-static int SCC_check_open( struct m68k_async_struct *info, struct tty_struct
-                           *tty, struct file *file );
-static void SCC_init( struct m68k_async_struct *info );
-static void SCC_deinit( struct m68k_async_struct *info, int leave_dtr );
-static void SCC_enab_tx_int( struct m68k_async_struct *info, int enab_flag );
-static int SCC_check_custom_divisor( struct m68k_async_struct *info, int baud_base,
-				    int divisor );
-static void SCC_change_speed( struct m68k_async_struct *info );
-#if 0
-static int SCC_clocksrc( unsigned baud_base, unsigned channel );
-#endif
-static void SCC_throttle( struct m68k_async_struct *info, int status );
-static void SCC_set_break( struct m68k_async_struct *info, int break_flag );
-static void SCC_get_serial_info( struct m68k_async_struct *info, struct
-				serial_struct *retinfo );
-static unsigned int SCC_get_modem_info( struct m68k_async_struct *info );
-static int SCC_set_modem_info( struct m68k_async_struct *info, int new_dtr, int
-			      new_rts );
-static int SCC_ioctl( struct tty_struct *tty, struct file *file, struct
-		     m68k_async_struct *info, unsigned int cmd, unsigned long arg );
-static void SCC_stop_receive (struct m68k_async_struct *info);
-static int SCC_trans_empty (struct m68k_async_struct *info);
-
-/************************* End of Prototypes **************************/
-
-
-static SERIALSWITCH SCC_switch = {
-	SCC_init, SCC_deinit, SCC_enab_tx_int,
-	SCC_check_custom_divisor, SCC_change_speed,
-	SCC_throttle, SCC_set_break,
-	SCC_get_serial_info, SCC_get_modem_info,
-	SCC_set_modem_info, SCC_ioctl, SCC_stop_receive, SCC_trans_empty,
-	SCC_check_open
-};
-
-/*
- * tmp_buf is used as a temporary buffer by serial_write.  We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char tmp_buf[4096]; /* This is cheating */
-static struct semaphore tmp_buf_sem = MUTEX;
-
-/*
- * This is used to figure out the divisor speeds and the timeouts
- */
-static int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 57600, 115200, 0 };
-
-/* 
- * Reading and writing Z8530 registers.
- */
-static inline unsigned char read_zsreg(struct mac_zschannel *channel,
-				       unsigned char reg)
-{
-	unsigned char retval;
-
-	if (reg != 0) {
-		*channel->control = reg;
-		RECOVERY_DELAY;
-	}
-	retval = *channel->control;
-	RECOVERY_DELAY;
-	return retval;
-}
-
-static inline void write_zsreg(struct mac_zschannel *channel,
-			       unsigned char reg, unsigned char value)
-{
-	if (reg != 0) {
-		*channel->control = reg;
-		RECOVERY_DELAY;
-	}
-	*channel->control = value;
-	RECOVERY_DELAY;
-	return;
-}
-
-static inline unsigned char read_zsdata(struct mac_zschannel *channel)
-{
-	unsigned char retval;
-
-	retval = *channel->data;
-	RECOVERY_DELAY;
-	return retval;
-}
-
-static inline void write_zsdata(struct mac_zschannel *channel,
-				unsigned char value)
-{
-	*channel->data = value;
-	RECOVERY_DELAY;
-	return;
-}
-
-static inline void load_zsregs(struct mac_zschannel *channel,
-			       unsigned char *regs)
-{
-	ZS_CLEARERR(channel);
-	ZS_CLEARFIFO(channel);
-	/* Load 'em up */
-	write_zsreg(channel, R4, regs[R4]);
-	write_zsreg(channel, R10, regs[R10]);
-	write_zsreg(channel, R3, regs[R3] & ~RxENABLE);
-	write_zsreg(channel, R5, regs[R5] & ~TxENAB);
-	write_zsreg(channel, R1, regs[R1]);
-	write_zsreg(channel, R9, regs[R9]);
-	write_zsreg(channel, R11, regs[R11]);
-	write_zsreg(channel, R12, regs[R12]);
-	write_zsreg(channel, R13, regs[R13]);
-	write_zsreg(channel, R14, regs[R14]);
-	write_zsreg(channel, R15, regs[R15]);
-	write_zsreg(channel, R3, regs[R3]);
-	write_zsreg(channel, R5, regs[R5]);
-	return;
-}
-
-/* Sets or clears DTR/RTS on the requested line */
-static inline void zs_rtsdtr(struct m68k_async_struct *ss, int set)
-{
-	if (set)
-		ss->private->curregs[5] |= (RTS | DTR);
-	else
-		ss->private->curregs[5] &= ~(RTS | DTR);
-	write_zsreg(ss->private->zs_channel, 5, ss->private->curregs[5]);
-	return;
-}
-
-static inline void kgdb_chaninit(struct m68k_async_struct *ss, int intson, int bps)
-{
-	int brg;
-
-	if (intson) {
-		kgdb_regs[R1] = INT_ALL_Rx;
-		kgdb_regs[R9] |= MIE;
-	} else {
-		kgdb_regs[R1] = 0;
-		kgdb_regs[R9] &= ~MIE;
-	}
-	brg = BPS_TO_BRG(bps, ZS_CLOCK/16);
-	kgdb_regs[R12] = brg;
-	kgdb_regs[R13] = brg >> 8;
-	load_zsregs(ss->private->zs_channel, kgdb_regs);
-}
-
-/* Utility routines for the Zilog */
-static inline int get_zsbaud(struct m68k_async_struct *ss)
-{
-	struct mac_zschannel *channel = ss->private->zs_channel;
-	int brg;
-
-	/* The baud rate is split up between two 8-bit registers in
-	 * what is termed 'BRG time constant' format in my docs for
-	 * the chip, it is a function of the clk rate the chip is
-	 * receiving which happens to be constant.
-	 */
-	brg = (read_zsreg(channel, 13) << 8);
-	brg |= read_zsreg(channel, 12);
-	return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->private->clk_divisor)));
-}
-
-/* On receive, this clears errors and the receiver interrupts */
-static inline void SCC_recv_clear(struct mac_zschannel *zsc)
-{
-	write_zsreg(zsc, 0, ERR_RES);
-	write_zsreg(zsc, 0, RES_H_IUS); /* XXX this is unnecessary */
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * Here starts the interrupt handling routines.  All of the following
- * subroutines are declared as inline and are folded into
- * rs_interrupt().  They were separated out for readability's sake.
- *
- * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
- * -----------------------------------------------------------------------
- */
-
-extern void breakpoint(void);  /* For the KGDB frame character */
-
-static /*_INLINE_*/ void receive_chars(struct m68k_async_struct *info,
-				   struct pt_regs *regs)
-{
-	struct tty_struct *tty = info->tty;
-	unsigned char ch, stat, flag;
-
-	while ((read_zsreg(info->private->zs_channel, 0) & Rx_CH_AV) != 0) {
-
-		stat = read_zsreg(info->private->zs_channel, R1);
-		ch = read_zsdata(info->private->zs_channel);
-
-#ifdef SCC_DEBUG
-		printk("mac_SCC: receive_chars stat=%X char=%X \n", stat, ch);
-#endif
-
-#if 0	/* KGDB not yet supported */
-		/* Look for kgdb 'stop' character, consult the gdb documentation
-		 * for remote target debugging and arch/sparc/kernel/sparc-stub.c
-		 * to see how all this works.
-		 */
-		if ((info->kgdb_channel) && (ch =='\003')) {
-			breakpoint();
-			continue;
-		}
-#endif
-
-		if (!tty)
-			continue;
-
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			tty_flip_buffer_push(tty);
-		
-		if (stat & Rx_OVR) {
-			flag = TTY_OVERRUN;
-			/* reset the error indication */
-			write_zsreg(info->private->zs_channel, 0, ERR_RES);
-		} else if (stat & FRM_ERR) {
-			/* this error is not sticky */
-			flag = TTY_FRAME;
-		} else if (stat & PAR_ERR) {
-			flag = TTY_PARITY;
-			/* reset the error indication */
-			write_zsreg(info->private->zs_channel, 0, ERR_RES);
-		} else
-			flag = 0;
-
-		if (tty->flip.buf_num 
-		    && tty->flip.count >= TTY_FLIPBUF_SIZE) {
-#ifdef SCC_DEBUG_OVERRUN
-			printk("mac_SCC: flip buffer overrun!\n");
-#endif
-			return;
-		}
-
-		if (!tty->flip.buf_num 
-		    && tty->flip.count >= 2*TTY_FLIPBUF_SIZE) {
-			printk("mac_SCC: double flip buffer overrun!\n");
-			return;
-		}
-
-		tty->flip.count++;
-		*tty->flip.flag_buf_ptr++ = flag;
-		*tty->flip.char_buf_ptr++ = ch;
-		info->icount.rx++;
-		tty_flip_buffer_push(tty);
-	}
-#if 0
-clear_and_exit:
-	SCC_recv_clear(info->private->zs_channel);
-#endif
-}
-
-/* that's SCC_enable_tx_int, basically */
-
-static void transmit_chars(struct m68k_async_struct *info)
-{
-	if ((read_zsreg(info->private->zs_channel, 0) & Tx_BUF_EMP) == 0)
-		return;
-	info->private->tx_active = 0;
-
-	if (info->x_char) {
-		/* Send next char */
-		write_zsdata(info->private->zs_channel, info->x_char);
-		info->x_char = 0;
-		info->private->tx_active = 1;
-		return;
-	}
-
-	if ((info->xmit_cnt <= 0) || info->tty->stopped 
-	     || info->private->tx_stopped) {
-		write_zsreg(info->private->zs_channel, 0, RES_Tx_P);
-		return;
-	}
-
-	/* Send char */
-	write_zsdata(info->private->zs_channel, info->xmit_buf[info->xmit_tail++]);
-	info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
-	info->icount.tx++;
-	info->xmit_cnt--;
-	info->private->tx_active = 1;
-
-	if (info->xmit_cnt < WAKEUP_CHARS)
-		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-}
-
-static /*_INLINE_*/ void status_handle(struct m68k_async_struct *info)
-{
-	unsigned char status;
-
-	/* Get status from Read Register 0 */
-	status = read_zsreg(info->private->zs_channel, 0);
-
-	/* Check for DCD transitions */
-	if (((status ^ info->private->read_reg_zero) & DCD) != 0
-	    && info->tty && C_CLOCAL(info->tty)) {
-		if (status & DCD) {
-			wake_up_interruptible(&info->open_wait);
-		} else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) {
-			if (info->tty)
-				tty_hangup(info->tty);
-		}
-	}
-
-	/* Check for CTS transitions */
-	if (info->tty && C_CRTSCTS(info->tty)) {
-		/*
-		 * For some reason, on the Power Macintosh,
-		 * it seems that the CTS bit is 1 when CTS is
-		 * *negated* and 0 when it is asserted.
-		 * The DCD bit doesn't seem to be inverted
-		 * like this.
-		 */
-		if ((status & CTS) == 0) {
-			if (info->private->tx_stopped) {
-				info->private->tx_stopped = 0;
-				if (!info->private->tx_active)
-					transmit_chars(info);
-			}
-		} else {
-			info->private->tx_stopped = 1;
-		}
-	}
-
-	/* Clear status condition... */
-	write_zsreg(info->private->zs_channel, 0, RES_EXT_INT);
-	info->private->read_reg_zero = status;
-}
-
-/*
- * This is the serial driver's generic interrupt routine
- */
-void mac_SCC_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
-	struct m68k_async_struct *info = (struct m68k_async_struct *) dev_id;
-	unsigned char zs_intreg;
-	int shift;
-
-	/* NOTE: The read register 3, which holds the irq status,
-	 *       does so for both channels on each chip.  Although
-	 *       the status value itself must be read from the A
-	 *       channel and is only valid when read from channel A.
-	 *       Yes... broken hardware...
-	 */
-#define CHAN_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT)
-
-#ifdef SCC_DEBUG
-	printk("mac_SCC: interrupt; port: %lx channel: %lx \n", 
-		info->port, info->private->zs_channel);
-#endif
-
-	if (info->private->zs_chan_a == info->private->zs_channel)
-		shift = 3;	/* Channel A */
-	else
-		shift = 0;	/* Channel B */
-
-	for (;;) {
-		zs_intreg = read_zsreg(info->private->zs_chan_a, 3);
-#ifdef SCC_DEBUG
-		printk("mac_SCC: status %x shift %d shifted %x \n", 
-		zs_intreg, shift, zs_intreg >> shift);
-#endif
-		zs_intreg = zs_intreg >> shift;
-		if ((zs_intreg & CHAN_IRQMASK) == 0)
-			break;
-
-		if (zs_intreg & CHBRxIP)
-			receive_chars(info, regs);
-		if (zs_intreg & CHBTxIP)
-			transmit_chars(info);
-		if (zs_intreg & CHBEXT)
-			status_handle(info);
-	}
-}
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-/*
- * ------------------------------------------------------------
- * rs_stop() and rs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * ------------------------------------------------------------
- */
-
-static void SCC_enab_tx_int( struct m68k_async_struct *info, int enab_flag )
-{
-	unsigned long flags;
-
-	if (enab_flag) {
-#if 0
-		save_flags(flags); cli();
-		if (info->private->curregs[5] & TxENAB) {
-			info->private->curregs[5] &= ~TxENAB;
-			info->private->pendregs[5] &= ~TxENAB;
-			write_zsreg(info->private->zs_channel, 5, 
-				    info->private->curregs[5]);
-		}
-		restore_flags(flags);
-#endif
-	/* FIXME: should call transmit_chars here ??? */
-		transmit_chars(info);
-	} else {
-	save_flags(flags); cli();
-#if 0
-		if (  info->xmit_cnt && info->xmit_buf && 
-		    !(info->private->curregs[5] & TxENAB)) {
-			info->private->curregs[5] |= TxENAB;
-			info->private->pendregs[5] = info->private->curregs[5];
-			write_zsreg(info->private->zs_channel, 5, 
-				    info->private->curregs[5]);
-		}
-#else
-		if ( info->xmit_cnt && info->xmit_buf && 
-		    !info->private->tx_active) {
-			transmit_chars(info);
-		}
-#endif
-		restore_flags(flags);	
-	}
-
-}
-
-#if 0
-/*
- * leftover from original driver ...
- */
-static int SCC_startup(struct m68k_async_struct * info)
-{
-	unsigned long flags;
-
-	save_flags(flags); cli();
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("starting up ttyS%d (irq %d)...", info->line, info->irq);
-#endif
-
-	/*
-	 * Clear the receive FIFO.
-	 */
-	ZS_CLEARFIFO(info->private->zs_channel);
-	info->xmit_fifo_size = 1;
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	write_zsreg(info->private->zs_channel, 0, ERR_RES);
-	write_zsreg(info->private->zs_channel, 0, RES_H_IUS);
-
-	/*
-	 * Turn on RTS and DTR.
-	 */
-	zs_rtsdtr(info, 1);
-
-	/*
-	 * Finally, enable sequencing and interrupts
-	 */
-	info->private->curregs[1] = (info->private->curregs[1] & ~0x18) 
-				    | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB);
-	info->private->pendregs[1] = info->private->curregs[1];
-	info->private->curregs[3] |= (RxENABLE | Rx8);
-	info->private->pendregs[3] = info->private->curregs[3];
-	info->private->curregs[5] |= (TxENAB | Tx8);
-	info->private->pendregs[5] = info->private->curregs[5];
-	info->private->curregs[9] |= (NV | MIE);
-	info->private->pendregs[9] = info->private->curregs[9];
-	write_zsreg(info->private->zs_channel, 3, info->private->curregs[3]);
-	write_zsreg(info->private->zs_channel, 5, info->private->curregs[5]);
-	write_zsreg(info->private->zs_channel, 9, info->private->curregs[9]);
-
-	/*
-	 * Set the speed of the serial port
-	 */
-	SCC_change_speed(info);
-
-	/* Save the current value of RR0 */
-	info->private->read_reg_zero = read_zsreg(info->private->zs_channel, 0);
-
-	restore_flags(flags);
-	return 0;
-}
-#endif
-
-/* FIXME: are these required ?? */
-static int SCC_check_open( struct m68k_async_struct *info, struct tty_struct *tty,
-			  struct file *file )
-{
-	/* check on the basis of info->whatever ?? */
-	if (info->private->kgdb_channel || info->private->is_cons)
-		return -EBUSY;
-	return( 0 );
-}
-
-static void SCC_init( struct m68k_async_struct *info )
-{
-	/* FIXME: init currently done in probe_sccs() */
-
-	/* BUT: startup part needs to be done here! */
-
-#ifdef SCC_DEBUG
-	printk("mac_SCC: init, info %lx, info->port %lx  \n", info, info->port);
-#endif
-	/*
-	 * Clear the receive FIFO.
-	 */
-	ZS_CLEARFIFO(info->private->zs_channel);
-	info->xmit_fifo_size = 1;
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	write_zsreg(info->private->zs_channel, 0, ERR_RES);
-	write_zsreg(info->private->zs_channel, 0, RES_H_IUS);
-
-	/*
-	 * Turn on RTS and DTR.
-	 */
-	zs_rtsdtr(info, 1);
-
-	/*
-	 * Finally, enable sequencing and interrupts
-	 */
-	info->private->curregs[1] = (info->private->curregs[1] & ~0x18) 
-				    | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB);
-	info->private->pendregs[1] = info->private->curregs[1];
-	info->private->curregs[3] |= (RxENABLE | Rx8);
-	info->private->pendregs[3] = info->private->curregs[3];
-	info->private->curregs[5] |= (TxENAB | Tx8);
-	info->private->pendregs[5] = info->private->curregs[5];
-	info->private->curregs[9] |= (NV | MIE);
-	info->private->pendregs[9] = info->private->curregs[9];
-	write_zsreg(info->private->zs_channel, 3, info->private->curregs[3]);
-	write_zsreg(info->private->zs_channel, 5, info->private->curregs[5]);
-	write_zsreg(info->private->zs_channel, 9, info->private->curregs[9]);
-
-	/*
-	 * Set the speed of the serial port - done in startup() !!
-	 */
-#if 0
-	SCC_change_speed(info);
-#endif
-
-	/* Save the current value of RR0 */
-	info->private->read_reg_zero = read_zsreg(info->private->zs_channel, 0);
-
-}
-
-static void SCC_init_port( struct m68k_async_struct *info, int type, int channel )
-{
-	static int got_autovector = 0;
-
-#ifdef SCC_DEBUG
-	printk("mac_SCC: init_port, info %x \n", info);
-#endif
-	info->sw = &SCC_switch;
-	info->private = &zs_soft_private[channel];
-	info->private->zs_channel = &zs_channels[channel];
-	info->irq = IRQ4;
-	info->private->clk_divisor = 16;
-	info->private->zs_baud = get_zsbaud(info);
-	info->port = (int) info->private->zs_channel->control;
-
-	/*
-	 * MSch: Extended interrupt scheme:
-	 * The generic m68k interrupt code can't use multiple handlers for
-	 * the same interrupt source (no chained interrupts).
-	 * We have to plug in a 'master' interrupt handler instead, calling 
-	 * mac_SCC_interrupt with the proper arguments ...
-	 */
-
-	if (!got_autovector) {
-		if(sys_request_irq(IRQ4, mac_SCC_handler, 0, "SCC master", info))
-			panic("macserial: can't get irq %d", IRQ4);
-#ifdef SCC_DEBUG
-		printk("mac_SCC: got SCC master interrupt %d, channel %d info %p\n",
-			IRQ4, channel, info);
-#endif
-		got_autovector = 1;
-	}
-
-	if (info->private->zs_chan_a == info->private->zs_channel) {
-		/* Channel A */
-		if (request_irq(IRQ_SCCA, mac_SCC_interrupt, 0, "SCC A", info))
-			panic("mac_SCC: can't get irq %d", IRQ_SCCA);
-#ifdef SCC_DEBUG
-		printk("mac_SCC: got SCC A interrupt %d, channel %d info %p\n",
-			IRQ_SCCA, channel, info);
-#endif
-	} else {
-		/* Channel B */
-		if (request_irq(IRQ_SCCB, mac_SCC_interrupt, 0, "SCC B", info))
-			panic("mac_SCC: can't get irq %d", IRQ_SCCB);
-#ifdef SCC_DEBUG
-		printk("mac_SCC: got SCC B interrupt %d, channel %d info %p\n", 
-			IRQ_SCCB, channel, info);
-#endif
-	}
-
-	/* If console serial line, then enable interrupts. */
-	if (info->private->is_cons) {
-		printk("mac_SCC: console line %lx; enabling interrupt!\n", info);
-		write_zsreg(info->private->zs_channel, R1,
-			    (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB));
-		write_zsreg(info->private->zs_channel, R9, (NV | MIE));
-		write_zsreg(info->private->zs_channel, R10, (NRZ));
-		write_zsreg(info->private->zs_channel, R3, (Rx8 | RxENABLE));
-		write_zsreg(info->private->zs_channel, R5, (Tx8 | TxENAB));
-	}
-	/* If this is the kgdb line, enable interrupts because we
-	 * now want to receive the 'control-c' character from the
-	 * client attached to us asynchronously.
-	 */
-	if (info->private->kgdb_channel) {
-		printk("mac_SCC: kgdb line %lx; enabling interrupt!\n", info);
-		kgdb_chaninit(info, 1, info->private->zs_baud);
-	}
-	/* Report settings (in m68kserial.c) */
-#ifndef CONFIG_MAC
-	printk("ttyS%d at 0x%08x (irq = %d)", info->line, 
-		       info->port, info->irq);
-	printk(" is a Z8530 SCC\n");
-#endif
-
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void SCC_deinit(struct m68k_async_struct * info, int leave_dtr)
-{
-	unsigned long	flags;
-
-	save_flags(flags); cli(); /* Disable interrupts */
-	
-	info->private->pendregs[1] = info->private->curregs[1] = 0;
-	write_zsreg(info->private->zs_channel, 1, 0);	/* no interrupts */
-
-	info->private->curregs[3] &= ~RxENABLE;
-	info->private->pendregs[3] = info->private->curregs[3];
-	write_zsreg(info->private->zs_channel, 3, info->private->curregs[3]);
-
-	info->private->curregs[5] &= ~TxENAB;
-
-	if (!leave_dtr)
-		info->private->curregs[5] &= ~(DTR | RTS);
-	else
-		info->private->curregs[5] &= ~(RTS);
-
-	info->private->pendregs[5] = info->private->curregs[5];
-	write_zsreg(info->private->zs_channel, 5, info->private->curregs[5]);
-
-	restore_flags(flags);
-}
-
-/* FIXME !!! */
-static int SCC_check_custom_divisor( struct m68k_async_struct *info,
-				    int baud_base, int divisor )
-{
-	return 0;
-}
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void SCC_change_speed(struct m68k_async_struct *info)
-{
-	unsigned short port;
-	unsigned cflag;
-	int	i;
-	int	brg;
-	unsigned long flags;
-
-	if (!info->tty || !info->tty->termios)
-		return;
-	cflag = info->tty->termios->c_cflag;
-	if (!(port = info->port))
-		return;
-	i = cflag & CBAUD;
-
-	if (i == 0 && !(info->flags & ASYNC_SPD_MASK)) {
-		/* speed == 0 -> drop DTR */
-		save_flags(flags);
-		cli();
-		info->private->curregs[5] &= ~(DTR | RTS);
-		write_zsreg(info->private->zs_channel, 5, info->private->curregs[5]);
-		restore_flags(flags);
-		return;
-	}
-
-
-	if (i & CBAUDEX) {
-		/* XXX CBAUDEX is not obeyed.
-		 * It is impossible at a 32bits PPC.  XXX??
-		 * But we have to report this to user ... someday.
-		 */
-		i = B9600;
-	}
-
-	save_flags(flags); cli();
-	info->private->zs_baud = baud_table[i];
-	info->private->clk_divisor = 16;
-
-	info->private->curregs[4] = X16CLK;
-	info->private->curregs[11] = TCBR | RCBR;
-	brg = BPS_TO_BRG(info->private->zs_baud, 
-			 ZS_CLOCK/info->private->clk_divisor);
-	info->private->curregs[12] = (brg & 255);
-	info->private->curregs[13] = ((brg >> 8) & 255);
-	info->private->curregs[14] = BRENABL;
-
-	/* byte size and parity */
-	info->private->curregs[3] &= ~RxNBITS_MASK;
-	info->private->curregs[5] &= ~TxNBITS_MASK;
-	switch (cflag & CSIZE) {
-	case CS5:
-		info->private->curregs[3] |= Rx5;
-		info->private->curregs[5] |= Tx5;
-		break;
-	case CS6:
-		info->private->curregs[3] |= Rx6;
-		info->private->curregs[5] |= Tx6;
-		break;
-	case CS7:
-		info->private->curregs[3] |= Rx7;
-		info->private->curregs[5] |= Tx7;
-		break;
-	case CS8:
-	default: /* defaults to 8 bits */
-		info->private->curregs[3] |= Rx8;
-		info->private->curregs[5] |= Tx8;
-		break;
-	}
-	info->private->pendregs[3] = info->private->curregs[3];
-	info->private->pendregs[5] = info->private->curregs[5];
-
-	info->private->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN);
-	if (cflag & CSTOPB) {
-		info->private->curregs[4] |= SB2;
-	} else {
-		info->private->curregs[4] |= SB1;
-	}
-	if (cflag & PARENB) {
-		info->private->curregs[4] |= PAR_ENA;
-	}
-	if (!(cflag & PARODD)) {
-		info->private->curregs[4] |= PAR_EVEN;
-	}
-	info->private->pendregs[4] = info->private->curregs[4];
-
-	info->private->curregs[15] &= ~(DCDIE | CTSIE);
-	if (!(cflag & CLOCAL)) {
-		info->private->curregs[15] |= DCDIE;
-	}
-	if (cflag & CRTSCTS) {
-		info->private->curregs[15] |= CTSIE;
-		if ((read_zsreg(info->private->zs_channel, 0) & CTS) != 0)
-			info->private->tx_stopped = 1;
-	} else
-		info->private->tx_stopped = 0;
-	info->private->pendregs[15] = info->private->curregs[15];
-
-	/* Load up the new values */
-	load_zsregs(info->private->zs_channel, info->private->curregs);
-
-	restore_flags(flags);
-}
-
-/* This is for console output over ttya/ttyb */
-static void SCC_put_char(char ch)
-{
-	struct mac_zschannel *chan = zs_conschan;
-	int loops = 0;
-	unsigned long flags;
-
-	if(!chan)
-		return;
-
-	save_flags(flags); cli();
-	while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0 && loops < 10000) {
-		loops++;
-		udelay(5);
-	}
-	write_zsdata(chan, ch);
-	restore_flags(flags);
-}
-
-/* These are for receiving and sending characters under the kgdb
- * source level kernel debugger.
- */
-void putDebugChar(char kgdb_char)
-{
-	struct mac_zschannel *chan = zs_kgdbchan;
-
-	while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0)
-		udelay(5);
-	write_zsdata(chan, kgdb_char);
-}
-
-char getDebugChar(void)
-{
-	struct mac_zschannel *chan = zs_kgdbchan;
-
-	while ((read_zsreg(chan, 0) & Rx_CH_AV) == 0)
-		udelay(5);
-	return read_zsdata(chan);
-}
-
-/*
- * Fair output driver allows a process to speak.
- */
-static void SCC_fair_output(void)
-{
-	int left;		/* Output no more than that */
-	unsigned long flags;
-	struct m68k_async_struct *info = zs_consinfo;
-	char c;
-
-	if (info == 0) return;
-	if (info->xmit_buf == 0) return;
-
-	save_flags(flags);  cli();
-	left = info->xmit_cnt;
-	while (left != 0) {
-		c = info->xmit_buf[info->xmit_tail];
-		info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1);
-		info->xmit_cnt--;
-		restore_flags(flags);
-
-		SCC_put_char(c);
-
-		save_flags(flags);  cli();
-		left = MIN(info->xmit_cnt, left-1);
-	}
-
-	restore_flags(flags);
-	return;
-}
-
-/*
- * zs_console_print is registered for printk.
- */
-static void zs_console_print(const char *p)
-{
-	char c;
-
-	while ((c = *(p++)) != 0) {
-		if (c == '\n')
-			SCC_put_char('\r');
-		SCC_put_char(c);
-	}
-
-	/* Comment this if you want to have a strict interrupt-driven output */
-	SCC_fair_output();
-}
-
-/* FIXME: check with SCC_enab_tx_int!! */
-#if 0
-static void rs_flush_chars(struct tty_struct *tty)
-{
-	struct m68k_async_struct *info = (struct m68k_async_struct *)tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))
-		return;
-
-	if (info->xmit_cnt <= 0 || tty->stopped || info->private->tx_stopped ||
-	    !info->xmit_buf)
-		return;
-
-	/* Enable transmitter */
-	save_flags(flags); cli();
-	transmit_chars(info);
-	restore_flags(flags);
-}
-
-static int rs_write(struct tty_struct * tty, int from_user,
-		    const unsigned char *buf, int count)
-{
-	int	c, total = 0;
-	struct m68k_async_struct *info = (struct m68k_async_struct *)tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->device, "rs_write"))
-		return 0;
-
-	if (!tty || !info->xmit_buf)
-		return 0;
-
-	save_flags(flags);
-	while (1) {
-		cli();		
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - info->xmit_head));
-		if (c <= 0)
-			break;
-
-		if (from_user) {
-			down(&tmp_buf_sem);
-			memcpy_fromfs(tmp_buf, buf, c);
-			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				       SERIAL_XMIT_SIZE - info->xmit_head));
-			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
-			up(&tmp_buf_sem);
-		} else
-			memcpy(info->xmit_buf + info->xmit_head, buf, c);
-		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		info->xmit_cnt += c;
-		restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
-	}
-	if (info->xmit_cnt && !tty->stopped && !info->tx_stopped
-	    && !info->tx_active)
-		transmit_chars(info);
-	restore_flags(flags);
-	return total;
-}
-#endif
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- * 
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void SCC_throttle(struct m68k_async_struct *info, int status)
-{
-	unsigned long	flags;
-
-	save_flags(flags); 
-	cli();
-
-	if (status) {
-		/*
-		 * Here we want to turn off the RTS line.  On Macintoshes,
-		 * we only get the DTR line, which goes to both DTR and
-		 * RTS on the modem.  RTS doesn't go out to the serial
-		 * port socket.  So you should make sure your modem is
-		 * set to ignore DTR if you're using CRTSCTS.
-		 */
-		info->private->curregs[5] &= ~(DTR | RTS);
-		info->private->pendregs[5] &= ~(DTR | RTS);
-		write_zsreg(info->private->zs_channel, 5, 
-			    info->private->curregs[5]);
-	} else {
-		/* Assert RTS and DTR lines */
-		info->private->curregs[5] |= DTR | RTS;
-		info->private->pendregs[5] |= DTR | RTS;
-		write_zsreg(info->private->zs_channel, 5, 
-			    info->private->curregs[5]);
-	}
-
-	restore_flags(flags);
-
-}
-
-/*
- * ------------------------------------------------------------
- * rs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-static void SCC_get_serial_info(struct m68k_async_struct * info,
-			   struct serial_struct * retinfo)
-{
-	struct serial_struct tmp;
-  
-	retinfo->baud_base = info->baud_base;
-	retinfo->custom_divisor = info->custom_divisor;
-}
-
-/* FIXME: set_serial_info needs check_custom_divisor !!! */
-
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * 	    is emptied.  On bus types like RS485, the transmitter must
- * 	    release the bus after transmitting. This must be done when
- * 	    the transmit shift register is empty, not be done when the
- * 	    transmit holding register is empty.  This functionality
- * 	    allows an RS485 driver to be written in user space. 
- */
-static int SCC_get_lsr_info(struct m68k_async_struct * info, unsigned int *value)
-{
-	unsigned char status;
-
-	cli();
-	status = read_zsreg(info->private->zs_channel, 0);
-	sti();
-	return status;
-}
-
-static unsigned int SCC_get_modem_info(struct m68k_async_struct *info)
-{
-	unsigned char control, status;
-	unsigned int result;
-
-	cli();
-	control = info->private->curregs[5];
-	status = read_zsreg(info->private->zs_channel, 0);
-	sti();
-	result =  ((control & RTS) ? TIOCM_RTS: 0)
-		| ((control & DTR) ? TIOCM_DTR: 0)
-		| ((status  & DCD) ? TIOCM_CAR: 0)
-		| ((status  & CTS) ? 0: TIOCM_CTS);
-	return result;
-}
-
-/* FIXME: zs_setdtr was used in rs_open ... */
-
-static int SCC_set_modem_info(struct m68k_async_struct *info, 
-			      int new_dtr, int new_rts)
-{
-	int error;
-	unsigned int arg, bits;
-
-	bits = (new_rts ? RTS: 0) + (new_dtr ? DTR: 0);
-	info->private->curregs[5] = (info->private->curregs[5] & ~(DTR | RTS)) | bits;
-	info->private->pendregs[5] = info->private->curregs[5];
-	write_zsreg(info->private->zs_channel, 5, info->private->curregs[5]);
-	sti();
-	return 0;
-}
-
-/*
- * This routine sends a break character out the serial port.
- */
-static void SCC_set_break(struct m68k_async_struct * info, int break_flag)
-{
-	unsigned long	flags;
-
-	save_flags(flags);
-	cli();
-
-	if (break_flag) {
-		info->private->curregs[5] |= SND_BRK;
-		write_zsreg(info->private->zs_channel, 5, 
-			    info->private->curregs[5]);
-	} else {
-		info->private->curregs[5] &= ~SND_BRK;
-		write_zsreg(info->private->zs_channel, 5, 
-			    info->private->curregs[5]);
-	}
-
-	restore_flags(flags);
-}
-
-/* FIXME: these have to be enabled in rs_ioctl !! */
-
-static int SCC_ioctl(struct tty_struct *tty, struct file * file,
-		    struct m68k_async_struct * info, unsigned int cmd, 
-	            unsigned long arg)
-{
-	int error;
-	int retval;
-
-	switch (cmd) {
-		case TIOCSERGETLSR: /* Get line status register */
-			error = verify_area(VERIFY_WRITE, (void *) arg,
-				sizeof(unsigned int));
-			if (error)
-				return error;
-			else
-			    return SCC_get_lsr_info(info, (unsigned int *) arg);
-
-		case TIOCSERGSTRUCT:
-			error = verify_area(VERIFY_WRITE, (void *) arg,
-						sizeof(struct m68k_async_struct));
-			if (error)
-				return error;
-			copy_to_user((struct m68k_async_struct *) arg,
-				      info, sizeof(struct m68k_async_struct));
-			return 0;
-			
-		default:
-			return -ENOIOCTLCMD;
-		}
-	return 0;
-}
-
-static void SCC_stop_receive (struct m68k_async_struct *info)
-{
-	/* disable Rx */
-	info->private->curregs[3] &= ~RxENABLE;
-	info->private->pendregs[3] = info->private->curregs[3];
-	write_zsreg(info->private->zs_channel, 3, info->private->curregs[3]);
-	/* disable Rx interrupts */
-	info->private->curregs[1] &= ~(0x18);	/* disable any rx ints */
-	info->private->pendregs[1] = info->private->curregs[1];
-	write_zsreg(info->private->zs_channel, 1, info->private->curregs[1]);
-	ZS_CLEARFIFO(info->private->zs_channel);
-}
-
-static int SCC_trans_empty (struct m68k_async_struct *info)
-{
-	return  (read_zsreg(info->private->zs_channel, 1) & ALL_SNT) != 0;
-}
-
-/* Finally, routines used to initialize the serial driver. */
-
-#ifdef CONFIG_MAC
-
-/*
- *	Mac: use boot_info data; assume 2 channels
- */
- 
-static void probe_sccs(void)
-{
-	int n;
-
-#define ZS_CONTROL	0x50F04000
-#define ZS_DATA		(ZS_CONTROL+4)
-#define ZS_IRQ		5
-#define ZS_MOVE		-2
-#define ZS_DATA_MOVE	4
-#define ZS_CH_A_FIRST	2
-
-	/* last-ditch fixup for NetBSD booter case */
-	if (mac_bi_data.sccbase == 0)
-		mac_bi_data.sccbase = ZS_CONTROL;
-
-	/* testing: fix up broken 24 bit addresses (ClassicII) */
-	if ((mac_bi_data.sccbase & 0x00FFFFFF) == mac_bi_data.sccbase)
-		mac_bi_data.sccbase |= 0x50000000;
-
-	for(n=0;n<2;n++)
-	{
-#if 0
-		zs_channels[n].control = (volatile unsigned char *)
-				ZS_CONTROL+ZS_MOVE*n;
-		zs_channels[n].data = (volatile unsigned char *)ZS_DATA+ZS_MOVE*n;
-#else
-		zs_channels[n].control = (volatile unsigned char *)
-			(mac_bi_data.sccbase+ZS_CH_A_FIRST)+ZS_MOVE*n;
-		zs_channels[n].data = (volatile unsigned char *)
-			(mac_bi_data.sccbase+ZS_CH_A_FIRST+ZS_DATA_MOVE)+ZS_MOVE*n;
-#endif
-		zs_soft[n].private = &zs_soft_private[n];
-		zs_soft[n].private->zs_channel = &zs_channels[n];
-		zs_soft[n].irq = IRQ4;
-#if 0		
-		if (request_irq(ch->intrs[0], rs_interrupt, 0,
-				"SCC", &zs_soft[n]))
-			panic("macserial: can't get irq %d",
-			      ch->intrs[0]);
-#endif
-		if (n & 1)
-			zs_soft[n].private->zs_chan_a = &zs_channels[n-1];
-		else
-			zs_soft[n].private->zs_chan_a = &zs_channels[n];
-	}
-
-	zs_channels_found=2;
-}
-
-#else
-
-/*
- *	PowerMAC - query the PROM
- */
- 
-static void show_serial_version(void)
-{
-	printk("PowerMac Z8530 serial driver version 1.00\n");
-}
-
-/* Ask the PROM how many Z8530s we have and initialize their zs_channels */
-static void
-probe_sccs()
-{
-	struct device_node *dev, *ch;
-	struct m68k_async_struct **pp;
-	int n;
-
-	n = 0;
-	pp = &zs_chain;
-	for (dev = find_devices("escc"); dev != 0; dev = dev->next) {
-		if (n >= NUM_CHANNELS) {
-			printk("Sorry, can't use %s: no more channels\n",
-			       dev->full_name);
-			continue;
-		}
-		for (ch = dev->child; ch != 0; ch = ch->sibling) {
-			if (ch->n_addrs < 1 || ch ->n_intrs < 1) {
-				printk("Can't use %s: %d addrs %d intrs\n",
-				      ch->full_name, ch->n_addrs, ch->n_intrs);
-				continue;
-			}
-			zs_channels[n].control = (volatile unsigned char *)
-				ch->addrs[0].address;
-			zs_channels[n].data = zs_channels[n].control
-				+ ch->addrs[0].size / 2;
-			zs_soft[n].private = &zs_soft_private[n];
-			zs_soft[n].private->zs_channel = &zs_channels[n];
-			zs_soft[n].irq = ch->intrs[0];
-			if (request_irq(ch->intrs[0], mac_SCC_interrupt, 0,
-					"SCC", &zs_soft[n]))
-				panic("macserial: can't get irq %d",
-				      ch->intrs[0]);
-			/* XXX this assumes the prom puts chan A before B */
-			if (n & 1)
-				zs_soft[n].private->zs_chan_a = &zs_channels[n-1];
-			else
-				zs_soft[n].private->zs_chan_a = &zs_channels[n];
-
-			*pp = &zs_soft[n];
-			pp = &zs_soft[n].private->zs_next;
-			++n;
-		}
-	}
-	*pp = 0;
-	zs_channels_found = n;
-}
-
-#endif
-
-extern void register_console(void (*proc)(const char *));
-
-static inline void
-rs_cons_check(struct m68k_async_struct *ss, int channel)
-{
-	int i, o, io;
-	static consout_registered = 0;
-	static msg_printed = 0;
-
-	i = o = io = 0;
-
-	/* Is this one of the serial console lines? */
-	if ((zs_cons_chanout != channel) &&
-	    (zs_cons_chanin != channel))
-		return;
-	zs_conschan = ss->private->zs_channel;
-	zs_consinfo = ss;
-
-	/* Register the console output putchar, if necessary */
-	if (zs_cons_chanout == channel) {
-		o = 1;
-		/* double whee.. */
-		if (!consout_registered) {
-			register_console(zs_console_print);
-			consout_registered = 1;
-		}
-	}
-
-	if (zs_cons_chanin == channel) {
-		i = 1;
-	}
-	if (o && i)
-		io = 1;
-	if (ss->private->zs_baud != 9600)
-		panic("Console baud rate weirdness");
-
-	/* Set flag variable for this port so that it cannot be
-	 * opened for other uses by accident.
-	 */
-	ss->private->is_cons = 1;
-
-	if (io) {
-		if(!msg_printed) {
-			printk("zs%d: console I/O\n", ((channel>>1)&1));
-			msg_printed = 1;
-		}
-	} else {
-		printk("zs%d: console %s\n", ((channel>>1)&1),
-		       (i==1 ? "input" : (o==1 ? "output" : "WEIRD")));
-	}
-
-	/* FIXME : register interrupt here??? */
-}
-
-volatile int test_done;
-
-/* rs_init inits the driver */
-int mac_SCC_init(void)
-{
-	int channel, line, nr = 0, i;
-	unsigned long flags;
-	struct serial_struct req;
-	struct m68k_async_struct *info;
-
-	printk("Mac68K Z8530 serial driver version 1.01\n");
-
-	/* SCC present at all? */
-	if (MACH_IS_ATARI || MACH_IS_AMIGA 
-#if 0
-	    || !(MACHW_PRESENT(SCC) || MACHW_PRESENT(ST_ESCC))
-#endif
-	   )
-		return( -ENODEV );
-
-	if (zs_chain == 0)
-		probe_sccs();
-
-	save_flags(flags);
-	cli();
-
-	/* 
-	 * FIXME: init of rs_table entry and register_serial now done,
-	 * but possible clash of zs_soft[channel] and rs_table[channel]!!
-	 * zs_soft initialized in probe_sccs(), some settings copied to
-	 * info = &rs_table[channel], which is used by the mid-level code.
-	 * The info->private part is shared among both!
-	 */
-
-	for (channel = 0; channel < zs_channels_found; ++channel) {
-		req.line = channel;
-		req.type = SER_SCC_MAC;
-		req.port = zs_soft[channel].private->zs_channel->control;
-
-		if ((line = register_serial( &req )) >= 0) {
-			SCC_init_port( &rs_table[line], req.type, line );
-			++nr;
-		}
-		else
-			printk(KERN_WARNING "Cannot allocate ttyS%d for SCC channel A\n", req.line );
-	}
-
-	restore_flags(flags);
-
-	return( nr > 0 ? 0 : -ENODEV );
-}
-
-/* Hooks for running a serial console.  con_init() calls this if the
- * console is being run over one of the serial ports.
- * 'channel' is decoded as 0=modem 1=printer, 'chip' is ignored.
- */
-void
-rs_cons_hook(int chip, int out, int channel)
-{
-	if (zs_chain == 0)
-		probe_sccs();
-	zs_soft[channel].private->clk_divisor = 16;
-	zs_soft[channel].private->zs_baud = get_zsbaud(&zs_soft[channel]);
-	rs_cons_check(&zs_soft[channel], channel);
-	if (out)
-		zs_cons_chanout = channel;
-	else
-		zs_cons_chanin = channel;
-
-	/* FIXME : register interrupt here??? */
-}
-
-/* This is called at boot time to prime the kgdb serial debugging
- * serial line.  The 'tty_num' argument is 0 for /dev/ttyS0 and 1
- * for /dev/ttyS1 which is determined in setup_arch() from the
- * boot command line flags.
- */
-void
-rs_kgdb_hook(int tty_num)
-{
-	if (zs_chain == 0)
-		probe_sccs();
-	zs_kgdbchan = zs_soft[tty_num].private->zs_channel;
-	zs_soft[tty_num].private->clk_divisor = 16;
-	zs_soft[tty_num].private->zs_baud = get_zsbaud(&zs_soft[tty_num]);
-	zs_soft[tty_num].private->kgdb_channel = 1;     /* This runs kgdb */
-	zs_soft[tty_num ^ 1].private->kgdb_channel = 0; /* This does not */
-	/* Turn on transmitter/receiver at 8-bits/char */
-	kgdb_chaninit(&zs_soft[tty_num], 0, 9600);
-	ZS_CLEARERR(zs_kgdbchan);
-	ZS_CLEARFIFO(zs_kgdbchan);
-
-	/* FIXME : register interrupt here??? */
-}
-
-/*
- * mac_SCC.c: m68k version of
- *
- * macserial.c: Serial port driver for Power Macintoshes.
- *		Extended for the 68K mac by Alan Cox.
- *              Rewritten to m68k serial design by Michael Schmitz
- *
- * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras.
- *
- * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-/*
- * Design note for the m68k rewrite:
- * The structure of the m68k serial code requires separation of the low-level
- * functions that talk directly to the hardware from the Linux serial driver 
- * code interfacing to the tty layer. The reason for this separation is simply
- * the fact that the m68k serial hardware is, unlike the i386, based on a 
- * variety of chips, and the rs_* serial routines need to be shared.
- *
- * I've tried to make consistent use of the async_struct info populated in the
- * midlevel code, and introduced an async_private struct to hold the Macintosh 
- * SCC internals (this was added to the async_struct for the PowerMac driver).
- * Exception: the console and kgdb hooks still use the zs_soft[] data, and this
- * is still filled in by the probe_sccs() routine, which provides some data 
- * for mac_SCC_init as well. Interrupts are registered in mac_SCC_init, so 
- * the console/kgdb stuff probably won't work before proper serial init, and 
- * I have to rely on keeping info and zs_soft consistent at least for the 
- * console/kgdb port.
- *
- * Update (16-11-97): The SCC interrupt handling was suffering from the problem
- * that the autovector SCC interrupt was registered only once, hence only one
- * async_struct was passed to the interrupt function and only interrupts from 
- * the corresponding channel could be handled (yes, major design flaw).
- * The autovector interrupt is now registered by the main interrupt initfunc, 
- * and uses a handler that will call the registered SCC specific interrupts in 
- * turn. The SCC init has to register these as machspec interrupts now, as is 
- * done for the VIA interrupts elsewhere.
- */
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/config.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-
-#include <asm/uaccess.h>
-#include <asm/setup.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/macints.h>
 #include <asm/macintosh.h>
 #ifndef CONFIG_MAC
 #include <asm/prom.h>
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/char/mac_SCC.h m68k/drivers/char/mac_SCC.h
--- jes-2.1.108/drivers/char/mac_SCC.h	Thu Jun 18 20:52:55 1998
+++ m68k/drivers/char/mac_SCC.h	Wed Jun 24 20:41:05 1998
@@ -319,324 +319,3 @@
 				} while(0)
 
 #endif /* !(_MAC_SCC_H) */
-/*
- * macserial.h: Definitions for the Macintosh Z8530 serial driver.
- *
- * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras.
- *
- * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-#ifndef _MAC_SCC_H
-#define _MAC_SCC_H
-
-/*
- * For the close wait times, 0 means wait forever for serial port to
- * flush its output.  65535 means don't wait at all.
- */
-#define ZILOG_CLOSING_WAIT_INF	0
-#define ZILOG_CLOSING_WAIT_NONE	65535
-
-/*
- * Definitions for ZILOG_struct (and serial_struct) flags field
- */
-#define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes 
-				   on the callout port */
-#define ZILOG_FOURPORT  0x0002	/* Set OU1, OUT2 per AST Fourport settings */
-#define ZILOG_SAK	0x0004	/* Secure Attention Key (Orange book) */
-#define ZILOG_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
-
-#define ZILOG_SPD_MASK	0x0030
-#define ZILOG_SPD_HI	0x0010	/* Use 56000 instead of 38400 bps */
-
-#define ZILOG_SPD_VHI	0x0020  /* Use 115200 instead of 38400 bps */
-#define ZILOG_SPD_CUST	0x0030  /* Use user-specified divisor */
-
-#define ZILOG_SKIP_TEST	0x0040 /* Skip UART test during autoconfiguration */
-#define ZILOG_AUTO_IRQ  0x0080 /* Do automatic IRQ during autoconfiguration */
-#define ZILOG_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
-#define ZILOG_PGRP_LOCKOUT    0x0200 /* Lock out cua opens based on pgrp */
-#define ZILOG_CALLOUT_NOHUP   0x0400 /* Don't do hangups for cua device */
-
-#define ZILOG_FLAGS	0x0FFF	/* Possible legal ZILOG flags */
-#define ZILOG_USR_MASK 0x0430	/* Legal flags that non-privileged
-				 * users can set or reset */
-
-/* Internal flags used only by kernel/chr_drv/serial.c */
-#define ZILOG_INITIALIZED	0x80000000 /* Serial port was initialized */
-#define ZILOG_CALLOUT_ACTIVE	0x40000000 /* Call out device is active */
-#define ZILOG_NORMAL_ACTIVE	0x20000000 /* Normal device is active */
-#define ZILOG_BOOT_AUTOCONF	0x10000000 /* Autoconfigure port on bootup */
-#define ZILOG_CLOSING		0x08000000 /* Serial port is closing */
-#define ZILOG_CTS_FLOW		0x04000000 /* Do CTS flow control */
-#define ZILOG_CHECK_CD		0x02000000 /* i.e., CLOCAL */
-
-/* Software state per channel */
-
-#ifdef __KERNEL__
-/*
- * This is our internal structure for each serial port's state.
- * 
- * Many fields are paralleled by the structure used by the serial_struct
- * structure.
- *
- * For definitions of the flags field, see tty.h
- */
-
-/* MSch: gone to <asm/serial.h> */
-
-#define SERIAL_MAGIC 0x5301
-
-/*
- * The size of the serial xmit buffer is 1 page, or 4096 bytes
- */
-#define SERIAL_XMIT_SIZE 4096
-
-/*
- * Events are used to schedule things to happen at timer-interrupt
- * time, instead of at rs interrupt time.
- */
-#define RS_EVENT_WRITE_WAKEUP	0
-
-#endif /* __KERNEL__ */
-
-/* Conversion routines to/from brg time constants from/to bits
- * per second.
- */
-#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
-#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
-
-/* The Zilog register set */
-
-#define	FLAG	0x7e
-
-/* Write Register 0 */
-#define	R0	0		/* Register selects */
-#define	R1	1
-#define	R2	2
-#define	R3	3
-#define	R4	4
-#define	R5	5
-#define	R6	6
-#define	R7	7
-#define	R8	8
-#define	R9	9
-#define	R10	10
-#define	R11	11
-#define	R12	12
-#define	R13	13
-#define	R14	14
-#define	R15	15
-
-#define	NULLCODE	0	/* Null Code */
-#define	POINT_HIGH	0x8	/* Select upper half of registers */
-#define	RES_EXT_INT	0x10	/* Reset Ext. Status Interrupts */
-#define	SEND_ABORT	0x18	/* HDLC Abort */
-#define	RES_RxINT_FC	0x20	/* Reset RxINT on First Character */
-#define	RES_Tx_P	0x28	/* Reset TxINT Pending */
-#define	ERR_RES		0x30	/* Error Reset */
-#define	RES_H_IUS	0x38	/* Reset highest IUS */
-
-#define	RES_Rx_CRC	0x40	/* Reset Rx CRC Checker */
-#define	RES_Tx_CRC	0x80	/* Reset Tx CRC Checker */
-#define	RES_EOM_L	0xC0	/* Reset EOM latch */
-
-/* Write Register 1 */
-
-#define	EXT_INT_ENAB	0x1	/* Ext Int Enable */
-#define	TxINT_ENAB	0x2	/* Tx Int Enable */
-#define	PAR_SPEC	0x4	/* Parity is special condition */
-
-#define	RxINT_DISAB	0	/* Rx Int Disable */
-#define	RxINT_FCERR	0x8	/* Rx Int on First Character Only or Error */
-#define	INT_ALL_Rx	0x10	/* Int on all Rx Characters or error */
-#define	INT_ERR_Rx	0x18	/* Int on error only */
-
-#define	WT_RDY_RT	0x20	/* Wait/Ready on R/T */
-#define	WT_FN_RDYFN	0x40	/* Wait/FN/Ready FN */
-#define	WT_RDY_ENAB	0x80	/* Wait/Ready Enable */
-
-/* Write Register #2 (Interrupt Vector) */
-
-/* Write Register 3 */
-
-#define	RxENABLE	0x1	/* Rx Enable */
-#define	SYNC_L_INH	0x2	/* Sync Character Load Inhibit */
-#define	ADD_SM		0x4	/* Address Search Mode (SDLC) */
-#define	RxCRC_ENAB	0x8	/* Rx CRC Enable */
-#define	ENT_HM		0x10	/* Enter Hunt Mode */
-#define	AUTO_ENAB	0x20	/* Auto Enables */
-#define	Rx5		0x0	/* Rx 5 Bits/Character */
-#define	Rx7		0x40	/* Rx 7 Bits/Character */
-#define	Rx6		0x80	/* Rx 6 Bits/Character */
-#define	Rx8		0xc0	/* Rx 8 Bits/Character */
-#define RxNBITS_MASK	0xc0
-
-/* Write Register 4 */
-
-#define	PAR_ENA		0x1	/* Parity Enable */
-#define	PAR_EVEN	0x2	/* Parity Even/Odd* */
-
-#define	SYNC_ENAB	0	/* Sync Modes Enable */
-#define	SB1		0x4	/* 1 stop bit/char */
-#define	SB15		0x8	/* 1.5 stop bits/char */
-#define	SB2		0xc	/* 2 stop bits/char */
-#define SB_MASK		0xc
-
-#define	MONSYNC		0	/* 8 Bit Sync character */
-#define	BISYNC		0x10	/* 16 bit sync character */
-#define	SDLC		0x20	/* SDLC Mode (01111110 Sync Flag) */
-#define	EXTSYNC		0x30	/* External Sync Mode */
-
-#define	X1CLK		0x0	/* x1 clock mode */
-#define	X16CLK		0x40	/* x16 clock mode */
-#define	X32CLK		0x80	/* x32 clock mode */
-#define	X64CLK		0xC0	/* x64 clock mode */
-#define XCLK_MASK	0xC0
-
-/* Write Register 5 */
-
-#define	TxCRC_ENAB	0x1	/* Tx CRC Enable */
-#define	RTS		0x2	/* RTS */
-#define	SDLC_CRC	0x4	/* SDLC/CRC-16 */
-#define	TxENAB		0x8	/* Tx Enable */
-#define	SND_BRK		0x10	/* Send Break */
-#define	Tx5		0x0	/* Tx 5 bits (or less)/character */
-#define	Tx7		0x20	/* Tx 7 bits/character */
-#define	Tx6		0x40	/* Tx 6 bits/character */
-#define	Tx8		0x60	/* Tx 8 bits/character */
-#define TxNBITS_MASK	0x60
-#define	DTR		0x80	/* DTR */
-
-/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
-
-/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
-
-/* Write Register 8 (transmit buffer) */
-
-/* Write Register 9 (Master interrupt control) */
-#define	VIS	1	/* Vector Includes Status */
-#define	NV	2	/* No Vector */
-#define	DLC	4	/* Disable Lower Chain */
-#define	MIE	8	/* Master Interrupt Enable */
-#define	STATHI	0x10	/* Status high */
-#define	NORESET	0	/* No reset on write to R9 */
-#define	CHRB	0x40	/* Reset channel B */
-#define	CHRA	0x80	/* Reset channel A */
-#define	FHWRES	0xc0	/* Force hardware reset */
-
-/* Write Register 10 (misc control bits) */
-#define	BIT6	1	/* 6 bit/8bit sync */
-#define	LOOPMODE 2	/* SDLC Loop mode */
-#define	ABUNDER	4	/* Abort/flag on SDLC xmit underrun */
-#define	MARKIDLE 8	/* Mark/flag on idle */
-#define	GAOP	0x10	/* Go active on poll */
-#define	NRZ	0	/* NRZ mode */
-#define	NRZI	0x20	/* NRZI mode */
-#define	FM1	0x40	/* FM1 (transition = 1) */
-#define	FM0	0x60	/* FM0 (transition = 0) */
-#define	CRCPS	0x80	/* CRC Preset I/O */
-
-/* Write Register 11 (Clock Mode control) */
-#define	TRxCXT	0	/* TRxC = Xtal output */
-#define	TRxCTC	1	/* TRxC = Transmit clock */
-#define	TRxCBR	2	/* TRxC = BR Generator Output */
-#define	TRxCDP	3	/* TRxC = DPLL output */
-#define	TRxCOI	4	/* TRxC O/I */
-#define	TCRTxCP	0	/* Transmit clock = RTxC pin */
-#define	TCTRxCP	8	/* Transmit clock = TRxC pin */
-#define	TCBR	0x10	/* Transmit clock = BR Generator output */
-#define	TCDPLL	0x18	/* Transmit clock = DPLL output */
-#define	RCRTxCP	0	/* Receive clock = RTxC pin */
-#define	RCTRxCP	0x20	/* Receive clock = TRxC pin */
-#define	RCBR	0x40	/* Receive clock = BR Generator output */
-#define	RCDPLL	0x60	/* Receive clock = DPLL output */
-#define	RTxCX	0x80	/* RTxC Xtal/No Xtal */
-
-/* Write Register 12 (lower byte of baud rate generator time constant) */
-
-/* Write Register 13 (upper byte of baud rate generator time constant) */
-
-/* Write Register 14 (Misc control bits) */
-#define	BRENABL	1	/* Baud rate generator enable */
-#define	BRSRC	2	/* Baud rate generator source */
-#define	DTRREQ	4	/* DTR/Request function */
-#define	AUTOECHO 8	/* Auto Echo */
-#define	LOOPBAK	0x10	/* Local loopback */
-#define	SEARCH	0x20	/* Enter search mode */
-#define	RMC	0x40	/* Reset missing clock */
-#define	DISDPLL	0x60	/* Disable DPLL */
-#define	SSBR	0x80	/* Set DPLL source = BR generator */
-#define	SSRTxC	0xa0	/* Set DPLL source = RTxC */
-#define	SFMM	0xc0	/* Set FM mode */
-#define	SNRZI	0xe0	/* Set NRZI mode */
-
-/* Write Register 15 (external/status interrupt control) */
-#define	ZCIE	2	/* Zero count IE */
-#define	DCDIE	8	/* DCD IE */
-#define	SYNCIE	0x10	/* Sync/hunt IE */
-#define	CTSIE	0x20	/* CTS IE */
-#define	TxUIE	0x40	/* Tx Underrun/EOM IE */
-#define	BRKIE	0x80	/* Break/Abort IE */
-
-
-/* Read Register 0 */
-#define	Rx_CH_AV	0x1	/* Rx Character Available */
-#define	ZCOUNT		0x2	/* Zero count */
-#define	Tx_BUF_EMP	0x4	/* Tx Buffer empty */
-#define	DCD		0x8	/* DCD */
-#define	SYNC_HUNT	0x10	/* Sync/hunt */
-#define	CTS		0x20	/* CTS */
-#define	TxEOM		0x40	/* Tx underrun */
-#define	BRK_ABRT	0x80	/* Break/Abort */
-
-/* Read Register 1 */
-#define	ALL_SNT		0x1	/* All sent */
-/* Residue Data for 8 Rx bits/char programmed */
-#define	RES3		0x8	/* 0/3 */
-#define	RES4		0x4	/* 0/4 */
-#define	RES5		0xc	/* 0/5 */
-#define	RES6		0x2	/* 0/6 */
-#define	RES7		0xa	/* 0/7 */
-#define	RES8		0x6	/* 0/8 */
-#define	RES18		0xe	/* 1/8 */
-#define	RES28		0x0	/* 2/8 */
-/* Special Rx Condition Interrupts */
-#define	PAR_ERR		0x10	/* Parity error */
-#define	Rx_OVR		0x20	/* Rx Overrun Error */
-#define	FRM_ERR		0x40	/* CRC/Framing Error */
-#define	END_FR		0x80	/* End of Frame (SDLC) */
-
-/* Read Register 2 (channel b only) - Interrupt vector */
-
-/* Read Register 3 (interrupt pending register) ch a only */
-#define	CHBEXT	0x1		/* Channel B Ext/Stat IP */
-#define	CHBTxIP	0x2		/* Channel B Tx IP */
-#define	CHBRxIP	0x4		/* Channel B Rx IP */
-#define	CHAEXT	0x8		/* Channel A Ext/Stat IP */
-#define	CHATxIP	0x10		/* Channel A Tx IP */
-#define	CHARxIP	0x20		/* Channel A Rx IP */
-
-/* Read Register 8 (receive data register) */
-
-/* Read Register 10  (misc status bits) */
-#define	ONLOOP	2		/* On loop */
-#define	LOOPSEND 0x10		/* Loop sending */
-#define	CLK2MIS	0x40		/* Two clocks missing */
-#define	CLK1MIS	0x80		/* One clock missing */
-
-/* Read Register 12 (lower byte of baud rate generator constant) */
-
-/* Read Register 13 (upper byte of baud rate generator constant) */
-
-/* Read Register 15 (value of WR 15) */
-
-/* Misc macros */
-#define ZS_CLEARERR(channel)    (write_zsreg(channel, 0, ERR_RES))
-#define ZS_CLEARFIFO(channel)   do { volatile unsigned char garbage; \
-				     garbage = read_zsdata(channel); \
-				     garbage = read_zsdata(channel); \
-				     garbage = read_zsdata(channel); \
-				} while(0)
-
-#endif /* !(_MAC_SCC_H) */
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/char/n_tty.c m68k/drivers/char/n_tty.c
--- jes-2.1.108/drivers/char/n_tty.c	Tue Mar 24 19:04:23 1998
+++ m68k/drivers/char/n_tty.c	Sun Jun 14 22:20:25 1998
@@ -59,10 +59,10 @@
 
 static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
 {
-	if (tty->read_cnt < N_TTY_BUF_SIZE) {
+	if (atomic_read(&tty->read_cnt) < N_TTY_BUF_SIZE) {
 		tty->read_buf[tty->read_head] = c;
 		tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
-		tty->read_cnt++;
+		atomic_inc(&tty->read_cnt);
 	}
 }
 
@@ -85,7 +85,8 @@
  */
 static void reset_buffer_flags(struct tty_struct *tty)
 {
-	tty->read_head = tty->read_tail = tty->read_cnt = 0;
+	tty->read_head = tty->read_tail = 0;
+	atomic_set(&tty->read_cnt, 0);
 	tty->canon_head = tty->canon_data = tty->erasing = 0;
 	memset(&tty->read_flags, 0, sizeof tty->read_flags);
 	check_unthrottle(tty);
@@ -120,7 +121,7 @@
 			tty->canon_head - tty->read_tail :
 			tty->canon_head + (N_TTY_BUF_SIZE - tty->read_tail);
 	}
-	return tty->read_cnt;
+	return atomic_read(&tty->read_cnt);
 }
 
 /*
@@ -293,14 +294,16 @@
 		kill_type = WERASE;
 	else {
 		if (!L_ECHO(tty)) {
-			tty->read_cnt -= ((tty->read_head - tty->canon_head) &
-					  (N_TTY_BUF_SIZE - 1));
+			atomic_sub(((tty->read_head - tty->canon_head) &
+				    (N_TTY_BUF_SIZE - 1)),
+				   &tty->read_cnt);
 			tty->read_head = tty->canon_head;
 			return;
 		}
 		if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) {
-			tty->read_cnt -= ((tty->read_head - tty->canon_head) &
-					  (N_TTY_BUF_SIZE - 1));
+			atomic_sub(((tty->read_head - tty->canon_head) &
+				    (N_TTY_BUF_SIZE - 1)),
+				   &tty->read_cnt);
 			tty->read_head = tty->canon_head;
 			finish_erasing(tty);
 			echo_char(KILL_CHAR(tty), tty);
@@ -324,7 +327,7 @@
 				break;
 		}
 		tty->read_head = head;
-		tty->read_cnt--;
+		atomic_dec(&tty->read_cnt);
 		if (L_ECHO(tty)) {
 			if (L_ECHOPRT(tty)) {
 				if (!tty->erasing) {
@@ -482,7 +485,7 @@
 		finish_erasing(tty);
 		tty->lnext = 0;
 		if (L_ECHO(tty)) {
-			if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
+			if (atomic_read(&tty->read_cnt) >= N_TTY_BUF_SIZE-1) {
 				put_char('\a', tty); /* beep if no space */
 				return;
 			}
@@ -561,7 +564,7 @@
 		}
 		if (c == '\n') {
 			if (L_ECHO(tty) || L_ECHONL(tty)) {
-				if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
+				if (atomic_read(&tty->read_cnt) >= N_TTY_BUF_SIZE-1) {
 					put_char('\a', tty);
 					return;
 				}
@@ -581,7 +584,7 @@
 			 * XXX are EOL_CHAR and EOL2_CHAR echoed?!?
 			 */
 			if (L_ECHO(tty)) {
-				if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
+				if (atomic_read(&tty->read_cnt) >= N_TTY_BUF_SIZE-1) {
 					put_char('\a', tty);
 					return;
 				}
@@ -612,7 +615,7 @@
 	
 	finish_erasing(tty);
 	if (L_ECHO(tty)) {
-		if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
+		if (atomic_read(&tty->read_cnt) >= N_TTY_BUF_SIZE-1) {
 			put_char('\a', tty); /* beep if no space */
 			return;
 		}
@@ -634,7 +637,7 @@
 
 static int n_tty_receive_room(struct tty_struct *tty)
 {
-	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+	int	left = N_TTY_BUF_SIZE - atomic_read(&tty->read_cnt) - 1;
 
 	/*
 	 * If we are doing input canonicalization, and there are no
@@ -662,19 +665,20 @@
 		return;
 
 	if (tty->real_raw) {
-		i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,
+		int read_cnt = atomic_read(&tty->read_cnt);
+		i = MIN(count, MIN(N_TTY_BUF_SIZE - read_cnt,
 				   N_TTY_BUF_SIZE - tty->read_head));
 		memcpy(tty->read_buf + tty->read_head, cp, i);
 		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
-		tty->read_cnt += i;
+		read_cnt += i;
 		cp += i;
 		count -= i;
 
-		i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,
+		i = MIN(count, MIN(N_TTY_BUF_SIZE - read_cnt,
 			       N_TTY_BUF_SIZE - tty->read_head));
 		memcpy(tty->read_buf + tty->read_head, cp, i);
 		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
-		tty->read_cnt += i;
+		atomic_set(&tty->read_cnt, read_cnt + i);
 	} else {
 		for (i=count, p = cp, f = fp; i; i--, p++) {
 			if (f)
@@ -703,7 +707,7 @@
 			tty->driver.flush_chars(tty);
 	}
 
-	if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
+	if (!tty->icanon && (atomic_read(&tty->read_cnt) >= tty->minimum_to_wake)) {
 		if (tty->fasync)
 			kill_fasync(tty->fasync, SIGIO);
 		if (tty->read_wait)
@@ -828,7 +832,7 @@
 	if (tty->icanon) {
 		if (tty->canon_data)
 			return 1;
-	} else if (tty->read_cnt >= (amt ? amt : 1))
+	} else if (atomic_read(&tty->read_cnt) >= (amt ? amt : 1))
 		return 1;
 
 	return 0;
@@ -848,14 +852,16 @@
 
 {
 	ssize_t n;
+	int read_cnt = atomic_read(&tty->read_cnt);
 
-	n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail));
+	n = MIN(*nr, MIN(read_cnt, N_TTY_BUF_SIZE - tty->read_tail));
 	if (!n)
 		return;
 	/* N.B. copy_to_user may work only partially */
 	n -= copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
 	tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
-	tty->read_cnt -= n;
+	/* tty->read_cnt may have changed while we slept. */
+	atomic_sub(n, &tty->read_cnt);
 	*b += n;
 	*nr -= n;
 }
@@ -973,7 +979,7 @@
 
 		if (tty->icanon) {
 			/* N.B. avoid overrun if nr == 0 */
-			while (nr && tty->read_cnt) {
+			while (nr && atomic_read(&tty->read_cnt)) {
  				int eol;
 
 				eol = test_and_clear_bit(tty->read_tail,
@@ -981,7 +987,7 @@
 				c = tty->read_buf[tty->read_tail];
 				tty->read_tail = ((tty->read_tail+1) &
 						  (N_TTY_BUF_SIZE-1));
-				tty->read_cnt--;
+				atomic_dec(&tty->read_cnt);
 
 				if (!eol || (c != __DISABLED_CHAR)) {
 					put_user(c, b++);
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/char/tty_ioctl.c m68k/drivers/char/tty_ioctl.c
--- jes-2.1.108/drivers/char/tty_ioctl.c	Tue Mar 24 19:04:17 1998
+++ m68k/drivers/char/tty_ioctl.c	Sun Jun 14 22:20:25 1998
@@ -120,7 +120,7 @@
 		tty->erasing = 0;
 	}
 	sti();
-	if (canon_change && !L_ICANON(tty) && tty->read_cnt)
+	if (canon_change && !L_ICANON(tty) && atomic_read(&tty->read_cnt))
 		/* Get characters left over from canonical mode. */
 		wake_up_interruptible(&tty->read_wait);
 
@@ -477,7 +477,7 @@
 					tty->driver.chars_in_buffer(tty) : 0,
 					(int *) arg);
 		case TIOCINQ:
-			retval = tty->read_cnt;
+			retval = atomic_read(&tty->read_cnt);
 			if (L_ICANON(tty))
 				retval = inq_canon(tty);
 			return put_user(retval, (unsigned int *) arg);
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/net/8390.c m68k/drivers/net/8390.c
--- jes-2.1.108/drivers/net/8390.c	Thu Jun 18 20:52:56 1998
+++ m68k/drivers/net/8390.c	Thu Jul  9 20:25:31 1998
@@ -950,7 +950,8 @@
 								int start_page)
 {
 	int e8390_base = dev->base_addr;
-    
+	struct ei_device *ei_local = (struct ei_device *) dev->priv;
+
 	outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
     
 	if (inb_p(e8390_base) & E8390_TRANS) 
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/net/8390.h m68k/drivers/net/8390.h
--- jes-2.1.108/drivers/net/8390.h	Mon Jun  8 20:46:05 1998
+++ m68k/drivers/net/8390.h	Thu Jul  9 20:25:31 1998
@@ -177,7 +177,7 @@
   unsigned char saved_irq;	/* Original dev->irq value. */
   /* The new statistics table. */
   struct net_device_stats stat;
-  unsigned char *reg_offset;    /* Register mapping table */
+  int *reg_offset;              /* Register mapping table */
 };
 
 /* The maximum number of 8390 interrupt service routines called per IRQ. */
@@ -207,11 +207,10 @@
 #define E8390_PAGE1	0x40	/* using the two high-order bits */
 #define E8390_PAGE2	0x80	/* Page 3 is invalid. */
 
-
-#ifndef CONFIG_MAC
-#define EI_SHIFT(x)	(x)
-#else
+#if defined(CONFIG_MAC) || defined(CONFIG_AMIGA_PCMCIA)
 #define EI_SHIFT(x)	(ei_local->reg_offset[x])
+#else
+#define EI_SHIFT(x)	(x)
 #endif
 
 #define E8390_CMD	EI_SHIFT(0x00)  /* The command register (for all pages) */
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/net/Makefile m68k/drivers/net/Makefile
--- jes-2.1.108/drivers/net/Makefile	Fri Jul 10 19:11:04 1998
+++ m68k/drivers/net/Makefile	Sun Jul 12 21:34:57 1998
@@ -82,6 +82,17 @@
 CONFIG_8390_BUILTIN = y
 endif
 
+ifeq ($(CONFIG_APNE),y)
+L_OBJS += apne.o
+CONFIG_8390_BUILTIN = y
+else
+  ifeq ($(CONFIG_APNE),m)
+  M_OBJS += apne.o
+  CONFIG_8390_MODULE = y
+  endif
+endif
+
+
 ifeq ($(CONFIG_SHAPER),y)
 L_OBJS += shaper.o
 else
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/net/Space.c m68k/drivers/net/Space.c
--- jes-2.1.108/drivers/net/Space.c	Fri Jul 10 19:11:04 1998
+++ m68k/drivers/net/Space.c	Sun Jul 12 20:30:02 1998
@@ -91,6 +91,7 @@
 extern int atarilance_probe(struct device *);
 extern int a2065_probe(struct device *);
 extern int ariadne_probe(struct device *);
+extern int apne_probe(struct device *);
 extern int hydra_probe(struct device *);
 extern int bionet_probe(struct device *);
 extern int pamsnet_probe(struct device *);
@@ -277,6 +278,9 @@
 #endif
 #ifdef CONFIG_ARIADNE		/* Village Tronic Ariadne Ethernet Board */
 	&& ariadne_probe(dev)
+#endif
+#ifdef CONFIG_APNE		/* Amiga PCMCIA NE2000 Ethernet Board */
+	&& apne_probe(dev)
 #endif
 #ifdef CONFIG_HYDRA		/* Hydra Systems Amiganet Ethernet board */
 	&& hydra_probe(dev)
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/net/apne.c m68k/drivers/net/apne.c
--- jes-2.1.108/drivers/net/apne.c	Thu Jan  1 01:00:00 1970
+++ m68k/drivers/net/apne.c	Thu Jul  9 20:25:31 1998
@@ -0,0 +1,634 @@
+/*
+ * Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200
+ *
+ * (C) Copyright 1997 Alain Malek
+ *                    (Alain.Malek@cryogen.com)
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is based on
+ *
+ * ne.c:       A general non-shared-memory NS8390 ethernet driver for linux
+ *             Written 1992-94 by Donald Becker.
+ *
+ * 8390.c:     A general NS8390 ethernet driver core for linux.
+ *             Written 1992-94 by Donald Becker.
+ *
+ * cnetdevice: A Sana-II ethernet driver for AmigaOS
+ *             Written by Bruce Abbott (bhabbott@inhb.co.nz)
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of the Linux
+ * distribution for more details.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/setup.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+#include <asm/amigayle.h>
+#include <asm/amipcmcia.h>
+
+#include "8390.h"
+
+/* ---- 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+GAYLE_ODD  /* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT	0x20
+
+#define NE_EN0_ISR		0x07+GAYLE_ODD
+#define NE_EN0_DCFG		0x0e
+
+#define NE_EN0_RSARLO	0x08
+#define NE_EN0_RSARHI	0x09+GAYLE_ODD
+#define NE_EN0_RCNTLO	0x0a
+#define NE_EN0_RXCR		0x0c
+#define NE_EN0_TXCR		0x0d+GAYLE_ODD
+#define NE_EN0_RCNTHI	0x0b+GAYLE_ODD
+#define NE_EN0_IMR		0x0f+GAYLE_ODD
+
+#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 */
+
+
+int apne_probe(struct device *dev);
+static int apne_probe1(struct device *dev, int ioaddr);
+
+static int apne_open(struct device *dev);
+static int apne_close(struct device *dev);
+
+static void apne_reset_8390(struct device *dev);
+static void apne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
+			  int ring_page);
+static void apne_block_input(struct device *dev, int count,
+								struct sk_buff *skb, int ring_offset);
+static void apne_block_output(struct device *dev, const int count,
+							const unsigned char *buf, const int start_page);
+static void apne_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+static int init_pcmcia(void);
+
+/* IO base address used for nic */
+
+#define IOBASE 0x300
+
+/*
+   use MANUAL_CONFIG and MANUAL_OFFSET for enabling IO by hand
+   you can find the values to use by looking at the cnet.device
+   config file example (the default values are for the CNET40BC card)
+*/
+
+/*
+#define MANUAL_CONFIG 0x20
+#define MANUAL_OFFSET 0x3f8
+
+#define MANUAL_HWADDR0 0x00
+#define MANUAL_HWADDR1 0x12
+#define MANUAL_HWADDR2 0x34
+#define MANUAL_HWADDR3 0x56
+#define MANUAL_HWADDR4 0x78
+#define MANUAL_HWADDR5 0x9a
+*/
+
+#define WORDSWAP(a) ( (((a)>>8)&0xff) | ((a)<<8) )
+
+
+static const char *version =
+    "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n";
+
+
+__initfunc(int apne_probe(struct device *dev))
+{
+#ifndef MANUAL_CONFIG
+	char tuple[8];
+#endif
+        
+	if ( !(AMIGAHW_PRESENT(PCMCIA)) )
+		return (ENODEV);
+                                
+	printk("Looking for PCMCIA ethernet card : ");
+                                        
+	/* check if a card is inserted */
+	if (!(PCMCIA_INSERTED)) {
+		printk("NO PCMCIA card inserted\n");
+		return (ENODEV);
+	}
+                                                                                                
+	/* disable pcmcia irq for readtuple */
+	pcmcia_disable_irq();
+
+#ifndef MANUAL_CONFIG
+	if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) ||
+		(tuple[2] != CISTPL_FUNCID_NETWORK)) {
+		printk("not an ethernet card\n");
+		return (ENODEV);
+	}
+#endif
+
+	printk("ethernet PCMCIA card inserted\n");
+
+	if (init_pcmcia())
+		return apne_probe1(dev, IOBASE+GAYLE_IO);
+	else
+		return (ENODEV);
+
+}
+
+
+__initfunc(static int apne_probe1(struct device *dev, int ioaddr))
+{
+    int i;
+    unsigned char SA_prom[32];
+    int wordlength = 2;
+    const char *name = NULL;
+    int start_page, stop_page;
+#ifndef MANUAL_HWADDR0
+    int neX000, ctron;
+#endif
+    static unsigned version_printed = 0;
+    static int pcmcia_offsets[16]={
+                0,   1+GAYLE_ODD,   2,   3+GAYLE_ODD,
+                4,   5+GAYLE_ODD,   6,   7+GAYLE_ODD,
+                8,   9+GAYLE_ODD, 0xa, 0xb+GAYLE_ODD,
+              0xc, 0xd+GAYLE_ODD, 0xe, 0xf+GAYLE_ODD };
+
+    if (load_8390_module("apne.c"))
+        return -ENOSYS;
+
+    /* We should have a "dev" from Space.c or the static module table. */
+    if (dev == NULL) {
+	printk(KERN_ERR "apne.c: Passed a NULL device.\n");
+	dev = init_etherdev(0, 0);
+    }
+
+    if (ei_debug  &&  version_printed++ == 0)
+	printk(version);
+
+    printk("PCMCIA NE*000 ethercard probe");
+
+    /* Reset card. Who knows what dain-bramaged state it was left in. */
+    {	unsigned long reset_start_time = jiffies;
+
+	writeb(readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+	while ((readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
+		if (jiffies - reset_start_time > 2*HZ/100) {
+			printk(" not found (no reset ack).\n");
+			return ENODEV;
+		}
+
+	writeb(0xff, ioaddr + NE_EN0_ISR);		/* Ack all intr. */
+    }
+
+#ifndef MANUAL_HWADDR0
+
+    /* 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 long value, offset; } program_seq[] = {
+	    {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/
+	    {0x48,	NE_EN0_DCFG},	/* Set byte-wide (0x48) access. */
+	    {0x00,	NE_EN0_RCNTLO},	/* Clear the count regs. */
+	    {0x00,	NE_EN0_RCNTHI},
+	    {0x00,	NE_EN0_IMR},	/* Mask completion irq. */
+	    {0xFF,	NE_EN0_ISR},
+	    {E8390_RXOFF, NE_EN0_RXCR},	/* 0x20  Set to monitor */
+	    {E8390_TXOFF, NE_EN0_TXCR},	/* 0x02  and loopback mode. */
+	    {32,	NE_EN0_RCNTLO},
+	    {0x00,	NE_EN0_RCNTHI},
+	    {0x00,	NE_EN0_RSARLO},	/* DMA starting at 0x0000. */
+	    {0x00,	NE_EN0_RSARHI},
+	    {E8390_RREAD+E8390_START, NE_CMD},
+	};
+	for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) {
+	    writeb(program_seq[i].value, ioaddr + program_seq[i].offset);
+	}
+
+    }
+    for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
+	SA_prom[i] = readb(ioaddr + NE_DATAPORT);
+	SA_prom[i+1] = readb(ioaddr + NE_DATAPORT);
+	if (SA_prom[i] != SA_prom[i+1])
+	    wordlength = 1;
+    }
+
+    /*	At this point, wordlength *only* tells us if the SA_prom is doubled
+	up or not because some broken PCI cards don't respect the byte-wide
+	request in program_seq above, and hence don't have doubled up values. 
+	These broken cards would otherwise be detected as an ne1000.  */
+
+    if (wordlength == 2)
+	for (i = 0; i < 16; i++)
+		SA_prom[i] = SA_prom[i+i];
+    
+    if (wordlength == 2) {
+	/* We must set the 8390 for word mode. */
+	writeb(0x49, ioaddr + NE_EN0_DCFG);
+	start_page = NESM_START_PG;
+	stop_page = NESM_STOP_PG;
+    } else {
+	start_page = NE1SM_START_PG;
+	stop_page = NE1SM_STOP_PG;
+    }
+
+    neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
+    ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
+
+    /* Set up the rest of the parameters. */
+    if (neX000) {
+	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 {
+	printk(" not found.\n");
+	return ENXIO;
+
+    }
+
+#else
+    wordlength = 2;
+    /* We must set the 8390 for word mode. */
+    writeb(0x49, ioaddr + NE_EN0_DCFG);
+    start_page = NESM_START_PG;
+    stop_page = NESM_STOP_PG;
+
+    SA_prom[0] = MANUAL_HWADDR0;
+    SA_prom[1] = MANUAL_HWADDR1;
+    SA_prom[2] = MANUAL_HWADDR2;
+    SA_prom[3] = MANUAL_HWADDR3;
+    SA_prom[4] = MANUAL_HWADDR4;
+    SA_prom[5] = MANUAL_HWADDR5;
+    name = "NE2000";
+#endif
+
+    dev->base_addr = ioaddr;
+
+    /* Install the Interrupt handler */
+    if (request_irq(IRQ_AMIGA_PORTS, apne_interrupt, 0, "apne Ethernet", dev))
+        return -EAGAIN;
+
+
+    /* Allocate dev->priv and fill in 8390 specific dev fields. */
+    if (ethdev_init(dev)) {
+	printk (" unable to get memory for dev->priv.\n");
+	return -ENOMEM;
+    }
+
+    for(i = 0; i < ETHER_ADDR_LEN; i++) {
+	printk(" %2.2x", SA_prom[i]);
+	dev->dev_addr[i] = SA_prom[i];
+    }
+
+    printk("\n%s: %s found.\n",
+	   dev->name, name);
+
+    ei_status.name = name;
+    ei_status.tx_start_page = start_page;
+    ei_status.stop_page = stop_page;
+    ei_status.word16 = (wordlength == 2);
+
+    ei_status.rx_start_page = start_page + TX_PAGES;
+
+    ei_status.reset_8390 = &apne_reset_8390;
+    ei_status.block_input = &apne_block_input;
+    ei_status.block_output = &apne_block_output;
+    ei_status.get_8390_hdr = &apne_get_8390_hdr;
+    ei_status.reg_offset = pcmcia_offsets;
+    dev->open = &apne_open;
+    dev->stop = &apne_close;
+    NS8390_init(dev, 0);
+
+    pcmcia_ack_int(pcmcia_get_intreq());		/* ack PCMCIA int req */
+    pcmcia_enable_irq();
+
+    return 0;
+}
+
+static int
+apne_open(struct device *dev)
+{
+    ei_open(dev);
+    MOD_INC_USE_COUNT;
+    return 0;
+}
+
+static int
+apne_close(struct device *dev)
+{
+    if (ei_debug > 1)
+	printk("%s: Shutting down ethercard.\n", dev->name);
+    ei_close(dev);
+    MOD_DEC_USE_COUNT;
+    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
+apne_reset_8390(struct device *dev)
+{
+    unsigned long reset_start_time = jiffies;
+
+    init_pcmcia();
+
+    if (ei_debug > 1) printk("resetting the 8390 t=%ld...", jiffies);
+
+    writeb(readb(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 ((readb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
+	if (jiffies - reset_start_time > 2*HZ/100) {
+	    printk("%s: ne_reset_8390() did not complete.\n", dev->name);
+	    break;
+	}
+    writeb(ENISR_RESET, NE_BASE + NE_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
+apne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+
+    int nic_base = dev->base_addr;
+    int cnt;
+    char *ptrc;
+    short *ptrs;
+
+    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+    if (ei_status.dmaing) {
+	printk("%s: DMAing conflict in ne_get_8390_hdr "
+	   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+	   dev->name, ei_status.dmaing, ei_status.irqlock,
+	   dev->interrupt);
+	return;
+    }
+
+    ei_status.dmaing |= 0x01;
+    writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+    writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
+    writeb(0, nic_base + NE_EN0_RCNTHI);
+    writeb(0, nic_base + NE_EN0_RSARLO);		/* On page boundary */
+    writeb(ring_page, nic_base + NE_EN0_RSARHI);
+    writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+    if (ei_status.word16) {
+        ptrs = (short*)hdr;
+        for(cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++)
+            *ptrs++ = readw(NE_BASE + NE_DATAPORT);
+    } else {
+        ptrc = (char*)hdr;
+        for(cnt = 0; cnt < sizeof(struct e8390_pkt_hdr); cnt++)
+            *ptrc++ = readb(NE_BASE + NE_DATAPORT);
+    }
+
+    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
+
+    hdr->count = WORDSWAP(hdr->count);
+
+    ei_status.dmaing &= ~0x01;
+}
+
+/* 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 writeb. */
+
+static void
+apne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+    int nic_base = dev->base_addr;
+    char *buf = skb->data;
+    char *ptrc;
+    short *ptrs;
+    int cnt;
+
+    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+    if (ei_status.dmaing) {
+	printk("%s: DMAing conflict in ne_block_input "
+	   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+	   dev->name, ei_status.dmaing, ei_status.irqlock,
+	   dev->interrupt);
+	return;
+    }
+    ei_status.dmaing |= 0x01;
+    writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+    writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+    writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
+    writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
+    writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
+    writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+    if (ei_status.word16) {
+      ptrs = (short*)buf;
+      for (cnt = 0; cnt < (count>>1); cnt++)
+        *ptrs++ = readw(NE_BASE + NE_DATAPORT);
+      if (count & 0x01) {
+	buf[count-1] = readb(NE_BASE + NE_DATAPORT);
+      }
+    } else {
+      ptrc = (char*)buf;
+      for (cnt = 0; cnt < count; cnt++)
+        *ptrc++ = readb(NE_BASE + NE_DATAPORT);
+    }
+
+    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+}
+
+static void
+apne_block_output(struct device *dev, int count,
+		const unsigned char *buf, const int start_page)
+{
+    int nic_base = NE_BASE;
+    unsigned long dma_start;
+    char *ptrc;
+    short *ptrs;
+    int cnt;
+
+    /* 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("%s: DMAing conflict in ne_block_output."
+	   "[DMAstat:%d][irqlock:%d][intr:%d]\n",
+	   dev->name, ei_status.dmaing, ei_status.irqlock,
+	   dev->interrupt);
+	return;
+    }
+    ei_status.dmaing |= 0x01;
+    /* We should already be in page 0, but to be safe... */
+    writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+
+   /* Now the normal output. */
+    writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+    writeb(count >> 8,   nic_base + NE_EN0_RCNTHI);
+    writeb(0x00, nic_base + NE_EN0_RSARLO);
+    writeb(start_page, nic_base + NE_EN0_RSARHI);
+
+    writeb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+    if (ei_status.word16) {
+        ptrs = (short*)buf;
+        for (cnt = 0; cnt < count>>1; cnt++)
+            writew(*ptrs++, NE_BASE+NE_DATAPORT);
+    } else {
+        ptrc = (char*)buf;
+        for (cnt = 0; cnt < count; cnt++)
+	    writeb(*ptrc++, NE_BASE + NE_DATAPORT);
+    }
+
+    dma_start = jiffies;
+
+    while ((readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
+	if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */
+		printk("%s: timeout waiting for Tx RDC.\n", dev->name);
+		apne_reset_8390(dev);
+		NS8390_init(dev,1);
+		break;
+	}
+
+    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+    return;
+}
+
+static void apne_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+    unsigned char pcmcia_intreq;
+
+    if (!(gayle.inten & GAYLE_IRQ_IRQ))
+        return;
+
+    pcmcia_intreq = pcmcia_get_intreq();
+
+    if (!(pcmcia_intreq & GAYLE_IRQ_IRQ)) {
+        pcmcia_ack_int(pcmcia_intreq);
+        return;
+    }
+    if (ei_debug > 3)
+        printk("pcmcia intreq = %x\n", pcmcia_intreq);
+    pcmcia_disable_irq();			/* to get rid of the sti() within ei_interrupt */
+    ei_interrupt(irq, dev_id, regs);
+    pcmcia_ack_int(pcmcia_get_intreq());
+    pcmcia_enable_irq();
+}
+
+#ifdef MODULE
+static char devicename[9] = {0, };
+
+static struct device apne_dev =
+{
+	devicename,
+	0, 0, 0, 0,
+	0, 0,
+	0, 0, 0, NULL, apne_probe,
+};
+
+int init_module(void)
+{
+	int err;
+	if ((err = register_netdev(&apne_dev))) {
+		if (err == -EIO)
+			printk("No PCMCIA NEx000 ethernet card found.\n");
+		return (err);
+	}
+	lock_8390_module();
+	return (0);
+}
+
+void cleanup_module(void)
+{
+	unregister_netdev(&apne_dev);
+
+	pcmcia_disable_irq();
+
+	free_irq(IRQ_AMIGA_PORTS, &apne_dev);
+
+	pcmcia_reset();
+
+	unlock_8390_module();
+}
+
+#endif
+
+static int init_pcmcia(void)
+{
+	u_char config;
+#ifndef MANUAL_CONFIG
+	u_char tuple[32];
+	int offset_len;
+#endif
+	u_long offset;
+
+	pcmcia_reset();
+	pcmcia_program_voltage(PCMCIA_0V);
+	pcmcia_access_speed(PCMCIA_SPEED_250NS);
+	pcmcia_write_enable();
+
+#ifdef MANUAL_CONFIG
+	config = MANUAL_CONFIG;
+#else
+	/* get and write config byte to enable IO port */
+
+	if (pcmcia_copy_tuple(CISTPL_CFTABLE_ENTRY, tuple, 32) < 3)
+		return 0;
+
+	config = tuple[2] & 0x3f;
+#endif
+#ifdef MANUAL_OFFSET
+	offset = MANUAL_OFFSET;
+#else
+	if (pcmcia_copy_tuple(CISTPL_CONFIG, tuple, 32) < 6)
+		return 0;
+
+	offset_len = (tuple[2] & 0x3) + 1;
+	offset = 0;
+	while(offset_len--) {
+		offset = (offset << 8) | tuple[4+offset_len];
+	}
+#endif
+
+	writeb(config, GAYLE_ATTRIBUTE+offset);
+
+	return 1;
+}
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/net/daynaport.c m68k/drivers/net/daynaport.c
--- jes-2.1.108/drivers/net/daynaport.c	Mon Jun  8 20:46:06 1998
+++ m68k/drivers/net/daynaport.c	Thu Jul  9 20:25:31 1998
@@ -281,13 +281,13 @@
 {
 	static unsigned version_printed = 0;
 
-	static unsigned char fwrd4_offsets[16]={
+	static int fwrd4_offsets[16]={
 		0,      4,      8,      12,
 		16,     20,     24,     28,
 		32,     36,     40,     44,
 		48,     52,     56,     60
 	};
-	static unsigned char back4_offsets[16]={
+	static int back4_offsets[16]={
 		60,     56,     52,     48,
 		44,     40,     36,     32,
 		28,     24,     20,     16,
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/sound/Makefile m68k/drivers/sound/Makefile
--- jes-2.1.108/drivers/sound/Makefile	Thu Jun 18 20:52:59 1998
+++ m68k/drivers/sound/Makefile	Thu Jun 18 21:59:26 1998
@@ -42,7 +42,7 @@
 
 ifeq ($(ARCH),m68k)
 
-obj-$(CONFIG_DMASOUND)		+= dmasound.o
+obj-$(CONFIG_DMASOUND)		+= dmasound.o sound_core.o
 
 else
 
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/sound/dmasound.c m68k/drivers/sound/dmasound.c
--- jes-2.1.108/drivers/sound/dmasound.c	Thu Jun 18 20:52:59 1998
+++ m68k/drivers/sound/dmasound.c	Mon Jun 29 21:29:22 1998
@@ -73,6 +73,8 @@
 
 1996/9/25	++geert: modularization
 
+1998-06-10	++andreas: converted to use sound_core
+
 */
 
 
@@ -85,6 +87,8 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
+#include <linux/sound.h>
+#include <linux/init.h>
 
 #ifdef __mc68000__
 #include <asm/setup.h>
@@ -122,7 +126,9 @@
 #define HAS_8BIT_TABLES
 
 #ifdef MODULE
-static int chrdev_registered = 0;
+static int sq_unit = -1;
+static int mixer_unit = -1;
+static int state_unit = -1;
 static int irq_installed = 0;
 #endif /* MODULE */
 static char **sound_buffers = NULL;
@@ -258,7 +264,9 @@
 #define MAX_BUFSIZE		128	/* Limit for Amiga */
 
 static int catchRadius = 0, numBufs = 4, bufSize = 32;
-
+MODULE_PARM(catchRadius, "i");
+MODULE_PARM(numBufs, "i");
+MODULE_PARM(bufSize, "i");
 
 #define arraysize(x)	(sizeof(x)/sizeof(*(x)))
 #define min(x, y)	((x) < (y) ? (x) : (y))
@@ -510,74 +518,105 @@
 
 
 #ifdef CONFIG_ATARI
-static long ata_ct_law(const u_char *userPtr, unsigned long userCount,
-		       u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ct_s8(const u_char *userPtr, unsigned long userCount,
-		      u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ct_u8(const u_char *userPtr, unsigned long userCount,
-		      u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ct_s16be(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ct_u16be(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ct_s16le(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ct_u16le(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ctx_law(const u_char *userPtr, unsigned long userCount,
-			u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ctx_s8(const u_char *userPtr, unsigned long userCount,
-		       u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ctx_u8(const u_char *userPtr, unsigned long userCount,
-		       u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ctx_s16be(const u_char *userPtr, unsigned long userCount,
-			  u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ctx_u16be(const u_char *userPtr, unsigned long userCount,
-			  u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ctx_s16le(const u_char *userPtr, unsigned long userCount,
-			  u_char frame[], long *frameUsed, long frameLeft);
-static long ata_ctx_u16le(const u_char *userPtr, unsigned long userCount,
-			  u_char frame[], long *frameUsed, long frameLeft);
+static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount,
+			  u_char frame[], ssize_t *frameUsed,
+			  ssize_t frameLeft);
+static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount,
+			 u_char frame[], ssize_t *frameUsed,
+			 ssize_t frameLeft);
+static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount,
+			 u_char frame[], ssize_t *frameUsed,
+			 ssize_t frameLeft);
+static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
+static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
+static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
+static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
+static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft);
+static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount,
+			  u_char frame[], ssize_t *frameUsed,
+			  ssize_t frameLeft);
+static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount,
+			  u_char frame[], ssize_t *frameUsed,
+			  ssize_t frameLeft);
+static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount,
+			     u_char frame[], ssize_t *frameUsed,
+			     ssize_t frameLeft);
+static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount,
+			     u_char frame[], ssize_t *frameUsed,
+			     ssize_t frameLeft);
+static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount,
+			     u_char frame[], ssize_t *frameUsed,
+			     ssize_t frameLeft);
+static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount,
+			     u_char frame[], ssize_t *frameUsed,
+			     ssize_t frameLeft);
 #endif /* CONFIG_ATARI */
 
 #ifdef CONFIG_AMIGA
-static long ami_ct_law(const u_char *userPtr, unsigned long userCount,
-		       u_char frame[], long *frameUsed, long frameLeft);
-static long ami_ct_s8(const u_char *userPtr, unsigned long userCount,
-		      u_char frame[], long *frameUsed, long frameLeft);
-static long ami_ct_u8(const u_char *userPtr, unsigned long userCount,
-		      u_char frame[], long *frameUsed, long frameLeft);
-static long ami_ct_s16be(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft);
-static long ami_ct_u16be(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft);
-static long ami_ct_s16le(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft);
-static long ami_ct_u16le(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft);
+static ssize_t ami_ct_law(const u_char *userPtr, size_t userCount,
+			  u_char frame[], ssize_t *frameUsed,
+			  ssize_t frameLeft);
+static ssize_t ami_ct_s8(const u_char *userPtr, size_t userCount,
+			 u_char frame[], ssize_t *frameUsed,
+			 ssize_t frameLeft);
+static ssize_t ami_ct_u8(const u_char *userPtr, size_t userCount,
+			 u_char frame[], ssize_t *frameUsed,
+			 ssize_t frameLeft);
+static ssize_t ami_ct_s16be(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
+static ssize_t ami_ct_u16be(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
+static ssize_t ami_ct_s16le(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
+static ssize_t ami_ct_u16le(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
 #endif /* CONFIG_AMIGA */
 
 #ifdef CONFIG_PMAC
-static long pmac_ct_law(const u_char *userPtr, unsigned long userCount,
-			u_char frame[], long *frameUsed, long frameLeft);
-static long pmac_ct_s8(const u_char *userPtr, unsigned long userCount,
-		       u_char frame[], long *frameUsed, long frameLeft);
-static long pmac_ct_u8(const u_char *userPtr, unsigned long userCount,
-		       u_char frame[], long *frameUsed, long frameLeft);
-static long pmac_ct_s16(const u_char *userPtr, unsigned long userCount,
-			u_char frame[], long *frameUsed, long frameLeft);
-static long pmac_ct_u16(const u_char *userPtr, unsigned long userCount,
-			u_char frame[], long *frameUsed, long frameLeft);
-static long pmac_ctx_law(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft);
-static long pmac_ctx_s8(const u_char *userPtr, unsigned long userCount,
-			u_char frame[], long *frameUsed, long frameLeft);
-static long pmac_ctx_u8(const u_char *userPtr, unsigned long userCount,
-			u_char frame[], long *frameUsed, long frameLeft);
-static long pmac_ctx_s16(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft);
-static long pmac_ctx_u16(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft);
+static ssize_t pmac_ct_law(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft);
+static ssize_t pmac_ct_s8(const u_char *userPtr, size_t userCount,
+			  u_char frame[], ssize_t *frameUsed,
+			  ssize_t frameLeft);
+static ssize_t pmac_ct_u8(const u_char *userPtr, size_t userCount,
+			  u_char frame[], ssize_t *frameUsed,
+			  ssize_t frameLeft);
+static ssize_t pmac_ct_s16(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft);
+static ssize_t pmac_ct_u16(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft);
+static ssize_t pmac_ctx_law(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
+static ssize_t pmac_ctx_s8(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft);
+static ssize_t pmac_ctx_u8(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft);
+static ssize_t pmac_ctx_s16(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
+static ssize_t pmac_ctx_u16(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
 #endif /* CONFIG_PMAC */
 
 /*** Machine definitions *****************************************************/
@@ -613,14 +652,14 @@
 } SETTINGS;
 
 typedef struct {
-	long (*ct_ulaw)(const u_char *, unsigned long, u_char *, long *, long);
-	long (*ct_alaw)(const u_char *, unsigned long, u_char *, long *, long);
-	long (*ct_s8)(const u_char *, unsigned long, u_char *, long *, long);
-	long (*ct_u8)(const u_char *, unsigned long, u_char *, long *, long);
-	long (*ct_s16be)(const u_char *, unsigned long, u_char *, long *, long);
-	long (*ct_u16be)(const u_char *, unsigned long, u_char *, long *, long);
-	long (*ct_s16le)(const u_char *, unsigned long, u_char *, long *, long);
-	long (*ct_u16le)(const u_char *, unsigned long, u_char *, long *, long);
+	ssize_t (*ct_ulaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+	ssize_t (*ct_alaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+	ssize_t (*ct_s8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+	ssize_t (*ct_u8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+	ssize_t (*ct_s16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+	ssize_t (*ct_u16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+	ssize_t (*ct_s16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+	ssize_t (*ct_u16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
 } TRANS;
 
 struct sound_settings {
@@ -645,9 +684,9 @@
 
 
 #ifdef CONFIG_ATARI
-static void *AtaAlloc(unsigned int size, int flags);
-static void AtaFree(void *, unsigned int size);
-static int AtaIrqInit(void);
+static void *AtaAlloc(unsigned int size, int flags) __init;
+static void AtaFree(void *, unsigned int size) __init;
+static int AtaIrqInit(void) __init;
 #ifdef MODULE
 static void AtaIrqCleanUp(void);
 #endif /* MODULE */
@@ -668,9 +707,9 @@
 #endif /* CONFIG_ATARI */
 
 #ifdef CONFIG_AMIGA
-static void *AmiAlloc(unsigned int size, int flags);
-static void AmiFree(void *, unsigned int);
-static int AmiIrqInit(void);
+static void *AmiAlloc(unsigned int size, int flags) __init;
+static void AmiFree(void *, unsigned int) __init;
+static int AmiIrqInit(void) __init;
 #ifdef MODULE
 static void AmiIrqCleanUp(void);
 #endif /* MODULE */
@@ -685,9 +724,9 @@
 #endif /* CONFIG_AMIGA */
 
 #ifdef CONFIG_PMAC
-static void *PMacAlloc(unsigned int size, int flags);
-static void PMacFree(void *ptr, unsigned int size);
-static int PMacIrqInit(void);
+static void *PMacAlloc(unsigned int size, int flags) __init;
+static void PMacFree(void *ptr, unsigned int size) __init;
+static int PMacIrqInit(void) __init;
 #ifdef MODULE
 static void PMacIrqCleanup(void);
 #endif /* MODULE */
@@ -720,10 +759,10 @@
 #if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA)
 static int sound_set_treble(int treble);
 #endif /* CONFIG_ATARI || CONFIG_AMIGA */
-static long sound_copy_translate(const u_char *userPtr,
-				 unsigned long userCount,
-				 u_char frame[], long *frameUsed,
-				 long frameLeft);
+static ssize_t sound_copy_translate(const u_char *userPtr,
+				    size_t userCount,
+				    u_char frame[], ssize_t *frameUsed,
+				    ssize_t frameLeft);
 
 
 /*
@@ -736,13 +775,6 @@
 
 static struct sound_mixer mixer;
 
-static void mixer_init(void);
-static int mixer_open(int open_mode);
-static int mixer_release(void);
-static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg);
-
-
 /*
  * Sound queue stuff, the heart of the driver
  */
@@ -787,16 +819,6 @@
 	interruptible_sleep_on(&queue);
 #define WAKE_UP(queue)	(wake_up_interruptible(&queue))
 
-static void sq_init(int numBufs, int bufSize, char **buffers);
-static void sq_play(void);
-static long sq_write(const char *src, unsigned long uLeft);
-static int sq_open(int open_mode);
-static void sq_reset(void);
-static int sq_sync(void);
-static int sq_release(void);
-static void init_settings(void);
-
-
 /*
  * /dev/sndstat
  */
@@ -809,23 +831,9 @@
 
 static struct sound_state state;
 
-static void state_init(void);
-static int state_open(int open_mode);
-static int state_release(void);
-static long state_read(char *dest, unsigned long count);
-
-
-/*** High level stuff ********************************************************/
+/*** Common stuff ********************************************************/
 
-
-static int sound_open(struct inode *inode, struct file *file);
-static int sound_fsync(struct file *filp, struct dentry *dentry);
-static int sound_release(struct inode *inode, struct file *file);
 static long long sound_lseek(struct file *file, long long offset, int orig);
-static ssize_t sound_read(struct file *file, char *buf, size_t count,
-			  loff_t *ppos);
-static ssize_t sound_write(struct file *file, const char *buf, size_t count,
-			   loff_t *ppos);
 static inline int ioctl_return(int *addr, int value)
 {
 	if (value < 0)
@@ -833,15 +841,12 @@
 
 	return put_user(value, addr)? -EFAULT: 0;
 }
-static int unknown_minor_dev(char *fname, int dev);
-static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg);
 
 
 /*** Config & Setup **********************************************************/
 
 
-void soundcard_init(void);
+void dmasound_init(void);
 void dmasound_setup(char *str, int *ints);
 
 
@@ -873,11 +878,12 @@
  */
 
 #ifdef CONFIG_ATARI
-static long ata_ct_law(const u_char *userPtr, unsigned long userCount,
-		       u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount,
+			  u_char frame[], ssize_t *frameUsed,
+			  ssize_t frameLeft)
 {
 	char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
-	long count, used;
+	ssize_t count, used;
 	u_char *p = &frame[*frameUsed];
 
 	count = min(userCount, frameLeft);
@@ -892,14 +898,15 @@
 		count--;
 	}
 	*frameUsed += used;
-	return(used);
+	return used;
 }
 
 
-static long ata_ct_s8(const u_char *userPtr, unsigned long userCount,
-		      u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount,
+			 u_char frame[], ssize_t *frameUsed,
+			 ssize_t frameLeft)
 {
-	long count, used;
+	ssize_t count, used;
 	void *p = &frame[*frameUsed];
 
 	count = min(userCount, frameLeft);
@@ -913,10 +920,11 @@
 }
 
 
-static long ata_ct_u8(const u_char *userPtr, unsigned long userCount,
-		      u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount,
+			 u_char frame[], ssize_t *frameUsed,
+			 ssize_t frameLeft)
 {
-	long count, used;
+	ssize_t count, used;
 
 	if (!sound.soft.stereo) {
 		u_char *p = &frame[*frameUsed];
@@ -946,17 +954,18 @@
 }
 
 
-static long ata_ct_s16be(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
 {
-	long count, used;
-	u_long data;
+	ssize_t count, used;
 
 	if (!sound.soft.stereo) {
 		u_short *p = (u_short *)&frame[*frameUsed];
 		count = min(userCount, frameLeft)>>1;
 		used = count*2;
 		while (count > 0) {
+			u_short data;
 			if (get_user(data, ((u_short *)userPtr)++))
 				return -EFAULT;
 			*p++ = data;
@@ -976,17 +985,18 @@
 }
 
 
-static long ata_ct_u16be(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
 {
-	long count, used;
-	u_long data;
+	ssize_t count, used;
 
 	if (!sound.soft.stereo) {
 		u_short *p = (u_short *)&frame[*frameUsed];
 		count = min(userCount, frameLeft)>>1;
 		used = count*2;
 		while (count > 0) {
+			u_short data;
 			if (get_user(data, ((u_short *)userPtr)++))
 				return -EFAULT;
 			data ^= 0x8000;
@@ -1000,6 +1010,7 @@
 		count = min(userCount, frameLeft)>>2;
 		used = count*4;
 		while (count > 0) {
+			u_long data;
 			if (get_user(data, ((u_int *)userPtr)++))
 				return -EFAULT;
 			*p++ = data ^ 0x80008000;
@@ -1011,11 +1022,11 @@
 }
 
 
-static long ata_ct_s16le(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
 {
-	long count, used;
-	u_long data;
+	ssize_t count, used;
 
 	count = frameLeft;
 	if (!sound.soft.stereo) {
@@ -1023,6 +1034,7 @@
 		count = min(userCount, frameLeft)>>1;
 		used = count*2;
 		while (count > 0) {
+			u_short data;
 			if (get_user(data, ((u_short *)userPtr)++))
 				return -EFAULT;
 			data = le2be16(data);
@@ -1036,6 +1048,7 @@
 		count = min(userCount, frameLeft)>>2;
 		used = count*4;
 		while (count > 0) {
+			u_long data;
 			if (get_user(data, ((u_int *)userPtr)++))
 				return -EFAULT;
 			data = le2be16dbl(data);
@@ -1048,11 +1061,11 @@
 }
 
 
-static long ata_ct_u16le(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
 {
-	long count, used;
-	u_long data;
+	ssize_t count, used;
 
 	count = frameLeft;
 	if (!sound.soft.stereo) {
@@ -1060,6 +1073,7 @@
 		count = min(userCount, frameLeft)>>1;
 		used = count*2;
 		while (count > 0) {
+			u_short data;
 			if (get_user(data, ((u_short *)userPtr)++))
 				return -EFAULT;
 			data = le2be16(data) ^ 0x8000;
@@ -1072,6 +1086,7 @@
 		count = min(userCount, frameLeft)>>2;
 		used = count;
 		while (count > 0) {
+			u_long data;
 			if (get_user(data, ((u_int *)userPtr)++))
 				return -EFAULT;
 			data = le2be16dbl(data) ^ 0x80008000;
@@ -1084,20 +1099,21 @@
 }
 
 
-static long ata_ctx_law(const u_char *userPtr, unsigned long userCount,
-			u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft)
 {
 	char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
 	/* this should help gcc to stuff everything into registers */
-	u_long data = sound.data;
 	long bal = sound.bal;
 	long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-	long used, usedf;
+	ssize_t used, usedf;
 
 	used = userCount;
 	usedf = frameLeft;
 	if (!sound.soft.stereo) {
 		u_char *p = &frame[*frameUsed];
+		u_char data = sound.data;
 		while (frameLeft) {
 			u_char c;
 			if (bal < 0) {
@@ -1113,8 +1129,10 @@
 			frameLeft--;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	} else {
 		u_short *p = (u_short *)&frame[*frameUsed];
+		u_short data = sound.data;
 		while (frameLeft >= 2) {
 			u_char c;
 			if (bal < 0) {
@@ -1133,28 +1151,29 @@
 			frameLeft -= 2;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	}
 	sound.bal = bal;
-	sound.data = data;
 	used -= userCount;
 	*frameUsed += usedf-frameLeft;
 	return(used);
 }
 
 
-static long ata_ctx_s8(const u_char *userPtr, unsigned long userCount,
-		       u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount,
+			  u_char frame[], ssize_t *frameUsed,
+			  ssize_t frameLeft)
 {
 	/* this should help gcc to stuff everything into registers */
-	u_long data = sound.data;
 	long bal = sound.bal;
 	long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-	long used, usedf;
+	ssize_t used, usedf;
 
 	used = userCount;
 	usedf = frameLeft;
 	if (!sound.soft.stereo) {
 		u_char *p = &frame[*frameUsed];
+		u_char data = sound.data;
 		while (frameLeft) {
 			if (bal < 0) {
 				if (!userCount)
@@ -1168,8 +1187,10 @@
 			frameLeft--;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	} else {
 		u_short *p = (u_short *)&frame[*frameUsed];
+		u_short data = sound.data;
 		while (frameLeft >= 2) {
 			if (bal < 0) {
 				if (userCount < 2)
@@ -1183,28 +1204,29 @@
 			frameLeft -= 2;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	}
 	sound.bal = bal;
-	sound.data = data;
 	used -= userCount;
 	*frameUsed += usedf-frameLeft;
 	return(used);
 }
 
 
-static long ata_ctx_u8(const u_char *userPtr, unsigned long userCount,
-		       u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount,
+			  u_char frame[], ssize_t *frameUsed,
+			  ssize_t frameLeft)
 {
 	/* this should help gcc to stuff everything into registers */
-	u_long data = sound.data;
 	long bal = sound.bal;
 	long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-	long used, usedf;
+	ssize_t used, usedf;
 
 	used = userCount;
 	usedf = frameLeft;
 	if (!sound.soft.stereo) {
 		u_char *p = &frame[*frameUsed];
+		u_char data = sound.data;
 		while (frameLeft) {
 			if (bal < 0) {
 				if (!userCount)
@@ -1219,8 +1241,10 @@
 			frameLeft--;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	} else {
 		u_short *p = (u_short *)&frame[*frameUsed];
+		u_short data = sound.data;
 		while (frameLeft >= 2) {
 			if (bal < 0) {
 				if (userCount < 2)
@@ -1235,28 +1259,29 @@
 			frameLeft -= 2;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	}
 	sound.bal = bal;
-	sound.data = data;
 	used -= userCount;
 	*frameUsed += usedf-frameLeft;
 	return(used);
 }
 
 
-static long ata_ctx_s16be(const u_char *userPtr, unsigned long userCount,
-			  u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount,
+			     u_char frame[], ssize_t *frameUsed,
+			     ssize_t frameLeft)
 {
 	/* this should help gcc to stuff everything into registers */
-	u_long data = sound.data;
 	long bal = sound.bal;
 	long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-	long used, usedf;
+	ssize_t used, usedf;
 
 	used = userCount;
 	usedf = frameLeft;
 	if (!sound.soft.stereo) {
 		u_short *p = (u_short *)&frame[*frameUsed];
+		u_short data = sound.data;
 		while (frameLeft >= 4) {
 			if (bal < 0) {
 				if (userCount < 2)
@@ -1271,8 +1296,10 @@
 			frameLeft -= 4;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	} else {
 		u_long *p = (u_long *)&frame[*frameUsed];
+		u_long data = sound.data;
 		while (frameLeft >= 4) {
 			if (bal < 0) {
 				if (userCount < 4)
@@ -1286,28 +1313,29 @@
 			frameLeft -= 4;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	}
 	sound.bal = bal;
-	sound.data = data;
 	used -= userCount;
 	*frameUsed += usedf-frameLeft;
 	return(used);
 }
 
 
-static long ata_ctx_u16be(const u_char *userPtr, unsigned long userCount,
-			  u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount,
+			     u_char frame[], ssize_t *frameUsed,
+			     ssize_t frameLeft)
 {
 	/* this should help gcc to stuff everything into registers */
-	u_long data = sound.data;
 	long bal = sound.bal;
 	long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-	long used, usedf;
+	ssize_t used, usedf;
 
 	used = userCount;
 	usedf = frameLeft;
 	if (!sound.soft.stereo) {
 		u_short *p = (u_short *)&frame[*frameUsed];
+		u_short data = sound.data;
 		while (frameLeft >= 4) {
 			if (bal < 0) {
 				if (userCount < 2)
@@ -1323,8 +1351,10 @@
 			frameLeft -= 4;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	} else {
 		u_long *p = (u_long *)&frame[*frameUsed];
+		u_long data = sound.data;
 		while (frameLeft >= 4) {
 			if (bal < 0) {
 				if (userCount < 4)
@@ -1339,28 +1369,29 @@
 			frameLeft -= 4;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	}
 	sound.bal = bal;
-	sound.data = data;
 	used -= userCount;
 	*frameUsed += usedf-frameLeft;
 	return(used);
 }
 
 
-static long ata_ctx_s16le(const u_char *userPtr, unsigned long userCount,
-			  u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount,
+			     u_char frame[], ssize_t *frameUsed,
+			     ssize_t frameLeft)
 {
 	/* this should help gcc to stuff everything into registers */
-	u_long data = sound.data;
 	long bal = sound.bal;
 	long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-	long used, usedf;
+	ssize_t used, usedf;
 
 	used = userCount;
 	usedf = frameLeft;
 	if (!sound.soft.stereo) {
 		u_short *p = (u_short *)&frame[*frameUsed];
+		u_short data = sound.data;
 		while (frameLeft >= 4) {
 			if (bal < 0) {
 				if (userCount < 2)
@@ -1376,8 +1407,10 @@
 			frameLeft -= 4;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	} else {
 		u_long *p = (u_long *)&frame[*frameUsed];
+		u_long data = sound.data;
 		while (frameLeft >= 4) {
 			if (bal < 0) {
 				if (userCount < 4)
@@ -1392,28 +1425,29 @@
 			frameLeft -= 4;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	}
 	sound.bal = bal;
-	sound.data = data;
 	used -= userCount;
 	*frameUsed += usedf-frameLeft;
 	return(used);
 }
 
 
-static long ata_ctx_u16le(const u_char *userPtr, unsigned long userCount,
-			  u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount,
+			     u_char frame[], ssize_t *frameUsed,
+			     ssize_t frameLeft)
 {
 	/* this should help gcc to stuff everything into registers */
-	u_long data = sound.data;
 	long bal = sound.bal;
 	long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-	long used, usedf;
+	ssize_t used, usedf;
 
 	used = userCount;
 	usedf = frameLeft;
 	if (!sound.soft.stereo) {
 		u_short *p = (u_short *)&frame[*frameUsed];
+		u_short data = sound.data;
 		while (frameLeft >= 4) {
 			if (bal < 0) {
 				if (userCount < 2)
@@ -1429,8 +1463,10 @@
 			frameLeft -= 4;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	} else {
 		u_long *p = (u_long *)&frame[*frameUsed];
+		u_long data = sound.data;
 		while (frameLeft >= 4) {
 			if (bal < 0) {
 				if (userCount < 4)
@@ -1445,9 +1481,9 @@
 			frameLeft -= 4;
 			bal -= sSpeed;
 		}
+		sound.data = data;
 	}
 	sound.bal = bal;
-	sound.data = data;
 	used -= userCount;
 	*frameUsed += usedf-frameLeft;
 	return(used);
@@ -1456,11 +1492,12 @@
 
 
 #ifdef CONFIG_AMIGA
-static long ami_ct_law(const u_char *userPtr, unsigned long userCount,
-		       u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ami_ct_law(const u_char *userPtr, size_t userCount,
+			  u_char frame[], ssize_t *frameUsed,
+			  ssize_t frameLeft)
 {
 	char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
-	long count, used;
+	ssize_t count, used;
 
 	if (!sound.soft.stereo) {
 		u_char *p = &frame[*frameUsed];
@@ -1494,10 +1531,10 @@
 }
 
 
-static long ami_ct_s8(const u_char *userPtr, unsigned long userCount,
-		      u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ami_ct_s8(const u_char *userPtr, size_t userCount,
+			 u_char frame[], ssize_t *frameUsed, ssize_t frameLeft)
 {
-	long count, used;
+	ssize_t count, used;
 
 	if (!sound.soft.stereo) {
 		void *p = &frame[*frameUsed];
@@ -1522,10 +1559,10 @@
 }
 
 
-static long ami_ct_u8(const u_char *userPtr, unsigned long userCount,
-		      u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ami_ct_u8(const u_char *userPtr, size_t userCount,
+			 u_char frame[], ssize_t *frameUsed, ssize_t frameLeft)
 {
-	long count, used;
+	ssize_t count, used;
 
 	if (!sound.soft.stereo) {
 		char *p = &frame[*frameUsed];
@@ -1559,11 +1596,12 @@
 }
 
 
-static long ami_ct_s16be(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ami_ct_s16be(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
 {
-	long count, used;
-	u_long data;
+	ssize_t count, used;
+	u_short data;
 
 	if (!sound.soft.stereo) {
 		u_char *high = &frame[*frameUsed>>1];
@@ -1601,11 +1639,12 @@
 }
 
 
-static long ami_ct_u16be(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ami_ct_u16be(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
 {
-	long count, used;
-	u_long data;
+	ssize_t count, used;
+	u_short data;
 
 	if (!sound.soft.stereo) {
 		u_char *high = &frame[*frameUsed>>1];
@@ -1646,11 +1685,12 @@
 }
 
 
-static long ami_ct_s16le(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ami_ct_s16le(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
 {
-	long count, used;
-	u_long data;
+	ssize_t count, used;
+	u_short data;
 
 	if (!sound.soft.stereo) {
 		u_char *high = &frame[*frameUsed>>1];
@@ -1691,11 +1731,12 @@
 }
 
 
-static long ami_ct_u16le(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t ami_ct_u16le(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
 {
-	long count, used;
-	u_long data;
+	ssize_t count, used;
+	u_short data;
 
 	if (!sound.soft.stereo) {
 		u_char *high = &frame[*frameUsed>>1];
@@ -1737,11 +1778,12 @@
 #endif /* CONFIG_AMIGA */
 
 #ifdef CONFIG_PMAC
-static long pmac_ct_law(const u_char *userPtr, unsigned long userCount,
-			u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t pmac_ct_law(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft)
 {
 	short *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16;
-	long count, used;
+	ssize_t count, used;
 	short *p = (short *) &frame[*frameUsed];
 	int val, stereo = sound.soft.stereo;
 
@@ -1768,10 +1810,11 @@
 }
 
 
-static long pmac_ct_s8(const u_char *userPtr, unsigned long userCount,
-		       u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t pmac_ct_s8(const u_char *userPtr, size_t userCount,
+			  u_char frame[], ssize_t *frameUsed,
+			  ssize_t frameLeft)
 {
-	long count, used;
+	ssize_t count, used;
 	short *p = (short *) &frame[*frameUsed];
 	int val, stereo = sound.soft.stereo;
 
@@ -1798,10 +1841,11 @@
 }
 
 
-static long pmac_ct_u8(const u_char *userPtr, unsigned long userCount,
-		       u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t pmac_ct_u8(const u_char *userPtr, size_t userCount,
+			  u_char frame[], ssize_t *frameUsed,
+			  ssize_t frameLeft)
 {
-	long count, used;
+	ssize_t count, used;
 	short *p = (short *) &frame[*frameUsed];
 	int val, stereo = sound.soft.stereo;
 
@@ -1828,10 +1872,11 @@
 }
 
 
-static long pmac_ct_s16(const u_char *userPtr, unsigned long userCount,
-			u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t pmac_ct_s16(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft)
 {
-	long count, used;
+	ssize_t count, used;
 	int stereo = sound.soft.stereo;
 	short *fp = (short *) &frame[*frameUsed];
 
@@ -1856,11 +1901,12 @@
 	return stereo? used * 4: used * 2;
 }
 
-static long pmac_ct_u16(const u_char *userPtr, unsigned long userCount,
-			u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t pmac_ct_u16(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft)
 {
-	long count, used;
-	int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
+	ssize_t count, used;
+	short mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
 	int stereo = sound.soft.stereo;
 	short *fp = (short *) &frame[*frameUsed];
 	short *up = (short *) userPtr;
@@ -1869,7 +1915,7 @@
 	userCount >>= (stereo? 2: 1);
 	used = count = min(userCount, frameLeft);
 	while (count > 0) {
-		int data;
+		short data;
 		if (get_user(data, up++))
 			return -EFAULT;
 		data ^= mask;
@@ -1887,8 +1933,9 @@
 }
 
 
-static long pmac_ctx_law(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t pmac_ctx_law(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
 {
 	unsigned short *table = (unsigned short *)
 		(sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16);
@@ -1933,8 +1980,9 @@
 }
 
 
-static long pmac_ctx_s8(const u_char *userPtr, unsigned long userCount,
-			u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t pmac_ctx_s8(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft)
 {
 	unsigned int *p = (unsigned int *) &frame[*frameUsed];
 	unsigned int data = sound.data;
@@ -1977,8 +2025,9 @@
 }
 
 
-static long pmac_ctx_u8(const u_char *userPtr, unsigned long userCount,
-			u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t pmac_ctx_u8(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft)
 {
 	unsigned int *p = (unsigned int *) &frame[*frameUsed];
 	unsigned int data = sound.data;
@@ -2021,8 +2070,9 @@
 }
 
 
-static long pmac_ctx_s16(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t pmac_ctx_s16(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
 {
 	unsigned int *p = (unsigned int *) &frame[*frameUsed];
 	unsigned int data = sound.data;
@@ -2065,8 +2115,9 @@
 }
 
 
-static long pmac_ctx_u16(const u_char *userPtr, unsigned long userCount,
-			 u_char frame[], long *frameUsed, long frameLeft)
+static ssize_t pmac_ctx_u16(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
 {
 	int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
 	unsigned int *p = (unsigned int *) &frame[*frameUsed];
@@ -3424,12 +3475,12 @@
 #endif /* CONFIG_ATARI || CONFIG_AMIGA */
 
 
-static long sound_copy_translate(const u_char *userPtr,
-				 unsigned long userCount,
-				 u_char frame[], long *frameUsed,
-				 long frameLeft)
+static ssize_t sound_copy_translate(const u_char *userPtr,
+				    size_t userCount,
+				    u_char frame[], ssize_t *frameUsed,
+				    ssize_t frameLeft)
 {
-	long (*ct_func)(const u_char *, unsigned long, u_char *, long *, long) = NULL;
+	ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL;
 
 	switch (sound.soft.format) {
 	case AFMT_MU_LAW:
@@ -3458,9 +3509,9 @@
 		break;
 	}
 	if (ct_func)
-		return(ct_func(userPtr, userCount, frame, frameUsed, frameLeft));
+		return ct_func(userPtr, userCount, frame, frameUsed, frameLeft);
 	else
-		return(0);
+		return 0;
 }
 
 
@@ -3474,53 +3525,19 @@
 #define RECLEVEL_GAIN_TO_VOXWARE(v) (((v) * 20 + 2) / 3)
 
 
-static void mixer_init(void)
-{
-	mixer.busy = 0;
-	sound.treble = 0;
-	sound.bass = 0;
-	switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-	case DMASND_TT:
-		atari_microwire_cmd(MW_LM1992_VOLUME(0));
-		sound.volume_left = 0;
-		atari_microwire_cmd(MW_LM1992_BALLEFT(0));
-		sound.volume_right = 0;
-		atari_microwire_cmd(MW_LM1992_BALRIGHT(0));
-		atari_microwire_cmd(MW_LM1992_TREBLE(0));
-		atari_microwire_cmd(MW_LM1992_BASS(0));
-		break;
-	case DMASND_FALCON:
-		sound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8;
-		sound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4;
-		break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	case DMASND_AMIGA:
-		sound.volume_left = 64;
-		sound.volume_right = 64;
-		custom.aud[0].audvol = sound.volume_left;
-		custom.aud[3].audvol = 1;	/* For pseudo 14bit */
-		custom.aud[1].audvol = sound.volume_right;
-		custom.aud[2].audvol = 1;	/* For pseudo 14bit */
-		sound.treble = 50;
-		break;
-#endif /* CONFIG_AMIGA */
-	}
-}
-
-
-static int mixer_open(int open_mode)
+static int mixer_open(struct inode *inode, struct file *file)
 {
+	MOD_INC_USE_COUNT;
 	mixer.busy = 1;
-	return(0);
+	return 0;
 }
 
 
-static int mixer_release(void)
+static int mixer_release(struct inode *inode, struct file *file)
 {
 	mixer.busy = 0;
-	return(0);
+	MOD_DEC_USE_COUNT;
+	return 0;
 }
 
 
@@ -3533,17 +3550,17 @@
 	case DMASND_FALCON:
 		switch (cmd) {
 		case SOUND_MIXER_READ_DEVMASK:
-			return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
+			return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER);
 		case SOUND_MIXER_READ_RECMASK:
-			return(IOCTL_OUT(arg, SOUND_MASK_MIC));
+			return IOCTL_OUT(arg, SOUND_MASK_MIC);
 		case SOUND_MIXER_READ_STEREODEVS:
-			return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC));
+			return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC);
 		case SOUND_MIXER_READ_CAPS:
-			return(IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT));
+			return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT);
 		case SOUND_MIXER_READ_VOLUME:
-			return(IOCTL_OUT(arg,
+			return IOCTL_OUT(arg,
 				VOLUME_ATT_TO_VOXWARE(sound.volume_left) |
-				VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8));
+				VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8);
 		case SOUND_MIXER_WRITE_MIC:
 			IOCTL_IN(arg, data);
 			tt_dmasnd.input_gain =
@@ -3551,9 +3568,9 @@
 				RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff);
 			/* fall thru, return set value */
 		case SOUND_MIXER_READ_MIC:
-			return(IOCTL_OUT(arg,
+			return IOCTL_OUT(arg,
 				RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) |
-				RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8));
+				RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8);
 		case SOUND_MIXER_READ_SPEAKER:
 			{
 				int porta;
@@ -3561,11 +3578,11 @@
 				sound_ym.rd_data_reg_sel = 14;
 				porta = sound_ym.rd_data_reg_sel;
 				sti();
-				return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
+				return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100);
 			}
 		case SOUND_MIXER_WRITE_VOLUME:
 			IOCTL_IN(arg, data);
-			return(IOCTL_OUT(arg, sound_set_volume(data)));
+			return IOCTL_OUT(arg, sound_set_volume(data));
 		case SOUND_MIXER_WRITE_SPEAKER:
 			{
 				int porta;
@@ -3576,7 +3593,7 @@
 					(data < 50 ? 0x40 : 0);
 				sound_ym.wd_data = porta;
 				sti();
-				return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
+				return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100);
 			}
 		}
 		break;
@@ -3584,23 +3601,23 @@
 	case DMASND_TT:
 		switch (cmd) {
 		case SOUND_MIXER_READ_DEVMASK:
-			return(IOCTL_OUT(arg,
+			return IOCTL_OUT(arg,
 					 SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
-					 (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0)));
+					 (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0));
 		case SOUND_MIXER_READ_RECMASK:
-			return(IOCTL_OUT(arg, 0));
+			return IOCTL_OUT(arg, 0);
 		case SOUND_MIXER_READ_STEREODEVS:
-			return(IOCTL_OUT(arg, SOUND_MASK_VOLUME));
+			return IOCTL_OUT(arg, SOUND_MASK_VOLUME);
 		case SOUND_MIXER_READ_VOLUME:
-			return(IOCTL_OUT(arg,
+			return IOCTL_OUT(arg,
 					 VOLUME_DB_TO_VOXWARE(sound.volume_left) |
-					 (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8)));
+					 (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8));
 		case SOUND_MIXER_READ_BASS:
-			return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.bass)));
+			return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.bass));
 		case SOUND_MIXER_READ_TREBLE:
-			return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.treble)));
+			return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.treble));
 		case SOUND_MIXER_READ_OGAIN:
-			return(IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(sound.gain)));
+			return IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(sound.gain));
 		case SOUND_MIXER_READ_SPEAKER:
 			{
 				int porta;
@@ -3609,22 +3626,22 @@
 					sound_ym.rd_data_reg_sel = 14;
 					porta = sound_ym.rd_data_reg_sel;
 					sti();
-					return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-				} else
-					return(-EINVAL);
+					return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100);
+				}
 			}
+			break;
 		case SOUND_MIXER_WRITE_VOLUME:
 			IOCTL_IN(arg, data);
-			return(IOCTL_OUT(arg, sound_set_volume(data)));
+			return IOCTL_OUT(arg, sound_set_volume(data));
 		case SOUND_MIXER_WRITE_BASS:
 			IOCTL_IN(arg, data);
-			return(IOCTL_OUT(arg, sound_set_bass(data)));
+			return IOCTL_OUT(arg, sound_set_bass(data));
 		case SOUND_MIXER_WRITE_TREBLE:
 			IOCTL_IN(arg, data);
-			return(IOCTL_OUT(arg, sound_set_treble(data)));
+			return IOCTL_OUT(arg, sound_set_treble(data));
 		case SOUND_MIXER_WRITE_OGAIN:
 			IOCTL_IN(arg, data);
-			return(IOCTL_OUT(arg, sound_set_gain(data)));
+			return IOCTL_OUT(arg, sound_set_gain(data));
 		case SOUND_MIXER_WRITE_SPEAKER:
 			if (MACH_IS_TT) {
 				int porta;
@@ -3635,9 +3652,8 @@
 					(data < 50 ? 0x40 : 0);
 				sound_ym.wd_data = porta;
 				sti();
-				return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-			} else
-				return(-EINVAL);
+				return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100);
+			}
 		}
 		break;
 #endif /* CONFIG_ATARI */
@@ -3646,23 +3662,23 @@
 	case DMASND_AMIGA:
 		switch (cmd) {
 		case SOUND_MIXER_READ_DEVMASK:
-			return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE));
+			return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE);
 		case SOUND_MIXER_READ_RECMASK:
-			return(IOCTL_OUT(arg, 0));
+			return IOCTL_OUT(arg, 0);
 		case SOUND_MIXER_READ_STEREODEVS:
-			return(IOCTL_OUT(arg, SOUND_MASK_VOLUME));
+			return IOCTL_OUT(arg, SOUND_MASK_VOLUME);
 		case SOUND_MIXER_READ_VOLUME:
-			return(IOCTL_OUT(arg,
+			return IOCTL_OUT(arg,
 				VOLUME_AMI_TO_VOXWARE(sound.volume_left) |
-				VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8));
+				VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8);
 		case SOUND_MIXER_WRITE_VOLUME:
 			IOCTL_IN(arg, data);
-			return(IOCTL_OUT(arg, sound_set_volume(data)));
+			return IOCTL_OUT(arg, sound_set_volume(data));
 		case SOUND_MIXER_READ_TREBLE:
-			return(IOCTL_OUT(arg, sound.treble));
+			return IOCTL_OUT(arg, sound.treble);
 		case SOUND_MIXER_WRITE_TREBLE:
 			IOCTL_IN(arg, data);
-			return(IOCTL_OUT(arg, sound_set_treble(data)));
+			return IOCTL_OUT(arg, sound_set_treble(data));
 		}
 		break;
 #endif /* CONFIG_AMIGA */
@@ -3777,17 +3793,73 @@
 #endif
 	}
 
-	return(-EINVAL);
+	return -EINVAL;
 }
 
 
+static struct file_operations mixer_fops =
+{
+	sound_lseek,
+	NULL,			/* mixer_read */
+	NULL,			/* mixer_write */
+	NULL,			/* mixer_readdir */
+	NULL,			/* mixer_poll */
+	mixer_ioctl,
+	NULL,			/* mixer_mmap */
+	mixer_open,
+	mixer_release,
+};
+
+
+__initfunc(static void mixer_init(void))
+{
+#ifndef MODULE
+	int mixer_unit;
+#endif
+	mixer_unit = register_sound_mixer(&mixer_fops);
+	if (mixer_unit < 0)
+		return;
+
+	mixer.busy = 0;
+	sound.treble = 0;
+	sound.bass = 0;
+	switch (sound.mach.type) {
+#ifdef CONFIG_ATARI
+	case DMASND_TT:
+		atari_microwire_cmd(MW_LM1992_VOLUME(0));
+		sound.volume_left = 0;
+		atari_microwire_cmd(MW_LM1992_BALLEFT(0));
+		sound.volume_right = 0;
+		atari_microwire_cmd(MW_LM1992_BALRIGHT(0));
+		atari_microwire_cmd(MW_LM1992_TREBLE(0));
+		atari_microwire_cmd(MW_LM1992_BASS(0));
+		break;
+	case DMASND_FALCON:
+		sound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8;
+		sound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4;
+		break;
+#endif /* CONFIG_ATARI */
+#ifdef CONFIG_AMIGA
+	case DMASND_AMIGA:
+		sound.volume_left = 64;
+		sound.volume_right = 64;
+		custom.aud[0].audvol = sound.volume_left;
+		custom.aud[3].audvol = 1;	/* For pseudo 14bit */
+		custom.aud[1].audvol = sound.volume_right;
+		custom.aud[2].audvol = 1;	/* For pseudo 14bit */
+		sound.treble = 50;
+		break;
+#endif /* CONFIG_AMIGA */
+	}
+}
+
 
 /*
  * Sound queue stuff, the heart of the driver
  */
 
 
-static void sq_init(int numBufs, int bufSize, char **buffers)
+static void sq_setup(int numBufs, int bufSize, char **buffers)
 {
 #ifdef CONFIG_PMAC
 	int i;
@@ -3827,47 +3899,6 @@
 #endif /* CONFIG_PMAC */
 }
 
-static void
-init_settings(void)
-{
-	/* whatever you like as startup mode for /dev/dsp,
-	 * (/dev/audio hasn't got a startup mode). note that
-	 * once changed a new open() will *not* restore these!
-	 */
-	sound.dsp.format = AFMT_U8;
-	sound.dsp.stereo = 0;
-	sound.dsp.size = 8;
-
-	/* set minimum rate possible without expanding */
-	switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-	case DMASND_TT:
-		sound.dsp.speed = 6258;
-		break;
-	case DMASND_FALCON:
-		sound.dsp.speed = 8195;
-		break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	case DMASND_AMIGA:
-		sound.dsp.speed = 8000;
-		break;
-#endif /* CONFIG_AMIGA */
-#ifdef CONFIG_PMAC
-	case DMASND_AWACS:
-		sound.dsp.speed = 8000;
-		break;
-#endif /* CONFIG_PMAC */
-	}
-
-	/* before the first open to /dev/dsp this wouldn't be set */
-	sound.soft = sound.dsp;
-	sound.hard = sound.dsp;
-
-	sound_silence();
-}
-
-
 static void sq_play(void)
 {
 	(*sound.mach.play)();
@@ -3876,18 +3907,19 @@
 
 /* ++TeSche: radically changed this one too */
 
-static long sq_write(const char *src, unsigned long uLeft)
+static ssize_t sq_write(struct file *file, const char *src, size_t uLeft,
+			loff_t *ppos)
 {
-	long uWritten = 0;
+	ssize_t uWritten = 0;
 	u_char *dest;
-	long uUsed, bUsed, bLeft;
+	ssize_t uUsed, bUsed, bLeft;
 
 	/* ++TeSche: Is something like this necessary?
 	 * Hey, that's an honest question! Or does any other part of the
 	 * filesystem already checks this situation? I really don't know.
 	 */
 	if (uLeft == 0)
-		return(0);
+		return 0;
 
 	/* The interrupt doesn't start to play the last, incomplete frame.
 	 * Thus we can append to it without disabling the interrupts! (Note
@@ -3910,10 +3942,10 @@
 		while (sq.count == sq.max_active) {
 			sq_play();
 			if (NON_BLOCKING(sq.open_mode))
-				return(uWritten > 0 ? uWritten : -EAGAIN);
+				return uWritten > 0 ? uWritten : -EAGAIN;
 			SLEEP(sq.write_queue, ONE_SECOND);
 			if (SIGNAL_RECEIVED)
-				return(uWritten > 0 ? uWritten : -EINTR);
+				return uWritten > 0 ? uWritten : -EINTR;
 		}
 
 		/* Here, we can avoid disabling the interrupt by first
@@ -3941,28 +3973,46 @@
 
 	sq_play();
 
-	return(uUsed < 0? uUsed: uWritten);
+	return uUsed < 0? uUsed: uWritten;
 }
 
 
-static int sq_open(int open_mode)
+static int sq_open(struct inode *inode, struct file *file)
 {
+	int rc = 0;
+
+	MOD_INC_USE_COUNT;
 	if (sq.busy) {
-		if (NON_BLOCKING(open_mode))
-			return(-EBUSY);
+		rc = -EBUSY;
+		if (NON_BLOCKING(file->f_flags))
+			goto err_out;
+		rc = -EINTR;
 		while (sq.busy) {
 			SLEEP(sq.open_queue, ONE_SECOND);
 			if (SIGNAL_RECEIVED)
-				return(-EINTR);
+				goto err_out;
 		}
+		rc = 0;
 	}
-	sq_init(numBufs, bufSize << 10, sound_buffers);
-	sq.open_mode = open_mode;
+	sq_setup(numBufs, bufSize << 10, sound_buffers);
+	sq.open_mode = file->f_flags;
 	sq.busy = 1;
 #ifdef CONFIG_ATARI
 	sq.ignore_int = 1;
 #endif /* CONFIG_ATARI */
-	return(0);
+	sound.minDev = MINOR(inode->i_rdev) & 0x0f;
+	sound.soft = sound.dsp;
+	sound.hard = sound.dsp;
+	sound_init();
+	if ((MINOR(inode->i_rdev) & 0x0f) == SND_DEV_AUDIO) {
+		sound_set_speed(8000);
+		sound_set_stereo(0);
+		sound_set_format(AFMT_MU_LAW);
+	}
+	return 0;
+err_out:
+	MOD_DEC_USE_COUNT;
+	return rc;
 }
 
 
@@ -3975,7 +4025,7 @@
 }
 
 
-static int sq_sync(void)
+static int sq_fsync(struct file *filp, struct dentry *dentry)
 {
 	int rc = 0;
 
@@ -3995,47 +4045,195 @@
 	}
 
 	sq.syncing = 0;
-	return(rc);
+	return rc;
 }
 
-
-static int sq_release(void)
+static int sq_release(struct inode *inode, struct file *file)
 {
 	int rc = 0;
 	if (sq.busy) {
-		rc = sq_sync();
+		rc = sq_fsync(file, file->f_dentry);
 		sq.busy = 0;
 		WAKE_UP(sq.open_queue);
 		/* Wake up a process waiting for the queue being released.
 		 * Note: There may be several processes waiting for a call
 		 * to open() returning. */
 	}
-	return(rc);
+	sound.soft = sound.dsp;
+	sound.hard = sound.dsp;
+	sound_silence();
+	if (rc == 0)
+		MOD_DEC_USE_COUNT;
+	return rc;
+}
+
+
+static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		    u_long arg)
+{
+	u_long fmt;
+	int data;
+	int size, nbufs;
+
+	switch (cmd) {
+	case SNDCTL_DSP_RESET:
+		sq_reset();
+		return 0;
+	case SNDCTL_DSP_POST:
+	case SNDCTL_DSP_SYNC:
+		return sq_fsync(file, file->f_dentry);
+
+		/* ++TeSche: before changing any of these it's
+		 * probably wise to wait until sound playing has
+		 * settled down. */
+	case SNDCTL_DSP_SPEED:
+		sq_fsync(file, file->f_dentry);
+		IOCTL_IN(arg, data);
+		return IOCTL_OUT(arg, sound_set_speed(data));
+	case SNDCTL_DSP_STEREO:
+		sq_fsync(file, file->f_dentry);
+		IOCTL_IN(arg, data);
+		return IOCTL_OUT(arg, sound_set_stereo(data));
+	case SOUND_PCM_WRITE_CHANNELS:
+		sq_fsync(file, file->f_dentry);
+		IOCTL_IN(arg, data);
+		return IOCTL_OUT(arg, sound_set_stereo(data-1)+1);
+	case SNDCTL_DSP_SETFMT:
+		sq_fsync(file, file->f_dentry);
+		IOCTL_IN(arg, data);
+		return IOCTL_OUT(arg, sound_set_format(data));
+	case SNDCTL_DSP_GETFMTS:
+		fmt = 0;
+		if (sound.trans) {
+			if (sound.trans->ct_ulaw)
+				fmt |= AFMT_MU_LAW;
+			if (sound.trans->ct_alaw)
+				fmt |= AFMT_A_LAW;
+			if (sound.trans->ct_s8)
+				fmt |= AFMT_S8;
+			if (sound.trans->ct_u8)
+				fmt |= AFMT_U8;
+			if (sound.trans->ct_s16be)
+				fmt |= AFMT_S16_BE;
+			if (sound.trans->ct_u16be)
+				fmt |= AFMT_U16_BE;
+			if (sound.trans->ct_s16le)
+				fmt |= AFMT_S16_LE;
+			if (sound.trans->ct_u16le)
+				fmt |= AFMT_U16_LE;
+		}
+		return IOCTL_OUT(arg, fmt);
+	case SNDCTL_DSP_GETBLKSIZE:
+		size = sq.block_size
+			* sound.soft.size * (sound.soft.stereo + 1)
+			/ (sound.hard.size * (sound.hard.stereo + 1));
+		return IOCTL_OUT(arg, size);
+	case SNDCTL_DSP_SUBDIVIDE:
+		break;
+	case SNDCTL_DSP_SETFRAGMENT:
+		if (sq.count || sq.playing || sq.syncing)
+			return -EINVAL;
+		IOCTL_IN(arg, size);
+		nbufs = size >> 16;
+		if (nbufs < 2 || nbufs > numBufs)
+			nbufs = numBufs;
+		size &= 0xffff;
+		if (size >= 8 && size <= 30) {
+			size = 1 << size;
+			size *= sound.hard.size * (sound.hard.stereo + 1);
+			size /= sound.soft.size * (sound.soft.stereo + 1);
+			if (size > (bufSize << 10))
+				size = bufSize << 10;
+		} else
+			size = bufSize << 10;
+		sq_setup(numBufs, size, sound_buffers);
+		sq.max_active = nbufs;
+		return 0;
+
+	default:
+		return mixer_ioctl(inode, file, cmd, arg);
+	}
+	return -EINVAL;
 }
 
 
 
-/*
- * /dev/sndstat
- */
+static struct file_operations sq_fops =
+{
+	sound_lseek,
+	NULL,			/* sq_read */
+	sq_write,
+	NULL,			/* sq_readdir */
+	NULL,			/* sq_poll */
+	sq_ioctl,
+	NULL,			/* sq_mmap */
+	sq_open,
+	sq_release,
+};
 
 
-static void state_init(void)
+__initfunc(static void sq_init(void))
 {
-	state.busy = 0;
+#ifndef MODULE
+	int sq_unit;
+#endif
+	sq_unit = register_sound_dsp(&sq_fops);
+	if (sq_unit < 0)
+		return;
+
+	/* whatever you like as startup mode for /dev/dsp,
+	 * (/dev/audio hasn't got a startup mode). note that
+	 * once changed a new open() will *not* restore these!
+	 */
+	sound.dsp.format = AFMT_U8;
+	sound.dsp.stereo = 0;
+	sound.dsp.size = 8;
+
+	/* set minimum rate possible without expanding */
+	switch (sound.mach.type) {
+#ifdef CONFIG_ATARI
+	case DMASND_TT:
+		sound.dsp.speed = 6258;
+		break;
+	case DMASND_FALCON:
+		sound.dsp.speed = 8195;
+		break;
+#endif /* CONFIG_ATARI */
+#ifdef CONFIG_AMIGA
+	case DMASND_AMIGA:
+		sound.dsp.speed = 8000;
+		break;
+#endif /* CONFIG_AMIGA */
+#ifdef CONFIG_PMAC
+	case DMASND_AWACS:
+		sound.dsp.speed = 8000;
+		break;
+#endif /* CONFIG_PMAC */
+	}
+
+	/* before the first open to /dev/dsp this wouldn't be set */
+	sound.soft = sound.dsp;
+	sound.hard = sound.dsp;
+
+	sound_silence();
 }
 
+/*
+ * /dev/sndstat
+ */
+
 
 /* state.buf should not overflow! */
 
-static int state_open(int open_mode)
+static int state_open(struct inode *inode, struct file *file)
 {
 	char *buffer = state.buf, *mach = "";
 	int len = 0;
 
 	if (state.busy)
-		return(-EBUSY);
+		return -EBUSY;
 
+	MOD_INC_USE_COUNT;
 	state.ptr = 0;
 	state.busy = 1;
 
@@ -4127,294 +4325,77 @@
 	len += sprintf(buffer+len, "\tsq.playing = %d sq.syncing = %d\n",
 		       sq.playing, sq.syncing);
 	state.len = len;
-	return(0);
+	return 0;
 }
 
 
-static int state_release(void)
+static int state_release(struct inode *inode, struct file *file)
 {
 	state.busy = 0;
-	return(0);
+	MOD_DEC_USE_COUNT;
+	return 0;
 }
 
 
-static long state_read(char *dest, unsigned long count)
+static ssize_t state_read(struct file *file, char *buf, size_t count,
+			  loff_t *ppos)
 {
-	int n = state.len-state.ptr;
+	int n = state.len - state.ptr;
 	if (n > count)
 		n = count;
 	if (n <= 0)
-		return(0);
-	if (copy_to_user(dest, &state.buf[state.ptr], n))
+		return 0;
+	if (copy_to_user(buf, &state.buf[state.ptr], n))
 		return -EFAULT;
 	state.ptr += n;
-	return(n);
+	return n;
 }
 
 
-
-/*** High level stuff ********************************************************/
-
-
-static int sound_open(struct inode *inode, struct file *file)
+static struct file_operations state_fops =
 {
-	int dev = MINOR(inode->i_rdev) & 0x0f;
-	int rc = 0;
-
-	switch (dev) {
-	case SND_DEV_STATUS:
-		rc = state_open(file->f_flags);
-		break;
-	case SND_DEV_CTL:
-		rc = mixer_open(file->f_flags);
-		break;
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-		rc = sq_open(file->f_flags);
-		if (rc == 0) {
-			sound.minDev = dev;
-			sound.soft = sound.dsp;
-			sound.hard = sound.dsp;
-			sound_init();
-			if (dev == SND_DEV_AUDIO) {
-				sound_set_speed(8000);
-				sound_set_stereo(0);
-				sound_set_format(AFMT_MU_LAW);
-			}
-		}
-		break;
-	default:
-		rc = -ENXIO;
-	}
-#ifdef MODULE
-	if (rc >= 0)
-		MOD_INC_USE_COUNT;
-#endif
-	return(rc);
-}
-
-
-static int sound_fsync(struct file *filp, struct dentry *dentry)
-{
-	int dev = MINOR(dentry->d_inode->i_rdev) & 0x0f;
-
-	switch (dev) {
-	case SND_DEV_STATUS:
-	case SND_DEV_CTL:
-		return(0);
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-		return(sq_sync());
-	default:
-		return(unknown_minor_dev("sound_fsync", dev));
-	}
-}
+	sound_lseek,
+	state_read,
+	NULL,			/* state_write */
+	NULL,			/* state_readdir */
+	NULL,			/* state_poll */
+	NULL,			/* state_ioctl */
+	NULL,			/* state_mmap */
+	state_open,
+	state_release,
+};
 
 
-static int sound_release(struct inode *inode, struct file *file)
+__initfunc(static void state_init(void))
 {
-	int dev = MINOR(inode->i_rdev);
-
-	switch (dev & 0x0f) {
-	case SND_DEV_STATUS:
-		state_release();
-		break;
-	case SND_DEV_CTL:
-		mixer_release();
-		break;
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-		sq_release();
-		sound.soft = sound.dsp;
-		sound.hard = sound.dsp;
-		sound_silence();
-		break;
-	default:
-		return unknown_minor_dev("sound_release", dev);
-	}
-#ifdef MODULE
-	MOD_DEC_USE_COUNT;
+#ifndef MODULE
+	int state_unit;
 #endif
-	return 0;
+	state_unit = register_sound_special(&state_fops, SND_DEV_STATUS);
+	if (state_unit < 0)
+		return;
+	state.busy = 0;
 }
 
 
+/*** Common stuff ********************************************************/
+
 static long long sound_lseek(struct file *file, long long offset, int orig)
 {
 	return -ESPIPE;
 }
 
 
-static ssize_t sound_read(struct file *file, char *buf, size_t count,
-			  loff_t *ppos)
-{
-	struct inode *inode = file->f_dentry->d_inode;
-	int dev = MINOR(inode->i_rdev);
-
-	switch (dev & 0x0f) {
-	case SND_DEV_STATUS:
-		return(state_read(buf, count));
-	case SND_DEV_CTL:
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-		return(-EPERM);
-	default:
-		return(unknown_minor_dev("sound_read", dev));
-	}
-}
-
-
-static ssize_t sound_write(struct file *file, const char *buf, size_t count,
-			   loff_t *ppos)
-{
-	struct inode *inode = file->f_dentry->d_inode;
-	int dev = MINOR(inode->i_rdev);
-
-	switch (dev & 0x0f) {
-	case SND_DEV_STATUS:
-	case SND_DEV_CTL:
-		return(-EPERM);
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-		return(sq_write(buf, count));
-	default:
-		return(unknown_minor_dev("sound_write", dev));
-	}
-}
-
-
-static int unknown_minor_dev(char *fname, int dev)
-{
-	/* printk("%s: Unknown minor device %d\n", fname, dev); */
-	return(-ENXIO);
-}
-
-
-static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg)
-{
-	int dev = MINOR(inode->i_rdev);
-	u_long fmt;
-	int data;
-	int size, nbufs;
-
-	switch (dev & 0x0f) {
-	case SND_DEV_STATUS:
-		return(-EPERM);
-	case SND_DEV_CTL:
-		return(mixer_ioctl(inode, file, cmd, arg));
-	case SND_DEV_AUDIO:
-	case SND_DEV_DSP:
-		switch (cmd) {
-		case SNDCTL_DSP_RESET:
-			sq_reset();
-			return(0);
-		case SNDCTL_DSP_POST:
-		case SNDCTL_DSP_SYNC:
-			return(sound_fsync(file, file->f_dentry));
-
-			/* ++TeSche: before changing any of these it's
-			 * probably wise to wait until sound playing has
-			 * settled down. */
-		case SNDCTL_DSP_SPEED:
-			sound_fsync(file, file->f_dentry);
-			IOCTL_IN(arg, data);
-			return(IOCTL_OUT(arg, sound_set_speed(data)));
-		case SNDCTL_DSP_STEREO:
-			sound_fsync(file, file->f_dentry);
-			IOCTL_IN(arg, data);
-			return(IOCTL_OUT(arg, sound_set_stereo(data)));
-		case SOUND_PCM_WRITE_CHANNELS:
-			sound_fsync(file, file->f_dentry);
-			IOCTL_IN(arg, data);
-			return(IOCTL_OUT(arg, sound_set_stereo(data-1)+1));
-		case SNDCTL_DSP_SETFMT:
-			sound_fsync(file, file->f_dentry);
-			IOCTL_IN(arg, data);
-			return(IOCTL_OUT(arg, sound_set_format(data)));
-		case SNDCTL_DSP_GETFMTS:
-			fmt = 0;
-			if (sound.trans) {
-				if (sound.trans->ct_ulaw)
-					fmt |= AFMT_MU_LAW;
-				if (sound.trans->ct_alaw)
-					fmt |= AFMT_A_LAW;
-				if (sound.trans->ct_s8)
-					fmt |= AFMT_S8;
-				if (sound.trans->ct_u8)
-					fmt |= AFMT_U8;
-				if (sound.trans->ct_s16be)
-					fmt |= AFMT_S16_BE;
-				if (sound.trans->ct_u16be)
-					fmt |= AFMT_U16_BE;
-				if (sound.trans->ct_s16le)
-					fmt |= AFMT_S16_LE;
-				if (sound.trans->ct_u16le)
-					fmt |= AFMT_U16_LE;
-			}
-			return(IOCTL_OUT(arg, fmt));
-		case SNDCTL_DSP_GETBLKSIZE:
-			size = sq.block_size
-				* sound.soft.size * (sound.soft.stereo + 1)
-				/ (sound.hard.size * (sound.hard.stereo + 1));
-			return(IOCTL_OUT(arg, size));
-		case SNDCTL_DSP_SUBDIVIDE:
-			break;
-		case SNDCTL_DSP_SETFRAGMENT:
-			if (sq.count || sq.playing || sq.syncing)
-				return -EINVAL;
-			IOCTL_IN(arg, size);
-			nbufs = size >> 16;
-			if (nbufs < 2 || nbufs > numBufs)
-				nbufs = numBufs;
-			size &= 0xffff;
-			if (size >= 8 && size <= 30) {
-				size = 1 << size;
-				size *= sound.hard.size * (sound.hard.stereo + 1);
-				size /= sound.soft.size * (sound.soft.stereo + 1);
-				if (size > (bufSize << 10))
-					size = bufSize << 10;
-			} else
-				size = bufSize << 10;
-			sq_init(numBufs, size, sound_buffers);
-			sq.max_active = nbufs;
-			break;
-
-		default:
-			return(mixer_ioctl(inode, file, cmd, arg));
-		}
-		break;
-
-	default:
-		return(unknown_minor_dev("sound_ioctl", dev));
-	}
-	return(-EINVAL);
-}
-
-
-static struct file_operations sound_fops =
-{
-	sound_lseek,
-	sound_read,
-	sound_write,
-	NULL,
-	NULL,                      /* select */
-	sound_ioctl,
-	NULL,
-	sound_open,
-	sound_release,
-	sound_fsync
-};
-
-
-
 /*** Config & Setup **********************************************************/
 
 
-void soundcard_init(void)
+__initfunc(void dmasound_init(void))
 {
 	int has_sound = 0;
 	int i;
+#ifdef CONFIG_PMAC
+	struct device_node *np;
+#endif
 
 #ifdef __mc68000__
 	switch (m68k_machtype) {
@@ -4447,8 +4428,6 @@
 #endif /* __mc68000__ */
 
 #ifdef CONFIG_PMAC
-	struct device_node *np;
-
 	np = find_devices("awacs");
 	if (np != NULL && np->n_addrs >= 3 && np->n_intrs >= 3) {
 		int vol;
@@ -4516,15 +4495,10 @@
 		}
 	}
 
-#ifndef MODULE
-	/* Register driver with the VFS. */
-	register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
-#endif
-
-	sq_init(numBufs, bufSize << 10, sound_buffers);
+	sq_setup(numBufs, bufSize << 10, sound_buffers);
 
 	/* Set default settings. */
-	init_settings();
+	sq_init();
 
 	/* Set up /dev/sndstat. */
 	state_init();
@@ -4549,7 +4523,7 @@
 
 #define MAXARGS		8	/* Should be sufficient for now */
 
-void dmasound_setup(char *str, int *ints)
+__initfunc(void dmasound_setup(char *str, int *ints))
 {
 	/* check the bootstrap parameter for "dmasound=" */
 
@@ -4580,28 +4554,9 @@
 
 #ifdef MODULE
 
-static int dmasound[MAXARGS] = { 0 };
-
 int init_module(void)
 {
-	int err, i = 0;
-	int ints[MAXARGS+1];
-
-	while (i < MAXARGS && dmasound[i])
-		ints[i + 1] = dmasound[i++];
-	ints[0] = i;
-
-	if (i)
-		dmasound_setup("dmasound=", ints);
-
-	err = register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
-	if (err) {
-		printk("dmasound: driver already loaded/included in kernel\n");
-		return err;
-	}
-	chrdev_registered = 1;
-	soundcard_init();
-
+	dmasound_init();
 	return 0;
 }
 
@@ -4610,12 +4565,6 @@
 {
 	int i;
 
-	if (MOD_IN_USE)
-		return;
-
-	if (chrdev_registered)
-		unregister_chrdev(SOUND_MAJOR, "sound");
-
 	if (irq_installed) {
 		sound_silence();
 		sound.mach.irqcleanup();
@@ -4626,6 +4575,13 @@
 			sound.mach.dma_free(sound_buffers[i], bufSize << 10);
 		kfree(sound_buffers);
 	}
+
+	if (mixer_unit >= 0)
+		unregister_sound_mixer(mixer_unit);
+	if (state_unit >= 0)
+		unregister_sound_special(state_unit);
+	if (sq_unit >= 0)
+		unregister_sound_dsp(sq_unit);
 }
 
 #endif /* MODULE */
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/video/Config.in m68k/drivers/video/Config.in
--- jes-2.1.108/drivers/video/Config.in	Fri Jul 10 19:11:07 1998
+++ m68k/drivers/video/Config.in	Sun Jul 12 21:48:09 1998
@@ -38,7 +38,7 @@
 #     bool 'Apple "valkyrie" display support' CONFIG_FB_VALKYRIE
       bool 'ATI Mach64 display support' CONFIG_FB_ATY
 #     bool 'IMS Twin Turbo display support' CONFIG_FB_IMSTT
-#     bool 'Chips 65550 display support' CONFIG_FB_CT65550
+      bool 'Chips 65550 display support' CONFIG_FB_CT65550
 #     bool 'S3 Trio display support' CONFIG_FB_S3TRIO
     fi
   fi
@@ -65,13 +65,12 @@
     tristate 'MDA dual-headed support' CONFIG_FB_MDA
   fi
   if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
-    bool 'PROM framebuffer' CONFIG_FB_PROM
     bool 'SBUS and UPA framebuffers' CONFIG_FB_SBUS
     if [ "$CONFIG_FB_SBUS" != "n" ]; then
       if [ "$ARCH" = "sparc64" ]; then
-	bool 'Creator/Creator3D support' CONFIG_FB_CREATOR
+	bool '  Creator/Creator3D support' CONFIG_FB_CREATOR
       fi
-      bool 'CGsix (GX,GXplus) support' CONFIG_FB_CGSIX
+      bool '  CGsix (GX,GXplus) support' CONFIG_FB_CGSIX
     fi
   fi
   tristate 'Virtual Frame Buffer support (ONLY FOR TESTING!)' CONFIG_FB_VIRTUAL
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/video/Makefile m68k/drivers/video/Makefile
--- jes-2.1.108/drivers/video/Makefile	Fri Jul 10 19:11:07 1998
+++ m68k/drivers/video/Makefile	Sun Jul 12 21:48:09 1998
@@ -29,6 +29,10 @@
   L_OBJS += dummycon.o
 endif
 
+ifeq ($(CONFIG_PROM_CONSOLE),y)
+  L_OBJS += promcon.o
+endif
+
 ifeq ($(CONFIG_FB),y)
   L_OBJS += fonts.o font_8x8.o font_8x16.o pearl_8x8.o font_6x11.o font_sun8x16.o
   OX_OBJS += fbcon.o fbcmap.o fbgen.o
@@ -60,6 +64,10 @@
 L_OBJS += atyfb.o
 endif
 
+ifeq ($(CONFIG_FB_CT65550),y)
+L_OBJS += chipsfb.o
+endif
+
 ifeq ($(CONFIG_FB_CYBER),y)
 L_OBJS += cyberfb.o
 else
@@ -129,14 +137,6 @@
 else
   ifeq ($(CONFIG_FB_VIRGE),m)
   M_OBJS += virgefb.o
-  endif
-endif
-
-ifeq ($(CONFIG_FB_PROM),y)
-L_OBJS += promfb.o
-else
-  ifeq ($(CONFIG_FB_PROM),m)
-  M_OBJS += promfb.o
   endif
 endif
 
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/video/chipsfb.c m68k/drivers/video/chipsfb.c
--- jes-2.1.108/drivers/video/chipsfb.c	Thu Jan  1 01:00:00 1970
+++ m68k/drivers/video/chipsfb.c	Sun Jul 12 21:48:09 1998
@@ -0,0 +1,407 @@
+/*
+ *  drivers/video/chipsfb.c -- frame buffer device for
+ *  Chips & Technologies 65550 chip.
+ *
+ *  Copyright (C) 1998 Paul Mackerras
+ *
+ *  This file is derived from the Powermac "chips" driver:
+ *  Copyright (C) 1997 Fabio Riccardi.
+ *  And from the frame buffer device for Open Firmware-initialized devices:
+ *  Copyright (C) 1997 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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/selection.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#ifdef CONFIG_FB_COMPAT_XPMAC
+#include <asm/vc_ioctl.h>
+#endif
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+
+#include "fbcon.h"
+#include "fbcon-cfb8.h"
+#include "fbcon-cfb16.h"
+
+static int currcon = 0;
+
+struct fb_info_chips {
+	struct fb_info info;
+	struct fb_fix_screeninfo fix;
+	struct fb_var_screeninfo var;
+	struct display disp;
+	struct {
+		__u8 red, green, blue;
+	} palette[256];
+	__u8 *frame_buffer;
+	__u8 *blitter_regs;
+	__u8 *io_base;
+	unsigned long chips_base_phys;
+	unsigned long chips_io_phys;
+};
+
+/*
+ * Exported functions
+ */
+void chips_init(void);
+void chips_of_init(struct device_node *dp);
+
+static int chips_open(struct fb_info *info, int user);
+static int chips_release(struct fb_info *info, int user);
+static int chips_get_fix(struct fb_fix_screeninfo *fix, int con,
+			 struct fb_info *info);
+static int chips_get_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info);
+static int chips_set_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info);
+static int chips_pan_display(struct fb_var_screeninfo *var, int con,
+			     struct fb_info *info);
+static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info);
+static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info);
+static int chips_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		       u_long arg, int con, struct fb_info *info);
+
+static struct fb_ops chipsfb_ops = {
+	chips_open,
+	chips_release,
+	chips_get_fix,
+	chips_get_var,
+	chips_set_var,
+	chips_get_cmap,
+	chips_set_cmap,
+	chips_pan_display,
+	chips_ioctl
+};
+
+static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green,
+			     u_int *blue, u_int *transp, struct fb_info *info);
+static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *info);
+static void do_install_cmap(int con, struct fb_info *info);
+
+static int chips_open(struct fb_info *info, int user)
+{
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int chips_release(struct fb_info *info, int user)
+{
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int chips_get_fix(struct fb_fix_screeninfo *fix, int con,
+			 struct fb_info *info)
+{
+	struct fb_info_chips *cp = (struct fb_info_chips *) info;
+
+	*fix = cp->fix;
+	return 0;
+}
+
+static int chips_get_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info)
+{
+	struct fb_info_chips *cp = (struct fb_info_chips *) info;
+
+	*var = cp->var;
+	return 0;
+}
+
+static int chips_set_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info)
+{
+	struct fb_info_chips *cp = (struct fb_info_chips *) info;
+	struct display *disp;
+
+	disp = (con >= 0)? &fb_display[con]: &cp->disp;
+
+	if (var->xres > 800 || var->yres > 600
+	    || var->xres_virtual > 800 || var->yres_virtual > 600
+	    || var->bits_per_pixel != 8
+	    || var->nonstd
+	    || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+		return -EINVAL;
+
+	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+		disp->var = *var;
+	}
+
+	return 0;
+}
+
+static int chips_pan_display(struct fb_var_screeninfo *var, int con,
+			     struct fb_info *info)
+{
+	if (var->xoffset != 0 || var->yoffset != 0)
+		return -EINVAL;
+	return 0;
+}
+
+static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info)
+{
+	if (con == currcon)		/* current console? */
+		return fb_get_cmap(cmap, &fb_display[con].var, kspc,
+				   chipsfb_getcolreg, info);
+	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(256), cmap, kspc? 0: 2);
+	return 0;
+}
+
+static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			 struct fb_info *info)
+{
+	struct display *disp = &fb_display[con];
+	int err;
+
+	if (disp->cmap.len == 0) {
+		err = fb_alloc_cmap(&disp->cmap, 256, 0);
+		if (err)
+			return err;
+	}
+
+	if (con == currcon)
+		return fb_set_cmap(cmap, &disp->var, kspc, chipsfb_setcolreg,
+				   info);
+	fb_copy_cmap(cmap, &disp->cmap, kspc==0);
+	return 0;
+}
+
+static int chips_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		       u_long arg, int con, struct fb_info *info)
+{
+	return -EINVAL;
+}
+
+static int chipsfb_switch(int con, struct fb_info *info)
+{
+	if (fb_display[currcon].cmap.len)
+		fb_get_cmap(&fb_display[currcon].cmap,
+			    &fb_display[currcon].var, 1, chipsfb_getcolreg,
+			    info);
+	currcon = con;
+	do_install_cmap(con, info);
+	return 0;
+}
+
+static int chipsfb_updatevar(int con, struct fb_info *info)
+{
+	return 0;
+}
+
+static void chipsfb_blank(int blank, struct fb_info *info)
+{
+	struct fb_info_chips *p = (struct fb_info_chips *) info;
+	int i;
+
+	if (blank) {
+		for (i = 0; i < 256; ++i) {
+			out_8(p->io_base + 0x3c8, i);
+			udelay(1);
+			out_8(p->io_base + 0x3c9, 0);
+			out_8(p->io_base + 0x3c9, 0);
+			out_8(p->io_base + 0x3c9, 0);
+		}
+	} else {
+		do_install_cmap(currcon, info);
+	}
+}
+
+static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green,
+			     u_int *blue, u_int *transp, struct fb_info *info)
+{
+	struct fb_info_chips *p = (struct fb_info_chips *) info;
+
+	if (regno > 255)
+		return 1;
+	*red = p->palette[regno].red;
+	*green = p->palette[regno].green;
+	*blue = p->palette[regno].blue;
+	return 0;
+}
+
+static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *info)
+{
+	struct fb_info_chips *p = (struct fb_info_chips *) info;
+
+	if (regno > 255)
+		return 1;
+	p->palette[regno].red = red;
+	p->palette[regno].green = green;
+	p->palette[regno].blue = blue;
+	out_8(p->io_base + 0x3c8, regno);
+	udelay(1);
+	out_8(p->io_base + 0x3c9, red);
+	out_8(p->io_base + 0x3c9, green);
+	out_8(p->io_base + 0x3c9, blue);
+	return 0;
+}
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+	if (con != currcon)
+		return;
+	if (fb_display[con].cmap.len)
+		fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
+			    chipsfb_setcolreg, info);
+	else
+		fb_set_cmap(fb_default_cmap(256), &fb_display[con].var, 1,
+			    chipsfb_setcolreg, info);
+}
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+extern struct vc_mode display_info;
+extern struct fb_info *console_fb_info;
+extern int (*console_setmode_ptr)(struct vc_mode *, int);
+extern int (*console_set_cmap_ptr)(struct fb_cmap *, int, int,
+				   struct fb_info *);
+/*static int chips_console_setmode(struct vc_mode *, int);*/
+#endif /* CONFIG_FB_COMPAT_XPMAC */
+
+__initfunc(static void init_chips(struct fb_info_chips *p))
+{
+	int i;
+
+	memset(&p->fix, 0, sizeof(p->fix));
+	strcpy(p->fix.id, "C&T 65550");
+	p->fix.smem_start = (char *) p->chips_base_phys;
+	p->fix.smem_len = 800 * 600;
+	p->fix.mmio_start = (char *) p->chips_io_phys;
+	p->fix.type = FB_TYPE_PACKED_PIXELS;
+	p->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	p->fix.line_length = 800;
+
+	memset(&p->var, 0, sizeof(p->var));
+	p->var.xres = 800;
+	p->var.yres = 600;
+	p->var.xres_virtual = 800;
+	p->var.yres_virtual = 600;
+	p->var.bits_per_pixel = 8;
+	p->var.red.length = p->var.green.length = p->var.blue.length = 8;
+	p->var.height = p->var.width = -1;
+	p->var.vmode = FB_VMODE_NONINTERLACED;
+	p->var.pixclock = 10000;
+	p->var.left_margin = p->var.right_margin = 16;
+	p->var.upper_margin = p->var.lower_margin = 16;
+	p->var.hsync_len = p->var.vsync_len = 8;
+
+	memset(&p->disp, 0, sizeof(p->disp));
+	p->disp.var = p->var;
+	p->disp.cmap.red = NULL;
+	p->disp.cmap.green = NULL;
+	p->disp.cmap.blue = NULL;
+	p->disp.cmap.transp = NULL;
+	p->disp.screen_base = (char *) p->frame_buffer;
+	p->disp.visual = p->fix.visual;
+	p->disp.type = p->fix.type;
+	p->disp.type_aux = p->fix.type_aux;
+	p->disp.line_length = p->fix.line_length;
+	p->disp.can_soft_blank = 1;
+	p->disp.dispsw = &fbcon_cfb8;
+
+	strcpy(p->info.modename, p->fix.id);
+	p->info.node = -1;
+	p->info.fbops = &chipsfb_ops;
+	p->info.disp = &p->disp;
+	p->info.fontname[0] = 0;
+	p->info.changevar = NULL;
+	p->info.switch_con = &chipsfb_switch;
+	p->info.updatevar = &chipsfb_updatevar;
+	p->info.blank = &chipsfb_blank;
+
+	for (i = 0; i < 16; ++i) {
+		int j = color_table[i];
+		p->palette[i].red = default_red[j];
+		p->palette[i].green = default_grn[j];
+		p->palette[i].blue = default_blu[j];
+	}
+
+	if (register_framebuffer(&p->info) < 0) {
+		kfree(p);
+		return;
+	}
+
+	printk("fb%d: Chips 65550 frame buffer\n", GET_FB_IDX(p->info.node));
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+	if (!console_fb_info) {
+		display_info.height = p->var.yres;
+		display_info.width = p->var.xres;
+		display_info.depth = 8;
+		display_info.pitch = p->fix.line_length;
+		display_info.mode = 10;
+		strncpy(display_info.name, "chips65550",
+			sizeof(display_info.name));
+		display_info.fb_address = p->chips_base_phys + 0x800000;
+		display_info.cmap_adr_address = p->chips_io_phys + 0x3c8;
+		display_info.cmap_data_address = p->chips_io_phys + 0x3c9;
+		display_info.disp_reg_address = p->chips_base_phys + 0xc00000;
+		console_fb_info = &p->info;
+		console_set_cmap_ptr = chips_set_cmap;
+	}
+#endif /* CONFIG_FB_COMPAT_XPMAC */
+}
+
+__initfunc(void chips_init(void))
+{
+#ifndef CONFIG_FB_OF
+	struct device_node *dp;
+
+	dp = find_devices("chips65550");
+	if (dp != 0)
+		chips_of_init(dp);
+#endif /* CONFIG_FB_OF */
+}
+
+__initfunc(void chips_of_init(struct device_node *dp))
+{
+	struct fb_info_chips *p;
+	unsigned long addr;
+	unsigned char bus, devfn;
+	unsigned short cmd;
+
+	if (dp->n_addrs == 0)
+		return;
+	p = kmalloc(sizeof(*p), GFP_ATOMIC);
+	if (p == 0)
+		return;
+	addr = dp->addrs[0].address;
+	p->chips_base_phys = addr;
+	p->frame_buffer = __ioremap(addr+0x800000, 0x100000, _PAGE_WRITETHRU);
+	p->blitter_regs = ioremap(addr + 0xC00000, 0x1000);
+
+	if (pci_device_loc(dp, &bus, &devfn) == 0) {
+		pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
+		cmd |= 3;	/* enable memory and IO space */
+		pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
+		p->io_base = (unsigned char *) pci_io_base(bus);
+		/* XXX really want the physical address here */
+		p->chips_io_phys = (unsigned long) pci_io_base(bus);
+	}
+
+	init_chips(p);
+}
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/video/dummycon.c m68k/drivers/video/dummycon.c
--- jes-2.1.108/drivers/video/dummycon.c	Fri Jul 10 19:11:08 1998
+++ m68k/drivers/video/dummycon.c	Sun Jul 12 21:48:09 1998
@@ -48,9 +48,9 @@
 }
 
 /*
- *  The console `switch' structure for the frame buffer based console
+ *  The console `switch' structure for the dummy console
  *
- *  Most of the operations are dummies. They are replaced by fbcon_startup().
+ *  Most of the operations are dummies.
  */
 
 struct consw dummy_con = {
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/video/fbcon-cfb24.c m68k/drivers/video/fbcon-cfb24.c
--- jes-2.1.108/drivers/video/fbcon-cfb24.c	Fri Jul 10 19:11:08 1998
+++ m68k/drivers/video/fbcon-cfb24.c	Sun Jul 12 21:48:09 1998
@@ -19,9 +19,6 @@
 #include "fbcon-cfb24.h"
 
 
-#warning Remove this warning after the test cycle was finalized
-
-
     /*
      *  24 bpp packed pixels
      */
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/video/fbcon.c m68k/drivers/video/fbcon.c
--- jes-2.1.108/drivers/video/fbcon.c	Fri Jul 10 19:11:09 1998
+++ m68k/drivers/video/fbcon.c	Sun Jul 12 21:48:09 1998
@@ -168,7 +168,7 @@
 static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
 			int height, int width);
 static int fbcon_switch(struct vc_data *conp);
-static int fbcon_blank(int blank);
+static int fbcon_blank(struct vc_data *conp, int blank);
 static int fbcon_get_font(struct vc_data *conp, int *w, int *h, char *data);
 static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data);
 static int fbcon_set_palette(struct vc_data *conp, unsigned char *table);
@@ -250,8 +250,6 @@
 	return display_desc;
     done = 1;
 
-    /* Replace the dummy calls by the real calls */
-
 #ifdef CONFIG_AMIGA
     if (MACH_IS_AMIGA) {
 	cursor_blink_rate = AMIGA_CURSOR_BLINK_RATE;
@@ -1009,9 +1007,9 @@
 }
 
 
-static int fbcon_blank(int blank)
+static int fbcon_blank(struct vc_data *conp, int blank)
 {
-    struct display *p = &fb_display[fg_console];
+    struct display *p = &fb_display[conp->vc_num];
     struct fb_info *info = p->fb_info;
 
     fbcon_cursor(p->conp, blank ? CM_ERASE : CM_DRAW);
@@ -1032,7 +1030,7 @@
 			     p->var.xres_virtual*p->var.yres_virtual*
 			     p->var.bits_per_pixel>>3);
 	     } else
-		 p->dispsw->clear(p->conp, p, 0, 0, p->conp->vc_rows, p->conp->vc_cols);
+		 p->dispsw->clear(conp, p, 0, 0, p->conp->vc_rows, p->conp->vc_cols);
 	    return 0;
 	} else {
 	    /* Tell console.c that it has to restore the screen itself */
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/video/offb.c m68k/drivers/video/offb.c
--- jes-2.1.108/drivers/video/offb.c	Fri Jul 10 19:11:09 1998
+++ m68k/drivers/video/offb.c	Sun Jul 12 21:48:09 1998
@@ -286,7 +286,9 @@
 #ifdef CONFIG_FB_S3TRIO
 extern void s3triofb_init_of(struct device_node *dp);
 #endif /* CONFIG_FB_S3TRIO */
-
+#ifdef CONFIG_FB_CT65550
+extern void chips_of_init(struct device_node *dp);
+#endif /* CONFIG_FB_CT65550 */
 
     /*
      *  Initialisation
@@ -320,6 +322,12 @@
             if (s3triofb_init_of(dp))
                 continue;
 #endif /* CONFIG_FB_S3TRIO */
+#ifdef CONFIG_FB_CT65550
+	    if (!strcmp(dp->name, "chips65550")) {
+		chips_of_init(dp);
+		continue;
+	    }
+#endif /* CONFIG_FB_CT65550 */
 	}
 
 	info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC);
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/video/promcon.c m68k/drivers/video/promcon.c
--- jes-2.1.108/drivers/video/promcon.c	Thu Jan  1 01:00:00 1970
+++ m68k/drivers/video/promcon.c	Sun Jul 12 21:48:09 1998
@@ -0,0 +1,359 @@
+/* $Id: promcon.c,v 1.1 1998/07/09 17:56:27 jj Exp $
+ * Console driver utilizing PROM sun terminal emulation
+ *
+ * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
+ * Copyright (C) 1998  Jakub Jelinek  (jj@ultra.linux.cz)
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/console.h>
+#include <linux/console_struct.h>
+#include <linux/fb.h>
+
+#include <asm/oplib.h>
+
+static short pw = 80 - 1, ph = 34 - 1;
+static short px, py;
+
+#ifdef __sparc_v9__
+extern void prom_puts(char *, int);
+#else
+extern inline void prom_puts(char *str, int cnt)
+{
+	while (cnt--) prom_putchar(*str++);
+}
+#endif
+
+__initfunc(const char *promcon_startup(void))
+{
+	const char *display_desc = "PROM";
+	int node;
+	char buf[40];
+	
+	node = prom_getchild(prom_root_node);
+	node = prom_searchsiblings(node, "options");
+	if (prom_getproperty(node,  "screen-#columns", buf, 40) != -1) {
+		pw = simple_strtoul(buf, NULL, 0);
+		if (pw < 10 || pw > 256)
+			pw = 80;
+		pw--;
+	}
+	if (prom_getproperty(node,  "screen-#rows", buf, 40) != -1) {
+		ph = simple_strtoul(buf, NULL, 0);
+		if (ph < 10 || ph > 256)
+			ph = 34;
+		ph--;
+	}
+	prom_puts("\033[H\033[J", 6);
+	return display_desc;
+}
+
+static void promcon_init(struct vc_data *conp, int init)
+{
+	conp->vc_can_do_color = 0;
+	conp->vc_cols = pw + 1;
+	conp->vc_rows = ph + 1;
+}
+
+static int promcon_switch(struct vc_data *conp)
+{
+	return 1;
+}
+
+static unsigned short *promcon_repaint_line(unsigned short *s, unsigned char *b, unsigned char **bp)
+{
+	int cnt = pw + 1;
+	unsigned short attr = 0;
+	unsigned char *buf = *bp;
+	
+	while (cnt--) {
+		if (attr != (*s & 0x0800)) {
+			attr = (*s & 0x0800);
+			if (attr) {
+				strcpy (buf, "\033[7m");
+				buf += 4;
+			} else {
+				strcpy (buf, "\033[m");
+				buf += 3;
+			}
+		}
+		*buf++ = *s++;
+		if (buf - b >= 240) {
+			prom_puts(b, buf - b);
+			buf = b;
+		}
+	}
+	*bp = buf;
+	return s;
+}
+
+static void promcon_putcs(struct vc_data *conp, const unsigned short *s, int count, int y, int x)
+{
+	unsigned char b[256], *buf = b;
+	unsigned short attr = *s;
+	int i, last = 0;
+
+	if (attr & 0x0800) {
+		strcpy(buf, "\033[7m");
+		buf += 4;
+	}
+	
+	if (px != x || py != y) {
+		buf += sprintf(buf, "\033[%d;%dH", y + 1, x + 1);
+		px = x;
+		py = y;
+	}
+	
+	if (x + count == pw + 1) {
+		if ((s[count - 1] & 0x8ff) == ' ') {
+			unsigned short *t = s + count - 2;
+			last = 2;
+			while (--count > 0)
+				if ((*t-- & 0x8ff) != ' ')
+					break;
+		} else if (y == ph) {
+			count--;
+//			last = 1;
+		}
+	}
+
+	for (i = 0; i < count; i++) {
+		if (buf - b >= 240) {
+			prom_puts(b, buf - b);
+			buf = b;
+		}
+		*buf++ = *s++;
+	}
+
+	px += count;
+	if (px == pw + 1) {
+		px = 0;
+		py++;
+	}
+	
+#if 0	
+	if (last == 1) {
+		strcpy(buf, "\033[r");
+		buf += 3;
+		*buf++ = *s++;
+	}
+#endif
+	
+	if (attr & 0x0800) {
+		strcpy(buf, "\033[m");
+		buf += 3;
+	}
+
+#if 0	
+	if (last == 1) {
+		strcpy(buf, "\033[1r");
+		buf += 4;
+		promcon_repaint_line((unsigned short *)conp->vc_origin, b, &buf);
+		buf += sprintf(buf, "\033[%d;%dH", ph + 1, pw + 1);
+	}
+#endif
+	if (last == 2) {
+		strcpy(buf, "\033[K");
+		buf += 3;
+	}
+	
+	prom_puts(b, buf - b);
+}
+
+static void promcon_putc(struct vc_data *conp, int c, int y, int x)
+{
+	unsigned short s = c;
+	promcon_putcs(conp, &s, 1, y, x);
+}
+
+static void promcon_clear(struct vc_data *conp, int sy, int sx, int height, int width)
+{
+	int i, j;
+	unsigned char b[256], *buf = b;
+	
+	if (!sx && width == pw + 1) {
+		if (!sy && height == ph + 1)
+			return prom_puts("\033[2J", 4);
+#if 0
+/* Seems like I have found a bug in PROM... and I don't want to die in the depths of PROM -jj */
+		else if (!sy)
+			return prom_printf("\033[%d;%dH\033[1J\033[%d;%dH", height, pw + 1, py + 1, px + 1);
+#endif			
+		else if (sy + height == ph + 1)
+			return prom_printf("\033[%dH\033[J\033[%d;%dH", sy + 1, py + 1, px + 1);
+		buf += sprintf(buf, "\033[%dH", sy + 1);
+		for (i = 1; i < height; i++) {
+			strcpy(buf, "\033[2K\n");
+			buf += 5;
+		}
+		buf += sprintf(buf, "\033[2K\033[%d;%dH", py + 1, px + 1);
+		return prom_puts(b, buf - b);
+	} else if (!sx) {
+		buf += sprintf(buf, "\033[%d;%dH", sy + 1, width + 1);
+		for (i = 1; i < height; i++) {
+			strcpy(buf, "\033[1K\n");
+			buf += 5;
+		}
+		buf += sprintf(buf, "\033[1K\033[%d;%dH", py + 1, px + 1);
+		return prom_puts(b, buf - b);
+	} else if (sx + width == pw + 1) {
+		buf += sprintf(buf, "\033[%d;%dH", sy + 1, sx + 1);
+		for (i = 1; i < height; i++) {
+			strcpy(buf, "\033[K\n");
+			buf += 4;
+		}
+		buf += sprintf(buf, "\033[K\033[%d;%dH", py + 1, px + 1);
+		return prom_puts(b, buf - b);
+	}
+	for (i = sy + 1; i <= sy + height; i++) {
+		buf += sprintf(buf, "\033[%d;%dH", i, sx + 1);
+		for (j = 0; j < width; j++)
+			*buf++ = ' ';
+		if (buf - b + width >= 240) {
+			prom_puts(b, buf - b);
+			buf = b;
+		}
+	}
+	buf += sprintf(buf, "\033[%d;%dH", py + 1, px + 1);
+	prom_puts(b, buf - b);
+}
+                        
+static void promcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, int h, int w)
+{
+	if (sy == dy && h == 1) {
+		if (dx > sx && dx + w == conp->vc_cols)
+			return prom_printf("\033[%d;%dH\033[%d@\033[%d;%dH", sy + 1, sx + 1, dx - sx, py + 1, px + 1);
+		else if (dx < sx && sx + w == conp->vc_cols)
+			return prom_printf("\033[%d;%dH\033[%dP\033[%d;%dH", dy + 1, dx + 1, sx - dx, py + 1, px + 1);
+	}
+	/* FIXME: What to do here??? Current console.c should not call it like that ever. */
+	prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
+}
+
+static void promcon_cursor(struct vc_data *conp, int mode)
+{
+	switch (mode) {
+	case CM_ERASE:
+		break;
+
+	case CM_MOVE:
+	case CM_DRAW:
+		if (px != conp->vc_x || py != conp->vc_y) {
+			px = conp->vc_x; py = conp->vc_y;
+			prom_printf("\033[%d;%dH", py + 1, px + 1);
+		}
+		break;
+	}
+}
+
+static int promcon_get_font(struct vc_data *conp, int *w, int *h, char *data)
+{
+	return -ENOSYS;
+}
+        
+static int promcon_set_font(struct vc_data *conp, int w, int h, char *data)
+{
+	return -ENOSYS;
+}
+
+static int promcon_blank(int blank)
+{
+	if (blank) {
+		prom_printf("\033[2J");
+		return 0;
+	} else
+		/* Let console.c redraw */
+		return 1;
+}
+
+static int promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
+{
+	int i;
+	unsigned short *s;
+	unsigned char buff[256], *buf;
+	
+	switch (dir) {
+	case SM_UP:
+		if (b == ph + 1) {
+			prom_printf("\033[%dH\033[%dM", t + 1, count);
+			px = 0; py = t;
+			break;
+		}
+		s = (unsigned short *)(conp->vc_origin + (t + count)*conp->vc_size_row);
+		buf = buff + sprintf(buff, "\033[%dH", t + 1);
+		for (i = t; i < b - count; i++)
+			s = promcon_repaint_line(s, buff, &buf);
+		for (; i < b - 1; i++) {
+			strcpy(buf, "\033[2K\n");
+			buf += 5;
+			if (buf - buff >= 240) {
+				prom_puts(buff, buf - buff);
+				buf = buff;
+			}
+		}
+		buf += sprintf(buf, "\033[2K\033[%d;%dH", py + 1, px + 1);
+		prom_puts(buff, buf - buff);
+		break;
+	case SM_DOWN:
+		if (b == ph + 1) {
+			prom_printf("\033[%dH\033[%dL", t + 1, count);
+			px = 0; py = t;
+			break;
+		}
+		s = (unsigned short *)(conp->vc_origin + t*conp->vc_size_row);
+		buf = buff + sprintf(buff, "\033[%dH", t + 1);
+		for (i = t; i < t + count; i++) {
+			strcpy(buf, "\033[2K\n");
+			buf += 5;
+			if (buf - buff >= 240) {
+				prom_puts(buff, buf - buff);
+				buf = buff;
+			}
+		}
+		for (; i < b; i++)
+			s = promcon_repaint_line(s, buff, &buf);
+		buf += sprintf(buf, "\033[%d;%dH", py + 1, px + 1);
+		prom_puts(buff, buf - buff);
+		break;
+	}
+	return 0;
+}
+                
+/*
+ *  The console witch' structure for the VGA based console
+ */
+
+static int promcon_dummy(void)
+{
+        return 0;
+}
+
+#define DUMMY (void *) promcon_dummy
+
+struct consw prom_con = {
+	con_startup:		promcon_startup,
+	con_init:		promcon_init,
+	con_deinit:		DUMMY,
+	con_clear:		promcon_clear,
+	con_putc:		promcon_putc,
+	con_putcs:		promcon_putcs,
+	con_cursor:		promcon_cursor,
+	con_scroll:		promcon_scroll,
+	con_bmove:		promcon_bmove,
+	con_switch:		promcon_switch,
+	con_blank:		promcon_blank,
+	con_get_font:		promcon_get_font,
+	con_set_font:		promcon_set_font,
+	con_set_palette:	DUMMY,
+	con_scrolldelta:	DUMMY,
+	con_set_origin:		NULL,
+	con_save_screen:	NULL,
+};
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/video/promfb.c m68k/drivers/video/promfb.c
--- jes-2.1.108/drivers/video/promfb.c	Fri Jul 10 19:11:09 1998
+++ m68k/drivers/video/promfb.c	Thu Jan  1 01:00:00 1970
@@ -1,488 +0,0 @@
-/* $Id: promfb.c,v 1.3 1998/07/08 07:36:49 ecd Exp $
- *
- * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/malloc.h>
-#include <linux/delay.h>
-#include <linux/console.h>
-#include <linux/fb.h>
-
-#include "promfb.h"
-
-extern int prom_stdout;
-
-#define PROM_FONT_HEIGHT	22
-#define PROM_FONT_WIDTH		12
-
-void promfb_init(void);
-void promfb_setup(char *options, int *ints);
-
-
-static int
-promfb_open(struct fb_info *info, int user)
-{
-	MOD_INC_USE_COUNT;
-	return 0;
-}
-
-static int
-promfb_release(struct fb_info *info, int user)
-{
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-static int
-promfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-{
-	struct fb_info_promfb *fb = promfbinfo(info);
-
-	memcpy(fix, &fb->fix, sizeof(struct fb_fix_screeninfo));
-	return 0;
-}
-
-static int
-promfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-{
-	struct fb_info_promfb *fb = promfbinfo(info);
-
-	memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));
-	return 0;
-}
-
-static int
-promfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-{
-	return -EINVAL;
-}
-
-static int
-promfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-{
-	return 0;
-}
-
-static int
-promfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-{
-	return -EINVAL;
-}
-
-static int
-promfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-{
-	if (var->xoffset || var->yoffset)
-		return -EINVAL;
-	return 0;
-}
-
-static int
-promfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-	     u_long arg, int con, struct fb_info *info)
-{
-	return -EINVAL;
-}
-
-static int
-promfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
-{
-	return -EINVAL;
-}
-
-static struct fb_ops promfb_ops = {
-	promfb_open,
-	promfb_release,
-	promfb_get_fix,
-	promfb_get_var,
-	promfb_set_var,
-	promfb_get_cmap,
-	promfb_set_cmap,
-	promfb_pan_display,
-	promfb_ioctl,
-	promfb_mmap
-};
-
-
-static int
-promfbcon_switch(int con, struct fb_info *info)
-{
-	return 0;
-}
-
-static int
-promfbcon_updatevar(int con, struct fb_info *info)
-{
-	return 0;
-}
-
-static void
-promfbcon_blank(int blank, struct fb_info *info)
-{
-	/* nothing */
-}
-
-
-static void
-prom_start(struct fb_info_promfb *fb, struct display *d)
-{
-	unsigned short *dst = fb->data + d->next_line * fb->cury + fb->curx;
-
-	if (fb->curx == fb->maxx && fb->cury == fb->maxy)
-		return;
-
-	if (*dst & 0x0800)
-		prom_printf("\033[7m%c\033[m\033[%d;%dH",
-			    *dst, fb->cury + 1, fb->curx + 1);
-	else
-		prom_printf("%c\033[%d;%dH",
-			    *dst, fb->cury + 1, fb->curx + 1);
-}
-
-static void
-prom_stop(struct fb_info_promfb *fb, struct display *d)
-{
-	unsigned short *dst = fb->data + d->next_line * fb->cury + fb->curx;
-
-	if (fb->curx == fb->maxx && fb->cury == fb->maxy)
-		return;
-
-	if (*dst & 0x0800)
-		prom_printf("\033[%d;%dH%c\033[%d;%dH",
-			    fb->cury + 1, fb->curx + 1, *dst,
-			    fb->cury + 1, fb->curx + 1);
-	else
-		prom_printf("\033[%d;%dH\033[7m%c\033[m\033[%d;%dH",
-			    fb->cury + 1, fb->curx + 1, *dst,
-			    fb->cury + 1, fb->curx + 1);
-}
-
-static void
-fbcon_prom_setup(struct display *d)
-{
-	d->next_line = d->line_length;
-	d->next_plane = 0;
-}
-
-static void
-fbcon_prom_putc(struct vc_data *con, struct display *d, int c, int y, int x)
-{
-	struct fb_info_promfb *fb = promfbinfod(d);
-	unsigned short *dst;
-
-	dst = fb->data + y * d->line_length + x;
-	if (*dst != (c & 0xffff)) {
-		*dst = c & 0xffff;
-
-		prom_start(fb, d);
-
-		if (fb->curx != x || fb->cury != y) {
-			prom_printf("\033[%d;%dH", y + 1, x + 1);
-			fb->curx = x;
-			fb->cury = y;
-		}
-
-		if (x == fb->maxx && y == fb->maxy)
-			/* Sorry */ return;
-
-		if (c & 0x0800)
-			prom_printf("\033[7m%c\033[m", c);
-		else
-			prom_putchar(c);
-
-		prom_stop(fb, d);
-	}
-}
-
-static void
-fbcon_prom_putcs(struct vc_data *con, struct display *d,
-		 const unsigned short *s, int count, int y, int x)
-{
-	struct fb_info_promfb *fb = promfbinfod(d);
-	unsigned short *dst;
-	unsigned short attr = *s;
-	int i;
-
-	dst = fb->data + y * d->line_length + x;
-
-	prom_start(fb, d);
-
-	if (attr & 0x0800)
-		prom_printf("\033[7m");
-
-	for (i = 0; i < count; i++) {
-		if (*dst != *s) {
-			*dst = *s;
-
-			if (fb->curx != x + i || fb->cury != y) {
-				prom_printf("\033[%d;%dH", y + 1, x + i + 1);
-				fb->curx = x + i;
-				fb->cury = y;
-			}
-
-			if (fb->curx == fb->maxx && fb->cury == fb->maxy)
-				/* Sorry */ goto out;
-
-			prom_putchar(*s);
-
-			if (i < count - 1)
-				fb->curx++;
-		}
-		dst++;
-		s++;
-	}
-out:
-	if (attr & 0x0800)
-		prom_printf("\033[m");
-
-	prom_stop(fb, d);
-}
-
-static void
-fbcon_prom_clear(struct vc_data *con, struct display *d, int sy, int sx,
-		 int h, int w)
-{
-	int x, y;
-
-	for (y = sy; y < sy + h; y++)
-		for (x = sx; x < sx + w; x++)
-			fbcon_prom_putc(con, d, con->vc_video_erase_char, y, x);
-}
-
-static void
-fbcon_prom_bmove(struct display *d, int sy, int sx, int dy, int dx,
-		 int h, int w)
-{
-	struct fb_info_promfb *fb = promfbinfod(d);
-	int linesize = d->next_line;
-	unsigned short *src, *dst;
-	int x, y;
-
-	if (dx == 0 && sx == 0 && dy == 0 && sy == 1 &&
-	    w == linesize && h == fb->maxy) {
-		memcpy(fb->data, fb->data + linesize, 2 * linesize * fb->maxy);
-		prom_start(fb, d);
-		prom_printf("\033[%d;%dH", fb->maxy + 1, fb->maxx + 1);
-		prom_putchar(*(fb->data + linesize * fb->maxy + fb->maxx));
-		fb->curx = 0;
-		fb->cury = fb->maxy;
-		prom_stop(fb, d);
-	} else if (dy < sy || (dy == sy && dx < sx)) {
-		src = fb->data + sy * linesize + sx;
-		dst = fb->data + dy * linesize + dx;
-		for (y = dy; y < dy + h; y++) {
-			for (x = dx; x < dx + w; x++) {
-				if (*src != *dst)
-					fbcon_prom_putc(d->conp, d, *src, y, x);
-				src++;
-				dst++;
-			}
-		}
-	} else {
-		src = fb->data + (sy + h - 1) * linesize + sx + w - 1;
-		dst = fb->data + (dy + h - 1) * linesize + dx + w - 1;
-		for (y = dy + h - 1; y >= dy; y--) {
-			for (x = dx + w - 1; x >= dx; x--) {
-				if (*src != *dst)
-					fbcon_prom_putc(d->conp, d, *src, y, x);
-				src--;
-				dst--;
-			}
-		}
-	}
-}
-
-static void
-fbcon_prom_revc(struct display *d, int x, int y)
-{
-	struct fb_info_promfb *fb = promfbinfod(d);
-	unsigned short *dst = fb->data + y * d->next_line + x;
-	unsigned short val = *dst ^ 0x0800;
-
-	fbcon_prom_putc(d->conp, d, val, y, x);
-}
-
-static void
-fbcon_prom_cursor(struct display *d, int mode, int x, int y)
-{
-	struct fb_info_promfb *fb = promfbinfod(d);
-
-	switch (mode) {
-		case CM_ERASE:
-			break;
-
-		case CM_MOVE:
-		case CM_DRAW:
-			prom_start(fb, d);
-			if (fb->curx != x || fb->cury != y) {
-				prom_printf("\033[%d;%dH", y + 1, x + 1);
-				fb->curx = x;
-				fb->cury = y;
-			}
-			break;
-	}
-}
-
-static struct display_switch fbcon_promfb = {
-	fbcon_prom_setup,
-	fbcon_prom_bmove,
-	fbcon_prom_clear,
-	fbcon_prom_putc,
-	fbcon_prom_putcs,
-	fbcon_prom_revc,
-	fbcon_prom_cursor
-};
-
-
-struct promfb_size {
-	int xres, yres;
-	int width, height;
-	int x_margin, y_margin;
-} promfb_sizes[] __initdata = {
-	{ 1024, 768, 80, 34, 32, 10 },
-	{ 80 * PROM_FONT_WIDTH, 24 * PROM_FONT_HEIGHT, 80, 24, 0, 0 },
-	{ 0 }
-};
-
-__initfunc(void promfb_init(void))
-{
-	extern int con_is_present(void);
-	struct fb_info_promfb *fb;
-	struct fb_fix_screeninfo *fix;
-	struct fb_var_screeninfo *var;
-	struct display *disp;
-	struct promfb_size *size;
-	int i, w, h;
-
-	if (!con_is_present())
-		return;
-
-	fb = kmalloc(sizeof(struct fb_info_promfb), GFP_ATOMIC);
-	if (!fb) {
-		prom_printf("Could not allocate promfb structure\n");
-		return;
-	}
-
-	memset(fb, 0, sizeof(struct fb_info_promfb));
-	fix = &fb->fix;
-	var = &fb->var;
-	disp = &fb->disp;
-
-	fb->node = prom_inst2pkg(prom_stdout);
-	w = prom_getintdefault(fb->node, "width", 80 * PROM_FONT_WIDTH);
-	h = prom_getintdefault(fb->node, "height", 24 * PROM_FONT_HEIGHT);
-
-	size = promfb_sizes;
-	while (size->xres) {
-		if (size->xres == w && size->yres == h)
-			break;
-		size++;
-	}
-	if (!size->xres) {
-		size->xres = w;
-		size->yres = h;
-		size->width = w / PROM_FONT_WIDTH;
-		size->height = h / PROM_FONT_HEIGHT;
-		size->x_margin = (w - size->width * PROM_FONT_WIDTH) >> 1;
-		size->y_margin = (h - size->width * PROM_FONT_HEIGHT) >> 1;
-	}
-
-	fb->data = kmalloc(2 * size->width * size->height, GFP_ATOMIC);
-	if (!fb->data) {
-		kfree(fb);
-		return;
-	}
-
-	fb->maxx = size->width - 1;
-	fb->maxy = size->height - 1;
-
-	strcpy(fb->info.modename, "PROM pseudo");
-	fb->info.node = -1;
-	fb->info.fbops = &promfb_ops;
-	fb->info.disp = disp;
-	fb->info.fontname[0] = '\0';
-	fb->info.changevar = NULL;
-	fb->info.switch_con = promfbcon_switch;
-	fb->info.updatevar = promfbcon_updatevar;
-	fb->info.blank = promfbcon_blank;
-
-	strcpy(fix->id, "PROM pseudo");
-	fix->type = FB_TYPE_TEXT;
-	fix->type_aux = FB_AUX_TEXT_MDA;
-	fix->visual = FB_VISUAL_MONO01;
-	fix->xpanstep = 0;
-	fix->ypanstep = 16;
-	fix->ywrapstep = 0;
-	fix->line_length = size->width;
-	fix->accel = FB_ACCEL_NONE;
-
-	var->xres = size->width * 8;
-	var->yres = size->height * 16;
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
-	var->bits_per_pixel = 1;
-	var->xoffset = 0;
-	var->yoffset = 0;
-	var->activate = 0;
-	var->height = -1;
-	var->width = -1;
-	var->accel_flags = FB_ACCELF_TEXT;
-	var->vmode = FB_VMODE_NONINTERLACED;
-
-	disp->var = *var;
-	disp->visual = fix->visual;
-	disp->type = fix->type;
-	disp->type_aux = fix->type_aux;
-	disp->ypanstep = fix->ypanstep;
-	disp->ywrapstep = fix->ywrapstep;
-	disp->line_length = fix->line_length;
-	disp->can_soft_blank = 1;
-	disp->dispsw = &fbcon_promfb;
-
-	for (i = 0; i < fb->maxy * size->width + fb->maxx; i++)
-		fb->data[i] = ' ';
-	prom_printf("\033[H\033[J");
-
-	if (register_framebuffer(&fb->info) < 0) {
-		kfree(fb->data);
-		kfree(fb);
-		return;
-	}
-
-	printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb->info.node),
-	       fb->info.modename);
-	MOD_INC_USE_COUNT;
-}
-
-__initfunc(void promfb_setup(char *options, int *ints)) {}
-
-void
-promfb_cleanup(struct fb_info *info)
-{
-	struct fb_info_promfb *fb = promfbinfo(info);
-
-	unregister_framebuffer(info);
-	kfree(fb->data);
-	kfree(fb);
-}
-
-#ifdef MODULE
-int init_module(void)
-{
-	promfb_init();
-	return 0
-}
-
-void cleanup_module(void)
-{
-	promfb_cleanup();
-}
-#endif /* MODULE */
-
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/video/promfb.h m68k/drivers/video/promfb.h
--- jes-2.1.108/drivers/video/promfb.h	Fri Jul 10 19:11:09 1998
+++ m68k/drivers/video/promfb.h	Thu Jan  1 01:00:00 1970
@@ -1,28 +0,0 @@
-/* $Id: promfb.h,v 1.1 1998/07/05 22:50:43 ecd Exp $
- *
- * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- */
-
-#ifndef _PROMFB_H
-#define _PROMFB_H 1
-
-#include <asm/oplib.h>
-
-#include "fbcon.h"
-
-struct fb_info_promfb {
-	struct fb_info info;
-	struct fb_fix_screeninfo fix;
-	struct fb_var_screeninfo var;
-	struct display disp;
-	struct display_switch dispsw;
-	int node;
-	unsigned short *data;
-	int curx, cury;
-	int maxx, maxy;
-};
-
-#define promfbinfo(info)	((struct fb_info_promfb *)(info))
-#define promfbinfod(disp)	((struct fb_info_promfb *)(disp->fb_info))
-
-#endif /* !(_PROM_FB_H) */
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/video/sbusfb.c m68k/drivers/video/sbusfb.c
--- jes-2.1.108/drivers/video/sbusfb.c	Fri Jul 10 19:11:09 1998
+++ m68k/drivers/video/sbusfb.c	Sun Jul 12 21:48:09 1998
@@ -591,7 +591,7 @@
 	case FBIOGVIDEO:
 		put_user_ret(fb->blanked, (int *) arg, -EFAULT);
 		break;
-	case FBIOGETCMAP: {
+	case FBIOGETCMAP_SPARC: {
 		char *rp, *gp, *bp;
 		int end, count, index;
 		struct fbcmap *cmap;
@@ -623,7 +623,7 @@
 		(*fb->loadcmap)(fb, index, count);
 		break;			
 	}
-	case FBIOPUTCMAP: {	/* load color map entries */
+	case FBIOPUTCMAP_SPARC: {	/* load color map entries */
 		char *rp, *gp, *bp;
 		int end, count, index;
 		struct fbcmap *cmap;
@@ -978,7 +978,10 @@
 	struct linux_sbus_device *sbdp;
 	struct linux_sbus *sbus;
 	char prom_name[40];
-    
+	extern int con_is_present(void);
+	
+	if (!con_is_present()) return;
+	
 #ifdef CONFIG_FB_CREATOR
 	root = prom_getchild(prom_root_node);
 	for (node = prom_searchsiblings(root, "SUNW,ffb"); node;
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/drivers/video/vgacon.c m68k/drivers/video/vgacon.c
--- jes-2.1.108/drivers/video/vgacon.c	Fri Jul 10 19:11:10 1998
+++ m68k/drivers/video/vgacon.c	Sun Jul 12 21:48:09 1998
@@ -37,8 +37,6 @@
  *
  *	- monochrome attribute encoding (convert abscon <-> VGA style)
  *
- *	- add support for VESA blanking
- *
  *	- Cursor shape fixes
  *
  * KNOWN PROBLEMS/TO DO ==================================================== */
@@ -69,8 +67,15 @@
 
 #undef VGA_CAN_DO_64KB
 
-#define dac_reg	(0x3c8)
-#define dac_val	(0x3c9)
+#define dac_reg		0x3c8
+#define dac_val		0x3c9
+#define attrib_port	0x3c0
+#define seq_port_reg	0x3c4
+#define seq_port_val	0x3c5
+#define gr_port_reg	0x3ce
+#define gr_port_val	0x3cf
+#define video_misc_rd	0x3cc
+#define video_misc_wr	0x3c2
 
 /*
  *  Interface used by the world
@@ -80,7 +85,7 @@
 static void vgacon_init(struct vc_data *c, int init);
 static void vgacon_cursor(struct vc_data *c, int mode);
 static int vgacon_switch(struct vc_data *c);
-static int vgacon_blank(int blank);
+static int vgacon_blank(struct vc_data *c, int blank);
 static int vgacon_get_font(struct vc_data *c, int *w, int *h, char *data);
 static int vgacon_set_font(struct vc_data *c, int w, int h, char *data);
 static int vgacon_set_palette(struct vc_data *c, unsigned char *table);
@@ -103,6 +108,9 @@
 static unsigned char   vga_hardscroll_enabled;
 static unsigned char   vga_hardscroll_user_enable = 1;
 static unsigned char   vga_font_is_default = 1;
+static int	       vga_vesa_blanked;
+static int	       vga_palette_blanked;
+
 
 void no_scroll(char *str, int *ints)
 {
@@ -114,7 +122,6 @@
 	vga_hardscroll_user_enable = vga_hardscroll_enabled = 0;
 }
 
-
 /*
  * By replacing the four outb_p with two back to back outw, we can reduce
  * the window of opportunity to see text mislocated to the RHS of the
@@ -139,7 +146,6 @@
 #endif
 }
 
-
 __initfunc(static const char *vgacon_startup(void))
 {
 	const char *display_desc = NULL;
@@ -271,7 +277,6 @@
 	return display_desc;
 }
 
-
 static void vgacon_init(struct vc_data *c, int init)
 {
 	/* We cannot be loaded as a module, therefore init is always 1 */
@@ -280,13 +285,11 @@
 	c->vc_rows = vga_video_num_lines;
 }
 
-
 static inline void vga_set_mem_top(struct vc_data *c)
 {
 	write_vga(12, (c->vc_visible_origin-vga_vram_base)/2);
 }
 
-
 static void vgacon_cursor(struct vc_data *c, int mode)
 {
     if (c->vc_origin != c->vc_visible_origin)
@@ -303,7 +306,6 @@
     }
 }
 
-
 static int vgacon_switch(struct vc_data *c)
 {
 	/*
@@ -317,21 +319,192 @@
 	return 0;	/* Redrawing not needed */
 }
 
+static void vga_set_palette(struct vc_data *c, unsigned char *table)
+{
+	int i, j ;
 
-static int vgacon_blank(int blank)
+	for (i=j=0; i<16; i++) {
+		outb_p (table[i], dac_reg) ;
+		outb_p (c->vc_palette[j++]>>2, dac_val) ;
+		outb_p (c->vc_palette[j++]>>2, dac_val) ;
+		outb_p (c->vc_palette[j++]>>2, dac_val) ;
+	}
+}
+
+static int vgacon_set_palette(struct vc_data *c, unsigned char *table)
 {
-    /* FIXME: Implement! */
-    /* FIXME: Check if we really ignore everything when the console is blanked. */
-    if (blank) {
-	scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size);
+#ifdef CAN_LOAD_PALETTE
+
+	if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked)
+		return -EINVAL;
+	vga_set_palette(c, table);
 	return 0;
-    } else {
-	/* Tell console.c that it has to restore the screen itself */
-	return 1;
-    }
-    return 0;
+#else
+	return -EINVAL;
+#endif
+}
+
+/* structure holding original VGA register settings */
+static struct {
+	unsigned char	SeqCtrlIndex;		/* Sequencer Index reg.   */
+	unsigned char	CrtCtrlIndex;		/* CRT-Contr. Index reg.  */
+	unsigned char	CrtMiscIO;		/* Miscellaneous register */
+	unsigned char	HorizontalTotal;	/* CRT-Controller:00h */
+	unsigned char	HorizDisplayEnd;	/* CRT-Controller:01h */
+	unsigned char	StartHorizRetrace;	/* CRT-Controller:04h */
+	unsigned char	EndHorizRetrace;	/* CRT-Controller:05h */
+	unsigned char	Overflow;		/* CRT-Controller:07h */
+	unsigned char	StartVertRetrace;	/* CRT-Controller:10h */
+	unsigned char	EndVertRetrace;		/* CRT-Controller:11h */
+	unsigned char	ModeControl;		/* CRT-Controller:17h */
+	unsigned char	ClockingMode;		/* Seq-Controller:01h */
+} vga_state;
+
+static void vga_vesa_blank(int mode)
+{
+	/* save original values of VGA controller registers */
+	if(!vga_vesa_blanked) {
+		cli();
+		vga_state.SeqCtrlIndex = inb_p(seq_port_reg);
+		vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
+		vga_state.CrtMiscIO = inb_p(video_misc_rd);
+		sti();
+
+		outb_p(0x00,vga_video_port_reg);	/* HorizontalTotal */
+		vga_state.HorizontalTotal = inb_p(vga_video_port_val);
+		outb_p(0x01,vga_video_port_reg);	/* HorizDisplayEnd */
+		vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
+		outb_p(0x04,vga_video_port_reg);	/* StartHorizRetrace */
+		vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
+		outb_p(0x05,vga_video_port_reg);	/* EndHorizRetrace */
+		vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
+		outb_p(0x07,vga_video_port_reg);	/* Overflow */
+		vga_state.Overflow = inb_p(vga_video_port_val);
+		outb_p(0x10,vga_video_port_reg);	/* StartVertRetrace */
+		vga_state.StartVertRetrace = inb_p(vga_video_port_val);
+		outb_p(0x11,vga_video_port_reg);	/* EndVertRetrace */
+		vga_state.EndVertRetrace = inb_p(vga_video_port_val);
+		outb_p(0x17,vga_video_port_reg);	/* ModeControl */
+		vga_state.ModeControl = inb_p(vga_video_port_val);
+		outb_p(0x01,seq_port_reg);		/* ClockingMode */
+		vga_state.ClockingMode = inb_p(seq_port_val);
+	}
+
+	/* assure that video is enabled */
+	/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
+	cli();
+	outb_p(0x01,seq_port_reg);
+	outb_p(vga_state.ClockingMode | 0x20,seq_port_val);
+
+	/* test for vertical retrace in process.... */
+	if ((vga_state.CrtMiscIO & 0x80) == 0x80)
+		outb_p(vga_state.CrtMiscIO & 0xef,video_misc_wr);
+
+	/*
+	 * Set <End of vertical retrace> to minimum (0) and
+	 * <Start of vertical Retrace> to maximum (incl. overflow)
+	 * Result: turn off vertical sync (VSync) pulse.
+	 */
+	if (mode & VESA_VSYNC_SUSPEND) {
+		outb_p(0x10,vga_video_port_reg);	/* StartVertRetrace */
+		outb_p(0xff,vga_video_port_val); 	/* maximum value */
+		outb_p(0x11,vga_video_port_reg);	/* EndVertRetrace */
+		outb_p(0x40,vga_video_port_val);	/* minimum (bits 0..3)  */
+		outb_p(0x07,vga_video_port_reg);	/* Overflow */
+		outb_p(vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */
+	}
+
+	if (mode & VESA_HSYNC_SUSPEND) {
+		/*
+		 * Set <End of horizontal retrace> to minimum (0) and
+		 *  <Start of horizontal Retrace> to maximum
+		 * Result: turn off horizontal sync (HSync) pulse.
+		 */
+		outb_p(0x04,vga_video_port_reg);	/* StartHorizRetrace */
+		outb_p(0xff,vga_video_port_val);	/* maximum */
+		outb_p(0x05,vga_video_port_reg);	/* EndHorizRetrace */
+		outb_p(0x00,vga_video_port_val);	/* minimum (0) */
+	}
+
+	/* restore both index registers */
+	outb_p(vga_state.SeqCtrlIndex,seq_port_reg);
+	outb_p(vga_state.CrtCtrlIndex,vga_video_port_reg);
+	sti();
 }
 
+static void vga_vesa_unblank(void)
+{
+	/* restore original values of VGA controller registers */
+	cli();
+	outb_p(vga_state.CrtMiscIO,video_misc_wr);
+
+	outb_p(0x00,vga_video_port_reg);		/* HorizontalTotal */
+	outb_p(vga_state.HorizontalTotal,vga_video_port_val);
+	outb_p(0x01,vga_video_port_reg);		/* HorizDisplayEnd */
+	outb_p(vga_state.HorizDisplayEnd,vga_video_port_val);
+	outb_p(0x04,vga_video_port_reg);		/* StartHorizRetrace */
+	outb_p(vga_state.StartHorizRetrace,vga_video_port_val);
+	outb_p(0x05,vga_video_port_reg);		/* EndHorizRetrace */
+	outb_p(vga_state.EndHorizRetrace,vga_video_port_val);
+	outb_p(0x07,vga_video_port_reg);		/* Overflow */
+	outb_p(vga_state.Overflow,vga_video_port_val);
+	outb_p(0x10,vga_video_port_reg);		/* StartVertRetrace */
+	outb_p(vga_state.StartVertRetrace,vga_video_port_val);
+	outb_p(0x11,vga_video_port_reg);		/* EndVertRetrace */
+	outb_p(vga_state.EndVertRetrace,vga_video_port_val);
+	outb_p(0x17,vga_video_port_reg);		/* ModeControl */
+	outb_p(vga_state.ModeControl,vga_video_port_val);
+	outb_p(0x01,seq_port_reg);		/* ClockingMode */
+	outb_p(vga_state.ClockingMode,seq_port_val);
+
+	/* restore index/control registers */
+	outb_p(vga_state.SeqCtrlIndex,seq_port_reg);
+	outb_p(vga_state.CrtCtrlIndex,vga_video_port_reg);
+	sti();
+}
+
+static void vga_pal_blank(void)
+{
+	int i;
+
+	for (i=0; i<16; i++) {
+		outb_p (i, dac_reg) ;
+		outb_p (0, dac_val) ;
+		outb_p (0, dac_val) ;
+		outb_p (0, dac_val) ;
+	}
+}
+
+static int vgacon_blank(struct vc_data *c, int blank)
+{
+	if (!blank) {			/* Unblank */
+		if (vga_vesa_blanked) {
+			vga_vesa_unblank();
+			vga_vesa_blanked = 0;
+		}
+		if (vga_palette_blanked) {
+			vga_set_palette(c, color_table);
+			vga_palette_blanked = 0;
+			return 0;
+		}
+		/* Tell console.c that it has to restore the screen itself */
+		return 1;
+	} else if (blank == 1) {	/* Normal blanking */
+		if (vga_video_type == VIDEO_TYPE_VGAC) {
+			vga_pal_blank();
+			vga_palette_blanked = 1;
+			return 0;
+		}
+		scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size);
+		return 0;
+	} else {			/* VESA blanking */
+		if (vga_video_type == VIDEO_TYPE_VGAC) {
+			vga_vesa_blank(blank-1);
+			vga_vesa_blanked = blank;
+		}
+		return 0;
+	}
+}
 
 /*
  * PIO_FONT support.
@@ -350,11 +523,6 @@
    should use 0xA0000 for the bwmap as well.. */
 #define blackwmap 0xa0000
 #define cmapsz 8192
-#define attrib_port (0x3c0)
-#define seq_port_reg (0x3c4)
-#define seq_port_val (0x3c5)
-#define gr_port_reg (0x3ce)
-#define gr_port_val (0x3cf)
 
 static int
 vgacon_font_op(char *arg, int set)
@@ -578,26 +746,6 @@
 	return rc;
 }
 
-static int vgacon_set_palette(struct vc_data *c, unsigned char *table)
-{
-#ifdef CAN_LOAD_PALETTE
-	int i, j ;
-
-	if (vga_video_type != VIDEO_TYPE_VGAC || console_blanked)
-		return -EINVAL;
-
-	for (i=j=0; i<16; i++) {
-		outb_p (table[i], dac_reg) ;
-		outb_p (c->vc_palette[j++]>>2, dac_val) ;
-		outb_p (c->vc_palette[j++]>>2, dac_val) ;
-		outb_p (c->vc_palette[j++]>>2, dac_val) ;
-	}
-	return 0;
-#else
-	return -EINVAL;
-#endif
-}
-
 static int vgacon_scrolldelta(struct vc_data *c, int lines)
 {
 	/* FIXME: Better scrollback strategy, maybe move it to generic code
@@ -670,7 +818,6 @@
 	c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
 	return 1;
 }
-
 
 
 /*
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/Config.in m68k/fs/Config.in
--- jes-2.1.108/fs/Config.in	Fri Jul 10 19:11:10 1998
+++ m68k/fs/Config.in	Sun Jul 12 20:42:03 1998
@@ -65,74 +65,11 @@
 tristate 'Kernel automounter support' CONFIG_AUTOFS_FS
 tristate 'UFS filesystem support (read only)' CONFIG_UFS_FS
 
-comment 'Partition Tables'
-if [ "$ARCH" = "i386" ]; then
-  define_bool CONFIG_MSDOS_PARTITION y
-fi
-if [ "$ARCH" = "alpha" ]; then
-  define_bool CONFIG_OSF_PARTITION y
-fi
-if [ "$ARCH" = "m68k" ]; then
-  if [ "$CONFIG_AMIGA" = "y" ]; then
-    define_bool CONFIG_AMIGA_PARTITION y
-  fi
-  if [ "$CONFIG_ATARI" = "y" ]; then
-    define_bool CONFIG_ATARI_PARTITION y
-  fi
-  if [ "$CONFIG_MAC" = "y" ]; then
-    define_bool CONFIG_MAC_PARTITION y
-  fi
-fi
-if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
-  define_bool CONFIG_SUN_PARTITION y
-fi
-if [ "$ARCH" = "ppc" ]; then
-  if [ "$CONFIG_MACH_SPECIFIC" = "y" ]; then
-    if [ "$CONFIG_PMAC" = "y" -o "$CONFIG_CHRP" = "y" ]; then
-      define_bool CONFIG_MAC_PARTITION y
-    fi
-    if [ "$CONFIG_PREP" = "y" -o "$CONFIG_CHRP" = "y" ]; then
-      define_bool CONFIG_MSDOS_PARTITION y
-    fi
-  else
-    define_bool CONFIG_MAC_PARTITION y
-    define_bool CONFIG_MSDOS_PARTITION y
-  fi
-fi
-bool 'Support for foreign partition tables' CONFIG_FOREIGN_PARTITIONS
-if [ "$CONFIG_FOREIGN_PARTITIONS" = "y" ]; then
-  if [ ! \( "$ARCH" = "i386" -o \
-            \( "$ARCH" = "ppc" -a \
-               \( "$CONFIG_MACH_SPECIFIC" = "n" -o "$CONFIG_PREP" = "y" -o \
-                  "$CONFIG_CHRP" = "y" \) \) \) ]; then
-  	tristate 'MS-DOS partition support' CONFIG_MSDOS_PARTITION
-  fi
-  if [ "$ARCH" != "alpha" ]; then
-  	tristate 'OSF partition support' CONFIG_OSF_PARTITION
-  fi
-  if [ "$ARCH" != "sparc" -a "$ARCH" != "sparc64" ]; then
-  	tristate 'Sun partition support' CONFIG_SUN_PARTITION
-  fi
-  if [ "$CONFIG_AMIGA" != "y" ]; then
-  	tristate 'Amiga RDB partition support' CONFIG_AMIGA_PARTITION
-  fi
-  if [ "$CONFIG_ATARI" != "y" ]; then
-  	tristate 'Atari partition support' CONFIG_ATARI_PARTITION
-  fi
-  if [ ! \( \( "$ARCH" = "m68k" -a "$CONFIG_MAC" = "y" \) -o \
-            \( "$ARCH" = "ppc" -a \
-               \( "$CONFIG_MACH_SPECIFIC" = "n" -o "$CONFIG_PMAC" = "y" -o \
-                  "$CONFIG_CHRP" = "y" \) \) \) ]; then
-  	tristate 'Mac partition support' CONFIG_MAC_PARTITION
-  fi
-fi
-if [ "$CONFIG_MSDOS_PARTITION" != "n" ]; then
-  bool 'BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
-  bool 'Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
-fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   tristate 'ADFS filesystem support (read only) (EXPERIMENTAL)' CONFIG_ADFS_FS
   tristate '/dev/pts filesystem support (EXPERIMENTAL)' CONFIG_DEVPTS_FS
 fi
 
 endmenu
+
+source fs/partitions/Config.in
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/Makefile m68k/fs/Makefile
--- jes-2.1.108/fs/Makefile	Fri Jul 10 19:11:10 1998
+++ m68k/fs/Makefile	Sun Jul 12 20:31:02 1998
@@ -14,11 +14,15 @@
 		super.o  block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
 		ioctl.o readdir.o select.o fifo.o locks.o filesystems.o \
 		dcache.o inode.o attr.o bad_inode.o $(BINFMTS) 
+OX_OBJS  := partcheck.o
 
 MOD_LIST_NAME := FS_MODULES
 ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
 		hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd nfsd \
-		nls devpts adfs
+		nls devpts adfs partitions
+
+SUB_DIRS := partitions
+MOD_IN_SUB_DIRS := partitions
 
 ifeq ($(CONFIG_QUOTA),y)
 O_OBJS += dquot.o
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/ext2/inode.c m68k/fs/ext2/inode.c
--- jes-2.1.108/fs/ext2/inode.c	Thu May 14 21:34:50 1998
+++ m68k/fs/ext2/inode.c	Sun Jun 14 22:20:26 1998
@@ -722,10 +722,11 @@
 	unsigned int	flags;
 	
 	retval = -EPERM;
-	if ((iattr->ia_attr_flags &
-	     (ATTR_FLAG_APPEND | ATTR_FLAG_IMMUTABLE)) ^
-	    (inode->u.ext2_i.i_flags &
-	     (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL))) {
+	if (iattr->ia_valid & ATTR_ATTR_FLAG &&
+	    ((!(iattr->ia_attr_flags & ATTR_FLAG_APPEND) !=
+	      !(inode->u.ext2_i.i_flags & EXT2_APPEND_FL)) ||
+	     (!(iattr->ia_attr_flags & ATTR_FLAG_IMMUTABLE) !=
+	      !(inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL)))) {
 		if (!capable(CAP_LINUX_IMMUTABLE))
 			goto out;
 	} else if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/partcheck.c m68k/fs/partcheck.c
--- jes-2.1.108/fs/partcheck.c	Thu Jan  1 01:00:00 1970
+++ m68k/fs/partcheck.c	Sun Jul 12 23:50:29 1998
@@ -0,0 +1,431 @@
+/*
+ *  Code extracted from drivers/block/genhd.c
+ *  Copyright (C) 1991-1998  Linus Torvalds
+ *  Re-organised May 1998 Roman Hodek and Russell King
+ *
+ *  We now have independent partition support from the
+ *  block drivers, which allows all the partition code to
+ *  be grouped in one location, and it to be mostly self
+ *  contained.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/init.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif
+
+#include <asm/system.h>
+#include "partcheck.h"
+
+static struct partition_parser *partition_parsers = NULL;
+
+/*
+ * disk_name() is used by genhd.c and md.c.
+ * It formats the devicename of the indicated disk
+ * into the supplied buffer, and returns a pointer
+ * to that same buffer (for convenience).
+ */
+char *disk_name (struct gendisk *hd, int minor, char *buf)
+{
+	unsigned int part;
+	const char *maj = hd->major_name;
+	char unit = (minor >> hd->minor_shift) + 'a';
+
+	/*
+	 * IDE devices use multiple major numbers, but the drives
+	 * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
+	 * This requires special handling here.
+	 */
+	switch (hd->major) {
+		case IDE3_MAJOR:
+			unit += 2;
+		case IDE2_MAJOR:
+			unit += 2;
+		case IDE1_MAJOR:
+			unit += 2;
+		case IDE0_MAJOR:
+			maj = "hd";
+	}
+	part = minor & ((1 << hd->minor_shift) - 1);
+	if (part)
+		sprintf(buf, "%s%c%d", maj, unit, part);
+	else
+		sprintf(buf, "%s%c", maj, unit);
+	return buf;
+}
+
+void add_partition (struct gendisk *hd, int minor, int start, int size)
+{
+	char buf[8];
+	hd->part[minor].start_sect = start;
+	hd->part[minor].nr_sects   = size;
+	printk(" %s", disk_name(hd, minor, buf));
+}
+
+unsigned int get_ptable_blocksize(kdev_t dev)
+{
+  int ret = 1024;
+
+  /*
+   * See whether the low-level driver has given us a minumum blocksize.
+   * If so, check to see whether it is larger than the default of 1024.
+   */
+  if (!blksize_size[MAJOR(dev)])
+    {
+      return ret;
+    }
+
+  /*
+   * Check for certain special power of two sizes that we allow.
+   * With anything larger than 1024, we must force the blocksize up to
+   * the natural blocksize for the device so that we don't have to try
+   * and read partial sectors.  Anything smaller should be just fine.
+   */
+  switch( blksize_size[MAJOR(dev)][MINOR(dev)] )
+    {
+    case 2048:
+      ret = 2048;
+      break;
+    case 4096:
+      ret = 4096;
+      break;
+    case 8192:
+      ret = 8192;
+      break;
+    case 1024:
+    case 512:
+    case 256:
+    case 0:
+      /*
+       * These are all OK.
+       */
+      break;
+    default:
+      panic("Strange blocksize for partition table\n");
+    }
+
+  return ret;
+
+}
+
+
+#if CONFIG_KMOD && CONFIG_FOREIGN_PARTITIONS
+
+#include <linux/kmod.h>
+
+#ifdef CONFIG_AMIGA_PARTITION_MODULE
+#include <linux/affs_hardblocks.h>
+static int probe_amiga_partition(struct gendisk *hd, kdev_t dev,
+				 struct buffer_head *bh_0)
+{
+	struct buffer_head *bh;
+	int blk, res;
+
+	if (*(u32 *)bh_0->b_data == cpu_to_be32(IDNAME_RIGIDDISK))
+		return 1;
+
+	/* also need to check other possible RDB blocks */
+	for (blk = 1; blk < RDB_ALLOCATION_LIMIT; blk++) {
+		if (!(bh = bread(dev,blk,512)))
+			return -1;
+		res = *(u32 *)bh->b_data == cpu_to_be32(IDNAME_RIGIDDISK);
+		brelse(bh);
+		if (res)
+			return 1;
+	}
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_ATARI_PARTITION_MODULE
+#include <linux/atari_rootsec.h>
+#include <linux/ctype.h>
+#define	VALID_PARTITION(pi,hdsiz)					     \
+    (((pi)->flg & 1) &&							     \
+     isalnum((pi)->id[0]) && isalnum((pi)->id[1]) && isalnum((pi)->id[2]) && \
+     be32_to_cpu((pi)->st) <= (hdsiz) &&				     \
+     be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz))
+static int probe_atari_partition(struct gendisk *hd, kdev_t dev,
+				 struct buffer_head *bh_0)
+{
+	struct rootsector *rs;
+	u32 hd_size;
+	int res;
+
+	rs = (struct rootsector *)bh_0->b_data;
+	hd_size = hd->part[0].nr_sects;
+	res = VALID_PARTITION( &rs->part[0], hd_size ) ||
+	      VALID_PARTITION( &rs->part[1], hd_size ) ||
+	      VALID_PARTITION( &rs->part[2], hd_size ) ||
+	      VALID_PARTITION( &rs->part[3], hd_size );
+	return res;
+}
+#endif
+
+#ifdef CONFIG_ACORN_PARTITION_MODULE
+# ifdef CONFIG_ACORN_PARTITION_ICS
+static int probe_acorn_ICS_partition(struct gendisk *hd, kdev_t dev,
+				     struct buffer_head *bh_0)
+{
+	unsigned long sum;
+	unsigned int i;
+
+	for (i = 0, sum = 0x50617274; i < 508; i++)
+	    sum += bh_0->b_data[i];
+	return sum == le32_to_cpu(*(unsigned long *)(&bh_0->b_data[508]));
+}
+# endif
+# ifdef CONFIG_ACORN_PARTITION_ADFS
+#include <linux/adfs_fs.h>
+static int probe_acorn_ADFS_partition(struct gendisk *hd, kdev_t dev,
+				      struct buffer_head *bh_0)
+{
+	struct buffer_head *bh;
+	int res;
+
+	if (!(bh = bread(dev, 3, 1024)))
+		return -1;
+	res = adfs_checkbblk(bh->b_data) == 0;
+	brelse(bh);
+	return res;
+}
+# endif
+#endif
+
+
+/*
+ * This table lists the magics to recognize the partition formats that are
+ * availble as modules. The magics can be stored as 16 or 32 bit little-endian
+ * or big-endian numbers. For the more complicated cases (Amiga and Atari), a
+ * function doing the real work is called.
+ */
+
+enum partbl_probe_type { BE16, BE32, LE16, LE32, FUNC };
+
+static struct partbl_probe {
+	char *name;
+	enum partbl_probe_type type;
+	u32 offset;
+	u32 magic;
+	int (*func)(struct gendisk *hd, kdev_t dev, struct buffer_head *bh_0);
+} partbl_modules[] = {
+#ifdef CONFIG_MSDOS_PARTITION_MODULE
+	{ "pc", LE16, 510, 0xAA55, NULL },
+#endif
+#ifdef CONFIG_OSF_PARTITION_MODULE
+	{ "osf",   LE32,  64, 0x82564557, NULL },
+#endif
+#ifdef CONFIG_SUN_PARTITION_MODULE
+	{ "sun",   BE16, 508, 0xDABE, NULL },
+#endif
+#ifdef CONFIG_AMIGA_PARTITION_MODULE
+	{ "amiga", FUNC,   0,      0, probe_amiga_partition },
+#endif
+#ifdef CONFIG_ATARI_PARTITION_MODULE
+	{ "atari", FUNC,   0,      0, probe_atari_partition },
+#endif
+#ifdef CONFIG_MAC_PARTITION_MODULE
+	{ "mac",   BE16,   0, 0x4552, NULL },
+#endif
+#ifdef CONFIG_ACORN_PARTITION_MODULE
+# ifdef CONFIG_ACORN_PARTITION_ICS
+	{ "acorn", FUNC,   0,      0, probe_acorn_ICS_partition },
+# endif
+# ifdef CONFIG_ACORN_PARTITION_ADFS
+	{ "acorn", FUNC,   0,      0, probe_acorn_ADFS_partition },
+# endif
+#endif
+};
+
+#define N_PARTBL_MODULES sizeof(partbl_modules)/sizeof(*partbl_modules)
+
+/*
+ * Try to load all partition parsers that could apply to this device
+ */
+static int try_to_load_parser(struct gendisk *hd, kdev_t dev)
+{
+	int i, hit = 0, loaded = 0;
+	char modname[24];
+	struct partbl_probe *mod;
+	struct partition_parser *p;
+	struct buffer_head *bh;
+
+	if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
+		return -1;
+
+	for( i = 0, mod = partbl_modules; i < N_PARTBL_MODULES; ++i, ++mod ) {
+		/* don't probe already loaded formats again */
+		for( p = partition_parsers; p; p = p->next )
+			if (!strcmp( mod->name, p->name))
+				goto skip;
+		
+		switch( mod->type ) {
+		    case LE16:
+			hit = le16_to_cpu(*(u16 *)(bh->b_data+mod->offset)) ==
+			      mod->magic;
+			break;
+		    case LE32:
+			hit = le32_to_cpu(*(u32 *)(bh->b_data+mod->offset)) ==
+			      mod->magic;
+			break;
+		    case BE16:
+			hit = be16_to_cpu(*(u16 *)(bh->b_data+mod->offset)) ==
+			      mod->magic;
+			break;
+		    case BE32:
+			hit = be32_to_cpu(*(u32 *)(bh->b_data+mod->offset)) ==
+			      mod->magic;
+			break;
+		    case FUNC:
+			hit = mod->func(hd, dev, bh) > 0;
+			break;
+		}
+		if (hit) {
+			strcpy(modname, "part-format-");
+			strcat(modname, mod->name);
+			request_module(modname);
+			++loaded;
+		}
+	    skip:
+	}
+	brelse(bh);
+	return loaded;
+}
+
+#endif /* CONFIG_KMOD && CONFIG_FOREIGN_PARTITIONS */
+
+
+void check_partition(struct gendisk *hd, kdev_t dev, int first_minor)
+{
+	static int first_time = 1;
+	int tries = 0;
+	unsigned long first_sector;
+	char buf[8];
+	struct partition_parser *parser;
+
+	if (first_time)
+		printk("Partition check:\n");
+	first_time = 0;
+	first_sector = hd->part[MINOR(dev)].start_sect;
+
+	/*
+	 * This is a kludge to allow the partition check to be
+	 * skipped for specific drives (e.g. IDE cd-rom drives)
+	 */
+	if ((int)first_sector == -1) {
+		hd->part[MINOR(dev)].start_sect = 0;
+		return;
+	}
+
+#if CONFIG_KMOD && CONFIG_FOREIGN_PARTITIONS
+    retry:
+#endif
+	printk(" %s:", disk_name(hd, MINOR(dev), buf));
+	for( parser = partition_parsers; parser; parser = parser->next ) {
+		if (parser->func(hd, dev, first_sector, first_minor))
+			return;
+	}
+	++tries;
+#if CONFIG_KMOD && CONFIG_FOREIGN_PARTITIONS
+	if (tries == 1 && try_to_load_parser(hd, dev))
+		goto retry;
+#endif
+	printk(" unknown partition table\n");
+}
+
+int register_partbl( struct partition_parser *parser )
+{
+	struct partition_parser **p;
+    
+	if (!parser)
+		return -EINVAL;
+	if (parser->next)
+		return -EBUSY;
+	for( p = &partition_parsers; *p; p = &(*p)->next )
+		if (*p == parser)
+			return -EBUSY;
+
+	/* Insert new parser at front of list, so that a user-loaded module can
+	 * (in case of some misdetection) override other parsers */
+	parser->next = partition_parsers;
+	partition_parsers = parser;
+	return 0;
+}
+
+#ifdef CONFIG_MODULES
+int unregister_partbl( struct partition_parser *parser )
+{
+	struct partition_parser **p;
+    
+	for( p = &partition_parsers; *p; p = &(*p)->next ) {
+		if (*p == parser) {
+			*p = parser->next;
+			parser->next = NULL;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+#endif
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_partbl;
+
+static int partbl_read_proc(char *buf, char **start, off_t offset,
+			    int len, int *eof, void *private)
+{
+	struct partition_parser *p;
+
+	len = 0;
+	for( p = partition_parsers; p && len < 4000; p = p->next )
+		len += sprintf(buf + len, "%s\n", p->name );
+	*start = buf + offset;
+	return len > offset ? len - offset : 0;
+}
+#endif
+
+__initfunc(void partbl_init( void ))
+{
+	extern void msdos_partbl_init(void);
+	extern void osf_partbl_init(void);
+	extern void sun_partbl_init(void);
+	extern void amiga_partbl_init(void);
+	extern void atari_partbl_init(void);
+	extern void mac_partbl_init(void);
+	extern void acorn_partbl_init(void);
+    
+	if (HAVE_ACORN_PARTITION)
+		acorn_partbl_init();
+	if (HAVE_MAC_PARTITION)
+		mac_partbl_init();
+	if (HAVE_ATARI_PARTITION)
+		atari_partbl_init();
+	if (HAVE_AMIGA_PARTITION)
+		amiga_partbl_init();
+	if (HAVE_SUN_PARTITION)
+		sun_partbl_init();
+	if (HAVE_OSF_PARTITION)
+		osf_partbl_init();
+	if (HAVE_MSDOS_PARTITION)
+		msdos_partbl_init();
+
+#ifdef CONFIG_PROC_FS
+	proc_partbl = create_proc_entry("partition-formats", 0, 0);
+	if (proc_partbl)
+		proc_partbl->read_proc = partbl_read_proc;
+#endif
+}
+
+/* symbols visible for modules */
+EXPORT_SYMBOL(add_partition);
+EXPORT_SYMBOL(get_ptable_blocksize);
+EXPORT_SYMBOL(register_partbl);
+EXPORT_SYMBOL(unregister_partbl);
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/partcheck.h m68k/fs/partcheck.h
--- jes-2.1.108/fs/partcheck.h	Thu Jan  1 01:00:00 1970
+++ m68k/fs/partcheck.h	Sun Jul 12 23:44:13 1998
@@ -0,0 +1,26 @@
+#ifndef _FS_PARTCHECK_H
+#define _FS_PARTCHECK_H
+
+#include <linux/genhd.h>
+
+/*
+ * disk_name() is used by genhd.c and md.c.
+ * It formats the devicename of the indicated disk
+ * into the supplied buffer, and returns a pointer
+ * to that same buffer (for convenience).
+ */
+char *disk_name (struct gendisk *hd, int minor, char *buf);
+void add_partition (struct gendisk *hd, int minor, int start, int size);
+unsigned int get_ptable_blocksize(kdev_t dev);
+
+struct partition_parser {
+	struct partition_parser *next;
+	char *name;
+	int (*func)(struct gendisk *hd, kdev_t dev,
+		    unsigned long first_sector, int first_minor);
+};
+
+int register_partbl( struct partition_parser *parser );
+int unregister_partbl( struct partition_parser *parser );
+
+#endif /* _FS_PARTCHECK_H */
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/partitions/Config.in m68k/fs/partitions/Config.in
--- jes-2.1.108/fs/partitions/Config.in	Thu Jan  1 01:00:00 1970
+++ m68k/fs/partitions/Config.in	Sun Jun 14 22:23:53 1998
@@ -0,0 +1,88 @@
+#
+# Partition configuration
+#
+mainmenu_option next_comment
+comment 'Partition Tables'
+
+if [ "$ARCH" = "i386" ]; then
+  define_bool CONFIG_MSDOS_PARTITION y
+fi
+if [ "$ARCH" = "alpha" ]; then
+  define_bool CONFIG_OSF_PARTITION y
+fi
+if [ "$ARCH" = "m68k" ]; then
+  if [ "$CONFIG_AMIGA" = "y" ]; then
+    define_bool CONFIG_AMIGA_PARTITION y
+  fi
+  if [ "$CONFIG_ATARI" = "y" ]; then
+    define_bool CONFIG_ATARI_PARTITION y
+  fi
+  if [ "$CONFIG_MAC" = "y" ]; then
+    define_bool CONFIG_MAC_PARTITION y
+  fi
+fi
+if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
+  define_bool CONFIG_SUN_PARTITION y
+fi
+if [ "$ARCH" = "ppc" ]; then
+  if [ "$CONFIG_MACH_SPECIFIC" = "y" ]; then
+    if [ "$CONFIG_PMAC" = "y" -o "$CONFIG_CHRP" = "y" ]; then
+      define_bool CONFIG_MAC_PARTITION y
+    fi
+    if [ "$CONFIG_PREP" = "y" -o "$CONFIG_CHRP" = "y" ]; then
+      define_bool CONFIG_MSDOS_PARTITION y
+    fi
+  else
+    define_bool CONFIG_MAC_PARTITION y
+    define_bool CONFIG_MSDOS_PARTITION y
+  fi
+fi
+if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
+  define_bool CONFIG_ACORN_PARTITION y
+fi
+
+bool 'Support for foreign partition tables' CONFIG_FOREIGN_PARTITIONS
+if [ "$CONFIG_FOREIGN_PARTITIONS" = "y" ]; then
+  if [ ! \( "$ARCH" = "i386" -o \
+            \( "$ARCH" = "ppc" -a \
+               \( "$CONFIG_MACH_SPECIFIC" = "n" -o "$CONFIG_PREP" = "y" -o \
+                  "$CONFIG_CHRP" = "y" \) \) \) ]; then
+  	tristate 'MS-DOS partition support' CONFIG_MSDOS_PARTITION
+  fi
+  if [ "$ARCH" != "alpha" ]; then
+  	tristate 'OSF partition support' CONFIG_OSF_PARTITION
+  fi
+  if [ "$ARCH" != "sparc" -a "$ARCH" != "sparc64" ]; then
+  	tristate 'Sun partition support' CONFIG_SUN_PARTITION
+  fi
+  if [ "$CONFIG_AMIGA" != "y" ]; then
+  	tristate 'Amiga RDB partition support' CONFIG_AMIGA_PARTITION
+  fi
+  if [ "$CONFIG_ATARI" != "y" ]; then
+  	tristate 'Atari partition support' CONFIG_ATARI_PARTITION
+  fi
+  if [ ! \( \( "$ARCH" = "m68k" -a "$CONFIG_MAC" = "y" \) -o \
+            \( "$ARCH" = "ppc" -a \
+               \( "$CONFIG_MACH_SPECIFIC" = "n" -o "$CONFIG_PMAC" = "y" -o \
+                  "$CONFIG_CHRP" = "y" \) \) \) ]; then
+  	tristate 'Mac partition support' CONFIG_MAC_PARTITION
+  fi
+  if [ "$CONFIG_ARCH_ACORN" != "y" ]; then
+    tristate 'Acorn partition support' CONFIG_ACORN_PARTITION
+  fi
+fi
+
+if [ "$CONFIG_MSDOS_PARTITION" != "n" ]; then
+  bool 'BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
+  bool 'Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
+fi
+
+if [ "$CONFIG_ACORN_PARTITION" != "n" ]; then
+  bool 'Acorn native filecore partition support' CONFIG_ACORN_PARTITION_ADFS
+#  bool 'Acorn Cumana partition support' CONFIG_ACORN_PARTITION_CUMANA
+  bool 'Acorn ICS partition support' CONFIG_ACORN_PARTITION_ICS
+#  bool 'Acorn PowerTec partition support' CONFIG_ACORN_PARTITION_POWERTEC
+  bool 'Acorn RISCiX partition support' CONFIG_ACORN_PARTITION_RISCIX
+fi
+
+endmenu
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/partitions/Makefile m68k/fs/partitions/Makefile
--- jes-2.1.108/fs/partitions/Makefile	Thu Jan  1 01:00:00 1970
+++ m68k/fs/partitions/Makefile	Sun Jun 14 22:23:53 1998
@@ -0,0 +1,72 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+O_TARGET := partitions.o
+O_OBJS   := 
+M_OBJS   := 
+
+MOD_LIST_NAME := PARTBL_MODULES
+
+ifeq ($(CONFIG_MSDOS_PARTITION),y)
+  O_OBJS += pc.o
+else
+  ifeq ($(CONFIG_MSDOS_PARTITION),m)
+    M_OBJS += pc.o
+  endif
+endif
+
+ifeq ($(CONFIG_OSF_PARTITION),y)
+  O_OBJS += osf.o
+else
+  ifeq ($(CONFIG_OSF_PARTITION),m)
+    M_OBJS += osf.o
+  endif
+endif
+
+ifeq ($(CONFIG_SUN_PARTITION),y)
+  O_OBJS += sun.o
+else
+  ifeq ($(CONFIG_SUN_PARTITION),m)
+    M_OBJS += sun.o
+  endif
+endif
+
+ifeq ($(CONFIG_AMIGA_PARTITION),y)
+  O_OBJS += amiga.o
+else
+  ifeq ($(CONFIG_AMIGA_PARTITION),m)
+    M_OBJS += amiga.o
+  endif
+endif
+
+ifeq ($(CONFIG_ATARI_PARTITION),y)
+  O_OBJS += atari.o
+else
+  ifeq ($(CONFIG_ATARI_PARTITION),m)
+    M_OBJS += atari.o
+  endif
+endif
+
+ifeq ($(CONFIG_MAC_PARTITION),y)
+  O_OBJS += mac.o
+else
+  ifeq ($(CONFIG_MAC_PARTITION),m)
+    M_OBJS += mac.o
+  endif
+endif
+
+ifeq ($(CONFIG_ACORN_PARTITION),y)
+  O_OBJS += acorn.o
+else
+  ifeq ($(CONFIG_ACORN_PARTITION),m)
+    M_OBJS += acorn.o
+  endif
+endif
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/partitions/acorn.c m68k/fs/partitions/acorn.c
--- jes-2.1.108/fs/partitions/acorn.c	Thu Jan  1 01:00:00 1970
+++ m68k/fs/partitions/acorn.c	Sun Jul 12 23:44:48 1998
@@ -0,0 +1,447 @@
+/*
+ * fs/partitions/acorn.c
+ *
+ * Copyright (c) 1996,1997 Russell King.
+ *
+ * Scan ADFS partitions on hard disk drives.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+
+#include "acorn.h"
+#include "../partcheck.h"
+
+static void adfspart_setgeometry (kdev_t dev, unsigned int secspertrack, unsigned int heads, unsigned long totalblocks)
+{
+	extern void hd_set_geometry (kdev_t dev, unsigned char, unsigned char, unsigned long, unsigned int);
+	extern void xd_set_geometry (kdev_t dev, unsigned char, unsigned char, unsigned long, unsigned int);
+
+	switch (MAJOR(dev)) {
+#ifdef CONFIG_BLK_DEV_HD
+	/*
+	 * It would actually look like the HD driver doesn't actually need this,
+	 * since it asks the drive about its the geometry...  However, the 'BIOS'
+	 * information is not updated...
+	 */
+	case HD_MAJOR:
+		hd_set_geometry (dev, secspertrack, heads, totalblocks, 1);
+		break;
+#endif
+#ifdef CONFIG_BLK_DEV_IDE
+#ifndef CONFIG_BLK_DEV_HD
+	case IDE0_MAJOR:
+#endif
+	case IDE1_MAJOR:
+	case IDE2_MAJOR:
+	case IDE3_MAJOR:
+		break;
+#endif
+#ifdef CONFIG_BLK_DEV_XD
+	case XT_DISK_MAJOR:
+		xd_set_geometry (dev, secspertrack, heads, totalblocks, 1);
+		break;
+#endif
+	case SCSI_DISK_MAJOR:
+		/* we don't need to set geometry for SCSI disks */
+		break;
+
+	default:
+		printk ("%s: don't know how to set geometry\n", kdevname (dev));
+		break;
+    }
+}
+
+#define LINUX_NATIVE_MAGIC 0xdeafa1de
+#define LINUX_SWAP_MAGIC   0xdeafab1e
+
+struct linux_part {
+	unsigned long magic;
+	unsigned long start_sect;
+	unsigned long nr_sects;
+};
+
+static struct disc_record *adfs_partition (struct gendisk *hd, char *name, char *data,
+					   unsigned long first_sector, unsigned int minor)
+{
+	struct disc_record *dr;
+	unsigned int nr_sects;
+
+	if (adfs_checkbblk (data))
+		return NULL;
+
+	dr = (struct disc_record *)(data + 0x1c0);
+
+	if (dr->disc_size == 0 && dr->disc_size_high == 0)
+		return NULL;
+
+	nr_sects = (le32_to_cpu(dr->disc_size_high) << 23) |
+		   (le32_to_cpu(dr->disc_size) >> 9);
+
+	if (name)
+		printk (" [%s]", name);
+	add_partition (hd, minor, first_sector, nr_sects);
+	return dr;
+}
+
+#ifdef CONFIG_ACORN_PARTITION_RISCIX
+static int riscix_partition (struct gendisk *hd, kdev_t dev, unsigned long first_sect,
+			     unsigned int minor, unsigned long nr_sects)
+{
+	struct buffer_head *bh;
+	struct riscix_record *rr;
+	unsigned int riscix_minor;
+
+	printk (" [RISCiX]");
+
+	add_partition (hd, riscix_minor = minor++, first_sect, nr_sects);
+	hd->sizes[riscix_minor] = hd->part[riscix_minor].nr_sects >> (BLOCK_SIZE_BITS - 9);
+	dev = MKDEV(hd->major, riscix_minor);
+
+	if (!(bh = bread (dev, 0, 1024)))
+		return -1;
+
+	rr = (struct riscix_record *)bh->b_data;
+	if (rr->magic == cpu_to_le32(RISCIX_MAGIC)) {
+		int part;
+
+		printk (" <");
+
+		for (part = 0; part < 8; part++) {
+			if (rr->part[part].one &&
+			    memcmp (rr->part[part].name, "All\0", 4)) {
+				add_partition (hd, minor++,
+						le32_to_cpu(rr->part[part].start),
+						le32_to_cpu(rr->part[part].length));
+				printk ("(%s)", rr->part[part].name);
+			}
+		}
+
+		printk (" >");
+
+		if (hd->part[riscix_minor].nr_sects > 2)
+			hd->part[riscix_minor].nr_sects = 2;
+	}
+
+	brelse (bh);
+	return minor;
+}
+#endif
+
+static int linux_partition (struct gendisk *hd, kdev_t dev, unsigned long first_sect,
+			    unsigned int minor, unsigned long nr_sects)
+{
+	struct buffer_head *bh;
+	struct linux_part *linuxp;
+	unsigned int linux_minor, mask = (1 << hd->minor_shift) - 1;
+
+	printk (" [Linux]");
+
+	add_partition (hd, linux_minor = minor++, first_sect, nr_sects);
+	hd->sizes[linux_minor] = hd->part[linux_minor].nr_sects >> (BLOCK_SIZE_BITS - 9);
+	dev = MKDEV(hd->major, linux_minor);
+
+	if (!(bh = bread (dev, 0, 1024)))
+		return -1;
+
+	linuxp = (struct linux_part *)bh->b_data;
+	printk (" <");
+	while (linuxp->magic == cpu_to_le32(LINUX_NATIVE_MAGIC) ||
+	       linuxp->magic == cpu_to_le32(LINUX_SWAP_MAGIC)) {
+		if (!(minor & mask))
+			break;
+		add_partition (hd, minor++,
+			       first_sect + le32_to_cpu(linuxp->start_sect),
+			       le32_to_cpu(linuxp->nr_sects));
+		linuxp ++;
+	}
+	printk (" >");
+	/*
+	 * Prevent someone doing a mkswap or mkfs on this partition
+	 */
+	if(hd->part[linux_minor].nr_sects > 2)
+		hd->part[linux_minor].nr_sects = 2;
+
+	brelse(bh);
+	return minor;
+}
+
+#ifdef CONFIG_ACORN_PARTITION_CUMANA
+static int adfspart_check_CUMANA (struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+				  unsigned int minor)
+{
+	unsigned int start_blk = 0, mask = (1 << hd->minor_shift) - 1;
+	struct buffer_head *bh = NULL;
+	char *name = "CUMANA/ADFS";
+	int first = 1;
+
+	/*
+	 * Try Cumana style partitions - sector 3 contains ADFS boot block with pointer
+	 * to next 'drive'.
+	 *
+	 * There are unknowns in this code - is the 'cylinder number' of the next
+	 * partition relative to the start of this one - I'm assuming it is.
+	 *
+	 * Also, which ID did Cumana use?
+	 *
+	 * This is totally unfinished, and will require more work to get it going.
+	 * Hence it is totally untested.
+	 */
+	do {
+		struct disc_record *dr;
+		unsigned int nr_sects;
+
+		if (!(minor & mask))
+			break;
+
+		if (!(bh = bread (dev, start_blk + 3, 1024)))
+			return -1;
+
+		dr = adfs_partition (hd, name, bh->b_data, first_sector, minor++);
+		if (!dr)
+			break;
+		name = NULL;
+
+		nr_sects = (bh->b_data[0x1fd] + (bh->b_data[0x1fe] << 8)) *
+			 (dr->heads + (dr->lowsector & 0x40 ? 1 : 0)) * dr->secspertrack;
+
+		if (!nr_sects)
+			break;
+
+		first = 0;
+		first_sector += nr_sects;
+		start_blk += nr_sects >> (BLOCK_SIZE_BITS - 9);
+		nr_sects = 0; /* hmm - should be partition size */
+
+		switch (bh->b_data[0x1fc] & 15) {
+		case 0: /* No partition / ADFS? */
+			break;
+
+#ifdef CONFIG_ACORN_PARTITION_RISCIX
+		case PARTITION_RISCIX_SCSI: /* RiscIX - we don't know how to find the next one. */
+			minor = riscix_partition (hd, dev, first_sector, minor, nr_sects);
+			break;
+#endif
+
+		case PARTITION_LINUX:
+			minor = linux_partition (hd, dev, first_sector, minor, nr_sects);
+			break;
+		}
+		brelse (bh);
+		bh = NULL;
+		if (minor == -1)
+			return minor;
+	} while (1);
+	if (bh)
+		brelse (bh);
+	return first ? 0 : 1;
+}
+#endif
+
+#ifdef CONFIG_ACORN_PARTITION_ADFS
+/*
+ * Purpose: allocate ADFS partitions.
+ *
+ * Params : hd		- pointer to gendisk structure to store partition info.
+ *	    dev		- device number to access.
+ *	    first_sector- first readable sector on the device.
+ *	    minor	- first available minor on device.
+ *
+ * Returns: -1 on error, 0 for no ADFS boot sector, 1 for ok.
+ *
+ * Alloc  : hda  = whole drive
+ *	    hda1 = ADFS partition on first drive.
+ *	    hda2 = non-ADFS partition.
+ */
+static int adfspart_check_ADFS (struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+				unsigned int minor)
+{
+	unsigned long start_sect, nr_sects, sectscyl, heads;
+	struct buffer_head *bh;
+	struct disc_record *dr;
+
+	if (!(bh = bread (dev, 3, 1024)))
+		return -1;
+
+	dr = adfs_partition (hd, "ADFS", bh->b_data, first_sector, minor++);
+	if (!dr) {
+	    	brelse (bh);
+    		return 0;
+	}
+
+	heads = dr->heads + ((dr->lowsector >> 6) & 1);
+	adfspart_setgeometry (dev, dr->secspertrack, heads, hd->part[MINOR(dev)].nr_sects);
+	sectscyl = dr->secspertrack * heads;
+
+	/*
+	 * Work out start of non-adfs partition.
+	 */
+	start_sect = ((bh->b_data[0x1fe] << 8) + bh->b_data[0x1fd]) * sectscyl;
+	nr_sects = hd->part[MINOR(dev)].nr_sects - start_sect;
+
+	if (start_sect) {
+		first_sector += start_sect;
+		/*
+		 * we now have a problem - how to set the origional disk size if the
+		 * disk doesn't report it, since there is no standard way of getting
+		 * that info.
+		 */
+		switch (bh->b_data[0x1fc] & 15) {
+#ifdef CONFIG_ACORN_PARTITION_RISCIX
+		case PARTITION_RISCIX_SCSI:
+		case PARTITION_RISCIX_MFM:
+			minor = riscix_partition (hd, dev, first_sector, minor, nr_sects);
+			break;
+#endif
+
+		case PARTITION_LINUX:
+			minor = linux_partition (hd, dev, first_sector, minor, nr_sects);
+			break;
+		}
+	}
+	brelse(bh);
+	return 1;
+}
+#endif
+
+#ifdef CONFIG_ACORN_PARTITION_ICS
+static int adfspart_check_ICSLinux (kdev_t dev, unsigned long block)
+{
+	struct buffer_head *bh;
+	int result = 0;
+
+	if ((bh = bread (dev, block >> 1, 1024)) != NULL) {
+		if (memcmp (bh->b_data + ((block & 1) ? 512 : 0),
+			    "LinuxPart", 9) == 0)
+			result = 1;
+
+		brelse (bh);
+	}
+
+	return result;
+}
+
+/*
+ * Purpose: allocate ICS partitions.
+ * Params : hd		- pointer to gendisk structure to store partition info.
+ *	    dev		- device number to access.
+ *	    first_sector- first readable sector on the device.
+ *	    minor	- first available minor on device.
+ * Returns: -1 on error, 0 for no ICS table, 1 for partitions ok.
+ * Alloc  : hda  = whole drive
+ *	    hda1 = ADFS partition 0 on first drive.
+ *	    hda2 = ADFS partition 1 on first drive.
+ *		..etc..
+ */
+static int adfspart_check_ICS (struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+			       unsigned int minor)
+{
+	struct buffer_head *bh;
+	unsigned long sum;
+	unsigned int i, mask = (1 << hd->minor_shift) - 1;
+	struct ics_part { unsigned long start; unsigned long size; } *p;
+
+	/*
+	 * Try ICS style partitions - sector 0 contains partition info.
+	 */
+	if (!(bh = bread (dev, 0, 1024)))
+	    	return -1;
+
+	/*
+	 * check for a valid checksum
+	 */
+	for (i = 0, sum = 0x50617274; i < 508; i++)
+		sum += bh->b_data[i];
+
+	if (sum != le32_to_cpu(*(unsigned long *)(&bh->b_data[508]))) {
+	    	brelse (bh);
+		return 0; /* not ICS partition table */
+	}
+
+	printk (" [ICS]");
+
+	for (p = (struct ics_part *)bh->b_data; p->size; p++) {
+		if ((minor & mask) == 0)
+			break;
+
+		if (p->size < 0 && adfspart_check_ICSLinux (dev, p->start)) {
+			/*
+			 * We use the first sector to identify what type
+			 * this partition is...
+			 */
+			if (p->size > 1)
+				add_partition (hd, minor, first_sector + p->start + 1, p->size - 1);
+		} else
+			add_partition (hd, minor, first_sector + p->start, p->size);
+		minor++;
+	}
+	brelse (bh);
+
+	return 1;
+}
+#endif
+
+/*
+ * Purpose: initialise all the partitions on an ADFS drive.
+ *          These may be other ADFS partitions or a Linux/RiscBSD/RiscIX
+ *	    partition.
+ *
+ * Params : hd		 - pointer to gendisk structure to store devices partitions.
+ *          dev		 - device number to access
+ *	    first_sector - first available sector on the disk.
+ *	    minor	 - first available minor on this device.
+ *
+ * Returns: -1 on error, 0 if not ADFS format, 1 if ok.
+ */
+int acorn_partition(struct gendisk *hd, kdev_t dev,
+		    unsigned long first_sector, int first_part_minor)
+{
+	int r = 0;
+
+	MOD_INC_USE_COUNT;
+#ifdef CONFIG_ACORN_PARTITION_ICS
+	if (r == 0)
+		r = adfspart_check_ICS (hd, dev, first_sector, first_part_minor);
+#endif
+#if 0
+#ifdef CONFIG_ACORN_PARTITION_CUMANA
+	if (r == 0)    
+		r = adfspart_check_CUMANA (hd, dev, first_sector, first_part_minor);
+#endif
+#endif
+#ifdef CONFIG_ACORN_PARTITION_ADFS
+	if (r == 0)
+		r = adfspart_check_ADFS (hd, dev, first_sector, first_part_minor);
+#endif
+	if (r < 0)
+		printk (" unable to read boot sectors / partition sectors\n");
+	else if (r)
+		printk ("\n");
+	MOD_DEC_USE_COUNT;
+	return r;
+}
+
+static struct partition_parser acorn_partition_parser =
+    { NULL, "acorn", acorn_partition };
+
+#ifndef MODULE
+__initfunc(void acorn_partbl_init( void ))
+{
+	(void)register_partbl( &acorn_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &acorn_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &acorn_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/partitions/acorn.h m68k/fs/partitions/acorn.h
--- jes-2.1.108/fs/partitions/acorn.h	Thu Jan  1 01:00:00 1970
+++ m68k/fs/partitions/acorn.h	Sun Jul 12 23:44:48 1998
@@ -0,0 +1,68 @@
+/*
+ * fs/partitions/acorn.h
+ *
+ * Copyright (C) 1996-1998 Russell King
+ */
+#include <linux/adfs_fs.h>
+
+/*
+ * Offset in bytes of the boot block on the disk.
+ */
+#define BOOT_SECTOR_ADDRESS 0xc00
+
+/*
+ * Disc record size
+ */
+#define RECSIZE 60
+
+/*
+ * Disc record
+ */
+struct disc_record {
+	unsigned char  log2secsize;
+	unsigned char  secspertrack;
+	unsigned char  heads;
+	unsigned char  density;
+	unsigned char  idlen;
+	unsigned char  log2bpmb;
+	unsigned char  skew;
+	unsigned char  bootoption;
+	unsigned char  lowsector;
+	unsigned char  nzones;
+	unsigned short zone_spare;
+	unsigned long  root;
+	unsigned long  disc_size;
+	unsigned short disc_id;
+	unsigned char  disc_name[10];
+	unsigned long  disc_type;
+	unsigned long  disc_size_high;
+	unsigned char  log2sharesize:4;
+	unsigned char  unused:4;
+	unsigned char  big_flag:1;
+};
+
+/*
+ * Partition types. (Oh for reusability)
+ */
+#define PARTITION_RISCIX_MFM	1
+#define PARTITION_RISCIX_SCSI	2
+#define PARTITION_LINUX		9
+
+struct riscix_part {
+	unsigned long  start;
+	unsigned long  length;
+	unsigned long  one;
+	char name[16];
+};
+
+struct riscix_record {
+	unsigned long  magic;
+#define RISCIX_MAGIC	(0x4a657320)
+	unsigned long  date;
+	struct riscix_part part[8];
+};
+
+int
+acorn_partition(struct gendisk *hd, kdev_t dev,
+		unsigned long first_sector, int first_part_minor);
+
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/partitions/amiga.c m68k/fs/partitions/amiga.c
--- jes-2.1.108/fs/partitions/amiga.c	Thu Jan  1 01:00:00 1970
+++ m68k/fs/partitions/amiga.c	Sun Jul 12 23:44:48 1998
@@ -0,0 +1,122 @@
+/*
+ *  fs/partitions/amiga.c -- Amiga RDSK partition table parser
+ *
+ *  Code extracted from
+ *  linux/drivers/block/genhd.c
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/affs_hardblocks.h>
+#include <asm/byteorder.h>
+#include "../partcheck.h"
+
+static __inline__ u32
+checksum_block(u32 *m, int size)
+{
+	u32 sum = 0;
+
+	while (size--)
+		sum += be32_to_cpu(*m++);
+	return sum;
+}
+
+static int
+amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+		int current_minor)
+{
+	struct buffer_head	*bh;
+	struct RigidDiskBlock	*rdb;
+	struct PartitionBlock	*pb;
+	int			 start_sect;
+	int			 nr_sects;
+	int			 blk;
+	int			 part, res;
+
+	MOD_INC_USE_COUNT;
+	set_blocksize(dev,512);
+	res = 0;
+
+	for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
+		if(!(bh = bread(dev,blk,512))) {
+			printk("Dev %s: unable to read RDB block %d\n",
+			       kdevname(dev),blk);
+			res = -1;
+			goto rdb_done;
+		}
+		if (*(u32 *)bh->b_data == cpu_to_be32(IDNAME_RIGIDDISK)) {
+			rdb = (struct RigidDiskBlock *)bh->b_data;
+			if (checksum_block((u32 *)bh->b_data,be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
+				printk("Dev %s: RDB in block %d has bad checksum\n",
+				       kdevname(dev),blk);
+				brelse(bh);
+				continue;
+			}
+			printk(" RDSK");
+			blk = be32_to_cpu(rdb->rdb_PartitionList);
+			brelse(bh);
+			for (part = 1; blk > 0 && part <= 16; part++) {
+				if (!(bh = bread(dev,blk,512))) {
+					printk("Dev %s: unable to read partition block %d\n",
+						       kdevname(dev),blk);
+					res = -1;
+					goto rdb_done;
+				}
+				pb  = (struct PartitionBlock *)bh->b_data;
+				blk = be32_to_cpu(pb->pb_Next);
+				if (pb->pb_ID == cpu_to_be32(IDNAME_PARTITION) && checksum_block(
+				    (u32 *)pb,be32_to_cpu(pb->pb_SummedLongs) & 0x7F) == 0 ) {
+					
+					/* Tell Kernel about it */
+
+					if (!(nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
+							  be32_to_cpu(pb->pb_Environment[9])) *
+							 be32_to_cpu(pb->pb_Environment[3]) *
+							 be32_to_cpu(pb->pb_Environment[5]))) {
+						continue;
+					}
+					start_sect = be32_to_cpu(pb->pb_Environment[9]) *
+						     be32_to_cpu(pb->pb_Environment[3]) *
+						     be32_to_cpu(pb->pb_Environment[5]);
+					add_partition(hd,current_minor,start_sect,nr_sects);
+					current_minor++;
+					res = 1;
+				}
+				brelse(bh);
+			}
+			printk("\n");
+			break;
+		}
+	}
+
+rdb_done:
+	set_blocksize(dev,BLOCK_SIZE);
+	MOD_DEC_USE_COUNT;
+	return res;
+}
+
+static struct partition_parser amiga_partition_parser =
+    { NULL, "amiga", amiga_partition };
+
+#ifndef MODULE
+__initfunc(void amiga_partbl_init( void ))
+{
+	(void)register_partbl( &amiga_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &amiga_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &amiga_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/partitions/atari.c m68k/fs/partitions/atari.c
--- jes-2.1.108/fs/partitions/atari.c	Thu Jan  1 01:00:00 1970
+++ m68k/fs/partitions/atari.c	Sun Jul 12 23:44:48 1998
@@ -0,0 +1,192 @@
+/*
+ *  fs/partitions/atari.c -- Atari partition table parser
+ *
+ *  Code extracted from
+ *  linux/drivers/block/genhd.c
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/atari_rootsec.h>
+#include <asm/byteorder.h>
+#include "../partcheck.h"
+
+
+/* check if a partition entry looks valid -- Atari format is assumed if at
+ * least one of the primary entries is ok this way */
+#define	VALID_PARTITION(pi,hdsiz)					     \
+    (((pi)->flg & 1) &&							     \
+     isalnum((pi)->id[0]) && isalnum((pi)->id[1]) && isalnum((pi)->id[2]) && \
+     be32_to_cpu((pi)->st) <= (hdsiz) &&				     \
+     be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz))
+
+static int atari_partition (struct gendisk *hd, kdev_t dev,
+			    unsigned long first_sector, int current_minor)
+{
+  int minor = current_minor, m_lim = current_minor + hd->max_p;
+  int i;
+  struct buffer_head *bh;
+  struct rootsector *rs;
+  struct partition_info *pi;
+  u32 extensect;
+  u32 hd_size;
+  int bsize, bdiv;
+  int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
+
+  MOD_INC_USE_COUNT;
+  bsize = get_ptable_blocksize(dev);
+  bdiv  = bsize / 512;
+  bh = bread (dev, 0, bsize);
+  if (!bh)
+    {
+      printk (" unable to read block 0\n");
+      MOD_DEC_USE_COUNT;
+      return -1;
+    }
+
+  rs = (struct rootsector *) bh->b_data;
+  hd_size = hd->part[current_minor-1].nr_sects;
+  if (!VALID_PARTITION( &rs->part[0], hd_size ) &&
+      !VALID_PARTITION( &rs->part[1], hd_size ) &&
+      !VALID_PARTITION( &rs->part[2], hd_size ) &&
+      !VALID_PARTITION( &rs->part[3], hd_size )) {
+      /* if there's no valid primary partition, assume that no Atari format
+       * partition table (there's no reliable magic or the like :-() */
+      MOD_DEC_USE_COUNT;
+      return 0;
+  }
+
+  printk (" AHDI");
+  pi = &rs->part[0];
+  for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++)
+    {
+      if (pi->flg & 1)
+	/* active partition */
+	{
+	  if (memcmp (pi->id, "XGM", 3) == 0)
+	    /* extension partition */
+	    {
+	      struct rootsector *xrs;
+	      struct buffer_head *xbh;
+	      u32 partsect;
+
+	      part_fmt = 1;
+	      printk(" XGM<");
+	      partsect = extensect = be32_to_cpu(pi->st);
+	      while (1)
+		{
+		  xbh = bread (dev, partsect / bdiv, bsize);
+		  if (!xbh)
+		    {
+		      printk (" block %u read failed\n", partsect);
+		      brelse(bh);
+		      MOD_DEC_USE_COUNT;
+		      return -1;
+		    }
+		  xrs = (struct rootsector *) &xbh->b_data[(partsect%bdiv)*512];
+
+		  /* ++roman: valid bit must be set in one of the first 3
+		   * slots */
+		  for( i = 0; i < 3; ++i )
+		      if (xrs->part[0].flg & 1)
+			  break;
+		  if (i == 3) {
+		    printk( "\nNo valid subpartition in extended "
+			    "partition!\n" );
+		    break;
+		  }
+		  
+		  add_partition(hd, minor,
+				partsect + be32_to_cpu(xrs->part[i].st),
+				be32_to_cpu(xrs->part[i].siz));
+
+		  /* the slot following must be either invalid (end of list)
+		   * or another XGM entry */
+		  if (!(xrs->part[i+1].flg & 1)) {
+		    brelse( xbh );
+		    break;
+		  }
+		  if (memcmp( xrs->part[i+1].id, "XGM", 3 ) != 0) {
+		    printk( "\nLink ID in extended partition is not XGM!\n" );
+		    brelse( xbh );
+		    break;
+		  }
+
+		  partsect = be32_to_cpu(xrs->part[i+1].st) + extensect;
+		  brelse (xbh);
+		  minor++;
+		  if (minor >= m_lim) {
+		    printk( "\nMaximum number of partitions reached!\n" );
+		    break;
+		  }
+		}
+	      printk(" >");
+	    }
+	  else
+	    {
+	      /* we don't care about other id's */
+	      add_partition (hd, minor, be32_to_cpu(pi->st),
+			     be32_to_cpu(pi->siz));
+	    }
+	}
+    }
+  if ( part_fmt!=1 ) /* no extended partitions -> test ICD-format */
+  {
+    pi = &rs->icdpart[0];
+    /* sanity check: no ICD format if first partition invalid */
+    if (memcmp (pi->id, "GEM", 3) == 0 ||
+        memcmp (pi->id, "BGM", 3) == 0 ||
+        memcmp (pi->id, "LNX", 3) == 0 ||
+        memcmp (pi->id, "SWP", 3) == 0 ||
+        memcmp (pi->id, "RAW", 3) == 0 )
+    {
+      printk(" ICD<");
+      for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++)
+      {
+        /* accept only GEM,BGM,RAW,LNX,SWP partitions */
+        if (pi->flg & 1 && 
+            (memcmp (pi->id, "GEM", 3) == 0 ||
+             memcmp (pi->id, "BGM", 3) == 0 ||
+             memcmp (pi->id, "LNX", 3) == 0 ||
+             memcmp (pi->id, "SWP", 3) == 0 ||
+             memcmp (pi->id, "RAW", 3) == 0) )
+        {
+          part_fmt = 2;
+	  add_partition (hd, minor, be32_to_cpu(pi->st), be32_to_cpu(pi->siz));
+        }
+      }
+      printk(" >");
+    }
+  }
+  brelse (bh);
+  printk ("\n");
+  MOD_DEC_USE_COUNT;
+  return 1;
+}
+
+static struct partition_parser atari_partition_parser =
+    { NULL, "atari", atari_partition };
+
+#ifndef MODULE
+__initfunc(void atari_partbl_init( void ))
+{
+	(void)register_partbl( &atari_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &atari_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &atari_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/partitions/mac.c m68k/fs/partitions/mac.c
--- jes-2.1.108/fs/partitions/mac.c	Thu Jan  1 01:00:00 1970
+++ m68k/fs/partitions/mac.c	Sun Jul 12 23:44:48 1998
@@ -0,0 +1,171 @@
+/*
+ *  fs/partitions/mac.c -- Mac partition table parser
+ *
+ *  Code extracted from
+ *  linux/drivers/block/genhd.c
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include "../partcheck.h"
+
+
+/*
+ * Code to understand MacOS partition tables.
+ */
+
+#define MAC_PARTITION_MAGIC	0x504d
+
+/* type field value for A/UX or other Unix partitions */
+#define APPLE_AUX_TYPE	"Apple_UNIX_SVR2"
+
+struct mac_partition {
+	__u16	signature;	/* expected to be MAC_PARTITION_MAGIC */
+	__u16	res1;
+	__u32	map_count;	/* # blocks in partition map */
+	__u32	start_block;	/* absolute starting block # of partition */
+	__u32	block_count;	/* number of blocks in partition */
+	char	name[32];	/* partition name */
+	char	type[32];	/* string type description */
+	__u32	data_start;	/* rel block # of first data block */
+	__u32	data_count;	/* number of data blocks */
+	__u32	status;		/* partition status bits */
+	__u32	boot_start;
+	__u32	boot_size;
+	__u32	boot_load;
+	__u32	boot_load2;
+	__u32	boot_entry;
+	__u32	boot_entry2;
+	__u32	boot_cksum;
+	char	processor[16];	/* identifies ISA of boot */
+	/* there is more stuff after this that we don't need */
+};
+
+#define MAC_STATUS_BOOTABLE	8	/* partition is bootable */
+
+#define MAC_DRIVER_MAGIC	0x4552
+
+/* Driver descriptor structure, in block 0 */
+struct mac_driver_desc {
+	__u16	signature;	/* expected to be MAC_DRIVER_MAGIC */
+	__u16	block_size;
+	__u32	block_count;
+    /* ... more stuff */
+};
+
+static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec,
+						 int current_minor)
+{
+	struct buffer_head *bh;
+	int blk, blocks_in_map;
+	int dev_bsize, dev_pos, pos;
+	unsigned secsize;
+#ifdef CONFIG_PMAC
+	int first_bootable = 1;
+#endif
+	struct mac_partition *part;
+	struct mac_driver_desc *md;
+
+	MOD_INC_USE_COUNT;
+	dev_bsize = get_ptable_blocksize(dev);
+	dev_pos = 0;
+	/* Get 0th block and look at the first partition map entry. */
+	if ((bh = bread(dev, 0, dev_bsize)) == 0) {
+	    printk("%s: error reading partition table\n",
+		   kdevname(dev));
+	    MOD_DEC_USE_COUNT;
+	    return -1;
+	}
+	md = (struct mac_driver_desc *) bh->b_data;
+	if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) {
+		brelse(bh);
+		MOD_DEC_USE_COUNT;
+		return 0;
+	}
+	secsize = be16_to_cpu(md->block_size);
+	if (secsize >= dev_bsize) {
+		brelse(bh);
+		dev_pos = secsize;
+		if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) {
+			printk("%s: error reading partition table\n",
+			       kdevname(dev));
+			MOD_DEC_USE_COUNT;
+			return -1;
+		}
+	}
+	part = (struct mac_partition *) (bh->b_data + secsize - dev_pos);
+	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
+		brelse(bh);
+		MOD_DEC_USE_COUNT;
+		return 0;		/* not a MacOS disk */
+	}
+	printk(" MAC");
+	blocks_in_map = be32_to_cpu(part->map_count);
+	for (blk = 1; blk <= blocks_in_map; ++blk) {
+		pos = blk * secsize;
+		if (pos >= dev_pos + dev_bsize) {
+			brelse(bh);
+			dev_pos = pos;
+			if ((bh = bread(dev, pos/dev_bsize, dev_bsize)) == 0) {
+				printk("%s: error reading partition table\n",
+				       kdevname(dev));
+				MOD_DEC_USE_COUNT;
+				return -1;
+			}
+		}
+		part = (struct mac_partition *) (bh->b_data + pos - dev_pos);
+		if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
+			break;
+		blocks_in_map = be32_to_cpu(part->map_count);
+		add_partition(hd, current_minor,
+			fsec + be32_to_cpu(part->start_block) * (secsize/512),
+			be32_to_cpu(part->block_count) * (secsize/512));
+
+#ifdef CONFIG_PMAC
+		/*
+		 * If this is the first bootable partition, tell the
+		 * setup code, in case it wants to make this the root.
+		 */
+		if (first_bootable
+		    && (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
+		    && strcasecmp(part->processor, "powerpc") == 0) {
+			note_bootable_part(dev, blk);
+			first_bootable = 0;
+		}
+#endif /* CONFIG_PMAC */
+
+		++current_minor;
+	}
+	brelse(bh);
+	printk("\n");
+	MOD_DEC_USE_COUNT;
+	return 1;
+}
+
+static struct partition_parser mac_partition_parser =
+    { NULL, "mac", mac_partition };
+
+#ifndef MODULE
+__initfunc(void mac_partbl_init( void ))
+{
+	(void)register_partbl( &mac_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &mac_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &mac_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/partitions/osf.c m68k/fs/partitions/osf.c
--- jes-2.1.108/fs/partitions/osf.c	Thu Jan  1 01:00:00 1970
+++ m68k/fs/partitions/osf.c	Sun Jul 12 23:44:48 1998
@@ -0,0 +1,117 @@
+/*
+ *  fs/partitions/osf.c -- partition table parser for OSF partitions (alpha)
+ *
+ *  Code extracted from
+ *  linux/drivers/block/genhd.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include "../partcheck.h"
+
+
+static int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int current_minor)
+{
+	int i;
+	int mask = (1 << hd->minor_shift) - 1;
+	struct buffer_head *bh;
+	struct disklabel {
+		u32 d_magic;
+		u16 d_type,d_subtype;
+		u8 d_typename[16];
+		u8 d_packname[16];
+		u32 d_secsize;
+		u32 d_nsectors;
+		u32 d_ntracks;
+		u32 d_ncylinders;
+		u32 d_secpercyl;
+		u32 d_secprtunit;
+		u16 d_sparespertrack;
+		u16 d_sparespercyl;
+		u32 d_acylinders;
+		u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
+		u32 d_headswitch, d_trkseek, d_flags;
+		u32 d_drivedata[5];
+		u32 d_spare[5];
+		u32 d_magic2;
+		u16 d_checksum;
+		u16 d_npartitions;
+		u32 d_bbsize, d_sbsize;
+		struct d_partition {
+			u32 p_size;
+			u32 p_offset;
+			u32 p_fsize;
+			u8  p_fstype;
+			u8  p_frag;
+			u16 p_cpg;
+		} d_partitions[8];
+	} * label;
+	struct d_partition * partition;
+#define DISKLABELMAGIC (0x82564557UL)
+
+	MOD_INC_USE_COUNT;
+	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
+		printk("unable to read partition table\n");
+	    MOD_DEC_USE_COUNT;
+		return -1;
+	}
+	label = (struct disklabel *) (bh->b_data+64);
+	partition = label->d_partitions;
+	if (label->d_magic != cpu_to_le32(DISKLABELMAGIC)) {
+#if 0
+		printk("magic: %08x\n", label->d_magic);
+#endif
+		brelse(bh);
+	    MOD_DEC_USE_COUNT;
+		return 0;
+	}
+	if (label->d_magic2 != cpu_to_le32(DISKLABELMAGIC)) {
+#if 0
+		printk("magic2: %08x\n", label->d_magic2);
+#endif
+		brelse(bh);
+	    MOD_DEC_USE_COUNT;
+		return 0;
+	}
+	printk(" OSF");
+	for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) {
+		if ((current_minor & mask) == 0)
+		        break;
+		if (partition->p_size)
+			add_partition(hd, current_minor,
+				first_sector+le32_to_cpu(partition->p_offset),
+				le32_to_cpu(partition->p_size));
+		current_minor++;
+	}
+	printk("\n");
+	brelse(bh);
+	MOD_DEC_USE_COUNT;
+	return 1;
+}
+
+static struct partition_parser osf_partition_parser =
+    { NULL, "osf",  osf_partition };
+
+#ifndef MODULE
+__initfunc(void osf_partbl_init( void ))
+{
+	(void)register_partbl( &osf_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &osf_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &osf_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/partitions/pc.c m68k/fs/partitions/pc.c
--- jes-2.1.108/fs/partitions/pc.c	Thu Jan  1 01:00:00 1970
+++ m68k/fs/partitions/pc.c	Sun Jul 12 23:44:48 1998
@@ -0,0 +1,425 @@
+/*
+ *  fs/partitions/pc.c -- PC (= MSDOS) partition table parser
+ *
+ *  Code extracted from
+ *  linux/drivers/block/genhd.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
+ *  in the early extended-partition checks and added DM partitions
+ *
+ *  Support for DiskManager v6.0x added by Mark Lord,
+ *  with information provided by OnTrack.  This now works for linux fdisk
+ *  and LILO, as well as loadlin and bootln.  Note that disks other than
+ *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
+ *
+ *  More flexible handling of extended partitions - aeb, 950831
+ *
+ *  Check partition table on IDE disks for common CHS translations
+ */
+
+#include <linux/module.h>
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include "../partcheck.h"
+
+static int current_minor;
+
+/*
+ * Many architectures don't like unaligned accesses, which is
+ * frequently the case with the nr_sects and start_sect partition
+ * table entries.
+ */
+#include <asm/unaligned.h>
+
+#define SYS_IND(p)	(get_unaligned(&p->sys_ind))
+#define NR_SECTS(p)	({ __typeof__(p->nr_sects) __a =	\
+				get_unaligned(&p->nr_sects);	\
+				le32_to_cpu(__a); \
+			})
+
+#define START_SECT(p)	({ __typeof__(p->start_sect) __a =	\
+				get_unaligned(&p->start_sect);	\
+				le32_to_cpu(__a); \
+			})
+
+
+static inline int is_extended_partition(struct partition *p)
+{
+	return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
+		SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
+		SYS_IND(p) == LINUX_EXTENDED_PARTITION);
+}
+
+/*
+ * Create devices for each logical partition in an extended partition.
+ * The logical partitions form a linked list, with each entry being
+ * a partition table with two entries.  The first entry
+ * is the real data partition (with a start relative to the partition
+ * table start).  The second is a pointer to the next logical partition
+ * (with a start relative to the entire extended partition).
+ * We do not create a Linux partition for the partition tables, but
+ * only for the actual data partitions.
+ */
+
+#define MSDOS_LABEL_MAGIC		0xAA55
+
+static void extended_partition(struct gendisk *hd, kdev_t dev)
+{
+	struct buffer_head *bh;
+	struct partition *p;
+	unsigned long first_sector, first_size, this_sector, this_size;
+	int mask = (1 << hd->minor_shift) - 1;
+	int i;
+
+	first_sector = hd->part[MINOR(dev)].start_sect;
+	first_size = hd->part[MINOR(dev)].nr_sects;
+	this_sector = first_sector;
+
+	while (1) {
+		if ((current_minor & mask) == 0)
+			return;
+		if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
+			return;
+	  /*
+	   * This block is from a device that we're about to stomp on.
+	   * So make sure nobody thinks this block is usable.
+	   */
+		bh->b_state = 0;
+
+		if ((*(unsigned short *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC))
+			goto done;
+
+		p = (struct partition *) (0x1BE + bh->b_data);
+
+		this_size = hd->part[MINOR(dev)].nr_sects;
+
+		/*
+		 * Usually, the first entry is the real data partition,
+		 * the 2nd entry is the next extended partition, or empty,
+		 * and the 3rd and 4th entries are unused.
+		 * However, DRDOS sometimes has the extended partition as
+		 * the first entry (when the data partition is empty),
+		 * and OS/2 seems to use all four entries.
+		 */
+
+		/* 
+		 * First process the data partition(s)
+		 */
+		for (i=0; i<4; i++, p++) {
+		    if (!NR_SECTS(p) || is_extended_partition(p))
+		      continue;
+
+		    /* Check the 3rd and 4th entries -
+		       these sometimes contain random garbage */
+		    if (i >= 2
+			&& START_SECT(p) + NR_SECTS(p) > this_size
+			&& (this_sector + START_SECT(p) < first_sector ||
+			    this_sector + START_SECT(p) + NR_SECTS(p) >
+			     first_sector + first_size))
+		      continue;
+
+		    add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
+		    current_minor++;
+		    if ((current_minor & mask) == 0)
+		      goto done;
+		}
+		/*
+		 * Next, process the (first) extended partition, if present.
+		 * (So far, there seems to be no reason to make
+		 *  extended_partition()  recursive and allow a tree
+		 *  of extended partitions.)
+		 * It should be a link to the next logical partition.
+		 * Create a minor for this just long enough to get the next
+		 * partition table.  The minor will be reused for the next
+		 * data partition.
+		 */
+		p -= 4;
+		for (i=0; i<4; i++, p++)
+		  if(NR_SECTS(p) && is_extended_partition(p))
+		    break;
+		if (i == 4)
+		  goto done;	 /* nothing left to do */
+
+		hd->part[current_minor].nr_sects = NR_SECTS(p);
+		hd->part[current_minor].start_sect = first_sector + START_SECT(p);
+		this_sector = first_sector + START_SECT(p);
+		dev = MKDEV(hd->major, current_minor);
+		brelse(bh);
+	}
+done:
+	brelse(bh);
+}
+
+#ifdef CONFIG_SOLARIS_X86_PARTITION
+static void
+solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) {
+
+	struct buffer_head *bh;
+	struct solaris_x86_vtoc *v;
+	struct solaris_x86_slice *s;
+	int i;
+
+	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev))))
+		return;
+	v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
+	if(v->v_sanity != cpu_to_le32(SOLARIS_X86_VTOC_SANE)) {
+		brelse(bh);
+		return;
+	}
+	printk(" <solaris:");
+	if(v->v_version != cpu_to_le32(1)) {
+		printk("  cannot handle version %d vtoc>", le32_to_cpu(v->v_version));
+		brelse(bh);
+		return;
+	}
+	for(i=0; i<SOLARIS_X86_NUMSLICE; i++) {
+		s = &v->v_slice[i];
+
+		if (s->s_tag == 0)
+			continue;
+		printk(" [s%d]", i);
+		/* solaris partitions are relative to current MS-DOS
+		 * one but add_partition starts relative to sector
+		 * zero of the disk.  Therefore, must add the offset
+		 * of the current partition */
+		add_partition(hd, current_minor, le32_to_cpu(s->s_start)+offset,
+					  le32_to_cpu(s->s_size));
+		current_minor++;
+	}
+	brelse(bh);
+	printk(" >");
+}
+#endif
+
+#ifdef CONFIG_BSD_DISKLABEL
+/* 
+ * Create devices for BSD partitions listed in a disklabel, under a
+ * dos-like partition. See extended_partition() for more information.
+ */
+static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev)
+{
+	struct buffer_head *bh;
+	struct bsd_disklabel *l;
+	struct bsd_partition *p;
+	int mask = (1 << hd->minor_shift) - 1;
+
+	if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
+		return;
+	bh->b_state = 0;
+	l = (struct bsd_disklabel *) (bh->b_data+512);
+	if (l->d_magic != cpu_to_le32(BSD_DISKMAGIC)) {
+		brelse(bh);
+		return;
+	}
+
+	p = &l->d_partitions[0];
+	while (p - &l->d_partitions[0] <= BSD_MAXPARTITIONS) {
+		if ((current_minor & mask) >= (4 + hd->max_p))
+			break;
+
+		if (p->p_fstype != BSD_FS_UNUSED) {
+			add_partition(hd, current_minor, le32_to_cpu(p->p_offset),
+						  le32_to_cpu(p->p_size));
+			current_minor++;
+		}
+		p++;
+	}
+	brelse(bh);
+
+}
+#endif
+
+static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_minor)
+{
+	int i, minor = current_minor = first_minor;
+	struct buffer_head *bh;
+	struct partition *p;
+	unsigned char *data;
+	int mask = (1 << hd->minor_shift) - 1;
+#ifdef CONFIG_BLK_DEV_IDE
+	int tested_for_xlate = 0;
+
+	MOD_INC_USE_COUNT;
+read_mbr:
+#endif
+	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
+		printk(" unable to read partition table\n");
+	    MOD_DEC_USE_COUNT;
+		return -1;
+	}
+	data = bh->b_data;
+	/* In some cases we modify the geometry    */
+	/*  of the drive (below), so ensure that   */
+	/*  nobody else tries to re-use this data. */
+	bh->b_state = 0;
+#ifdef CONFIG_BLK_DEV_IDE
+check_table:
+#endif
+	if (*(unsigned short *)  (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
+		brelse(bh);
+	    MOD_DEC_USE_COUNT;
+		return 0;
+	}
+	p = (struct partition *) (0x1be + data);
+
+#ifdef CONFIG_BLK_DEV_IDE
+	if (!tested_for_xlate++) {	/* Do this only once per disk */
+		/*
+		 * Look for various forms of IDE disk geometry translation
+		 */
+		extern int ide_xlate_1024(kdev_t, int, const char *);
+		unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
+		if (SYS_IND(p) == EZD_PARTITION) {
+			/*
+			 * The remainder of the disk must be accessed using
+			 * a translated geometry that reduces the number of 
+			 * apparent cylinders to less than 1024 if possible.
+			 *
+			 * ide_xlate_1024() will take care of the necessary
+			 * adjustments to fool fdisk/LILO and partition check.
+			 */
+			if (ide_xlate_1024(dev, -1, " [EZD]")) {
+				data += 512;
+				goto check_table;
+			}
+		} else if (SYS_IND(p) == DM6_PARTITION) {
+
+			/*
+			 * Everything on the disk is offset by 63 sectors,
+			 * including a "new" MBR with its own partition table,
+			 * and the remainder of the disk must be accessed using
+			 * a translated geometry that reduces the number of 
+			 * apparent cylinders to less than 1024 if possible.
+			 *
+			 * ide_xlate_1024() will take care of the necessary
+			 * adjustments to fool fdisk/LILO and partition check.
+			 */
+			if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
+				brelse(bh);
+				goto read_mbr;	/* start over with new MBR */
+			}
+		} else if (sig <= 0x1ae &&
+			   *(unsigned short *)(data + sig) == cpu_to_le16(0x55AA) &&
+			   (1 & *(unsigned char *)(data + sig + 2))) {
+			/* DM6 signature in MBR, courtesy of OnTrack */
+			(void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
+		} else if (SYS_IND(p) == DM6_AUX1PARTITION || SYS_IND(p) == DM6_AUX3PARTITION) {
+			/*
+			 * DM6 on other than the first (boot) drive
+			 */
+			(void) ide_xlate_1024(dev, 0, " [DM6:AUX]");
+		} else {
+			/*
+			 * Examine the partition table for common translations.
+			 * This is necessary for drives for situations where
+			 * the translated geometry is unavailable from the BIOS.
+			 */
+			for (i = 0; i < 4 ; i++) {
+				struct partition *q = &p[i];
+				if (NR_SECTS(q)
+				   && (q->sector & 63) == 1
+				   && (q->end_sector & 63) == 63) {
+					unsigned int heads = q->end_head + 1;
+					if (heads == 32 || heads == 64 || heads == 128 || heads == 255) {
+
+						(void) ide_xlate_1024(dev, heads, " [PTBL]");
+						break;
+					}
+				}
+			}
+		}
+	}
+#endif	/* CONFIG_BLK_DEV_IDE */
+
+	printk(" PC");	/* show partition type */
+	current_minor += 4;  /* first "extra" minor (for extended partitions) */
+	for (i=1 ; i<=4 ; minor++,i++,p++) {
+		if (!NR_SECTS(p))
+			continue;
+		add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
+		if (is_extended_partition(p)) {
+			printk(" <");
+			/*
+			 * If we are rereading the partition table, we need
+			 * to set the size of the partition so that we will
+			 * be able to bread the block containing the extended
+			 * partition info.
+			 */
+			hd->sizes[minor] = hd->part[minor].nr_sects 
+			  	>> (BLOCK_SIZE_BITS - 9);
+			extended_partition(hd, MKDEV(hd->major, minor));
+			printk(" >");
+			/* prevent someone doing mkfs or mkswap on an
+			   extended partition, but leave room for LILO */
+			if (hd->part[minor].nr_sects > 2)
+				hd->part[minor].nr_sects = 2;
+		}
+#ifdef CONFIG_BSD_DISKLABEL
+		if (SYS_IND(p) == BSD_PARTITION) {
+			printk(" BSD<");
+			bsd_disklabel_partition(hd, MKDEV(hd->major, minor));
+			printk(" >");
+		}
+#endif
+#ifdef CONFIG_SOLARIS_X86_PARTITION
+
+		/* james@bpgc.com: Solaris has a nasty indicator: 0x82
+		 * which also means linux swap.  For that reason, all
+		 * of the prints are done inside the
+		 * solaris_x86_partition routine */
+
+		if(SYS_IND(p) == SOLARIS_X86_PARTITION) {
+			solaris_x86_partition(hd, MKDEV(hd->major, minor),
+					      first_sector+START_SECT(p));
+		}
+#endif
+	}
+	/*
+	 *  Check for old-style Disk Manager partition table
+	 */
+	if (*(unsigned short *) (data+0xfc) == cpu_to_le16(MSDOS_LABEL_MAGIC)) {
+		p = (struct partition *) (0x1be + data);
+		for (i = 4 ; i < 16 ; i++, current_minor++) {
+			p--;
+			if ((current_minor & mask) == 0)
+				break;
+			if (!(START_SECT(p) && NR_SECTS(p)))
+				continue;
+			add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
+		}
+	}
+	printk("\n");
+	brelse(bh);
+	MOD_DEC_USE_COUNT;
+	return 1;
+}
+
+static struct partition_parser msdos_partition_parser =
+    { NULL, "msdos", msdos_partition };
+
+#ifndef MODULE
+__initfunc(void msdos_partbl_init( void ))
+{
+	(void)register_partbl( &msdos_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &msdos_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &msdos_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/fs/partitions/sun.c m68k/fs/partitions/sun.c
--- jes-2.1.108/fs/partitions/sun.c	Thu Jan  1 01:00:00 1970
+++ m68k/fs/partitions/sun.c	Sun Jul 12 23:44:48 1998
@@ -0,0 +1,113 @@
+/*
+ *  fs/partitions/sun.c -- Sun partition table parser
+ *
+ *  Code extracted from
+ *  linux/drivers/block/genhd.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include "../partcheck.h"
+
+
+static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int current_minor)
+{
+	int i, csum;
+	unsigned short *ush;
+	struct buffer_head *bh;
+	struct sun_disklabel {
+		unsigned char info[128];   /* Informative text string */
+		unsigned char spare[292];  /* Boot information etc. */
+		unsigned short rspeed;     /* Disk rotational speed */
+		unsigned short pcylcount;  /* Physical cylinder count */
+		unsigned short sparecyl;   /* extra sects per cylinder */
+		unsigned char spare2[4];   /* More magic... */
+		unsigned short ilfact;     /* Interleave factor */
+		unsigned short ncyl;       /* Data cylinder count */
+		unsigned short nacyl;      /* Alt. cylinder count */
+		unsigned short ntrks;      /* Tracks per cylinder */
+		unsigned short nsect;      /* Sectors per track */
+		unsigned char spare3[4];   /* Even more magic... */
+		struct sun_partition {
+			__u32 start_cylinder;
+			__u32 num_sectors;
+		} partitions[8];
+		unsigned short magic;      /* Magic number */
+		unsigned short csum;       /* Label xor'd checksum */
+	} * label;		
+	struct sun_partition *p;
+	unsigned long spc;
+#define SUN_LABEL_MAGIC          0xDABE
+
+	MOD_INC_USE_COUNT;
+	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
+		printk("Dev %s: unable to read partition table\n",
+		       kdevname(dev));
+	    MOD_DEC_USE_COUNT;
+		return -1;
+	}
+	label = (struct sun_disklabel *) bh->b_data;
+	p = label->partitions;
+	if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
+		printk("Dev %s Sun disklabel: bad magic %04x\n",
+		       kdevname(dev), be16_to_cpu(label->magic));
+		brelse(bh);
+	    MOD_DEC_USE_COUNT;
+		return 0;
+	}
+	/* Look at the checksum */
+	ush = ((unsigned short *) (label+1)) - 1;
+	for(csum = 0; ush >= ((unsigned short *) label);)
+		csum ^= *ush--;
+	if(csum) {
+		printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
+		       kdevname(dev));
+		brelse(bh);
+	    MOD_DEC_USE_COUNT;
+		return 0;
+	}
+	printk(" UFS");
+	/* All Sun disks have 8 partition entries */
+	spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
+	for(i=0; i < 8; i++, p++) {
+		unsigned long st_sector;
+		int num_sectors;
+
+		st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc;
+		num_sectors = be32_to_cpu(p->num_sectors);
+		if (num_sectors)
+			add_partition(hd, current_minor, st_sector, num_sectors);
+		current_minor++;
+	}
+	printk("\n");
+	brelse(bh);
+	MOD_DEC_USE_COUNT;
+	return 1;
+}
+
+static struct partition_parser sun_partition_parser =
+    { NULL, "sun", sun_partition };
+
+#ifndef MODULE
+__initfunc(void sun_partbl_init( void ))
+{
+	(void)register_partbl( &sun_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &sun_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &sun_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/include/asm-m68k/amigayle.h m68k/include/asm-m68k/amigayle.h
--- jes-2.1.108/include/asm-m68k/amigayle.h	Thu Jan  1 01:00:00 1970
+++ m68k/include/asm-m68k/amigayle.h	Sun Jul 12 23:32:45 1998
@@ -0,0 +1,107 @@
+
+/*
+** asm-m68k/amigayle.h -- This header defines the registers of the gayle chip
+**                        found on the Amiga 1200
+**                        This information was found by disassembling card.resource,
+**                        so the definitions may not be 100% correct
+**                        anyone has an official doc ?
+**
+** Copyright 1997 by Alain Malek
+**
+** 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.
+**
+** Created: 11/28/97 by Alain Malek
+*/
+
+#ifndef _ASMm68k_AMIGAYLE_H_
+#define _ASMm68k_AMIGAYLE_H_
+
+#include <asm/amigahw.h>
+#include <asm/io.h>
+
+/* memory layout */
+
+#define GAYLE_RAM		(0x600000+zTwoBase)
+#define GAYLE_RAMSIZE		(0x400000)
+#define GAYLE_ATTRIBUTE		(0xa00000+zTwoBase)
+#define GAYLE_ATTRIBUTESIZE	(0x020000)
+#define GAYLE_IO		(0xa20000+zTwoBase)	/* 16bit and even 8bit registers */
+#define GAYLE_IOSIZE		(0x010000)
+#define GAYLE_IO_8BITODD	(0xa30000+zTwoBase)	/* odd 8bit registers */
+
+/* offset for accessing odd IO registers */
+#define GAYLE_ODD		(GAYLE_IO_8BITODD-GAYLE_IO-1)
+
+/* GAYLE registers */
+
+struct GAYLE {
+	u_char cardstatus;
+	u_char pad0[0x1000-1];
+
+	u_char intreq;
+	u_char pad1[0x1000-1];
+
+	u_char inten;
+	u_char pad2[0x1000-1];
+
+	u_char config;
+	u_char pad3[0x1000-1];
+};
+
+#define GAYLE_ADDRESS	(0xda8000)	/* gayle main registers base address */
+
+#define GAYLE_RESET	(0xa40000)	/* write 0x00 to start reset,
+                                           read 1 byte to stop reset */
+
+#define gayle (*(volatile struct GAYLE *)(zTwoBase+GAYLE_ADDRESS))
+#define gayle_reset (*(volatile u_char *)(zTwoBase+GAYLE_RESET))
+
+#define gayle_attribute ((volatile u_char *)(GAYLE_ATTRIBUTE))
+
+#define gayle_inb(a) readb( GAYLE_IO+(a)+(((a)&1)*GAYLE_ODD) )
+#define gayle_outb(v,a) writeb( v, GAYLE_IO+(a)+(((a)&1)*GAYLE_ODD) )
+
+#define gayle_inw(a) readw( GAYLE_IO+(a) )
+#define gayle_outw(v,a) writew( v, GAYLE_IO+(a) )
+
+/* GAYLE_CARDSTATUS bit def */
+
+#define GAYLE_CS_CCDET		0x40	/* credit card detect */
+#define GAYLE_CS_BVD1		0x20	/* battery voltage detect 1 */
+#define GAYLE_CS_SC		0x20	/* credit card status change */
+#define GAYLE_CS_BVD2		0x10	/* battery voltage detect 2 */
+#define GAYLE_CS_DA		0x10	/* digital audio */
+#define GAYLE_CS_WR		0x08	/* write enable (1 == enabled) */
+#define GAYLE_CS_BSY		0x04	/* credit card busy */
+#define GAYLE_CS_IRQ		0x04	/* interrupt request */
+
+/* GAYLE_IRQ bit def */
+
+#define GAYLE_IRQ_IDE		0x80
+#define GAYLE_IRQ_CCDET		0x40
+#define GAYLE_IRQ_BVD1		0x20
+#define GAYLE_IRQ_SC		0x20
+#define GAYLE_IRQ_BVD2		0x10
+#define GAYLE_IRQ_DA		0x10
+#define GAYLE_IRQ_WR		0x08
+#define GAYLE_IRQ_BSY		0x04
+#define GAYLE_IRQ_IRQ		0x04
+#define GAYLE_IRQ_IDEACK1	0x02
+#define GAYLE_IRQ_IDEACK0	0x01
+
+/* GAYLE_CONFIG bit def
+   (bit 0-1 for program voltage, bit 2-3 for access speed */
+
+#define GAYLE_CFG_0V		0x00
+#define GAYLE_CFG_5V		0x01
+#define GAYLE_CFG_12V		0x02
+
+#define GAYLE_CFG_100NS		0x08
+#define GAYLE_CFG_150NS		0x04
+#define GAYLE_CFG_250NS		0x00
+#define GAYLE_CFG_720NS		0x0c
+
+#endif /* asm-m68k/amigayle.h */
+
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/include/asm-m68k/amipcmcia.h m68k/include/asm-m68k/amipcmcia.h
--- jes-2.1.108/include/asm-m68k/amipcmcia.h	Thu Jan  1 01:00:00 1970
+++ m68k/include/asm-m68k/amipcmcia.h	Sun Jul 12 23:32:45 1998
@@ -0,0 +1,111 @@
+
+/*
+** asm-m68k/pcmcia.h -- Amiga Linux PCMCIA Definitions
+**
+** Copyright 1997 by Alain Malek
+**
+** 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.
+**
+** Created: 12/10/97 by Alain Malek
+*/
+
+#ifndef __AMIGA_PCMCIA_H__
+#define __AMIGA_PCMCIA_H__
+
+#include <asm/amigayle.h>
+
+/* prototypes */
+
+void pcmcia_reset(void);
+int pcmcia_copy_tuple(unsigned char tuple_id, void *tuple, int max_len);
+void pcmcia_program_voltage(int voltage);
+void pcmcia_access_speed(int speed);
+void pcmcia_write_enable(void);
+void pcmcia_write_disable(void);
+
+static inline u_char pcmcia_read_status(void)
+{
+	return (gayle.cardstatus & 0x7c);
+}
+
+static inline u_char pcmcia_get_intreq(void)
+{
+	return (gayle.intreq);
+}
+
+static inline void pcmcia_ack_int(u_char intreq)
+{
+	gayle.intreq = ((intreq & 0x2c) ^ 0x2c) | 0xc0;
+}
+
+static inline void pcmcia_enable_irq(void)
+{
+	gayle.inten = GAYLE_IRQ_IDE|GAYLE_IRQ_IRQ;
+}
+
+static inline void pcmcia_disable_irq(void)
+{
+	gayle.inten = GAYLE_IRQ_IDE;
+}
+
+#define PCMCIA_INSERTED	(gayle.cardstatus & GAYLE_CS_CCDET)
+
+/* valid voltages for pcmcia_ProgramVoltage */
+
+#define PCMCIA_0V	0
+#define PCMCIA_5V	5
+#define PCMCIA_12V	12
+
+/* valid speeds for pcmcia_AccessSpeed */
+
+#define PCMCIA_SPEED_100NS	100
+#define PCMCIA_SPEED_150NS	150
+#define PCMCIA_SPEED_250NS	250
+#define PCMCIA_SPEED_720NS	720
+
+/* PCMCIA Tuple codes */
+
+#define CISTPL_NULL		0x00
+#define CISTPL_DEVICE		0x01
+#define CISTPL_LONGLINK_CB	0x02
+#define CISTPL_CONFIG_CB	0x04
+#define CISTPL_CFTABLE_ENTRY_CB	0x05
+#define CISTPL_LONGLINK_MFC	0x06
+#define CISTPL_BAR		0x07
+#define CISTPL_CHECKSUM		0x10
+#define CISTPL_LONGLINK_A	0x11
+#define CISTPL_LONGLINK_C	0x12
+#define CISTPL_LINKTARGET	0x13
+#define CISTPL_NO_LINK		0x14
+#define CISTPL_VERS_1		0x15
+#define CISTPL_ALTSTR		0x16
+#define CISTPL_DEVICE_A		0x17
+#define CISTPL_JEDEC_C		0x18
+#define CISTPL_JEDEC_A		0x19
+#define CISTPL_CONFIG		0x1a
+#define CISTPL_CFTABLE_ENTRY	0x1b
+#define CISTPL_DEVICE_OC	0x1c
+#define CISTPL_DEVICE_OA	0x1d
+#define CISTPL_DEVICE_GEO	0x1e
+#define CISTPL_DEVICE_GEO_A	0x1f
+#define CISTPL_MANFID		0x20
+#define CISTPL_FUNCID		0x21
+#define CISTPL_FUNCE		0x22
+#define CISTPL_SWIL		0x23
+#define CISTPL_END		0xff
+
+/* FUNCID */
+
+#define CISTPL_FUNCID_MULTI	0x00
+#define CISTPL_FUNCID_MEMORY	0x01
+#define CISTPL_FUNCID_SERIAL	0x02
+#define CISTPL_FUNCID_PARALLEL	0x03
+#define CISTPL_FUNCID_FIXED	0x04
+#define CISTPL_FUNCID_VIDEO	0x05
+#define CISTPL_FUNCID_NETWORK	0x06
+#define CISTPL_FUNCID_AIMS	0x07
+#define CISTPL_FUNCID_SCSI	0x08
+
+#endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/include/asm-m68k/machdep.h m68k/include/asm-m68k/machdep.h
--- jes-2.1.108/include/asm-m68k/machdep.h	Sun Feb  8 22:29:50 1998
+++ m68k/include/asm-m68k/machdep.h	Sun Jun 14 22:18:24 1998
@@ -13,6 +13,7 @@
 extern int (*mach_keyb_init) (void);
 extern int (*mach_kbdrate) (struct kbd_repeat *);
 extern void (*mach_kbd_leds) (unsigned int);
+extern void (*kbd_reset_setup) (char *, int);
 /* machine dependent irq functions */
 extern void (*mach_init_IRQ) (void);
 extern void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/include/linux/console.h m68k/include/linux/console.h
--- jes-2.1.108/include/linux/console.h	Fri Jul 10 19:11:15 1998
+++ m68k/include/linux/console.h	Sun Jul 12 22:44:30 1998
@@ -35,7 +35,7 @@
 	int	(*con_scroll)(struct vc_data *, int, int, int, int);
 	void	(*con_bmove)(struct vc_data *, int, int, int, int, int, int);
 	int	(*con_switch)(struct vc_data *);
-	int	(*con_blank)(int);
+	int	(*con_blank)(struct vc_data *, int);
 	int	(*con_get_font)(struct vc_data *, int *, int *, char *);
 	int	(*con_set_font)(struct vc_data *, int, int, char *);
 	int	(*con_set_palette)(struct vc_data *, unsigned char *);
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/include/linux/genhd.h m68k/include/linux/genhd.h
--- jes-2.1.108/include/linux/genhd.h	Sun Feb  8 22:28:08 1998
+++ m68k/include/linux/genhd.h	Sun Jul 12 23:43:56 1998
@@ -48,6 +48,12 @@
 # define HAVE_MAC_PARTITION 0
 #endif
 
+#ifdef CONFIG_ACORN_PARTITION
+# define HAVE_ACORN_PARTITION 1
+#else
+# define HAVE_ACORN_PARTITION 0
+#endif
+
 /* These three have identical behaviour; use the second one if DOS fdisk gets
    confused about extended/logical partitions starting past cylinder 1023. */
 #define DOS_EXTENDED_PARTITION 5
@@ -183,26 +189,5 @@
 #endif	/* CONFIG_BSD_DISKLABEL */
 
 extern struct gendisk *gendisk_head;	/* linked list of disks */
-
-/*
- * disk_name() is used by genhd.c and md.c.
- * It formats the devicename of the indicated disk
- * into the supplied buffer, and returns a pointer
- * to that same buffer (for convenience).
- */
-char *disk_name (struct gendisk *hd, int minor, char *buf);
-void add_partition (struct gendisk *hd, int minor, int start, int size);
-unsigned int get_ptable_blocksize(kdev_t dev);
-extern int current_minor;
-
-struct partition_parser {
-	struct partition_parser *next;
-	char *name;
-	int (*func)(struct gendisk *hd, kdev_t dev,
-		    unsigned long first_sector);
-};
-
-int register_partbl( struct partition_parser *parser );
-int unregister_partbl( struct partition_parser *parser );
 
 #endif
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/include/linux/tty.h m68k/include/linux/tty.h
--- jes-2.1.108/include/linux/tty.h	Fri Jul 10 19:11:15 1998
+++ m68k/include/linux/tty.h	Sun Jul 12 22:24:43 1998
@@ -24,6 +24,7 @@
 #include <linux/serialP.h>
 
 #include <asm/system.h>
+#include <asm/atomic.h>
 
 
 /*
@@ -273,7 +274,7 @@
 	char *read_buf;
 	int read_head;
 	int read_tail;
-	int read_cnt;
+	atomic_t read_cnt;
 	unsigned long read_flags[N_TTY_BUF_SIZE/(8*sizeof(unsigned long))];
 	int canon_data;
 	unsigned long canon_head;
@@ -367,7 +368,7 @@
 
 /* serial.c */
 
-extern void serial_console_init(void);
+extern long serial_console_init(long kmem_start, long kmem_end);
  
 /* pcxx.c */
 
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/include/linux/zorro.h m68k/include/linux/zorro.h
--- jes-2.1.108/include/linux/zorro.h	Fri Jul 10 19:11:16 1998
+++ m68k/include/linux/zorro.h	Sun Jul 12 20:32:54 1998
@@ -411,7 +411,7 @@
 #define ZORRO_MANUF_ARMAX					0x0885
 #define  ZORRO_PROD_ARMAX_OMNIBUS				ZORRO_ID(ARMAX, 0x00, 0)
 
-#define ZORRO_MANUF_ZEUS					0x088d
+#define ZORRO_MANUF_ZEUS					0x088D
 #define  ZORRO_PROD_ZEUS_SPIDER					ZORRO_ID(ZEUS, 0x04, 0)
 
 #define ZORRO_MANUF_NEWTEK					0x088F
diff -u --recursive --exclude-from=/home/geert/diff-excludes-linux --new-file jes-2.1.108/kernel/kmod.c m68k/kernel/kmod.c
--- jes-2.1.108/kernel/kmod.c	Fri Jul 10 19:11:16 1998
+++ m68k/kernel/kmod.c	Sun Jul 12 21:34:57 1998
@@ -14,8 +14,10 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/unistd.h>
+#include <linux/mm.h>
 #include <asm/smp_lock.h>
 #include <asm/uaccess.h>
+#include <asm/pgtable.h>
 
 /*
 	modprobe_path is set via /proc/sys.
@@ -49,6 +51,16 @@
 {
 	char *argv[] = { modprobe_path, "-s", "-k", (char*)module_name, NULL};
 	int i;
+
+	/*
+	 * The MMU ATC entries need flushing somewhere round here.  This
+	 * thread was created with CLONE_VM, so there was no cause to
+	 * flush it there.  exec_mmap() called as a result of the
+	 * following execve() finds current->mm->count=2, so that doesn't
+	 * flush the MMU either.
+	 */
+
+	flush_tlb_mm(current->mm);
 
 	use_init_file_context();
 
Greetings,

						Geert

--
Geert Uytterhoeven                     Geert.Uytterhoeven@cs.kuleuven.ac.be
Wavelets, Linux/{m68k~Amiga,PPC~CHRP}  http://www.cs.kuleuven.ac.be/~geert/
Department of Computer Science -- Katholieke Universiteit Leuven -- Belgium

