diff -u --recursive --new-file v1.3.39/linux/Makefile linux/Makefile
--- v1.3.39/linux/Makefile	Thu Nov  9 11:23:46 1995
+++ linux/Makefile	Sat Nov 11 13:29:37 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 39
+SUBLEVEL = 40
 
 ARCH = i386
 
@@ -223,12 +223,14 @@
 net: dummy
 	$(MAKE) linuxsubdirs SUBDIRS=net
 
+MODFLAGS = -DMODULE
+
 ifdef CONFIG_MODVERSIONS
-MODV = -DMODVERSIONS
+MODFLAGS += -DMODVERSIONS -include $(HPATH)/linux/modversions.h
 endif
 
 modules: include/linux/version.h
-	@set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i CFLAGS="$(CFLAGS) -DMODULE $(MODV)" modules; done
+	@set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i CFLAGS="$(CFLAGS) $(MODFLAGS)" modules; done
 
 modules_install:
 	@( \
@@ -280,17 +282,18 @@
 	cd .. && tar cf - linux | gzip -9 > backup.gz
 	sync
 
-#depend dep: .hdepend
-depend dep: archdep .hdepend include/linux/version.h
+dep-files: archdep .hdepend include/linux/version.h
 	$(AWK) -f scripts/depend.awk init/*.c > .tmpdepend
 	set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i fastdep; done
 	mv .tmpdepend .depend
+
+MODVERFILE :=
+
 ifdef CONFIG_MODVERSIONS
-	@echo updating $(TOPDIR)/include/linux/modversions.h
-	@(cd $(TOPDIR)/include/linux/modules; for f in *.ver;\
-	do echo "#include <linux/modules/$${f}>"; done) \
-	> $(TOPDIR)/include/linux/modversions.h
+MODVERFILE := $(TOPDIR)/include/linux/modversions.h
 endif
+
+depend dep: dep-files $(MODVERFILE)
 
 ifdef CONFIGURATION
 ..$(CONFIGURATION):
diff -u --recursive --new-file v1.3.39/linux/Rules.make linux/Rules.make
--- v1.3.39/linux/Rules.make	Thu Nov  9 11:23:46 1995
+++ linux/Rules.make	Sat Nov 11 13:24:52 1995
@@ -138,17 +138,26 @@
 SYMTAB_OBJS = $(LX_OBJS) $(OX_OBJS) $(MX_OBJS)
 ifneq "$(strip $(SYMTAB_OBJS))" ""
 
-%.ver: %.c
+MODINCL = $(TOPDIR)/include/linux/modules
+
+$(MODINCL)/%.ver: %.c
 	@if [ ! -x /sbin/genksyms ]; then echo "Please read: README.modules"; fi
-	$(CC) $(CFLAGS) -E -D__GENKSYMS__ $< | /sbin/genksyms -w $(TOPDIR)/include/linux/modules
-	@ln -sf $(TOPDIR)/include/linux/modules/$@ .
+	$(CC) $(CFLAGS) -E -D__GENKSYMS__ $< | /sbin/genksyms -w $(MODINCL)
 
 $(SYMTAB_OBJS:.o=.ver): $(TOPDIR)/include/linux/autoconf.h
 
-$(TOPDIR)/include/linux/modversions.h: $(SYMTAB_OBJS:.o=.ver)
+$(TOPDIR)/include/linux/modversions.h: $(join $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver))
 	@echo updating $(TOPDIR)/include/linux/modversions.h
-	@(cd $(TOPDIR)/include/linux/modules; for f in *.ver;\
-	do echo "#include <linux/modules/$${f}>"; done) \
+	@(echo "#ifdef MODVERSIONS";\
+	echo "#undef  CONFIG_MODVERSIONS";\
+	echo "#define CONFIG_MODVERSIONS";\
+	echo "#ifndef _set_ver";\
+	echo "#define _set_ver(sym,vers) sym ## _R ## vers";\
+	echo "#endif";\
+	cd $(TOPDIR)/include/linux/modules; for f in *.ver;\
+	do echo "#include <linux/modules/$${f}>"; done; \
+	echo "#undef  CONFIG_MODVERSIONS";\
+	echo "#endif") \
 	> $(TOPDIR)/include/linux/modversions.h
 
 $(MX_OBJS): $(TOPDIR)/include/linux/modversions.h
diff -u --recursive --new-file v1.3.39/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- v1.3.39/linux/arch/i386/kernel/head.S	Wed Nov  8 07:11:29 1995
+++ linux/arch/i386/kernel/head.S	Sat Nov 11 14:51:55 1995
@@ -10,7 +10,6 @@
 
 .text
 #include <linux/tasks.h>
-#include <linux/fd.h>
 #include <linux/linkage.h>
 #include <asm/segment.h>
 
diff -u --recursive --new-file v1.3.39/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v1.3.39/linux/drivers/block/floppy.c	Thu Nov  9 11:23:47 1995
+++ linux/drivers/block/floppy.c	Sat Nov 11 14:51:55 1995
@@ -81,10 +81,6 @@
  * errors to allow safe writing by specialized programs.
  */
 
-/*
- * 1995/8/26 -- Andreas Busse -- added Mips support.
- */
-
 /* 1995/4/24 -- Dan Fandrich -- added support for Commodore 1581 3.5" disks
  * by defining bit 1 of the "stretch" parameter to mean put sectors on the
  * opposite side of the disk, leaving the sector IDs alone (i.e. Commodore's
@@ -92,10 +88,15 @@
  */
 
 /*
- * 1995/18/10 -- Ralf Baechle -- Portability cleanup; move machine dependend
+ * 1995/8/26 -- Andreas Busse -- added Mips support.
+ */
+
+/*
+ * 1995/10/18 -- Ralf Baechle -- Portability cleanup; move machine dependend
  * features to asm/floppy.h.
  */
 
+
 #define FLOPPY_SANITY_CHECK
 #undef  FLOPPY_SILENT_DCL_CLEAR
 
@@ -116,7 +117,8 @@
  * a drive is allowed. */
 static int FLOPPY_IRQ=6;
 static int FLOPPY_DMA=2;
-static int ALLOWED_DRIVE_MASK = 0x33;
+static int allowed_drive_mask = 0x33;
+ 
 
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -126,47 +128,11 @@
 #define FDPATCHES
 #include <linux/fdreg.h>
 
-/* ============================================ *
- * old fd.h					*
- * =========================================== */
-
-#define OLDFDCLRPRM 0 /* clear user-defined parameters */
-#define OLDFDSETPRM 1 /* set user-defined parameters for current media */
-#define OLDFDSETMEDIAPRM 1
-#define OLDFDDEFPRM 2 /* set user-defined parameters until explicitly cleared */
-#define OLDFDDEFMEDIAPRM 2
-#define OLDFDGETPRM 3 /* get disk parameters */
-#define OLDFDGETMEDIAPRM 3
-#define	OLDFDMSGON  4 /* issue kernel messages on media type change */
-#define	OLDFDMSGOFF 5 /* don't issue kernel messages on media type change */
-#define OLDFDFMTBEG 6 /* begin formatting a disk */
-#define	OLDFDFMTTRK 7 /* format the specified track */
-#define OLDFDFMTEND 8 /* end formatting a disk */
-#define OLDFDSETEMSGTRESH	10	/* set fdc error reporting threshold */
-#define OLDFDFLUSH  11 /* flush buffers for media; either for verifying media, or for
-                       handling a media change without closing the file
-		       descriptor */
-#define OLDFDSETMAXERRS 12 /* set abortion and read_track threshold */
-#define OLDFDGETMAXERRS 14 /* get abortion and read_track threshold */
-#define OLDFDGETDRVTYP 16          /* get drive type: 5 1/4 or 3 1/2 */
-
-#define OLDFDSETDRVPRM 20 /* set drive parameters */
-#define OLDFDGETDRVPRM 21 /* get drive parameters */
-#define OLDFDGETDRVSTAT 22 /* get drive state */
-#define OLDFDPOLLDRVSTAT 23 /* get drive state */
-#define OLDFDRESET 24 /* reset FDC */
-
-#define OLDFD_RESET_IF_NEEDED 0
-#define OLDFD_RESET_IF_RAWCMD 1
-#define OLDFD_RESET_ALWAYS 2
-
-#define OLDFDGETFDCSTAT 25 /* get fdc state */
-#define OLDFDWERRORCLR  27 /* clear write error and badness information */
-#define OLDFDWERRORGET  28 /* get write error and badness information */
 
-#define OLDFDRAWCMD 30 /* send a raw command to the fdc */
+#include <linux/fd.h>
+
 
-#define OLDFDTWADDLE 40 /* flicker motor-on bit before reading a sector */
+#define OLDFDRAWCMD 0x020d /* send a raw command to the fdc */
 
 struct old_floppy_raw_cmd {
   void *data;
@@ -181,22 +147,6 @@
   int track;
 };
 
-struct old_floppy_fdc_state {	
-	int spec1; /* spec1 value last used */
-	int spec2; /* spec2 value last used */
-	int dtr;
-	unsigned char version;	/* FDC version code */
-	unsigned char dor;
-	int address; /* io address */
-	unsigned int rawcmd:2;
-	unsigned int reset:1;
-	unsigned int need_configure:1;
-	unsigned int perp_mode:2;
-	unsigned int has_fifo:1;
-};
-
-
-#include <linux/fd.h>
 #include <linux/errno.h>
 #include <linux/malloc.h>
 #include <linux/mm.h>
@@ -214,12 +164,12 @@
 #include <asm/segment.h>
 
 #define MAJOR_NR FLOPPY_MAJOR
+
 #include <linux/blk.h>
 
 
-/*
- * Dma Memory related stuff
- */
+/* Dma Memory related stuff */
+
 /* Pure 2^n version of get_order */
 static inline int __get_order (int size)
 {
@@ -228,7 +178,7 @@
 #ifdef  _ASM_IO_H2
 	__asm__ __volatile__("bsr %1,%0"
 			     : "=r" (order)
-			     : "r" (size / PAGE_SIZE) );
+			     : "r" (size / PAGE_SIZE));
 #else
 	for (order = 0; order < NR_MEM_LISTS; ++order)
 		if (size <= (PAGE_SIZE << order))
@@ -246,6 +196,8 @@
 	return __get_dma_pages(GFP_KERNEL,order);
 }
 
+/* End dma memory related stuff */
+
 static unsigned int fake_change = 0;
 static int initialising=1;
 
@@ -253,12 +205,12 @@
 	return  (MINOR(x)>>2) & 0x1f;
 }
 static inline int DRIVE(kdev_t x) {
-	return (MINOR(x)&0x03) | ((MINOR(x)&0x80 ) >> 5);
+	return (MINOR(x)&0x03) | ((MINOR(x)&0x80) >> 5);
 }
 #define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
-#define UNIT(x) ( (x) & 0x03 )		/* drive on fdc */
-#define FDC(x) ( ((x) & 0x04) >> 2 )  /* fdc of drive */
-#define REVDRIVE(fdc, unit) ( (unit) + ((fdc) << 2 ))
+#define UNIT(x) ((x) & 0x03)		/* drive on fdc */
+#define FDC(x) (((x) & 0x04) >> 2)  /* fdc of drive */
+#define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2))
 				/* reverse mapping from unit and fdc to drive */
 #define DP (&drive_params[current_drive])
 #define DRS (&drive_state[current_drive])
@@ -287,6 +239,8 @@
 #define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2)
 #define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH)
 
+#define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x)))
+
 /* read/write */
 #define COMMAND raw_cmd->cmd[0]
 #define DR_SELECT raw_cmd->cmd[1]
@@ -332,7 +286,7 @@
 
 #define SEL_DLY (2*HZ/100)
 
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof( (x)[0] ))
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 /*
  * this struct defines the different floppy drive types.
  */
@@ -439,10 +393,10 @@
 };
 
 #define	NUMBER(x)	(sizeof(x) / sizeof(*(x)))
-#define SECTSIZE ( _FD_SECTSIZE(*floppy))
+#define SECTSIZE (_FD_SECTSIZE(*floppy))
 
 /* Auto-detection: Disk type used until the next media change occurs. */
-struct floppy_struct *current_type[N_DRIVE] = {
+static struct floppy_struct *current_type[N_DRIVE] = {
 	NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL
 };
@@ -451,7 +405,7 @@
  * User-provided type information. current_type points to
  * the respective entry of this array.
  */
-struct floppy_struct user_params[N_DRIVE];
+static struct floppy_struct user_params[N_DRIVE];
 
 static int floppy_sizes[256];
 static int floppy_blocksizes[256] = { 0, };
@@ -464,7 +418,6 @@
 static int probing = 0;
 
 /* Synchronization of FDC access. */
-#define FD_COMMAND_DETECT -2
 #define FD_COMMAND_NONE -1
 #define FD_COMMAND_ERROR 2
 #define FD_COMMAND_OKAY 3
@@ -472,8 +425,8 @@
 static volatile int command_status = FD_COMMAND_NONE, fdc_busy = 0;
 static struct wait_queue *fdc_wait = NULL, *command_done = NULL;
 #define NO_SIGNAL (!(current->signal & ~current->blocked) || !interruptible)
-#define CALL(x) if( (x) == -EINTR) return -EINTR
-#define ECALL(x) if((ret = (x))) return ret;
+#define CALL(x) if ((x) == -EINTR) return -EINTR
+#define ECALL(x) if ((ret = (x))) return ret;
 #define _WAIT(x,i) CALL(ret=wait_til_done((x),i))
 #define WAIT(x) _WAIT((x),interruptible)
 #define IWAIT(x) _WAIT((x),1)
@@ -497,12 +450,12 @@
  * corrupted/lost. Alignment of these is enforced in boot/head.S.
  * Note that you must not change the sizes below without updating head.S.
  */
-char *floppy_track_buffer=0;
-int max_buffer_sectors=0;
+static char *floppy_track_buffer=0;
+static int max_buffer_sectors=0;
 
-int *errors;
+static int *errors;
 typedef void (*done_f)(int);
-struct cont_t {
+static struct cont_t {
 	void (*interrupt)(void); /* this is called after the interrupt of the
 				  * main command */
 	void (*redo)(void); /* this is called to retry the operation */
@@ -527,7 +480,7 @@
  * reset doesn't need to be tested before sending commands, because
  * output_byte is automatically disabled when reset is set.
  */
-#define CHECK_RESET { if ( FDCS->reset ){ reset_fdc(); return ; } }
+#define CHECK_RESET { if (FDCS->reset){ reset_fdc(); return; } }
 static void reset_fdc(void);
 
 /*
@@ -559,7 +512,7 @@
 static unsigned char sector_t; /* sector in track */
 
 #ifdef DEBUGT
-long unsigned debugtimer;
+static long unsigned debugtimer;
 #endif
 
 /*
@@ -576,8 +529,8 @@
 static inline void debugt(const char *message)
 {
 #ifdef DEBUGT
-	if ( DP->flags & DEBUGT )
-		printk("%s dtime=%lu\n", message, jiffies-debugtimer );
+	if (DP->flags & DEBUGT)
+		printk("%s dtime=%lu\n", message, jiffies-debugtimer);
 #endif
 }
 
@@ -601,11 +554,11 @@
 
 #define OLOGSIZE 20
 
-void (*lasthandler)(void) = NULL;
-int interruptjiffies=0;
-int resultjiffies=0;
-int resultsize=0;
-int lastredo=0;
+static void (*lasthandler)(void) = NULL;
+static int interruptjiffies=0;
+static int resultjiffies=0;
+static int resultsize=0;
+static int lastredo=0;
 
 static struct output_log {
 	unsigned char data;
@@ -619,11 +572,9 @@
 #define CURRENTD -1
 #define MAXTIMEOUT -2
 
-
-
 static void reschedule_timeout(int drive, const char *message, int marg)
 {
-	if (drive == CURRENTD )
+	if (drive == CURRENTD)
 		drive = current_drive;
 	del_timer(&fd_timeout);
 	if (drive < 0 || drive > N_DRIVE) {
@@ -640,6 +591,25 @@
 	timeout_message = message;
 }
 
+static int maximum(int a, int b)
+{
+	if(a > b)
+		return a;
+	else
+		return b;
+}
+#define INFBOUND(a,b) (a)=maximum((a),(b));
+
+static int minimum(int a, int b)
+{
+	if(a < b)
+		return a;
+	else
+		return b;
+}
+#define SUPBOUND(a,b) (a)=minimum((a),(b));
+
+
 /*
  * Bottom half floppy driver.
  * ==========================
@@ -677,9 +647,9 @@
 {
 	int fdc=FDC(drive);
 #ifdef FLOPPY_SANITY_CHECK
-	if(jiffies < UDP->select_delay + UDRS->select_date)
+	if (jiffies < UDP->select_delay + UDRS->select_date)
 		DPRINT("WARNING disk change called early\n");
-	if(! (FDCS->dor & (0x10 << UNIT(drive))) ||
+	if (!(FDCS->dor & (0x10 << UNIT(drive))) ||
 	   (FDCS->dor & 3) != UNIT(drive) ||
 	   fdc != FDC(drive)){
 		DPRINT("probing disk change on unselected drive\n");
@@ -698,9 +668,9 @@
 #endif
 	if (UDP->flags & FD_BROKEN_DCL)
 		return UTESTF(FD_DISK_CHANGED);
-	if( (fd_inb(FD_DIR) ^ UDP->flags) & 0x80){
+	if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80){
 		USETF(FD_VERIFY); /* verify write protection */
-		if(UDRS->maxblock){
+		if (UDRS->maxblock){
 			/* mark it changed */
 			USETF(FD_DISK_CHANGED);
 
@@ -725,21 +695,21 @@
 
 static inline int is_selected(int dor, int unit)
 {
-	return ( (dor  & (0x10 << unit)) && (dor &3) == unit);
+	return ((dor  & (0x10 << unit)) && (dor &3) == unit);
 }
 
 static int set_dor(int fdc, char mask, char data)
 {
 	register unsigned char drive, unit, newdor,olddor;
 
-	if(FDCS->address == -1)
+	if (FDCS->address == -1)
 		return -1;
 
 	olddor = FDCS->dor;
 	newdor =  (olddor & mask) | data;
-	if ( newdor != olddor ){
+	if (newdor != olddor){
 		unit = olddor & 0x3;
-		if(is_selected(olddor, unit) && !is_selected(newdor,unit)){
+		if (is_selected(olddor, unit) && !is_selected(newdor,unit)){
 			drive = REVDRIVE(fdc,unit);
 #ifdef DCL_DEBUG
 			if (UDP->flags & FD_DEBUG){
@@ -752,14 +722,14 @@
 		fd_outb(newdor, FD_DOR);
 
 		unit = newdor & 0x3;
-		if(!is_selected(olddor, unit) && is_selected(newdor,unit)){
+		if (!is_selected(olddor, unit) && is_selected(newdor,unit)){
 			drive = REVDRIVE(fdc,unit);
 			UDRS->select_date = jiffies;
 		}
 	}
-	if ( newdor & 0xf0 )
+	if (newdor & 0xf0)
 		floppy_grab_irq_and_dma();
-	if( olddor & 0xf0 )
+	if (olddor & 0xf0)
 		floppy_release_irq_and_dma();
 	return olddor;
 }
@@ -783,9 +753,9 @@
 	FDCS->need_configure = 1;
 	FDCS->perp_mode = 1;
 	FDCS->rawcmd = 0;
-	for ( drive = 0; drive < N_DRIVE; drive++)
+	for (drive = 0; drive < N_DRIVE; drive++)
 		if (FDC(drive) == fdc &&
-		    ( mode || UDRS->track != NEED_1_RECAL))
+		    (mode || UDRS->track != NEED_1_RECAL))
 			UDRS->track = NEED_2_RECAL;
 }
 
@@ -796,18 +766,22 @@
 		fdc = FDC(drive);
 		current_drive = drive;
 	}
+	if (fdc != 1 && fdc != 0) {
+		printk("bad fdc value\n");
+		return;
+	}
 	set_dor(fdc,~0,8);
 	set_dor(1-fdc, ~8, 0);
-	if ( FDCS->rawcmd == 2 )
+	if (FDCS->rawcmd == 2)
 		reset_fdc_info(1);
-	if ( fd_inb(FD_STATUS) != STATUS_READY )
+	if (fd_inb(FD_STATUS) != STATUS_READY)
 		FDCS->reset = 1;
 }
 
 /* locks the driver */
 static int lock_fdc(int drive, int interruptible)
 {
-	if(!usage_count){
+	if (!usage_count){
 		printk("trying to lock fdc while usage count=0\n");
 		return -1;
 	}
@@ -815,20 +789,20 @@
 	cli();
 	while (fdc_busy && NO_SIGNAL)
 		interruptible_sleep_on(&fdc_wait);
-	if(fdc_busy){
+	if (fdc_busy){
 		sti();
 		return -EINTR;
 	}
 	fdc_busy = 1;
 	sti();
 	command_status = FD_COMMAND_NONE;
-	set_fdc(drive);
 	reschedule_timeout(drive, "lock fdc", 0);
+	set_fdc(drive);
 	return 0;
 }
 
 #define LOCK_FDC(drive,interruptible) \
-if(lock_fdc(drive,interruptible)) return -EINTR;
+if (lock_fdc(drive,interruptible)) return -EINTR;
 
 
 /* unlocks the driver */
@@ -838,7 +812,7 @@
 	if (!fdc_busy)
 		DPRINT("FDC access conflict!\n");
 
-	if ( DEVICE_INTR )
+	if (DEVICE_INTR)
 		DPRINT1("device interrupt still active at FDC release: %p!\n",
 			DEVICE_INTR);
 	command_status = FD_COMMAND_NONE;
@@ -854,7 +828,7 @@
 {
 	unsigned char mask = ~(0x10 << UNIT(nr));
 
-	set_dor( FDC(nr), mask, 0 );
+	set_dor(FDC(nr), mask, 0);
 }
 
 static struct timer_list motor_off_timer[N_DRIVE] = {
@@ -874,17 +848,17 @@
 	unsigned long volatile delta;
 	register int fdc=FDC(drive);
 
-	if( !(FDCS->dor & ( 0x10 << UNIT(drive))))
+	if (!(FDCS->dor & (0x10 << UNIT(drive))))
 		return;
 
 	del_timer(motor_off_timer+drive);
 
 	/* make spindle stop in a position which minimizes spinup time
 	 * next time */
-	if (UDP->rps ){
+	if (UDP->rps){
 		delta = jiffies - UDRS->first_read_date + HZ -
 			UDP->spindown_offset;
-		delta = (( delta * UDP->rps) % HZ ) / UDP->rps;
+		delta = ((delta * UDP->rps) % HZ) / UDP->rps;
 		motor_off_timer[drive].expires = jiffies + UDP->spindown - delta;
 	}
 	add_timer(motor_off_timer+drive);
@@ -903,16 +877,16 @@
 		return;
 
 	saved_drive = current_drive;
-	for(i=0; i< N_DRIVE; i++){
-		drive = (saved_drive + i + 1 ) % N_DRIVE;
-		if ( UDRS->fd_ref == 0 || UDP->select_delay != 0)
+	for (i=0; i < N_DRIVE; i++){
+		drive = (saved_drive + i + 1) % N_DRIVE;
+		if (UDRS->fd_ref == 0 || UDP->select_delay != 0)
 			continue; /* skip closed drives */
 		set_fdc(drive);
-		if(! (set_dor( fdc, ~3, UNIT(drive) | ( 0x10 << UNIT(drive))) &
+		if (!(set_dor(fdc, ~3, UNIT(drive) | (0x10 << UNIT(drive))) &
 		      (0x10 << UNIT(drive))))
 			/* switch the motor off again, if it was off to
 			 * begin with */
-			set_dor( fdc, ~( 0x10 << UNIT(drive) ), 0 );
+			set_dor(fdc, ~(0x10 << UNIT(drive)), 0);
 	}
 	set_fdc(saved_drive);
 }
@@ -929,7 +903,7 @@
 	}
 #endif
 
-	if ( disk_change(current_drive) ){
+	if (disk_change(current_drive)){
 		DPRINT("disk removed during i/o\n");
 		floppy_shutdown();
 	} else {
@@ -949,14 +923,14 @@
 /* waits for a delay (spinup or select) to pass */
 static int wait_for_completion(int delay, timeout_fn function)
 {
-	if ( FDCS->reset ){
+	if (FDCS->reset){
 		reset_fdc(); /* do the reset during sleep to win time
 			      * if we don't need to sleep, it's a good
 			      * occasion anyways */
 		return 1;
 	}
 
-	if ( jiffies < delay ){
+	if (jiffies < delay){
 		del_timer(&fd_timer);
 		fd_timer.function = function;
 		fd_timer.expires = delay;
@@ -972,7 +946,7 @@
 	unsigned long flags;
 	save_flags(flags);
 	cli();
-	if(!hlt_disabled){
+	if (!hlt_disabled){
 		hlt_disabled=1;
 #ifdef HAVE_DISABLE_HLT
 		disable_hlt();
@@ -986,7 +960,7 @@
 	unsigned long flags;
 	save_flags(flags);
 	cli();
-	if(hlt_disabled){
+	if (hlt_disabled){
 		hlt_disabled=0;
 #ifdef HAVE_DISABLE_HLT
 		enable_hlt();
@@ -1003,36 +977,15 @@
 		int i;
 
 		printk("zero dma transfer size:");
-		for(i=0; i< raw_cmd->cmd_count; i++)
+		for (i=0; i < raw_cmd->cmd_count; i++)
 			printk("%x,", raw_cmd->cmd[i]);
 		printk("\n");
 		cont->done(0);
 		FDCS->reset = 1;
 		return;
 	}
-#if 0
-	/* disabled because of new buffer location for raw cmd */
-	if ((!CURRENT ||
-	     CURRENT->buffer != raw_cmd->kernel_data ||
-	     raw_cmd->length > 512 * CURRENT->nr_sectors) &&
-	    (raw_cmd->kernel_data < floppy_track_buffer ||
-	     raw_cmd->kernel_data + raw_cmd->length >
-	     floppy_track_buffer + 1024 * max_buffer_sectors)){
-		printk("bad address. start=%p lg=%lx tb=%p\n",
-		       raw_cmd->kernel_data, raw_cmd->length, 
-		       floppy_track_buffer);
-		if ( CURRENT ){
-			printk("buffer=%p nr=%lx cnr=%lx\n",
-			       CURRENT->buffer, CURRENT->nr_sectors,
-			       CURRENT->current_nr_sectors);
-		}
-		cont->done(0);
-		FDCS->reset=1;
-		return;
-	}
-#endif
-	if ((long) raw_cmd->kernel_data % 512 ){
-		printk("non aligned address: %p\n", raw_cmd->kernel_data );
+	if ((long) raw_cmd->kernel_data % 512){
+		printk("non aligned address: %p\n", raw_cmd->kernel_data);
 		cont->done(0);
 		FDCS->reset=1;
 		return;
@@ -1050,7 +1003,7 @@
 	fd_disable_dma();
 	fd_clear_dma_ff();
 	fd_set_dma_mode((raw_cmd->flags & FD_RAW_READ)?
-	                 DMA_MODE_READ : DMA_MODE_WRITE);
+			DMA_MODE_READ : DMA_MODE_WRITE);
 	fd_set_dma_addr(virt_to_bus(raw_cmd->kernel_data));
 	fd_set_dma_count(raw_cmd->length);
 	fd_enable_dma();
@@ -1067,7 +1020,7 @@
 
 	if (FDCS->reset)
 		return -1;
-	for(counter = 0 ; counter < 10000 && !FDCS->reset ; counter++) {
+	for (counter = 0; counter < 10000 && !FDCS->reset; counter++) {
 		rstatus = fd_inb(FD_STATUS);
 		status =  rstatus &(STATUS_READY|STATUS_DIR|STATUS_DMA);
 		if (!(status & STATUS_READY))
@@ -1086,12 +1039,12 @@
 			break;
 	}
 	FDCS->reset = 1;
-	if ( !initialising )
+	if (!initialising)
 		DPRINT2("Unable to send byte %x to FDC. Status=%x\n",
 			byte, status);
 	return -1;
 }
-#define LAST_OUT(x) if(output_byte(x)){ reset_fdc();return;}
+#define LAST_OUT(x) if (output_byte(x)){ reset_fdc();return;}
 
 /* gets the response from the fdc */
 static int result(void)
@@ -1100,7 +1053,7 @@
 
 	if (FDCS->reset)
 		return -1;
-	for (counter = 0 ; counter < 10000 && !FDCS->reset ; counter++) {
+	for (counter = 0; counter < 10000 && !FDCS->reset; counter++) {
 		status = fd_inb(FD_STATUS)&
 			(STATUS_DIR|STATUS_READY|STATUS_BUSY|STATUS_DMA);
 		if (!(status & STATUS_READY))
@@ -1112,7 +1065,7 @@
 #endif
 			return i;
 		}
-		if (status & STATUS_DMA )
+		if (status & STATUS_DMA)
 			break;
 		if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) {
 			if (i >= MAX_REPLIES) {
@@ -1123,7 +1076,7 @@
 		}
 	}
 	FDCS->reset = 1;
-	if ( !initialising )
+	if (!initialising)
 		DPRINT3("Getstatus times out (%x) on fdc %d [%d]\n",
 			status, fdc, i);
 	return -1;
@@ -1157,7 +1110,7 @@
 	} else
 		perp_mode = 0;
 
-	if ( FDCS->perp_mode == perp_mode )
+	if (FDCS->perp_mode == perp_mode)
 		return;
 	if (FDCS->version >= FDC_82077_ORIG && FDCS->has_fifo) {
 		output_byte(FD_PERPENDICULAR);
@@ -1199,7 +1152,7 @@
 	int hut_max_code = 0xf;
 
 	if (FDCS->need_configure && FDCS->has_fifo) {
-		if ( FDCS->reset )
+		if (FDCS->reset)
 			return;
 		/* Turn on FIFO for 82077-class FDC (improves performance) */
 		/* TODO: lock this in via LOCK during initialization */
@@ -1207,7 +1160,7 @@
 		output_byte(0);
 		output_byte(0x2A);	/* FIFO on, polling off, 10 byte threshold */
 		output_byte(0);		/* precompensation from track 0 upwards */
-		if ( FDCS->reset ){
+		if (FDCS->reset){
 			FDCS->has_fifo=0;
 			return;
 		}
@@ -1235,10 +1188,8 @@
 
 	/* Convert step rate from microseconds to milliseconds and 4 bits */
 	srt = 16 - (DP->srt*scale_dtr/1000 + NOMINAL_DTR - 1)/NOMINAL_DTR;
-	if (srt > 0xf)
-		srt = 0xf;
-	else if (srt < 0)
-		srt = 0;
+	SUPBOUND(srt, 0xf);
+	INFBOUND(srt, 0);
 
 	hlt = (DP->hlt*scale_dtr/2 + NOMINAL_DTR - 1)/NOMINAL_DTR;
 	if (hlt < 0x01)
@@ -1271,7 +1222,7 @@
 static int fdc_dtr(void)
 {
 	/* If data rate not already set to desired value, set it. */
-	if ( raw_cmd->rate == FDCS->dtr)
+	if (raw_cmd->rate == FDCS->dtr)
 		return 0;
 
 	/* Set dtr */
@@ -1323,10 +1274,10 @@
 			} else if (ST1 & ST1_ND) {
 				SETF(FD_NEED_TWADDLE);
 			} else if (ST1 & ST1_OR) {
-				if (DP->flags & FTD_MSG )
+				if (DP->flags & FTD_MSG)
 					DPRINT("Over/Underrun - retrying\n");
 				bad = 0;
-			}else if(*errors >= DP->max_errors.reporting){
+			}else if (*errors >= DP->max_errors.reporting){
 				DPRINT("");
 				if (ST0 & ST0_ECE) {
 					printk("Recalibrate failed!");
@@ -1353,7 +1304,7 @@
 				printk("\n");
 
 			}
-			if ( ST2 & ST2_WC || ST2 & ST2_BC)
+			if (ST2 & ST2_WC || ST2 & ST2_BC)
 				/* wrong cylinder => recal */
 				DRS->track = NEED_2_RECAL;
 			return bad;
@@ -1381,7 +1332,7 @@
 	timeout_fn function;
 
 	flags = raw_cmd->flags;
-	if ( flags & ( FD_RAW_READ | FD_RAW_WRITE))
+	if (flags & (FD_RAW_READ | FD_RAW_WRITE))
 		flags |= FD_RAW_INTR;
 
 	if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)){
@@ -1390,7 +1341,7 @@
 		 * again just before spinup completion. Beware that
 		 * after scandrives, we must again wait for selection.
 		 */
-		if ( ready_date > jiffies + DP->select_delay){
+		if (ready_date > jiffies + DP->select_delay){
 			ready_date -= DP->select_delay;
 			function = (timeout_fn) floppy_start;
 		} else
@@ -1402,28 +1353,28 @@
 	}
 	dflags = DRS->flags;
 
-	if ( (flags & FD_RAW_READ) || (flags & FD_RAW_WRITE))
+	if ((flags & FD_RAW_READ) || (flags & FD_RAW_WRITE))
 		setup_DMA();
 
-	if ( flags & FD_RAW_INTR )
+	if (flags & FD_RAW_INTR)
 		SET_INTR(main_command_interrupt);
 
 	r=0;
-	for(i=0; i< raw_cmd->cmd_count; i++)
-		r|=output_byte( raw_cmd->cmd[i] );
+	for (i=0; i< raw_cmd->cmd_count; i++)
+		r|=output_byte(raw_cmd->cmd[i]);
 
 #ifdef DEBUGT
 	debugt("rw_command: ");
 #endif
-	if ( r ){
+	if (r){
 		reset_fdc();
 		return;
 	}
 
-	if ( ! ( flags & FD_RAW_INTR )){
+	if (!(flags & FD_RAW_INTR)){
 		inr = result();
 		cont->interrupt();
-	} else if ( flags & FD_RAW_NEED_DISK )
+	} else if (flags & FD_RAW_NEED_DISK)
 		fd_watchdog();
 }
 
@@ -1438,7 +1389,7 @@
 #ifdef DEBUGT
 	debugt("seek interrupt:");
 #endif
-	if (inr != 2 || (ST0 & 0xF8) != 0x20 ) {
+	if (inr != 2 || (ST0 & 0xF8) != 0x20) {
 		DPRINT("seek failed\n");
 		DRS->track = NEED_2_RECAL;
 		cont->error();
@@ -1463,9 +1414,9 @@
 {
 	if (TESTF(FD_VERIFY)) {
 		/* check write protection */
-		output_byte( FD_GETSTATUS );
-		output_byte( UNIT(current_drive) );
-		if ( result() != 1 ){
+		output_byte(FD_GETSTATUS);
+		output_byte(UNIT(current_drive));
+		if (result() != 1){
 			FDCS->reset = 1;
 			return;
 		}
@@ -1477,7 +1428,7 @@
 			DPRINT1("wp=%x\n",ST3 & 0x40);
 		}
 #endif
-		if (!( ST3  & 0x40))
+		if (!(ST3  & 0x40))
 			SETF(FD_DISK_WRITABLE);
 		else
 			CLEARF(FD_DISK_WRITABLE);
@@ -1508,7 +1459,7 @@
 		cont->redo();
 		return;
 	}
-	if ( DRS->track <= NEED_1_RECAL ){
+	if (DRS->track <= NEED_1_RECAL){
 		recalibrate_floppy();
 		return;
 	} else if (TESTF(FD_DISK_NEWCHANGE) &&
@@ -1516,10 +1467,10 @@
 		   (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) {
 		/* we seek to clear the media-changed condition. Does anybody
 		 * know a more elegant way, which works on all drives? */
-		if ( raw_cmd->track )
+		if (raw_cmd->track)
 			track = raw_cmd->track - 1;
 		else {
-			if(DP->flags & FD_SILENT_DCL_CLEAR){
+			if (DP->flags & FD_SILENT_DCL_CLEAR){
 				set_dor(fdc, ~(0x10 << UNIT(current_drive)), 0);
 				blind_seek = 1;
 				raw_cmd->flags |= FD_RAW_NEED_SEEK;
@@ -1551,7 +1502,7 @@
 #ifdef DEBUGT
 	debugt("recal interrupt:");
 #endif
-	if (inr !=2 )
+	if (inr !=2)
 		FDCS->reset = 1;
 	else if (ST0 & ST0_ECE) {
 	       	switch(DRS->track){
@@ -1610,29 +1561,29 @@
 static void unexpected_floppy_interrupt(void)
 {
 	int i;
-	if ( initialising )
+	if (initialising)
 		return;
-	if(print_unex){
+	if (print_unex){
 		DPRINT("unexpected interrupt\n");
-		if ( inr >= 0 )
-			for(i=0; i<inr; i++)
-				printk("%d %x\n", i, reply_buffer[i] );
+		if (inr >= 0)
+			for (i=0; i<inr; i++)
+				printk("%d %x\n", i, reply_buffer[i]);
 	}
 	while(1){
 		output_byte(FD_SENSEI);
 		inr=result();
-		if ( inr != 2 )
+		if (inr != 2)
 			break;
-		if(print_unex){
+		if (print_unex){
 			printk("sensei\n");
-			for(i=0; i<inr; i++)
-				printk("%d %x\n", i, reply_buffer[i] );
+			for (i=0; i<inr; i++)
+				printk("%d %x\n", i, reply_buffer[i]);
 		}
 	}
 	FDCS->reset = 1;
 }
 
-struct tq_struct floppy_tq =
+static struct tq_struct floppy_tq =
 { 0, 0, (void *) (void *) unexpected_floppy_interrupt, 0 };
 
 /* interrupt handler */
@@ -1645,7 +1596,7 @@
 
 	floppy_enable_hlt();
 	CLEAR_INTR;
-	if ( fdc >= N_FDC || FDCS->address == -1){
+	if (fdc >= N_FDC || FDCS->address == -1){
 		/* we don't even know which FDC is the culprit */
 		printk("DOR0=%x\n", fdc_state[0].dor);
 		printk("floppy interrupt on bizarre fdc %d\n",fdc);
@@ -1659,11 +1610,11 @@
 		is_alive("unexpected");
 		return;
 	}
-	if ( inr == 0 ){
+	if (inr == 0){
 		do {
 			output_byte(FD_SENSEI);
 			inr = result();
-		} while ( (ST0 & 0x83) != UNIT(current_drive) && inr == 2);
+		} while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2);
 	}
 	floppy_tq.routine = (void *)(void *) handler;
 	queue_task_irq(&floppy_tq, &tq_timer);
@@ -1690,8 +1641,10 @@
 #endif
 	/* fdc_specify();	   reprogram fdc */
 	result();		/* get the status ready for set_fdc */
-	if ( FDCS->reset )
+	if (FDCS->reset) {
+		printk("reset set in interrupt, calling %p\n", cont->error);
 		cont->error(); /* a reset just after a reset. BAD! */
+	}
 	cont->redo();
 }
 
@@ -1704,12 +1657,12 @@
 	SET_INTR(reset_interrupt);
 	FDCS->reset = 0;
 	reset_fdc_info(0);
-	if ( FDCS->version >= FDC_82077 )
-		fd_outb(0x80 | ( FDCS->dtr &3), FD_STATUS);
+	if (FDCS->version >= FDC_82077)
+		fd_outb(0x80 | (FDCS->dtr &3), FD_STATUS);
 	else {
 		fd_outb(FDCS->dor & ~0x04, FD_DOR);
 		udelay(FD_RESET_DELAY);
-		fd_outb(FDCS->dor, FD_DOR);
+		outb(FDCS->dor, FD_DOR);
 	}
 }
 
@@ -1731,37 +1684,28 @@
 #ifdef FLOPPY_SANITY_CHECK
 	printk("timeout_message=%s\n", timeout_message);
 	printk("last output bytes:\n");
-	for(i=0; i < OLOGSIZE; i++)
+	for (i=0; i < OLOGSIZE; i++)
 		printk("%2x %2x %ld\n",
 		       output_log[(i+output_log_pos) % OLOGSIZE].data,
 		       output_log[(i+output_log_pos) % OLOGSIZE].status,
 		       output_log[(i+output_log_pos) % OLOGSIZE].jiffies);
 	printk("last result at %d\n", resultjiffies);
 	printk("last redo_fd_request at %d\n", lastredo);
-	for(i=0; i<resultsize; i++){
+	for (i=0; i<resultsize; i++){
 		printk("%2x ", reply_buffer[i]);
 	}
 	printk("\n");
 #endif
 
-#if 0
-	for(i=0; i<N_FDC; i++){
-		if(FDCS->address != -1){
-			printk("dor %d = %x\n", i, fdc_state[i].dor );
-			fd_outb(fdc_state[i].address+2, fdc_state[i].dor);
-			udelay(1000); /* maybe we'll catch an interrupt... */
-		}
-	}
-#endif
 	printk("status=%x\n", fd_inb(FD_STATUS));
 	printk("fdc_busy=%d\n", fdc_busy);
-	if( DEVICE_INTR)
+	if (DEVICE_INTR)
 		printk("DEVICE_INTR=%p\n", DEVICE_INTR);
-	if(floppy_tq.sync)
+	if (floppy_tq.sync)
 		printk("floppy_tq.routine=%p\n", floppy_tq.routine);
-	if(fd_timer.prev)
+	if (fd_timer.prev)
 		printk("fd_timer.function=%p\n", fd_timer.function);
-	if(fd_timeout.prev){
+	if (fd_timeout.prev){
 		printk("timer_table=%p\n",fd_timeout.function);
 		printk("expires=%ld\n",fd_timeout.expires-jiffies);
 		printk("now=%ld\n",jiffies);
@@ -1774,18 +1718,18 @@
 
 static void floppy_shutdown(void)
 {
-	if(!initialising)
+	if (!initialising)
 		show_floppy();
 	CLEAR_INTR;
 	floppy_tq.routine = (void *)(void *) empty;
-	del_timer( &fd_timer);
+	del_timer(&fd_timer);
 	sti();
 
 	floppy_enable_hlt();
 	fd_disable_dma();
 	/* avoid dma going to a random drive after shutdown */
 
-	if(!initialising)
+	if (!initialising)
 		DPRINT("floppy timeout\n");
 	FDCS->reset = 1;
 	if (cont){
@@ -1800,14 +1744,14 @@
 /*typedef void (*timeout_fn)(unsigned long);*/
 
 /* start motor, check media-changed condition and write protection */
-static int start_motor( void (*function)(void)  )
+static int start_motor(void (*function)(void) )
 {
 	int mask, data;
 
 	mask = 0xfc;
 	data = UNIT(current_drive);
 	if (!(raw_cmd->flags & FD_RAW_NO_MOTOR)){
-		if(!(FDCS->dor & ( 0x10 << UNIT(current_drive) ) )){
+		if (!(FDCS->dor & (0x10 << UNIT(current_drive)))){
 			set_debugt();
 			/* no read since this drive is running */
 			DRS->first_read_date = 0;
@@ -1816,12 +1760,12 @@
 			data |= (0x10 << UNIT(current_drive));
 		}
 	} else
-		if (FDCS->dor & ( 0x10 << UNIT(current_drive) ) )
+		if (FDCS->dor & (0x10 << UNIT(current_drive)))
 			mask &= ~(0x10 << UNIT(current_drive));
 
 	/* starts motor and selects floppy */
 	del_timer(motor_off_timer + current_drive);
-	set_dor( fdc, mask, data);
+	set_dor(fdc, mask, data);
 
 	/* wait_for_completion also schedules reset if needed. */
 	return(wait_for_completion(DRS->select_date+DP->select_delay,
@@ -1831,8 +1775,8 @@
 static void floppy_ready(void)
 {
 	CHECK_RESET;
-	if(start_motor(floppy_ready)) return;
-	if(fdc_dtr()) return;
+	if (start_motor(floppy_ready)) return;
+	if (fdc_dtr()) return;
 
 #ifdef DCL_DEBUG
 	if (DP->flags & FD_DEBUG){
@@ -1840,13 +1784,13 @@
 	}
 #endif
 
-	if(!(raw_cmd->flags & FD_RAW_NO_MOTOR) &&
+	if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) &&
 	   disk_change(current_drive) &&
 	   !DP->select_delay)
 		twaddle(); /* this clears the dcl on certain drive/controller
 			    * combinations */
 
-	if ( raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){
+	if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){
 		perpendicular_mode();
 		fdc_specify(); /* must be done here because of hut, hlt ... */
 		seek_floppy();
@@ -1897,7 +1841,7 @@
 	(done_f)empty
 };
 
-static int wait_til_done(void (*handler)(void ), int interruptible)
+static int wait_til_done(void (*handler)(void), int interruptible)
 {
 	int ret;
 
@@ -1907,12 +1851,12 @@
 	cli();
 	while(command_status < 2 && NO_SIGNAL){
 		is_alive("wait_til_done");
-		if(interruptible)
+		if (interruptible)
 			interruptible_sleep_on(&command_done);
 		else
 			sleep_on(&command_done);
 	}
-	if(command_status < 2){
+	if (command_status < 2){
 		floppy_shutdown();
 		sti();
 		process_fd_request();
@@ -1920,9 +1864,9 @@
 	}
 	sti();
 
-	if ( FDCS->reset )
+	if (FDCS->reset)
 		command_status = FD_COMMAND_ERROR;
-	if ( command_status == FD_COMMAND_OKAY )
+	if (command_status == FD_COMMAND_OKAY)
 		ret=0;
 	else
 		ret=-EIO;
@@ -1964,12 +1908,12 @@
 
 	probed_format = DRS->probed_format;
 	while(1){
-		if ( probed_format >= 8 ||
-		     ! DP->autodetect[probed_format] ){
+		if (probed_format >= 8 ||
+		     !DP->autodetect[probed_format]){
 			DRS->probed_format = 0;
 			return 1;
 		}
-		if ( floppy_type[DP->autodetect[probed_format]].sect ){
+		if (floppy_type[DP->autodetect[probed_format]].sect){
 			DRS->probed_format = probed_format;
 			return 0;
 		}
@@ -1979,14 +1923,13 @@
 
 static void bad_flp_intr(void)
 {
-	if ( probing ){
+	if (probing){
 		DRS->probed_format++;
-		if ( !next_valid_format())
+		if (!next_valid_format())
 			return;
 	}
 	(*errors)++;
-	if (*errors > DRWE->badness)
-	        DRWE->badness = *errors;
+	INFBOUND(DRWE->badness, *errors);
 	if (*errors > DP->max_errors.abort)
 		cont->done(0);
 	if (*errors > DP->max_errors.reset)
@@ -2020,9 +1963,9 @@
 	cont->redo();
 }
 
-#define CODE2SIZE (ssize = ( ( 1 << SIZECODE ) + 3 ) >> 2)
-#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80 ) >>1))
-#define CT(x) ( (x) | 0x40 )
+#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2)
+#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1))
+#define CT(x) ((x) | 0x40)
 static void setup_format_params(int track)
 {
 	struct fparm {
@@ -2055,7 +1998,7 @@
 	track_shift = 2 * head_shift + 3;
 
 	/* position of logical sector 1 on this track */
-	n = (track_shift * format_req.track + head_shift * format_req.head )
+	n = (track_shift * format_req.track + head_shift * format_req.head)
 		% F_SECT_PER_TRACK;
 
 	/* determine interleave */
@@ -2147,20 +2090,19 @@
 		/* maintain values for invalidation on geometry
 		 * change */
 		block = current_count_sectors + CURRENT->sector;
-		if (block > DRS->maxblock)
-			DRS->maxblock=block;
-		if ( block > floppy->sect)
+		INFBOUND(DRS->maxblock, block);
+		if (block > floppy->sect)
 			DRS->maxtrack = 1;
 
 		/* unlock chained buffers */
 		while (current_count_sectors && CURRENT &&
-		       current_count_sectors >= CURRENT->current_nr_sectors ){
+		       current_count_sectors >= CURRENT->current_nr_sectors){
 			current_count_sectors -= CURRENT->current_nr_sectors;
 			CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
 			CURRENT->sector += CURRENT->current_nr_sectors;
 			end_request(1);
 		}
-		if ( current_count_sectors && CURRENT){
+		if (current_count_sectors && CURRENT){
 			/* "unlock" last subsector */
 			CURRENT->buffer += current_count_sectors <<9;
 			CURRENT->current_nr_sectors -= current_count_sectors;
@@ -2169,14 +2111,14 @@
 			return;
 		}
 
-		if ( current_count_sectors && ! CURRENT )
+		if (current_count_sectors && !CURRENT)
 			DPRINT("request list destroyed in floppy request done\n");
 
 	} else {
-		if(CURRENT->cmd == WRITE) {
+		if (CURRENT->cmd == WRITE) {
 			/* record write error information */
 			DRWE->write_errors++;
-			if(DRWE->write_errors == 1) {
+			if (DRWE->write_errors == 1) {
 				DRWE->first_error_sector = CURRENT->sector;
 				DRWE->first_error_generation = DRS->generation;
 			}
@@ -2192,7 +2134,7 @@
 {
 	int nr_sectors, ssize;
 
-	if ( ! DRS->first_read_date )
+	if (!DRS->first_read_date)
 		DRS->first_read_date = jiffies;
 
 	nr_sectors = 0;
@@ -2202,7 +2144,7 @@
 		(sector_t % floppy->sect) % ssize;
 
 #ifdef FLOPPY_SANITY_CHECK
-	if ( nr_sectors > current_count_sectors + ssize -
+	if (nr_sectors > current_count_sectors + ssize -
 	     (current_count_sectors + sector_t) % ssize +
 	     sector_t % ssize){
 		DPRINT2("long rw: %x instead of %lx\n",
@@ -2214,24 +2156,22 @@
 		       sector_t, ssize);
 	}
 #endif
-	if ( nr_sectors < 0 )
-		nr_sectors = 0;
-	if ( nr_sectors < current_count_sectors )
-		current_count_sectors = nr_sectors;
+	INFBOUND(nr_sectors,0);
+	SUPBOUND(current_count_sectors, nr_sectors);
 
 	switch (interpret_errors()){
 		case 2:
 			cont->redo();
 			return;
 		case 1:
-			if (  !current_count_sectors){
+			if (!current_count_sectors){
 				cont->error();
 				cont->redo();
 				return;
 			}
 			break;
 		case 0:
-			if (  !current_count_sectors){
+			if (!current_count_sectors){
 				cont->redo();
 				return;
 			}
@@ -2249,15 +2189,14 @@
 		probing = 0;
 	}
 
-	if ( CT(COMMAND) != FD_READ || 
-	     raw_cmd->kernel_data == CURRENT->buffer ){
+	if (CT(COMMAND) != FD_READ || 
+	     raw_cmd->kernel_data == CURRENT->buffer){
 		/* transfer directly from buffer */
 		cont->done(1);
-	} else if ( CT(COMMAND) == FD_READ){
+	} else if (CT(COMMAND) == FD_READ){
 		buffer_track = raw_cmd->track;
 		buffer_drive = current_drive;
-		if ( nr_sectors + sector_t > buffer_max )
-			buffer_max = nr_sectors + sector_t;
+		INFBOUND(buffer_max, nr_sectors + sector_t);
 	}
 	cont->redo();
 }
@@ -2275,7 +2214,7 @@
 
 	if (bh){
 		bh = bh->b_reqnext;
-		while ( bh && bh->b_data == base + size ){
+		while (bh && bh->b_data == base + size){
 			size += bh->b_size;
 			bh = bh->b_reqnext;
 		}
@@ -2286,11 +2225,10 @@
 /* Compute the maximal transfer size */
 static int transfer_size(int ssize, int max_sector, int max_size)
 {
-	if ( max_sector > sector_t + max_size)
-		max_sector = sector_t + max_size;
+	SUPBOUND(max_sector, sector_t + max_size);
 
 	/* alignment */
-	max_sector -= (max_sector % floppy->sect ) % ssize;
+	max_sector -= (max_sector % floppy->sect) % ssize;
 
 	/* transfer size, beginning not aligned */
 	current_count_sectors = max_sector - sector_t ;
@@ -2308,21 +2246,19 @@
 	char *buffer, *dma_buffer;
 	int size;
 
-	if ( max_sector > max_sector_2 )
-		max_sector = max_sector_2;
-
-	max_sector = transfer_size(ssize, max_sector, CURRENT->nr_sectors);
+	max_sector = transfer_size(ssize,
+				   minimum(max_sector, max_sector_2),
+				   CURRENT->nr_sectors);
 
 	if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE &&
-	    buffer_max > sector_t + CURRENT->nr_sectors){
-		current_count_sectors = buffer_max - sector_t;
-		if ( current_count_sectors > CURRENT->nr_sectors )
-			current_count_sectors = CURRENT->nr_sectors;
-	}
+	    buffer_max > sector_t + CURRENT->nr_sectors)
+		current_count_sectors = minimum(buffer_max - sector_t,
+						CURRENT->nr_sectors);
+
 	remaining = current_count_sectors << 9;
 #ifdef FLOPPY_SANITY_CHECK
 	if ((remaining >> 9) > CURRENT->nr_sectors  &&
-	    CT(COMMAND) == FD_WRITE ){
+	    CT(COMMAND) == FD_WRITE){
 		DPRINT("in copy buffer\n");
 		printk("current_count_sectors=%ld\n", current_count_sectors);
 		printk("remaining=%d\n", remaining >> 9);
@@ -2334,8 +2270,7 @@
 	}
 #endif
 
-	if ( max_sector > buffer_max )
-		buffer_max = max_sector;
+	buffer_max = maximum(max_sector, buffer_max);
 
 	dma_buffer = floppy_track_buffer + ((sector_t - buffer_min) << 9);
 
@@ -2343,44 +2278,42 @@
 	size = CURRENT->current_nr_sectors << 9;
 	buffer = CURRENT->buffer;
 
-	while ( remaining > 0){
-		if ( size > remaining )
-			size = remaining;
+	while (remaining > 0){
+		SUPBOUND(size, remaining);
 #ifdef FLOPPY_SANITY_CHECK
 		if (dma_buffer + size >
 		    floppy_track_buffer + (max_buffer_sectors << 10) ||
-		    dma_buffer < floppy_track_buffer ){
+		    dma_buffer < floppy_track_buffer){
 			DPRINT1("buffer overrun in copy buffer %d\n",
 				(int) ((floppy_track_buffer - dma_buffer) >>9));
 			printk("sector_t=%d buffer_min=%d\n",
 			       sector_t, buffer_min);
 			printk("current_count_sectors=%ld\n",
 			       current_count_sectors);
-			if ( CT(COMMAND) == FD_READ )
+			if (CT(COMMAND) == FD_READ)
 				printk("read\n");
-			if ( CT(COMMAND) == FD_READ )
+			if (CT(COMMAND) == FD_READ)
 				printk("write\n");
 			break;
 		}
-		if ( ((unsigned long)buffer) % 512 )
+		if (((unsigned long)buffer) % 512)
 			DPRINT1("%p buffer not aligned\n", buffer);
 #endif
-		if ( CT(COMMAND) == FD_READ ) {
+		if (CT(COMMAND) == FD_READ) {
 			fd_cacheflush(dma_buffer, size);
-			memcpy( buffer, dma_buffer, size);
-		}	
-		else {
-			memcpy( dma_buffer, buffer, size);
+			memcpy(buffer, dma_buffer, size);
+		} else {
+			memcpy(dma_buffer, buffer, size);
 			fd_cacheflush(dma_buffer, size);
-		}	
+		}
 		remaining -= size;
-		if ( !remaining)
+		if (!remaining)
 			break;
 
 		dma_buffer += size;
 		bh = bh->b_reqnext;
 #ifdef FLOPPY_SANITY_CHECK
-		if ( !bh){
+		if (!bh){
 			DPRINT("bh=null in copy buffer after copy\n");
 			break;
 		}
@@ -2389,8 +2322,8 @@
 		buffer = bh->b_data;
 	}
 #ifdef FLOPPY_SANITY_CHECK
-	if ( remaining ){
-		if ( remaining > 0 )
+	if (remaining){
+		if (remaining > 0)
 			max_sector -= remaining >> 9;
 		DPRINT1("weirdness: remaining %d\n", remaining>>9);
 	}
@@ -2433,21 +2366,20 @@
 
 	TRACK = CURRENT->sector / max_sector;
 	sector_t = CURRENT->sector % max_sector;
-	if ( floppy->track && TRACK >= floppy->track )
+	if (floppy->track && TRACK >= floppy->track)
 		return 0;
 	HEAD = sector_t / floppy->sect;
 
-	if (((floppy->stretch & FD_SWAPSIDES) || TESTF( FD_NEED_TWADDLE)) &&
-	    sector_t < floppy->sect )
+	if (((floppy->stretch & FD_SWAPSIDES) || TESTF(FD_NEED_TWADDLE)) &&
+	    sector_t < floppy->sect)
 		max_sector = floppy->sect;
 
 	/* 2M disks have phantom sectors on the first track */
-	if ( (floppy->rate & FD_2M ) && (!TRACK) && (!HEAD)){
+	if ((floppy->rate & FD_2M) && (!TRACK) && (!HEAD)){
 		max_sector = 2 * floppy->sect / 3;
 		if (sector_t >= max_sector){
-			current_count_sectors =  (floppy->sect - sector_t);
-			if ( current_count_sectors > CURRENT->nr_sectors )
-				current_count_sectors = CURRENT->nr_sectors;
+			current_count_sectors = minimum(floppy->sect - sector_t,
+							CURRENT->nr_sectors);
 			return 1;
 		}
 		SIZECODE = 2;
@@ -2455,11 +2387,11 @@
 		SIZECODE = FD_SIZECODE(floppy);
 	raw_cmd->rate = floppy->rate & 3;
 	if ((floppy->rate & FD_2M) &&
-	    (TRACK || HEAD ) &&
+	    (TRACK || HEAD) &&
 	    raw_cmd->rate == 2)
 		raw_cmd->rate = 1;
 
-	if ( SIZECODE )
+	if (SIZECODE)
 		SIZECODE2 = 0xff;
 	else
 		SIZECODE2 = 0x80;
@@ -2470,12 +2402,12 @@
 	SECT_PER_TRACK = floppy->sect << 2 >> SIZECODE;
 	SECTOR = ((sector_t % floppy->sect) << 2 >> SIZECODE) + 1;
 	tracksize = floppy->sect - floppy->sect % ssize;
-	if ( tracksize < floppy->sect ){
+	if (tracksize < floppy->sect){
 		SECT_PER_TRACK ++;
-		if (  tracksize <= sector_t % floppy->sect)
+		if (tracksize <= sector_t % floppy->sect)
 			SECTOR--;
-		while ( tracksize <= sector_t % floppy->sect){
-			while( tracksize + ssize > floppy->sect ){
+		while (tracksize <= sector_t % floppy->sect){
+			while(tracksize + ssize > floppy->sect){
 				SIZECODE--;
 				ssize >>= 1;
 			}
@@ -2483,12 +2415,13 @@
 			tracksize += ssize;
 		}
 		max_sector = HEAD * floppy->sect + tracksize;
-	} else if ( !TRACK && !HEAD && !( floppy->rate & FD_2M ) && probing)
+	} else if (!TRACK && !HEAD && !(floppy->rate & FD_2M) && probing)
 		max_sector = floppy->sect;
 
-	aligned_sector_t = sector_t - ( sector_t % floppy->sect ) % ssize;
+	aligned_sector_t = sector_t - (sector_t % floppy->sect) % ssize;
 	max_size = CURRENT->nr_sectors;
-	if ((raw_cmd->track == buffer_track) && (current_drive == buffer_drive) &&
+	if ((raw_cmd->track == buffer_track) && 
+	    (current_drive == buffer_drive) &&
 	    (sector_t >= buffer_min) && (sector_t < buffer_max)) {
 		/* data already in track buffer */
 		if (CT(COMMAND) == FD_READ) {
@@ -2497,8 +2430,8 @@
 		}
 	} else if (aligned_sector_t != sector_t || CURRENT->nr_sectors < ssize){
 		if (CT(COMMAND) == FD_WRITE){
-			if(sector_t + CURRENT->nr_sectors > ssize &&
-			   sector_t + CURRENT->nr_sectors < ssize + ssize)
+			if (sector_t + CURRENT->nr_sectors > ssize &&
+			    sector_t + CURRENT->nr_sectors < ssize + ssize)
 				max_size = ssize + ssize;
 			else
 				max_size = ssize;
@@ -2506,18 +2439,18 @@
 		raw_cmd->flags &= ~FD_RAW_WRITE;
 		raw_cmd->flags |= FD_RAW_READ;
 		COMMAND = FM_MODE(floppy,FD_READ);
-	} else if ((unsigned long)CURRENT->buffer < MAX_DMA_ADDRESS ) {
+	} else if ((unsigned long)CURRENT->buffer < MAX_DMA_ADDRESS) {
 		int direct, indirect;
 
 		indirect= transfer_size(ssize,max_sector,max_buffer_sectors*2) -
 			sector_t;
 
-		max_size = buffer_chain_size();
-		if ( max_size > ( MAX_DMA_ADDRESS - ((unsigned long) CURRENT->buffer))>>9)
-			max_size=(MAX_DMA_ADDRESS - ((unsigned long) CURRENT->buffer))>>9;
+		max_size = minimum(buffer_chain_size(),
+				   (MAX_DMA_ADDRESS - 
+				    ((unsigned long) CURRENT->buffer))>>9);
 		/* 64 kb boundaries */
 		if (CROSS_64KB(CURRENT->buffer, max_size << 9))
-			max_size = ( K_64 - ((long) CURRENT->buffer) % K_64)>>9;
+			max_size = (K_64 - ((long) CURRENT->buffer) % K_64)>>9;
 		direct = transfer_size(ssize,max_sector,max_size) - sector_t;
 		/*
 		 * We try to read tracks, but if we get too many errors, we
@@ -2529,7 +2462,7 @@
 		if (!direct ||
 		    (indirect * 2 > direct * 3 &&
 		     *errors < DP->max_errors.read_track &&
-		     /*!TESTF( FD_NEED_TWADDLE) &&*/
+		     /*!TESTF(FD_NEED_TWADDLE) &&*/
 		     ((!probing || (DP->read_track&(1<<DRS->probed_format)))))){
 			max_size = CURRENT->nr_sectors;
 		} else {
@@ -2545,7 +2478,7 @@
 		}
 	}
 
-	if ( CT(COMMAND) == FD_READ )
+	if (CT(COMMAND) == FD_READ)
 		max_size = max_sector; /* unbounded */
 
 	/* claim buffer track if needed */
@@ -2554,24 +2487,24 @@
 	    sector_t > buffer_max ||
 	    sector_t < buffer_min ||
 	    ((CT(COMMAND) == FD_READ ||
-	      (aligned_sector_t == sector_t && CURRENT->nr_sectors >= ssize ))&&
+	      (aligned_sector_t == sector_t && CURRENT->nr_sectors >= ssize))&&
 	     max_sector > 2 * max_buffer_sectors + buffer_min &&
 	     max_size + sector_t > 2 * max_buffer_sectors + buffer_min)
-	    /* not enough space */ ){
+	    /* not enough space */){
 		buffer_track = -1;
 		buffer_drive = current_drive;
 		buffer_max = buffer_min = aligned_sector_t;
 	}
 	raw_cmd->kernel_data = floppy_track_buffer + 
-		((aligned_sector_t-buffer_min )<<9);
+		((aligned_sector_t-buffer_min)<<9);
 
-	if ( CT(COMMAND) == FD_WRITE ){
+	if (CT(COMMAND) == FD_WRITE){
 		/* copy write buffer to track buffer.
 		 * if we get here, we know that the write
 		 * is either aligned or the data already in the buffer
 		 * (buffer will be overwritten) */
 #ifdef FLOPPY_SANITY_CHECK
-		if (sector_t != aligned_sector_t && buffer_track == -1 )
+		if (sector_t != aligned_sector_t && buffer_track == -1)
 			DPRINT("internal error offset !=0 on write\n");
 #endif
 		buffer_track = raw_cmd->track;
@@ -2590,15 +2523,15 @@
 	    (raw_cmd->kernel_data != CURRENT->buffer &&
 	     CT(COMMAND) == FD_WRITE &&
 	     (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max ||
-	      aligned_sector_t < buffer_min )) ||
-	    raw_cmd->length % ( 128 << SIZECODE ) ||
+	      aligned_sector_t < buffer_min)) ||
+	    raw_cmd->length % (128 << SIZECODE) ||
 	    raw_cmd->length <= 0 || current_count_sectors <= 0){
 		DPRINT2("fractionary current count b=%lx s=%lx\n",
 			raw_cmd->length, current_count_sectors);
-		if ( raw_cmd->kernel_data != CURRENT->buffer )
+		if (raw_cmd->kernel_data != CURRENT->buffer)
 			printk("addr=%d, length=%ld\n",
 			       (int) ((raw_cmd->kernel_data - 
-				       floppy_track_buffer ) >> 9),
+				       floppy_track_buffer) >> 9),
 			       current_count_sectors);
 		printk("st=%d ast=%d mse=%d msi=%d\n",
 		       sector_t, aligned_sector_t, max_sector, max_size);
@@ -2607,12 +2540,12 @@
 		       COMMAND, SECTOR, HEAD, TRACK);
 		printk("buffer drive=%d\n", buffer_drive);
 		printk("buffer track=%d\n", buffer_track);
-		printk("buffer_min=%d\n", buffer_min );
-		printk("buffer_max=%d\n", buffer_max );
+		printk("buffer_min=%d\n", buffer_min);
+		printk("buffer_max=%d\n", buffer_max);
 		return 0;
 	}
 
-	if (raw_cmd->kernel_data != CURRENT->buffer ){
+	if (raw_cmd->kernel_data != CURRENT->buffer){
 		if (raw_cmd->kernel_data < floppy_track_buffer ||
 		    current_count_sectors < 0 ||
 		    raw_cmd->length < 0 ||
@@ -2621,12 +2554,12 @@
 			DPRINT("buffer overrun in schedule dma\n");
 			printk("sector_t=%d buffer_min=%d current_count=%ld\n",
 			       sector_t, buffer_min,
-			       raw_cmd->length >> 9 );
+			       raw_cmd->length >> 9);
 			printk("current_count_sectors=%ld\n",
 			       current_count_sectors);
-			if ( CT(COMMAND) == FD_READ )
+			if (CT(COMMAND) == FD_READ)
 				printk("read\n");
-			if ( CT(COMMAND) == FD_READ )
+			if (CT(COMMAND) == FD_READ)
 				printk("write\n");
 			return 0;
 		}
@@ -2634,9 +2567,9 @@
 		   current_count_sectors > CURRENT->nr_sectors){
 		DPRINT("buffer overrun in direct transfer\n");
 		return 0;
-	} else if ( raw_cmd->length < current_count_sectors << 9 ){
+	} else if (raw_cmd->length < current_count_sectors << 9){
 		DPRINT("more sectors than bytes\n");
-		printk("bytes=%ld\n", raw_cmd->length >> 9 );
+		printk("bytes=%ld\n", raw_cmd->length >> 9);
 		printk("sectors=%ld\n", current_count_sectors);
 	}
 	if (raw_cmd->length == 0){
@@ -2680,8 +2613,8 @@
 		set_floppy(device);
 		raw_cmd = & default_raw_cmd;
 		raw_cmd->flags = 0;
-		if(start_motor(redo_fd_request)) return;
-		if(test_bit(current_drive, &fake_change) ||
+		if (start_motor(redo_fd_request)) return;
+		if (test_bit(current_drive, &fake_change) ||
 		   TESTF(FD_DISK_CHANGED)){
 			DPRINT("disk absent or changed during operation\n");
 			REPEAT;
@@ -2689,7 +2622,7 @@
 		if (!floppy) { /* Autodetection */
 			if (!probing){
 				DRS->probed_format = 0;
-				if ( next_valid_format() ){
+				if (next_valid_format()){
 					DPRINT("no autodetectable formats\n");
 					floppy = NULL;
 					REPEAT;
@@ -2701,7 +2634,7 @@
 			probing = 0;
 		errors = & (CURRENT->errors);
 		tmp = make_raw_rw_request();
-		if ( tmp < 2 ){
+		if (tmp < 2){
 			request_done(tmp);
 			continue;
 		}
@@ -2724,7 +2657,7 @@
 	bad_flp_intr,
 	request_done };
 
-struct tq_struct request_tq =
+static struct tq_struct request_tq =
 { 0, 0, (void *) (void *) redo_fd_request, 0 };
 
 static void process_fd_request(void)
@@ -2741,10 +2674,7 @@
 		is_alive("do fd request, old request running");
 		return;
 	}
-	/* fdc_busy cannot be set by an interrupt or a bh */
-	floppy_grab_irq_and_dma();
-	fdc_busy=1;
-	reschedule_timeout(MAXTIMEOUT, "do fd request",0);
+	lock_fdc(MAXTIMEOUT,0);
 	process_fd_request();
 	is_alive("do fd request");
 }
@@ -2795,14 +2725,11 @@
 	int ret;
 
 	ret=0;
-	if(arg == FD_RESET_IF_NEEDED && !FDCS->reset)
-		return 0;
 	LOCK_FDC(drive,interruptible);
-	if(arg == FD_RESET_ALWAYS)
+	if (arg == FD_RESET_ALWAYS)
 		FDCS->reset=1;
-	if ( FDCS->reset ){
+	if (FDCS->reset){
 		cont = &reset_cont;
-		reschedule_timeout(CURRENTD, "user reset fdc", 0);
 		WAIT(reset_fdc);
 	}
 	process_fd_request();
@@ -2813,47 +2740,43 @@
  * Misc Ioctl's and support
  * ========================
  */
-static int fd_copyout(void *param, volatile void *address, int size)
+static int fd_copyout(void *param, const void *address, int size)
 {
-	int i;
+	int ret;
 
-	i = verify_area(VERIFY_WRITE,param,size);
-	if (i)
-		return i;
-	fd_cacheflush(address, size);		/* is this necessary ??? */
-			/* Ralf: Yes; only the l2 cache is completly chipset
-			   controlled */
+	ECALL(verify_area(VERIFY_WRITE,param,size));
+	fd_cacheflush(address, size); /* is this necessary ??? */
+	/* Ralf: Yes; only the l2 cache is completly chipset
+	   controlled */
 	memcpy_tofs(param,(void *) address, size);
 	return 0;
 }
 
-static int fd_copyin(void *param, volatile void *address, int size)
+static int fd_copyin(void *param, void *address, int size)
 {
-	int i;
+	int ret;
 
-	i = verify_area(VERIFY_READ,param,size);
-	if (i)
-		return i;
+	ECALL(verify_area(VERIFY_READ,param,size));
 	memcpy_fromfs((void *) address, param, size);
 	return 0;
 }
 
-#define COPYOUT(x) ECALL(fd_copyout( (void *)param, &(x), sizeof(x)))
-#define COPYIN(x) ECALL(fd_copyin( (void *)param, &(x), sizeof(x)))
+#define COPYOUT(x) ECALL(fd_copyout((void *)param, &(x), sizeof(x)))
+#define COPYIN(x) ECALL(fd_copyin((void *)param, &(x), sizeof(x)))
 
-static const char *drive_name(int type, int drive )
+static inline const char *drive_name(int type, int drive)
 {
 	struct floppy_struct *floppy;
 
-	if ( type )
+	if (type)
 		floppy = floppy_type + type;
 	else {
-		if ( UDP->native_format )
+		if (UDP->native_format)
 			floppy = floppy_type + UDP->native_format;
 		else
 			return "(null)";
 	}
-	if ( floppy->name )
+	if (floppy->name)
 		return floppy->name;
 	else
 		return "(null)";
@@ -2865,29 +2788,29 @@
 {
 	int i;
 
-	if(!flag) {
+	if (!flag) {
 		raw_cmd->flags = FD_RAW_FAILURE;
 		raw_cmd->flags |= FD_RAW_HARDFAILURE;
 	} else {
 		raw_cmd->reply_count = inr;
-		for( i=0; i< raw_cmd->reply_count; i++)
+		for (i=0; i< raw_cmd->reply_count; i++)
 			raw_cmd->reply[i] = reply_buffer[i];
 
-		if ( raw_cmd->flags & ( FD_RAW_READ | FD_RAW_WRITE ))
+		if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE))
 			raw_cmd->length = get_dma_residue(FLOPPY_DMA);
 		
-		if( (raw_cmd->flags & FD_RAW_SOFTFAILURE) &&
+		if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) &&
 		    (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0)))
 			raw_cmd->flags |= FD_RAW_FAILURE;
 
-		if( disk_change(current_drive) )
+		if (disk_change(current_drive))
 			raw_cmd->flags |= FD_RAW_DISK_CHANGE;
 		else
 			raw_cmd->flags &= ~FD_RAW_DISK_CHANGE;
-		if(raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER)
+		if (raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER)
 			motor_off_callback(current_drive);
 
-		if(raw_cmd->next &&
+		if (raw_cmd->next &&
 		   (!(raw_cmd->flags & FD_RAW_FAILURE) ||
 		    !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) &&
 		   ((raw_cmd->flags & FD_RAW_FAILURE) ||
@@ -2914,7 +2837,7 @@
 	int ret;
 
 	while(ptr) {
-		if(cmd == OLDFDRAWCMD) {
+		if (cmd == OLDFDRAWCMD) {
 			old_raw_cmd.flags = ptr->flags;
 			old_raw_cmd.data = ptr->data;
 			old_raw_cmd.length = ptr->length;
@@ -2928,8 +2851,8 @@
 			param += sizeof(struct floppy_raw_cmd);
 		}
 
-		if ( (ptr->flags & FD_RAW_READ) && ptr->buffer_length){
-			if(ptr->length>=0 && ptr->length<=ptr->buffer_length)
+		if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length){
+			if (ptr->length>=0 && ptr->length<=ptr->buffer_length)
 				ECALL(fd_copyout(ptr->data, 
 						 ptr->kernel_data, 
 						 ptr->buffer_length - 
@@ -2943,18 +2866,19 @@
 
 static void raw_cmd_free(struct floppy_raw_cmd **ptr)
 {
-	struct floppy_raw_cmd **next;
+	struct floppy_raw_cmd *next,*this;
 
-	while(*ptr) {
-		next = & (*ptr)->next;
-		if((*ptr)->buffer_length) {
-			free_pages((unsigned long)(*ptr)->kernel_data,
-				   __get_order((*ptr)->buffer_length));
-			(*ptr)->buffer_length = 0;
-		}
-		kfree(*ptr);
-		*ptr = 0;
-		ptr = next;
+	this = *ptr;
+	*ptr = 0;
+	while(this) {
+		if (this->buffer_length) {
+			free_pages((unsigned long)this->kernel_data,
+				   __get_order(this->buffer_length));
+			this->buffer_length = 0;
+		}
+		next = this->next;
+		kfree(this);
+		this = next;
 	}
 }
 
@@ -2970,13 +2894,11 @@
 	*rcmd = 0;
 	while(1) {
 		ptr = (struct floppy_raw_cmd *) 
-			kmalloc(sizeof(struct floppy_raw_cmd ), GFP_USER);
-		if(!ptr)
+			kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER);
+		if (!ptr)
 			return -ENOMEM;
-		ptr->next = 0;
-		ptr->buffer_length = 0;
 		*rcmd = ptr;
-		if(cmd == OLDFDRAWCMD){
+		if (cmd == OLDFDRAWCMD){
 			COPYIN(old_raw_cmd);
 			ptr->flags = old_raw_cmd.flags;
 			ptr->data = old_raw_cmd.data;
@@ -2984,43 +2906,45 @@
 			ptr->rate = old_raw_cmd.rate;
 			ptr->cmd_count = old_raw_cmd.cmd_count;
 			ptr->track = old_raw_cmd.track;
-			memcpy(ptr->cmd, old_raw_cmd.cmd, 9);
-			if(ptr->cmd_count > 9)
-				return -EINVAL;			
-			ptr->next = 0;
 			ptr->phys_length = 0;
+			ptr->next = 0;
+			ptr->buffer_length = 0;
+			memcpy(ptr->cmd, old_raw_cmd.cmd, 9);
 			param += sizeof(struct old_floppy_raw_cmd);
+			if (ptr->cmd_count > 9)
+				return -EINVAL;
 		} else {
 			COPYIN(*ptr);
+			ptr->next = 0;
+			ptr->buffer_length = 0;
 			param += sizeof(struct floppy_raw_cmd);
-			if(ptr->cmd_count > 16)
+			if (ptr->cmd_count > 16)
 				return -EINVAL;
 		}
 
-		for(i=0; i< 16; i++)
+		for (i=0; i< 16; i++)
 			ptr->reply[i] = 0;
 		ptr->resultcode = 0;
-
-		ptr->next = 0;
-		ptr->buffer_length = 0;
 		ptr->kernel_data = 0;
 
-		if(ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
-			if(!ptr->length)
+		if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
+			if (ptr->length <= 0)
 				return -EINVAL;
-
 			ptr->kernel_data =(char*)dma_mem_alloc(ptr->length);
-			if(!ptr->kernel_data)
+			if (!ptr->kernel_data)
 				return -ENOMEM;
 			ptr->buffer_length = ptr->length;
 		}
-		if(ptr->flags & FD_RAW_WRITE)
-			fd_copyin(ptr->data, ptr->kernel_data, ptr->length);
+		if ( ptr->flags & FD_RAW_READ )
+		    ECALL( verify_area( VERIFY_WRITE, ptr->data, 
+					ptr->length ));
+		if (ptr->flags & FD_RAW_WRITE)
+			ECALL(fd_copyin(ptr->data, ptr->kernel_data, 
+					ptr->length));
 		rcmd = & (ptr->next);
-		if( ! (ptr->flags & FD_RAW_MORE))
+		if (!(ptr->flags & FD_RAW_MORE))
 			return 0;
 		ptr->rate &= 0x03;
-
 	}
 }
 
@@ -3030,27 +2954,27 @@
 	int drive, ret, ret2;
 	struct floppy_raw_cmd *my_raw_cmd;
 
-	if ( FDCS->rawcmd <= 1 )
+	if (FDCS->rawcmd <= 1)
 		FDCS->rawcmd = 1;
-	for ( drive= 0; drive < N_DRIVE; drive++){
-		if ( FDC(drive) != fdc)
+	for (drive= 0; drive < N_DRIVE; drive++){
+		if (FDC(drive) != fdc)
 			continue;
-		if ( drive == current_drive ){
-			if ( UDRS->fd_ref > 1 ){
+		if (drive == current_drive){
+			if (UDRS->fd_ref > 1){
 				FDCS->rawcmd = 2;
 				break;
 			}
-		} else if ( UDRS->fd_ref ){
+		} else if (UDRS->fd_ref){
 			FDCS->rawcmd = 2;
 			break;
 		}
 	}
 
-	if(FDCS->reset)
+	if (FDCS->reset)
 		return -EIO;
 
 	ret = raw_cmd_copyin(cmd, param, &my_raw_cmd);
-	if(ret) {
+	if (ret) {
 		raw_cmd_free(&my_raw_cmd);
 		return ret;
 	}
@@ -3064,13 +2988,13 @@
 	}
 #endif
 
-	if(ret != -EINTR && FDCS->reset)
-		ret = -EINTR;
+	if (ret != -EINTR && FDCS->reset)
+		ret = -EIO;
 
 	DRS->track = NO_TRACK;
 
 	ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd);
-	if(!ret)
+	if (!ret)
 		ret = ret2;
 	raw_cmd_free(&my_raw_cmd);
 	return ret;
@@ -3079,26 +3003,187 @@
 static int invalidate_drive(kdev_t rdev)
 {
 	/* invalidate the buffer track to force a reread */
-	set_bit( DRIVE(rdev), &fake_change);
+	set_bit(DRIVE(rdev), &fake_change);
 	process_fd_request();
 	check_disk_change(rdev);
 	return 0;
 }
 
+
+static inline void clear_write_error(int drive)
+{
+	CLEARSTRUCT(UDRWE);
+}
+
+static inline int set_geometry(int cmd, struct floppy_struct *g,
+			       int drive, int type, int device)
+{
+	int cnt;
+
+	/* sanity checking for parameters.*/
+	if (g->sect <= 0 ||
+	    g->head <= 0 ||
+	    g->track <= 0 ||
+	    g->track > UDP->tracks>>STRETCH(g) ||
+	    /* check if reserved bits are set */
+	    (g->stretch&~(FD_STRETCH|FD_SWAPSIDES)) != 0)
+		return -EINVAL;
+	if (type){
+		if (!suser())
+			return -EPERM;
+		LOCK_FDC(drive,1);
+		for (cnt = 0; cnt < N_DRIVE; cnt++){
+			if (TYPE(drive_state[cnt].fd_device) ==
+			    type &&
+			    drive_state[cnt].fd_ref)
+				set_bit(drive, &fake_change);
+		}
+		floppy_type[type] = *g;
+		floppy_type[type].name="user format";
+		for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
+			floppy_sizes[cnt]= floppy_sizes[cnt+0x80]=
+				floppy_type[type].size>>1;
+		process_fd_request();
+		for (cnt = 0; cnt < N_DRIVE; cnt++){
+			if (TYPE(drive_state[cnt].fd_device) == type &&
+			    drive_state[cnt].fd_ref)
+				check_disk_change(drive_state[cnt].fd_device);
+		}
+	} else {
+		LOCK_FDC(drive,1);
+		if (cmd != FDDEFPRM)
+			/* notice a disk change immediately, else
+			 * we loose our settings immediately*/
+			CALL(poll_drive(1,0));
+		user_params[drive] = *g;
+		if (buffer_drive == drive)
+			SUPBOUND(buffer_max, user_params[drive].sect);
+		current_type[drive] = &user_params[drive];
+		floppy_sizes[drive] = user_params[drive].size >> 1;
+		if (cmd == FDDEFPRM)
+			DRS->keep_data = -1;
+		else
+			DRS->keep_data = 1;
+		/* invalidation. Invalidate only when needed, i.e.
+		 * when there are already sectors in the buffer cache
+		 * whose number will change. This is useful, because
+		 * mtools often changes the geometry of the disk after
+		 * looking at the boot block */
+		if (DRS->maxblock > user_params[drive].sect || DRS->maxtrack)
+			invalidate_drive(device);
+		else
+			process_fd_request();
+	}
+	return 0;
+}
+
+/* handle obsolete ioctl's */
+static struct translation_entry {
+    int newcmd;
+    int oldcmd;
+    int oldsize; /* size of 0x00xx-style ioctl. Reflects old structures, thus
+		  * use numeric values. NO SIZEOFS */
+} translation_table[]= {
+    {FDCLRPRM,		 0,  0},
+    {FDSETPRM,		 1, 28},
+    {FDDEFPRM,		 2, 28},
+    {FDGETPRM,		 3, 28},
+    {FDMSGON,		 4,  0},
+    {FDMSGOFF,		 5,  0},
+    {FDFMTBEG,		 6,  0},
+    {FDFMTTRK,		 7, 12},
+    {FDFMTEND,		 8,  0},
+    {FDSETEMSGTRESH,	10,  0},
+    {FDFLUSH,		11,  0},
+    {FDSETMAXERRS,	12, 20},
+    {OLDFDRAWCMD,      	30,  0},
+    {FDGETMAXERRS,	14, 20},
+    {FDGETDRVTYP,	16, 16},
+    {FDSETDRVPRM,	20, 88},
+    {FDGETDRVPRM,	21, 88},
+    {FDGETDRVSTAT,	22, 52},
+    {FDPOLLDRVSTAT,	23, 52},
+    {FDRESET,		24,  0},
+    {FDGETFDCSTAT,	25, 40},
+    {FDWERRORCLR,	27,  0},
+    {FDWERRORGET,	28, 24},
+    {FDRAWCMD,		 0,  0},
+    {FDTWADDLE,		40,  0} };
+
+static inline int normalize_0x02xx_ioctl(int *cmd, int *size)
+{
+	int i, orig_size, ocmd;
+
+	orig_size = IOC_SIZE(*cmd);
+	ocmd = *cmd;
+	for (i=0; i < ARRAY_SIZE(translation_table); i++) {
+		if ((*cmd & 0xff3f) == (translation_table[i].newcmd & 0xff3f)){
+			*cmd = translation_table[i].newcmd;
+			if (!orig_size && IOC_SIZE(*cmd)) {
+				/* kernels 1.3.34 to 1.3.37 : */
+				*size = IOC_SIZE(*cmd); 
+				DPRINT1("warning: obsolete ioctl 0x%x\n",ocmd);
+				DPRINT("please recompile your program\n");
+				/* these ioctls only existed
+				 * in two (development)
+				 * kernels anyways. That's why we
+				 * complain about these, and not about
+				 * the much older 0x00xx ioctl's
+				 */
+			} else {
+				*size = orig_size;
+				if (*size > IOC_SIZE(*cmd)) {
+					printk("ioctl not yet supported\n");
+					return -EFAULT;
+				}
+			}
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static inline int xlate_0x00xx_ioctl(int *cmd, int *size)
+{
+	int i;
+	/* kernels <= 1.3.33 */
+	/* we might want to start warning in 1.4.x (by then, no user
+	 * programs will have an excuse to use the old ioctls: there
+	 * will be a stable kernel supporting them :)
+	 *
+	 * when the first 1.5.x kernel will come out, this loop will
+	 * be removed as well.
+	 */
+	for (i=0; i < ARRAY_SIZE(translation_table); i++) {
+		if (*cmd == translation_table[i].oldcmd) {
+			*size = translation_table[i].oldsize;
+			*cmd = translation_table[i].newcmd;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 		    unsigned long param)
 {
 #define IOCTL_MODE_BIT 8
 #define OPEN_WRITE_BIT 16
 #define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT))
+#define OUT(c,x) case c: outparam = (const char *) (x); break
+#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
 
-	struct floppy_struct newparams;
-	struct format_descr tmp_format_req;
-	int i,drive,type,cnt;
+	int i,drive,type;
 	kdev_t device;
-	struct floppy_struct *this_floppy;
-	const char *name;
 	int ret;
+	int size;
+	union inparam {
+		struct floppy_struct g; /* geometry */
+		struct format_descr f;
+		struct floppy_max_errors max_errors;
+		struct floppy_drive_params dp;
+	} inparam; /* parameters coming from user space */
+	const char *outparam; /* parameters passed back to user space */
 
 	device = inode->i_rdev;
 	switch (cmd) {
@@ -3106,68 +3191,99 @@
 	}
 	type = TYPE(device);
 	drive = DRIVE(device);
+
+	/* convert the old style command into a new style command */
+	if ((cmd & 0xff00) == 0x0200) {
+		ECALL(normalize_0x02xx_ioctl(&cmd, &size));
+	} else if ((cmd & 0xff00) == 0x0000) {
+		ECALL(xlate_0x00xx_ioctl(&cmd, &size));
+	} else
+		return -EINVAL;
+
+	/* permission checks */
+	if (((cmd & 0x80) && !suser()) ||
+	     ((cmd & 0x40) && !IOCTL_ALLOWED))
+		return -EPERM;
+
+	/* verify writability of result, and fail early */
+	if (_IOC_DIR(cmd) & _IOC_WRITE)
+		ECALL(verify_area(VERIFY_WRITE,(void *) param, size));
+		
+	/* copyin */
+	CLEARSTRUCT(&inparam);
+	if (_IOC_DIR(cmd) & _IOC_READ)
+		ECALL(fd_copyin((void *)param, &inparam, size))
+
 	switch (cmd) {
-		case OLDFDGETDRVTYP:
-		case FDGETDRVTYP:
-			i=verify_area(VERIFY_WRITE,(void *) param,16);
-			if (i)
-				return i;
-			name = drive_name(type,drive);
-			for ( cnt=0; cnt<16; cnt++){
-				put_user(name[cnt], ((char*)param)+cnt);
-				if ( ! *name )
-					break;
-			}
-			return 0;
-		case OLDFDGETMAXERRS:
-		case FDGETMAXERRS:
-			COPYOUT(UDP->max_errors);
-			return 0;
-		case OLDFDGETPRM:
+		case FDCLRPRM:
+			LOCK_FDC(drive,1);
+			current_type[drive] = NULL;
+			floppy_sizes[drive] = MAX_DISK_SIZE;
+			UDRS->keep_data = 0;
+			return invalidate_drive(device);
+		case FDSETPRM:
+		case FDDEFPRM:
+			return set_geometry(cmd, & inparam.g,
+					    drive, type, device);
 		case FDGETPRM:
 			if (type)
-				this_floppy = &floppy_type[type];
-			else if ((this_floppy = current_type[drive]) == NULL)
+				outparam = (char *) &floppy_type[type];
+			else 
+				outparam = (char *) current_type[drive];
+			if(!outparam)
 				return -ENODEV;
-			COPYOUT(this_floppy[0]);
+			break;
+
+		case FDMSGON:
+			UDP->flags |= FTD_MSG;
+			return 0;
+		case FDMSGOFF:
+			UDP->flags &= ~FTD_MSG;
+			return 0;
+
+		case FDFMTBEG:
+			return 0;
+		case FDFMTTRK:
+			if (UDRS->fd_ref != 1)
+				return -EBUSY;
+			return do_format(device, &inparam.f);
+		case FDFMTEND:
+		case FDFLUSH:
+			LOCK_FDC(drive,1);
+			return invalidate_drive(device);
+
+		case FDSETEMSGTRESH:
+			UDP->max_errors.reporting =
+				(unsigned short) (param & 0x0f);
 			return 0;
-		case OLDFDPOLLDRVSTAT:
+		OUT(FDGETMAXERRS, &UDP->max_errors);
+		IN(FDSETMAXERRS, &UDP->max_errors, max_errors);
+
+		case FDGETDRVTYP:
+			outparam = drive_name(type,drive);
+			SUPBOUND(size,strlen(outparam));
+			break;
+
+		IN(FDSETDRVPRM, UDP, dp);
+		OUT(FDGETDRVPRM, UDP);
+
 		case FDPOLLDRVSTAT:
 			LOCK_FDC(drive,1);
 			CALL(poll_drive(1, FD_RAW_NEED_DISK));
 			process_fd_request();
 			/* fall through */
-		case OLDFDGETDRVSTAT:
-		case FDGETDRVSTAT:
-			COPYOUT(*UDRS);
-			return 0;
-		case OLDFDGETFDCSTAT:
-			COPYOUT(* (struct old_floppy_fdc_state *) UFDCS);
-			return 0;
-		case FDGETFDCSTAT:
-			COPYOUT(*UFDCS);
-			return 0;
-		case OLDFDGETDRVPRM:
-		case FDGETDRVPRM:
-			COPYOUT(*UDP);
-			return 0;
-		case OLDFDWERRORGET:
-		case FDWERRORGET:
-			COPYOUT(*UDRWE);
-			return 0;
-	}
-	if (!IOCTL_ALLOWED)
-		return -EPERM;
-	switch (cmd) {
-		case OLDFDWERRORCLR:
+	       	OUT(FDGETDRVSTAT, UDRS);
+
+		case FDRESET:
+			return user_reset_fdc(drive, (int)param, 1);
+
+		OUT(FDGETFDCSTAT,UFDCS);
+
 		case FDWERRORCLR:
-			UDRWE->write_errors = 0;
-			UDRWE->first_error_sector = 0;
-			UDRWE->first_error_generation = 0;
-			UDRWE->last_error_sector = 0;
-			UDRWE->last_error_generation = 0;
-			UDRWE->badness = 0;
+			CLEARSTRUCT(UDRWE);
 			return 0;
+		OUT(FDWERRORGET,UDRWE);
+
 		case OLDFDRAWCMD:
 		case FDRAWCMD:
 			if (type)
@@ -3177,133 +3293,24 @@
 			CALL(i = raw_cmd_ioctl(cmd,(void *) param));
 			process_fd_request();
 			return i;
-		case OLDFDFMTTRK:
-		case FDFMTTRK:
-			if (UDRS->fd_ref != 1)
-				return -EBUSY;
-			COPYIN(tmp_format_req);
-			return do_format(device, &tmp_format_req);
-		case OLDFDSETMAXERRS:
-		case FDSETMAXERRS:
-			COPYIN(UDP->max_errors);
-			return 0;
-		case OLDFDFMTBEG:
-		case FDFMTBEG:
-			return 0;
-		case OLDFDCLRPRM:
-		case FDCLRPRM:
-			LOCK_FDC(drive,1);
-			current_type[drive] = NULL;
-			floppy_sizes[drive] = MAX_DISK_SIZE;
-			UDRS->keep_data = 0;
-			return invalidate_drive(device);
-		case OLDFDFMTEND:
-		case FDFMTEND:
-		case OLDFDFLUSH:
-		case FDFLUSH:
-			LOCK_FDC(drive,1);
-			return invalidate_drive(device);
-		case OLDFDSETPRM:
-		case FDSETPRM:
-		case OLDFDDEFPRM:
-		case FDDEFPRM:
-			COPYIN(newparams);
-			/* sanity checking for parameters.*/
-			if(newparams.sect <= 0 ||
-			   newparams.head <= 0 ||
-			   newparams.track <= 0 ||
-			   newparams.track > UDP->tracks>> STRETCH(&newparams) ||
-			   /* check if reserved bits are set */
-			   (newparams.stretch & ~(FD_STRETCH | FD_SWAPSIDES)) != 0)
-				return -EINVAL;
-			if ( type){
-				if ( !suser() )
-					return -EPERM;
-				LOCK_FDC(drive,1);
-				for ( cnt = 0; cnt < N_DRIVE; cnt++){
-					if (TYPE(drive_state[cnt].fd_device) == type &&
-					    drive_state[cnt].fd_ref)
-						set_bit(drive, &fake_change);
-				}
-				floppy_type[type] = newparams;
-				floppy_type[type].name="user format";
-				for (cnt = type << 2 ;
-				     cnt < (type << 2 ) + 4 ;
-				     cnt++)
-					floppy_sizes[cnt]=
-						floppy_sizes[cnt+0x80]=
-						floppy_type[type].size>>1;
-				process_fd_request();
-				for ( cnt = 0; cnt < N_DRIVE; cnt++){
-					if (TYPE(drive_state[cnt].fd_device) == type &&
-					    drive_state[cnt].fd_ref)
-						check_disk_change(drive_state[cnt].
-								  fd_device);
-				}
-				return 0;
-			}
 
-			LOCK_FDC(drive,1);
-			if ( cmd != FDDEFPRM )
-				/* notice a disk change immediately, else
-				 * we loose our settings immediately*/
-				CALL(poll_drive(1,0));
-			user_params[drive] = newparams;
-			if (buffer_drive == drive &&
-			    buffer_max > user_params[drive].sect)
-				buffer_max=user_params[drive].sect;
-			current_type[drive] = &user_params[drive];
-			floppy_sizes[drive] = user_params[drive].size >> 1;
-			if (cmd == FDDEFPRM)
-				DRS->keep_data = -1;
-			else
-				DRS->keep_data = 1;
-			/* invalidation. Invalidate only when needed, i.e.
-			 * when there are already sectors in the buffer cache
-			 * whose number will change. This is useful, because
-			 * mtools often changes the geometry of the disk after
-			 * looking at the boot block */
-			if (DRS->maxblock >
-			    user_params[drive].sect ||
-			    DRS->maxtrack )
-				invalidate_drive(device);
-			else
-				process_fd_request();
-			return 0;
-		case OLDFDRESET:
-		case FDRESET:
-			return user_reset_fdc( drive, (int)param, 1);
-		case OLDFDMSGON:
-		case FDMSGON:
-			UDP->flags |= FTD_MSG;
-			return 0;
-		case OLDFDMSGOFF:
-		case FDMSGOFF:
-			UDP->flags &= ~FTD_MSG;
-			return 0;
-		case OLDFDSETEMSGTRESH:
-		case FDSETEMSGTRESH:
-			UDP->max_errors.reporting =
-			(unsigned short) (param & 0x0f);
-			return 0;
-		case OLDFDTWADDLE:
 		case FDTWADDLE:
 			LOCK_FDC(drive,1);
 			twaddle();
 			process_fd_request();
-	}
-	if ( ! suser() )
-		return -EPERM;
-	switch(cmd){
-		case OLDFDSETDRVPRM:
-		case FDSETDRVPRM:
-			COPYIN(*UDP);
 			return 0;
+
 		default:
 			return -EINVAL;
 	}
-	return 0;
+
+	if (_IOC_DIR(cmd) & _IOC_WRITE)
+		return fd_copyout((void *)param, outparam, size);
+	else
+		return 0;
 #undef IOCTL_ALLOWED
+#undef OUT
+#undef IN
 }
 
 static void config_types(void)
@@ -3313,7 +3320,7 @@
 
 	/* read drive info out of physical cmos */
 	drive=0;
-	if (!UDP->cmos )
+	if (!UDP->cmos)
 		UDP->cmos= FLOPPY0_TYPE;
 	drive=1;
 	if (!UDP->cmos && FLOPPY1_TYPE)
@@ -3333,8 +3340,8 @@
 			else
 				printk(", ");
 			first=0;
-			if (UDP->cmos > 0 ){
-				ALLOWED_DRIVE_MASK |= 1 << drive;
+			if (UDP->cmos > 0){
+				allowed_drive_mask |= 1 << drive;
 				printk("fd%d is %s", drive,
 				       default_drive_params[(int)UDP->cmos].name);
 			} else
@@ -3342,7 +3349,7 @@
 				       UDP->cmos);
 		}
 	}
-	if(!first)
+	if (!first)
 		printk("\n");
 }
 
@@ -3364,16 +3371,15 @@
 	int ret;
 	int drive = DRIVE(inode->i_rdev);
 
-	if(!UDRS->maxblock)
+	if (!UDRS->maxblock)
 		UDRS->maxblock=1;/* make change detectable */
 	check_disk_change(inode->i_rdev);
 	if (UTESTF(FD_DISK_CHANGED))
 		return -ENXIO;
-	if(!UTESTF(FD_DISK_WRITABLE))
+	if (!UTESTF(FD_DISK_WRITABLE))
 		return -EROFS;
 	block = (filp->f_pos + count) >> 9;
-	if(block > UDRS->maxblock)
-		UDRS->maxblock = block;
+	INFBOUND(UDRS->maxblock, block);
 	ret= block_write(inode, filp, buf, count);
 	return ret;
 }
@@ -3384,7 +3390,7 @@
 
 	drive = DRIVE(inode->i_rdev);
 
-	if( !filp || (filp->f_mode & (2 | OPEN_WRITE_BIT)))
+	if (!filp || (filp->f_mode & (2 | OPEN_WRITE_BIT)))
 		/* if the file is mounted OR (writable now AND writable at
 		 * open time) Linus: Does this cover all cases? */
 		block_fsync(inode,filp);
@@ -3418,9 +3424,8 @@
 	}
 
 	drive = DRIVE(inode->i_rdev);
-
 	if (drive >= N_DRIVE ||
-	    !( ALLOWED_DRIVE_MASK & ( 1 << drive)) ||
+	    !(allowed_drive_mask & (1 << drive)) ||
 	    fdc_state[FDC(drive)].version == FDC_NONE)
 		return -ENXIO;
 
@@ -3430,12 +3435,12 @@
 	if (UDRS->fd_ref && old_dev != MINOR(inode->i_rdev))
 		return -EBUSY;
 
-	if(!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){
+	if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){
 		USETF(FD_DISK_CHANGED);
 		USETF(FD_VERIFY);
 	}
 
-	if(UDRS->fd_ref == -1 ||
+	if (UDRS->fd_ref == -1 ||
 	   (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
 		return -EBUSY;
 
@@ -3458,8 +3463,7 @@
 		tmp=(char *)dma_mem_alloc(1024 * try);
 		if (!tmp) {
 			try >>= 1; /* buffer only one side */
-			if (try < 16)
-				try=16;
+			INFBOUND(try, 16);
 			tmp= (char *)dma_mem_alloc(1024*try);
 		}
 		if (!tmp) {
@@ -3510,7 +3514,7 @@
  */
 static int check_floppy_change(kdev_t dev)
 {
-	int drive = DRIVE( dev );
+	int drive = DRIVE(dev);
 
 	if (MAJOR(dev) != MAJOR_NR) {
 		DPRINT("floppy_changed: not a floppy\n");
@@ -3520,13 +3524,13 @@
 	if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
 		return 1;
 
-	if(UDRS->last_checked + UDP->checkfreq < jiffies){
+	if (UDRS->last_checked + UDP->checkfreq < jiffies){
 		lock_fdc(drive,0);
 		poll_drive(0,0);
 		process_fd_request();
 	}
 
-	if(UTESTF(FD_DISK_CHANGED) ||
+	if (UTESTF(FD_DISK_CHANGED) ||
 	   UTESTF(FD_VERIFY) ||
 	   test_bit(drive, &fake_change) ||
 	   (!TYPE(dev) && !current_type[drive]))
@@ -3545,25 +3549,25 @@
 	int drive=DRIVE(dev);
 	int cf;
 
-	if(UTESTF(FD_DISK_CHANGED) ||
+	if (UTESTF(FD_DISK_CHANGED) ||
 	   UTESTF(FD_VERIFY) ||
 	   test_bit(drive, &fake_change) ||
 	   NO_GEOM){
 		lock_fdc(drive,0);
 		cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY);
-		if(! (cf || test_bit(drive, &fake_change) || NO_GEOM)){
+		if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)){
 			process_fd_request(); /*already done by another thread*/
 			return 0;
 		}
 		UDRS->maxblock = 0;
 		UDRS->maxtrack = 0;
-		if ( buffer_drive == drive)
+		if (buffer_drive == drive)
 			buffer_track = -1;
 		clear_bit(drive, &fake_change);
 		UCLEARF(FD_DISK_CHANGED);
-		if(cf)
+		if (cf)
 			UDRS->generation++;
-		if(NO_GEOM){
+		if (NO_GEOM){
 			/* auto-sensing */
 			int size = floppy_blocksizes[MINOR(dev)];
 			if (!size)
@@ -3572,14 +3576,14 @@
 				process_fd_request();
 				return 1;
 			}
-			if ( bh && ! bh->b_uptodate)
+			if (bh && !bh->b_uptodate)
 				ll_rw_block(READ, 1, &bh);
 			process_fd_request();
 			wait_on_buffer(bh);
 			brelse(bh);
 			return 0;
 		}
-		if(cf)
+		if (cf)
 			poll_drive(0, FD_RAW_NEED_DISK);
 		process_fd_request();
 	}
@@ -3614,13 +3618,13 @@
 	int r;
 
 	output_byte(FD_DUMPREGS);	/* 82072 and better know DUMPREGS */
-	if ( FDCS->reset )
+	if (FDCS->reset)
 		return FDC_NONE;
-	if ( (r = result()) <= 0x00)
+	if ((r = result()) <= 0x00)
 		return FDC_NONE;	/* No FDC present ??? */
 	if ((r==1) && (reply_buffer[0] == 0x80)){
 		printk("FDC %d is a 8272A\n",fdc);
-		return FDC_8272A;		/* 8272a/765 don't know DUMPREGS */
+		return FDC_8272A;	/* 8272a/765 don't know DUMPREGS */
 	}
 	if (r != 10) {
 		printk("FDC init: DUMPREGS: unexpected return of %d bytes.\n", r);
@@ -3653,8 +3657,8 @@
 /* lilo configuration */
 
 /* we make the invert_dcl function global. One day, somebody might
-want to centralize all thinkpad related options into one lilo option,
-there are just so many thinkpad related quirks! */
+ * want to centralize all thinkpad related options into one lilo option,
+ * there are just so many thinkpad related quirks! */
 void floppy_invert_dcl(int *ints,int param)
 {
 	int i;
@@ -3686,14 +3690,14 @@
 
 static void allow_drives(int *ints, int param)
 {
-	ALLOWED_DRIVE_MASK=param;
+	allowed_drive_mask=param;
 	DPRINT1("setting allowed_drive_mask to 0x%x\n", param);
 }
 
 static void fdc2_adr(int *ints, int param)
 {
 	FDC2 = param;
-	if(param)
+	if (param)
 		DPRINT1("enabling second fdc at address 0x%3x\n", FDC2);
 	else
 		DPRINT("disabling second fdc\n");
@@ -3710,18 +3714,18 @@
 {
 	int current_drive=0;
 
-	if ( ints[0] != 2 ){
+	if (ints[0] != 2){
 		DPRINT("wrong number of parameter for cmos\n");
 		return;
 	}
 	current_drive = ints[1];
-	if (current_drive < 0 || current_drive >= 8 ){
+	if (current_drive < 0 || current_drive >= 8){
 		DPRINT("bad drive for set_cmos\n");
 		return;
 	}
-	if(current_drive >= 4 && !FDC2)
+	if (current_drive >= 4 && !FDC2)
 		fdc2_adr(0, 0x370);
-	if(ints[2] <= 0 || ints[2] >= NUMBER(default_drive_params)){
+	if (ints[2] <= 0 || ints[2] >= NUMBER(default_drive_params)){
 		DPRINT1("bad cmos code %d\n", ints[2]);
 		return;
 	}
@@ -3756,10 +3760,10 @@
 {
 	int i;
 	int param;
-	if(str)
-		for(i=0; i< ARRAY_SIZE(config_params); i++){
-			if (strcmp(str,config_params[i].name) == 0 ){
-				if (ints[0] )
+	if (str)
+		for (i=0; i< ARRAY_SIZE(config_params); i++){
+			if (strcmp(str,config_params[i].name) == 0){
+				if (ints[0])
 					param = ints[1];
 				else
 					param = config_params[i].def_param;
@@ -3767,11 +3771,11 @@
 				return;
 			}
 		}
-	if(str) {
+	if (str) {
 		DPRINT1("unknown floppy option [%s]\n", str);
 		
 		DPRINT("allowed options are:");
-		for(i=0; i< ARRAY_SIZE(config_params); i++)
+		for (i=0; i< ARRAY_SIZE(config_params); i++)
 			printk(" %s",config_params[i].name);
 		printk("\n");
 	} else
@@ -3782,7 +3786,7 @@
 int floppy_init(void)
 {
 	int i,unit,drive;
-	int have_no_fdc=0;
+	int have_no_fdc= -EIO;
 
 	raw_cmd = 0;
 
@@ -3793,7 +3797,7 @@
 		return -EBUSY;
 	}
 
-	for(i=0; i<256; i++)
+	for (i=0; i<256; i++)
 		if (TYPE(i))
 			floppy_sizes[i] = floppy_type[TYPE(i)].size >> 1;
 		else
@@ -3805,52 +3809,41 @@
 	reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
 	config_types();
 
-	fdc_state[0].address = FDC1;
-	fdc_state[0].dor = 0;
-#if N_FDC > 1
-	fdc_state[1].address = FDC2;
-	fdc_state[1].dor = 0;
-#endif
-
-	for (i = 0 ; i < N_FDC ; i++) {
+	for (i = 0; i < N_FDC; i++) {
 		fdc = i;
+		CLEARSTRUCT(FDCS);
 		FDCS->dtr = -1;
 		FDCS->dor = 0x4;
-		FDCS->reset = 0;
-		FDCS->version = FDC_NONE;
 	}
 
-	if(floppy_grab_irq_and_dma()){
+	fdc_state[0].address = FDC1;
+#if N_FDC > 1
+	fdc_state[1].address = FDC2;
+#endif
+
+	if (floppy_grab_irq_and_dma()){
 		unregister_blkdev(MAJOR_NR,"fd");
 		return -EBUSY;
 	}
 
 	/* initialise drive state */
-	for (drive = 0; drive < N_DRIVE ; drive++) {
+	for (drive = 0; drive < N_DRIVE; drive++) {
+		CLEARSTRUCT(UDRS);
+		CLEARSTRUCT(UDRWE);
 		UDRS->flags = FD_VERIFY | FD_DISK_NEWCHANGE | FD_DISK_CHANGED;
-		UDRS->generation = 0;
-		UDRS->keep_data = 0;
-		UDRS->fd_ref = 0;
-		UDRS->fd_device = 0;
 		floppy_track_buffer = NULL;
 		max_buffer_sectors = 0;
-		UDRWE->write_errors = 0;
-		UDRWE->first_error_sector = 0;
-		UDRWE->first_error_generation = 0;
-		UDRWE->last_error_sector = 0;
-		UDRWE->last_error_generation = 0;
-		UDRWE->badness = 0;
 	}
 
-	for (i = 0 ; i < N_FDC ; i++) {
+	for (i = 0; i < N_FDC; i++) {
 		fdc = i;
 		FDCS->driver_version = FD_DRIVER_VERSION;
-		for(unit=0; unit<4; unit++)
+		for (unit=0; unit<4; unit++)
 			FDCS->track[unit] = 0;
-		if (FDCS->address == -1 )
+		if (FDCS->address == -1)
 			continue;
 		FDCS->rawcmd = 2;
-		if(user_reset_fdc(-1,FD_RESET_IF_NEEDED,0)){
+		if (user_reset_fdc(-1,FD_RESET_ALWAYS,0)){
 			FDCS->address = -1;
 			continue;
 		}
@@ -3879,9 +3872,10 @@
 	current_drive = 0;
 	floppy_release_irq_and_dma();
 	initialising=0;
-	if(have_no_fdc)
+	if (have_no_fdc) {
+		DPRINT("no floppy controllers found\n");
 		unregister_blkdev(MAJOR_NR,"fd");
-	else
+	} else
 		virtual_dma_init();
 	return have_no_fdc;
 }
@@ -3896,8 +3890,8 @@
 	}
 	sti();
 	MOD_INC_USE_COUNT;
-	for(i=0; i< N_FDC; i++){
-		if(FDCS->address != -1){
+	for (i=0; i< N_FDC; i++){
+		if (FDCS->address != -1){
 			fdc = i;
 			reset_fdc_info(1);
 			fd_outb(FDCS->dor, FD_DOR);
@@ -3916,8 +3910,8 @@
 		fd_free_irq();
 		return -1;
 	}
-	for(fdc = 0; fdc < N_FDC ; fdc++)
-		if(FDCS->address != -1)
+	for (fdc = 0; fdc < N_FDC; fdc++)
+		if (FDCS->address != -1)
 			fd_outb(FDCS->dor, FD_DOR);
 	fdc = 0;
 	fd_enable_irq();
@@ -3959,15 +3953,15 @@
 	}
 
 #ifdef FLOPPY_SANITY_CHECK
-	for(drive=0; drive < N_FDC * 4; drive++)
-		if( motor_off_timer[drive].next )
+	for (drive=0; drive < N_FDC * 4; drive++)
+		if (motor_off_timer[drive].next)
 			printk("motor off timer %d still active\n", drive);
 
-	if(fd_timeout.next)
+	if (fd_timeout.next)
 		printk("floppy timer still active:%s\n", timeout_message);
 	if (fd_timer.next)
 		printk("auxiliary floppy timer still active\n");
-	if(floppy_tq.sync)
+	if (floppy_tq.sync)
 		printk("task queue still active\n");
 #endif
 }
@@ -3990,29 +3984,29 @@
 	match=0;
 	j=1;
 
-	for(i=current->mm->env_start; i< current->mm->env_end; i ++){
+	for (i=current->mm->env_start; i< current->mm->env_end; i ++){
 		c= get_fs_byte(i);
-		if(match){
-			if(j==99)
+		if (match){
+			if (j==99)
 				c='\0';
 			buffer[j] = c;
-			if(!c || c == ' ' || c == '\t'){
-				if(j){
+			if (!c || c == ' ' || c == '\t'){
+				if (j){
 					buffer[j] = '\0';
 					setup(get_options(buffer,ints),ints);
 				}
 				j=0;
 			} else
 				j++;
-			if(!c)
+			if (!c)
 				break;
 			continue;
 		}
-		if( (!j && !c) || ( j && c == pattern[j-1]))
+		if ((!j && !c) || (j && c == pattern[j-1]))
 			j++;
 		else
 			j=0;
-		if(j==length){
+		if (j==length){
 			match=1;
 			j=0;
 		}
@@ -4025,20 +4019,18 @@
 #endif
 int init_module(void)
 {
-	int ret;
 	printk("inserting floppy driver for %s\n", kernel_version);
 		
 	mod_setup("floppy=", floppy_setup);
 		
-	ret = floppy_init();
-		return 0;
+	return floppy_init();
 }
 
 void cleanup_module(void)
 {
 	int fdc;
 		
-	for(fdc=0; fdc<2; fdc++)
+	for (fdc=0; fdc<2; fdc++)
 		if (FDCS->address != -1){
 			release_region(FDCS->address, 6);
 			release_region(FDCS->address+7, 1);
diff -u --recursive --new-file v1.3.39/linux/drivers/char/console.c linux/drivers/char/console.c
--- v1.3.39/linux/drivers/char/console.c	Wed Nov  8 07:11:31 1995
+++ linux/drivers/char/console.c	Fri Nov 10 11:44:04 1995
@@ -1909,7 +1909,7 @@
  */
 unsigned long con_init(unsigned long kmem_start)
 {
-	char display_desc[5] = "????";
+	char display_desc[] = "????";
 	int currcons = 0;
 	int orig_x = ORIG_X;
 	int orig_y = ORIG_Y;
diff -u --recursive --new-file v1.3.39/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v1.3.39/linux/drivers/char/keyboard.c	Wed Nov  8 07:11:31 1995
+++ linux/drivers/char/keyboard.c	Sat Nov 11 11:18:58 1995
@@ -36,6 +36,17 @@
 #include "diacr.h"
 #include "vt_kern.h"
 
+/*
+ * On non-x86 hardware we do a full keyboard controller
+ * initialization, in case the bootup software hasn't done
+ * it. On a x86, the BIOS will already have initialized the
+ * keyboard.
+ */
+#ifndef __i386__
+#define INIT_KBD
+static int initialize_kbd(void);
+#endif
+
 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
 
 #define KBD_REPORT_ERR
@@ -1195,35 +1206,15 @@
 	bh_base[KEYBOARD_BH].routine = kbd_bh;
 	request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard");
 	request_region(0x60,16,"kbd");
-#ifdef __alpha__
-#if 0
-	/* if there is an input byte left, eat it up: */
-	if (inb(0x64) & 0x01) {
-	    inb(0x60);
-	}
-
-	/* enable keyboard interrupts, PC/AT mode */
-	kb_wait();
-	outb(0x60,0x64);	/* write PS/2 Mode Register */
-	kb_wait();
-	outb(0x65,0x60);	/* KCC | DMS | SYS | EKI */
-	kb_wait();
-	if (!send_data(0xf0) || !send_data(0x02))
-		printk("Scanmode 2 change failed\n");
-#else /* 0 */
-	{
-	    static int alpha_kbd_init(void);	/* forward decl */
-
-	    alpha_kbd_init();
-	}
-#endif /* 0 */
-#endif /* __alpha __ */
+#ifdef INIT_KBD
+	initialize_kbd();
+#endif
 	mark_bh(KEYBOARD_BH);
 	enable_bh(KEYBOARD_BH);
 	return 0;
 }
 
-#ifdef __alpha__
+#ifdef INIT_KBD
 /*
  * keyboard controller registers
  */
@@ -1260,11 +1251,13 @@
  * keyboard controller mode register bits
  */
 #define KBD_EKI		    (unsigned int) 0x01
+#define KBD_SYS		    (unsigned int) 0x04
+#define KBD_DMS		    (unsigned int) 0x20
+#define KBD_KCC		    (unsigned int) 0x40
 
 #define TIMEOUT_CONST	500000
 
-static int
-kbd_wait_for_input(void)
+static int kbd_wait_for_input(void)
 {
         int     n;
         int     status, data;
@@ -1297,105 +1290,102 @@
         return (-1);	/* timed-out if fell through to here... */
 }
 
-static void
-kbd_write(int address, int data)
+static void kbd_write(int address, int data)
 {
-    int status;
-   
-   do {
-      status = inb(KBD_STATUS_REG);  /* spin until input buffer empty*/
-   } while (status & KBD_IBF);
-   outb(data, address);               /* write out the data*/
-}
-
-static int
-alpha_kbd_init(void)
-{
-    unsigned long flags;
-
-    save_flags(flags); cli();
-
-    /* Flush any pending input. */
-    while (kbd_wait_for_input() != -1)
-      continue;
-
-    /*
-     * Test the keyboard interface.
-     * This seems to be the only way to get it going.
-     * If the test is successful a x55 is placed in the input buffer.
-     */
-    kbd_write(KBD_CNTL_REG, KBD_SELF_TEST);
-    if (kbd_wait_for_input() != 0x55) {
-      printk("alpha_kbd_init: keyboard failed self test.\n");
-      restore_flags(flags);
-      return(-1);
-    }
+	int status;
 
-    /*
-     * Perform a keyboard interface test.  This causes the controller
-     * to test the keyboard clock and data lines.  The results of the
-     * test are placed in the input buffer.
-     */
-    kbd_write(KBD_CNTL_REG, KBD_SELF_TEST2);
-    if (kbd_wait_for_input() != 0x00) {
-      printk("alpha_kbd_init: keyboard failed self test 2.\n");
-      restore_flags(flags);
-      return(-1);
-    }
+	do {
+		status = inb(KBD_STATUS_REG);  /* spin until input buffer empty*/
+	} while (status & KBD_IBF);
+	outb(data, address);               /* write out the data*/
+}
 
-    /* Enable the keyboard by allowing the keyboard clock to run. */
-    kbd_write(KBD_CNTL_REG, KBD_CNTL_ENABLE);
+static int initialize_kbd(void)
+{
+	unsigned long flags;
 
-    /*
-     * Reset keyboard. If the read times out
-     * then the assumption is that no keyboard is
-     * plugged into the machine.
-     * This defaults the keyboard to scan-code set 2.
-     */
-    kbd_write(KBD_DATA_REG, KBD_RESET);
-    if (kbd_wait_for_input() != KBD_ACK) {
-      printk("alpha_kbd_init: reset kbd failed, no ACK.\n");
-      restore_flags(flags);
-      return(-1);
-    }
+	save_flags(flags); cli();
 
-    if (kbd_wait_for_input() != KBD_POR) {
-      printk("alpha_kbd_init: reset kbd failed, not POR.\n");
-      restore_flags(flags);
-      return(-1);
-    }
+	/* Flush any pending input. */
+	while (kbd_wait_for_input() != -1)
+		continue;
 
-    /*
-     * now do a DEFAULTS_DISABLE always
-     */
-    kbd_write(KBD_DATA_REG, KBD_DISABLE);
-    if (kbd_wait_for_input() != KBD_ACK) {
-      printk("alpha_kbd_init: disable kbd failed, no ACK.\n");
-      restore_flags(flags);
-      return(-1);
-    }
+	/*
+	 * Test the keyboard interface.
+	 * This seems to be the only way to get it going.
+	 * If the test is successful a x55 is placed in the input buffer.
+	 */
+	kbd_write(KBD_CNTL_REG, KBD_SELF_TEST);
+	if (kbd_wait_for_input() != 0x55) {
+		printk("initialize_kbd: keyboard failed self test.\n");
+		restore_flags(flags);
+		return(-1);
+	}
 
-    /*
-     * enable keyboard interrupt, operate in "real" mode,
-     * Enable keyboard (by clearing the disable keyboard bit),
-     * no conversion of keycodes.
-     */
-    kbd_write(KBD_CNTL_REG, KBD_WRITE_MODE);
-    kbd_write(KBD_DATA_REG, KBD_EKI);
-
-    /*
-     * now ENABLE the keyboard to set it scanning...
-     */
-    kbd_write(KBD_DATA_REG, KBD_ENABLE);
-    if (kbd_wait_for_input() != KBD_ACK) {
-      printk("alpha_kbd_init: keyboard enable failed.\n");
-      restore_flags(flags);
-      return(-1);
-    }
+	/*
+	 * Perform a keyboard interface test.  This causes the controller
+	 * to test the keyboard clock and data lines.  The results of the
+	 * test are placed in the input buffer.
+	 */
+	kbd_write(KBD_CNTL_REG, KBD_SELF_TEST2);
+	if (kbd_wait_for_input() != 0x00) {
+		printk("initialize_kbd: keyboard failed self test 2.\n");
+		restore_flags(flags);
+		return(-1);
+	}
+
+	/* Enable the keyboard by allowing the keyboard clock to run. */
+	kbd_write(KBD_CNTL_REG, KBD_CNTL_ENABLE);
+
+	/*
+	 * Reset keyboard. If the read times out
+	 * then the assumption is that no keyboard is
+	 * plugged into the machine.
+	 * This defaults the keyboard to scan-code set 2.
+	 */
+	kbd_write(KBD_DATA_REG, KBD_RESET);
+	if (kbd_wait_for_input() != KBD_ACK) {
+		printk("initialize_kbd: reset kbd failed, no ACK.\n");
+		restore_flags(flags);
+		return(-1);
+	}
+
+	if (kbd_wait_for_input() != KBD_POR) {
+		printk("initialize_kbd: reset kbd failed, not POR.\n");
+		restore_flags(flags);
+		return(-1);
+	}
+
+	/*
+	 * now do a DEFAULTS_DISABLE always
+	 */
+	kbd_write(KBD_DATA_REG, KBD_DISABLE);
+	if (kbd_wait_for_input() != KBD_ACK) {
+		printk("initialize_kbd: disable kbd failed, no ACK.\n");
+		restore_flags(flags);
+		return(-1);
+	}
 
-    restore_flags(flags);
+	/*
+	 * Enable keyboard interrupt, operate in "sys" mode,
+	 *  enable keyboard (by clearing the disable keyboard bit),
+	 *  disable mouse, do conversion of keycodes.
+	 */
+	kbd_write(KBD_CNTL_REG, KBD_WRITE_MODE);
+	kbd_write(KBD_DATA_REG, KBD_EKI|KBD_SYS|KBD_DMS|KBD_KCC);
+
+	/*
+	 * now ENABLE the keyboard to set it scanning...
+	 */
+	kbd_write(KBD_DATA_REG, KBD_ENABLE);
+	if (kbd_wait_for_input() != KBD_ACK) {
+		printk("initialize_kbd: keyboard enable failed.\n");
+		restore_flags(flags);
+		return(-1);
+	}
 
-    return (1);
+	restore_flags(flags);
 
+	return (1);
 }
-#endif /* __alpha__ */
+#endif /* INIT_KBD */
diff -u --recursive --new-file v1.3.39/linux/drivers/char/vga.c linux/drivers/char/vga.c
--- v1.3.39/linux/drivers/char/vga.c	Wed Nov  8 07:11:31 1995
+++ linux/drivers/char/vga.c	Fri Nov 10 07:51:31 1995
@@ -144,14 +144,14 @@
 		{
 			video_type = VIDEO_TYPE_EGAM;
 			video_mem_term = 0xb8000;
-			display_desc = "EGA+";
+			strcpy(display_desc, "EGA+");
 			request_region(0x3b0,16,"ega");
 		}
 		else
 		{
 			video_type = VIDEO_TYPE_MDA;
 			video_mem_term = 0xb2000;
-			display_desc = "*MDA";
+			strcpy(display_desc, "*MDA");
 			request_region(0x3b0,12,"mda");
 			request_region(0x3bf, 1,"mda");
 		}
@@ -170,11 +170,11 @@
 
 			if (!ORIG_VIDEO_ISVGA) {
 				video_type = VIDEO_TYPE_EGAC;
-				display_desc = "EGA";
+				strcpy(display_desc, "EGA");
 				request_region(0x3c0,32,"ega");
 			} else {
 				video_type = VIDEO_TYPE_VGAC;
-				display_desc = "VGA+";
+				strcpy(display_desc, "VGA+");
 				request_region(0x3c0,32,"vga+");
 
 #ifdef VGA_CAN_DO_64KB
@@ -215,7 +215,7 @@
 		{
 			video_type = VIDEO_TYPE_CGA;
 			video_mem_term = 0xba000;
-			display_desc = "*CGA";
+			strcpy(display_desc, "*CGA");
 			request_region(0x3d4,2,"cga");
 		}
 	}
diff -u --recursive --new-file v1.3.39/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v1.3.39/linux/drivers/net/Config.in	Mon Oct 23 18:02:06 1995
+++ linux/drivers/net/Config.in	Fri Nov 10 08:34:30 1995
@@ -64,6 +64,7 @@
   fi
   tristate 'Apricot Xen-II on board ethernet' CONFIG_APRICOT
   tristate 'DE425, DE434, DE435, DE500 support' CONFIG_DE4X5
+  tristate 'ICL EtherTeam 16i/32 support' CONFIG_ETH16
 # tristate 'DEC 21040 PCI support' CONFIG_DEC_ELCP
 # bool 'LPL T100V 100Mbs support' CONFIG_LPL_T100
 # bool 'PCnet32 (32 bit VLB and PCI LANCE) support' CONFIG_PCNET32
diff -u --recursive --new-file v1.3.39/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v1.3.39/linux/drivers/net/Makefile	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/Makefile	Fri Nov 10 08:34:30 1995
@@ -332,6 +332,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_ETH16),y)
+L_OBJS += eth16i.o
+else
+  ifeq ($(CONFIG_ETH16),m)
+  M_OBJS += eth16i.o
+  endif
+endif
+
 ifeq ($(CONFIG_PI),y)
 L_OBJS += pi2.o
 CONFIG_PI = CONFIG_PI
diff -u --recursive --new-file v1.3.39/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c
--- v1.3.39/linux/drivers/net/eth16i.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/net/eth16i.c	Fri Nov 10 08:29:51 1995
@@ -0,0 +1,1215 @@
+/* eth16i.c An ICL EtherTeam 16i/32 ethernet driver for Linux
+
+   Written 1994-95 by Mika Kuoppala
+
+   Copyright (C) 1994, 1995 by Mika Kuoppala
+   Based on skeleton.c and at1700.c by Donald Becker
+
+   This software may be used and distributed according to the terms
+   of the GNU Public Licence, incorporated herein by reference.
+
+   The author may be reached as miku@pupu.elt.icl.fi
+
+   Sources:
+     - skeleton.c  a sample network driver core for linux,
+       written by Donald Becker <becker@cesdis.gsfc.nasa.gov>
+     - at1700.c a driver for Allied Telesis AT1700, written 
+       by Donald Becker.
+     - e16iSRV.asm a Netware 3.X Server Driver for ICL EtherTeam16i
+       written by Markku Viima
+     - The Fujitsu MB86965 databook.
+   
+   Valuable assistance from:
+	Markku Viima (ICL) 
+	Ari Valve (ICL)
+   
+   Revision history:
+
+   Version	Date		Description
+   
+   0.01		15.12-94	Initial version (card detection)
+   0.02         23.01-95        Interrupt is now hooked correctly
+   0.03         01.02-95        Rewrote initialization part
+   0.04         07.02-95        Base skeleton done...
+				Made a few changes to signature checking
+				to make it a bit reliable.
+				- fixed bug in tx_buf mapping
+				- fixed bug in initialization (DLC_EN
+				  wasn't enabled when initialization
+				  was done.)
+   0.05		08.02-95	If there were more than one packet to send,
+				transmit was jammed due to invalid
+				register write...now fixed
+   0.06         19.02-95        Rewrote interrupt handling        
+   0.07         13.04-95        Wrote EEPROM read routines
+                                Card configuration now set according to
+				data read from EEPROM
+   0.08         23.06-95        Wrote part that tries to probe used interface
+                                port if AUTO is selected
+
+   0.09         01.09-95	Added module support
+   
+   0.10         04.09-95	Fixed receive packet allocation to work		
+        			with kernels > 1.3.x
+   
+   0.20		20.09-95	Added support for EtherTeam32 EISA	
+
+   0.21         17.10-95        Removed the unnecessary extern 
+				init_etherdev() declaration. Some
+				other cleanups.
+   Bugs:
+	In some cases the interface autoprobing code doesn't find 
+	the correct interface type. In this case you can 
+	manually choose the interface type in DOS with E16IC.EXE which is 
+	configuration software for EtherTeam16i and EtherTeam32 cards.
+	
+   To do:
+	- Real multicast support
+*/
+
+static char *version = 
+	"eth16i.c: v0.21 17-10-95 Mika Kuoppala (miku@pupu.elt.icl.fi)\n";
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>		  
+#include <linux/fcntl.h>		  
+#include <linux/interrupt.h>		  
+#include <linux/ptrace.h>		  
+#include <linux/ioport.h>		  
+#include <linux/in.h>		  
+#include <linux/malloc.h>		  
+#include <linux/string.h>		  
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/system.h>		  
+#include <asm/bitops.h>		  
+#include <asm/io.h>		  
+#include <asm/dma.h>
+
+/* Few macros */
+#define BIT(a)		        ( (1 << (a)) )  
+#define BITSET(ioaddr, bnum)   ((outb(((inb(ioaddr)) | (bnum)), ioaddr))) 
+#define BITCLR(ioaddr, bnum)   ((outb(((inb(ioaddr)) & (~(bnum))), ioaddr)))
+
+/* This is the I/O address space for Etherteam 16i adapter. */
+#define ETH16I_IO_EXTENT 32
+
+/* Ticks before deciding that transmit has timed out */
+#define TIMEOUT_TICKS          30
+
+/* Maximum loop count when receiving packets */
+#define MAX_RX_LOOP            40
+
+/* Some interrupt masks */
+#define ETH16I_INTR_ON	       0x8f82
+#define ETH16I_INTR_OFF	       0x0000
+	 
+/* Buffers header status byte meanings */
+#define PKT_GOOD               BIT(5)
+#define PKT_GOOD_RMT           BIT(4)
+#define PKT_SHORT              BIT(3)
+#define PKT_ALIGN_ERR          BIT(2)
+#define PKT_CRC_ERR            BIT(1)
+#define PKT_RX_BUF_OVERFLOW    BIT(0)
+
+/* Transmit status register (DLCR0) */
+#define TX_STATUS_REG          0
+#define TX_DONE                BIT(7)
+#define NET_BUSY               BIT(6)
+#define TX_PKT_RCD             BIT(5)
+#define CR_LOST                BIT(4)
+#define COLLISION              BIT(2)
+#define COLLISIONS_16          BIT(1)
+
+/* Receive status register (DLCR1) */
+#define RX_STATUS_REG          1
+#define RX_PKT                 BIT(7)  /* Packet received */
+#define BUS_RD_ERR             BIT(6)
+#define SHORT_PKT_ERR          BIT(3)
+#define ALIGN_ERR              BIT(2)
+#define CRC_ERR                BIT(1)
+#define RX_BUF_OVERFLOW        BIT(0)
+              
+/* Transmit Interrupt Enable Register (DLCR2) */
+#define TX_INTR_REG            2
+#define TX_INTR_DONE           BIT(7)
+#define TX_INTR_COL            BIT(2)
+#define TX_INTR_16_COL         BIT(1)
+
+/* Receive Interrupt Enable Register (DLCR3) */
+#define RX_INTR_REG            3
+#define RX_INTR_RECEIVE        BIT(7)
+#define RX_INTR_SHORT_PKT      BIT(3)
+#define RX_INTR_CRC_ERR        BIT(1)
+#define RX_INTR_BUF_OVERFLOW   BIT(0)
+
+/* Transmit Mode Register (DLCR4) */
+#define TRANSMIT_MODE_REG      4
+#define LOOPBACK_CONTROL       BIT(1)
+#define CONTROL_OUTPUT         BIT(2)
+
+/* Receive Mode Register (DLCR5) */
+#define RECEIVE_MODE_REG       5
+#define RX_BUFFER_EMPTY        BIT(6)
+#define ACCEPT_BAD_PACKETS     BIT(5)
+#define RECEIVE_SHORT_ADDR     BIT(4)
+#define ACCEPT_SHORT_PACKETS   BIT(3)
+#define REMOTE_RESET           BIT(2)
+
+#define ADDRESS_FILTER_MODE    BIT(1) | BIT(0)
+#define REJECT_ALL             0
+#define ACCEPT_ALL             3
+#define MODE_1                 1            /* NODE ID, BC, MC, 2-24th bit */
+#define MODE_2                 2            /* NODE ID, BC, MC, Hash Table */
+
+/* Configuration Register 0 (DLCR6) */
+#define CONFIG_REG_0           6
+#define DLC_EN                 BIT(7)
+#define SRAM_CYCLE_TIME_100NS  BIT(6)
+#define SYSTEM_BUS_WIDTH_8     BIT(5)       /* 1 = 8bit, 0 = 16bit */
+#define BUFFER_WIDTH_8         BIT(4)       /* 1 = 8bit, 0 = 16bit */
+#define TBS1                   BIT(3)       
+#define TBS0                   BIT(2)
+#define BS1                    BIT(1)       /* 00=8kb,  01=16kb  */
+#define BS0                    BIT(0)       /* 10=32kb, 11=64kb  */
+
+#ifndef ETH16I_TX_BUF_SIZE                   /* 0 = 2kb, 1 = 4kb  */ 
+#define ETH16I_TX_BUF_SIZE     2             /* 2 = 8kb, 3 = 16kb */
+#endif                                      
+#define TX_BUF_1x2048            0
+#define TX_BUF_2x2048            1
+#define TX_BUF_2x4098            2
+#define TX_BUF_2x8192            3
+
+/* Configuration Register 1 (DLCR7) */
+#define CONFIG_REG_1           7
+#define POWERUP                BIT(5)
+
+/* Transmit start register */
+#define TRANSMIT_START_REG     10
+#define TRANSMIT_START_RB      2
+#define TX_START               BIT(7)       /* Rest of register bit indicate*/
+                                            /* number of packets in tx buffer*/
+/* Node ID registers (DLCR8-13) */
+#define NODE_ID_0              8
+#define NODE_ID_RB             0
+
+/* Hash Table registers (HT8-15) */
+#define HASH_TABLE_0           8
+#define HASH_TABLE_RB          1
+
+/* Buffer memory ports */
+#define BUFFER_MEM_PORT_LB    8
+#define DATAPORT              BUFFER_MEM_PORT_LB
+#define BUFFER_MEM_PORT_HB    9
+
+/* 16 Collision control register (BMPR11) */
+#define COL_16_REG             11
+#define HALT_ON_16             0x00
+#define RETRANS_AND_HALT_ON_16 0x02
+
+/* DMA Burst and Transceiver Mode Register (BMPR13) */
+#define TRANSCEIVER_MODE_REG   13
+#define TRANSCEIVER_MODE_RB    2         
+#define IO_BASE_UNLOCK	       BIT(7)
+#define LOWER_SQUELCH_TRESH    BIT(6)
+#define LINK_TEST_DISABLE      BIT(5)
+#define AUI_SELECT             BIT(4)
+#define DIS_AUTO_PORT_SEL      BIT(3)
+
+/* Filter Self Receive Register (BMPR14)  */
+#define FILTER_SELF_RX_REG     14
+#define SKIP_RECEIVE_PACKET    BIT(2)
+#define FILTER_SELF_RECEIVE    BIT(0)
+#define RX_BUF_SKIP_PACKET     SKIP_RECEIVE_PACKET | FILTER_SELF_RECEIVE
+
+/* EEPROM Control Register (BMPR 16) */
+#define EEPROM_CTRL_REG        16
+
+/* EEPROM Data Register (BMPR 17) */
+#define EEPROM_DATA_REG        17
+
+/* NMC93CSx6 EEPROM Control Bits */
+#define CS_0                   0x00
+#define CS_1                   0x20
+#define SK_0                   0x00
+#define SK_1                   0x40
+#define DI_0                   0x00
+#define DI_1                   0x80
+
+/* NMC93CSx6 EEPROM Instructions */
+#define EEPROM_READ            0x80
+
+/* NMC93CSx6 EEPROM Addresses */
+#define E_NODEID_0                     0x02
+#define E_NODEID_1                     0x03
+#define E_NODEID_2                     0x04
+#define E_PORT_SELECT                  0x14
+  #define E_PORT_BNC                   0
+  #define E_PORT_DIX                   1
+  #define E_PORT_TP                    2
+  #define E_PORT_AUTO                  3
+#define E_PRODUCT_CFG                  0x30
+ 
+
+/* Macro to slow down io between EEPROM clock transitions */
+#define eeprom_slow_io() do { int _i = 40; while(--_i > 0) { __SLOW_DOWN_IO; }}while(0)
+
+/* Jumperless Configuration Register (BMPR19) */
+#define JUMPERLESS_CONFIG      19
+
+/* ID ROM registers, writing to them also resets some parts of chip */
+#define ID_ROM_0               24
+#define ID_ROM_7               31
+#define RESET                  ID_ROM_0
+
+/* This is the I/O address list to be probed when seeking the card */
+static unsigned int eth16i_portlist[] =
+   { 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 };
+
+static unsigned int eth32i_portlist[] =
+   { 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
+     0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0 };
+
+/* This is the Interrupt lookup table for Eth16i card */
+static unsigned int eth16i_irqmap[] = { 9, 10, 5, 15 };
+
+/* This is the Interrupt lookup table for Eth32i card */
+static unsigned int eth32i_irqmap[] = { 3, 5, 7, 9, 10, 11, 12, 15 };  
+#define EISA_IRQ_REG	0xc89
+
+static unsigned int eth16i_tx_buf_map[] = { 2048, 2048, 4096, 8192 };
+unsigned int boot = 1;
+
+/* Use 0 for production, 1 for verification, >2 for debug */
+#ifndef ETH16I_DEBUG
+#define ETH16I_DEBUG 0
+#endif
+static unsigned int eth16i_debug = ETH16I_DEBUG;
+
+/* Information for each board */
+struct eth16i_local {
+  struct enet_statistics stats;
+  unsigned int tx_started:1;
+  unsigned char tx_queue;         /* Number of packets in transmit buffer */
+  unsigned short tx_queue_len;         
+  unsigned int tx_buf_size;
+  unsigned long open_time;
+};
+
+/* Function prototypes */
+
+extern int eth16i_probe(struct device *dev);
+
+static int eth16i_probe1(struct device *dev, short ioaddr);
+static int eth16i_check_signature(short ioaddr);
+static int eth16i_probe_port(short ioaddr);
+static void eth16i_set_port(short ioaddr, int porttype);
+static int eth16i_send_probe_packet(short ioaddr, unsigned char *b, int l);
+static int eth16i_receive_probe_packet(short ioaddr);
+static int eth16i_get_irq(short ioaddr);
+static int eth16i_read_eeprom(int ioaddr, int offset);
+static int eth16i_read_eeprom_word(int ioaddr);
+static void eth16i_eeprom_cmd(int ioaddr, unsigned char command);
+static int eth16i_open(struct device *dev);
+static int eth16i_close(struct device *dev);
+static int eth16i_tx(struct sk_buff *skb, struct device *dev);
+static void eth16i_rx(struct device *dev);
+static void eth16i_interrupt(int irq, struct pt_regs *regs);
+static void eth16i_multicast(struct device *dev, int num_addrs, void *addrs); 
+static void eth16i_select_regbank(unsigned char regbank, short ioaddr);
+static void eth16i_initialize(struct device *dev);
+static struct enet_statistics *eth16i_get_stats(struct device *dev);
+
+static char *cardname = "ICL EtherTeam 16i/32";
+
+#ifdef HAVE_DEVLIST 
+/* Support for alternate probe manager */
+/struct netdev_entry eth16i_drv = 
+   {"eth16i", eth16i_probe1, ETH16I_IO_EXTENT, eth16i_probe_list}; 
+
+#else  /* Not HAVE_DEVLIST */
+int eth16i_probe(struct device *dev)
+{
+  int i;
+  int ioaddr;
+  int base_addr = dev ? dev->base_addr : 0;
+
+  if(eth16i_debug > 4) 
+    printk("Probing started for %s\n", cardname);
+
+  if(base_addr > 0x1ff)           /* Check only single location */
+    return eth16i_probe1(dev, base_addr);
+  else if(base_addr != 0)         /* Don't probe at all */
+    return ENXIO;
+
+  /* Seek card from the ISA io address space */
+  for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++) {
+    if(check_region(ioaddr, ETH16I_IO_EXTENT))
+      continue;
+    if(eth16i_probe1(dev, ioaddr) == 0)
+      return 0;
+  }
+
+  /* Seek card from the EISA io address space */
+  for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++) {
+    if(check_region(ioaddr, ETH16I_IO_EXTENT))
+	continue;
+    if(eth16i_probe1(dev, ioaddr) == 0)
+	return 0;
+   }
+
+  return ENODEV;
+}
+#endif  /* Not HAVE_DEVLIST */
+
+static int eth16i_probe1(struct device *dev, short ioaddr)
+{
+  static unsigned version_printed = 0;
+  unsigned int irq = 0;
+  boot = 1;          /* To inform initilization that we are in boot probe */
+
+  /*
+     The MB86985 chip has on register which holds information in which 
+     io address the chip lies. First read this register and compare
+     it to our current io address and if match then this could
+     be our chip.
+  */
+  
+  if(ioaddr < 0x1000) {
+    if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)] != ioaddr)
+      return -ENODEV;
+  }
+
+  /* Now we will go a bit deeper and try to find the chip's signature */
+
+  if(eth16i_check_signature(ioaddr) != 0) /* Can we find the signature here */
+    return -ENODEV;
+  
+  /* 
+     Now it seems that we have found a ethernet chip in this particular
+     ioaddr. The MB86985 chip has this feature, that when you read a 
+     certain register it will increase it's io base address to next
+     configurable slot. Now when we have found the chip, first thing is
+     to make sure that the chip's ioaddr will hold still here.
+  */
+  
+  eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
+  outb(0x00, ioaddr + TRANSCEIVER_MODE_REG);
+  
+  outb(0x00, ioaddr + RESET);             /* Will reset some parts of chip */
+  BITSET(ioaddr + CONFIG_REG_0, BIT(7));  /* This will disable the data link */
+  
+  if(dev == NULL)
+    dev = init_etherdev(0, sizeof(struct eth16i_local));
+
+  if( (eth16i_debug & version_printed++) == 0)
+    printk(version);
+
+  dev->base_addr = ioaddr;
+ 
+  irq = eth16i_get_irq(ioaddr);
+  dev->irq = irq;
+
+  /* Try to obtain interrupt vector */
+  if(request_irq(dev->irq, &eth16i_interrupt, 0, "eth16i")) {
+    printk("%s: %s at %#3x, but is unusable due 
+           conflict on IRQ %d.\n", dev->name, cardname, ioaddr, irq);
+    return EAGAIN;
+  }
+
+  printk("%s: %s at %#3x, IRQ %d, ", 
+	 dev->name, cardname, ioaddr, dev->irq);
+
+  /* Let's grab the region */
+  request_region(ioaddr, ETH16I_IO_EXTENT, "eth16i");
+
+  /* Now we will have to lock the chip's io address */
+  eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
+  outb(0x38, ioaddr + TRANSCEIVER_MODE_REG); 
+
+  eth16i_initialize(dev);   /* Initialize rest of the chip's registers */
+  
+  /* Now let's same some energy by shutting down the chip ;) */
+  BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
+   
+  /* Initialize the device structure */
+  if(dev->priv == NULL)
+    dev->priv = kmalloc(sizeof(struct eth16i_local), GFP_KERNEL);
+  memset(dev->priv, 0, sizeof(struct eth16i_local));
+
+  dev->open               = eth16i_open;
+  dev->stop               = eth16i_close;
+  dev->hard_start_xmit    = eth16i_tx;
+  dev->get_stats          = eth16i_get_stats;
+  dev->set_multicast_list = &eth16i_multicast;
+
+  /* Fill in the fields of the device structure with ethernet values. */
+  ether_setup(dev);
+
+  boot = 0;
+
+  return 0;
+}
+
+
+static void eth16i_initialize(struct device *dev)
+{
+  short ioaddr = dev->base_addr;
+  int i, node_w = 0;
+  unsigned char node_byte = 0;
+
+  /* Setup station address */
+  eth16i_select_regbank(NODE_ID_RB, ioaddr);
+  for(i = 0 ; i < 3 ; i++) {
+    unsigned short node_val = eth16i_read_eeprom(ioaddr, E_NODEID_0 + i);
+    ((unsigned short *)dev->dev_addr)[i] = ntohs(node_val);
+  }
+
+  for(i = 0; i < 6; i++) { 
+    outb( ((unsigned char *)dev->dev_addr)[i], ioaddr + NODE_ID_0 + i);
+    if(boot) {
+      printk("%02x", inb(ioaddr + NODE_ID_0 + i));
+      if(i != 5)
+	printk(":");
+    }
+  }
+
+  /* Now we will set multicast addresses to accept none */
+  eth16i_select_regbank(HASH_TABLE_RB, ioaddr);
+  for(i = 0; i < 8; i++) 
+    outb(0x00, ioaddr + HASH_TABLE_0 + i);
+
+  /*
+     Now let's disable the transmitter and receiver, set the buffer ram 
+     cycle time, bus width and buffer data path width. Also we shall
+     set transmit buffer size and total buffer size.
+  */
+
+  eth16i_select_regbank(2, ioaddr);
+
+  node_byte = 0;
+  node_w = eth16i_read_eeprom(ioaddr, E_PRODUCT_CFG);
+
+  if( (node_w & 0xFF00) == 0x0800)
+    node_byte |= BUFFER_WIDTH_8;
+
+  node_byte |= BS1;
+
+  if( (node_w & 0x00FF) == 64)
+    node_byte |= BS0;
+  
+  node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2);
+
+  outb(node_byte, ioaddr + CONFIG_REG_0);
+
+  /* We shall halt the transmitting, if 16 collisions are detected */
+  outb(RETRANS_AND_HALT_ON_16, ioaddr + COL_16_REG);
+
+  if(boot) /* Now set port type */
+  {
+    char *porttype[] = {"BNC", "DIX", "TP", "AUTO"};
+    
+    ushort ptype = eth16i_read_eeprom(ioaddr, E_PORT_SELECT);
+    dev->if_port = (ptype & 0x00FF);
+    
+    printk(" %s interface.\n", porttype[dev->if_port]);
+
+    if(ptype == E_PORT_AUTO)
+      ptype = eth16i_probe_port(ioaddr);
+    
+    eth16i_set_port(ioaddr, ptype);
+  }
+
+  /* Set Receive Mode to normal operation */
+  outb(MODE_2, ioaddr + RECEIVE_MODE_REG);
+}
+
+static int eth16i_probe_port(short ioaddr)
+{
+  int i;
+  int retcode;
+  unsigned char dummy_packet[64] = { 0 };
+
+  /* Powerup the chip */
+  outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
+
+  BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+
+  eth16i_select_regbank(NODE_ID_RB, ioaddr);
+
+  for(i = 0; i < 6; i++) {
+    dummy_packet[i] = inb(ioaddr + NODE_ID_0 + i);
+    dummy_packet[i+6] = inb(ioaddr + NODE_ID_0 + i);
+  }
+
+  dummy_packet[12] = 0x00;
+  dummy_packet[13] = 0x04;
+
+  eth16i_select_regbank(2, ioaddr);
+
+  for(i = 0; i < 3; i++) {
+    BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+    BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+    eth16i_set_port(ioaddr, i);
+   
+    if(eth16i_debug > 1)
+    	printk("Set port number %d\n", i);
+
+    retcode = eth16i_send_probe_packet(ioaddr, dummy_packet, 64);
+    if(retcode == 0) {
+      retcode = eth16i_receive_probe_packet(ioaddr);
+      if(retcode != -1) {
+	if(eth16i_debug > 1)
+		printk("Eth16i interface port found at %d\n", i);
+	return i;
+      }
+    }
+    else {
+      if(eth16i_debug > 1)
+      	printk("TRANSMIT_DONE timeout\n");
+    }
+  }
+  
+  if( eth16i_debug > 1)
+  	printk("Using default port\n");
+ 
+ return E_PORT_BNC;
+}
+
+static void eth16i_set_port(short ioaddr, int porttype)
+{ 
+    unsigned short temp = 0;
+
+    eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
+    outb(LOOPBACK_CONTROL, ioaddr + TRANSMIT_MODE_REG);
+
+    temp |= DIS_AUTO_PORT_SEL;
+
+    switch(porttype) {
+
+    case E_PORT_BNC :
+      temp |= AUI_SELECT;
+      break;
+
+    case E_PORT_TP :
+      break;
+      
+    case E_PORT_DIX :
+      temp |= AUI_SELECT;
+      BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT);
+      break;
+    }  
+    outb(temp, ioaddr + TRANSCEIVER_MODE_REG);
+
+    if(eth16i_debug > 1) {
+    	printk("TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG));
+    	printk("TRANSCEIVER_MODE_REG = %x\n", inb(ioaddr+TRANSCEIVER_MODE_REG));
+    }
+}
+
+static int eth16i_send_probe_packet(short ioaddr, unsigned char *b, int l)
+{
+  int starttime;
+
+  outb(0xff, ioaddr + TX_STATUS_REG);
+
+  outw(l, ioaddr + DATAPORT);
+  outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1);  
+  
+  starttime = jiffies;
+  outb(TX_START | 1, ioaddr + TRANSMIT_START_REG); 
+
+  while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) {
+    if( (jiffies - starttime) > TIMEOUT_TICKS) {
+      break;
+    }
+  }
+  
+  return(0);
+}
+
+static int eth16i_receive_probe_packet(short ioaddr)
+{
+  int starttime;
+  
+  starttime = jiffies;
+  
+  while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) {
+    if( (jiffies - starttime) > TIMEOUT_TICKS) {
+      
+      if(eth16i_debug > 1)
+	printk("Timeout occured waiting transmit packet received\n");
+      starttime = jiffies;
+      while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
+	if( (jiffies - starttime) > TIMEOUT_TICKS) {
+	if(eth16i_debug > 1)
+	  printk("Timeout occured waiting receive packet\n");
+        return -1;
+        }
+      }
+      
+      if(eth16i_debug > 1)
+      	printk("RECEIVE_PACKET\n");
+      return(0); /* Found receive packet */
+    }
+  }
+
+  if(eth16i_debug > 1) {
+  	printk("TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG));
+  	printk("RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
+  }
+
+  return(0); /* Return success */
+}
+
+static int eth16i_get_irq(short ioaddr)
+{
+  unsigned char cbyte;
+  
+  if( ioaddr < 0x1000) {
+  	cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
+	return( eth16i_irqmap[ ((cbyte & 0xC0) >> 6) ] );
+  } else {  /* Oh..the card is EISA so method getting IRQ different */
+	unsigned short index = 0;
+	cbyte = inb(ioaddr + EISA_IRQ_REG);
+	while( (cbyte & 0x01) == 0) {
+		cbyte = cbyte >> 1;
+		index++;
+        }
+	return( eth32i_irqmap[ index ] );
+  }
+}
+
+static int eth16i_check_signature(short ioaddr)
+{
+  int i;
+  unsigned char creg[4] = { 0 };
+  
+  for(i = 0; i < 4 ; i++) {
+
+    creg[i] = inb(ioaddr + TRANSMIT_MODE_REG + i);
+  
+    if(eth16i_debug > 1)
+	printk("eth16i: read signature byte %x at %x\n", creg[i],
+	       ioaddr + TRANSMIT_MODE_REG + i);
+  }
+
+  creg[0] &= 0x0F;      /* Mask collision cnr */
+  creg[2] &= 0x7F;      /* Mask DCLEN bit */
+
+#ifdef 0
+/* 
+	This was removed because the card was sometimes left to state
+  	from which it couldn't be find anymore. If there is need
+	to more strict chech still this have to be fixed.
+*/
+  if( !( (creg[0] == 0x06) && (creg[1] == 0x41)) ) {
+    if(creg[1] != 0x42)
+      return -1;
+  }
+#endif
+
+  if( !( (creg[2] == 0x36) && (creg[3] == 0xE0)) ) {
+      creg[2] &= 0x42;
+      creg[3] &= 0x03;
+
+      if( !( (creg[2] == 0x42) && (creg[3] == 0x00)) )
+	return -1;
+  }
+
+  if(eth16i_read_eeprom(ioaddr, E_NODEID_0) != 0)
+    return -1;
+  if((eth16i_read_eeprom(ioaddr, E_NODEID_1) & 0xFF00) != 0x4B00)
+    return -1;
+
+  return 0;
+}
+
+static int eth16i_read_eeprom(int ioaddr, int offset)
+{
+  int data = 0;
+
+  eth16i_eeprom_cmd(ioaddr, EEPROM_READ | offset);
+  outb(CS_1, ioaddr + EEPROM_CTRL_REG);
+  data = eth16i_read_eeprom_word(ioaddr);
+  outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
+
+  return(data);  
+}
+
+static int eth16i_read_eeprom_word(int ioaddr)
+{
+  int i;
+  int data = 0;
+
+  for(i = 16; i > 0; i--) {
+    outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
+    eeprom_slow_io();
+    outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
+    eeprom_slow_io();
+    data = (data << 1) | ((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0);
+    eeprom_slow_io();
+  }
+
+  return(data);
+}
+
+static void eth16i_eeprom_cmd(int ioaddr, unsigned char command)
+{
+  int i;
+  
+  outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
+  outb(DI_0, ioaddr + EEPROM_DATA_REG);
+  outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
+  outb(DI_1, ioaddr + EEPROM_DATA_REG);
+  outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
+
+  for(i = 7; i >= 0; i--) {
+    short cmd = ( (command & (1 << i)) ? DI_1 : DI_0 );
+    outb(cmd, ioaddr + EEPROM_DATA_REG);
+    outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
+    eeprom_slow_io();
+    outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
+    eeprom_slow_io();
+  } 
+}
+
+static int eth16i_open(struct device *dev)
+{
+  struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+  int ioaddr = dev->base_addr;
+  
+  irq2dev_map[dev->irq] = dev;
+
+  /* Powerup the chip */
+  outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
+  
+  /* Initialize the chip */
+  eth16i_initialize(dev);  
+  
+  /* Set the transmit buffer size */
+  lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03];
+  
+  if(eth16i_debug > 3)
+    printk("%s: transmit buffer size %d\n", dev->name, lp->tx_buf_size);
+
+  /* Now enable Transmitter and Receiver sections */
+  BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+ 
+  /* Now switch to register bank 2, for run time operation */
+  eth16i_select_regbank(2, ioaddr);
+
+  lp->open_time = jiffies;
+  lp->tx_started = 0;
+  lp->tx_queue = 0;
+  lp->tx_queue_len = 0;
+
+  /* Turn on interrupts*/
+  outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);  
+
+  dev->tbusy = 0;
+  dev->interrupt = 0;
+  dev->start = 1;
+
+#ifdef MODULE
+  MOD_INC_USE_COUNT;
+#endif
+
+  return 0;
+}
+
+static int eth16i_close(struct device *dev)
+{
+  struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+  int ioaddr = dev->base_addr;
+
+  lp->open_time = 0;
+
+  dev->tbusy = 1;
+  dev->start = 0;
+
+  /* Disable transmit and receive */
+  BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+
+  /* Reset the chip */
+  outb(0xff, ioaddr + RESET);
+
+  /* Save some energy by switching off power */
+  BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
+
+#ifdef MODULE
+  MOD_DEC_USE_COUNT;
+#endif
+
+  return 0;
+}
+
+static int eth16i_tx(struct sk_buff *skb, struct device *dev)
+{
+  struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+  int ioaddr = dev->base_addr;
+
+  if(dev->tbusy) {
+    /* 
+       If we get here, some higher level has decided that we are broken. 
+       There should really be a "kick me" function call instead. 
+    */
+    
+    int tickssofar = jiffies - dev->trans_start;
+    if(tickssofar < TIMEOUT_TICKS)  /* Let's not rush with our timeout, */  
+      return 1;                     /* wait a couple of ticks first     */
+
+    printk("%s: transmit timed out with status %04x, %s ?\n", dev->name,
+	   inw(ioaddr + TX_STATUS_REG), 
+	   (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ? 
+	   "IRQ conflict" : "network cable problem");
+
+    /* Let's dump all registers */
+    if(eth16i_debug > 0) { 
+      printk("%s: timeout regs: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
+	     dev->name, inb(ioaddr + 0), inb(ioaddr + 1), inb(ioaddr + 2), 
+	     inb(ioaddr + 3), inb(ioaddr + 4), inb(ioaddr + 5),
+	     inb(ioaddr + 6), inb(ioaddr + 7));
+
+
+      printk("lp->tx_queue = %d\n", lp->tx_queue);
+      printk("lp->tx_queue_len = %d\n", lp->tx_queue_len);
+      printk("lp->tx_started = %d\n", lp->tx_started);
+
+    }
+
+    lp->stats.tx_errors++;
+
+    /* Now let's try to restart the adaptor */
+    
+    BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+    outw(0xffff, ioaddr + RESET);
+    eth16i_initialize(dev);
+    outw(0xffff, ioaddr + TX_STATUS_REG);
+    BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+            
+    lp->tx_started = 0;
+    lp->tx_queue = 0;
+    lp->tx_queue_len = 0;
+    
+    outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+    
+    dev->tbusy = 0;
+    dev->trans_start = jiffies;
+  }
+
+  /* 
+     If some higher layer thinks we've missed an tx-done interrupt
+     we are passed NULL. Caution: dev_tint() handles the cli()/sti()
+     itself 
+  */
+  if(skb == NULL) {
+    dev_tint(dev);
+    return 0;
+  }
+
+  /* Block a timer based transmitter from overlapping. This could better be
+     done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+
+  /* Turn off TX interrupts */
+  outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+
+  if(set_bit(0, (void *)&dev->tbusy) != 0)
+    printk("%s: Transmitter access conflict.\n", dev->name);
+  else {
+    short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+    unsigned char *buf = skb->data;
+  
+    outw(length, ioaddr + DATAPORT);
+    
+    if( ioaddr < 0x1000 ) 
+    	outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+    else {
+	unsigned char frag = length % 4;
+
+	outsl(ioaddr + DATAPORT, buf, length >> 2);
+	
+	if( frag != 0 ) {
+	  outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
+	  if( frag == 3 ) 
+	    outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC) + 2), 1);
+	}
+    }
+
+    lp->tx_queue++;
+    lp->tx_queue_len += length + 2;
+
+    if(lp->tx_started == 0) {
+      /* If the transmitter is idle..always trigger a transmit */
+      outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
+      lp->tx_queue = 0;
+      lp->tx_queue_len = 0;
+      dev->trans_start = jiffies;
+      lp->tx_started = 1;
+      dev->tbusy = 0;
+    }
+    else if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
+      /* There is still more room for one more packet in tx buffer */
+      dev->tbusy = 0;
+    }
+        
+    outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+
+    /* Turn TX interrupts back on */
+    /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
+  } 
+  dev_kfree_skb(skb, FREE_WRITE);
+
+  return 0;
+}
+
+static void eth16i_rx(struct device *dev)
+{
+  struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+  int ioaddr = dev->base_addr;
+  int boguscount = MAX_RX_LOOP;
+
+  /* Loop until all packets have been read */
+  while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) {
+    
+    /* Read status byte from receive buffer */ 
+    ushort status = inw(ioaddr + DATAPORT);
+
+    if(eth16i_debug > 4)
+      printk("%s: Receiving packet mode %02x status %04x.\n", 
+	     dev->name, inb(ioaddr + RECEIVE_MODE_REG), status);
+  
+      if( !(status & PKT_GOOD) ) {
+	/* Hmm..something went wrong. Let's check what error occured */
+	lp->stats.rx_errors++;
+	if( status & PKT_SHORT     ) lp->stats.rx_length_errors++;
+	if( status & PKT_ALIGN_ERR ) lp->stats.rx_frame_errors++;
+	if( status & PKT_CRC_ERR   ) lp->stats.rx_crc_errors++;
+	if( status & PKT_RX_BUF_OVERFLOW) lp->stats.rx_over_errors++;
+      }
+      else {   /* Ok so now we should have a good packet */
+	struct sk_buff *skb;
+
+	/* Get the size of the packet from receive buffer */
+	ushort pkt_len = inw(ioaddr + DATAPORT);
+
+	if(pkt_len > ETH_FRAME_LEN) {
+	  printk("%s: %s claimed a very large packet, size of %d bytes.\n", 
+		 dev->name, cardname, pkt_len);
+	  outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
+	  lp->stats.rx_dropped++;
+	  break;
+	}
+
+	skb = dev_alloc_skb(pkt_len + 3);
+	if( skb == NULL ) {
+	  printk("%s: Could'n allocate memory for packet (len %d)\n", 
+		 dev->name, pkt_len);
+	  outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
+	  lp->stats.rx_dropped++;
+	  break;
+	}
+	
+	skb->dev = dev;
+	skb_reserve(skb,2);
+	/* 
+	   Now let's get the packet out of buffer.
+	   size is (pkt_len + 1) >> 1, cause we are now reading words
+	   and it have to be even aligned.
+	*/ 
+
+	if( ioaddr < 0x1000) 
+	  insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), (pkt_len + 1) >> 1);
+	else {	
+	  unsigned char *buf = skb_put(skb, pkt_len);
+	  unsigned char frag = pkt_len % 4;
+
+	  insl(ioaddr + DATAPORT, buf, pkt_len >> 2);
+	
+	  if(frag != 0) {
+	  	unsigned short rest[2];
+		rest[0] = inw( ioaddr + DATAPORT );
+		if(frag == 3)
+			rest[1] = inw( ioaddr + DATAPORT );
+
+		memcpy(buf + (pkt_len & 0xfffc), (char *)rest, frag);
+	  }
+	}
+	
+        skb->protocol=eth_type_trans(skb, dev);
+	netif_rx(skb);
+	lp->stats.rx_packets++;
+         
+	if( eth16i_debug > 5 ) {
+	  int i;
+	  printk("%s: Received packet of length %d.\n", dev->name, pkt_len);
+	  for(i = 0; i < 14; i++) 
+	    printk(" %02x", skb->data[i]);
+	  printk(".\n");
+	}
+	
+      } /* else */
+
+    if(--boguscount <= 0)
+      break;
+
+  } /* while */
+
+#if 0
+  {
+    int i;
+
+    for(i = 0; i < 20; i++) {
+      if( (inb(ioaddr+RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == RX_BUFFER_EMPTY)
+	break;
+      inw(ioaddr + DATAPORT);
+      outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
+    }
+
+    if(eth16i_debug > 1)
+      printk("%s: Flushed receive buffer.\n", dev->name);
+  }
+#endif
+
+  return;
+}
+
+static void eth16i_interrupt(int irq, struct pt_regs *regs)
+{
+  struct device *dev = (struct device *)(irq2dev_map[irq]);
+  struct eth16i_local *lp;
+  int ioaddr = 0,
+      status;
+
+  if(dev == NULL) {
+    printk("eth16i_interrupt(): irq %d for unknown device. \n", irq);
+    return;
+  }
+
+  /* Turn off all interrupts from adapter */
+  outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG); 
+
+  dev->interrupt = 1;
+
+  ioaddr = dev->base_addr;
+  lp = (struct eth16i_local *)dev->priv;
+  status = inw(ioaddr + TX_STATUS_REG);      /* Get the status */
+  outw(status, ioaddr + TX_STATUS_REG);      /* Clear status bits */
+  
+  if(eth16i_debug > 3)
+    printk("%s: Interrupt with status %04x.\n", dev->name, status);
+
+  if( status & 0x00ff ) {          /* Let's check the transmit status reg */
+    
+    if(status & TX_DONE) {         /* The transmit has been done */
+      lp->stats.tx_packets++;
+
+      if(lp->tx_queue) {           /* Is there still packets ? */
+	  /* There was packet(s) so start transmitting and write also
+	   how many packets there is to be sended */
+	outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
+	lp->tx_queue = 0;
+	lp->tx_queue_len = 0;
+	dev->trans_start = jiffies;
+	dev->tbusy = 0;
+	mark_bh(NET_BH);
+      }
+      else {
+	lp->tx_started = 0;
+	dev->tbusy = 0;
+	mark_bh(NET_BH);
+      }
+    }
+  }
+    
+  if( ( status & 0xff00 ) || 
+     ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) {
+    eth16i_rx(dev);  /* We have packet in receive buffer */
+  }
+
+  dev->interrupt = 0;
+  
+  /* Turn interrupts back on */
+  outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+
+  return;
+}
+
+static void eth16i_multicast(struct device *dev, int num_addrs, void *addrs)
+{
+  short ioaddr = dev->base_addr;
+  
+  if(num_addrs) {
+    outb(3, ioaddr + RECEIVE_MODE_REG);    
+  } else {
+    outb(2, ioaddr + RECEIVE_MODE_REG);
+  }
+}
+
+static struct enet_statistics *eth16i_get_stats(struct device *dev)
+{
+  struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+
+  return &lp->stats;
+}
+
+static void eth16i_select_regbank(unsigned char banknbr, short ioaddr)
+{
+  unsigned char data;
+
+  data = inb(ioaddr + CONFIG_REG_1);
+  outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1); 
+}
+
+#ifdef MODULE
+char kernel_version[] = UTS_RELEASE;
+static char devicename[9] = { 0, };
+static struct device dev_eth16i = {
+	devicename,
+	0, 0, 0, 0,
+	0, 0,
+	0, 0, 0, NULL, eth16i_probe };
+
+int io = 0x2a0;
+int irq = 0;
+
+int init_module(void)
+{
+	if(io == 0)
+		printk("eth16i: You should not use auto-probing with insmod!\n");
+	
+	dev_eth16i.base_addr = io;
+	dev_eth16i.irq = irq;
+	if( register_netdev( &dev_eth16i ) != 0 ) {
+		printk("eth16i: register_netdev() returned non-zero.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	if (MOD_IN_USE)
+		printk("eth16i: Device busy, remove delayed\n");
+	else
+	{
+		unregister_netdev( &dev_eth16i );
+
+		free_irq( dev_eth16i.irq );
+		irq2dev_map[ dev_eth16i.irq ] = NULL;
+		release_region( dev_eth16i.base_addr, ETH16I_IO_EXTENT );
+	}
+}
+
+#endif /* MODULE */
+
+
diff -u --recursive --new-file v1.3.39/linux/drivers/net/plip.c linux/drivers/net/plip.c
--- v1.3.39/linux/drivers/net/plip.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/plip.c	Fri Nov 10 07:56:23 1995
@@ -1138,6 +1138,6 @@
 
 /*
  * Local variables:
- * compile-command: "gcc -DMODULE -DCONFIG_MODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -g -fomit-frame-pointer -pipe -m486 -c plip.c"
+ * compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -g -fomit-frame-pointer -pipe -m486 -c plip.c"
  * End:
  */
diff -u --recursive --new-file v1.3.39/linux/drivers/scsi/constants.c linux/drivers/scsi/constants.c
--- v1.3.39/linux/drivers/scsi/constants.c	Mon Oct 23 18:02:10 1995
+++ linux/drivers/scsi/constants.c	Sat Nov 11 13:10:39 1995
@@ -3,19 +3,13 @@
  * etc.
  */
 
-#ifdef MODULE
 /*
  * Don't import our own symbols, as this would severely mess up our
  * symbol tables.
  */
 #define _SCSI_SYMS_VER_
-#include <linux/autoconf.h>
+#define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
 
 #include <linux/config.h>
 #include <linux/blk.h>
diff -u --recursive --new-file v1.3.39/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v1.3.39/linux/drivers/scsi/hosts.c	Mon Oct 23 18:02:11 1995
+++ linux/drivers/scsi/hosts.c	Sat Nov 11 13:09:55 1995
@@ -16,19 +16,13 @@
  *  hosts currently present in the system.
  */
 
-#ifdef MODULE
 /*
  * Don't import our own symbols, as this would severely mess up our
  * symbol tables.
  */
 #define _SCSI_SYMS_VER_
-#include <linux/autoconf.h>
+#define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
 
 #include <linux/config.h>
 #include <linux/blk.h>
diff -u --recursive --new-file v1.3.39/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.3.39/linux/drivers/scsi/scsi.c	Thu Nov  9 11:23:50 1995
+++ linux/drivers/scsi/scsi.c	Sat Nov 11 10:58:56 1995
@@ -2499,7 +2499,8 @@
 	for(i=0; i < dma_sectors >> 3; i++)
 	    scsi_init_free(dma_malloc_pages[i], PAGE_SIZE);
 	if (dma_malloc_pages)
-	    scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
+	    scsi_init_free((char *) dma_malloc_pages,
+                           (dma_sectors>>3)*sizeof(*dma_malloc_pages));
 	dma_malloc_pages = NULL;
 	if (dma_malloc_freelist)
 	    scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
@@ -2555,8 +2556,10 @@
 	memset(new_dma_malloc_freelist, 0, new_dma_sectors >> 3);
 	
 	new_dma_malloc_pages = (unsigned char **)
-	    scsi_init_malloc(new_dma_sectors >> 1, GFP_ATOMIC);
-	memset(new_dma_malloc_pages, 0, new_dma_sectors >> 1);
+	    scsi_init_malloc((new_dma_sectors>>3)*sizeof(*new_dma_malloc_pages),
+                             GFP_ATOMIC);
+	memset(new_dma_malloc_pages, 0,
+               (new_dma_sectors>>3)*sizeof(*new_dma_malloc_pages));
     }
     
     /*
@@ -2582,8 +2585,10 @@
     
     if (dma_malloc_pages)
     {
-	memcpy(new_dma_malloc_pages, dma_malloc_pages, dma_sectors >> 1);
-	scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
+	memcpy(new_dma_malloc_pages, dma_malloc_pages,
+               (dma_sectors>>3)*sizeof(*dma_malloc_pages));
+	scsi_init_free((char *) dma_malloc_pages,
+                       (dma_sectors>>3)*sizeof(*dma_malloc_pages));
     }
     
     dma_free_sectors += new_dma_sectors - dma_sectors;
@@ -3084,7 +3089,7 @@
     
     /* One pointer per page for the page list */
     dma_malloc_pages = (unsigned char **)
-	scsi_init_malloc(dma_sectors >> 1, GFP_ATOMIC);
+	scsi_init_malloc((dma_sectors >> 3)*sizeof(*dma_malloc_pages), GFP_ATOMIC);
     dma_malloc_pages[0] = (unsigned char *)
 	scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
     return 0;
diff -u --recursive --new-file v1.3.39/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v1.3.39/linux/drivers/scsi/scsi_ioctl.c	Mon Oct 23 18:02:11 1995
+++ linux/drivers/scsi/scsi_ioctl.c	Sat Nov 11 13:14:22 1995
@@ -1,16 +1,10 @@
-#ifdef MODULE
 /*
  * Don't import our own symbols, as this would severely mess up our
  * symbol tables.
  */
 #define _SCSI_SYMS_VER_
-#include <linux/autoconf.h>
+#define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
 
 #include <asm/io.h>
 #include <asm/segment.h>
diff -u --recursive --new-file v1.3.39/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c
--- v1.3.39/linux/drivers/scsi/scsi_proc.c	Mon Oct 23 18:02:11 1995
+++ linux/drivers/scsi/scsi_proc.c	Sat Nov 11 13:11:19 1995
@@ -13,19 +13,13 @@
  * Andreas Heilwagen <crashcar@informatik.uni-koblenz.de>
  */
 
-#ifdef MODULE
 /*
  * Don't import our own symbols, as this would severely mess up our
  * symbol tables.
  */
 #define _SCSI_SYMS_VER_
-#include <linux/autoconf.h>
+#define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
 
 #include <linux/string.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v1.3.39/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- v1.3.39/linux/drivers/scsi/scsi_syms.c	Thu Nov  9 11:23:50 1995
+++ linux/drivers/scsi/scsi_syms.c	Sat Nov 11 13:36:03 1995
@@ -2,10 +2,7 @@
  * We should not even be trying to compile this if we are not doing
  * a module.
  */
-#ifndef MODULE
-#error Go away.
-#endif
-
+#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/config.h>
 
@@ -16,6 +13,7 @@
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/blk.h>
+#include <linux/fs.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
diff -u --recursive --new-file v1.3.39/linux/drivers/scsi/scsicam.c linux/drivers/scsi/scsicam.c
--- v1.3.39/linux/drivers/scsi/scsicam.c	Mon Oct 23 18:02:12 1995
+++ linux/drivers/scsi/scsicam.c	Sat Nov 11 13:06:51 1995
@@ -10,19 +10,13 @@
  * For more information, please consult the SCSI-CAM draft.
  */
 
-#ifdef MODULE
 /*
  * Don't import our own symbols, as this would severely mess up our
  * symbol tables.
  */
 #define _SCSI_SYMS_VER_
-#include <linux/autoconf.h>
+#define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
 
 #include <linux/fs.h>
 #include <linux/genhd.h>
diff -u --recursive --new-file v1.3.39/linux/drivers/scsi/sd_ioctl.c linux/drivers/scsi/sd_ioctl.c
--- v1.3.39/linux/drivers/scsi/sd_ioctl.c	Mon Oct 23 18:02:12 1995
+++ linux/drivers/scsi/sd_ioctl.c	Sat Nov 11 13:16:39 1995
@@ -1,8 +1,8 @@
-#ifdef MODULE
-#include <linux/autoconf.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#endif /* MODULE */
+/*
+ * drivers/scsi/sd_ioctl.c
+ *
+ * ioctl handling for SCSI disks
+ */
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v1.3.39/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v1.3.39/linux/drivers/scsi/sr.c	Thu Nov  9 11:23:50 1995
+++ linux/drivers/scsi/sr.c	Sat Nov 11 11:04:19 1995
@@ -14,7 +14,7 @@
  *	    Modified by Eric Youngdale eric@aib.com to support loadable
  *	    low-level scsi drivers.
  *
- *	 Modified by Thomas Quinot thomas@melchior.frmug.fr.net to
+ *	 Modified by Thomas Quinot thomas@melchior.cuivre.fdn.fr to
  *	 provide auto-eject.
  *
  */
@@ -69,13 +69,13 @@
 {
 	sync_dev(inode->i_rdev);
 	if(! --scsi_CDs[MINOR(inode->i_rdev)].device->access_count)
-        {
-            sr_ioctl(inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0);
+	{
+	    sr_ioctl(inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0);
 	    if (scsi_CDs[MINOR(inode->i_rdev)].auto_eject)
-                sr_ioctl(inode, NULL, CDROMEJECT, 0);
-        }
+		sr_ioctl(inode, NULL, CDROMEJECT, 0);
+	}
 	if (scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count)
-            (*scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count)--;
+	    (*scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count)--;
 	if(sr_template.usage_count) (*sr_template.usage_count)--;
 }
 
@@ -307,7 +307,7 @@
  *   kraxel@cs.tu-berlin.de (Gerd Knorr)
  */
 /*
- * 19950704 operator@melchior.frmug.fr.net (Thomas Quinot)
+ * 19950704 operator@melchior.cuivre.fdn.fr (Thomas Quinot)
  *
  *   - SONY:	Same as Nec.
  *
@@ -368,7 +368,7 @@
 	    break;
 	}
 	if (rec[14] != 0 && rec[14] != 0xb0) {
-	    printk("sr_photocd: Hmm, seems the CDROM doesn't support multisession CD's\n");
+	    printk("sr_photocd: (NEC) Hmm, seems the CDROM doesn't support multisession CD's\n");
 	    no_multi = 1;
 	    break;
 	}
@@ -407,7 +407,7 @@
 				      SCSI_IOCTL_TEST_UNIT_READY, NULL)) {
 		    printk("sr_photocd: drive not ready\n");
 		} else {
-		    printk("sr_photocd: Hmm, seems the CDROM doesn't support multisession CD's\n");
+		    printk("sr_photocd: (TOSHIBA) Hmm, seems the CDROM doesn't support multisession CD's\n");
 		    no_multi = 1;
 		}
 	    } else
@@ -468,32 +468,37 @@
 	}
 	break;
 
-    case SCSI_MAN_SONY: /* Thomas QUINOT <thomas@melchior.frmug.fr.net> */
+    case SCSI_MAN_SONY: /* Thomas QUINOT <thomas@melchior.cuivre.fdn.fr> */
     case SCSI_MAN_PIONEER:
 #ifdef DEBUG
-        printk("sr_photocd: use SONY/PIONEER code\n");
+	printk("sr_photocd: use SONY/PIONEER code\n");
 #endif
-        memset(buf,0,40);
-        *((unsigned long*)buf)   = 0x0;   /* we send nothing...     */
-        *((unsigned long*)buf+1) = 0x0c;  /* and receive 0x0c bytes */
-        cmd[0] = 0x43; /* Read TOC */
-        cmd[8] = 0x0c;
-        cmd[9] = 0x40;
-        rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-                               SCSI_IOCTL_SEND_COMMAND, buf);
-        
-        if ((rc != 0) || ((rec[0] << 8) + rec[1] != 0x0a)) {
-            printk("sr_photocd: ioctl error (SONY): 0x%x\n",rc);
-            break;
-        }
-        sector = rec[11] + (rec[10] << 8) + (rec[9] << 16) + (rec[8] << 24);
-        is_xa = !!sector;
+	memset(buf,0,40);
+	*((unsigned long*)buf)   = 0x0;   /* we send nothing...     */
+	*((unsigned long*)buf+1) = 0x0c;  /* and receive 0x0c bytes */
+	cmd[0] = 0x43; /* Read TOC */
+	cmd[8] = 0x0c;
+	cmd[9] = 0x40;
+	rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
+			       SCSI_IOCTL_SEND_COMMAND, buf);
+	
+	if (rc != 0) {
+	    printk("sr_photocd: ioctl error (SONY): 0x%x\n",rc);
+	    break;
+	}
+	if ((rec[0] << 8) + rec[1] != 0x0a) {
+	    printk("sr_photocd: (SONY) Hmm, seems the CDROM doesn't support multisession CD's\n");
+	    no_multi = 1;
+	    break;
+	}
+	sector = rec[11] + (rec[10] << 8) + (rec[9] << 16) + (rec[8] << 24);
+	is_xa = !!sector;
 #ifdef DEBUG
-        if (sector)
-            printk ("sr_photocd: multisession CD detected. start: %lu\n",sector);
+	if (sector)
+	    printk ("sr_photocd: multisession CD detected. start: %lu\n",sector);
 #endif
-        break;
-                
+	break;
+		
     case SCSI_MAN_NEC_OLDCDR:
     case SCSI_MAN_UNKNOWN:
     default:
@@ -565,15 +570,15 @@
 	
 	INIT_SCSI_REQUEST;
  
-        SDev = scsi_CDs[DEVICE_NR(CURRENT->rq_dev)].device;
-        
-        /*
-         * I am not sure where the best place to do this is.  We need
-         * to hook in a place where we are likely to come if in user
-         * space.
-         */
-        if( SDev->was_reset )
-        {
+	SDev = scsi_CDs[DEVICE_NR(CURRENT->rq_dev)].device;
+	
+	/*
+	 * I am not sure where the best place to do this is.  We need
+	 * to hook in a place where we are likely to come if in user
+	 * space.
+	 */
+	if( SDev->was_reset )
+	{
  	    /*
  	     * We need to relock the door, but we might
  	     * be in an interrupt handler.  Only do this
@@ -582,11 +587,11 @@
  	     */
  	    if( SDev->removable && !intr_count )
  	    {
-                scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0);
+		scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0);
  	    }
  	    SDev->was_reset = 0;
-        }
-        
+	}
+	
 	if (flag++ == 0)
 	    SCpnt = allocate_device(&CURRENT,
 				    scsi_CDs[DEVICE_NR(CURRENT->rq_dev)].device, 0); 
@@ -1060,7 +1065,7 @@
 					     sizeof(int), GFP_ATOMIC);
 	for(i=0;i<sr_template.dev_max;i++) sr_blocksizes[i] = 2048;
 	blksize_size[MAJOR_NR] = sr_blocksizes;
-        return 0;
+	return 0;
 }
 
 void sr_finish()
diff -u --recursive --new-file v1.3.39/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v1.3.39/linux/drivers/scsi/sr_ioctl.c	Mon Oct 23 18:02:12 1995
+++ linux/drivers/scsi/sr_ioctl.c	Sat Nov 11 12:48:43 1995
@@ -1,9 +1,3 @@
-#ifdef MODULE
-#include <linux/autoconf.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#endif /* MODULE */
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v1.3.39/linux/drivers/sound/os.h linux/drivers/sound/os.h
--- v1.3.39/linux/drivers/sound/os.h	Wed Nov  8 07:11:36 1995
+++ linux/drivers/sound/os.h	Fri Nov 10 08:16:22 1995
@@ -3,8 +3,6 @@
 #undef NO_INLINE_ASM
 #undef SHORT_BANNERS
 
-#include <linux/module.h>
-
 #include <linux/param.h>
 #include <linux/types.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v1.3.39/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v1.3.39/linux/drivers/sound/soundcard.c	Thu Nov  9 11:23:51 1995
+++ linux/drivers/sound/soundcard.c	Sat Nov 11 10:58:56 1995
@@ -30,6 +30,8 @@
  * Created modular version by Peter Trattler (peter@sbox.tu-graz.ac.at)
  */
 
+#include <linux/module.h>
+
 #include "sound_config.h"
 
 #ifdef CONFIGURE_SOUNDCARD
@@ -604,7 +606,7 @@
 	}
     }
   dmap->raw_buf = start_addr;
-  dmap->raw_buf_phys = virt_to_phys (start_addr);
+  dmap->raw_buf_phys = virt_to_bus (start_addr);
 
   memset (dmap->raw_buf, 0x00, audio_devs[dev]->buffsize);
 
diff -u --recursive --new-file v1.3.39/linux/fs/exec.c linux/fs/exec.c
--- v1.3.39/linux/fs/exec.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/exec.c	Sat Nov 11 11:00:47 1995
@@ -82,7 +82,8 @@
 			return -EBUSY;
 		tmp = &(*tmp)->next;
 	}
-	*tmp = fmt;
+	fmt->next = formats;
+	formats = fmt;
 	return 0;	
 }
 
diff -u --recursive --new-file v1.3.39/linux/fs/msdos/dir.c linux/fs/msdos/dir.c
--- v1.3.39/linux/fs/msdos/dir.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/msdos/dir.c	Fri Nov 10 08:08:18 1995
@@ -1,9 +1,10 @@
 /*
  *  linux/fs/msdos/dir.c
+ *  MS-DOS directory handling functions
  *
  *  Written 1992,1993 by Werner Almesberger
  *
- *  MS-DOS directory handling functions
+ *  Hidden files 1995 by Albert Cahalan <albert@ccs.neu.edu> <adc@coe.neu.edu>
  */
 
 #include <linux/fs.h>
@@ -85,13 +86,20 @@
 		return -ENOENT;
 	bh = NULL;
 	while ((ino = msdos_get_entry(inode,&filp->f_pos,&bh,&de)) > -1) {
-		if (!IS_FREE(de->name)
-			&& !(de->attr & (ATTR_VOLUME|ATTR_SYS|ATTR_HIDDEN))) {
-			char bufname[12];
+		if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) {
+			char bufname[13];
 			char *ptname = bufname;
+			int dotoffset = 0;
+			if ((de->attr & ATTR_HIDDEN) && MSDOS_SB(sb)->dotsOK) {
+				bufname[0] = '.';
+				dotoffset = 1;
+				ptname = bufname+1;
+			}
 			for (i = last = 0; i < 8; i++) {
 				if (!(c = de->name[i])) break;
 				if (c >= 'A' && c <= 'Z') c += 32;
+				/* see namei.c, msdos_format_name */
+				if (c == 0x05) c = 0xE5;
 				if (c != ' ')
 					last = i+1;
 				ptname[i] = c;
@@ -112,7 +120,7 @@
 					ino = inode->i_ino;
 				else if (!strcmp(de->name,MSDOS_DOTDOT))
 					ino = msdos_parent_ino(inode,0);
-				if (filldir(dirent, bufname, i, oldpos, ino) < 0) {
+				if (filldir(dirent, bufname, i+dotoffset, oldpos, ino) < 0) {
 					filp->f_pos = oldpos;
 					break;
 				}
diff -u --recursive --new-file v1.3.39/linux/fs/msdos/file.c linux/fs/msdos/file.c
--- v1.3.39/linux/fs/msdos/file.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/msdos/file.c	Fri Nov 10 08:08:18 1995
@@ -6,8 +6,6 @@
  *  MS-DOS regular file handling primitives
  */
 
-#include <linux/module.h>
-
 #include <linux/sched.h>
 #include <linux/locks.h>
 #include <linux/fs.h>
@@ -285,6 +283,8 @@
 		printk("msdos_file_write: mode = %07o\n",inode->i_mode);
 		return -EINVAL;
 	}
+	/* Must not harm system files */
+	if (MSDOS_I(inode)->i_attrs & ATTR_SYS) return -EPERM;
 /*
  * ok, append may not work when many processes are writing at the same time
  * but so what. That way leads to madness anyway.
@@ -362,6 +362,9 @@
 {
 	int cluster;
 
+	/* Must not harm system files */
+	/* Why no return value?  Surely the disk could fail... */
+	if (MSDOS_I(inode)->i_attrs & ATTR_SYS) return /* -EPERM */;
 	cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
 	(void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
 	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
diff -u --recursive --new-file v1.3.39/linux/fs/msdos/inode.c linux/fs/msdos/inode.c
--- v1.3.39/linux/fs/msdos/inode.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/msdos/inode.c	Fri Nov 10 08:08:18 1995
@@ -75,12 +75,13 @@
 
 static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
     gid_t *gid,int *umask,int *debug,int *fat,int *quiet,
-	int *blksize)
+	int *blksize, char *dotsOK)
 {
 	char *this_char,*value;
 
 	*check = 'n';
 	*conversion = 'b';
+	*dotsOK =1;
 	*uid = current->uid;
 	*gid = current->gid;
 	*umask = current->fs->umask;
@@ -105,6 +106,11 @@
 			else if (!strcmp(value,"auto")) *conversion = 'a';
 			else return 0;
 		}
+		else if (!strcmp(this_char,"dotsOK") && value) {
+			if (!strcmp(value,"yes")) *dotsOK = 1;
+			else if (!strcmp(value,"no")) *dotsOK = 0;
+			else return 0;
+		}
 		else if (!strcmp(this_char,"uid")) {
 			if (!value || !*value)
 				return 0;
@@ -164,7 +170,7 @@
 	struct msdos_boot_sector *b;
 	int data_sectors,logical_sector_size,sector_mult,fat_clusters=0;
 	int debug,error,fat,quiet;
-	char check,conversion;
+	char check,conversion,dotsOK;
 	uid_t uid;
 	gid_t gid;
 	int umask;
@@ -178,7 +184,7 @@
 		}
 	}
 	if (!parse_options((char *) data,&check,&conversion,&uid,&gid,&umask,
-	    &debug,&fat,&quiet,&blksize)
+	    &debug,&fat,&quiet,&blksize,&dotsOK)
 		|| (blksize != 512 && blksize != 1024)) {
 		sb->s_dev = 0;
 		MOD_DEC_USE_COUNT;
@@ -290,6 +296,7 @@
 	MSDOS_SB(sb)->fs_gid = gid;
 	MSDOS_SB(sb)->fs_umask = umask;
 	MSDOS_SB(sb)->quiet = quiet;
+	MSDOS_SB(sb)->dotsOK = dotsOK;
 	MSDOS_SB(sb)->free_clusters = -1; /* don't know yet */
 	MSDOS_SB(sb)->fat_wait = NULL;
 	MSDOS_SB(sb)->fat_lock = 0;
@@ -409,11 +416,10 @@
 					break;
 				}
 			}
-	}
-	else {
-		inode->i_mode = MSDOS_MKMODE(raw_entry->attr,(IS_NOEXEC(inode)
-		    ? S_IRUGO|S_IWUGO : S_IRWXUGO) & ~MSDOS_SB(inode->i_sb)->fs_umask) |
-		    S_IFREG;
+	} else { /* not a directory */
+		inode->i_mode = MSDOS_MKMODE(raw_entry->attr,
+		    (IS_NOEXEC(inode) ? S_IRUGO|S_IWUGO : S_IRWXUGO)
+		    & ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFREG;
 		inode->i_op = sb->s_blocksize == 1024
 			? &msdos_file_inode_operations_1024
 			: &msdos_file_inode_operations;
diff -u --recursive --new-file v1.3.39/linux/fs/msdos/misc.c linux/fs/msdos/misc.c
--- v1.3.39/linux/fs/msdos/misc.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/msdos/misc.c	Fri Nov 10 08:08:18 1995
@@ -365,7 +365,7 @@
 
 static int raw_scan_sector(struct super_block *sb,int sector,const char *name,
     int *number,int *ino,struct buffer_head **res_bh,
-    struct msdos_dir_entry **res_de)
+    struct msdos_dir_entry **res_de,char scantype)
 {
 	struct buffer_head *bh;
 	struct msdos_dir_entry *data;
@@ -375,8 +375,15 @@
 	if (!(bh = bread(sb->s_dev,sector,SECTOR_SIZE))) return -EIO;
 	data = (struct msdos_dir_entry *) bh->b_data;
 	for (entry = 0; entry < MSDOS_DPS; entry++) {
-		if (name) RSS_NAME
-		else {
+/* RSS_COUNT:  if (data[entry].name == name) done=true else done=false. */
+		if (name) {
+			RSS_NAME
+			if (done && scantype) {   /* scantype != SCAN_ANY */
+				done = (data[entry].attr & ATTR_HIDDEN)
+					? (scantype==SCAN_HID)
+					: (scantype==SCAN_NOTHID);
+			}
+		} else {
 			if (!ino) RSS_COUNT
 			else {
 				if (number) RSS_START
@@ -405,13 +412,13 @@
  */
 
 static int raw_scan_root(struct super_block *sb,const char *name,int *number,int *ino,
-    struct buffer_head **res_bh,struct msdos_dir_entry **res_de)
+    struct buffer_head **res_bh,struct msdos_dir_entry **res_de,char scantype)
 {
 	int count,cluster;
 
 	for (count = 0; count < MSDOS_SB(sb)->dir_entries/MSDOS_DPS; count++) {
 		if ((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count,
-		    name,number,ino,res_bh,res_de)) >= 0) return cluster;
+		    name,number,ino,res_bh,res_de,scantype)) >= 0) return cluster;
 	}
 	return -ENOENT;
 }
@@ -424,7 +431,7 @@
 
 static int raw_scan_nonroot(struct super_block *sb,int start,const char *name,
     int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry
-    **res_de)
+    **res_de,char scantype)
 {
 	int count,cluster;
 
@@ -435,7 +442,7 @@
 		for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) {
 			if ((cluster = raw_scan_sector(sb,(start-2)*
 			    MSDOS_SB(sb)->cluster_size+MSDOS_SB(sb)->data_start+
-			    count,name,number,ino,res_bh,res_de)) >= 0)
+			    count,name,number,ino,res_bh,res_de,scantype)) >= 0)
 				return cluster;
 		}
 		if (!(start = fat_access(sb,start,-1))) {
@@ -458,12 +465,14 @@
  *       being created.
  */
 
-static int raw_scan(struct super_block *sb,int start,const char *name,int *number,
-    int *ino,struct buffer_head **res_bh,struct msdos_dir_entry **res_de)
-{
-	if (start)
-		return raw_scan_nonroot(sb,start,name,number,ino,res_bh,res_de);
-	else return raw_scan_root(sb,name,number,ino,res_bh,res_de);
+static int raw_scan(struct super_block *sb, int start, const char *name,
+    int *number, int *ino, struct buffer_head **res_bh,
+    struct msdos_dir_entry **res_de, char scantype)
+{
+	if (start) return raw_scan_nonroot
+		(sb,start,name,number,ino,res_bh,res_de,scantype);
+	else return raw_scan_root
+		(sb,name,number,ino,res_bh,res_de,scantype);
 }
 
 
@@ -482,19 +491,19 @@
 	if (dir->i_ino == MSDOS_ROOT_INO) return dir->i_ino;
 	if (!locked) lock_creation(); /* prevent renames */
 	if ((curr = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,MSDOS_DOTDOT,
-	    &zero,NULL,NULL,NULL)) < 0) {
+	    &zero,NULL,NULL,NULL,SCAN_ANY)) < 0) {
 		if (!locked) unlock_creation();
 		return curr;
 	}
 	if (!curr) nr = MSDOS_ROOT_INO;
 	else {
 		if ((prev = raw_scan(dir->i_sb,curr,MSDOS_DOTDOT,&zero,NULL,
-		    NULL,NULL)) < 0) {
+		    NULL,NULL,SCAN_ANY)) < 0) {
 			if (!locked) unlock_creation();
 			return prev;
 		}
 		if ((error = raw_scan(dir->i_sb,prev,NULL,&curr,&nr,NULL,
-		    NULL)) < 0) {
+		    NULL,SCAN_ANY)) < 0) {
 			if (!locked) unlock_creation();
 			return error;
 		}
@@ -515,11 +524,11 @@
 
 	count = 0;
 	if (dir->i_ino == MSDOS_ROOT_INO)
-		(void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL);
+		(void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL,SCAN_ANY);
 	else {
 		if (!MSDOS_I(dir)->i_start) return 0; /* in mkdir */
 		else (void) raw_scan_nonroot(dir->i_sb,MSDOS_I(dir)->i_start,
-		    NULL,&count,NULL,NULL,NULL);
+		    NULL,&count,NULL,NULL,NULL,SCAN_ANY);
 	}
 	return count;
 }
@@ -531,14 +540,14 @@
  */
 
 int msdos_scan(struct inode *dir,const char *name,struct buffer_head **res_bh,
-    struct msdos_dir_entry **res_de,int *ino)
+    struct msdos_dir_entry **res_de,int *ino, char scantype)
 {
 	int res;
 
-	if (name)
-		res = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,name,NULL,ino,
-		    res_bh,res_de);
-	else res = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,NULL,NULL,ino,
-		    res_bh,res_de);
-	return res < 0 ? res : 0;
+	res = (name)
+		? raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,
+		    name, NULL, ino, res_bh, res_de, scantype)
+		: raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,
+		    NULL, NULL, ino, res_bh, res_de, scantype);
+	return res<0 ? res : 0;
 }
diff -u --recursive --new-file v1.3.39/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v1.3.39/linux/fs/msdos/namei.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/msdos/namei.c	Fri Nov 10 08:08:18 1995
@@ -2,6 +2,7 @@
  *  linux/fs/msdos/namei.c
  *
  *  Written 1992,1993 by Werner Almesberger
+ *  Hidden files 1995 by Albert Cahalan <albert@ccs.neu.edu> <adc@coe.neu.edu>
  */
 
 #include <linux/sched.h>
@@ -32,24 +33,31 @@
 static char bad_if_strict[] = "+=,; ";
 
 
-/* Formats an MS-DOS file name. Rejects invalid names. */
-
-static int msdos_format_name(char conv,const char *name,int len,char *res,
-  int dot_dirs)
+/***** Formats an MS-DOS file name. Rejects invalid names. */
+static int msdos_format_name(char conv,const char *name,int len,
+	char *res,int dot_dirs,char dotsOK)
+	/* conv is relaxed/normal/strict, name is proposed name,
+	 * len is the length of the proposed name, res is the result name,
+	 * dot_dirs is . and .. are OK, dotsOK is if hidden files get dots.
+	 */
 {
 	char *walk;
 	const char **reserved;
 	unsigned char c;
 	int space;
 
-	if (IS_FREE(name)) return -EINVAL;
 	if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
 		if (!dot_dirs) return -EEXIST;
 		memset(res+1,' ',10);
 		while (len--) *res++ = '.';
 		return 0;
 	}
-	space = 1; /* disallow names starting with a dot */
+	if (name[0] == '.') {  /* dotfile because . and .. already done */
+		if (!dotsOK) return -EINVAL;
+		/* Get rid of dot - test for it elsewhere */
+		name++; len--;
+	}
+	space = 1; /* disallow names that _really_ start with a dot */
 	c = 0;
 	for (walk = res; len && walk-res < 8; walk++) {
 	    	c = *name++;
@@ -58,9 +66,14 @@
 		if (conv == 's' && strchr(bad_if_strict,c)) return -EINVAL;
   		if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
 		if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
+/*  0xE5 is legal as a first character, but we must substitute 0x05     */
+/*  because 0xE5 marks deleted files.  Yes, DOS really does this.       */
+/*  It seems that Microsoft hacked DOS to support non-US characters     */
+/*  after the 0xE5 character was already in use to mark deleted files.  */
+		if((res==walk) && (c==0xE5)) c=0x05;
 		if (c == '.') break;
-		space = c == ' ';
-		*walk = c >= 'a' && c <= 'z' ? c-32 : c;
+		space = (c == ' ');
+		*walk = (c >= 'a' && c <= 'z') ? c-32 : c;
 	}
 	if (space) return -EINVAL;
 	if (conv == 's' && len && c != '.') {
@@ -93,21 +106,34 @@
 }
 
 
-/* Locates a directory entry. */
-
+/***** Locates a directory entry.  Uses unformatted name. */
 static int msdos_find(struct inode *dir,const char *name,int len,
     struct buffer_head **bh,struct msdos_dir_entry **de,int *ino)
 {
 	char msdos_name[MSDOS_NAME];
 	int res;
+	char dotsOK;
+	char scantype;
 
-	res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len, msdos_name,1);
+	dotsOK = MSDOS_SB(dir->i_sb)->dotsOK;
+	res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,
+	    name,len, msdos_name,1,dotsOK);
 	if (res < 0)
 		return -ENOENT;
-	return msdos_scan(dir,msdos_name,bh,de,ino);
+	if((name[0]=='.') && dotsOK){
+	    switch(len){
+		case  0: panic("Empty name in msdos_find!");
+		case  1: scantype = SCAN_ANY;				break;
+		case  2: scantype = ((name[1]=='.')?SCAN_ANY:SCAN_HID); break;
+		default: scantype = SCAN_HID;
+	    }
+	} else {
+	    scantype = (dotsOK ? SCAN_NOTHID : SCAN_ANY);
+	}
+	return msdos_scan(dir,msdos_name,bh,de,ino,scantype);
 }
 
-
+/***** Get inode using directory and name */
 int msdos_lookup(struct inode *dir,const char *name,int len,
     struct inode **result)
 {
@@ -173,21 +199,20 @@
 }
 
 
-/* Creates a directory entry (name is already formatted). */
-
-static int msdos_create_entry(struct inode *dir,const char *name,int is_dir,
-    struct inode **result)
+/***** Creates a directory entry (name is already formatted). */
+static int msdos_create_entry(struct inode *dir, const char *name,
+    int is_dir, int is_hid, struct inode **result)
 {
 	struct super_block *sb = dir->i_sb;
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
 	int res,ino;
 
-	if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) {
+	if ((res = msdos_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) {
 		if (res != -ENOENT) return res;
 		if (dir->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
 		if ((res = msdos_add_cluster(dir)) < 0) return res;
-		if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) return res;
+		if ((res = msdos_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) return res;
 	}
 	/*
 	 * XXX all times should be set by caller upon successful completion.
@@ -197,6 +222,7 @@
 	memcpy(de->name,name,MSDOS_NAME);
 	memset(de->unused, 0, sizeof(de->unused));
 	de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
+	de->attr = is_hid ? (de->attr|ATTR_HIDDEN) : (de->attr&~ATTR_HIDDEN);
 	de->start = 0;
 	date_unix2dos(dir->i_mtime,&de->time,&de->date);
 	de->size = 0;
@@ -211,7 +237,7 @@
 	return 0;
 }
 
-
+/***** Create a file or directory */
 int msdos_create(struct inode *dir,const char *name,int len,int mode,
 	struct inode **result)
 {
@@ -219,22 +245,33 @@
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
 	char msdos_name[MSDOS_NAME];
-	int ino,res;
+	int ino,res,is_hid;
 
 	if (!dir) return -ENOENT;
 	if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
-	    msdos_name,0)) < 0) {
+	    msdos_name,0,MSDOS_SB(dir->i_sb)->dotsOK)) < 0) {
 		iput(dir);
 		return res;
 	}
+	is_hid = (name[0]=='.') && (msdos_name[0]!='.');
 	lock_creation();
-	if (msdos_scan(dir,msdos_name,&bh,&de,&ino) >= 0) {
+	/* Scan for existing file twice, so that creating a file fails
+	 * with -EINVAL if the other (dotfile/nondotfile) exists.
+	 * Else SCAN_ANY would do. Maybe use EACCES, EBUSY, ENOSPC, ENFILE?
+	 */
+	if (msdos_scan(dir,msdos_name,&bh,&de,&ino,SCAN_HID) >= 0) {
 		unlock_creation();
 		brelse(bh);
 		iput(dir);
-		return -EEXIST;
+		return is_hid ? -EEXIST : -EINVAL;
+ 	}
+	if (msdos_scan(dir,msdos_name,&bh,&de,&ino,SCAN_NOTHID) >= 0) {
+		unlock_creation();
+		brelse(bh);
+		iput(dir);
+		return is_hid ? -EINVAL : -EEXIST;
  	}
-	res = msdos_create_entry(dir,msdos_name,S_ISDIR(mode),result);
+	res = msdos_create_entry(dir,msdos_name,S_ISDIR(mode),is_hid,result);
 	unlock_creation();
 	iput(dir);
 	return res;
@@ -260,7 +297,7 @@
 
 #endif
 
-
+/***** Make a directory */
 int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
 {
 	struct super_block *sb = dir->i_sb;
@@ -268,21 +305,22 @@
 	struct msdos_dir_entry *de;
 	struct inode *inode,*dot;
 	char msdos_name[MSDOS_NAME];
-	int ino,res;
+	int ino,res,is_hid;
 
 	if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
-	    msdos_name,0)) < 0) {
+	    msdos_name,0,MSDOS_SB(dir->i_sb)->dotsOK)) < 0) {
 		iput(dir);
 		return res;
 	}
+	is_hid = (name[0]=='.') && (msdos_name[0]!='.');
 	lock_creation();
-	if (msdos_scan(dir,msdos_name,&bh,&de,&ino) >= 0) {
+	if (msdos_scan(dir,msdos_name,&bh,&de,&ino,SCAN_ANY) >= 0) {
 		unlock_creation();
 		brelse(bh);
 		iput(dir);
 		return -EEXIST;
  	}
-	if ((res = msdos_create_entry(dir,msdos_name,1,&inode)) < 0) {
+	if ((res = msdos_create_entry(dir,msdos_name,1,is_hid,&inode)) < 0) {
 		unlock_creation();
 		iput(dir);
 		return res;
@@ -291,14 +329,14 @@
 	inode->i_nlink = 2; /* no need to mark them dirty */
 	MSDOS_I(inode)->i_busy = 1; /* prevent lookups */
 	if ((res = msdos_add_cluster(inode)) < 0) goto mkdir_error;
-	if ((res = msdos_create_entry(inode,MSDOS_DOT,1,&dot)) < 0)
+	if ((res = msdos_create_entry(inode,MSDOS_DOT,1,0,&dot)) < 0)
 		goto mkdir_error;
 	dot->i_size = inode->i_size; /* doesn't grow in the 2nd create_entry */
 	MSDOS_I(dot)->i_start = MSDOS_I(inode)->i_start;
 	dot->i_nlink = inode->i_nlink;
 	dot->i_dirt = 1;
 	iput(dot);
-	if ((res = msdos_create_entry(inode,MSDOS_DOTDOT,1,&dot)) < 0)
+	if ((res = msdos_create_entry(inode,MSDOS_DOTDOT,1,0,&dot)) < 0)
 		goto mkdir_error;
 	unlock_creation();
 	dot->i_size = dir->i_size;
@@ -318,7 +356,7 @@
 	return res;
 }
 
-
+/***** See if directory is empty */
 static int msdos_empty(struct inode *dir)
 {
 	struct super_block *sb = dir->i_sb;
@@ -344,7 +382,7 @@
 	return 0;
 }
 
-
+/***** Remove a directory */
 int msdos_rmdir(struct inode *dir,const char *name,int len)
 {
 	struct super_block *sb = dir->i_sb;
@@ -383,7 +421,7 @@
 	return res;
 }
 
-
+/***** Unlink a file */
 static int msdos_unlinkx(
 	struct inode *dir,
 	const char *name,
@@ -408,6 +446,10 @@
 		res = -EPERM;
 		goto unlink_done;
 	}
+	if (MSDOS_I(inode)->i_attrs & ATTR_SYS){
+		res = -EPERM;
+		goto unlink_done;
+	}
 	inode->i_nlink = 0;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	MSDOS_I(inode)->i_busy = 1;
@@ -421,21 +463,22 @@
 	return res;
 }
 
+/***** Unlink, as called for msdosfs */
 int msdos_unlink(struct inode *dir,const char *name,int len)
 {
 	return msdos_unlinkx (dir,name,len,1);
 }
-/*
-	Special entry for umsdos
-*/
+
+/***** Unlink, as called for umsdosfs */
 int msdos_unlink_umsdos(struct inode *dir,const char *name,int len)
 {
 	return msdos_unlinkx (dir,name,len,0);
 }
 
+/***** Rename within a directory */
 static int rename_same_dir(struct inode *old_dir,char *old_name,
     struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
-    struct msdos_dir_entry *old_de,int old_ino)
+    struct msdos_dir_entry *old_de,int old_ino,int is_hid)
 {
 	struct super_block *sb = old_dir->i_sb;
 	struct buffer_head *new_bh;
@@ -443,8 +486,8 @@
 	struct inode *new_inode,*old_inode;
 	int new_ino,exists,error;
 
-	if (!strncmp(old_name,new_name,MSDOS_NAME)) return 0;
-	exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino) >= 0;
+	if (!strncmp(old_name,new_name,MSDOS_NAME)) goto set_hid;
+	exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0;
 	if (*(unsigned char *) old_de->name == DELETED_FLAG) {
 		if (exists) brelse(new_bh);
 		return -ENOENT;
@@ -454,9 +497,14 @@
 			brelse(new_bh);
 			return -EIO;
 		}
-		error = S_ISDIR(new_inode->i_mode) ? (old_de->attr & ATTR_DIR) ?
-		    msdos_empty(new_inode) : -EPERM : (old_de->attr & ATTR_DIR)
-		    ? -EPERM : 0;
+		error = S_ISDIR(new_inode->i_mode)
+			? (old_de->attr & ATTR_DIR)
+				? msdos_empty(new_inode)
+				: -EPERM
+			: (old_de->attr & ATTR_DIR)
+				? -EPERM
+				: 0;
+		if (!error && (old_de->attr & ATTR_SYS)) error = -EPERM;
 		if (error) {
 			iput(new_inode);
 			brelse(new_bh);
@@ -475,19 +523,26 @@
 		brelse(new_bh);
 	}
 	memcpy(old_de->name,new_name,MSDOS_NAME);
+set_hid:
+	old_de->attr = is_hid
+		? (old_de->attr | ATTR_HIDDEN)
+		: (old_de->attr &~ ATTR_HIDDEN);
 	mark_buffer_dirty(old_bh, 1);
-	if (MSDOS_SB(old_dir->i_sb)->conversion == 'a') /* update binary info */
-		if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
-			msdos_read_inode(old_inode);
-			iput(old_inode);
-		}
+	/* update binary info for conversion, i_attrs */
+	if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
+		msdos_read_inode(old_inode);
+		MSDOS_I(old_inode)->i_attrs = is_hid
+			? (MSDOS_I(old_inode)->i_attrs |  ATTR_HIDDEN)
+			: (MSDOS_I(old_inode)->i_attrs &~ ATTR_HIDDEN);
+		iput(old_inode);
+	}
 	return 0;
 }
 
-
+/***** Rename across directories - a nonphysical move */
 static int rename_diff_dir(struct inode *old_dir,char *old_name,
     struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
-    struct msdos_dir_entry *old_de,int old_ino)
+    struct msdos_dir_entry *old_de,int old_ino,int is_hid)
 {
 	struct super_block *sb = old_dir->i_sb;
 	struct buffer_head *new_bh,*free_bh,*dotdot_bh;
@@ -499,6 +554,7 @@
 	if (old_dir->i_dev != new_dir->i_dev) return -EINVAL;
 	if (old_ino == new_dir->i_ino) return -EINVAL;
 	if (!(walk = iget(new_dir->i_sb,new_dir->i_ino))) return -EIO;
+	/* prevent moving directory below itself */
 	while (walk->i_ino != MSDOS_ROOT_INO) {
 		ino = msdos_parent_ino(walk,1);
 		iput(walk);
@@ -507,13 +563,14 @@
 		if (!(walk = iget(new_dir->i_sb,ino))) return -EIO;
 	}
 	iput(walk);
-	while ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino)) <
-	     0) {
+	/* find free spot */
+	while ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino,
+	    SCAN_ANY)) < 0) {
 		if (error != -ENOENT) return error;
 		error = msdos_add_cluster(new_dir);
 		if (error) return error;
 	}
-	exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino) >= 0;
+	exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0;
 	if (!(old_inode = iget(old_dir->i_sb,old_ino))) {
 		brelse(free_bh);
 		if (exists) brelse(new_bh);
@@ -526,15 +583,20 @@
 		return -ENOENT;
 	}
 	new_inode = NULL; /* to make GCC happy */
-	if (exists) {
+	if (exists) {  /* Trash the old file! */
 		if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
 			iput(old_inode);
 			brelse(new_bh);
 			return -EIO;
 		}
-		error = S_ISDIR(new_inode->i_mode) ? (old_de->attr & ATTR_DIR) ?
-		    msdos_empty(new_inode) : -EPERM : (old_de->attr & ATTR_DIR)
-		    ? -EPERM : 0;
+		error = S_ISDIR(new_inode->i_mode)
+			? (old_de->attr & ATTR_DIR)
+				? msdos_empty(new_inode)
+				: -EPERM
+			: (old_de->attr & ATTR_DIR)
+				? -EPERM
+				: 0;
+		if (!error && (old_de->attr & ATTR_SYS)) error = -EPERM;
 		if (error) {
 			iput(new_inode);
 			iput(old_inode);
@@ -549,6 +611,9 @@
 	}
 	memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
 	memcpy(free_de->name,new_name,MSDOS_NAME);
+	free_de->attr = is_hid
+		? (free_de->attr|ATTR_HIDDEN)
+		: (free_de->attr&~ATTR_HIDDEN);
 	if (!(free_inode = iget(new_dir->i_sb,free_ino))) {
 		free_de->name[0] = DELETED_FLAG;
 /*  Don't mark free_bh as dirty. Both states are supposed to be equivalent. */
@@ -580,7 +645,7 @@
 	}
 	if (S_ISDIR(old_inode->i_mode)) {
 		if ((error = msdos_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
-		    &dotdot_de,&dotdot_ino)) < 0) goto rename_done;
+		    &dotdot_de,&dotdot_ino,SCAN_ANY)) < 0) goto rename_done;
 		if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
 			brelse(dotdot_bh);
 			error = -EIO;
@@ -604,7 +669,7 @@
 	return error;
 }
 
-
+/***** Rename, a wrapper for rename_same_dir & rename_diff_dir */
 int msdos_rename(struct inode *old_dir,const char *old_name,int old_len,
 	struct inode *new_dir,const char *new_name,int new_len)
 {
@@ -613,19 +678,24 @@
 	struct buffer_head *old_bh;
 	struct msdos_dir_entry *old_de;
 	int old_ino,error;
+	int is_hid,old_hid; /* if new file and old file are hidden */
 
 	if ((error = msdos_format_name(MSDOS_SB(old_dir->i_sb)->name_check,
-	    old_name,old_len,old_msdos_name,1)) < 0) goto rename_done;
+	    old_name,old_len,old_msdos_name,1,MSDOS_SB(old_dir->i_sb)->dotsOK))
+	    < 0) goto rename_done;
 	if ((error = msdos_format_name(MSDOS_SB(new_dir->i_sb)->name_check,
-	    new_name,new_len,new_msdos_name,0)) < 0) goto rename_done;
+	    new_name,new_len,new_msdos_name,0,MSDOS_SB(new_dir->i_sb)->dotsOK))
+	    < 0) goto rename_done;
+	is_hid = (new_name[0]=='.') && (new_msdos_name[0]!='.');
+	old_hid = (old_name[0]=='.') && (old_msdos_name[0]!='.');
 	if ((error = msdos_scan(old_dir,old_msdos_name,&old_bh,&old_de,
-	    &old_ino)) < 0) goto rename_done;
+	    &old_ino,old_hid?SCAN_HID:SCAN_NOTHID)) < 0) goto rename_done;
 	lock_creation();
 	if (old_dir == new_dir)
 		error = rename_same_dir(old_dir,old_msdos_name,new_dir,
-		    new_msdos_name,old_bh,old_de,old_ino);
+		    new_msdos_name,old_bh,old_de,old_ino,is_hid);
 	else error = rename_diff_dir(old_dir,old_msdos_name,new_dir,
-		    new_msdos_name,old_bh,old_de,old_ino);
+		    new_msdos_name,old_bh,old_de,old_ino,is_hid);
 	unlock_creation();
 	brelse(old_bh);
 rename_done:
diff -u --recursive --new-file v1.3.39/linux/fs/proc/array.c linux/fs/proc/array.c
--- v1.3.39/linux/fs/proc/array.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/proc/array.c	Fri Nov 10 08:15:13 1995
@@ -482,10 +482,11 @@
 		tty_pgrp = -1;
 
 	/* scale priority and nice values from timeslices to -20..20 */
+	/* to make it look like a "normal" unix priority/nice value  */
 	priority = tsk->counter;
-	priority = (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY - 20;
+	priority = 20 - (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY;
 	nice = tsk->priority;
-	nice = (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY - 20;
+	nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY;
 
 	return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
 %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu \
@@ -507,10 +508,8 @@
 		tsk->stime,
 		tsk->cutime,
 		tsk->cstime,
-		priority,  /* this is the kernel priority ---
-				   subtract 20 in your user-level program. */
-		nice,	   /* this is the nice value ---
-				   subtract 20 in your user-level program. */
+		priority,
+		nice,
 		tsk->timeout,
 		tsk->it_real_value,
 		tsk->start_time,
diff -u --recursive --new-file v1.3.39/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v1.3.39/linux/fs/smbfs/dir.c	Wed Nov  8 07:11:40 1995
+++ linux/fs/smbfs/dir.c	Fri Nov 10 07:54:00 1995
@@ -5,8 +5,6 @@
  *
  */
 
-#include <linux/module.h>
-
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v1.3.39/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
--- v1.3.39/linux/fs/smbfs/file.c	Wed Nov  8 07:11:40 1995
+++ linux/fs/smbfs/file.c	Fri Nov 10 07:54:00 1995
@@ -5,8 +5,6 @@
  *
  */
 
-#include <linux/module.h>
-
 #include <asm/segment.h>
 #include <asm/system.h>
 
diff -u --recursive --new-file v1.3.39/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v1.3.39/linux/fs/smbfs/inode.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/smbfs/inode.c	Sat Nov 11 13:30:46 1995
@@ -405,9 +405,6 @@
 
 #ifdef MODULE
 
-/* looks ugly, taken from gcc-info */
-static void *shut_up_gcc = (&shut_up_gcc, kernel_version);
-
 static struct file_system_type smb_fs_type = {
         smb_read_super, "smbfs", 0, NULL
         };
diff -u --recursive --new-file v1.3.39/linux/fs/smbfs/ioctl.c linux/fs/smbfs/ioctl.c
--- v1.3.39/linux/fs/smbfs/ioctl.c	Wed Nov  8 07:11:40 1995
+++ linux/fs/smbfs/ioctl.c	Fri Nov 10 07:54:00 1995
@@ -4,7 +4,6 @@
  *  Copyright (C) 1995 by Volker Lendecke
  *
  */
-#include <linux/module.h>
 
 #include <asm/segment.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v1.3.39/linux/fs/smbfs/mmap.c linux/fs/smbfs/mmap.c
--- v1.3.39/linux/fs/smbfs/mmap.c	Wed Nov  8 07:11:40 1995
+++ linux/fs/smbfs/mmap.c	Fri Nov 10 07:54:00 1995
@@ -5,8 +5,6 @@
  *
  */
 
-#include <linux/module.h>
-
 #include <linux/stat.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v1.3.39/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c
--- v1.3.39/linux/fs/smbfs/proc.c	Wed Nov  8 07:11:40 1995
+++ linux/fs/smbfs/proc.c	Fri Nov 10 07:54:00 1995
@@ -5,8 +5,6 @@
  *
  */
 
-#include <linux/module.h>
-
 #include <linux/fs.h>
 #include <linux/smbno.h>
 #include <linux/smb_fs.h>
diff -u --recursive --new-file v1.3.39/linux/fs/smbfs/sock.c linux/fs/smbfs/sock.c
--- v1.3.39/linux/fs/smbfs/sock.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/smbfs/sock.c	Fri Nov 10 07:54:00 1995
@@ -5,8 +5,6 @@
  *
  */
 
-#include <linux/module.h>
-
 #include <linux/sched.h>
 #include <linux/smb_fs.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v1.3.39/linux/include/linux/fd.h linux/include/linux/fd.h
--- v1.3.39/linux/include/linux/fd.h	Fri Oct 13 14:44:45 1995
+++ linux/include/linux/fd.h	Sat Nov 11 14:51:55 1995
@@ -1,62 +1,26 @@
 #ifndef _LINUX_FD_H
 #define _LINUX_FD_H
 
-/* new interface flag */
-#define FDHAVEBATCHEDRAWCMD
-
-/* commands needing write access have 0x40 set */
-/* commands needing super user access have 0x80 set */
-
-#define FDCLRPRM 0x0241 /* clear user-defined parameters */
-#define FDSETPRM 0x0242 /* set user-defined parameters for current media */
-#define FDSETMEDIAPRM 0x0242
-#define FDDEFPRM 0x0243 /* set user-defined parameters until explicitly 
-			* cleared */
-#define FDDEFMEDIAPRM 0x0243
-#define FDGETPRM 0x0204 /* get disk parameters */
-#define FDGETMEDIAPRM 0x0204
-#define	FDMSGON  0x0205 /* issue kernel messages on media type change */
-#define	FDMSGOFF 0x0206 /* don't issue kernel messages on media type change */
-#define FDFMTBEG 0x0247 /* begin formatting a disk */
-#define	FDFMTTRK 0x0248 /* format the specified track */
-#define FDFMTEND 0x0249 /* end formatting a disk */
-#define FDSETEMSGTRESH	0x024a	/* set fdc error reporting threshold */
-#define FDFLUSH  0x024b /* flush buffers for media; either for verifying media, or for
-                       handling a media change without closing the file
-		       descriptor */
-#define FDSETMAXERRS 0x024c /* set abortion and read_track threshold */
-#define FDGETMAXERRS 0x020e /* get abortion and read_track threshold */
-#define FDGETDRVTYP 0x020f          /* get drive type: 5 1/4 or 3 1/2 */
-
-#define FDSETDRVPRM 0x0250 /* set drive parameters */
-#define FDGETDRVPRM 0x0211 /* get drive parameters */
-#define FDGETDRVSTAT 0x0212 /* get drive state */
-#define FDPOLLDRVSTAT 0x0213 /* get drive state */
-#define FDRESET 0x0254 /* reset FDC */
+#include <linux/ioctl.h>
 
-#ifndef __ASSEMBLY__
-enum reset_mode {
-	FD_RESET_IF_NEEDED ,
-	FD_RESET_IF_RAWCMD ,
-	FD_RESET_ALWAYS };
-#endif
-
-#define FDGETFDCSTAT 0x0215 /* get fdc state */
-#define FDWERRORCLR  0x0256 /* clear write error and badness information */
-#define FDWERRORGET  0x0217 /* get write error and badness information */
-
-#define FDRAWCMD 0x0258 /* send a raw command to the fdc */
-
-#define FDTWADDLE 0x0259 /* flicker motor-on bit before reading a sector */
+/* New file layout: Now the ioctl definitions immediately follow the
+ * definitions of the structures that they use */
 
 /*
- * Maximum number of sectors in a track buffer. Track buffering is disabled
- * if tracks are bigger.
+ * Geometry
  */
-#define MAX_BUFFER_SECTORS 24 /* was 18 -bb */
+struct floppy_struct {
+	unsigned int	size,		/* nr of sectors total */
+			sect,		/* sectors per track */
+			head,		/* nr of heads */
+			track,		/* nr of tracks */
+			stretch;	/* !=0 means double track steps */
+#define FD_STRETCH 1
+#define FD_SWAPSIDES 2
 
-#define FD_FILL_BYTE 0xF6 /* format fill byte */
+	unsigned char	gap,		/* gap1 size */
 
+			rate,		/* data rate. |= 0x40 for perpendicular */
 #define FD_2M 0x4
 #define FD_SIZECODEMASK 0x38
 #define FD_SIZECODE(floppy) (((((floppy)->rate&FD_SIZECODEMASK)>> 3)+ 2) %8)
@@ -64,28 +28,54 @@
 			     512 : 128 << FD_SIZECODE(floppy) )
 #define FD_PERP 0x40
 
-#define FD_STRETCH 1
-#define FD_SWAPSIDES 2
-
-#ifndef __ASSEMBLY__
-/* the following structure is used by FDSETPRM, FDDEFPRM and FDGETPRM */
-struct floppy_struct {
-	unsigned int	size,		/* nr of sectors total */
-			sect,		/* sectors per track */
-			head,		/* nr of heads */
-			track,		/* nr of tracks */
-			stretch;	/* !=0 means double track steps */
-	unsigned char	gap,		/* gap1 size */
-			rate,		/* data rate. |= 0x40 for perpendicular */
 			spec1,		/* stepping rate, head unload time */
 			fmt_gap;	/* gap2 size */
 	const char	* name; /* used only for predefined formats */
 };
 
+
+/* commands needing write access have 0x40 set */
+/* commands needing super user access have 0x80 set */
+
+#define FDCLRPRM _IO(2, 0x41)
+/* clear user-defined parameters */
+
+#define FDSETPRM _IOW(2, 0x42, struct floppy_struct) 
+#define FDSETMEDIAPRM FDSETPRM
+/* set user-defined parameters for current media */
+
+#define FDDEFPRM _IOW(2, 0x43, struct floppy_struct) 
+#define FDGETPRM _IOR(2, 0x04, struct floppy_struct)
+#define FDDEFMEDIAPRM FDDEFPRM
+#define FDGETMEDIAPRM FDGETPRM
+/* set/get disk parameters */
+
+
+#define	FDMSGON  _IO(2,0x45)
+#define	FDMSGOFF _IO(2,0x46)
+/* issue/don't issue kernel messages on media type change */
+
+
+/* 
+ * Formatting (obsolete)
+ */
+#define FD_FILL_BYTE 0xF6 /* format fill byte. */
+
 struct format_descr {
 	unsigned int device,head,track;
 };
 
+#define FDFMTBEG _IO(2,0x47)
+/* begin formatting a disk */
+#define	FDFMTTRK _IOW(2,0x48, struct format_descr)
+/* format the specified track */
+#define FDFMTEND _IO(2,0x49)
+/* end formatting a disk */
+
+
+/*
+ * Error thresholds
+ */
 struct floppy_max_errors {
 	unsigned int
 	  abort,      /* number of errors to be reached before aborting */
@@ -104,7 +94,27 @@
 
 };
 
-/* the following structure is used by FDSETDRVPRM and FDGETDRVPRM */
+#define FDSETEMSGTRESH	_IO(2,0x4a)
+/* set fdc error reporting threshold */
+
+#define FDFLUSH  _IO(2,0x4b)
+/* flush buffers for media; either for verifying media, or for
+ * handling a media change without closing the file descriptor */
+
+#define FDSETMAXERRS _IOW(2, 0x4c, struct floppy_max_errors)
+#define FDGETMAXERRS _IOR(2, 0x0e, struct floppy_max_errors)
+/* set/get abortion and read_track threshold. See also floppy_drive_params
+ * structure */
+
+
+typedef char floppy_drive_name[16];
+#define FDGETDRVTYP _IOR(2, 0x0f, floppy_drive_name)
+/* get drive type: 5 1/4 or 3 1/2 */
+
+
+/*
+ * Drive parameters (user modifyable)
+ */
 struct floppy_drive_params {
 	char cmos;			/* cmos type */
 	
@@ -160,15 +170,25 @@
 };
 
 enum {
-	FD_NEED_TWADDLE_BIT, /* more magic */
-	FD_VERIFY_BIT, /* inquire for write protection */
-	FD_DISK_NEWCHANGE_BIT, /* change detected, and no action undertaken yet
-				* to clear media change status */
+	FD_NEED_TWADDLE_BIT,	/* more magic */
+	FD_VERIFY_BIT,		/* inquire for write protection */
+	FD_DISK_NEWCHANGE_BIT,	/* change detected, and no action undertaken yet
+				 * to clear media change status */
 	FD_UNUSED_BIT,
-	FD_DISK_CHANGED_BIT, /* disk has been changed since last i/o */
-	FD_DISK_WRITABLE_BIT /* disk is writable */
+	FD_DISK_CHANGED_BIT,	/* disk has been changed since last i/o */
+	FD_DISK_WRITABLE_BIT	/* disk is writable */
 };
 
+#define FDSETDRVPRM _IOW(2, 0x90, struct floppy_drive_params)
+#define FDGETDRVPRM _IOR(2, 0x11, struct floppy_drive_params)
+/* set/get drive parameters */
+
+
+/*
+ * Current drive state (not directly modifyable by user, readonly)
+ */
+struct floppy_drive_struct {
+	signed char flags;
 /* values for these flags */
 #define FD_NEED_TWADDLE (1 << FD_NEED_TWADDLE_BIT)
 #define FD_VERIFY (1 << FD_VERIFY_BIT)
@@ -176,10 +196,6 @@
 #define FD_DISK_CHANGED (1 << FD_DISK_CHANGED_BIT)
 #define FD_DISK_WRITABLE (1 << FD_DISK_WRITABLE_BIT)
 
-#define FD_DRIVE_PRESENT 0 /* keep fdpatch utils compiling */
-
-struct floppy_drive_struct {
-	signed char flags;
 	unsigned long spinup_date;
 	unsigned long select_date;
 	unsigned long first_read_date;
@@ -206,28 +222,25 @@
 	int bufblocks;
 };
 
-struct floppy_write_errors {
-	/* Write error logging.
-	 *
-	 * These fields can be cleared with the FDWERRORCLR ioctl.
-	 * Only writes that were attempted but failed due to a physical media
-	 * error are logged.  write(2) calls that fail and return an error code
-	 * to the user process are not counted.
-	 */
+#define FDGETDRVSTAT _IOR(2, 0x12, struct floppy_drive_struct)
+#define FDPOLLDRVSTAT _IOR(2, 0x13, struct floppy_drive_struct)
+/* get drive state: GET returns the cached state, POLL polls for new state */
 
-	unsigned int write_errors;  /* number of physical write errors 
-				     * encountered */
-	
-	/* position of first and last write errors */
-	unsigned long first_error_sector;
-	int           first_error_generation;
-	unsigned long last_error_sector;
-	int           last_error_generation;
-	
-	unsigned int badness; /* highest retry count for a read or write 
-			       * operation */
+
+/*
+ * reset FDC
+ */
+enum reset_mode {
+	FD_RESET_IF_NEEDED,	/* reset only if the reset flags is set */
+	FD_RESET_IF_RAWCMD,	/* obsolete */
+	FD_RESET_ALWAYS		/* reset always */
 };
+#define FDRESET _IO(2, 0x54)
+
 
+/*
+ * FDC state
+ */
 struct floppy_fdc_state {	
 	int spec1;		/* spec1 value last used */
 	int spec2;		/* spec2 value last used */
@@ -241,26 +254,6 @@
 	unsigned int perp_mode:2;
 	unsigned int has_fifo:1;
 	unsigned int driver_version;	/* version code for floppy driver */
-
-	unsigned char track[4]; /* Position of the heads of the 4
-				 * units attached to this FDC, as
-				 * stored on the FDC. In the future,
-				 * the position as stored on the FDC
-				 * might not agree with the actual
-				 * physical position of these drive
-				 * heads. By allowing such
-				 * disagreement, it will be possible
-				 * to reset the FDC without incurring
-				 * the expensive cost of repositioning
-				 * all heads. 
-				 * Right now, these positions are
-				 * hard wired to 0. */
-
-	unsigned int reserved1;
-	unsigned int reserved2;
-};
-
-
 #define FD_DRIVER_VERSION 0x100
 /* user programs using the floppy API should use floppy_fdc_state to
  * get the version number of the floppy driver that they are running
@@ -269,33 +262,59 @@
  * to bigger structures
  */
 
+	unsigned char track[4];
+	/* Position of the heads of the 4 units attached to this FDC,
+	 * as stored on the FDC. In the future, the position as stored
+	 * on the FDC might not agree with the actual physical
+	 * position of these drive heads. By allowing such
+	 * disagreement, it will be possible to reset the FDC without
+	 * incurring the expensive cost of repositioning all heads.
+	 * Right now, these positions are hard wired to 0. */
 
-struct floppy_raw_cmd {
-	unsigned int flags;
-	void *data;
-	char *kernel_data; /* location of data buffer in the kernel */
-	struct floppy_raw_cmd *next; /* used for chaining of raw cmd's 
-				      * withing the kernel */
-	long length; /* in: length of dma transfer. out: remaining bytes */
-	long phys_length; /* physical length, if different from dma length */
-	int buffer_length; /* length of allocated buffer */
+};
 
-	unsigned char rate;
-	unsigned char cmd_count;
-	unsigned char cmd[16];
-	unsigned char reply_count;
-	unsigned char reply[16];
-	int track;
-	int resultcode;
+#define FDGETFDCSTAT _IOR(2, 0x15, struct floppy_fdc_state)
 
-	int reserved1;
-	int reserved2;
+
+/*
+ * Asynchronous Write error tracking
+ */
+struct floppy_write_errors {
+	/* Write error logging.
+	 *
+	 * These fields can be cleared with the FDWERRORCLR ioctl.
+	 * Only writes that were attempted but failed due to a physical media
+	 * error are logged.  write(2) calls that fail and return an error code
+	 * to the user process are not counted.
+	 */
+
+	unsigned int write_errors;  /* number of physical write errors 
+				     * encountered */
+	
+	/* position of first and last write errors */
+	unsigned long first_error_sector;
+	int           first_error_generation;
+	unsigned long last_error_sector;
+	int           last_error_generation;
+	
+	unsigned int badness; /* highest retry count for a read or write 
+			       * operation */
 };
-#endif
 
-/* meaning of the various bytes */
+#define FDWERRORCLR  _IO(2, 0x56)
+/* clear write error and badness information */
+#define FDWERRORGET  _IOR(2, 0x17, struct floppy_write_errors)
+/* get write error and badness information */
+
 
-/* flags */
+/*
+ * Raw commands
+ */
+/* new interface flag: now we can do them in batches */
+#define FDHAVEBATCHEDRAWCMD
+
+struct floppy_raw_cmd {
+	unsigned int flags;
 #define FD_RAW_READ 1
 #define FD_RAW_WRITE 2
 #define FD_RAW_NO_MOTOR 4
@@ -317,4 +336,33 @@
 /* more "out" flags */
 #define FD_RAW_FAILURE 0x10000 /* command sent to fdc, fdc returned error */
 #define FD_RAW_HARDFAILURE 0x20000 /* fdc had to be reset, or timed out */
+
+	void *data;
+	char *kernel_data; /* location of data buffer in the kernel */
+	struct floppy_raw_cmd *next; /* used for chaining of raw cmd's 
+				      * withing the kernel */
+	long length; /* in: length of dma transfer. out: remaining bytes */
+	long phys_length; /* physical length, if different from dma length */
+	int buffer_length; /* length of allocated buffer */
+
+	unsigned char rate;
+	unsigned char cmd_count;
+	unsigned char cmd[16];
+	unsigned char reply_count;
+	unsigned char reply[16];
+	int track;
+	int resultcode;
+
+	int reserved1;
+	int reserved2;
+};
+
+#define FDRAWCMD _IO(2, 0x58)
+/* send a raw command to the fdc. Structure size not included, because of
+ * batches */
+
+#define FDTWADDLE _IO(2, 0x59)
+/* flicker motor-on bit before reading a sector. Experimental */
+
+
 #endif
diff -u --recursive --new-file v1.3.39/linux/include/linux/module.h linux/include/linux/module.h
--- v1.3.39/linux/include/linux/module.h	Thu Nov  9 11:23:52 1995
+++ linux/include/linux/module.h	Sat Nov 11 14:29:41 1995
@@ -9,21 +9,16 @@
 
 #ifdef __GENKSYMS__
 #  define _set_ver(sym,vers) sym
+#  undef  MODVERSIONS
 #  define MODVERSIONS
 #else /* ! __GENKSYMS__ */
 # ifdef MODVERSIONS
-#  undef CONFIG_MODVERSIONS /* the *.ver files need this... */
-#  define CONFIG_MODVERSIONS /* the *.ver files need this... */
-#  ifdef MODULE
-#   define _set_ver(sym,vers) sym ## _R ## vers
-#   include <linux/modversions.h>
-#  else /* !MODULE */
+#  ifndef MODULE
 #   ifdef EXPORT_SYMTAB
 #    define _set_ver(sym,vers) sym
 #    include <linux/modversions.h>
 #   endif /* EXPORT_SYMTAB */
 #  endif /* MODULE */
-#  undef CONFIG_MODVERSIONS /* the *.ver files needed this... */
 # endif /* MODVERSIONS */
 #endif /* __GENKSYMS__ */
 
diff -u --recursive --new-file v1.3.39/linux/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h
--- v1.3.39/linux/include/linux/msdos_fs.h	Mon Sep 18 14:54:09 1995
+++ linux/include/linux/msdos_fs.h	Sat Nov 11 14:57:41 1995
@@ -35,6 +35,11 @@
 #define ATTR_UNUSED  (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
 	/* attribute bits that are copied "as is" */
 
+#define SCAN_ANY     0  /* either hidden or not */
+#define SCAN_HID     1  /* only hidden */
+#define SCAN_NOTHID  2  /* only not hidden */
+#define SCAN_NOTANY  3  /* test name, then use SCAN_HID or SCAN_NOTHID */
+
 #define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
 #define IS_FREE(n) (!*(n) || *(const unsigned char *) (n) == DELETED_FLAG || \
   *(const unsigned char *) (n) == FD_FILL_BYTE)
@@ -54,8 +59,8 @@
 /*
  * Conversion from and to little-endian byte order. (no-op on i386/i486)
  *
- * Naming: Ca_b_c, where a: F = from, T = to, b: LE = little-endian, BE = big-
- * endian, c: W = word (16 bits), L = longword (32 bits)
+ * Naming: Ca_b_c, where a: F = from, T = to, b: LE = little-endian,
+ * BE = big-endian, c: W = word (16 bits), L = longword (32 bits)
  */
 
 #define CF_LE_W(v) (v)
@@ -99,16 +104,13 @@
 };
 
 /* Determine whether this FS has kB-aligned data. */
-
 #define MSDOS_CAN_BMAP(mib) (!(((mib)->cluster_size & 1) || \
     ((mib)->data_start & 1)))
 
 /* Convert attribute bits and a mask to the UNIX mode. */
-
 #define MSDOS_MKMODE(a,m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO))
 
 /* Convert the UNIX mode to MS-DOS attribute bits. */
-
 #define MSDOS_MKATTR(m) ((m & S_IWUGO) ? ATTR_NONE : ATTR_RO)
 
 #ifdef __KERNEL__
@@ -127,7 +129,7 @@
 extern int msdos_get_entry(struct inode *dir,loff_t *pos,struct buffer_head **bh,
     struct msdos_dir_entry **de);
 extern int msdos_scan(struct inode *dir,const char *name,struct buffer_head **res_bh,
-    struct msdos_dir_entry **res_de,int *ino);
+    struct msdos_dir_entry **res_de,int *ino,char scantype);
 extern int msdos_parent_ino(struct inode *dir,int locked);
 extern int msdos_subdirs(struct inode *dir);
 
diff -u --recursive --new-file v1.3.39/linux/include/linux/msdos_fs_sb.h linux/include/linux/msdos_fs_sb.h
--- v1.3.39/linux/include/linux/msdos_fs_sb.h	Wed Dec  1 14:44:15 1993
+++ linux/include/linux/msdos_fs_sb.h	Fri Nov 10 08:08:18 1995
@@ -22,6 +22,7 @@
 	int fat_lock;
 	int prev_free; /* previously returned free cluster number */
 	int free_clusters; /* -1 if undefined */
+	char dotsOK;
 };
 
 #endif
diff -u --recursive --new-file v1.3.39/linux/include/net/netlink.h linux/include/net/netlink.h
--- v1.3.39/linux/include/net/netlink.h	Wed Nov  8 07:11:42 1995
+++ linux/include/net/netlink.h	Sat Nov 11 15:04:32 1995
@@ -11,7 +11,7 @@
 extern int netlink_donothing(struct sk_buff *skb);
 extern void netlink_detach(int unit);
 extern int netlink_post(int unit, struct sk_buff *skb);
-extern void init_netlink(void);
+extern int init_netlink(void);
 
 #define NETLINK_ROUTE		0	/* Routing/device hook				*/
 #define NETLINK_SKIP		1	/* Reserved for ENskip  			*/
diff -u --recursive --new-file v1.3.39/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v1.3.39/linux/net/ipv4/tcp.c	Wed Nov  8 07:11:46 1995
+++ linux/net/ipv4/tcp.c	Sat Nov 11 10:58:56 1995
@@ -1799,11 +1799,11 @@
 				/* Add more stuff to the end of skb->len */
 				if (!(flags & MSG_OOB)) 
 				{
-					copy = min(sk->mss - (skb->len - hdrlen), len);
+					copy = min(sk->mss - (skb->len - hdrlen), seglen);
 					/* FIXME: this is really a bug. */
 					if (copy <= 0) 
 					{
-				  		printk("TCP: **bug**: \"copy\" <= 0!!\n");
+						printk("TCP: **bug**: \"copy\" <= 0: %d - (%ld - %d) <= %d\n", sk->mss, skb->len, hdrlen, seglen);
 				  		copy = 0;
 					}		  
 					memcpy_fromfs(skb_put(skb,copy), from, copy);
@@ -1836,8 +1836,8 @@
 			copy = sk->window_seq - sk->write_seq;
 			if (copy <= 0 || copy < (sk->max_window >> 1) || copy > sk->mss)
 				copy = sk->mss;
-			if (copy > len)
-				copy = len;
+			if (copy > seglen)
+				copy = seglen;
 
 		/*
 		 *	We should really check the window here also. 
@@ -1933,7 +1933,7 @@
 			}
 			skb->dev = dev;
 			skb->h.th =(struct tcphdr *)skb_put(skb,sizeof(struct tcphdr));
-			tmp = tcp_build_header(skb->h.th, sk, len-copy);
+			tmp = tcp_build_header(skb->h.th, sk, seglen-copy);
 			if (tmp < 0) 
 			{
 				sock_wfree(sk, skb);
@@ -2306,7 +2306,7 @@
 
 		if (sk->err) 
 		{
-			copied = -xchg(&sk->err,0);
+			copied = sock_error(sk);
 			break;
 		}
 
