diff -u --recursive --new-file v1.1.46/linux/Makefile linux/Makefile
--- v1.1.46/linux/Makefile	Sun Aug 21 17:48:24 1994
+++ linux/Makefile	Sun Aug 21 17:49:23 1994
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 46
+SUBLEVEL = 47
 
 ARCH = i386
 
diff -u --recursive --new-file v1.1.46/linux/drivers/block/blk.h linux/drivers/block/blk.h
--- v1.1.46/linux/drivers/block/blk.h	Tue Aug  9 17:20:30 1994
+++ linux/drivers/block/blk.h	Sun Aug 21 15:57:22 1994
@@ -223,10 +223,6 @@
 #define DEVICE_ON(device)
 #define DEVICE_OFF(device)
 
-#else
-
-#error "unknown blk device"
-
 #endif
 
 #if (MAJOR_NR != SCSI_TAPE_MAJOR)
diff -u --recursive --new-file v1.1.46/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v1.1.46/linux/drivers/block/floppy.c	Fri Aug 19 14:04:01 1994
+++ linux/drivers/block/floppy.c	Sun Aug 21 15:35:55 1994
@@ -231,7 +231,7 @@
 {{3,  250, 16, 16, 3000, 100, 300,  0, 2, 5,  83, 3*HZ, 20, {3,1,2,0,2}, 0,
       0, { 4,22,21,30, 3, 0, 0, 0}, 150, 4 }, "720k" }, /*3 1/2 DD*/
 
-{{4,  500, 16, 16, 3000,  40, 300, 10, 2, 5,  83, 3*HZ, 20, {3,1,2,0,2}, 0,
+{{4,  500, 16, 16, 4000,  40, 300, 10, 2, 5,  83, 3*HZ, 20, {3,1,2,0,2}, 0,
       0, { 7, 4,25,22,31,21,29,11}, 150, 7 }, "1.44M" }, /*3 1/2 HD*/
 
 {{5, 1000, 15,  8, 3000,  40, 300, 10, 2, 5,  83, 3*HZ, 40, {3,1,2,0,2}, 0,
diff -u --recursive --new-file v1.1.46/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v1.1.46/linux/drivers/block/hd.c	Sun Aug 21 17:48:25 1994
+++ linux/drivers/block/hd.c	Sun Aug 21 14:40:28 1994
@@ -866,6 +866,7 @@
 			if (err)
 				return err;
 			memcpy_tofs((char *)arg, (char *) hd_ident_info[dev], sizeof(struct hd_driveid));
+			return 0;
 
 		RO_IOCTLS(inode->i_rdev,arg);
 		default:
diff -u --recursive --new-file v1.1.46/linux/drivers/char/console.c linux/drivers/char/console.c
--- v1.1.46/linux/drivers/char/console.c	Mon Aug 15 11:47:05 1994
+++ linux/drivers/char/console.c	Sun Aug 21 15:43:53 1994
@@ -1457,13 +1457,13 @@
 	}
 }
 
-void * memsetw(void * s,unsigned short c,int count)
+void * memsetw(void * s, unsigned short c, unsigned int count)
 {
 __asm__("cld\n\t"
 	"rep\n\t"
 	"stosw"
 	: /* no output */
-	:"a" (c),"D" (s),"c" (count)
+	:"a" (c),"D" (s),"c" (count/2)
 	:"cx","di");
 return s;
 }
diff -u --recursive --new-file v1.1.46/linux/drivers/char/kbd_kern.h linux/drivers/char/kbd_kern.h
--- v1.1.46/linux/drivers/char/kbd_kern.h	Sun Aug 21 17:48:25 1994
+++ linux/drivers/char/kbd_kern.h	Mon Aug 22 10:29:24 1994
@@ -16,13 +16,17 @@
  * Note: lockstate is used as index in the array key_map.
  */
 struct kbd_struct {
-	unsigned char ledstate;		/* 3 bits */
+        unsigned char ledstate;		/* 3 bits */
 	unsigned char default_ledstate;
-	unsigned char lockstate;	/* 3 bits */ 
 #define VC_SCROLLOCK	0	/* scroll-lock mode */
 #define VC_NUMLOCK	1	/* numeric lock mode */
 #define VC_CAPSLOCK	2	/* capslock mode */
 
+	unsigned char lockstate;	/* 4 bits - must be in 0..15 */
+#define VC_SHIFTLOCK	KG_SHIFT	/* shift lock mode */
+#define VC_ALTGRLOCK	KG_ALTGR	/* altgr lock mode */
+#define VC_CTRLLOCK	KG_CTRL 	/* control lock mode */
+#define VC_ALTLOCK	KG_ALT  	/* alt lock mode */
 
 	unsigned char modeflags;
 #define VC_APPLIC	0	/* application key mode */
diff -u --recursive --new-file v1.1.46/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v1.1.46/linux/drivers/char/keyboard.c	Sun Aug 21 17:48:25 1994
+++ linux/drivers/char/keyboard.c	Mon Aug 22 10:29:24 1994
@@ -344,15 +344,15 @@
 		u_char type;
 
 		/* the XOR below used to be an OR */
-		int shift_final = shift_state ^ vc_kbd_lock(kbd,VC_CAPSLOCK);
+		int shift_final = shift_state ^ kbd->lockstate;
 
 		key_code = key_map[shift_final][scancode];
 		type = KTYP(key_code);
 
 		if (type == KT_LETTER) {
 		    type = KT_LATIN;
-		    if (vc_kbd_lock(kbd,VC_CAPSLOCK))
-			key_code = key_map[shift_final][scancode];
+		    if (vc_kbd_led(kbd,VC_CAPSLOCK))
+			key_code = key_map[shift_final ^ (1<<KG_SHIFT)][scancode];
 		}
 		(*key_handler[type])(key_code & 0xff, up_flag);
 	}
@@ -404,7 +404,6 @@
 	if (rep)
 		return;
 	chg_vc_kbd_led(kbd,VC_CAPSLOCK);
-	chg_vc_kbd_lock(kbd,VC_CAPSLOCK);
 }
 
 static void caps_on(void)
@@ -412,7 +411,6 @@
 	if (rep)
 		return;
 	set_vc_kbd_led(kbd,VC_CAPSLOCK);
-	set_vc_kbd_lock(kbd,VC_CAPSLOCK);
 }
 
 static void show_ptregs(void)
@@ -463,10 +461,8 @@
 		applkey('P', 1);
 		return;
 	}
-	if (!rep) {	/* no autorepeat for numlock, ChN */
+	if (!rep)	/* no autorepeat for numlock, ChN */
 		chg_vc_kbd_led(kbd,VC_NUMLOCK);
-		chg_vc_kbd_lock(kbd,VC_NUMLOCK);
-	}
 }
 
 static void lastcons(void)
@@ -647,7 +643,8 @@
 		applkey(app_map[value], 1);
 		return;
 	}
-	if (!vc_kbd_lock(kbd,VC_NUMLOCK))
+
+	if (!vc_kbd_led(kbd,VC_NUMLOCK))
 		switch (value) {
 			case KVAL(K_PCOMMA):
 			case KVAL(K_PDOT):
@@ -709,10 +706,8 @@
 	/* kludge... */
 	if (value == KVAL(K_CAPSSHIFT)) {
 		value = KVAL(K_SHIFT);
-		if (!up_flag) {
+		if (!up_flag)
 			clr_vc_kbd_led(kbd, VC_CAPSLOCK);
-			clr_vc_kbd_lock(kbd, VC_CAPSLOCK);
-		}
 	}
 
 	if (up_flag) {
diff -u --recursive --new-file v1.1.46/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- v1.1.46/linux/drivers/char/n_tty.c	Thu Aug 11 20:43:04 1994
+++ linux/drivers/char/n_tty.c	Mon Aug 22 08:20:24 1994
@@ -931,9 +931,9 @@
 				if (opost(c, tty) < 0)
 					break;
 				b++; nr--;
-				if (tty->driver.flush_chars)
-					tty->driver.flush_chars(tty);
 			}
+			if (tty->driver.flush_chars)
+				tty->driver.flush_chars(tty);
 		} else {
 			c = tty->driver.write(tty, 1, b, nr);
 			b += c;
diff -u --recursive --new-file v1.1.46/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v1.1.46/linux/drivers/char/tty_io.c	Sun Aug 21 17:48:25 1994
+++ linux/drivers/char/tty_io.c	Mon Aug 22 08:20:24 1994
@@ -1535,8 +1535,10 @@
 		return 0;
 
 	error = register_chrdev(driver->major, driver->name, &tty_fops);
-	if (error)
+	if (error < 0)
 		return error;
+	else if(driver->major == 0)
+		driver->major = error;
 
 	if (!driver->put_char)
 		driver->put_char = tty_default_put_char;
@@ -1545,7 +1547,7 @@
 	driver->next = tty_drivers;
 	tty_drivers->prev = driver;
 	tty_drivers = driver;
-	return 0;
+	return error;
 }
 
 /*
@@ -1589,7 +1591,7 @@
 		panic("size of tty structure > PAGE_SIZE!");
 	if (register_chrdev(TTY_MAJOR,"tty",&tty_fops))
 		panic("unable to get major %d for tty device", TTY_MAJOR);
-	if (register_chrdev(TTYAUX_MAJOR,"tty",&tty_fops))
+	if (register_chrdev(TTYAUX_MAJOR,"cua",&tty_fops))
 		panic("unable to get major %d for tty device", TTYAUX_MAJOR);
 
 	kmem_start = kbd_init(kmem_start);
diff -u --recursive --new-file v1.1.46/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c
--- v1.1.46/linux/drivers/scsi/NCR5380.c	Sun Aug 21 17:48:26 1994
+++ linux/drivers/scsi/NCR5380.c	Sun Aug 21 15:52:02 1994
@@ -193,6 +193,11 @@
  * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential
  * 	transceivers. 
  *
+ * LIMIT_TRANSFERSIZE - if defined, limit the pseudo-dma transfers to 512
+ *	bytes at a time.  Since interrupts are disabled by default during
+ *	these transfers, we might need this to give reasonable interrupt
+ *	service time if the transfer size gets too large.
+ *
  * LINKED - if defined, linked commands are supported.
  *
  * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases.
@@ -1980,10 +1985,16 @@
 		if (!cmd->device->borken &&
 		    (transfersize = NCR5380_dma_xfer_len(instance, cmd)) != 0) {
 #else
-		if (!cmd->device->borken && 
-		    (transfersize = cmd->transfersize) && 
-		    cmd->SCp.this_residual && !(cmd->SCp.this_residual % 
-		    transfersize)) {
+                transfersize = cmd->transfersize;
+
+#ifdef LIMIT_TRANSFERSIZE  /* If we have problems with interrupt service */
+                if( transfersize > 512 )
+                    transfersize = 512;
+#endif  /* LIMIT_TRANSFERSIZE */
+
+                if (!cmd->device->borken && transfersize && 
+                    cmd->SCp.this_residual && !(cmd->SCp.this_residual % 
+                    transfersize)) {
 #endif
 		    len = transfersize;
 		    if (NCR5380_transfer_dma(instance, &phase,
diff -u --recursive --new-file v1.1.46/linux/drivers/scsi/constants.h linux/drivers/scsi/constants.h
--- v1.1.46/linux/drivers/scsi/constants.h	Sun Aug  7 03:30:38 1994
+++ linux/drivers/scsi/constants.h	Sun Aug 21 15:52:01 1994
@@ -4,4 +4,5 @@
 extern int print_msg(unsigned char *);
 extern void print_sense(char *,  Scsi_Cmnd *);
 extern void print_status(int);
+extern void print_Scsi_Cmnd (Scsi_Cmnd *);
 #endif /* def _CONSTANTS_H */
diff -u --recursive --new-file v1.1.46/linux/drivers/scsi/pas16.c linux/drivers/scsi/pas16.c
--- v1.1.46/linux/drivers/scsi/pas16.c	Sun Aug 21 17:48:28 1994
+++ linux/drivers/scsi/pas16.c	Sun Aug 21 15:52:02 1994
@@ -1,5 +1,7 @@
 #define AUTOSENSE
 #define PSEUDO_DMA
+#define FOO
+#define UNSAFE  /* Not unsafe for PAS16 -- use it */
 
 /*
  * This driver adapted from Drew Eckhardt's Trantor T128 driver
@@ -40,6 +42,11 @@
  * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
  *      for commands that return with a CHECK CONDITION status. 
  *
+ * LIMIT_TRANSFERSIZE - if defined, limit the pseudo-dma transfers to 512
+ *      bytes at a time.  Since interrupts are disabled by default during
+ *      these transfers, we might need this to give reasonable interrupt
+ *      service time if the transfer size gets too large.
+ *
  * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
  * increase compared to polled I/O.
  *
@@ -47,11 +54,13 @@
  * 
  * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
  *
- *
- * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.  You
- *          only really want to use this if you're having a problem with
- *          dropped characters during high speed communications, and even
- *          then, you're going to be better off twiddling with transfersize.
+ * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.  This
+ *	    parameter comes from the NCR5380 code.  It is NOT unsafe with
+ *	    the PAS16 and you should use it.  If you don't you will have
+ *	    a problem with dropped characters during high speed
+ *	    communications during SCSI transfers.  If you really don't
+ *	    want to use UNSAFE you can try defining LIMIT_TRANSFERSIZE or
+ *	    twiddle with the transfer size in the high level code.
  *
  * USLEEP - enable support for devices that don't disconnect.  Untested.
  *
@@ -242,7 +251,7 @@
 int     pas16_hw_detect( unsigned short  board_num )
 {
     unsigned char	board_rev, tmp;
-    unsigned short	port = bases[ board_num ].io_port;
+    unsigned short	io_port = bases[ board_num ].io_port;
 
     /* See if we can find a PAS16 board at the address associated
      * with this logical board number.
@@ -251,26 +260,39 @@
     /* First, attempt to take a newer model board out of reset and
      * give it a base address.  This shouldn't affect older boards.
      */
-    enable_board( board_num, port );
+    enable_board( board_num, io_port );
 
     /* Now see if it looks like a PAS16 board */
-    board_rev = inb( port + PCB_CONFIG );
+    board_rev = inb( io_port + PCB_CONFIG );
 
     if( board_rev == 0xff )
 	return 0;
 
     tmp = board_rev ^ 0xe0;
 
-    outb( tmp, port + PCB_CONFIG );
-    tmp = inb( port + PCB_CONFIG );
-    outb( board_rev, port + PCB_CONFIG );
+    outb( tmp, io_port + PCB_CONFIG );
+    tmp = inb( io_port + PCB_CONFIG );
+    outb( board_rev, io_port + PCB_CONFIG );
 
     if( board_rev != tmp ) 	/* Not a PAS-16 */
 	return 0;
 
-    if( ( inb( port + OPERATION_MODE_1 ) & 0x03 ) != 0x03 ) 
+    if( ( inb( io_port + OPERATION_MODE_1 ) & 0x03 ) != 0x03 ) 
 	return 0;  	/* return if no SCSI interface found */
 
+    /* Mediavision has some new model boards that return ID bits
+     * that indicate a SCSI interface, but they're not (LMS).  We'll
+     * put in an additional test to try and weed them out.
+     */
+
+    outb( 0x01, io_port + WAIT_STATE ); 	/* 1 Wait state */
+    NCR5380_write( MODE_REG, 0x20 );		/* Is it really SCSI? */
+    if( NCR5380_read( MODE_REG ) != 0x20 )	/* Write to a reg.    */
+	return 0;				/* and try to read    */
+    NCR5380_write( MODE_REG, 0x00 );		/* it back.	      */
+    if( NCR5380_read( MODE_REG ) != 0x00 )
+	return 0;
+
     return 1;
 }
 
@@ -426,7 +448,15 @@
   int size = disk->capacity;
   ip[0] = 64;
   ip[1] = 32;
-  ip[2] = size >> 11;
+  ip[2] = size >> 11;		/* I think I have it as /(32*64) */
+  if( ip[2] > 1024 ) {		/* yes, >, not >= */
+        ip[0]=255;
+        ip[1]=63;
+        ip[2]=size/(63*255);
+        if( ip[2] > 1023 )	/* yes >1023... */
+                ip[2] = 1023;
+  }
+
   return 0;
 }
 
diff -u --recursive --new-file v1.1.46/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v1.1.46/linux/drivers/scsi/sr.c	Sun Aug 21 17:48:29 1994
+++ linux/drivers/scsi/sr.c	Sun Aug 21 15:52:02 1994
@@ -627,7 +627,20 @@
 	  printk("\n");
 	};
 #endif
-	
+
+/* Some dumb host adapters can speed transfers by knowing the
+ * minimum tranfersize in advance.
+ *
+ * We shouldn't disconnect in the middle of a sector, but the cdrom
+ * sector size can be larger than the size of a buffer and the
+ * transfer may be split to the size of a buffer.  So it's safe to
+ * assume that we can at least transfer the minimum of the buffer
+ * size (1024) and the sector size between each connect / disconnect.
+ */
+
+        SCpnt->transfersize = (scsi_CDs[dev].sector_size > 1024) ?
+                        1024 : scsi_CDs[dev].sector_size;
+
 	SCpnt->this_count = this_count;
 	scsi_do_cmd (SCpnt, (void *) cmd, buffer, 
 		     realcount * scsi_CDs[dev].sector_size, 
diff -u --recursive --new-file v1.1.46/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- v1.1.46/linux/fs/ext2/balloc.c	Sun Aug 21 17:48:35 1994
+++ linux/fs/ext2/balloc.c	Sun Aug 21 17:36:17 1994
@@ -316,10 +316,7 @@
 			else
 				lmap |= 0xffffffff << (31 - (j & 31));
 			if (lmap != 0xffffffffl) {
-				__asm__ ("bsfl %1,%0"
-					 : "=r" (k)
-					 : "r" (~lmap));
-				k++;
+				k = ffz(lmap) + 1;
 				if ((j + k) < EXT2_BLOCKS_PER_GROUP(sb)) {
 					j += k;
 					goto got_block;
diff -u --recursive --new-file v1.1.46/linux/include/asm-i386/bitops.h linux/include/asm-i386/bitops.h
--- v1.1.46/linux/include/asm-i386/bitops.h	Sun Aug 21 17:48:37 1994
+++ linux/include/asm-i386/bitops.h	Sun Aug 21 17:42:15 1994
@@ -121,4 +121,16 @@
 	return (offset + set + res);
 }
 
+/*
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
+ */
+extern inline unsigned long ffz(unsigned long word)
+{
+	__asm__("bsfl %1,%0"
+		:"=r" (word)
+		:"r" (~word));
+	return word;
+}
+
 #endif /* _I386_BITOPS_H */
diff -u --recursive --new-file v1.1.46/linux/include/linux/ncp.h linux/include/linux/ncp.h
--- v1.1.46/linux/include/linux/ncp.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/ncp.h	Sun Aug 21 17:30:01 1994
@@ -0,0 +1,106 @@
+#ifndef _LINUX_NCP_H_
+#define _LINUX_NCP_H_
+
+#define NCP_OPEN	0x1111
+#define NCP_CLOSE	0x5555
+#define NCP_REQUEST	0x2222
+#define NCP_REPLY	0x3333
+
+struct ncp_request
+{
+	unsigned short	p_type			__attribute__ ((packed));
+	unsigned char	seq			__attribute__ ((packed));
+	unsigned char	c_low			__attribute__ ((packed));
+	unsigned char	task			__attribute__ ((packed));
+	unsigned char	c_high			__attribute__ ((packed));
+	unsigned char	func			__attribute__ ((packed));
+};
+
+struct ncp_request_sf
+{
+	unsigned short	p_type			__attribute__ ((packed));
+	unsigned char	seq			__attribute__ ((packed));
+	unsigned char	c_low			__attribute__ ((packed));
+	unsigned char	task			__attribute__ ((packed));
+	unsigned char	c_high			__attribute__ ((packed));
+	unsigned char	func			__attribute__ ((packed));
+	unsigned short	s_len			__attribute__ ((packed));
+	unsigned char	s_func			__attribute__ ((packed));
+};
+
+struct ncp_reply
+{
+	unsigned short	p_type			__attribute__ ((packed));
+	unsigned char	seq			__attribute__ ((packed));
+	unsigned char	c_low			__attribute__ ((packed));
+	unsigned char	task			__attribute__ ((packed));
+	unsigned char	c_high			__attribute__ ((packed));
+	unsigned char	f_stat			__attribute__ ((packed));
+	unsigned char	c_stat			__attribute__ ((packed));
+};
+
+#define OTYPE_USER		0x0001
+#define OTYPE_GROUP		0x0002
+#define OTYPE_PQUEUE		0x0003
+#define OTYPE_FSERVER		0x0004
+#define OTYPE_JSERVER		0x0005
+#define OTYPE_PSERVER		0x0007
+#define OTYPE_UNKNOWN_1		0x002E
+#define OTYPE_ADV_PSERVER	0x0047
+#define OTYPE_AFSERVER		0x0107
+#define OTYPE_UNKNOWN_2		0x0143
+#define OTYPE_UNKNOWN_3		0x01F5
+#define OTYPE_UNKNOWN_4		0x023F
+
+#define LIMIT_OBJNAME	47
+
+struct bind_obj
+{
+	unsigned long	id			__attribute__ ((packed));
+	unsigned short	type			__attribute__ ((packed));
+	char		name[LIMIT_OBJNAME+1]	__attribute__ ((packed));
+};
+
+struct	get_bind_obj
+{
+	unsigned short	type			__attribute__ ((packed));
+	unsigned char	n_len			__attribute__ ((packed));
+	char		name[0]			__attribute__ ((packed));
+};
+
+struct	scan_bind_obj
+{
+	unsigned long	id			__attribute__ ((packed));
+	unsigned short	type			__attribute__ ((packed));
+	unsigned char	n_len			__attribute__ ((packed));
+	char		name[0]			__attribute__ ((packed));
+};
+
+struct	login_req
+{
+	unsigned char	password[8]		__attribute__ ((packed));
+	unsigned short	type			__attribute__ ((packed));
+	unsigned char	n_len			__attribute__ ((packed));
+	char		name[0]			__attribute__ ((packed));
+};
+
+struct	ncp_time
+{
+	unsigned char	year			__attribute__ ((packed));
+	unsigned char	month			__attribute__ ((packed));
+	unsigned char	day			__attribute__ ((packed));
+	unsigned char	hours			__attribute__ ((packed));
+	unsigned char	mins			__attribute__ ((packed));
+	unsigned char	secs			__attribute__ ((packed));
+	unsigned char	c_secs			__attribute__ ((packed));
+};
+
+struct login_info
+{
+	unsigned long	id			__attribute__ ((packed));
+	unsigned short	un1			__attribute__ ((packed));
+	char		name[LIMIT_OBJNAME+1]	__attribute__ ((packed));
+	struct ncp_time time			__attribute__ ((packed));
+};
+#endif
+
diff -u --recursive --new-file v1.1.46/linux/include/linux/socket.h linux/include/linux/socket.h
--- v1.1.46/linux/include/linux/socket.h	Thu Aug 11 20:43:33 1994
+++ linux/include/linux/socket.h	Sun Aug 21 17:30:01 1994
@@ -20,6 +20,7 @@
 #define SOCK_RAW	3		/* raw socket			*/
 #define SOCK_RDM	4		/* reliably-delivered message	*/
 #define SOCK_SEQPACKET	5		/* sequential packet socket	*/
+#define SOCK_NCP	6		/* Novell NCP socket		*/
 #define SOCK_PACKET	10		/* linux specific way of	*/
 					/* getting packets at the dev	*/
 					/* level.  For writing rarp and	*/
diff -u --recursive --new-file v1.1.46/linux/net/inet/datagram.c linux/net/inet/datagram.c
--- v1.1.46/linux/net/inet/datagram.c	Thu Aug 11 20:43:37 1994
+++ linux/net/inet/datagram.c	Sun Aug 21 17:30:01 1994
@@ -177,7 +177,8 @@
 	switch(sel_type)
 	{
 		case SEL_IN:
-			if (sk->type==SOCK_SEQPACKET && sk->state==TCP_CLOSE)
+			if ((sk->type==SOCK_SEQPACKET || sk->type==SOCK_NCP)
+				&& sk->state==TCP_CLOSE)
 			{
 				/* Connection closed: Wake up */
 				return(1);
diff -u --recursive --new-file v1.1.46/linux/net/inet/ipx.c linux/net/inet/ipx.c
--- v1.1.46/linux/net/inet/ipx.c	Thu Aug 11 20:43:39 1994
+++ linux/net/inet/ipx.c	Sun Aug 21 17:30:02 1994
@@ -56,8 +56,16 @@
 #include <linux/termios.h>	/* For TIOCOUTQ/INQ */
 #include <linux/interrupt.h>
 #include "p8022.h"
+#include "ncp.h"
 
 #ifdef CONFIG_IPX
+
+static void ipx_delete_timer (ipx_socket *sk);
+static int ipx_do_sendto(ipx_socket *sk, ipx_address *ipx,
+			 void *ubuf, int len, int flag, unsigned char type);
+static void ipx_add_timer (ipx_socket *sk, int len);
+static void ipx_reset_timer (ipx_socket *sk, int len);
+
 /***********************************************************************************************************************\
 *															*
 *						Handlers for the socket list.						*
@@ -75,7 +83,9 @@
 static void ipx_remove_socket(ipx_socket *sk)
 {
 	ipx_socket *s;
+	unsigned long flags;
 	
+	save_flags(flags);
 	cli();
 	s=ipx_socket_list;
 	if(s==sk)
@@ -89,20 +99,23 @@
 		if(s->next==sk)
 		{
 			s->next=sk->next;
-			sti();
+			restore_flags(flags);
 			return;
 		}
 		s=s->next;
 	}
-	sti();
+	restore_flags(flags);
 }
 
 static void ipx_insert_socket(ipx_socket *sk)
 {
+	unsigned long flags;
+	
+	save_flags(flags);
 	cli();
 	sk->next=ipx_socket_list;
 	ipx_socket_list=sk;
-	sti();
+	restore_flags(flags);
 }
 
 static ipx_socket *ipx_find_socket(int port)
@@ -133,9 +146,10 @@
 	ipx_remove_socket(sk);
 	
 	while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
-	{
 		kfree_skb(skb,FREE_READ);
-	}
+	
+	while((skb=skb_dequeue(&sk->write_queue))!=NULL)
+		kfree_skb(skb,FREE_WRITE);
 	
 	kfree_s(sk,sizeof(*sk));
 }
@@ -151,20 +165,24 @@
 
 	/* Theory.. Keep printing in the same place until we pass offset */
 	
-	len += sprintf (buffer,"Type local_address             rem_address              tx_queue rx_queue st uid\n");
+	len += sprintf (buffer,"   local_address              rem_address                tx_queue rx_queue st uid\n");
 	for (s = ipx_socket_list; s != NULL; s = s->next)
 	{
-		len += sprintf (buffer+len,"%02X   ", s->ipx_type);
-		len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%02X ", htonl(s->ipx_source_addr.net),
+		len += sprintf (buffer+len,"%02X ", s->ipx_type);
+		len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%04X ", htonl(s->ipx_source_addr.net),
 			s->ipx_source_addr.node[0], s->ipx_source_addr.node[1], s->ipx_source_addr.node[2],
 			s->ipx_source_addr.node[3], s->ipx_source_addr.node[4], s->ipx_source_addr.node[5],
 			htons(s->ipx_source_addr.sock));
-		len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%02X ", htonl(s->ipx_dest_addr.net),
+		len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%04X ", htonl(s->ipx_dest_addr.net),
 			s->ipx_dest_addr.node[0], s->ipx_dest_addr.node[1], s->ipx_dest_addr.node[2],
 			s->ipx_dest_addr.node[3], s->ipx_dest_addr.node[4], s->ipx_dest_addr.node[5],
 			htons(s->ipx_dest_addr.sock));
 		len += sprintf (buffer+len,"%08lX:%08lX ", s->wmem_alloc, s->rmem_alloc);
-		len += sprintf (buffer+len,"%02X %d\n", s->state, SOCK_INODE(s->socket)->i_uid);
+		len += sprintf (buffer+len,"%02X ", s->state);
+		if (s->socket)
+			len += sprintf (buffer+len,"%d\n", SOCK_INODE(s->socket)->i_uid);
+		else
+			len += sprintf (buffer+len,"%d\n", SOCK_INODE(s->ncp.ncp->socket)->i_uid);
 		
 		/* Are we still dumping unwanted data then discard the record */
 		pos=begin+len;
@@ -566,20 +584,56 @@
 		wake_up_interruptible(sk->sleep);
 }
 
-static int ipx_create(struct socket *sock, int protocol)
+static void watch_callback(struct sock *sk, int len)
 {
-	ipx_socket *sk;
-	sk=(ipx_socket *)kmalloc(sizeof(*sk),GFP_KERNEL);
-	if(sk==NULL)
-		return(-ENOMEM);
-	switch(sock->type)
+	ipx_packet	*ipx;
+	struct sk_buff *skb;
+	char *data;
+
+	skb=skb_dequeue(&sk->receive_queue);
+	if(skb==NULL)
+		return; 
+
+	ipx = (ipx_packet *)(skb->h.raw);
+	data = (char *)(ipx+1);
+
+        if (*(data+1) == '?')
+		ipx_do_sendto(sk,&(ipx->ipx_source),"\0Y",2,0,sk->ipx_type);
+
+	kfree_skb(skb, FREE_READ);
+}
+
+static void mail_callback(struct sock *sk, int len)
+{
+	ipx_packet	*ipx;
+	struct sk_buff *skb;
+	char *data;
+
+	skb=skb_dequeue(&sk->receive_queue);
+	if(skb==NULL)
+		return; 
+
+	ipx = (ipx_packet *)(skb->h.raw);
+	data = (char *)(ipx+1);
+        if (*(data+1) == '!')
 	{
-		case SOCK_DGRAM:
-			break;
-		default:
-			kfree_s((void *)sk,sizeof(*sk));
-			return(-ESOCKTNOSUPPORT);
+	 	struct ncp_request_sf req;
+
+		req.func=0x15;
+		req.s_func=0x01;
+		req.s_len=htons(1);
+
+		ipx_do_sendto(sk->ncp.ncp, &(sk->ncp.ncp->ipx_dest_addr),
+				&req, sizeof(req), 0,sk->ncp.ncp->ipx_type);
 	}
+
+	kfree_skb(skb, FREE_READ);
+
+}
+
+static void ipx_do_create(struct socket *sock, ipx_socket *sk)
+{
+
 	sk->dead=0;
 	sk->next=NULL;
 	sk->broadcast=0;
@@ -598,7 +652,6 @@
 	skb_queue_head_init(&sk->back_log);
 	sk->state=TCP_CLOSE;
 	sk->socket=sock;
-	sk->type=sock->type;
 	sk->ipx_type=0;		/* General user level IPX */
 	sk->debug=0;
 	
@@ -610,14 +663,76 @@
 	{
 		sock->data=(void *)sk;
 		sk->sleep=sock->wait;
+		sk->type=sock->type;
 	}
+	else
+		sk->type=SOCK_DGRAM;
 	
+	sk->priority=SOPRI_NORMAL;
 	sk->state_change=def_callback1;
 	sk->data_ready=def_callback2;
 	sk->write_space=def_callback1;
 	sk->error_report=def_callback1;
 
 	sk->zapped=1;
+
+	return;
+}
+
+static int ncp_create(struct socket *sock, int protocol)
+{
+	ipx_socket *sk;
+	ipx_socket *skw;
+	ipx_socket *skm;
+
+	if ((sk=(ipx_socket *)kmalloc(sizeof(*sk),GFP_KERNEL))==NULL)
+		return(-ENOMEM);
+
+	if ((skw=(ipx_socket *)kmalloc(sizeof(*skw),GFP_KERNEL))==NULL)
+	{
+		kfree_s((void *)sk, sizeof(*sk));
+		return(-ENOMEM);
+	}
+
+	if ((skm=(ipx_socket *)kmalloc(sizeof(*skm),GFP_KERNEL))==NULL)
+	{
+		kfree_s((void *)skw, sizeof(*skw));
+		kfree_s((void *)sk, sizeof(*sk));
+		return(-ENOMEM);
+	}
+
+	ipx_do_create(sock, sk);
+	sk->ncp.ncp=NULL;
+	sk->ncp.watchdog=skw;
+	sk->ncp.mail=skm;
+	ipx_do_create(NULL, skw);
+	skw->ncp.ncp=sk;
+	skw->data_ready=watch_callback;
+	ipx_do_create(NULL, skm);
+	skm->ncp.ncp=sk;
+	skm->data_ready=mail_callback;
+	
+	return(0);
+}
+
+static int ipx_create(struct socket *sock, int protocol)
+{
+	ipx_socket *sk;
+
+	switch(sock->type)
+	{
+		case SOCK_DGRAM:
+			break;
+ 		case SOCK_NCP:
+			return(ncp_create(sock, protocol));
+		default:
+			return(-ESOCKTNOSUPPORT);
+	}
+	if ((sk=(ipx_socket *)kmalloc(sizeof(*sk),GFP_KERNEL))==NULL)
+		return(-ENOMEM);
+
+	ipx_do_create(sock, sk);
+
 	return(0);
 }
 
@@ -633,47 +748,79 @@
 		return(0);
 	if(!sk->dead)
 		sk->state_change(sk);
-	sk->dead=1;
+
 	sock->data=NULL;
-	ipx_destroy_socket(sk);
+
+	if (sk->type == SOCK_NCP)
+	{
+		sk->ncp.watchdog->dead=1;
+		ipx_destroy_socket(sk->ncp.watchdog);
+		sk->ncp.mail->dead=1;
+		ipx_destroy_socket(sk->ncp.mail);
+
+		if ((sk->state == TCP_ESTABLISHED) || (sk->state == TCP_SYN_SENT))
+		{
+	 		struct ncp_request req;
+		
+			sk->state=TCP_CLOSE_WAIT;
+	
+			ipx_do_sendto(sk, &(sk->ipx_dest_addr), &req,
+					 sizeof(req), 0, sk->ipx_type);
+		}
+		else
+		{
+			sk->dead=1;
+			if (sk->state != TCP_CLOSE)
+				ipx_delete_timer(sk);
+			ipx_destroy_socket(sk);
+		}
+	}
+	else
+	{
+		sk->dead=1;
+		ipx_destroy_socket(sk);
+	}
 	return(0);
 }
 		
 static unsigned short first_free_socketnum(void)
 {
-	static unsigned short	socketNum = 0x4000;
+	static unsigned short	socketNum = 0x3fff;
 
-	while (ipx_find_socket(htons(socketNum)) != NULL)
-		if (socketNum > 0x7ffc) socketNum = 0x4000;
+	while (ipx_find_socket(htons(++socketNum)) != NULL)
+		if (socketNum > 0x7ffc) socketNum = 0x3fff;
 
-	return	htons(socketNum++);
+	return	htons(socketNum);
 }
 	
 static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
 {
-	ipx_socket *sk;
+	ipx_socket *sk=(ipx_socket *)sock->data;
 	struct ipx_route *rt;
 	unsigned char	*nodestart;
 	struct sockaddr_ipx *addr=(struct sockaddr_ipx *)uaddr;
 	
-	sk=(ipx_socket *)sock->data;
-	
 	if(sk->zapped==0)
 		return(-EIO);
 		
 	if(addr_len!=sizeof(struct sockaddr_ipx))
 		return -EINVAL;
 	
+
 	if (addr->sipx_port == 0) 
 	{
 		addr->sipx_port = first_free_socketnum();
+		if (sk->type == SOCK_NCP)
+			while ((ipx_find_socket(htons(ntohs(addr->sipx_port)+1)))
+				|| (ipx_find_socket(htons(ntohs(addr->sipx_port)+2))))
+				addr->sipx_port = first_free_socketnum();
 		if (addr->sipx_port == 0)
 			return -EINVAL;
 	}
 		
 	if(ntohs(addr->sipx_port)<0x4000 && !suser())
 		return(-EPERM);	/* protect IPX system stuff like routing/sap */
-	
+
 	/* Source addresses are easy. It must be our network:node pair for
 	   an interface routed to IPX with the ipx routing ioctl() */
 
@@ -685,6 +832,19 @@
 		return -EADDRINUSE;	   
 	}
 
+	if (sk->type == SOCK_NCP)
+	{
+		if ((ipx_find_socket(htons(ntohs(addr->sipx_port)+1)))
+			|| (ipx_find_socket(htons(ntohs(addr->sipx_port)+2))))
+		{
+			if(sk->debug)
+				printk("IPX: bind failed because port %X in use.\n",
+				(int)addr->sipx_port);
+			return -EADDRINUSE;	   
+		}
+		addr->sipx_type=IPX_TYPE_NCP;
+	}
+
 	sk->ipx_source_addr.sock=addr->sipx_port;
 
 	if (addr->sipx_network == 0L) 
@@ -705,6 +865,7 @@
 	}
 
 	sk->ipx_source_addr.net=rt->net;
+	sk->ipx_type=addr->sipx_type;
 
 	/* IPX addresses zero pad physical addresses less than 6 */
 	memset(sk->ipx_source_addr.node,'\0',6);
@@ -713,41 +874,102 @@
 
 	ipx_insert_socket(sk);
 	sk->zapped=0;
+
+	if (sk->type == SOCK_NCP)
+	{
+		sk->ncp.watchdog->ipx_source_addr.net=rt->net;
+		sk->ncp.watchdog->ipx_source_addr.sock=htons(ntohs(addr->sipx_port)+1);
+
+		memset(sk->ncp.watchdog->ipx_source_addr.node,'\0',6);
+		nodestart = sk->ncp.watchdog->ipx_source_addr.node + (6 - rt->dev->addr_len);
+		memcpy(nodestart,rt->dev->dev_addr,rt->dev->addr_len);
+	
+		ipx_insert_socket(sk->ncp.watchdog);
+		sk->ncp.watchdog->zapped=0;
+
+		sk->ncp.mail->ipx_source_addr.net=rt->net;
+		sk->ncp.mail->ipx_source_addr.sock=htons(ntohs(addr->sipx_port)+2);
+
+		memset(sk->ncp.mail->ipx_source_addr.node,'\0',6);
+		nodestart = sk->ncp.mail->ipx_source_addr.node + (6 - rt->dev->addr_len);
+		memcpy(nodestart,rt->dev->dev_addr,rt->dev->addr_len);
+
+		ipx_insert_socket(sk->ncp.mail);
+		sk->ncp.mail->zapped=0;
+
+		sk->mtu=rt->dev->mtu;
+	}
+
 	if(sk->debug)
 		printk("IPX: socket is bound.\n");
 	return(0);
 }
 
+static int ncp_connect(struct socket *sock, ipx_socket *sk)
+{
+	struct ncp_request req;
+	int err;
+
+	sk->ncp.conn=0xffff;
+	sk->ncp.seq=0;
+	
+	sock->state = SS_CONNECTING;
+	sk->state = TCP_SYN_SENT;
+	sk->rto = 0;
+
+	ipx_do_sendto(sk, &(sk->ipx_dest_addr), &req, sizeof(req), 0, sk->ipx_type);
+
+	while(sk->state != TCP_ESTABLISHED)
+	{
+		if (sk->err)
+		{
+			err=sk->err;
+			sk->err=0;
+			return -err;
+		}
+		interruptible_sleep_on(sk->sleep);
+	}
+
+	return(0);
+}
+
 static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
 	int addr_len, int flags)
 {
 	ipx_socket *sk=(ipx_socket *)sock->data;
-	struct sockaddr_ipx *addr;
-	
+	struct sockaddr_ipx *addr=(struct sockaddr_ipx *)uaddr;
+
 	sk->state = TCP_CLOSE;	
 	sock->state = SS_UNCONNECTED;
 	
-	if(addr_len!=sizeof(addr))
+	if(addr_len!=sizeof(struct sockaddr_ipx))
 		return(-EINVAL);
-	addr=(struct sockaddr_ipx *)uaddr;
 	
-	if(sk->ipx_source_addr.net==0)
+	if(sk->ipx_source_addr.sock==0)
 	/* put the autobinding in */
 	{
-		struct sockaddr_ipx uaddr;
 		int ret;
+		struct sockaddr_ipx addr;
 	
-		uaddr.sipx_port = 0;
-		uaddr.sipx_network = 0L; 
-		ret = ipx_bind (sock, (struct sockaddr *)&uaddr, sizeof(struct sockaddr_ipx));
+		addr.sipx_type = 0;
+		addr.sipx_port = 0;
+		addr.sipx_network = 0L; 
+		ret = ipx_bind (sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_ipx));
 		if (ret != 0) return (ret);
 	}
+
 	
 	sk->ipx_dest_addr.net=addr->sipx_network;
 	sk->ipx_dest_addr.sock=addr->sipx_port;
 	memcpy(sk->ipx_dest_addr.node,addr->sipx_node,sizeof(sk->ipx_source_addr.node));
 	if(ipxrtr_get_dev(sk->ipx_dest_addr.net)==NULL)
 		return -ENETUNREACH;
+
+	if (sk->type == SOCK_NCP)
+		return(ncp_connect(sock, sk));
+
+	sk->ipx_type=addr->sipx_type;
+
 	sock->state = SS_CONNECTED;
 	sk->state=TCP_ESTABLISHED;
 	return(0);
@@ -770,10 +992,9 @@
 {
 	ipx_address *addr;
 	struct sockaddr_ipx sipx;
-	ipx_socket *sk;
-	
-	sk=(ipx_socket *)sock->data;
+	ipx_socket *sk=(ipx_socket *)sock->data;
 	
+
 	*uaddr_len = sizeof(struct sockaddr_ipx);
 		
 	if(peer)
@@ -783,7 +1004,21 @@
 		addr=&sk->ipx_dest_addr;
 	}
 	else
+	{
+		if(sk->ipx_source_addr.sock==0)
+		/* put the autobinding in */
+		{
+			int ret;
+	
+			sipx.sipx_type = 0;
+			sipx.sipx_port = 0;
+			sipx.sipx_network = 0L; 
+			ret = ipx_bind (sock, (struct sockaddr *)&sipx, sizeof(struct sockaddr_ipx));
+			if (ret != 0) return (ret);
+		}
+	
 		addr=&sk->ipx_source_addr;
+	}
 		
 	sipx.sipx_family = AF_IPX;
 	sipx.sipx_port = addr->sock;
@@ -793,6 +1028,411 @@
 	return(0);
 }
 
+static int ipx_build_header(ipx_address *ipx, struct sk_buff *skb,
+				ipx_socket *sk, int len, unsigned char type)
+{
+	ipx_packet *ipx_pack;
+	ipx_route *rt;
+	struct datalink_proto *dl = NULL;
+	unsigned char IPXaddr[6];
+	int self_addressing = 0;
+	int broadcast = 0;
+
+	if(sk->debug)
+		printk("IPX: build_header: Addresses built.\n");
+
+	if(memcmp(&ipx->node,&ipx_broadcast_node,6)==0) 
+	{
+		if (!sk->broadcast)
+			return -ENETUNREACH;
+		broadcast = 1;
+	}
+
+	/* Build a packet */
+	
+	if(sk->debug)
+		printk("IPX: build_header: building packet.\n");
+		
+	/* Find out where this has to go */
+	if (ipx->net == 0L) {
+		rt = ipxrtr_get_default_net();
+		if (rt != NULL)
+			ipx->net = rt->net;
+	} else
+		rt=ipxrtr_get_dev(ipx->net);
+
+	if(rt==NULL)
+	{
+		return -ENETUNREACH;
+	}
+
+	dl=rt->datalink;
+
+	skb->mem_addr=skb;
+	skb->sk=sk;
+	skb->free=1;
+	skb->arp=1;
+	skb->tries=0;
+
+	if(sk->debug)
+		printk("Building MAC header.\n");		
+	skb->dev=rt->dev;
+
+	/* Build Data Link header */
+	dl->datalink_header(dl, skb, 
+		(rt->flags&IPX_RT_ROUTED)?rt->router_node:ipx->node);
+
+	/* See if we are sending to ourself */
+	memset(IPXaddr, '\0', 6);
+	memcpy(IPXaddr+(6 - skb->dev->addr_len), skb->dev->dev_addr, 
+			skb->dev->addr_len);
+
+	self_addressing = !memcmp(IPXaddr, 
+				(rt->flags&IPX_RT_ROUTED)?rt->router_node
+				:ipx->node,
+				6);
+
+	/* Now the IPX */
+	if(sk->debug)
+		printk("Building IPX Header.\n");
+	ipx_pack=(ipx_packet *)skb->h.raw;
+	ipx_pack->ipx_checksum=0xFFFF;
+	ipx_pack->ipx_pktsize=htons(len+sizeof(ipx_packet));
+	ipx_pack->ipx_tctrl=0;
+	ipx_pack->ipx_type=type;
+
+	memcpy(&ipx_pack->ipx_source,&sk->ipx_source_addr,sizeof(ipx_pack->ipx_source));
+	memcpy(&ipx_pack->ipx_dest,ipx,sizeof(ipx_pack->ipx_dest));
+
+	if((skb->dev->flags&IFF_LOOPBACK) || self_addressing)
+		skb->pkt_type=PACKET_HOST;
+	else
+		if (broadcast)
+			skb->pkt_type=PACKET_BROADCAST;
+		else
+			skb->pkt_type=PACKET_OTHERHOST;
+
+	return 0;
+}
+
+static int ipx_xmit(struct sk_buff *skb)
+{
+	struct sk_buff *skb1;
+	struct device *dev= skb->dev;
+	ipx_packet *ipx=(ipx_packet *)skb->h.raw; 
+	ipx_route *rt;
+	struct packet_type	pt;
+
+	if (ipx->ipx_dest.net == 0L)
+		rt = ipxrtr_get_default_net();
+	else
+		rt=ipxrtr_get_dev(ipx->ipx_dest.net);
+
+	if (rt == NULL)
+		return -ENETUNREACH;
+
+	pt.type=rt->dlink_type;
+
+	skb->tries++;
+
+	switch (skb->pkt_type)
+	{
+		case PACKET_HOST:
+			if (!skb->free)
+			{
+				skb1=alloc_skb(skb->len, GFP_ATOMIC);
+				if (skb1 != NULL)
+				{
+					skb1->mem_addr=skb1;
+					skb1->free=1;
+					skb1->arp=1;
+					skb1->len=skb->len;
+					skb1->sk = NULL;
+					skb1->h.raw = skb1->data + rt->datalink->header_length
+						+ dev->hard_header_len;
+					memcpy(skb1->data, skb->data, skb->len);
+					ipx_rcv(skb1,dev,&pt);
+				}
+			}
+			else
+			{
+		
+		
+				/* loop back */
+				skb->sk->wmem_alloc-=skb->mem_len;
+				skb->sk = NULL;
+				ipx_rcv(skb,dev,&pt);
+			}
+			break;
+
+		case PACKET_BROADCAST:
+			skb1=alloc_skb(skb->len, GFP_ATOMIC);
+			if (skb1 != NULL)
+			{
+				skb1->mem_addr=skb1;
+				skb1->free=1;
+				skb1->arp=1;
+				skb1->len=skb->len;
+				skb1->sk = NULL;
+				skb1->h.raw = skb1->data + rt->datalink->header_length
+					+ dev->hard_header_len;
+				memcpy(skb1->data, skb->data, skb->len);
+				ipx_rcv(skb1,dev,&pt);
+			}
+		default:
+			if (!skb->free)
+			{
+				skb1=alloc_skb(skb->len, GFP_ATOMIC);
+				if (skb1 != NULL)
+				{
+					skb1->mem_addr=skb1;
+					skb1->free=1;
+					skb1->arp=1;
+					skb1->len=skb->len;
+					skb1->sk = NULL;
+					skb1->h.raw = skb1->data + rt->datalink->header_length
+						+ dev->hard_header_len;
+					memcpy(skb1->data, skb->data, skb->len);
+				}
+			}
+			else
+				skb1=skb;
+			if (skb1 != NULL)
+			{
+				if (skb1->sk)
+					dev_queue_xmit(skb1,dev,skb->sk->priority);
+				else
+					dev_queue_xmit(skb1,dev,SOPRI_NORMAL);
+			}
+	}
+
+	return(0);
+
+}
+
+static int ipx_retransmit(ipx_socket *sk)
+{
+	struct sk_buff *skb = sk->write_queue.next;
+	int num=0;
+
+	ipx_packet *ipx;
+	struct ncp_request *req;
+
+	if (skb == NULL)
+		return(num);
+
+	if (skb == skb->next)
+		return(num);
+
+	do 
+	{
+		ipx=(ipx_packet *)skb->h.raw; 
+		req=(struct ncp_request *)(ipx+1);
+
+		ipx_xmit(skb);
+
+		num++;
+		skb=skb->next;
+	}
+	while (skb->next != sk->write_queue.next);
+
+	return (num);
+}
+
+static void ipx_timer (unsigned long data)
+{
+	ipx_socket *sk = (ipx_socket *) data;
+        int num;
+
+	cli();
+	if (in_bh)
+	{
+		sk->timer.expires = 10;
+		add_timer(&sk->timer);
+		sti();
+		return;
+	}
+	sti();
+
+	num=ipx_retransmit(sk);
+
+	sk->rto++;
+
+	if (sk->rto >= MAX_TIMEOUT)
+	{
+		struct sk_buff *skb;
+
+		while((skb=skb_dequeue(&sk->write_queue))!=NULL)
+			kfree_skb(skb,FREE_WRITE);
+
+		sk->err=ETIMEDOUT;
+		sk->state=TCP_CLOSE;
+		sk->socket->state=SS_UNCONNECTED;
+		if(!sk->dead)
+			sk->error_report(sk);
+		return;
+	}
+		
+	if (num)
+		ipx_reset_timer(sk, NCP_TIMEOUT);
+
+	return;
+}
+
+static void ipx_delete_timer (ipx_socket *sk)
+{
+	unsigned long flags;
+
+	save_flags (flags);
+	cli();
+
+	del_timer (&sk->timer);
+
+	restore_flags(flags);
+}
+
+static void ipx_add_timer (ipx_socket *sk, int len)
+{
+	init_timer (&sk->timer);
+	sk->timer.data = (unsigned long) sk;
+	sk->timer.function = &ipx_timer;
+	sk->timer.expires = len;
+	add_timer(&sk->timer);
+}
+
+static void ipx_reset_timer (ipx_socket *sk, int len)
+{
+
+	ipx_delete_timer (sk);
+	sk->timer.data = (unsigned long) sk;
+	sk->timer.function = &ipx_timer;
+	sk->timer.expires = len;
+	add_timer(&sk->timer);
+}
+
+static struct sk_buff *find_req(ipx_socket *sk, unsigned char seq)
+{
+	ipx_packet *ipx;
+	struct ncp_request *req;
+	struct sk_buff *skb = sk->write_queue.next;
+
+	if (skb == NULL)
+		return (NULL);
+
+	if (skb == skb->next)
+		return (NULL);
+
+	do 
+	{
+		ipx=(ipx_packet *)skb->h.raw; 
+		req=(struct ncp_request *)(ipx+1);
+		if (req->seq == seq)
+		{
+			skb_unlink(skb);
+			return (skb);
+		}
+		skb=skb->next;
+	}
+	while (skb->next != sk->write_queue.next);
+
+	return (NULL);
+}
+
+static int ncp_rcv(ipx_socket *sk, struct sk_buff *skb)
+{
+	ipx_packet *ipx=(ipx_packet *)skb->h.raw; 
+	struct ncp_reply *rep= (struct ncp_reply *)(ipx+1);
+	struct ncp_request_sf *req;
+	struct sk_buff *skb1;
+
+	if (rep->p_type != NCP_REPLY)
+	{
+		kfree_skb(skb, FREE_READ);
+		return (0);
+	}
+
+	skb1=find_req(sk, rep->seq);
+
+	if (skb1 == NULL)
+	{
+		kfree_skb(skb, FREE_READ);
+		return (0);
+	}
+
+	if (&sk->write_queue == sk->write_queue.next)
+	{
+		sk->rto=0;
+		ipx_delete_timer(sk);
+	}
+
+	ipx=(ipx_packet *)skb1->h.raw; 
+	req=(struct ncp_request_sf *)(ipx+1);
+
+	switch (sk->state)
+	{
+		case TCP_CLOSE_WAIT:
+			kfree_skb(skb, FREE_READ);
+			sk->socket->data = NULL;
+			sk->state=TCP_CLOSE;
+			if(!sk->dead)
+				sk->state_change(sk);
+			sk->dead=1;
+			if (&sk->write_queue != sk->write_queue.next)
+				ipx_delete_timer(sk);
+			ipx_destroy_socket(sk);
+			break;
+		case TCP_SYN_SENT:
+
+			if ((rep->f_stat == 0) && (rep->c_stat == 0))
+			{
+				sk->state=TCP_ESTABLISHED;
+				sk->socket->state = SS_CONNECTED;
+				sk->ncp.conn=rep->c_low + (rep->c_high * 0xff);
+				if(!sk->dead)
+					sk->state_change(sk);
+			}
+			else
+			{
+				sk->state=TCP_CLOSE;
+				sk->socket->state = SS_UNCONNECTED;
+				sk->err=ECONNREFUSED;
+				if (&sk->write_queue != sk->write_queue.next)
+					ipx_delete_timer(sk);
+				if(!sk->dead)
+					sk->error_report(sk);
+			}
+			kfree_skb(skb, FREE_READ);
+			break;
+		default:
+			if ((req->func==0x15)&&(req->s_func==0x01))
+			{
+				char *data = (char *)(rep+1);
+				int len=(int)*data; 
+				
+				if (len != 0)
+				{
+					memcpy(data, data+1, len);
+					*(data+len)='\0';
+					printk("\007%s\n",data);
+				}
+				kfree_skb(skb, FREE_READ);
+			}
+			else
+			{
+				sk->rmem_alloc+=skb->mem_len;
+				skb->sk = sk;
+
+				skb_queue_tail(&sk->receive_queue,skb);
+				if(!sk->dead)
+					sk->data_ready(sk,skb->len);
+			}
+	}	
+	
+	kfree_skb(skb1, FREE_WRITE);
+
+	return(0);
+}
+
 int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 {
 	/* NULL here for pt means the packet was looped back */
@@ -942,6 +1582,9 @@
 		kfree_skb(skb,FREE_READ);	/* Socket is full */
 		return(0);
 	}
+
+	if (sock->type == SOCK_NCP)
+		return (ncp_rcv(sock, skb));
 	
 	sock->rmem_alloc+=skb->mem_len;
 	skb->sk = sock;
@@ -952,65 +1595,27 @@
 	return(0);
 }
 
-static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock,
-	unsigned flags, struct sockaddr *usip, int addr_len)
+static int ipx_do_sendto(ipx_socket *sk, ipx_address *ipx,
+			 void *ubuf, int len, int flag, unsigned char type)
 {
-	ipx_socket *sk=(ipx_socket *)sock->data;
-	struct sockaddr_ipx *usipx=(struct sockaddr_ipx *)usip;
-	struct sockaddr_ipx local_sipx;
 	struct sk_buff *skb;
 	struct device *dev;
-	struct ipx_packet *ipx;
+	ipx_packet *ipx_pack;
 	int size;
 	ipx_route *rt;
 	struct datalink_proto *dl = NULL;
-	unsigned char IPXaddr[6];
-	int self_addressing = 0;
-	int broadcast = 0;
-
-	if(flags)
-		return -EINVAL;
-		
-	if(usipx)
-	{
-		if(sk->ipx_source_addr.net==0)
-		/* put the autobinding in */
-		{
-			struct sockaddr_ipx uaddr;
-			int ret;
 
-			uaddr.sipx_port = 0;
-			uaddr.sipx_network = 0L; 
-			ret = ipx_bind (sock, (struct sockaddr *)&uaddr, sizeof(struct sockaddr_ipx));
-			if (ret != 0) return (ret);
-		}
 
-		if(addr_len <sizeof(*usipx))
-			return(-EINVAL);
-		if(usipx->sipx_family != AF_IPX)
-			return -EINVAL;
-		if(htons(usipx->sipx_port)<0x4000 && !suser())
-			return -EPERM;
-	}
-	else
-	{
-		if(sk->state!=TCP_ESTABLISHED)
-			return -ENOTCONN;
-		usipx=&local_sipx;
-		usipx->sipx_family=AF_IPX;
-		usipx->sipx_port=sk->ipx_dest_addr.sock;
-		usipx->sipx_network=sk->ipx_dest_addr.net;
-		memcpy(usipx->sipx_node,sk->ipx_dest_addr.node,sizeof(usipx->sipx_node));
-	}
-	
 	if(sk->debug)
 		printk("IPX: sendto: Addresses built.\n");
 
-	if(memcmp(&usipx->sipx_node,&ipx_broadcast_node,6)==0) 
+	if ((sk->type == SOCK_NCP) && (len < sizeof (struct ncp_request)))
+		return -EINVAL;
+
+	if(memcmp(&ipx->node,&ipx_broadcast_node,6)==0) 
 	{
 		if (!sk->broadcast)
 			return -ENETUNREACH;
-		broadcast = 1;
 	}
 
 	/* Build a packet */
@@ -1021,12 +1626,12 @@
 	size=sizeof(ipx_packet)+len;	/* For mac headers */
 
 	/* Find out where this has to go */
-	if (usipx->sipx_network == 0L) {
+	if (ipx->net == 0L) {
 		rt = ipxrtr_get_default_net();
 		if (rt != NULL)
-			usipx->sipx_network = rt->net;
+			ipx->net = rt->net;
 	} else
-		rt=ipxrtr_get_dev(usipx->sipx_network);
+		rt=ipxrtr_get_dev(ipx->net);
 
 	if(rt==NULL)
 	{
@@ -1046,86 +1651,117 @@
 		return -EAGAIN;
 	}
 		
-	skb=alloc_skb(size,GFP_KERNEL);
+	if (flag)
+		skb=alloc_skb(size,GFP_KERNEL);
+	else
+		skb=alloc_skb(size,GFP_ATOMIC);
+
 	if(skb==NULL)
 		return -ENOMEM;
+
+	sk->wmem_alloc+=skb->mem_len;
 		
-	skb->mem_addr=skb;
-	skb->sk=sk;
-	skb->free=1;
-	skb->arp=1;
 	skb->len=size;
 
-	sk->wmem_alloc+=skb->mem_len;
+	ipx_build_header(ipx, skb, sk, len, type);
 
-	if(sk->debug)
-		printk("Building MAC header.\n");		
-	skb->dev=rt->dev;
-	
-	/* Build Data Link header */
-	dl->datalink_header(dl, skb, 
-		(rt->flags&IPX_RT_ROUTED)?rt->router_node:usipx->sipx_node);
+	ipx_pack = (ipx_packet *)(skb->h.raw);
 
-	/* See if we are sending to ourself */
-	memset(IPXaddr, '\0', 6);
-	memcpy(IPXaddr+(6 - skb->dev->addr_len), skb->dev->dev_addr, 
-			skb->dev->addr_len);
+	/* User data follows immediately after the IPX data */
+	if (flag)
+		memcpy_fromfs((char *)(ipx_pack+1),ubuf,len);
+	else
+		memcpy((char *)(ipx_pack+1),ubuf,len);
 
-	self_addressing = !memcmp(IPXaddr, 
-				(rt->flags&IPX_RT_ROUTED)?rt->router_node
-				:usipx->sipx_node,
-				6);
+	if (sk->type == SOCK_NCP)
+	{
+		struct ncp_request *req=(struct ncp_request *)(ipx_pack+1);
 
-	/* Now the IPX */
-	if(sk->debug)
-		printk("Building IPX Header.\n");
-	ipx=(ipx_packet *)skb->h.raw;
-	ipx->ipx_checksum=0xFFFF;
-	ipx->ipx_pktsize=htons(len+sizeof(ipx_packet));
-	ipx->ipx_tctrl=0;
-	ipx->ipx_type=usipx->sipx_type;
-
-	memcpy(&ipx->ipx_source,&sk->ipx_source_addr,sizeof(ipx->ipx_source));
-	ipx->ipx_dest.net=usipx->sipx_network;
-	memcpy(ipx->ipx_dest.node,usipx->sipx_node,sizeof(ipx->ipx_dest.node));
-	ipx->ipx_dest.sock=usipx->sipx_port;
-	if(sk->debug)
-		printk("IPX: Appending user data.\n");
-	/* User data follows immediately after the IPX data */
-	memcpy_fromfs((char *)(ipx+1),ubuf,len);
+		switch (sk->state)
+		{
+			case TCP_SYN_SENT:
+				req->p_type = NCP_OPEN;
+				break;
+			case TCP_CLOSE_WAIT:
+				req->p_type = NCP_CLOSE;
+				break;
+			default:
+				req->p_type = NCP_REQUEST;
+		}
+		req->c_low = (sk->ncp.conn) & 0xff;
+		req->c_high = (sk->ncp.conn >>8) & 0xff;
+		req->seq = (sk->ncp.seq)++;
+		req->task = 1;
+
+		skb->free=0;
+
+		if (&sk->write_queue == sk->write_queue.next)
+			ipx_add_timer(sk, NCP_TIMEOUT);
+		else
+			ipx_reset_timer(sk, NCP_TIMEOUT);
+	
+		skb_queue_tail(&sk->write_queue,skb);
+	}
+
 	if(sk->debug)
 		printk("IPX: Transmitting buffer\n");
-	if((dev->flags&IFF_LOOPBACK) || self_addressing) {
-		struct packet_type	pt;
 
-		/* loop back */
-		pt.type = rt->dlink_type;
-		sk->wmem_alloc-=skb->mem_len;
-		skb->sk = NULL;
-		ipx_rcv(skb,dev,&pt);
-	} else {
-		if (broadcast) {
-			struct packet_type	pt;
-			struct sk_buff		*skb2;
+	ipx_xmit(skb);
 
-			/* loop back */
-			pt.type = rt->dlink_type;
-			
-			skb2=alloc_skb(skb->len, GFP_ATOMIC);
-			skb2->mem_addr=skb2;
-			skb2->free=1;
-			skb2->arp=1;
-			skb2->len=skb->len;
-			skb2->sk = NULL;
-			skb2->h.raw = skb2->data + rt->datalink->header_length
-				+ dev->hard_header_len;
-			memcpy(skb2->data, skb->data, skb->len);
-			ipx_rcv(skb2,dev,&pt);
+	return len;
+}
+
+static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock,
+	unsigned flags, struct sockaddr *usip, int addr_len)
+{
+	ipx_socket *sk=(ipx_socket *)sock->data;
+        ipx_address ipx;
+	struct sockaddr_ipx *usipx=(struct sockaddr_ipx *)usip;
+	struct sockaddr_ipx local_sipx;
+
+	if(flags)
+		return -EINVAL;
+		
+	if(usipx)
+	{
+		if (sk->type == SOCK_NCP)
+			return -EINVAL;
+
+		if(sk->ipx_source_addr.sock==0)
+		/* put the autobinding in */
+		{
+			int ret;
+
+			local_sipx.sipx_type = 0;
+			local_sipx.sipx_port = 0;
+			local_sipx.sipx_network = 0L; 
+			ret = ipx_bind (sock, (struct sockaddr *)&local_sipx, sizeof(struct sockaddr_ipx));
+			if (ret != 0) return (ret);
 		}
-		dev_queue_xmit(skb,dev,SOPRI_NORMAL);
+
+		if(addr_len <sizeof(*usipx))
+			return(-EINVAL);
+		if(usipx->sipx_family != AF_IPX)
+			return -EINVAL;
+		if(htons(usipx->sipx_port)<0x4000 && !suser())
+			return -EPERM;
+
+		ipx.net=usipx->sipx_network;
+		ipx.sock=usipx->sipx_port;
+		memcpy(ipx.node,usipx->sipx_node, sizeof(ipx.node));
+		return (ipx_do_sendto(sk, &ipx, ubuf, len, 1,
+			usipx->sipx_type));
 	}
-	return len;
+	else
+	{
+		if(sk->state!=TCP_ESTABLISHED)
+			return -ENOTCONN;
+
+		return (ipx_do_sendto(sk, &(sk->ipx_dest_addr), ubuf,
+			len, 1, sk->ipx_type));
+	}
 }
+	
 
 static int ipx_send(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags)
 {
@@ -1142,7 +1778,7 @@
 	int copied = 0;
 	struct sk_buff *skb;
 	int er;
-	
+
 	if(sk->err)
 	{
 		er= -sk->err;
@@ -1170,12 +1806,14 @@
 		sipx->sipx_type = ipx->ipx_type;
 	}
 	skb_free_datagram(skb);
+
 	return(copied);
 }		
 
 
 static int ipx_write(struct socket *sock, char *ubuf, int size, int noblock)
 {
+
 	return ipx_send(sock,ubuf,size,noblock,0);
 }
 
diff -u --recursive --new-file v1.1.46/linux/net/inet/ncp.h linux/net/inet/ncp.h
--- v1.1.46/linux/net/inet/ncp.h	Thu Jan  1 02:00:00 1970
+++ linux/net/inet/ncp.h	Sun Aug 21 17:30:02 1994
@@ -0,0 +1,26 @@
+/*
+ *
+ * Kernel support for NCP
+ *
+ * Mark Evans 1994
+ *
+ */
+
+#ifndef _NCP_H
+#define _NCP_H
+
+#include <linux/ncp.h>
+
+struct ncp_info
+{
+	unsigned short 	conn;		/* connection number */
+	unsigned char	seq;		/* sequence number */
+	ipx_socket	*ncp;		/* ncp socket */
+	ipx_socket	*watchdog;	/* watchdog socket */
+	ipx_socket	*mail;		/* mail socket */
+};
+
+#define NCP_TIMEOUT (3*HZ)
+#define MAX_TIMEOUT 15
+
+#endif	/* _NCP_H */
diff -u --recursive --new-file v1.1.46/linux/net/inet/sock.h linux/net/inet/sock.h
--- v1.1.46/linux/net/inet/sock.h	Mon Jun 27 16:47:03 1994
+++ linux/net/inet/sock.h	Sun Aug 21 17:30:02 1994
@@ -41,6 +41,7 @@
 #endif
 #ifdef CONFIG_IPX
 #include "ipx.h"
+#include "ncp.h"
 #endif
 
 #define SOCK_ARRAY_SIZE	64
@@ -137,6 +138,7 @@
 #ifdef CONFIG_IPX
   ipx_address			ipx_source_addr,ipx_dest_addr;
   unsigned short		ipx_type;
+  struct ncp_info		ncp;
 #endif
 #ifdef CONFIG_AX25
 /* Really we want to add a per protocol private area */
diff -u --recursive --new-file v1.1.46/linux/net/socket.c linux/net/socket.c
--- v1.1.46/linux/net/socket.c	Thu Aug 11 20:43:41 1994
+++ linux/net/socket.c	Sun Aug 21 17:30:02 1994
@@ -592,7 +592,8 @@
   
 	if ((type != SOCK_STREAM && type != SOCK_DGRAM &&
 		type != SOCK_SEQPACKET && type != SOCK_RAW &&
-		type != SOCK_PACKET) || protocol < 0)
+		type != SOCK_PACKET && type != SOCK_NCP)
+		|| protocol < 0)
 			return(-EINVAL);
 
 /*
