ALPHA-pl15c
diff --git a/Makefile b/Makefile
index 47407f6..5c71b86 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 0.99
 PATCHLEVEL = 15
-ALPHA = b
+ALPHA = c
 
 all:	Version zImage
 
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index ff9b04a..84cf7e4 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -301,7 +301,7 @@
 
 static void floppy_select(unsigned int nr)
 {
-	static struct timer_list select = { NULL, 0, 0, select_callback };
+	static struct timer_list select = { NULL, NULL, 0, 0, select_callback };
 
 	if (current_drive == (current_DOR & 3)) {
 		floppy_ready();
@@ -324,10 +324,10 @@
 }
 
 static struct timer_list motor_on_timer[4] = {
-	{ NULL, 0, 0, motor_on_callback },
-	{ NULL, 0, 1, motor_on_callback },
-	{ NULL, 0, 2, motor_on_callback },
-	{ NULL, 0, 3, motor_on_callback }
+	{ NULL, NULL, 0, 0, motor_on_callback },
+	{ NULL, NULL, 0, 1, motor_on_callback },
+	{ NULL, NULL, 0, 2, motor_on_callback },
+	{ NULL, NULL, 0, 3, motor_on_callback }
 };
 
 static void motor_off_callback(unsigned long nr)
@@ -341,10 +341,10 @@
 }
 
 static struct timer_list motor_off_timer[4] = {
-	{ NULL, 0, 0, motor_off_callback },
-	{ NULL, 0, 1, motor_off_callback },
-	{ NULL, 0, 2, motor_off_callback },
-	{ NULL, 0, 3, motor_off_callback }
+	{ NULL, NULL, 0, 0, motor_off_callback },
+	{ NULL, NULL, 0, 1, motor_off_callback },
+	{ NULL, NULL, 0, 2, motor_off_callback },
+	{ NULL, NULL, 0, 3, motor_off_callback }
 };
 
 static void floppy_on(unsigned int nr)
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 07a4a42..ef8fa07 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -60,6 +60,7 @@
 	{ 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Digital WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */
 	{ 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */
 	{ 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */
+	{ 0x1000,"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,"n OMTI 5520" }, /* Dirk Melchers, dirk@merlin.nbg.sub.org */
 };
 static u_char *xd_bases[] =
 {
@@ -580,6 +581,34 @@
 		printk("xd_seagate_init_drive: error reading geometry from drive %d\n",drive);
 }
 
+/* Omti support courtesy Dirk Melchers */
+static void xd_omti_init_controller (u_char *address)
+{
+	switch ((u_long) address) {
+		case 0xC8000:	xd_iobase = 0x320; break;
+		case 0xD0000:	xd_iobase = 0x324; break;
+		case 0xD8000:	xd_iobase = 0x328; break;
+		case 0xE0000:	xd_iobase = 0x32C; break;
+		default:	printk("xd_omti_init_controller: unsupported BIOS address %p\n",address);
+				xd_iobase = 0x320; break;
+	}
+	
+	xd_irq = 5;			/* the IRQ and DMA channel are fixed on the Omti controllers */
+	xd_dma = 3;
+	xd_maxsectors = 0x40;
+
+	outb(0,XD_RESET);		/* reset the controller */
+}
+
+static void xd_omti_init_drive (u_char drive)
+{
+	/* gets infos from drive */
+	xd_override_init_drive(drive);
+
+	/* set other parameters, Hardcoded, not that nice :-) */
+	xd_info[drive].control = 2;
+}
+
 /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads
    etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */
 static void xd_override_init_drive (u_char drive)
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 9bad94d..4ef9f62 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -34,7 +34,11 @@
 #endif
 
 #ifndef KBD_DEFLEDS
-#define KBD_DEFLEDS (1 << VC_NUMLOCK)
+/*
+ * Some laptops take the 789uiojklm,. keys as number pad when NumLock
+ * is on. This seems a good reason to start with NumLock off.
+ */
+#define KBD_DEFLEDS 0
 #endif
 
 #ifndef KBD_DEFLOCK
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index bb9474d..3895262 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -523,6 +523,9 @@
 		case TIOCSTI:
 			if ((current->tty != dev) && !suser())
 				return -EACCES;
+			retval = verify_area(VERIFY_READ, (void *) arg, 1);
+			if (retval)
+				return retval;
 			put_tty_queue(get_fs_byte((char *) arg), &tty->read_q);
 			TTY_READ_FLUSH(tty);
 			return 0;
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 2fb3731..07385b0 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -86,7 +86,7 @@
 void
 kd_mksound(unsigned int count, unsigned int ticks)
 {
-	static struct timer_list sound_timer = { NULL, 0, 0, kd_nosound };
+	static struct timer_list sound_timer = { NULL, NULL, 0, 0, kd_nosound };
 
 	cli();
 	del_timer(&sound_timer);
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index 7e18ce7..148d91b 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -377,7 +377,7 @@
 		return 0;
 
 	if (el3_debug > 4) {
-		printk("%s: el3_start_xmit(lenght = %d) called, status %4.4x.\n",
+		printk("%s: el3_start_xmit(lenght = %ld) called, status %4.4x.\n",
 			   dev->name, skb->len, inw(ioaddr + EL3_STATUS));
 	}
 #ifndef final_version
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 6025755..4eecd8b 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -127,10 +127,12 @@
 static struct blist blacklist[] = 
 {
    {"DENON","DRD-25X","V"},   /* A cdrom that locks up when probed at lun != 0 */
+   {"MAXTOR","XT-3280","PR02"},  /* Locks-up when LUN>0 polled. */
    {"MAXTOR","XT-4380S","B3C"},  /* Locks-up when LUN>0 polled. */
    {"MAXTOR","MXT-1240S","I1.2"}, /* Locks up when LUN > 0 polled */
    {"MAXTOR","XT-4170S","B5A"},  /* Locks-up sometimes when LUN>0 polled. */
    {"NEC","CD-ROM DRIVE:841","1.0"},  /* Locks-up when LUN>0 polled. */
+   {"RODIME","RO3000S","2.33"},  /* Locks up if polled for lun != 0 */
    {"SEAGATE", "ST157N", "\004|j"}, /* causes failed REQUEST SENSE on lun 1 for aha152x
 				     * controller, which causes SCSI code to reset bus.*/
    {"SEAGATE", "ST296","921"},   /* Responds to all lun */
@@ -387,7 +389,7 @@
 
 			scsi_devices[NR_SCSI_DEVICES].tagged_queue = 0;
 
-			if ((scsi_devices[NR_SCSI_DEVICES].scsi_level == SCSI_2) &&
+			if ((scsi_devices[NR_SCSI_DEVICES].scsi_level >= SCSI_2) &&
 			    (scsi_result[7] & 2)) {
 			    scsi_devices[NR_SCSI_DEVICES].tagged_supported = 1;
 			    scsi_devices[NR_SCSI_DEVICES].current_tag = 0;
@@ -451,6 +453,9 @@
 			/* Some scsi devices cannot be polled for lun != 0
 			   due to firmware bugs */
 			if(blacklisted(scsi_result)) break;
+			/* Old drives like the MAXTOR XT-3280 say vers=0 */
+			if ((scsi_result[2] & 0x07) == 0)
+			    break;
 			/* Some scsi-1 peripherals do not handle lun != 0.
 			   I am assuming that scsi-2 peripherals do better */
 			if((scsi_result[2] & 0x07) == 1 && 
diff --git a/drivers/sound/os.h b/drivers/sound/os.h
index bff4a43..fbad9ea 100644
--- a/drivers/sound/os.h
+++ b/drivers/sound/os.h
@@ -140,7 +140,7 @@
 
 #define DEFINE_TIMER(name, proc) \
   static struct timer_list name = \
-  {NULL, 0, 0, proc}
+  {NULL, NULL, 0, 0, proc}
 
 /*
  * The ACTIVATE_TIMER requests system to call 'proc' after 'time' ticks.
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index b34778b..e6c3dbe 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -363,11 +363,9 @@
 	/*
 	 * First, test whether the goal block is free.
 	 */
-	i = ((goal - es->s_first_data_block) / EXT2_BLOCKS_PER_GROUP(sb));
-	if (i >= EXT2_BLOCKS_PER_GROUP(sb) || i < 0) {
-		i = 0;
+	if (goal < es->s_first_data_block || goal >= es->s_blocks_count)
 		goal = es->s_first_data_block;
-	}
+	i = (goal - es->s_first_data_block) / EXT2_BLOCKS_PER_GROUP(sb);
 	gdp = get_group_desc (sb, i, &bh2);
 	if (gdp->bg_free_blocks_count > 0) {
 		j = ((goal - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb));
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index d5a47b2..960fae9 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -653,15 +653,13 @@
 		retval = -ENOTDIR;
 		goto end_rmdir;
 	}
-	if (!empty_dir (inode)) {
+	down(&inode->i_sem);
+	if (!empty_dir (inode))
 		retval = -ENOTEMPTY;
-		goto end_rmdir;
-	}
-	if (de->inode != inode->i_ino) {
+	else if (de->inode != inode->i_ino)
 		retval = -ENOENT;
-		goto end_rmdir;
-	}
-	if (inode->i_count > 1) {
+	else {
+		if (inode->i_count > 1) {
 		/*
 		 * Are we deleting the last instance of a busy directory?
 		 * Better clean up if so.
@@ -669,9 +667,11 @@
 		 * Make directory empty (it will be truncated when finally
 		 * dereferenced).  This also inhibits ext2_add_entry.
 		 */
-		inode->i_size = 0;
+			inode->i_size = 0;
+		}
+		retval = ext2_delete_entry (de, bh);
 	}
-	retval = ext2_delete_entry (de, bh);
+	up(&inode->i_sem);
 	if (retval)
 		goto end_rmdir;
 	bh->b_dirt = 1;
diff --git a/fs/hpfs/hpfs_fs.c b/fs/hpfs/hpfs_fs.c
index 0bd09f2..9498f5a 100644
--- a/fs/hpfs/hpfs_fs.c
+++ b/fs/hpfs/hpfs_fs.c
@@ -124,7 +124,7 @@
 static void hpfs_read_inode(struct inode *);
 static void hpfs_put_super(struct super_block *);
 static void hpfs_statfs(struct super_block *, struct statfs *);
-static int hpfs_remount_fs(struct super_block *, int *);
+static int hpfs_remount_fs(struct super_block *, int *, char *);
 
 static const struct super_operations hpfs_sops =
 {
@@ -752,7 +752,7 @@
  * remount.  Don't let read only be turned off.
  */
 
-static int hpfs_remount_fs(struct super_block *s, int *flags)
+static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
 {
 	if (!(*flags & MS_RDONLY))
 		return -EINVAL;
diff --git a/fs/inode.c b/fs/inode.c
index 0db43c9..b95e9c9 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -384,6 +384,7 @@
 	clear_inode(inode);
 	inode->i_count = 1;
 	inode->i_nlink = 1;
+	inode->i_sem.count = 1;
 	nr_free_inodes--;
 	if (nr_free_inodes < 0) {
 		printk ("VFS: get_empty_inode: bad free inode count.\n");
diff --git a/fs/namei.c b/fs/namei.c
index 9273627..03ff84b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -275,7 +275,7 @@
 	struct inode ** res_inode, struct inode * base)
 {
 	const char * basename;
-	int namelen,error,i;
+	int namelen,error;
 	struct inode * dir, *inode;
 	struct task_struct ** p;
 
@@ -297,43 +297,35 @@
 		*res_inode=dir;
 		return 0;
 	}
-	for (i = 0; i < 5; i++) {	/* races... */
-		dir->i_count++;		/* lookup eats the dir */
+	dir->i_count++;		/* lookup eats the dir */
+	if (flag & O_CREAT) {
+		down(&dir->i_sem);
 		error = lookup(dir,basename,namelen,&inode);
-		if (!error)
-			break;
-		if (!(flag & O_CREAT)) {
+		if (!error) {
+			if (flag & O_EXCL) {
+				iput(inode);
+				error = -EEXIST;
+			}
+		} else if (!permission(dir,MAY_WRITE | MAY_EXEC))
+			error = -EACCES;
+		else if (!dir->i_op || !dir->i_op->create)
+			error = -EACCES;
+		else if (IS_RDONLY(dir))
+			error = -EROFS;
+		else {
+			dir->i_count++;		/* create eats the dir */
+			error = dir->i_op->create(dir,basename,namelen,mode,res_inode);
+			up(&dir->i_sem);
 			iput(dir);
 			return error;
 		}
-		if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
-			iput(dir);
-			return -EACCES;
-		}
-		if (!dir->i_op || !dir->i_op->create) {
-			iput(dir);
-			return -EACCES;
-		}
-		if (IS_RDONLY(dir)) {
-			iput(dir);
-			return -EROFS;
-		}
-		dir->i_count++;		/* create eats the dir */
-		error = dir->i_op->create(dir,basename,namelen,mode,res_inode);
-		if (error != -EEXIST) {
-			iput(dir);
-			return error;
-		}
-	}
+		up(&dir->i_sem);
+	} else
+		error = lookup(dir,basename,namelen,&inode);
 	if (error) {
 		iput(dir);
 		return error;
 	}
-	if ((flag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
-		iput(dir);
-		iput(inode);
-		return -EEXIST;
-	}
 	error = follow_link(dir,inode,flag,mode,&inode);
 	if (error)
 		return error;
@@ -415,7 +407,10 @@
 		iput(dir);
 		return -EPERM;
 	}
-	return dir->i_op->mknod(dir,basename,namelen,mode,dev);
+	down(&dir->i_sem);
+	error = dir->i_op->mknod(dir,basename,namelen,mode,dev);
+	up(&dir->i_sem);
+	return error;
 }
 
 asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev)
@@ -467,7 +462,10 @@
 		iput(dir);
 		return -EPERM;
 	}
-	return dir->i_op->mkdir(dir,basename,namelen,mode);
+	down(&dir->i_sem);
+	error = dir->i_op->mkdir(dir,basename,namelen,mode);
+	up(&dir->i_sem);
+	return error;
 }
 
 asmlinkage int sys_mkdir(const char * pathname, int mode)
@@ -590,7 +588,10 @@
 		iput(dir);
 		return -EPERM;
 	}
-	return dir->i_op->symlink(dir,basename,namelen,oldname);
+	down(&dir->i_sem);
+	error = dir->i_op->symlink(dir,basename,namelen,oldname);
+	up(&dir->i_sem);
+	return error;
 }
 
 asmlinkage int sys_symlink(const char * oldname, const char * newname)
@@ -646,7 +647,10 @@
 		iput(oldinode);
 		return -EPERM;
 	}
-	return dir->i_op->link(oldinode, dir, basename, namelen);
+	down(&dir->i_sem);
+	error = dir->i_op->link(oldinode, dir, basename, namelen);
+	up(&dir->i_sem);
+	return error;
 }
 
 asmlinkage int sys_link(const char * oldname, const char * newname)
@@ -719,8 +723,11 @@
 		iput(new_dir);
 		return -EPERM;
 	}
-	return old_dir->i_op->rename(old_dir, old_base, old_len, 
+	down(&new_dir->i_sem);
+	error = old_dir->i_op->rename(old_dir, old_base, old_len, 
 		new_dir, new_base, new_len);
+	up(&new_dir->i_sem);
+	return error;
 }
 
 asmlinkage int sys_rename(const char * oldname, const char * newname)
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 2605d7f..1a4f2c2 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -441,7 +441,7 @@
 	return sz;
 }
 
-asmlinkage int get_module_list( char *);
+extern int get_module_list(char *);
 
 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
 {
diff --git a/include/asm/bitops.h b/include/asm/bitops.h
index 41b4f29..4a18616 100644
--- a/include/asm/bitops.h
+++ b/include/asm/bitops.h
@@ -89,7 +89,7 @@
 	addr += nr >> 5;
 	mask = 1 << (nr & 0x1f);
 	cli();
-	retval = (mask & *addr) == 0;
+	retval = (mask & *addr) != 0;
 	*addr &= ~mask;
 	sti();
 	return retval;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index eaf22af..be397d6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -171,6 +171,7 @@
 	time_t		i_ctime;
 	unsigned long	i_blksize;
 	unsigned long	i_blocks;
+	struct semaphore i_sem;
 	struct inode_operations * i_op;
 	struct super_block * i_sb;
 	struct wait_queue * i_wait;
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index 6eeee46..68d5330 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -21,7 +21,7 @@
 /* IEEE 802.3 Ethernet magic constants. */
 #define ETH_ALEN	6		/* #bytes in eth addr		*/
 #define ETH_HLEN	14		/* #bytes in eth header		*/
-#define ETH_ZLEN	64		/* min #bytes in frame		*/
+#define ETH_ZLEN	60		/* min #bytes in frame		*/
 #define ETH_FLEN	1536		/* max #bytes in frame		*/
 #define ETH_DLEN	(ETH_FLEN - ETH_HLEN)	/* max #bytes of data	*/
 
diff --git a/include/linux/route.h b/include/linux/route.h
index 6326a10..eb0ca2e 100644
--- a/include/linux/route.h
+++ b/include/linux/route.h
@@ -21,21 +21,32 @@
 #include <linux/if.h>
 
 
+/* This structure gets passed by the SIOCADDRTOLD and SIOCDELRTOLD calls. */
+struct old_rtentry {
+	unsigned long	rt_genmask;
+	struct sockaddr	rt_dst;
+	struct sockaddr	rt_gateway;
+	short		rt_flags;
+	short		rt_refcnt;
+	unsigned long	rt_use;
+	char		*rt_dev; 
+};
+
 /* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */
 struct rtentry {
-  unsigned long		rt_hash;	/* hash key for lookups		*/
-#define rt_genmask rt_hash
-  struct sockaddr	rt_dst;
-  struct sockaddr	rt_gateway;
-  short			rt_flags;
-  short			rt_refcnt;
-  unsigned long		rt_use;
-#ifdef BSD_COMPATIBLE
-  struct ifnet		*rt_ifp;
-#else
-  void			*rt_dev; 
-#endif
+	unsigned long	rt_hash;	/* hash key for lookups		*/
+	struct sockaddr	rt_dst;		/* target address		*/
+	struct sockaddr	rt_gateway;	/* gateway addr (RTF_GATEWAY)	*/
+	struct sockaddr	rt_genmask;	/* target network mask (IP)	*/
+	short		rt_flags;
+	short		rt_refcnt;
+	unsigned long	rt_use;
+	struct ifnet	*rt_ifp;
+	short		rt_metric;	/* +1 for binary compatibility!	*/
+	char		*rt_dev;	/* forcing the device at add	*/
 };
+
+
 #define	RTF_UP		0x0001		/* route useable		*/
 #define	RTF_GATEWAY	0x0002		/* destination is a gateway	*/
 #define	RTF_HOST	0x0004		/* host entry (net otherwise)	*/
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6ee77bf..932d26c 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -479,6 +479,21 @@
 	p->nr++;
 }
 
+extern void __down(struct semaphore * sem);
+
+extern inline void down(struct semaphore * sem)
+{
+	if (sem->count <= 0)
+		__down(sem);
+	sem->count--;
+}
+
+extern inline void up(struct semaphore * sem)
+{
+	sem->count++;
+	wake_up(&sem->wait);
+}	
+
 static inline unsigned long _get_base(char * addr)
 {
 	unsigned long __base;
diff --git a/include/linux/sockios.h b/include/linux/sockios.h
index 2090c33..ed5aeed 100644
--- a/include/linux/sockios.h
+++ b/include/linux/sockios.h
@@ -39,6 +39,10 @@
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
 
+/* Routing table calls. */
+#define SIOCADDRT	0x890B		/* add routing table entry	*/
+#define SIOCDELRT	0x890C		/* delete routing table entry	*/
+
 /* Socket configuration controls. */
 #define SIOCGIFNAME	0x8910		/* get iface name		*/
 #define SIOCSIFLINK	0x8911		/* set iface channel		*/
@@ -64,9 +68,9 @@
 #define SIOCGIFENCAP	0x8925		/* get/set slip encapsulation   */
 #define SIOCSIFENCAP	0x8926		
 
-/* Routing table calls. */
-#define SIOCADDRT	0x8940		/* add routing table entry	*/
-#define SIOCDELRT	0x8941		/* delete routing table entry	*/
+/* Routing table calls (oldrtent - don't use) */
+#define SIOCADDRTOLD	0x8940		/* add routing table entry	*/
+#define SIOCDELRTOLD	0x8941		/* delete routing table entry	*/
 
 /* ARP cache control calls. */
 #define SIOCDARP	0x8950		/* delete ARP table entry	*/
diff --git a/include/linux/timer.h b/include/linux/timer.h
index ad23e32..448bc2a 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -75,6 +75,7 @@
  */
 struct timer_list {
 	struct timer_list *next;
+	struct timer_list *prev;
 	unsigned long expires;
 	unsigned long data;
 	void (*function)(unsigned long);
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 92fb67d..3af5609 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -11,6 +11,13 @@
 	struct wait_queue * next;
 };
 
+struct semaphore {
+	int count;
+	struct wait_queue * wait;
+};
+
+#define MUTEX ((struct semaphore) { 1, NULL })
+
 struct select_table_entry {
 	struct wait_queue wait;
 	struct wait_queue ** wait_address;
diff --git a/include/linux/xd.h b/include/linux/xd.h
index 567584b..c4146a4 100644
--- a/include/linux/xd.h
+++ b/include/linux/xd.h
@@ -131,6 +131,8 @@
 static void xd_wd_init_drive (u_char drive);
 static void xd_seagate_init_controller (u_char *address);
 static void xd_seagate_init_drive (u_char drive);
+static void xd_omti_init_controller (u_char *address);
+static void xd_omti_init_drive (u_char drive);
 static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc);
 static void xd_override_init_drive (u_char drive);
 
diff --git a/kernel/module.c b/kernel/module.c
index 2e38de5..789ca4a 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -233,8 +233,7 @@
 /*
  * Called by the /proc file system to return a current list of modules.
  */
-int
-get_module_list( char *buf)
+int get_module_list(char *buf)
 {
 	char *p;
 	char *q;
diff --git a/kernel/sched.c b/kernel/sched.c
index 43c6489..a9f52ce 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -361,6 +361,19 @@
 	} while (tmp != *q);
 }
 
+void __down(struct semaphore * sem)
+{
+	struct wait_queue wait = { current, NULL };
+	add_wait_queue(&sem->wait, &wait);
+	current->state = TASK_UNINTERRUPTIBLE;
+	while (sem->count <= 0) {
+		schedule();
+		current->state = TASK_UNINTERRUPTIBLE;
+	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&sem->wait, &wait);
+}
+
 static inline void __sleep_on(struct wait_queue **p, int state)
 {
 	unsigned long flags;
diff --git a/kernel/signal.c b/kernel/signal.c
index a284eea..db3df6d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -211,30 +211,34 @@
  */
 asmlinkage int sys_sigreturn(unsigned long __unused)
 {
-#define CHECK_SEG(x) if (x) x |= 3
 #define COPY(x) regs->x = context.x
+#define COPY_SEG(x) \
+if ((context.x & 0xfffc) && (context.x & 3) != 3) goto badframe; COPY(x);
+#define COPY_SEG_STRICT(x) \
+if (!(context.x & 0xfffc) || (context.x & 3) != 3) goto badframe; COPY(x);
 	struct sigcontext_struct context;
 	struct pt_regs * regs;
 
 	regs = (struct pt_regs *) &__unused;
+	if (verify_area(VERIFY_READ, (void *) regs->esp, sizeof(context)))
+		goto badframe;
 	memcpy_fromfs(&context,(void *) regs->esp, sizeof(context));
 	current->blocked = context.oldmask & _BLOCKABLE;
-	CHECK_SEG(context.ss);
-	CHECK_SEG(context.cs);
-	CHECK_SEG(context.ds);
-	CHECK_SEG(context.es);
-	CHECK_SEG(context.fs);
-	CHECK_SEG(context.gs);
+	COPY_SEG(ds);
+	COPY_SEG(es);
+	COPY_SEG(fs);
+	COPY_SEG(gs);
+	COPY_SEG_STRICT(ss);
+	COPY_SEG_STRICT(cs);
 	COPY(eip); COPY(eflags);
 	COPY(ecx); COPY(edx);
 	COPY(ebx);
 	COPY(esp); COPY(ebp);
 	COPY(edi); COPY(esi);
-	COPY(cs); COPY(ss);
-	COPY(ds); COPY(es);
-	COPY(fs); COPY(gs);
 	regs->orig_eax = -1;		/* disable syscall checks */
 	return context.eax;
+badframe:
+	do_exit(SIGSEGV);
 }
 
 /*
diff --git a/kernel/traps.c b/kernel/traps.c
index 78ca139..e0145cc 100644
--- a/kernel/traps.c
+++ b/kernel/traps.c
@@ -89,7 +89,7 @@
 	printk("EIP:    %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags);
 	printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
 		regs->eax, regs->ebx, regs->ecx, regs->edx);
-	printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08x\n",
+	printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
 		regs->esi, regs->edi, regs->ebp, regs->esp);
 	printk("ds: %04x   es: %04x   fs: %04x   gs: %04x\n",
 		regs->ds, regs->es, regs->fs, regs->gs);
@@ -98,9 +98,11 @@
 	for(i=0;i<20;i++)
 		printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
 	printk("\n");
+#if 0
 	for(i=0;i<5;i++)
-		printk("%08x ", get_seg_long(regs->ss,(i+(unsigned long *)regs->esp)));
+		printk("%08lx ", get_seg_long(regs->ss,(i+(unsigned long *)regs->esp)));
 	printk("\n");
+#endif
 	do_exit(SIGSEGV);
 }
 
diff --git a/net/inet/arp.c b/net/inet/arp.c
index 71384af..7b1540f 100644
--- a/net/inet/arp.c
+++ b/net/inet/arp.c
@@ -39,6 +39,7 @@
  *		Dominik Kubla	:	Better checking
  *		Tegge		:	Assorted corrections on cross port stuff
  *		Alan Cox	:	ATF_PERM was backwards! - might be useful now (sigh)
+ *		Alan Cox	:	Arp timer added.
  *
  * To Fix:
  *				:	arp response allocates an skbuff to send. However there is a perfectly
@@ -60,6 +61,7 @@
 #include <linux/config.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
+#include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/if_arp.h>
 #include <linux/in.h>
@@ -250,6 +252,28 @@
 }
 
 
+static struct timer_list arp_timer;
+
+static void arp_queue_ticker(unsigned long data);
+
+static void arp_queue_kick(void)
+{
+	arp_timer.expires = 500;	/* 5 seconds */
+	arp_timer.data = 0;
+	arp_timer.function = arp_queue_ticker;
+	del_timer(&arp_timer);
+	add_timer(&arp_timer);
+}
+
+static void arp_queue_ticker(unsigned long data/*UNUSED*/)
+{
+	arp_send_q();
+	if (skb_peek(&arp_q))
+		arp_queue_kick();
+}
+
+
+
 /* Create and send our response to an ARP request. */
 static int
 arp_response(struct arphdr *arp1, struct device *dev,  int addrtype)
@@ -753,6 +777,8 @@
 	printk("ARP: arp_queue skb already on queue magic=%X.\n", skb->magic);
 	return;
   }
+  if(arp_q==NULL)
+  	arp_queue_kick();
   skb_queue_tail(&arp_q,skb);
   skb->magic = ARP_QUEUE_MAGIC;
   sti();
diff --git a/net/inet/datagram.c b/net/inet/datagram.c
index 7d0687e..0101fd8 100644
--- a/net/inet/datagram.c
+++ b/net/inet/datagram.c
@@ -186,7 +186,7 @@
 			return(0);
 
 		case SEL_OUT:
-			if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
+			if (sk->prot && sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
 			{
 				return(1);
 			}
diff --git a/net/inet/route.c b/net/inet/route.c
index 9624d5a..5a67bd7 100644
--- a/net/inet/route.c
+++ b/net/inet/route.c
@@ -253,17 +253,33 @@
 
 static int rt_new(struct rtentry *r)
 {
-	struct device *dev;
+	int err;
+	char * devname;
+	struct device * dev = NULL;
 	unsigned long flags, daddr, mask, gw;
 
+	if ((devname = r->rt_dev) != NULL) {
+		err = getname(devname, &devname);
+		if (err)
+			return err;
+		dev = dev_get(devname);
+		putname(devname);
+		if (!dev)
+			return -EINVAL;
+	}
+
 	if (r->rt_dst.sa_family != AF_INET)
 		return -EAFNOSUPPORT;
 
 	flags = r->rt_flags;
 	daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr;
-	mask = r->rt_genmask;
+	mask = ((struct sockaddr_in *) &r->rt_genmask)->sin_addr.s_addr;
 	gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
-	dev = (struct device *) r->rt_dev;
+
+	if (flags & RTF_HOST)
+		mask = 0xffffffff;
+	else if (r->rt_genmask.sa_family != AF_INET)
+		return -EAFNOSUPPORT;
 
 	if (flags & RTF_GATEWAY) {
 		if (r->rt_gateway.sa_family != AF_INET)
@@ -343,19 +359,41 @@
 	return NULL;
 }
 
+static int get_old_rtent(struct old_rtentry * src, struct rtentry * rt)
+{
+	int err;
+	struct old_rtentry tmp;
+
+	err=verify_area(VERIFY_READ, src, sizeof(*src));
+	if (err)
+		return err;
+	memcpy_fromfs(&tmp, src, sizeof(*src));
+	memset(rt, 0, sizeof(*rt));
+	rt->rt_dst = tmp.rt_dst;
+	rt->rt_gateway = tmp.rt_gateway;
+	rt->rt_genmask.sa_family = AF_INET;
+	((struct sockaddr_in *) &rt->rt_genmask)->sin_addr.s_addr = tmp.rt_genmask;
+	rt->rt_flags = tmp.rt_flags;
+	rt->rt_dev = tmp.rt_dev;
+	return 0;
+}
 
 int rt_ioctl(unsigned int cmd, void *arg)
 {
-	struct device *dev;
-	struct rtentry rt;
-	char *devname;
-	int ret;
 	int err;
+	struct rtentry rt;
 
 	switch(cmd) {
 	case DDIOCSDBG:
-		ret = dbg_ioctl(arg, DBG_RT);
-		break;
+		return dbg_ioctl(arg, DBG_RT);
+	case SIOCADDRTOLD:
+	case SIOCDELRTOLD:
+		if (!suser())
+			return -EPERM;
+		err = get_old_rtent((struct old_rtentry *) arg, &rt);
+		if (err)
+			return err;
+		return (cmd == SIOCDELRTOLD) ? rt_kill(&rt) : rt_new(&rt);
 	case SIOCADDRT:
 	case SIOCDELRT:
 		if (!suser())
@@ -364,21 +402,8 @@
 		if (err)
 			return err;
 		memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
-		if ((devname = (char *) rt.rt_dev) != NULL) {
-			err = getname(devname, &devname);
-			if (err)
-				return err;
-			dev = dev_get(devname);
-			putname(devname);
-			if (!dev)
-				return -EINVAL;
-			rt.rt_dev = dev;
-		}
-		ret = (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
-		break;
-	default:
-		ret = -EINVAL;
+		return (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
 	}
 
-	return ret;
+	return -EINVAL;
 }
diff --git a/net/inet/sock.c b/net/inet/sock.c
index 3de12e3..c937071 100644
--- a/net/inet/sock.c
+++ b/net/inet/sock.c
@@ -1531,8 +1531,8 @@
 	case DDIOCSDBG:
 		return(dbg_ioctl((void *) arg, DBG_INET));
 
-	case SIOCADDRT:
-	case SIOCDELRT:
+	case SIOCADDRT: case SIOCADDRTOLD:
+	case SIOCDELRT: case SIOCDELRTOLD:
 		return(rt_ioctl(cmd,(void *) arg));
 
 	case SIOCDARP:
@@ -1595,7 +1595,7 @@
 {
   if (sk) {
 	if (sk->rmem_alloc + size < sk->rcvbuf || force) {
-		void *c = alloc_skb(size, priority);
+		struct sk_buff *c = alloc_skb(size, priority);
 		cli();
 		if (c) sk->rmem_alloc += size;
 		sti();