diff -u --recursive --new-file v1.0.6/linux/Makefile linux/Makefile
--- v1.0.6/linux/Makefile	Tue Apr  5 07:23:05 1994
+++ linux/Makefile	Tue Apr  5 07:41:50 1994
@@ -1,6 +1,6 @@
 VERSION = 1
-PATCHLEVEL = 0
-SUBLEVEL = 6
+PATCHLEVEL = 1
+SUBLEVEL = 0
 
 all:	Version zImage
 
@@ -9,6 +9,7 @@
 CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
 	  else if [ -x /bin/bash ]; then echo /bin/bash; \
 	  else echo sh; fi ; fi)
+ROOT	:= $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
 
 #
 # Make "config" the default target if there is no configuration file or
@@ -76,7 +77,7 @@
 LD	=ld
 LDFLAGS	=#-qmagic
 HOSTCC	=gcc
-CC	=gcc -D__KERNEL__
+CC	=gcc -D__KERNEL__ -I$(ROOT)/include
 MAKE	=make
 CPP	=$(CC) -E
 AR	=ar
diff -u --recursive --new-file v1.0.6/linux/drivers/block/blk.h linux/drivers/block/blk.h
--- v1.0.6/linux/drivers/block/blk.h	Tue Apr  5 07:23:05 1994
+++ linux/drivers/block/blk.h	Wed Apr  6 10:40:57 1994
@@ -42,12 +42,9 @@
  * This is used in the elevator algorithm: Note that
  * reads always go before writes. This is natural: reads
  * are much more time-critical than writes.
- *
- * Update: trying with writes being preferred due to test
- * by Alessandro Rubini..
  */
 #define IN_ORDER(s1,s2) \
-((s1)->cmd > (s2)->cmd || ((s1)->cmd == (s2)->cmd && \
+((s1)->cmd < (s2)->cmd || ((s1)->cmd == (s2)->cmd && \
 ((s1)->dev < (s2)->dev || (((s1)->dev == (s2)->dev && \
 (s1)->sector < (s2)->sector)))))
 
diff -u --recursive --new-file v1.0.6/linux/drivers/block/mcd.c linux/drivers/block/mcd.c
--- v1.0.6/linux/drivers/block/mcd.c	Sun Mar  6 16:12:04 1994
+++ linux/drivers/block/mcd.c	Wed Apr  6 11:18:19 1994
@@ -476,9 +476,23 @@
 #endif
 		return 0;
 
-	case CDROMEJECT:     /* Eject the drive - N/A */
+	case CDROMEJECT:
+ 	       /* all drives can atleast stop! */
+ 		if (audioStatus == CDROM_AUDIO_PLAY) {
+ 		  outb(MCMD_STOP, MCDPORT(0));
+ 		  i = getMcdStatus(MCD_STATUS_DELAY);
+ 		}
+ 
+ 		audioStatus = CDROM_AUDIO_NO_STATUS;
+ 
+		outb(MCMD_EJECT, MCDPORT(0));
+		/*
+		 * the status (i) shows failure on all but the FX drives.
+		 * But nothing we can do about that in software!
+		 * So just read the status and forget it. - Jon.
+		 */
+ 		i = getMcdStatus(MCD_STATUS_DELAY);
 		return 0;
-
 	default:
 		return -EINVAL;
 	}
diff -u --recursive --new-file v1.0.6/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v1.0.6/linux/drivers/block/xd.c	Sat Feb 12 18:27:33 1994
+++ linux/drivers/block/xd.c	Tue Apr  5 07:24:51 1994
@@ -1,13 +1,22 @@
 /*
- * This file contains the driver for an XT hard disk controller (at least the DTC 5150X) for Linux.
+ * This file contains the driver for an XT hard disk controller
+ * (at least the DTC 5150X) for Linux.
  *
- * Author: Pat Mackinlay, smackinla@cc.curtin.edu.au
+ * Author: Pat Mackinlay, pat@it.com.au
  * Date: 29/09/92
  * 
  * Revised: 01/01/93, ...
  *
- * Ref: DTC 5150X Controller Specification (thanks to Kevin Fowler, kevinf@agora.rain.com)
- * Also thanks to: Salvador Abreu, Dave Thaler, Risto Kankkunen and Wim Van Dorst.
+ * Ref: DTC 5150X Controller Specification (thanks to Kevin Fowler,
+ *   kevinf@agora.rain.com)
+ * Also thanks to: Salvador Abreu, Dave Thaler, Risto Kankkunen and
+ *   Wim Van Dorst.
+ *
+ * Revised: 04/04/94 by Risto Kankkunen
+ *   Moved the detection code from xd_init() to xd_geninit() as it needed
+ *   interrupts enabled and Linus didn't want to enable them in that first
+ *   phase. xd_geninit() is the place to do these kinds of things anyway,
+ *   he says.
  */
 
 
@@ -53,8 +62,8 @@
    should be able to detect your drive's geometry from this info. (eg: xd=0,5,0x320,3 is the "standard"). */
 
 static XD_SIGNATURE xd_sigs[] = {
-	{ 0x0000,"Override geometry handler",NULL,xd_override_init_drive,"n unknown" }, /* Pat Mackinlay, smackinla@cc.curtin.edu.au (pat@gu.uwa.edu.au) */
-	{ 0x000B,"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Pat Mackinlay, smackinla@cc.curtin.edu.au (pat@gu.uwa.edu.au) */
+	{ 0x0000,"Override geometry handler",NULL,xd_override_init_drive,"n unknown" }, /* Pat Mackinlay, pat@it.com.au */
+	{ 0x000B,"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Pat Mackinlay, pat@it.com.au */
 	{ 0x0008,"07/15/86 (C) Copyright 1986 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Digital 1002AWX1" }, /* Ian Justman, citrus!ianj@csusac.ecs.csus.edu */
 	{ 0x0008,"06/24/88 (C) Copyright 1988 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Digital 1004A27X" }, /* Dave Thaler, thalerd@engin.umich.edu */
 	{ 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 */
@@ -70,21 +79,42 @@
 };
 
 static struct hd_struct xd[XD_MAXDRIVES << 6];
-static int xd_sizes[XD_MAXDRIVES << 6],xd_access[XD_MAXDRIVES] = { 0,0 };
+static int xd_sizes[XD_MAXDRIVES << 6], xd_access[XD_MAXDRIVES] = { 0, 0 };
 static int xd_blocksizes[XD_MAXDRIVES << 6];
-static struct gendisk xd_gendisk = { MAJOR_NR,"xd",6,1 << 6,XD_MAXDRIVES,xd_geninit,xd,xd_sizes,0,(void *) xd_info,NULL };
-static struct file_operations xd_fops = { NULL,block_read,block_write,NULL,NULL,xd_ioctl,NULL,xd_open,xd_release,block_fsync };
-
-static struct wait_queue *xd_wait_int = NULL,*xd_wait_open = NULL;
+static struct gendisk xd_gendisk = {
+	MAJOR_NR,	/* Major number */
+	"xd",		/* Major name */
+	6,		/* Bits to shift to get real from partition */
+	1 << 6,		/* Number of partitions per real */
+	XD_MAXDRIVES,	/* maximum number of real */
+	xd_geninit,	/* init function */
+	xd,		/* hd struct */
+	xd_sizes,	/* block sizes */
+	0,		/* number */
+	(void *) xd_info,	/* internal */
+	NULL		/* next */
+};
+static struct file_operations xd_fops = {
+	NULL,			/* lseek - default */
+	block_read,		/* read - general block-dev read */
+	block_write,		/* write - general block-dev write */
+	NULL,			/* readdir - bad */
+	NULL,			/* select */
+	xd_ioctl,		/* ioctl */
+	NULL,			/* mmap */
+	xd_open,		/* open */
+	xd_release,		/* release */
+	block_fsync		/* fsync */
+};
+static struct wait_queue *xd_wait_int = NULL, *xd_wait_open = NULL;
 static u_char xd_valid[XD_MAXDRIVES] = { 0,0 };
-static u_char xd_drives = 0,xd_irq = 0,xd_dma = 0,xd_maxsectors,xd_override = 0,xd_type = 0;
+static u_char xd_drives = 0, xd_irq = 0, xd_dma = 0, xd_maxsectors;
+static u_char xd_override = 0, xd_type = 0;
 static u_short xd_iobase = 0;
 
-/* xd_init: grab the IRQ and DMA channel and initialise the drives */
+/* xd_init: register the block device number and set up pointer tables */
 u_long xd_init (u_long mem_start,u_long mem_end)
 {
-	u_char i,controller,*address;
-	
 	if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) {
 		printk("xd_init: unable to get major number %d\n",MAJOR_NR);
 		return (mem_start);
@@ -94,26 +124,6 @@
 	xd_gendisk.next = gendisk_head;
 	gendisk_head = &xd_gendisk;
 
-	if (xd_detect(&controller,&address)) {
-
-		printk("xd_init: detected a%s controller (type %d) at address %p\n",xd_sigs[controller].name,controller,address);
-		if (controller)
-			xd_sigs[controller].init_controller(address);
-		xd_drives = xd_initdrives(xd_sigs[controller].init_drive);
-		
-		printk("xd_init: detected %d hard drive%s (using IRQ%d & DMA%d)\n",xd_drives,xd_drives == 1 ? "" : "s",xd_irq,xd_dma);
-		for (i = 0; i < xd_drives; i++)
-			printk("xd_init: drive %d geometry - heads = %d, cylinders = %d, sectors = %d\n",i,xd_info[i].heads,xd_info[i].cylinders,xd_info[i].sectors);
-
-		if (!request_irq(xd_irq,xd_interrupt_handler)) {
-			if (request_dma(xd_dma)) {
-				printk("xd_init: unable to get DMA%d\n",xd_dma);
-				free_irq(xd_irq);
-			}
-		}
-		else
-			printk("xd_init: unable to get IRQ%d\n",xd_irq);
-	}
 	return mem_start;
 }
 
@@ -139,11 +149,33 @@
 	return (found);
 }
 
-/* xd_geninit: set up the "raw" device entries in the table */
+/* xd_geninit: grab the IRQ and DMA channel, initialise the drives */
+/* and set up the "raw" device entries in the table */
 static void xd_geninit (void)
 {
-	u_char i;
+	u_char i,controller,*address;
 
+	if (xd_detect(&controller,&address)) {
+
+		printk("xd_geninit: detected a%s controller (type %d) at address %p\n",xd_sigs[controller].name,controller,address);
+		if (controller)
+			xd_sigs[controller].init_controller(address);
+		xd_drives = xd_initdrives(xd_sigs[controller].init_drive);
+		
+		printk("xd_geninit: detected %d hard drive%s (using IRQ%d & DMA%d)\n",xd_drives,xd_drives == 1 ? "" : "s",xd_irq,xd_dma);
+		for (i = 0; i < xd_drives; i++)
+			printk("xd_geninit: drive %d geometry - heads = %d, cylinders = %d, sectors = %d\n",i,xd_info[i].heads,xd_info[i].cylinders,xd_info[i].sectors);
+
+		if (!request_irq(xd_irq,xd_interrupt_handler)) {
+			if (request_dma(xd_dma)) {
+				printk("xd_geninit: unable to get DMA%d\n",xd_dma);
+				free_irq(xd_irq);
+			}
+		}
+		else
+			printk("xd_geninit: unable to get IRQ%d\n",xd_irq);
+	}
+
 	for (i = 0; i < xd_drives; i++) {
 		xd[i << 6].nr_sects = xd_info[i].heads * xd_info[i].cylinders * xd_info[i].sectors;
 		xd_valid[i] = 1;
@@ -188,10 +220,12 @@
 
 			switch (CURRENT->cmd) {
 				case READ:
-				case WRITE:	for (retry = 0; (retry < XD_RETRIES) && !code; retry++)
-							code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count);
-						break;
-				default:	printk("do_xd_request: unknown request\n"); break;
+				case WRITE:
+					for (retry = 0; (retry < XD_RETRIES) && !code; retry++)
+						code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count);
+					break;
+				default:
+					printk("do_xd_request: unknown request\n"); break;
 			}
 		}
 		end_request(code);	/* wrap up, 0 = fail, 1 = success */
@@ -206,25 +240,27 @@
 
 	if (inode && (dev < xd_drives))
 		switch (cmd) {
-			case HDIO_GETGEO:	if (arg) {
-							if ((err = verify_area(VERIFY_WRITE,geometry,sizeof(*geometry))))
-								return (err);
-							put_fs_byte(xd_info[dev].heads,(char *) &geometry->heads);
-							put_fs_byte(xd_info[dev].sectors,(char *) &geometry->sectors);
-							put_fs_word(xd_info[dev].cylinders,(short *) &geometry->cylinders);
-							put_fs_long(xd[MINOR(inode->i_rdev)].start_sect,(long *) &geometry->start);
-
-							return (0);
-						}
-						break;
-			case BLKGETSIZE:	if (arg) {
-							if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long))))
-								return (err);
-							put_fs_long(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
-
-							return (0);
-						}
-						break;
+			case HDIO_GETGEO:
+				if (arg) {
+					if ((err = verify_area(VERIFY_WRITE,geometry,sizeof(*geometry))))
+						return (err);
+					put_fs_byte(xd_info[dev].heads,(char *) &geometry->heads);
+					put_fs_byte(xd_info[dev].sectors,(char *) &geometry->sectors);
+					put_fs_word(xd_info[dev].cylinders,(short *) &geometry->cylinders);
+					put_fs_long(xd[MINOR(inode->i_rdev)].start_sect,(long *) &geometry->start);
+
+					return (0);
+				}
+				break;
+			case BLKGETSIZE:
+				if (arg) {
+					if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long))))
+						return (err);
+					put_fs_long(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
+
+					return (0);
+				}
+				break;
 			case BLKFLSBUF:
 				if(!suser())  return -EACCES;
 				if(!inode->i_rdev) return -EINVAL;
@@ -232,7 +268,8 @@
 				invalidate_buffers(inode->i_rdev);
 				return 0;
 				
-			case BLKRRPART:		return (xd_reread_partitions(inode->i_rdev));
+			case BLKRRPART:
+				return (xd_reread_partitions(inode->i_rdev));
 			RO_IOCTLS(inode->i_rdev,arg);
 		}
 	return (-EINVAL);
@@ -303,8 +340,12 @@
 		xd_build(cmdblk,operation == READ ? CMD_READ : CMD_WRITE,drive,head,cylinder,sector,temp & 0xFF,control);
 
 		switch (xd_command(cmdblk,mode,(u_char *) buffer,(u_char *) buffer,sense,XD_TIMEOUT)) {
-			case 1: printk("xd_readwrite: timeout, recalibrating drive\n"); xd_recalibrate(drive); return (0);
-			case 2: switch ((sense[0] & 0x30) >> 4) {
+			case 1:
+				printk("xd_readwrite: timeout, recalibrating drive\n");
+				xd_recalibrate(drive);
+				return (0);
+			case 2:
+				switch ((sense[0] & 0x30) >> 4) {
 					case 0: printk("xd_readwrite: drive error, code = 0x%X",sense[0] & 0x0F); break;
 					case 1: printk("xd_readwrite: controller error, code = 0x%X",sense[0] & 0x0F); break;
 					case 2: printk("xd_readwrite: command error, code = 0x%X",sense[0] & 0x0F); break;
@@ -412,28 +453,31 @@
 		if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout))
 			return (1);
 		switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) {
-			case 0:			if (mode == DMA_MODE) {
-							enable_dma(xd_dma);
-							sleep_on(&xd_wait_int);
-							disable_dma(xd_dma);
-						}
-						else
-							outb(outdata ? *outdata++ : 0,XD_DATA);
-						break;
-			case STAT_INPUT:	if (mode == DMA_MODE) {
-							enable_dma(xd_dma);
-							sleep_on(&xd_wait_int);
-							disable_dma(xd_dma);
-						}
-						else
-							if (indata)
-								*indata++ = inb(XD_DATA);
-							else
-								inb(XD_DATA);
-						break;
-			case STAT_COMMAND:	outb(command ? *command++ : 0,XD_DATA); break;
-			case STAT_COMMAND
-			     | STAT_INPUT:	complete = 1; break;
+			case 0:
+				if (mode == DMA_MODE) {
+					enable_dma(xd_dma);
+					sleep_on(&xd_wait_int);
+					disable_dma(xd_dma);
+				} else
+					outb(outdata ? *outdata++ : 0,XD_DATA);
+				break;
+			case STAT_INPUT:
+				if (mode == DMA_MODE) {
+					enable_dma(xd_dma);
+					sleep_on(&xd_wait_int);
+					disable_dma(xd_dma);
+				} else
+					if (indata)
+						*indata++ = inb(XD_DATA);
+					else
+						inb(XD_DATA);
+				break;
+			case STAT_COMMAND:
+				outb(command ? *command++ : 0,XD_DATA);
+				break;
+			case STAT_COMMAND | STAT_INPUT:
+				complete = 1;
+				break;
 		}
 	}
 	csb = inb(XD_DATA);
@@ -460,7 +504,7 @@
 
 	for (i = 0; i < XD_MAXDRIVES; i++) {
 		xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);
-		if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2)) {
+		if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8)) {
 			init_drive(count);
 			count++;
 		}
diff -u --recursive --new-file v1.0.6/linux/include/asm/bitops.h linux/include/asm/bitops.h
--- v1.0.6/linux/include/asm/bitops.h	Fri Feb 11 09:25:54 1994
+++ linux/include/asm/bitops.h	Tue Apr  5 11:38:58 1994
@@ -39,6 +39,16 @@
 	return oldbit;
 }
 
+extern __inline__ int change_bit(int nr, void * addr)
+{
+	int oldbit;
+
+	__asm__ __volatile__("btcl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit),"=m" (ADDR)
+		:"r" (nr));
+	return oldbit;
+}
+
 /*
  * This routine doesn't need to be atomic, but it's faster to code it
  * this way.
diff -u --recursive --new-file v1.0.6/linux/include/linux/if.h linux/include/linux/if.h
--- v1.0.6/linux/include/linux/if.h	Wed Dec  1 14:44:15 1993
+++ linux/include/linux/if.h	Tue Apr  5 08:14:29 1994
@@ -24,6 +24,7 @@
 
 
 /* Structure defining a queue for a network interface. */
+#ifdef not_yet_in_linux
 struct ifnet {
   char		*if_name;		/* name, e.g. ``en'' or ``lo''	*/
   short		if_unit;		/* sub-unit for device driver	*/
@@ -33,13 +34,11 @@
   int		if_metric;		/* routing metric (not used)	*/
   struct	ifaddr *if_addrlist;	/* linked list of addrs per if	*/
   struct	ifqueue {
-#ifdef not_yet_in_linux
 	struct mbuf	*ifq_head;
 	struct mbuf	*ifq_tail;
 	int		ifq_len;
 	int		ifq_maxlen;
 	int		ifq_drops;
-#endif
   } if_snd;				/* output queue			*/
 
   /* Procedure handles. */
@@ -59,6 +58,7 @@
   /* Linked list: pointer to next interface. */
   struct ifnet	*if_next;
 };
+#endif
 
 /* Standard interface flags. */
 #define	IFF_UP		0x1		/* interface is up		*/
diff -u --recursive --new-file v1.0.6/linux/include/linux/mcd.h linux/include/linux/mcd.h
--- v1.0.6/linux/include/linux/mcd.h	Mon Jan  3 08:19:44 1994
+++ linux/include/linux/mcd.h	Wed Apr  6 11:18:19 1994
@@ -31,7 +31,7 @@
 #define MCD_STATUS_DELAY	100
 
 /* number of times to retry a command before giving up */
-#define MCD_RETRY_ATTEMPTS      3
+#define MCD_RETRY_ATTEMPTS      5
 
 /* port access macro */
 #define MCDPORT(x)		(mcd_port + (x))
@@ -64,6 +64,7 @@
 #define MCMD_SET_VOLUME		0xAE		/* set audio level */
 #define MCMD_PLAY_READ		0xC0		/* play or read data */
 #define MCMD_GET_VERSION  	0xDC
+#define MCMD_EJECT		0xF6            /* eject (FX drive) */
 
 /* borrowed from hd.c */
 
diff -u --recursive --new-file v1.0.6/linux/include/linux/mm.h linux/include/linux/mm.h
--- v1.0.6/linux/include/linux/mm.h	Mon Mar 21 20:42:09 1994
+++ linux/include/linux/mm.h	Wed Apr  6 11:39:19 1994
@@ -92,22 +92,31 @@
 };
 /* end of planning stage */
 
-extern volatile short free_page_ptr; /* used by malloc and tcp/ip. */
+/*
+ * Free area management
+ */
 
 extern int nr_swap_pages;
 extern int nr_free_pages;
-extern unsigned long free_page_list;
-extern int nr_secondary_pages;
-extern unsigned long secondary_page_list;
 
 #define MAX_SECONDARY_PAGES 20
+#define NR_MEM_LISTS 6
+
+struct mem_list {
+	struct mem_list * next;
+	struct mem_list * prev;
+};
 
+extern struct mem_list free_area_list[NR_MEM_LISTS];
+extern unsigned char * free_area_map[NR_MEM_LISTS];
+
 /*
  * This is timing-critical - most of the time in getting a new page
  * goes to clearing the page. If you want a page without the clearing
  * overhead, just use __get_free_page() directly..
  */
-extern unsigned long __get_free_page(int priority);
+#define __get_free_page(priority) __get_free_pages((priority),0)
+extern unsigned long __get_free_pages(int priority, unsigned long gfporder);
 extern inline unsigned long get_free_page(int priority)
 {
 	unsigned long page;
@@ -121,9 +130,12 @@
 	return page;
 }
 
-/* memory.c */
+/* memory.c & swap.c*/
+
+#define free_page(addr) free_pages((addr),0)
+extern void free_pages(unsigned long addr, unsigned long order);
 
-extern void free_page(unsigned long addr);
+extern void show_free_areas(void);
 extern unsigned long put_dirty_page(struct task_struct * tsk,unsigned long page,
 	unsigned long address);
 extern void free_page_tables(struct task_struct * tsk);
diff -u --recursive --new-file v1.0.6/linux/include/linux/string.h linux/include/linux/string.h
--- v1.0.6/linux/include/linux/string.h	Wed Dec  1 14:44:15 1993
+++ linux/include/linux/string.h	Tue Apr  5 07:37:24 1994
@@ -7,6 +7,10 @@
 #define NULL ((void *) 0)
 #endif
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * This string-include defines all string functions as inline
  * functions. Use gcc. It also assumes ds=es=data space, this should be
@@ -415,5 +419,9 @@
 	:"cx","di","memory");
 return s;
 }
+
+#ifdef __cplusplus
+}
+#endif
 
 #endif
diff -u --recursive --new-file v1.0.6/linux/include/linux/sys.h linux/include/linux/sys.h
--- v1.0.6/linux/include/linux/sys.h	Mon Jan 31 16:31:24 1994
+++ linux/include/linux/sys.h	Tue Apr  5 09:00:20 1994
@@ -1,179 +1,37 @@
 #ifndef _LINUX_SYS_H
 #define _LINUX_SYS_H
+
 /*
- * system call entry points
+ * system call entry points ... but not all are defined
  */
-
-#define sys_clone sys_fork
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#define NR_syscalls 256
 
-extern int sys_setup();         /* 0 */
-extern int sys_exit();
-extern int sys_fork();
-extern int sys_read();
-extern int sys_write();
-extern int sys_open();          /* 5 */
-extern int sys_close();
-extern int sys_waitpid();
-extern int sys_creat();
-extern int sys_link();
-extern int sys_unlink();        /* 10 */
-extern int sys_execve();
-extern int sys_chdir();
-extern int sys_time();
-extern int sys_mknod();
-extern int sys_chmod();         /* 15 */
-extern int sys_chown();
-extern int sys_break();
-extern int sys_stat();
-extern int sys_lseek();
-extern int sys_getpid();        /* 20 */
-extern int sys_mount();
-extern int sys_umount();
-extern int sys_setuid();
-extern int sys_getuid();
-extern int sys_stime();         /* 25 */
-extern int sys_ptrace();
-extern int sys_alarm();
-extern int sys_fstat();
-extern int sys_pause();
-extern int sys_utime();         /* 30 */
-extern int sys_stty();
-extern int sys_gtty();
-extern int sys_access();
-extern int sys_nice();
-extern int sys_ftime();         /* 35 */
-extern int sys_sync();
-extern int sys_kill();
-extern int sys_rename();
-extern int sys_mkdir();
-extern int sys_rmdir();         /* 40 */
-extern int sys_dup();
-extern int sys_pipe();
-extern int sys_times();
-extern int sys_prof();
-extern int sys_brk();           /* 45 */
-extern int sys_setgid();
-extern int sys_getgid();
-extern int sys_signal();
-extern int sys_geteuid();
-extern int sys_getegid();       /* 50 */
-extern int sys_acct();
-extern int sys_phys();
-extern int sys_lock();
-extern int sys_ioctl();
-extern int sys_fcntl();         /* 55 */
-extern int sys_mpx();
-extern int sys_setpgid();
-extern int sys_ulimit();
-extern int sys_uname();
-extern int sys_umask();         /* 60 */
-extern int sys_chroot();
-extern int sys_ustat();
-extern int sys_dup2();
-extern int sys_getppid();
-extern int sys_getpgrp();       /* 65 */
-extern int sys_setsid();
-extern int sys_sigaction();
-extern int sys_sgetmask();
-extern int sys_ssetmask();
-extern int sys_setreuid();      /* 70 */
-extern int sys_setregid();
-extern int sys_sigpending();
-extern int sys_sigsuspend();
-extern int sys_sethostname();
-extern int sys_setrlimit();     /* 75 */
-extern int sys_getrlimit();
-extern int sys_getrusage();
-extern int sys_gettimeofday();
-extern int sys_settimeofday();
-extern int sys_getgroups();     /* 80 */
-extern int sys_setgroups();
-extern int sys_select();
-extern int sys_symlink();
-extern int sys_lstat();
-extern int sys_readlink();      /* 85 */
-extern int sys_uselib();
-extern int sys_swapon();
-extern int sys_reboot();
-extern int sys_readdir();
-extern int sys_mmap();          /* 90 */
-extern int sys_munmap();
-extern int sys_truncate();
-extern int sys_ftruncate();
-extern int sys_fchmod();
-extern int sys_fchown();        /* 95 */
-extern int sys_getpriority();
-extern int sys_setpriority();
-extern int sys_profil();
-extern int sys_statfs();
-extern int sys_fstatfs();       /* 100 */
-extern int sys_ioperm();
-extern int sys_socketcall();
-extern int sys_syslog();
-extern int sys_getitimer();
-extern int sys_setitimer();     /* 105 */
-extern int sys_newstat();
-extern int sys_newlstat();
-extern int sys_newfstat();
-extern int sys_newuname();
-extern int sys_iopl();          /* 110 */
-extern int sys_vhangup();
-extern int sys_idle();
-extern int sys_vm86();
-extern int sys_wait4();
-extern int sys_swapoff();       /* 115 */
-extern int sys_sysinfo();
-extern int sys_ipc();
-extern int sys_fsync();
-extern int sys_sigreturn();
-extern int sys_setdomainname(); /* 120 */
-extern int sys_olduname();
-extern int sys_old_syscall();
-extern int sys_modify_ldt();
-extern int sys_adjtimex();
-extern int sys_mprotect();      /* 125 */
-extern int sys_sigprocmask();
-extern int sys_create_module();
-extern int sys_init_module();
-extern int sys_delete_module();
-extern int sys_get_kernel_syms(); /* 130 */
-extern int sys_quotactl();
-extern int sys_getpgid();
-extern int sys_fchdir();
-extern int sys_bdflush();
+/*
+ * These are system calls with the same entry-point
+ */
+#define _sys_clone _sys_fork
 
 /*
  * These are system calls that will be removed at some time
  * due to newer versions existing..
  */
 #ifdef notdef
-#define sys_waitpid	sys_old_syscall	/* sys_wait4	*/
-#define sys_olduname	sys_old_syscall /* sys_newuname	*/
-#define sys_uname	sys_old_syscall /* sys_newuname	*/
-#define sys_stat	sys_old_syscall /* sys_newstat	*/
-#define sys_fstat	sys_old_syscall	/* sys_newfstat	*/
-#define sys_lstat	sys_old_syscall /* sys_newlstat	*/
-#define sys_signal	sys_old_syscall	/* sys_sigaction */
-#define sys_sgetmask	sys_old_syscall /* sys_sigprocmask */
-#define sys_ssetmask	sys_old_syscall /* sig_sigprocmask */
+#define _sys_waitpid	_sys_old_syscall	/* _sys_wait4 */
+#define _sys_olduname	_sys_old_syscall	/* _sys_newuname */
+#define _sys_uname	_sys_old_syscall	/* _sys_newuname */
+#define _sys_stat	_sys_old_syscall	/* _sys_newstat */
+#define _sys_fstat	_sys_old_syscall	/* _sys_newfstat */
+#define _sys_lstat	_sys_old_syscall	/* _sys_newlstat */
+#define _sys_signal	_sys_old_syscall	/* _sys_sigaction */
+#define _sys_sgetmask	_sys_old_syscall	/* _sys_sigprocmask */
+#define _sys_ssetmask	_sys_old_syscall	/* _sys_sigprocmask */
 #endif
 
 /*
  * These are system calls that haven't been implemented yet
  * but have an entry in the table for future expansion..
  */
-
-#define sys_quotactl	sys_ni_syscall
-#define sys_bdflush	sys_ni_syscall
-
-typedef int (*fn_ptr)();
-
-#ifdef __cplusplus
-}
-#endif
+#define _sys_quotactl	_sys_ni_syscall
+#define _sys_bdflush	_sys_ni_syscall
 
 #endif
diff -u --recursive --new-file v1.0.6/linux/include/linux/xd.h linux/include/linux/xd.h
--- v1.0.6/linux/include/linux/xd.h	Sat Feb 12 18:27:32 1994
+++ linux/include/linux/xd.h	Tue Apr  5 07:24:51 1994
@@ -4,7 +4,7 @@
 /*
  * This file contains the definitions for the IO ports and errors etc. for XT hard disk controllers (at least the DTC 5150X).
  *
- * Author: Pat Mackinlay, smackinla@cc.curtin.edu.au
+ * Author: Pat Mackinlay, pat@it.com.au
  * Date: 29/09/92
  *
  * Revised: 01/01/93, ...
diff -u --recursive --new-file v1.0.6/linux/init/main.c linux/init/main.c
--- v1.0.6/linux/init/main.c	Sun Apr  3 14:58:24 1994
+++ linux/init/main.c	Tue Apr  5 07:37:24 1994
@@ -78,7 +78,6 @@
 extern void sock_init(void);
 extern long rd_init(long mem_start, int length);
 unsigned long net_dev_init(unsigned long, unsigned long);
-extern unsigned long simple_strtoul(const char *,char **,unsigned int);
 
 extern void hd_setup(char *str, int *ints);
 extern void bmouse_setup(char *str, int *ints);
@@ -267,7 +266,7 @@
 {
 	char *next;
 	char *devnames[] = { "hda", "hdb", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL };
-	int devnums[]    = { 0x300, 0x340, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xC00, 0xC40, 0};
+	int devnums[]    = { 0x300, 0x340, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0};
 	int args, envs;
 
 	if (!*line)
diff -u --recursive --new-file v1.0.6/linux/kernel/Makefile linux/kernel/Makefile
--- v1.0.6/linux/kernel/Makefile	Fri Dec 17 08:14:28 1993
+++ linux/kernel/Makefile	Tue Apr  5 07:37:24 1994
@@ -34,14 +34,6 @@
 sched.o: sched.c
 	$(CC) $(CFLAGS) $(PROFILING) -fno-omit-frame-pointer -c $<
 
-ksyms.lst: ksyms.S ../include/linux/autoconf.h
-	$(CPP) $(CFLAGS) $< > $@
- 
-ksyms.s: ksyms.sh ksyms.lst
-	sh $< > $@
-
-ksyms.o: ksyms.s
-
 dep:
 	$(CPP) -M *.c > .depend
 
diff -u --recursive --new-file v1.0.6/linux/kernel/ksyms.S linux/kernel/ksyms.S
--- v1.0.6/linux/kernel/ksyms.S	Wed Feb 16 09:30:21 1994
+++ linux/kernel/ksyms.S
@@ -1,30 +0,0 @@
-#include <linux/autoconf.h>
-/* 
- * Herein lies all the functions/variables that are "exported" for linkage
- * With dynamically loaded kernel modules. Could do with making this a bit
- * cleaner!
- *
- *  Jon.
- */
-
-_register_chrdev
-_unregister_chrdev
-_register_blkdev
-_unregister_blkdev
-_wake_up_interruptible
-
-_wp_works_ok
-___verify_write
-
-_current
-_jiffies
-_printk
-_schedule
-
-#ifdef CONFIG_FTAPE
-#
-# The next labels are needed for ftape driver.
-#
-_ftape_big_buffer
-_do_floppy
-#endif
diff -u --recursive --new-file v1.0.6/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.0.6/linux/kernel/ksyms.c
+++ linux/kernel/ksyms.c	Wed Apr  6 11:38:21 1994
@@ -0,0 +1,40 @@
+/* 
+ * Herein lies all the functions/variables that are "exported" for linkage
+ * with dynamically loaded kernel modules.
+ *			Jon.
+ */
+
+#include <linux/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+
+#define X(name)	{ (void *) &name, #name }
+
+struct {
+	void *addr;
+	const char *name;
+} symbol_table[] = {
+	X(register_chrdev),
+	X(unregister_chrdev),
+	X(register_blkdev),
+	X(unregister_blkdev),
+	X(wake_up_interruptible),
+
+	X(wp_works_ok),
+	X(__verify_write),
+
+	X(current),
+	X(jiffies),
+	X(printk),
+	X(schedule),
+
+#ifdef CONFIG_FTAPE
+	/* The next labels are needed for ftape driver.  */
+	X(ftape_big_buffer),
+	X(do_floppy),
+#endif
+
+};
+
+int symbol_table_size = sizeof (symbol_table) / sizeof (symbol_table[0]);
diff -u --recursive --new-file v1.0.6/linux/kernel/ksyms.sh linux/kernel/ksyms.sh
--- v1.0.6/linux/kernel/ksyms.sh	Fri Feb 18 16:54:02 1994
+++ linux/kernel/ksyms.sh
@@ -1,37 +0,0 @@
-# This program will construct ksyms.s.  Ksyms.s contains a symbol table
-# for all the kernel symbols included in the file ksyms.lst.  The following
-# variables are defined in ksym.s:
-#
-#	int symbol_table_size;		/* number of symbols */
-#	struct {
-#		void *value;		/* value of symbol */
-#		char *name;		/* name of symbol */
-#	} symbol_table[];
-#
-#
-
-trap "rm -f ksyms.tmp ksyms.lst ; exit 1" 1 2 
-
-sed -e '/^#/d' -e '/^[	 ]*$/d' ksyms.lst | sort > ksyms.tmp
-
-echo '	.data
-	.globl	_symbol_table_size, _symbol_table
-
-_symbol_table_size:'
-echo "	.long" `wc -l < ksyms.tmp`
-echo '
-_symbol_table:'
-awk 'BEGIN {stringloc = 0}
-{print "	.long " $1; print "	.long strings+" stringloc; \
-        stringloc += length($1) + 1;}' ksyms.tmp
-echo '
-strings:'
-awk '{print "	.ascii \"" $1 "\\0\""}' ksyms.tmp
-rm -f ksyms.tmp
-
-
-#
-# Alternativly, if the kernel is c++ compiled:
-# By using gsub() we can forse all function names to appear as extern "C".
-# This allows linkable drivers written in C or C++ - Jon
-# awk '{gsub(/__F.*/, "") ; print "	.ascii \"" $0 "\\0\""}' ksyms.tmp
diff -u --recursive --new-file v1.0.6/linux/kernel/sched.c linux/kernel/sched.c
--- v1.0.6/linux/kernel/sched.c	Tue Apr  5 07:23:07 1994
+++ linux/kernel/sched.c	Tue Apr  5 08:49:45 1994
@@ -17,7 +17,6 @@
 #include <linux/timer.h>
 #include <linux/kernel.h>
 #include <linux/kernel_stat.h>
-#include <linux/sys.h>
 #include <linux/fdreg.h>
 #include <linux/errno.h>
 #include <linux/time.h>
@@ -102,55 +101,7 @@
 	short b;
 	} stack_start = { & user_stack [PAGE_SIZE>>2] , KERNEL_DS };
 
-struct kernel_stat kstat =
-	{ 0, 0, 0, { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-/*
- * int 0x80 entry points.. Moved away from the header file, as
- * iBCS2 may also want to use the '<linux/sys.h>' headers..
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int sys_ni_syscall(void)
-{
-	return -EINVAL;
-}
-
-fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
-sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
-sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
-sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
-sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
-sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
-sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
-sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
-sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
-sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
-sys_olduname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
-sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
-sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending,
-sys_sethostname, sys_setrlimit, sys_getrlimit, sys_getrusage,
-sys_gettimeofday, sys_settimeofday, sys_getgroups, sys_setgroups,
-sys_select, sys_symlink, sys_lstat, sys_readlink, sys_uselib,
-sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap, sys_truncate,
-sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority, sys_setpriority,
-sys_profil, sys_statfs, sys_fstatfs, sys_ioperm, sys_socketcall,
-sys_syslog, sys_setitimer, sys_getitimer, sys_newstat, sys_newlstat,
-sys_newfstat, sys_uname, sys_iopl, sys_vhangup, sys_idle, sys_vm86,
-sys_wait4, sys_swapoff, sys_sysinfo, sys_ipc, sys_fsync, sys_sigreturn,
-sys_clone, sys_setdomainname, sys_newuname, sys_modify_ldt,
-sys_adjtimex, sys_mprotect, sys_sigprocmask, sys_create_module,
-sys_init_module, sys_delete_module, sys_get_kernel_syms, sys_quotactl,
-sys_getpgid, sys_fchdir, sys_bdflush };
-
-/* So we don't have to do any more manual updating.... */
-int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
-
-#ifdef __cplusplus
-}
-#endif
+struct kernel_stat kstat = { 0 };
 
 /*
  *  'math_state_restore()' saves the current math information in the
diff -u --recursive --new-file v1.0.6/linux/kernel/sys.c linux/kernel/sys.c
--- v1.0.6/linux/kernel/sys.c	Mon Mar 21 20:42:10 1994
+++ linux/kernel/sys.c	Tue Apr  5 08:32:36 1994
@@ -30,6 +30,11 @@
 
 #define	PZERO	15
 
+asmlinkage int sys_ni_syscall(void)
+{
+	return -EINVAL;
+}
+
 static int proc_sel(struct task_struct *p, int which, int who)
 {
 	switch (which) {
diff -u --recursive --new-file v1.0.6/linux/kernel/sys_call.S linux/kernel/sys_call.S
--- v1.0.6/linux/kernel/sys_call.S	Wed Dec  1 14:44:15 1993
+++ linux/kernel/sys_call.S	Tue Apr  5 09:01:38 1994
@@ -41,6 +41,7 @@
  */
 
 #include <linux/segment.h>
+#include <linux/sys.h>
 
 EBX		= 0x00
 ECX		= 0x04
@@ -87,7 +88,7 @@
 .globl _invalid_TSS,_segment_not_present,_stack_segment
 .globl _general_protection,_reserved
 .globl _alignment_check,_page_fault
-.globl ret_from_sys_call
+.globl ret_from_sys_call, _sys_call_table
 
 #define SAVE_ALL \
 	cld; \
@@ -163,8 +164,11 @@
 	pushl %eax			# save orig_eax
 	SAVE_ALL
 	movl $-ENOSYS,EAX(%esp)
-	cmpl _NR_syscalls,%eax
+	cmpl $(NR_syscalls),%eax
 	jae ret_from_sys_call
+	movl _sys_call_table(,%eax,4),%eax
+	testl %eax,%eax
+	je ret_from_sys_call
 	movl _current,%ebx
 	andl $~CF_MASK,EFLAGS(%esp)	# clear carry - assume no errors
 	movl $0,errno(%ebx)
@@ -172,7 +176,7 @@
 	movl %edx,dbgreg6(%ebx)  # save current hardware debugging status
 	testb $0x20,flags(%ebx)		# PF_TRACESYS
 	jne 1f
-	call _sys_call_table(,%eax,4)
+	call *%eax
 	movl %eax,EAX(%esp)		# save the return value
 	movl errno(%ebx),%edx
 	negl %edx
@@ -388,3 +392,144 @@
 _page_fault:
 	pushl $_do_page_fault
 	jmp error_code
+
+.data
+.align 4
+_sys_call_table:
+	.long _sys_setup		/* 0 */
+	.long _sys_exit
+	.long _sys_fork
+	.long _sys_read
+	.long _sys_write
+	.long _sys_open			/* 5 */
+	.long _sys_close
+	.long _sys_waitpid
+	.long _sys_creat
+	.long _sys_link
+	.long _sys_unlink		/* 10 */
+	.long _sys_execve
+	.long _sys_chdir
+	.long _sys_time
+	.long _sys_mknod
+	.long _sys_chmod		/* 15 */
+	.long _sys_chown
+	.long _sys_break
+	.long _sys_stat
+	.long _sys_lseek
+	.long _sys_getpid		/* 20 */
+	.long _sys_mount
+	.long _sys_umount
+	.long _sys_setuid
+	.long _sys_getuid
+	.long _sys_stime		/* 25 */
+	.long _sys_ptrace
+	.long _sys_alarm
+	.long _sys_fstat
+	.long _sys_pause
+	.long _sys_utime		/* 30 */
+	.long _sys_stty
+	.long _sys_gtty
+	.long _sys_access
+	.long _sys_nice
+	.long _sys_ftime		/* 35 */
+	.long _sys_sync
+	.long _sys_kill
+	.long _sys_rename
+	.long _sys_mkdir
+	.long _sys_rmdir		/* 40 */
+	.long _sys_dup
+	.long _sys_pipe
+	.long _sys_times
+	.long _sys_prof
+	.long _sys_brk			/* 45 */
+	.long _sys_setgid
+	.long _sys_getgid
+	.long _sys_signal
+	.long _sys_geteuid
+	.long _sys_getegid		/* 50 */
+	.long _sys_acct
+	.long _sys_phys
+	.long _sys_lock
+	.long _sys_ioctl
+	.long _sys_fcntl		/* 55 */
+	.long _sys_mpx
+	.long _sys_setpgid
+	.long _sys_ulimit
+	.long _sys_olduname
+	.long _sys_umask		/* 60 */
+	.long _sys_chroot
+	.long _sys_ustat
+	.long _sys_dup2
+	.long _sys_getppid
+	.long _sys_getpgrp		/* 65 */
+	.long _sys_setsid
+	.long _sys_sigaction
+	.long _sys_sgetmask
+	.long _sys_ssetmask
+	.long _sys_setreuid		/* 70 */
+	.long _sys_setregid
+	.long _sys_sigsuspend
+	.long _sys_sigpending
+	.long _sys_sethostname
+	.long _sys_setrlimit		/* 75 */
+	.long _sys_getrlimit
+	.long _sys_getrusage
+	.long _sys_gettimeofday
+	.long _sys_settimeofday
+	.long _sys_getgroups		/* 80 */
+	.long _sys_setgroups
+	.long _sys_select
+	.long _sys_symlink
+	.long _sys_lstat
+	.long _sys_readlink		/* 85 */
+	.long _sys_uselib
+	.long _sys_swapon
+	.long _sys_reboot
+	.long _sys_readdir
+	.long _sys_mmap			/* 90 */
+	.long _sys_munmap
+	.long _sys_truncate
+	.long _sys_ftruncate
+	.long _sys_fchmod
+	.long _sys_fchown		/* 95 */
+	.long _sys_getpriority
+	.long _sys_setpriority
+	.long _sys_profil
+	.long _sys_statfs
+	.long _sys_fstatfs		/* 100 */
+	.long _sys_ioperm
+	.long _sys_socketcall
+	.long _sys_syslog
+	.long _sys_setitimer
+	.long _sys_getitimer		/* 105 */
+	.long _sys_newstat
+	.long _sys_newlstat
+	.long _sys_newfstat
+	.long _sys_uname
+	.long _sys_iopl			/* 110 */
+	.long _sys_vhangup
+	.long _sys_idle
+	.long _sys_vm86
+	.long _sys_wait4
+	.long _sys_swapoff		/* 115 */
+	.long _sys_sysinfo
+	.long _sys_ipc
+	.long _sys_fsync
+	.long _sys_sigreturn
+	.long _sys_clone		/* 120 */
+	.long _sys_setdomainname
+	.long _sys_newuname
+	.long _sys_modify_ldt
+	.long _sys_adjtimex
+	.long _sys_mprotect		/* 125 */
+	.long _sys_sigprocmask
+	.long _sys_create_module
+	.long _sys_init_module
+	.long _sys_delete_module
+	.long _sys_get_kernel_syms	/* 130 */
+	.long _sys_quotactl
+	.long _sys_getpgid
+	.long _sys_fchdir
+	.long _sys_bdflush
+
+	.space (NR_syscalls-130)*4
diff -u --recursive --new-file v1.0.6/linux/lib/string.c linux/lib/string.c
--- v1.0.6/linux/lib/string.c	Wed Dec  1 14:44:15 1993
+++ linux/lib/string.c	Tue Apr  5 09:51:29 1994
@@ -10,7 +10,19 @@
 
 #include <linux/types.h>
 
+#ifdef __cplusplus
+#define C_BEGIN extern "C" {
+#define C_END }
+#else
+#define C_BEGIN
+#define C_END
+#endif
+
+#undef __cplusplus
 #define extern
 #define inline
 #define __LIBRARY__
+
+C_BEGIN
 #include <linux/string.h>
+C_END
diff -u --recursive --new-file v1.0.6/linux/mm/kmalloc.c linux/mm/kmalloc.c
--- v1.0.6/linux/mm/kmalloc.c	Tue Apr  5 07:23:08 1994
+++ linux/mm/kmalloc.c	Tue Apr  5 14:52:20 1994
@@ -7,6 +7,11 @@
  *
  */
 
+/*
+ * Modified by Alex Bligh (alex@cconcepts.co.uk) 4 Apr 1994 to use multiple
+ * pages. So for 'page' throughout, read 'area'.
+ */
+
 #include <linux/mm.h>
 #include <asm/system.h>
 #include <linux/delay.h>
@@ -17,7 +22,7 @@
    I want this number to be increased in the near future:
         loadable device drivers should use this function to get memory */
 
-#define MAX_KMALLOC_K 4
+#define MAX_KMALLOC_K ((PAGE_SIZE<<(NUM_AREA_ORDERS-1))>>10)
 
 
 /* This defines how many times we should try to allocate a free page before
@@ -86,25 +91,35 @@
 	int nfrees;
 	int nbytesmalloced;
 	int npages;
+	unsigned long gfporder; /* number of pages in the area required */
 };
 
+/*
+ * For now it is unsafe to allocate bucket sizes between n & n=16 where n is
+ * 4096 * any power of two
+ */
 
 struct size_descriptor sizes[] = { 
-	{ NULL,  32,127, 0,0,0,0 },
-	{ NULL,  64, 63, 0,0,0,0 },
-	{ NULL, 128, 31, 0,0,0,0 },
-	{ NULL, 252, 16, 0,0,0,0 },
-	{ NULL, 508,  8, 0,0,0,0 },
-	{ NULL,1020,  4, 0,0,0,0 },
-	{ NULL,2040,  2, 0,0,0,0 },
-	{ NULL,4080,  1, 0,0,0,0 },
-	{ NULL,   0,  0, 0,0,0,0 }
+	{ NULL,  32,127, 0,0,0,0, 0},
+	{ NULL,  64, 63, 0,0,0,0, 0 },
+	{ NULL, 128, 31, 0,0,0,0, 0 },
+	{ NULL, 252, 16, 0,0,0,0, 0 },
+	{ NULL, 508,  8, 0,0,0,0, 0 },
+	{ NULL,1020,  4, 0,0,0,0, 0 },
+	{ NULL,2040,  2, 0,0,0,0, 0 },
+	{ NULL,4096-16,  1, 0,0,0,0, 0 },
+	{ NULL,8192-16,  1, 0,0,0,0, 1 },
+	{ NULL,16384-16,  1, 0,0,0,0, 2 },
+	{ NULL,32768-16,  1, 0,0,0,0, 3 },
+	{ NULL,65536-16,  1, 0,0,0,0, 4 },
+	{ NULL,131072-16,  1, 0,0,0,0, 5 },
+	{ NULL,   0,  0, 0,0,0,0, 0 }
 };
 
 
 #define NBLOCKS(order)          (sizes[order].nblocks)
 #define BLOCKSIZE(order)        (sizes[order].size)
-
+#define AREASIZE(order)		(PAGE_SIZE<<(sizes[order].gfporder))
 
 
 long kmalloc_init (long start_mem,long end_mem)
@@ -118,12 +133,12 @@
 for (order = 0;BLOCKSIZE(order);order++)
     {
     if ((NBLOCKS (order)*BLOCKSIZE(order) + sizeof (struct page_descriptor)) >
-        PAGE_SIZE) 
+        AREASIZE(order)) 
         {
         printk ("Cannot use %d bytes out of %d in order = %d block mallocs\n",
                 NBLOCKS (order) * BLOCKSIZE(order) + 
                         sizeof (struct page_descriptor),
-                (int) PAGE_SIZE,
+                (int) AREASIZE(order),
                 BLOCKSIZE (order));
         panic ("This only happens if someone messes with kmalloc");
         }
@@ -161,12 +176,6 @@
 			priority = GFP_ATOMIC;
 		}
 	}
-if (size > MAX_KMALLOC_K * 1024) 
-     {
-     printk ("kmalloc: I refuse to allocate %d bytes (for now max = %d).\n",
-                size,MAX_KMALLOC_K*1024);
-     return (NULL);
-     }
 
 order = get_order (size);
 if (order < 0)
@@ -215,7 +224,7 @@
     sz = BLOCKSIZE(order); /* sz is the size of the blocks we're dealing with */
 
     /* This can be done with ints on: This is private to this invocation */
-    page = (struct page_descriptor *) __get_free_page (priority & GFP_LEVEL_MASK);
+    page = (struct page_descriptor *) __get_free_pages (priority & GFP_LEVEL_MASK, sizes[order].gfporder);
     if (!page) {
         static unsigned long last = 0;
         if (last + 10*HZ < jiffies) {
@@ -339,10 +348,15 @@
         else
             printk ("Ooops. page %p doesn't show on freelist.\n", page);
         }
-    free_page ((long)page);
+/* FIXME: I'm sure we should do something with npages here (like npages--) */
+    free_pages ((long)page, sizes[order].gfporder);
     }
 restore_flags(flags);
 
+/* FIXME: ?? Are these increment & decrement operations guaranteed to be
+ *	     atomic? Could an IRQ not occur between the read & the write?
+ *	     Maybe yes on a x86 with GCC...??
+ */
 sizes[order].nfrees++;      /* Noncritical (monitoring) admin stuff */
 sizes[order].nbytesmalloced -= size;
 }
diff -u --recursive --new-file v1.0.6/linux/mm/memory.c linux/mm/memory.c
--- v1.0.6/linux/mm/memory.c	Wed Feb 23 10:36:51 1994
+++ linux/mm/memory.c	Wed Apr  6 11:47:17 1994
@@ -1,7 +1,7 @@
 /*
  *  linux/mm/memory.c
  *
- *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  */
 
 /*
@@ -28,6 +28,11 @@
  * 20.12.91  -  Ok, making the swap-device changeable like the root.
  */
 
+/*
+ * 05.04.94  -  Multi-page memory management added for v1.1.
+ * 		Idea by Alex Bligh (alex@cconcepts.co.uk)
+ */
+
 #include <asm/system.h>
 #include <linux/config.h>
 
@@ -48,17 +53,14 @@
 extern void sound_mem_init(void);
 extern void die_if_kernel(char *,struct pt_regs *,long);
 
-int nr_swap_pages = 0;
-int nr_free_pages = 0;
-unsigned long free_page_list = 0;
 /*
- * The secondary free_page_list is used for malloc() etc things that
- * may need pages during interrupts etc. Normal get_free_page() operations
- * don't touch it, so it stays as a kind of "panic-list", that can be
- * accessed when all other mm tricks have failed.
+ * The free_area_list arrays point to the queue heads of the free areas
+ * of different sizes
  */
-int nr_secondary_pages = 0;
-unsigned long secondary_page_list = 0;
+int nr_swap_pages = 0;
+int nr_free_pages = 0;
+struct mem_list free_area_list[NR_MEM_LISTS];
+unsigned char * free_area_map[NR_MEM_LISTS];
 
 #define copy_page(from,to) \
 __asm__("cld ; rep ; movsl": :"S" (from),"D" (to),"c" (1024):"cx","di","si")
@@ -978,8 +980,7 @@
 	int shared = 0;
 
 	printk("Mem-info:\n");
-	printk("Free pages:      %6dkB\n",nr_free_pages<<(PAGE_SHIFT-10));
-	printk("Secondary pages: %6dkB\n",nr_secondary_pages<<(PAGE_SHIFT-10));
+	show_free_areas();
 	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
 	i = high_memory >> PAGE_SHIFT;
 	while (i-- > 0) {
@@ -1052,7 +1053,7 @@
 	int codepages = 0;
 	int reservedpages = 0;
 	int datapages = 0;
-	unsigned long tmp;
+	unsigned long tmp, mask;
 	unsigned short * p;
 	extern int etext;
 
@@ -1067,22 +1068,34 @@
 	start_mem = (unsigned long) p;
 	while (p > mem_map)
 		*--p = MAP_PAGE_RESERVED;
+
+	/* set up the free-area data structures */
+	for (mask = PAGE_MASK, tmp = 0 ; tmp < NR_MEM_LISTS ; tmp++, mask <<= 1) {
+		unsigned long bitmap_size;
+		free_area_list[tmp].prev = free_area_list[tmp].next = &free_area_list[tmp];
+		end_mem = (end_mem + ~mask) & mask;
+		bitmap_size = end_mem >> (PAGE_SHIFT + tmp);
+		bitmap_size = (bitmap_size + 7) >> 3;
+		free_area_map[tmp] = (unsigned char *) start_mem;
+		memset((void *) start_mem, 0, bitmap_size);
+		start_mem += bitmap_size;
+	}
+
+	/* mark usable pages in the mem_map[] */
 	start_low_mem = PAGE_ALIGN(start_low_mem);
 	start_mem = PAGE_ALIGN(start_mem);
 	while (start_low_mem < 0xA0000) {
 		mem_map[MAP_NR(start_low_mem)] = 0;
 		start_low_mem += PAGE_SIZE;
 	}
-	while (start_mem < end_mem) {
+	while (start_mem < high_memory) {
 		mem_map[MAP_NR(start_mem)] = 0;
 		start_mem += PAGE_SIZE;
 	}
 #ifdef CONFIG_SOUND
 	sound_mem_init();
 #endif
-	free_page_list = 0;
-	nr_free_pages = 0;
-	for (tmp = 0 ; tmp < end_mem ; tmp += PAGE_SIZE) {
+	for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) {
 		if (mem_map[MAP_NR(tmp)]) {
 			if (tmp >= 0xA0000 && tmp < 0x100000)
 				reservedpages++;
@@ -1092,14 +1105,13 @@
 				datapages++;
 			continue;
 		}
-		*(unsigned long *) tmp = free_page_list;
-		free_page_list = tmp;
-		nr_free_pages++;
+		mem_map[MAP_NR(tmp)] = 1;
+		free_page(tmp);
 	}
 	tmp = nr_free_pages << PAGE_SHIFT;
 	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
 		tmp >> 10,
-		end_mem >> 10,
+		high_memory >> 10,
 		codepages << (PAGE_SHIFT-10),
 		reservedpages << (PAGE_SHIFT-10),
 		datapages << (PAGE_SHIFT-10));
diff -u --recursive --new-file v1.0.6/linux/mm/swap.c linux/mm/swap.c
--- v1.0.6/linux/mm/swap.c	Tue Apr  5 07:23:08 1994
+++ linux/mm/swap.c	Wed Apr  6 11:48:16 1994
@@ -1,7 +1,7 @@
 /*
  *  linux/mm/swap.c
  *
- *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  */
 
 /*
@@ -45,7 +45,6 @@
 	unsigned long max;
 } swap_info[MAX_SWAPFILES];
 
-extern unsigned long free_page_list;
 extern int shm_swap (int);
 
 /*
@@ -486,16 +485,18 @@
 	return 0;
 }
 
-/*
- * Note that this must be atomic, or bad things will happen when
- * pages are requested in interrupts (as malloc can do). Thus the
- * cli/sti's.
- */
-static inline void add_mem_queue(unsigned long addr, unsigned long * queue)
-{
-	addr &= PAGE_MASK;
-	*(unsigned long *) addr = *queue;
-	*queue = addr;
+static inline void add_mem_queue(struct mem_list * head, struct mem_list * entry)
+{
+	entry->prev = head;
+	entry->next = head->next;
+	entry->next->prev = entry;
+	head->next = entry;
+}
+
+static inline void remove_mem_queue(struct mem_list * head, struct mem_list * entry)
+{
+	entry->next->prev = entry->prev;
+	entry->prev->next = entry->next;
 }
 
 /*
@@ -509,27 +510,40 @@
  * With the above two rules, you get a straight-line execution path
  * for the normal case, giving better asm-code.
  */
-void free_page(unsigned long addr)
+
+/*
+ * Buddy system. Hairy. You really aren't expected to understand this
+ */
+static inline void free_pages_ok(unsigned long addr, unsigned long order)
+{
+	unsigned long index = addr >> (PAGE_SHIFT + 1 + order);
+	unsigned long mask = PAGE_MASK << order;
+
+	addr &= mask;
+	nr_free_pages += 1 << order;
+	while (order < NR_MEM_LISTS-1) {
+		if (!change_bit(index, free_area_map[order]))
+			break;
+		remove_mem_queue(free_area_list+order, (struct mem_list *) (addr ^ (1+~mask)));
+		order++;
+		index >>= 1;
+		mask <<= 1;
+		addr &= mask;
+	}
+	add_mem_queue(free_area_list+order, (struct mem_list *) addr);
+}
+
+void free_pages(unsigned long addr, unsigned long order)
 {
 	if (addr < high_memory) {
+		unsigned long flag;
 		unsigned short * map = mem_map + MAP_NR(addr);
-
 		if (*map) {
 			if (!(*map & MAP_PAGE_RESERVED)) {
-				unsigned long flag;
-
 				save_flags(flag);
 				cli();
-				if (!--*map) {
-					if (nr_secondary_pages < MAX_SECONDARY_PAGES) {
-						add_mem_queue(addr,&secondary_page_list);
-						nr_secondary_pages++;
-						restore_flags(flag);
-						return;
-					}
-					add_mem_queue(addr,&free_page_list);
-					nr_free_pages++;
-				}
+				if (!--*map)
+					free_pages_ok(addr, order);
 				restore_flags(flag);
 			}
 			return;
@@ -541,57 +555,43 @@
 }
 
 /*
- * This is one ugly macro, but it simplifies checking, and makes
- * this speed-critical place reasonably fast, especially as we have
- * to do things with the interrupt flag etc.
- *
- * Note that this #define is heavily optimized to give fast code
- * for the normal case - the if-statements are ordered so that gcc-2.2.2
- * will make *no* jumps for the normal code. Don't touch unless you
- * know what you are doing.
- */
-#define REMOVE_FROM_MEM_QUEUE(queue,nr) \
-	cli(); \
-	if ((result = queue) != 0) { \
-		if (!(result & ~PAGE_MASK) && result < high_memory) { \
-			queue = *(unsigned long *) result; \
-			if (!mem_map[MAP_NR(result)]) { \
-				mem_map[MAP_NR(result)] = 1; \
-				nr--; \
-last_free_pages[index = (index + 1) & (NR_LAST_FREE_PAGES - 1)] = result; \
-				restore_flags(flag); \
-				return result; \
-			} \
-			printk("Free page %08lx has mem_map = %d\n", \
-				result,mem_map[MAP_NR(result)]); \
-		} else \
-			printk("Result = 0x%08lx - memory map destroyed\n", result); \
-		queue = 0; \
-		nr = 0; \
-	} else if (nr) { \
-		printk(#nr " is %d, but " #queue " is empty\n",nr); \
-		nr = 0; \
-	} \
-	restore_flags(flag)
+ * Some ugly macros to speed up __get_free_pages()..
+ */
+#define RMQUEUE(order) \
+do { struct mem_list * queue = free_area_list+order; \
+     unsigned long new_order = order; \
+	do { struct mem_list *next = queue->next; \
+		if (queue != next) { \
+			queue->next = next->next; \
+			next->next->prev = queue; \
+			mark_used((unsigned long) next, new_order); \
+			nr_free_pages -= 1 << order; \
+			restore_flags(flags); \
+			EXPAND(next, order, new_order); \
+			return (unsigned long) next; \
+		} new_order++; queue++; \
+	} while (new_order < NR_MEM_LISTS); \
+} while (0)
+
+static inline int mark_used(unsigned long addr, unsigned long order)
+{
+	return change_bit(addr >> (PAGE_SHIFT+1+order), free_area_map[order]);
+}
+
+#define EXPAND(addr,low,high) \
+do { unsigned long size = PAGE_SIZE << high; \
+	while (high > low) { \
+		high--; size >>= 1; cli(); \
+		add_mem_queue(free_area_list+high, addr); \
+		mark_used((unsigned long) addr, high); \
+		restore_flags(flags); \
+		addr = (void *) (size + (unsigned long) addr); \
+	} mem_map[MAP_NR((unsigned long) addr)] = 1; \
+} while (0)
 
-/*
- * Get physical address of first (actually last :-) free page, and mark it
- * used. If no free pages left, return 0.
- *
- * Note that this is one of the most heavily called functions in the kernel,
- * so it's a bit timing-critical (especially as we have to disable interrupts
- * in it). See the above macro which does most of the work, and which is
- * optimized for a fast normal path of execution.
- */
-unsigned long __get_free_page(int priority)
-{
-	unsigned long result, flag;
-	static unsigned long index = 0;
-
-	/* this routine can be called at interrupt time via
-	   malloc.  We want to make sure that the critical
-	   sections of code have interrupts disabled. -RAB
-	   Is this code reentrant? */
+unsigned long __get_free_pages(int priority, unsigned long order)
+{
+	unsigned long flags;
 
 	if (intr_count && priority != GFP_ATOMIC) {
 		static int count = 0;
@@ -601,16 +601,44 @@
 			priority = GFP_ATOMIC;
 		}
 	}
-	save_flags(flag);
+	save_flags(flags);
 repeat:
-	REMOVE_FROM_MEM_QUEUE(free_page_list,nr_free_pages);
-	if (priority == GFP_BUFFER)
+	cli();
+	if ((priority==GFP_ATOMIC) || nr_free_pages > MAX_SECONDARY_PAGES) {
+		RMQUEUE(order);
+		restore_flags(flags);
 		return 0;
-	if (priority != GFP_ATOMIC)
-		if (try_to_free_page())
-			goto repeat;
-	REMOVE_FROM_MEM_QUEUE(secondary_page_list,nr_secondary_pages);
+	}
+	restore_flags(flags);
+        if (priority != GFP_BUFFER && try_to_free_page())
+		goto repeat;
 	return 0;
+}
+
+/*
+ * Show free area list (used inside shift_scroll-lock stuff)
+ * We also calculate the percentage fragmentation. We do this by counting the
+ * memory on each free list with the exception of the first item on the list.
+ */
+void show_free_areas(void)
+{
+ 	unsigned long order, flags;
+ 	unsigned long total = 0;
+
+	printk("Free pages:      %6dkB\n ( ",nr_free_pages<<(PAGE_SHIFT-10));
+	save_flags(flags);
+	cli();
+ 	for (order=0 ; order < NR_MEM_LISTS; order++) {
+		struct mem_list * tmp;
+		unsigned long nr = 0;
+		for (tmp = free_area_list[order].next ; tmp != free_area_list + order ; tmp = tmp->next) {
+			nr ++;
+		}
+		total += nr * (4 << order);
+		printk("%lu*%ukB ", nr, 4 << order);
+	}
+	restore_flags(flags);
+	printk("= %lukB)\n", total);
 }
 
 /*
diff -u --recursive --new-file v1.0.6/linux/net/inet/proc.c linux/net/inet/proc.c
--- v1.0.6/linux/net/inet/proc.c	Wed Mar  2 11:11:16 1994
+++ linux/net/inet/proc.c	Mon Apr  4 09:23:07 1994
@@ -95,7 +95,7 @@
 		if (timer_active)
 			add_timer(&sp->timer);
 		/* Is place in buffer too rare? then abort. */
-		if (pos > buffer+PAGE_SIZE-80) {
+		if (pos > buffer+PAGE_SIZE-90) {
 			printk("oops, too many %s sockets for netinfo.\n",
 					pro->name);
 			return(strlen(buffer));
diff -u --recursive --new-file v1.0.6/linux/net/inet/raw.c linux/net/inet/raw.c
--- v1.0.6/linux/net/inet/raw.c	Sun Feb  6 12:17:40 1994
+++ linux/net/inet/raw.c	Tue Apr  5 10:17:16 1994
@@ -244,14 +244,6 @@
   }
 
   skb->len = tmp + len;
-  
-  if(dev!=NULL && skb->len > 4095)
-  {
-  	kfree_skb(skb, FREE_WRITE);
-  	release_sock(sk);
-  	return(-EMSGSIZE);
-  }
-  
   sk->prot->queue_xmit(sk, dev, skb, 1);
   release_sock(sk);
   return(len);
diff -u --recursive --new-file v1.0.6/linux/net/inet/skbuff.c linux/net/inet/skbuff.c
--- v1.0.6/linux/net/inet/skbuff.c	Tue Apr  5 07:23:08 1994
+++ linux/net/inet/skbuff.c	Tue Apr  5 07:37:25 1994
@@ -458,7 +458,7 @@
 
 void kfree_skbmem(void *mem,unsigned size)
 {
-	struct sk_buff *x=mem;
+	struct sk_buff *x=(struct sk_buff *) mem;
 	IS_SKB(x);
 	if(x->magic_debug_cookie==SK_GOOD_SKB)
 	{
diff -u --recursive --new-file v1.0.6/linux/net/inet/skbuff.h linux/net/inet/skbuff.h
--- v1.0.6/linux/net/inet/skbuff.h	Tue Mar  1 13:11:55 1994
+++ linux/net/inet/skbuff.h	Tue Apr  5 07:30:48 1994
@@ -79,7 +79,7 @@
   unsigned char			data[0];
 };
 
-#define SK_WMEM_MAX	8192
+#define SK_WMEM_MAX	32767
 #define SK_RMEM_MAX	32767
 
 #define SK_FREED_SKB	0x0DE2C0DE
diff -u --recursive --new-file v1.0.6/linux/net/inet/sock.c linux/net/inet/sock.c
--- v1.0.6/linux/net/inet/sock.c	Tue Apr  5 07:23:08 1994
+++ linux/net/inet/sock.c	Tue Apr  5 07:37:25 1994
@@ -1655,7 +1655,7 @@
 {
   DPRINTF((DBG_INET, "sock_wfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size));
 
-  IS_SKB(mem);
+  IS_SKB((struct sk_buff *) mem);
   kfree_skbmem(mem, size);
   if (sk) {
 	sk->wmem_alloc -= size;
@@ -1675,7 +1675,7 @@
 sock_rfree(struct sock *sk, void *mem, unsigned long size)
 {
   DPRINTF((DBG_INET, "sock_rfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size));
-  IS_SKB(mem);
+  IS_SKB((struct sk_buff *) mem);
   kfree_skbmem(mem, size);
   if (sk) {
 	sk->rmem_alloc -= size;
diff -u --recursive --new-file v1.0.6/linux/net/inet/tcp.c linux/net/inet/tcp.c
--- v1.0.6/linux/net/inet/tcp.c	Fri Mar 18 10:21:35 1994
+++ linux/net/inet/tcp.c	Tue Apr  5 09:52:28 1994
@@ -152,22 +152,6 @@
   return skb_dequeue(&sk->rqueue);
 }
 
-/*
- *	Difference between two values in tcp ack terms.
- */
-
-static long
-diff(unsigned long seq1, unsigned long seq2)
-{
-  long d;
-
-  d = seq1 - seq2;
-  if (d > 0) return(d);
-
-  /* I hope this returns what I want. */
-  return(~d+1);
-}
-
 /* This routine picks a TCP windows for a socket based on
    the following constraints
    
diff -u --recursive --new-file v1.0.6/linux/net/inet/udp.c linux/net/inet/udp.c
--- v1.0.6/linux/net/inet/udp.c	Tue Jan 25 08:51:48 1994
+++ linux/net/inet/udp.c	Tue Apr  5 10:16:24 1994
@@ -263,21 +263,6 @@
 
   skb->len = tmp + sizeof(struct udphdr) + len;	/* len + UDP + IP + MAC */
   skb->dev = dev;
-#ifdef OLD
-  /*
-   * This code used to hack in some form of fragmentation.
-   * I removed that, since it didn't work anyway, and it made the
-   * code a bad thing to read and understand. -FvK
-   */
-  if (len > dev->mtu) {
-#else
-  if (skb->len > 4095)
-  {
-#endif    
-	printk("UDP: send: length %d > mtu %d (ignored)\n", len, dev->mtu);
-	sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
-	return(-EMSGSIZE);
-  }
 
   /* Fill in the UDP header. */
   uh = (struct udphdr *) buff;
