diff -u --recursive --new-file v1.3.82/linux/CREDITS linux/CREDITS
--- v1.3.82/linux/CREDITS	Sun Mar 31 00:13:16 1996
+++ linux/CREDITS	Wed Apr  3 09:27:33 1996
@@ -867,9 +867,8 @@
 S: Germany
 
 N: David C. Niemi
-E: niemidc@clark.net
-D: FSSTND, The XFree86 Project
-D: DMA memory support, floppy driver
+E: niemi@erols.com
+D: Mtools/VFAT/floppy work, benchmarking, random kernel dilettante
 S: 2364 Old Trail Drive
 S: Reston, Virginia 22091
 S: USA
diff -u --recursive --new-file v1.3.82/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v1.3.82/linux/Documentation/Configure.help	Tue Apr  2 13:32:18 1996
+++ linux/Documentation/Configure.help	Tue Apr  2 13:33:13 1996
@@ -937,13 +937,14 @@
   turn your Linux box into a fully featured Netware file server and
   IPX router, say Y here and fetch either lwared from
   sunsite.unc.edu:/pub/Linux/system/Network/daemons/ or mars_nwe from
-  linux01.gwdg.de:/pub/ncpfs. For more information, read the IPX-HOWTO
-  in sunsite.unc.edu:/pub/Linux/docs/howto. The IPX driver would
-  enlarge your kernel by about 5 kB. This driver is also available as
-  a module ( = code which can be inserted in and removed from the
-  running kernel whenever you want). If you want to compile it as a
-  module, say M here and read Documentation/modules.txt. Unless you
-  want to integrate your Linux box with a local Novell network, say N.
+  ftp.gwdg.de:/pub/linux/misc/ncpfs. For more information, read the
+  IPX-HOWTO in sunsite.unc.edu:/pub/Linux/docs/howto. The IPX driver
+  would enlarge your kernel by about 5 kB. This driver is also
+  available as a module ( = code which can be inserted in and removed
+  from the running kernel whenever you want). If you want to compile
+  it as a module, say M here and read Documentation/modules.txt.
+  Unless you want to integrate your Linux box with a local Novell
+  network, say N.
 
 Full internal IPX network
 CONFIG_IPX_INTERN
@@ -958,7 +959,7 @@
   packets targeted at 'special' sockets to sockets listening on the
   primary network is disabled. This might break existing applications,
   especially RIP/SAP daemons. A RIP/SAP daemon that works well with the
-  full internal net can be found on linux01.gwdg.de:/pub/ncpfs.
+  full internal net can be found on ftp.gwdg.de:/pub/linux/misc/ncpfs.
   If you don't know what you are doing, say N.
 
 Appletalk DDP
diff -u --recursive --new-file v1.3.82/linux/Documentation/filesystems/ncpfs.txt linux/Documentation/filesystems/ncpfs.txt
--- v1.3.82/linux/Documentation/filesystems/ncpfs.txt	Thu Feb 22 15:20:19 1996
+++ linux/Documentation/filesystems/ncpfs.txt	Tue Apr  2 13:33:13 1996
@@ -1,11 +1,12 @@
 ncpfs is a filesystem which understands the NCP protocol, designed by the
 Novell Corporation for their NetWare(tm) product. NCP is functionally
 similar to the NFS used in the tcp/ip community.
-To mount a Netware-Filesystem, you need a special mount program, which can
-be found in ncpfs package. Homesite for ncpfs is linux01.gwdg.de/pub/ncpfs,
-but sunsite and its many mirrors will have it as well.
+To mount a Netware-Filesystem, you need a special mount program, which
+can be found in ncpfs package. Homesite for ncpfs is
+ftp.gwdg.de/pub/linux/misc/ncpfs, but sunsite and its many mirrors
+will have it as well.
 
 Related products are linware and mars_nwe, which will give Linux partial
-Netware Server functionality.
+NetWare Server functionality.
 Linware's home site is: klokan.sh.cvut.cz/pub/linux/linware,
-Mars_nwe can be found on linux01.gwdg.de/pub/ncpfs.
+Mars_nwe can be found on ftp.gwdg.de/pub/linux/misc/ncpfs.
diff -u --recursive --new-file v1.3.82/linux/Documentation/filesystems/smbfs.txt linux/Documentation/filesystems/smbfs.txt
--- v1.3.82/linux/Documentation/filesystems/smbfs.txt	Mon Aug 28 09:48:36 1995
+++ linux/Documentation/filesystems/smbfs.txt	Tue Apr  2 13:33:13 1996
@@ -8,5 +8,6 @@
 netbios name or share.
 
 To use smbfs, you need a special mount program, which can be found in
-the ksmbfs package, found on sunsite.unc.edu:/pub/Linux/ALPHA/smbfs.
+the ksmbfs package, found on
+sunsite.unc.edu:/pub/Linux/system/Filesystems/smbfs.
 
diff -u --recursive --new-file v1.3.82/linux/Makefile linux/Makefile
--- v1.3.82/linux/Makefile	Tue Apr  2 13:32:18 1996
+++ linux/Makefile	Tue Apr  2 13:33:31 1996
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 82
+SUBLEVEL = 83
 
 ARCH = i386
 
diff -u --recursive --new-file v1.3.82/linux/arch/alpha/boot/main.c linux/arch/alpha/boot/main.c
--- v1.3.82/linux/arch/alpha/boot/main.c	Sat Mar 16 13:52:12 1996
+++ linux/arch/alpha/boot/main.c	Wed Apr  3 10:59:32 1996
@@ -149,7 +149,7 @@
 	printk("Ok (rev %lx)\n", rev);
 	/* remove the old virtual page-table mapping */
 	L1[1] = 0;
-	invalidate_all();
+	flush_tlb_all();
 }
 
 extern int _end;
diff -u --recursive --new-file v1.3.82/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c
--- v1.3.82/linux/arch/alpha/kernel/ptrace.c	Sun Oct 29 14:54:27 1995
+++ linux/arch/alpha/kernel/ptrace.c	Wed Apr  3 10:59:32 1996
@@ -257,7 +257,7 @@
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
 /* this should also re-instate whatever read-only mode there was before */
 	set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-	invalidate();
+	flush_tlb();
 }
 
 static struct vm_area_struct * find_extend_vma(struct task_struct * tsk,
diff -u --recursive --new-file v1.3.82/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c
--- v1.3.82/linux/arch/alpha/mm/init.c	Sun Mar 31 00:13:16 1996
+++ linux/arch/alpha/mm/init.c	Wed Apr  3 10:59:32 1996
@@ -135,7 +135,7 @@
 	init_task.kernel_stack_page = INIT_STACK;
 	load_PCB(&init_task.tss);
 
-	invalidate_all();
+	flush_tlb_all();
 	return start_mem;
 }
 
diff -u --recursive --new-file v1.3.82/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v1.3.82/linux/arch/i386/defconfig	Tue Apr  2 13:32:19 1996
+++ linux/arch/i386/defconfig	Wed Apr  3 11:55:34 1996
@@ -141,6 +141,7 @@
 # Character devices
 #
 CONFIG_SERIAL=y
+# CONFIG_DIGI is not set
 # CONFIG_CYCLADES is not set
 # CONFIG_STALDRV is not set
 # CONFIG_PRINTER is not set
diff -u --recursive --new-file v1.3.82/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v1.3.82/linux/arch/i386/kernel/irq.c	Tue Apr  2 13:32:19 1996
+++ linux/arch/i386/kernel/irq.c	Wed Apr  3 10:59:32 1996
@@ -370,7 +370,7 @@
 {
 	struct irqaction * action = *(irq + irq_action);
 #ifdef __SMP__
-	/* IRQ 13 is allowed - thats an invalidate */
+	/* IRQ 13 is allowed - thats a flush tlb */
 	if(smp_threads_ready && active_kernel_processor!=smp_processor_id() && irq!=13)
 		panic("fast_IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id());
 #endif
diff -u --recursive --new-file v1.3.82/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v1.3.82/linux/arch/i386/kernel/process.c	Sat Mar 16 13:52:10 1996
+++ linux/arch/i386/kernel/process.c	Wed Apr  3 10:59:32 1996
@@ -160,7 +160,7 @@
                 	 *	Oops.. This is kind of important in some cases...
                 	 */
                 	if(clear_bit(smp_processor_id(), &smp_invalidate_needed))
-                		local_invalidate();
+                		local_flush_tlb();
                 }
                 if (0==(0x7fffffff & smp_process_available)){
                         clear_bit(31,&smp_process_available);
diff -u --recursive --new-file v1.3.82/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v1.3.82/linux/arch/i386/kernel/ptrace.c	Thu Sep  7 17:54:27 1995
+++ linux/arch/i386/kernel/ptrace.c	Wed Apr  3 10:59:32 1996
@@ -179,7 +179,7 @@
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
 /* this should also re-instate whatever read-only mode there was before */
 	set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-	invalidate();
+	flush_tlb();
 }
 
 static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
diff -u --recursive --new-file v1.3.82/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v1.3.82/linux/arch/i386/kernel/smp.c	Mon Mar 25 08:58:20 1996
+++ linux/arch/i386/kernel/smp.c	Wed Apr  3 10:59:32 1996
@@ -346,7 +346,7 @@
 			 
 					cfg=pg0[0];
 					pg0[0] = (apic_addr | 7);
-					local_invalidate();
+					local_flush_tlb();
 
 					boot_cpu_id = GET_APIC_ID(*((volatile unsigned long *) APIC_ID));
 
@@ -355,7 +355,7 @@
 					 */
 
 					pg0[0]= cfg;
-					local_invalidate();
+					local_flush_tlb();
 
 /*
  *
@@ -563,11 +563,11 @@
 	load_ldt(0);
 /*	printk("Testing faulting...\n");
 	*(long *)0=1;		 OOPS... */
-	local_invalidate();
+	local_flush_tlb();
 	while(!smp_commenced);
 	if (cpu_number_map[cpuid] == -1)
 		while(1);
-	local_invalidate();
+	local_flush_tlb();
 	SMP_PRINTK(("Commenced..\n"));
 	
 	load_TR(cpu_number_map[cpuid]);
@@ -716,7 +716,7 @@
 			
 			CMOS_WRITE(0xa, 0xf);
 			pg0[0]=7;
-			local_invalidate();
+			local_flush_tlb();
 			*((volatile unsigned short *) 0x469) = ((unsigned long)stack)>>4;
 			*((volatile unsigned short *) 0x467) = 0;
 			
@@ -725,7 +725,7 @@
 			 */
 			 
 			pg0[0]= cfg;
-			local_invalidate();
+			local_flush_tlb();
 
 			/*
 			 *	Be paranoid about clearing APIC errors.
@@ -874,7 +874,7 @@
 
 	cfg = pg0[0];
 	pg0[0] = 3;	/* writeable, present, addr 0 */
-	local_invalidate();
+	local_flush_tlb();
 
 	/*
 	 *	Paranoid:  Set warm reset code and vector here back
@@ -890,7 +890,7 @@
 	 */
 
 	pg0[0] = cfg;
-	local_invalidate();
+	local_flush_tlb();
 
 	/*
 	 *	Allow the user to impress friends.
@@ -927,7 +927,7 @@
  *	get stuck with irq's off waiting to send a message and thus not replying to the person
  *	spinning for a reply....
  *
- *	In the end invalidate ought to be the NMI and a very very short function (to avoid the old
+ *	In the end flush tlb ought to be the NMI and a very very short function (to avoid the old
  *	IDE disk problems), and other messages sent with IRQ's enabled in a civilised fashion. That
  *	will also boost performance.
  */
@@ -966,7 +966,7 @@
 	 *	Sanity check we don't re-enter this across CPU's. Only the kernel
 	 *	lock holder may send messages. For a STOP_CPU we are bringing the
 	 *	entire box to the fastest halt we can.. A reschedule carries
-	 *	no data and can occur during an invalidate.. guess what panic
+	 *	no data and can occur during a flush.. guess what panic
 	 *	I got to notice this bug...
 	 */
 	 
@@ -1081,22 +1081,22 @@
 }
 
 /*
- *	This is fraught with deadlocks. Linus does an invalidate at a whim
- *	even with IRQ's off. We have to avoid a pair of crossing invalidates
+ *	This is fraught with deadlocks. Linus does a flush tlb at a whim
+ *	even with IRQ's off. We have to avoid a pair of crossing flushes
  *	or we are doomed.  See the notes about smp_message_pass.
  */
  
-void smp_invalidate(void)
+void smp_flush_tlb(void)
 {
 	unsigned long flags;
 	if(smp_activated && smp_processor_id()!=active_kernel_processor)
-		panic("CPU #%d:Attempted invalidate IPI when not AKP(=%d)\n",smp_processor_id(),active_kernel_processor);
+		panic("CPU #%d:Attempted flush tlb IPI when not AKP(=%d)\n",smp_processor_id(),active_kernel_processor);
 /*	printk("SMI-");*/
 	
 	/*
 	 *	The assignment is safe because its volatile so the compiler cannot reorder it,
 	 *	because the i586 has strict memory ordering and because only the kernel lock holder
-	 *	may issue an invalidate. If you break any one of those three change this to an atomic
+	 *	may issue a tlb flush. If you break any one of those three change this to an atomic
 	 *	bus locked or.
 	 */
 	
@@ -1104,7 +1104,7 @@
 	
 	/*
 	 *	Processors spinning on the lock will see this IRQ late. The smp_invalidate_needed map will
-	 *	ensure they dont do a spurious invalidate or miss one.
+	 *	ensure they dont do a spurious flush tlb or miss one.
 	 */
 	 
 	save_flags(flags);
@@ -1115,7 +1115,7 @@
 	 *	Flush the local TLB
 	 */
 	 
-	local_invalidate();
+	local_flush_tlb();
 	
 	restore_flags(flags);
 	
@@ -1174,7 +1174,7 @@
 		 
 		case MSG_INVALIDATE_TLB:
 			if(clear_bit(i,(unsigned long *)&smp_invalidate_needed))
-				local_invalidate();
+				local_flush_tlb();
 			set_bit(i, (unsigned long *)&cpu_callin_map[0]);
 		/*	cpu_callin_map[0]|=1<<smp_processor_id();*/
 			break;
diff -u --recursive --new-file v1.3.82/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v1.3.82/linux/arch/i386/kernel/traps.c	Tue Nov 21 08:34:54 1995
+++ linux/arch/i386/kernel/traps.c	Wed Apr  3 10:59:32 1996
@@ -193,7 +193,7 @@
 asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
 {
 #ifdef CONFIG_SMP_NMI_INVAL
-	smp_invalidate_rcv();
+	smp_flush_tlb_rcv();
 #else
 #ifndef CONFIG_IGNORE_NMI
 	printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
diff -u --recursive --new-file v1.3.82/linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c
--- v1.3.82/linux/arch/i386/kernel/vm86.c	Mon Mar 11 10:33:56 1996
+++ linux/arch/i386/kernel/vm86.c	Wed Apr  3 10:59:32 1996
@@ -96,7 +96,7 @@
 			set_pte(pte, pte_wrprotect(*pte));
 		pte++;
 	}
-	invalidate();
+	flush_tlb();
 }
 
 asmlinkage int sys_vm86(struct vm86_struct * v86)
diff -u --recursive --new-file v1.3.82/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
--- v1.3.82/linux/arch/i386/mm/fault.c	Sun Nov 19 12:46:20 1995
+++ linux/arch/i386/mm/fault.c	Wed Apr  3 10:59:32 1996
@@ -116,7 +116,7 @@
 	if (wp_works_ok < 0 && address == TASK_SIZE && (error_code & 1)) {
 		wp_works_ok = 1;
 		pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
-		invalidate();
+		flush_tlb();
 		printk("This processor honours the WP bit even when in supervisor mode. Good.\n");
 		return;
 	}
diff -u --recursive --new-file v1.3.82/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v1.3.82/linux/arch/i386/mm/init.c	Mon Mar 25 08:58:20 1996
+++ linux/arch/i386/mm/init.c	Wed Apr  3 10:59:32 1996
@@ -193,7 +193,7 @@
 			address += PAGE_SIZE;
 		}
 	}
-	invalidate();
+	flush_tlb();
 	return free_area_init(start_mem, end_mem);
 }
 
@@ -267,10 +267,10 @@
 /* test if the WP bit is honoured in supervisor mode */
 	if (wp_works_ok < 0) {
 		pg0[0] = pte_val(mk_pte(0, PAGE_READONLY));
-		invalidate();
+		flush_tlb();
 		__asm__ __volatile__("movb 0,%%al ; movb %%al,0": : :"ax", "memory");
 		pg0[0] = 0;
-		invalidate();
+		flush_tlb();
 		if (wp_works_ok < 0)
 			wp_works_ok = 0;
 	}
diff -u --recursive --new-file v1.3.82/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v1.3.82/linux/drivers/char/Config.in	Sun Mar 31 00:13:17 1996
+++ linux/drivers/char/Config.in	Wed Apr  3 09:20:45 1996
@@ -5,6 +5,7 @@
 comment 'Character devices'
 
 bool 'Standard/generic serial support' CONFIG_SERIAL
+bool 'Digiboard PC/X Support' CONFIG_DIGI
 tristate 'Cyclades async mux support' CONFIG_CYCLADES
 bool 'Stallion multiport serial support' CONFIG_STALDRV
 if [ "$CONFIG_STALDRV" = "y" ]; then
diff -u --recursive --new-file v1.3.82/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v1.3.82/linux/drivers/char/Makefile	Sun Mar 31 00:13:17 1996
+++ linux/drivers/char/Makefile	Wed Apr  3 09:20:45 1996
@@ -23,9 +23,13 @@
 L_OBJS   := tty_io.o n_tty.o console.o keyboard.o \
 	tty_ioctl.o pty.o vt.o mem.o vc_screen.o random.o \
 	defkeymap.o consolemap.o selection.o
-
+ 
 ifeq ($(CONFIG_SERIAL),y)
 L_OBJS += serial.o
+endif
+
+ifeq ($(CONFIG_DIGI),y)
+L_OBJS += pcxx.o
 endif
 
 ifeq ($(CONFIG_CYCLADES),y)
diff -u --recursive --new-file v1.3.82/linux/drivers/char/digi.h linux/drivers/char/digi.h
--- v1.3.82/linux/drivers/char/digi.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/digi.h	Wed Apr  3 09:20:45 1996
@@ -0,0 +1,71 @@
+/*          Definitions for DigiBoard ditty(1) command.                 */
+
+#if !defined(TIOCMODG)
+#define	TIOCMODG	('d'<<8) | 250		/* get modem ctrl state	*/
+#define	TIOCMODS	('d'<<8) | 251		/* set modem ctrl state	*/
+#endif
+
+#if !defined(TIOCMSET)
+#define	TIOCMSET	('d'<<8) | 252		/* set modem ctrl state	*/
+#define	TIOCMGET	('d'<<8) | 253		/* set modem ctrl state	*/
+#endif
+
+#if !defined(TIOCMBIC)
+#define	TIOCMBIC	('d'<<8) | 254		/* set modem ctrl state */
+#define	TIOCMBIS	('d'<<8) | 255		/* set modem ctrl state */
+#endif
+
+#if !defined(TIOCSDTR)
+#define	TIOCSDTR	('e'<<8) | 0		/* set DTR		*/
+#define	TIOCCDTR	('e'<<8) | 1		/* clear DTR		*/
+#endif
+
+/************************************************************************
+ * Ioctl command arguments for DIGI parameters.
+ ************************************************************************/
+#define DIGI_GETA	('e'<<8) | 94		/* Read params		*/
+
+#define DIGI_SETA	('e'<<8) | 95		/* Set params		*/
+#define DIGI_SETAW	('e'<<8) | 96		/* Drain & set params	*/
+#define DIGI_SETAF	('e'<<8) | 97		/* Drain, flush & set params */
+
+#define	DIGI_GETFLOW	('e'<<8) | 99		/* Get startc/stopc flow */
+						/* control characters 	 */
+#define	DIGI_SETFLOW	('e'<<8) | 100		/* Set startc/stopc flow */
+						/* control characters	 */
+#define	DIGI_GETAFLOW	('e'<<8) | 101		/* Get Aux. startc/stopc */
+						/* flow control chars 	 */
+#define	DIGI_SETAFLOW	('e'<<8) | 102		/* Set Aux. startc/stopc */
+						/* flow control chars	 */
+
+struct	digiflow_struct {
+	unsigned char	startc;				/* flow cntl start char	*/
+	unsigned char	stopc;				/* flow cntl stop char	*/
+};
+
+typedef struct digiflow_struct digiflow_t;
+
+
+/************************************************************************
+ * Values for digi_flags 
+ ************************************************************************/
+#define DIGI_IXON	0x0001		/* Handle IXON in the FEP	*/
+#define DIGI_FAST	0x0002		/* Fast baud rates		*/
+#define RTSPACE		0x0004		/* RTS input flow control	*/
+#define CTSPACE		0x0008		/* CTS output flow control	*/
+#define DSRPACE		0x0010		/* DSR output flow control	*/
+#define DCDPACE		0x0020		/* DCD output flow control	*/
+#define DTRPACE		0x0040		/* DTR input flow control	*/
+#define DIGI_FORCEDCD	0x0100		/* Force carrier		*/
+#define	DIGI_ALTPIN	0x0200		/* Alternate RJ-45 pin config	*/
+#define	DIGI_AIXON	0x0400		/* Aux flow control in fep	*/
+
+
+/************************************************************************
+ * Structure used with ioctl commands for DIGI parameters.
+ ************************************************************************/
+struct digi_struct {
+	unsigned short	digi_flags;		/* Flags (see above)	*/
+};
+
+typedef struct digi_struct digi_t;
diff -u --recursive --new-file v1.3.82/linux/drivers/char/digi_bios.h linux/drivers/char/digi_bios.h
--- v1.3.82/linux/drivers/char/digi_bios.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/digi_bios.h	Wed Apr  3 09:20:45 1996
@@ -0,0 +1,177 @@
+/* DigiBoard PCXX Bios */
+
+static unsigned char pcxx_bios[] = {
+  0x28,0x43,0x29,0x20,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,
+  0x74,0x20,0x31,0x39,0x39,0x34,0x2c,0x20,0x44,0x69,0x67,0x69,
+  0x42,0x6f,0x61,0x72,0x64,0x20,0x49,0x6e,0x63,0x2e,0x00,0x00,
+  0x8a,0xf8,0x8a,0xf8,0x15,0xf9,0x8a,0xf8,0x8a,0xf8,0x8a,0xf8,
+  0x8a,0xf8,0x8a,0xf8,0xbc,0xf8,0x8a,0xf8,0x96,0xf8,0x96,0xf8,
+  0x96,0xf8,0x96,0xf8,0x96,0xf8,0x96,0xf8,0x8a,0xf8,0x8a,0xf8,
+  0x96,0xf8,0x96,0xf8,0x8a,0xf8,0xad,0xf8,0xb0,0xf8,0x8a,0xf8,
+  0x8a,0xf8,0x8a,0xf8,0x8a,0xf8,0x8a,0xf8,0x8a,0xf8,0x8a,0xf8,
+  0x8a,0xf8,0x8a,0xf8,0x8a,0xf8,0x04,0x02,0x00,0x02,0x14,0x02,
+  0x10,0x02,0x24,0x02,0x20,0x02,0x34,0x02,0x30,0x02,0x44,0x02,
+  0x40,0x02,0x54,0x02,0x50,0x02,0x64,0x02,0x60,0x02,0x74,0x02,
+  0x70,0x02,0x04,0x01,0x00,0x01,0x1e,0x2e,0x8e,0x1e,0x22,0xf8,
+  0xfe,0x06,0x70,0x00,0x1f,0xcf,0x1e,0x50,0x52,0x2e,0x8e,0x1e,
+  0x22,0xf8,0xfe,0x06,0x71,0x00,0xb8,0x00,0x80,0xba,0x22,0xff,
+  0xef,0x5a,0x58,0x1f,0xcf,0xb4,0x80,0xcf,0x1e,0x2e,0x8e,0x1e,
+  0x22,0xf8,0xfe,0x06,0x2b,0x00,0x1f,0xcf,0x1e,0x52,0x50,0x2e,
+  0x8e,0x1e,0x22,0xf8,0xcd,0x16,0xfe,0x06,0x2a,0x00,0x80,0x3e,
+  0x2a,0x00,0x12,0x72,0x39,0xc6,0x06,0x2a,0x00,0x00,0xfe,0x06,
+  0x29,0x00,0x80,0x3e,0x29,0x00,0x3c,0x72,0x29,0xc6,0x06,0x29,
+  0x00,0x00,0xfe,0x06,0x28,0x00,0x80,0x3e,0x28,0x00,0x3c,0x72,
+  0x19,0xc6,0x06,0x28,0x00,0x00,0xfe,0x06,0x27,0x00,0x80,0x3e,
+  0x27,0x00,0x18,0x72,0x09,0xc6,0x06,0x27,0x00,0x00,0xff,0x06,
+  0x25,0x00,0xba,0x22,0xff,0xb8,0x00,0x80,0xef,0x58,0x5a,0x1f,
+  0xcf,0x60,0x1e,0x06,0xfc,0x2e,0x8e,0x06,0x22,0xf8,0x2e,0x8e,
+  0x1e,0x22,0xf8,0x8d,0x36,0x40,0x00,0xad,0x3c,0x3f,0x7f,0x22,
+  0x3c,0x1f,0x7f,0x22,0x32,0xe4,0xd1,0xe0,0x3d,0x16,0x00,0x90,
+  0x73,0x14,0xbb,0x56,0xf9,0x03,0xd8,0x2e,0xff,0x17,0x8d,0x36,
+  0x40,0x00,0xb0,0x00,0x89,0x04,0x07,0x1f,0x61,0xcf,0xb4,0x80,
+  0xeb,0xf0,0xcd,0x15,0xeb,0xec,0x6c,0xf9,0x79,0xf9,0xb9,0xf9,
+  0xd3,0xf9,0xd8,0xf9,0xe1,0xf9,0xe9,0xf9,0xf2,0xf9,0xfa,0xf9,
+  0xfd,0xf9,0x2a,0xfa,0xe4,0x00,0x24,0xf7,0xe6,0x00,0x0c,0x08,
+  0xe6,0x00,0xb4,0x00,0xc3,0x1e,0xad,0x8b,0xd8,0xad,0x8e,0xdb,
+  0x8b,0xf0,0x33,0xdb,0x8b,0x07,0x3d,0x4f,0x53,0x75,0x2a,0x8a,
+  0x47,0x02,0x32,0xe4,0x86,0xc4,0x8b,0xc8,0x32,0xc0,0x02,0x07,
+  0x43,0xe2,0xfb,0x0a,0xc0,0x75,0x16,0x8c,0xd9,0x1f,0x89,0x0e,
+  0x2e,0x00,0x89,0x36,0x2c,0x00,0x8d,0x1e,0x02,0x00,0xc7,0x07,
+  0x45,0x4d,0x32,0xe4,0xc3,0x1f,0xb4,0x80,0xc3,0xad,0x8b,0xd8,
+  0xad,0x8b,0xd0,0xad,0x8e,0xc0,0xad,0x8b,0xf8,0xad,0x8b,0xc8,
+  0x8b,0xf2,0x1e,0x8e,0xdb,0xf3,0xa4,0x1f,0x32,0xe4,0xc3,0xea,
+  0xf0,0xff,0x00,0xf0,0xad,0x8b,0xd0,0xec,0x88,0x04,0x32,0xe4,
+  0xc3,0xad,0x8b,0xd0,0xac,0xee,0x32,0xe4,0xc3,0xad,0x8b,0xd0,
+  0xed,0x89,0x04,0x32,0xe4,0xc3,0xad,0x8b,0xd0,0xad,0xef,0x32,
+  0xe4,0xc3,0xb4,0x80,0xc3,0xac,0x3c,0x12,0x7f,0x25,0xfe,0xc8,
+  0x32,0xe4,0xd1,0xe0,0x8d,0x1e,0x66,0xf8,0x03,0xd8,0x2e,0x8b,
+  0x17,0xec,0xac,0x3c,0x0f,0x7f,0x10,0x3c,0x00,0x74,0x03,0xee,
+  0x90,0x90,0xec,0x8b,0xfe,0x1e,0x07,0xaa,0x32,0xe4,0xc3,0xb4,
+  0x80,0xc3,0xac,0x3c,0x12,0x7f,0x1f,0xfe,0xc8,0x32,0xe4,0xd1,
+  0xe0,0x8d,0x1e,0x66,0xf8,0x03,0xd8,0x2e,0x8b,0x17,0xec,0xac,
+  0x3c,0x0f,0x7f,0x0a,0x3c,0x00,0x74,0x01,0xee,0xac,0xee,0x32,
+  0xe4,0xc3,0xb4,0x80,0xc3,0xfc,0x8e,0xc0,0xb8,0xff,0xff,0x8b,
+  0xcb,0x33,0xff,0xf3,0xab,0x8b,0xcb,0x33,0xff,0xf3,0xaf,0xe3,
+  0x01,0xc3,0x8b,0xcb,0xbf,0x00,0x00,0x26,0x89,0x3d,0x83,0xc7,
+  0x02,0xe2,0xf8,0xbe,0x00,0x00,0x8b,0xcb,0x26,0x8b,0x3c,0x3b,
+  0xfe,0x74,0x01,0xc3,0x83,0xc6,0x02,0x83,0xc7,0x02,0xe2,0xf0,
+  0x33,0xc0,0x8b,0xcb,0x33,0xff,0xf3,0xab,0x8b,0xcb,0x33,0xff,
+  0xf3,0xaf,0xc3,0x32,0xc0,0x26,0x80,0x3e,0x23,0x00,0x00,0x74,
+  0x02,0x0c,0x01,0x26,0xf7,0x06,0x20,0x00,0x0f,0x00,0x74,0x02,
+  0x0c,0x02,0x26,0xf7,0x06,0x20,0x00,0xf0,0x00,0x74,0x02,0x0c,
+  0x04,0x26,0xf7,0x06,0x20,0x00,0x00,0xff,0x74,0x02,0x0c,0x08,
+  0x26,0xa2,0x24,0x00,0xb8,0x00,0x40,0xba,0x5e,0xff,0xef,0xba,
+  0x66,0xff,0xef,0xba,0x52,0xff,0xb8,0x63,0x0e,0xef,0xba,0x56,
+  0xff,0xb8,0x05,0xe0,0xef,0xba,0x28,0xff,0xb8,0xfc,0x00,0xef,
+  0xb8,0x00,0x02,0x26,0xa3,0x2e,0x00,0xb8,0x04,0x00,0x26,0xa3,
+  0x2c,0x00,0xb0,0xc3,0xe6,0x08,0x8a,0xd8,0xe4,0x08,0x3a,0xc3,
+  0x75,0x06,0x26,0xc6,0x06,0xb4,0x00,0x01,0xb0,0x00,0xe6,0x00,
+  0xfc,0x8d,0x3e,0x00,0x00,0xb8,0x47,0x44,0xab,0xb8,0xff,0xff,
+  0xab,0xab,0xab,0xb8,0x42,0x49,0xab,0xb8,0x4f,0x53,0xab,0xb8,
+  0x58,0x69,0x26,0x80,0x3e,0x10,0x00,0x04,0x74,0x0e,0xb8,0x58,
+  0x65,0x26,0x80,0x3e,0x10,0x00,0x03,0x74,0x03,0xb8,0x58,0x74,
+  0xab,0x8d,0x36,0xfe,0xff,0x8a,0x04,0x8d,0x36,0xff,0xff,0x8a,
+  0x24,0xab,0xfb,0x26,0x81,0x0e,0x12,0x00,0x00,0x08,0x06,0x1f,
+  0xa1,0x00,0x00,0x8b,0x1e,0x02,0x00,0x3d,0x44,0x47,0x75,0x0b,
+  0x26,0x81,0x0e,0x12,0x00,0x00,0x10,0xff,0x2e,0x2c,0x00,0x81,
+  0xfb,0x45,0x4d,0x75,0xe3,0x26,0x81,0x0e,0x12,0x00,0x00,0x20,
+  0xff,0x2e,0x2c,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  0xff,0xff,0xff,0xff,0xfa,0xba,0xa8,0xff,0xb8,0xba,0x81,0xef,
+  0xba,0xa4,0xff,0xb8,0x3a,0x00,0xef,0x90,0xe4,0x00,0xa8,0x60,
+  0x75,0x0c,0x24,0x06,0x74,0x14,0x3c,0x02,0x74,0x1c,0x3c,0x04,
+  0x74,0x24,0xbb,0x38,0xc0,0xbe,0xf8,0x81,0xbf,0xba,0xa0,0xeb,
+  0x22,0x90,0xbb,0x38,0xf0,0xbe,0xf8,0x41,0xbf,0xba,0x81,0xeb,
+  0x16,0x90,0xbb,0x38,0xf0,0xbe,0xf8,0xe1,0xbf,0xba,0x88,0xeb,
+  0x0a,0x90,0xbb,0x38,0xc0,0xbe,0xf8,0x41,0xbf,0xba,0x81,0xba,
+  0xa0,0xff,0x8b,0xc3,0xef,0xba,0xa2,0xff,0xb8,0xf8,0x0f,0xef,
+  0xba,0xa6,0xff,0x8b,0xc6,0xef,0xba,0xa8,0xff,0x8b,0xc7,0xef,
+  0x8c,0xc8,0x8e,0xd8,0xe4,0x00,0x24,0x06,0x74,0x17,0xbb,0x00,
+  0x80,0xbd,0xc0,0xe0,0x3c,0x02,0x74,0x5a,0xbd,0xc0,0xc0,0x3c,
+  0x04,0x74,0x53,0xbd,0xc0,0x80,0xeb,0x4e,0x90,0xb9,0x08,0x00,
+  0xb8,0x00,0x80,0x8e,0xc0,0x26,0xa3,0x00,0x00,0x05,0x00,0x10,
+  0xe2,0xf5,0xbd,0xc0,0xf0,0xbb,0x00,0x7c,0xb8,0x00,0xe0,0x8e,
+  0xc0,0x26,0x8b,0x0e,0x00,0x00,0x3b,0xc8,0x75,0x28,0xbb,0x00,
+  0x80,0xbd,0xc0,0xe0,0xb8,0x00,0xc0,0x8e,0xc0,0x26,0x8b,0x0e,
+  0x00,0x00,0x3b,0xc8,0x75,0x14,0xbd,0xc0,0xc0,0xb8,0x00,0x80,
+  0x8e,0xc0,0x26,0x8b,0x0e,0x00,0x00,0x3b,0xc8,0x75,0x03,0xbd,
+  0xc0,0x80,0x8c,0xc8,0x8e,0xd0,0xbc,0xed,0xfc,0x8b,0xc5,0x25,
+  0x00,0xf0,0xe9,0x6c,0xfd,0xb4,0x00,0x74,0x06,0xb4,0xff,0xeb,
+  0x02,0xe5,0xfc,0x8e,0xc5,0x2e,0x89,0x2e,0x22,0xf8,0xe4,0x00,
+  0x24,0x16,0x26,0xa2,0x11,0x00,0x26,0x83,0x0e,0x12,0x00,0x01,
+  0x80,0xfc,0x00,0x74,0x06,0x26,0x83,0x0e,0x14,0x00,0x01,0x26,
+  0xc7,0x06,0x18,0x00,0x40,0x00,0x26,0xc6,0x06,0x10,0x00,0x03,
+  0xa8,0x10,0x74,0x06,0x26,0xc6,0x06,0x10,0x00,0x04,0xb8,0x00,
+  0x00,0x8e,0xc0,0xb8,0xaa,0x55,0x26,0xa3,0x00,0x00,0x26,0xc7,
+  0x06,0x02,0x00,0x00,0x00,0x26,0xc7,0x06,0x04,0x00,0x00,0x00,
+  0x8b,0xcd,0x81,0xe1,0x00,0xf0,0x8e,0xc1,0x26,0x8b,0x1e,0x00,
+  0x00,0x3b,0xc3,0x75,0x13,0x8e,0xc5,0x26,0xc6,0x06,0x10,0x00,
+  0x05,0xb8,0x40,0x00,0x8e,0xd0,0xbc,0x00,0x04,0xe9,0x99,0x00,
+  0x8c,0xc8,0x8e,0xd0,0xbc,0x7c,0xfd,0xb8,0x00,0x00,0xbb,0x00,
+  0x20,0xe9,0xdd,0xfc,0xb4,0x00,0x74,0x06,0xb4,0xff,0xeb,0x02,
+  0x74,0xfd,0x8e,0xc5,0x80,0xfc,0x00,0x74,0x08,0x26,0x83,0x0e,
+  0x14,0x00,0x02,0xeb,0x0d,0x26,0xc7,0x06,0x16,0x00,0x10,0x00,
+  0x26,0x83,0x0e,0x12,0x00,0x02,0xb8,0x40,0x00,0x8e,0xd0,0xbc,
+  0x00,0x04,0xe4,0x00,0xa8,0x60,0x75,0x07,0xba,0xa2,0xff,0xb8,
+  0xfc,0x0f,0xef,0xb8,0x00,0x04,0x8e,0xc0,0xb8,0xaa,0x55,0x26,
+  0xa3,0x00,0x00,0x26,0xc7,0x06,0x02,0x00,0x00,0x00,0x26,0xc7,
+  0x06,0x04,0x00,0x00,0x00,0xb9,0x00,0x00,0x8e,0xc1,0x26,0x8b,
+  0x1e,0x00,0x00,0x3b,0xc3,0x75,0x02,0xeb,0x24,0x8e,0xc5,0x26,
+  0x83,0x0e,0x12,0x00,0x04,0xb8,0x00,0x04,0xbb,0x00,0x60,0x06,
+  0xe8,0x66,0xfc,0x07,0x75,0x09,0x26,0xc7,0x06,0x16,0x00,0x40,
+  0x00,0xeb,0x06,0x26,0x83,0x0e,0x14,0x00,0x04,0x8e,0xc5,0x8c,
+  0xc0,0x3d,0xc0,0xf0,0x75,0x03,0xe9,0x9f,0x00,0x3d,0xc0,0x80,
+  0x74,0x62,0x3d,0xc0,0xc0,0x74,0x23,0x26,0x83,0x0e,0x12,0x00,
+  0x08,0xb8,0x00,0xf0,0xbb,0x00,0x7c,0x06,0xe8,0x2e,0xfc,0x07,
+  0x75,0x08,0x26,0x83,0x06,0x18,0x00,0x40,0xeb,0x06,0x26,0x83,
+  0x0e,0x14,0x00,0x08,0xeb,0x72,0xb9,0x03,0x00,0xb8,0x00,0xd0,
+  0xba,0x08,0x00,0xbb,0x00,0x80,0x3d,0x00,0xf0,0x75,0x03,0xbb,
+  0x00,0x7c,0x26,0x09,0x16,0x12,0x00,0x06,0x50,0x51,0xe8,0xfc,
+  0xfb,0x59,0x58,0x07,0x75,0x0f,0x26,0x83,0x06,0x18,0x00,0x40,
+  0xd1,0xe2,0x05,0x00,0x10,0xe2,0xd8,0xeb,0x05,0x26,0x09,0x16,
+  0x14,0x00,0xeb,0x38,0xb9,0x07,0x00,0xb8,0x00,0x90,0xba,0x08,
+  0x00,0xbb,0x00,0x80,0x3d,0x00,0xf0,0x75,0x03,0xbb,0x00,0x7c,
+  0x26,0x09,0x16,0x12,0x00,0x06,0x50,0x51,0xe8,0xc2,0xfb,0x59,
+  0x58,0x07,0x75,0x0f,0x26,0x83,0x06,0x18,0x00,0x40,0xd1,0xe2,
+  0x05,0x00,0x10,0xe2,0xd8,0xeb,0x05,0x26,0x09,0x16,0x14,0x00,
+  0x26,0xa1,0x18,0x00,0x2d,0x10,0x00,0x26,0xa3,0x1a,0x00,0x06,
+  0xfc,0x33,0xff,0x8e,0xc7,0xb9,0x00,0x02,0xb8,0x00,0xf0,0xf3,
+  0xab,0x33,0xff,0xbe,0x24,0xf8,0xb9,0x20,0x00,0xa5,0x47,0x47,
+  0xe2,0xfb,0xbe,0x64,0xf8,0xb9,0xe0,0x00,0x8b,0x1c,0x26,0x89,
+  0x1d,0x83,0xc7,0x04,0xe2,0xf8,0x07,0xba,0x28,0xff,0xb8,0xfd,
+  0x00,0xef,0xba,0x32,0xff,0xb8,0x0d,0x00,0xef,0xba,0x34,0xff,
+  0xb8,0x0f,0x00,0xef,0xba,0x36,0xff,0xb8,0x0e,0x00,0xef,0xba,
+  0x38,0xff,0xb8,0x19,0x00,0xef,0xba,0x3a,0xff,0xb8,0x18,0x00,
+  0xef,0xba,0x3c,0xff,0xb8,0x0b,0x00,0xef,0xba,0x3e,0xff,0xb8,
+  0x1a,0x00,0xef,0x8d,0x3e,0x90,0x00,0x8d,0x36,0x66,0xf8,0xb9,
+  0x10,0x00,0xf3,0xa5,0x8d,0x3e,0xb0,0x00,0x8d,0x36,0x86,0xf8,
+  0xb9,0x02,0x00,0xf3,0xa5,0xb9,0x10,0x00,0x8d,0x36,0x90,0x00,
+  0x83,0xc6,0x1e,0x26,0x8b,0x14,0xb3,0x10,0x32,0xc0,0xec,0xb0,
+  0x0c,0xee,0x8a,0xc3,0x8a,0xc3,0xee,0x83,0xee,0x02,0x26,0x8b,
+  0x14,0xfe,0xcb,0xe2,0xeb,0xb9,0x10,0x00,0x8d,0x36,0x90,0x00,
+  0x26,0x8b,0x14,0xb3,0x01,0xbf,0x00,0x80,0xb0,0x0c,0xee,0xf6,
+  0xe8,0xec,0x3a,0xc3,0x75,0x0e,0xd1,0xc7,0x26,0x09,0x3e,0x20,
+  0x00,0x26,0xfe,0x06,0x22,0x00,0xeb,0x07,0x33,0xc0,0x26,0x89,
+  0x04,0xd1,0xc7,0x83,0xc6,0x02,0x26,0x8b,0x14,0xfe,0xc3,0xe2,
+  0xd7,0x26,0xc6,0x06,0x23,0x00,0x01,0x8d,0x36,0xb0,0x00,0x26,
+  0x8b,0x14,0x32,0xc0,0xee,0xb0,0x0c,0xee,0xb0,0x5a,0xee,0xb0,
+  0x0c,0xee,0xf6,0xe8,0xec,0x3c,0x5a,0x74,0x14,0x26,0xc7,0x06,
+  0xb0,0x00,0x00,0x00,0x26,0xc7,0x06,0xb2,0x00,0x00,0x00,0x26,
+  0xc6,0x06,0x23,0x00,0x00,0xe9,0xd3,0xfa,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0xea,0x00,0xfc,0x00,0xf0,0x4d,0x2f,0x50,
+  0x43,0x2f,0x58,0x2a,0x39,0x34,0x34,0x31
+};
+
+
diff -u --recursive --new-file v1.3.82/linux/drivers/char/digi_fep.h linux/drivers/char/digi_fep.h
--- v1.3.82/linux/drivers/char/digi_fep.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/digi_fep.h	Wed Apr  3 09:20:45 1996
@@ -0,0 +1,517 @@
+/* DigiBoard PCXX Bios */
+
+static unsigned char pcxx_cook[] = {
+  0x4f,0x53,0x18,0x80,0xe9,0xbf,0x15,0x00,0x40,0x28,0x23,0x29,
+  0x46,0x45,0x50,0x4f,0x53,0x20,0x37,0x2e,0x30,0x38,0x20,0x34,
+  0x2f,0x32,0x30,0x2f,0x39,0x35,0x00,0x40,0x28,0x23,0x29,0x28,
+  0x43,0x29,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,
+  0x31,0x39,0x38,0x39,0x2d,0x31,0x39,0x39,0x35,0x20,0x44,0x69,
+  0x67,0x69,0x42,0x6f,0x61,0x72,0x64,0x20,0x49,0x6e,0x63,0x2e,
+  0x00,0xcb,0x0c,0xcb,0x0c,0xe2,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,
+  0x0c,0xcb,0x0c,0xcb,0x0c,0x57,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,
+  0x0c,0x53,0x0b,0xcb,0x0c,0xcb,0x0c,0x42,0x0b,0xcb,0x0c,0xcb,
+  0x0c,0x12,0x0d,0xcb,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,
+  0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,
+  0x0c,0xcb,0x0c,0xcb,0x0c,0x00,0x10,0x80,0x10,0x00,0x11,0x80,
+  0x11,0x00,0x12,0x80,0x12,0x00,0x13,0x80,0x13,0x00,0x14,0x80,
+  0x14,0x00,0x15,0x80,0x15,0x00,0x16,0x80,0x16,0x00,0x17,0x80,
+  0x17,0x78,0x0b,0xb9,0x0b,0x50,0x0c,0xb9,0x0b,0x8d,0x0b,0x8d,
+  0x0b,0x8d,0x0b,0x8d,0x0b,0xc0,0x0b,0xc0,0x0b,0xc0,0x0b,0xc0,
+  0x0b,0x8d,0x0b,0x8d,0x0b,0x8d,0x0b,0x8d,0x0b,0x50,0x0c,0xb9,
+  0x0b,0x50,0x0c,0xb9,0x0b,0x8d,0x0b,0x8d,0x0b,0x8d,0x0b,0x8d,
+  0x0b,0xc0,0x0b,0xc0,0x0b,0xc0,0x0b,0xc0,0x0b,0x8d,0x0b,0x8d,
+  0x0b,0x8d,0x0b,0x8d,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,
+  0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,
+  0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,
+  0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,
+  0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,
+  0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x16,0x00,0xfe,
+  0x11,0xfe,0x0b,0x2c,0x08,0xb5,0x06,0xfe,0x05,0x7e,0x04,0xfe,
+  0x02,0x7e,0x01,0xbe,0x00,0x7e,0x00,0x5e,0x00,0x2e,0x00,0x16,
+  0x00,0x0a,0x00,0x04,0x00,0x16,0x00,0x02,0x00,0x01,0x00,0x00,
+  0x00,0x0e,0x00,0x06,0x00,0x7e,0x04,0xfe,0x02,0x7e,0x01,0xbe,
+  0x00,0x7e,0x00,0x5e,0x00,0x2e,0x00,0x16,0x00,0x0a,0x00,0x04,
+  0x00,0x18,0x00,0x86,0x13,0x03,0x0d,0xdf,0x08,0x41,0x07,0x81,
+  0x06,0xe0,0x04,0x3f,0x03,0x9f,0x01,0xce,0x00,0x89,0x00,0x66,
+  0x00,0x32,0x00,0x18,0x00,0x0b,0x00,0x0b,0x00,0x18,0x00,0x0b,
+  0x00,0x0b,0x00,0x0b,0x00,0x41,0x07,0x81,0x06,0xe0,0x04,0x3f,
+  0x03,0x9f,0x01,0xce,0x00,0x89,0x00,0x66,0x00,0x32,0x00,0x18,
+  0x00,0x0b,0x00,0x0b,0x00,0x00,0x80,0x40,0xc0,0x1f,0x3f,0x7f,
+  0xff,0x00,0x04,0x02,0x06,0x08,0x0c,0x0a,0x0e,0x00,0x04,0x02,
+  0x06,0x08,0x0c,0x0a,0x0e,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
+  0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0x1e,0x06,0x3e,
+  0x06,0xef,0x06,0xf8,0x05,0x0e,0x06,0x55,0x07,0xa0,0x08,0xa0,
+  0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
+  0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
+  0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,
+  0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,
+  0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,
+  0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,
+  0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x5b,0x05,0xea,0x05,0xea,0x05,0xea,
+  0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,
+  0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,
+  0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,
+  0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0x69,
+  0x05,0x77,0x05,0x85,0x05,0x93,0x05,0xa0,0x08,0xa0,0x08,0xa0,
+  0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
+  0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
+  0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
+  0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
+  0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
+  0x08,0x00,0x00,0xfa,0x8a,0x5c,0x50,0xf6,0xc3,0x0e,0x75,0x3c,
+  0xf6,0xc3,0x40,0x75,0x16,0xf6,0xc3,0x10,0x74,0x26,0xf6,0xc3,
+  0x01,0x75,0x13,0xf6,0xc3,0x20,0x75,0x15,0xc7,0x04,0xb6,0x04,
+  0xe9,0xcf,0x00,0x8b,0x44,0x02,0x89,0x04,0xff,0xe0,0xc7,0x04,
+  0x03,0x05,0xe9,0x0e,0x01,0xc7,0x04,0x66,0x08,0xe9,0x6a,0x04,
+  0xf6,0xc3,0x20,0x74,0x1a,0xc7,0x04,0xb3,0x08,0xe9,0xab,0x04,
+  0x8b,0x54,0x20,0xec,0x8a,0xc8,0xf6,0xc3,0x02,0x75,0x42,0xf6,
+  0xc3,0x08,0x75,0x0e,0xeb,0x69,0x90,0xc7,0x04,0x20,0x04,0xfb,
+  0x81,0xc6,0x80,0x00,0xff,0x24,0xf6,0xc1,0x04,0x74,0x27,0x80,
+  0x64,0x50,0xf7,0xf6,0x44,0x51,0x02,0x74,0x13,0xf6,0x44,0x29,
+  0x10,0x74,0x0d,0x8a,0x44,0x5d,0x83,0xc2,0x02,0xee,0x83,0xea,
+  0x02,0xe9,0x49,0x04,0x8a,0x44,0x5c,0x83,0xc2,0x02,0xee,0x83,
+  0xea,0x02,0xe9,0x3c,0x04,0xf6,0x44,0x50,0x04,0x75,0x28,0x83,
+  0x7c,0x24,0xff,0x74,0x1f,0xa1,0x00,0x0e,0x2b,0x44,0x26,0x3d,
+  0x64,0x00,0x77,0x14,0xb0,0x05,0xee,0x8a,0x44,0x75,0x24,0xef,
+  0x88,0x44,0x75,0xee,0x80,0x64,0x50,0xfd,0x80,0x64,0x4b,0xfd,
+  0xe9,0x0e,0x04,0xb0,0x01,0xee,0x90,0x90,0x90,0xec,0xa8,0x01,
+  0x74,0x25,0xb0,0x05,0xee,0x8a,0x44,0x75,0x0c,0x10,0x88,0x44,
+  0x75,0xee,0xa1,0x00,0x0e,0x03,0x44,0x24,0x89,0x44,0x26,0x80,
+  0x64,0x50,0xfb,0x80,0x64,0x4b,0xfb,0x80,0x4c,0x50,0x02,0x80,
+  0x4c,0x4b,0x02,0xe9,0xdb,0x03,0xfa,0x8b,0x54,0x20,0xec,0x8a,
+  0xc8,0x22,0x44,0x52,0x3a,0x44,0x53,0x75,0x19,0x8b,0x7c,0x0c,
+  0x3b,0x7c,0x0a,0x74,0x18,0x8e,0x44,0x08,0x26,0x8a,0x05,0x47,
+  0x23,0x7c,0x0e,0x89,0x7c,0x0c,0x83,0xc2,0x02,0xee,0xfb,0x81,
+  0xc6,0x80,0x00,0xff,0x24,0xb0,0x01,0xee,0x90,0x90,0x90,0xec,
+  0xa8,0x01,0x74,0x0c,0x80,0x64,0x50,0xef,0x80,0x64,0x4b,0xef,
+  0xc7,0x04,0xc3,0x03,0xfb,0x81,0xc6,0x80,0x00,0xff,0x24,0xfa,
+  0x8b,0x54,0x20,0xec,0x8a,0xc8,0x22,0x44,0x52,0x3a,0x44,0x53,
+  0x75,0x3a,0x8b,0x7c,0x0c,0x3b,0x7c,0x0a,0x74,0x1b,0x8e,0x44,
+  0x08,0x26,0x8a,0x05,0x47,0x23,0x7c,0x0e,0x89,0x7c,0x0c,0x8a,
+  0xd8,0x22,0x5c,0x62,0x32,0xff,0x03,0xdb,0x2e,0xff,0xa7,0xc1,
+  0x01,0xb0,0x01,0xee,0x90,0x90,0x90,0xec,0xa8,0x01,0x74,0x0c,
+  0x80,0x64,0x50,0xef,0x80,0x64,0x4b,0xef,0xc7,0x04,0xc3,0x03,
+  0xf6,0xc1,0x01,0x75,0x07,0xfb,0x81,0xc6,0x80,0x00,0xff,0x24,
+  0xe9,0x61,0x03,0xf6,0x44,0x2a,0x01,0x75,0x03,0xe9,0x39,0x03,
+  0xb0,0x27,0xeb,0x42,0x90,0xf6,0x44,0x2a,0x01,0x75,0x03,0xe9,
+  0x2b,0x03,0xb0,0x28,0xeb,0x34,0x90,0xf6,0x44,0x2a,0x01,0x75,
+  0x03,0xe9,0x1d,0x03,0xb0,0x21,0xeb,0x26,0x90,0xf6,0x44,0x2a,
+  0x01,0x75,0x03,0xe9,0x0f,0x03,0xb0,0x29,0xeb,0x18,0x90,0xf6,
+  0x44,0x2a,0x01,0x75,0x03,0xe9,0x01,0x03,0xb0,0x5e,0xeb,0x0a,
+  0x90,0xf6,0x44,0x2a,0x01,0x75,0x03,0xe9,0xf3,0x02,0x88,0x44,
+  0x61,0xb0,0x5c,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0x80,0x4c,
+  0x50,0x40,0xc7,0x04,0xc6,0x05,0xc7,0x44,0x02,0xc6,0x05,0xe9,
+  0xcb,0x02,0xfa,0x8b,0x54,0x20,0xec,0x8a,0xc8,0x22,0x44,0x52,
+  0x3a,0x44,0x53,0x75,0x12,0x80,0x64,0x50,0xbf,0xc7,0x04,0x03,
+  0x05,0x83,0x44,0x30,0x02,0x8a,0x44,0x61,0xe9,0xb9,0x02,0xe9,
+  0xa7,0x02,0xf6,0x44,0x2a,0x02,0x75,0x03,0xe9,0xaa,0x02,0x2c,
+  0x20,0xe9,0xa5,0x02,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0xf6,
+  0x44,0x2b,0x40,0x75,0x03,0xe9,0x89,0x02,0xb8,0x7f,0x00,0xe9,
+  0x9b,0x01,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0xf6,0x44,0x2b,
+  0x80,0x75,0xed,0xe9,0x73,0x02,0x83,0xc2,0x02,0xee,0x83,0xea,
+  0x02,0xf7,0x44,0x30,0xff,0xff,0x74,0x03,0xff,0x4c,0x30,0xf6,
+  0x44,0x2b,0x20,0x75,0x03,0xe9,0x59,0x02,0xb8,0x02,0x00,0xe9,
+  0x6b,0x01,0xb3,0x18,0x22,0x5c,0x2b,0x75,0x16,0x83,0xc2,0x02,
+  0xee,0x83,0xea,0x02,0x8b,0x44,0x30,0x05,0x08,0x00,0x25,0xf8,
+  0xff,0x89,0x44,0x30,0xe9,0x36,0x02,0x80,0xfb,0x18,0x75,0x57,
+  0xb0,0x20,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0x8b,0x44,0x30,
+  0x8b,0xd8,0x05,0x08,0x00,0x25,0xf8,0xff,0x89,0x44,0x30,0x2b,
+  0xc3,0x48,0x74,0x38,0x89,0x44,0x32,0x80,0x4c,0x50,0x40,0xc7,
+  0x44,0x02,0x8f,0x06,0xc7,0x04,0x8f,0x06,0xe9,0x02,0x02,0xfa,
+  0x8b,0x54,0x20,0xec,0x8a,0xc8,0x22,0x44,0x52,0x3a,0x44,0x53,
+  0x75,0x16,0xb0,0x20,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0xff,
+  0x4c,0x32,0x75,0x08,0x80,0x64,0x50,0xbf,0xc7,0x04,0x03,0x05,
+  0xe9,0xda,0x01,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0x80,0xfb,
+  0x08,0x75,0x18,0x8b,0x44,0x30,0x8b,0xd8,0x05,0x08,0x00,0x25,
+  0xf8,0xff,0x89,0x44,0x30,0x2b,0xc3,0x3d,0x05,0x00,0x7c,0xdc,
+  0xe9,0xce,0x00,0x8b,0x44,0x30,0x8b,0xd8,0x05,0x08,0x00,0x25,
+  0xf8,0xff,0x89,0x44,0x30,0xb8,0x02,0x00,0xe9,0xba,0x00,0xf6,
+  0x44,0x2a,0x20,0x75,0x43,0xf6,0x44,0x2a,0x04,0x74,0x42,0xf6,
+  0x44,0x2a,0x10,0x74,0x07,0xf7,0x44,0x30,0xff,0xff,0x74,0x30,
+  0xb0,0x0d,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0x80,0x4c,0x50,
+  0x40,0xc7,0x04,0x21,0x07,0xc7,0x44,0x02,0x21,0x07,0xe9,0x70,
+  0x01,0xfa,0x8b,0x54,0x20,0xec,0x8a,0xc8,0x22,0x44,0x52,0x3a,
+  0x44,0x53,0x75,0x1c,0x80,0x64,0x50,0xbf,0xc7,0x04,0x03,0x05,
+  0xb0,0x0a,0xeb,0x2b,0x90,0xb0,0x0a,0x83,0xc2,0x02,0xee,0x83,
+  0xea,0x02,0xf6,0x44,0x2b,0x01,0x75,0x03,0xe9,0x42,0x01,0xb8,
+  0x05,0x00,0xeb,0x55,0x90,0xf6,0x44,0x2a,0x08,0x75,0xe2,0xf6,
+  0x44,0x2a,0x10,0x74,0x06,0x83,0x7c,0x30,0x00,0x74,0x13,0x83,
+  0xc2,0x02,0xee,0x83,0xea,0x02,0xb3,0x06,0x22,0x5c,0x2b,0x75,
+  0x08,0xc7,0x44,0x30,0x00,0x00,0xe9,0x14,0x01,0x80,0xfb,0x02,
+  0x75,0x14,0x8b,0x44,0x30,0xc1,0xe8,0x04,0x05,0x03,0x00,0x3d,
+  0x06,0x00,0x72,0x14,0xb8,0x06,0x00,0xeb,0x0f,0x90,0x80,0xfb,
+  0x04,0x75,0x06,0xb8,0x05,0x00,0xeb,0x04,0x90,0xb8,0x09,0x00,
+  0xc7,0x44,0x30,0x00,0x00,0xf6,0x44,0x2a,0x40,0x74,0x45,0x3d,
+  0x20,0x00,0x77,0x40,0xbb,0x01,0x00,0x3d,0x03,0x00,0x7e,0x03,
+  0xbb,0x02,0x00,0x89,0x5c,0x32,0x80,0x4c,0x50,0x40,0xc7,0x44,
+  0x02,0xd2,0x07,0xc7,0x04,0xd2,0x07,0xe9,0xbf,0x00,0xfa,0x8b,
+  0x54,0x20,0xec,0x8a,0xc8,0x22,0x44,0x52,0x3a,0x44,0x53,0x75,
+  0x10,0x8a,0x44,0x60,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0x83,
+  0x6c,0x32,0x01,0x7e,0x50,0xe9,0x9d,0x00,0x05,0x06,0x00,0x03,
+  0xc0,0x89,0x44,0x32,0x80,0x4c,0x50,0x40,0xc7,0x44,0x02,0x0c,
+  0x08,0xc7,0x04,0x0c,0x08,0xe9,0x85,0x00,0xfa,0x8b,0x54,0x20,
+  0xec,0x8a,0xc8,0xb0,0x01,0xee,0x90,0x90,0x90,0xec,0xa8,0x01,
+  0x74,0x0f,0xa1,0x00,0x0e,0x01,0x44,0x32,0xc7,0x44,0x02,0x30,
+  0x08,0xc7,0x04,0x30,0x08,0xeb,0x62,0x90,0x8b,0x54,0x20,0xec,
+  0x8a,0xc8,0xa1,0x00,0x0e,0x2b,0x44,0x32,0x3d,0xe8,0x03,0x77,
+  0xec,0x80,0x64,0x50,0xbf,0xc7,0x04,0x03,0x05,0xeb,0x46,0x90,
+  0xb0,0x01,0xee,0x90,0x90,0x90,0xec,0xa8,0x01,0x74,0x3a,0x80,
+  0x64,0x50,0xef,0x80,0x64,0x4b,0xef,0xc7,0x04,0xb3,0x08,0xeb,
+  0x2c,0x90,0xfa,0x8b,0x54,0x20,0xec,0x8a,0xc8,0x22,0x44,0x52,
+  0x3a,0x44,0x53,0x75,0x1c,0x8b,0x7c,0x0c,0x3b,0x7c,0x0a,0x74,
+  0xcf,0x8e,0x44,0x08,0x26,0x8a,0x05,0x47,0x23,0x7c,0x0e,0x89,
+  0x7c,0x0c,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0xf6,0xc1,0x01,
+  0x75,0x26,0xfb,0x81,0xc6,0x80,0x00,0xff,0x24,0xff,0x44,0x30,
+  0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0xf6,0xc1,0x01,0x75,0x10,
+  0xfb,0x81,0xc6,0x80,0x00,0xff,0x24,0xfa,0x8b,0x54,0x20,0xec,
+  0xa8,0x01,0x74,0xda,0xc6,0x44,0x49,0x02,0x8b,0x7c,0x12,0x8e,
+  0x44,0x10,0xb0,0x01,0xee,0x90,0x90,0x90,0xec,0x8a,0xe0,0x90,
+  0xb0,0x30,0xee,0x83,0xc2,0x02,0x90,0xec,0x83,0xea,0x02,0x23,
+  0x44,0x34,0xff,0x64,0x06,0xb3,0x1c,0x22,0x5c,0x51,0x75,0x1a,
+  0xf6,0x44,0x29,0x04,0x74,0x21,0xf6,0x44,0x29,0x20,0x75,0x2b,
+  0x80,0x7c,0x5e,0x00,0x75,0x1d,0xc7,0x44,0x06,0x58,0x0a,0xe9,
+  0x56,0x01,0xf6,0xc3,0x10,0x75,0x2e,0xf6,0xc3,0x04,0x75,0x74,
+  0xeb,0x6b,0x90,0xc7,0x44,0x06,0x62,0x0a,0xe9,0x4b,0x01,0xc7,
+  0x44,0x06,0x53,0x0a,0xe9,0x34,0x01,0x80,0x7c,0x5e,0x00,0x75,
+  0x08,0xc7,0x44,0x06,0xca,0x09,0xe9,0x9d,0x00,0xc7,0x44,0x06,
+  0xc5,0x09,0xe9,0x90,0x00,0x0a,0xc0,0x74,0x2a,0xfe,0x4c,0x63,
+  0x74,0x1a,0x80,0xe3,0xef,0x75,0xc4,0xf6,0x44,0x29,0x04,0x74,
+  0x21,0xf6,0x44,0x29,0x20,0x75,0x21,0x80,0x7c,0x5e,0x00,0x75,
+  0x18,0xe9,0x00,0x01,0x80,0x64,0x51,0xef,0x80,0xe3,0xef,0x75,
+  0xa6,0xeb,0x85,0x80,0x64,0x51,0xef,0xe9,0x06,0x01,0xe9,0xf5,
+  0x00,0xe9,0xe3,0x00,0x80,0x7c,0x5e,0x00,0x75,0x4f,0xeb,0x52,
+  0x90,0x80,0x64,0x51,0xf7,0xe9,0xe2,0x00,0x80,0x64,0x53,0x3f,
+  0x80,0x64,0x54,0xfe,0x80,0x4c,0x58,0x01,0x80,0x64,0x51,0xfb,
+  0xf6,0x44,0x29,0x40,0x75,0x2c,0x3a,0x44,0x5d,0x74,0x27,0x3a,
+  0x44,0x5c,0x74,0x22,0xf6,0x44,0x29,0x20,0x74,0x0a,0x3a,0x44,
+  0x5a,0x74,0x17,0x3a,0x44,0x5b,0x74,0x12,0xf6,0x44,0x5e,0xff,
+  0x74,0x09,0x3a,0x44,0x5e,0x75,0x04,0x80,0x4c,0x51,0x08,0xe9,
+  0xa0,0x00,0xe9,0xab,0x00,0x3a,0x44,0x5e,0x74,0x7d,0x3a,0x44,
+  0x5c,0x74,0x3d,0x3a,0x44,0x5d,0x74,0x55,0x3a,0x44,0x5a,0x74,
+  0x08,0x3a,0x44,0x5b,0x74,0x18,0xe9,0x81,0x00,0xf6,0x44,0x53,
+  0x40,0x74,0x07,0x80,0x64,0x53,0xbf,0xe9,0x82,0x00,0x3a,0x44,
+  0x5b,0x74,0x03,0xeb,0x7b,0x90,0x80,0x4c,0x53,0x40,0xf6,0x44,
+  0x29,0x08,0x74,0x70,0x80,0x4c,0x51,0x04,0xc7,0x44,0x06,0xe1,
+  0x08,0xeb,0x65,0x90,0xf6,0x44,0x53,0x80,0x74,0x0f,0x80,0x64,
+  0x53,0x7f,0x80,0x64,0x54,0xfe,0x80,0x4c,0x58,0x01,0xeb,0x50,
+  0x90,0x3a,0x44,0x5d,0x74,0x03,0xeb,0x48,0x90,0x80,0x4c,0x53,
+  0x80,0x80,0x4c,0x54,0x01,0x80,0x4c,0x58,0x01,0xf6,0x44,0x29,
+  0x08,0x74,0x35,0x80,0x4c,0x51,0x04,0xc7,0x44,0x06,0xe1,0x08,
+  0xeb,0x2a,0x90,0x80,0x4c,0x51,0x08,0xc7,0x44,0x06,0xe1,0x08,
+  0xeb,0x10,0x90,0x3a,0x44,0x5e,0x74,0xef,0x3a,0x44,0x5c,0x74,
+  0xaf,0x3a,0x44,0x5d,0x74,0xc7,0x3d,0xff,0x00,0x73,0x26,0xaa,
+  0x23,0x7c,0x16,0x3b,0x7c,0x14,0x74,0x4f,0xec,0xa8,0x01,0x74,
+  0x03,0xe9,0x4e,0xfe,0x89,0x7c,0x12,0x2b,0x7c,0x14,0x23,0x7c,
+  0x16,0x3b,0x7c,0x1c,0x73,0x46,0xfb,0x81,0xc6,0x80,0x00,0xff,
+  0x24,0x0a,0xe4,0x75,0x1e,0xb3,0x0c,0x22,0x5c,0x28,0x80,0xfb,
+  0x08,0x75,0xcc,0xaa,0x23,0x7c,0x16,0x3b,0x7c,0x14,0x74,0x1b,
+  0xaa,0x23,0x7c,0x16,0x3b,0x7c,0x14,0x74,0x12,0xeb,0xc1,0xf6,
+  0x44,0x28,0x04,0x75,0xbb,0xf6,0x44,0x28,0x08,0x75,0x50,0x32,
+  0xc0,0xeb,0xa8,0x4f,0x23,0x7c,0x16,0x89,0x7c,0x12,0xc6,0x44,
+  0x59,0x01,0xeb,0xa4,0xf6,0x44,0x51,0x02,0x74,0x07,0xfb,0x81,
+  0xc6,0x80,0x00,0xff,0x24,0x80,0x4c,0x51,0x02,0xb0,0x05,0xee,
+  0xb0,0x82,0x22,0x44,0x5f,0xf6,0xd0,0x22,0x44,0x75,0x88,0x44,
+  0x75,0xee,0xf6,0x44,0x29,0x10,0x74,0x10,0x80,0x4c,0x54,0x04,
+  0x80,0x4c,0x58,0x04,0x80,0x74,0x50,0x08,0xc7,0x04,0xc3,0x03,
+  0xfb,0x81,0xc6,0x80,0x00,0xff,0x24,0x26,0xc6,0x05,0xff,0x47,
+  0x23,0x7c,0x16,0x3b,0x7c,0x14,0x74,0xa7,0x32,0xff,0xf6,0x44,
+  0x29,0x80,0x74,0x0a,0x8a,0xdc,0xc0,0xeb,0x04,0x2e,0x8a,0xbf,
+  0xb1,0x01,0x26,0x88,0x3d,0x47,0x23,0x7c,0x16,0x3b,0x7c,0x14,
+  0x74,0x89,0xaa,0x23,0x7c,0x16,0x3b,0x7c,0x14,0x74,0x80,0xe9,
+  0x2e,0xff,0x1e,0x2e,0x8e,0x1e,0xc1,0x03,0xff,0x06,0x1c,0x0e,
+  0x60,0xbe,0x00,0x14,0xeb,0x0f,0x90,0x1e,0x2e,0x8e,0x1e,0xc1,
+  0x03,0xff,0x06,0x1a,0x0e,0x60,0xbe,0x00,0x10,0xb9,0x08,0x00,
+  0x8b,0x54,0x20,0xb0,0x03,0xee,0x90,0x90,0x32,0xff,0xec,0x8a,
+  0xd8,0x02,0xd8,0x2e,0xff,0xa7,0xa9,0x00,0x81,0xc6,0x00,0x01,
+  0x8b,0x54,0x20,0x0b,0xd2,0xe0,0xe4,0xb8,0x00,0x80,0xba,0x22,
+  0xff,0xef,0x61,0x1f,0xcf,0x81,0xce,0x80,0x00,0x8b,0x54,0x20,
+  0xff,0x06,0x20,0x0e,0xb0,0x01,0xee,0x8a,0x44,0x71,0x24,0xe7,
+  0x88,0x44,0x71,0xee,0xc6,0x44,0x49,0x02,0x80,0x4c,0x50,0x20,
+  0xc7,0x04,0xc3,0x03,0x81,0xe6,0x7f,0xff,0x8b,0x54,0x20,0xeb,
+  0xae,0x81,0xce,0x80,0x00,0x8b,0x54,0x20,0xff,0x06,0x22,0x0e,
+  0xec,0x0a,0xc0,0x79,0x7a,0x80,0x4c,0x51,0x10,0xc7,0x44,0x06,
+  0xe1,0x08,0xc6,0x44,0x63,0x04,0xf6,0x44,0x51,0x04,0x74,0x08,
+  0x80,0x64,0x51,0xfb,0x80,0x64,0x53,0x3f,0xf6,0x44,0x28,0x01,
+  0x75,0x59,0xf6,0x44,0x28,0x02,0x75,0x4f,0x8b,0x7c,0x12,0x8c,
+  0xc3,0x8e,0x44,0x10,0xf6,0x44,0x28,0x08,0x74,0x1e,0xb0,0xff,
+  0xaa,0x23,0x7c,0x16,0x3b,0x7c,0x14,0x74,0x26,0x32,0xc0,0xf6,
+  0x44,0x29,0x80,0x74,0x02,0xb0,0x10,0xaa,0x23,0x7c,0x16,0x3b,
+  0x7c,0x14,0x74,0x13,0x32,0xc0,0xaa,0x23,0x7c,0x16,0x3b,0x7c,
+  0x14,0x74,0x08,0x8e,0xc3,0x89,0x7c,0x12,0xeb,0x15,0x90,0x8e,
+  0xc3,0x4f,0x23,0x7c,0x16,0x89,0x7c,0x12,0xc6,0x44,0x59,0x01,
+  0xeb,0x05,0x90,0x80,0x4c,0x4f,0x01,0xb0,0x10,0xee,0x81,0xe6,
+  0x7f,0xff,0x8b,0x54,0x20,0xe9,0x17,0xff,0xff,0x06,0x1e,0x0e,
+  0xe9,0x10,0xff,0x1e,0x2e,0x8e,0x1e,0xc1,0x03,0x50,0x52,0x55,
+  0x8b,0xec,0x8b,0x46,0x08,0xa3,0x12,0x0e,0x32,0xe4,0xa0,0x22,
+  0x0c,0xa3,0x10,0x0e,0xff,0x06,0x00,0x0e,0x83,0x06,0x0e,0x0e,
+  0x0a,0x83,0x3e,0x04,0x0e,0x00,0x74,0x31,0x8b,0x16,0x00,0x0e,
+  0x2b,0x16,0x02,0x0e,0x3b,0x16,0x04,0x0e,0x72,0x23,0x8b,0x16,
+  0x00,0x0e,0x89,0x16,0x02,0x0e,0x8b,0x16,0x18,0x0d,0x3b,0x16,
+  0x1a,0x0d,0x74,0x11,0x80,0x3e,0x10,0x0c,0x01,0x74,0x16,0xb0,
+  0x00,0x90,0xe6,0x00,0x0c,0x08,0x90,0xe6,0x00,0xb8,0x00,0x80,
+  0xba,0x22,0xff,0xef,0x5d,0x5a,0x58,0x1f,0xcf,0xb0,0x80,0xe6,
+  0x00,0xa0,0x11,0x0c,0x0c,0x10,0xa2,0x11,0x0c,0xeb,0xe6,0x1e,
+  0x2e,0x8e,0x1e,0xc1,0x03,0xff,0x06,0x28,0x0e,0x55,0x8b,0xec,
+  0x8b,0x6e,0x02,0x89,0x2e,0x16,0x0e,0x5d,0x1f,0xcf,0x1e,0x2e,
+  0x8e,0x1e,0xc1,0x03,0xff,0x06,0x24,0x0e,0x55,0x8b,0xec,0x8b,
+  0x6e,0x02,0x89,0x2e,0x14,0x0e,0x5d,0x80,0x3e,0x10,0x0c,0x01,
+  0x75,0x12,0x50,0xa0,0x11,0x0c,0x0c,0x01,0xa2,0x11,0x0c,0xe4,
+  0x00,0x90,0x90,0x24,0x7f,0xe6,0x00,0x58,0x1f,0xcf,0x1e,0x06,
+  0x60,0xb8,0x00,0x80,0xba,0x22,0xff,0xef,0x2e,0x8e,0x1e,0xc1,
+  0x03,0x2e,0x8e,0x06,0xc1,0x03,0x2e,0xff,0x06,0x30,0x0d,0xfc,
+  0xff,0x26,0x2e,0x0e,0x00,0x00,0xfb,0x40,0x43,0x41,0x42,0x46,
+  0x47,0x45,0xeb,0xf6,0xc3,0x00,0x00,0x8f,0x06,0x2e,0x0e,0x2e,
+  0xff,0x06,0x3d,0x0d,0xb8,0x00,0x00,0xba,0x58,0xff,0xef,0xb8,
+  0x00,0xe0,0xba,0x5e,0xff,0xef,0x61,0x07,0x1f,0xcf,0xc2,0xfe,
+  0xff,0x8b,0x7c,0x0a,0x2b,0x7c,0x0c,0x23,0x7c,0x0e,0x3b,0x7c,
+  0x18,0x77,0x2e,0xc6,0x44,0x4d,0x00,0x80,0x4c,0x4f,0x02,0xeb,
+  0x5a,0x90,0x8b,0x7c,0x0a,0x3b,0x7c,0x0c,0x75,0x1b,0x8b,0x3e,
+  0x10,0x0d,0x3b,0x3e,0x12,0x0d,0x75,0x53,0xf6,0x44,0x4b,0xff,
+  0x75,0x4d,0xc6,0x44,0x4c,0x00,0x80,0x4c,0x4f,0x04,0xeb,0x43,
+  0x90,0xf6,0x44,0x50,0x10,0x75,0x3c,0xeb,0x09,0x90,0x8b,0x7c,
+  0x0a,0x2b,0x7c,0x0c,0x74,0x31,0x80,0x4c,0x50,0x10,0x80,0x4c,
+  0x4b,0x10,0xc7,0x04,0xc3,0x03,0xeb,0x23,0x90,0xfa,0x8b,0x36,
+  0x08,0x0e,0x8b,0x54,0x20,0xec,0x8a,0xf8,0x8a,0x5c,0x54,0x32,
+  0xfb,0xf6,0x44,0x4d,0xff,0x75,0x8e,0xf6,0x44,0x4c,0xff,0x75,
+  0xa1,0xf6,0x44,0x50,0x10,0x74,0xc7,0xec,0x32,0xc3,0x22,0xf8,
+  0x83,0x2e,0x10,0x0e,0x01,0x78,0x05,0xd0,0x6c,0x49,0x72,0x45,
+  0x8b,0x7c,0x12,0x2b,0x7c,0x14,0x74,0x22,0x80,0x7c,0x4e,0x00,
+  0x74,0x1c,0x23,0x7c,0x16,0x03,0xff,0x3b,0x7c,0x16,0x73,0x43,
+  0x8b,0x0e,0x0e,0x0e,0x2b,0x4c,0x6e,0x3b,0x4c,0x22,0x73,0x37,
+  0x80,0x7c,0x49,0x00,0x74,0x31,0xf6,0x44,0x51,0x02,0x75,0x3c,
+  0xec,0x32,0xc3,0x22,0xf8,0x80,0xe7,0x38,0xfb,0x89,0x1e,0x30,
+  0x0e,0xbe,0x00,0x10,0xff,0x14,0xeb,0x61,0x90,0xb0,0x01,0xee,
+  0x8a,0x44,0x71,0x0c,0x10,0x88,0x44,0x71,0xee,0x80,0x64,0x50,
+  0xdf,0xc7,0x04,0xc3,0x03,0xeb,0xa5,0xc6,0x44,0x4e,0x00,0x8b,
+  0x0e,0x0e,0x0e,0x89,0x4c,0x6e,0x80,0x4c,0x4f,0x08,0xeb,0xbe,
+  0x8b,0x7c,0x12,0x2b,0x7c,0x14,0x23,0x7c,0x16,0x3b,0x7c,0x1a,
+  0x73,0xb6,0x80,0x64,0x51,0xfd,0xf6,0x44,0x29,0x10,0x74,0x10,
+  0x80,0x64,0x54,0xfb,0x80,0x4c,0x58,0x04,0x80,0x74,0x50,0x08,
+  0xc7,0x04,0xc3,0x03,0xb0,0x05,0xee,0xb0,0x82,0x22,0x44,0x5f,
+  0x0a,0x44,0x75,0x88,0x44,0x75,0xee,0xeb,0x8b,0xfa,0x8b,0x36,
+  0x08,0x0e,0x8b,0x1e,0x30,0x0e,0x8a,0xcb,0xe5,0x80,0x23,0x44,
+  0x2e,0x74,0x02,0xf6,0xd1,0x80,0xe1,0x40,0x0a,0xf9,0x8a,0xdf,
+  0x22,0x5c,0x55,0x30,0x5c,0x54,0x32,0xfb,0x88,0x7c,0x55,0x0a,
+  0x5c,0x58,0x88,0x5c,0x58,0x22,0x5c,0x56,0x75,0x24,0x80,0x7c,
+  0x4f,0x00,0x75,0x22,0xfb,0x03,0x74,0x1e,0x89,0x36,0x08,0x0e,
+  0xff,0x06,0x26,0x0e,0x8b,0x3e,0x12,0x0d,0x3b,0x3e,0x10,0x0d,
+  0x75,0x46,0xbe,0x00,0x10,0xff,0x14,0xe9,0xd3,0xfe,0x80,0x4c,
+  0x4f,0x20,0x8b,0x3e,0x18,0x0d,0x8a,0x44,0x48,0x8a,0x64,0x4f,
+  0x89,0x85,0x00,0x08,0x8a,0x44,0x54,0x8a,0x64,0x57,0x89,0x85,
+  0x02,0x08,0x83,0xc7,0x04,0x81,0xe7,0xfc,0x03,0x3b,0x3e,0x1a,
+  0x0d,0x74,0x13,0x88,0x44,0x57,0xc6,0x44,0x4f,0x00,0x8a,0x44,
+  0x56,0xf6,0xd0,0x20,0x44,0x58,0x89,0x3e,0x18,0x0d,0xeb,0xa4,
+  0xff,0x06,0x2c,0x0e,0xbe,0x00,0x10,0xff,0x14,0xfa,0x8b,0x3e,
+  0x12,0x0d,0x81,0xc7,0x00,0x04,0x8a,0x5d,0x01,0x83,0xe3,0x0f,
+  0x03,0xdb,0x2e,0x8b,0xb7,0x89,0x00,0x8b,0x54,0x20,0x0b,0xd2,
+  0x74,0x0d,0x8a,0x1d,0x83,0xe3,0x1f,0x03,0xdb,0xfa,0x2e,0xff,
+  0xa7,0x9c,0x0f,0xff,0x06,0x2a,0x0e,0x8b,0x3e,0x12,0x0d,0x8b,
+  0x36,0x18,0x0d,0x8b,0x9d,0x00,0x04,0x89,0x9c,0x00,0x08,0x8b,
+  0x9d,0x02,0x04,0x89,0x9c,0x02,0x08,0x83,0xc6,0x04,0x81,0xe6,
+  0xfc,0x03,0x3b,0x36,0x1a,0x0d,0x74,0x04,0x89,0x36,0x18,0x0d,
+  0xfb,0x8b,0x3e,0x12,0x0d,0x83,0xc7,0x04,0x81,0xe7,0xfc,0x03,
+  0x89,0x3e,0x12,0x0d,0xbe,0x00,0x10,0xff,0x14,0xe9,0x1d,0xfe,
+  0xdc,0x0f,0xe4,0x0f,0xec,0x0f,0x0d,0x10,0x1c,0x10,0x57,0x0f,
+  0x2f,0x10,0x57,0x0f,0x3b,0x10,0x54,0x10,0x83,0x10,0xcf,0x10,
+  0xdb,0x10,0xe4,0x10,0xeb,0x10,0x35,0x11,0x7d,0x11,0x83,0x11,
+  0xa1,0x11,0xb9,0x11,0xf2,0x11,0x38,0x12,0x03,0x13,0x0c,0x13,
+  0x57,0x0f,0x57,0x0f,0x57,0x0f,0x57,0x0f,0x57,0x0f,0x57,0x0f,
+  0x57,0x0f,0x57,0x0f,0x8b,0x45,0x02,0x89,0x44,0x1a,0xeb,0xa0,
+  0x8b,0x45,0x02,0x89,0x44,0x1c,0xeb,0x98,0x8b,0x45,0x02,0x8b,
+  0x5c,0x0a,0x2b,0x5c,0x0c,0x23,0x5c,0x0e,0x8b,0x4c,0x0a,0x2b,
+  0xc8,0x23,0x4c,0x0e,0x3b,0xd9,0x76,0x06,0x23,0x44,0x0e,0x89,
+  0x44,0x0c,0xe9,0x77,0xff,0x80,0x4c,0x53,0x80,0x80,0x4c,0x54,
+  0x01,0x80,0x4c,0x58,0x01,0xe9,0x68,0xff,0x80,0x64,0x53,0x3f,
+  0x80,0x64,0x54,0xfe,0x80,0x4c,0x58,0x01,0x80,0x64,0x51,0xfb,
+  0xe9,0x55,0xff,0x8b,0x45,0x02,0x88,0x44,0x5a,0x88,0x64,0x5b,
+  0xe9,0x49,0xff,0x8b,0x45,0x02,0x0b,0xc0,0x74,0x03,0x89,0x44,
+  0x24,0x80,0x4c,0x50,0x04,0x80,0x4c,0x4b,0x04,0xc7,0x04,0xc3,
+  0x03,0xe9,0x30,0xff,0x8b,0x5d,0x02,0xf6,0xd7,0x22,0x7c,0x54,
+  0x0a,0xdf,0x8a,0x44,0x54,0x32,0xc3,0x24,0x82,0x30,0x44,0x54,
+  0xb0,0x05,0xee,0x8a,0x44,0x75,0x32,0xd8,0x8a,0x7c,0x5f,0xf6,
+  0xd7,0x22,0xdf,0x80,0xe3,0x82,0x32,0xc3,0x88,0x44,0x75,0xee,
+  0xe9,0x01,0xff,0x8b,0x5d,0x02,0xf6,0xc7,0x04,0x75,0x08,0x80,
+  0x64,0x53,0x3f,0x80,0x64,0x51,0xfb,0x8a,0x44,0x29,0x32,0xc7,
+  0xa8,0x10,0x74,0x0e,0xf6,0x44,0x51,0x02,0x74,0x08,0x80,0x74,
+  0x50,0x08,0xc7,0x04,0xc3,0x03,0x88,0x5c,0x28,0x88,0x7c,0x29,
+  0xb4,0x60,0xf6,0xc3,0x10,0x74,0x03,0x80,0xcc,0x10,0x8a,0x44,
+  0x62,0xf6,0xc3,0x20,0x74,0x02,0x24,0x7f,0x89,0x44,0x34,0xc7,
+  0x44,0x06,0xe1,0x08,0xe9,0xb5,0xfe,0x8b,0x45,0x02,0x88,0x44,
+  0x5c,0x88,0x64,0x5d,0xe9,0xa9,0xfe,0x8b,0x45,0x02,0x89,0x44,
+  0x18,0xe9,0xa0,0xfe,0xff,0x1e,0x24,0x0d,0xe9,0x99,0xfe,0xf6,
+  0x44,0x51,0x02,0x75,0x41,0x8b,0x44,0x12,0x2b,0x44,0x14,0x23,
+  0x44,0x16,0x3b,0x44,0x1a,0x72,0x33,0x80,0x4c,0x51,0x02,0xf6,
+  0x44,0x29,0x10,0x74,0x10,0x80,0x4c,0x54,0x04,0x80,0x4c,0x58,
+  0x04,0x80,0x74,0x50,0x08,0xc7,0x04,0xc3,0x03,0xf6,0x44,0x5f,
+  0x82,0x74,0x13,0xb0,0x05,0xee,0x8a,0x44,0x75,0xb4,0x82,0x22,
+  0x64,0x5f,0xf6,0xd4,0x22,0xc4,0x88,0x44,0x75,0xee,0xe9,0x4f,
+  0xfe,0xf6,0x44,0x51,0x02,0x74,0x3f,0x8b,0x44,0x12,0x2b,0x44,
+  0x14,0x23,0x44,0x16,0x3b,0x44,0x1c,0x73,0xe9,0x80,0x64,0x51,
+  0xfd,0xf6,0x44,0x29,0x10,0x74,0x10,0x80,0x64,0x54,0xfb,0x80,
+  0x4c,0x58,0x04,0x80,0x74,0x50,0x08,0xc7,0x04,0xc3,0x03,0xf6,
+  0x44,0x5f,0x02,0x74,0x11,0xb0,0x05,0xee,0x8a,0x44,0x75,0xb4,
+  0x82,0x22,0x64,0x5f,0x0a,0xc4,0x88,0x44,0x75,0xee,0xe9,0x07,
+  0xfe,0xe8,0x8a,0x02,0xe9,0x01,0xfe,0x8b,0x45,0x02,0xbb,0x10,
+  0x27,0xf7,0xe3,0xbb,0x0f,0x00,0xf7,0xf3,0xa3,0x06,0x0e,0xba,
+  0x52,0xff,0xef,0xba,0x50,0xff,0xb8,0x00,0x00,0xef,0xe9,0xe3,
+  0xfd,0x8b,0x45,0x02,0x3a,0x06,0x22,0x0c,0x72,0x0c,0x3b,0x06,
+  0x1a,0x0c,0x77,0x06,0xe8,0xab,0x01,0xe9,0xce,0xfd,0xe9,0x9e,
+  0xfd,0x8b,0x45,0x02,0x88,0x44,0x2a,0x88,0x64,0x2b,0x0b,0xc0,
+  0x75,0x07,0x80,0x64,0x50,0xfe,0xeb,0x10,0x90,0xf6,0x44,0x50,
+  0x01,0x75,0x09,0x80,0x4c,0x50,0x01,0xc7,0x44,0x30,0x00,0x00,
+  0xa8,0x80,0x75,0x07,0xc6,0x44,0x60,0x00,0xeb,0x05,0x90,0xc6,
+  0x44,0x60,0x7f,0xc7,0x04,0xc3,0x03,0xe9,0x92,0xfd,0x8b,0x5d,
+  0x02,0xf6,0xd7,0x22,0x7c,0x5f,0x0a,0xdf,0x8a,0xfb,0x88,0x5c,
+  0x5f,0x8a,0x44,0x52,0x8a,0x64,0x53,0x8b,0xcb,0x33,0xc8,0x81,
+  0xe1,0x38,0x38,0x33,0xc1,0x88,0x44,0x52,0x88,0x64,0x53,0xb0,
+  0x05,0xee,0xf6,0xd3,0x22,0x5c,0x54,0xf6,0x44,0x51,0x02,0x75,
+  0x02,0x0a,0xdf,0x8a,0x44,0x75,0x32,0xd8,0x80,0xe3,0x82,0x32,
+  0xc3,0x88,0x44,0x75,0xee,0xe9,0x4c,0xfd,0x8b,0x5d,0x02,0x88,
+  0x5c,0x2c,0x88,0x7c,0x2d,0x8b,0xcb,0x83,0xe3,0x0f,0x03,0xdb,
+  0x80,0x3e,0x10,0x0c,0x01,0x75,0x1f,0xa1,0x0e,0x0c,0x86,0xe0,
+  0x3d,0x32,0x31,0x73,0x15,0xf6,0xc5,0x04,0x75,0x08,0x2e,0x8b,
+  0x9f,0x69,0x01,0xeb,0x1b,0x90,0x2e,0x8b,0x9f,0x89,0x01,0xeb,
+  0x13,0x90,0xf6,0xc5,0x04,0x75,0x08,0x2e,0x8b,0x9f,0x29,0x01,
+  0xeb,0x06,0x90,0x2e,0x8b,0x9f,0x49,0x01,0xb0,0x0c,0xee,0x8a,
+  0xc3,0x88,0x44,0x7c,0xee,0xb0,0x0d,0x90,0x90,0xee,0x8a,0xc7,
+  0x88,0x44,0x7d,0xee,0xb0,0x04,0xee,0xb0,0x44,0xf6,0xc1,0x40,
+  0x74,0x0c,0xf6,0xc1,0x80,0x74,0x05,0x04,0x04,0xeb,0x03,0x90,
+  0x0c,0x08,0xf6,0xc5,0x01,0x74,0x09,0x0c,0x01,0xf6,0xc5,0x02,
+  0x75,0x02,0x0c,0x02,0x88,0x44,0x74,0xee,0xb0,0x03,0x90,0x90,
+  0xee,0x8a,0xd9,0x80,0xe3,0x30,0xc0,0xeb,0x04,0x32,0xff,0x2e,
+  0x8a,0xa7,0xa9,0x01,0x8a,0x44,0x73,0x24,0x3f,0x0a,0xc4,0x88,
+  0x44,0x73,0xee,0x90,0x90,0xb0,0x05,0xee,0xd0,0xec,0x8a,0x44,
+  0x75,0x24,0x9f,0x0a,0xc4,0x88,0x44,0x75,0xee,0x2e,0x8a,0x87,
+  0xad,0x01,0x88,0x44,0x62,0xf6,0x44,0x28,0x20,0x74,0x02,0x24,
+  0x7f,0x88,0x44,0x34,0xe9,0x81,0xfc,0x8a,0x45,0x02,0x88,0x44,
+  0x5e,0xe9,0x78,0xfc,0x8b,0x45,0x02,0xba,0x5a,0xff,0xef,0x9c,
+  0xff,0x36,0x26,0x0d,0xff,0x36,0x24,0x0d,0x1e,0x06,0x60,0x8b,
+  0x36,0x0a,0x0e,0xc7,0x04,0x3f,0x0d,0xe9,0x5a,0xfc,0xb8,0x00,
+  0x00,0x8e,0xc0,0x8b,0xf0,0x8b,0xf8,0x2e,0x8b,0x9c,0x49,0x00,
+  0x83,0xc6,0x02,0x26,0x89,0x1d,0x26,0x8c,0x4d,0x02,0x83,0xc7,
+  0x04,0x81,0xff,0x80,0x00,0x72,0xe8,0x26,0xc7,0x05,0xcb,0x0c,
+  0x26,0x8c,0x4d,0x02,0x83,0xc7,0x04,0x81,0xff,0x00,0x04,0x72,
+  0xee,0xc3,0xc1,0xe0,0x06,0x8b,0xd8,0x8c,0xda,0x81,0xc2,0x00,
+  0x04,0x8b,0xfa,0x8a,0x0e,0x22,0x0c,0xb5,0x00,0xbe,0x00,0x10,
+  0x33,0xc0,0x89,0x44,0x0a,0x89,0x44,0x0c,0x89,0x44,0x12,0x89,
+  0x44,0x14,0x81,0xc6,0x80,0x00,0xe2,0xee,0x89,0x36,0x0a,0x0e,
+  0xb8,0x01,0x00,0x8b,0xd0,0xb3,0x00,0x8a,0x0e,0x22,0x0c,0xb5,
+  0x00,0xbe,0x00,0x10,0x2b,0xda,0x72,0x29,0x89,0x44,0x16,0x81,
+  0xc6,0x80,0x00,0xe2,0xf3,0x8a,0x0e,0x22,0x0c,0xb5,0x00,0xbe,
+  0x00,0x10,0x2b,0xda,0x72,0x13,0x89,0x44,0x0e,0x81,0xc6,0x80,
+  0x00,0xe2,0xf3,0x8b,0xd0,0x03,0xc0,0x81,0xfa,0x00,0x02,0x72,
+  0xca,0x8a,0x0e,0x22,0x0c,0xb5,0x00,0xbe,0x00,0x10,0x89,0x7c,
+  0x10,0x8b,0x44,0x16,0x03,0xf8,0x8b,0xd7,0xc1,0xe0,0x04,0x48,
+  0x89,0x44,0x16,0x81,0xc6,0x80,0x00,0xe2,0xe9,0x8a,0x0e,0x22,
+  0x0c,0xb5,0x00,0xbe,0x00,0x10,0x89,0x7c,0x08,0x8b,0x44,0x0e,
+  0x03,0xf8,0x8b,0xd7,0xc1,0xe0,0x04,0x48,0x89,0x44,0x0e,0x81,
+  0xc6,0x80,0x00,0xe2,0xe9,0xc3,0xc7,0x04,0x20,0x04,0xc7,0x44,
+  0x06,0xe1,0x08,0x8b,0xc6,0x2d,0x00,0x10,0xb1,0x80,0xf6,0xf1,
+  0x88,0x44,0x48,0xc7,0x44,0x0a,0x00,0x00,0xc7,0x44,0x0c,0x00,
+  0x00,0xc7,0x44,0x12,0x00,0x00,0xc7,0x44,0x14,0x00,0x00,0xc7,
+  0x44,0x18,0x00,0x00,0xc7,0x44,0x1a,0x00,0x00,0xc7,0x44,0x1c,
+  0xff,0xff,0x8a,0x5c,0x48,0x83,0xe3,0x0f,0x03,0xdb,0x8b,0x97,
+  0x90,0x0c,0x89,0x54,0x20,0xb8,0x01,0x00,0x8a,0x4c,0x48,0xd3,
+  0xe0,0x89,0x44,0x2e,0xc7,0x44,0x24,0x19,0x00,0xc7,0x44,0x26,
+  0x00,0x00,0xc6,0x44,0x4a,0x00,0xc7,0x44,0x30,0x00,0x00,0xc7,
+  0x44,0x32,0x00,0x00,0xc6,0x44,0x4c,0x00,0xc6,0x44,0x4d,0x00,
+  0xc6,0x44,0x4e,0x00,0xc6,0x44,0x4f,0x00,0xc6,0x44,0x50,0x00,
+  0xc6,0x44,0x4b,0x00,0xc6,0x44,0x51,0x00,0xc6,0x44,0x28,0x00,
+  0xc6,0x44,0x29,0x00,0xc6,0x44,0x2a,0x00,0xc6,0x44,0x2b,0x00,
+  0xc6,0x44,0x54,0x00,0xc6,0x44,0x57,0x00,0xc6,0x44,0x55,0x00,
+  0xc6,0x44,0x56,0x00,0xc6,0x44,0x58,0x00,0xc6,0x44,0x52,0x04,
+  0xc6,0x44,0x53,0x04,0xc6,0x44,0x5f,0x00,0xc6,0x44,0x2c,0x3d,
+  0xc6,0x44,0x2d,0x00,0xc7,0x44,0x34,0xff,0x60,0xc6,0x44,0x62,
+  0xff,0xc6,0x44,0x5d,0x13,0xc6,0x44,0x5c,0x11,0xc6,0x44,0x5e,
+  0x00,0xc6,0x44,0x60,0x23,0xc6,0x44,0x61,0x23,0x0b,0xd2,0x75,
+  0x03,0xe9,0xd9,0x00,0xb0,0x09,0xee,0x8a,0x4c,0x48,0xb0,0x80,
+  0xd2,0xe8,0xee,0xc6,0x44,0x70,0x00,0xb0,0x01,0xee,0xb0,0x11,
+  0x88,0x44,0x71,0xee,0xb0,0x02,0x90,0x90,0xee,0x8a,0x44,0x48,
+  0xc0,0xe0,0x03,0x24,0xf0,0x88,0x44,0x72,0xee,0xb0,0x03,0x90,
+  0x90,0xee,0xb0,0xc0,0x88,0x44,0x73,0xee,0xb0,0x04,0x90,0x90,
+  0xee,0xb0,0x44,0x88,0x44,0x74,0xee,0xb0,0x05,0x90,0xee,0xb0,
+  0x60,0x88,0x44,0x75,0xee,0xc6,0x44,0x76,0x00,0xc6,0x44,0x77,
+  0x00,0xc6,0x44,0x78,0x00,0xb0,0x09,0xee,0xb0,0x09,0x88,0x44,
+  0x79,0xee,0xc6,0x44,0x7a,0x00,0xb0,0x0b,0xee,0xb0,0x52,0x88,
+  0x44,0x7b,0xee,0x80,0x3e,0x10,0x0c,0x01,0x75,0x21,0xa1,0x0e,
+  0x0c,0x86,0xe0,0x3d,0x32,0x31,0x73,0x17,0xb0,0x0c,0xee,0xb0,
+  0x18,0x88,0x44,0x7c,0xee,0xb0,0x0d,0x90,0x90,0xee,0xb0,0x00,
+  0x88,0x44,0x7d,0xee,0xeb,0x15,0x90,0xb0,0x0c,0xee,0xb0,0x16,
+  0x88,0x44,0x7c,0xee,0xb0,0x0d,0x90,0x90,0xee,0xb0,0x00,0x88,
+  0x44,0x7d,0xee,0xb0,0x0e,0x90,0x90,0xee,0xb0,0x03,0x88,0x44,
+  0x7e,0xee,0xb0,0x0f,0x90,0x90,0xee,0xb0,0x80,0x88,0x44,0x7f,
+  0xee,0xb0,0x03,0x90,0x90,0xee,0x8a,0x44,0x73,0x0c,0x01,0x88,
+  0x44,0x73,0xee,0x90,0x90,0xb0,0x05,0xee,0x8a,0x44,0x75,0x0c,
+  0x08,0x88,0x44,0x75,0xee,0xc3,0xfa,0x8c,0xd8,0x25,0x00,0xf0,
+  0x8e,0xd0,0xbc,0xfe,0x1f,0x8c,0xd8,0x25,0x00,0xf0,0x8e,0xd8,
+  0x80,0x3e,0x40,0x0d,0x01,0x75,0x51,0xa1,0x0e,0x0c,0x86,0xe0,
+  0x3d,0x30,0x32,0x73,0x47,0x8b,0x1e,0x20,0x0c,0x8a,0x16,0x23,
+  0x0c,0xc6,0x06,0x23,0x0c,0x00,0x83,0xfb,0x00,0x74,0x07,0xfe,
+  0xca,0xc6,0x06,0x23,0x0c,0x01,0x88,0x16,0x22,0x0c,0xbe,0x10,
+  0x0c,0xbf,0x90,0x0c,0xb9,0x08,0x00,0x1e,0x07,0xfc,0xf3,0xa5,
+  0xbf,0xa0,0x0c,0xb8,0x00,0x00,0xb9,0x08,0x00,0xf3,0xab,0xc7,
+  0x06,0x1a,0x0c,0x70,0x00,0xa0,0x40,0x0d,0xa2,0x10,0x0c,0xc6,
+  0x06,0x11,0x0c,0x00,0x2e,0x8c,0x1e,0xc1,0x03,0xc7,0x06,0x18,
+  0x0e,0x02,0x00,0xe8,0xec,0xfc,0xc7,0x06,0x24,0x0d,0x5a,0x0d,
+  0x8c,0x0e,0x26,0x0d,0xc7,0x06,0x18,0x0e,0x06,0x00,0xa1,0x1a,
+  0x0c,0xe8,0x0a,0xfd,0xc7,0x06,0x18,0x0e,0x0a,0x00,0xbe,0x00,
+  0x10,0xc7,0x44,0x1e,0x80,0x00,0xe8,0xa5,0xfd,0x81,0xc6,0x80,
+  0x00,0x81,0xfe,0x00,0x18,0x72,0xee,0xa0,0x22,0x0c,0xb4,0x80,
+  0xf6,0xe4,0xbe,0x00,0x10,0x03,0xf0,0x89,0x36,0x0a,0x0e,0x29,
+  0x44,0x9e,0xc7,0x06,0x00,0x0e,0x00,0x00,0xc7,0x06,0x02,0x0e,
+  0x00,0x00,0xc7,0x06,0x04,0x0e,0x00,0x00,0xc7,0x06,0x06,0x0e,
+  0x9a,0x02,0xba,0x52,0xff,0xa1,0x06,0x0e,0xef,0xba,0x50,0xff,
+  0xb8,0x00,0x00,0xef,0xba,0x56,0xff,0xb8,0x05,0xe0,0xef,0xba,
+  0x5e,0xff,0xb8,0x00,0x40,0xef,0xba,0x66,0xff,0xb8,0x00,0x40,
+  0xef,0xc7,0x06,0x10,0x0d,0x00,0x00,0xc7,0x06,0x12,0x0d,0x00,
+  0x00,0xc7,0x06,0x14,0x0d,0x00,0x04,0xc7,0x06,0x16,0x0d,0xfc,
+  0x03,0xc7,0x06,0x18,0x0d,0x00,0x00,0xc7,0x06,0x1a,0x0d,0x00,
+  0x00,0xc7,0x06,0x1c,0x0d,0x00,0x08,0xc7,0x06,0x1e,0x0d,0xfc,
+  0x03,0xb0,0x00,0x90,0xe6,0x00,0xc7,0x06,0x18,0x0e,0x32,0x00,
+  0xba,0x38,0xff,0xb8,0x11,0x00,0xef,0xba,0x3a,0xff,0xb8,0x08,
+  0x00,0xef,0xba,0x3c,0xff,0xb8,0x08,0x00,0xef,0xba,0x3e,0xff,
+  0xb8,0x08,0x00,0x80,0x3e,0x22,0x0c,0x08,0x76,0x03,0xb8,0x12,
+  0x00,0xef,0xba,0x32,0xff,0xb8,0x05,0x00,0xef,0xba,0x28,0xff,
+  0xb8,0x6c,0x00,0xef,0xba,0x22,0xff,0xb8,0x00,0x80,0xef,0xc7,
+  0x06,0x18,0x0e,0x33,0x00,0xc7,0x06,0x20,0x0d,0x4f,0x00,0xc7,
+  0x06,0x21,0x0d,0x53,0x00,0x8b,0x36,0x0a,0x0e,0xc7,0x04,0x3c,
+  0x0d,0xc7,0x06,0x08,0x0e,0x00,0x10,0xe9,0x63,0xf6,0x40,0x28,
+  0x23,0x29,0x20,0x24,0x49,0x64,0x3a,0x20,0x78,0x61,0x63,0x6f,
+  0x6f,0x6b,0x2e,0x61,0x73,0x6d,0x2c,0x76,0x20,0x37,0x2e,0x32,
+  0x35,0x20,0x31,0x39,0x39,0x35,0x2f,0x30,0x31,0x2f,0x31,0x32,
+  0x20,0x32,0x30,0x3a,0x35,0x39,0x3a,0x32,0x31,0x20,0x6d,0x69,
+  0x6c,0x74,0x20,0x45,0x78,0x70,0x20,0x24,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
diff -u --recursive --new-file v1.3.82/linux/drivers/char/fep.h linux/drivers/char/fep.h
--- v1.3.82/linux/drivers/char/fep.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/fep.h	Wed Apr  3 09:20:45 1996
@@ -0,0 +1,168 @@
+
+#define CSTART       0x400L
+#define CMAX         0x800L
+#define ISTART       0x800L
+#define IMAX         0xC00L
+#define CIN          0xD10L
+#define GLOBAL       0xD10L
+#define EIN          0xD18L
+#define FEPSTAT      0xD20L
+#define CHANSTRUCT   0x1000L
+#define RXTXBUF      0x4000L
+
+
+struct global_data {
+	volatile ushort cin;
+	volatile ushort cout;
+	volatile ushort cstart;
+	volatile ushort cmax;
+	volatile ushort ein;
+	volatile ushort eout;
+	volatile ushort istart;
+	volatile ushort imax;
+};
+
+
+struct board_chan {
+	int filler1; 
+	int filler2;
+	volatile ushort tseg;
+	volatile ushort tin;
+	volatile ushort tout;
+	volatile ushort tmax;
+	
+	volatile ushort rseg;
+	volatile ushort rin;
+	volatile ushort rout;
+	volatile ushort rmax;
+	
+	volatile ushort tlow;
+	volatile ushort rlow;
+	volatile ushort rhigh;
+	volatile ushort incr;
+	
+	volatile ushort etime;
+	volatile ushort edelay;
+	volatile unchar *dev;
+	
+	volatile ushort iflag;
+	volatile ushort oflag;
+	volatile ushort cflag;
+	volatile ushort gmask;
+	
+	volatile ushort col;
+	volatile ushort delay;
+	volatile ushort imask;
+	volatile ushort tflush;
+
+	int filler3;
+	int filler4;
+	int filler5;
+	int filler6;
+	
+	volatile unchar num;
+	volatile unchar ract;
+	volatile unchar bstat;
+	volatile unchar tbusy;
+	volatile unchar iempty;
+	volatile unchar ilow;
+	volatile unchar idata;
+	volatile unchar eflag;
+	
+	volatile unchar tflag;
+	volatile unchar rflag;
+	volatile unchar xmask;
+	volatile unchar xval;
+	volatile unchar mstat;
+	volatile unchar mchange;
+	volatile unchar mint;
+	volatile unchar lstat;
+
+	volatile unchar mtran;
+	volatile unchar orun;
+	volatile unchar startca;
+	volatile unchar stopca;
+	volatile unchar startc;
+	volatile unchar stopc;
+	volatile unchar vnext;
+	volatile unchar hflow;
+
+	volatile unchar fillc;
+	volatile unchar ochar;
+	volatile unchar omask;
+
+	unchar filler7;
+	unchar filler8[28];
+}; 
+
+
+#define SRXLWATER      0xE0
+#define SRXHWATER      0xE1
+#define STOUT          0xE2
+#define PAUSETX        0xE3
+#define RESUMETX       0xE4
+#define SAUXONOFFC     0xE6
+#define SENDBREAK      0xE8
+#define SETMODEM       0xE9
+#define SETIFLAGS      0xEA
+#define SONOFFC        0xEB
+#define STXLWATER      0xEC
+#define PAUSERX        0xEE
+#define RESUMERX       0xEF
+#define SETBUFFER      0xF2
+#define SETCOOKED      0xF3
+#define SETHFLOW       0xF4
+#define SETCTRLFLAGS   0xF5
+#define SETVNEXT       0xF6
+
+
+#define BREAK_IND        0x01
+#define LOWTX_IND        0x02
+#define EMPTYTX_IND      0x04
+#define DATA_IND         0x08
+#define MODEMCHG_IND     0x20
+
+
+#define RTS   0x02
+#define CD    0x08
+#define DSR   0x10
+#define CTS   0x20
+#define RI    0x40
+#define DTR   0x80
+
+	/* These are termios bits as the FEP understands them */
+
+/* c_cflag bit meaning */
+#define FEP_CBAUD	0000017
+#define  FEP_B0		0000000		/* hang up */
+#define  FEP_B50	0000001
+#define  FEP_B75	0000002
+#define  FEP_B110	0000003
+#define  FEP_B134	0000004
+#define  FEP_B150	0000005
+#define  FEP_B200	0000006
+#define  FEP_B300	0000007
+#define  FEP_B600	0000010
+#define  FEP_B1200	0000011
+#define  FEP_B1800	0000012
+#define  FEP_B2400	0000013
+#define  FEP_B4800	0000014
+#define  FEP_B9600	0000015
+#define  FEP_B19200	0000016
+#define  FEP_B38400	0000017
+#define FEP_EXTA FEP_B19200
+#define FEP_EXTB FEP_B38400
+#define FEP_CSIZE	0000060
+#define   FEP_CS5	0000000
+#define   FEP_CS6	0000020
+#define   FEP_CS7	0000040
+#define   FEP_CS8	0000060
+#define FEP_CSTOPB	0000100
+#define FEP_CREAD	0000200
+#define FEP_PARENB	0000400
+#define FEP_PARODD	0001000
+#define FEP_HUPCL	0002000
+#define FEP_CLOCAL	0004000
+#define FEP_CIBAUD	03600000		/* input baud rate (not used) */
+#define FEP_CRTSCTS	  020000000000		/* flow control */
+
diff -u --recursive --new-file v1.3.82/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c
--- v1.3.82/linux/drivers/char/pcxx.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/pcxx.c	Wed Apr  3 14:06:28 1996
@@ -0,0 +1,1961 @@
+/*
+ *  linux/drivers/char/pcxe.c
+ * 
+ *  Written by Troy De Jongh, November, 1994
+ *
+ *  Copyright (C) 1994,1995 Troy De Jongh
+ *  This software may be used and distributed according to the terms 
+ *  of the GNU Public License.
+ *
+ *  This driver is for the DigiBoard PC/Xe and PC/Xi line of products.
+ *
+ *  This driver does NOT support DigiBoard's fastcook FEP option and
+ *  does not support the transparent print (i.e. digiprint) option.
+ *
+ *  Please email any suggestions or bug reports to troyd@skypoint.com
+ *
+ *
+ *  January 1996 Bug fixes by an unknown author and released as 1.5.2
+ *  1.5.3 March 9, 1996 Christoph Lameter: Fixed 115.2K Support. Memory
+ *		allocation harmonized with 1.3.X Series.
+ *  1.5.4 March 30, 1996 Christoph Lameter: Fixup for 1.3.81. Use init_bh
+ *		instead of direct assigment to kernel arrays.
+ *
+ */
+
+#undef SPEED_HACK
+/* If you define SPEED_HACK then you get the following Baudrate translation
+   19200 = 57600
+   38400 = 115K
+   The driver supports the native 57.6K and 115K Baudrates under Linux, but
+   some distributions like Slackware 3.0 dont like these high baudrates.
+*/
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/serial.h>
+#include <linux/tty_driver.h>
+#include <linux/malloc.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/bitops.h>
+
+#define VERSION 	"1.5.4"
+/*#define	DEFAULT_HW_FLOW	1 */
+/*#define	DEBUG_IOCTL */
+
+#include "digi.h"
+#include "fep.h"
+#include "pcxx.h"
+#include "digi_fep.h"
+#include "digi_bios.h"
+#include "pcxxconfig.h"
+
+#define DIGIMAJOR   30
+#define DIGICUMAJOR 31 
+
+#define MAXPORTS 16     /* Max ports per PC/Xx type board */
+#define NBDEVS   (NUMCARDS * MAXPORTS)
+#define PORTNUM(x)  ((x)->dev % MAXPORTS)
+#define LINENUM(x)  (MINOR((x)->device) - (x)->driver.minor_start)
+
+int pcxx_ncook=sizeof(pcxx_cook);
+int pcxx_nbios=sizeof(pcxx_bios);
+
+struct channel digi_channels[NBDEVS];
+
+#define MIN(a,b)	((a) < (b) ? (a) : (b))
+#define pcxxassert(x, msg)  if(!(x)) pcxx_error(__LINE__, msg)
+
+#define FEPTIMEOUT 200000  
+#define SERIAL_TYPE_NORMAL	1
+#define SERIAL_TYPE_CALLOUT	2
+#define PCXE_EVENT_HANGUP   1
+
+struct tty_driver pcxe_driver;
+struct tty_driver pcxe_callout;
+static int pcxe_refcount;
+
+DECLARE_TASK_QUEUE(tq_pcxx);
+static struct tty_struct *pcxe_table[NBDEVS];
+static struct termios *pcxe_termios[NBDEVS];
+static struct termios *pcxe_termios_locked[NBDEVS];
+
+static void pcxxpoll(void);
+static void pcxxdelay(int);
+static void fepcmd(struct channel *, int, int, int, int, int);
+static void pcxe_put_char(struct tty_struct *, unsigned char);
+static void pcxe_flush_chars(struct tty_struct *);
+static void pcxx_error(int, char *);
+static void pcxe_close(struct tty_struct *, struct file *);
+static int pcxe_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);
+static void pcxe_set_termios(struct tty_struct *, struct termios *);
+static int pcxe_write(struct tty_struct *, int, const unsigned char *, int);
+static int pcxe_write_room(struct tty_struct *);
+static int pcxe_chars_in_buffer(struct tty_struct *);
+static void pcxe_flush_buffer(struct tty_struct *);
+static void doevent(int);
+static void receive_data(struct channel *);
+static void pcxxparam(struct tty_struct *, struct channel *ch);
+static void do_softint(void *);
+static inline void pcxe_sched_event(struct channel *, int);
+static void do_pcxe_bh(void);
+static void pcxe_start(struct tty_struct *);
+static void pcxe_stop(struct tty_struct *);
+static void pcxe_throttle(struct tty_struct *);
+static void pcxe_unthrottle(struct tty_struct *);
+static void digi_send_break(struct channel *ch, int msec);
+static void shutdown(struct channel *);
+static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
+static inline void memwinon(struct board_info *b, unsigned int win);
+static inline void memwinoff(struct board_info *b, unsigned int win);
+static inline void globalwinon(struct channel *ch);
+static inline void rxwinon(struct channel *ch);
+static inline void txwinon(struct channel *ch);
+static inline void memoff(struct channel *ch);
+static inline void assertgwinon(struct channel *ch);
+static inline void assertmemoff(struct channel *ch);
+
+#define TZ_BUFSZ 4096
+
+static inline struct channel *chan(register struct tty_struct *tty)
+{
+	if (tty) {
+		register struct channel *ch=(struct channel *)tty->driver_data;
+		if ((ch >= &digi_channels[0]) && (ch < &digi_channels[NBDEVS])) {
+			if (ch->magic==PCXX_MAGIC)
+				return ch;
+		}
+	}
+	return NULL;
+}
+
+/* These inline routines are to turn board memory on and off */
+static inline void memwinon(struct board_info *b, unsigned int win)
+{
+	if(b->type == PCXEVE)
+		outb_p(FEPWIN|win, b->port+1);
+	else
+		outb_p(inb(b->port)|FEPMEM, b->port);
+}
+
+static inline void memwinoff(struct board_info *b, unsigned int win)
+{
+	outb_p(inb(b->port)&~FEPMEM, b->port);
+	if(b->type == PCXEVE)
+		outb_p(0, b->port + 1);
+}
+
+static inline void globalwinon(struct channel *ch)
+{
+	if(ch->board->type == PCXEVE)
+		outb_p(FEPWIN, ch->board->port+1);
+	else
+		outb_p(FEPMEM, ch->board->port);
+}
+
+static inline void rxwinon(struct channel *ch)
+{
+	if(ch->rxwin == 0)
+		outb_p(FEPMEM, ch->board->port);
+	else 
+		outb_p(ch->rxwin, ch->board->port+1);
+}
+
+static inline void txwinon(struct channel *ch)
+{
+	if(ch->txwin == 0)
+		outb_p(FEPMEM, ch->board->port);
+	else
+		outb_p(ch->txwin, ch->board->port+1);
+}
+
+static inline void memoff(struct channel *ch)
+{
+	outb_p(0, ch->board->port);
+	if(ch->board->type == PCXEVE)
+		outb_p(0, ch->board->port+1);
+}
+
+static inline void assertgwinon(struct channel *ch)
+{
+	if(ch->board->type != PCXEVE)
+		pcxxassert(inb(ch->board->port) & FEPMEM, "Global memory off");
+}
+
+static inline void assertmemoff(struct channel *ch)
+{
+	if(ch->board->type != PCXEVE)
+		pcxxassert(!(inb(ch->board->port) & FEPMEM), "Memory on");
+}
+
+static inline void pcxe_sched_event(struct channel *info, int event)
+{
+	info->event |= 1 << event;
+	queue_task_irq_off(&info->tqueue, &tq_pcxx);
+	mark_bh(DIGI_BH);
+}
+
+static void pcxx_error(int line, char *msg)
+{
+	printk("pcxx_error (DigiBoard): line=%d %s\n", line, msg);
+}
+
+static int pcxx_waitcarrier(struct tty_struct *tty,struct file *filp,struct channel *info)
+{
+	struct wait_queue wait = { current, NULL };
+	int	retval = 0;
+	int	do_clocal = 0;
+
+	if (info->asyncflags & ASYNC_CALLOUT_ACTIVE) {
+		if (info->normal_termios.c_cflag & CLOCAL)
+			do_clocal = 1;
+	} else {
+		if (tty->termios->c_cflag & CLOCAL)
+			do_clocal = 1;
+	}
+
+	/*
+	 * Block waiting for the carrier detect and the line to become free
+	 */
+
+	retval = 0;
+	add_wait_queue(&info->open_wait, &wait);
+	info->count--;
+	info->blocked_open++;
+
+	for (;;) {
+		cli();
+		if ((info->asyncflags & ASYNC_CALLOUT_ACTIVE) == 0) {
+			globalwinon(info);
+			info->omodem |= DTR|RTS;
+			fepcmd(info, SETMODEM, DTR|RTS, 0, 10, 1);
+			memoff(info);
+		}
+		sti();
+		current->state = TASK_INTERRUPTIBLE;
+		if(tty_hung_up_p(filp) || (info->asyncflags & ASYNC_INITIALIZED) == 0) {
+			if(info->asyncflags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;	
+			break;
+		}
+		if ((info->asyncflags & ASYNC_CALLOUT_ACTIVE) == 0 &&
+		    (info->asyncflags & ASYNC_CLOSING) == 0 &&
+			(do_clocal || (info->imodem & info->dcd)))
+			break;
+		if(current->signal & ~current->blocked) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+		schedule();
+	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&info->open_wait, &wait);
+
+	if(!tty_hung_up_p(filp))
+		info->count++;
+	info->blocked_open--;
+
+	return retval;
+}	
+
+
+/* static  ???why static??? */
+int pcxe_open(struct tty_struct *tty, struct file * filp)
+{
+	volatile struct board_chan *bc;
+	struct channel *ch;
+	unsigned long flags;
+	int line;
+	int boardnum;
+	int retval;
+
+	line = MINOR(tty->device) - tty->driver.minor_start;
+	if(line < 0 || line >= NBDEVS) {
+		printk("line out of range in pcxe_open\n");
+		tty->driver_data = NULL;
+		return(-ENODEV);
+	}
+
+	boardnum = line / 16;
+	if(boardnum >= NUMCARDS || boards[boardnum].status == DISABLED ||
+								(line % MAXPORTS) >= boards[boardnum].numports) {
+		tty->driver_data = NULL;   /* Mark this device as 'down' */
+		return(-ENODEV);
+	}
+	
+	ch = &digi_channels[line];
+
+	if(ch->brdchan == 0) {
+		tty->driver_data = NULL;
+		return(-ENODEV);
+	}
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if(ch->asyncflags & ASYNC_CLOSING) {
+		interruptible_sleep_on(&ch->close_wait);
+		if(ch->asyncflags & ASYNC_HUP_NOTIFY)
+			return -EAGAIN;
+		else
+			return -ERESTARTSYS;
+	}
+
+	save_flags(flags);
+	cli();
+	ch->count++;
+	tty->driver_data = ch;
+	ch->tty = tty;
+
+	if ((ch->asyncflags & ASYNC_INITIALIZED) == 0) {
+		unsigned int head;
+
+		globalwinon(ch);
+		ch->statusflags = 0;
+		bc=ch->brdchan;
+		ch->imodem = bc->mstat;
+		head = bc->rin;
+		bc->rout = head;
+		ch->tty = tty;
+		pcxxparam(tty,ch);
+		ch->imodem = bc->mstat;
+		bc->idata = 1;
+		ch->omodem = DTR|RTS;
+		fepcmd(ch, SETMODEM, DTR|RTS, 0, 10, 1);
+		memoff(ch);
+		ch->asyncflags |= ASYNC_INITIALIZED;
+	}
+	restore_flags(flags);
+
+	if(ch->asyncflags & ASYNC_CLOSING) {
+		interruptible_sleep_on(&ch->close_wait);
+		if(ch->asyncflags & ASYNC_HUP_NOTIFY)
+			return -EAGAIN;
+		else
+			return -ERESTARTSYS;
+	}
+	/*
+	 * If this is a callout device, then just make sure the normal
+	 * device isn't being used.
+	 */
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+		if (ch->asyncflags & ASYNC_NORMAL_ACTIVE)
+			return -EBUSY;
+		if (ch->asyncflags & ASYNC_CALLOUT_ACTIVE) {
+			if ((ch->asyncflags & ASYNC_SESSION_LOCKOUT) &&
+		    		(ch->session != current->session))
+			    return -EBUSY;
+			if((ch->asyncflags & ASYNC_PGRP_LOCKOUT) &&
+			    (ch->pgrp != current->pgrp))
+			    return -EBUSY;
+		}
+		ch->asyncflags |= ASYNC_CALLOUT_ACTIVE;
+	}
+	else {
+		if (filp->f_flags & O_NONBLOCK) {
+			if(ch->asyncflags & ASYNC_CALLOUT_ACTIVE)
+				return -EBUSY;
+		}
+		else {
+			if ((retval = pcxx_waitcarrier(tty, filp, ch)) != 0)
+				return retval;
+		}
+		ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
+	}
+ 	
+	save_flags(flags);
+	cli();
+	if((ch->count == 1) && (ch->asyncflags & ASYNC_SPLIT_TERMIOS)) {
+		if(tty->driver.subtype == SERIAL_TYPE_NORMAL)
+			*tty->termios = ch->normal_termios;
+		else 
+			*tty->termios = ch->callout_termios;
+		globalwinon(ch);
+		pcxxparam(tty,ch);
+		memoff(ch);
+	}
+
+	ch->session = current->session;
+	ch->pgrp = current->pgrp;
+	restore_flags(flags);
+	return 0;
+} 
+
+static void shutdown(struct channel *info)
+{
+	unsigned long flags;
+	volatile struct board_chan *bc;
+	struct tty_struct *tty;
+
+	if (!(info->asyncflags & ASYNC_INITIALIZED)) 
+		return;
+
+	save_flags(flags);
+	cli();
+	globalwinon(info);
+
+	bc = info->brdchan;
+	if(bc)
+		bc->idata = 0;
+
+	tty = info->tty;
+
+	/*
+	 * If we're a modem control device and HUPCL is on, drop RTS & DTR.
+	 */
+	if(tty->termios->c_cflag & HUPCL) {
+		info->omodem &= ~(RTS|DTR);
+		fepcmd(info, SETMODEM, 0, DTR|RTS, 10, 1);
+	}
+
+	memoff(info);
+	info->asyncflags &= ~ASYNC_INITIALIZED;
+	restore_flags(flags);
+}
+
+
+static void pcxe_close(struct tty_struct * tty, struct file * filp)
+{
+	struct channel *info;
+
+	if ((info=chan(tty))!=NULL) {
+		unsigned long flags;
+		save_flags(flags);
+		cli();
+
+		if(tty_hung_up_p(filp)) {
+			restore_flags(flags);
+			return;
+		}
+		if (info->count-- > 1) {
+			restore_flags(flags);
+			return;
+		}
+		if (info->count < 0) {
+			info->count = 0;
+		}
+
+		info->asyncflags |= ASYNC_CLOSING;
+	
+		/*
+		* Save the termios structure, since this port may have
+		* separate termios for callout and dialin.
+		*/
+		if(info->asyncflags & ASYNC_NORMAL_ACTIVE)
+			info->normal_termios = *tty->termios;
+		if(info->asyncflags & ASYNC_CALLOUT_ACTIVE)
+			info->callout_termios = *tty->termios;
+		tty->closing = 1;
+		if(info->asyncflags & ASYNC_INITIALIZED) {
+			setup_empty_event(tty,info);		
+			tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
+		}
+	
+		if(tty->driver.flush_buffer)
+			tty->driver.flush_buffer(tty);
+		if(tty->ldisc.flush_buffer)
+			tty->ldisc.flush_buffer(tty);
+		shutdown(info);
+		tty->closing = 0;
+		info->event = 0;
+		info->tty = NULL;
+		if(tty->ldisc.num != ldiscs[N_TTY].num) {
+			if(tty->ldisc.close)
+				(tty->ldisc.close)(tty);
+			tty->ldisc = ldiscs[N_TTY];
+			tty->termios->c_line = N_TTY;
+			if(tty->ldisc.open)
+				(tty->ldisc.open)(tty);
+		}
+		if(info->blocked_open) {
+			if(info->close_delay) {
+				current->state = TASK_INTERRUPTIBLE;
+				current->timeout = jiffies + info->close_delay;
+				schedule();
+			}
+			wake_up_interruptible(&info->open_wait);
+		}
+		info->asyncflags &= ~(ASYNC_NORMAL_ACTIVE|
+							  ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING);
+		wake_up_interruptible(&info->close_wait);
+		restore_flags(flags);
+	}
+}
+
+
+void pcxe_hangup(struct tty_struct *tty)
+{
+	struct channel *ch;
+
+	if ((ch=chan(tty))!=NULL) {
+		unsigned long flags;
+
+		save_flags(flags);
+		cli();
+		shutdown(ch);
+		ch->event = 0;
+		ch->count = 0;
+		ch->tty = NULL;
+		ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+		wake_up_interruptible(&ch->open_wait);
+		restore_flags(flags);
+	}
+}
+
+
+
+static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+{
+	struct channel *ch;
+	volatile struct board_chan *bc;
+	int total, remain, size, stlen;
+	unsigned int head, tail;
+	unsigned long flags;
+
+	/* printk("Entering pcxe_write()\n"); */
+
+	if ((ch=chan(tty))==NULL)
+		return 0;
+
+	bc = ch->brdchan;
+	size = ch->txbufsize;
+
+	if (from_user) {
+
+		save_flags(flags);
+		cli();
+		globalwinon(ch);
+		head = bc->tin & (size - 1);
+		tail = bc->tout;
+		if (tail != bc->tout)
+			tail = bc->tout;
+		tail &= (size - 1);
+		stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1);
+		count = MIN(stlen, count);
+		if (count) {
+			if (verify_area(VERIFY_READ, (char*)buf, count))
+				count=0;
+			else memcpy_fromfs(ch->tmp_buf, buf, count);
+		}
+		buf = ch->tmp_buf;
+		memoff(ch);
+		restore_flags(flags);
+	}
+
+	/*
+	 * All data is now local
+	 */
+
+	total = 0;
+	save_flags(flags);
+	cli();
+	globalwinon(ch);
+	head = bc->tin & (size - 1);
+	tail = bc->tout;
+	if (tail != bc->tout)
+		tail = bc->tout;
+	tail &= (size - 1);
+	if (head >= tail) {
+		remain = size - (head - tail) - 1;
+		stlen = size - head;
+	}
+	else {
+		remain = tail - head - 1;
+		stlen = remain;
+	}
+	count = MIN(remain, count);
+
+	txwinon(ch);
+	while (count > 0) {
+		stlen = MIN(count, stlen);
+		memcpy(ch->txptr + head, buf, stlen);
+		buf += stlen;
+		count -= stlen;
+		total += stlen;
+		head += stlen;
+		if (head >= size) {
+			head = 0;
+			stlen = tail;
+		}
+	}
+	ch->statusflags |= TXBUSY;
+	globalwinon(ch);
+	bc->tin = head;
+	if ((ch->statusflags & LOWWAIT) == 0) {
+		ch->statusflags |= LOWWAIT;
+		bc->ilow = 1;
+	}
+	memoff(ch);
+	restore_flags(flags);
+
+	return(total);
+}
+
+
+static void pcxe_put_char(struct tty_struct *tty, unsigned char c)
+{
+	pcxe_write(tty, 0, &c, 1);
+	return;
+}
+
+
+static int pcxe_write_room(struct tty_struct *tty)
+{
+	struct channel *ch;
+	int remain;
+
+	remain = 0;
+	if ((ch=chan(tty))!=NULL) {
+		volatile struct board_chan *bc;
+		unsigned int head, tail;
+		unsigned long flags;
+
+		save_flags(flags);
+		cli();
+		globalwinon(ch);
+
+		bc = ch->brdchan;
+		head = bc->tin & (ch->txbufsize - 1);
+		tail = bc->tout;
+		if (tail != bc->tout)
+			tail = bc->tout;
+		tail &= (ch->txbufsize - 1);
+
+		if((remain = tail - head - 1) < 0 )
+			remain += ch->txbufsize;
+
+		if (remain && (ch->statusflags & LOWWAIT) == 0) {
+			ch->statusflags |= LOWWAIT;
+			bc->ilow = 1;
+		}
+		memoff(ch);
+		restore_flags(flags);
+	}
+
+	return remain;
+}
+
+
+static int pcxe_chars_in_buffer(struct tty_struct *tty)
+{
+	int chars;
+	unsigned int ctail, head, tail;
+	int remain;
+	unsigned long flags;
+	struct channel *ch;
+	volatile struct board_chan *bc;
+
+	if ((ch=chan(tty))==NULL)
+		return(0);
+
+	save_flags(flags);
+	cli();
+	globalwinon(ch);
+
+	bc = ch->brdchan;
+	tail = bc->tout;
+	head = bc->tin;
+	ctail = ch->mailbox->cout;
+	if(tail == head && ch->mailbox->cin == ctail && bc->tbusy == 0)
+		chars = 0;
+	else {
+		head = bc->tin & (ch->txbufsize - 1);
+		tail &= (ch->txbufsize - 1);
+		if((remain = tail - head - 1) < 0 )
+			remain += ch->txbufsize;
+
+		chars = (int)(ch->txbufsize - remain);
+
+		/* 
+		 * Make it possible to wakeup anything waiting for output
+		 * in tty_ioctl.c, etc.
+		 */
+		if(!(ch->statusflags & EMPTYWAIT))
+			setup_empty_event(tty,ch);
+	}
+
+	memoff(ch);
+	restore_flags(flags);
+
+	return(chars);
+}
+
+
+static void pcxe_flush_buffer(struct tty_struct *tty)
+{
+	unsigned int tail;
+	volatile struct board_chan *bc;
+	struct channel *ch;
+	unsigned long flags;
+
+	if ((ch=chan(tty))==NULL)
+		return;
+
+	save_flags(flags);
+	cli();
+
+	globalwinon(ch);
+	bc = ch->brdchan;
+	tail = bc->tout;
+	fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
+
+	memoff(ch);
+	restore_flags(flags);
+
+	wake_up_interruptible(&tty->write_wait);
+	if((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+}
+
+static void pcxe_flush_chars(struct tty_struct *tty)
+{
+	struct channel * ch;
+
+	if ((ch=chan(tty))!=NULL) {
+		unsigned long flags;
+
+		save_flags(flags);
+		cli();
+		if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
+			setup_empty_event(tty,ch);
+		restore_flags(flags);
+	}
+}
+
+
+int pcxe_init(void)
+{
+	ulong flags, save_loops_per_sec, memory_seg=0, memory_size;
+	int lowwater, i, crd, shrinkmem=0, topwin = 0xff00L, botwin=0x100L;
+	unchar *fepos, *memaddr, *bios, v;
+	volatile struct global_data *gd;
+	struct board_info *bd;
+	volatile struct board_chan *bc;
+	struct channel *ch;
+
+	init_bh(DIGI_BH,do_pcxe_bh);
+	enable_bh(DIGI_BH);
+
+	timer_table[DIGI_TIMER].fn = pcxxpoll;
+	timer_table[DIGI_TIMER].expires = 0;
+
+	memset(&pcxe_driver, 0, sizeof(struct tty_driver));
+	pcxe_driver.magic = TTY_DRIVER_MAGIC;
+	pcxe_driver.name = "ttyd";
+	pcxe_driver.major = DIGIMAJOR; 
+	pcxe_driver.minor_start = 0;
+	pcxe_driver.num = NBDEVS;
+	pcxe_driver.type = TTY_DRIVER_TYPE_SERIAL;
+	pcxe_driver.subtype = SERIAL_TYPE_NORMAL;
+	pcxe_driver.init_termios = tty_std_termios;
+	pcxe_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
+	pcxe_driver.flags = TTY_DRIVER_REAL_RAW;
+	pcxe_driver.refcount = &pcxe_refcount;
+	pcxe_driver.table = pcxe_table;
+	pcxe_driver.termios = pcxe_termios;
+	pcxe_driver.termios_locked = pcxe_termios_locked;
+
+	pcxe_driver.open = pcxe_open;
+	pcxe_driver.close = pcxe_close;
+	pcxe_driver.write = pcxe_write;
+	pcxe_driver.put_char = pcxe_put_char;
+	pcxe_driver.flush_chars = pcxe_flush_chars;
+	pcxe_driver.write_room = pcxe_write_room;
+	pcxe_driver.chars_in_buffer = pcxe_chars_in_buffer;
+	pcxe_driver.flush_buffer = pcxe_flush_buffer;
+	pcxe_driver.ioctl = pcxe_ioctl;
+	pcxe_driver.throttle = pcxe_throttle;
+	pcxe_driver.unthrottle = pcxe_unthrottle;
+	pcxe_driver.set_termios = pcxe_set_termios;
+	pcxe_driver.stop = pcxe_stop;
+	pcxe_driver.start = pcxe_start;
+	pcxe_driver.hangup = pcxe_hangup;
+
+	pcxe_callout = pcxe_driver;
+	pcxe_callout.name = "ttyD";
+	pcxe_callout.major = DIGICUMAJOR;
+	pcxe_callout.subtype = SERIAL_TYPE_CALLOUT;
+	pcxe_callout.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+
+	/* 
+	 * loops_per_sec hasn't been set at this point :-(, so fake it out... 
+	 * I set it so that I can use the __delay() function.
+	 */
+	save_loops_per_sec = loops_per_sec;
+	loops_per_sec = 13L*500000L;
+
+	save_flags(flags);
+	cli();
+
+	for(crd=0; crd < NUMCARDS; crd++) {
+		bd = &boards[crd];
+		outb(FEPRST, bd->port);
+		pcxxdelay(1);
+
+		for(i=0; (inb(bd->port) & FEPMASK) != FEPRST; i++) {
+			if(i > 1000) {
+				printk("Board not found at port 0x%x! Check switch settings.\n",
+					bd->port);
+				bd->status = DISABLED;
+				break;
+			}
+			pcxxdelay(1);
+		}
+		if(bd->status == DISABLED)
+			continue;
+
+		v = inb(bd->port);
+
+		if((v & 0x1) == 0x1) {
+			if((v & 0x30) == 0) {        /* PC/Xi 64K card */
+				memory_seg = 0xf000;
+				memory_size = 0x10000;
+			} 
+
+			if((v & 0x30) == 0x10) {     /* PC/Xi 128K card */
+				memory_seg = 0xe000;
+				memory_size = 0x20000;
+			}
+			
+			if((v & 0x30) == 0x20) {     /* PC/Xi 256K card */
+				memory_seg = 0xc000;
+				memory_size = 0x40000;
+			}
+
+			if((v & 0x30) == 0x30) {     /* PC/Xi 512K card */
+				memory_seg = 0x8000;
+				memory_size = 0x80000;
+			}
+			bd->type = PCXI;
+		} else {
+			if((v & 0x1) == 0x1) {
+				bd->status = DISABLED;   /* PC/Xm unsupported card */
+				printk("PC/Xm at 0x%x not supported!!\n", bd->port);
+				continue;
+			} else {
+				if(v & 0xC0) {    
+					topwin = 0x1f00L;
+					outb((((ulong)bd->membase>>8) & 0xe0) | 0x10, bd->port+2);
+					outb(((ulong)bd->membase>>16) & 0xff, bd->port+3);
+					bd->type = PCXEVE; /* PC/Xe 8K card */
+				} else { 
+					bd->type = PCXE;    /* PC/Xe 64K card */
+				}
+					
+				memory_seg = 0xf000;
+				memory_size = 0x10000;
+			}
+		}
+
+		memaddr = (unchar *) bd->membase;
+
+		outb(FEPRST|FEPMEM, bd->port);
+
+		for(i=0; (inb(bd->port) & FEPMASK) != (FEPRST|FEPMEM); i++) {
+			if(i > 10000) {
+				printk("%s not resetting at port 0x%x! Check switch settings.\n",
+					board_desc[bd->type], bd->port);
+				bd->status = DISABLED;
+				break;
+			}
+			pcxxdelay(1);
+		}
+		if(bd->status == DISABLED)
+			continue;
+
+		memwinon(bd,0);
+		*(ulong *)(memaddr + botwin) = 0xa55a3cc3;
+		*(ulong *)(memaddr + topwin) = 0x5aa5c33c;
+
+		if(*(ulong *)(memaddr + botwin) != 0xa55a3cc3 ||
+					*(ulong *)(memaddr + topwin) != 0x5aa5c33c) {
+			printk("Failed memory test at %lx for %s at port %x, check switch settings.\n",
+				bd->membase, board_desc[bd->type], bd->port);
+			bd->status = DISABLED;
+			continue;
+		}
+
+		for(i=0; i < 16; i++) {
+			memaddr[MISCGLOBAL+i] = 0;
+		}
+
+		if(bd->type == PCXI || bd->type == PCXE) {
+			bios = memaddr + BIOSCODE + ((0xf000 - memory_seg) << 4);
+
+			memcpy(bios, pcxx_bios, pcxx_nbios);
+
+			outb(FEPMEM, bd->port);
+
+			for(i=0; i <= 10000; i++) {
+				if(*(ushort *)((ulong)memaddr + MISCGLOBAL) == *(ushort *)"GD" ) {
+					goto load_fep;
+				}
+				pcxxdelay(1);
+			}
+
+			printk("BIOS download failed on the %s at 0x%x!\n",
+							board_desc[bd->type], bd->port);
+			bd->status = DISABLED;
+			continue;
+		}
+
+		if(bd->type == PCXEVE) {
+			bios = memaddr + (BIOSCODE & 0x1fff);
+			memwinon(bd,0xff);
+			
+			memcpy(bios, pcxx_bios, pcxx_nbios);
+
+			outb(FEPCLR, bd->port);
+			memwinon(bd,0);
+
+			for(i=0; i <= 10000; i++) {
+				if(*(ushort *)((ulong)memaddr + MISCGLOBAL) == *(ushort *)"GD" ) {
+					goto load_fep;
+				}
+				pcxxdelay(1);
+			}
+
+			printk("BIOS download failed on the %s at 0x%x!\n",
+				board_desc[bd->type], bd->port);
+			bd->status = DISABLED;
+			continue;
+		}
+
+load_fep:
+		fepos = memaddr + FEPCODE;
+		if(bd->type == PCXEVE)
+			fepos = memaddr + (FEPCODE & 0x1fff);
+
+		memwinon(bd, (FEPCODE >> 13));
+		memcpy(fepos, pcxx_cook, pcxx_ncook);
+		memwinon(bd, 0);
+
+		*(ushort *)((ulong)memaddr + MBOX +  0) = 2;
+		*(ushort *)((ulong)memaddr + MBOX +  2) = memory_seg + FEPCODESEG;
+		*(ushort *)((ulong)memaddr + MBOX +  4) = 0;
+		*(ushort *)((ulong)memaddr + MBOX +  6) = FEPCODESEG;
+		*(ushort *)((ulong)memaddr + MBOX +  8) = 0;
+		*(ushort *)((ulong)memaddr + MBOX + 10) = pcxx_ncook;
+
+		outb(FEPMEM|FEPINT, bd->port);
+		outb(FEPMEM, bd->port);
+
+		for(i=0; *(ushort *)((ulong)memaddr + MBOX); i++) {
+			if(i > 2000) {
+				printk("Command failed for the %s at 0x%x!\n",
+					board_desc[bd->type], bd->port);
+				bd->status = DISABLED;
+				break;
+			}
+			pcxxdelay(1);
+		}
+
+		if(bd->status == DISABLED)
+			continue;
+
+		*(ushort *)(memaddr + FEPSTAT) = 0;
+		*(ushort *)(memaddr + MBOX + 0) = 1;
+		*(ushort *)(memaddr + MBOX + 2) = FEPCODESEG;
+		*(ushort *)(memaddr + MBOX + 4) = 0x4L;
+
+		outb(FEPINT, bd->port);
+		outb(FEPCLR, bd->port);
+		memwinon(bd, 0);
+
+		for(i=0; *(ushort *)((ulong)memaddr + FEPSTAT) != *(ushort *)"OS"; i++) {
+			if(i > 10000) {
+				printk("FEP/OS download failed on the %s at 0x%x!\n",
+					board_desc[bd->type], bd->port);
+				bd->status = DISABLED;
+				break;
+			}
+			pcxxdelay(1);
+		}
+		if(bd->status == DISABLED)
+			continue;
+
+		ch = &digi_channels[MAXPORTS * crd];
+		pcxxassert(ch <= &digi_channels[NBDEVS-1], "ch out of range");
+
+		bc = (volatile struct board_chan *)((ulong)memaddr + CHANSTRUCT);
+		gd = (volatile struct global_data *)((ulong)memaddr + GLOBAL);
+
+		if((bd->type == PCXEVE) && (*(ushort *)((ulong)memaddr+NPORT) < 3))
+			shrinkmem = 1;
+
+		request_region(bd->port, 4, "PC/Xx");
+
+		for(i=0; i < bd->numports; i++, ch++, bc++) {
+			if(((ushort *)((ulong)memaddr + PORTBASE))[i] == 0) {
+				ch->brdchan = 0;
+				continue;
+			}
+			ch->brdchan = bc;
+			ch->mailbox = gd;
+			ch->tqueue.routine = do_softint;
+			ch->tqueue.data = ch;
+			ch->board = &boards[crd];
+#ifdef DEFAULT_HW_FLOW
+			ch->digiext.digi_flags = RTSPACE|CTSPACE;
+#endif
+			if(boards[crd].altpin) {
+				ch->dsr = CD;
+				ch->dcd = DSR;
+				ch->digiext.digi_flags |= DIGI_ALTPIN;
+			} else { 
+				ch->dcd = CD;
+				ch->dsr = DSR;
+			}
+
+			ch->magic = PCXX_MAGIC;
+			ch->boardnum = crd;
+			ch->channelnum = i;
+
+			ch->dev = (MAXPORTS * crd) + i;
+			ch->tty = 0;
+
+			if(shrinkmem) {
+				fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
+				shrinkmem = 0;
+			}
+			
+			if(bd->type != PCXEVE) {
+				ch->txptr = memaddr+((bc->tseg-memory_seg) << 4);
+				ch->rxptr = memaddr+((bc->rseg-memory_seg) << 4);
+				ch->txwin = ch->rxwin = 0;
+			} else {
+				ch->txptr = memaddr+(((bc->tseg-memory_seg) << 4) & 0x1fff);
+				ch->txwin = FEPWIN | ((bc->tseg-memory_seg) >> 9);
+				ch->rxptr = memaddr+(((bc->rseg-memory_seg) << 4) & 0x1fff);
+				ch->rxwin = FEPWIN | ((bc->rseg-memory_seg) >>9 );
+			}
+
+			ch->txbufsize = bc->tmax + 1;
+			ch->rxbufsize = bc->rmax + 1;
+
+			ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL);
+
+			lowwater = ch->txbufsize >= 2000 ? 1024 : ch->txbufsize/2;
+			fepcmd(ch, STXLWATER, lowwater, 0, 10, 0);
+			fepcmd(ch, SRXLWATER, ch->rxbufsize/4, 0, 10, 0);
+			fepcmd(ch, SRXHWATER, 3 * ch->rxbufsize/4, 0, 10, 0);
+
+			bc->edelay = 100;
+			bc->idata = 1;
+
+			ch->startc = bc->startc;
+			ch->stopc = bc->stopc;
+			ch->startca = bc->startca;
+			ch->stopca = bc->stopca;
+
+			ch->fepcflag = 0;
+			ch->fepiflag = 0;
+			ch->fepoflag = 0;
+			ch->fepstartc = 0;
+			ch->fepstopc = 0;
+			ch->fepstartca = 0;
+			ch->fepstopca = 0;
+
+			ch->close_delay = 50;
+			ch->count = 0;
+			ch->blocked_open = 0;
+			ch->callout_termios = pcxe_callout.init_termios;
+			ch->normal_termios = pcxe_driver.init_termios;
+			ch->open_wait = 0;
+			ch->close_wait = 0;
+		}
+
+		printk("DigiBoard PC/Xx Driver V%s:  %s I/O=0x%x Mem=0x%lx Ports=%d\n", 
+				VERSION, board_desc[bd->type], bd->port, bd->membase, bd->numports);
+
+		memwinoff(bd, 0);
+	}
+
+	if(tty_register_driver(&pcxe_driver))
+		panic("Couldn't register PC/Xe driver");
+
+	if(tty_register_driver(&pcxe_callout))
+		panic("Couldn't register PC/Xe callout");
+
+
+	loops_per_sec = save_loops_per_sec;  /* reset it to what it should be */
+
+	/*
+	 * Start up the poller to check for events on all enabled boards
+	 */
+	timer_active |= 1 << DIGI_TIMER;
+	restore_flags(flags);
+
+	return 0;
+}
+
+
+static void pcxxpoll(void)
+{
+	unsigned long flags;
+	int crd;
+	volatile unsigned int head, tail;
+	struct channel *ch;
+	struct board_info *bd;
+
+	save_flags(flags);
+	cli();
+
+	for(crd=0; crd < NUMCARDS; crd++) {
+		bd = &boards[crd];
+		ch = &digi_channels[MAXPORTS*crd];
+
+		if(bd->status == DISABLED)
+			continue;
+
+		assertmemoff(ch);
+
+		globalwinon(ch);
+		head = ch->mailbox->ein;
+		tail = ch->mailbox->eout;
+
+		if(head != tail)
+			doevent(crd);
+
+		memoff(ch);
+	}
+
+	timer_table[DIGI_TIMER].fn = pcxxpoll;
+	timer_table[DIGI_TIMER].expires = jiffies + HZ/25;
+	timer_active |= 1 << DIGI_TIMER;
+	restore_flags(flags);
+}
+
+static void doevent(int crd)
+{
+	volatile struct board_info *bd;
+	static struct tty_struct *tty;
+	volatile struct board_chan *bc;
+	volatile unchar *eventbuf;
+	volatile unsigned int head;
+	volatile unsigned int tail;
+	struct channel *ch;
+	struct channel *chan0;
+	int channel, event, mstat, lstat;
+
+	bd = &boards[crd];
+
+	chan0 = &digi_channels[MAXPORTS * crd];
+	pcxxassert(chan0 <= &digi_channels[NBDEVS-1], "ch out of range");
+
+	assertgwinon(chan0);
+
+	while ((tail = chan0->mailbox->eout) != (head = chan0->mailbox->ein)) {
+		assertgwinon(chan0);
+		eventbuf = (volatile unchar *)bd->membase + tail + ISTART;
+		channel = eventbuf[0];
+		event = eventbuf[1];
+		mstat = eventbuf[2];
+		lstat = eventbuf[3];
+
+		ch=chan0+channel;
+
+		if ((unsigned)channel >= bd->numports || !ch) { 
+			printk("physmem=%lx, tail=%x, head=%x\n", bd->membase, tail, head);
+			printk("doevent(%x) channel %x, event %x, mstat %x, lstat %x\n",
+					crd, (unsigned)channel, event, (unsigned)mstat, lstat);
+			if(channel >= bd->numports)
+				ch = chan0;
+			bc = ch->brdchan;
+			goto next;
+		}
+		if ((bc = ch->brdchan) == NULL)
+			goto next;
+
+		if (event & DATA_IND) {
+			receive_data(ch);
+			assertgwinon(ch);
+		}
+
+		if (event & MODEMCHG_IND) {
+			ch->imodem = mstat;
+			if (ch->asyncflags & (ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE)) {
+				if (ch->asyncflags & ASYNC_CHECK_CD) {
+					if (mstat & ch->dcd) {
+						wake_up_interruptible(&ch->open_wait);
+					} else {
+						pcxe_sched_event(ch, PCXE_EVENT_HANGUP);
+					}
+				}
+			}
+		}
+
+		tty = ch->tty;
+
+		if (tty) {
+
+			if (event & BREAK_IND) {
+				tty->flip.count++;
+				*tty->flip.flag_buf_ptr++ = TTY_BREAK;
+				*tty->flip.char_buf_ptr++ = 0;
+#if 0
+				if (ch->asyncflags & ASYNC_SAK)
+					do_SAK(tty);
+#endif
+				tty_schedule_flip(tty); 
+			}
+
+			if (event & LOWTX_IND) {
+				if (ch->statusflags & LOWWAIT) {
+					ch->statusflags &= ~LOWWAIT;
+					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+						tty->ldisc.write_wakeup)
+						(tty->ldisc.write_wakeup)(tty);
+					wake_up_interruptible(&tty->write_wait);
+				}
+			}
+
+			if (event & EMPTYTX_IND) {
+				ch->statusflags &= ~TXBUSY;
+				if (ch->statusflags & EMPTYWAIT) {
+					ch->statusflags &= ~EMPTYWAIT;
+					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+						tty->ldisc.write_wakeup)
+						(tty->ldisc.write_wakeup)(tty);
+					wake_up_interruptible(&tty->write_wait);
+				}
+			}
+		}
+
+	next:
+		globalwinon(ch);
+		if(!bc) printk("bc == NULL in doevent!\n");
+		else bc->idata = 1;
+
+		chan0->mailbox->eout = (tail+4) & (IMAX-ISTART-4);
+		globalwinon(chan0);
+	}
+
+}
+
+
+/*
+ * pcxxdelay - delays a specified number of milliseconds
+ */
+static void pcxxdelay(int msec)
+{
+	while(msec-- > 0)
+		__delay(loops_per_sec/1000);
+}
+
+
+static void 
+fepcmd(struct channel *ch, int cmd, int word_or_byte, int byte2, int ncmds,
+						int bytecmd)
+{
+	unchar *memaddr;
+	unsigned int head, tail;
+	long count;
+	int n;
+
+	if(ch->board->status == DISABLED)
+		return;
+
+	assertgwinon(ch);
+
+	memaddr = (unchar *)ch->board->membase;
+	head = ch->mailbox->cin;
+
+	if(head >= (CMAX-CSTART) || (head & 03)) {
+		printk("line %d: Out of range, cmd=%x, head=%x\n", __LINE__, cmd, head);
+		return;
+	}
+
+	if(bytecmd) {
+		*(unchar *)(memaddr+head+CSTART+0) = cmd;
+		*(unchar *)(memaddr+head+CSTART+1) = PORTNUM(ch);
+		*(unchar *)(memaddr+head+CSTART+2) = word_or_byte;
+		*(unchar *)(memaddr+head+CSTART+3) = byte2;
+	} else {
+		*(unchar *)(memaddr+head+CSTART+0) = cmd;
+		*(unchar *)(memaddr+head+CSTART+1) = PORTNUM(ch);
+		*(ushort*)(memaddr+head+CSTART+2) = word_or_byte;
+	}
+
+	head = (head+4) & (CMAX-CSTART-4);
+	ch->mailbox->cin = head;
+
+	count = FEPTIMEOUT;
+
+	while(1) {
+		count--;
+		if(count == 0) {
+			printk("Fep not responding in fepcmd()\n");
+			return;
+		}
+
+		head = ch->mailbox->cin;
+		tail = ch->mailbox->cout;
+
+		n = (head-tail) & (CMAX-CSTART-4);
+
+		if(n <= ncmds * (sizeof(short)*4))
+			break;
+	}
+}
+
+
+static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
+{
+	unsigned res = 0;
+#ifdef SPEED_HACK
+	/* CL: HACK to force 115200 at 38400 and 57600 at 19200 Baud */
+	if ((cflag & CBAUD)== B38400) cflag=cflag - B38400 + B115200;
+	if ((cflag & CBAUD)== B19200) cflag=cflag - B19200 + B57600;
+#endif
+	if (cflag & CBAUDEX)
+	{
+		ch->digiext.digi_flags |= DIGI_FAST;
+		res |= FEP_HUPCL;
+		/* This gets strange but if we dont do this we will get 78600
+		 * instead of 115200. 57600 is mapped to 50 baud yielding 57600 in
+		 * FAST mode. 115200 is mapped to 75. We need to map it to 110 to
+		 * do 115K
+		 */
+		if (cflag & B115200) res|=1;
+	}
+	else ch->digiext.digi_flags &= ~DIGI_FAST;
+	res |= cflag & (CBAUD | PARODD | PARENB | CSTOPB | CSIZE);
+	return res;
+}
+
+static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
+{
+	unsigned res = iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|IXON|IXANY|IXOFF);
+	
+	if(ch->digiext.digi_flags & DIGI_AIXON)
+		res |= IAIXON;
+	return res;
+}
+
+static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
+{
+	unsigned res = 0;
+
+	if(cflag & CRTSCTS) {
+		ch->digiext.digi_flags |= (RTSPACE|CTSPACE);
+		res |= (CTS | RTS);
+	}
+	if(ch->digiext.digi_flags & RTSPACE)
+		res |= RTS;
+	if(ch->digiext.digi_flags & DTRPACE)
+		res |= DTR;
+	if(ch->digiext.digi_flags & CTSPACE)
+		res |= CTS;
+	if(ch->digiext.digi_flags & DSRPACE)
+		res |= ch->dsr;
+	if(ch->digiext.digi_flags & DCDPACE)
+		res |= ch->dcd;
+
+	if (res & RTS)
+		ch->digiext.digi_flags |= RTSPACE;
+	if (res & CTS)
+		ch->digiext.digi_flags |= CTSPACE;
+
+	return res;
+}
+
+static void pcxxparam(struct tty_struct *tty, struct channel *ch)
+{
+	volatile struct board_chan *bc;
+	unsigned int head;
+	unsigned mval, hflow, cflag, iflag;
+	struct termios *ts;
+
+	bc = ch->brdchan;
+	assertgwinon(ch);
+	ts = tty->termios;
+
+	if((ts->c_cflag & CBAUD) == 0) {
+		head = bc->rin;
+		bc->rout = head;
+		head = bc->tin;
+		fepcmd(ch, STOUT, (unsigned) head, 0, 0, 0);
+		mval = 0;
+	} else {
+
+		cflag = termios2digi_c(ch, ts->c_cflag);
+
+		if(cflag != ch->fepcflag) {
+			ch->fepcflag = cflag;
+			fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0);
+		}
+
+		if(cflag & CLOCAL)
+			ch->asyncflags &= ~ASYNC_CHECK_CD;
+		else {
+			ch->asyncflags |= ASYNC_CHECK_CD;
+		}
+
+		mval = DTR | RTS;
+	}
+
+	iflag = termios2digi_i(ch, ts->c_iflag);
+
+	if(iflag != ch->fepiflag) {
+		ch->fepiflag = iflag;
+		fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
+	}
+
+	bc->mint = ch->dcd;
+	if((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD))
+		if(ch->digiext.digi_flags & DIGI_FORCEDCD)
+			bc->mint = 0;
+
+	ch->imodem = bc->mstat;
+
+	hflow = termios2digi_h(ch, ts->c_cflag);
+
+	if(hflow != ch->hflow) {
+		ch->hflow = hflow;
+		fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1);
+	}
+
+	/* mval ^= ch->modemfake & (mval ^ ch->modem); */
+
+	if(ch->omodem != mval) {
+		ch->omodem = mval;
+		fepcmd(ch, SETMODEM, mval, RTS|DTR, 0, 1);
+	}
+
+	if(ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) {
+		ch->fepstartc = ch->startc;
+		ch->fepstopc = ch->stopc;
+		fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
+	}
+
+	if(ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) {
+		ch->fepstartca = ch->startca;
+		ch->fepstopca = ch->stopca;
+		fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
+	}
+}
+
+
+static void receive_data(struct channel *ch)
+{
+	volatile struct board_chan *bc;
+	struct tty_struct *tty;
+	unsigned int tail, head, wrapmask;
+	int n;
+	int piece;
+	struct termios *ts=0;
+	unchar *rptr;
+	int rc;
+	int wrapgap;
+
+    globalwinon(ch);
+
+	if (ch->statusflags & RXSTOPPED)
+		return;
+
+	tty = ch->tty;
+	if(tty)
+		ts = tty->termios;
+
+	bc = ch->brdchan;
+
+	if(!bc) {
+		printk("bc is NULL in receive_data!\n");
+		return;
+	}
+
+	wrapmask = ch->rxbufsize - 1;
+
+	head = bc->rin;
+	head &= wrapmask;
+	tail = bc->rout & wrapmask;
+
+	n = (head-tail) & wrapmask;
+
+	if(n == 0)
+		return;
+
+	/*
+	 * If CREAD bit is off or device not open, set TX tail to head
+	 */
+	if(!tty || !ts || !(ts->c_cflag & CREAD)) {
+		bc->rout = head;
+		return;
+	}
+
+	if(tty->flip.count == TTY_FLIPBUF_SIZE) {
+		/* printk("tty->flip.count = TTY_FLIPBUF_SIZE\n"); */
+		return;
+	}
+
+	if(bc->orun) {
+		bc->orun = 0;
+		printk("overrun! DigiBoard device minor=%d\n",MINOR(tty->device));
+	}
+
+	rxwinon(ch);
+	rptr = tty->flip.char_buf_ptr;
+	rc = tty->flip.count;
+	while(n > 0) {
+		wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
+		piece = (wrapgap < n) ? wrapgap : n;
+
+		/*
+		 * Make sure we don't overflow the buffer
+		 */
+
+		if ((rc + piece) > TTY_FLIPBUF_SIZE)
+			piece = TTY_FLIPBUF_SIZE - rc;
+
+		if (piece == 0)
+			break;
+
+		memcpy(rptr, ch->rxptr + tail, piece);
+		rptr += piece;
+		rc += piece;
+		tail = (tail + piece) & wrapmask;
+		n -= piece;
+	}
+	tty->flip.count = rc;
+	tty->flip.char_buf_ptr = rptr;
+    globalwinon(ch);
+	bc->rout = tail;
+
+	/* Must be called with global data */
+	tty_schedule_flip(ch->tty); 
+	return;
+}
+
+
+static int pcxe_ioctl(struct tty_struct *tty, struct file * file,
+		    unsigned int cmd, unsigned long arg)
+{
+	int error;
+	struct channel *ch = (struct channel *) tty->driver_data;
+	volatile struct board_chan *bc;
+	int retval;
+	unsigned int mflag, mstat;
+	unsigned char startc, stopc;
+	unsigned long flags;
+	digiflow_t dflow;
+
+	if(ch)
+		bc = ch->brdchan;
+	else {
+		printk("ch is NULL in pcxe_ioctl!\n");
+		return(-EINVAL);
+	}
+
+	save_flags(flags);
+
+	switch(cmd) {
+		case TCSBRK:	/* SVID version: non-zero arg --> no break */
+			retval = tty_check_change(tty);
+			if(retval)
+				return retval;
+			setup_empty_event(tty,ch);		
+			tty_wait_until_sent(tty, 0);
+			if(!arg)
+				digi_send_break(ch, HZ/4);    /* 1/4 second */
+			return 0;
+
+		case TCSBRKP:	/* support for POSIX tcsendbreak() */
+			retval = tty_check_change(tty);
+			if(retval)
+				return retval;
+			setup_empty_event(tty,ch);		
+			tty_wait_until_sent(tty, 0);
+			digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
+			return 0;
+
+		case TIOCGSOFTCAR:
+			error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));
+			if(error)
+				return error;
+			put_fs_long(C_CLOCAL(tty) ? 1 : 0,
+				    (unsigned long *) arg);
+			return 0;
+
+		case TIOCSSOFTCAR:
+			arg = get_fs_long((unsigned long *) arg);
+			tty->termios->c_cflag =	((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
+			return 0;
+
+		case TIOCMODG:
+		case TIOCMGET:
+			mflag = 0;
+
+			cli();
+			globalwinon(ch);
+			mstat = bc->mstat;
+			memoff(ch);
+			restore_flags(flags);
+
+			if(mstat & DTR)
+				mflag |= TIOCM_DTR;
+			if(mstat & RTS)
+				mflag |= TIOCM_RTS;
+			if(mstat & CTS)
+				mflag |= TIOCM_CTS;
+			if(mstat & ch->dsr)
+				mflag |= TIOCM_DSR;
+			if(mstat & RI)
+				mflag |= TIOCM_RI;
+			if(mstat & ch->dcd)
+				mflag |= TIOCM_CD;
+
+			error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));
+			if(error)
+				return error;
+			put_fs_long(mflag, (unsigned long *) arg);
+			break;
+
+		case TIOCMBIS:
+		case TIOCMBIC:
+		case TIOCMODS:
+		case TIOCMSET:
+			mstat = get_fs_long((unsigned long *) arg);
+
+			mflag = 0;
+			if(mstat & TIOCM_DTR)
+				mflag |= DTR;
+			if(mstat & TIOCM_RTS)
+				mflag |= RTS;
+
+			switch(cmd) {
+				case TIOCMODS:
+				case TIOCMSET:
+					ch->modemfake = DTR|RTS;
+					ch->modem = mflag;
+					break;
+
+				case TIOCMBIS:
+					ch->modemfake |= mflag;
+					ch->modem |= mflag;
+					break;
+
+				case TIOCMBIC:
+					ch->modemfake |= mflag;
+					ch->modem &= ~mflag;
+					break;
+			}
+
+			cli();
+			globalwinon(ch);
+			pcxxparam(tty,ch);
+			memoff(ch);
+			restore_flags(flags);
+			break;
+
+		case TIOCSDTR:
+			cli();
+			ch->omodem |= DTR;
+			globalwinon(ch);
+			fepcmd(ch, SETMODEM, DTR, 0, 10, 1);
+			memoff(ch);
+			restore_flags(flags);
+			break;
+
+		case TIOCCDTR:
+			ch->omodem &= ~DTR;
+			cli();
+			globalwinon(ch);
+			fepcmd(ch, SETMODEM, 0, DTR, 10, 1);
+			memoff(ch);
+			restore_flags(flags);
+			break;
+
+		case DIGI_GETA:
+			if((error=verify_area(VERIFY_WRITE, (char*)arg, sizeof(digi_t))))
+				return(error);
+
+			memcpy_tofs((char*)arg, &ch->digiext, sizeof(digi_t));
+			break;
+
+		case DIGI_SETAW:
+		case DIGI_SETAF:
+			if(cmd == DIGI_SETAW) {
+				setup_empty_event(tty,ch);		
+				tty_wait_until_sent(tty, 0);
+			}
+			else {
+				if(tty->ldisc.flush_buffer)
+					tty->ldisc.flush_buffer(tty);
+			}
+
+			/* Fall Thru */
+
+		case DIGI_SETA:
+			if((error=verify_area(VERIFY_READ, (char*)arg,sizeof(digi_t))))
+				return(error);
+
+			memcpy_fromfs(&ch->digiext, (char*)arg, sizeof(digi_t));
+#ifdef DEBUG_IOCTL
+			printk("ioctl(DIGI_SETA): flags = %x\n", ch->digiext.digi_flags);
+#endif
+			
+			if(ch->digiext.digi_flags & DIGI_ALTPIN) {
+				ch->dcd = DSR;
+				ch->dsr = CD;
+			} else {
+				ch->dcd = CD;
+				ch->dsr = DSR;
+			}
+		
+			cli();
+			globalwinon(ch);
+			pcxxparam(tty,ch);
+			memoff(ch);
+			restore_flags(flags);
+			break;
+
+		case DIGI_GETFLOW:
+		case DIGI_GETAFLOW:
+			cli();	
+			globalwinon(ch);
+			if(cmd == DIGI_GETFLOW) {
+				dflow.startc = bc->startc;
+				dflow.stopc = bc->stopc;
+			} else {
+				dflow.startc = bc->startca;
+				dflow.stopc = bc->stopca;
+			}
+			memoff(ch);
+			restore_flags(flags);
+
+			if((error=verify_area(VERIFY_WRITE, (char*)arg,sizeof(dflow))))
+				return(error);
+
+			memcpy_tofs((char*)arg, &dflow, sizeof(dflow));
+			break;
+
+		case DIGI_SETAFLOW:
+		case DIGI_SETFLOW:
+			if(cmd == DIGI_SETFLOW) {
+				startc = ch->startc;
+				stopc = ch->stopc;
+			} else {
+				startc = ch->startca;
+				stopc = ch->stopca;
+			}
+
+			if((error=verify_area(VERIFY_READ, (char*)arg,sizeof(dflow))))
+				return(error);
+
+			memcpy_fromfs(&dflow, (char*)arg, sizeof(dflow));
+
+			if(dflow.startc != startc || dflow.stopc != stopc) {
+				cli();
+				globalwinon(ch);
+
+				if(cmd == DIGI_SETFLOW) {
+					ch->fepstartc = ch->startc = dflow.startc;
+					ch->fepstopc = ch->stopc = dflow.stopc;
+					fepcmd(ch,SONOFFC,ch->fepstartc,ch->fepstopc,0, 1);
+				} else {
+					ch->fepstartca = ch->startca = dflow.startc;
+					ch->fepstopca  = ch->stopca = dflow.stopc;
+					fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
+				}
+
+				if(ch->statusflags & TXSTOPPED)
+					pcxe_start(tty);
+
+				memoff(ch);
+				restore_flags(flags);
+			}
+			break;
+
+		default:
+			return -ENOIOCTLCMD;
+	}
+
+	return 0;
+}
+
+static void pcxe_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+	struct channel *info;
+
+	if ((info=chan(tty))!=NULL) {
+		unsigned long flags;
+		save_flags(flags);
+		cli();
+		globalwinon(info);
+		pcxxparam(tty,info);
+		memoff(info);
+
+		if ((old_termios->c_cflag & CRTSCTS) &&
+			((tty->termios->c_cflag & CRTSCTS) == 0))
+			tty->hw_stopped = 0;
+		if(!(old_termios->c_cflag & CLOCAL) &&
+			(tty->termios->c_cflag & CLOCAL))
+			wake_up_interruptible(&info->open_wait);
+		restore_flags(flags);
+	}
+}
+
+
+static void do_pcxe_bh(void)
+{
+	run_task_queue(&tq_pcxx);
+}
+
+
+static void do_softint(void *private_)
+{
+	struct channel *info = (struct channel *) private_;
+	
+	if(info && info->magic == PCXX_MAGIC) {
+		struct tty_struct *tty = info->tty;
+		if (tty && tty->driver_data) {
+			if(clear_bit(PCXE_EVENT_HANGUP, &info->event)) {
+				tty_hangup(tty);
+				wake_up_interruptible(&info->open_wait);
+				info->asyncflags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+			}
+		}
+	}
+}
+
+
+static void pcxe_stop(struct tty_struct *tty)
+{
+	struct channel *info;
+
+	if ((info=chan(tty))!=NULL) {
+		unsigned long flags;
+		save_flags(flags); 
+		cli();
+		if ((info->statusflags & TXSTOPPED) == 0) {
+			globalwinon(info);
+			fepcmd(info, PAUSETX, 0, 0, 0, 0);
+			info->statusflags |= TXSTOPPED;
+			memoff(info);
+		}
+		restore_flags(flags);
+	}
+}
+
+static void pcxe_throttle(struct tty_struct * tty)
+{
+	struct channel *info;
+
+	if ((info=chan(tty))!=NULL) {
+		unsigned long flags;
+		save_flags(flags);
+		cli();
+		if ((info->statusflags & RXSTOPPED) == 0) {
+			globalwinon(info);
+			fepcmd(info, PAUSERX, 0, 0, 0, 0);
+			info->statusflags |= RXSTOPPED;
+			memoff(info);
+		}
+		restore_flags(flags);
+	}
+}
+
+static void pcxe_unthrottle(struct tty_struct *tty)
+{
+	struct channel *info;
+
+	if ((info=chan(tty)) != NULL) {
+		unsigned long flags;
+
+		/* Just in case output was resumed because of a change in Digi-flow */
+		save_flags(flags);
+		cli();
+		if(info->statusflags & RXSTOPPED) {
+			volatile struct board_chan *bc;
+			globalwinon(info);
+			bc = info->brdchan;
+			fepcmd(info, RESUMERX, 0, 0, 0, 0);
+			info->statusflags &= ~RXSTOPPED;
+			memoff(info);
+		}
+		restore_flags(flags);
+	}
+}
+
+
+static void pcxe_start(struct tty_struct *tty)
+{
+	struct channel *info;
+
+	if ((info=chan(tty))!=NULL) {
+		unsigned long flags;
+
+		save_flags(flags);
+		cli();
+		/* Just in case output was resumed because of a change in Digi-flow */
+		if(info->statusflags & TXSTOPPED) {
+			volatile struct board_chan *bc;
+			globalwinon(info);
+			bc = info->brdchan;
+			if(info->statusflags & LOWWAIT)
+				bc->ilow = 1;
+			fepcmd(info, RESUMETX, 0, 0, 0, 0);
+			info->statusflags &= ~TXSTOPPED;
+			memoff(info);
+		}
+		restore_flags(flags);
+	}
+}
+
+
+void digi_send_break(struct channel *ch, int msec)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	globalwinon(ch);
+
+	/* 
+	 * Maybe I should send an infinite break here, schedule() for
+	 * msec amount of time, and then stop the break.  This way,
+	 * the user can't screw up the FEP by causing digi_send_break()
+	 * to be called (i.e. via an ioctl()) more than once in msec amount 
+	 * of time.  Try this for now...
+	 */
+
+	fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
+	memoff(ch);
+
+	restore_flags(flags);
+}
+
+static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
+{
+	volatile struct board_chan *bc;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	globalwinon(ch);
+	ch->statusflags |= EMPTYWAIT;
+	bc = ch->brdchan;
+	bc->iempty = 1;
+	memoff(ch);
+	restore_flags(flags);
+}
+
diff -u --recursive --new-file v1.3.82/linux/drivers/char/pcxx.h linux/drivers/char/pcxx.h
--- v1.3.82/linux/drivers/char/pcxx.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/pcxx.h	Wed Apr  3 09:20:45 1996
@@ -0,0 +1,116 @@
+#define FEPCODESEG  0x0200L
+#define FEPCODE     0x2000L
+#define BIOSCODE    0xf800L
+
+#define MISCGLOBAL  0x0C00L
+#define NPORT       0x0C22L
+#define MBOX        0x0C40L
+#define PORTBASE    0x0C90L
+
+#define FEPCLR      0x00
+#define FEPMEM      0x02
+#define FEPRST      0x04
+#define FEPINT      0x08
+#define	FEPMASK     0x0e
+#define	FEPWIN      0x80
+
+#define PCXI    0
+#define PCXE    1
+#define	PCXEVE	2
+
+static char *board_desc[] = {
+	"PC/Xi (64K)",
+	"PC/Xe (64K)",
+	"PC/Xe (8K) ",
+};
+
+#define STARTC      021
+#define STOPC       023
+#define IAIXON      0x2000
+
+
+struct board_info	{
+	unchar status;
+	unchar type;
+	unchar altpin;
+	ushort numports;
+	ushort port;
+	ulong  membase;
+};
+
+
+#define TXSTOPPED   0x01
+#define LOWWAIT		0x02
+#define EMPTYWAIT	0x04
+#define RXSTOPPED	0x08
+#define TXBUSY		0x10
+
+#define DISABLED   0
+#define ENABLED    1
+#define OFF        0
+#define ON         1
+
+#define FEPTIMEOUT 200000  
+#define SERIAL_TYPE_NORMAL	1
+#define SERIAL_TYPE_CALLOUT	2
+#define PCXE_EVENT_HANGUP   1
+#define PCXX_MAGIC	0x5c6df104L
+
+struct channel {
+							/* --------- Board/channel information ---------- */
+	long						magic;
+	unchar						boardnum;
+	unchar						channelnum;
+	uint						dev;
+	long						session;
+	long						pgrp;
+	struct tty_struct			*tty;
+	struct board_info			*board;
+	volatile struct board_chan	*brdchan;
+	volatile struct global_data *mailbox;
+	int							asyncflags;
+	int							count;
+	int							blocked_open;
+	int							close_delay;
+	int							event;
+	struct wait_queue			*open_wait;
+	struct wait_queue			*close_wait;
+	struct tq_struct			tqueue;
+							/* ------------ Async control data ------------- */
+	unchar						modemfake;      /* Modem values to be forced */
+	unchar						modem;          /* Force values */
+	ulong						statusflags;
+	unchar						omodem;         /* FEP output modem status */
+	unchar						imodem;         /* FEP input modem status */
+	unchar						hflow;
+	unchar						dsr;
+	unchar						dcd;
+	unchar						stopc;
+	unchar						startc;
+	unchar						stopca;
+	unchar						startca;
+	unchar						fepstopc;
+	unchar						fepstartc;
+	unchar						fepstopca;
+	unchar						fepstartca;
+	ushort						fepiflag;
+	ushort						fepcflag;
+	ushort						fepoflag;
+							/* ---------- Transmit/receive system ---------- */
+	unchar						txwin;
+	unchar						rxwin;
+	ushort						txbufsize;
+	ushort						rxbufsize;
+	unchar						*txptr;
+	unchar						*rxptr;
+	unchar						*tmp_buf;		/* Temp buffer */
+							/* ---- Termios data ---- */
+	ulong						c_iflag;
+	ulong						c_cflag;
+	ulong						c_lflag;
+	ulong						c_oflag;
+	struct termios				normal_termios;
+	struct termios				callout_termios;
+	struct digi_struct			digiext;
+	ulong						dummy[8];
+};
diff -u --recursive --new-file v1.3.82/linux/drivers/char/pcxxconfig.h linux/drivers/char/pcxxconfig.h
--- v1.3.82/linux/drivers/char/pcxxconfig.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/pcxxconfig.h	Wed Apr  3 09:20:45 1996
@@ -0,0 +1,5 @@
+#define NUMCARDS 1
+
+struct board_info boards[NUMCARDS]={
+{	ENABLED, 0, ON, 16, 0x200, 0xd0000 }
+};
diff -u --recursive --new-file v1.3.82/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v1.3.82/linux/drivers/char/tty_io.c	Sun Mar 31 00:13:17 1996
+++ linux/drivers/char/tty_io.c	Wed Apr  3 09:20:45 1996
@@ -1838,6 +1838,9 @@
 #ifdef CONFIG_ISTALLION
 	stli_init();
 #endif
+#ifdef CONFIG_DIGI
+	pcxe_init();
+#endif
 	pty_init();
 	vcs_init();
 	if (register_chrdev(TTY_MAJOR,"tty",&tty_fops))
diff -u --recursive --new-file v1.3.82/linux/drivers/net/3c505.c linux/drivers/net/3c505.c
--- v1.3.82/linux/drivers/net/3c505.c	Fri Mar  1 07:50:42 1996
+++ linux/drivers/net/3c505.c	Wed Apr  3 08:51:36 1996
@@ -1,36 +1,37 @@
 /*
  * Linux ethernet device driver for the 3Com Etherlink Plus (3C505)
- * 	By Craig Southeren and Juha Laiho
+ *      By Craig Southeren and Juha Laiho
  *
- * 3c505.c	This module implements an interface to the 3Com
- *		Etherlink Plus (3c505) ethernet card. Linux device 
- *		driver interface reverse engineered from the Linux 3C509
- *		device drivers. Some 3C505 information gleaned from
- *		the Crynwr packet driver. Still this driver would not
- *		be here without 3C505 technical reference provided by
- *		3Com.
+ * 3c505.c      This module implements an interface to the 3Com
+ *              Etherlink Plus (3c505) ethernet card. Linux device 
+ *              driver interface reverse engineered from the Linux 3C509
+ *              device drivers. Some 3C505 information gleaned from
+ *              the Crynwr packet driver. Still this driver would not
+ *              be here without 3C505 technical reference provided by
+ *              3Com.
  *
- * Version:	@(#)3c505.c	0.8.4	17-Dec-95
+ * $Id: 3c505.c,v 0.9.1.1 1996/04/02 13:58:06 root Exp $
  *
- * Authors:	Linux 3c505 device driver by
- *			Craig Southeren, <craigs@ineluki.apana.org.au>
+ * Authors:     Linux 3c505 device driver by
+ *                      Craig Southeren, <craigs@ineluki.apana.org.au>
  *              Final debugging by
- *			Andrew Tridgell, <tridge@nimbus.anu.edu.au>
- *		Auto irq/address, tuning, cleanup and v1.1.4+ kernel mods by
- *			Juha Laiho, <jlaiho@ichaos.nullnet.fi>
+ *                      Andrew Tridgell, <tridge@nimbus.anu.edu.au>
+ *              Auto irq/address, tuning, cleanup and v1.1.4+ kernel mods by
+ *                      Juha Laiho, <jlaiho@ichaos.nullnet.fi>
  *              Linux 3C509 driver by
- *             		Donald Becker, <becker@super.org>
- *		Crynwr packet driver by
- *			Krishnan Gopalan and Gregg Stefancik,
- * 			   Clemson University Engineering Computer Operations.
- *			Portions of the code have been adapted from the 3c505
- *			   driver for NCSA Telnet by Bruce Orchard and later
- *			   modified by Warren Van Houten and krus@diku.dk.
+ *                      Donald Becker, <becker@super.org>
+ *              Crynwr packet driver by
+ *                      Krishnan Gopalan and Gregg Stefancik,
+ *                      Clemson University Engineering Computer Operations.
+ *                      Portions of the code have been adapted from the 3c505
+ *                         driver for NCSA Telnet by Bruce Orchard and later
+ *                         modified by Warren Van Houten and krus@diku.dk.
  *              3C505 technical information provided by
  *                      Terry Murphy, of 3Com Network Adapter Division
- *		Linux 1.3.0 changes by
- *			Alan Cox <Alan.Cox@linux.org>
- *                     
+ *              Linux 1.3.0 changes by
+ *                      Alan Cox <Alan.Cox@linux.org>
+ *              More debugging by Philip Blundell <pjb27@cam.ac.uk>
+ *
  */
 
 #include <linux/module.h>
@@ -61,10 +62,6 @@
 
 static const char * filename = __FILE__;
 
-static const char * null_msg = "*** NULL at %s:%s (line %d) ***\n";
-#define CHECK_NULL(p) \
-	if (!p) printk(null_msg, filename,__FUNCTION__,__LINE__)
-
 static const char * timeout_msg = "*** timeout at %s:%s (line %d) ***\n";
 #define TIMEOUT_MSG(lineno) \
 	printk(timeout_msg, filename,__FUNCTION__,(lineno))
@@ -103,8 +100,6 @@
  *  3 = messages when interrupts received
  */
 
-#define	ELP_VERSION	"0.8.4"
-
 /*****************************************************************
  *
  * useful macros
@@ -230,34 +225,6 @@
 	sti(); 
 }
 
-#define WAIT_HCRE(addr,toval) wait_hcre((addr),(toval),__LINE__)
-static inline int
-wait_hcre (unsigned int base_addr, int toval, int lineno)
-{
-	int timeout = jiffies + toval;
-	while (((inb_status(base_addr)&HCRE)==0) && (jiffies <= timeout))
-		;
-	if (jiffies >= timeout) {
-		TIMEOUT_MSG(lineno);
-		return FALSE;
-	}
-	return TRUE;
-}
-
-static inline int
-wait_fast_hcre (unsigned int base_addr, int toval, int lineno)
-{
-	int timeout = 0;
-	while (((inb_status(base_addr)&HCRE)==0) && (timeout++ < toval))
-		;
-	if (timeout >= toval) {
-		sti();
-		TIMEOUT_MSG(lineno);
-		return FALSE;
-	}
-	return TRUE;
-}
-
 static int start_receive (struct device *, pcb_struct *);
 static void adapter_hard_reset (struct device *);
 
@@ -303,6 +270,46 @@
 		printk("%s: start receive command failed \n", dev->name);
 }
 
+/* These should be moved to the private data area */
+static int send_pcb_semaphore = 0;
+static int rx_restart_needed = 0;
+
+/* Primitive functions used by send_pcb() */
+static inline int send_pcb_slow(unsigned int base_addr, unsigned char byte)
+{
+	int timeout;
+	outb_command(byte, base_addr);
+	for (timeout = jiffies + 5; jiffies < timeout; ) {
+		if (inb_status(base_addr) & HCRE) return FALSE;
+	}
+	printk("3c505: send_pcb_slow timed out\n");
+	return TRUE;
+}
+
+static inline int send_pcb_fast(unsigned int base_addr, unsigned char byte)
+{
+	int timeout;
+	outb_command(byte, base_addr);
+	for (timeout = 0; timeout < 40000; timeout++) {
+		if (inb_status(base_addr) & HCRE) return FALSE;
+	}
+	printk("3c505: send_pcb_fast timed out\n");
+	return TRUE;
+}
+
+static int
+start_receive (struct device * dev, pcb_struct * tx_pcb);
+
+/* Check to see if the receiver needs restarting, and kick it if so */
+static inline void prime_rx(struct device *dev)
+{
+	if (rx_restart_needed) {
+		elp_device *adapter = dev->priv;
+		rx_restart_needed = 0;
+		start_receive(dev, &adapter->itx_pcb);
+	}
+}
+
 /*****************************************************************
  *
  * send_pcb
@@ -318,71 +325,79 @@
  *
  *****************************************************************/
 
+/* This can be quite slow -- the adapter is allowed to take up to 40ms
+ * to respond to the initial interrupt.
+ *
+ * We run initially with interrupts turned on, but with a semaphore set
+ * so that nobody tries to re-enter this code.  Once the first byte has
+ * gone through, we turn interrupts off and then send the others (the
+ * timeout is reduced to 500us).
+ */
+
 static int
 send_pcb (struct device * dev, pcb_struct * pcb)
 {
 	int i;
 	int timeout;
-	int cont;
+
+        /* Avoid contention */
+	if (set_bit(1, &send_pcb_semaphore)) {
+		if (elp_debug >= 3) {
+			printk("%s: send_pcb entered while threaded\n", dev->name);
+		}
+		return FALSE;
+	}
 
 	/*
 	 * load each byte into the command register and
 	 * wait for the HCRE bit to indicate the adapter
 	 * had read the byte
 	 */
-	set_hsf(dev->base_addr,0); 
-	if ((cont = WAIT_HCRE(dev->base_addr,5))) {
-		cli();
-		if (pcb->command==CMD_TRANSMIT_PACKET)
-			outb_control(inb_control(dev->base_addr)&~DIR,dev->base_addr);
-		outb_command(pcb->command, dev->base_addr);
-		sti();
-		cont = WAIT_HCRE(dev->base_addr,5);
-	}
+	set_hsf(dev->base_addr,0);
 
-	if (cont) {
-		outb_command(pcb->length, dev->base_addr);
-		cont = WAIT_HCRE(dev->base_addr,5);
-	}
+	if (send_pcb_slow(dev->base_addr, pcb->command)) goto abort;
 
 	cli();
-	for (i = 0; cont && (i < pcb->length); i++) {
-		outb_command(pcb->data.raw[i], dev->base_addr);
-		cont = wait_fast_hcre(dev->base_addr,20000,__LINE__);
-	} /* if wait_fast_hcre() failed, has already done sti() */
-
-	/* set the host status bits to indicate end of PCB */
-	/* send the total packet length as well */
-	/* wait for the adapter to indicate that it has read the PCB */
-	if (cont) {
-		set_hsf(dev->base_addr,HSF_PCB_END);
-		outb_command(2+pcb->length, dev->base_addr);
-		sti();
-		timeout = jiffies + 7;
-		while (jiffies < timeout) {
-			i = GET_ASF(dev->base_addr);
-			if ((i == ASF_PCB_ACK) || (i == ASF_PCB_NAK))
-				break;
-		}
 
-		if (i == ASF_PCB_ACK) {
-			reset_count=0;
+	if (send_pcb_fast(dev->base_addr, pcb->length)) goto sti_abort;
+
+	for (i = 0; i < pcb->length; i++) {
+		if (send_pcb_fast(dev->base_addr, pcb->data.raw[i])) goto sti_abort;
+	}
+
+	outb_control(inb_control(dev->base_addr) | 3, dev->base_addr);  /* signal end of PCB */
+	outb_command(2+pcb->length, dev->base_addr);
+
+	/* now wait for the acknowledgement */
+	sti();
+
+	for (timeout = jiffies+5; jiffies < timeout; ) {
+		switch (GET_ASF(dev->base_addr)) {
+		case ASF_PCB_ACK:
+			send_pcb_semaphore = 0;
+			if (pcb->command != CMD_TRANSMIT_PACKET) {
+				prime_rx(dev);
+			}
 			return TRUE;
+			break;
+		case ASF_PCB_NAK:
+			printk(KERN_INFO "%s: send_pcb got NAK\n", dev->name);
+			goto abort;
+			break;
 		}
-		else if (i == ASF_PCB_NAK) {
-			printk("%s: PCB send was NAKed\n", dev->name);
-		} else {
-			printk("%s: timeout after sending PCB\n", dev->name);
-		}
-	} else {
-		sti();
-		printk("%s: timeout in middle of sending PCB\n", dev->name);
 	}
 
-	adapter_reset(dev);
+	printk("%s: timeout waiting for PCB acknowledge (status %02x)\n", dev->name, inb_status(dev->base_addr));
+
+sti_abort:
+	sti();
+abort:
+	send_pcb_semaphore = 0;
+	prime_rx(dev);
 	return FALSE;
 }
 
+
 /*****************************************************************
  *
  * receive_pcb
@@ -404,9 +419,6 @@
 	int stat;
 	int timeout;
 
-	CHECK_NULL(pcb);
-	CHECK_NULL(dev);
-
 	set_hsf(dev->base_addr,0);
 
 	/* get the command code */
@@ -426,6 +438,7 @@
 		;
 	if (jiffies >= timeout) {
 		TIMEOUT_MSG(__LINE__);
+		printk("%s: status %02x\n", dev->name, stat);
 		return FALSE;
 	}
 	pcb->length = inb_command(dev->base_addr);
@@ -475,8 +488,6 @@
 	int timeout;
 	long flags;
 
-	CHECK_NULL(dev);
-
 	save_flags(flags);
 	sti();
 
@@ -524,9 +535,6 @@
 static int
 start_receive (struct device * dev, pcb_struct * tx_pcb)
 {
-	CHECK_NULL(dev);
-	CHECK_NULL(tx_pcb);
-
 	if (elp_debug >= 3)
 		printk("%s: restarting receiver\n", dev->name);
 	tx_pcb->command = CMD_RECEIVE_PACKET;
@@ -557,7 +565,6 @@
 	struct sk_buff *skb;
 	elp_device * adapter;
 
-	CHECK_NULL(dev);
 	adapter=dev->priv;
 
 	if (len <= 0 || ((len & ~1) != len))
@@ -581,6 +588,7 @@
 	 * if buffer could not be allocated, swallow it
 	 */
 	if (skb == NULL) {
+		printk(KERN_INFO "%s: memory squeeze, dropping packet\n", dev->name);
 		for (i = 0; i < (rlen/2); i++) {
 			timeout = 0;
 			while ((inb_status(dev->base_addr)&HRDY) == 0 && timeout++ < 20000)
@@ -657,8 +665,6 @@
 
 	adapter = (elp_device *) dev->priv;
 
-	CHECK_NULL(adapter);
-
 	if (dev->interrupt)
 		if (elp_debug >= 2)
 			printk("%s: Re-entering the interrupt handler.\n", dev->name);
@@ -687,9 +693,6 @@
 					if (dev->start == 0)
 						break;
 					cli();
-					/* Set direction of adapter FIFO */
-					outb_control(inb_control(dev->base_addr)|DIR,
-					             dev->base_addr);
 					len = adapter->irx_pcb.data.rcv_resp.pkt_len;
 					dlen = adapter->irx_pcb.data.rcv_resp.buf_len;
 					if (adapter->irx_pcb.data.rcv_resp.timeout != 0) {
@@ -706,9 +709,11 @@
 						if (elp_debug >= 3)
 							printk("%s: packet received\n", dev->name);
 					}
-					if (dev->start && !start_receive(dev, &adapter->itx_pcb)) 
+					if (dev->start && !start_receive(dev, &adapter->itx_pcb)) {
 						if (elp_debug >= 2)
-							printk("%s: interrupt - failed to send receive start PCB\n", dev->name);
+							printk("%s: interrupt - receiver start deferred\n", dev->name);
+						rx_restart_needed = 1;
+					}
 					if (elp_debug >= 3)
 					printk("%s: receive procedure complete\n", dev->name);
 
@@ -815,8 +820,6 @@
 {
 	elp_device * adapter;
 
-	CHECK_NULL(dev);
-
 	adapter = dev->priv;
 
 	if (elp_debug >= 3)  
@@ -923,6 +926,12 @@
 	 */
 	if (!start_receive(dev, &adapter->tx_pcb))
 		printk("%s: start receive command failed \n", dev->name);
+	if (!start_receive(dev, &adapter->tx_pcb))
+		printk("%s: start receive command failed \n", dev->name);
+	if (!start_receive(dev, &adapter->tx_pcb))
+		printk("%s: start receive command failed \n", dev->name);
+	if (!start_receive(dev, &adapter->tx_pcb))
+		printk("%s: start receive command failed \n", dev->name);
 	if (elp_debug >= 3)
 		printk("%s: start receive command sent\n", dev->name);
 
@@ -950,9 +959,6 @@
 	 */
 	unsigned int nlen = (((len < 60) ? 60 : len) + 1) & (~1);
 
-	CHECK_NULL(dev);
-	CHECK_NULL(ptr);
-
 	adapter = dev->priv;
 
 	if (nlen < len)
@@ -991,6 +997,8 @@
 	}
 	sti();
 
+	prime_rx(dev);
+
 	return TRUE;
 }
 
@@ -1004,19 +1012,28 @@
 static int
 elp_start_xmit (struct sk_buff *skb, struct device *dev)
 {
-	CHECK_NULL(dev);
-
 	/*
-	 * not sure what this does, but the 3c509 driver does it, so...
+	 * if the transmitter is still busy, we have a transmit timeout...
 	 */
+	if (dev->tbusy) {
+		int tickssofar = jiffies - dev->trans_start;
+		int stat;
+		if (tickssofar < 40)
+			return 1;
+		stat = inb_status(dev->base_addr);
+		printk("%s: transmit timed out, %s?\n", dev->name, (stat & ACRF)?"IRQ conflict":"network cable problem");
+		if (elp_debug >= 1)
+		  printk("%s: status %#02x\n", dev->name, stat);
+		dev->trans_start = jiffies;
+		dev->tbusy = 0;
+	}
+
+	/* Some upper layer thinks we've missed a tx-done interrupt */
 	if (skb == NULL) {
 		dev_tint(dev);
 		return 0;
 	}
 
-	/*
-	 * if we ended up with a munged length, don't send it
-	 */
 	if (skb->len <= 0)
 		return 0;
 
@@ -1024,26 +1041,10 @@
 		printk("%s: request to send packet of length %d\n", dev->name, (int)skb->len);
 
 	/*
-	 * if the transmitter is still busy, we have a transmit timeout...
-	 */
-	if (dev->tbusy) {
-		int tickssofar = jiffies - dev->trans_start;
-		int stat;
-		if (tickssofar < 50) /* was 500, AJT */
-			return 1;
-		printk("%s: transmit timed out, not resetting adapter\n", dev->name);
-		if (((stat=inb_status(dev->base_addr))&ACRF) != 0) 
-			printk("%s: hmmm...seemed to have missed an interrupt!\n", dev->name);
-		printk("%s: status %#02x\n", dev->name, stat);
-		dev->trans_start = jiffies;
-		dev->tbusy = 0;
-	}
-
-	/*
 	 * send the packet at skb->data for skb->len
 	 */
 	if (!send_packet(dev, skb->data, skb->len)) {
-		printk("%s: send packet PCB failed\n", dev->name);
+		printk("%s: failed to transmit packet\n", dev->name);
 		return 1;
 	}
 
@@ -1119,9 +1120,7 @@
 {
 	elp_device * adapter;
 
-	CHECK_NULL(dev);
 	adapter = dev->priv;
-	CHECK_NULL(adapter);
 
 	if (elp_debug >= 3)
 		printk("%s: request to close device\n", dev->name);
@@ -1242,8 +1241,6 @@
 {
 	elp_device * adapter;
 
-	CHECK_NULL(dev);
-
 	/*
 	 * set ptrs to various functions
 	 */
@@ -1260,7 +1257,6 @@
 	 * setup ptr to adapter specific information
 	 */
 	adapter = (elp_device *)(dev->priv = kmalloc(sizeof(elp_device), GFP_KERNEL));
-	CHECK_NULL(adapter);
 	if (adapter == NULL)
 		return;
 	memset(&(adapter->stats), 0, sizeof(struct enet_statistics));
@@ -1392,8 +1388,6 @@
 	elp_device adapter;
 	int i;
 
-	CHECK_NULL(dev);
-
 	/*
 	 *  setup adapter structure
 	 */
@@ -1420,6 +1414,7 @@
 	    (adapter.rx_pcb.command != CMD_ADDRESS_RESPONSE) ||
 	    (adapter.rx_pcb.length != 6)) {
 		printk("%s: not responding to first PCB\n", dev->name);
+		autoirq_report(0);
 		return -ENODEV;
 	}
 
diff -u --recursive --new-file v1.3.82/linux/drivers/net/README.3c505 linux/drivers/net/README.3c505
--- v1.3.82/linux/drivers/net/README.3c505	Wed Jun  7 11:39:06 1995
+++ linux/drivers/net/README.3c505	Wed Apr  3 08:51:36 1996
@@ -16,17 +16,21 @@
  to 1 may help. As of 3c505.c v0.8 the driver should be able to find
  out whether of not this is needed, but I'm not completely sure.
 ELP_DEBUG
- The driver debug level. 1 is ok for most everything, 0 will provide
- less verbose bootup messages, and 2 and 3 are usually too verbose
- for anything.
+ The driver debug level.  It's probably best to leave it at 0 most of the time.
+ If you are having trouble, setting it to 1 may give you more information.
+ Any higher setting is too verbose for most purposes.
 
 Known problems:
- During startup the driver shows the following two messages:
- *** timeout at 3c505.c:elp_set_mc_list (line 1158) ***
- *** timeout at 3c505.c:elp_set_mc_list (line 1183) ***
- These are because upper parts of the networking code attempt
- to load multicast address lists to the adapter before the
- adapter is properly up and running.
+ The 3c505 is a slow card, mostly because of the way it talks to the host.
+ Don't expect any great performance from it.
+
+ I am seeing periodic "transmit timed out" and "timeout waiting for PCB
+ acknowledge" messages under high load.  I'm not sure what's causing these -
+ it seems that the 3c505 occasionally just loses a command.  They seem not to
+ be fatal, anyway.
+
+ There may be some initialisation problems still lurking, particularly when
+ warm-booting from DOS (ELP_NEED_HARD_RESET seems not to help).
 
 Authors:
  The driver is mainly written by Craig Southeren, email
@@ -34,3 +38,4 @@
  Parts of the driver (adapting the driver to 1.1.4+ kernels,
  IRQ/address detection, some changes) and this README by
  Juha Laiho <jlaiho@ichaos.nullnet.fi>.
+ Philip Blundell <pjb27@cam.ac.uk> made some more changes.
diff -u --recursive --new-file v1.3.82/linux/drivers/sound/pss.c linux/drivers/sound/pss.c
--- v1.3.82/linux/drivers/sound/pss.c	Sun Mar 24 22:50:16 1996
+++ linux/drivers/sound/pss.c	Wed Apr  3 09:02:40 1996
@@ -426,7 +426,7 @@
 #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   return probe_mpu401 (hw_config);
 #else
-  return 0
+  return 0;
 #endif
 }
 
@@ -775,15 +775,17 @@
 long
 attach_pss_mpu (long mem_start, struct address_info *hw_config)
 {
-  int             prev_devs;
   long            ret;
 
 #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
-  prev_devs = num_midis;
-  ret = attach_mpu401 (mem_start, hw_config);
-
-  if (num_midis == (prev_devs + 1))	/* The MPU driver installed itself */
-    midi_devs[prev_devs]->coproc = &pss_coproc_operations;
+  {
+    int             prev_devs;
+    prev_devs = num_midis;
+    ret = attach_mpu401 (mem_start, hw_config);
+
+    if (num_midis == (prev_devs + 1))	/* The MPU driver installed itself */
+      midi_devs[prev_devs]->coproc = &pss_coproc_operations;
+  }
 #endif
   return ret;
 }
diff -u --recursive --new-file v1.3.82/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v1.3.82/linux/fs/ncpfs/dir.c	Wed Mar 27 08:19:29 1996
+++ linux/fs/ncpfs/dir.c	Tue Apr  2 13:33:13 1996
@@ -125,10 +125,10 @@
 
 /* Here we encapsulate the inode number handling that depends upon the
  * mount mode: When we mount a complete server, the memory address of
- * the npc_inode_info is used as an inode. When only a single volume
- * is mounted, then the DosDirNum is used as the inode number. As this
- * is unique for the complete volume, this should enable the NFS
- * exportability of a ncpfs-mounted volume.
+ * the ncp_inode_info is used as the inode number. When only a single
+ * volume is mounted, then the DosDirNum is used as the inode
+ * number. As this is unique for the complete volume, this should
+ * enable the NFS exportability of a ncpfs-mounted volume.
  */
 
 static inline int
@@ -183,10 +183,6 @@
 	return -EISDIR;
 }
 
-/* In ncpfs, we have unique inodes across all mounted filesystems, for
-   all inodes that are in memory. That's why it's enough to index the
-   directory cache by the inode number. */
-
 static kdev_t             c_dev = 0;
 static unsigned long      c_ino = 0;
 static int                c_size;
@@ -320,11 +316,6 @@
 
         while (index < c_size)
 	{
-                /* We found it.  For getwd(), we have to return the
-                   correct inode in d_ino if the inode is currently in
-                   use. Otherwise the inode number does not
-                   matter. (You can argue a lot about this..) */
-
 		ino_t ino;
 
 		if (ncp_single_volume(server))
@@ -333,6 +324,10 @@
 		}
 		else
 		{
+			/* For getwd() we have to return the correct
+			 * inode in d_ino if the inode is currently in
+			 * use. Otherwise the inode number does not
+			 * matter. (You can argue a lot about this..) */
 			struct ncp_inode_info *ino_info;
 			ino_info = ncp_find_dir_inode(inode,
 						      entry->i.entryName);
diff -u --recursive --new-file v1.3.82/linux/fs/ncpfs/sock.c linux/fs/ncpfs/sock.c
--- v1.3.82/linux/fs/ncpfs/sock.c	Sun Mar 10 13:49:16 1996
+++ linux/fs/ncpfs/sock.c	Tue Apr  2 13:33:13 1996
@@ -1,5 +1,5 @@
 /*
- *  linux/fs/ncp/sock.c
+ *  linux/fs/ncpfs/sock.c
  *
  *  Copyright (C) 1992, 1993  Rick Sladkey
  *
diff -u --recursive --new-file v1.3.82/linux/fs/nfs/rpcsock.c linux/fs/nfs/rpcsock.c
--- v1.3.82/linux/fs/nfs/rpcsock.c	Tue Apr  2 13:32:22 1996
+++ linux/fs/nfs/rpcsock.c	Wed Apr  3 08:29:11 1996
@@ -412,10 +412,8 @@
 		while (rsock->pending != slot) {
 			if (!slot->w_gotit)
 				interruptible_sleep_on(&slot->w_wait);
-			if (slot->w_gotit) {
-				result = slot->w_result; /* quite important */
-				return result;
-			}
+			if (slot->w_gotit)
+				return slot->w_result; /* quite important */
 			if (current->signal & ~current->blocked)
 				return -ERESTARTSYS;
 			if (rsock->shutdown)
@@ -427,15 +425,15 @@
 		/* Wait for data to arrive */
 		if ((result = rpc_select(rsock)) < 0) {
 			dprintk("RPC: select error = %d\n", result);
-			break;
+			return result;
 		}
 
 		/* Receive and dispatch */
 		if ((result = rpc_grok(rsock)) < 0)
-			break;
+			return result;
 	} while (current->timeout && !slot->w_gotit);
 
-	return slot->w_gotit? result : -ETIMEDOUT;
+	return slot->w_gotit? slot->w_result : -ETIMEDOUT;
 }
 
 /*
diff -u --recursive --new-file v1.3.82/linux/fs/proc/mem.c linux/fs/proc/mem.c
--- v1.3.82/linux/fs/proc/mem.c	Fri Dec 22 13:00:19 1995
+++ linux/fs/proc/mem.c	Wed Apr  3 10:59:32 1996
@@ -267,6 +267,8 @@
 	stmp    = vma->vm_offset;
 	dtmp    = vma->vm_start;
 
+	flush_cache_range(vma->vm_mm, vma->vm_start, vma->vm_end);
+	flush_cache_range(src_vma->vm_mm, src_vma->vm_start, src_vma->vm_end);
 	while (dtmp < vma->vm_end) {
 		while (src_vma && stmp > src_vma->vm_end)
 			src_vma = src_vma->vm_next;
@@ -297,8 +299,8 @@
 		dtmp += PAGE_SIZE;
 	}
 
-	invalidate_range(vma->vm_mm, vma->vm_start, vma->vm_end);
-	invalidate_range(src_vma->vm_mm, src_vma->vm_start, src_vma->vm_end);
+	flush_tlb_range(vma->vm_mm, vma->vm_start, vma->vm_end);
+	flush_tlb_range(src_vma->vm_mm, src_vma->vm_start, src_vma->vm_end);
 	return 0;
 }
 
diff -u --recursive --new-file v1.3.82/linux/include/asm-alpha/hwrpb.h linux/include/asm-alpha/hwrpb.h
--- v1.3.82/linux/include/asm-alpha/hwrpb.h	Tue Apr  2 13:32:22 1996
+++ linux/include/asm-alpha/hwrpb.h	Wed Apr  3 09:22:22 1996
@@ -37,7 +37,7 @@
 #define ST_DEC_EB64P		 20	/* EB64+ systype	*/
 #define ST_DEC_EB66P		-19	/* EB66 systype		*/
 #define ST_DEC_EBPC64		-20	/* Cabriolet (AlphaPC64) systype */
-#defien ST_DEC_EB164		 26	/* EB164 systype	*/
+#define ST_DEC_EB164		 26	/* EB164 systype	*/
 
 struct pcb_struct {
 	unsigned long ksp;
diff -u --recursive --new-file v1.3.82/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h
--- v1.3.82/linux/include/asm-alpha/pgtable.h	Thu Mar 14 16:33:27 1996
+++ linux/include/asm-alpha/pgtable.h	Wed Apr  3 11:01:23 1996
@@ -11,27 +11,34 @@
 
 #include <asm/system.h>
 
+/* Caches aren't brain-dead on the alpha. */
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(mm, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_page_to_ram(page)			do { } while (0)
+
 /*
- * Invalidate current user mapping.
+ * Flush current user mapping.
  */
-static inline void invalidate(void)
+static inline void flush_tlb(void)
 {
 	tbiap();
 }
 
 /*
- * Invalidate everything (kernel mapping may also have
+ * Flush everything (kernel mapping may also have
  * changed due to vmalloc/vfree)
  */
-static inline void invalidate_all(void)
+static inline void flush_tlb_all(void)
 {
 	tbia();
 }
 
 /*
- * Invalidate a specified user mapping
+ * Flush a specified user mapping
  */
-static inline void invalidate_mm(struct mm_struct *mm)
+static inline void flush_tlb_mm(struct mm_struct *mm)
 {
 	if (mm != current->mm)
 		mm->context = 0;
@@ -40,14 +47,14 @@
 }
 
 /*
- * Page-granular invalidate.
+ * Page-granular tlb flush.
  *
  * do a tbisd (type = 2) normally, and a tbis (type = 3)
  * if it is an executable mapping.  We want to avoid the
- * itlb invalidate, because that potentially also does a
- * icache invalidate. 
+ * itlb flush, because that potentially also does a
+ * icache flush.
  */
-static inline void invalidate_page(struct vm_area_struct *vma,
+static inline void flush_tlb_page(struct vm_area_struct *vma,
 	unsigned long addr)
 {
 	struct mm_struct * mm = vma->vm_mm;
@@ -59,10 +66,10 @@
 }
 
 /*
- * Invalidate a specified range of user mapping: on the
- * alpha we invalidate the whole user tlb
+ * Flush a specified range of user mapping: on the
+ * alpha we flush the whole user tlb
  */
-static inline void invalidate_range(struct mm_struct *mm,
+static inline void flush_tlb_range(struct mm_struct *mm,
 	unsigned long start, unsigned long end)
 {
 	if (mm != current->mm)
diff -u --recursive --new-file v1.3.82/linux/include/asm-i386/locks.h linux/include/asm-i386/locks.h
--- v1.3.82/linux/include/asm-i386/locks.h	Mon Oct  2 14:25:11 1995
+++ linux/include/asm-i386/locks.h	Wed Apr  3 10:59:32 1996
@@ -40,7 +40,7 @@
 			 
 			if(smp_invalidate_needed&(1<<processor));
 				while(lock_clear_bit(processor,&smp_invalidate_needed))
-					local_invalidate();
+					local_flush_tlb();
 			sp->spins++;
 		}
 		/*
diff -u --recursive --new-file v1.3.82/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v1.3.82/linux/include/asm-i386/pgtable.h	Thu Mar 14 16:33:04 1996
+++ linux/include/asm-i386/pgtable.h	Wed Apr  3 11:01:23 1996
@@ -19,139 +19,146 @@
  * the i386 page table tree.
  */
 
+/* Caches aren't brain-dead on the intel. */
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(mm, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_page_to_ram(page)			do { } while (0)
+
 /*
- * TLB invalidation:
+ * TLB flushing:
  *
- *  - invalidate() invalidates the current mm struct TLBs
- *  - invalidate_all() invalidates all processes TLBs
- *  - invalidate_mm(mm) invalidates the specified mm context TLB's
- *  - invalidate_page(mm, vmaddr) invalidates one page
- *  - invalidate_range(mm, start, end) invalidates a range of pages
+ *  - flush_tlb() flushes the current mm struct TLBs
+ *  - flush_tlb_all() flushes all processes TLBs
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(mm, start, end) flushes a range of pages
  *
- * ..but the i386 has somewhat limited invalidation capabilities,
- * and page-granular invalidates are available only on i486 and up.
+ * ..but the i386 has somewhat limited tlb flushing capabilities,
+ * and page-granular flushes are available only on i486 and up.
  */
 
-#define __invalidate() \
+#define __flush_tlb() \
 __asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax")
 
 #ifdef CONFIG_M386
-#define __invalidate_one(addr) invalidate()
+#define __flush_tlb_one(addr) flush_tlb()
 #else
-#define __invalidate_one(addr) \
+#define __flush_tlb_one(addr) \
 __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
 #endif
  
 #ifndef __SMP__
 
-#define invalidate() __invalidate()
-#define invalidate_all() __invalidate()
+#define flush_tlb() __flush_tlb()
+#define flush_tlb_all() __flush_tlb()
 
-static inline void invalidate_mm(struct mm_struct *mm)
+static inline void flush_tlb_mm(struct mm_struct *mm)
 {
 	if (mm == current->mm)
-		__invalidate();
+		__flush_tlb();
 }
 
-static inline void invalidate_page(struct vm_area_struct *vma,
+static inline void flush_tlb_page(struct vm_area_struct *vma,
 	unsigned long addr)
 {
 	if (vma->vm_mm == current->mm)
-		__invalidate_one(addr);
+		__flush_tlb_one(addr);
 }
 
-static inline void invalidate_range(struct mm_struct *mm,
+static inline void flush_tlb_range(struct mm_struct *mm,
 	unsigned long start, unsigned long end)
 {
 	if (mm == current->mm)
-		__invalidate();
+		__flush_tlb();
 }
 
 #else
 
 /*
  * We aren't very clever about this yet -  SMP could certainly
- * avoid some global invalidates..
+ * avoid some global flushes..
  */
 
 #include <asm/smp.h>
 
-#define local_invalidate() \
-	__invalidate()
+#define local_flush_tlb() \
+	__flush_tlb()
 
 
 #undef CLEVER_SMP_INVALIDATE
 #ifdef CLEVER_SMP_INVALIDATE
 
 /*
- *	Smarter SMP invalidation macros. 
+ *	Smarter SMP flushing macros. 
  *		c/o Linus Torvalds.
  *
  *	These mean you can really definitely utterly forget about
  *	writing to user space from interrupts. (Its not allowed anyway).
  *
- *	Doesn't currently work as Linus makes invalidate calls before
+ *	Doesn't currently work as Linus makes flush tlb calls before
  *	stuff like current/current->mm are setup properly
  */
  
-static inline void invalidate_current_task(void)
+static inline void flush_tlb_current_task(void)
 {
 	if (current->mm->count == 1)	/* just one copy of this mm */
-		local_invalidate();	/* and that's us, so.. */
+		local_flush_tlb();	/* and that's us, so.. */
 	else
-		smp_invalidate();
+		smp_flush_tlb();
 }
 
-#define invalidate() invalidate_current_task()
+#define flush_tlb() flush_tlb_current_task()
 
-#define invalidate_all() smp_invalidate()
+#define flush_tlb_all() smp_flush_tlb()
 
-static inline void invalidate_mm(struct mm_struct * mm)
+static inline void flush_tlb_mm(struct mm_struct * mm)
 {
 	if (mm == current->mm && mm->count == 1)
-		local_invalidate();
+		local_flush_tlb();
 	else
-		smp_invalidate();
+		smp_flush_tlb();
 }
 
-static inline void invalidate_page(struct vm_area_struct * vma,
+static inline void flush_tlb_page(struct vm_area_struct * vma,
 	unsigned long va)
 {
 	if (vma->vm_mm == current->mm && current->mm->count == 1)
-		__invalidate_one(va);
+		__flush_tlb_one(va);
 	else
-		smp_invalidate();
+		smp_flush_tlb();
 }
 
-static inline void invalidate_range(struct mm_struct * mm,
+static inline void flush_tlb_range(struct mm_struct * mm,
 	unsigned long start, unsigned long end)
 {
-	invalidate_mm(mm);
+	flush_tlb_mm(mm);
 }
 
 
 #else
 
-#define invalidate() \
-	smp_invalidate()
+#define flush_tlb() \
+	smp_flush_tlb()
 
-#define invalidate_all() invalidate()
+#define flush_tlb_all() flush_tlb()
 
-static inline void invalidate_mm(struct mm_struct *mm)
+static inline void flush_tlb_mm(struct mm_struct *mm)
 {
-	invalidate();
+	flush_tlb();
 }
 
-static inline void invalidate_page(struct vm_area_struct *vma,
+static inline void flush_tlb_page(struct vm_area_struct *vma,
 	unsigned long addr)
 {
-	invalidate();
+	flush_tlb();
 }
 
-static inline void invalidate_range(struct mm_struct *mm,
+static inline void flush_tlb_range(struct mm_struct *mm,
 	unsigned long start, unsigned long end)
 {
-	invalidate();
+	flush_tlb();
 }
 #endif
 #endif
diff -u --recursive --new-file v1.3.82/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h
--- v1.3.82/linux/include/asm-i386/smp.h	Mon Mar 25 08:58:21 1996
+++ linux/include/asm-i386/smp.h	Wed Apr  3 10:59:32 1996
@@ -184,7 +184,7 @@
 extern volatile int cpu_number_map[NR_CPUS];
 extern volatile int cpu_logical_map[NR_CPUS];
 extern volatile unsigned long smp_invalidate_needed;
-extern void smp_invalidate(void);
+extern void smp_flush_tlb(void);
 extern volatile unsigned long kernel_flag, kernel_counter;
 extern volatile unsigned long cpu_callin_map[NR_CPUS];
 extern volatile unsigned char active_kernel_processor;
diff -u --recursive --new-file v1.3.82/linux/include/asm-i386/smp_lock.h linux/include/asm-i386/smp_lock.h
--- v1.3.82/linux/include/asm-i386/smp_lock.h	Fri Feb  9 16:59:04 1996
+++ linux/include/asm-i386/smp_lock.h	Wed Apr  3 10:59:32 1996
@@ -32,7 +32,7 @@
 			 */
 			if (test_bit(proc, (void *)&smp_invalidate_needed))
 				if (clear_bit(proc, (void *)&smp_invalidate_needed))
-					local_invalidate();
+					local_flush_tlb();
 		}
 		while(test_bit(0, (void *)&kernel_flag));
 	}
diff -u --recursive --new-file v1.3.82/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
--- v1.3.82/linux/include/asm-i386/system.h	Tue Apr  2 13:32:22 1996
+++ linux/include/asm-i386/system.h	Wed Apr  3 11:25:40 1996
@@ -199,17 +199,17 @@
 	switch (size) {
 		case 1:
 			__asm__("xchgb %b0,%1"
-				:"=q" (x), "=m" (*__xg(ptr))
+				:"=&q" (x), "=m" (*__xg(ptr))
 				:"0" (x), "m" (*__xg(ptr)));
 			break;
 		case 2:
 			__asm__("xchgw %w0,%1"
-				:"=r" (x), "=m" (*__xg(ptr))
+				:"=&r" (x), "=m" (*__xg(ptr))
 				:"0" (x), "m" (*__xg(ptr)));
 			break;
 		case 4:
 			__asm__("xchgl %0,%1"
-				:"=r" (x), "=m" (*__xg(ptr))
+				:"=&r" (x), "=m" (*__xg(ptr))
 				:"0" (x), "m" (*__xg(ptr)));
 			break;
 	}
diff -u --recursive --new-file v1.3.82/linux/include/linux/interrupt.h linux/include/linux/interrupt.h
--- v1.3.82/linux/include/linux/interrupt.h	Sat Mar 16 14:29:29 1996
+++ linux/include/linux/interrupt.h	Wed Apr  3 09:20:45 1996
@@ -29,6 +29,7 @@
 	TIMER_BH = 0,
 	CONSOLE_BH,
 	TQUEUE_BH,
+	DIGI_BH,
 	SERIAL_BH,
 	NET_BH,
 	IMMEDIATE_BH,
diff -u --recursive --new-file v1.3.82/linux/include/linux/timer.h linux/include/linux/timer.h
--- v1.3.82/linux/include/linux/timer.h	Fri Feb 23 09:39:35 1996
+++ linux/include/linux/timer.h	Wed Apr  3 09:20:45 1996
@@ -55,6 +55,8 @@
 #define HD_TIMER2	24
 #define GSCD_TIMER	25
 
+#define DIGI_TIMER	29
+
 struct timer_struct {
 	unsigned long expires;
 	void (*fn)(void);
diff -u --recursive --new-file v1.3.82/linux/include/linux/tty.h linux/include/linux/tty.h
--- v1.3.82/linux/include/linux/tty.h	Mon Mar 25 10:22:43 1996
+++ linux/include/linux/tty.h	Wed Apr  3 14:07:04 1996
@@ -284,6 +284,7 @@
 extern int lp_init(void);
 extern int pty_init(void);
 extern int tty_init(void);
+extern int pcxe_init(void);
 extern int vcs_init(void);
 extern int cy_init(void);
 extern int stl_init(void);
@@ -328,6 +329,7 @@
 /* pty.c */
 
 extern int  pty_open(struct tty_struct * tty, struct file * filp);
+extern int pcxe_open(struct tty_struct *tty, struct file *filp);
 
 /* console.c */
 
diff -u --recursive --new-file v1.3.82/linux/ipc/shm.c linux/ipc/shm.c
--- v1.3.82/linux/ipc/shm.c	Wed Mar 13 13:56:21 1996
+++ linux/ipc/shm.c	Wed Apr  3 10:59:32 1996
@@ -433,6 +433,7 @@
 	/* map page range */
 	shm_sgn = shmd->vm_pte +
 	  SWP_ENTRY(0, (shmd->vm_offset >> PAGE_SHIFT) << SHM_IDX_SHIFT);
+	flush_cache_range(shmd->vm_mm, shmd->vm_start, shmd->vm_end);
 	for (tmp = shmd->vm_start;
 	     tmp < shmd->vm_end;
 	     tmp += PAGE_SIZE, shm_sgn += SWP_ENTRY(0, 1 << SHM_IDX_SHIFT))
@@ -446,7 +447,7 @@
 			return -ENOMEM;
 		set_pte(page_table, __pte(shm_sgn));
 	}
-	invalidate_range(shmd->vm_mm, shmd->vm_start, shmd->vm_end);
+	flush_tlb_range(shmd->vm_mm, shmd->vm_start, shmd->vm_end);
 	return 0;
 }
 
@@ -760,12 +761,13 @@
 		}
 		if (pte_page(pte) != pte_page(page))
 			printk("shm_swap_out: page and pte mismatch\n");
+		flush_cache_page(shmd, tmp);
 		set_pte(page_table,
 		  __pte(shmd->vm_pte + SWP_ENTRY(0, idx << SHM_IDX_SHIFT)));
 		mem_map[MAP_NR(pte_page(pte))].count--;
 		if (shmd->vm_mm->rss > 0)
 			shmd->vm_mm->rss--;
-		invalidate_page(shmd, tmp);
+		flush_tlb_page(shmd, tmp);
 	    /* continue looping through circular list */
 	    } while (0);
 	    if ((shmd = shmd->vm_next_share) == shp->attaches)
diff -u --recursive --new-file v1.3.82/linux/kernel/sched.c linux/kernel/sched.c
--- v1.3.82/linux/kernel/sched.c	Tue Apr  2 13:32:23 1996
+++ linux/kernel/sched.c	Wed Apr  3 10:59:33 1996
@@ -125,7 +125,7 @@
 		{
 			if(clear_bit(cpu,&smp_invalidate_needed))
 			{
-				local_invalidate();
+				local_flush_tlb();
 				set_bit(cpu,&cpu_callin_map[0]);
 			}
 		}
diff -u --recursive --new-file v1.3.82/linux/mm/filemap.c linux/mm/filemap.c
--- v1.3.82/linux/mm/filemap.c	Tue Apr  2 13:32:23 1996
+++ linux/mm/filemap.c	Wed Apr  3 10:59:33 1996
@@ -579,9 +579,9 @@
 	unsigned long page = pte_page(*page_table);
 	unsigned long entry = SWP_ENTRY(SHM_SWP_TYPE, MAP_NR(page));
 
+	flush_cache_page(vma, (offset + vma->vm_start - vma->vm_offset));
 	set_pte(page_table, __pte(entry));
-	/* Yuck, perhaps a slightly modified swapout parameter set? */
-	invalidate_page(vma, (offset + vma->vm_start - vma->vm_offset));
+	flush_tlb_page(vma, (offset + vma->vm_start - vma->vm_offset));
 	error = filemap_write_page(vma, offset, page);
 	if (pte_val(*page_table) == entry)
 		pte_clear(page_table);
@@ -618,15 +618,17 @@
 			return 0;
 		if (!pte_dirty(pte))
 			return 0;
+		flush_cache_page(vma, address);
 		set_pte(ptep, pte_mkclean(pte));
-		invalidate_page(vma, address);
+		flush_tlb_page(vma, address);
 		page = pte_page(pte);
 		mem_map[MAP_NR(page)].count++;
 	} else {
 		if (pte_none(pte))
 			return 0;
+		flush_cache_page(vma, address);
 		pte_clear(ptep);
-		invalidate_page(vma, address);
+		flush_tlb_page(vma, address);
 		if (!pte_present(pte)) {
 			swap_free(pte_val(pte));
 			return 0;
@@ -710,12 +712,13 @@
 	int error = 0;
 
 	dir = pgd_offset(current->mm, address);
+	flush_cache_range(vma->vm_mm, end - size, end);
 	while (address < end) {
 		error |= filemap_sync_pmd_range(dir, address, end - address, vma, flags);
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	}
-	invalidate_range(vma->vm_mm, end - size, end);
+	flush_tlb_range(vma->vm_mm, end - size, end);
 	return error;
 }
 
diff -u --recursive --new-file v1.3.82/linux/mm/memory.c linux/mm/memory.c
--- v1.3.82/linux/mm/memory.c	Fri Mar 22 14:05:44 1996
+++ linux/mm/memory.c	Wed Apr  3 14:12:34 1996
@@ -135,9 +135,10 @@
 		printk("%s trying to clear kernel page-directory: not good\n", tsk->comm);
 		return;
 	}
+	flush_cache_mm(tsk->mm);
 	for (i = 0 ; i < USER_PTRS_PER_PGD ; i++)
 		free_one_pgd(page_dir + i);
-	invalidate_mm(tsk->mm);
+	flush_tlb_mm(tsk->mm);
 }
 
 /*
@@ -156,7 +157,8 @@
 		printk("%s trying to free kernel page-directory: not good\n", tsk->comm);
 		return;
 	}
-	invalidate_mm(tsk->mm);
+	flush_cache_mm(tsk->mm);
+	flush_tlb_mm(tsk->mm);
 	SET_PAGE_DIR(tsk, swapper_pg_dir);
 	tsk->mm->pgd = swapper_pg_dir;	/* or else... */
 	for (i = 0 ; i < USER_PTRS_PER_PGD ; i++)
@@ -171,9 +173,10 @@
 	if (!(new_pg = pgd_alloc()))
 		return -ENOMEM;
 	page_dir = pgd_offset(&init_mm, 0);
+	flush_cache_mm(tsk->mm);
 	memcpy(new_pg + USER_PTRS_PER_PGD, page_dir + USER_PTRS_PER_PGD,
 	       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof (pgd_t));
-	invalidate_mm(tsk->mm);
+	flush_tlb_mm(tsk->mm);
 	SET_PAGE_DIR(tsk, new_pg);
 	tsk->mm->pgd = new_pg;
 	return 0;
@@ -285,6 +288,8 @@
 	cow = (vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE;
 	src_pgd = pgd_offset(src, address);
 	dst_pgd = pgd_offset(dst, address);
+	flush_cache_range(src, vma->vm_start, vma->vm_end);
+	flush_cache_range(dst, vma->vm_start, vma->vm_end);
 	while (address < end) {
 		error = copy_pmd_range(dst_pgd++, src_pgd++, address, end - address, cow);
 		if (error)
@@ -292,8 +297,8 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 	}
 	/* Note that the src ptes get c-o-w treatment, so they change too. */
-	invalidate_range(src, vma->vm_start, vma->vm_end);
-	invalidate_range(dst, vma->vm_start, vma->vm_end);
+	flush_tlb_range(src, vma->vm_start, vma->vm_end);
+	flush_tlb_range(dst, vma->vm_start, vma->vm_end);
 	return error;
 }
 
@@ -373,12 +378,13 @@
 	unsigned long end = address + size;
 
 	dir = pgd_offset(mm, address);
+	flush_cache_range(mm, end - size, end);
 	while (address < end) {
 		zap_pmd_range(dir, address, end - address);
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	}
-	invalidate_range(mm, end - size, end);
+	flush_tlb_range(mm, end - size, end);
 	return 0;
 }
 
@@ -428,6 +434,7 @@
 
 	zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE, prot));
 	dir = pgd_offset(current->mm, address);
+	flush_cache_range(current->mm, beg, end);
 	while (address < end) {
 		pmd_t *pmd = pmd_alloc(dir, address);
 		error = -ENOMEM;
@@ -439,7 +446,7 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	}
-	invalidate_range(current->mm, beg, end);
+	flush_tlb_range(current->mm, beg, end);
 	return error;
 }
 
@@ -499,6 +506,7 @@
 
 	offset -= from;
 	dir = pgd_offset(current->mm, from);
+	flush_cache_range(current->mm, beg, from);
 	while (from < end) {
 		pmd_t *pmd = pmd_alloc(dir, from);
 		error = -ENOMEM;
@@ -510,7 +518,7 @@
 		from = (from + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	}
-	invalidate_range(current->mm, beg, from);
+	flush_tlb_range(current->mm, beg, from);
 	return error;
 }
 
@@ -619,19 +627,24 @@
 			if (mem_map[MAP_NR(old_page)].reserved)
 				++vma->vm_mm->rss;
 			copy_page(old_page,new_page);
+			flush_page_to_ram(old_page);
+			flush_page_to_ram(new_page);
+			flush_cache_page(vma, address);
 			set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
 			free_page(old_page);
-			invalidate_page(vma, address);
+			flush_tlb_page(vma, address);
 			return;
 		}
+		flush_cache_page(vma, address);
 		set_pte(page_table, BAD_PAGE);
+		flush_tlb_page(vma, address);
 		free_page(old_page);
 		oom(tsk);
-		invalidate_page(vma, address);
 		return;
 	}
+	flush_cache_page(vma, address);
 	set_pte(page_table, pte_mkdirty(pte_mkwrite(pte)));
-	invalidate_page(vma, address);
+	flush_tlb_page(vma, address);
 	if (new_page)
 		free_page(new_page);
 	return;
@@ -901,6 +914,7 @@
 	}
 	address &= PAGE_MASK;
 	if (!vma->vm_ops || !vma->vm_ops->nopage) {
+		flush_cache_page(vma, address);
 		get_empty_page(tsk, vma, page_table, write_access);
 		return;
 	}
@@ -914,7 +928,9 @@
 	page = vma->vm_ops->nopage(vma, address, write_access && !(vma->vm_flags & VM_SHARED));
 	if (!page) {
 		send_sig(SIGBUS, current, 1);
+		flush_cache_page(vma, address);
 		put_page(page_table, BAD_PAGE);
+		flush_tlb_page(vma, address);
 		return;
 	}
 	/*
@@ -932,7 +948,9 @@
 		entry = pte_mkwrite(pte_mkdirty(entry));
 	} else if (mem_map[MAP_NR(page)].count > 1 && !(vma->vm_flags & VM_SHARED))
 		entry = pte_wrprotect(entry);
+	flush_cache_page(vma, address);
 	put_page(page_table, entry);
+	flush_tlb_page(vma, address);
 }
 
 /*
diff -u --recursive --new-file v1.3.82/linux/mm/mprotect.c linux/mm/mprotect.c
--- v1.3.82/linux/mm/mprotect.c	Mon Dec 11 15:41:12 1995
+++ linux/mm/mprotect.c	Wed Apr  3 10:59:33 1996
@@ -75,12 +75,13 @@
 	unsigned long beg = start;
 
 	dir = pgd_offset(current->mm, start);
+	flush_cache_range(current->mm, beg, end);
 	while (start < end) {
 		change_pmd_range(dir, start, end - start, newprot);
 		start = (start + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	}
-	invalidate_range(current->mm, beg, end);
+	flush_tlb_range(current->mm, beg, end);
 	return;
 }
 
diff -u --recursive --new-file v1.3.82/linux/mm/mremap.c linux/mm/mremap.c
--- v1.3.82/linux/mm/mremap.c	Sat Mar 23 19:25:55 1996
+++ linux/mm/mremap.c	Wed Apr  3 10:59:33 1996
@@ -93,7 +93,8 @@
 {
 	unsigned long offset = len;
 
-	invalidate_range(mm, old_addr, old_addr + len);
+	flush_cache_range(mm, old_addr, old_addr + len);
+	flush_tlb_range(mm, old_addr, old_addr + len);
 
 	/*
 	 * This is not the clever way to do this, but we're taking the
@@ -115,9 +116,10 @@
 	 * the old page tables)
 	 */
 oops_we_failed:
+	flush_cache_range(mm, new_addr, new_addr + len);
 	while ((offset += PAGE_SIZE) < len)
 		move_one_page(mm, new_addr + offset, old_addr + offset);
-	invalidate_range(mm, new_addr, new_addr + len);
+	flush_tlb_range(mm, new_addr, new_addr + len);
 	zap_page_range(mm, new_addr, new_addr + len);
 	return -1;
 }
diff -u --recursive --new-file v1.3.82/linux/mm/vmalloc.c linux/mm/vmalloc.c
--- v1.3.82/linux/mm/vmalloc.c	Mon Dec 11 15:41:12 1995
+++ linux/mm/vmalloc.c	Wed Apr  3 10:59:33 1996
@@ -100,12 +100,13 @@
 	unsigned long end = address + size;
 
 	dir = pgd_offset(&init_mm, address);
+	flush_cache_all();
 	while (address < end) {
 		free_area_pmd(dir, address, end - address);
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	}
-	invalidate_all();
+	flush_tlb_all();
 }
 
 static inline int alloc_area_pte(pte_t * pte, unsigned long address, unsigned long size)
@@ -156,6 +157,7 @@
 	unsigned long end = address + size;
 
 	dir = pgd_offset(&init_mm, address);
+	flush_cache_all();
 	while (address < end) {
 		pmd_t *pmd = pmd_alloc_kernel(dir, address);
 		if (!pmd)
@@ -166,7 +168,7 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	}
-	invalidate_all();
+	flush_tlb_all();
 	return 0;
 }
 
@@ -217,6 +219,7 @@
 
 	offset -= address;
 	dir = pgd_offset(&init_mm, address);
+	flush_cache_all();
 	while (address < end) {
 		pmd_t *pmd = pmd_alloc_kernel(dir, address);
 		if (!pmd)
@@ -227,7 +230,7 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	}
-	invalidate_all();
+	flush_tlb_all();
 	return 0;
 }
 
diff -u --recursive --new-file v1.3.82/linux/mm/vmscan.c linux/mm/vmscan.c
--- v1.3.82/linux/mm/vmscan.c	Wed Mar 13 15:15:22 1996
+++ linux/mm/vmscan.c	Wed Apr  3 10:59:33 1996
@@ -110,8 +110,9 @@
 			if (!(entry = get_swap_page()))
 				return 0;
 			vma->vm_mm->rss--;
+			flush_cache_page(vma, address);
 			set_pte(page_table, __pte(entry));
-			invalidate_page(vma, address);
+			flush_tlb_page(vma, address);
 			tsk->nswap++;
 			rw_swap_page(WRITE, entry, (char *) page, wait);
 		}
@@ -125,14 +126,16 @@
 			return 0;
 		}
 		vma->vm_mm->rss--;
+		flush_cache_page(vma, address);
 		set_pte(page_table, __pte(entry));
-		invalidate_page(vma, address);
+		flush_tlb_page(vma, address);
 		free_page(page);
 		return 1;
 	} 
 	vma->vm_mm->rss--;
+	flush_cache_page(vma, address);
 	pte_clear(page_table);
-	invalidate_page(vma, address);
+	flush_tlb_page(vma, address);
 	entry = page_unuse(page);
 	free_page(page);
 	return entry;
diff -u --recursive --new-file v1.3.82/linux/net/core/firewall.c linux/net/core/firewall.c
--- v1.3.82/linux/net/core/firewall.c	Mon Nov  6 12:59:01 1995
+++ linux/net/core/firewall.c	Wed Apr  3 11:29:39 1996
@@ -41,13 +41,18 @@
 		p=&((*p)->next);
 	}
 
-	fw->next=*p;
+	
 	/*
-	 *	We need to set p atomically in case someone runs down the list
-	 *	at the wrong moment. This saves locking it 
+	 * We need to use a memory barrier to make sure that this
+	 * works correctly even in SMP with weakly ordered writes.
+	 *
+	 * This is atomic wrt interrupts (and generally walking the
+	 * chain), but not wrt itself (so you can't call this from
+	 * an interrupt. Not that you'd want to).
 	 */
-	 
-	xchg(p,fw);
+	fw->next=*p;
+	mb();
+	*p = fw;
 
 	/*
 	 *	And release the sleep lock
@@ -83,7 +88,7 @@
 		if(*nl==fw)
 		{
 			struct firewall_ops *f=fw->next;
-			xchg(nl,f);
+			*nl = f;
 			firewall_lock=0;
 			return 0;
 		}			
diff -u --recursive --new-file v1.3.82/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v1.3.82/linux/net/ipv4/tcp_input.c	Tue Apr  2 13:32:24 1996
+++ linux/net/ipv4/tcp_input.c	Wed Apr  3 11:56:50 1996
@@ -1384,35 +1384,6 @@
 	 
 	if (!skb->acked) 
 	{
-	
-	/*
-	 *	This is important.  If we don't have much room left,
-	 *	we need to throw out a few packets so we have a good
-	 *	window.  Note that mtu is used, not mss, because mss is really
-	 *	for the send side.  He could be sending us stuff as large as mtu.
-	 */
-		 
-		while (sock_rspace(sk) < sk->mtu) 
-		{
-			struct sk_buff * skb1 = skb_peek(&sk->receive_queue);
-			if (skb1 == NULL) 
-			{
-				printk("INET: tcp.c:tcp_data memory leak detected.\n");
-				break;
-			}
-
-			/*
-			 *	Don't throw out something that has been acked. 
-			 */
-		 
-			if (skb1->acked) 
-			{
-				break;
-			}
-		
-			skb_unlink(skb1);
-			kfree_skb(skb1, FREE_READ);
-		}
 		tcp_send_ack(sk->sent_seq, sk->acked_seq, sk, th, saddr);
 		sk->ack_backlog++;
 		tcp_reset_xmit_timer(sk, TIME_WRITE, min(sk->ato, HZ/2));
@@ -1500,6 +1471,66 @@
 	}
 }
 
+/*
+ * Throw out all unnecessary packets: we've gone over the
+ * receive queue limit. This shouldn't happen in a normal
+ * TCP connection, but we might have gotten duplicates etc.
+ */
+static inline void tcp_forget_unacked(struct sk_buff_head * list)
+{
+	for (;;) {
+		struct sk_buff * skb = list->prev;
+
+		/* gone through it all? */
+		if (skb == (struct sk_buff *) list)
+			break;
+		if (skb->acked)
+			break;
+		__skb_unlink(skb, list);
+	}
+}
+
+/*
+ * This should be a bit smarter and remove partially
+ * overlapping stuff too, but this should be good
+ * enough for any even remotely normal case (and the
+ * worst that can happen is that we have a few
+ * unnecessary packets in the receive queue).
+ */
+static inline void tcp_remove_dups(struct sk_buff_head * list)
+{
+	struct sk_buff * skb = list->next;
+
+	for (;;) {
+		struct sk_buff * next;
+
+		if (skb == (struct sk_buff *) list)
+			break;
+		next = skb->next;
+		if (next->seq == skb->seq) {
+			if (before(next->end_seq, skb->end_seq)) {
+				__skb_unlink(next, list);
+				continue;
+			}
+			__skb_unlink(skb, list);
+		}
+		skb = next;
+	}
+}
+
+static void prune_queue(struct sk_buff_head * list)
+{
+	/*
+	 * Throw out things we haven't acked.
+	 */
+	tcp_forget_unacked(list);
+
+	/*
+	 * Throw out duplicates
+	 */
+	tcp_remove_dups(list);
+}
+
 
 /*
  *	A TCP packet has arrived.
@@ -1846,19 +1877,6 @@
 	 *	now drop it (we must process the ack first to avoid
 	 *	deadlock cases).
 	 */
-#if 0
-	/*
-	 *	Is this test really a good idea? We should
-	 *	throw away packets that aren't in order, not
-	 *	new packets.
-	 */
-	if (sk->rmem_alloc  >= sk->rcvbuf) 
-	{
-		kfree_skb(skb, FREE_READ);
-		return(0);
-	}
-#endif
-
 
 	/*
 	 *	Process urgent data
@@ -1872,6 +1890,13 @@
 	
 	if(tcp_data(skb,sk, saddr, len))
 		kfree_skb(skb, FREE_READ);
+
+	/*
+	 *	If our receive queue has grown past its limits,
+	 *	try to prune away duplicates etc..
+	 */
+	if (sk->rmem_alloc > sk->rcvbuf)
+		prune_queue(&sk->receive_queue);
 
 	/*
 	 *	And done
