## Automatically generated incremental diff
## From:   linux-2.2.17-pre1
## To:     linux-2.2.17-pre2
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.2.17-pre1/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.2.17-pre1/Documentation/Configure.help	Wed Jun  7 14:26:42 2000
+++ linux/Documentation/Configure.help	Mon Dec  3 22:05:27 2001
@@ -5755,6 +5755,34 @@
 
   If unsure, say N here.
 
+Cyclades-PC300 support
+CONFIG_PC300
+  This is a driver for the Cyclades-PC300 synchronous communication
+  boards. These boards provide synchronous serial interfaces to your
+  Linux box. All protocols supported by the HDLC generic driver
+  (currently synchronous PPP, Cisco HDLC and Frame Relay) are available
+  by default. If you wish to support other protocols, please select one
+  of the available options below this one.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called pc300.o.
+
+  If unsure, say N here.
+
+Cyclades-PC300 X.25 Support
+CONFIG_PC300_X25
+  Say Y to this option if you intend to use the Cyclades-PC300 to
+  provide X.25 interfaces to your Linux box.
+
+  IMPORTANT: Additional X.25 support must be enabled in the kernel
+  for this support to be functional (say Y to "CCITT X.25 Packet Layer"
+  and "LAPB Data Link Driver", in the "Networking Options"
+  configuration section).
+
+  If unsure, say N here.
+
 Ethernet (10 or 100Mbit)
 CONFIG_NET_ETHERNET
   Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
diff -urN linux-2.2.17-pre1/MAINTAINERS linux/MAINTAINERS
--- linux-2.2.17-pre1/MAINTAINERS	Mon Dec  3 22:05:22 2001
+++ linux/MAINTAINERS	Mon Dec  3 22:05:27 2001
@@ -220,6 +220,12 @@
 W:	http://www.cyclades.com/
 S:	Supported
 
+CYCLADES PC300 DRIVER
+P:	Ivan Passos
+M:	ivan@cyclades.com
+W:	http://www.cyclades.com/
+S:	Supported
+
 DAMA SLAVE for AX.25
 P:	Joerg Reuter
 M:	jreuter@poboxes.com
@@ -261,6 +267,14 @@
 L:	linux-net@vger.rutgers.edu
 W:	http://www.dgii.com/linux/
 S:	Maintained
+
+DISK GEOMETRY AND PARTITION HANDLING
+P:     Andries Brouwer
+M:     aeb@veritas.com
+W:     http://www.win.tue.nl/~aeb/linux/Large-Disk.html
+W:     http://www.win.tue.nl/~aeb/linux/zip/zip-1.html
+W:     http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
+S:     Maintained
 
 DISKQUOTA:
 P:	Marco van Wieringen
diff -urN linux-2.2.17-pre1/Makefile linux/Makefile
--- linux-2.2.17-pre1/Makefile	Mon Dec  3 22:05:22 2001
+++ linux/Makefile	Mon Dec  3 22:05:27 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 17
-EXTRAVERSION = -pre1
+EXTRAVERSION = pre2
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
diff -urN linux-2.2.17-pre1/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- linux-2.2.17-pre1/arch/i386/kernel/setup.c	Wed Jun  7 14:26:42 2000
+++ linux/arch/i386/kernel/setup.c	Mon Dec  3 22:05:27 2001
@@ -27,6 +27,8 @@
  *	Added proper Cascades CPU and L2 cache detection for Cascades
  *	and 8-way type cache happy bunch from Intel:^)
  *	Dragan Stancevic <visitor@valinux.com>, May 2000
+ *
+ *	Transmeta CPU detection.  H. Peter Anvin <hpa@zytor.com>, May 2000
  */
 
 /*
@@ -436,8 +438,10 @@
 {
 	unsigned int n, dummy, *v, ecx, edx;
 
-	/* Actually we must have cpuid or we could never have
-	 * figured out that this was AMD from the vendor info :-).
+	/* 
+	 * Actually we must have cpuid or we could never have
+	 * figured out that this was AMD/Cyrix/Transmeta
+	 * from the vendor info :-).
 	 */
 
 	cpuid(0x80000000, &n, &dummy, &dummy, &dummy);
@@ -450,8 +454,9 @@
 	cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
 	c->x86_model_id[48] = 0;
 	
-	if(c->x86_vendor == X86_VENDOR_AMD)
+	switch(c->x86_vendor)
 	{
+	case X86_VENDOR_AMD:
 		/*  Set MTRR capability flag if appropriate  */
 		if(boot_cpu_data.x86 == 5) {
 			if((boot_cpu_data.x86_model == 9) ||
@@ -459,7 +464,10 @@
 			    (boot_cpu_data.x86_mask >= 8)))
 				c->x86_capability |= X86_FEATURE_MTRR;
 		}
+		/* Fall through */
 
+	case X86_VENDOR_TRANSMETA:
+		/* Cache information */
 		if (n >= 0x80000005){
 			cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
 			printk("CPU: L1 I Cache: %dK  L1 D Cache: %dK\n",
@@ -471,6 +479,10 @@
 			printk("CPU: L2 Cache: %dK\n", ecx>>16);
 			c->x86_cache_size = ecx>>16;
 		}
+		break;
+
+	default:		/* Cyrix */
+		break;
 	}
 	return 1;
 }
@@ -735,6 +747,70 @@
 	return;
 }
 
+__initfunc(static void transmeta_model(struct cpuinfo_x86 *c))
+{
+	unsigned int cap_mask, uk, max, dummy, n, ecx, edx;
+	unsigned int cms_rev1, cms_rev2;
+	unsigned int cpu_rev, cpu_freq, cpu_flags;
+	char cpu_info[65];
+
+	get_model_name(c);	/* Same as AMD/Cyrix */
+
+	/* Print CMS and CPU revision */
+	cpuid(0x80860000, &max, &dummy, &dummy, &dummy);
+	if ( max >= 0x80860001 ) {
+		cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags); 
+		printk("CPU: Processor revision %u.%u.%u.%u, %u MHz%s%s\n",
+		       (cpu_rev >> 24) & 0xff,
+		       (cpu_rev >> 16) & 0xff,
+		       (cpu_rev >> 8) & 0xff,
+		       cpu_rev & 0xff,
+		       cpu_freq,
+		       (cpu_flags & 1) ? " [recovery]" : "",
+		       (cpu_flags & 2) ? " [longrun]" : "");
+	}
+	if ( max >= 0x80860002 ) {
+		cpuid(0x80860002, &dummy, &cms_rev1, &cms_rev2, &dummy);
+		printk("CPU: Code Morphing Software revision %u.%u.%u-%u-%u\n",
+		       (cms_rev1 >> 24) & 0xff,
+		       (cms_rev1 >> 16) & 0xff,
+		       (cms_rev1 >> 8) & 0xff,
+		       cms_rev1 & 0xff,
+		       cms_rev2);
+	}
+	if ( max >= 0x80860006 ) {
+		cpuid(0x80860003,
+		      (void *)&cpu_info[0],
+		      (void *)&cpu_info[4],
+		      (void *)&cpu_info[8],
+		      (void *)&cpu_info[12]);
+		cpuid(0x80860004,
+		      (void *)&cpu_info[16],
+		      (void *)&cpu_info[20],
+		      (void *)&cpu_info[24],
+		      (void *)&cpu_info[28]);
+		cpuid(0x80860005,
+		      (void *)&cpu_info[32],
+		      (void *)&cpu_info[36],
+		      (void *)&cpu_info[40],
+		      (void *)&cpu_info[44]);
+		cpuid(0x80860006,
+		      (void *)&cpu_info[48],
+		      (void *)&cpu_info[52],
+		      (void *)&cpu_info[56],
+		      (void *)&cpu_info[60]);
+		cpu_info[64] = '\0';
+		printk("CPU: %s\n", cpu_info);
+	}
+
+	/* Unhide possibly hidden flags */
+	rdmsr(0x80860004, cap_mask, uk);
+	wrmsr(0x80860004, ~0, uk);
+	cpuid(0x00000001, &dummy, &dummy, &dummy, &c->x86_capability);
+	wrmsr(0x80860004, cap_mask, uk);
+}
+
+
 __initfunc(void get_cpu_vendor(struct cpuinfo_x86 *c))
 {
 	char *v = c->x86_vendor_id;
@@ -751,6 +827,10 @@
 		c->x86_vendor = X86_VENDOR_CENTAUR;
 	else if (!strcmp(v, "NexGenDriven"))
 		c->x86_vendor = X86_VENDOR_NEXGEN;
+	else if (!strcmp(v, "RiseRiseRise"))
+		c->x86_vendor = X86_VENDOR_RISE;
+	else if (!strcmp(v, "GenuineTMx86"))
+		c->x86_vendor = X86_VENDOR_TRANSMETA;
 	else
 		c->x86_vendor = X86_VENDOR_UNKNOWN;
 }
@@ -815,6 +895,18 @@
 	    c->cpuid_level < 0)
 		return;
 
+	/* It should be possible for the user to override this. */
+	if(c->cpuid_level > 0 && 
+	   (c->x86_vendor == X86_VENDOR_INTEL || c->x86_vendor == X86_VENDOR_TRANSMETA) &&
+	   c->x86_capability&(1<<18)) {
+		/* Disable processor serial number */
+		unsigned long lo,hi;
+		rdmsr(0x119,lo,hi);
+		lo |= 0x200000;
+		wrmsr(0x119,lo,hi);
+		printk(KERN_INFO "CPU serial number disabled.\n");
+	}
+
 	if (c->x86_vendor == X86_VENDOR_CYRIX) {
 		cyrix_model(c);
 		return;
@@ -823,18 +915,9 @@
 	if (c->x86_vendor == X86_VENDOR_AMD && amd_model(c))
 		return;
 		
-	if (c->cpuid_level > 0 && c->x86_vendor == X86_VENDOR_INTEL)
-	{
-		if(c->x86_capability&(1<<18))
-		{
-			/* Disable processor serial number on Intel Pentium III 
-			   from code by Phil Karn */
-			unsigned long lo,hi;
-			rdmsr(0x119,lo,hi);
-			lo |= 0x200000;
-			wrmsr(0x119,lo,hi);
-			printk(KERN_INFO "Pentium-III serial number disabled.\n");
-		}
+	if (c->x86_vendor == X86_VENDOR_TRANSMETA) {
+		transmeta_model(c);
+		return;
 	}
 
 	if (c->cpuid_level > 1) {
@@ -928,7 +1011,7 @@
 	
 
 static char *cpu_vendor_names[] __initdata = {
-	"Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur" };
+	"Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur", "Rise", "Transmeta" };
 
 
 __initfunc(void print_cpu_info(struct cpuinfo_x86 *c))
@@ -940,7 +1023,7 @@
 	else if (c->cpuid_level >= 0)
 		vendor = c->x86_vendor_id;
 
-	if (vendor)
+	if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor)))
 		printk("%s ", vendor);
 
 	if (!c->x86_model_id[0])
@@ -1050,8 +1133,8 @@
 			break;
 
 		    default:
-			/* Unknown CPU manufacturer. Transmeta ? :-) */
-			break;
+		        /* Unknown CPU manufacturer or no specal action needed */
+		        break;
 		}
 
 		sep_bug = c->x86_vendor == X86_VENDOR_INTEL &&
diff -urN linux-2.2.17-pre1/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- linux-2.2.17-pre1/arch/i386/kernel/traps.c	Wed Jun  7 14:26:42 2000
+++ linux/arch/i386/kernel/traps.c	Mon Dec  3 22:05:27 2001
@@ -367,6 +367,9 @@
 
 	__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
 
+	/* Ensure the debug status register is visible to ptrace (or the process itself) */
+	tsk->tss.debugreg[6] = condition;
+
 	/* Mask out spurious TF errors due to lazy TF clearing */
 	if (condition & DR_STEP) {
 		/*
diff -urN linux-2.2.17-pre1/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- linux-2.2.17-pre1/drivers/cdrom/cdrom.c	Mon Dec  3 22:05:22 2001
+++ linux/drivers/cdrom/cdrom.c	Mon Dec  3 22:05:27 2001
@@ -214,15 +214,19 @@
   that case switch block size and issue plain READ_10 again, then switch
   back.
 
-  3.09 Jun 10, 2000 - Jens Axboe <axboe@suse.de>
+  3.10 Jun 10, 2000 - Jens Axboe <axboe@suse.de>
   -- Fix volume control on CD's - old SCSI-II drives now use their own
   code, as doing MODE6 stuff in here is really not my intention.
   -- Use READ_DISC_INFO for more reliable end-of-disc.
+
+  3.11 Jun 12, 2000 - Jens Axboe <axboe@suse.de>
+  -- Fix bug in getting rpc phase 2 region info.
+  -- Reinstate "correct" CDROMPLAYTRKIND
  
 -------------------------------------------------------------------------*/
 
-#define REVISION "Revision: 3.10"
-#define VERSION "Id: cdrom.c 3.10 2000/06/10"
+#define REVISION "Revision: 3.11"
+#define VERSION "Id: cdrom.c 3.11 2000/06/12"
 
 /* I use an error-log mask to give fine grain control over the type of
    messages dumped to the system logs.  The available masks include: */
@@ -1101,8 +1105,8 @@
 	case DVD_LU_SEND_RPC_STATE:
 		cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
 		setup_report_key(&cgc, 0, 8);
+		memset(&rpc_state, 0, sizeof(rpc_state_t));
 
-		init_cdrom_command(&cgc, &rpc_state, 0);
 		if ((ret = cdo->generic_packet(cdi, &cgc)))
 			return ret;
 
@@ -1113,7 +1117,7 @@
 		ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme;
 		break;
 
-		/* Set region settings */
+	/* Set region settings */
 	case DVD_HOST_SEND_RPC_STATE:
 		cdinfo(CD_DVD, "entering DVD_HOST_SEND_RPC_STATE\n");
 		setup_send_key(&cgc, 0, 6);
@@ -1964,36 +1968,15 @@
 		}
 	case CDROMPLAYTRKIND: {
 		struct cdrom_ti ti;
-		struct cdrom_tocentry entry;
-		struct cdrom_tochdr tochdr;
 
 		cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n");
 		IOCTL_IN(arg, struct cdrom_ti, ti);
-		entry.cdte_format = CDROM_MSF;
-
-		/* get toc entry for start and end track */
-		if (cdo->audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr))
-			return -EINVAL;
-		if ((entry.cdte_track = ti.cdti_trk0) > tochdr.cdth_trk1)
-			return -EINVAL;
-		if (cdo->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry))
-			return -EINVAL;
-
-		cgc.cmd[3] = entry.cdte_addr.msf.minute;
-		cgc.cmd[4] = entry.cdte_addr.msf.second;
-		cgc.cmd[5] = entry.cdte_addr.msf.frame;
-
-		entry.cdte_track = ti.cdti_trk1 + 1;
-		if (entry.cdte_track > tochdr.cdth_trk1)
-			entry.cdte_track = CDROM_LEADOUT;
-
-		if (cdo->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry))
-			return -EINVAL;
 
-		cgc.cmd[6] = entry.cdte_addr.msf.minute;
-		cgc.cmd[7] = entry.cdte_addr.msf.second;
-		cgc.cmd[8] = entry.cdte_addr.msf.frame;
-		cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
+		cgc.cmd[0] = GPCMD_PLAY_AUDIO_TI;
+		cgc.cmd[4] = ti.cdti_trk0;
+		cgc.cmd[5] = ti.cdti_ind0;
+		cgc.cmd[7] = ti.cdti_trk1;
+		cgc.cmd[8] = ti.cdti_ind1;
 		return cdo->generic_packet(cdi, &cgc);
 		}
 	case CDROMPLAYMSF: {
diff -urN linux-2.2.17-pre1/drivers/char/sx.c linux/drivers/char/sx.c
--- linux-2.2.17-pre1/drivers/char/sx.c	Wed May  3 17:16:39 2000
+++ linux/drivers/char/sx.c	Mon Dec  3 22:05:27 2001
@@ -896,6 +896,9 @@
 
 	func_enter2();
 
+	if (!port->gs.tty)
+		return 0;
+
 	/* What is this doing here? -- REW
 	   Ha! figured it out. It is to allow you to get DTR active again
 	   if you've dropped it with stty 0. Moved to set_baud, where it
@@ -1545,9 +1548,36 @@
    exit minicom.  I expect an "oops".  -- REW */
 static void sx_hungup (void *ptr)
 {
+/*
 	func_enter ();
 	MOD_DEC_USE_COUNT;
 	func_exit ();
+*/
+	/* 
+	 * Got this from the 2.4.0-test1 serie. The port was closed before
+	 * the lines were set in the proper condition. -- pvdl
+	 */
+	struct sx_port *port = ptr; 
+	func_enter ();
+
+	/* 
+	 *  Set the lines in the proper codition before closing the port.
+	 *  Got the from 2.4.0-test1 series. -- pvdl
+	 */
+	sx_setsignals (port, 0, 0);
+	sx_reconfigure_port(port);	
+	sx_send_command (port, HS_CLOSE, -1, HS_IDLE_CLOSED);
+
+	if (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED) {
+		if (sx_send_command (port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) != 1) {
+			printk (KERN_ERR 
+			        "sx: sent the force_close command, but card didn't react\n");
+		} else
+			sx_dprintk (SX_DEBUG_CLOSE, "sent the force_close command.\n");
+	}
+
+	MOD_DEC_USE_COUNT;
+	func_exit ();
 }
 
 
@@ -1558,6 +1588,9 @@
 	int to = 5 * HZ; 
 
 	func_enter ();
+
+	sx_setsignals (port, 0, 0);
+	sx_reconfigure_port(port);	
 	sx_send_command (port, HS_CLOSE, 0, 0);
 
 	while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED)) {
@@ -1920,7 +1953,10 @@
 	func_enter();
 
 	/* This is preceded by downloading the download code. */
-
+	/* 
+	 * The board should be set to initialized to make sure 
+	 * we can boot the other cards. --pvdl
+	 */ 
 	board->flags |= SX_BOARD_INITIALIZED;
 
 	if (read_sx_byte (board, 0))
diff -urN linux-2.2.17-pre1/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c
--- linux-2.2.17-pre1/drivers/misc/parport_share.c	Tue Jan  4 10:12:17 2000
+++ linux/drivers/misc/parport_share.c	Mon Dec  3 22:05:27 2001
@@ -125,7 +125,18 @@
 	 * This function must not run from an irq handler so we don' t need
 	 * to clear irq on the local CPU. -arca
 	 */
+
 	spin_lock(&parportlist_lock);
+
+	/* We are locked against anyone else performing alterations, but
+	 * because of parport_enumerate people can still _read_ the list
+	 * while we are changing it, so be careful..
+	 *
+	 * It's okay to have portlist_tail a little bit out of sync
+	 * since it's only used for changing the list, not for reading
+	 * from it.
+	 */
+
 	if (portlist_tail)
 		portlist_tail->next = tmp;
 	portlist_tail = tmp;
@@ -144,6 +155,10 @@
 	struct parport *p;
 
 	spin_lock(&parportlist_lock);
+
+	/* We are protected from other people changing the list, but
+	 * they can still see it (using parport_enumerate).  So be
+	 * careful about the order of writes.. */
 	if (portlist == port) {
 		if ((portlist = port->next) == NULL)
 			portlist_tail = NULL;
@@ -212,17 +227,25 @@
 		}
 	}
 
+	/* We up our own module reference count, and that of the port
+           on which a device is to be registered, to ensure that
+           neither of us gets unloaded while we sleep in (e.g.)
+           kmalloc.  To be absolutely safe, we have to require that
+           our caller doesn't sleep in between parport_enumerate and
+           parport_register_device.. */
+	inc_parport_count ();
+	port->ops->inc_use_count ();
+
 	tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL);
 	if (tmp == NULL) {
 		printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name);
-		return NULL;
+		goto out;
 	}
 
 	tmp->state = kmalloc(sizeof(struct parport_state), GFP_KERNEL);
 	if (tmp->state == NULL) {
 		printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name);
-		kfree(tmp);
-		return NULL;
+		goto out_free_pardevice;
 	}
 
 	/* We may need to claw back the port hardware. */
@@ -231,9 +254,7 @@
 			printk(KERN_WARNING
 			       "%s: unable to get hardware to register %s.\n",
 			       port->name, name);
-			kfree (tmp->state);
-			kfree (tmp);
-			return NULL;
+			goto out_free_all;
 		}
 		port->flags &= ~PARPORT_FLAG_COMA;
 	}
@@ -259,17 +280,18 @@
 	if (flags & PARPORT_DEV_EXCL) {
 		if (port->devices) {
 			spin_unlock (&port->pardevice_lock);
-			kfree (tmp->state);
-			kfree (tmp);
 			printk (KERN_DEBUG
 				"%s: cannot grant exclusive access for "
 				"device %s\n", port->name, name);
-			return NULL;
+			goto out_free_all;
 		}
 		port->flags |= PARPORT_FLAG_EXCL;
 	}
 
 	tmp->next = port->devices;
+	wmb(); /* Make sure that tmp->next is written before it's
+                  added to the list; see comments marked 'no locking
+                  required' */
 	if (port->devices)
 		port->devices->prev = tmp;
 	port->devices = tmp;
@@ -283,11 +305,21 @@
 	tmp->waitnext = tmp->waitprev = NULL;
 
 	return tmp;
+
+ out_free_all:
+	kfree (tmp->state);
+ out_free_pardevice:
+	kfree (tmp);
+ out:
+	dec_parport_count ();
+	port->ops->dec_use_count ();
+	return NULL;
 }
 
 void parport_unregister_device(struct pardevice *dev)
 {
 	struct parport *port;
+	unsigned long flags;
 
 #ifdef PARPORT_PARANOID
 	if (dev == NULL) {
@@ -298,11 +330,14 @@
 
 	port = dev->port;
 
+	read_lock_irqsave (&port->cad_lock, flags);
 	if (port->cad == dev) {
+		read_unlock_irqrestore (&port->cad_lock, flags);
 		printk(KERN_DEBUG "%s: %s forgot to release port\n",
 		       port->name, dev->name);
 		parport_release (dev);
 	}
+	read_unlock_irqrestore (&port->cad_lock, flags);
 
 	spin_lock(&port->pardevice_lock);
 	if (dev->next)
@@ -336,14 +371,17 @@
 	struct parport *port = dev->port;
 	unsigned long flags;
 
+	read_lock_irqsave (&port->cad_lock, flags);
 	if (port->cad == dev) {
+		read_unlock_irqrestore (&port->cad_lock, flags);
 		printk(KERN_INFO "%s: %s already owner\n",
 			   dev->port->name,dev->name);
 		return 0;
 	}
+	read_unlock_irqrestore (&port->cad_lock, flags);
 
-try_again:
 	/* Preempt any current device */
+	write_lock_irqsave (&port->cad_lock, flags);
 	if ((oldcad = port->cad) != NULL) {
 		if (oldcad->preempt) {
 			if (oldcad->preempt(oldcad->private))
@@ -366,7 +404,7 @@
 		dev->waiting = 0;
 
 		/* Take ourselves out of the wait list again.  */
-		spin_lock_irqsave (&port->waitlist_lock, flags);
+		spin_lock_irq (&port->waitlist_lock);
 		if (dev->waitprev)
 			dev->waitprev->waitnext = dev->waitnext;
 		else
@@ -375,7 +413,7 @@
 			dev->waitnext->waitprev = dev->waitprev;
 		else
 			port->waittail = dev->waitprev;
-		spin_unlock_irqrestore (&port->waitlist_lock, flags);
+		spin_unlock_irq (&port->waitlist_lock);
 		dev->waitprev = dev->waitnext = NULL;
 	}
 
@@ -399,6 +437,7 @@
 
 	/* Restore control registers */
 	port->ops->restore_state(port, dev->state);
+	write_unlock_irqrestore (&port->cad_lock, flags);
 	dev->time = jiffies;
 	return 0;
 
@@ -406,13 +445,10 @@
 	/* If this is the first time we tried to claim the port, register an
 	   interest.  This is only allowed for devices sleeping in
 	   parport_claim_or_block(), or those with a wakeup function.  */
+
+	/* The cad_lock is still held for writing here */
 	if (dev->waiting & 2 || dev->wakeup) {
-		spin_lock_irqsave (&port->waitlist_lock, flags);
-		if (port->cad == NULL) {
-			/* The port got released in the meantime. */
-			spin_unlock_irqrestore (&port->waitlist_lock, flags);
-			goto try_again;
-		}
+		spin_lock (&port->waitlist_lock);
 		if (test_and_set_bit(0, &dev->waiting) == 0) {
 			/* First add ourselves to the end of the wait list. */
 			dev->waitnext = NULL;
@@ -423,8 +459,9 @@
 			} else
 				port->waithead = port->waittail = dev;
 		}
-		spin_unlock_irqrestore (&port->waitlist_lock, flags);
+		spin_unlock (&port->waitlist_lock);
 	}
+	write_unlock_irqrestore (&port->cad_lock, flags);
 	return -EAGAIN;
 }
 
@@ -474,12 +511,14 @@
 	unsigned long flags;
 
 	/* Make sure that dev is the current device */
+	write_lock_irqsave (&port->cad_lock, flags);
 	if (port->cad != dev) {
+		write_unlock_irqrestore (&port->cad_lock, flags);
 		printk(KERN_WARNING "%s: %s tried to release parport "
 		       "when not owner\n", port->name, dev->name);
 		return;
 	}
-	write_lock_irqsave(&port->cad_lock, flags);
+
 	port->cad = NULL;
 	write_unlock_irqrestore(&port->cad_lock, flags);
 
@@ -503,7 +542,7 @@
 			return;
 		} else if (pd->wakeup) {
 			pd->wakeup(pd->private);
-			if (dev->port->cad)
+			if (dev->port->cad) /* racy but no matter */
 				return;
 		} else {
 			printk(KERN_ERR "%s: don't know how to wake %s\n", port->name, pd->name);
@@ -511,7 +550,7 @@
 	}
 
 	/* Nobody was waiting, so walk the list to see if anyone is
-	   interested in being woken up.  */
+	   interested in being woken up. (Note: no locking required) */
 	for (pd = port->devices; (port->cad == NULL) && pd; pd = pd->next) {
 		if (pd->wakeup && pd != dev)
 			pd->wakeup(pd->private);
diff -urN linux-2.2.17-pre1/drivers/net/Config.in linux/drivers/net/Config.in
--- linux-2.2.17-pre1/drivers/net/Config.in	Wed Jun  7 14:26:43 2000
+++ linux/drivers/net/Config.in	Mon Dec  3 22:05:27 2001
@@ -319,6 +319,10 @@
 
     if [ "$CONFIG_PCI" != "n" ]; then
       dep_tristate '  SBE wanXL support' CONFIG_WANXL $CONFIG_HDLC
+      dep_tristate '  Cyclades-PC300 support' CONFIG_PC300 $CONFIG_HDLC
+      if [ "$CONFIG_PC300" != "n" ]; then
+        bool '    Cyclades-PC300 X.25 support (please read help)' CONFIG_PC300_X25
+      fi
     fi
   fi
 fi
diff -urN linux-2.2.17-pre1/drivers/net/Makefile linux/drivers/net/Makefile
--- linux-2.2.17-pre1/drivers/net/Makefile	Wed Jun  7 14:26:43 2000
+++ linux/drivers/net/Makefile	Mon Dec  3 22:05:27 2001
@@ -1003,6 +1003,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_PC300),y)
+L_OBJS += pc300.o
+else
+  ifeq ($(CONFIG_PC300),m)
+  M_OBJS += pc300.o
+  endif
+endif
+
 # If anything built-in uses syncppp, then build it into the kernel also.
 # If not, but a module uses it, build as a module.
 
diff -urN linux-2.2.17-pre1/drivers/net/hdlc.c linux/drivers/net/hdlc.c
--- linux-2.2.17-pre1/drivers/net/hdlc.c	Wed Jun  7 14:26:43 2000
+++ linux/drivers/net/hdlc.c	Mon Dec  3 22:05:27 2001
@@ -884,7 +884,12 @@
 		dev->do_ioctl = hdlc_ioctl;
 		hdlc->pppdev.sppp.pp_flags&=~PP_CISCO;
 		dev->type=ARPHRD_PPP;
-		sppp_open(dev);
+		result = sppp_open(dev);
+		if (result) {
+			sppp_detach(dev);
+			hdlc->close(hdlc);
+			return result;
+		}
 	}
 
 	return 0;
diff -urN linux-2.2.17-pre1/drivers/net/pc300.c linux/drivers/net/pc300.c
--- linux-2.2.17-pre1/drivers/net/pc300.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/pc300.c	Mon Dec  3 22:05:27 2001
@@ -0,0 +1,2815 @@
+#define	USE_PCI_CLOCK
+static char rcsid[] =
+"$Revision: 3.1.0.0 $$Date: 2000/05/26 $";
+
+/*
+ * pc300.c	Cyclades-PC300(tm) Driver.
+ *
+ * Author:	Ivan Passos <ivan@cyclades.com>
+ *
+ * Copyright:	(c) 1999-2000 Cyclades Corp.
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ * 
+ * $Log: pc300.c,v $
+ * Revision 3.1.0.0 $$Date: 2000/05/26 ivan
+ * Added Frame-Relay support.
+ * Driver now uses HDLC generic driver to provide protocol support.
+ * Added logic in the SCA interrupt handler so that no board can monopolize 
+ * the driver.
+ * Request PLX I/O region, although driver doesn't use it, to avoid
+ * problems with other drivers accessing it.
+ *
+ * Revision 3.0.0.0 $$Date: 2000/05/15 ivan
+ * Did some changes in the DMA programming implementation to avoid the 
+ * occurrence of a SCA-II bug in the second channel.
+ * Implemented workaround for PLX9050 bug that would cause a system lockup
+ * in certain systems, depending on the MMIO addresses allocated to the
+ * board.
+ * Fixed the FALC chip programming to avoid synchronization problems in the 
+ * second channel (TE only).
+ * Implemented a cleaner and faster Tx DMA descriptor cleanup procedure in 
+ * cpc_queue_xmit().
+ * Changed the built-in driver implementation so that the driver can use the 
+ * general 'hdlcN' naming convention instead of proprietary device names.
+ * Driver load messages are now device-centric, instead of board-centric.
+ * Dynamic allocation of device structures.
+ *
+ * Revision 2.0.0.0 $$Date: 2000/04/15 ivan
+ * Added support for the PC300/TE boards (T1/FT1/E1/FE1).
+ *
+ * Revision 1.1.0.0 2000/02/28 ivan
+ * Major changes in the driver architecture.
+ * Driver now reports physical instead of virtual memory addresses.
+ * Added cpc_change_mtu function.
+ *
+ * Revision 1.0.0.0 1999/12/16 ivan
+ * First official release.
+ * Support for 1- and 2-channel boards (which use distinct PCI Device ID's).
+ * Support for monolythic installation (i.e., drv built into the kernel).
+ * X.25 additional checking when lapb_[dis]connect_request returns an error.
+ * SCA programming now covers X.21 as well.
+ *
+ * Revision 0.3.1.0 1999/11/18 ivan
+ * Made X.25 support configuration-dependent (as it depends on external 
+ * modules to work).
+ * Changed X.25-specific function names to comply with adopted convention.
+ * Fixed typos in X.25 functions that would cause compile errors (Daniela).
+ * Fixed bug in ch_config that would disable interrupts on a previously 
+ * enabled channel if the other channel on the same board was enabled later.
+ *
+ * Revision 0.3.0.0 1999/11/16 Daniela Squassoni
+ * X.25 support.
+ *
+ * Revision 0.2.3.0 1999/11/15 ivan
+ * Function cpc_ch_status now provides more detailed information.
+ * Added support for X.21 clock configuration.
+ * Changed TNR1 setting in order to prevent Tx FIFO overaccesses by the SCA.
+ * Now using PCI clock instead of internal oscillator clock for the SCA.
+ *
+ * Revision 0.2.2.0 1999/11/10 ivan
+ * Changed the *_dma_buf_check functions so that they would print only 
+ * the useful info instead of the whole buffer descriptor bank.
+ * Fixed bug in cpc_queue_xmit that would eventually crash the system 
+ * in case of a packet drop.
+ * Implemented TX underrun handling.
+ * Improved SCA fine tuning to boost up its performance.
+ *
+ * Revision 0.2.1.0 1999/11/03 ivan
+ * Added functions *dma_buf_pt_init to allow independent initialization 
+ * of the next-descr. and DMA buffer pointers on the DMA descriptors.
+ * Kernel buffer release and tbusy clearing is now done in the interrupt 
+ * handler.
+ * Fixed bug in cpc_open that would cause an interface reopen to fail.
+ * Added a protocol-specific code section in cpc_net_rx.
+ * Removed printk level defs (they might be added back after the beta phase).
+ *
+ * Revision 0.2.0.0 1999/10/28 ivan
+ * Revisited the code so that new protocols can be easily added / supported. 
+ *
+ * Revision 0.1.0.1 1999/10/20 ivan
+ * Mostly "esthetic" changes.
+ *
+ * Revision 0.1.0.0 1999/10/11 ivan
+ * Initial version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <net/arp.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_PC300_X25
+#include <linux/lapb.h>
+#endif /* CONFIG_PC300_X25 */
+
+#include "syncppp.h"
+
+#include <linux/pc300.h>
+
+#include <asm/spinlock.h>
+
+#define	CPC_LOCK(card,flags)					\
+		do {						\
+		spin_lock_irqsave(&card->card_lock, flags);	\
+		} while (0)
+
+#define CPC_UNLOCK(card,flags)						\
+		do {							\
+		spin_unlock_irqrestore(&card->card_lock, flags);	\
+		} while (0)
+
+#undef	PC300_DEBUG_PCI
+#undef	PC300_DEBUG_INTR
+#undef	PC300_DEBUG_TX
+#undef	PC300_DEBUG_RX
+
+/* Hardware configuration options.
+ * These are arrays of configuration options used by verification routines.
+ * The first element of each array is its size (i.e. number of options).
+ */
+static unsigned short	cpc_pci_dev_id[] = {
+	PCI_DEVICE_ID_PC300_RX_1,	/* PC300/RSV or PC300/X21, 1 chan */
+	PCI_DEVICE_ID_PC300_RX_2,	/* PC300/RSV or PC300/X21, 2 chan */
+	PCI_DEVICE_ID_PC300_TE_1,	/* PC300/TE, 1 chan */
+	PCI_DEVICE_ID_PC300_TE_2,	/* PC300/TE, 2 chan */
+	0				/* end of table */
+};
+
+/* This is the per-card data structure containing mem. addresses, irq, etc.
+ * This driver supports a maximum of PC300_MAXCARDS cards.
+ */
+static pc300_t	cpc_card[PC300_MAXCARDS];
+
+static ucshort	cpc_nboards = 0;
+
+#ifndef min
+#define	min(a,b)	(((a)<(b))?(a):(b))
+#endif
+#ifndef max
+#define	max(a,b)	(((a)>(b))?(a):(b))
+#endif
+
+/************************/
+/***   DMA Routines   ***/
+/************************/
+static void 
+tx_dma_buf_pt_init(pc300_t *card, int ch)
+{
+    int i;
+    int ch_factor = ch * N_DMA_TX_BUF;
+    volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *)(card->hw.rambase 
+		+ DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
+
+    for (i = 0 ; i < N_DMA_TX_BUF ; i++, ptdescr++) {
+	cpc_writel(&ptdescr->next, (uclong) (DMA_TX_BD_BASE + 
+		   (ch_factor + ((i + 1) & (N_DMA_TX_BUF - 1))) * 
+		   sizeof(pcsca_bd_t)));
+	cpc_writel(&ptdescr->ptbuf, 
+		   (uclong)(DMA_TX_BASE + (ch_factor + i)*BD_DEF_LEN));
+    }
+}
+
+static void 
+tx_dma_buf_init(pc300_t *card, int ch)
+{
+    int i;
+    int ch_factor = ch * N_DMA_TX_BUF;
+    volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *)(card->hw.rambase 
+		+ DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
+
+    for (i = 0 ; i < N_DMA_TX_BUF ; i++, ptdescr++) {
+	memset_io(ptdescr, 0, sizeof (pcsca_bd_t));
+	cpc_writew(&ptdescr->len, 0);
+	cpc_writeb(&ptdescr->status, 0);
+    }
+    tx_dma_buf_pt_init(card, ch);
+}
+
+static void 
+rx_dma_buf_pt_init(pc300_t *card, int ch)
+{
+    int i;
+    int ch_factor = ch * N_DMA_RX_BUF;
+    volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *)(card->hw.rambase 
+		+ DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
+
+    for (i = 0 ; i < N_DMA_RX_BUF ; i++, ptdescr++) {
+	cpc_writel(&ptdescr->next, (uclong) (DMA_RX_BD_BASE + 
+		   (ch_factor + ((i + 1) & (N_DMA_RX_BUF - 1))) * 
+		   sizeof(pcsca_bd_t)));
+	cpc_writel(&ptdescr->ptbuf, 
+		   (uclong)(DMA_RX_BASE + (ch_factor + i)*BD_DEF_LEN));
+    }
+}
+
+static void 
+rx_dma_buf_init(pc300_t *card, int ch)
+{
+    int i;
+    int ch_factor = ch * N_DMA_RX_BUF;
+    volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *)(card->hw.rambase 
+		+ DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
+
+    for (i = 0 ; i < N_DMA_RX_BUF ; i++, ptdescr++) {
+	memset_io(ptdescr, 0, sizeof (pcsca_bd_t));
+	cpc_writew(&ptdescr->len, 0);
+	cpc_writeb(&ptdescr->status, 0);
+    }
+    rx_dma_buf_pt_init(card, ch);
+}
+
+static void
+tx_dma_buf_check(pc300_t *card, int ch)
+{
+    volatile pcsca_bd_t *ptdescr;
+    int i;
+    ucshort first_bd = card->chan[ch].tx_first_bd;
+    ucshort next_bd = card->chan[ch].tx_next_bd;
+
+    printk("#CH%d: f_bd = %d(0x%08x), n_bd = %d(0x%08x)\n", ch, 
+	   first_bd, TX_BD_ADDR(ch, first_bd), 
+	   next_bd, TX_BD_ADDR(ch, next_bd));
+    for (i = first_bd, 
+	  ptdescr = (pcsca_bd_t *)(card->hw.rambase + TX_BD_ADDR(ch, first_bd));
+	 i != ((next_bd + 1) & (N_DMA_TX_BUF - 1)) ;
+	 i = (i + 1) & (N_DMA_TX_BUF - 1), 
+	  ptdescr = (pcsca_bd_t *)(card->hw.rambase + TX_BD_ADDR(ch, i))) {
+	printk("\n CH%d TX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d", 
+	       ch, i,
+	       (uclong)cpc_readl(&ptdescr->next), 
+	       (uclong)cpc_readl(&ptdescr->ptbuf),
+	       cpc_readb(&ptdescr->status), 
+	       cpc_readw(&ptdescr->len));
+    }
+    printk("\n");
+}
+
+static void
+rx_dma_buf_check(pc300_t *card, int ch)
+{
+    volatile pcsca_bd_t *ptdescr;
+    int i;
+    ucshort first_bd = card->chan[ch].rx_first_bd;
+    ucshort last_bd = card->chan[ch].rx_last_bd;
+    int ch_factor;
+
+    ch_factor = ch * N_DMA_RX_BUF;
+    printk("#CH%d: f_bd = %d, l_bd = %d\n", ch, first_bd, last_bd);
+    for (i = 0, ptdescr = (pcsca_bd_t *)(card->hw.rambase +
+                        DMA_RX_BD_BASE + ch_factor*sizeof(pcsca_bd_t));
+	 i < N_DMA_RX_BUF ;
+	 i++, ptdescr++) {
+	if (cpc_readb(&ptdescr->status) & DST_OSB)
+	    printk("\n CH%d RX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d", 
+		   ch, i,
+		   (uclong)cpc_readl(&ptdescr->next), 
+		   (uclong)cpc_readl(&ptdescr->ptbuf),
+		   cpc_readb(&ptdescr->status), 
+		   cpc_readw(&ptdescr->len));
+    }
+    printk("\n");
+}
+
+int 
+dma_get_rx_frame_size(pc300_t *card, int ch)
+{
+    volatile pcsca_bd_t *ptdescr;
+    ucshort first_bd = card->chan[ch].rx_first_bd;
+    int rcvd = 0;
+    volatile ucchar status;
+
+    ptdescr = (pcsca_bd_t *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd));
+    while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
+	rcvd += cpc_readw(&ptdescr->len);
+	first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1);
+	if (status & DST_EOM)
+	    return (rcvd);
+	ptdescr = (pcsca_bd_t *)(card->hw.rambase + cpc_readl(&ptdescr->next));
+    }
+    return (-1);
+}
+
+/*
+ * dma_buf_write: writes a frame to the Tx DMA buffers
+ * NOTE: this function writes one frame at a time.
+ */ 
+int 
+dma_buf_write(pc300_t *card, int ch, ucchar *ptdata, int len)
+{
+    int i, nchar;
+    volatile pcsca_bd_t *ptdescr;
+    int tosend = len;
+    ucchar nbuf = ((len - 1)/BD_DEF_LEN) + 1;
+
+    for (i = 0 ; i < nbuf ; i++) {
+	ptdescr = (pcsca_bd_t *)(card->hw.rambase + 
+		TX_BD_ADDR(ch, card->chan[ch].tx_next_bd));
+	nchar = min(BD_DEF_LEN,tosend);
+	if (!(cpc_readb(&ptdescr->status) & DST_OSB)) {
+	    memcpy_toio((void *)(card->hw.rambase + 
+				 cpc_readl(&ptdescr->ptbuf)), 
+			&ptdata[len - tosend], 
+			nchar);
+	    if ((i + 1) == nbuf) {
+		/* This must be the last BD to be used */
+		cpc_writeb(&ptdescr->status, (DST_EOM | DST_EOT));
+	    } else {
+		cpc_writeb(&ptdescr->status, 0);
+	    }
+	    cpc_writew(&ptdescr->len, nchar);
+	} else {
+	    return -ENOMEM;
+	}
+	tosend -= nchar;
+	card->chan[ch].tx_next_bd = 
+		(card->chan[ch].tx_next_bd + 1) & (N_DMA_TX_BUF - 1);
+    }
+    /* If it gets to here, it means we have sent the whole frame */
+    return 0;
+}
+
+/*
+ * dma_buf_read: reads a frame from the Rx DMA buffers
+ * NOTE: this function reads one frame at a time.
+ */ 
+int 
+dma_buf_read(pc300_t *card, int ch, struct sk_buff *skb)
+{
+    int nchar;
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    volatile pcsca_bd_t *ptdescr;
+    int rcvd = 0;
+    volatile ucchar status;
+
+    ptdescr = (pcsca_bd_t *)(card->hw.rambase + 
+			     RX_BD_ADDR(ch, chan->rx_first_bd));
+    while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
+	if (status & (DST_OVR | DST_CRC | DST_RBIT | DST_SHRT | DST_ABT)) {
+	    rcvd = -status;
+	    /* Discard remaining descriptors used by the bad frame */
+	    while(chan->rx_first_bd != chan->rx_last_bd) {
+		cpc_writeb(&ptdescr->status, 0);
+		chan->rx_first_bd = 
+			(chan->rx_first_bd + 1) & (N_DMA_RX_BUF - 1);
+		if(status & DST_EOM)
+		    break;
+		ptdescr = (pcsca_bd_t *)(card->hw.rambase + 
+					 cpc_readl(&ptdescr->next));
+		status = cpc_readb(&ptdescr->status);
+	    }
+	    break;
+	}
+	if ((nchar = cpc_readw(&ptdescr->len)) != 0) {
+	    memcpy_fromio(skb_put(skb, nchar), 
+			  (void *)(card->hw.rambase + 
+				   cpc_readl(&ptdescr->ptbuf)), 
+			  nchar);
+	    rcvd += nchar;
+	}
+	cpc_writeb(&ptdescr->status, 0);
+	cpc_writeb(&ptdescr->len, 0);
+	chan->rx_first_bd = (chan->rx_first_bd + 1) & (N_DMA_RX_BUF - 1);
+
+	if (status & DST_EOM)	break;
+
+	ptdescr = (pcsca_bd_t *)(card->hw.rambase + cpc_readl(&ptdescr->next));
+    }
+
+    if (rcvd != 0) {
+	/* Update pointer */
+	chan->rx_last_bd = (chan->rx_first_bd - 1) & (N_DMA_RX_BUF - 1);
+	/* Update EDA */
+	cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch),
+		   RX_BD_ADDR(ch, chan->rx_last_bd));
+    }
+    return (rcvd);
+}
+
+void 
+tx_dma_stop(pc300_t *card, int ch)
+{
+    uclong scabase = card->hw.scabase;
+    ucchar drr_ena_bit = 1<<(5 + 2*ch);
+    ucchar drr_rst_bit = 1<<(1 + 2*ch);
+
+    /* Disable DMA */
+    cpc_writeb(scabase + DRR, drr_ena_bit);
+    cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
+}
+
+void 
+rx_dma_stop(pc300_t *card, int ch)
+{
+    uclong scabase = card->hw.scabase;
+    ucchar drr_ena_bit = 1<<(4 + 2*ch);
+    ucchar drr_rst_bit = 1<<(2*ch);
+
+    /* Disable DMA */
+    cpc_writeb(scabase + DRR, drr_ena_bit);
+    cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
+}
+
+/*************************/
+/***   FALC Routines   ***/
+/*************************/
+void 
+falc_issue_cmd(pc300_t *card, int ch, ucchar cmd)
+{
+    uclong falcbase = card->hw.falcbase;
+    unsigned long i = 0;
+
+    while (cpc_readb(falcbase + F_REG(SIS, ch)) & SIS_CEC) {
+        if (i++ >= PC300_FALC_MAXLOOP) {
+            printk("%s: FALC command locked(cmd=0x%x).\n", 
+		   card->chan[ch].d.name, cmd);
+            break;
+        }
+    }
+    cpc_writeb(falcbase + F_REG(CMDR, ch), cmd);
+}
+
+void 
+falc_intr_enable(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    uclong falcbase = card->hw.falcbase;
+
+    /* Interrupt pins are open-drain */
+    cpc_writeb(falcbase + F_REG(IPC, ch), 
+	       cpc_readb(falcbase + F_REG(IPC, ch)) & ~IPC_IC0);
+    /* Conters updated each second */
+    cpc_writeb(falcbase + F_REG(FMR1, ch), 
+	       cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_ECM);
+    /* Enable SEC and ES interrupts  */
+    cpc_writeb(falcbase + F_REG(IMR3, ch), 
+	       cpc_readb(falcbase + F_REG(IMR3, ch)) & ~(IMR3_SEC | IMR3_ES));
+    cpc_writeb(falcbase + F_REG(IMR4, ch), 
+	       cpc_readb(falcbase + F_REG(IMR4, ch)) & 
+    	       ~(IMR4_LFA | IMR4_AIS | IMR4_LOS | IMR4_SLIP));
+    if (conf->media == LINE_T1) {
+	cpc_writeb(falcbase + F_REG(IMR3, ch), 
+		   cpc_readb(falcbase + F_REG(IMR3, ch)) & ~IMR3_LLBSC);
+    } else {
+	cpc_writeb(falcbase + F_REG(IPC, ch), 
+		   cpc_readb(falcbase + F_REG(IPC, ch)) | IPC_SCI);
+	cpc_writeb(falcbase + F_REG(IMR2, ch), 
+		   cpc_readb(falcbase + F_REG(IMR2, ch)) & 
+		   ~(IMR2_FAR | IMR2_LFA | IMR2_AIS | IMR2_LOS));
+	cpc_writeb(falcbase + F_REG(IMR1, ch), 
+		   cpc_readb(falcbase + F_REG(IMR1, ch)) & ~IMR1_LLBSC);
+	if (pfalc->multiframe_mode) {
+	    cpc_writeb(falcbase + F_REG(IMR2, ch), 
+		       cpc_readb(falcbase + F_REG(IMR2, ch)) & 
+		       ~(IMR2_T400MS | IMR2_MFAR));
+	} else {
+	    cpc_writeb(falcbase + F_REG(IMR2, ch), 
+		       cpc_readb(falcbase + F_REG(IMR2, ch)) | 
+		       IMR2_T400MS | IMR2_MFAR);
+	}
+    }
+}
+
+void 
+falc_open_timeslot(pc300_t *card, int ch, int timeslot)
+{
+    uclong falcbase = card->hw.falcbase;
+    ucchar tshf = card->chan[ch].falc.offset;
+
+    cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf)/8), ch),
+	       cpc_readb(falcbase + F_REG((ICB1 + (timeslot - tshf)/8), ch)) & 
+	       ~(0x80 >> ((timeslot - tshf) & 0x07)));
+    cpc_writeb(falcbase + F_REG((TTR1 + timeslot/8), ch),
+	       cpc_readb(falcbase + F_REG((TTR1 + timeslot/8), ch)) | 
+	       (0x80 >> (timeslot & 0x07)));
+    cpc_writeb(falcbase + F_REG((RTR1 + timeslot/8), ch),
+	       cpc_readb(falcbase + F_REG((RTR1 + timeslot/8), ch)) | 
+	       (0x80 >> (timeslot & 0x07)));
+}
+
+void 
+falc_close_timeslot(pc300_t *card, int ch, int timeslot)
+{
+    uclong falcbase = card->hw.falcbase;
+    ucchar tshf = card->chan[ch].falc.offset;
+
+    cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf)/8), ch),
+	       cpc_readb(falcbase + F_REG((ICB1 + (timeslot - tshf)/8), ch)) | 
+	       (0x80 >> ((timeslot - tshf) & 0x07)));
+    cpc_writeb(falcbase + F_REG((TTR1 + timeslot/8), ch),
+	       cpc_readb(falcbase + F_REG((TTR1 + timeslot/8), ch)) & 
+	       ~(0x80 >> (timeslot & 0x07)));
+    cpc_writeb(falcbase + F_REG((RTR1 + timeslot/8), ch),
+	       cpc_readb(falcbase + F_REG((RTR1 + timeslot/8), ch)) & 
+	       ~(0x80 >> (timeslot & 0x07)));
+}
+
+void 
+falc_close_all_timeslots(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+    uclong falcbase = card->hw.falcbase;
+
+    cpc_writeb(falcbase + F_REG(ICB1, ch), 0xff);
+    cpc_writeb(falcbase + F_REG(TTR1, ch), 0);
+    cpc_writeb(falcbase + F_REG(RTR1, ch), 0);
+    cpc_writeb(falcbase + F_REG(ICB2, ch), 0xff);
+    cpc_writeb(falcbase + F_REG(TTR2, ch), 0);
+    cpc_writeb(falcbase + F_REG(RTR2, ch), 0);
+    cpc_writeb(falcbase + F_REG(ICB3, ch), 0xff);
+    cpc_writeb(falcbase + F_REG(TTR3, ch), 0);
+    cpc_writeb(falcbase + F_REG(RTR3, ch), 0);
+    if (conf->media == LINE_E1) {
+	cpc_writeb(falcbase + F_REG(ICB4, ch), 0xff);
+	cpc_writeb(falcbase + F_REG(TTR4, ch), 0);
+	cpc_writeb(falcbase + F_REG(RTR4, ch), 0);
+    }
+}
+
+void 
+falc_open_all_timeslots(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+    uclong falcbase = card->hw.falcbase;
+
+    /* Timeslot 0 is never enabled */
+    cpc_writeb(falcbase + F_REG(ICB1, ch), 0);
+    cpc_writeb(falcbase + F_REG(TTR1, ch), 0x7f);
+    cpc_writeb(falcbase + F_REG(RTR1, ch), 0x7f);
+    cpc_writeb(falcbase + F_REG(ICB2, ch), 0);
+    cpc_writeb(falcbase + F_REG(TTR2, ch), 0xff);
+    cpc_writeb(falcbase + F_REG(RTR2, ch), 0xff);
+    cpc_writeb(falcbase + F_REG(ICB3, ch), 0);
+    cpc_writeb(falcbase + F_REG(TTR3, ch), 0xff);
+    cpc_writeb(falcbase + F_REG(RTR3, ch), 0xff);
+    if (conf->media == LINE_E1) {
+	cpc_writeb(falcbase + F_REG(ICB4, ch), 0);
+	cpc_writeb(falcbase + F_REG(TTR4, ch), 0xff);
+	cpc_writeb(falcbase + F_REG(RTR4, ch), 0xff);
+    } else {
+	cpc_writeb(falcbase + F_REG(ICB4, ch), 0xff);
+	cpc_writeb(falcbase + F_REG(TTR4, ch), 0x80);
+	cpc_writeb(falcbase + F_REG(RTR4, ch), 0x80);
+    }
+}
+
+void 
+falc_init_timeslot(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    int tslot;
+
+    for (tslot = 0 ; tslot < pfalc->num_channels ; tslot++) {
+	if (conf->tslot_bitmap & (1<<tslot)) {
+	    // Channel enabled
+	    falc_open_timeslot(card, ch, tslot + 1);
+	} else {
+	    // Channel disabled
+	    falc_close_timeslot(card, ch, tslot + 1);
+	}
+    }
+}
+
+void 
+falc_enable_comm(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    falc_t *pfalc = (falc_t *)&chan->falc;
+
+    if (pfalc->full_bandwidth) {
+	falc_open_all_timeslots(card, ch);
+    } else {
+	falc_init_timeslot(card, ch);
+    }
+    // CTS/DCD ON
+    cpc_writeb(card->hw.falcbase + CPLD_REG1,
+	       cpc_readb(card->hw.falcbase + CPLD_REG1) | 
+	       ((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2*ch)));
+}
+
+void 
+falc_disable_comm(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    falc_t *pfalc = (falc_t *)&chan->falc;
+
+    if (pfalc->loop_active != 2) {
+	falc_close_all_timeslots(card, ch);
+    }
+    // CTS/DCD OFF
+    cpc_writeb(card->hw.falcbase + CPLD_REG1,
+	       cpc_readb(card->hw.falcbase + CPLD_REG1) & 
+	       ~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2*ch)));
+}
+
+void
+falc_init_t1(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    uclong falcbase = card->hw.falcbase;
+    ucchar dja = (ch ? (LIM2_DJA2|LIM2_DJA1) : 0);
+
+    /* Switch to T1 mode (PCM 24) */
+    cpc_writeb(falcbase + F_REG(FMR1, ch), FMR1_PMOD);
+
+    /* Wait 20 us for setup */
+    udelay(20);
+
+    /* Transmit Buffer Size (1 frame) */
+    cpc_writeb(falcbase + F_REG(SIC1, ch), SIC1_XBS0); 
+	
+    /* Clock mode */
+    if (conf->clkrate) {	/* Master mode */
+	cpc_writeb(falcbase + F_REG(LIM0, ch), 
+		   cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_MAS); 
+    } else {	/* Slave mode */
+	cpc_writeb(falcbase + F_REG(LIM0, ch), 
+		   cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_MAS); 
+	cpc_writeb(falcbase + F_REG(LOOP, ch), 
+		   cpc_readb(falcbase + F_REG(LOOP, ch)) & ~LOOP_RTM); 
+    }
+
+    cpc_writeb(falcbase + F_REG(IPC, ch), IPC_SCI);
+    cpc_writeb(falcbase + F_REG(FMR0, ch), 
+	       cpc_readb(falcbase + F_REG(FMR0, ch)) & 
+	       ~(FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1));
+
+    switch (conf->lcode) {
+	case PC300_LC_AMI:
+	    cpc_writeb(falcbase + F_REG(FMR0, ch), 
+		       cpc_readb(falcbase + F_REG(FMR0, ch)) | 
+		       FMR0_XC1 | FMR0_RC1);
+	    /* Clear Channel register to ON for all channels */
+	    cpc_writeb(falcbase + F_REG(CCB1, ch), 0xff);
+	    cpc_writeb(falcbase + F_REG(CCB2, ch), 0xff);
+	    cpc_writeb(falcbase + F_REG(CCB3, ch), 0xff);
+	    break;			
+
+	case PC300_LC_B8ZS:
+	    cpc_writeb(falcbase + F_REG(FMR0, ch), 
+		       cpc_readb(falcbase + F_REG(FMR0, ch)) | 
+		       FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1);
+	    break;
+
+	case PC300_LC_NRZ:
+	    cpc_writeb(falcbase + F_REG(FMR0, ch), 
+		       cpc_readb(falcbase + F_REG(FMR0, ch)) | 0x00);
+	    break;
+    }
+
+    cpc_writeb(falcbase + F_REG(LIM0, ch), 
+	       cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_ELOS); 
+    cpc_writeb(falcbase + F_REG(LIM0, ch), 
+	       cpc_readb(falcbase + F_REG(LIM0, ch)) &
+	       ~(LIM0_SCL1 | LIM0_SCL0)); 
+    /* Set interface mode to 2 MBPS */	
+    cpc_writeb(falcbase + F_REG(FMR1, ch), 
+	       cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_IMOD); 
+
+    switch (conf->fr_mode) {
+	case PC300_FR_ESF:
+	    pfalc->multiframe_mode = 0;
+	    cpc_writeb(falcbase + F_REG(FMR4, ch), 
+		       cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_FM1);
+	    cpc_writeb(falcbase + F_REG(FMR1, ch), 
+		       cpc_readb(falcbase + F_REG(FMR1, ch)) | 
+		       FMR1_CRC | FMR1_EDL);
+	    cpc_writeb(falcbase + F_REG(XDL1, ch), 0);
+	    cpc_writeb(falcbase + F_REG(XDL2, ch), 0);
+	    cpc_writeb(falcbase + F_REG(XDL3, ch), 0);
+	    cpc_writeb(falcbase + F_REG(FMR0, ch), 
+		       cpc_readb(falcbase + F_REG(FMR0, ch)) & ~FMR0_SRAF);
+	    cpc_writeb(falcbase + F_REG(FMR2, ch), 
+		       cpc_readb(falcbase + F_REG(FMR2, ch)) | 
+		       FMR2_MCSP | FMR2_SSP);
+	    break;
+
+	case PC300_FR_D4:
+	    pfalc->multiframe_mode = 1;
+	    cpc_writeb(falcbase + F_REG(FMR4, ch), 
+		       cpc_readb(falcbase + F_REG(FMR4, ch)) &
+	    	       ~(FMR4_FM1 | FMR4_FM0));
+	    cpc_writeb(falcbase + F_REG(FMR0, ch), 
+		       cpc_readb(falcbase + F_REG(FMR0, ch)) | FMR0_SRAF);
+	    cpc_writeb(falcbase + F_REG(FMR2, ch), 
+		       cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_SSP);
+	    break;
+    }
+	
+    /* Enable Automatic Resynchronization */
+    cpc_writeb(falcbase + F_REG(FMR4, ch), 
+	       cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_AUTO);
+
+    /* Transmit Automatic Remote Alarm */
+    cpc_writeb(falcbase + F_REG(FMR2, ch), 
+	       cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA);
+
+    /* Channel translation mode 1 : one to one */
+    cpc_writeb(falcbase + F_REG(FMR1, ch), 
+	       cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_CTM);
+
+    /* No signaling */
+    cpc_writeb(falcbase + F_REG(FMR1, ch), 
+	       cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_SIGM);
+    cpc_writeb(falcbase + F_REG(FMR5, ch), 
+	       cpc_readb(falcbase + F_REG(FMR5, ch)) & 
+	       ~(FMR5_EIBR | FMR5_SRS));
+    cpc_writeb(falcbase + F_REG(CCR1, ch), 0);
+
+    cpc_writeb(falcbase + F_REG(LIM1, ch), 
+	       cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RIL0 | LIM1_RIL1); 
+
+    switch (conf->lbo) {
+	/* Provides proper Line Build Out */
+	case PC300_LBO_0_DB:
+	    cpc_writeb(falcbase + F_REG(LIM2, ch), (LIM2_LOS1 | dja));
+	    cpc_writeb(falcbase + F_REG(XPM0, ch), 0x5a);
+	    cpc_writeb(falcbase + F_REG(XPM1, ch), 0x8f);
+	    cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20);
+	    break;
+	case PC300_LBO_7_5_DB:
+	    cpc_writeb(falcbase + F_REG(LIM2, ch), (0x40 | LIM2_LOS1 | dja));
+	    cpc_writeb(falcbase + F_REG(XPM0, ch), 0x11);
+	    cpc_writeb(falcbase + F_REG(XPM1, ch), 0x02);
+	    cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20);
+	    break;
+	case PC300_LBO_15_DB:
+	    cpc_writeb(falcbase + F_REG(LIM2, ch), (0x80 | LIM2_LOS1 | dja));
+	    cpc_writeb(falcbase + F_REG(XPM0, ch), 0x8e);
+	    cpc_writeb(falcbase + F_REG(XPM1, ch), 0x01);
+	    cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20);
+	    break;
+	case PC300_LBO_22_5_DB:
+	    cpc_writeb(falcbase + F_REG(LIM2, ch), (0xc0 | LIM2_LOS1 | dja));
+	    cpc_writeb(falcbase + F_REG(XPM0, ch), 0x09);
+	    cpc_writeb(falcbase + F_REG(XPM1, ch), 0x01);
+	    cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20);
+	    break;
+    }
+                                              
+    /* Transmit Clock-Slot Offset */
+    cpc_writeb(falcbase + F_REG(XC0, ch), 
+	       cpc_readb(falcbase + F_REG(XC0, ch)) | 0x01); 
+    /* Transmit Time-slot Offset */
+    cpc_writeb(falcbase + F_REG(XC1, ch), 0x3e);
+    /* Receive  Clock-Slot offset */
+    cpc_writeb(falcbase + F_REG(RC0, ch), 0x05);
+    /* Receive  Time-slot offset */
+    cpc_writeb(falcbase + F_REG(RC1, ch), 0x00);
+
+    /* LOS Detection after 176 consecutive 0s */
+    cpc_writeb(falcbase + F_REG(PCDR, ch), 0x0a);
+    /* LOS Recovery after 22 ones in the time window of PCD */
+    cpc_writeb(falcbase + F_REG(PCRR, ch), 0x15);
+
+    cpc_writeb(falcbase + F_REG(IDLE, ch), 0x7f);
+
+    if (conf->fr_mode == PC300_FR_ESF_JAPAN) {
+	cpc_writeb(falcbase + F_REG(RC1, ch), 
+		   cpc_readb(falcbase + F_REG(RC1, ch)) | 0x80);
+    }
+	
+    falc_close_all_timeslots(card, ch);
+}
+
+void
+falc_init_e1(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    uclong falcbase = card->hw.falcbase;
+    ucchar dja = (ch ? (LIM2_DJA2|LIM2_DJA1) : 0);
+
+    /* Switch to E1 mode (PCM 30) */
+    cpc_writeb(falcbase + F_REG(FMR1, ch), 
+	       cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_PMOD);
+
+    /* Clock mode */
+    if (conf->clkrate) {	/* Master mode */
+	cpc_writeb(falcbase + F_REG(LIM0, ch), 
+		   cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_MAS); 
+    } else {	/* Slave mode */
+	cpc_writeb(falcbase + F_REG(LIM0, ch), 
+		   cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_MAS); 
+    }
+    cpc_writeb(falcbase + F_REG(LOOP, ch), 
+	       cpc_readb(falcbase + F_REG(LOOP, ch)) & ~LOOP_RTM); 
+
+    cpc_writeb(falcbase + F_REG(IPC, ch), IPC_SCI);
+    cpc_writeb(falcbase + F_REG(FMR0, ch), 
+	       cpc_readb(falcbase + F_REG(FMR0, ch)) & 
+	       ~(FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1));
+
+    switch (conf->lcode) {
+	case PC300_LC_AMI:
+	    cpc_writeb(falcbase + F_REG(FMR0, ch), 
+		       cpc_readb(falcbase + F_REG(FMR0, ch)) | 
+		       FMR0_XC1 | FMR0_RC1);
+	    break;			
+
+	case PC300_LC_HDB3:
+	    cpc_writeb(falcbase + F_REG(FMR0, ch), 
+		       cpc_readb(falcbase + F_REG(FMR0, ch)) | 
+		       FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1);
+	    break;
+
+	case PC300_LC_NRZ:
+	    break;
+    }
+
+    cpc_writeb(falcbase + F_REG(LIM0, ch), 
+	       cpc_readb(falcbase + F_REG(LIM0, ch)) &
+	       ~(LIM0_SCL1 | LIM0_SCL0)); 
+    /* Set interface mode to 2 MBPS */	
+    cpc_writeb(falcbase + F_REG(FMR1, ch), 
+	       cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_IMOD); 
+
+    cpc_writeb(falcbase + F_REG(XPM0, ch), 0x18);
+    cpc_writeb(falcbase + F_REG(XPM1, ch), 0x03);
+    cpc_writeb(falcbase + F_REG(XPM2, ch), 0x00);
+
+    switch (conf->fr_mode) {
+	case PC300_FR_MF_CRC4:
+	    pfalc->multiframe_mode = 1;
+	    cpc_writeb(falcbase + F_REG(FMR1, ch), 
+		       cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_XFS);
+	    cpc_writeb(falcbase + F_REG(FMR2, ch), 
+		       cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_RFS1);
+	    cpc_writeb(falcbase + F_REG(FMR2, ch), 
+		       cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_RFS0);
+	    cpc_writeb(falcbase + F_REG(FMR3, ch), 
+		       cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_EXTIW);
+			
+	    /* MultiFrame Resynchronization */
+	    cpc_writeb(falcbase + F_REG(FMR1, ch), 
+		       cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_MFCS);
+
+	    /* Automatic Loss of Multiframe > 914 CRC errors */
+	    cpc_writeb(falcbase + F_REG(FMR2, ch), 
+		       cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_ALMF);
+
+	    /* S1 and SI1/SI2 spare Bits set to 1 */
+	    cpc_writeb(falcbase + F_REG(XSP, ch), 
+		       cpc_readb(falcbase + F_REG(XSP, ch)) & ~XSP_AXS);
+	    cpc_writeb(falcbase + F_REG(XSP, ch), 
+		       cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_EBP);
+	    cpc_writeb(falcbase + F_REG(XSP, ch), 
+		       cpc_readb(falcbase + F_REG(XSP, ch)) | 
+		       XSP_XS13 | XSP_XS15);
+	    break;
+
+	case PC300_FR_MF_NON_CRC4:
+	case PC300_FR_D4:
+	    pfalc->multiframe_mode = 0;
+	    cpc_writeb(falcbase + F_REG(FMR1, ch), 
+		       cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_XFS);
+	    cpc_writeb(falcbase + F_REG(FMR2, ch), 
+		       cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_RFS1);
+	    cpc_writeb(falcbase + F_REG(FMR2, ch), 
+		       cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_RFS0);
+	    cpc_writeb(falcbase + F_REG(XSW, ch), 
+		       cpc_readb(falcbase + F_REG(XSW, ch)) | XSW_XSIS);
+	    cpc_writeb(falcbase + F_REG(XSP, ch), 
+		       cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_XSIF);
+	    break;
+    }
+
+    /* Automatic Force Resynchronization */
+    cpc_writeb(falcbase + F_REG(FMR1, ch), 
+	       cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_AFR);
+
+    /* Transmit Automatic Remote Alarm */
+    cpc_writeb(falcbase + F_REG(FMR2, ch), 
+	       cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA);
+
+    /* No signaling */
+    cpc_writeb(falcbase + F_REG(XSP, ch), 
+	       cpc_readb(falcbase + F_REG(XSP, ch)) & ~XSP_CASEN);
+    cpc_writeb(falcbase + F_REG(CCR1, ch), 0);
+
+    cpc_writeb(falcbase + F_REG(LIM1, ch), 
+	       cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RIL0 | LIM1_RIL1); 
+    cpc_writeb(falcbase + F_REG(LIM2, ch), (LIM2_LOS1 | dja));
+
+    /* Transmit Clock-Slot Offset */
+    cpc_writeb(falcbase + F_REG(XC0, ch), 
+	       cpc_readb(falcbase + F_REG(XC0, ch)) | 0x01); 
+    /* Transmit Time-slot Offset */
+    cpc_writeb(falcbase + F_REG(XC1, ch), 0x3e);
+    /* Receive  Clock-Slot offset */
+    cpc_writeb(falcbase + F_REG(RC0, ch), 0x05);
+    /* Receive  Time-slot offset */
+    cpc_writeb(falcbase + F_REG(RC1, ch), 0x00);
+
+    /* LOS Detection after 176 consecutive 0s */
+    cpc_writeb(falcbase + F_REG(PCDR, ch), 0x0a);
+    /* LOS Recovery after 22 ones in the time window of PCD */
+    cpc_writeb(falcbase + F_REG(PCRR, ch), 0x15);
+
+    /* Transmit Spare Bits for National Use (Y-Bits, Sn-Bits, Sa-Bits) */
+    cpc_writeb(falcbase + F_REG(XSW, ch), 
+	       cpc_readb(falcbase + F_REG(XSW, ch)) | 
+	       XSW_XY0 | XSW_XY1 | XSW_XY2 | XSW_XY3 | XSW_XY4);
+
+    cpc_writeb(falcbase + F_REG(IDLE, ch), 0x7f);
+
+    falc_close_all_timeslots(card, ch);
+}
+
+void
+falc_init_hdlc(pc300_t *card, int ch)
+{
+    uclong falcbase = card->hw.falcbase;
+
+    /* Enable transparent data transfer */
+    cpc_writeb(falcbase + F_REG(MODE, ch), 
+	       cpc_readb(falcbase + F_REG(MODE, ch)) | MODE_HRAC | MODE_MDS2);
+    cpc_writeb(falcbase + F_REG(RAH2, ch), 0xff);
+    cpc_writeb(falcbase + F_REG(RAH1, ch), 0xff);
+    cpc_writeb(falcbase + F_REG(RAL2, ch), 0xff);
+    cpc_writeb(falcbase + F_REG(RAL1, ch), 0xff);
+
+    /* Tx/Rx reset  */
+    falc_issue_cmd(card, ch, CMDR_RRES | CMDR_XRES | CMDR_SRES);  
+
+    /* Enable interrupt sources */
+    falc_intr_enable(card, ch);
+}
+
+void 
+te_config(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    uclong falcbase = card->hw.falcbase;
+    ucchar dummy;
+    unsigned long flags;
+
+    memset(pfalc, 0, sizeof(falc_t));
+    switch (conf->media) {
+	case LINE_T1:
+	    pfalc->num_channels = NUM_OF_T1_CHANNELS;
+	    pfalc->offset = 1;
+	    break;
+	case LINE_E1:
+	    pfalc->num_channels = NUM_OF_E1_CHANNELS;
+	    pfalc->offset = 0;
+	    break;
+    }
+    if (conf->tslot_bitmap == 0xffffffffUL)
+	pfalc->full_bandwidth = 1;
+    else
+	pfalc->full_bandwidth = 0;
+
+    CPC_LOCK(card, flags);
+    /* Reset the FALC chip */
+    cpc_writeb(card->hw.falcbase + CPLD_REG1,
+	       cpc_readb(card->hw.falcbase + CPLD_REG1) | 
+	       (CPLD_REG1_FALC_RESET << (2*ch)));
+    udelay(10000);
+    cpc_writeb(card->hw.falcbase + CPLD_REG1,
+	       cpc_readb(card->hw.falcbase + CPLD_REG1) & 
+	       ~(CPLD_REG1_FALC_RESET << (2*ch)));
+
+    if (conf->media == LINE_T1) {
+	falc_init_t1(card, ch);
+    } else {
+	falc_init_e1(card, ch);
+    }
+    falc_init_hdlc(card, ch);
+    if (conf->rx_sens == PC300_RX_SENS_SH) {
+	cpc_writeb(falcbase + F_REG(LIM0, ch),
+		   cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_EQON);
+    } else {
+	cpc_writeb(falcbase + F_REG(LIM0, ch),
+		   cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_EQON);
+    }
+    cpc_writeb(card->hw.falcbase + CPLD_REG2,
+	       cpc_readb(card->hw.falcbase + CPLD_REG2) | 
+	       ((CPLD_REG2_FALC_TX_CLK | CPLD_REG2_FALC_RX_CLK) << (2*ch)));
+
+    /* Clear all interrupt registers */
+    dummy = cpc_readb(falcbase + F_REG(FISR0, ch)) +
+	    cpc_readb(falcbase + F_REG(FISR1, ch)) +
+	    cpc_readb(falcbase + F_REG(FISR2, ch)) +
+	    cpc_readb(falcbase + F_REG(FISR3, ch));
+    CPC_UNLOCK(card, flags);
+} 
+
+void 
+falc_check_status (pc300_t *card, int ch, unsigned char frs0)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    uclong falcbase = card->hw.falcbase;
+
+    /* Verify AIS alarm */
+    if (frs0 & FRS0_AIS) {
+	if (!pfalc->blue_alarm) {
+	    pfalc->blue_alarm = 1;
+	    pfalc->ais++;
+	    // EVENT_AIS
+	    if (conf->media == LINE_T1) {
+		/* Disable this interrupt as it may otherwise interfere with 
+		   other working boards. */
+		cpc_writeb(falcbase + F_REG(IMR0, ch), 
+			   cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN);
+	    }
+	    falc_disable_comm(card, ch);
+	    // EVENT_AIS
+	}
+    } else {
+	pfalc->blue_alarm = 0;
+    }
+
+    /* Verify LOS */
+    if (frs0 & FRS0_LOS) {
+	if (! pfalc->red_alarm) {
+	    pfalc->red_alarm = 1;
+	    pfalc->los++;
+	    if (!pfalc->blue_alarm) {
+		// EVENT_FALC_ABNORMAL
+		if (conf->media == LINE_T1) {
+		    /* Disable this interrupt as it may otherwise interfere 
+		       with other working boards. */
+		    cpc_writeb(falcbase + F_REG(IMR0, ch), 
+			       cpc_readb(falcbase + F_REG(IMR0, ch)) | 
+			       IMR0_PDEN);
+		}
+		falc_disable_comm(card, ch);
+		// EVENT_FALC_ABNORMAL
+	    }
+	}
+    } else {
+	if (pfalc->red_alarm) {
+	    pfalc->red_alarm = 0;
+	    pfalc->losr++;
+	}
+    }
+
+    /* Verify LFA */
+    if (frs0 & FRS0_LFA) {
+	if (!pfalc->loss_fa) {
+	    pfalc->loss_fa = 1;
+	    pfalc->lfa++;
+	    if (!pfalc->blue_alarm && !pfalc->red_alarm) {
+		// EVENT_FALC_ABNORMAL
+		if (conf->media == LINE_T1) {
+		    /* Disable this interrupt as it may otherwise interfere 
+		       with other working boards. */
+		    cpc_writeb(falcbase + F_REG(IMR0, ch), 
+			       cpc_readb(falcbase + F_REG(IMR0, ch)) | 
+			       IMR0_PDEN);
+		}
+		falc_disable_comm(card, ch);
+		// EVENT_FALC_ABNORMAL
+	    }
+	}
+    } else {
+	if (pfalc->loss_fa) {
+	    pfalc->loss_fa = 0;
+	    pfalc->farec++;
+	}
+    }
+									
+    /* Verify LMFA */
+    if ((pfalc->multiframe_mode) && (frs0 & FRS0_LMFA)) { 
+	/* D4 or CRC4 frame mode */
+	if (! pfalc->loss_mfa) {
+	    pfalc->loss_mfa = 1;
+	    pfalc->lmfa++;
+	    if (!pfalc->blue_alarm && !pfalc->red_alarm && !pfalc->loss_fa) {
+		// EVENT_FALC_ABNORMAL
+		if (conf->media == LINE_T1) {
+		    /* Disable this interrupt as it may otherwise interfere 
+		       with other working boards. */
+		    cpc_writeb(falcbase + F_REG(IMR0, ch), 
+			       cpc_readb(falcbase + F_REG(IMR0, ch)) | 
+			       IMR0_PDEN);
+		}
+		falc_disable_comm(card, ch);
+		// EVENT_FALC_ABNORMAL
+	    }
+	}
+    } else {
+	pfalc->loss_mfa = 0;
+    }
+
+    if (pfalc->red_alarm || pfalc->loss_fa || 
+	pfalc->loss_mfa || pfalc->blue_alarm) {
+	if (pfalc->sync) {
+	    pfalc->sync = 0;
+	    cpc_writeb(falcbase + CPLD_REG2,
+		       cpc_readb(falcbase + CPLD_REG2) & 
+		       ~(CPLD_REG2_FALC_LED2 << (2*ch)));
+	}
+    } else {
+	if ((!pfalc->sync)) {
+	    pfalc->sync = 1;
+	    cpc_writeb(falcbase + CPLD_REG2,
+		       cpc_readb(falcbase + CPLD_REG2) |
+		       (CPLD_REG2_FALC_LED2 << (2*ch)));
+	}
+    }
+
+    /* Verify Remote Alarm */
+    if (frs0 & FRS0_RRA) {
+	if (! pfalc->yellow_alarm) {
+	    pfalc->yellow_alarm = 1;
+	    pfalc->rai++;
+	    if (pfalc->sync) {
+		// EVENT_RAI
+		falc_disable_comm(card, ch);
+		// EVENT_RAI
+	    }
+	}
+    } else {
+	pfalc->yellow_alarm = 0;
+    }
+
+    if ((pfalc->sync) && (!(pfalc->yellow_alarm))) {
+	if (! pfalc->active) {
+	    // EVENT_FALC_NORMAL
+	    if (pfalc->loop_active) {
+		return;
+	    }
+	    if (conf->media == LINE_T1) {
+		cpc_writeb(falcbase + F_REG(IMR0, ch), 
+			   cpc_readb(falcbase + F_REG(IMR0, ch)) & ~IMR0_PDEN);
+	    }
+	    falc_enable_comm(card, ch);
+	    // EVENT_FALC_NORMAL
+	    pfalc->active = 1;
+	}
+    } else {
+	if (pfalc->active) {
+	    pfalc->active = 0;
+	}
+    }
+}
+
+void 
+falc_update_stats(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    uclong falcbase = card->hw.falcbase;
+    ucshort counter;
+
+    counter = cpc_readb(falcbase + F_REG(FECL, ch));
+    counter |= cpc_readb(falcbase + F_REG(FECH, ch)) << 8;
+    pfalc->fec += counter;
+
+    counter = cpc_readb(falcbase + F_REG(CVCL, ch));
+    counter |= cpc_readb(falcbase + F_REG(CVCH, ch)) << 8;
+    pfalc->cvc += counter;
+
+    counter = cpc_readb(falcbase + F_REG(CECL, ch));
+    counter |= cpc_readb(falcbase + F_REG(CECH, ch)) << 8;
+    pfalc->cec += counter;
+
+    counter = cpc_readb(falcbase + F_REG(EBCL, ch));
+    counter |= cpc_readb(falcbase + F_REG(EBCH, ch)) << 8;
+    pfalc->ebc += counter;
+
+    if (cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) {
+	counter = cpc_readb(falcbase + F_REG(BECL, ch));
+	counter |= cpc_readb(falcbase + F_REG(BECH, ch)) << 8;
+	pfalc->bec += counter;
+
+	if (((conf->media == LINE_T1) && 
+	     (cpc_readb(falcbase + F_REG(FRS1, ch)) & FRS1_LLBAD) && 
+	     (!(cpc_readb(falcbase + F_REG(FRS1, ch)) & FRS1_PDEN))) 
+	    ||
+	    ((conf->media == LINE_E1) && 
+	     (cpc_readb(falcbase + F_REG(RSP, ch)) & RSP_LLBAD))) {
+	    pfalc->prbs = 2;
+	} else {
+	    pfalc->prbs = 1;
+	}
+    }
+}
+
+void 
+falc_remote_loop(pc300_t *card, int ch, int loop_on)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    uclong falcbase = card->hw.falcbase;
+
+    if (loop_on) {
+	// EVENT_FALC_ABNORMAL
+	if (conf->media == LINE_T1) {
+	    /* Disable this interrupt as it may otherwise interfere with 
+	       other working boards. */
+	    cpc_writeb(falcbase + F_REG(IMR0, ch), 
+		       cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN);
+	}
+	falc_disable_comm(card, ch);
+	// EVENT_FALC_ABNORMAL
+	cpc_writeb(falcbase + F_REG(LIM1, ch), 
+		   cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RL);
+	pfalc->loop_active = 1;
+    } else {
+	cpc_writeb(falcbase + F_REG(LIM1, ch), 
+		   cpc_readb(falcbase + F_REG(LIM1, ch)) & ~LIM1_RL);
+	pfalc->sync = 0;
+	cpc_writeb(falcbase + CPLD_REG2,
+		   cpc_readb(falcbase + CPLD_REG2) & 
+		   ~(CPLD_REG2_FALC_LED2 << (2*ch)));
+	pfalc->active = 0;
+	falc_issue_cmd(card, ch, CMDR_XRES);
+	pfalc->loop_active = 0;
+    }
+}
+
+/**********************************/
+/***   Net Interface Routines   ***/
+/**********************************/
+int cpc_queue_xmit(struct sk_buff *skb, struct device *dev)
+{
+    pc300dev_t *d = (pc300dev_t *)dev->priv;
+    pc300ch_t *chan = (pc300ch_t *)d->chan;
+    pc300_t *card = (pc300_t *)chan->card;
+    struct enet_statistics *stats = &d->hdlc->stats;
+    int ch = chan->channel;
+    volatile pcsca_bd_t *ptdescr;
+    uclong flags;
+#ifdef PC300_DEBUG_TX
+    int i;
+#endif
+
+    if (dev->tbusy) {
+	ucchar ilar;
+
+	if (time_before(jiffies, dev->trans_start + PC300_TX_TIMEOUT))
+	    return 1;
+
+	stats->tx_errors++;
+	stats->tx_aborted_errors++;
+	printk("%s: transmit timed out, restarting channel.", dev->name);
+	CPC_LOCK(card, flags);
+	if ((ilar = cpc_readb(card->hw.scabase + ILAR)) != 0) {
+	    printk("(ILAR=0x%x)", ilar);
+	    cpc_writeb(card->hw.scabase + ILAR, ilar);
+	    cpc_writeb(card->hw.scabase + DMER, 0x80);
+	}
+	printk("\n");
+	cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_BUF_CLR);
+	if (d->tx_skb) {
+	    dev_kfree_skb(d->tx_skb);
+	    d->tx_skb = NULL;
+	}
+	if (card->hw.type == PC300_TE) {
+	    cpc_writeb(card->hw.falcbase + CPLD_REG2,
+		       cpc_readb(card->hw.falcbase + CPLD_REG2) &
+		       ~(CPLD_REG2_FALC_LED1 << (2*ch)));
+	}
+	CPC_UNLOCK(card, flags);
+	dev->tbusy = 0;
+    }
+    if (test_and_set_bit(0, (void*)&dev->tbusy)) {
+	printk("%s: transmitter access conflict.\n", dev->name);
+	return 1;
+    }
+
+    /* Clean up descriptors from previous transmission */
+    while (chan->tx_first_bd != chan->tx_next_bd) {
+	ptdescr = (pcsca_bd_t *)
+		   (card->hw.rambase + TX_BD_ADDR(ch, chan->tx_first_bd));
+	cpc_writeb(&ptdescr->status, 0);
+	chan->tx_first_bd = (chan->tx_first_bd + 1) & (N_DMA_TX_BUF - 1);
+    }
+
+    /* Write buffer to DMA buffers */
+    if(dma_buf_write(card, ch, (ucchar *)skb->data, skb->len) != 0) {
+	CPC_LOCK(card, flags);
+//	printk("%s: write error. Dropping TX packet.\n", dev->name);
+	dev->tbusy = 0;
+	CPC_UNLOCK(card, flags);
+	stats->tx_dropped++;
+	return 1;
+    }
+
+#ifdef PC300_DEBUG_TX
+    printk("%s T:", dev->name);
+    for(i = 0 ; i < skb->len ; i++)
+	printk(" %02x", *(skb->data + i));
+    printk("\n");
+#endif
+
+    d->tx_skb = skb;
+    dev->trans_start = jiffies;
+
+    /* Start transmission */
+    CPC_LOCK(card, flags);
+    cpc_writel(card->hw.scabase + DTX_REG(EDAL, ch), 
+	       TX_BD_ADDR(ch, chan->tx_next_bd));
+    cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_ENA);
+    cpc_writeb(card->hw.scabase + DSR_TX(ch), DSR_DE);
+    if (card->hw.type == PC300_TE) {
+	cpc_writeb(card->hw.falcbase + CPLD_REG2,
+		   cpc_readb(card->hw.falcbase + CPLD_REG2) |
+		   (CPLD_REG2_FALC_LED1 << (2*ch)));
+    }
+    CPC_UNLOCK(card, flags);
+
+    return 0;
+}
+
+void 
+cpc_net_rx(hdlc_device *hdlc)
+{
+    struct device *dev = hdlc_to_dev(hdlc);
+    pc300dev_t *d = (pc300dev_t *)dev->priv;
+    pc300ch_t *chan = (pc300ch_t *)d->chan;
+    pc300_t *card = (pc300_t *)chan->card;
+    struct enet_statistics *stats = &hdlc->stats;
+    int ch = chan->channel;
+#ifdef PC300_DEBUG_RX
+    int i;
+#endif
+    int rxb;
+    struct sk_buff *skb;
+
+    while (1) {
+	if ((rxb = dma_get_rx_frame_size(card, ch)) == -1)
+	    return;
+
+	skb = dev_alloc_skb(rxb);
+	if (skb == NULL) {
+	    printk("%s: Memory squeeze!!\n", dev->name);
+	    return;
+	}
+	skb->dev = dev;
+
+	if((rxb = dma_buf_read(card, ch, skb)) <= 0) {
+	    if (rxb < 0) {	/* Invalid frame */
+		rxb = -rxb;
+		stats->rx_errors++;
+		if (rxb & DST_OVR) {
+		    stats->rx_fifo_errors++;
+		}
+		if (rxb & DST_CRC) {
+		    stats->rx_crc_errors++;
+		}
+		if (rxb & (DST_RBIT | DST_SHRT | DST_ABT)) {
+		    stats->rx_frame_errors++;
+		}
+	    }
+	    dev_kfree_skb(skb);
+	    continue;
+	}
+
+#ifdef PC300_DEBUG_RX
+	printk("%s R:", dev->name);
+	for(i = 0 ; i < skb->len ; i++)
+	    printk(" %02x", *(skb->data + i));
+	printk("\n");
+#endif
+
+	switch(hdlc->mode & ~MODE_SOFT) {
+#ifdef CONFIG_PC300_X25
+	    case MODE_X25:
+	    {
+		int err;
+
+		skb->protocol=htons(ETH_P_X25);
+		skb->mac.raw=skb->data;
+		skb->dev=hdlc_to_dev(d->hdlc);
+
+		/* Send it to the upper layer */
+		if ((err = lapb_data_received(d, skb)) != LAPB_OK) {
+		    printk("%s: lapb_data_received err - %d\n", dev->name, err);
+		    dev_kfree_skb(skb);
+		}
+		stats->rx_bytes += rxb;
+		stats->rx_packets++;
+		break;
+	    }
+#endif /* CONFIG_PC300_X25 */
+	    default:
+		hdlc_netif_rx(hdlc, skb, 0);
+		break;
+	}
+    }
+}
+
+#ifdef CONFIG_PC300_X25
+/*********************************/
+/***   X.25 Support Routines   ***/
+/*********************************/
+int 
+cpc_x25_packetlayer_xmit(struct sk_buff *skb, struct device *dev)
+{
+    pc300dev_t *d = (pc300dev_t *)dev->priv;
+    int err;
+	
+    switch (skb->data[0]) {
+	case 0x00:
+	    break;
+
+	case 0x01:
+	    if ((err = lapb_connect_request(d)) != LAPB_OK) {
+		if (err == LAPB_CONNECTED) {
+		    /* Send connect confirm. msg to level 3 */
+		    cpc_lapb_connected(d, 0);
+		} else {
+		    printk("%s: lapb_connect_request error - %d\n",
+			   dev->name, err);
+		}
+	    }
+	    dev_kfree_skb(skb);
+	    return 0;
+
+	case 0x02:
+	    if ((err = lapb_disconnect_request(d)) != LAPB_OK) {
+		if (err == LAPB_NOTCONNECTED) {
+		    /* Send disconnect confirm. msg to level 3 */
+		    cpc_lapb_disconnected(d, 0);
+		} else {
+		    printk("%s: lapb_disconnect_request error - %d\n",
+			   dev->name, err);
+		}
+	    }
+	    dev_kfree_skb(skb);
+	    return 0;
+			
+	default:
+	    dev_kfree_skb(skb);
+	    return 0;
+    }
+
+    skb_pull(skb, 1);
+
+    if ((err = lapb_data_request(d, skb)) != LAPB_OK) {
+	printk("%s: lapb_data_request error - %d\n", dev->name, err);
+	dev_kfree_skb(skb);
+	return -ENOMEM;
+    }
+
+    return 0;
+}
+
+void 
+cpc_lapb_connected(void *token, int reason)
+{
+    pc300dev_t *d = (pc300dev_t *)token;
+    struct sk_buff *skb;
+    unsigned char *ptr;
+
+    if ((skb = dev_alloc_skb(1)) == NULL) {
+	printk("%s: out of memory\n", d->name);
+	return;
+    }
+
+    ptr  = skb_put(skb, 1);
+    *ptr = 0x01;
+
+    skb->dev      = hdlc_to_dev(d->hdlc);
+    skb->protocol = htons(ETH_P_X25);
+    skb->mac.raw  = skb->data;
+    skb->pkt_type = PACKET_HOST;
+
+    netif_rx(skb);
+}
+
+void 
+cpc_lapb_disconnected(void *token, int reason)
+{
+    pc300dev_t *d = (pc300dev_t *)token;
+    struct sk_buff *skb;
+    unsigned char *ptr;
+
+    if ((skb = dev_alloc_skb(1)) == NULL) {
+	printk("%s: out of memory\n", d->name);
+	return;
+    }
+
+    ptr  = skb_put(skb, 1);
+    *ptr = 0x02;
+
+    skb->dev      = hdlc_to_dev(d->hdlc);
+    skb->protocol = htons(ETH_P_X25);
+    skb->mac.raw  = skb->data;
+    skb->pkt_type = PACKET_HOST;
+
+    netif_rx(skb);
+}
+
+void 
+cpc_lapb_data_indication(void *token, struct sk_buff *skb)
+{
+    pc300dev_t *d = (pc300dev_t *)token;
+    unsigned char *ptr;
+
+    ptr  = skb_push(skb, 1);
+    *ptr = 0x00;
+
+    skb->dev      = hdlc_to_dev(d->hdlc);
+    skb->protocol = htons(ETH_P_X25);
+    skb->mac.raw  = skb->data;
+    skb->pkt_type = PACKET_HOST;
+
+    netif_rx(skb);
+}
+
+void 
+cpc_lapb_data_transmit(void *token, struct sk_buff *skb)
+{
+    pc300dev_t *d = (pc300dev_t *)token;
+    struct device *dev = hdlc_to_dev(d->hdlc);
+
+    cpc_queue_xmit (skb, dev);
+}
+#endif /* CONFIG_PC300_X25 */
+
+/************************************/
+/***   PC300 Interrupt Routines   ***/
+/************************************/
+static void 
+sca_intr(pc300_t *card)
+{
+    uclong scabase = card->hw.scabase;
+    volatile uclong status;
+    int ch;
+    int intr_count = 0;
+
+    while ((status = cpc_readl(scabase + ISR0)) != 0) {
+	for (ch = 0 ; ch < card->hw.nchan ; ch++) {
+	    pc300ch_t *chan = &card->chan[ch];
+	    pc300dev_t *d = &chan->d;
+	    hdlc_device *hdlc = d->hdlc;
+	    struct device *dev = hdlc_to_dev(hdlc);
+
+	    dev->interrupt = 1;
+
+	    /**** Reception ****/
+	    if (status & IR0_DRX((IR0_DMIA|IR0_DMIB), ch)) {
+		ucchar drx_stat = cpc_readb(scabase + DSR_RX(ch));
+
+		/* Clear RX interrupts */
+		cpc_writeb(scabase + DSR_RX(ch), drx_stat | DSR_DWE);
+
+#ifdef PC300_DEBUG_INTR
+	        printk("sca_intr: RX intr (st=0x%08lx, dsr=0x%02x)\n", 
+		       status, drx_stat);
+#endif
+		if (status & IR0_DRX(IR0_DMIA, ch)) {
+		    if (drx_stat & DSR_BOF) {
+			chan->rx_first_bd = 0;
+			chan->rx_last_bd = N_DMA_RX_BUF - 1;
+			cpc_writel(scabase + DRX_REG(CDAL, ch), 
+				   RX_BD_ADDR(ch, chan->rx_first_bd));
+			cpc_writel(scabase + DRX_REG(EDAL, ch), 
+				   RX_BD_ADDR(ch, chan->rx_last_bd));
+			cpc_writew(scabase + DRX_REG(BFLL, ch), BD_DEF_LEN);
+			cpc_writeb(scabase + DSR_RX(ch), DSR_DE);
+		    }
+		}
+		if (status & IR0_DRX(IR0_DMIB, ch)) {
+		    if (drx_stat & DSR_EOM) {
+			if (card->hw.type == PC300_TE) {
+			    cpc_writeb(card->hw.falcbase + CPLD_REG2,
+				       cpc_readb(card->hw.falcbase + CPLD_REG2)
+				       | (CPLD_REG2_FALC_LED1 << (2*ch)));
+			}
+			cpc_net_rx(hdlc);
+			if (card->hw.type == PC300_TE) {
+			    cpc_writeb(card->hw.falcbase + CPLD_REG2,
+				       cpc_readb(card->hw.falcbase + CPLD_REG2)
+				       & ~(CPLD_REG2_FALC_LED1 << (2*ch)));
+			}
+		    }
+		}
+	    }
+
+	    /**** Transmission ****/
+	    if (status & IR0_DTX((IR0_EFT|IR0_DMIA|IR0_DMIB), ch)) {
+		ucchar dtx_stat = cpc_readb(scabase + DSR_TX(ch));
+
+		/* Clear TX interrupts */
+		cpc_writeb(scabase + DSR_TX(ch), dtx_stat | DSR_DWE);
+
+#ifdef PC300_DEBUG_INTR
+	        printk("sca_intr: TX intr (st=0x%08lx, dsr=0x%02x)\n", 
+		       status, dtx_stat);
+#endif
+		if (status & IR0_DTX(IR0_EFT, ch)) {
+		    if (dtx_stat & DSR_UDRF) {
+			if (cpc_readb(scabase + M_REG(TBN, ch)) != 0) {
+			    cpc_writeb(scabase + M_REG(CMD, ch), 
+				CMD_TX_BUF_CLR);
+			}
+			if (card->hw.type == PC300_TE) {
+			    cpc_writeb(card->hw.falcbase + CPLD_REG2,
+				       cpc_readb(card->hw.falcbase + CPLD_REG2)
+				       & ~(CPLD_REG2_FALC_LED1 << (2*ch)));
+			}
+			if (d->tx_skb) {
+			    struct sk_buff *skb = d->tx_skb;
+
+			    dev_kfree_skb(skb);
+			    d->tx_skb = NULL;
+			    hdlc->stats.tx_errors++;
+			    hdlc->stats.tx_fifo_errors++;
+			    /* Tell the upper layer we are ready to transmit
+			       more packets */
+			    dev->tbusy = 0;
+			    mark_bh(NET_BH);
+			}
+		    }
+		}
+		if (status & IR0_DTX(IR0_DMIA, ch)) {
+		    if (dtx_stat & DSR_BOF) {
+		    }
+		}
+		if (status & IR0_DTX(IR0_DMIB, ch)) {
+		    if (dtx_stat & DSR_EOM) {
+			if (card->hw.type == PC300_TE) {
+			    cpc_writeb(card->hw.falcbase + CPLD_REG2,
+				       cpc_readb(card->hw.falcbase + CPLD_REG2)
+				       & ~(CPLD_REG2_FALC_LED1 << (2*ch)));
+			}
+			if (d->tx_skb) {
+			    struct sk_buff *skb = d->tx_skb;
+
+			    dev_kfree_skb(skb);
+			    d->tx_skb = NULL;
+			    hdlc->stats.tx_bytes += skb->len;
+			    hdlc->stats.tx_packets++;
+			    /* Tell the upper layer we are ready to transmit
+			       more packets */
+			    dev->tbusy = 0;
+			    mark_bh(NET_BH);
+			}
+		    }
+		}
+	    }
+	    dev->interrupt = 0;
+	}
+	if (++intr_count == 10) 
+	    /* Too much work at this board. Force exit */
+	    break;
+    }
+}
+
+static void 
+falc_t1_loop_detection(pc300_t *card, int ch, ucchar frs1)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    uclong falcbase = card->hw.falcbase;
+
+    if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) && 
+	!pfalc->loop_gen) {
+	if (frs1 & FRS1_LLBDD) {
+	    // A Line Loop Back Deactuation signal detected
+	    if (pfalc->loop_active) {
+		falc_remote_loop(card, ch, 0);
+	    }
+	} else {
+	    if ((frs1 & FRS1_LLBAD) && 
+		((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) == 0)) {
+		// A Line Loop Back Actuation signal detected	
+		if (!pfalc->loop_active) {
+		    falc_remote_loop(card, ch, 1);
+		}
+	    }
+	}
+    }
+}
+
+static void 
+falc_e1_loop_detection(pc300_t *card, int ch, ucchar rsp)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    uclong falcbase = card->hw.falcbase;
+
+    if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) && 
+	!pfalc->loop_gen) {
+	if (rsp & RSP_LLBDD) {
+	    // A Line Loop Back Deactuation signal detected
+	    if (pfalc->loop_active) {
+		falc_remote_loop(card, ch, 0);
+	    }
+	} else {
+	    if ((rsp & RSP_LLBAD) && 
+		((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) == 0)) {
+		// A Line Loop Back Actuation signal detected	
+		if (!pfalc->loop_active) {
+		    falc_remote_loop(card, ch, 1);
+		}
+	    }
+	}
+    }
+}
+
+static void 
+falc_t1_intr(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    uclong falcbase = card->hw.falcbase;
+    ucchar isr0, isr3, gis;
+    ucchar dummy;
+
+    while ((gis = cpc_readb(falcbase + F_REG(GIS, ch))) != 0) {
+	if (gis & GIS_ISR0) {
+	    isr0 = cpc_readb(falcbase + F_REG(FISR0, ch));
+	    if (isr0 & FISR0_PDEN)  { 
+		/* Read the bit to clear the situation */
+		if (cpc_readb(falcbase + F_REG(FRS1, ch)) & FRS1_PDEN) {
+			pfalc->pden++;
+		}
+	    }
+	}
+
+	if (gis & GIS_ISR1) {
+	    dummy = cpc_readb(falcbase + F_REG(FISR1, ch));
+	}
+	      
+	if (gis & GIS_ISR2) {
+	    dummy = cpc_readb(falcbase + F_REG(FISR2, ch));
+	}
+      
+	if (gis & GIS_ISR3) {
+	    isr3 = cpc_readb(falcbase + F_REG(FISR3, ch));
+	    if (isr3 & FISR3_SEC) {
+		pfalc->sec++;
+		falc_update_stats(card, ch);
+		falc_check_status(card, ch, 
+				  cpc_readb(falcbase + F_REG(FRS0, ch)));
+	    }
+	    if (isr3 & FISR3_ES) {
+		pfalc->es++;
+	    }
+	    if (isr3 & FISR3_LLBSC) {
+		falc_t1_loop_detection(card, ch, 
+				cpc_readb(falcbase + F_REG(FRS1, ch)));
+	    }
+	}
+    }
+}
+
+static void 
+falc_e1_intr(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = (pc300ch_t *)&card->chan[ch];
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    uclong falcbase = card->hw.falcbase;
+    ucchar isr1, isr2, isr3, gis, rsp;
+    ucchar dummy;
+
+    while ((gis = cpc_readb(falcbase + F_REG(GIS, ch))) != 0) {
+	rsp = cpc_readb(falcbase + F_REG(RSP, ch));
+
+	if (gis & GIS_ISR0)  { 
+	    dummy = cpc_readb(falcbase + F_REG(FISR0, ch));
+	}
+	if (gis & GIS_ISR1) {
+	    isr1 = cpc_readb(falcbase + F_REG(FISR1, ch));
+	    if (isr1 & FISR1_XMB) {
+		if ((pfalc->xmb_cause & 2) && pfalc->multiframe_mode) {
+		    if (cpc_readb(falcbase + F_REG(FRS0, ch)) & 
+			(FRS0_LOS | FRS0_AIS | FRS0_LFA)) {
+			cpc_writeb(falcbase + F_REG(XSP, ch), 
+				   cpc_readb(falcbase + F_REG(XSP, ch)) & 
+				   ~XSP_AXS);
+		    } else {
+			cpc_writeb(falcbase + F_REG(XSP, ch), 
+				   cpc_readb(falcbase + F_REG(XSP, ch)) | 
+				   XSP_AXS);
+		    }
+		}
+		pfalc->xmb_cause = 0;
+		cpc_writeb(falcbase + F_REG(IMR1, ch), 
+			   cpc_readb(falcbase + F_REG(IMR1, ch)) | IMR1_XMB);
+	    }
+	    if (isr1 & FISR1_LLBSC) {
+		falc_e1_loop_detection(card, ch, rsp);
+	    }
+	}
+	if (gis & GIS_ISR2) {
+	    isr2 = cpc_readb(falcbase + F_REG(FISR2, ch));
+	    if (isr2 & FISR2_T400MS) {
+		cpc_writeb(falcbase + F_REG(XSW, ch), 
+			   cpc_readb(falcbase + F_REG(XSW, ch)) | XSW_XRA);
+	    }
+	    if (isr2 & FISR2_MFAR) {
+		cpc_writeb(falcbase + F_REG(XSW, ch), 
+			   cpc_readb(falcbase + F_REG(XSW, ch)) & ~XSW_XRA);
+	    }
+	    if (isr2 & (FISR2_FAR | FISR2_LFA | FISR2_AIS | FISR2_LOS)) {
+		pfalc->xmb_cause |= 2;
+		cpc_writeb(falcbase + F_REG(IMR1, ch), 
+			   cpc_readb(falcbase + F_REG(IMR1, ch)) & ~IMR1_XMB);
+	    }
+	}
+	if (gis & GIS_ISR3) {
+	    isr3 = cpc_readb(falcbase + F_REG(FISR3, ch));
+	    if (isr3 & FISR3_SEC) {
+		pfalc->sec++;
+		falc_update_stats(card, ch);
+		falc_check_status(card, ch, 
+				  cpc_readb(falcbase + F_REG(FRS0, ch)));
+	    }
+	    if (isr3 & FISR3_ES) {
+		pfalc->es++;
+	    }
+	}
+    }
+}
+
+static void
+falc_intr(pc300_t *card)
+{
+    int ch;
+
+    for (ch = 0 ; ch < card->hw.nchan ; ch++) {
+	pc300ch_t *chan = &card->chan[ch];
+	pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+
+	if (conf->media == LINE_T1) {
+	    falc_t1_intr(card, ch);
+	} else {
+	    falc_e1_intr(card, ch);
+	}
+    }
+}
+
+static void
+cpc_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+    pc300_t *card;
+    volatile ucchar plx_status;
+
+    if((card = (pc300_t *)dev_id) == 0){
+#ifdef PC300_DEBUG_INTR
+        printk("cpc_intr: spurious intr %d\n", irq);
+#endif
+        return; /* spurious intr */
+    }
+
+    switch (card->hw.type) {
+	case PC300_RSV:
+	case PC300_X21:
+	    sca_intr(card);
+	    break;
+
+	case PC300_TE:
+	    while ((plx_status = (cpc_readb(card->hw.plxbase + 0x4c) & 
+			(PLX_9050_LINT1_STATUS|PLX_9050_LINT2_STATUS))) != 0) {
+		if (plx_status & PLX_9050_LINT1_STATUS) { /* SCA Interrupt */
+		    sca_intr(card);
+		}
+		if (plx_status & PLX_9050_LINT2_STATUS) { /* FALC Interrupt */
+		    falc_intr(card);
+		}
+	    }
+	    break;
+    }
+}
+
+void 
+cpc_sca_status(pc300_t *card, int ch)
+{
+    ucchar ilar;
+    uclong scabase = card->hw.scabase;
+    uclong flags;
+
+    tx_dma_buf_check(card, ch);
+    rx_dma_buf_check(card, ch);
+    ilar = cpc_readb(scabase + ILAR);
+    printk("ILAR=0x%02x, WCRL=0x%02x, PCR=0x%02x, BTCR=0x%02x, BOLR=0x%02x\n", 
+	   ilar, cpc_readb(scabase + WCRL),
+	   cpc_readb(scabase + PCR),
+	   cpc_readb(scabase + BTCR),
+	   cpc_readb(scabase + BOLR));
+    printk("TX_CDA=0x%08lx, TX_EDA=0x%08lx\n", 
+	   (uclong)cpc_readl(scabase + DTX_REG(CDAL, ch)),
+	   (uclong)cpc_readl(scabase + DTX_REG(EDAL, ch)));
+    printk("RX_CDA=0x%08lx, RX_EDA=0x%08lx, BFL=0x%04x\n", 
+	   (uclong)cpc_readl(scabase + DRX_REG(CDAL, ch)),
+	   (uclong)cpc_readl(scabase + DRX_REG(EDAL, ch)),
+	   cpc_readw(scabase + DRX_REG(BFLL, ch)));
+    printk("DMER=0x%02x, DSR_TX=0x%02x, DSR_RX=0x%02x\n", 
+	   cpc_readb(scabase + DMER),
+	   cpc_readb(scabase + DSR_TX(ch)),
+	   cpc_readb(scabase + DSR_RX(ch)));
+    printk("DMR_TX=0x%02x, DMR_RX=0x%02x, DIR_TX=0x%02x, DIR_RX=0x%02x\n", 
+	   cpc_readb(scabase + DMR_TX(ch)),
+	   cpc_readb(scabase + DMR_RX(ch)),
+	   cpc_readb(scabase + DIR_TX(ch)),
+	   cpc_readb(scabase + DIR_RX(ch)));
+    printk("DCR_TX=0x%02x, DCR_RX=0x%02x, FCT_TX=0x%02x, FCT_RX=0x%02x\n", 
+	   cpc_readb(scabase + DCR_TX(ch)),
+	   cpc_readb(scabase + DCR_RX(ch)),
+	   cpc_readb(scabase + FCT_TX(ch)),
+	   cpc_readb(scabase + FCT_RX(ch)));
+    printk("MD0=0x%02x, MD1=0x%02x, MD2=0x%02x, MD3=0x%02x, IDL=0x%02x\n",
+	   cpc_readb(scabase + M_REG(MD0, ch)),
+	   cpc_readb(scabase + M_REG(MD1, ch)),
+	   cpc_readb(scabase + M_REG(MD2, ch)),
+	   cpc_readb(scabase + M_REG(MD3, ch)),
+	   cpc_readb(scabase + M_REG(IDL, ch)));
+    printk("CMD=0x%02x, SA0=0x%02x, SA1=0x%02x, TFN=0x%02x, CTL=0x%02x\n",
+	   cpc_readb(scabase + M_REG(CMD, ch)),
+	   cpc_readb(scabase + M_REG(SA0, ch)),
+	   cpc_readb(scabase + M_REG(SA1, ch)),
+	   cpc_readb(scabase + M_REG(TFN, ch)),
+	   cpc_readb(scabase + M_REG(CTL, ch)));
+    printk("ST0=0x%02x, ST1=0x%02x, ST2=0x%02x, ST3=0x%02x, ST4=0x%02x\n",
+	   cpc_readb(scabase + M_REG(ST0, ch)),
+	   cpc_readb(scabase + M_REG(ST1, ch)),
+	   cpc_readb(scabase + M_REG(ST2, ch)),
+	   cpc_readb(scabase + M_REG(ST3, ch)),
+	   cpc_readb(scabase + M_REG(ST4, ch)));
+    printk("CST0=0x%02x, CST1=0x%02x, CST2=0x%02x, CST3=0x%02x, FST=0x%02x\n",
+	   cpc_readb(scabase + M_REG(CST0, ch)),
+	   cpc_readb(scabase + M_REG(CST1, ch)),
+	   cpc_readb(scabase + M_REG(CST2, ch)),
+	   cpc_readb(scabase + M_REG(CST3, ch)),
+	   cpc_readb(scabase + M_REG(FST, ch)));
+    printk("TRC0=0x%02x, TRC1=0x%02x, RRC=0x%02x, TBN=0x%02x, RBN=0x%02x\n",
+	   cpc_readb(scabase + M_REG(TRC0, ch)),
+	   cpc_readb(scabase + M_REG(TRC1, ch)),
+	   cpc_readb(scabase + M_REG(RRC, ch)),
+	   cpc_readb(scabase + M_REG(TBN, ch)),
+	   cpc_readb(scabase + M_REG(RBN, ch)));
+    printk("TFS=0x%02x, TNR0=0x%02x, TNR1=0x%02x, RNR=0x%02x\n",
+	   cpc_readb(scabase + M_REG(TFS, ch)),
+	   cpc_readb(scabase + M_REG(TNR0, ch)),
+	   cpc_readb(scabase + M_REG(TNR1, ch)),
+	   cpc_readb(scabase + M_REG(RNR, ch)));
+    printk("TCR=0x%02x, RCR=0x%02x, TNR1=0x%02x, RNR=0x%02x\n",
+	   cpc_readb(scabase + M_REG(TCR, ch)),
+	   cpc_readb(scabase + M_REG(RCR, ch)),
+	   cpc_readb(scabase + M_REG(TNR1, ch)),
+	   cpc_readb(scabase + M_REG(RNR, ch)));
+    printk("TXS=0x%02x, RXS=0x%02x, EXS=0x%02x, TMCT=0x%02x, TMCR=0x%02x\n",
+	   cpc_readb(scabase + M_REG(TXS, ch)),
+	   cpc_readb(scabase + M_REG(RXS, ch)),
+	   cpc_readb(scabase + M_REG(EXS, ch)),
+	   cpc_readb(scabase + M_REG(TMCT, ch)),
+	   cpc_readb(scabase + M_REG(TMCR, ch)));
+    printk("IE0=0x%02x, IE1=0x%02x, IE2=0x%02x, IE4=0x%02x, FIE=0x%02x\n",
+	   cpc_readb(scabase + M_REG(IE0, ch)),
+	   cpc_readb(scabase + M_REG(IE1, ch)),
+	   cpc_readb(scabase + M_REG(IE2, ch)),
+	   cpc_readb(scabase + M_REG(IE4, ch)),
+	   cpc_readb(scabase + M_REG(FIE, ch)));
+    printk("IER0=0x%08lx\n", (uclong)cpc_readl(scabase + IER0)); 
+
+    if (ilar != 0) {
+	CPC_LOCK(card, flags);
+	cpc_writeb(scabase + ILAR, ilar);
+	cpc_writeb(scabase + DMER, 0x80);
+	CPC_UNLOCK(card, flags);
+    }
+}
+
+void 
+cpc_falc_status(pc300_t *card, int ch)
+{
+    pc300ch_t *chan = &card->chan[ch];
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    uclong flags;
+
+    CPC_LOCK(card, flags);
+    printk("CH%d:   %s %s  %d channels\n",
+	ch, (pfalc->sync ? "SYNC":""), (pfalc->active ? "ACTIVE":""), 
+	pfalc->num_channels);
+
+    printk("        pden=%d,  los=%d,  losr=%d,  lfa=%d,  farec=%d\n",
+        pfalc->pden, pfalc->los, pfalc->losr, pfalc->lfa, pfalc->farec);
+    printk("        lmfa=%d,  ais=%d,  sec=%d,  es=%d,  rai=%d\n",
+        pfalc->lmfa, pfalc->ais, pfalc->sec, pfalc->es, pfalc->rai);
+    printk("        bec=%d,  fec=%d,  cvc=%d,  cec=%d,  ebc=%d\n",
+        pfalc->bec, pfalc->fec, pfalc->cvc, pfalc->cec, pfalc->ebc);
+
+    printk("\n");
+    printk("        STATUS: %s  %s  %s  %s  %s  %s\n",
+	(pfalc->red_alarm ? "RED":""), 
+	(pfalc->blue_alarm ? "BLU":""), 
+	(pfalc->yellow_alarm ? "YEL":""), 
+	(pfalc->loss_fa ? "LFA":""), 
+	(pfalc->loss_mfa ? "LMF":""), 
+	(pfalc->prbs ? "PRB":""));
+    CPC_UNLOCK(card, flags);
+}
+
+int 
+cpc_ioctl(hdlc_device *hdlc, struct ifreq *ifr, int cmd)
+{
+    struct device *dev = hdlc_to_dev(hdlc);
+    pc300dev_t *d = (pc300dev_t *)dev->priv;
+    pc300ch_t *chan = (pc300ch_t *)d->chan;
+    pc300_t *card = (pc300_t *)chan->card;
+    pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+    int ch = chan->channel;
+    int value;
+    void *arg = (void *) ifr->ifr_data;
+
+    if(!capable(CAP_NET_ADMIN))
+	return -EPERM;
+
+    switch(cmd) {
+	case SIOCGPC300CONF:
+	    conf->proto = hdlc->mode;
+	    if (!arg || copy_to_user(arg, conf, sizeof(pc300chconf_t)))
+		return -EINVAL;
+	    return 0;
+	case SIOCSPC300CONF:
+	    if (!suser())
+		return -EPERM;
+	    if (!arg || copy_from_user(conf, arg, sizeof(pc300chconf_t)))
+		return -EINVAL;
+	    return 0;
+	case SIOCGPC300STATUS:
+	    cpc_sca_status(card, ch);
+	    return 0;
+	case SIOCGPC300FALCSTATUS:
+	    cpc_falc_status(card, ch);
+	    return 0;
+	case HDLCSETLINE:
+	    value = ifr->ifr_ifru.ifru_ivalue;
+	    switch (value) {
+		case LINE_V35:
+		case LINE_X21:
+		case LINE_RS232:
+		case LINE_T1:
+		case LINE_E1:
+		    /* Media */
+		    conf->media = value;
+		    return 0;
+
+		default:
+		    /* Clock rate */
+		    conf->clkrate = value;
+		    return 0;
+	    }
+	
+	default:
+	    switch(hdlc->mode & ~MODE_SOFT) {
+#ifdef CONFIG_PC300_X25
+		case MODE_X25:
+		    /* There are no X.25-specific ioctls */
+		    return -EINVAL;
+#endif /* CONFIG_PC300_X25 */
+		default:
+		    return -EINVAL;
+	    }
+    }
+}
+
+static int
+clock_rate_calc(uclong rate, uclong clock, int *br_io)
+{
+    int br, tc;
+    int br_pwr, error;
+
+    if (rate == 0)
+	return (0);
+
+    for (br = 0, br_pwr = 1 ; br <= 9 ; br++, br_pwr <<= 1) {
+	if ((tc = clock / br_pwr / rate) <= 0xff) {
+	    *br_io = br;
+	    break;
+	}
+    }
+
+    if (tc <= 0xff) {
+	error = ((rate - (clock / br_pwr / rate)) / rate) * 1000;
+	/* Errors bigger than +/- 1% won't be tolerated */
+	if (error < -10 || error > 10)
+	    return (-1);
+	else
+	    return (tc);
+    } else {
+	return (-1);
+    }
+}
+
+int
+ch_config(pc300dev_t *d)
+{
+    pc300ch_t *chan = (pc300ch_t *)d->chan;
+    pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+    pc300_t *card = (pc300_t *)chan->card;
+    uclong scabase = card->hw.scabase;
+    uclong plxbase = card->hw.plxbase;
+    int ch = chan->channel;
+    uclong clkrate = chan->conf.clkrate;
+    int tmc, br;
+
+    /* Reset the channel */
+    cpc_writeb(scabase + M_REG(CMD, ch), CMD_CH_RST);
+
+    /* Configure the SCA registers */
+    cpc_writeb(scabase + M_REG(MD0, ch),
+                (MD0_CRC_CCITT|MD0_CRCC0|MD0_BIT_SYNC));
+    cpc_writeb(scabase + M_REG(MD1, ch), 0);
+    cpc_writeb(scabase + M_REG(MD2, ch), (MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_NRZ));
+    cpc_writeb(scabase + M_REG(IDL, ch), 0x7e);
+    cpc_writeb(scabase + M_REG(CTL, ch), CTL_URSKP|CTL_IDLC);
+
+    /* Configure HW media */
+    switch(card->hw.type) {
+	case PC300_RSV:
+	    if(conf->media == LINE_V35) {
+		cpc_writel((plxbase+0x50),
+			cpc_readl(plxbase+0x50) | PC300_CHMEDIA_MASK(ch));
+	    } else {
+		cpc_writel((plxbase+0x50),
+			cpc_readl(plxbase+0x50) & ~PC300_CHMEDIA_MASK(ch));
+	    }
+	    break;
+
+	case PC300_X21:
+	    break;
+
+	case PC300_TE:
+	    te_config(card, ch);
+	    break;
+    }
+
+    switch(card->hw.type) {
+	case PC300_RSV:
+	case PC300_X21:
+	    if (clkrate) {
+		/* Calculate the clkrate rate parameters */
+		tmc = clock_rate_calc(clkrate, card->hw.clock, &br);
+		cpc_writeb(scabase + M_REG(TMCT, ch), tmc);
+		cpc_writeb(scabase + M_REG(TXS, ch), (TXS_DTRXC|TXS_IBRG|br));
+		cpc_writeb(scabase + M_REG(TMCR, ch), tmc);
+		cpc_writeb(scabase + M_REG(RXS, ch), (RXS_IBRG|br));
+		if (card->hw.type == PC300_X21)
+		    cpc_writeb(scabase + M_REG(GPO, ch), 1);
+	    } else {
+		cpc_writeb(scabase + M_REG(TMCT, ch), 1);
+		cpc_writeb(scabase + M_REG(TXS, ch), TXS_DTRXC);
+		cpc_writeb(scabase + M_REG(TMCR, ch), 1);
+		cpc_writeb(scabase + M_REG(RXS, ch), 0);
+		if (card->hw.type == PC300_X21)
+		    cpc_writeb(scabase + M_REG(GPO, ch), 0);
+	    }
+	    cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1|EXS_RES1);
+	    break;
+
+	case PC300_TE:
+	    /* SCA always receives clock from the FALC chip */
+	    cpc_writeb(scabase + M_REG(TMCT, ch), 1);
+	    cpc_writeb(scabase + M_REG(TXS, ch), 0);
+	    cpc_writeb(scabase + M_REG(TMCR, ch), 1);
+	    cpc_writeb(scabase + M_REG(RXS, ch), 0);
+	    cpc_writeb(scabase + M_REG(EXS, ch), 0);
+	    break;
+    }
+
+    /* Enable Interrupts */
+    cpc_writel(scabase + IER0, 
+	cpc_readl(scabase + IER0) |
+	IR0_DRX(IR0_EFT|IR0_DMIA|IR0_DMIB, ch) |
+	IR0_DTX(IR0_EFT|IR0_DMIA|IR0_DMIB, ch) );
+
+    return 0;
+}
+
+int
+rx_config(pc300dev_t *d)
+{
+    pc300ch_t *chan = (pc300ch_t *)d->chan;
+    pc300_t *card = (pc300_t *)chan->card;
+    uclong scabase = card->hw.scabase;
+    int ch = chan->channel;
+
+    cpc_writeb(scabase + DSR_RX(ch), 0);
+
+    /* General RX settings */
+    cpc_writeb(scabase + M_REG(RRC, ch), 0);
+    cpc_writeb(scabase + M_REG(RNR, ch), 16);
+
+    /* Enable reception */
+    cpc_writeb(scabase + M_REG(CMD, ch), CMD_RX_CRC_INIT);
+    cpc_writeb(scabase + M_REG(CMD, ch), CMD_RX_ENA);
+
+    /* Initialize DMA stuff */
+    chan->rx_first_bd = 0;
+    chan->rx_last_bd = N_DMA_RX_BUF - 1;
+    rx_dma_buf_init(card, ch);
+    cpc_writeb(scabase + DCR_RX(ch), DCR_FCT_CLR);
+    cpc_writeb(scabase + DMR_RX(ch), (DMR_TMOD | DMR_NF));
+    cpc_writeb(scabase + DIR_RX(ch), (DIR_EOM | DIR_BOF));
+
+    /* Start DMA */
+    cpc_writel(scabase + DRX_REG(CDAL, ch), RX_BD_ADDR(ch, chan->rx_first_bd));
+    cpc_writel(scabase + DRX_REG(EDAL, ch), RX_BD_ADDR(ch, chan->rx_last_bd));
+    cpc_writew(scabase + DRX_REG(BFLL, ch), BD_DEF_LEN);
+    cpc_writeb(scabase + DSR_RX(ch), DSR_DE);
+
+    return 0;
+}
+
+int
+tx_config(pc300dev_t *d)
+{
+    pc300ch_t *chan = (pc300ch_t *)d->chan;
+    pc300_t *card = (pc300_t *)chan->card;
+    uclong scabase = card->hw.scabase;
+    int ch = chan->channel;
+
+    cpc_writeb(scabase + DSR_TX(ch), 0);
+
+    /* General TX settings */
+    cpc_writeb(scabase + M_REG(TRC0, ch), 0);
+    cpc_writeb(scabase + M_REG(TFS, ch), 32);
+    cpc_writeb(scabase + M_REG(TNR0, ch), 20);
+    cpc_writeb(scabase + M_REG(TNR1, ch), 48);
+    cpc_writeb(scabase + M_REG(TCR, ch), 8);
+
+    /* Enable transmission */
+    cpc_writeb(scabase + M_REG(CMD, ch), CMD_TX_CRC_INIT);
+
+    /* Initialize DMA stuff */
+    chan->tx_first_bd = 0;
+    chan->tx_next_bd = 0;
+    tx_dma_buf_init(card, ch);
+    cpc_writeb(scabase + DCR_TX(ch), DCR_FCT_CLR);
+    cpc_writeb(scabase + DMR_TX(ch), (DMR_TMOD | DMR_NF));
+    cpc_writeb(scabase + DIR_TX(ch), (DIR_EOM | DIR_BOF | DIR_UDRF));
+    cpc_writel(scabase + DTX_REG(CDAL, ch), TX_BD_ADDR(ch, chan->tx_first_bd));
+    cpc_writel(scabase + DTX_REG(EDAL, ch), TX_BD_ADDR(ch, chan->tx_next_bd));
+
+    return 0;
+}
+
+int
+cpc_opench(pc300dev_t *d)
+{
+    pc300ch_t *chan = (pc300ch_t *)d->chan;
+    pc300_t *card = (pc300_t *)chan->card;
+    int ch = chan->channel;
+    uclong scabase = card->hw.scabase;
+    int err = -1;
+
+    err = ch_config(d);
+    if (err)
+	return err;
+
+    err = rx_config(d);
+    if (err)
+	return err;
+
+    err = tx_config(d);
+    if (err)
+	return err;
+
+    /* Assert RTS and DTR */
+    cpc_writeb(scabase + M_REG(CTL, ch), 
+	cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR));
+
+    return 0;
+}
+
+void
+cpc_closech(pc300dev_t *d)
+{
+    pc300ch_t *chan = (pc300ch_t *)d->chan;
+    pc300_t *card = (pc300_t *)chan->card;
+    falc_t *pfalc = (falc_t *)&chan->falc;
+    int ch = chan->channel;
+
+    cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_CH_RST);
+    if (card->hw.type == PC300_TE) {
+	memset(pfalc, 0, sizeof(falc_t));
+	cpc_writeb(card->hw.falcbase + CPLD_REG2,
+		   cpc_readb(card->hw.falcbase + CPLD_REG2) & 
+		   ~((CPLD_REG2_FALC_TX_CLK | CPLD_REG2_FALC_RX_CLK | 
+		      CPLD_REG2_FALC_LED2) << (2*ch)));
+	/* Reset the FALC chip */
+	cpc_writeb(card->hw.falcbase + CPLD_REG1,
+		   cpc_readb(card->hw.falcbase + CPLD_REG1) | 
+		   (CPLD_REG1_FALC_RESET << (2*ch)));
+	udelay(10000);
+	cpc_writeb(card->hw.falcbase + CPLD_REG1,
+		   cpc_readb(card->hw.falcbase + CPLD_REG1) & 
+		   ~(CPLD_REG1_FALC_RESET << (2*ch)));
+    }
+}
+
+int
+cpc_open(hdlc_device *hdlc)
+{
+    struct device *dev = hdlc_to_dev(hdlc);
+    pc300dev_t *d = (pc300dev_t *)dev->priv;
+    int err = -1;
+
+    err = cpc_opench(d);
+    if (err)
+	return err;
+
+    switch(hdlc->mode & ~MODE_SOFT) {
+#ifdef CONFIG_PC300_X25
+	case MODE_X25:
+	{
+	    struct lapb_register_struct cpc_lapb_callbacks;
+
+	    hdlc->ioctl = cpc_ioctl;
+	    cpc_lapb_callbacks.connect_confirmation = cpc_lapb_connected;
+	    cpc_lapb_callbacks.connect_indication = cpc_lapb_connected;
+	    cpc_lapb_callbacks.disconnect_confirmation = cpc_lapb_disconnected;
+	    cpc_lapb_callbacks.disconnect_indication = cpc_lapb_disconnected;
+	    cpc_lapb_callbacks.data_indication = cpc_lapb_data_indication;
+	    cpc_lapb_callbacks.data_transmit = cpc_lapb_data_transmit;
+
+	    if ((err = lapb_register(d, &cpc_lapb_callbacks)) != LAPB_OK) {
+		printk("%s: lapb_register error - %d\n", dev->name, err);
+		dev->tbusy = 1;
+		dev->start = 0;
+		return -ENODEV;
+	    }
+	    dev->hard_start_xmit = cpc_x25_packetlayer_xmit;
+	    dev->type = ARPHRD_X25;
+	    dev->hard_header_len = 2;
+	    dev->addr_len = 0;
+	    break;
+	}
+#endif /* CONFIG_PC300_X25 */
+	default:
+	    break;
+    }
+    dev->tbusy = 0;
+    dev->interrupt = 0;
+    dev->start = 1;
+    MOD_INC_USE_COUNT;
+    return 0;
+}
+
+void
+cpc_close(hdlc_device *hdlc)
+{
+    struct device *dev = hdlc_to_dev(hdlc);
+    pc300dev_t *d = (pc300dev_t *)dev->priv;
+    pc300ch_t *chan = (pc300ch_t *)d->chan;
+    pc300_t *card = (pc300_t *)chan->card;
+    uclong flags;
+
+    CPC_LOCK(card, flags);
+    switch(hdlc->mode & ~MODE_SOFT) {
+#ifdef CONFIG_PC300_X25
+	case MODE_X25:
+	{
+	    int err;
+
+	    if ((err = lapb_unregister(d)) != LAPB_OK) {
+		printk("%s: lapb_unregister error - %d\n", dev->name, err);
+	    }
+	    break;
+	}
+#endif /* CONFIG_PC300_X25 */
+	default:
+	    break;
+    }
+    if (d->tx_skb) {
+	dev_kfree_skb(d->tx_skb);
+	d->tx_skb = NULL;
+    }
+    dev->tbusy = 1;
+    dev->start = 0;
+    cpc_closech(d);
+    CPC_UNLOCK(card, flags);
+
+    MOD_DEC_USE_COUNT;
+}
+
+static uclong
+detect_ram(pc300_t *card)
+{
+    uclong i;
+    ucchar data;
+    uclong rambase = card->hw.rambase;
+
+    card->hw.ramsize = PC300_RAMSIZE;
+    /* Let's find out how much RAM is present on this board */
+    for (i = 0; i < card->hw.ramsize ; i++) {
+        data = (ucchar)(i & 0xff);
+        cpc_writeb(rambase + i, data);
+        if (cpc_readb(rambase + i) != data) {
+            break;
+        }
+    }
+    return (i);
+}
+
+static void
+plx_init(pc300_t *card)
+{
+  struct RUNTIME_9050 *plx_ctl = (struct RUNTIME_9050 *)card->hw.plxbase;
+
+    /* Reset PLX */
+    cpc_writel(&plx_ctl->init_ctrl, cpc_readl(&plx_ctl->init_ctrl)|0x40000000);
+    udelay(10000L);
+    cpc_writel(&plx_ctl->init_ctrl, cpc_readl(&plx_ctl->init_ctrl)&~0x40000000);
+
+    /* Reload Config. Registers from EEPROM */
+    cpc_writel(&plx_ctl->init_ctrl, cpc_readl(&plx_ctl->init_ctrl)|0x20000000);
+    udelay(10000L);
+    cpc_writel(&plx_ctl->init_ctrl, cpc_readl(&plx_ctl->init_ctrl)&~0x20000000);
+
+}
+
+__initfunc(static int  
+cpc_detect(void))
+{
+#ifdef CONFIG_PCI
+    static struct pci_dev	*pdev = NULL;
+    ucchar	cpc_rev_id;
+    ucchar	cpc_irq = 0;
+    uclong	cpc_plxphys, cpc_ramphys, cpc_scaphys, cpc_falcphys, cpc_iophys;
+    uclong	cpc_plxbase, cpc_rambase, cpc_scabase, cpc_falcbase;
+    ucshort	i, j, eeprom_outdated = 0;
+    ucshort	device_id, dev_index = 0;
+    pc300_t	*card;
+
+    if(pci_present() == 0) {    /* PCI bus not present */
+	return 0;
+    }
+    for (i = 0 ; i < PC300_MAXCARDS ; i++) {
+	/* look for a Cyclades card by vendor and device id */
+	while((device_id = cpc_pci_dev_id[dev_index]) != 0) {
+	    if((pdev = pci_find_device(PCI_VENDOR_ID_CYCLADES, 
+				       device_id, pdev)) == NULL) {
+		dev_index++;    /* try next device id */
+	    } else {
+		break;    /* found a board */
+	    }
+	}
+	if (device_id == 0)
+	    break;
+
+	/* read PCI configuration area */
+	cpc_irq = pdev->irq;
+	cpc_iophys = pdev->base_address[1];
+	cpc_scaphys = pdev->base_address[2];
+	cpc_ramphys = pdev->base_address[3];
+	cpc_falcphys = pdev->base_address[4];
+	cpc_plxphys = pdev->base_address[5];
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &cpc_rev_id);
+
+	if ((device_id == PCI_DEVICE_ID_PC300_RX_1) ||
+	    (device_id == PCI_DEVICE_ID_PC300_RX_2) ||
+	    (device_id == PCI_DEVICE_ID_PC300_TE_1) ||
+	    (device_id == PCI_DEVICE_ID_PC300_TE_2)) {
+#ifdef PC300_DEBUG_PCI
+	    printk("cpc (bus=0x0%x, pci_id=0x%x, ",
+		   pdev->bus->number, pdev->devfn);
+	    printk("rev_id=%d) IRQ%d\n", cpc_rev_id, (int)cpc_irq);
+	    printk("cpc:found  ramaddr=0x%lx plxaddr=0x%lx "
+		   "ctladdr=0x%lx falcaddr=0x%lx\n",
+		   (ulong)cpc_ramphys, (ulong)cpc_plxphys, 
+		   (ulong)cpc_scaphys, (ulong)cpc_falcphys);
+#endif
+	    cpc_iophys &= PCI_BASE_ADDRESS_IO_MASK;
+	    cpc_plxphys &= PCI_BASE_ADDRESS_MEM_MASK;
+	    cpc_ramphys &= PCI_BASE_ADDRESS_MEM_MASK;
+	    cpc_scaphys &= PCI_BASE_ADDRESS_MEM_MASK;
+	    cpc_falcphys &= PCI_BASE_ADDRESS_MEM_MASK;
+
+	    /* Although we don't use this I/O region, we should
+	       request it from the kernel anyway, to avoid problems
+	       with other drivers accessing it. */
+	    request_region(cpc_iophys, PC300_PLX_WIN, "Cyclades-PC300");
+
+	    if (cpc_plxphys) {
+		pdev->base_address[0] = cpc_plxphys;
+		pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, cpc_plxphys);
+	    } else {
+		eeprom_outdated = 1;
+		cpc_plxphys = pdev->base_address[0];
+		cpc_plxphys &= PCI_BASE_ADDRESS_MEM_MASK;
+	    }
+
+	    cpc_plxbase = (uclong) ioremap(cpc_plxphys, PC300_PLX_WIN);
+	    cpc_rambase = (uclong) ioremap(cpc_ramphys, PC300_RAMSIZE);
+	    cpc_scabase = (uclong) ioremap(cpc_scaphys, PC300_SCASIZE);
+	    switch(device_id) {
+		case PCI_DEVICE_ID_PC300_TE_1:
+		case PCI_DEVICE_ID_PC300_TE_2:
+		    cpc_falcbase = (uclong) ioremap(cpc_falcphys, 
+						    PC300_FALCSIZE);
+		    break;
+
+		case PCI_DEVICE_ID_PC300_RX_1:
+		case PCI_DEVICE_ID_PC300_RX_2:
+		default:
+		    cpc_falcbase = 0;
+		    break;
+	    }
+
+#ifdef PC300_DEBUG_PCI
+	    printk("cpc: relocate ramaddr=0x%lx plxaddr=0x%lx "
+		   "ctladdr=0x%lx falcaddr=0x%lx\n",
+		   (ulong)cpc_rambase, (ulong)cpc_plxbase, 
+		   (ulong)cpc_scabase, (ulong)cpc_falcbase);
+#endif
+	    /* Fill the next card structure available */
+	    for (j = 0 ; j < PC300_MAXCARDS ; j++) {
+		if (cpc_card[j].hw.rambase == 0)  break;
+	    }
+
+	    if (j == PC300_MAXCARDS) {	/* No more cards available */
+		printk("PC300 found at RAM 0x%lx, "
+		       "but no more cards can be used.\n",
+		       (ulong) cpc_ramphys);
+		printk("Change PC300_MAXCARDS in pc300drv.c and "
+		       "recompile your kernel.\n");
+		return(i);
+	    }
+
+	    /* Allocate IRQ */
+	    if(request_irq(cpc_irq, cpc_intr, SA_SHIRQ, "Cyclades-PC300", 
+			   &cpc_card[j]))
+	    {
+		printk("PC300 found at RAM 0x%lx, "
+		       "but could not allocate IRQ%d.\n",
+		       (ulong) cpc_ramphys, cpc_irq);
+		return(i);
+	    }
+
+	    card = &cpc_card[j];
+
+	    /* Set PC300 HW structure */
+	    card->hw.plxphys = cpc_plxphys;
+	    card->hw.plxbase = cpc_plxbase;
+	    card->hw.plxsize = (uclong)PC300_PLX_WIN;
+	    card->hw.scaphys = cpc_scaphys;
+	    card->hw.scabase = cpc_scabase;
+	    card->hw.scasize = (uclong)PC300_SCASIZE;
+	    card->hw.ramphys = cpc_ramphys;
+	    card->hw.rambase = cpc_rambase;
+	    card->hw.ramsize = detect_ram(card);
+	    card->hw.falcphys = cpc_falcphys;
+	    card->hw.falcbase = cpc_falcbase;
+	    card->hw.falcsize = (uclong)PC300_FALCSIZE;
+	    card->hw.irq = (int)cpc_irq;
+	    switch(device_id) {
+		case PCI_DEVICE_ID_PC300_RX_1:
+		case PCI_DEVICE_ID_PC300_TE_1:
+		    card->hw.nchan = 1;
+		    break;
+
+		case PCI_DEVICE_ID_PC300_RX_2:
+		case PCI_DEVICE_ID_PC300_TE_2:
+		default:
+		    card->hw.nchan = PC300_MAXCHAN;
+		    break;
+	    }
+
+	    /* Enable interrupts on the PCI bridge */
+	    plx_init(&cpc_card[j]);
+	    cpc_writew(card->hw.plxbase+0x4c, 
+		cpc_readw(card->hw.plxbase+0x4c) | 0x0040);
+
+#ifdef USE_PCI_CLOCK
+	    /* Set board clock to PCI clock */
+	    cpc_writel(card->hw.plxbase+0x50, 
+		cpc_readl(card->hw.plxbase+0x50) | 0x00000004UL);
+	    card->hw.clock = PC300_PCI_CLOCK;
+#else
+	    /* Set board clock to internal oscillator clock */
+	    cpc_writel(card->hw.plxbase+0x50, 
+		cpc_readl(card->hw.plxbase+0x50) & ~0x00000004UL);
+	    card->hw.clock = PC300_OSC_CLOCK;
+#endif
+
+	    /* Set Global SCA-II registers */
+	    cpc_writeb(card->hw.scabase + PCR, PCR_PR2);
+	    cpc_writeb(card->hw.scabase + BTCR, 0x10);
+	    cpc_writeb(card->hw.scabase + WCRL, 0);
+	    cpc_writeb(card->hw.scabase + DMER, 0x80);
+
+	    /* Set board type */
+	    switch(device_id) {
+		case PCI_DEVICE_ID_PC300_TE_1:
+		case PCI_DEVICE_ID_PC300_TE_2:
+		    card->hw.type = PC300_TE;
+		    /* Enable the board's global clock */
+		    cpc_writeb(card->hw.falcbase + CPLD_REG1,
+			       cpc_readb(card->hw.falcbase + CPLD_REG1) | 
+			       CPLD_REG1_GLOBAL_CLK);
+		    break;
+
+		case PCI_DEVICE_ID_PC300_RX_1:
+		case PCI_DEVICE_ID_PC300_RX_2:
+		default:
+		    if((cpc_readl(card->hw.plxbase+0x50) & PC300_CTYPE_MASK)) {
+			card->hw.type = PC300_X21;
+		    } else {
+			card->hw.type = PC300_RSV;
+		    }
+		    break;
+	    }
+	}
+    }
+    if (eeprom_outdated)
+	printk("WARNING: detected at least one PC300 with an outdated "
+	       "EEPROM.\n");
+    return i;
+#else
+    printk("cpc: WARNING: your kernel does not have PCI support.\n");
+    return 0;
+#endif /* CONFIG_PCI */
+}
+
+/*
+ * This routine prints out the appropriate serial driver version number
+ * and identifies which options were configured into this driver.
+ */
+static inline void
+show_version(void)
+{
+  char *rcsvers, *rcsdate, *tmp;
+    rcsvers = strchr(rcsid, ' '); rcsvers++;
+    tmp = strchr(rcsvers, ' '); *tmp++ = '\0';
+    rcsdate = strchr(tmp, ' '); rcsdate++;
+    tmp = strrchr(rcsdate, ' '); *tmp = '\0';
+    printk("Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate);
+    printk("        built %s %s\n", __DATE__, __TIME__);
+} /* show_version */
+
+__initfunc(int 
+cpc_init(void))
+{
+    int i, j, devcount = 0;
+
+    show_version();
+    memset(&cpc_card, 0, (PC300_MAXCARDS * sizeof(pc300_t)));
+    if((cpc_nboards = cpc_detect()) == 0) {
+	printk("** No boards were found.\n");
+	return -ENODEV;
+    }
+
+    /* Fill in valid structures and invalidate the remaining */
+    for (i = 0 ; i < PC300_MAXCARDS ; i++) {
+	pc300_t *card = &cpc_card[i];
+
+	if (card->hw.rambase != 0) {
+	    for(j = 0; j < card->hw.nchan; j++) {
+		pc300ch_t *chan = &card->chan[j];
+		pc300dev_t *d = &chan->d;
+		hdlc_device *hdlc;
+		struct device *dev;
+
+		memset(chan, 0, sizeof(pc300ch_t));
+
+		chan->card = card;
+		chan->channel = j;
+		chan->conf.clkrate = 64000;
+		switch(card->hw.type) {
+		    case PC300_TE:
+			chan->conf.media = LINE_T1;
+			chan->conf.lcode = PC300_LC_B8ZS;
+			chan->conf.fr_mode = PC300_FR_ESF;
+			chan->conf.lbo = PC300_LBO_0_DB;
+			chan->conf.rx_sens = PC300_RX_SENS_SH;
+			chan->conf.tslot_bitmap = 0xffffffffUL;
+			break;
+
+		    case PC300_X21:
+			chan->conf.media = LINE_X21;
+			break;
+
+		    case PC300_RSV:
+		    default:
+			chan->conf.media = LINE_RS232;
+			break;
+		}
+		chan->tx_first_bd = 0;
+		chan->tx_next_bd = 0;
+		chan->rx_first_bd = 0;
+		chan->rx_last_bd = N_DMA_RX_BUF - 1;
+
+		d->chan = chan;
+		d->tx_skb = NULL;
+
+		d->hdlc = (hdlc_device *)
+			kmalloc(sizeof(hdlc_device), GFP_KERNEL);
+		if (d->hdlc == NULL)
+		    continue;
+		memset(d->hdlc, 0, sizeof(hdlc_device));
+
+		hdlc = d->hdlc;
+		hdlc->open = cpc_open;
+		hdlc->close = cpc_close;
+		hdlc->ioctl = cpc_ioctl;
+		d->if_ptr = &hdlc->pppdev;
+
+		dev = hdlc_to_dev(d->hdlc);
+		dev->mem_start = card->hw.ramphys;
+		dev->mem_end = card->hw.ramphys + card->hw.ramsize - 1;
+		dev->irq = card->hw.irq;
+		dev->interrupt = 0;
+		dev->start = 0;
+		dev->tx_queue_len = PC300_TX_QUEUE_LEN;
+		dev->hard_start_xmit = cpc_queue_xmit;
+		dev->set_multicast_list = NULL;
+		dev->set_mac_address = NULL;
+
+		if(register_hdlc_device(hdlc) == 0) {
+		    dev->priv = d;	/* We need 'priv', hdlc doesn't */
+		    printk("%s: PC300/", hdlc->name);
+		    switch(card->hw.type) {
+			case PC300_TE:
+			    printk("TE ");
+			    break;
+
+			case PC300_X21:
+			    printk("X21");
+			    break;
+
+			case PC300_RSV:
+			default:
+			    printk("RSV");
+			    break;
+		    }
+		    printk(" #%d, %ldKB of RAM at 0x%lx, IRQ%d, channel %d.\n",
+			   i + 1, card->hw.ramsize/1024, card->hw.ramphys, 
+			   card->hw.irq, j + 1);
+		    devcount++;
+		} else {
+		    *(d->name) = 0;
+		    kfree(d->hdlc);
+		    continue;
+		}
+	    }
+	    spin_lock_init(&card->card_lock);
+	} else {
+	    memset(&card->hw, 0, sizeof (pc300hw_t));
+	}
+    }
+
+    return 0;
+}
+
+#ifdef MODULE
+int init_module (void)
+{
+    return (cpc_init());
+} /* init_module */
+
+void cleanup_module (void)
+{
+    int i, j;
+
+    for (i = 0 ; i < PC300_MAXCARDS ; i++) {
+	pc300_t *card = &cpc_card[i];
+
+        if (card->hw.rambase != 0) {
+	    for(j = 0 ; j < card->hw.nchan ; j++) {
+		unregister_hdlc_device(card->chan[j].d.hdlc);
+	    }
+
+	    iounmap((void *)card->hw.plxbase);
+	    iounmap((void *)card->hw.scabase);
+	    iounmap((void *)card->hw.rambase);
+	    if (card->hw.type == PC300_TE)
+		iounmap((void *)card->hw.falcbase);
+	    if (card->hw.irq)
+		free_irq(card->hw.irq, card);
+        }
+    }
+}
+#endif
+
diff -urN linux-2.2.17-pre1/drivers/net/rtl8139.c linux/drivers/net/rtl8139.c
--- linux-2.2.17-pre1/drivers/net/rtl8139.c	Wed May  3 17:16:41 2000
+++ linux/drivers/net/rtl8139.c	Mon Dec  3 22:05:27 2001
@@ -1265,8 +1265,8 @@
 			} else {
 #if 1  /* USE_IP_COPYSUM */
 				eth_copy_and_sum(skb, &rx_ring[ring_offset + 4],
-								 rx_size, 0);
-				skb_put(skb, rx_size);
+						 rx_size - 4, 0);
+				skb_put(skb, rx_size - 4);
 #else
 				memcpy(skb_put(skb, rx_size), &rx_ring[ring_offset + 4],
 					   rx_size);
diff -urN linux-2.2.17-pre1/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c
--- linux-2.2.17-pre1/drivers/pci/oldproc.c	Wed Jun  7 14:26:43 2000
+++ linux/drivers/pci/oldproc.c	Mon Dec  3 22:05:27 2001
@@ -458,6 +458,10 @@
 	DEVICE( CYCLADES,	CYCLOM_8Y_Hi,	"Cyclom-8Y above 1Mbyte"),
 	DEVICE( CYCLADES,	CYCLOM_Z_Lo,	"Cyclades-Z below 1Mbyte"),
 	DEVICE( CYCLADES,	CYCLOM_Z_Hi,	"Cyclades-Z above 1Mbyte"),
+	DEVICE( CYCLADES,	PC300_RX_2,	"PC300/RSV or /X21 (2 ports)"),
+	DEVICE( CYCLADES,	PC300_RX_1,	"PC300/RSV or /X21 (1 port)"),
+	DEVICE( CYCLADES,	PC300_TE_2,	"PC300/TE (2 ports)"),
+	DEVICE( CYCLADES,	PC300_TE_1,	"PC300/TE (1 port)"),
 	DEVICE( ESSENTIAL,	ESSENTIAL_ROADRUNNER,"Roadrunner serial HIPPI"),
 	DEVICE( O2,		O2_6832,	"6832"),
 	DEVICE( 3DFX,		3DFX_VOODOO,	"Voodoo"),
diff -urN linux-2.2.17-pre1/drivers/scsi/aic7xxx/aic7xxx.seq linux/drivers/scsi/aic7xxx/aic7xxx.seq
--- linux-2.2.17-pre1/drivers/scsi/aic7xxx/aic7xxx.seq	Wed May  3 17:16:44 2000
+++ linux/drivers/scsi/aic7xxx/aic7xxx.seq	Mon Dec  3 22:05:27 2001
@@ -60,11 +60,7 @@
 	clr	SCSISIGO;		/* De-assert BSY */
 	and	SXFRCTL1, ~BITBUCKET;
 	/* Always allow reselection */
-	if ((p->flags & AHC_TARGETMODE) != 0) {
-		mvi	SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP;
-	} else {
-		mvi	SCSISEQ, ENRSELI|ENAUTOATNP;
-	}
+	mvi	SCSISEQ, ENRSELI|ENAUTOATNP;
 
 	if ((p->features & AHC_CMD_CHAN) != 0) {
 		/* Ensure that no DMA operations are in progress */
@@ -236,118 +232,6 @@
 
 selection:
 	test	SSTAT0,SELDO	jnz select_out;
-select_in:
-	if ((p->flags & AHC_TARGETMODE) != 0) {
-		test	SSTAT0, TARGET	jz initiator_reselect;
-		/*
-		 * We've just been selected.  Assert BSY and
-		 * setup the phase for receiving the messages
-		 * from the target.
-		 */
-		mvi	SCSISIGO, P_MESGOUT|BSYO;
-		mvi	CLRSINT0, CLRSELDO;
-
-		/*
-		 * If ATN isn't asserted, go directly to bus free.
-		 */
-		test	SCSISIGI, ATNI	jz	target_busfree;
-
-		/*
-		 * Setup the DMA for sending the identify and
-		 * command information.
-		 */
-		mov	A, TMODE_CMDADDR_NEXT;
-		mvi	DINDEX, HADDR;
-		mvi	TMODE_CMDADDR call set_32byte_addr;
-		mvi	DFCNTRL, FIFORESET;
-
-		clr	SINDEX;
-		/* Watch ATN closely now */
-message_loop:
-		or	SXFRCTL0, SPIOEN;
-		test	SSTAT0, SPIORDY jz .;
-		and	SXFRCTL0, ~SPIOEN;
-		mov	DINDEX, SCSIDATL;
-		mov	DFDAT, DINDEX;
-		inc	SINDEX;
-
-		/* Message Testing... */
-		test	DINDEX, MSG_IDENTIFYFLAG jz . + 2;
-		mov	ARG_1, DINDEX;
-
-		test	SCSISIGI, ATNI	jnz	message_loop;
-		add	A, -4, SINDEX;
-		jc	target_cmdphase;
-		mvi	DFDAT, SCB_LIST_NULL;	/* Terminate the message list */
-
-target_cmdphase:
-		add	HCNT[0], 1, A;
-		clr	HCNT[1];
-		clr	HCNT[2];
-		mvi	SCSISIGO, P_COMMAND|BSYO;
-		or	SXFRCTL0, SPIOEN;
-		test	SSTAT0, SPIORDY jz .;
-		mov	A, SCSIDATL;
-		mov	DFDAT, A;	/* Store for host */
-
-		/*
-		 * Determine the number of bytes to read
-		 * based on the command group code.  Count is
-		 * one less than the total since we've already
-		 * fetched the first byte.
-		 */
-		clr	SINDEX;
-		shr	A, CMD_GROUP_CODE_SHIFT;
-		add	SEQADDR0, A;
-
-		add	SINDEX, CMD_GROUP0_BYTE_DELTA;
-		nop;	/* Group 1 and 2 are the same */
-		add	SINDEX, CMD_GROUP2_BYTE_DELTA;
-		nop;	/* Group 3 is reserved */
-		add	SINDEX, CMD_GROUP4_BYTE_DELTA;
-		add	SINDEX, CMD_GROUP5_BYTE_DELTA;
-		/* Group 6 and 7 are not handled yet */
-
-		mov	A, SINDEX;
-		add	HCNT[0], A;
-
-command_loop:
-		test	SSTAT0, SPIORDY jz .;
-		cmp	SINDEX, 1 jne . + 2;
-		and	SXFRCTL0, ~SPIOEN;	/* Last Byte */
-		mov	DFDAT, SCSIDATL;
-		dec	SINDEX;
-		test	SINDEX, 0xFF jnz command_loop;
-
-		or	DFCNTRL, HDMAEN|FIFOFLUSH;
-	
-		call	dma_finish;
-
-		test	ARG_1, MSG_IDENTIFY_DISCFLAG jz selectin_post;
-
-		mvi	SCSISIGO, P_MESGIN|BSYO;
-
-		or	SXFRCTL0, SPIOEN;
-
-		mvi	MSG_DISCONNECT call target_outb;
-	
-selectin_post:
-		inc	TMODE_CMDADDR_NEXT;
-		cmp	TMODE_CMDADDR_NEXT, TMODE_NUMCMDS jne . + 2;
-		clr	TMODE_CMDADDR_NEXT;
-		mvi	QOUTFIFO, SCB_LIST_NULL;
-		mvi	INTSTAT,CMDCMPLT;
-
-		test	ARG_1, MSG_IDENTIFY_DISCFLAG jnz target_busfree;
-
-		/* Busy loop on something then go to data or status phase */
-
-target_busfree:
-		clr	SCSISIGO;
-		jmp	poll_for_work;
-
-	}
-
 /*
  * Reselection has been initiated by a target. Make a note that we've been
  * reselected, but haven't seen an IDENTIFY message from the target yet.
@@ -453,14 +337,14 @@
  * STCNT may have been cleared, so restore it from the residual field.
  */
 data_phase_reinit:
-	if ((p->features & AHC_CMD_CHAN) != 0) {
-		if ((p->features & AHC_ULTRA2) != 0) {
-			bmov	HADDR, SHADDR, 4;
-			bmov    HCNT, SCB_RESID_DCNT, 3;
-		} else {
-			bmov    STCNT, SCB_RESID_DCNT, 3;
-		}
-	} else {
+	if ((p->features & AHC_ULTRA2) != 0) {
+		bmov	HADDR, SHADDR, 4;
+		bmov    HCNT, SCB_RESID_DCNT, 3;
+	}
+	if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
+		bmov    STCNT, SCB_RESID_DCNT, 3;
+	}
+	if ((p->features & AHC_CMD_CHAN) == 0) {
 		mvi	DINDEX, STCNT;
 		mvi	SCB_RESID_DCNT	call bcopy_3;
 	}
@@ -687,10 +571,13 @@
 		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
 		test	DFSTATUS, MREQPEND	jnz .;
 ultra2_dmahalt:
-		and     DFCNTRL, ~HDMAEN;
-		test	DFCNTRL, HDMAEN jnz .;
-		and     DFCNTRL, ~SCSIEN;
-		test	DFCNTRL, SCSIEN jnz .;
+		test	SCSIOFFSET, 0x7f	jnz ultra2_shutdown;
+ultra2_await_nreq:
+		test	SCSISIGI, REQI	jz ultra2_shutdown;
+		test	SSTAT1, PHASEMIS	jz ultra2_await_nreq;
+ultra2_shutdown:
+		and     DFCNTRL, ~(HDMAEN|SCSIEN);
+		test	DFCNTRL, (HDMAEN|SCSIEN) jnz .;
 		bmov	SCB_RESID_DCNT, STCNT, 3;
 		mov	SCB_RESID_SGCNT, SG_COUNT;
 		or	SXFRCTL0, CLRSTCNT|CLRCHN;
@@ -729,10 +616,11 @@
 		test	SSTAT0, SDONE jnz p_command_ultra2_dma_done;
 		test	SSTAT1,PHASEMIS	jz p_command_dma_loop;	/* ie. underrun */
 p_command_ultra2_dma_done:
-		and     DFCNTRL, ~HDMAEN;
-		test	DFCNTRL, HDMAEN jnz .;
-		and	DFCNTRL, ~SCSIEN;
-		test	DFCNTRL, SCSIEN jnz .;
+		test	SCSISIGI, REQI	jz p_command_ultra2_shutdown;
+		test	SSTAT1, PHASEMIS	jz p_command_ultra2_dma_done;
+p_command_ultra2_shutdown:
+		and     DFCNTRL, ~(HDMAEN|SCSIEN);
+		test	DFCNTRL, (HDMAEN|SCSIEN) jnz .;
 		or	SXFRCTL0, CLRSTCNT|CLRCHN;
 	}
 	jmp	ITloop;
@@ -1079,22 +967,12 @@
 	mvi	ARG_1	call inb_next; /* ACK the wide_residue and get */
 				       /* the size byte */
 /*
- * See if we'll ignore this wide residue (because it's an overrun byte)
- */
-	test	SCB_RESID_SGCNT,0xff jnz wide_residue_int;
-	test	SCB_RESID_DCNT[0],0xff jnz wide_residue_int;
-	test	SCB_RESID_DCNT[1],0xff jnz wide_residue_int;
-	test	SCB_RESID_DCNT[2],0xff jnz wide_residue_int;
-	jmp	mesgin_done;
-
-wide_residue_int:
-/*
  * In order for this to be reliable, we have to do all sorts of horrible
  * magic in terms of resetting the datafifo and reloading the shadow layer
  * with the correct new values (so that a subsequent save data pointers
  * message will do the right thing).  We let the kernel do that work.
  */
- 	mvi	INTSTAT,WIDE_RESIDUE;
+ 	mvi	INTSTAT, WIDE_RESIDUE;
 	jmp	mesgin_done;
 	
 /*
@@ -1143,17 +1021,6 @@
 inb_last:
 	mov	NONE,SCSIDATL ret;		/*dummy read from latch to ACK*/
 
-if ((p->flags & AHC_TARGETMODE) != 0) {
-	/*
-	 * Send a byte to an initiator in Automatic PIO mode.
-	 * SPIOEN must be on prior to calling this routine.
-	 */
-target_outb:
-	mov	SCSIDATL, SINDEX;
-	test	SSTAT0, SPIORDY	jz .;
-	ret;
-}
-	
 mesgin_phasemis:
 /*
  * We expected to receive another byte, but the target changed phase
@@ -1198,6 +1065,12 @@
  * actually off first lest we get an ILLSADDR.
  */
 dma_dmadone:
+	cmp	LASTPHASE, P_COMMAND	je dma_await_nreq;
+	test	SCSIRATE, 0x0f	jnz dma_shutdown;
+dma_await_nreq:
+	test	SCSISIGI, REQI	jz dma_shutdown;
+	test	SSTAT1, PHASEMIS	jz dma_await_nreq;
+dma_shutdown:
 	and	DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
 dma_halt:
 	/*
diff -urN linux-2.2.17-pre1/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- linux-2.2.17-pre1/drivers/scsi/aic7xxx.c	Wed May  3 17:16:44 2000
+++ linux/drivers/scsi/aic7xxx.c	Mon Dec  3 22:05:27 2001
@@ -270,7 +270,7 @@
     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-#define AIC7XXX_C_VERSION  "5.1.28"
+#define AIC7XXX_C_VERSION  "5.1.30"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -576,7 +576,7 @@
  * AIC-7770 I/O range to reserve for a card
  */
 #define MINREG                0xC00
-#define MAXREG                0xCBF
+#define MAXREG                0xCFF
 
 #define INTDEF                0x5C      /* Interrupt Definition Register */
 
@@ -1491,10 +1491,10 @@
   {
     outb(val, p->base + port);
     mb(); /* locked operation in order to force ordering */
-    inb(p->base + HCNTRL); /* dummy read to flush the write */
   }
 #else
   outb(val, p->base + port);
+  mb(); /* locked operation in order to force ordering */
 #endif
 }
 
@@ -1664,6 +1664,10 @@
   {
     ;
   }
+  if(p->features & AHC_ULTRA2)
+  {
+    aic_inb(p, CCSCBCTL);
+  }
 }
 
 /*+F*************************************************************************
@@ -2133,7 +2137,7 @@
      * Use async transfers for this target
      */
     *options = 0;
-    *period = 0;
+    *period = 255;
     syncrate = NULL;
   }
   return (syncrate);
@@ -2901,6 +2905,7 @@
 #define WIDE_INQUIRY_BITS 0x60
 #define SYNC_INQUIRY_BITS 0x10
 #define SCSI_VERSION_BITS 0x07
+#define SCSI_DT_BIT       0x04
       if ( (buffer[7] & WIDE_INQUIRY_BITS) &&
            (p->features & AHC_WIDE) )
       {
@@ -2919,61 +2924,66 @@
                                                    AHC_TRANS_CUR) );
         unpause_sequencer(p, FALSE);
       }
-      if (buffer[7] & SYNC_INQUIRY_BITS)
+      if ( (buffer[7] & SYNC_INQUIRY_BITS) &&
+            p->transinfo[tindex].user_offset )
       {
-        p->needsdtr |= (1<<tindex);
-        p->needsdtr_copy |= (1<<tindex);
-
         p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
         p->transinfo[tindex].goal_options = p->transinfo[tindex].user_options;
-        if (p->transinfo[tindex].user_offset)
+        if (p->features & AHC_ULTRA2)
+          p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+        else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
+          p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+        else
+          p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+        if ( (((buffer[2] & SCSI_VERSION_BITS) == 3) ||
+               (buffer[56] & SCSI_DT_BIT) ||
+	       (p->dev_flags[tindex] & DEVICE_SCSI_3) ) &&
+               (p->transinfo[tindex].user_period <= 9) &&
+               (p->transinfo[tindex].user_options) )
         {
-          if (p->features & AHC_ULTRA2)
-            p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
-          else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
-            p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
-          else
-            p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+          p->needppr |= (1<<tindex);
+          p->needppr_copy |= (1<<tindex);
+          p->needsdtr &= ~(1<<tindex);
+          p->needsdtr_copy &= ~(1<<tindex);
+          p->needwdtr &= ~(1<<tindex);
+          p->needwdtr_copy &= ~(1<<tindex);
+          p->dev_flags[tindex] |= DEVICE_SCSI_3;
+        }
+        else
+        {
+          p->needsdtr |= (1<<tindex);
+          p->needsdtr_copy |= (1<<tindex);
+          p->transinfo[tindex].goal_period = 
+            MAX(10, p->transinfo[tindex].goal_period);
+          p->transinfo[tindex].goal_options = 0;
         }
       }
       else
       {
         p->needsdtr &= ~(1<<tindex);
         p->needsdtr_copy &= ~(1<<tindex);
-        p->transinfo[tindex].goal_period = 0;
+        p->transinfo[tindex].goal_period = 255;
         p->transinfo[tindex].goal_offset = 0;
         p->transinfo[tindex].goal_options = 0;
       }
-      if ( (buffer[2] & SCSI_VERSION_BITS) == 3 )
+      /*
+       * This is needed to work around a sequencer bug for now.  Regardless
+       * of the controller in use, if we have a Quantum drive, we need to
+       * limit the speed to 80MByte/sec.  As soon as I get a fixed version
+       * of the sequencer, this code will get yanked.
+       */
+      if(!strncmp(buffer + 8, "QUANTUM", 7) &&
+         p->transinfo[tindex].goal_options )
       {
-        p->dev_flags[tindex] |= DEVICE_SCSI_3;
-        /*
-         * OK, we are a SCSI 3 device and we are in need of negotiation.
-         * Use PPR messages instead of WDTR and SDTR messages.
-         */
-        if ( (p->needsdtr & (1<<tindex)) ||
-             (p->needwdtr & (1<<tindex)) )
-        {
-          p->needppr |= (1<<tindex);
-          p->needppr_copy |= (1<<tindex);
-        }
-        p->needwdtr &= ~(1<<tindex);
-        p->needwdtr_copy &= ~(1<<tindex);
-        p->needsdtr &= ~(1<<tindex);
-        p->needsdtr_copy &= ~(1<<tindex);
-        /*
-         * This is needed to work around a sequencer bug for now.  Regardless
-         * of the controller in use, if we have a Quantum drive, we need to
-         * limit the speed to 80MByte/sec.  As soon as I get a fixed version
-         * of the sequencer, this code will get yanked.
-         */
-        if(!strncmp(buffer + 8, "QUANTUM", 7) &&
-           p->transinfo[tindex].goal_options )
-        {
-          p->transinfo[tindex].goal_period = 
-            MAX(p->transinfo[tindex].goal_period, 10);
-          p->transinfo[tindex].goal_options = 0;
-        }
+        p->transinfo[tindex].goal_period = 
+          MAX(p->transinfo[tindex].goal_period, 10);
+        p->transinfo[tindex].goal_options = 0;
+        p->needppr &= ~(1<<tindex);
+        p->needppr_copy &= ~(1<<tindex);
+        p->needsdtr |= (1<<tindex);
+        p->needsdtr_copy |= (1<<tindex);
+        p->needwdtr |= (1<<tindex);
+        p->needwdtr_copy |= (1<<tindex);
       }
       /*
        * Get the INQUIRY checksum.  We use this on Ultra 160/m
@@ -3003,6 +3013,7 @@
 #undef WIDE_INQUIRY_BITS
 #undef SYNC_INQUIRY_BITS
 #undef SCSI_VERSION_BITS
+#undef SCSI_DT_BIT
     }
   }
   else if ((scb->flags & SCB_MSGOUT_BITS) != 0)
@@ -4639,7 +4650,9 @@
            * As per the draft specs, any device capable of supporting any of
            * the option values other than 0 are not allowed to reject the
            * PPR message.  Instead, they must negotiate out what they do
-           * support instead of rejecting our offering.
+           * support instead of rejecting our offering or else they cause
+           * a parity error during msg_out phase to signal that they don't
+           * like our settings.
            */
           p->needppr &= ~target_mask;
           p->needppr_copy &= ~target_mask;
@@ -4817,51 +4830,6 @@
                 scb->sg_count = hscb->SG_segment_count = 1;
                 scb->sg_length = sizeof(cmd->sense_buffer);
                 scb->tag_action = 0;
-                /*
-                 * This problem could be caused if the target has lost power
-                 * or found some other way to loose the negotiation settings,
-                 * so if needed, we'll re-negotiate while doing the sense cmd.
-                 * However, if this SCB already was attempting to negotiate,
-                 * then we assume this isn't the problem and skip this part.
-                 */
-                if ( (scb->cmd->cmnd[0] != TEST_UNIT_READY) &&
-                     (p->dev_flags[tindex] & DEVICE_SCANNED) &&
-                     !(p->dtr_pending & target_mask) ) 
-                {
-                  p->needppr |= (p->needppr_copy & target_mask);
-                  p->needwdtr |= (p->needwdtr_copy & target_mask);
-                  p->needsdtr |= (p->needsdtr_copy & target_mask);
-                }
-                else if ( scb->cmd == p->dev_dtr_cmnd[tindex] )
-                {
-                  /*
-                   * This is already a negotiation command, so we must have
-                   * already done PPR, WDTR or SDTR.  Since our negotiation
-                   * could have gotten rejected, we don't really know the
-                   * full state of things.  Don't do anything here, and allow
-                   * the negotiation_complete() handler to do the right
-                   * thing.
-                   */
-
-                  /*
-                   * This is the important part though.  We are getting sense
-                   * info back from this device.  It's going into a fake
-                   * command.  We need to put that into the real command
-                   * instead so that the mid level SCSI code can act upon it.
-                   * So, when we set up these fake commands, the next pointer
-                   * is used to point to the real command.  Use that to change
-                   * the address of our sense_buffer[] to the real command.
-                   * However, don't do this if the real command is also a
-                   * TEST_UNIT_READY as it will most likely pull down its own
-                   * SENSE information anyway.
-                   */
-                  if (cmd->next->cmnd[0] != TEST_UNIT_READY)
-                  {
-                    scb->sg_list[0].address = 
-                      cpu_to_le32(VIRT_TO_BUS(&cmd->next->sense_buffer[0]));
-                    hscb->data_pointer = scb->sg_list[0].address;
-                  }
-                }
                 scb->flags |= SCB_SENSE;
                 /*
                  * Ensure the target is busy since this will be an
@@ -4884,7 +4852,7 @@
                 aic7xxx_error(cmd) = DID_OK;
                 break;
               }  /* first time sense, no errors */
-              aic7xxx_error(cmd) = DID_OK;
+              aic7xxx_error(cmd) = DID_ERROR;
               scb->flags &= ~SCB_SENSE;
               break;
 
@@ -5135,51 +5103,14 @@
         }
         else if (scb->flags & SCB_MSGOUT_PPR)
         {
-          unsigned int max_sync, period;
-          unsigned char options = 0;
-
-          if (p->features & AHC_ULTRA2)
-          {
-            if ( (aic_inb(p, SBLKCTL) & ENAB40) &&
-                !(aic_inb(p, SSTAT2) & EXP_ACTIVE) )
-            {
-              if( (p->features & AHC_ULTRA3) &&
-                  (p->dev_flags[tindex] & DEVICE_SCSI_3) &&
-                  (p->transinfo[tindex].goal_width ==
-                   MSG_EXT_WDTR_BUS_16_BIT) &&
-                  (p->transinfo[tindex].goal_options != 0) )
-              {
-                max_sync = AHC_SYNCRATE_ULTRA3;
-                options = p->transinfo[tindex].goal_options;
-              }
-              else
-              {
-                max_sync = AHC_SYNCRATE_ULTRA2;
-              }
-            }
-            else
-            {
-              max_sync = AHC_SYNCRATE_ULTRA;
-            }
-          }
-          else if (p->features & AHC_ULTRA)
-          {
-            max_sync = AHC_SYNCRATE_ULTRA;
-          }
-          else
-          {
-            max_sync = AHC_SYNCRATE_FAST;
-          }
-          period = p->transinfo[tindex].goal_period;
-          aic7xxx_find_syncrate(p, &period, max_sync, &options);
-          p->transinfo[tindex].goal_period = period;
-          p->transinfo[tindex].goal_options = options;
           if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
           {
             printk(INFO_LEAD "Sending PPR (%d/%d/%d/%d) message.\n",
-                   p->host_no, CTL_OF_SCB(scb), period,
+                   p->host_no, CTL_OF_SCB(scb),
+                   p->transinfo[tindex].goal_period,
                    p->transinfo[tindex].goal_offset,
-                   p->transinfo[tindex].goal_width, options);
+                   p->transinfo[tindex].goal_width,
+                   p->transinfo[tindex].goal_options);
           }
           aic7xxx_construct_ppr(p, scb);
         }
@@ -5225,8 +5156,7 @@
           if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
           {
             printk(INFO_LEAD "Sending SDTR %d/%d message.\n", p->host_no,
-                   CTL_OF_SCB(scb),
-                   p->transinfo[tindex].goal_period,
+                   CTL_OF_SCB(scb), period,
                    p->transinfo[tindex].goal_offset);
           }
           aic7xxx_construct_sdtr(p, period,
@@ -5339,7 +5269,7 @@
         resid_sgcnt = aic_inb(p, SCB_RESID_SGCNT);
         resid_dcnt = aic_inb(p, SCB_RESID_DCNT) |
           (aic_inb(p, SCB_RESID_DCNT + 1) << 8) |
-          (aic_inb(p, SCB_RESID_DCNT + 2) << 24);
+          (aic_inb(p, SCB_RESID_DCNT + 2) << 16);
         index = scb->sg_count - (resid_sgcnt + 1);
         native_addr = le32_to_cpu(scb->sg_list[index].address);
         native_length = le32_to_cpu(scb->sg_list[index].length);
@@ -5347,7 +5277,7 @@
          * Make sure this is a valid sg_seg for the given pointer
          */
         if(cur_addr < native_addr ||
-           cur_addr > (native_addr + native_length))
+           cur_addr > (native_addr + native_length + 1))
         {
           printk(WARN_LEAD "invalid cur_addr:0x%x during WIDE_RESIDUE\n",
                  p->host_no, CTL_OF_SCB(scb), cur_addr);
@@ -5364,16 +5294,31 @@
                    p->host_no, CTL_OF_SCB(scb),
                    le32_to_cpu(scb->sg_list[index + 1].address),
                    le32_to_cpu(scb->sg_list[index + 1].length));
+          printk(WARN_LEAD "  cur_address:0x%x resid_dcnt:0x%06x\n",
+                 p->host_no, CTL_OF_SCB(scb),
+                 cur_addr, resid_dcnt);
           break;
         }
 
-        /*
-         * If our current address matches the sg_seg->address then we
-         * have to back up the sg array to the previous segment and set
-         * it up to have only one byte of transfer left to go.
-         */
-        if(cur_addr == native_addr)
+        if( (resid_sgcnt == 0) &&
+            ((resid_dcnt == 0) || (resid_dcnt == 0xffffff)))
         {
+          /*
+           * We are at the end of the transfer and this is about a byte
+           * we ignored already (because the sequencer knew this was
+           * the last segment and set the adapter to ignore any wide
+           * residue bytes that might come through, which is only done
+           * on the last scatter gather segment of transfers).
+           */
+          break;
+        }
+        else if(cur_addr == native_addr)
+        {
+          /*
+           * If our current address matches the sg_seg->address then we
+           * have to back up the sg array to the previous segment and set
+           * it up to have only one byte of transfer left to go.
+           */
           if(index == 0)
           {
             printk(WARN_LEAD "bogus WIDE_RESIDUE message, no data has been "
@@ -5403,39 +5348,6 @@
           aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
           aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
           aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
-          /*
-           * The sequencer actually wants to find the new address and byte
-           * count in the SHCNT and SHADDR register sets.  These registers
-           * are a shadow of the regular HCNT and HADDR registers.  On the
-           * Ultra2 controllers, these registers are read only and the way
-           * we have to set their values is to put the values we want into
-           * the HCNT and HADDR registers and then output PRELOADEN into
-           * the DFCNTRL register which causes the card to latch the current
-           * values in the HADDR and HCNT registers and drop it through to
-           * the shadow registers.  On older cards we copy them directly
-           * across by hand.
-           */
-          if(p->features & AHC_ULTRA2)
-          {
-            aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
-            i=0;
-            udelay(1);
-            while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
-            {
-              aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
-              udelay(1);
-            }
-          }
-          else
-          {
-            aic_outb(p, 1, STCNT); 
-            aic_outb(p, 0, STCNT + 1); 
-            aic_outb(p, 0, STCNT + 2); 
-            aic_outb(p, cur_addr & 0xff, SHADDR);
-            aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1);
-            aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2);
-            aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3);
-          }
         }
         else
         {
@@ -5455,28 +5367,46 @@
           aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
           aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
           aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
-          if(p->features & AHC_ULTRA2)
+        }
+        /*
+         * The sequencer actually wants to find the new address and byte
+         * count in the SHCNT and SHADDR register sets.  These registers
+         * are a shadow of the regular HCNT and HADDR registers.  On the
+         * Ultra2 controllers, these registers are read only and the way
+         * we have to set their values is to put the values we want into
+         * the HCNT and HADDR registers and then output PRELOADEN into
+         * the DFCNTRL register which causes the card to latch the current
+         * values in the HADDR and HCNT registers and drop it through to
+         * the shadow registers.  On older cards we copy them directly
+         * across by hand.
+         */
+        if(p->features & AHC_ULTRA2)
+        {
+          aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+          i=0;
+          udelay(1);
+          while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
           {
-            aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
-            i=0;
             udelay(1);
-            while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
-            {
-              aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
-              udelay(1);
-            }
           }
-          else
+          aic_outb(p, aic_inb(p, DMAPARAMS) & ~(SCSIEN|HDMAEN), DFCNTRL);
+          i=0;
+          udelay(1);
+          while(((aic_inb(p, DFCNTRL) & (SCSIEN|HDMAEN)) != 0) && (i++ < 1000))
           {
-            aic_outb(p, resid_dcnt & 0xff, STCNT); 
-            aic_outb(p, (resid_dcnt >> 8) & 0xff, STCNT + 1); 
-            aic_outb(p, (resid_dcnt >> 16) & 0xff, STCNT + 2); 
-            aic_outb(p, cur_addr & 0xff, SHADDR);
-            aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1);
-            aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2);
-            aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3);
+            udelay(1);
           }
         }
+        else
+        {
+          aic_outb(p, resid_dcnt & 0xff, STCNT); 
+          aic_outb(p, (resid_dcnt >> 8) & 0xff, STCNT + 1); 
+          aic_outb(p, (resid_dcnt >> 16) & 0xff, STCNT + 2); 
+          aic_outb(p, cur_addr & 0xff, SHADDR);
+          aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1);
+          aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2);
+          aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3);
+        }
       }
       break;
 
@@ -5885,6 +5815,7 @@
           reply = TRUE;
           scb->flags &= ~SCB_MSGOUT_BITS;
           scb->flags |= SCB_MSGOUT_PPR;
+	  p->dev_flags[tindex] |= DEVICE_SCSI_3;
           if (!(p->dev_flags[tindex] & DEVICE_SCANNED))
           {
             /*
@@ -5918,7 +5849,6 @@
               p->transinfo[tindex].user_width;
             p->transinfo[tindex].goal_options =
               p->transinfo[tindex].user_options;
-            p->needppr_copy |= target_mask;
           }
           if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
           {
@@ -5952,6 +5882,25 @@
               break;
             }
           }
+          if ( (p->transinfo[tindex].goal_period > 9) ||
+               (p->transinfo[tindex].goal_options == 0) )
+          {
+            scb->flags &= ~SCB_MSGOUT_BITS;
+            reject = TRUE;
+            reply = FALSE;
+            p->needppr &= ~(1 << tindex);
+            p->needppr_copy &= ~(1 << tindex);
+            if ( p->transinfo[tindex].goal_offset )
+            {
+              p->needsdtr |= (1 << tindex);
+              p->needsdtr_copy |= (1 << tindex);
+            }
+            if ( p->transinfo[tindex].goal_width )
+            {
+              p->needwdtr |= (1 << tindex);
+              p->needwdtr_copy |= (1 << tindex);
+            }
+          }
         }
         else
         {
@@ -5959,7 +5908,7 @@
           {
             default:
             {
-              reply = TRUE;
+              reject = TRUE;
               if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
                    ((p->dev_flags[tindex] & DEVICE_PRINT_DTR) ||
                     (aic7xxx_verbose > 0xffff)) )
@@ -5985,27 +5934,18 @@
           }
         }
 
-        aic7xxx_set_width(p, target, channel, lun, bus_width,
-                          AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
-        syncrate = aic7xxx_find_syncrate(p, &period, maxsync,
-                                         &new_trans_options);
-        aic7xxx_validate_offset(p, syncrate, &offset, bus_width);
-        aic7xxx_set_syncrate(p, syncrate, target, channel, period,
-                             offset, new_trans_options,
-                             AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
-
-        if( (offset != saved_offset) ||
-            (trans_options != new_trans_options) ||
-            ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) !=
-             (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) )
+        if ( !reject )
         {
           aic7xxx_set_width(p, target, channel, lun, bus_width,
-                            AHC_TRANS_GOAL|AHC_TRANS_QUITE);
+                            AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+          syncrate = aic7xxx_find_syncrate(p, &period, maxsync,
+                                           &new_trans_options);
+          aic7xxx_validate_offset(p, syncrate, &offset, bus_width);
           aic7xxx_set_syncrate(p, syncrate, target, channel, period,
                                offset, new_trans_options,
-                               AHC_TRANS_GOAL|AHC_TRANS_QUITE);
-          reply = TRUE;
+                               AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
         }
+
         p->dtr_pending &= ~target_mask;
         p->needppr &= ~target_mask;
         if(reply)
@@ -6411,20 +6351,14 @@
     /*
      * Keep the sequencer from trying to restart any selections
      */
-    aic_outb(p, 0, SCSISEQ);
+    aic_outb(p, aic_inb(p, SCSISEQ) & ~ENSELO, SCSISEQ);
     /*
      * Make sure the data bits on the bus are released
+     * Don't do this on 7770 chipsets, it makes them give us
+     * a BRKADDRINT and kills the card.
      */
-    if(p->features & AHC_WIDE)
-      aic_outb(p, 0, SCSIBUSH);
-    aic_outb(p, 0, SCSIBUSL);
-    /*
-     * Clear the target id bit from the SCSI bus
-     */
-    if(p->features & AHC_ULTRA2)
-      aic_outb(p, aic_inb(p, SCSIID_ULTRA2) & 0x0f, SCSIID_ULTRA2);
-    else
-      aic_outb(p, aic_inb(p, SCSIID) & 0x0f, SCSIID);
+    if( (p->chip & ~AHC_CHIPID_MASK) == AHC_PCI )
+      aic_outb(p, 0, SCSIBUSL);
 
     /*
      * Delay for the selection timeout delay period then stop the selection
@@ -6507,7 +6441,9 @@
      * A parity error has occurred during a data
      * transfer phase. Flag it and continue.
      */
-    if( (aic_inb(p, SCSIRATE) & AHC_SYNCRATE_CRC) && (lastphase == P_DATAIN) )
+    if( (p->features & AHC_ULTRA3) && 
+        (aic_inb(p, SCSIRATE) & AHC_SYNCRATE_CRC) &&
+        (lastphase == P_DATAIN) )
     {
       printk(WARN_LEAD "CRC error during %s phase.\n",
              p->host_no, CTL_OF_SCB(scb), phase);
@@ -6532,13 +6468,50 @@
                p->host_no, CTL_OF_SCB(scb));
       }
     }
-    else
+    else if( (lastphase == P_MESGOUT) &&
+             (cmd == p->dev_dtr_cmnd[tindex]) &&
+             (scb->flags & SCB_MSGOUT_PPR) )
     {
-      printk(WARN_LEAD "Parity error during %s phase.\n",
-             p->host_no, CTL_OF_SCB(scb), phase);
+      /*
+       * As per the draft specs, any device capable of supporting any of
+       * the option values other than 0 are not allowed to reject the
+       * PPR message.  Instead, they must negotiate out what they do
+       * support instead of rejecting our offering or else they cause
+       * a parity error during msg_out phase to signal that they don't
+       * like our settings.
+       */
+      p->needppr &= ~(1 << tindex);
+      p->needppr_copy &= ~(1 << tindex);
+      aic7xxx_set_width(p, scb->cmd->target, scb->cmd->channel, scb->cmd->lun,
+                        MSG_EXT_WDTR_BUS_8_BIT,
+                        (AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE));
+      aic7xxx_set_syncrate(p, NULL, scb->cmd->target, scb->cmd->channel, 0, 0,
+                           0, AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE);
+      p->transinfo[tindex].goal_options = 0;
+      p->dtr_pending &= ~(1 << tindex);
+      scb->flags &= ~SCB_MSGOUT_BITS;
+      if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+      {
+        printk(INFO_LEAD "parity error during PPR message, reverting "
+               "to WDTR/SDTR\n", p->host_no, CTL_OF_SCB(scb));
+      }
+      if ( p->transinfo[tindex].goal_width )
+      {
+        p->needwdtr |= (1 << tindex);
+        p->needwdtr_copy |= (1 << tindex);
+      }
+      if ( p->transinfo[tindex].goal_offset )
+      {
+        if( p->transinfo[tindex].goal_period <= 9 )
+        {
+          p->transinfo[tindex].goal_period = 10;
+        }
+        p->needsdtr |= (1 << tindex);
+        p->needsdtr_copy |= (1 << tindex);
+      }
+      scb = NULL;
     }
-
-    if(p->dev_flags[tindex] & DEVICE_PARITY_ERROR)
+    else if(p->dev_flags[tindex] & DEVICE_PARITY_ERROR)
     {
       struct aic7xxx_syncrate *syncrate;
       unsigned int period = p->transinfo[tindex].cur_period;
@@ -6550,6 +6523,8 @@
        * instead of slowing down if those exist.  That's hard to do with simple
        * checksums though.
        */
+      printk(WARN_LEAD "Parity error during %s phase.\n",
+             p->host_no, CTL_OF_SCB(scb), phase);
       if((syncrate = aic7xxx_find_syncrate(p, &period, 0, &options)) != NULL)
       {
         syncrate++;
@@ -6557,20 +6532,59 @@
             (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) )
         {
           p->transinfo[tindex].goal_period = syncrate->period;
-          if( !(syncrate->sxfr_ultra2 & 0x40) )
+          if( p->transinfo[tindex].goal_period > 9 )
           {
             p->transinfo[tindex].goal_options = 0;
+            p->needppr &= ~(1<<tindex);
+            p->needsdtr |= (1<<tindex);
+            p->needppr_copy &= ~(1<<tindex);
+            p->needsdtr_copy |= (1<<tindex);
+            if (p->transinfo[tindex].goal_width)
+            {
+              p->needwdtr |= (1<<tindex);
+              p->needwdtr_copy |= (1<<tindex);
+            }
+          }
+        }
+        else if (p->transinfo[tindex].goal_width)
+        {
+          p->transinfo[tindex].goal_width = 0;
+          p->needwdtr &= ~(1<<tindex);
+          p->needwdtr_copy &= ~(1<<tindex);
+          p->transinfo[tindex].goal_offset =
+            p->transinfo[tindex].user_offset;
+          p->transinfo[tindex].goal_period =
+            p->transinfo[tindex].user_period;
+          p->transinfo[tindex].goal_options =
+            p->transinfo[tindex].user_options;
+          if( p->transinfo[tindex].goal_period <= 9 )
+          {
+            p->needppr |= (1<<tindex);
+            p->needsdtr &= ~(1<<tindex);
+            p->needppr_copy |= (1<<tindex);
+            p->needsdtr_copy &= ~(1<<tindex);
+          }
+          else
+          {
+            p->needppr &= ~(1<<tindex);
+            p->needsdtr |= (1<<tindex);
+            p->needppr_copy &= ~(1<<tindex);
+            p->needsdtr_copy |= (1<<tindex);
           }
         }
         else
         {
           p->transinfo[tindex].goal_offset = 0;
-          p->transinfo[tindex].goal_period = 0;
+          p->transinfo[tindex].goal_period = 255;
           p->transinfo[tindex].goal_options = 0;
+          p->transinfo[tindex].goal_width = 0;
+          p->needppr &= ~(1<<tindex);
+          p->needsdtr &= ~(1<<tindex);
+          p->needwdtr &= ~(1<<tindex);
+          p->needppr_copy &= ~(1<<tindex);
+          p->needsdtr_copy &= ~(1<<tindex);
+          p->needwdtr_copy &= ~(1<<tindex);
         }
-        p->needppr |= (p->needppr_copy & (1<<tindex));
-        p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
-        p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
       }
       p->dev_flags[tindex] &= ~DEVICE_PARITY_ERROR;
     }
@@ -6588,6 +6602,7 @@
     if (mesg_out != MSG_NOOP)
     {
       aic_outb(p, mesg_out, MSG_OUT);
+      aic_outb(p, aic_inb(p, SCSISIGI) | ATNO, SCSISIGO);
       scb = NULL;
     }
     aic_outb(p, CLRSCSIPERR, CLRSINT1);
@@ -6779,7 +6794,7 @@
 {
   struct aic7xxx_scb *scb = NULL;
   Scsi_Cmnd *cmd;
-  unsigned char scb_index;
+  unsigned char scb_index, tindex;
 
 #ifdef AIC7XXX_VERBOSE_DEBUGGING
   if( (p->isr_count < 16) && (aic7xxx_verbose > 0xffff) )
@@ -6805,23 +6820,21 @@
     scb_index = p->qoutfifo[p->qoutfifonext];
     p->qoutfifo[p->qoutfifonext++] = SCB_LIST_NULL;
     if ( scb_index >= p->scb_data->numscbs )
-      scb = NULL;
-    else
-      scb = p->scb_data->scb_array[scb_index];
-    if (scb == NULL)
     {
       printk(WARN_LEAD "CMDCMPLT with invalid SCB index %d\n", p->host_no,
         -1, -1, -1, scb_index);
       continue;
     }
-    else if (!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL))
+    scb = p->scb_data->scb_array[scb_index];
+    if (!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL))
     {
       printk(WARN_LEAD "CMDCMPLT without command for SCB %d, SCB flags "
         "0x%x, cmd 0x%lx\n", p->host_no, -1, -1, -1, scb_index, scb->flags,
         (unsigned long) scb->cmd);
       continue;
     }
-    else if (scb->flags & SCB_QUEUED_ABORT)
+    tindex = TARGET_INDEX(scb->cmd);
+    if (scb->flags & SCB_QUEUED_ABORT)
     {
       pause_sequencer(p);
       if ( ((aic_inb(p, LASTPHASE) & PHASE_MASK) != P_BUSFREE) &&
@@ -6844,6 +6857,43 @@
        */
       scb->flags &= ~(SCB_ABORT|SCB_RESET);
     }
+    else if (scb->flags & SCB_SENSE)
+    {
+      char *buffer = &scb->cmd->sense_buffer[0];
+      if (scb->cmd == p->dev_dtr_cmnd[tindex])
+      {
+        struct aic7xxx_scb *old_scb;
+        /*
+         * We have valid sense data, send it back immediately.
+         */
+        old_scb = p->scb_data->scb_array[scb->cmd->next->tag];
+        *old_scb->cmd->sense_buffer = *scb->cmd->sense_buffer;
+        old_scb->hscb->target_status = scb->hscb->target_status;
+        old_scb->cmd->result = scb->hscb->target_status;
+        old_scb->cmd->result |= (DID_ERROR << 16);
+        aic7xxx_status(old_scb->cmd) = scb->hscb->target_status;
+        scbq_remove(&p->waiting_scbs, old_scb);
+        scbq_remove(&p->delayed_scbs[tindex], old_scb);
+        scb->cmd->next = NULL;
+	aic7xxx_done(p, scb);
+        aic7xxx_done(p, old_scb);
+	continue;
+      } 
+      else if (buffer[12] == 0x47 || buffer[12] == 0x54)
+      {
+        /*
+         * SCSI errors, run domain validation and re-run negotiation
+         */
+        p->needdv |= (1<<tindex);
+        /*
+         * Signal that we need to re-negotiate things, this also gets us our
+         * INQUIRY command to re-checksum off of.
+         */
+        p->needppr |= (p->needppr_copy & (1<<tindex));
+        p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
+        p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
+      }
+    }
     switch (status_byte(scb->hscb->target_status))
     {
       case QUEUE_FULL:
@@ -6973,6 +7023,13 @@
 
   if (intstat & SEQINT)
   {
+    /*
+     * Read the CCSCBCTL register to work around a bug in the Ultra2 cards
+     */
+    if(p->features & AHC_ULTRA2)
+    {
+      aic_inb(p, CCSCBCTL);
+    }
     aic7xxx_handle_seqint(p, intstat);
   }
 
@@ -7055,7 +7112,7 @@
  *   with queue depths for individual devices.  It also allows tagged
  *   queueing to be [en|dis]abled for a specific adapter.
  *-F*************************************************************************/
-static void
+static int
 aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device)
 {
   int default_depth = 3;
@@ -7065,6 +7122,14 @@
   tindex = device->id | (device->channel << 3);
   target_mask = (1 << tindex);
 
+  if (p->dev_max_queue_depth[tindex] > 1)
+  {
+    /*
+     * We've already scanned this device, leave it alone
+     */
+    return(p->dev_max_queue_depth[tindex]);
+  }
+
   device->queue_depth = default_depth;
   p->dev_temp_queue_depth[tindex] = 1;
   p->dev_max_queue_depth[tindex] = 1;
@@ -7133,6 +7198,7 @@
       }
     }
   }
+  return(p->dev_max_queue_depth[tindex]);
 }
 
 /*+F*************************************************************************
@@ -7160,8 +7226,7 @@
   {
     if (device->host == host)
     {
-      aic7xxx_device_queue_depth(p, device);
-      scbnum += device->queue_depth;
+      scbnum += aic7xxx_device_queue_depth(p, device);
     }
   }
   while (scbnum > p->scb_data->numscbs)
@@ -8371,23 +8436,8 @@
   }
   aic_outb(p, 0, SEQ_FLAGS);
 
-  /*
-   * We are starting to do real work on the card....it's possible we could
-   * generate some spurious interrupts at this point, especially in the
-   * event of a PCI error or some such.  If there are other devices already
-   * registered on the same interrupt as us, this could cause the machine
-   * to lock up.  So, we disable the interrupt this card is on until we
-   * finish our card setup.  We only need to do this for modules, if we are
-   * compiled into the kernel then interrupts are already off during this
-   * part of the code.
-   */
-#ifdef MODULE
-  disable_irq(p->irq);
-#endif
-
   detect_maxscb(p);
 
-
   printk("%d/%d SCBs\n", p->scb_data->maxhscbs, p->scb_data->maxscbs);
   if (aic7xxx_verbose & VERBOSE_PROBE2)
   {
@@ -8616,9 +8666,6 @@
       printk("(scsi%d) Unable to allocate hardware SCB array; "
              "failing detection.\n", p->host_no);
       aic_outb(p, 0, SIMODE1);
-#ifdef MODULE
-      enable_irq(p->irq);
-#endif
       p->irq = 0;
       return(0);
     }
@@ -8796,9 +8843,6 @@
     printk(KERN_WARNING "(scsi%d) Couldn't register IRQ %d, ignoring "
            "controller.\n", p->host_no, p->irq);
     aic_outb(p, 0, SIMODE1);
-#ifdef MODULE
-    enable_irq(p->irq);
-#endif
     p->irq = 0;
     return (0);
   }
@@ -8808,10 +8852,6 @@
       p->host_no, -1, -1 , -1);
   aic7xxx_clear_intstat(p);
 
-#ifdef MODULE
-  enable_irq(p->irq);
-#endif
-
   unpause_sequencer(p, /* unpause_always */ TRUE);
 
   return (found);
@@ -8920,7 +8960,7 @@
     p->orderedtag = 0;
     for (i=0; i<MAX_TARGETS; i++)
     {
-      p->transinfo[i].goal_period = 0;
+      p->transinfo[i].goal_period = 255;
       p->transinfo[i].goal_offset = 0;
       p->transinfo[i].goal_options = 0;
       p->transinfo[i].goal_width = MSG_EXT_WDTR_BUS_8_BIT;
@@ -9709,7 +9749,8 @@
           {
             if ( ((current_p->pci_bus == temp_p->pci_bus) &&
                   (current_p->pci_device_fn == temp_p->pci_device_fn)) ||
-                  (current_p->base == temp_p->base) )
+                 (temp_p->base && (current_p->base == temp_p->base)) ||
+                 (temp_p->mbase && (current_p->mbase == temp_p->mbase)) )
             {
               /* duplicate PCI entry, skip it */
               kfree(temp_p);
@@ -9769,7 +9810,8 @@
           {
             if ( ((current_p->pci_bus == temp_p->pci_bus) &&
                   (current_p->pci_device_fn == temp_p->pci_device_fn)) ||
-                  (current_p->base == temp_p->base) )
+                 (temp_p->base && (current_p->base == temp_p->base)) ||
+                 (temp_p->mbase && (current_p->mbase == temp_p->mbase)) )
             {
               /* duplicate PCI entry, skip it */
               kfree(temp_p);
@@ -9812,7 +9854,7 @@
 #endif /* AIC7XXX_STRICT_PCI_SETUP */
 #endif /* LINUIX_VERSION_CODE > KERNEL_VERSION(2,1,92) */
 
-          if(check_region(temp_p->base, MAXREG - MINREG))
+          if(temp_p->base && check_region(temp_p->base, MAXREG - MINREG))
           {
             printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
               board_names[aic_pdevs[i].board_name_index],
@@ -9843,7 +9885,7 @@
           }
 
 #ifdef MMAPIO
-          if ( !(temp_p->flags & AHC_MULTI_CHANNEL) ||
+          if ( !(temp_p->base) || !(temp_p->flags & AHC_MULTI_CHANNEL) ||
                ((temp_p->chip != (AHC_AIC7870 | AHC_PCI)) &&
                 (temp_p->chip != (AHC_AIC7880 | AHC_PCI))) )
           {
@@ -9881,6 +9923,18 @@
                 vfree((void *) (((unsigned long) temp_p->maddr) & PAGE_MASK));
 #endif
                 temp_p->maddr = 0;
+                if(temp_p->base == 0)
+                {
+                  printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
+                    board_names[aic_pdevs[i].board_name_index],
+                    temp_p->pci_bus,
+                    PCI_SLOT(temp_p->pci_device_fn),
+                    PCI_FUNC(temp_p->pci_device_fn));
+                  printk("aic7xxx: Controller disabled by BIOS, ignoring.\n");
+                  kfree(temp_p);
+                  temp_p = NULL;
+                  continue;
+                }
               }
             }
           }
@@ -9889,7 +9943,8 @@
           /*
            * Lock out other contenders for our i/o space.
            */
-          request_region(temp_p->base, MAXREG - MINREG, "aic7xxx");
+          if(temp_p->base)
+            request_region(temp_p->base, MAXREG - MINREG, "aic7xxx");
 
           /*
            * We HAVE to make sure the first pause_sequencer() and all other
@@ -10801,20 +10856,59 @@
               (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) )
           {
             p->transinfo[tindex].goal_period = syncrate->period;
-            if( !(syncrate->sxfr_ultra2 & 0x40) )
+            if( p->transinfo[tindex].goal_period > 9 )
             {
               p->transinfo[tindex].goal_options = 0;
+              p->needppr &= ~(1<<tindex);
+              p->needsdtr |= (1<<tindex);
+              p->needppr_copy &= ~(1<<tindex);
+              p->needsdtr_copy |= (1<<tindex);
+              if (p->transinfo[tindex].goal_width)
+              {
+                p->needwdtr |= (1<<tindex);
+                p->needwdtr_copy |= (1<<tindex);
+              }
+            }
+          }
+          else if (p->transinfo[tindex].goal_width)
+          {
+            p->transinfo[tindex].goal_width = 0;
+            p->needwdtr &= ~(1<<tindex);
+            p->needwdtr_copy &= ~(1<<tindex);
+            p->transinfo[tindex].goal_offset =
+              p->transinfo[tindex].user_offset;
+            p->transinfo[tindex].goal_period =
+              p->transinfo[tindex].user_period;
+            p->transinfo[tindex].goal_options =
+              p->transinfo[tindex].user_options;
+            if( p->transinfo[tindex].goal_period <= 9 )
+            {
+              p->needppr |= (1<<tindex);
+              p->needsdtr &= ~(1<<tindex);
+              p->needppr_copy |= (1<<tindex);
+              p->needsdtr_copy &= ~(1<<tindex);
+            }
+            else
+            {
+              p->needppr &= ~(1<<tindex);
+              p->needsdtr |= (1<<tindex);
+              p->needppr_copy &= ~(1<<tindex);
+              p->needsdtr_copy |= (1<<tindex);
             }
           }
           else
           {
             p->transinfo[tindex].goal_offset = 0;
-            p->transinfo[tindex].goal_period = 0;
+            p->transinfo[tindex].goal_period = 255;
             p->transinfo[tindex].goal_options = 0;
+            p->transinfo[tindex].goal_width = 0;
+            p->needppr &= ~(1<<tindex);
+            p->needsdtr &= ~(1<<tindex);
+            p->needwdtr &= ~(1<<tindex);
+            p->needppr_copy &= ~(1<<tindex);
+            p->needsdtr_copy &= ~(1<<tindex);
+            p->needwdtr_copy &= ~(1<<tindex);
           }
-          p->needppr |= (p->needppr_copy & (1<<tindex));
-          p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
-          p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
         }
         p->needdv &= ~(1<<tindex);
       }
@@ -10865,8 +10959,16 @@
    * and we didn't follow up with SDTR yet, then this will get it started.
    * For all other cases, this should work out to be a no-op, unless we are
    * doing domain validation and happen to need a new negotiation command.
+   *
+   * In case we don't want this to go any further, the cmdcmplt interrupt
+   * handler will NULL out the cmd->next entry so that the real SCSI command
+   * can be sent back to the mid layer code with SENSE data intact.  We'll
+   * finish things up when the cmd gets sent back down to us, so no worries.
    */
-  aic7xxx_build_negotiation_cmnd(p, cmd->next, tindex);
+  if(cmd->next)
+  {
+    aic7xxx_build_negotiation_cmnd(p, cmd->next, tindex);
+  }
   return;
 }
 
@@ -10988,13 +11090,13 @@
    */
   hscb->control = 0;
   scb->tag_action = 0;
+  cmd->tag = hscb->tag;
   if (p->discenable & mask)
   {
     hscb->control |= DISCENB;
     if ( (p->tagenable & mask) &&
          (cmd->cmnd[0] != TEST_UNIT_READY) )
     {
-      cmd->tag = hscb->tag;
       p->dev_commands_sent[tindex]++;
       if (p->dev_commands_sent[tindex] < 200)
       {
@@ -12275,7 +12377,8 @@
 
   if(p->irq)
     free_irq(p->irq, p);
-  release_region(p->base, MAXREG - MINREG);
+  if(p->base)
+    release_region(p->base, MAXREG - MINREG);
 #ifdef MMAPIO
   if(p->maddr)
   {
diff -urN linux-2.2.17-pre1/drivers/scsi/aic7xxx_seq.c linux/drivers/scsi/aic7xxx_seq.c
--- linux-2.2.17-pre1/drivers/scsi/aic7xxx_seq.c	Wed May  3 17:16:44 2000
+++ linux/drivers/scsi/aic7xxx_seq.c	Mon Dec  3 22:05:27 2001
@@ -4,34 +4,33 @@
 static unsigned char seqprog[] = {
 	0xff, 0x6a, 0x06, 0x08,
 	0x7f, 0x02, 0x04, 0x08,
-	0x32, 0x6a, 0x00, 0x00,
 	0x12, 0x6a, 0x00, 0x00,
 	0xff, 0x6a, 0xd6, 0x09,
 	0xff, 0x6a, 0xdc, 0x09,
-	0x00, 0x65, 0x44, 0x59,
+	0x00, 0x65, 0xca, 0x58,
 	0xf7, 0x01, 0x02, 0x08,
 	0xff, 0x4e, 0xc8, 0x08,
 	0xbf, 0x60, 0xc0, 0x08,
-	0x60, 0x0b, 0x88, 0x68,
-	0x40, 0x00, 0x0e, 0x68,
+	0x60, 0x0b, 0x86, 0x68,
+	0x40, 0x00, 0x0c, 0x68,
 	0x08, 0x1f, 0x3e, 0x10,
-	0x60, 0x0b, 0x88, 0x68,
-	0x40, 0x00, 0x0e, 0x68,
+	0x60, 0x0b, 0x86, 0x68,
+	0x40, 0x00, 0x0c, 0x68,
 	0x08, 0x1f, 0x3e, 0x10,
-	0xff, 0x3e, 0x4a, 0x60,
-	0x40, 0xfa, 0x12, 0x78,
+	0xff, 0x3e, 0x48, 0x60,
+	0x40, 0xfa, 0x10, 0x78,
 	0xff, 0xf6, 0xd4, 0x08,
 	0x01, 0x4e, 0x9c, 0x18,
 	0x40, 0x60, 0xc0, 0x00,
-	0x00, 0x4d, 0x12, 0x70,
+	0x00, 0x4d, 0x10, 0x70,
 	0x01, 0x4e, 0x9c, 0x18,
 	0xbf, 0x60, 0xc0, 0x08,
-	0x00, 0x6a, 0xbe, 0x5c,
+	0x00, 0x6a, 0x3e, 0x5c,
 	0xff, 0x4e, 0xc8, 0x18,
-	0x02, 0x6a, 0xd4, 0x5b,
+	0x02, 0x6a, 0x54, 0x5b,
 	0xff, 0x52, 0x20, 0x09,
 	0x0d, 0x6a, 0x6a, 0x00,
-	0x00, 0x52, 0x4a, 0x5c,
+	0x00, 0x52, 0xca, 0x5b,
 	0x03, 0xb0, 0x52, 0x31,
 	0xff, 0xb0, 0x52, 0x09,
 	0xff, 0xb1, 0x54, 0x09,
@@ -40,8 +39,8 @@
 	0xff, 0x3e, 0x74, 0x09,
 	0xff, 0x90, 0x7c, 0x08,
 	0xff, 0x3e, 0x20, 0x09,
-	0x00, 0x65, 0x50, 0x58,
-	0x00, 0x65, 0x0e, 0x40,
+	0x00, 0x65, 0x4e, 0x58,
+	0x00, 0x65, 0x0c, 0x40,
 	0xf7, 0x1f, 0xca, 0x08,
 	0x08, 0xa1, 0xc8, 0x08,
 	0x00, 0x65, 0xca, 0x00,
@@ -56,88 +55,28 @@
 	0x5a, 0x6a, 0x00, 0x04,
 	0x12, 0x65, 0x02, 0x00,
 	0x31, 0x6a, 0xca, 0x00,
-	0x80, 0x37, 0x70, 0x68,
+	0x80, 0x37, 0x6e, 0x68,
 	0xff, 0x65, 0xca, 0x18,
 	0xff, 0x37, 0xdc, 0x08,
 	0xff, 0x6e, 0xc8, 0x08,
-	0x00, 0x6c, 0x78, 0x78,
+	0x00, 0x6c, 0x76, 0x78,
 	0x20, 0x01, 0x02, 0x00,
 	0x4c, 0x37, 0xc8, 0x28,
-	0x08, 0x1f, 0x80, 0x78,
+	0x08, 0x1f, 0x7e, 0x78,
 	0x08, 0x37, 0x6e, 0x00,
 	0x08, 0x64, 0xc8, 0x00,
 	0x70, 0x64, 0xca, 0x18,
 	0xff, 0x6c, 0x0a, 0x08,
 	0x20, 0x64, 0xca, 0x18,
 	0xff, 0x6c, 0x08, 0x0c,
-	0x40, 0x0b, 0x10, 0x69,
-	0x80, 0x0b, 0x02, 0x79,
-	0xa4, 0x6a, 0x06, 0x00,
-	0x40, 0x6a, 0x16, 0x00,
-	0x10, 0x03, 0xfe, 0x78,
-	0xff, 0x50, 0xc8, 0x08,
-	0x88, 0x6a, 0xcc, 0x00,
-	0x49, 0x6a, 0x3a, 0x5c,
-	0x01, 0x6a, 0x26, 0x01,
-	0xff, 0x6a, 0xca, 0x08,
-	0x08, 0x01, 0x02, 0x00,
-	0x02, 0x0b, 0x9e, 0x78,
-	0xf7, 0x01, 0x02, 0x08,
-	0xff, 0x06, 0xcc, 0x08,
-	0xff, 0x66, 0x32, 0x09,
-	0x01, 0x65, 0xca, 0x18,
-	0x80, 0x66, 0xac, 0x78,
-	0xff, 0x66, 0xa2, 0x08,
-	0x10, 0x03, 0x9c, 0x68,
-	0xfc, 0x65, 0xc8, 0x18,
-	0x00, 0x65, 0xb4, 0x48,
-	0xff, 0x6a, 0x32, 0x01,
-	0x01, 0x64, 0x18, 0x19,
-	0xff, 0x6a, 0x1a, 0x09,
-	0xff, 0x6a, 0x1c, 0x09,
-	0x84, 0x6a, 0x06, 0x00,
-	0x08, 0x01, 0x02, 0x00,
-	0x02, 0x0b, 0xbe, 0x78,
-	0xff, 0x06, 0xc8, 0x08,
-	0xff, 0x64, 0x32, 0x09,
-	0xff, 0x6a, 0xca, 0x08,
-	0x5b, 0x64, 0xc8, 0x28,
-	0x00, 0x62, 0xc4, 0x18,
-	0xfc, 0x65, 0xca, 0x18,
-	0xff, 0x6a, 0xd4, 0x08,
-	0xfa, 0x65, 0xca, 0x18,
-	0xff, 0x6a, 0xd4, 0x08,
-	0x04, 0x65, 0xca, 0x18,
-	0x0b, 0x65, 0xca, 0x18,
-	0xff, 0x65, 0xc8, 0x08,
-	0x00, 0x8c, 0x18, 0x19,
-	0x02, 0x0b, 0xda, 0x78,
-	0x01, 0x65, 0xe0, 0x60,
-	0xf7, 0x01, 0x02, 0x08,
-	0xff, 0x06, 0x32, 0x09,
-	0xff, 0x65, 0xca, 0x18,
-	0xff, 0x65, 0xda, 0x68,
-	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xb0, 0x5c,
-	0x40, 0x51, 0xf2, 0x78,
-	0xe4, 0x6a, 0x06, 0x00,
-	0x08, 0x01, 0x02, 0x00,
-	0x04, 0x6a, 0x6c, 0x5b,
-	0x01, 0x50, 0xa0, 0x18,
-	0x00, 0x50, 0xf8, 0xe0,
-	0xff, 0x6a, 0xa0, 0x08,
-	0xff, 0x6a, 0x3a, 0x01,
-	0x02, 0x6a, 0x22, 0x01,
-	0x40, 0x51, 0xfe, 0x68,
-	0xff, 0x6a, 0x06, 0x08,
-	0x00, 0x65, 0x0e, 0x40,
+	0x40, 0x0b, 0x96, 0x68,
 	0x20, 0x6a, 0x16, 0x00,
 	0xf0, 0x19, 0x6e, 0x08,
 	0x08, 0x6a, 0x18, 0x00,
 	0x08, 0x11, 0x22, 0x00,
-	0x08, 0x6a, 0x68, 0x58,
+	0x08, 0x6a, 0x66, 0x58,
 	0x08, 0x6a, 0x68, 0x00,
-	0x00, 0x65, 0x24, 0x41,
+	0x00, 0x65, 0xaa, 0x40,
 	0x12, 0x6a, 0x00, 0x00,
 	0x40, 0x6a, 0x16, 0x00,
 	0xff, 0x3e, 0x20, 0x09,
@@ -145,24 +84,24 @@
 	0xff, 0xa1, 0x6e, 0x08,
 	0x08, 0x6a, 0x18, 0x00,
 	0x08, 0x11, 0x22, 0x00,
-	0x08, 0x6a, 0x68, 0x58,
+	0x08, 0x6a, 0x66, 0x58,
 	0x80, 0x6a, 0x68, 0x00,
 	0x80, 0x36, 0x6c, 0x00,
-	0x00, 0x65, 0x1e, 0x5c,
+	0x00, 0x65, 0x9e, 0x5b,
 	0xff, 0x3d, 0xc8, 0x08,
-	0xbf, 0x64, 0x5c, 0x79,
-	0x80, 0x64, 0x24, 0x72,
-	0xa0, 0x64, 0x54, 0x72,
-	0xc0, 0x64, 0x4c, 0x72,
-	0xe0, 0x64, 0x94, 0x72,
+	0xbf, 0x64, 0xe2, 0x78,
+	0x80, 0x64, 0xac, 0x71,
+	0xa0, 0x64, 0xdc, 0x71,
+	0xc0, 0x64, 0xd4, 0x71,
+	0xe0, 0x64, 0x1c, 0x72,
 	0x01, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x24, 0x41,
+	0x00, 0x65, 0xaa, 0x40,
 	0xf7, 0x11, 0x22, 0x08,
-	0x00, 0x65, 0x44, 0x59,
+	0x00, 0x65, 0xca, 0x58,
 	0xff, 0x06, 0xd4, 0x08,
 	0xf7, 0x01, 0x02, 0x08,
-	0x09, 0x0c, 0x3e, 0x79,
-	0x08, 0x0c, 0x0e, 0x68,
+	0x09, 0x0c, 0xc4, 0x78,
+	0x08, 0x0c, 0x0c, 0x68,
 	0x01, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0x26, 0x09,
 	0x02, 0x6a, 0x08, 0x30,
@@ -174,25 +113,25 @@
 	0x03, 0xa9, 0x18, 0x31,
 	0x03, 0xa9, 0x10, 0x30,
 	0x08, 0x6a, 0xcc, 0x00,
-	0xa9, 0x6a, 0x34, 0x5c,
-	0x00, 0x65, 0x7c, 0x41,
+	0xa9, 0x6a, 0xb4, 0x5b,
+	0x00, 0x65, 0x02, 0x41,
 	0xa8, 0x6a, 0x6a, 0x00,
 	0x79, 0x6a, 0x6a, 0x00,
-	0x40, 0x3d, 0x64, 0x69,
+	0x40, 0x3d, 0xea, 0x68,
 	0x04, 0x35, 0x6a, 0x00,
-	0x00, 0x65, 0x8e, 0x5b,
+	0x00, 0x65, 0x0e, 0x5b,
 	0x80, 0x6a, 0xd4, 0x01,
-	0x10, 0x36, 0x50, 0x69,
+	0x10, 0x36, 0xd6, 0x68,
 	0x10, 0x36, 0x6c, 0x00,
 	0x07, 0xac, 0x10, 0x31,
 	0x03, 0x8c, 0x10, 0x30,
 	0x05, 0xa3, 0x70, 0x30,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xac, 0x6a, 0x2c, 0x5c,
-	0x00, 0x65, 0x26, 0x5c,
+	0xac, 0x6a, 0xac, 0x5b,
+	0x00, 0x65, 0xa6, 0x5b,
 	0x38, 0x6a, 0xcc, 0x00,
-	0xa3, 0x6a, 0x30, 0x5c,
-	0xff, 0x38, 0x8c, 0x69,
+	0xa3, 0x6a, 0xb0, 0x5b,
+	0xff, 0x38, 0x12, 0x69,
 	0x80, 0x02, 0x04, 0x00,
 	0xe7, 0x35, 0x6a, 0x08,
 	0x03, 0x69, 0x18, 0x31,
@@ -200,337 +139,334 @@
 	0xff, 0x6a, 0x10, 0x00,
 	0xff, 0x6a, 0x12, 0x00,
 	0xff, 0x6a, 0x14, 0x00,
-	0x01, 0x38, 0x92, 0x61,
+	0x01, 0x38, 0x18, 0x61,
 	0xbf, 0x35, 0x6a, 0x08,
 	0x02, 0x6a, 0xf8, 0x01,
 	0xff, 0x69, 0xca, 0x08,
 	0xff, 0x35, 0x26, 0x09,
-	0x04, 0x0b, 0x96, 0x69,
-	0x04, 0x0b, 0xa2, 0x69,
-	0x10, 0x0c, 0x98, 0x79,
-	0x04, 0x0b, 0xa2, 0x69,
+	0x04, 0x0b, 0x1c, 0x69,
+	0x04, 0x0b, 0x28, 0x69,
+	0x10, 0x0c, 0x1e, 0x79,
+	0x04, 0x0b, 0x28, 0x69,
 	0xff, 0x6a, 0xca, 0x08,
-	0x00, 0x35, 0x76, 0x5b,
-	0x80, 0x02, 0xf6, 0x69,
-	0xff, 0x65, 0xe6, 0x79,
+	0x00, 0x35, 0xee, 0x5a,
+	0x80, 0x02, 0x7c, 0x69,
+	0xff, 0x65, 0x6c, 0x79,
 	0xff, 0x38, 0x70, 0x18,
-	0xff, 0x38, 0xe6, 0x79,
-	0x80, 0xea, 0xc2, 0x61,
+	0xff, 0x38, 0x6c, 0x79,
+	0x80, 0xea, 0x48, 0x61,
 	0xef, 0x38, 0xc8, 0x18,
 	0x80, 0x6a, 0xc8, 0x00,
-	0x00, 0x65, 0xb4, 0x49,
+	0x00, 0x65, 0x3a, 0x49,
 	0x33, 0x38, 0xc8, 0x28,
 	0xff, 0x64, 0xd0, 0x09,
 	0x04, 0x39, 0xc0, 0x31,
 	0x09, 0x6a, 0xd6, 0x01,
-	0x80, 0xeb, 0xba, 0x79,
+	0x80, 0xeb, 0x40, 0x79,
 	0xf7, 0xeb, 0xd6, 0x09,
-	0x08, 0xeb, 0xbe, 0x69,
+	0x08, 0xeb, 0x44, 0x69,
 	0x01, 0x6a, 0xd6, 0x01,
 	0x08, 0xe9, 0x10, 0x31,
 	0x03, 0x8c, 0x10, 0x30,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x39, 0x6a, 0x32, 0x5c,
+	0x39, 0x6a, 0xb2, 0x5b,
 	0x08, 0x6a, 0x18, 0x01,
 	0xff, 0x6a, 0x1a, 0x09,
 	0xff, 0x6a, 0x1c, 0x09,
 	0x0d, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xb0, 0x5c,
-	0x88, 0x6a, 0xa0, 0x5c,
-	0x00, 0x65, 0x26, 0x5c,
+	0x00, 0x65, 0x30, 0x5c,
+	0x88, 0x6a, 0x20, 0x5c,
+	0x00, 0x65, 0xa6, 0x5b,
 	0xff, 0x6a, 0xc8, 0x08,
 	0x08, 0x39, 0x72, 0x18,
 	0x00, 0x3a, 0x74, 0x20,
-	0x01, 0x0c, 0xde, 0x79,
-	0x10, 0x0c, 0x7c, 0x79,
+	0x01, 0x0c, 0x64, 0x79,
+	0x10, 0x0c, 0x02, 0x79,
 	0xff, 0x35, 0x26, 0x09,
-	0x04, 0x0b, 0xe4, 0x69,
-	0x00, 0x65, 0xfe, 0x59,
+	0x04, 0x0b, 0x6a, 0x69,
+	0x00, 0x65, 0x84, 0x59,
 	0x03, 0x08, 0x52, 0x31,
 	0xff, 0x38, 0x50, 0x09,
 	0xff, 0x08, 0x52, 0x09,
 	0xff, 0x09, 0x54, 0x09,
 	0xff, 0x0a, 0x56, 0x09,
 	0xff, 0x38, 0x50, 0x09,
-	0x00, 0x65, 0x24, 0x41,
-	0x00, 0x65, 0xfe, 0x59,
+	0x00, 0x65, 0xaa, 0x40,
+	0x00, 0x65, 0x84, 0x59,
 	0x7f, 0x02, 0x04, 0x08,
 	0xe1, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x24, 0x41,
-	0x04, 0x93, 0x14, 0x6a,
+	0x00, 0x65, 0xaa, 0x40,
+	0x04, 0x93, 0x9a, 0x69,
 	0xdf, 0x93, 0x26, 0x09,
-	0x20, 0x93, 0x02, 0x6a,
+	0x20, 0x93, 0x88, 0x69,
 	0x02, 0x93, 0x26, 0x01,
-	0x01, 0x94, 0x04, 0x7a,
-	0x01, 0x94, 0x04, 0x7a,
-	0x01, 0x94, 0x04, 0x7a,
-	0x01, 0x94, 0x04, 0x7a,
-	0x01, 0x94, 0x04, 0x7a,
-	0x01, 0x94, 0x04, 0x7a,
-	0x10, 0x94, 0x12, 0x6a,
-	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0x16, 0x6a,
-	0xdf, 0x93, 0x26, 0x09,
-	0x20, 0x93, 0x1a, 0x6a,
+	0x01, 0x94, 0x8a, 0x79,
+	0x01, 0x94, 0x8a, 0x79,
+	0x01, 0x94, 0x8a, 0x79,
+	0x01, 0x94, 0x8a, 0x79,
+	0x01, 0x94, 0x8a, 0x79,
+	0x01, 0x94, 0x8a, 0x79,
+	0x10, 0x94, 0x98, 0x69,
+	0x7f, 0x05, 0xa0, 0x69,
+	0x02, 0x03, 0xa0, 0x79,
+	0x10, 0x0c, 0x9c, 0x79,
+	0xd7, 0x93, 0x26, 0x09,
+	0x28, 0x93, 0xa2, 0x69,
 	0x03, 0x08, 0x52, 0x31,
 	0xff, 0x38, 0x50, 0x09,
 	0x12, 0x01, 0x02, 0x00,
 	0xff, 0x6a, 0xd4, 0x0c,
-	0x00, 0x65, 0x8e, 0x5b,
+	0x00, 0x65, 0x0e, 0x5b,
 	0x05, 0xb4, 0x10, 0x31,
 	0x02, 0x6a, 0x1a, 0x31,
 	0x03, 0x8c, 0x10, 0x30,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xb4, 0x6a, 0x30, 0x5c,
+	0xb4, 0x6a, 0xb0, 0x5b,
 	0xff, 0x6a, 0x1a, 0x09,
 	0xff, 0x6a, 0x1c, 0x09,
-	0x00, 0x65, 0x26, 0x5c,
-	0x3d, 0x6a, 0x76, 0x5b,
+	0x00, 0x65, 0xa6, 0x5b,
+	0x3d, 0x6a, 0xee, 0x5a,
 	0xac, 0x6a, 0x26, 0x01,
-	0x04, 0x0b, 0x3a, 0x6a,
-	0x04, 0x0b, 0x40, 0x6a,
-	0x10, 0x0c, 0x3c, 0x7a,
-	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0x42, 0x6a,
-	0xdf, 0x93, 0x26, 0x09,
-	0x20, 0x93, 0x46, 0x6a,
+	0x04, 0x0b, 0xc2, 0x69,
+	0x04, 0x0b, 0xc8, 0x69,
+	0x10, 0x0c, 0xc4, 0x79,
+	0x02, 0x03, 0xcc, 0x79,
+	0x10, 0x0c, 0xc8, 0x79,
+	0xd7, 0x93, 0x26, 0x09,
+	0x28, 0x93, 0xce, 0x69,
 	0x12, 0x01, 0x02, 0x00,
-	0x00, 0x65, 0x24, 0x41,
-	0x00, 0x65, 0x8e, 0x5b,
+	0x00, 0x65, 0xaa, 0x40,
+	0x00, 0x65, 0x0e, 0x5b,
 	0xff, 0x06, 0x44, 0x09,
-	0x00, 0x65, 0x24, 0x41,
+	0x00, 0x65, 0xaa, 0x40,
 	0x10, 0x3d, 0x06, 0x00,
 	0xff, 0x34, 0xca, 0x08,
-	0x80, 0x65, 0x78, 0x62,
+	0x80, 0x65, 0x00, 0x62,
 	0x0f, 0xa1, 0xca, 0x08,
 	0x07, 0xa1, 0xca, 0x08,
 	0x40, 0xa0, 0xc8, 0x08,
 	0x00, 0x65, 0xca, 0x00,
 	0x80, 0x65, 0xca, 0x00,
-	0x80, 0xa0, 0x68, 0x7a,
+	0x80, 0xa0, 0xf0, 0x79,
 	0xff, 0x65, 0x0c, 0x08,
-	0x00, 0x65, 0x7a, 0x42,
-	0x20, 0xa0, 0x80, 0x7a,
+	0x00, 0x65, 0x02, 0x42,
+	0x20, 0xa0, 0x08, 0x7a,
 	0xff, 0x65, 0x0c, 0x08,
-	0x00, 0x65, 0x1e, 0x5c,
-	0xa0, 0x3d, 0x88, 0x62,
+	0x00, 0x65, 0x9e, 0x5b,
+	0xa0, 0x3d, 0x10, 0x62,
 	0x23, 0xa0, 0x0c, 0x08,
-	0x00, 0x65, 0x1e, 0x5c,
-	0xa0, 0x3d, 0x88, 0x62,
-	0x00, 0xb9, 0x80, 0x42,
-	0xff, 0x65, 0x80, 0x62,
+	0x00, 0x65, 0x9e, 0x5b,
+	0xa0, 0x3d, 0x10, 0x62,
+	0x00, 0xb9, 0x08, 0x42,
+	0xff, 0x65, 0x08, 0x62,
 	0xa1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
-	0x10, 0x51, 0x88, 0x72,
+	0x10, 0x51, 0x10, 0x72,
 	0x40, 0x6a, 0x18, 0x00,
 	0xff, 0x65, 0x0c, 0x08,
-	0x00, 0x65, 0x1e, 0x5c,
-	0xa0, 0x3d, 0x52, 0x72,
+	0x00, 0x65, 0x9e, 0x5b,
+	0xa0, 0x3d, 0xda, 0x71,
 	0x40, 0x6a, 0x18, 0x00,
 	0xff, 0x34, 0xa6, 0x08,
-	0x80, 0x34, 0x90, 0x62,
+	0x80, 0x34, 0x18, 0x62,
 	0x7f, 0xa0, 0x40, 0x09,
 	0x08, 0x6a, 0x68, 0x00,
-	0x00, 0x65, 0x24, 0x41,
-	0x64, 0x6a, 0x66, 0x5b,
-	0x80, 0x64, 0x06, 0x6b,
-	0x04, 0x64, 0xe8, 0x72,
-	0x02, 0x64, 0xee, 0x72,
-	0x00, 0x6a, 0xb0, 0x72,
-	0x03, 0x64, 0x02, 0x73,
-	0x01, 0x64, 0xe4, 0x72,
-	0x07, 0x64, 0x44, 0x73,
-	0x08, 0x64, 0xac, 0x72,
-	0x23, 0x64, 0x48, 0x73,
+	0x00, 0x65, 0xaa, 0x40,
+	0x64, 0x6a, 0xe4, 0x5a,
+	0x80, 0x64, 0x8e, 0x6a,
+	0x04, 0x64, 0x70, 0x72,
+	0x02, 0x64, 0x76, 0x72,
+	0x00, 0x6a, 0x38, 0x72,
+	0x03, 0x64, 0x8a, 0x72,
+	0x01, 0x64, 0x6c, 0x72,
+	0x07, 0x64, 0xcc, 0x72,
+	0x08, 0x64, 0x34, 0x72,
+	0x23, 0x64, 0xd0, 0x72,
 	0x11, 0x6a, 0x22, 0x01,
-	0x07, 0x6a, 0x58, 0x5b,
+	0x07, 0x6a, 0xd6, 0x5a,
 	0xff, 0x06, 0xd4, 0x08,
-	0x00, 0x65, 0x24, 0x41,
-	0xff, 0xa8, 0xb4, 0x6a,
-	0xff, 0xa2, 0xcc, 0x7a,
+	0x00, 0x65, 0xaa, 0x40,
+	0xff, 0xa8, 0x3c, 0x6a,
+	0xff, 0xa2, 0x54, 0x7a,
 	0x01, 0x6a, 0x6a, 0x00,
-	0x00, 0xb9, 0x4a, 0x5c,
-	0xff, 0xa2, 0xcc, 0x7a,
+	0x00, 0xb9, 0xca, 0x5b,
+	0xff, 0xa2, 0x54, 0x7a,
 	0x71, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
-	0x40, 0x51, 0xcc, 0x62,
+	0x40, 0x51, 0x54, 0x62,
 	0x0d, 0x6a, 0x6a, 0x00,
-	0x00, 0xb9, 0x4a, 0x5c,
+	0x00, 0xb9, 0xca, 0x5b,
 	0xff, 0x3e, 0x74, 0x09,
 	0xff, 0x90, 0x7c, 0x08,
-	0x00, 0x65, 0x50, 0x58,
-	0x00, 0x65, 0x36, 0x41,
-	0x20, 0xa0, 0xd4, 0x6a,
+	0x00, 0x65, 0x4e, 0x58,
+	0x00, 0x65, 0xbc, 0x40,
+	0x20, 0xa0, 0x5c, 0x6a,
 	0xff, 0x37, 0xc8, 0x08,
-	0x00, 0x6a, 0xf4, 0x5b,
-	0xff, 0x6a, 0x0a, 0x5c,
+	0x00, 0x6a, 0x74, 0x5b,
+	0xff, 0x6a, 0x8a, 0x5b,
 	0xff, 0xf8, 0xc8, 0x08,
 	0xff, 0x4f, 0xc8, 0x08,
-	0x01, 0x6a, 0xf4, 0x5b,
-	0x00, 0xb9, 0x0a, 0x5c,
+	0x01, 0x6a, 0x74, 0x5b,
+	0x00, 0xb9, 0x8a, 0x5b,
 	0x01, 0x4f, 0x9e, 0x18,
 	0x02, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0xb8, 0x5c,
-	0x00, 0x65, 0x36, 0x41,
+	0x00, 0x65, 0x38, 0x5c,
+	0x00, 0x65, 0xbc, 0x40,
 	0x41, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x24, 0x41,
+	0x00, 0x65, 0xaa, 0x40,
 	0x04, 0xa0, 0x40, 0x01,
-	0x00, 0x65, 0xd0, 0x5c,
-	0x00, 0x65, 0x36, 0x41,
-	0x10, 0x36, 0xac, 0x7a,
+	0x00, 0x65, 0x50, 0x5c,
+	0x00, 0x65, 0xbc, 0x40,
+	0x10, 0x36, 0x34, 0x7a,
 	0x05, 0x38, 0x46, 0x31,
 	0x04, 0x14, 0x58, 0x31,
 	0x03, 0xa9, 0x60, 0x31,
 	0xa3, 0x6a, 0xcc, 0x00,
-	0x38, 0x6a, 0x30, 0x5c,
+	0x38, 0x6a, 0xb0, 0x5b,
 	0xac, 0x6a, 0xcc, 0x00,
-	0x14, 0x6a, 0x32, 0x5c,
-	0xa9, 0x6a, 0x34, 0x5c,
-	0x00, 0x65, 0xac, 0x42,
+	0x14, 0x6a, 0xb2, 0x5b,
+	0xa9, 0x6a, 0xb4, 0x5b,
+	0x00, 0x65, 0x34, 0x42,
 	0xef, 0x36, 0x6c, 0x08,
-	0x00, 0x65, 0xac, 0x42,
+	0x00, 0x65, 0x34, 0x42,
 	0x0f, 0x64, 0xc8, 0x08,
 	0x07, 0x64, 0xc8, 0x08,
 	0x00, 0x37, 0x6e, 0x00,
 	0xff, 0x6a, 0xa4, 0x00,
-	0x00, 0x65, 0xc4, 0x5b,
-	0xff, 0x51, 0x18, 0x73,
-	0x20, 0x36, 0x22, 0x7b,
-	0x00, 0x90, 0xb2, 0x5b,
-	0x00, 0x65, 0x24, 0x43,
+	0x00, 0x65, 0x44, 0x5b,
+	0xff, 0x51, 0xa0, 0x72,
+	0x20, 0x36, 0xaa, 0x7a,
+	0x00, 0x90, 0x32, 0x5b,
+	0x00, 0x65, 0xac, 0x42,
 	0xff, 0x06, 0xd4, 0x08,
-	0x00, 0x65, 0x1e, 0x5c,
-	0xe0, 0x3d, 0x3e, 0x63,
-	0x20, 0x12, 0x3e, 0x63,
-	0x51, 0x6a, 0x5c, 0x5b,
-	0x00, 0x65, 0xac, 0x5b,
+	0x00, 0x65, 0x9e, 0x5b,
+	0xe0, 0x3d, 0xc6, 0x62,
+	0x20, 0x12, 0xc6, 0x62,
+	0x51, 0x6a, 0xda, 0x5a,
+	0x00, 0x65, 0x2c, 0x5b,
 	0xff, 0x37, 0xc8, 0x08,
-	0x00, 0xa1, 0x36, 0x63,
-	0x04, 0xa0, 0x36, 0x7b,
+	0x00, 0xa1, 0xbe, 0x62,
+	0x04, 0xa0, 0xbe, 0x7a,
 	0xfb, 0xa0, 0x40, 0x09,
 	0x80, 0x36, 0x6c, 0x00,
-	0x80, 0xa0, 0xac, 0x7a,
+	0x80, 0xa0, 0x34, 0x7a,
 	0x7f, 0xa0, 0x40, 0x09,
-	0xff, 0x6a, 0x58, 0x5b,
-	0x00, 0x65, 0xac, 0x42,
-	0x04, 0xa0, 0x3c, 0x7b,
-	0x00, 0x65, 0xd0, 0x5c,
-	0x00, 0x65, 0x3e, 0x43,
-	0x00, 0x65, 0xb8, 0x5c,
+	0xff, 0x6a, 0xd6, 0x5a,
+	0x00, 0x65, 0x34, 0x42,
+	0x04, 0xa0, 0xc4, 0x7a,
+	0x00, 0x65, 0x50, 0x5c,
+	0x00, 0x65, 0xc6, 0x42,
+	0x00, 0x65, 0x38, 0x5c,
 	0x31, 0x6a, 0x22, 0x01,
-	0x0c, 0x6a, 0x58, 0x5b,
-	0x00, 0x65, 0xac, 0x42,
+	0x0c, 0x6a, 0xd6, 0x5a,
+	0x00, 0x65, 0x34, 0x42,
 	0x61, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0xac, 0x42,
-	0x51, 0x6a, 0x5c, 0x5b,
-	0xff, 0xa8, 0x54, 0x6b,
-	0xff, 0xa9, 0x54, 0x6b,
-	0xff, 0xaa, 0x54, 0x6b,
-	0xff, 0xab, 0x54, 0x6b,
-	0x00, 0x65, 0xac, 0x42,
+	0x00, 0x65, 0x34, 0x42,
+	0x51, 0x6a, 0xda, 0x5a,
 	0x51, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0xac, 0x42,
+	0x00, 0x65, 0x34, 0x42,
 	0x10, 0x3d, 0x06, 0x00,
 	0xff, 0x65, 0x68, 0x0c,
 	0xff, 0x06, 0xd4, 0x08,
-	0x01, 0x0c, 0x5e, 0x7b,
-	0x04, 0x0c, 0x60, 0x6b,
+	0x01, 0x0c, 0xdc, 0x7a,
+	0x04, 0x0c, 0xde, 0x6a,
 	0xe0, 0x03, 0x7a, 0x08,
-	0xe0, 0x3d, 0x72, 0x63,
+	0xe0, 0x3d, 0xea, 0x62,
 	0xff, 0x65, 0xcc, 0x08,
 	0xff, 0x12, 0xda, 0x0c,
 	0xff, 0x06, 0xd4, 0x0c,
-	0xff, 0x65, 0x0c, 0x08,
-	0x02, 0x0b, 0x6e, 0x7b,
-	0xff, 0x6a, 0xd4, 0x0c,
 	0xd1, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x24, 0x41,
+	0x00, 0x65, 0xaa, 0x40,
 	0xff, 0x65, 0x26, 0x09,
-	0x01, 0x0b, 0x86, 0x6b,
-	0x10, 0x0c, 0x78, 0x7b,
-	0x04, 0x0b, 0x80, 0x6b,
+	0x01, 0x0b, 0xfe, 0x6a,
+	0x10, 0x0c, 0xf0, 0x7a,
+	0x04, 0x0b, 0xf8, 0x6a,
 	0xff, 0x6a, 0xca, 0x08,
-	0x04, 0x93, 0x84, 0x6b,
-	0x01, 0x94, 0x82, 0x7b,
-	0x10, 0x94, 0x84, 0x6b,
+	0x04, 0x93, 0xfc, 0x6a,
+	0x01, 0x94, 0xfa, 0x7a,
+	0x10, 0x94, 0xfc, 0x6a,
+	0x80, 0x3d, 0x02, 0x73,
+	0x0f, 0x04, 0x06, 0x6b,
+	0x02, 0x03, 0x06, 0x7b,
+	0x10, 0x0c, 0x02, 0x7b,
 	0xc7, 0x93, 0x26, 0x09,
 	0xff, 0x99, 0xd4, 0x08,
-	0x38, 0x93, 0x88, 0x6b,
+	0x38, 0x93, 0x08, 0x6b,
 	0xff, 0x6a, 0xd4, 0x0c,
-	0x80, 0x36, 0x8c, 0x6b,
+	0x80, 0x36, 0x0c, 0x6b,
 	0x21, 0x6a, 0x22, 0x05,
 	0xff, 0x65, 0x20, 0x09,
-	0xff, 0x51, 0x9a, 0x63,
+	0xff, 0x51, 0x1a, 0x63,
 	0xff, 0x37, 0xc8, 0x08,
-	0xa1, 0x6a, 0xa6, 0x43,
+	0xa1, 0x6a, 0x26, 0x43,
 	0xff, 0x51, 0xc8, 0x08,
-	0xb9, 0x6a, 0xa6, 0x43,
+	0xb9, 0x6a, 0x26, 0x43,
 	0xff, 0x90, 0xa4, 0x08,
-	0xff, 0xba, 0xaa, 0x73,
+	0xff, 0xba, 0x2a, 0x73,
 	0xff, 0xba, 0x20, 0x09,
 	0xff, 0x65, 0xca, 0x18,
-	0x00, 0x6c, 0x9e, 0x63,
+	0x00, 0x6c, 0x1e, 0x63,
 	0xff, 0x90, 0xca, 0x0c,
 	0xff, 0x6a, 0xca, 0x04,
-	0x20, 0x36, 0xbe, 0x7b,
-	0x00, 0x90, 0x92, 0x5b,
-	0xff, 0x65, 0xbe, 0x73,
-	0xff, 0x52, 0xbc, 0x73,
+	0x20, 0x36, 0x3e, 0x7b,
+	0x00, 0x90, 0x12, 0x5b,
+	0xff, 0x65, 0x3e, 0x73,
+	0xff, 0x52, 0x3c, 0x73,
 	0xff, 0xba, 0xcc, 0x08,
 	0xff, 0x52, 0x20, 0x09,
 	0xff, 0x66, 0x74, 0x09,
 	0xff, 0x65, 0x20, 0x0d,
 	0xff, 0xba, 0x7e, 0x0c,
-	0x00, 0x6a, 0xbe, 0x5c,
+	0x00, 0x6a, 0x3e, 0x5c,
 	0x0d, 0x6a, 0x6a, 0x00,
-	0x00, 0x51, 0x4a, 0x44,
-	0xff, 0x3f, 0x18, 0x74,
+	0x00, 0x51, 0xca, 0x43,
+	0xff, 0x3f, 0x98, 0x73,
 	0xff, 0x6a, 0xa2, 0x00,
-	0x00, 0x3f, 0x92, 0x5b,
-	0xff, 0x65, 0x18, 0x74,
+	0x00, 0x3f, 0x12, 0x5b,
+	0xff, 0x65, 0x98, 0x73,
 	0x20, 0x36, 0x6c, 0x00,
-	0x20, 0xa0, 0xd2, 0x6b,
+	0x20, 0xa0, 0x52, 0x6b,
 	0xff, 0xb9, 0xa2, 0x0c,
 	0xff, 0x6a, 0xa2, 0x04,
 	0xff, 0x65, 0xa4, 0x08,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0x3e, 0x5c,
+	0x45, 0x6a, 0xbe, 0x5b,
 	0x01, 0x6a, 0xd0, 0x01,
 	0x09, 0x6a, 0xd6, 0x01,
-	0x80, 0xeb, 0xde, 0x7b,
+	0x80, 0xeb, 0x5e, 0x7b,
 	0x01, 0x6a, 0xd6, 0x01,
 	0x01, 0xe9, 0xa4, 0x34,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0x3e, 0x5c,
+	0x45, 0x6a, 0xbe, 0x5b,
 	0x01, 0x6a, 0x18, 0x01,
 	0xff, 0x6a, 0x1a, 0x09,
 	0xff, 0x6a, 0x1c, 0x09,
 	0x0d, 0x6a, 0x26, 0x01,
-	0x00, 0x65, 0xb0, 0x5c,
+	0x00, 0x65, 0x30, 0x5c,
 	0xff, 0x99, 0xa4, 0x0c,
 	0xff, 0x65, 0xa4, 0x08,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0x3e, 0x5c,
+	0x45, 0x6a, 0xbe, 0x5b,
 	0x01, 0x6a, 0xd0, 0x01,
 	0x01, 0x6a, 0xdc, 0x05,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0x3e, 0x5c,
+	0x45, 0x6a, 0xbe, 0x5b,
 	0x01, 0x6a, 0x18, 0x01,
 	0xff, 0x6a, 0x1a, 0x09,
 	0xff, 0x6a, 0x1c, 0x09,
 	0x01, 0x6a, 0x26, 0x05,
 	0x01, 0x65, 0xd8, 0x31,
 	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0x0e, 0x7c,
+	0x80, 0xee, 0x8e, 0x7b,
 	0xff, 0x6a, 0xdc, 0x0d,
 	0xff, 0x65, 0x32, 0x09,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xb0, 0x44,
+	0x00, 0x65, 0x30, 0x44,
 	0xff, 0x37, 0xc8, 0x08,
-	0x00, 0x6a, 0xd4, 0x5b,
+	0x00, 0x6a, 0x54, 0x5b,
 	0xff, 0x52, 0xa2, 0x0c,
-	0x01, 0x0c, 0x1e, 0x7c,
-	0x04, 0x0c, 0x1e, 0x6c,
+	0x01, 0x0c, 0x9e, 0x7b,
+	0x04, 0x0c, 0x9e, 0x6b,
 	0xe0, 0x03, 0x06, 0x08,
 	0xe0, 0x03, 0x7a, 0x0c,
 	0xff, 0x8c, 0x10, 0x08,
@@ -553,29 +489,29 @@
 	0x00, 0x6c, 0xda, 0x24,
 	0xff, 0x65, 0xc8, 0x08,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x41, 0x6a, 0x3a, 0x5c,
+	0x41, 0x6a, 0xba, 0x5b,
 	0xff, 0x90, 0xe2, 0x09,
 	0x20, 0x6a, 0xd0, 0x01,
-	0x04, 0x35, 0x5c, 0x7c,
+	0x04, 0x35, 0xdc, 0x7b,
 	0x1d, 0x6a, 0xdc, 0x01,
-	0xdc, 0xee, 0x58, 0x64,
-	0x00, 0x65, 0x68, 0x44,
+	0xdc, 0xee, 0xd8, 0x63,
+	0x00, 0x65, 0xe8, 0x43,
 	0x01, 0x6a, 0xdc, 0x01,
 	0x20, 0xa0, 0xd8, 0x31,
 	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0x62, 0x7c,
+	0x80, 0xee, 0xe2, 0x7b,
 	0x19, 0x6a, 0xdc, 0x01,
-	0xd8, 0xee, 0x66, 0x64,
+	0xd8, 0xee, 0xe6, 0x63,
 	0xff, 0x6a, 0xdc, 0x09,
-	0x18, 0xee, 0x6a, 0x6c,
+	0x18, 0xee, 0xea, 0x6b,
 	0xff, 0x6a, 0xd4, 0x0c,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x41, 0x6a, 0x3a, 0x5c,
+	0x41, 0x6a, 0xba, 0x5b,
 	0x20, 0x6a, 0x18, 0x01,
 	0xff, 0x6a, 0x1a, 0x09,
 	0xff, 0x6a, 0x1c, 0x09,
 	0xff, 0x35, 0x26, 0x09,
-	0x04, 0x35, 0x94, 0x6c,
+	0x04, 0x35, 0x14, 0x6c,
 	0xa0, 0x6a, 0xca, 0x00,
 	0x20, 0x65, 0xc8, 0x18,
 	0xff, 0x6c, 0x32, 0x09,
@@ -586,14 +522,14 @@
 	0xff, 0x6c, 0x32, 0x09,
 	0xff, 0x6c, 0x32, 0x09,
 	0xff, 0x6c, 0x32, 0x09,
-	0x00, 0x65, 0x80, 0x64,
+	0x00, 0x65, 0x00, 0x64,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xb0, 0x5c,
-	0x04, 0x35, 0x8c, 0x7b,
-	0xa0, 0x6a, 0xa0, 0x5c,
-	0x00, 0x65, 0xa2, 0x5c,
-	0x00, 0x65, 0xa2, 0x5c,
-	0x00, 0x65, 0xa2, 0x44,
+	0x00, 0x65, 0x30, 0x5c,
+	0x04, 0x35, 0x0c, 0x7b,
+	0xa0, 0x6a, 0x20, 0x5c,
+	0x00, 0x65, 0x22, 0x5c,
+	0x00, 0x65, 0x22, 0x5c,
+	0x00, 0x65, 0x22, 0x44,
 	0xff, 0x65, 0xcc, 0x08,
 	0xff, 0x99, 0xda, 0x08,
 	0xff, 0x99, 0xda, 0x08,
@@ -602,19 +538,19 @@
 	0xff, 0x99, 0xda, 0x08,
 	0xff, 0x99, 0xda, 0x08,
 	0xff, 0x99, 0xda, 0x0c,
-	0x08, 0x94, 0xb0, 0x7c,
+	0x08, 0x94, 0x30, 0x7c,
 	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0xb4, 0x6c,
+	0x08, 0x93, 0x34, 0x6c,
 	0xff, 0x6a, 0xd4, 0x0c,
 	0xff, 0x40, 0x74, 0x09,
 	0xff, 0x90, 0x80, 0x08,
 	0xff, 0x6a, 0x72, 0x05,
-	0xff, 0x40, 0xcc, 0x64,
-	0xff, 0x3f, 0xc4, 0x64,
+	0xff, 0x40, 0x4c, 0x64,
+	0xff, 0x3f, 0x44, 0x64,
 	0xff, 0x6a, 0xca, 0x04,
 	0xff, 0x3f, 0x20, 0x09,
 	0x01, 0x6a, 0x6a, 0x00,
-	0x00, 0xb9, 0x4a, 0x5c,
+	0x00, 0xb9, 0xca, 0x5b,
 	0xff, 0xba, 0x7e, 0x0c,
 	0xff, 0x40, 0x20, 0x09,
 	0xff, 0xba, 0x80, 0x0c,
@@ -622,20 +558,12 @@
 	0xff, 0x90, 0x7e, 0x0c,
 };
 
-static int aic7xxx_patch13_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch13_func(struct aic7xxx_host *p)
-{
-	return ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895);
-}
-
 static int aic7xxx_patch12_func(struct aic7xxx_host *p);
 
 static int
 aic7xxx_patch12_func(struct aic7xxx_host *p)
 {
-	return ((p->features & AHC_CMD_CHAN) == 0);
+	return ((p->features & AHC_WIDE) != 0);
 }
 
 static int aic7xxx_patch11_func(struct aic7xxx_host *p);
@@ -643,7 +571,7 @@
 static int
 aic7xxx_patch11_func(struct aic7xxx_host *p)
 {
-	return ((p->features & AHC_WIDE) != 0);
+	return ((p->features & AHC_ULTRA2) == 0);
 }
 
 static int aic7xxx_patch10_func(struct aic7xxx_host *p);
@@ -651,7 +579,7 @@
 static int
 aic7xxx_patch10_func(struct aic7xxx_host *p)
 {
-	return ((p->features & AHC_ULTRA2) == 0);
+	return ((p->features & AHC_CMD_CHAN) == 0);
 }
 
 static int aic7xxx_patch9_func(struct aic7xxx_host *p);
@@ -659,7 +587,7 @@
 static int
 aic7xxx_patch9_func(struct aic7xxx_host *p)
 {
-	return ((p->features & AHC_ULTRA) != 0);
+	return ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895);
 }
 
 static int aic7xxx_patch8_func(struct aic7xxx_host *p);
@@ -667,7 +595,7 @@
 static int
 aic7xxx_patch8_func(struct aic7xxx_host *p)
 {
-	return ((p->features & AHC_ULTRA2) != 0);
+	return ((p->features & AHC_ULTRA) != 0);
 }
 
 static int aic7xxx_patch7_func(struct aic7xxx_host *p);
@@ -675,7 +603,7 @@
 static int
 aic7xxx_patch7_func(struct aic7xxx_host *p)
 {
-	return ((p->flags & AHC_PAGESCBS) == 0);
+	return ((p->features & AHC_ULTRA2) != 0);
 }
 
 static int aic7xxx_patch6_func(struct aic7xxx_host *p);
@@ -683,7 +611,7 @@
 static int
 aic7xxx_patch6_func(struct aic7xxx_host *p)
 {
-	return ((p->flags & AHC_PAGESCBS) != 0);
+	return ((p->flags & AHC_PAGESCBS) == 0);
 }
 
 static int aic7xxx_patch5_func(struct aic7xxx_host *p);
@@ -691,7 +619,7 @@
 static int
 aic7xxx_patch5_func(struct aic7xxx_host *p)
 {
-	return ((p->features & AHC_QUEUE_REGS) != 0);
+	return ((p->flags & AHC_PAGESCBS) != 0);
 }
 
 static int aic7xxx_patch4_func(struct aic7xxx_host *p);
@@ -699,7 +627,7 @@
 static int
 aic7xxx_patch4_func(struct aic7xxx_host *p)
 {
-	return ((p->features & AHC_TWIN) != 0);
+	return ((p->features & AHC_QUEUE_REGS) != 0);
 }
 
 static int aic7xxx_patch3_func(struct aic7xxx_host *p);
@@ -707,7 +635,7 @@
 static int
 aic7xxx_patch3_func(struct aic7xxx_host *p)
 {
-	return ((p->features & AHC_QUEUE_REGS) == 0);
+	return ((p->features & AHC_TWIN) != 0);
 }
 
 static int aic7xxx_patch2_func(struct aic7xxx_host *p);
@@ -715,7 +643,7 @@
 static int
 aic7xxx_patch2_func(struct aic7xxx_host *p)
 {
-	return ((p->features & AHC_CMD_CHAN) != 0);
+	return ((p->features & AHC_QUEUE_REGS) == 0);
 }
 
 static int aic7xxx_patch1_func(struct aic7xxx_host *p);
@@ -723,7 +651,7 @@
 static int
 aic7xxx_patch1_func(struct aic7xxx_host *p)
 {
-	return ((p->flags & AHC_TARGETMODE) != 0);
+	return ((p->features & AHC_CMD_CHAN) != 0);
 }
 
 static int aic7xxx_patch0_func(struct aic7xxx_host *p);
@@ -740,83 +668,78 @@
 			skip_instr :10,
 			skip_patch :12;
 } sequencer_patches[] = {
-	{ aic7xxx_patch1_func, 2, 1, 2 },
-	{ aic7xxx_patch0_func, 3, 1, 1 },
-	{ aic7xxx_patch2_func, 4, 2, 1 },
-	{ aic7xxx_patch3_func, 8, 1, 1 },
-	{ aic7xxx_patch3_func, 9, 1, 1 },
-	{ aic7xxx_patch4_func, 12, 4, 1 },
-	{ aic7xxx_patch5_func, 17, 3, 2 },
-	{ aic7xxx_patch0_func, 20, 4, 1 },
-	{ aic7xxx_patch6_func, 24, 1, 1 },
-	{ aic7xxx_patch7_func, 27, 1, 1 },
-	{ aic7xxx_patch2_func, 30, 1, 2 },
-	{ aic7xxx_patch0_func, 31, 3, 1 },
-	{ aic7xxx_patch4_func, 40, 4, 1 },
-	{ aic7xxx_patch8_func, 44, 3, 2 },
-	{ aic7xxx_patch0_func, 47, 3, 1 },
-	{ aic7xxx_patch9_func, 53, 7, 1 },
-	{ aic7xxx_patch4_func, 61, 3, 1 },
-	{ aic7xxx_patch8_func, 64, 2, 1 },
-	{ aic7xxx_patch1_func, 69, 60, 1 },
-	{ aic7xxx_patch8_func, 163, 1, 2 },
-	{ aic7xxx_patch0_func, 164, 2, 1 },
-	{ aic7xxx_patch2_func, 168, 3, 4 },
-	{ aic7xxx_patch8_func, 168, 2, 2 },
-	{ aic7xxx_patch0_func, 170, 1, 1 },
-	{ aic7xxx_patch0_func, 171, 2, 1 },
-	{ aic7xxx_patch8_func, 174, 1, 2 },
-	{ aic7xxx_patch0_func, 175, 1, 1 },
-	{ aic7xxx_patch2_func, 179, 1, 1 },
-	{ aic7xxx_patch2_func, 182, 3, 2 },
-	{ aic7xxx_patch0_func, 185, 5, 1 },
-	{ aic7xxx_patch2_func, 193, 2, 3 },
-	{ aic7xxx_patch8_func, 193, 1, 1 },
-	{ aic7xxx_patch0_func, 195, 3, 1 },
-	{ aic7xxx_patch10_func, 199, 1, 2 },
-	{ aic7xxx_patch0_func, 200, 1, 1 },
-	{ aic7xxx_patch8_func, 201, 7, 2 },
-	{ aic7xxx_patch0_func, 208, 1, 1 },
-	{ aic7xxx_patch2_func, 213, 14, 3 },
-	{ aic7xxx_patch10_func, 226, 1, 1 },
-	{ aic7xxx_patch0_func, 227, 9, 1 },
-	{ aic7xxx_patch8_func, 241, 2, 1 },
-	{ aic7xxx_patch8_func, 243, 1, 1 },
-	{ aic7xxx_patch10_func, 244, 6, 3 },
-	{ aic7xxx_patch2_func, 244, 2, 2 },
-	{ aic7xxx_patch0_func, 246, 4, 1 },
-	{ aic7xxx_patch8_func, 251, 1, 1 },
-	{ aic7xxx_patch8_func, 255, 19, 1 },
-	{ aic7xxx_patch2_func, 275, 3, 3 },
-	{ aic7xxx_patch10_func, 277, 1, 1 },
-	{ aic7xxx_patch0_func, 278, 5, 1 },
-	{ aic7xxx_patch10_func, 283, 1, 2 },
-	{ aic7xxx_patch0_func, 284, 9, 1 },
-	{ aic7xxx_patch11_func, 300, 1, 2 },
-	{ aic7xxx_patch0_func, 301, 1, 1 },
-	{ aic7xxx_patch5_func, 362, 1, 2 },
-	{ aic7xxx_patch0_func, 363, 1, 1 },
-	{ aic7xxx_patch3_func, 366, 1, 1 },
-	{ aic7xxx_patch2_func, 376, 3, 2 },
-	{ aic7xxx_patch0_func, 379, 5, 1 },
-	{ aic7xxx_patch11_func, 387, 1, 2 },
-	{ aic7xxx_patch0_func, 388, 1, 1 },
-	{ aic7xxx_patch6_func, 393, 1, 1 },
-	{ aic7xxx_patch1_func, 438, 3, 1 },
-	{ aic7xxx_patch10_func, 443, 11, 1 },
-	{ aic7xxx_patch2_func, 491, 7, 2 },
-	{ aic7xxx_patch0_func, 498, 8, 1 },
-	{ aic7xxx_patch2_func, 507, 4, 2 },
-	{ aic7xxx_patch0_func, 511, 6, 1 },
-	{ aic7xxx_patch2_func, 517, 4, 2 },
-	{ aic7xxx_patch0_func, 521, 3, 1 },
-	{ aic7xxx_patch12_func, 531, 10, 1 },
-	{ aic7xxx_patch2_func, 550, 17, 4 },
-	{ aic7xxx_patch13_func, 558, 4, 2 },
-	{ aic7xxx_patch0_func, 562, 2, 1 },
-	{ aic7xxx_patch0_func, 567, 33, 1 },
-	{ aic7xxx_patch12_func, 600, 4, 1 },
-	{ aic7xxx_patch6_func, 604, 2, 1 },
-	{ aic7xxx_patch6_func, 607, 9, 1 },
+	{ aic7xxx_patch1_func, 3, 2, 1 },
+	{ aic7xxx_patch2_func, 7, 1, 1 },
+	{ aic7xxx_patch2_func, 8, 1, 1 },
+	{ aic7xxx_patch3_func, 11, 4, 1 },
+	{ aic7xxx_patch4_func, 16, 3, 2 },
+	{ aic7xxx_patch0_func, 19, 4, 1 },
+	{ aic7xxx_patch5_func, 23, 1, 1 },
+	{ aic7xxx_patch6_func, 26, 1, 1 },
+	{ aic7xxx_patch1_func, 29, 1, 2 },
+	{ aic7xxx_patch0_func, 30, 3, 1 },
+	{ aic7xxx_patch3_func, 39, 4, 1 },
+	{ aic7xxx_patch7_func, 43, 3, 2 },
+	{ aic7xxx_patch0_func, 46, 3, 1 },
+	{ aic7xxx_patch8_func, 52, 7, 1 },
+	{ aic7xxx_patch3_func, 60, 3, 1 },
+	{ aic7xxx_patch7_func, 63, 2, 1 },
+	{ aic7xxx_patch7_func, 102, 1, 2 },
+	{ aic7xxx_patch0_func, 103, 2, 1 },
+	{ aic7xxx_patch7_func, 107, 2, 1 },
+	{ aic7xxx_patch9_func, 109, 1, 1 },
+	{ aic7xxx_patch10_func, 110, 2, 1 },
+	{ aic7xxx_patch7_func, 113, 1, 2 },
+	{ aic7xxx_patch0_func, 114, 1, 1 },
+	{ aic7xxx_patch1_func, 118, 1, 1 },
+	{ aic7xxx_patch1_func, 121, 3, 2 },
+	{ aic7xxx_patch0_func, 124, 5, 1 },
+	{ aic7xxx_patch1_func, 132, 2, 3 },
+	{ aic7xxx_patch7_func, 132, 1, 1 },
+	{ aic7xxx_patch0_func, 134, 3, 1 },
+	{ aic7xxx_patch11_func, 138, 1, 2 },
+	{ aic7xxx_patch0_func, 139, 1, 1 },
+	{ aic7xxx_patch7_func, 140, 7, 2 },
+	{ aic7xxx_patch0_func, 147, 1, 1 },
+	{ aic7xxx_patch1_func, 152, 14, 3 },
+	{ aic7xxx_patch11_func, 165, 1, 1 },
+	{ aic7xxx_patch0_func, 166, 9, 1 },
+	{ aic7xxx_patch7_func, 180, 2, 1 },
+	{ aic7xxx_patch7_func, 182, 1, 1 },
+	{ aic7xxx_patch11_func, 183, 6, 3 },
+	{ aic7xxx_patch1_func, 183, 2, 2 },
+	{ aic7xxx_patch0_func, 185, 4, 1 },
+	{ aic7xxx_patch7_func, 190, 1, 1 },
+	{ aic7xxx_patch7_func, 194, 20, 1 },
+	{ aic7xxx_patch1_func, 215, 3, 3 },
+	{ aic7xxx_patch11_func, 217, 1, 1 },
+	{ aic7xxx_patch0_func, 218, 5, 1 },
+	{ aic7xxx_patch11_func, 223, 1, 2 },
+	{ aic7xxx_patch0_func, 224, 9, 1 },
+	{ aic7xxx_patch12_func, 240, 1, 2 },
+	{ aic7xxx_patch0_func, 241, 1, 1 },
+	{ aic7xxx_patch4_func, 302, 1, 2 },
+	{ aic7xxx_patch0_func, 303, 1, 1 },
+	{ aic7xxx_patch2_func, 306, 1, 1 },
+	{ aic7xxx_patch1_func, 316, 3, 2 },
+	{ aic7xxx_patch0_func, 319, 5, 1 },
+	{ aic7xxx_patch12_func, 327, 1, 2 },
+	{ aic7xxx_patch0_func, 328, 1, 1 },
+	{ aic7xxx_patch5_func, 333, 1, 1 },
+	{ aic7xxx_patch11_func, 375, 15, 1 },
+	{ aic7xxx_patch1_func, 427, 7, 2 },
+	{ aic7xxx_patch0_func, 434, 8, 1 },
+	{ aic7xxx_patch1_func, 443, 4, 2 },
+	{ aic7xxx_patch0_func, 447, 6, 1 },
+	{ aic7xxx_patch1_func, 453, 4, 2 },
+	{ aic7xxx_patch0_func, 457, 3, 1 },
+	{ aic7xxx_patch10_func, 467, 10, 1 },
+	{ aic7xxx_patch1_func, 486, 17, 4 },
+	{ aic7xxx_patch9_func, 494, 4, 2 },
+	{ aic7xxx_patch0_func, 498, 2, 1 },
+	{ aic7xxx_patch0_func, 503, 33, 1 },
+	{ aic7xxx_patch10_func, 536, 4, 1 },
+	{ aic7xxx_patch5_func, 540, 2, 1 },
+	{ aic7xxx_patch5_func, 543, 9, 1 },
 
 };
diff -urN linux-2.2.17-pre1/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c
--- linux-2.2.17-pre1/drivers/scsi/sym53c8xx.c	Mon Dec  3 22:05:22 2001
+++ linux/drivers/scsi/sym53c8xx.c	Mon Dec  3 22:05:27 2001
@@ -9021,7 +9021,7 @@
 **	code will get more complex later).
 */
 
-#ifdef SCSI_NCR_USE_64BIT_DAC
+#if BITS_PER_LONG > 32
 #define SCATTER_ONE(data, badd, len)					\
 	(data)->addr = cpu_to_scr(badd);				\
 	(data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len);
diff -urN linux-2.2.17-pre1/drivers/sound/ac97_codec.c linux/drivers/sound/ac97_codec.c
--- linux-2.2.17-pre1/drivers/sound/ac97_codec.c	Wed Jun  7 14:26:43 2000
+++ linux/drivers/sound/ac97_codec.c	Mon Dec  3 22:05:27 2001
@@ -530,6 +530,11 @@
 	/* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should 
 	   be read zero. Probing of AC97 in this way is not reliable, it is not even SAFE !! */
 	codec->codec_write(codec, AC97_RESET, 0L);
+	
+	/* We need a codec->codec_reset() function here but the delay is a
+	   reasonable hack for the moment */
+	   
+	schedule_timeout((5*HZ)/100);
 	if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) {
 		printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n",
 		       codec->id ? "Secondary" : "Primary");
diff -urN linux-2.2.17-pre1/drivers/sound/i810_audio.c linux/drivers/sound/i810_audio.c
--- linux-2.2.17-pre1/drivers/sound/i810_audio.c	Wed Jun  7 14:26:43 2000
+++ linux/drivers/sound/i810_audio.c	Mon Dec  3 22:05:27 2001
@@ -46,6 +46,18 @@
  *	There is no midi support, no synth support. Use timidity. To get
  *	esd working you need to use esd -r 48000 as it won't probe 48KHz
  *	by default. mpg123 can't handle 48Khz only audio so use xmms.
+ *
+ *	Fix The Sound On Dell
+ *
+ *	Not everyone uses 48KHz. We know of no way to detect this reliably
+ *	and certainly not to get the right data. If your i810 audio sounds
+ *	stupid you may need to investigate other speeds. According to Analog
+ *	they tend to use a 14.318MHz clock which gives you a base rate of
+ *	41194Hz.
+ *
+ *	This is available via the 'ftsodell=1' option. 
+ *
+ *	If you need to force a specific rate set the clocking= option
  */
  
 #include <linux/module.h>
@@ -74,10 +86,16 @@
 #ifndef PCI_DEVICE_ID_INTEL_82901
 #define PCI_DEVICE_ID_INTEL_82901	0x2425
 #endif
+#ifndef PCI_DEVICE_ID_INTEL_ICH2
+#define PCI_DEVICE_ID_INTEL_ICH2	0x2445
+#endif
 #ifndef PCI_DEVICE_ID_INTEL_440MX
 #define PCI_DEVICE_ID_INTEL_440MX	0x7195
 #endif
 
+static int ftsodell=0;
+static int clocking=48000;
+
 #define ADC_RUNNING	1
 #define DAC_RUNNING	2
 
@@ -180,7 +198,8 @@
 enum {
 	ICH82801AA = 0,
 	ICH82901AB,
-	INTEL440MX
+	INTEL440MX,
+	INTELICH2
 };
 
 /* "software" or virtual channel, an instance of opened /dev/dsp */
@@ -345,14 +364,26 @@
 	
 	if(!(state->card->ac97_features&0x0001))
 	{
-		dmabuf->rate=48000;
-		return 48000;
+		dmabuf->rate=clocking;
+		return clocking;
 	}
 			
 	if (rate > 48000)
 		rate = 48000;
-	if (rate < 4000)
-		rate = 4000;
+	if (rate < 8000)
+		rate = 8000;
+	
+	/*
+	 *	Adjust for misclocked crap
+	 */
+	 
+	rate = ( rate * clocking)/48000;
+	
+	/* Analog codecs can go lower via magic registers but others
+	   might not */
+	   
+	if(rate < 8000)
+		rate = 8000;
 
 	/* Power down the DAC */
 	dacp=i810_ac97_get(codec, AC97_POWER_CONTROL);
@@ -365,7 +396,7 @@
 //	printk("DAC rate set to %d Returned %d\n", 
 //		rate, (int)rp);
 		
-	rate=rp;
+	rate=(rp*48000) / clocking;
 		
 	/* Power it back up */
 	i810_ac97_set(codec, AC97_POWER_CONTROL, dacp);
@@ -387,14 +418,26 @@
 	
 	if(!(state->card->ac97_features&0x0001))
 	{
-		dmabuf->rate = 48000;
-		return 48000;
+		dmabuf->rate = clocking;
+		return clocking;
 	}
 			
 	if (rate > 48000)
 		rate = 48000;
-	if (rate < 4000)
-		rate = 4000;
+	if (rate < 8000)
+		rate = 8000;
+
+	/*
+	 *	Adjust for misclocked crap
+	 */
+	 
+	rate = ( rate * clocking)/48000;
+	
+	/* Analog codecs can go lower via magic registers but others
+	   might not */
+	   
+	if(rate < 8000)
+		rate = 8000;
 
 	/* Power down the ADC */
 	dacp=i810_ac97_get(codec, AC97_POWER_CONTROL);
@@ -407,7 +450,7 @@
 //	printk("ADC rate set to %d Returned %d\n", 
 //		rate, (int)rp);
 		
-	rate=rp;
+	rate = (rp * 48000) / clocking;
 		
 	/* Power it back up */
 	i810_ac97_set(codec, AC97_POWER_CONTROL, dacp);
@@ -1806,6 +1849,8 @@
 
 MODULE_AUTHOR("Assorted");
 MODULE_DESCRIPTION("Intel 810 audio support");
+MODULE_PARM(ftsodell, "i");
+MODULE_PARM(clocking, "i");
 
 int __init i810_probe(void)
 {
@@ -1815,6 +1860,9 @@
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
 
+	if(ftsodell=1)
+		clocking=41194;
+		
 	printk(KERN_INFO "Intel 810 + AC97 Audio, version "
 	       DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
 
@@ -1828,6 +1876,11 @@
 	}
 	while( (pcidev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_440MX, pcidev))!=NULL ) {
 		if (i810_install(pcidev, INTEL440MX, "Intel 440MX")==0)
+			foundone++;
+	}
+
+	while( (pcidev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH2, pcidev))!=NULL ) {
+		if (i810_install(pcidev, INTELICH2, "Intel ICH2")==0)
 			foundone++;
 	}
 
diff -urN linux-2.2.17-pre1/drivers/telephony/ixj.c linux/drivers/telephony/ixj.c
--- linux-2.2.17-pre1/drivers/telephony/ixj.c	Wed May  3 17:16:46 2000
+++ linux/drivers/telephony/ixj.c	Mon Dec  3 22:05:27 2001
@@ -1,10 +1,10 @@
-/*
+/****************************************************************************
  *    ixj.c
  *
  *    Device Driver for the Internet PhoneJACK and
  *    Internet LineJACK Telephony Cards.
  *
- *    (c) Copyright 1999 Quicknet Technologies, Inc.
+ *    (c) Copyright 1999-2000  Quicknet Technologies, Inc.
  *
  *    This program is free software; you can redistribute it and/or
  *    modify it under the terms of the GNU General Public License
@@ -12,25 +12,42 @@
  *    2 of the License, or (at your option) any later version.
  *
  * Author:          Ed Okerson, <eokerson@quicknet.net>
- *    
+ *
  * Contributors:    Greg Herlein, <gherlein@quicknet.net>
  *                  David W. Erhart, <derhart@quicknet.net>
  *                  John Sellers, <jsellers@quicknet.net>
  *                  Mike Preston, <mpreston@quicknet.net>
- *
+ *    
  * Fixes:
- *
- * More information about the hardware related to this driver can be found
+ * 
+ * More information about the hardware related to this driver can be found  
  * at our website:    http://www.quicknet.net
  *
- */
+ * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET
+ * TECHNOLOGIES, INC.HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *    
+ * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION
+ * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ ***************************************************************************/
 
-static char ixj_c_rcsid[] = "$Id: ixj.c,v 3.4 1999/12/16 22:18:36 root Exp root $";
+static char ixj_c_rcsid[] = "$Id: ixj.c,v 3.31 2000/04/14 19:24:47 jaugenst Exp $";
+static char ixj_c_revision[] = "$Revision: 3.31 $";
 
 //#define PERFMON_STATS
 #define IXJDEBUG 0
 #define MAXRINGS 5
 
+#ifdef CONFIG_PCMCIA
+#include <pcmcia/config.h>
+#include <pcmcia/k_compat.h>
+#endif
+
 #include <linux/module.h>
 
 #include <linux/init.h>
@@ -54,8 +71,18 @@
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_ISAPNP
-#include "../pnp/pnpio.h"
-#include "../pnp/isapnp.h"
+#include "../isapnp/pnpio.h"
+#include "../isapnp/isapnp.h"
+#endif
+
+#ifdef CONFIG_PCMCIA
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ciscode.h>
 #endif
 
 #include "ixj.h"
@@ -100,14 +127,17 @@
 static void ixj_write_frame(int board);
 static void ixj_init_timer(void);
 static void ixj_add_timer(void);
-static void ixj_del_timer(void);
 static void ixj_timeout(unsigned long ptr);
 static int read_filters(int board);
 static int LineMonitor(int board);
 static int ixj_fasync(int fd, struct file *, int mode);
+static int ixj_set_port(int board, int arg);
+static int ixj_set_pots(int board, int arg);
 static int ixj_hookstate(int board);
 static int ixj_record_start(int board);
 static void ixj_record_stop(int board);
+static void set_rec_volume(int board, int volume);
+static void ixj_vad(int board, int arg);
 static int ixj_play_start(int board);
 static void ixj_play_stop(int board);
 static int ixj_set_tone_on(unsigned short arg, int board);
@@ -124,6 +154,7 @@
 static char daa_int_read(int board);
 static int daa_set_mode(int board, int mode);
 static int ixj_linetest(int board);
+static int ixj_daa_write(int board);
 static int ixj_daa_cid_read(int board);
 static void DAA_Coeff_US(int board);
 static void DAA_Coeff_UK(int board);
@@ -134,12 +165,18 @@
 static int ixj_init_filter(int board, IXJ_FILTER * jf);
 static int ixj_init_tone(int board, IXJ_TONE * ti);
 static int ixj_build_cadence(int board, IXJ_CADENCE * cp);
+static int ixj_build_filter_cadence(int board, IXJ_FILTER_CADENCE * cp);
 // Serial Control Interface funtions
 static int SCI_Control(int board, int control);
 static int SCI_Prepare(int board);
 static int SCI_WaitHighSCI(int board);
 static int SCI_WaitLowSCI(int board);
 static DWORD PCIEE_GetSerialNumber(WORD wAddress);
+static int ixj_PCcontrol_wait(int board);
+static void ixj_write_cid(int board);
+static void ixj_write_cid_bit(int board, int bit);
+static int set_base_frame(int board, int size);
+static int set_play_codec(int board, int rate);
 
 /************************************************************************
 CT8020/CT8021 Host Programmers Model
@@ -160,12 +197,19 @@
 	ixj[board].hsr.bytes.low = inb_p(ixj[board].DSPbase + 8);
 	ixj[board].hsr.bytes.high = inb_p(ixj[board].DSPbase + 9);
 }
+
 extern __inline__ int IsControlReady(int board)
 {
 	ixj_read_HSR(board);
 	return ixj[board].hsr.bits.controlrdy ? 1 : 0;
 }
 
+extern __inline__ int IsPCControlReady(int board)
+{
+	ixj[board].pccr1.byte = inb_p(ixj[board].XILINXbase + 3);
+	return ixj[board].pccr1.bits.crr ? 1 : 0;
+}
+
 extern __inline__ int IsStatusReady(int board)
 {
 	ixj_read_HSR(board);
@@ -175,21 +219,54 @@
 extern __inline__ int IsRxReady(int board)
 {
 	ixj_read_HSR(board);
+#ifdef PERFMON_STATS
+	++ixj[board].rxreadycheck;
+#endif
 	return ixj[board].hsr.bits.rxrdy ? 1 : 0;
 }
 
 extern __inline__ int IsTxReady(int board)
 {
 	ixj_read_HSR(board);
+#ifdef PERFMON_STATS
+	++ixj[board].txreadycheck;
+#endif
 	return ixj[board].hsr.bits.txrdy ? 1 : 0;
 }
 
+extern __inline__ void set_play_volume(int board, int volume)
+{
+	ixj_WriteDSPCommand(0xCF02, board);
+	ixj_WriteDSPCommand(volume, board);
+}
+
+extern __inline__ int get_play_volume(int board)
+{
+	ixj_WriteDSPCommand(0xCF00, board);
+	return ixj[board].ssr.high << 8 | ixj[board].ssr.low;
+}
+
 extern __inline__ BYTE SLIC_GetState(int board)
 {
 	IXJ *j = &ixj[board];
 
-	j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01);
-
+	if (j->cardtype == 600) {
+		j->pccr1.byte = 0;
+		j->psccr.bits.dev = 3;
+		j->psccr.bits.rw = 1;
+		outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00);
+		ixj_PCcontrol_wait(board);
+		j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF;
+		ixj_PCcontrol_wait(board);
+		if (j->pslic.bits.powerdown)
+			return PLD_SLIC_STATE_OC;
+		else if (!j->pslic.bits.ring0 && !j->pslic.bits.ring1)
+			return PLD_SLIC_STATE_ACTIVE;
+		else
+			return PLD_SLIC_STATE_RINGING;
+	} else {
+		j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01);
+	}
 	return j->pld_slicr.bits.state;
 }
 
@@ -198,78 +275,122 @@
 	BOOL fRetVal = FALSE;
 	IXJ *j = &ixj[board];
 
-	// Set the C1, C2, C3 & B2EN signals.
-	switch (byState) {
-	case PLD_SLIC_STATE_OC:
-		j->pld_slicw.bits.c1 = 0;
-		j->pld_slicw.bits.c2 = 0;
-		j->pld_slicw.bits.c3 = 0;
-		j->pld_slicw.bits.b2en = 0;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		fRetVal = TRUE;
-		break;
-	case PLD_SLIC_STATE_RINGING:
-		j->pld_slicw.bits.c1 = 1;
-		j->pld_slicw.bits.c2 = 0;
-		j->pld_slicw.bits.c3 = 0;
-		j->pld_slicw.bits.b2en = 1;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		fRetVal = TRUE;
-		break;
-	case PLD_SLIC_STATE_ACTIVE:
-		j->pld_slicw.bits.c1 = 0;
-		j->pld_slicw.bits.c2 = 1;
-		j->pld_slicw.bits.c3 = 0;
-		j->pld_slicw.bits.b2en = 0;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		fRetVal = TRUE;
-		break;
-	case PLD_SLIC_STATE_OHT:	// On-hook transmit
+	if (j->cardtype == 600) {
+		if (j->flags.pcmciasct) {
+			switch (byState) {
+			case PLD_SLIC_STATE_TIPOPEN:
+			case PLD_SLIC_STATE_OC:
+				j->pslic.bits.powerdown = 1;
+				j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0;
+				fRetVal = TRUE;
+				break;
+			case PLD_SLIC_STATE_RINGING:
+				if (j->readers || j->writers) {
+					j->pslic.bits.powerdown = 0;
+					j->pslic.bits.ring0 = 1;
+					j->pslic.bits.ring1 = 0;
+					fRetVal = TRUE;
+				}
+				break;
+			case PLD_SLIC_STATE_OHT:	// On-hook transmit
 
-		j->pld_slicw.bits.c1 = 1;
-		j->pld_slicw.bits.c2 = 1;
-		j->pld_slicw.bits.c3 = 0;
-		j->pld_slicw.bits.b2en = 0;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		fRetVal = TRUE;
-		break;
-	case PLD_SLIC_STATE_TIPOPEN:
-		j->pld_slicw.bits.c1 = 0;
-		j->pld_slicw.bits.c2 = 0;
-		j->pld_slicw.bits.c3 = 1;
-		j->pld_slicw.bits.b2en = 0;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		fRetVal = TRUE;
-		break;
-	case PLD_SLIC_STATE_STANDBY:
-		j->pld_slicw.bits.c1 = 1;
-		j->pld_slicw.bits.c2 = 0;
-		j->pld_slicw.bits.c3 = 1;
-		j->pld_slicw.bits.b2en = 1;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		fRetVal = TRUE;
-		break;
-	case PLD_SLIC_STATE_APR:	// Active polarity reversal
+			case PLD_SLIC_STATE_STANDBY:
+			case PLD_SLIC_STATE_ACTIVE:
+				if (j->readers || j->writers) {
+					j->pslic.bits.powerdown = 0;
+				} else {
+					j->pslic.bits.powerdown = 1;
+				}
+				j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0;
+				fRetVal = TRUE;
+				break;
+			case PLD_SLIC_STATE_APR:	// Active polarity reversal
 
-		j->pld_slicw.bits.c1 = 0;
-		j->pld_slicw.bits.c2 = 1;
-		j->pld_slicw.bits.c3 = 1;
-		j->pld_slicw.bits.b2en = 0;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		fRetVal = TRUE;
-		break;
-	case PLD_SLIC_STATE_OHTPR:	// OHT polarity reversal
+			case PLD_SLIC_STATE_OHTPR:	// OHT polarity reversal
 
-		j->pld_slicw.bits.c1 = 1;
-		j->pld_slicw.bits.c2 = 1;
-		j->pld_slicw.bits.c3 = 1;
-		j->pld_slicw.bits.b2en = 0;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		fRetVal = TRUE;
-		break;
-	default:
-		fRetVal = FALSE;
-		break;
+			default:
+				fRetVal = FALSE;
+				break;
+			}
+			j->psccr.bits.dev = 3;
+			j->psccr.bits.rw = 0;
+			outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);
+			ixj_PCcontrol_wait(board);
+		}
+	} else {
+		// Set the C1, C2, C3 & B2EN signals.
+		switch (byState) {
+		case PLD_SLIC_STATE_OC:
+			j->pld_slicw.bits.c1 = 0;
+			j->pld_slicw.bits.c2 = 0;
+			j->pld_slicw.bits.c3 = 0;
+			j->pld_slicw.bits.b2en = 0;
+			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
+			fRetVal = TRUE;
+			break;
+		case PLD_SLIC_STATE_RINGING:
+			j->pld_slicw.bits.c1 = 1;
+			j->pld_slicw.bits.c2 = 0;
+			j->pld_slicw.bits.c3 = 0;
+			j->pld_slicw.bits.b2en = 1;
+			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
+			fRetVal = TRUE;
+			break;
+		case PLD_SLIC_STATE_ACTIVE:
+			j->pld_slicw.bits.c1 = 0;
+			j->pld_slicw.bits.c2 = 1;
+			j->pld_slicw.bits.c3 = 0;
+			j->pld_slicw.bits.b2en = 0;
+			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
+			fRetVal = TRUE;
+			break;
+		case PLD_SLIC_STATE_OHT:	// On-hook transmit
+
+			j->pld_slicw.bits.c1 = 1;
+			j->pld_slicw.bits.c2 = 1;
+			j->pld_slicw.bits.c3 = 0;
+			j->pld_slicw.bits.b2en = 0;
+			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
+			fRetVal = TRUE;
+			break;
+		case PLD_SLIC_STATE_TIPOPEN:
+			j->pld_slicw.bits.c1 = 0;
+			j->pld_slicw.bits.c2 = 0;
+			j->pld_slicw.bits.c3 = 1;
+			j->pld_slicw.bits.b2en = 0;
+			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
+			fRetVal = TRUE;
+			break;
+		case PLD_SLIC_STATE_STANDBY:
+			j->pld_slicw.bits.c1 = 1;
+			j->pld_slicw.bits.c2 = 0;
+			j->pld_slicw.bits.c3 = 1;
+			j->pld_slicw.bits.b2en = 1;
+			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
+			fRetVal = TRUE;
+			break;
+		case PLD_SLIC_STATE_APR:	// Active polarity reversal
+
+			j->pld_slicw.bits.c1 = 0;
+			j->pld_slicw.bits.c2 = 1;
+			j->pld_slicw.bits.c3 = 1;
+			j->pld_slicw.bits.b2en = 0;
+			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
+			fRetVal = TRUE;
+			break;
+		case PLD_SLIC_STATE_OHTPR:	// OHT polarity reversal
+
+			j->pld_slicw.bits.c1 = 1;
+			j->pld_slicw.bits.c2 = 1;
+			j->pld_slicw.bits.c3 = 1;
+			j->pld_slicw.bits.b2en = 0;
+			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
+			fRetVal = TRUE;
+			break;
+		default:
+			fRetVal = FALSE;
+			break;
+		}
 	}
 
 	return fRetVal;
@@ -361,51 +482,42 @@
 	add_timer(&ixj_timer);
 }
 
-static void ixj_del_timer(void)
-{
-	del_timer(&ixj_timer);
-}
-
 static void ixj_tone_timeout(int board)
 {
 	IXJ *j = &ixj[board];
 	IXJ_TONE ti;
-	
+
 	j->tone_state++;
 	if (j->tone_state == 3) {
 		j->tone_state = 0;
 		if (j->cadence_t) {
 			j->tone_cadence_state++;
-			if (j->tone_cadence_state >= j->cadence_t->elements_used) 
-			{
-				switch (j->cadence_t->termination) 
-				{
-					case PLAY_ONCE:
-						ixj_cpt_stop(board);
-							break;
-					case REPEAT_LAST_ELEMENT:
-						j->tone_cadence_state--;
-						ixj_play_tone(board, j->cadence_t->ce[j->tone_cadence_state].index);
-						break;
-					case REPEAT_ALL:
-						j->tone_cadence_state = 0;
-						if (j->cadence_t->ce[j->tone_cadence_state].freq0) 
-						{
-							ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index;
-							ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0;
-							ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;
-							ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;
-							ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;
-							ixj_init_tone(board, &ti);
-						}
-						ixj_set_tone_on(j->cadence_t->ce[0].tone_on_time, board);
-						ixj_set_tone_off(j->cadence_t->ce[0].tone_off_time, board);
-						ixj_play_tone(board, j->cadence_t->ce[0].index);
-						break;
+			if (j->tone_cadence_state >= j->cadence_t->elements_used) {
+				switch (j->cadence_t->termination) {
+				case PLAY_ONCE:
+					ixj_cpt_stop(board);
+					break;
+				case REPEAT_LAST_ELEMENT:
+					j->tone_cadence_state--;
+					ixj_play_tone(board, j->cadence_t->ce[j->tone_cadence_state].index);
+					break;
+				case REPEAT_ALL:
+					j->tone_cadence_state = 0;
+					if (j->cadence_t->ce[j->tone_cadence_state].freq0) {
+						ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index;
+						ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0;
+						ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;
+						ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;
+						ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;
+						ixj_init_tone(board, &ti);
+					}
+					ixj_set_tone_on(j->cadence_t->ce[0].tone_on_time, board);
+					ixj_set_tone_off(j->cadence_t->ce[0].tone_off_time, board);
+					ixj_play_tone(board, j->cadence_t->ce[0].index);
+					break;
 				}
 			} else {
-				if (j->cadence_t->ce[j->tone_cadence_state].gain0) 
-				{
+				if (j->cadence_t->ce[j->tone_cadence_state].gain0) {
 					ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index;
 					ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0;
 					ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;
@@ -421,50 +533,50 @@
 	}
 }
 
+extern __inline__ void ixj_kill_fasync(int board)
+{
+	if (ixj[board].async_queue)
+		kill_fasync(ixj[board].async_queue, SIGIO);	// Send apps notice of change
+
+}
 static void ixj_timeout(unsigned long ptr)
 {
 	int board;
 	unsigned long jifon;
 	IXJ *j;
 
-	for (board = 0; board < IXJMAX; board++) 
-	{
+	for (board = 0; board < IXJMAX; board++) {
 		j = &ixj[board];
 
-		if (j->DSPbase) 
-		{
+		if (j->DSPbase) {
 #ifdef PERFMON_STATS
 			j->timerchecks++;
 #endif
-			if (j->tone_state) 
-			{
-				if (!ixj_hookstate(board)) 
-				{
+			if (j->tone_state) {
+				if (!ixj_hookstate(board)) {
 					ixj_cpt_stop(board);
-					if (j->m_hook) 
-					{
+					if (j->m_hook) {
 						j->m_hook = 0;
 						j->ex.bits.hookstate = 1;
-						if (j->async_queue)
-							kill_fasync(j->async_queue, SIGIO);	// Send apps notice of change
+						ixj_kill_fasync(board);
 					}
-					goto timer_end;
+					continue;
 				}
 				if (j->tone_state == 1)
 					jifon = (hertz * j->tone_on_time * 25 / 100000);
 				else
 					jifon = (hertz * j->tone_on_time * 25 / 100000) +
 					    (hertz * j->tone_off_time * 25 / 100000);
-				if (jiffies < j->tone_start_jif + jifon) {
+				if (time_before(jiffies, j->tone_start_jif + jifon)) {
 					if (j->tone_state == 1) {
 						ixj_play_tone(board, j->tone_index);
 						if (j->dsp.low == 0x20) {
-							goto timer_end;
+							continue;
 						}
 					} else {
 						ixj_play_tone(board, 0);
 						if (j->dsp.low == 0x20) {
-							goto timer_end;
+							continue;
 						}
 					}
 				} else {
@@ -475,13 +587,13 @@
 					if (j->flags.busytone) {
 						ixj_busytone(board);
 						if (j->dsp.low == 0x20) {
-							goto timer_end;
+							continue;
 						}
 					}
 					if (j->flags.ringback) {
 						ixj_ringback(board);
 						if (j->dsp.low == 0x20) {
-							goto timer_end;
+							continue;
 						}
 					}
 					if (!j->tone_state) {
@@ -498,7 +610,7 @@
 				if (IsRxReady(board)) {
 					ixj_read_frame(board);
 				}
-				if (IsTxReady(board)) {
+				if (IsTxReady(board) && !j->flags.cidplay) {
 					ixj_write_frame(board);
 				}
 			}
@@ -507,7 +619,12 @@
 					j->flags.cringing = 0;
 					ixj_ring_off(board);
 				} else {
-					if (jiffies - j->ring_cadence_jif >= (hertz/2)) {
+					if (jiffies - j->ring_cadence_jif >= (.5 * hertz)) {
+						if (j->flags.cidring && !j->flags.cidsent) {
+							j->flags.cidsent = 1;
+							ixj_write_cid(board);
+							j->flags.cidring = 0;
+						}
 						j->ring_cadence_t--;
 						if (j->ring_cadence_t == -1)
 							j->ring_cadence_t = 15;
@@ -517,16 +634,15 @@
 						ixj_ring_on(board);
 					} else {
 						ixj_ring_off(board);
+						j->flags.cidring = 1;
 					}
-					goto timer_end;
+					continue;
 				}
 			}
 			if (!j->flags.ringing) {
 				if (ixj_hookstate(board)) {
-					if ((j->dsp.low == 0x21 || j->dsp.low == 0x22 )&&
-					    j->pld_slicr.bits.state != PLD_SLIC_STATE_ACTIVE)
-               // Internet LineJACK
-					{
+					if (j->dsp.low != 0x20 &&
+					    SLIC_GetState(board) != PLD_SLIC_STATE_ACTIVE) {
 						SLIC_SetState(PLD_SLIC_STATE_ACTIVE, board);
 					}
 					LineMonitor(board);
@@ -535,13 +651,12 @@
 					j->proc_load = j->ssr.high << 8 | j->ssr.low;
 					if (!j->m_hook) {
 						j->m_hook = j->ex.bits.hookstate = 1;
-						if (j->async_queue)
-							kill_fasync(j->async_queue, SIGIO);	// Send apps notice of change
+						ixj_kill_fasync(board);
 					}
 				} else {
-					if ((j->dsp.low == 0x21 || j->dsp.low == 0x22) &&
-					    j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE)
-               // Internet LineJACK
+					if (j->dsp.low != 0x20 &&
+					    SLIC_GetState(board) == PLD_SLIC_STATE_ACTIVE)
+						// Internet LineJACK
 					{
 						SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
 					}
@@ -551,15 +666,14 @@
 					if (j->m_hook) {
 						j->m_hook = 0;
 						j->ex.bits.hookstate = 1;
-						if (j->async_queue)
-							kill_fasync(j->async_queue, SIGIO);	// Send apps notice of change
+						ixj_kill_fasync(board);
 					}
 				}
 			}
-			if (j->cardtype == 300) {
+			if (j->cardtype == 300 && !j->flags.incheck) {
 				if (j->flags.pstn_present) {
 					j->pld_scrr.byte = inb_p(j->XILINXbase);
-					if (jiffies >= j->pstn_sleeptil && j->pld_scrr.bits.daaflag) {
+					if (j->pld_scrr.bits.daaflag) {
 						daa_int_read(board);
 						if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.RING) {
 							if (!j->flags.pstn_ringing) {
@@ -568,22 +682,38 @@
 									daa_set_mode(board, SOP_PU_RINGING);
 							}
 						}
-						if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
+						if (time_after(jiffies, j->pstn_sleeptil) && j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
 							j->pstn_winkstart = 0;
+							j->pstn_ring_stop = 0;
+							ixj[board].pld_scrw.bits.led1 = 1;
 							if (j->flags.pstn_ringing && !j->pstn_envelope) {
+								if (j->daa_mode != SOP_PU_RINGING) {
+									j->flags.pstn_ringing = 0;
+								} else {
+									ixj[board].pld_scrw.bits.led2 = 0;
+									j->pstn_envelope = 1;
+									j->pstn_ring_start = jiffies;
+									j->pstn_ring_stop = 0;
+								}
 								j->ex.bits.pstn_ring = 0;
-								j->pstn_envelope = 1;
-								j->pstn_ring_start = jiffies;
 							}
+							outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase);
 						} else {
-							if (j->flags.pstn_ringing && j->pstn_envelope &&
-							    jiffies > j->pstn_ring_start + ((hertz * 15) / 10)) {
-								j->ex.bits.pstn_ring = 1;
-								j->pstn_envelope = 0;
+							ixj[board].pld_scrw.bits.led1 = 0;
+							ixj[board].pld_scrw.bits.led2 = 1;
+							outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase);
+							if (j->flags.pstn_ringing && j->pstn_envelope) {
+								if(!j->pstn_ring_stop) {
+									j->pstn_ring_stop = jiffies;
+								} else if (time_after(jiffies, j->pstn_ring_stop + ((hertz * 5) / 100))){
+									j->pstn_ring_stop = 0;
+									j->ex.bits.pstn_ring = 1;
+									j->pstn_envelope = 0;
+								}
 							} else if (j->daa_mode == SOP_PU_CONVERSATION) {
 								if (!j->pstn_winkstart) {
 									j->pstn_winkstart = jiffies;
-								} else if (jiffies > j->pstn_winkstart + (hertz * j->winktime / 1000)) {
+								} else if (time_after(jiffies, j->pstn_winkstart + (hertz * j->winktime / 1000))) {
 									daa_set_mode(board, SOP_PU_SLEEP);
 									j->pstn_winkstart = 0;
 									j->ex.bits.pstn_wink = 1;
@@ -620,13 +750,23 @@
 							j->ex.bits.caller_id = 0;
 						}
 						if (!j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
+							ixj[board].pld_scrw.bits.led1 = 0;
+							ixj[board].pld_scrw.bits.led2 = 1;
+							outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase);
 							if (j->flags.pstn_ringing && j->pstn_envelope) {
-								j->ex.bits.pstn_ring = 1;
-								j->pstn_envelope = 0;
+								if(!j->pstn_ring_stop) {
+									j->pstn_ring_stop = jiffies;
+								} else if (time_after(jiffies, j->pstn_ring_stop + ((hertz * 5) / 100))){
+									j->pstn_ring_stop = 0;
+									j->ex.bits.pstn_ring = 1;
+									j->pstn_envelope = 0;
+								}
+								ixj[board].pld_scrw.bits.led1 = 0;
+								outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase);
 							} else if (j->daa_mode == SOP_PU_CONVERSATION) {
 								if (!j->pstn_winkstart) {
 									j->pstn_winkstart = jiffies;
-								} else if (jiffies > j->pstn_winkstart + (hertz * 320 / 1000)) {
+								} else if (time_after(jiffies, j->pstn_winkstart + (hertz * j->winktime / 1000))) {
 									daa_set_mode(board, SOP_PU_SLEEP);
 									j->pstn_winkstart = 0;
 									j->ex.bits.pstn_wink = 1;
@@ -636,19 +776,15 @@
 					}
 				}
 			}
-			if ((j->ex.bits.f0 || j->ex.bits.f1 || j->ex.bits.f2 || j->ex.bits.f3)
-			    && j->filter_cadence) {
-			}
 			if (j->ex.bytes) {
 				wake_up_interruptible(&j->poll_q);	// Wake any blocked selects
-				if (j->async_queue)
-					kill_fasync(j->async_queue, SIGIO);	// Send apps notice of change
+
+				ixj_kill_fasync(board);
 			}
 		} else {
 			break;
 		}
 	}
-timer_end:
 	ixj_add_timer();
 }
 
@@ -665,6 +801,19 @@
 	return 0;
 }
 
+static int ixj_PCcontrol_wait(int board)
+{
+	unsigned long jif;
+
+	jif = jiffies;
+	while (!IsPCControlReady(board)) {
+		if (jiffies - jif > (60 * (hertz / 100))) {
+			return -1;
+		}
+	}
+	return 0;
+}
+
 int ixj_WriteDSPCommand(unsigned short cmd, int board)
 {
 	BYTES bytes;
@@ -710,7 +859,7 @@
 
 extern __inline__ void LED_SetState(int state, int board)
 {
-	if (ixj[board].dsp.low == 0x21) {
+	if (ixj[board].cardtype == 300) {
 		ixj[board].pld_scrw.bits.led1 = state & 0x1 ? 1 : 0;
 		ixj[board].pld_scrw.bits.led2 = state & 0x2 ? 1 : 0;
 		ixj[board].pld_scrw.bits.led3 = state & 0x4 ? 1 : 0;
@@ -748,12 +897,19 @@
 	case PORT_POTS:
 		j->port = PORT_POTS;
 		switch (j->cardtype) {
+		case 600:
+			if (j->flags.pcmciasct == 1)
+				SLIC_SetState(PLD_SLIC_STATE_ACTIVE, board);
+			else
+				return 11;
+			break;
 		case 500:
 			j->pld_slicw.pcib.mic = 0;
 			j->pld_slicw.pcib.spk = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
 			break;
 		case 300:
+			ixj_set_pots(board, 0);
 			if (ixj_WriteDSPCommand(0xC528, board))		/* Write CODEC config to
 									   Software Control Register */
 				return 2;
@@ -791,12 +947,21 @@
 	case PORT_SPEAKER:
 		j->port = PORT_SPEAKER;
 		switch (j->cardtype) {
+		case 600:
+			if (j->flags.pcmciasct) {
+				SLIC_SetState(PLD_SLIC_STATE_OC, board);
+//                              while(SLIC_GetState(board) != PLD_SLIC_STATE_OC) {
+				//                                      SLIC_SetState(PLD_SLIC_STATE_OC,board);
+				//                              }
+			}
+			break;
 		case 500:
 			j->pld_slicw.pcib.mic = 1;
 			j->pld_slicw.pcib.spk = 1;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
 			break;
 		case 300:
+			ixj_set_pots(board, 0);
 			break;
 		case 100:
 			j->gpio.bytes.high = 0x0B;
@@ -861,8 +1026,7 @@
 		j->gpio.bits.gpio2 = 1;
 		j->gpio.bits.gpio5 = 0;
 		ixj_WriteDSPCommand(j->gpio.word, board);	/* send the ring signal */
-	} else			//  Internet LineJACK, Internet PhoneJACK Lite or
-              //  Internet PhoneJACK PCI
+	} else			// Internet LineJACK, Internet PhoneJACK Lite or Internet PhoneJACK PCI
 	 {
 		if (ixjdebug > 0)
 			printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", board);
@@ -871,6 +1035,212 @@
 	}
 }
 
+static int ixj_pcmcia_cable_check(int board)
+{
+	IXJ *j = &ixj[board];
+
+	j->pccr1.byte = inb_p(j->XILINXbase + 0x03);
+	if (!j->flags.pcmciastate) {
+		j->pccr2.byte = inb_p(j->XILINXbase + 0x02);
+		if (j->pccr1.bits.drf || j->pccr2.bits.rstc) {
+			j->flags.pcmciastate = 4;
+			return 0;
+		}
+		if (j->pccr1.bits.ed) {
+			j->pccr1.bits.ed = 0;
+			j->psccr.bits.dev = 3;
+			j->psccr.bits.rw = 1;
+			outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00);
+			ixj_PCcontrol_wait(board);
+			j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF;
+			j->pslic.bits.led2 = j->pslic.bits.det ? 1 : 0;
+			j->psccr.bits.dev = 3;
+			j->psccr.bits.rw = 0;
+			outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);
+			ixj_PCcontrol_wait(board);
+			return j->pslic.bits.led2 ? 1 : 0;
+		} else if (j->flags.pcmciasct) {
+			return j->r_hook;
+		} else {
+			return 1;
+		}
+	} else if (j->flags.pcmciastate == 4) {
+		if (!j->pccr1.bits.drf) {
+			j->flags.pcmciastate = 3;
+		}
+		return 0;
+	} else if (j->flags.pcmciastate == 3) {
+		j->pccr2.bits.pwr = 0;
+		j->pccr2.bits.rstc = 1;
+		outb_p(j->pccr2.byte, j->XILINXbase + 0x02);
+		j->checkwait = jiffies + hertz * 2;
+		j->flags.incheck = 1;
+		j->flags.pcmciastate = 2;
+		return 0;
+	} else if (j->flags.pcmciastate == 2) {
+		if (j->flags.incheck) {
+			if (time_before(jiffies, j->checkwait)) {
+				return 0;
+			} else {
+				j->flags.incheck = 0;
+			}
+		}
+		j->pccr2.bits.pwr = 0;
+		j->pccr2.bits.rstc = 0;
+		outb_p(j->pccr2.byte, j->XILINXbase + 0x02);
+		j->flags.pcmciastate = 1;
+		return 0;
+	} else if (j->flags.pcmciastate == 1) {
+		j->flags.pcmciastate = 0;
+		if (!j->pccr1.bits.drf) {
+			j->psccr.bits.dev = 3;
+			j->psccr.bits.rw = 1;
+			outb_p(j->psccr.byte, j->XILINXbase + 0x01);
+			ixj_PCcontrol_wait(board);
+			j->flags.pcmciascp = 1;		// Set Cable Present Flag
+
+			j->flags.pcmciasct = (inw_p(j->XILINXbase + 0x00) >> 8) & 0x03;		// Get Cable Type
+
+			if (j->flags.pcmciasct == 3) {
+				j->flags.pcmciastate = 4;
+				return 0;
+			} else if (j->flags.pcmciasct == 0) {
+				j->pccr2.bits.pwr = 1;
+				j->pccr2.bits.rstc = 0;
+				outb_p(j->pccr2.byte, j->XILINXbase + 0x02);
+				j->port = PORT_SPEAKER;
+			} else {
+				j->port = PORT_POTS;
+			}
+			j->sic1.bits.cpd = 0;	// Chip Power Down
+
+			j->sic1.bits.mpd = 0;	// MIC Bias Power Down
+
+			j->sic1.bits.hpd = 0;	// Handset Bias Power Down
+
+			j->sic1.bits.lpd = 0;	// Line Bias Power Down
+
+			j->sic1.bits.spd = 1;	// Speaker Drive Power Down
+
+			j->psccr.bits.addr = 1;		// R/W Smart Cable Register Address
+
+			j->psccr.bits.rw = 0;	// Read / Write flag
+
+			j->psccr.bits.dev = 0;
+			outb(j->sic1.byte, j->XILINXbase + 0x00);
+			outb(j->psccr.byte, j->XILINXbase + 0x01);
+			ixj_PCcontrol_wait(board);
+			j->sic2.bits.al = 0;	// Analog Loopback DAC analog -> ADC analog
+
+			j->sic2.bits.dl2 = 0;	// Digital Loopback DAC -> ADC one bit
+
+			j->sic2.bits.dl1 = 0;	// Digital Loopback ADC -> DAC one bit
+
+			j->sic2.bits.pll = 0;	// 1 = div 10, 0 = div 5
+
+			j->sic2.bits.hpd = 0;	// HPF disable
+
+			j->psccr.bits.addr = 2;		// R/W Smart Cable Register Address
+
+			j->psccr.bits.rw = 0;	// Read / Write flag
+
+			j->psccr.bits.dev = 0;
+			outb(j->sic2.byte, j->XILINXbase + 0x00);
+			outb(j->psccr.byte, j->XILINXbase + 0x01);
+			ixj_PCcontrol_wait(board);
+			j->psccr.bits.addr = 3;		// R/W Smart Cable Register Address
+
+			j->psccr.bits.rw = 0;	// Read / Write flag
+
+			j->psccr.bits.dev = 0;
+			outb(0x00, j->XILINXbase + 0x00);	// PLL Divide N1
+
+			outb(j->psccr.byte, j->XILINXbase + 0x01);
+			ixj_PCcontrol_wait(board);
+			j->psccr.bits.addr = 4;		// R/W Smart Cable Register Address
+
+			j->psccr.bits.rw = 0;	// Read / Write flag
+
+			j->psccr.bits.dev = 0;
+			outb(0x09, j->XILINXbase + 0x00);	// PLL Multiply M1
+
+			outb(j->psccr.byte, j->XILINXbase + 0x01);
+			ixj_PCcontrol_wait(board);
+			j->sirxg.bits.lig = 1;	// Line In Gain
+
+			j->sirxg.bits.lim = 1;	// Line In Mute
+
+			j->sirxg.bits.mcg = 0;	// MIC In Gain // was 3
+
+			j->sirxg.bits.mcm = 0;	// MIC In Mute
+
+			j->sirxg.bits.him = 0;	// Handset In Mute
+
+			j->sirxg.bits.iir = 1;	// IIR
+
+			j->psccr.bits.addr = 5;		// R/W Smart Cable Register Address
+
+			j->psccr.bits.rw = 0;	// Read / Write flag
+
+			j->psccr.bits.dev = 0;
+			outb(j->sirxg.byte, j->XILINXbase + 0x00);
+			outb(j->psccr.byte, j->XILINXbase + 0x01);
+			ixj_PCcontrol_wait(board);
+			j->siadc.bits.hom = 0;	// Handset Out Mute
+
+			j->siadc.bits.lom = 0;	// Line Out Mute
+
+			j->siadc.bits.rxg = 23;		//(0xC000 - 0x41C8) / 0x4EF;    // RX PGA Gain
+
+			j->psccr.bits.addr = 6;		// R/W Smart Cable Register Address
+
+			j->psccr.bits.rw = 0;	// Read / Write flag
+
+			j->psccr.bits.dev = 0;
+			outb(j->siadc.byte, j->XILINXbase + 0x00);
+			outb(j->psccr.byte, j->XILINXbase + 0x01);
+			ixj_PCcontrol_wait(board);
+			j->sidac.bits.srm = 1;	// Speaker Right Mute
+
+			j->sidac.bits.slm = 1;	// Speaker Left Mute
+
+			j->sidac.bits.txg = (0xC000 - 0x45E4) / 0x5D3;	// TX PGA Gain
+
+			j->psccr.bits.addr = 7;		// R/W Smart Cable Register Address
+
+			j->psccr.bits.rw = 0;	// Read / Write flag
+
+			j->psccr.bits.dev = 0;
+			outb(j->sidac.byte, j->XILINXbase + 0x00);
+			outb(j->psccr.byte, j->XILINXbase + 0x01);
+			ixj_PCcontrol_wait(board);
+			j->siaatt.bits.sot = 0;
+			j->psccr.bits.addr = 9;		// R/W Smart Cable Register Address
+
+			j->psccr.bits.rw = 0;	// Read / Write flag
+
+			j->psccr.bits.dev = 0;
+			outb(j->siaatt.byte, j->XILINXbase + 0x00);
+			outb(j->psccr.byte, j->XILINXbase + 0x01);
+			ixj_PCcontrol_wait(board);
+
+			if (j->flags.pcmciasct == 1 && !j->readers && !j->writers) {
+				j->psccr.byte = j->pslic.byte = 0;
+				j->pslic.bits.powerdown = 1;
+				j->psccr.bits.dev = 3;
+				j->psccr.bits.rw = 0;
+				outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);
+				ixj_PCcontrol_wait(board);
+			}
+		}
+		return 0;
+	} else {
+		j->flags.pcmciascp = 0;
+		return 0;
+	}
+	return 0;
+}
+
 static int ixj_hookstate(int board)
 {
 	unsigned long det;
@@ -887,12 +1257,9 @@
 	case 500:
 		SLIC_GetState(board);
 		if (j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE ||
-		    j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) 
-		{
-			if (j->flags.ringing) 
-			{
-				if(!in_interrupt())
-				{
+		    j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) {
+			if (j->flags.ringing) {
+				if (!in_interrupt()) {
 					det = jiffies + (hertz / 50);
 					while (time_before(jiffies, det)) {
 						current->state = TASK_INTERRUPTIBLE;
@@ -911,14 +1278,17 @@
 				fOffHook = j->pld_slicr.bits.det ? 1 : 0;
 		}
 		break;
+	case 600:
+		fOffHook = ixj_pcmcia_cable_check(board);
+		break;
 	}
 	if (j->r_hook != fOffHook) {
 		j->r_hook = fOffHook;
 		if (j->port != PORT_POTS) {
 			j->ex.bits.hookstate = 1;
-			if (j->async_queue)
-				kill_fasync(j->async_queue, SIGIO);	// Send apps notice of change
-
+			ixj_kill_fasync(board);
+		} else if (!fOffHook) {
+			j->flash_end = jiffies + (hertz / 10 * 6);
 		}
 	}
 	if (j->port == PORT_PSTN && j->daa_mode == SOP_PU_CONVERSATION)
@@ -930,7 +1300,10 @@
 	if (j->port == PORT_HANDSET)
 		fOffHook |= 2;
 
-	return fOffHook;
+	if (fOffHook && time_before(jiffies, j->flash_end))
+		return 0;
+	else
+		return fOffHook;
 }
 
 static void ixj_ring_off(board)
@@ -952,7 +1325,7 @@
 		if (ixjdebug > 0)
 			printk(KERN_INFO "IXJ Ring Off\n");
 
-		SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);	
+		SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
 
 		SLIC_GetState(board);
 	}
@@ -1002,7 +1375,7 @@
 			}
 			current->state = TASK_INTERRUPTIBLE;
 			schedule_timeout(1);
-			if(signal_pending(current))
+			if (signal_pending(current))
 				break;
 		}
 		jif = jiffies + (3 * hertz);
@@ -1013,7 +1386,7 @@
 				while (time_before(jiffies, det)) {
 					current->state = TASK_INTERRUPTIBLE;
 					schedule_timeout(1);
-					if(signal_pending(current))
+					if (signal_pending(current))
 						break;
 				}
 				if (ixj_hookstate(board) & 1) {
@@ -1023,7 +1396,7 @@
 			}
 			current->state = TASK_INTERRUPTIBLE;
 			schedule_timeout(1);
-			if(signal_pending(current))
+			if (signal_pending(current))
 				break;
 		}
 	}
@@ -1034,40 +1407,70 @@
 
 int ixj_open(struct phone_device *p, struct file *file_p)
 {
-	IXJ *j = &ixj[p->board];
+	IXJ *j = file_p->private_data = &ixj[p->board];
 
 	if (!j->DSPbase)
 		return -ENODEV;
 
-	if (file_p->f_mode & FMODE_READ)
-		j->readers++;
-	if (file_p->f_mode & FMODE_WRITE)
-		j->writers++;
+        if (file_p->f_mode & FMODE_READ) {
+		if(!j->readers) {
+	                j->readers++;
+        	} else {
+                	return -EBUSY;
+		}
+        }
+
+	if (file_p->f_mode & FMODE_WRITE) {
+		if(!j->writers) {
+			j->writers++;
+		} else {
+			if (file_p->f_mode & FMODE_READ){
+				j->readers--;
+			}
+			return -EBUSY;
+		}
+	}
 
+	if (j->cardtype == 600) {
+		j->pslic.bits.powerdown = 0;
+		j->psccr.bits.dev = 3;
+		j->psccr.bits.rw = 0;
+		outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);
+		ixj_PCcontrol_wait(p->board);
+	}
 	MOD_INC_USE_COUNT;
 
 	if (ixjdebug > 0)
-//    printk(KERN_INFO "Opening board %d\n", NUM(inode->i_rdev));
 		printk(KERN_INFO "Opening board %d\n", p->board);
 
+	j->framesread = j->frameswritten = 0;
 	return 0;
 }
 
 int ixj_release(struct inode *inode, struct file *file_p)
 {
 	IXJ_TONE ti;
-	int board = NUM(inode->i_rdev);
-	IXJ *j = &ixj[board];
+//	int board = NUM(inode->i_rdev);
+	IXJ *j = file_p->private_data;
+	int board = j->p.board;
+//	IXJ *j = &ixj[board];
 
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Closing board %d\n", NUM(inode->i_rdev));
 
 	daa_set_mode(board, SOP_PU_SLEEP);
-	ixj_set_port(board, PORT_POTS);
+	if (j->cardtype == 600)
+		ixj_set_port(board, PORT_SPEAKER);
+	else
+		ixj_set_port(board, PORT_POTS);
 	aec_stop(board);
 	ixj_play_stop(board);
 	ixj_record_stop(board);
+	set_play_volume(board, 0x100);
+	set_rec_volume(board, 0x100);
+	ixj_ring_off(board);
 
+	// Restore the tone table to default settings.
 	ti.tone_index = 10;
 	ti.gain0 = 1;
 	ti.freq0 = hz941;
@@ -1176,6 +1579,10 @@
 
 	idle(board);
 
+//        if(j->cardtype == 600) { // && j->flags.pcmciasct == 1 && j->readers == 1 && j->writers == 1) {
+	SLIC_SetState(PLD_SLIC_STATE_OC, board);
+//      }
+
 	if (file_p->f_mode & FMODE_READ)
 		j->readers--;
 	if (file_p->f_mode & FMODE_WRITE)
@@ -1193,8 +1600,16 @@
 	}
 	j->rec_codec = j->play_codec = 0;
 	j->rec_frame_size = j->play_frame_size = 0;
+	j->flags.cidsent = j->flags.cidring = 0;
 	ixj_fasync(-1, file_p, 0);	// remove from list of async notification
 
+	if(j->cardtype == 300 && !j->readers && !j->writers) {
+		ixj_set_port(board, PORT_PSTN);
+		ixj_set_pots(board, 1);
+	}
+	ixj_WriteDSPCommand(0x0FE3, board);	// Put the DSP in 1/5 power mode.
+
+	file_p->private_data = NULL;
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -1202,6 +1617,7 @@
 static int read_filters(int board)
 {
 	unsigned short fc, cnt;
+	int var;
 	IXJ *j = &ixj[board];
 
 	if (ixj_WriteDSPCommand(0x5144, board))
@@ -1213,6 +1629,11 @@
 
 	j->frame_count = fc;
 
+	if (j->dtmf_proc)
+		return 1;
+
+	var = 10;
+
 	for (cnt = 0; cnt < 4; cnt++) {
 		if (ixj_WriteDSPCommand(0x5154 + cnt, board))
 			return -1;
@@ -1221,8 +1642,108 @@
 			return -1;
 
 		j->filter_hist[cnt] = j->ssr.high << 8 | j->ssr.low;
-		if ((j->filter_hist[cnt] & 1 && !(j->filter_hist[cnt] & 2)) ||
-		(j->filter_hist[cnt] & 2 && !(j->filter_hist[cnt] & 1))) {
+
+		if (j->cadence_f[cnt].enable) {
+			if (j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) {
+				if (j->cadence_f[cnt].state == 0) {
+					j->cadence_f[cnt].state = 1;
+					j->cadence_f[cnt].on1min = jiffies + (j->cadence_f[cnt].on1 * hertz * (100 - var) / 10000);
+					j->cadence_f[cnt].on1dot = jiffies + (j->cadence_f[cnt].on1 * hertz * (100) / 10000);
+					j->cadence_f[cnt].on1max = jiffies + (j->cadence_f[cnt].on1 * hertz * (100 + var) / 10000);
+				} else if (j->cadence_f[cnt].state == 2 &&
+					   (time_after(jiffies, j->cadence_f[cnt].off1min) &&
+					    time_before(jiffies, j->cadence_f[cnt].off1max))) {
+					if (j->cadence_f[cnt].on2) {
+						j->cadence_f[cnt].state = 3;
+						j->cadence_f[cnt].on2min = jiffies + (j->cadence_f[cnt].on2 * hertz * (100 - var) / 10000);
+						j->cadence_f[cnt].on2dot = jiffies + (j->cadence_f[cnt].on2 * hertz * (100) / 10000);
+						j->cadence_f[cnt].on2max = jiffies + (j->cadence_f[cnt].on2 * hertz * (100 + var) / 10000);
+					} else {
+						j->cadence_f[cnt].state = 6;
+					}
+				} else if (j->cadence_f[cnt].state == 4 &&
+					   (time_after(jiffies, j->cadence_f[cnt].off2min) &&
+					    time_before(jiffies, j->cadence_f[cnt].off2max))) {
+					if (j->cadence_f[cnt].on2) {
+						j->cadence_f[cnt].state = 5;
+						j->cadence_f[cnt].on3min = jiffies + (j->cadence_f[cnt].on3 * hertz * (100 - var) / 10000);
+						j->cadence_f[cnt].on3dot = jiffies + (j->cadence_f[cnt].on3 * hertz * (100) / 10000);
+						j->cadence_f[cnt].on3max = jiffies + (j->cadence_f[cnt].on3 * hertz * (100 + var) / 10000);
+					} else {
+						j->cadence_f[cnt].state = 6;
+					}
+				} else {
+					j->cadence_f[cnt].state = 0;
+				}
+			} else if (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)) {
+				if (j->cadence_f[cnt].state == 1 &&
+				    (time_after(jiffies, j->cadence_f[cnt].on1min) &&
+				     time_before(jiffies, j->cadence_f[cnt].on1max))) {
+					j->cadence_f[cnt].state = 2;
+					j->cadence_f[cnt].off1min = jiffies + (j->cadence_f[cnt].off1 * hertz * (100 - var) / 10000);
+					j->cadence_f[cnt].off1max = jiffies + (j->cadence_f[cnt].off1 * hertz * (100 + var) / 10000);
+				} else if (j->cadence_f[cnt].state == 3 &&
+					   (time_after(jiffies, j->cadence_f[cnt].on2min) &&
+					    time_before(jiffies, j->cadence_f[cnt].on2max))) {
+					j->cadence_f[cnt].state = 4;
+					j->cadence_f[cnt].off2min = jiffies + (j->cadence_f[cnt].off2 * hertz * (100 - var) / 10000);
+					j->cadence_f[cnt].off2max = jiffies + (j->cadence_f[cnt].off2 * hertz * (100 + var) / 10000);
+				} else if (j->cadence_f[cnt].state == 5 &&
+					   (time_after(jiffies, j->cadence_f[cnt].on3min) &&
+					    time_before(jiffies, j->cadence_f[cnt].on3max))) {
+					j->cadence_f[cnt].state = 6;
+					j->cadence_f[cnt].off3min = jiffies + (j->cadence_f[cnt].off3 * hertz * (100 - var) / 10000);
+					j->cadence_f[cnt].off3max = jiffies + (j->cadence_f[cnt].off3 * hertz * (100 + var) / 10000);
+				} else {
+					j->cadence_f[cnt].state = 0;
+				}
+			} else {
+				switch(j->cadence_f[cnt].state) {
+					case 1:
+						if(time_after(jiffies, j->cadence_f[cnt].on1dot) &&
+						   !j->cadence_f[cnt].off1 &&
+						   !j->cadence_f[cnt].on2 && !j->cadence_f[cnt].off2 &&
+						   !j->cadence_f[cnt].on3 && !j->cadence_f[cnt].off3) {
+							j->cadence_f[cnt].state = 6;
+						}
+						break;
+					case 3:
+						if(time_after(jiffies, j->cadence_f[cnt].on2dot) &&
+						   !j->cadence_f[cnt].off2 &&
+						   !j->cadence_f[cnt].on3 && !j->cadence_f[cnt].off3) {
+							j->cadence_f[cnt].state = 6;
+						}
+						break;
+					case 5:
+						if(time_after(jiffies, j->cadence_f[cnt].on3dot) &&
+						   !j->cadence_f[cnt].off3) {
+							j->cadence_f[cnt].state = 6;
+						}
+						break;
+				}
+			}
+		}
+		if (j->cadence_f[cnt].state == 6) {
+			j->cadence_f[cnt].state = 0;
+			if (j->cadence_f[cnt].enable == 1)
+				j->cadence_f[cnt].enable = 0;
+			switch (cnt) {
+			case 0:
+				j->ex.bits.fc0 = 1;
+				break;
+			case 1:
+				j->ex.bits.fc1 = 1;
+				break;
+			case 2:
+				j->ex.bits.fc2 = 1;
+				break;
+			case 3:
+				j->ex.bits.fc3 = 1;
+				break;
+			}
+		}
+		if (j->filter_en[cnt] && ((j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) ||
+					  (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)))) {
 			switch (cnt) {
 			case 0:
 				j->ex.bits.f0 = 1;
@@ -1263,11 +1784,16 @@
 	}
 	if (j->dtmf_state && !j->dtmf.bits.dtmf_valid)	// && j->dtmf_wp != j->dtmf_rp)
 	 {
-		j->dtmfbuffer[j->dtmf_wp] = j->dtmf_current;
-		j->dtmf_wp++;
-		if (j->dtmf_wp == 79)
-			j->dtmf_wp = 0;
-		j->ex.bits.dtmf_ready = 1;
+		if(!j->flags.cidplay) {
+			j->dtmfbuffer[j->dtmf_wp] = j->dtmf_current;
+			j->dtmf_wp++;
+			if (j->dtmf_wp == 79)
+				j->dtmf_wp = 0;
+			j->ex.bits.dtmf_ready = 1;
+		}
+		else if(j->dtmf_current == 25 || j->dtmf_current == 31) {
+			j->flags.cidcw_ack = 1;
+		}
 		j->dtmf_state = 0;
 	}
 	j->dtmf_proc = 0;
@@ -1282,26 +1808,38 @@
 	struct wait_queue wait =
 	{current, NULL};
 
+	if (j->flags.inread)
+		return -EALREADY;
+
+	j->flags.inread = 1;
+
 	add_wait_queue(&j->read_q, &wait);
 	current->state = TASK_INTERRUPTIBLE;
 	mb();
 
 	while (!j->read_buffer_ready || (j->dtmf_state && j->flags.dtmf_oob)) {
 		++j->read_wait;
+		if(j->tone_state) {
+			j->flags.inread = 0;
+			return -EAGAIN;
+		}
 		if (file_p->f_flags & O_NONBLOCK) {
 			current->state = TASK_RUNNING;
 			remove_wait_queue(&j->read_q, &wait);
+			j->flags.inread = 0;
 			return -EAGAIN;
 		}
 		if (!ixj_hookstate(NUM(file_p->f_dentry->d_inode->i_rdev))) {
 			current->state = TASK_RUNNING;
 			remove_wait_queue(&j->read_q, &wait);
+			j->flags.inread = 0;
 			return 0;
 		}
 		interruptible_sleep_on(&j->read_q);
 		if (signal_pending(current)) {
 			current->state = TASK_RUNNING;
 			remove_wait_queue(&j->read_q, &wait);
+			j->flags.inread = 0;
 			return -EINTR;
 		}
 	}
@@ -1311,10 +1849,13 @@
 	/* Don't ever copy more than the user asks */
 	i = copy_to_user(buf, j->read_buffer, min(length, j->read_buffer_size));
 	j->read_buffer_ready = 0;
-	if (i)
+	if (i) {
+		j->flags.inread = 0;
 		return -EFAULT;
-	else
+	} else {
+		j->flags.inread = 0;
 		return min(length, j->read_buffer_size);
+	}
 }
 
 ssize_t ixj_enhanced_read(struct file * file_p, char *buf, size_t length,
@@ -1342,51 +1883,63 @@
 	return read_retval;
 }
 
-ssize_t ixj_write(struct file * file_p, const char *buf, size_t count, loff_t * ppos)
+ssize_t ixj_write(struct file *file_p, const char *buf, size_t count, loff_t * ppos)
 {
 	unsigned long i = *ppos;
-	int board = NUM(file_p->f_dentry->d_inode->i_rdev);
-	IXJ *j = &ixj[board];
+	IXJ *j = file_p->private_data;
 	struct wait_queue wait =
 	{current, NULL};
 
-	add_wait_queue(&j->read_q, &wait);
+	if (j->flags.inwrite)
+		return -EALREADY;
+
+	j->flags.inwrite = 1;
+
+	add_wait_queue(&j->write_q, &wait);
 	current->state = TASK_INTERRUPTIBLE;
 	mb();
 
 
 	while (!j->write_buffers_empty) {
 		++j->write_wait;
+		if(j->tone_state) {
+			j->flags.inwrite = 0;
+			return -EAGAIN;
+		}
 		if (file_p->f_flags & O_NONBLOCK) {
 			current->state = TASK_RUNNING;
-			remove_wait_queue(&j->read_q, &wait);
+			remove_wait_queue(&j->write_q, &wait);
+			j->flags.inwrite = 0;
 			return -EAGAIN;
 		}
 		if (!ixj_hookstate(NUM(file_p->f_dentry->d_inode->i_rdev))) {
 			current->state = TASK_RUNNING;
-			remove_wait_queue(&j->read_q, &wait);
+			remove_wait_queue(&j->write_q, &wait);
+			j->flags.inwrite = 0;
 			return 0;
 		}
 		interruptible_sleep_on(&j->write_q);
 		if (signal_pending(current)) {
 			current->state = TASK_RUNNING;
-			remove_wait_queue(&j->read_q, &wait);
+			remove_wait_queue(&j->write_q, &wait);
+			j->flags.inwrite = 0;
 			return -EINTR;
 		}
 	}
 	current->state = TASK_RUNNING;
-	remove_wait_queue(&j->read_q, &wait);
+	remove_wait_queue(&j->write_q, &wait);
 	if (j->write_buffer_wp + count >= j->write_buffer_end)
 		j->write_buffer_wp = j->write_buffer;
 	i = copy_from_user(j->write_buffer_wp, buf, min(count, j->write_buffer_size));
-	if (i)
+	if (i) {
+		j->flags.inwrite = 0;
 		return -EFAULT;
-
+	}
+	j->flags.inwrite = 0;
 	return min(count, j->write_buffer_size);
 }
 
-ssize_t ixj_enhanced_write(struct file * file_p, const char *buf, size_t count,
-			   loff_t * ppos)
+ssize_t ixj_enhanced_write(struct file * file_p, const char *buf, size_t count, loff_t * ppos)
 {
 	int pre_retval;
 	ssize_t write_retval = 0;
@@ -1443,9 +1996,7 @@
 			*(j->read_buffer + cnt) = inb_p(j->DSPbase + 0x0E);
 			*(j->read_buffer + cnt + 1) = inb_p(j->DSPbase + 0x0F);
 		}
-#ifdef PERFMON_STATS
 		++j->framesread;
-#endif
 		if (j->intercom != -1) {
 			if (IsTxReady(j->intercom)) {
 				for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) {
@@ -1462,21 +2013,478 @@
 					outb_p(*(j->read_buffer + cnt), ixj[j->intercom].DSPbase + 0x0C);
 					outb_p(*(j->read_buffer + cnt + 1), ixj[j->intercom].DSPbase + 0x0D);
 				}
-#ifdef PERFMON_STATS
 				++ixj[j->intercom].frameswritten;
-#endif
 			}
 		} else {
 			j->read_buffer_ready = 1;
 			wake_up_interruptible(&j->read_q);	// Wake any blocked readers
 
-			wake_up_interruptible(&j->poll_q);	// Wake any blocked selects
+			wake_up_interruptible(&j->poll_q);	// Wake any blocked selects
+
+			ixj_kill_fasync(board);
+		}
+	}
+}
+
+static short fsk[][6][20] =
+{
+	{
+		{
+			0, 17846, 29934, 32364, 24351, 8481, -10126, -25465, -32587, -29196,
+			-16384, 1715, 19260, 30591, 32051, 23170, 6813, -11743, -26509, -32722
+		},
+		{
+			-28377, -14876, 3425, 20621, 31163, 31650, 21925, 5126, -13328, -27481,
+			-32767, -27481, -13328, 5126, 21925, 31650, 31163, 20621, 3425, -14876
+		},
+		{
+			-28377, -32722, -26509, -11743, 6813, 23170, 32051, 30591, 19260, 1715,
+			-16384, -29196, -32587, -25465, -10126, 8481, 24351, 32364, 29934, 17846
+		},
+		{
+			0, -17846, -29934, -32364, -24351, -8481, 10126, 25465, 32587, 29196,
+			16384, -1715, -19260, -30591, -32051, -23170, -6813, 11743, 26509, 32722
+		},
+		{
+			28377, 14876, -3425, -20621, -31163, -31650, -21925, -5126, 13328, 27481,
+			32767, 27481, 13328, -5126, -21925, -31650, -31163, -20621, -3425, 14876
+		},
+		{
+			28377, 32722, 26509, 11743, -6813, -23170, -32051, -30591, -19260, -1715,
+			16384, 29196, 32587, 25465, 10126, -8481, -24351, -32364, -29934, -17846
+		}
+	},
+	{
+		{
+			0, 10126, 19260, 26509, 31163, 32767, 31163, 26509, 19260, 10126,
+			0, -10126, -19260, -26509, -31163, -32767, -31163, -26509, -19260, -10126
+		},
+		{
+			-28377, -21925, -13328, -3425, 6813, 16384, 24351, 29934, 32587, 32051,
+			28377, 21925, 13328, 3425, -6813, -16384, -24351, -29934, -32587, -32051
+		},
+		{
+			-28377, -32051, -32587, -29934, -24351, -16384, -6813, 3425, 13328, 21925,
+			28377, 32051, 32587, 29934, 24351, 16384, 6813, -3425, -13328, -21925
+		},
+		{
+			0, -10126, -19260, -26509, -31163, -32767, -31163, -26509, -19260, -10126,
+			0, 10126, 19260, 26509, 31163, 32767, 31163, 26509, 19260, 10126
+		},
+		{
+			28377, 21925, 13328, 3425, -6813, -16383, -24351, -29934, -32587, -32051,
+			-28377, -21925, -13328, -3425, 6813, 16383, 24351, 29934, 32587, 32051
+		},
+		{
+			28377, 32051, 32587, 29934, 24351, 16384, 6813, -3425, -13328, -21925,
+			-28377, -32051, -32587, -29934, -24351, -16384, -6813, 3425, 13328, 21925
+		}
+	}
+};
+
+
+static void ixj_write_cid_bit(int board, int bit)
+{
+	int dly;
+	IXJ_WORD dat;
+	IXJ *j = &ixj[board];
+
+	while (j->fskcnt < 20) {
+		if (!IsTxReady(board)) {
+			dly = 0;
+			while (!IsTxReady(board)) {
+				if (dly++ > 5) {
+					dly = 0;
+					//      break;
+					//      printk("CID delay\n");
+				}
+				udelay(10);
+			}
+		}
+		dat.word = j->fskdata[j->fskdcnt++] =
+		    fsk[bit][j->fskz][j->fskcnt];
+		outb_p(dat.bytes.low, j->DSPbase + 0x0C);
+		outb_p(dat.bytes.high, j->DSPbase + 0x0D);
+		j->fskcnt += 3;
+	}
+	j->fskcnt %= 20;
+
+	if (!bit)
+		j->fskz++;
+	if (j->fskz >= 6)
+		j->fskz = 0;
+
+}
+
+static void ixj_write_cid_byte(int board, char byte)
+{
+	IXJ_CBYTE cb;
+
+//  printk("Writing CID data %x - %c\n", byte, byte);
+	cb.cbyte = byte;
+	ixj_write_cid_bit(board, 0);
+	ixj_write_cid_bit(board, cb.cbits.b0 ? 1 : 0);
+	ixj_write_cid_bit(board, cb.cbits.b1 ? 1 : 0);
+	ixj_write_cid_bit(board, cb.cbits.b2 ? 1 : 0);
+	ixj_write_cid_bit(board, cb.cbits.b3 ? 1 : 0);
+	ixj_write_cid_bit(board, cb.cbits.b4 ? 1 : 0);
+	ixj_write_cid_bit(board, cb.cbits.b5 ? 1 : 0);
+	ixj_write_cid_bit(board, cb.cbits.b6 ? 1 : 0);
+	ixj_write_cid_bit(board, cb.cbits.b7 ? 1 : 0);
+	ixj_write_cid_bit(board, 1);
+}
+
+static void ixj_write_cid_seize(int board)
+{
+	int cnt;
+
+	for (cnt = 0; cnt < 150; cnt++) {
+		ixj_write_cid_bit(board, 0);
+		ixj_write_cid_bit(board, 1);
+	}
+	for (cnt = 0; cnt < 180; cnt++) {
+		ixj_write_cid_bit(board, 1);
+	}
+}
+
+static void ixj_write_cidcw_seize(int board)
+{
+	int cnt;
+
+	for (cnt = 0; cnt < 80; cnt++) {
+		ixj_write_cid_bit(board, 1);
+	}
+}
+
+static int ixj_write_cid_string(int board, char *s, int checksum)
+{
+	int cnt;
+
+	for (cnt = 0; cnt < strlen(s); cnt++) {
+		ixj_write_cid_byte(board, s[cnt]);
+		checksum = (checksum + s[cnt]);
+	}
+	return checksum;
+}
+
+static void ixj_pad_fsk(int board, int pad)
+{
+	int cnt, dly;
+	IXJ *j = &ixj[board];
+
+	for (cnt = 0; cnt < pad; cnt++) {
+		if (!IsTxReady(board)) {
+			dly = 0;
+			while (!IsTxReady(board)) {
+				if (dly++ > 5) {
+					dly = 0;
+				}
+				udelay(10);
+			}
+		}
+		outb_p(0x00, j->DSPbase + 0x0C);
+		outb_p(0x00, j->DSPbase + 0x0D);
+	}
+	for (cnt = 0; cnt < 720; cnt++) {
+		if (!IsTxReady(board)) {
+			dly = 0;
+			while (!IsTxReady(board)) {
+				if (dly++ > 5) {
+					dly = 0;
+				}
+				udelay(10);
+			}
+		}
+		outb_p(0x00, j->DSPbase + 0x0C);
+		outb_p(0x00, j->DSPbase + 0x0D);
+	}
+}
+
+static void ixj_write_cid(int board)
+{
+	IXJ *j = &ixj[board];
+
+	char sdmf1[50];
+	char sdmf2[50];
+	char sdmf3[80];
+	char mdmflen, len1, len2, len3;
+	int pad;
+
+	int checksum = 0;
+
+	if (ixj[board].dsp.low == 0x20)
+		return;
+
+	ixj[board].fskz = ixj[board].fskphase = ixj[board].fskcnt =
+	    ixj[board].fskdcnt = 0;
+
+	ixj[board].flags.cidplay = 1;
+
+	strcpy(sdmf1, j->cid_send.month);
+	strcat(sdmf1, j->cid_send.day);
+	strcat(sdmf1, j->cid_send.hour);
+	strcat(sdmf1, j->cid_send.min);
+	strcpy(sdmf2, j->cid_send.number);
+	strcpy(sdmf3, j->cid_send.name);
+
+	len1 = strlen(sdmf1);
+	len2 = strlen(sdmf2);
+	len3 = strlen(sdmf3);
+	mdmflen = len1 + len2 + len3 + 6;
+
+	printk("CID Lengths = %d %d %d %d\n", len1, len2, len3, mdmflen);
+
+	set_base_frame(board, 30);
+	set_play_codec(board, LINEAR16);
+
+	if (ixj[board].port == PORT_POTS)
+		if(!j->r_hook)
+			SLIC_SetState(PLD_SLIC_STATE_OHT, board);
+
+	set_play_volume(board, 0x1B);
+	ixj_play_start(board);
+	ixj_write_cid_seize(board);
+
+	ixj_write_cid_byte(board, 0x80);
+	checksum = 0x80;
+	ixj_write_cid_byte(board, mdmflen);
+	checksum = checksum + mdmflen;
+
+	ixj_write_cid_byte(board, 0x01);
+	checksum = checksum + 0x01;
+	ixj_write_cid_byte(board, len1);
+	checksum = checksum + len1;
+	checksum = ixj_write_cid_string(board, sdmf1, checksum);
+
+	ixj_write_cid_byte(board, 0x02);
+	checksum = checksum + 0x02;
+	ixj_write_cid_byte(board, len2);
+	checksum = checksum + len2;
+	checksum = ixj_write_cid_string(board, sdmf2, checksum);
+
+	ixj_write_cid_byte(board, 0x07);
+	checksum = checksum + 0x07;
+	ixj_write_cid_byte(board, len3);
+	checksum = checksum + len3;
+	checksum = ixj_write_cid_string(board, sdmf3, checksum);
+
+	checksum %= 256;
+	checksum ^= 0xFF;
+	checksum += 1;
+	printk("14Checksum = %d\n", checksum);
+
+	ixj_write_cid_byte(board, (char) checksum);
+
+	pad = j->fskdcnt % 240;
+	if (pad) {
+		pad = 240 - pad;
+	}
+	ixj_pad_fsk(board, pad);
+	SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
+	ixj[board].flags.cidplay = 0;
+	ixj_play_stop(board);
+}
+
+static void ixj_write_cidcw(int board)
+{
+	IXJ_TONE ti;
+
+	IXJ *j = &ixj[board];
+
+	char sdmf1[50];
+	char sdmf2[50];
+	char sdmf3[80];
+	char mdmflen, len1, len2, len3;
+	int pad;
+
+	int checksum = 0;
+
+	if (ixj[board].dsp.low == 0x20)
+		return;
+
+	ixj[board].fskz = ixj[board].fskphase = ixj[board].fskcnt = ixj[board].fskdcnt = 0;
+
+	ixj[board].flags.cidplay = 1;
+
+	ti.tone_index = 23;
+	ti.gain0 = 1;
+	ti.freq0 = hz440;
+	ti.gain1 = 0;
+	ti.freq1 = 0;
+	ixj_init_tone(board, &ti);
+
+	ti.tone_index = 24;
+	ti.gain0 = 1;
+	ti.freq0 = hz2130;
+	ti.gain1 = 0;
+	ti.freq1 = hz2750;
+	ixj_init_tone(board, &ti);
+
+	ixj_set_tone_on(1200, board);
+	ixj_play_tone(board, 23);
+
+	while(j->tone_state) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+	}
+
+	ixj_set_tone_on(320, board);
+	ixj_play_tone(board, 24);
+
+	while(j->tone_state) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+	}
+
+	j->cidcw_wait = jiffies + (200 * hertz / 100000);
+
+	while(!j->flags.cidcw_ack && time_before(jiffies, j->cidcw_wait)) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+	}
+
+	if(!j->flags.cidcw_ack) {
+		return;
+	}
+
+	strcpy(sdmf1, j->cid_send.month);
+	strcat(sdmf1, j->cid_send.day);
+	strcat(sdmf1, j->cid_send.hour);
+	strcat(sdmf1, j->cid_send.min);
+	strcpy(sdmf2, j->cid_send.number);
+	strcpy(sdmf3, j->cid_send.name);
+
+	len1 = strlen(sdmf1);
+	len2 = strlen(sdmf2);
+	len3 = strlen(sdmf3);
+	mdmflen = len1 + len2 + len3 + 6;
+
+	printk("CID Lengths = %d %d %d %d\n", len1, len2, len3, mdmflen);
+
+	j->cid_play_codec = j->play_codec;
+	ixj_play_stop(board);
+
+	switch(j->baseframe.low) {
+		case 0xA0:
+			j->cid_base_frame_size = 20;
+			break;
+		case 0x50:
+			j->cid_base_frame_size = 10;
+			break;
+		default:
+			j->cid_base_frame_size = 30;
+			break;
+	}
+	set_base_frame(board, 30);
+	set_play_codec(board, LINEAR16);
+
+	set_play_volume(board, 0x1B);
+	ixj_play_start(board);
+	ixj_write_cidcw_seize(board);
+
+	ixj_write_cid_byte(board, 0x80);
+	checksum = 0x80;
+	ixj_write_cid_byte(board, mdmflen);
+	checksum = checksum + mdmflen;
+
+	ixj_write_cid_byte(board, 0x01);
+	checksum = checksum + 0x01;
+	ixj_write_cid_byte(board, len1);
+	checksum = checksum + len1;
+	checksum = ixj_write_cid_string(board, sdmf1, checksum);
+
+	ixj_write_cid_byte(board, 0x02);
+	checksum = checksum + 0x02;
+	ixj_write_cid_byte(board, len2);
+	checksum = checksum + len2;
+	checksum = ixj_write_cid_string(board, sdmf2, checksum);
+
+	ixj_write_cid_byte(board, 0x07);
+	checksum = checksum + 0x07;
+	ixj_write_cid_byte(board, len3);
+	checksum = checksum + len3;
+	checksum = ixj_write_cid_string(board, sdmf3, checksum);
+
+	checksum %= 256;
+	checksum ^= 0xFF;
+	checksum += 1;
+	printk("14Checksum = %d\n", checksum);
+
+	ixj_write_cid_byte(board, (char) checksum);
+
+	pad = j->fskdcnt % 240;
+	if (pad) {
+		pad = 240 - pad;
+	}
+	ixj_pad_fsk(board, pad);
+	ixj[board].flags.cidplay = 0;
+	ixj_play_stop(board);
+
+	set_base_frame(board, j->cid_base_frame_size);
+	set_play_codec(board, j->cid_play_codec);
+}
+
+static void ixj_write_vmwi(int board, int msg)
+{
+	IXJ *j = &ixj[board];
 
-			if (j->async_queue)
-				kill_fasync(j->async_queue, SIGIO);	// Send apps notice of frame
+	char mdmflen;
+	int pad;
 
-		}
+	int checksum = 0;
+
+	if (ixj[board].dsp.low == 0x20)
+		return;
+
+	ixj[board].fskz = ixj[board].fskphase = ixj[board].fskcnt = ixj[board].fskdcnt = 0;
+
+	ixj[board].flags.cidplay = 1;
+
+	mdmflen = 3;
+
+	set_base_frame(board, 30);
+	set_play_codec(board, LINEAR16);
+
+	if (ixj[board].port == PORT_POTS)
+		SLIC_SetState(PLD_SLIC_STATE_OHT, board);
+
+	set_play_volume(board, 0x1B);
+	ixj_play_start(board);
+	ixj_write_cid_seize(board);
+
+	ixj_write_cid_byte(board, 0x82);
+	checksum = 0x82;
+	ixj_write_cid_byte(board, mdmflen);
+	checksum = checksum + mdmflen;
+
+	ixj_write_cid_byte(board, 0x0B);
+	checksum = checksum + 0x0B;
+	ixj_write_cid_byte(board, 1);
+	checksum = checksum + 1;
+
+	if(msg) {
+		ixj_write_cid_byte(board, 0xFF);
+		checksum = checksum + 0xFF;
 	}
+	else {
+		ixj_write_cid_byte(board, 0x00);
+		checksum = checksum + 0x00;
+	}
+
+	checksum %= 256;
+	checksum ^= 0xFF;
+	checksum += 1;
+
+	ixj_write_cid_byte(board, (char) checksum);
+
+	pad = j->fskdcnt % 240;
+	if (pad) {
+		pad = 240 - pad;
+	}
+	ixj_pad_fsk(board, pad);
+	SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
+	ixj[board].flags.cidplay = 0;
+	ixj_play_stop(board);
 }
 
 static void ixj_write_frame(int board)
@@ -1554,15 +2562,12 @@
 				j->write_buffer_rp = j->write_buffer;
 			}
 			j->write_buffers_empty++;
-			wake_up_interruptible(&(j->write_q));	// Wake any blocked writers
+			wake_up_interruptible(&j->write_q);	// Wake any blocked writers
 
 			wake_up_interruptible(&j->poll_q);	// Wake any blocked selects
 
-			if (j->async_queue)
-				kill_fasync(j->async_queue, SIGIO);	// Send apps notice of empty buffer
-#ifdef PERFMON_STATS
+			ixj_kill_fasync(board);
 			++j->frameswritten;
-#endif
 		}
 	} else {
 		j->drybuffer++;
@@ -1795,6 +2800,12 @@
 	unsigned short cmd = 0x0000;
 	IXJ *j = &ixj[board];
 
+	if (j->read_buffer) {
+		ixj_record_stop(board);
+	}
+	j->flags.recording = 1;
+	ixj_WriteDSPCommand(0x0FE0, board);	// Put the DSP in full power mode.
+
 	if (!j->rec_mode) {
 		switch (j->rec_codec) {
 		case G723_63:
@@ -1893,10 +2904,26 @@
 {
 	IXJ *j = &ixj[board];
 
+	if (j->read_buffer) {
+		kfree(j->read_buffer);
+		j->read_buffer = NULL;
+		j->read_buffer_size = 0;
+	}
 	if (j->rec_mode > -1) {
 		ixj_WriteDSPCommand(0x5120, board);
 		j->rec_mode = -1;
 	}
+	j->flags.recording = 0;
+	if (!j->flags.playing)
+		ixj_WriteDSPCommand(0x0FE3, board);	// Put the DSP in 1/5 power mode.
+
+}
+static void ixj_vad(int board, int arg)
+{
+	if (arg)
+		ixj_WriteDSPCommand(0x513F, board);
+	else
+		ixj_WriteDSPCommand(0x513E, board);
 }
 
 static void set_rec_depth(int board, int depth)
@@ -1914,13 +2941,23 @@
 	ixj_WriteDSPCommand(volume, board);
 }
 
+static int get_rec_volume(int board)
+{
+	ixj_WriteDSPCommand(0xCF03, board);
+	return ixj[board].ssr.high << 8 | ixj[board].ssr.low;
+}
+
 static int get_rec_level(int board)
 {
+	int retval;
+
 	IXJ *j = &ixj[board];
 
 	ixj_WriteDSPCommand(0xCF88, board);
 
-	return j->ssr.high << 8 | j->ssr.low;
+	retval = j->ssr.high << 8 | j->ssr.low;
+	retval = (retval * 256) / 240;
+	return retval;
 }
 
 static void ixj_aec_start(int board, int level)
@@ -1929,7 +2966,7 @@
 
 	j->aec_level = level;
 	if (!level) {
-		ixj_WriteDSPCommand(0xB002, board);
+		aec_stop(board);
 	} else {
 		if (j->rec_codec == G729 || j->play_codec == G729) {
 			ixj_WriteDSPCommand(0xE022, board);	// Move AEC filter buffer
@@ -1941,26 +2978,41 @@
 		ixj_WriteDSPCommand(0xE013, board);	// Advanced AEC C1
 
 		switch (level) {
-		case 1:
+		case AEC_LOW:
 			ixj_WriteDSPCommand(0x0000, board);	// Advanced AEC C2 = off
 
 			ixj_WriteDSPCommand(0xE011, board);
 			ixj_WriteDSPCommand(0xFFFF, board);
 			break;
 
-		case 2:
+		case AEC_MED:
 			ixj_WriteDSPCommand(0x0600, board);	// Advanced AEC C2 = on medium
 
 			ixj_WriteDSPCommand(0xE011, board);
 			ixj_WriteDSPCommand(0x0080, board);
 			break;
 
-		case 3:
+		case AEC_HIGH:
 			ixj_WriteDSPCommand(0x0C00, board);	// Advanced AEC C2 = on high
 
 			ixj_WriteDSPCommand(0xE011, board);
 			ixj_WriteDSPCommand(0x0080, board);
 			break;
+
+		case AEC_AUTO:
+			ixj_WriteDSPCommand(0x0002, board);	// Attenuation scaling factor of 2
+
+			ixj_WriteDSPCommand(0xE011, board);
+			ixj_WriteDSPCommand(0x0100, board);	// Higher Threshold Floor
+
+			ixj_WriteDSPCommand(0xE012, board);	// Set Train and Lock
+
+			ixj_WriteDSPCommand(0x0023, board);
+
+			ixj_WriteDSPCommand(0xE014, board);
+			ixj_WriteDSPCommand(0x0003, board);	// Lock threashold at 3dB
+
+			break;
 		}
 	}
 }
@@ -1974,7 +3026,7 @@
 
 		ixj_WriteDSPCommand(0x0700, board);
 	}
-	if (ixj[board].play_mode != -1 && ixj[board].rec_mode != -1)
+	if (ixj[board].play_mode != -1 && ixj[board].rec_mode != -1);
 	{
 		ixj_WriteDSPCommand(0xB002, board);	// AEC Stop
 
@@ -2148,6 +3200,12 @@
 	unsigned short cmd = 0x0000;
 	IXJ *j = &ixj[board];
 
+	if (j->write_buffer) {
+		ixj_play_stop(board);
+	}
+	j->flags.playing = 1;
+	ixj_WriteDSPCommand(0x0FE0, board);	// Put the DSP in full power mode.
+
 	j->flags.play_first_frame = 1;
 	j->drybuffer = 0;
 
@@ -2183,12 +3241,10 @@
 		if (ixj_WriteDSPCommand(cmd, board))
 			return -1;
 	}
+	j->write_buffer = kmalloc(j->play_frame_size * 2, GFP_ATOMIC);
 	if (!j->write_buffer) {
-		j->write_buffer = kmalloc(j->play_frame_size * 2, GFP_ATOMIC);
-		if (!j->write_buffer) {
-			printk("Write buffer allocation for ixj board %d failed!\n", board);
-			return -ENOMEM;
-		}
+		printk("Write buffer allocation for ixj board %d failed!\n", board);
+		return -ENOMEM;
 	}
 	j->write_buffers_empty = 2;
 	j->write_buffer_size = j->play_frame_size * 2;
@@ -2250,11 +3306,20 @@
 {
 	IXJ *j = &ixj[board];
 
+	if (j->write_buffer) {
+		kfree(j->write_buffer);
+		j->write_buffer = NULL;
+		j->write_buffer_size = 0;
+	}
 	if (j->play_mode > -1) {
-		ixj_WriteDSPCommand(0x5221, board);	// Stop playback
+		ixj_WriteDSPCommand(0x5221, board);	// Stop playback and flush buffers.  8022 reference page 9-40
 
 		j->play_mode = -1;
 	}
+	j->flags.playing = 0;
+	if (!j->flags.recording)
+		ixj_WriteDSPCommand(0x0FE3, board);	// Put the DSP in 1/5 power mode.
+
 }
 
 extern __inline__ void set_play_depth(int board, int depth)
@@ -2266,16 +3331,15 @@
 	ixj_WriteDSPCommand(0x5280 + depth, board);
 }
 
-extern __inline__ void set_play_volume(int board, int volume)
-{
-	ixj_WriteDSPCommand(0xCF02, board);
-	ixj_WriteDSPCommand(volume, board);
-}
-
 extern __inline__ int get_play_level(int board)
 {
-	ixj_WriteDSPCommand(0xCF8F, board);
+	int retval;
+
+	ixj_WriteDSPCommand(0xCF8F, board); // 8022 Reference page 9-38
 	return ixj[board].ssr.high << 8 | ixj[board].ssr.low;
+	retval = ixj[board].ssr.high << 8 | ixj[board].ssr.low;
+	retval = (retval * 256) / 240;
+	return retval;
 }
 
 static unsigned int ixj_poll(struct file *file_p, poll_table * wait)
@@ -2484,6 +3548,8 @@
 		break;
 	}
 
+	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = reg;
+
 	switch (j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGX) {
 	case 0:
 		j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 0;
@@ -2653,7 +3719,7 @@
 		}
 		pIn += 5, pOut += 4;
 	}
-	memset(&j->cid, 0, sizeof(IXJ_CID));
+	memset(&j->cid, 0, sizeof(PHONE_CID));
 	pOut = j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID;
 	pOut += 4;
 	strncpy(j->cid.month, pOut, 2);
@@ -2729,7 +3795,6 @@
 	//      ALIS-A part.
 	//
 
-
 	BYTES bytes;
 	IXJ *j = &ixj[board];
 
@@ -2738,6 +3803,19 @@
 
 	switch (mode) {
 	case SOP_PU_SLEEP:
+		if(j->daa_mode == SOP_PU_CONVERSATION)
+		{
+			j->pld_scrw.bits.daafsyncen = 0;	// Turn off DAA Frame Sync
+
+			outb_p(j->pld_scrw.byte, j->XILINXbase);
+			j->pld_slicw.bits.rly2 = 0;
+			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
+			bytes.high = 0x10;
+			bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
+			daa_load(&bytes, board);
+			if (!SCI_Prepare(board))
+				return 0;
+		}
 		j->pld_scrw.bits.daafsyncen = 0;	// Turn off DAA Frame Sync
 
 		outb_p(j->pld_scrw.byte, j->XILINXbase);
@@ -2748,10 +3826,15 @@
 		daa_load(&bytes, board);
 		if (!SCI_Prepare(board))
 			return 0;
+
 		j->daa_mode = SOP_PU_SLEEP;
 		j->flags.pstn_ringing = 0;
-		j->pstn_sleeptil = jiffies + (hertz * 3);
-		break;
+		j->ex.bits.pstn_ring = 0;
+		j->pstn_sleeptil = jiffies + (hertz / 2);
+		wake_up_interruptible(&j->read_q);      // Wake any blocked readers
+		wake_up_interruptible(&j->write_q);     // Wake any blocked writers
+		wake_up_interruptible(&j->poll_q);      // Wake any blocked selects
+ 		break;
 	case SOP_PU_RINGING:
 		j->pld_scrw.bits.daafsyncen = 0;	// Turn off DAA Frame Sync
 
@@ -3289,14 +4372,11 @@
 int ixj_set_tone_off(unsigned short arg, int board)
 {
 	ixj[board].tone_off_time = arg;
-
 	if (ixj_WriteDSPCommand(0x6E05, board))		// Set Tone Off Period
 
 		return -1;
-
 	if (ixj_WriteDSPCommand(arg, board))
 		return -1;
-
 	return 0;
 }
 
@@ -3305,7 +4385,6 @@
 	if (ixj_WriteDSPCommand(0x6E06, board))		// Get Tone On Period
 
 		return -1;
-
 	return 0;
 }
 
@@ -3314,7 +4393,6 @@
 	if (ixj_WriteDSPCommand(0x6E07, board))		// Get Tone Off Period
 
 		return -1;
-
 	return 0;
 }
 
@@ -3323,7 +4401,6 @@
 	ixj[board].flags.ringback = 0;
 	ixj[board].flags.dialtone = 0;
 	ixj[board].flags.busytone = 1;
-
 	ixj_set_tone_on(0x07D0, board);
 	ixj_set_tone_off(0x07D0, board);
 	ixj_play_tone(board, 27);
@@ -3334,13 +4411,11 @@
 	ixj[board].flags.ringback = 0;
 	ixj[board].flags.dialtone = 1;
 	ixj[board].flags.busytone = 0;
-
 	if (ixj[board].dsp.low == 0x20) {
 		return;
 	} else {
 		ixj_set_tone_on(0xFFFF, board);
 		ixj_set_tone_off(0x0000, board);
-
 		ixj_play_tone(board, 25);
 	}
 }
@@ -3348,28 +4423,24 @@
 static void ixj_cpt_stop(board)
 {
 	IXJ *j = &ixj[board];
-
-	j->flags.dialtone = 0;
-	j->flags.busytone = 0;
-	j->flags.ringback = 0;
-
-	ixj_set_tone_on(0x0001, board);
-	ixj_set_tone_off(0x0000, board);
-
-	ixj_play_tone(board, 0);
-
-	j->tone_state = 0;
-
-	ixj_del_timer();
-	if (j->cadence_t) {
-		if (j->cadence_t->ce) {
-			kfree(j->cadence_t->ce);
+	if(j->tone_state)
+	{
+		j->flags.dialtone = 0;
+		j->flags.busytone = 0;
+		j->flags.ringback = 0;
+		ixj_set_tone_on(0x0001, board);
+		ixj_set_tone_off(0x0000, board);
+		ixj_play_tone(board, 0);
+		j->tone_state = 0;
+		if (j->cadence_t) {
+			if (j->cadence_t->ce) {
+				kfree(j->cadence_t->ce);
+			}
+			kfree(j->cadence_t);
+			j->cadence_t = NULL;
 		}
-		kfree(j->cadence_t);
-		j->cadence_t = NULL;
 	}
-	ixj_add_timer();
-	if (j->dsp.low == 0x20 || (j->play_mode == -1 && j->rec_mode == -1))
+	if (j->play_mode == -1 && j->rec_mode == -1)
 		idle(board);
 	if (j->play_mode != -1)
 		ixj_play_start(board);
@@ -3382,7 +4453,6 @@
 	ixj[board].flags.busytone = 0;
 	ixj[board].flags.dialtone = 0;
 	ixj[board].flags.ringback = 1;
-
 	ixj_set_tone_on(0x0FA0, board);
 	ixj_set_tone_off(0x2EE0, board);
 	ixj_play_tone(board, 26);
@@ -3399,14 +4469,11 @@
 	IXJ_CADENCE_ELEMENT *lcep;
 	IXJ_TONE ti;
 	IXJ *j = &ixj[board];
-
 	lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL);
 	if (lcp == NULL)
 		return -ENOMEM;
-
 	if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_CADENCE)))
 		return -EFAULT;
-
 	lcep = kmalloc(sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used, GFP_KERNEL);
 	if (lcep == NULL) {
 		kfree(lcp);
@@ -3414,13 +4481,10 @@
 	}
 	if (copy_from_user(lcep, lcp->ce, sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used))
 		return -EFAULT;
-
-	if(j->cadence_t)
-	{
+	if (j->cadence_t) {
 		kfree(j->cadence_t->ce);
 		kfree(j->cadence_t);
 	}
-	
 	lcp->ce = (void *) lcep;
 	j->cadence_t = lcp;
 	j->tone_cadence_state = 0;
@@ -3435,16 +4499,50 @@
 		ixj_init_tone(board, &ti);
 	}
 	ixj_play_tone(board, lcp->ce[0].index);
-
 	return 1;
 }
 
+static int ixj_build_filter_cadence(int board, IXJ_FILTER_CADENCE * cp)
+{
+	IXJ_FILTER_CADENCE *lcp;
+	IXJ *j = &ixj[board];
+	lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL);
+	if (lcp == NULL)
+		return -ENOMEM;
+	if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_FILTER_CADENCE)))
+		return -EFAULT;
+	if (lcp->filter > 4)
+		return -1;
+	j->cadence_f[lcp->filter].state = 0;
+	j->cadence_f[lcp->filter].enable = lcp->enable;
+	j->filter_en[lcp->filter] = j->cadence_f[lcp->filter].en_filter = lcp->en_filter;
+	j->cadence_f[lcp->filter].on1 = lcp->on1;
+	j->cadence_f[lcp->filter].on1min = 0;
+	j->cadence_f[lcp->filter].on1max = 0;
+	j->cadence_f[lcp->filter].off1 = lcp->off1;
+	j->cadence_f[lcp->filter].off1min = 0;
+	j->cadence_f[lcp->filter].off1max = 0;
+	j->cadence_f[lcp->filter].on2 = lcp->on2;
+	j->cadence_f[lcp->filter].on2min = 0;
+	j->cadence_f[lcp->filter].on2max = 0;
+	j->cadence_f[lcp->filter].off2 = lcp->off2;
+	j->cadence_f[lcp->filter].off2min = 0;
+	j->cadence_f[lcp->filter].off2max = 0;
+	j->cadence_f[lcp->filter].on3 = lcp->on3;
+	j->cadence_f[lcp->filter].on3min = 0;
+	j->cadence_f[lcp->filter].on3max = 0;
+	j->cadence_f[lcp->filter].off3 = lcp->off3;
+	j->cadence_f[lcp->filter].off3min = 0;
+	j->cadence_f[lcp->filter].off3max = 0;
+	kfree(lcp);
+	return 0;
+}
+
 static void add_caps(int board)
 {
 	IXJ *j = &ixj[board];
 	j->caps = 0;
-
-	j->caplist[j->caps].cap = vendor;
+	j->caplist[j->caps].cap = PHONE_VENDOR_QUICKNET;
 	strcpy(j->caplist[j->caps].desc, "Quicknet Technologies, Inc. (www.quicknet.net)");
 	j->caplist[j->caps].captype = vendor;
 	j->caplist[j->caps].handle = j->caps++;
@@ -3540,10 +4638,9 @@
 	int cnt;
 	IXJ *j = &ixj[board];
 	int retval = 0;
-
 	for (cnt = 0; cnt < j->caps; cnt++) {
-		if (pcreq->captype == j->caplist[cnt].captype &&
-		    pcreq->cap == j->caplist[cnt].cap) {
+		if (pcreq->captype == j->caplist[cnt].captype
+		    && pcreq->cap == j->caplist[cnt].cap) {
 			retval = 1;
 			break;
 		}
@@ -3551,8 +4648,7 @@
 	return retval;
 }
 
-int ixj_ioctl(struct inode *inode, struct file *file_p,
-	      unsigned int cmd, unsigned long arg)
+int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, unsigned long arg)
 {
 	IXJ_TONE ti;
 	IXJ_FILTER jf;
@@ -3560,16 +4656,13 @@
 	int board = NUM(inode->i_rdev);
 	IXJ *j = &ixj[NUM(inode->i_rdev)];
 	int retval = 0;
-
 	if (ixjdebug > 1)
 		printk(KERN_DEBUG "phone%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg);
 	if (minor >= IXJMAX)
 		return -ENODEV;
-
 	/*
 	 *    Check ioctls only root can use.
 	 */
-
 	if (!capable(CAP_SYS_ADMIN)) {
 		switch (cmd) {
 		case IXJCTL_TESTRAM:
@@ -3588,10 +4681,33 @@
 	case IXJCTL_SERIAL:
 		retval = j->serial;
 		break;
+	case IXJCTL_VERSION:
+		if (copy_to_user((char *) arg, ixj_c_revision, strlen(ixj_c_revision)))
+			return -EFAULT;
+		break;
 	case PHONE_RING_CADENCE:
 		j->ring_cadence = arg;
 		break;
+	case IXJCTL_CIDCW:
+		if(arg) {
+			copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID));
+		}
+		else {
+			memcpy(&j->cid_send, 0, sizeof(PHONE_CID));
+		}
+		ixj_write_cidcw(board);
+		break;
+	/* Binary compatbility */
+	case OLD_PHONE_RING_START:
+		arg = 0;
+		/* Fall through */
 	case PHONE_RING_START:
+		if(arg) {
+			copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID));
+		}
+		else {
+			memcpy(&j->cid_send, 0, sizeof(PHONE_CID));
+		}
 		ixj_ring_start(board);
 		break;
 	case PHONE_RING_STOP:
@@ -3603,7 +4719,19 @@
 		break;
 	case PHONE_EXCEPTION:
 		retval = j->ex.bytes;
-		j->ex.bytes &= 0x03;
+		j->ex.bits.flash = 0;
+		j->ex.bits.pstn_ring = 0;
+		j->ex.bits.caller_id = 0;
+		j->ex.bits.pstn_wink = 0;
+		j->ex.bits.f0 = 0;
+		j->ex.bits.f1 = 0;
+		j->ex.bits.f2 = 0;
+		j->ex.bits.f3 = 0;
+		j->ex.bits.fc0 = 0;
+		j->ex.bits.fc1 = 0;
+		j->ex.bits.fc2 = 0;
+		j->ex.bits.fc3 = 0;
+		j->ex.bits.reserved = 0;
 		break;
 	case PHONE_HOOKSTATE:
 		j->ex.bits.hookstate = 0;
@@ -3618,6 +4746,9 @@
 	case PHONE_REC_CODEC:
 		retval = set_rec_codec(board, arg);
 		break;
+	case PHONE_VAD:
+		ixj_vad(board, arg);
+		break;
 	case PHONE_REC_START:
 		ixj_record_start(board);
 		break;
@@ -3628,7 +4759,13 @@
 		set_rec_depth(board, arg);
 		break;
 	case PHONE_REC_VOLUME:
-		set_rec_volume(board, arg);
+		if(arg == -1) {
+			retval = get_rec_volume(board);
+		}
+		else {
+			set_rec_volume(board, arg);
+			retval = arg;
+		}
 		break;
 	case PHONE_REC_LEVEL:
 		retval = get_rec_level(board);
@@ -3646,7 +4783,7 @@
 		retval = set_play_codec(board, arg);
 		break;
 	case PHONE_PLAY_START:
-		ixj_play_start(board);
+		retval = ixj_play_start(board);
 		break;
 	case PHONE_PLAY_STOP:
 		ixj_play_stop(board);
@@ -3655,7 +4792,13 @@
 		set_play_depth(board, arg);
 		break;
 	case PHONE_PLAY_VOLUME:
-		set_play_volume(board, arg);
+		if(arg == -1) {
+			retval = get_play_volume(board);
+		}
+		else {
+			set_play_volume(board, arg);
+			retval = arg;
+		}
 		break;
 	case PHONE_PLAY_LEVEL:
 		retval = get_play_level(board);
@@ -3836,41 +4979,45 @@
 		switch (arg) {
 		case DAA_US:
 			DAA_Coeff_US(board);
-			ixj_daa_write(board);
+			retval = ixj_daa_write(board);
 			break;
 		case DAA_UK:
 			DAA_Coeff_UK(board);
-			ixj_daa_write(board);
+			retval = ixj_daa_write(board);
 			break;
 		case DAA_FRANCE:
 			DAA_Coeff_France(board);
-			ixj_daa_write(board);
+			retval = ixj_daa_write(board);
 			break;
 		case DAA_GERMANY:
 			DAA_Coeff_Germany(board);
-			ixj_daa_write(board);
+			retval = ixj_daa_write(board);
 			break;
 		case DAA_AUSTRALIA:
 			DAA_Coeff_Australia(board);
-			ixj_daa_write(board);
+			retval = ixj_daa_write(board);
 			break;
 		case DAA_JAPAN:
 			DAA_Coeff_Japan(board);
-			ixj_daa_write(board);
+			retval = ixj_daa_write(board);
 			break;
 		default:
+			retval = 1;
 			break;
 		}
+		j->country = arg;
 		break;
 	case IXJCTL_DAA_AGAIN:
 		ixj_daa_cr4(board, arg | 0x02);
 		break;
 	case IXJCTL_PSTN_LINETEST:
-	case PHONE_PSTN_LINETEST:
 		retval = ixj_linetest(board);
 		break;
+	case IXJCTL_VMWI:
+		ixj_write_vmwi(board, arg);
+		break;
 	case IXJCTL_CID:
-		if (copy_to_user((char *) arg, &j->cid, sizeof(IXJ_CID)))
+		if (copy_to_user((char *) arg, &j->cid, sizeof(PHONE_CID)))
 			return -EFAULT;
 		j->ex.bits.caller_id = 0;
 		break;
@@ -3891,7 +5038,7 @@
 		break;
 	case PHONE_CAPABILITIES_LIST:
 		if (copy_to_user((char *) arg, j->caplist, sizeof(struct phone_capability) * j->caps))
-			return -EFAULT;
+			 return -EFAULT;
 		break;
 	case PHONE_CAPABILITIES_CHECK:
 		retval = capabilities_check(board, (struct phone_capability *) arg);
@@ -3904,7 +5051,7 @@
 		j->ex.bits.pstn_ring = 0;
 		break;
 	case IXJCTL_SET_FILTER:
-		if (copy_from_user(&jf, (char *) arg, sizeof(ti)))
+		if (copy_from_user(&jf, (char *) arg, sizeof(jf)))
 			return -EFAULT;
 		retval = ixj_init_filter(board, &jf);
 		break;
@@ -3918,6 +5065,9 @@
 	case IXJCTL_TONE_CADENCE:
 		retval = ixj_build_cadence(board, (IXJ_CADENCE *) arg);
 		break;
+	case IXJCTL_FILTER_CADENCE:
+		retval = ixj_build_filter_cadence(board, (IXJ_FILTER_CADENCE *) arg);
+		break;
 	case IXJCTL_INTERCOM_STOP:
 		ixj[board].intercom = -1;
 		ixj[arg].intercom = -1;
@@ -3967,14 +5117,14 @@
 	NULL,			/* revalidate */
 	NULL			/* lock */
 };
-
 static int ixj_linetest(int board)
 {
 	unsigned long jifwait;
 	IXJ *j = &ixj[board];
 
+	j->flags.incheck = 1;	// Testing
 	if (!j->flags.pots_correct) {
-		j->flags.pots_correct = 1;	// Testing
+		j->flags.pots_correct = 1;
 
 		daa_int_read(board);	//Clear DAA Interrupt flags
 		//
@@ -4026,23 +5176,23 @@
 			}
 		}
 	}
-	if (!j->flags.pstn_present) {
-		j->pld_slicw.bits.rly3 = 0;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		daa_set_mode(board, SOP_PU_CONVERSATION);
-		jifwait = jiffies + hertz;
-		while (time_before(jiffies, jifwait)) {
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(1);
-		}
-		daa_int_read(board);
-		daa_set_mode(board, SOP_PU_SLEEP);
-		if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
-			j->flags.pstn_present = 1;
-		} else {
-			j->flags.pstn_present = 0;
-		}
+//      if (!j->flags.pstn_present) {
+	j->pld_slicw.bits.rly3 = 0;
+	outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
+	daa_set_mode(board, SOP_PU_CONVERSATION);
+	jifwait = jiffies + hertz;
+	while (time_before(jiffies, jifwait)) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+	}
+	daa_int_read(board);
+	daa_set_mode(board, SOP_PU_SLEEP);
+	if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
+		j->flags.pstn_present = 1;
+	} else {
+		j->flags.pstn_present = 0;
 	}
+//      }
 	if (j->flags.pstn_present) {
 		if (j->flags.pots_correct) {
 			LED_SetState(0xA, board);
@@ -4056,6 +5206,7 @@
 			LED_SetState(0x5, board);
 		}
 	}
+	j->flags.incheck = 0;	// Testing
 	return j->flags.pstn_present;
 }
 
@@ -4063,46 +5214,39 @@
 {
 	unsigned short cmd;
 	unsigned long jif;
+	int cnt;
 	BYTES bytes;
 	IXJ *j = &ixj[board];
-
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Write IDLE to Software Control Register\n");
+	ixj_WriteDSPCommand(0x0FE0, board);	// Put the DSP in full power mode.
 
 	if (ixj_WriteDSPCommand(0x0000, board))		/* Write IDLE to Software Control Register */
 		return -1;
-
 // The read values of the SSR should be 0x00 for the IDLE command
 	if (j->ssr.low || j->ssr.high)
 		return -1;
-
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Get Device ID Code\n");
-
 	if (ixj_WriteDSPCommand(0x3400, board))		/* Get Device ID Code */
 		return -1;
-
 	j->dsp.low = j->ssr.low;
 	j->dsp.high = j->ssr.high;
-
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Get Device Version Code\n");
-
 	if (ixj_WriteDSPCommand(0x3800, board))		/* Get Device Version Code */
 		return -1;
-
 	j->ver.low = j->ssr.low;
 	j->ver.high = j->ssr.high;
-
 	if (!j->cardtype) {
 		if (j->dsp.low == 0x21) {
 //      j->XILINXbase = j->DSPbase + 0x10;
 			bytes.high = bytes.low = inb_p(j->XILINXbase + 0x02);
 			outb_p(bytes.low ^ 0xFF, j->XILINXbase + 0x02);
-      // Test for Internet LineJACK or Internet PhoneJACK Lite
+// Test for Internet LineJACK or Internet PhoneJACK Lite
 			bytes.low = inb_p(j->XILINXbase + 0x02);
 			if (bytes.low == bytes.high)	//  Register is read only on
-                                    //  Internet PhoneJack Lite
+				//  Internet PhoneJack Lite
 			 {
 				j->cardtype = 400;	// Internet PhoneJACK Lite
 
@@ -4163,18 +5307,18 @@
 			j->pld_slicw.pcib.e1 = 1;
 			outb_p(j->pld_slicw.byte, j->XILINXbase);
 			break;
+		case 600:	//Internet PhoneCARD
+
+			break;
 		}
 	}
 	if (j->dsp.low == 0x20 || j->cardtype == 400 || j->cardtype == 500) {
 		if (ixjdebug > 0)
 			printk(KERN_INFO "Write CODEC config to Software Control Register\n");
-
 		if (ixj_WriteDSPCommand(0xC462, board))		/* Write CODEC config to Software Control Register */
 			return -1;
-
 		if (ixjdebug > 0)
 			printk(KERN_INFO "Write CODEC timing to Software Control Register\n");
-
 		if (j->cardtype == 100) {
 			cmd = 0x9FF2;
 		} else {
@@ -4185,17 +5329,17 @@
 	} else {
 		if (set_base_frame(board, 30) != 30)
 			return -1;
-
+		if (ixjdebug > 0)
+			printk(KERN_INFO "Write CODEC config to Software Control Register\n");
+		if (j->cardtype == 600) {
+			if (ixj_WriteDSPCommand(0xC528, board))		/* Write CODEC config to Software Control Register */
+				return -1;
+		}
 		if (j->cardtype == 300) {
-			if (ixjdebug > 0)
-				printk(KERN_INFO "Write CODEC config to Software Control Register\n");
-
 			if (ixj_WriteDSPCommand(0xC528, board))		/* Write CODEC config to Software Control Register */
 				return -1;
-
 			if (ixjdebug > 0)
 				printk(KERN_INFO "Turn on the PLD Clock at 8Khz\n");
-
 			j->pld_clock.byte = 0;
 			outb_p(j->pld_clock.byte, j->XILINXbase + 0x04);
 		}
@@ -4204,7 +5348,6 @@
 	if (j->dsp.low == 0x20) {
 		if (ixjdebug > 0)
 			printk(KERN_INFO "Configure GPIO pins\n");
-
 		j->gpio.bytes.high = 0x09;
 /*  bytes.low = 0xEF;  0xF7 */
 		j->gpio.bits.gpio1 = 1;
@@ -4215,10 +5358,8 @@
 		j->gpio.bits.gpio6 = 1;
 		j->gpio.bits.gpio7 = 1;
 		ixj_WriteDSPCommand(ixj[board].gpio.word, board);	/* Set GPIO pin directions */
-
 		if (ixjdebug > 0)
 			printk(KERN_INFO "Enable SLIC\n");
-
 		j->gpio.bytes.high = 0x0B;
 		j->gpio.bytes.low = 0x00;
 		j->gpio.bits.gpio1 = 0;
@@ -4253,23 +5394,16 @@
 				schedule_timeout(1);
 			}
 			LED_SetState(0x0, board);
-
 			daa_get_version(board);
-
 			if (ixjdebug > 0)
 				printk("Loading DAA Coefficients\n");
-
 			DAA_Coeff_US(board);
 			if (!ixj_daa_write(board))
 				printk("DAA write failed on board %d\n", board);
-
 			ixj_daa_cid_reset(board);
-
 			j->flags.pots_correct = 0;
 			j->flags.pstn_present = 0;
-
 			ixj_linetest(board);
-
 			if (j->flags.pots_correct) {
 				j->pld_scrw.bits.daafsyncen = 0;	// Turn off DAA Frame Sync
 
@@ -4280,9 +5414,10 @@
 				SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
 				j->port = PORT_POTS;
 			}
+			ixj_set_port(board, PORT_PSTN);
+			ixj_set_pots(board, 1);
 			if (ixjdebug > 0)
 				printk(KERN_INFO "Enable Mixer\n");
-
 			ixj_mixer(0x0000, board);	//Master Volume Left unmute 0db
 
 			ixj_mixer(0x0100, board);	//Master Volume Right unmute 0db
@@ -4306,43 +5441,43 @@
 			ixj_mixer(0x1800, board);	//ADC Source select
 
 		} else {
-			j->port = PORT_POTS;
-			SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
+			if (j->cardtype == 600) {
+				ixj_WriteDSPCommand(0xCF07, board);
+				ixj_WriteDSPCommand(0x00B0, board);
+				ixj_set_port(board, PORT_SPEAKER);
+			} else {
+				ixj_set_port(board, PORT_POTS);
+				SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
+			}
 		}
 	}
 
 	j->intercom = -1;
 	j->framesread = j->frameswritten = 0;
+	j->read_wait = j->write_wait = 0;
 	j->rxreadycheck = j->txreadycheck = 0;
-
+	set_play_volume(board, 0x100);
+	set_rec_volume(board, 0x100);
 	if (ixj_WriteDSPCommand(0x0000, board))		/* Write IDLE to Software Control Register */
 		return -1;
-
 // The read values of the SSR should be 0x00 for the IDLE command
 	if (j->ssr.low || j->ssr.high)
 		return -1;
-
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Enable Line Monitor\n");
-
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Set Line Monitor to Asyncronous Mode\n");
-
 	if (ixj_WriteDSPCommand(0x7E01, board))		// Asynchronous Line Monitor
 
 		return -1;
-
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Enable DTMF Detectors\n");
-
 	if (ixj_WriteDSPCommand(0x5151, board))		// Enable DTMF detection
 
 		return -1;
-
 	if (ixj_WriteDSPCommand(0x6E01, board))		// Set Asyncronous Tone Generation
 
 		return -1;
-
 	set_rec_depth(board, 2);	// Set Record Channel Limit to 2 frames
 
 	set_play_depth(board, 2);	// Set Playback Channel Limit to 2 frames
@@ -4350,7 +5485,6 @@
 	j->ex.bits.dtmf_ready = 0;
 	j->dtmf_state = 0;
 	j->dtmf_wp = ixj[board].dtmf_rp = 0;
-
 	j->rec_mode = ixj[board].play_mode = -1;
 	j->flags.ringing = 0;
 	j->maxrings = MAXRINGS;
@@ -4358,15 +5492,16 @@
 	j->drybuffer = 0;
 	j->winktime = 320;
 	j->flags.dtmf_oob = 0;
-
+	for (cnt = 0; cnt < 4; cnt++)
+		j->cadence_f[cnt].enable = 0;
 	/* must be a device on the specified address */
+	ixj_WriteDSPCommand(0x0FE3, board);	// Put the DSP in 1/5 power mode.
 	/* Register with the Telephony for Linux subsystem */
 	j->p.f_op = &ixj_fops;
 	j->p.open = ixj_open;
+	j->p.board = board;
 	phone_register_device(&j->p, PHONE_UNIT_ANY);
-
 	add_caps(board);
-
 	return 0;
 }
 
@@ -4375,11 +5510,9 @@
 	int cnt;
 	IXJ *j;
 	len = 0;
-
 	len += sprintf(buf + len, "\n%s", ixj_c_rcsid);
 	len += sprintf(buf + len, "\n%s", ixj_h_rcsid);
 	len += sprintf(buf + len, "\n%s", ixjuser_h_rcsid);
-
 	for (cnt = 0; cnt < IXJMAX; cnt++) {
 		j = &ixj[cnt];
 		if (j->DSPbase) {
@@ -4398,6 +5531,7 @@
 				len += sprintf(buf + len, "\nCard Type = Internet LineJACK");
 				if (j->flags.g729_loaded)
 					len += sprintf(buf + len, " w/G.729 A/B");
+				len += sprintf(buf + len, " Country = %d", j->country);
 				break;
 			case (400):
 				len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK Lite");
@@ -4409,18 +5543,35 @@
 				if (j->flags.g729_loaded)
 					len += sprintf(buf + len, " w/G.729 A/B");
 				break;
+			case (600):
+				len += sprintf(buf + len, "\nCard Type = Internet PhoneCARD");
+				if (j->flags.g729_loaded)
+					len += sprintf(buf + len, " w/G.729 A/B");
+				len += sprintf(buf + len, "\nSmart Cable %spresent", j->pccr1.bits.drf ? "not " : "");
+				if (!j->pccr1.bits.drf)
+					len += sprintf(buf + len, "\nSmart Cable type %d", j->flags.pcmciasct);
+				len += sprintf(buf + len, "\nSmart Cable state %d", j->flags.pcmciastate);
+				break;
 			default:
 				len += sprintf(buf + len, "\nCard Type = %d", j->cardtype);
 				break;
 			}
+			len += sprintf(buf + len, "\nReaders %d", j->readers);
+			len += sprintf(buf + len, "\nWriters %d", j->writers);
+			len += sprintf(buf + len, "\nFSK words %d", ixj[2].fskdcnt);
 			len += sprintf(buf + len, "\nCapabilities %d", j->caps);
 			if (j->dsp.low != 0x20)
 				len += sprintf(buf + len, "\nDSP Processor load %d", j->proc_load);
-//    if(j->intercom != -1)
-			//      len += sprintf(buf+len, "\nIntercom call to board %2.2x", j->intercom);
+			if (j->flags.cidsent)
+				len += sprintf(buf + len, "\nCaller ID data sent");
+			else
+				len += sprintf(buf + len, "\nCaller ID data not sent");
+
+			len += sprintf(buf + len, "\nCaller ID Date %s%s", j->cid_send.month, j->cid_send.day);
+			len += sprintf(buf + len, "\nCaller ID Time %s%s", j->cid_send.hour, j->cid_send.min);
+			len += sprintf(buf + len, "\nCaller ID Name %s", j->cid_send.name);
+			len += sprintf(buf + len, "\nCaller ID Number %s", j->cid_send.number);
 
-//    len += sprintf(buf+len, "\nRead buffer size %d", j->read_buffer_size);
-			//    len += sprintf(buf+len, "\nWrite buffer size %d", j->write_buffer_size);
 			len += sprintf(buf + len, "\nPlay CODEC ");
 			switch (j->play_codec) {
 			case G723_63:
@@ -4463,9 +5614,6 @@
 				len += sprintf(buf + len, "NO CODEC CHOSEN");
 				break;
 			}
-//    len += sprintf(buf+len, "\nPlay Frame Size %d", j->play_frame_size);
-			//    len += sprintf(buf+len, "\nInfo_write.convert_mode = %d", j->Info_write.convert_mode);
-			//    len += sprintf(buf+len, "\nInfo_write.convert_dir = %d", j->Info_write.convert_dir);
 			len += sprintf(buf + len, "\nRecord CODEC ");
 			switch (j->rec_codec) {
 			case G723_63:
@@ -4508,7 +5656,6 @@
 				len += sprintf(buf + len, "NO CODEC CHOSEN");
 				break;
 			}
-//    len += sprintf(buf+len, "\nRecord Frame Size %d", j->rec_frame_size);
 			switch (j->aec_level) {
 			case AEC_OFF:
 				len += sprintf(buf + len, "\n AEC OFF");
@@ -4523,16 +5670,13 @@
 				len += sprintf(buf + len, "\n AEC HIGH");
 				break;
 			}
-//    len += sprintf(buf+len, "\nInfo_read.convert_mode = %d", j->Info_read.convert_mode);
-			//    len += sprintf(buf+len, "\nInfo_read.convert_dir = %d", j->Info_read.convert_dir);
 			len += sprintf(buf + len, "\nHook state %d", j->r_hook);	// ixj_hookstate(cnt));
 
 			if (j->cardtype == 300) {
 				len += sprintf(buf + len, "\nPOTS Correct %d", j->flags.pots_correct);
 				len += sprintf(buf + len, "\nPSTN Present %d", j->flags.pstn_present);
 				len += sprintf(buf + len, "\nPOTS to PSTN %d", j->flags.pots_pstn);
-//      len += sprintf(buf+len, "\nDAA Interrupt flags %d", j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg);
-				//      len += sprintf(buf+len, "\nDAA version %d", j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg);
+				len += sprintf(buf + len, "\nPSTN sleeptil %ld - jiffies %ld", j->pstn_sleeptil, jiffies);
 				switch (j->daa_mode) {
 				case SOP_PU_SLEEP:
 					len += sprintf(buf + len, "\nDAA PSTN On Hook");
@@ -4547,7 +5691,6 @@
 					len += sprintf(buf + len, "\nDAA PSTN Pulse Dialing");
 					break;
 				}
-//      len += sprintf(buf+len, "\nDAA PSTN Ring flag = %d", j->pstn_ringing);
 			}
 			switch (j->port) {
 			case PORT_POTS:
@@ -4598,23 +5741,8 @@
 					break;
 				}
 			}
-//    len += sprintf(buf+len, "\nRead buffers ready %d", j->read_buffer_ready);
-			//    len += sprintf(buf+len, "\nWrite buffers empty %d",j->write_buffers_empty);
-
-//    len += sprintf(buf+len, "\nDTMF ready %d", j->ex.bits.dtmf_ready);
-			//    len += sprintf(buf+len, "\nDTMF proc %d", j->dtmf_proc);
-			//    len += sprintf(buf+len, "\nDTMF wp %d", j->dtmf_wp);
-			//    len += sprintf(buf+len, "\nDTMF rp %d", j->dtmf_rp);
-			//    len += sprintf(buf+len, "\nDTMF digits ");
-			//    for(x=j->dtmf_rp; x <j->dtmf_wp; x++)
-			//    {
-			//      if(x == 79)
-			//        x = 0;
-			//      len += sprintf(buf+len, "%x", j->dtmfbuffer[x]);
-			//    }
 #ifdef PERFMON_STATS
 			len += sprintf(buf + len, "\nTimer Checks %ld", j->timerchecks);
-
 			len += sprintf(buf + len, "\nRX Ready Checks %ld", j->rxreadycheck);
 			len += sprintf(buf + len, "\nTX Ready Checks %ld", j->txreadycheck);
 			len += sprintf(buf + len, "\nBase Frame %2.2x.%2.2x", j->baseframe.high, j->baseframe.low);
@@ -4629,7 +5757,15 @@
 	}
 	return len;
 }
-
+int ixj_read_proc_fsk(char *buf, char **start, off_t offset, int len, int unused)
+{
+	len = 0;
+	if (ixj[2].fskdcnt) {
+		memcpy(buf, &ixj[2].fskdata, (ixj[2].fskdcnt) * 2);
+		len += ixj[2].fskdcnt * 2;
+	}
+	return len;
+}
 static struct proc_dir_entry ixj_proc_entry =
 {
 	0,
@@ -4640,14 +5776,310 @@
 	NULL,
 	&ixj_read_proc
 };
+static struct proc_dir_entry ixjfsk_proc_entry =
+{
+	0,
+	6, "ixjfsk",
+	S_IFREG | S_IRUGO,
+	1, 0, 0,
+	0,
+	NULL,
+	&ixj_read_proc_fsk
+};
+
+MODULE_DESCRIPTION("Internet Phone/Internet LineJack module - www.quicknet.net");
+MODULE_AUTHOR("Ed Okerson <eokerson@quicknet.net>");
+#ifdef CONFIG_PCMCIA
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+MODULE_PARM(pc_debug, "i");
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+#else
+#define DEBUG(n, args...)
+#endif
+typedef struct ixj_info_t {
+	int ndev;
+	dev_node_t node;
+	struct ixj *port;
+} ixj_info_t;
+static dev_link_t *ixj_attach(void);
+static void ixj_detach(dev_link_t *);
+static void ixj_config(dev_link_t * link);
+static void ixj_cs_release(u_long arg);
+static int ixj_event(event_t event, int priority, event_callback_args_t * args);
+static dev_info_t dev_info = "ixj_cs";
+static dev_link_t *dev_list = NULL;
+static void cs_error(client_handle_t handle, int func, int ret)
+{
+	error_info_t err =
+	{
+		func, ret
+	};
+	CardServices(ReportError, handle, &err);
+}
+
+static dev_link_t *ixj_attach(void)
+{
+	client_reg_t client_reg;
+	dev_link_t *link;
+	int ret;
+	DEBUG(0, "ixj_attach()\n");
+	/* Create new ixj device */
+	link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
+	memset(link, 0, sizeof(struct dev_link_t));
+	link->release.function = &ixj_cs_release;
+	link->release.data = (u_long) link;
+	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+	link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
+	link->io.IOAddrLines = 3;
+	link->conf.Vcc = 50;
+	link->conf.IntType = INT_MEMORY_AND_IO;
+	link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
+	memset(link->priv, 0, sizeof(struct ixj_info_t));
+	/* Register with Card Services */
+	link->next = dev_list;
+	dev_list = link;
+	client_reg.dev_info = &dev_info;
+	client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+	client_reg.EventMask =
+	    CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+	    CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+	    CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+	client_reg.event_handler = &ixj_event;
+	client_reg.Version = 0x0210;
+	client_reg.event_callback_args.client_data = link;
+	ret = CardServices(RegisterClient, &link->handle, &client_reg);
+	if (ret != CS_SUCCESS) {
+		cs_error(link->handle, RegisterClient, ret);
+		ixj_detach(link);
+		return NULL;
+	}
+	return link;
+}
+
+static void ixj_detach(dev_link_t * link)
+{
+	dev_link_t **linkp;
+	long flags;
+	int ret;
+	DEBUG(0, "ixj_detach(0x%p)\n", link);
+	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+		if (*linkp == link)
+			break;
+	if (*linkp == NULL)
+		return;
+	save_flags(flags);
+	cli();
+	if (link->state & DEV_RELEASE_PENDING) {
+		del_timer(&link->release);
+		link->state &= ~DEV_RELEASE_PENDING;
+	}
+	restore_flags(flags);
+	if (link->state & DEV_CONFIG)
+		ixj_cs_release((u_long) link);
+	if (link->handle) {
+		ret = CardServices(DeregisterClient, link->handle);
+		if (ret != CS_SUCCESS)
+			cs_error(link->handle, DeregisterClient, ret);
+	}
+	/* Unlink device structure, free bits */
+	*linkp = link->next;
+	kfree_s(link->priv, sizeof(ixj_info_t));
+	kfree_s(link, sizeof(struct dev_link_t));
+}
+
+#define CS_CHECK(fn, args...) \
+while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
+
+#define CFG_CHECK(fn, args...) \
+if (CardServices(fn, args) != 0) goto next_entry
+
+void ixj_get_serial(dev_link_t * link, IXJ * j)
+{
+	client_handle_t handle;
+	tuple_t tuple;
+	u_short buf[128];
+	char *str;
+	int last_ret, last_fn, i, place;
+	handle = link->handle;
+	DEBUG(0, "ixj_get_serial(0x%p)\n", link);
+	tuple.TupleData = (cisdata_t *) buf;
+	tuple.TupleOffset = 0;
+	tuple.TupleDataMax = 80;
+	tuple.Attributes = 0;
+	tuple.DesiredTuple = CISTPL_VERS_1;
+	CS_CHECK(GetFirstTuple, handle, &tuple);
+	CS_CHECK(GetTupleData, handle, &tuple);
+	str = (char *) buf;
+	printk("PCMCIA Version %d.%d\n", str[0], str[1]);
+	str += 2;
+	printk("%s", str);
+	str = str + strlen(str) + 1;
+	printk(" %s", str);
+	str = str + strlen(str) + 1;
+	place = 1;
+	for (i = strlen(str) - 1; i >= 0; i--) {
+		switch (str[i]) {
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			j->serial += (str[i] - 48) * place;
+			break;
+		case 'A':
+		case 'B':
+		case 'C':
+		case 'D':
+		case 'E':
+		case 'F':
+			j->serial += (str[i] - 55) * place;
+			break;
+		case 'a':
+		case 'b':
+		case 'c':
+		case 'd':
+		case 'e':
+		case 'f':
+			j->serial += (str[i] - 87) * place;
+			break;
+		}
+		place = place * 0x10;
+	}
+	str = str + strlen(str) + 1;
+	printk(" version %s\n", str);
+      cs_failed:
+	return;
+}
+
+void ixj_config(dev_link_t * link)
+{
+	client_handle_t handle;
+	ixj_info_t *info;
+	tuple_t tuple;
+	u_short buf[128];
+	cisparse_t parse;
+	config_info_t conf;
+	cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
+	cistpl_cftable_entry_t dflt =
+	{
+		0
+	};
+	int last_ret, last_fn;
+	handle = link->handle;
+	info = link->priv;
+	DEBUG(0, "ixj_config(0x%p)\n", link);
+	tuple.TupleData = (cisdata_t *) buf;
+	tuple.TupleOffset = 0;
+	tuple.TupleDataMax = 255;
+	tuple.Attributes = 0;
+	tuple.DesiredTuple = CISTPL_CONFIG;
+	CS_CHECK(GetFirstTuple, handle, &tuple);
+	CS_CHECK(GetTupleData, handle, &tuple);
+	CS_CHECK(ParseTuple, handle, &tuple, &parse);
+	link->conf.ConfigBase = parse.config.base;
+	link->conf.Present = parse.config.rmask[0];
+	link->state |= DEV_CONFIG;
+	CS_CHECK(GetConfigurationInfo, handle, &conf);
+	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+	tuple.Attributes = 0;
+	CS_CHECK(GetFirstTuple, handle, &tuple);
+	while (1) {
+		CFG_CHECK(GetTupleData, handle, &tuple);
+		CFG_CHECK(ParseTuple, handle, &tuple, &parse);
+		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
+			link->conf.ConfigIndex = cfg->index;
+			link->io.BasePort1 = io->win[0].base;
+			link->io.NumPorts1 = io->win[0].len;
+			if (io->nwin == 2) {
+				link->io.BasePort2 = io->win[1].base;
+				link->io.NumPorts2 = io->win[1].len;
+			}
+			CFG_CHECK(RequestIO, link->handle, &link->io);
+			/* If we've got this far, we're done */
+			break;
+		}
+	      next_entry:
+		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+			dflt = *cfg;
+		CS_CHECK(GetNextTuple, handle, &tuple);
+	}
+
+	CS_CHECK(RequestConfiguration, handle, &link->conf);
+	ixj[0].DSPbase = link->io.BasePort1;
+	ixj[0].XILINXbase = link->io.BasePort1 + 0x10;
+	ixj[0].cardtype = 600;
+	ixj_selfprobe(0);
+	info->ndev = 1;
+	info->node.major = PHONE_MAJOR;
+	link->dev = &info->node;
+	ixj_get_serial(link, &ixj[0]);
+	link->state &= ~DEV_CONFIG_PENDING;
+	return;
+      cs_failed:
+	cs_error(link->handle, last_fn, last_ret);
+	ixj_cs_release((u_long) link);
+}
+
+void ixj_cs_release(u_long arg)
+{
+	dev_link_t *link = (dev_link_t *) arg;
+	ixj_info_t *info = link->priv;
+	DEBUG(0, "ixj_cs_release(0x%p)\n", link);
+	info->ndev = 0;
+	link->dev = NULL;
+	CardServices(ReleaseConfiguration, link->handle);
+	CardServices(ReleaseIO, link->handle, &link->io);
+	link->state &= ~DEV_CONFIG;
+}
+
+int ixj_event(event_t event, int priority, event_callback_args_t * args)
+{
+	dev_link_t *link = args->client_data;
+	DEBUG(1, "ixj_event(0x%06x)\n", event);
+	switch (event) {
+	case CS_EVENT_CARD_REMOVAL:
+		link->state &= ~DEV_PRESENT;
+		if (link->state & DEV_CONFIG) {
+			link->release.expires = RUN_AT(HZ / 20);
+			link->state |= DEV_RELEASE_PENDING;
+			add_timer(&link->release);
+		}
+		break;
+	case CS_EVENT_CARD_INSERTION:
+		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+		ixj_config(link);
+		break;
+	case CS_EVENT_PM_SUSPEND:
+		link->state |= DEV_SUSPEND;
+		/* Fall through... */
+	case CS_EVENT_RESET_PHYSICAL:
+		if (link->state & DEV_CONFIG)
+			CardServices(ReleaseConfiguration, link->handle);
+		break;
+	case CS_EVENT_PM_RESUME:
+		link->state &= ~DEV_SUSPEND;
+		/* Fall through... */
+	case CS_EVENT_CARD_RESET:
+		if (DEV_OK(link))
+			CardServices(RequestConfiguration, link->handle, &link->conf);
+		break;
+	}
+	return 0;
+}
+
+#endif				// PCMCIA
 
 static void cleanup(void)
 {
 	int cnt;
-
 	del_timer(&ixj_timer);
-//  if (ixj_major)
-	//    unregister_chrdev(ixj_major, "ixj");
 	for (cnt = 0; cnt < IXJMAX; cnt++) {
 		if (ixj[cnt].cardtype == 300) {
 			ixj[cnt].pld_scrw.bits.daafsyncen = 0;	// Turn off DAA Frame Sync
@@ -4658,7 +6090,6 @@
 			ixj[cnt].pld_slicw.bits.rly3 = 0;
 			outb_p(ixj[cnt].pld_slicw.byte, ixj[cnt].XILINXbase + 0x01);
 			LED_SetState(0x0, cnt);
-
 			release_region(ixj[cnt].XILINXbase, 8);
 		}
 		if (ixj[cnt].cardtype == 400 || ixj[cnt].cardtype == 500) {
@@ -4676,17 +6107,22 @@
 		if (ixj[cnt].dev)
 			ixj[cnt].dev->deactivate(ixj[cnt].dev);
 #endif
+#ifdef CONFIG_PCMCIA
+		DEBUG(0, "ixj_cs: unloading\n");
+		unregister_pcmcia_driver(&dev_info);
+		while (dev_list != NULL)
+			ixj_detach(dev_list);
+#endif
 	}
 	proc_unregister(&proc_root, ixj_proc_entry.low_ino);
+	proc_unregister(&proc_root, ixjfsk_proc_entry.low_ino);
 }
 
-
 // Typedefs
 typedef struct {
 	BYTE length;
 	DWORD bits;
 } DATABLOCK;
-
 static void PCIEE_WriteBit(WORD wEEPROMAddress, BYTE lastLCC, BYTE byData)
 {
 	lastLCC = lastLCC & 0xfb;
@@ -4699,7 +6135,6 @@
 
 	byData = byData << 1;
 	lastLCC = lastLCC & 0xfe;
-
 	udelay(1000);
 	outb(lastLCC, wEEPROMAddress);	//after delay, SK falling edge
 
@@ -4724,11 +6159,8 @@
 	WORD wEEPROMAddress = wAddress + 3;
 	DWORD i;
 	BYTE byResult;
-
 	*pwResult = 0;
-
 	lastLCC = inb(wEEPROMAddress);
-
 	lastLCC = lastLCC | 0x02;
 	lastLCC = lastLCC & 0xfe;
 	outb(lastLCC, wEEPROMAddress);	// CS hi, SK lo
@@ -4738,7 +6170,6 @@
 	PCIEE_WriteBit(wEEPROMAddress, lastLCC, 1);
 	PCIEE_WriteBit(wEEPROMAddress, lastLCC, 1);
 	PCIEE_WriteBit(wEEPROMAddress, lastLCC, 0);
-
 	for (i = 0; i < 8; i++) {
 		PCIEE_WriteBit(wEEPROMAddress, lastLCC, wLoc & 0x80 ? 1 : 0);
 		wLoc <<= 1;
@@ -4760,27 +6191,29 @@
 static DWORD PCIEE_GetSerialNumber(WORD wAddress)
 {
 	WORD wLo, wHi;
-
 	if (PCIEE_ReadWord(wAddress, 62, &wLo))
 		return 0;
-
 	if (PCIEE_ReadWord(wAddress, 63, &wHi))
 		return 0;
-
 	return (((DWORD) wHi << 16) | wLo);
 }
 
-static int dspio[IXJMAX + 1] = {0,};
-static int xio[IXJMAX + 1] = {0,};
-
-MODULE_DESCRIPTION("Internet PhoneJACK/Internet LineJACK module - www.quicknet.net");
-MODULE_AUTHOR("Ed Okerson <eokerson@quicknet.net>");
+#ifndef CONFIG_PCMCIA
+#ifndef CONFIG_ISAPNP
+static int dspio[IXJMAX + 1] =
+{
+	0,
+};
+static int xio[IXJMAX + 1] =
+{
+	0,
+};
 
 MODULE_PARM(dspio, "1-" __MODULE_STRING(IXJMAX) "i");
 MODULE_PARM(xio, "1-" __MODULE_STRING(IXJMAX) "i");
-
+#endif
+#endif
 #ifdef MODULE
-
 void cleanup_module(void)
 {
 	cleanup();
@@ -4792,23 +6225,35 @@
 #endif
 {
 	int result;
-
-	int func = 0x110, i = 0;
+	int i = 0;
 	int cnt = 0;
 	int probe = 0;
+#ifdef CONFIG_ISAPNP
+	int func = 0x110;
 	struct pnp_dev *dev = NULL, *old_dev = NULL;
+#endif
+#ifdef CONFIG_PCI
 	struct pci_dev *pci = NULL;
-
+#endif
+#ifdef CONFIG_PCMCIA
+	servinfo_t serv;
+	DEBUG(0, "%s\n", version);
+	CardServices(GetCardServicesInfo, &serv);
+	if (serv.Revision != CS_RELEASE_CODE) {
+		printk(KERN_NOTICE "ixj_cs: Card Services release does not match!\n");
+		return -1;
+	}
+	register_pcmcia_driver(&dev_info, &ixj_attach, &ixj_detach);
+	probe = 0;
+#else
 #ifdef CONFIG_ISAPNP
 	while (1) {
 		do {
 			old_dev = dev;
 			dev = isapnp_find_dev(NULL, ISAPNP_VENDOR('Q', 'T', 'I'),
 					 ISAPNP_FUNCTION(func), old_dev);
-//(old_dev==NULL?NULL:old_dev));
 			if (!dev)
 				break;
-			printk("preparing %x\n", func);
 			result = dev->prepare(dev);
 			if (result < 0) {
 				printk("preparing failed %d \n", result);
@@ -4826,7 +6271,6 @@
 			ixj[cnt].DSPbase = dev->resource[0].start;	/* get real port */
 			if (func != 0x110)
 				ixj[cnt].XILINXbase = dev->resource[1].start;	/* get real port */
-
 			result = check_region(ixj[cnt].DSPbase, 16);
 			if (result) {
 				printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[cnt].DSPbase);
@@ -4846,13 +6290,21 @@
 				break;
 			}
 			probe = ixj_selfprobe(cnt);
-
 			ixj[cnt].serial = dev->bus->serial;
 			ixj[cnt].dev = dev;
-			printk(KERN_INFO "ixj: found card at 0x%x\n", ixj[cnt].DSPbase);
+			switch (func) {
+			case 0x110:
+				printk(KERN_INFO "ixj: found Internet PhoneJACK at 0x%x\n", ixj[cnt].DSPbase);
+				break;
+			case 0x310:
+				printk(KERN_INFO "ixj: found Internet LineJACK at 0x%x\n", ixj[cnt].DSPbase);
+				break;
+			case 0x410:
+				printk(KERN_INFO "ixj: found Internet PhoneJACK Lite at 0x%x\n", ixj[cnt].DSPbase);
+				break;
+			}
 			cnt++;
 		} while (dev);
-
 		if (func == 0x410)
 			break;
 		if (func == 0x310)
@@ -4863,11 +6315,10 @@
 	}
 #else				//CONFIG_ISAPNP
 	/* Use passed parameters for older kernels without PnP */
-
-	for (cnt = 0; cnt < IXJMAX; cnt++) {
-		if (dspio[cnt]) {
-			ixj[cnt].DSPbase = dspio[cnt];
-			ixj[cnt].XILINXbase = xio[cnt];
+	for (i = 0; i < IXJMAX; i++) {
+		if (dspio[i]) {
+			ixj[cnt].DSPbase = dspio[i];
+			ixj[cnt].XILINXbase = xio[i];
 			ixj[cnt].cardtype = 0;
 			result = check_region(ixj[cnt].DSPbase, 16);
 			if (result) {
@@ -4878,9 +6329,11 @@
 			request_region(ixj[cnt].DSPbase, 16, "ixj DSP");
 			probe = ixj_selfprobe(cnt);
 			ixj[cnt].dev = NULL;
+			cnt++;
 		}
 	}
-#endif
+#endif				// !CONFIG_ISAPNP
+#endif				// CONFIG_PCMCIA
 #ifdef CONFIG_PCI
 	if (pci_present()) {
 		for (i = 0; i < IXJMAX - cnt; i++) {
@@ -4891,7 +6344,6 @@
 				ixj[cnt].DSPbase = pci->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
 				ixj[cnt].XILINXbase = ixj[cnt].DSPbase + 0x10;
 				ixj[cnt].serial = PCIEE_GetSerialNumber(pci->base_address[2] & PCI_BASE_ADDRESS_IO_MASK);
-
 				result = check_region(ixj[cnt].DSPbase, 16);
 				if (result) {
 					printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[cnt].DSPbase);
@@ -4901,43 +6353,35 @@
 				request_region(ixj[cnt].DSPbase, 16, "ixj DSP");
 				ixj[cnt].cardtype = 500;
 				probe = ixj_selfprobe(cnt);
+				if (probe)
+					printk(KERN_INFO "ixj: found Internet PhoneJACK PCI at 0x%x\n", ixj[cnt].DSPbase);
 				cnt++;
 			}
 		}
 	}
 #endif
 	printk("%s\n", ixj_c_rcsid);
-
-//  result = register_chrdev(ixj_major, "ixj", &ixj_fops);
-	//  if (result < 0) {
-	//    printk(KERN_INFO "ixj: can't get major number\n");
-	//    cleanup();
-	//    return result;
-	//  }
-	//  if (ixj_major == 0)
-	//    ixj_major = result;               /* dynamic */
-
 	proc_register(&proc_root, &ixj_proc_entry);
-
+	proc_register(&proc_root, &ixjfsk_proc_entry);
 	ixj_init_timer();
-	ixj_add_timer();	
+	ixj_add_timer();
 	return probe;
 }
 
 static void DAA_Coeff_US(int board)
 {
 	IXJ *j = &ixj[board];
-
 	int i;
 
+	j->daa_country = DAA_US;
 	//-----------------------------------------------
 	// CAO
 	for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) {
 		j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0;
 	}
 
-	// Bytes for IM-filter part 1 (04): 0E,32,E2,2F,C2,5A,C0,00
-	    j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x0E;
+// Bytes for IM-filter part 1 (04): 0E,32,E2,2F,C2,5A,C0,00
+	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x0E;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0x32;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xE2;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2F;
@@ -4945,7 +6389,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x5A;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xC0;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00;
-
 // Bytes for IM-filter part 2 (05): 72,85,00,0E,2B,3A,D0,08
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x72;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x85;
@@ -4955,7 +6398,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x3A;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xD0;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08;
-
 // Bytes for FRX-filter       (08): 03,8F,48,F2,8F,48,70,08
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x03;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x8F;
@@ -4965,7 +6407,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x48;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x70;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08;
-
 // Bytes for FRR-filter       (07): 04,8F,38,7F,9B,EA,B0,08
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x04;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F;
@@ -4975,19 +6416,16 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xEA;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xB0;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08;
-
 // Bytes for AX-filter        (0A): 16,55,DD,CA
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x16;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0x55;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA;
-
 // Bytes for AR-filter        (09): 52,D3,11,42
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x52;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xD3;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x11;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0x42;
-
 // Bytes for TH-filter part 1 (00): 00,42,48,81,B3,80,00,98
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42;
@@ -4997,7 +6435,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98;
-
 // Bytes for TH-filter part 2 (01): 02,F2,33,A0,68,AB,8A,AD
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xF2;
@@ -5007,7 +6444,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0xAB;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x8A;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xAD;
-
 // Bytes for TH-filter part 3 (02): 00,88,DA,54,A4,BA,2D,BB
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88;
@@ -5017,7 +6453,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xBA;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x2D;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xBB;
-
 // ;  (10K, 0.68uF)
 	// 
 	// Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23
@@ -5029,7 +6464,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x1C;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xB3;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23;
-
 // Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x13;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x42;
@@ -5039,14 +6473,12 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x73;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0xCA;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5;
-
 // 
 	// Levelmetering Ringing        (0D):B2,45,0F,8E      
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xB2;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E;
-
 // Caller ID 1st Tone           (0E):CA,0E,CA,09,99,99,99,99
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E;
@@ -5056,7 +6488,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99;
-
 // Caller ID 2nd Tone           (0F):FD,B5,BA,07,DA,00,00,00
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5;
@@ -5066,64 +6497,52 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00;
-
 // 
 	// ;CR Registers
 	// Config. Reg. 0 (filters)       (cr0):FE ; CLK gen. by crystal
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE;
-
+	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF;
 // Config. Reg. 1 (dialing)       (cr1):05
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05;
-
 // Config. Reg. 2 (caller ID)     (cr2):04
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04;
-
 // Config. Reg. 3 (testloops)     (cr3):03 ; SEL Bit==0, HP-disabled
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x03;
-
 // Config. Reg. 4 (analog gain)   (cr4):01
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02;		//0x01;
-
-// Config. Reg. 5 (Version)       (cr5):02
+	// Config. Reg. 5 (Version)       (cr5):02
 	// Config. Reg. 6 (Reserved)      (cr6):00
 	// Config. Reg. 7 (Reserved)      (cr7):00
 	// 
-
-// ;xr Registers
+	// ;xr Registers
 	// Ext. Reg. 0 (Interrupt Reg.)   (xr0):02
+
 	j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02;	// SO_1 set to '1' because it is inverted.
+	// Ext. Reg. 1 (Interrupt enable) (xr1):1C // Cadence, RING, Caller ID, VDD_OK
 
-// Ext. Reg. 1 (Interrupt enable) (xr1):1C // Cadence, RING, Caller ID, VDD_OK
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x3C;
-
 // Ext. Reg. 2 (Cadence Time Out) (xr2):7D
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D;
-
 // Ext. Reg. 3 (DC Char)          (xr3):32 ; B-Filter Off == 1
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x12;		//0x32;
+	// Ext. Reg. 4 (Cadence)          (xr4):00
 
-// Ext. Reg. 4 (Cadence)          (xr4):00
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00;
-
 // Ext. Reg. 5 (Ring timer)       (xr5):22
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22;
-
 // Ext. Reg. 6 (Power State)      (xr6):00
 	j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00;
-
 // Ext. Reg. 7 (Vdd)              (xr7):40
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40;		// 0x40 ??? Should it be 0x00?
-
-// 
+	// 
 	// DTMF Tone 1                     (0B): 11,B3,5A,2C ;   697 Hz  
 	//                                       12,33,5A,C3 ;  770 Hz  
 	//                                       13,3C,5B,32 ;  852 Hz  
 	//                                       1D,1B,5C,CC ;  941 Hz  
+
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C;
-
 // DTMF Tone 2                     (0C): 32,32,52,B3 ;  1209 Hz  
 	//                                       EC,1D,52,22 ;  1336 Hz  
 	//                                       AA,AC,51,D2 ;  1477 Hz  
@@ -5132,23 +6551,22 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
-
 }
 
 static void DAA_Coeff_UK(int board)
 {
 	IXJ *j = &ixj[board];
-
 	int i;
 
+	j->daa_country = DAA_UK;
 	//-----------------------------------------------
 	// CAO
 	for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) {
 		j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0;
 	}
 
-	//  Bytes for IM-filter part 1 (04): 00,C2,BB,A8,CB,81,A0,00
-	    j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00;
+//  Bytes for IM-filter part 1 (04): 00,C2,BB,A8,CB,81,A0,00
+	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xC2;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xBB;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xA8;
@@ -5156,8 +6574,7 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x81;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00;
-
-	// Bytes for IM-filter part 2 (05): 40,00,00,0A,A4,33,E0,08
+// Bytes for IM-filter part 2 (05): 40,00,00,0A,A4,33,E0,08
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x40;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00;
@@ -5166,7 +6583,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08;
-
 // Bytes for FRX-filter       (08): 07,9B,ED,24,B2,A2,A0,08
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x9B;
@@ -5176,7 +6592,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0xA2;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xA0;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08;
-
 // Bytes for FRR-filter       (07): 0F,92,F2,B2,87,D2,30,08
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x0F;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x92;
@@ -5186,19 +6601,16 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xD2;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x30;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08;
-
 // Bytes for AX-filter        (0A): 1B,A5,DD,CA
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x1B;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xA5;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA;
-
 // Bytes for AR-filter        (09): E2,27,10,D6
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0xE2;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x27;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6;
-
 // Bytes for TH-filter part 1 (00): 80,2D,38,8B,D0,00,00,98
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x2D;
@@ -5208,7 +6620,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98;
-
 // Bytes for TH-filter part 2 (01): 02,5A,53,F0,0B,5F,84,D4
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0x5A;
@@ -5218,7 +6629,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x5F;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x84;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xD4;
-
 // Bytes for TH-filter part 3 (02): 00,88,6A,A4,8F,52,F5,32
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88;
@@ -5228,10 +6638,8 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x52;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0xF5;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x32;
-
 // ; idle
-
-// Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23
+	// Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93;
@@ -5240,7 +6648,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23;
-
 // Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2;
@@ -5250,13 +6657,11 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5;
-
 // Levelmetering Ringing           (0D):AA,35,0F,8E     ; 25Hz 30V less possible?
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E;
-
 // Caller ID 1st Tone              (0E):CA,0E,CA,09,99,99,99,99
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E;
@@ -5266,7 +6671,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99;
-
 // Caller ID 2nd Tone              (0F):FD,B5,BA,07,DA,00,00,00
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5;
@@ -5276,61 +6680,49 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00;
-
 // ;CR Registers
 	// Config. Reg. 0 (filters)        (cr0):FF
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF;		//0xFE;
-
+	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE;
 // Config. Reg. 1 (dialing)        (cr1):05
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05;
-
 // Config. Reg. 2 (caller ID)      (cr2):04
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04;
-
 // Config. Reg. 3 (testloops)      (cr3):00        ; 
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00;
-
 // Config. Reg. 4 (analog gain)    (cr4):01
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02;		//0x01;
-
-// Config. Reg. 5 (Version)        (cr5):02
+	// Config. Reg. 5 (Version)        (cr5):02
 	// Config. Reg. 6 (Reserved)       (cr6):00
 	// Config. Reg. 7 (Reserved)       (cr7):00
-
-// ;xr Registers
+	// ;xr Registers
 	// Ext. Reg. 0 (Interrupt Reg.)    (xr0):02
+
 	j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02;	// SO_1 set to '1' because it is inverted.
+	// Ext. Reg. 1 (Interrupt enable)  (xr1):1C
 
-// Ext. Reg. 1 (Interrupt enable)  (xr1):1C
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C;		// RING, Caller ID, VDD_OK
+	// Ext. Reg. 2 (Cadence Time Out)  (xr2):7D
 
-// Ext. Reg. 2 (Cadence Time Out)  (xr2):7D
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D;
-
 // Ext. Reg. 3 (DC Char)           (xr3):36        ; 
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x36;
-
 // Ext. Reg. 4 (Cadence)           (xr4):00
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00;
-
 // Ext. Reg. 5 (Ring timer)        (xr5):22
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22;
-
 // Ext. Reg. 6 (Power State)       (xr6):00
 	j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00;
-
 // Ext. Reg. 7 (Vdd)               (xr7):46
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46;		// 0x46 ??? Should it be 0x00?
-
-// DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz  
+	// DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz  
 	//                                       12,33,5A,C3    ;  770 Hz  
 	//                                       13,3C,5B,32    ;  852 Hz  
 	//                                       1D,1B,5C,CC    ;  941 Hz  
+
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C;
-
 // DTMF Tone 2                     (0C): 32,32,52,B3    ;  1209 Hz  
 	//                                       EC,1D,52,22    ;  1336 Hz  
 	//                                       AA,AC,51,D2    ;  1477 Hz  
@@ -5339,24 +6731,23 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
-
 }
 
 
 static void DAA_Coeff_France(int board)
 {
 	IXJ *j = &ixj[board];
-
 	int i;
 
+	j->daa_country = DAA_FRANCE;
 	//-----------------------------------------------
 	// CAO
 	for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) {
 		j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0;
 	}
 
-	// Bytes for IM-filter part 1 (04): 02,A2,43,2C,22,AF,A0,00
-	    j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x02;
+// Bytes for IM-filter part 1 (04): 02,A2,43,2C,22,AF,A0,00
+	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x02;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xA2;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0x43;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2C;
@@ -5364,7 +6755,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xAF;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00;
-
 // Bytes for IM-filter part 2 (05): 67,CE,00,0C,22,33,E0,08
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x67;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0xCE;
@@ -5374,7 +6764,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08;
-
 // Bytes for FRX-filter       (08): 07,9A,28,F6,23,4A,B0,08
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x9A;
@@ -5384,7 +6773,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x4A;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xB0;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08;
-
 // Bytes for FRR-filter       (07): 03,8F,F9,2F,9E,FA,20,08
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x03;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F;
@@ -5394,19 +6782,16 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xFA;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x20;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08;
-
 // Bytes for AX-filter        (0A): 16,B5,DD,CA
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x16;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xB5;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA;
-
 // Bytes for AR-filter        (09): 52,C7,10,D6
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0xE2;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xC7;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6;
-
 // Bytes for TH-filter part 1 (00): 00,42,48,81,A6,80,00,98
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42;
@@ -5416,7 +6801,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98;
-
 // Bytes for TH-filter part 2 (01): 02,AC,2A,30,78,AC,8A,2C
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xAC;
@@ -5426,7 +6810,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0xAC;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x8A;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x2C;
-
 // Bytes for TH-filter part 3 (02): 00,88,DA,A5,22,BA,2C,45
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88;
@@ -5436,10 +6819,8 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xBA;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x2C;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x45;
-
 // ; idle
-
-// Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23
+	// Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93;
@@ -5448,7 +6829,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23;
-
 // Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2;
@@ -5458,13 +6838,11 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5;
-
 // Levelmetering Ringing           (0D):32,45,B5,84     ; 50Hz 20V
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0x32;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0xB5;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x84;
-
 // Caller ID 1st Tone              (0E):CA,0E,CA,09,99,99,99,99
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E;
@@ -5474,7 +6852,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99;
-
 // Caller ID 2nd Tone              (0F):FD,B5,BA,07,DA,00,00,00
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5;
@@ -5484,61 +6861,49 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00;
-
 // ;CR Registers
 	// Config. Reg. 0 (filters)        (cr0):FF
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF;
-
+	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE;
 // Config. Reg. 1 (dialing)        (cr1):05
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05;
-
 // Config. Reg. 2 (caller ID)      (cr2):04
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04;
-
 // Config. Reg. 3 (testloops)      (cr3):00        ; 
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00;
-
 // Config. Reg. 4 (analog gain)    (cr4):01
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02;		//0x01;
-
-// Config. Reg. 5 (Version)        (cr5):02
+	// Config. Reg. 5 (Version)        (cr5):02
 	// Config. Reg. 6 (Reserved)       (cr6):00
 	// Config. Reg. 7 (Reserved)       (cr7):00
-
-// ;xr Registers
+	// ;xr Registers
 	// Ext. Reg. 0 (Interrupt Reg.)    (xr0):02
+
 	j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02;	// SO_1 set to '1' because it is inverted.
+	// Ext. Reg. 1 (Interrupt enable)  (xr1):1C
 
-// Ext. Reg. 1 (Interrupt enable)  (xr1):1C
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C;		// RING, Caller ID, VDD_OK
+	// Ext. Reg. 2 (Cadence Time Out)  (xr2):7D
 
-// Ext. Reg. 2 (Cadence Time Out)  (xr2):7D
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D;
-
 // Ext. Reg. 3 (DC Char)           (xr3):36        ; 
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x36;
-
 // Ext. Reg. 4 (Cadence)           (xr4):00
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00;
-
 // Ext. Reg. 5 (Ring timer)        (xr5):22
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22;
-
 // Ext. Reg. 6 (Power State)       (xr6):00
 	j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00;
-
 // Ext. Reg. 7 (Vdd)               (xr7):46
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46;		// 0x46 ??? Should it be 0x00?
-
-// DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz  
+	// DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz  
 	//                                       12,33,5A,C3    ;  770 Hz  
 	//                                       13,3C,5B,32    ;  852 Hz  
 	//                                       1D,1B,5C,CC    ;  941 Hz  
+
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C;
-
 // DTMF Tone 2                     (0C): 32,32,52,B3    ;  1209 Hz  
 	//                                       EC,1D,52,22    ;  1336 Hz  
 	//                                       AA,AC,51,D2    ;  1477 Hz  
@@ -5547,24 +6912,23 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
-
 }
 
 
 static void DAA_Coeff_Germany(int board)
 {
 	IXJ *j = &ixj[board];
-
 	int i;
 
+	j->daa_country = DAA_GERMANY;
 	//-----------------------------------------------
 	// CAO
 	for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) {
 		j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0;
 	}
 
-	// Bytes for IM-filter part 1 (04): 00,CE,BB,B8,D2,81,B0,00
-	    j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00;
+// Bytes for IM-filter part 1 (04): 00,CE,BB,B8,D2,81,B0,00
+	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xCE;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xBB;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xB8;
@@ -5572,7 +6936,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x81;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xB0;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00;
-
 // Bytes for IM-filter part 2 (05): 45,8F,00,0C,D2,3A,D0,08
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x45;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x8F;
@@ -5582,7 +6945,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x3A;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xD0;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08;
-
 // Bytes for FRX-filter       (08): 07,AA,E2,34,24,89,20,08
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0xAA;
@@ -5592,7 +6954,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x89;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x20;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08;
-
 // Bytes for FRR-filter       (07): 02,87,FA,37,9A,CA,B0,08
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x02;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x87;
@@ -5602,19 +6963,16 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xCA;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xB0;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08;
-
 // Bytes for AX-filter        (0A): 72,D5,DD,CA
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x72;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xD5;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA;
-
 // Bytes for AR-filter        (09): 72,42,13,4B
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x72;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x42;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x13;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0x4B;
-
 // Bytes for TH-filter part 1 (00): 80,52,48,81,AD,80,00,98
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x52;
@@ -5624,7 +6982,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98;
-
 // Bytes for TH-filter part 2 (01): 02,42,5A,20,E8,1A,81,27
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0x42;
@@ -5634,7 +6991,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x1A;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x81;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x27;
-
 // Bytes for TH-filter part 3 (02): 00,88,63,26,BD,4B,A3,C2
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88;
@@ -5644,10 +7000,8 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x4B;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0xA3;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xC2;
-
 // ;  (10K, 0.68uF)
-
-// Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23
+	// Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3B;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x9B;
@@ -5656,7 +7010,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x1C;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xB3;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23;
-
 // Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x13;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x42;
@@ -5666,13 +7019,11 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x73;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0xCA;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5;
-
 // Levelmetering Ringing        (0D):B2,45,0F,8E      
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xB2;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E;
-
 // Caller ID 1st Tone           (0E):CA,0E,CA,09,99,99,99,99
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E;
@@ -5682,7 +7033,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99;
-
 // Caller ID 2nd Tone           (0F):FD,B5,BA,07,DA,00,00,00
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5;
@@ -5692,61 +7042,49 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00;
-
 // ;CR Registers
 	// Config. Reg. 0 (filters)        (cr0):FF ; all Filters enabled, CLK from ext. source
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF;
-
+	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE;
 // Config. Reg. 1 (dialing)        (cr1):05 ; Manual Ring, Ring metering enabled
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05;
-
 // Config. Reg. 2 (caller ID)      (cr2):04 ; Analog Gain 0dB, FSC internal
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04;
-
 // Config. Reg. 3 (testloops)      (cr3):00 ; SEL Bit==0, HP-enabled
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00;
-
 // Config. Reg. 4 (analog gain)    (cr4):01
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02;		//0x01;
-
-// Config. Reg. 5 (Version)        (cr5):02
+	// Config. Reg. 5 (Version)        (cr5):02
 	// Config. Reg. 6 (Reserved)       (cr6):00
 	// Config. Reg. 7 (Reserved)       (cr7):00
-
-// ;xr Registers
+	// ;xr Registers
 	// Ext. Reg. 0 (Interrupt Reg.)    (xr0):02
+
 	j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02;	// SO_1 set to '1' because it is inverted.
+	// Ext. Reg. 1 (Interrupt enable)  (xr1):1C ; Ring, CID, VDDOK Interrupts enabled
 
-// Ext. Reg. 1 (Interrupt enable)  (xr1):1C ; Ring, CID, VDDOK Interrupts enabled
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C;		// RING, Caller ID, VDD_OK
+	// Ext. Reg. 2 (Cadence Time Out)  (xr2):7D
 
-// Ext. Reg. 2 (Cadence Time Out)  (xr2):7D
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D;
-
 // Ext. Reg. 3 (DC Char)           (xr3):32 ; B-Filter Off==1, U0=3.5V, R=200Ohm
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x32;
-
 // Ext. Reg. 4 (Cadence)           (xr4):00
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00;
-
 // Ext. Reg. 5 (Ring timer)        (xr5):22
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22;
-
 // Ext. Reg. 6 (Power State)       (xr6):00
 	j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00;
-
 // Ext. Reg. 7 (Vdd)               (xr7):40 ; VDD=4.25 V
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40;		// 0x40 ??? Should it be 0x00?
-
-// DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz  
+	// DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz  
 	//                                       12,33,5A,C3    ;  770 Hz  
 	//                                       13,3C,5B,32    ;  852 Hz  
 	//                                       1D,1B,5C,CC    ;  941 Hz  
+
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C;
-
 // DTMF Tone 2                     (0C): 32,32,52,B3    ;  1209 Hz  
 	//                                       EC,1D,52,22    ;  1336 Hz  
 	//                                       AA,AC,51,D2    ;  1477 Hz  
@@ -5755,24 +7093,23 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
-
 }
 
 
 static void DAA_Coeff_Australia(int board)
 {
 	IXJ *j = &ixj[board];
-
 	int i;
 
+	j->daa_country = DAA_AUSTRALIA;
 	//-----------------------------------------------
 	// CAO
 	for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) {
 		j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0;
 	}
 
-	// Bytes for IM-filter part 1 (04): 00,A3,AA,28,B3,82,D0,00
-	    j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00;
+// Bytes for IM-filter part 1 (04): 00,A3,AA,28,B3,82,D0,00
+	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xA3;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xAA;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x28;
@@ -5780,7 +7117,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x82;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xD0;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00;
-
 // Bytes for IM-filter part 2 (05): 70,96,00,09,32,6B,C0,08
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x70;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x96;
@@ -5790,7 +7126,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x6B;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xC0;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08;
-
 // Bytes for FRX-filter       (08): 07,96,E2,34,32,9B,30,08
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x96;
@@ -5800,7 +7135,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x9B;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x30;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08;
-
 // Bytes for FRR-filter       (07): 0F,9A,E9,2F,22,CC,A0,08
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x0F;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x9A;
@@ -5810,19 +7144,16 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xCC;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xA0;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08;
-
 // Bytes for AX-filter        (0A): CB,45,DD,CA
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0xCB;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0x45;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA;
-
 // Bytes for AR-filter        (09): 1B,67,10,D6
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x1B;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x67;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6;
-
 // Bytes for TH-filter part 1 (00): 80,52,48,81,AF,80,00,98
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x52;
@@ -5832,7 +7163,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98;
-
 // Bytes for TH-filter part 2 (01): 02,DB,52,B0,38,01,82,AC
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xDB;
@@ -5842,7 +7172,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x01;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x82;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xAC;
-
 // Bytes for TH-filter part 3 (02): 00,88,4A,3E,2C,3B,24,46
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88;
@@ -5852,10 +7181,8 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x3B;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x24;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x46;
-
 // ;  idle
-
-// Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23
+	// Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93;
@@ -5864,7 +7191,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23;
-
 // Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2;
@@ -5874,13 +7200,11 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5;
-
 // Levelmetering Ringing           (0D):32,45,B5,84   ; 50Hz 20V
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0x32;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0xB5;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x84;
-
 // Caller ID 1st Tone              (0E):CA,0E,CA,09,99,99,99,99
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E;
@@ -5890,7 +7214,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99;
-
 // Caller ID 2nd Tone              (0F):FD,B5,BA,07,DA,00,00,00
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5;
@@ -5900,61 +7223,49 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00;
-
 // ;CR Registers
 	// Config. Reg. 0 (filters)        (cr0):FF
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF;
-
 // Config. Reg. 1 (dialing)        (cr1):05
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05;
-
 // Config. Reg. 2 (caller ID)      (cr2):04
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04;
-
 // Config. Reg. 3 (testloops)      (cr3):00        ; 
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00;
-
 // Config. Reg. 4 (analog gain)    (cr4):01
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02;		//0x01;
-
-// Config. Reg. 5 (Version)        (cr5):02
+	// Config. Reg. 5 (Version)        (cr5):02
 	// Config. Reg. 6 (Reserved)       (cr6):00
 	// Config. Reg. 7 (Reserved)       (cr7):00
-
-// ;xr Registers
+	// ;xr Registers
 	// Ext. Reg. 0 (Interrupt Reg.)    (xr0):02
+
 	j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02;	// SO_1 set to '1' because it is inverted.
+	// Ext. Reg. 1 (Interrupt enable)  (xr1):1C
 
-// Ext. Reg. 1 (Interrupt enable)  (xr1):1C
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C;		// RING, Caller ID, VDD_OK
+	// Ext. Reg. 2 (Cadence Time Out)  (xr2):7D
 
-// Ext. Reg. 2 (Cadence Time Out)  (xr2):7D
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D;
-
 // Ext. Reg. 3 (DC Char)           (xr3):2B      ; 
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x2B;
-
 // Ext. Reg. 4 (Cadence)           (xr4):00
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00;
-
 // Ext. Reg. 5 (Ring timer)        (xr5):22
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22;
-
 // Ext. Reg. 6 (Power State)       (xr6):00
 	j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00;
-
 // Ext. Reg. 7 (Vdd)               (xr7):40
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40;		// 0x40 ??? Should it be 0x00?
-
-// DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz  
+	// DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz  
 	//                                       12,33,5A,C3    ;  770 Hz  
 	//                                       13,3C,5B,32    ;  852 Hz  
 	//                                       1D,1B,5C,CC    ;  941 Hz  
+
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C;
-
 // DTMF Tone 2                     (0C): 32,32,52,B3    ;  1209 Hz  
 	//                                       EC,1D,52,22    ;  1336 Hz  
 	//                                       AA,AC,51,D2    ;  1477 Hz  
@@ -5963,23 +7274,22 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
-
 }
 
 static void DAA_Coeff_Japan(int board)
 {
 	IXJ *j = &ixj[board];
-
 	int i;
 
+	j->daa_country = DAA_JAPAN;
 	//-----------------------------------------------
 	// CAO
 	for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) {
 		j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0;
 	}
 
-	// Bytes for IM-filter part 1 (04): 06,BD,E2,2D,BA,F9,A0,00
-	    j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x06;
+// Bytes for IM-filter part 1 (04): 06,BD,E2,2D,BA,F9,A0,00
+	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x06;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xBD;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xE2;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2D;
@@ -5987,7 +7297,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xF9;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00;
-
 // Bytes for IM-filter part 2 (05): 6F,F7,00,0E,34,33,E0,08
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x6F;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0xF7;
@@ -5997,7 +7306,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0;
 	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08;
-
 // Bytes for FRX-filter       (08): 02,8F,68,77,9C,58,F0,08
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x02;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x8F;
@@ -6007,7 +7315,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x58;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xF0;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08;
-
 // Bytes for FRR-filter       (07): 03,8F,38,73,87,EA,20,08
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x03;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F;
@@ -6017,19 +7324,16 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xEA;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x20;
 	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08;
-
 // Bytes for AX-filter        (0A): 51,C5,DD,CA
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x51;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xC5;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD;
 	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA;
-
 // Bytes for AR-filter        (09): 25,A7,10,D6
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x25;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xA7;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10;
 	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6;
-
 // Bytes for TH-filter part 1 (00): 00,42,48,81,AE,80,00,98
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42;
@@ -6039,7 +7343,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98;
-
 // Bytes for TH-filter part 2 (01): 02,AB,2A,20,99,5B,89,28
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xAB;
@@ -6049,7 +7352,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x5B;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x89;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x28;
-
 // Bytes for TH-filter part 3 (02): 00,88,DA,25,34,C5,4C,BA
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88;
@@ -6059,10 +7361,8 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xC5;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x4C;
 	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xBA;
-
 // ;  idle
-
-// Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23
+	// Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93;
@@ -6071,7 +7371,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23;
-
 // Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2;
@@ -6081,13 +7380,11 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A;
 	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5;
-
 // Levelmetering Ringing           (0D):AA,35,0F,8E    ; 25Hz 30V ?????????
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F;
 	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E;
-
 // Caller ID 1st Tone              (0E):CA,0E,CA,09,99,99,99,99
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E;
@@ -6097,7 +7394,6 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99;
-
 // Caller ID 2nd Tone              (0F):FD,B5,BA,07,DA,00,00,00
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5;
@@ -6107,76 +7403,62 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00;
 	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00;
-
 // ;CR Registers
 	// Config. Reg. 0 (filters)        (cr0):FF
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF;
-
+	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE;
 // Config. Reg. 1 (dialing)        (cr1):05
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05;
-
 // Config. Reg. 2 (caller ID)      (cr2):04
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04;
-
 // Config. Reg. 3 (testloops)      (cr3):00        ; 
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00;
-
 // Config. Reg. 4 (analog gain)    (cr4):01
 	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02;		//0x01;
-
-// Config. Reg. 5 (Version)        (cr5):02
+	// Config. Reg. 5 (Version)        (cr5):02
 	// Config. Reg. 6 (Reserved)       (cr6):00
 	// Config. Reg. 7 (Reserved)       (cr7):00
-
-// ;xr Registers
+	// ;xr Registers
 	// Ext. Reg. 0 (Interrupt Reg.)    (xr0):02
+
 	j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02;	// SO_1 set to '1' because it is inverted.
+	// Ext. Reg. 1 (Interrupt enable)  (xr1):1C
 
-// Ext. Reg. 1 (Interrupt enable)  (xr1):1C
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C;		// RING, Caller ID, VDD_OK
+	// Ext. Reg. 2 (Cadence Time Out)  (xr2):7D
 
-// Ext. Reg. 2 (Cadence Time Out)  (xr2):7D
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D;
-
 // Ext. Reg. 3 (DC Char)           (xr3):22        ; 
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x22;
-
 // Ext. Reg. 4 (Cadence)           (xr4):00
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00;
-
 // Ext. Reg. 5 (Ring timer)        (xr5):22
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22;
-
 // Ext. Reg. 6 (Power State)       (xr6):00
 	j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00;
-
 // Ext. Reg. 7 (Vdd)               (xr7):40
 	j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40;		// 0x40 ??? Should it be 0x00?
-
-// DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz  
+	// DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz  
 	//                                       12,33,5A,C3    ;  770 Hz  
 	//                                       13,3C,5B,32    ;  852 Hz  
 	//                                       1D,1B,5C,CC    ;  941 Hz  
+
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C;
-
 // DTMF Tone 2                     (0C): 32,32,52,B3    ;  1209 Hz  
 	//                                       EC,1D,52,22    ;  1336 Hz  
 	//                                       AA,AC,51,D2    ;  1477 Hz  
 	//                                       9B,3B,51,25    ;  1633 Hz  
-
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52;
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
-
 }
 
 static s16 tone_table[][19] =
 {
-	{			// f20_50[]
+	{			// f20_50[] 11
 		32538,		// A1 = 1.985962
 		 -32325,	// A2 = -0.986511
 		 -343,		// B2 = -0.010493
@@ -6197,7 +7479,7 @@
 		 21,		// 21/32 in-band to broad-band ratio
 		 0x0FF5		// shift-mask 0x0FF (look at 16 half-frames) bit count = 5
 	},
-	{			// f133_200[]
+	{			// f133_200[] 12
 		32072,		// A1 = 1.95752
 		 -31896,	// A2 = -0.973419
 		 -435,		// B2 = -0.013294
@@ -6218,7 +7500,7 @@
 		 21,		// 21/32 in-band to broad-band ratio
 		 0x0FF5		// shift-mask 0x0FF (look at 16 half-frames) bit count = 5
 	},
-	{			// 300.txt
+	{			// 300.txt 13
 		31769,		// A1 = -1.939026
 		 -32584,	// A2 = 0.994385
 		 -475,		// B2 = -0.014522
@@ -6239,7 +7521,7 @@
 		 21,		// 21/32 in-band to broad-band ratio
 		 0x0FF5		// shift-mask 0x0FF (look at 16 half-frames) bit count = 5
 	},
-	{			// f300_420[]
+	{			// f300_420[] 14
 		30750,		// A1 = 1.876892
 		 -31212,	// A2 = -0.952515
 		 -804,		// B2 = -0.024541
@@ -6260,7 +7542,7 @@
 		 21,		// 21/32 in-band to broad-band ratio
 		 0x0FF5		// shift-mask 0x0FF (look at 16 half-frames) bit count = 5
 	},
-	{			// 330.txt
+	{			// 330.txt 15
 		31613,		// A1 = -1.929565
 		 -32646,	// A2 = 0.996277
 		 -185,		// B2 = -0.005657
@@ -6281,7 +7563,7 @@
 		 21,		// 21/32 in-band to broad-band ratio
 		 0x0FF5		// shift-mask 0x0FF (look at 16 half-frames) bit count = 5
 	},
-	{			// f300_425[]
+	{			// f300_425[] 16
 		30741,		// A1 = 1.876282
 		 -31475,	// A2 = -0.960541
 		 -703,		// B2 = -0.021484
@@ -6302,7 +7584,7 @@
 		 21,		// 21/32 in-band to broad-band ratio
 		 0x0FF5		// shift-mask 0x0FF (look at 16 half-frames) bit count = 5
 	},
-	{			// f330_440[]
+	{			// f330_440[] 17
 		30627,		// A1 = 1.869324
 		 -31338,	// A2 = -0.95636
 		 -843,		// B2 = -0.025749
@@ -6323,7 +7605,7 @@
 		 21,		// 21/32 in-band to broad-band ratio
 		 0x0FF5		// shift-mask 0x0FF (look at 16 half-frames) bit count = 5
 	},
-	{			// 340.txt
+	{			// 340.txt 18
 		31546,		// A1 = -1.925476
 		 -32646,	// A2 = 0.996277
 		 -445,		// B2 = -0.013588
@@ -6344,7 +7626,7 @@
 		 21,		// 21/32 in-band to broad-band ratio
 		 0x0FF5		// shift-mask 0x0FF (look at 16 half-frames) bit count = 5
 	},
-	{			// f350_400[]
+	{			// f350_400[] 19
 		31006,		// A1 = 1.892517
 		 -32029,	// A2 = -0.977448
 		 -461,		// B2 = -0.014096
@@ -7708,21 +8990,19 @@
 		 159,		// Minimum in-band energy threshold
 		 21,		// 21/32 in-band to broad-band ratio
 		 0x0FF5		// shift-mask 0x0FF (look at 16 half-frames) bit count = 5
-	},};
-
+	},
+};
 static int ixj_init_filter(int board, IXJ_FILTER * jf)
 {
 	unsigned short cmd;
 	int cnt, max;
 	IXJ *j = &ixj[board];
-
 	if (jf->filter > 3) {
 		return -1;
 	}
 	if (ixj_WriteDSPCommand(0x5154 + jf->filter, board))	// Select Filter
 
 		return -1;
-
 	if (!jf->enable) {
 		if (ixj_WriteDSPCommand(0x5152, board))		// Disable Filter
 
@@ -7733,7 +9013,6 @@
 		if (ixj_WriteDSPCommand(0x5153, board))		// Enable Filter
 
 			return -1;
-
 		// Select the filter (f0 - f3) to use.
 		if (ixj_WriteDSPCommand(0x5154 + jf->filter, board))
 			return -1;
@@ -7750,7 +9029,6 @@
 		// frequency we want.
 		if (ixj_WriteDSPCommand(0x5170 + jf->filter, board))
 			return -1;
-
 		if (j->ver.low != 0x12) {
 			cmd = 0x515B;
 			max = 19;
@@ -7760,23 +9038,12 @@
 		}
 		if (ixj_WriteDSPCommand(cmd, board))
 			return -1;
-
 		for (cnt = 0; cnt < max; cnt++) {
-			if (ixj_WriteDSPCommand(tone_table[jf->freq][cnt], board))
+			if (ixj_WriteDSPCommand(tone_table[jf->freq - 12][cnt], board))
 				return -1;
 		}
-/*    if(j->ver.low != 0x12)
-   {
-   if(ixj_WriteDSPCommand(7, board))
-   return -1;
-   if(ixj_WriteDSPCommand(159, board))
-   return -1;
-   if(ixj_WriteDSPCommand(21, board))
-   return -1;
-   if(ixj_WriteDSPCommand(0x0FF5, board))
-   return -1;
-   } */
 	}
+	j->filter_en[jf->filter] = jf->enable;
 	return 0;
 }
 
@@ -7784,7 +9051,6 @@
 {
 	int freq0, freq1;
 	unsigned short data;
-
 	if (ti->freq0) {
 		freq0 = ti->freq0;
 	} else {
@@ -7797,18 +9063,15 @@
 		freq1 = 0x7FFF;
 	}
 
-//  if(ti->tone_index > 12 && ti->tone_index < 28)
+	if(ti->tone_index > 12 && ti->tone_index < 28)
 	{
 		if (ixj_WriteDSPCommand(0x6800 + ti->tone_index, board))
 			return -1;
-
 		if (ixj_WriteDSPCommand(0x6000 + (ti->gain0 << 4) + ti->gain1, board))
 			return -1;
-
 		data = freq0;
 		if (ixj_WriteDSPCommand(data, board))
 			return -1;
-
 		data = freq1;
 		if (ixj_WriteDSPCommand(data, board))
 			return -1;
diff -urN linux-2.2.17-pre1/drivers/telephony/ixj.h linux/drivers/telephony/ixj.h
--- linux-2.2.17-pre1/drivers/telephony/ixj.h	Tue Jan  4 10:12:22 2000
+++ linux/drivers/telephony/ixj.h	Mon Dec  3 22:05:27 2001
@@ -1,4 +1,4 @@
-/*
+/******************************************************************************
  *    ixj.h
  *
  *    Device Driver for the Internet PhoneJACK and
@@ -22,8 +22,20 @@
  * at our website:    http://www.quicknet.net
  *
  * Fixes:
- */
-static char ixj_h_rcsid[] = "$Id: ixj.h,v 3.4 1999/12/16 22:18:36 root Exp root $";
+ *
+ * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET
+ * TECHNOLOGIES, INC.HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION 
+ * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ *****************************************************************************/
+static char ixj_h_rcsid[] = "$Id: ixj.h,v 3.14 2000/03/30 22:06:48 eokerson Exp $";
 
 #ifndef _I386_TYPES_H
 #include <asm/types.h>
@@ -60,6 +72,27 @@
 	unsigned char high;
 } BYTES;
 
+typedef union {
+        BYTES bytes;
+        short word;
+} IXJ_WORD;
+
+typedef struct{
+	unsigned int b0:1;
+	unsigned int b1:1;
+	unsigned int b2:1;
+	unsigned int b3:1;
+	unsigned int b4:1;
+	unsigned int b5:1;
+	unsigned int b6:1;
+	unsigned int b7:1;
+} IXJ_CBITS;
+
+typedef union{
+	IXJ_CBITS cbits;
+	  char  cbyte;
+} IXJ_CBYTE;
+
 int ixj_WriteDSPCommand(unsigned short, int board);
 
 /******************************************************************************
@@ -327,6 +360,199 @@
 
 /******************************************************************************
 *
+*  These structures deal with the control logic on the Internet PhoneCARD
+*
+******************************************************************************/
+typedef struct {
+	unsigned int x0:4;	// unused bits
+
+	unsigned int ed:1;	// Event Detect
+
+	unsigned int drf:1;	// Smart Cable Removal Flag 1=no cable
+
+	unsigned int dspf:1;	// DSP Flag 1=DSP Ready
+
+	unsigned int crr:1;	// Control Register Ready
+
+} COMMAND_REG1;
+
+typedef union {
+	COMMAND_REG1 bits;
+	unsigned char byte;
+} PCMCIA_CR1;
+
+typedef struct {
+	unsigned int x0:4;	// unused bits
+
+	unsigned int rstc:1;	// Smart Cable Reset
+
+	unsigned int pwr:1;	// Smart Cable Power
+
+	unsigned int x1:2;	// unused bits
+
+} COMMAND_REG2;
+
+typedef union {
+	COMMAND_REG2 bits;
+	unsigned char byte;
+} PCMCIA_CR2;
+
+typedef struct {
+	unsigned int addr:5;	// R/W Smart Cable Register Address
+
+	unsigned int rw:1;	// Read / Write flag
+
+	unsigned int dev:2;	// 2 bit Smart Cable Device Address
+
+} CONTROL_REG;
+
+typedef union {
+	CONTROL_REG bits;
+	unsigned char byte;
+} PCMCIA_SCCR;
+
+typedef struct {
+	unsigned int hsw:1;
+	unsigned int det:1;
+	unsigned int led2:1;
+	unsigned int led1:1;
+	unsigned int ring1:1;
+	unsigned int ring0:1;
+	unsigned int x:1;
+	unsigned int powerdown:1;
+} PCMCIA_SLIC_REG;
+
+typedef union {
+	PCMCIA_SLIC_REG bits;
+	unsigned char byte;
+} PCMCIA_SLIC;
+
+typedef struct {
+	unsigned int cpd:1;	// Chip Power Down
+
+	unsigned int mpd:1;	// MIC Bias Power Down
+
+	unsigned int hpd:1;	// Handset Drive Power Down
+
+	unsigned int lpd:1;	// Line Drive Power Down
+
+	unsigned int spd:1;	// Speaker Drive Power Down
+
+	unsigned int x:2;	// unused bits
+
+	unsigned int sr:1;	// Software Reset
+
+} Si3CONTROL1;
+
+typedef union {
+	Si3CONTROL1 bits;
+	unsigned char byte;
+} Si3C1;
+
+typedef struct {
+	unsigned int al:1;	// Analog Loopback DAC analog -> ADC analog
+
+	unsigned int dl2:1;	// Digital Loopback DAC -> ADC one bit
+
+	unsigned int dl1:1;	// Digital Loopback ADC -> DAC one bit
+
+	unsigned int pll:1;	// 1 = div 10, 0 = div 5
+
+	unsigned int hpd:1;	// HPF disable
+
+	unsigned int x:3;	// unused bits
+
+} Si3CONTROL2;
+
+typedef union {
+	Si3CONTROL2 bits;
+	unsigned char byte;
+} Si3C2;
+
+typedef struct {
+	unsigned int iir:1;	// 1 enables IIR, 0 enables FIR
+
+	unsigned int him:1;	// Handset Input Mute
+
+	unsigned int mcm:1;	// MIC In Mute
+
+	unsigned int mcg:2;	// MIC In Gain
+
+	unsigned int lim:1;	// Line In Mute
+
+	unsigned int lig:2;	// Line In Gain
+
+} Si3RXGAIN;
+
+typedef union {
+	Si3RXGAIN bits;
+	unsigned char byte;
+} Si3RXG;
+
+typedef struct {
+	unsigned int hom:1;	// Handset Out Mute
+
+	unsigned int lom:1;	// Line Out Mute
+
+	unsigned int rxg:5;	// RX PGA Gain
+
+	unsigned int x:1;	// unused bit
+
+} Si3ADCVOLUME;
+
+typedef union {
+	Si3ADCVOLUME bits;
+	unsigned char byte;
+} Si3ADC;
+
+typedef struct {
+	unsigned int srm:1;	// Speaker Right Mute
+
+	unsigned int slm:1;	// Speaker Left Mute
+
+	unsigned int txg:5;	// TX PGA Gain
+
+	unsigned int x:1;	// unused bit
+
+} Si3DACVOLUME;
+
+typedef union {
+	Si3DACVOLUME bits;
+	unsigned char byte;
+} Si3DAC;
+
+typedef struct {
+	unsigned int x:5;	// unused bit
+
+	unsigned int losc:1;	// Line Out Short Circuit
+
+	unsigned int srsc:1;	// Speaker Right Short Circuit
+
+	unsigned int slsc:1;	// Speaker Left Short Circuit
+
+} Si3STATUSREPORT;
+
+typedef union {
+	Si3STATUSREPORT bits;
+	unsigned char byte;
+} Si3STAT;
+
+typedef struct {
+	unsigned int sot:2;	// Speaker Out Attenuation
+
+	unsigned int lot:2;	// Line Out Attenuation
+
+	unsigned int x:4;	// unused bits
+
+} Si3ANALOGATTN;
+
+typedef union {
+	Si3ANALOGATTN bits;
+	unsigned char byte;
+} Si3AATT;
+
+/******************************************************************************
+*
 *  These structures deal with the DAA on the Internet LineJACK
 *
 ******************************************************************************/
@@ -854,10 +1080,49 @@
 };
 
 typedef struct {
+	char enable;
+	char en_filter;
+	unsigned int filter;
+	unsigned int state;	// State 0 when cadence has not started.
+
+	unsigned int on1;	// State 1
+
+	unsigned long on1min;	// State 1 - 10% + jiffies
+ 	unsigned long on1dot;	// State 1 + jiffies
+
+	unsigned long on1max;	// State 1 + 10% + jiffies
+
+	unsigned int off1;	// State 2
+
+	unsigned long off1min;
+	unsigned long off1max;
+	unsigned int on2;	// State 3
+
+	unsigned long on2min;
+	unsigned long on2dot;
+	unsigned long on2max;
+	unsigned int off2;	// State 4
+
+	unsigned long off2min;
+	unsigned long off2max;
+	unsigned int on3;	// State 5
+
+	unsigned long on3min;
+	unsigned long on3dot;
+	unsigned long on3max;
+	unsigned int off3;	// State 6
+
+	unsigned long off3min;
+	unsigned long off3max;
+} IXJ_CADENCE_F;
+
+typedef struct {
 	unsigned int busytone:1;
 	unsigned int dialtone:1;
 	unsigned int ringback:1;
 	unsigned int ringing:1;
+	unsigned int playing:1;
+	unsigned int recording:1;
 	unsigned int cringing:1;
 	unsigned int play_first_frame:1;
 	unsigned int pstn_present:1;
@@ -868,6 +1133,28 @@
 	unsigned int ts85_loaded:1;
 	unsigned int dtmf_oob:1;	// DTMF Out-Of-Band
 
+	unsigned int pcmciascp:1;	// Smart Cable Present
+
+	unsigned int pcmciasct:2;	// Smart Cable Type
+
+	unsigned int pcmciastate:3;	// Smart Cable Init State
+
+	unsigned int inwrite:1;	// Currently writing
+
+	unsigned int inread:1;	// Currently reading
+
+	unsigned int incheck:1;	// Currently checking the smart cable
+
+	unsigned int cidplay:1; // Currently playing Caller ID
+
+	unsigned int cidring:1; // This is the ring for Caller ID
+
+	unsigned int cidsent:1; // Caller ID has been sent
+
+	unsigned int cidcw_ack:1; // Caller ID CW ACK (from CPE)
+
+	unsigned int x:6;	// unsed bits
+
 } IXJ_FLAGS;
 
 /******************************************************************************
@@ -884,15 +1171,19 @@
 	unsigned int serial;
 	struct phone_capability caplist[30];
 	unsigned int caps;
+	unsigned int country;
 	struct pnp_dev *dev;
 	unsigned int cardtype;
 	unsigned int rec_codec;
 	char rec_mode;
 	unsigned int play_codec;
+	unsigned int cid_play_codec;
 	char play_mode;
 	IXJ_FLAGS flags;
 	unsigned int rec_frame_size;
 	unsigned int play_frame_size;
+	unsigned int cid_base_frame_size;
+	unsigned long cidcw_wait;
 	int aec_level;
 	int readers, writers;
 	struct wait_queue *poll_q;
@@ -919,6 +1210,7 @@
 	char maxrings;
 	IXJ_CADENCE *cadence_t;
 	int tone_cadence_state;
+	IXJ_CADENCE_F cadence_f[4];
 	DTMF dtmf;
 	CPTF cptf;
 	BYTES dsp;
@@ -933,30 +1225,50 @@
 	PLD_SLICW pld_slicw;
 	PLD_SLICR pld_slicr;
 	PLD_CLOCK pld_clock;
+	PCMCIA_CR1 pccr1;
+	PCMCIA_CR2 pccr2;
+	PCMCIA_SCCR psccr;
+	PCMCIA_SLIC pslic;
+	char pscdd;
+	Si3C1 sic1;
+	Si3C2 sic2;
+	Si3RXG sirxg;
+	Si3ADC siadc;
+	Si3DAC sidac;
+	Si3STAT sistat;
+	Si3AATT siaatt;
 	MIX mix;
 	unsigned short ring_cadence;
 	int ring_cadence_t;
 	unsigned long ring_cadence_jif;
+	unsigned long checkwait;
 	int intercom;
 	int m_hook;
 	int r_hook;
 	char pstn_envelope;
 	char pstn_cid_intr;
+	unsigned char fskz;
+	unsigned char fskphase;
+	unsigned char fskcnt;
 	unsigned pstn_cid_recieved;
-	IXJ_CID cid;
+	PHONE_CID cid;
+	PHONE_CID cid_send;
 	unsigned long pstn_ring_start;
+	unsigned long pstn_ring_stop;
 	unsigned long pstn_winkstart;
 	unsigned int winktime;
+	unsigned long flash_end;
 	char port;
 	union telephony_exception ex;
 	char daa_mode;
+	char daa_country;
 	unsigned long pstn_sleeptil;
 	DAA_REGS m_DAAShadowRegs;
 	Proc_Info_Type Info_read;
 	Proc_Info_Type Info_write;
 	unsigned short frame_count;
-	unsigned int filter_cadence;
 	unsigned int filter_hist[4];
+	unsigned char filter_en[4];
 	unsigned short proc_load;
 	unsigned long framesread;
 	unsigned long frameswritten;
@@ -965,6 +1277,8 @@
 	unsigned long timerchecks;
 	unsigned long txreadycheck;
 	unsigned long rxreadycheck;
+	short fskdata[8000];
+	int fskdcnt;
 } IXJ;
 
 typedef int (*IXJ_REGFUNC) (IXJ * j, unsigned long arg);
diff -urN linux-2.2.17-pre1/fs/affs/file.c linux/fs/affs/file.c
--- linux-2.2.17-pre1/fs/affs/file.c	Mon Aug 24 13:02:44 1998
+++ linux/fs/affs/file.c	Mon Dec  3 22:05:27 2001
@@ -221,6 +221,8 @@
 
 	for (index = 0; index < 4; index++) {
 		kc = &inode->u.affs_i.i_ec->kc[index];
+		if (kc->kc_last == -1)		/* don't look in cache if invalid */
+			continue;
 		if (*ext == kc->kc_this_seq) {
 			return kc->kc_this_key;
 		} else if (*ext == kc->kc_this_seq + 1) {
@@ -893,7 +895,7 @@
 	/* Invalidate cache */
 	if (inode->u.affs_i.i_ec) {
 		inode->u.affs_i.i_ec->max_ext = 0;
-		for (key = 0; key < 3; key++) {
+		for (key = 0; key < 4; key++) {
 			inode->u.affs_i.i_ec->kc[key].kc_next_key = 0;
 			inode->u.affs_i.i_ec->kc[key].kc_last     = -1;
 		}
diff -urN linux-2.2.17-pre1/fs/proc/array.c linux/fs/proc/array.c
--- linux-2.2.17-pre1/fs/proc/array.c	Wed Jun  7 14:26:44 2000
+++ linux/fs/proc/array.c	Mon Dec  3 22:05:28 2001
@@ -1486,7 +1486,7 @@
 		case PROC_PID_CPU:
 			return 0;	
 	}
-	if(capable(CAP_DAC_OVERRIDE) || (current->fsuid == euid && ok))
+	if((current->fsuid == euid && ok) || capable(CAP_DAC_OVERRIDE))
 		return 0;
 	return 1;
 }
diff -urN linux-2.2.17-pre1/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- linux-2.2.17-pre1/include/asm-alpha/unistd.h	Wed May  3 17:16:47 2000
+++ linux/include/asm-alpha/unistd.h	Mon Dec  3 22:05:28 2001
@@ -315,7 +315,7 @@
 #define __NR_mincore			375	/* implemented in 2.3 */
 #define __NR_pciconfig_iobase		376
 
-#if defined(__LIBRARY__) && defined(__GNUC__)
+#if defined(__GNUC__)
 
 #define _syscall_return(type)						\
 	return (_sc_err ? errno = _sc_ret, _sc_ret = -1L : 0), (type) _sc_ret
@@ -495,7 +495,7 @@
 	_syscall_return(type);						\
 }
 
-#endif /* __LIBRARY__ && __GNUC__ */
+#endif /* __GNUC__ */
 
 #ifdef __KERNEL_SYSCALLS__
 
diff -urN linux-2.2.17-pre1/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- linux-2.2.17-pre1/include/asm-i386/processor.h	Tue May 11 10:35:44 1999
+++ linux/include/asm-i386/processor.h	Mon Dec  3 22:05:28 2001
@@ -48,6 +48,8 @@
 #define X86_VENDOR_UMC 3
 #define X86_VENDOR_NEXGEN 4
 #define X86_VENDOR_CENTAUR 5
+#define X86_VENDOR_RISE 6
+#define X86_VENDOR_TRANSMETA 7
 #define X86_VENDOR_UNKNOWN 0xff
 
 /*
diff -urN linux-2.2.17-pre1/include/linux/cdrom.h linux/include/linux/cdrom.h
--- linux-2.2.17-pre1/include/linux/cdrom.h	Mon Dec  3 22:05:22 2001
+++ linux/include/linux/cdrom.h	Mon Dec  3 22:05:28 2001
@@ -443,6 +443,7 @@
 #define GPCMD_PAUSE_RESUME		    0x4b
 #define GPCMD_PLAY_AUDIO_10		    0x45
 #define GPCMD_PLAY_AUDIO_MSF		    0x47
+#define GPCMD_PLAY_AUDIO_TI		    0x48
 #define GPCMD_PLAY_CD			    0xbc
 #define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL  0x1e
 #define GPCMD_READ_10			    0x28
diff -urN linux-2.2.17-pre1/include/linux/falc-lh.h linux/include/linux/falc-lh.h
--- linux-2.2.17-pre1/include/linux/falc-lh.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/falc-lh.h	Mon Dec  3 22:05:28 2001
@@ -0,0 +1,1231 @@
+/*
+ * falc.h	Description of the Siemens FALC T1/E1 framer.
+ *
+ * Author:	Ivan Passos <ivan@cyclades.com>
+ *
+ * Copyright:	(c) 2000 Cyclades Corp.
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ * $Log: falc.h,v $
+ * Revision 1.1 2000/05/15 ivan
+ * Included DJA bits for the LIM2 register.
+ *
+ * Revision 1.0 2000/02/22 ivan
+ * Initial version.
+ *
+ */
+
+#ifndef _FALC_LH_H
+#define _FALC_LH_H
+
+#define NUM_OF_T1_CHANNELS	24
+#define NUM_OF_E1_CHANNELS	32
+
+/*>>>>>>>>>>>>>>>>>  FALC Register Bits (Transmit Mode)  <<<<<<<<<<<<<<<<<<< */
+
+/* CMDR (Command Register)
+   ---------------- E1 & T1 ------------------------------ */
+#define CMDR_RMC	0x80
+#define CMDR_RRES	0x40
+#define CMDR_XREP	0x20
+#define CMDR_XRES	0x10
+#define CMDR_XHF	0x08
+#define CMDR_XTF	0x04
+#define CMDR_XME	0x02
+#define CMDR_SRES	0x01
+
+/* MODE (Mode Register)
+   ----------------- E1 & T1 ----------------------------- */
+#define MODE_MDS2	0x80
+#define MODE_MDS1	0x40
+#define MODE_MDS0	0x20
+#define MODE_BRAC	0x10
+#define MODE_HRAC	0x08
+
+/* IPC (Interrupt Port Configuration)
+   ----------------- E1 & T1 ----------------------------- */
+#define IPC_VIS		0x80
+#define IPC_SCI		0x04
+#define IPC_IC1		0x02
+#define IPC_IC0		0x01
+
+/* CCR1 (Common Configuration Register 1)
+   ----------------- E1 & T1 ----------------------------- */
+#define CCR1_SFLG       0x80
+#define CCR1_XTS16RA    0x40
+#define CCR1_BRM        0x40
+#define CCR1_CASSYM     0x20
+#define CCR1_EDLX       0x20
+#define CCR1_EITS       0x10
+#define CCR1_ITF        0x08
+#define CCR1_RFT1       0x02
+#define CCR1_RFT0       0x01
+
+/* CCR3 (Common Configuration Register 3)
+   ---------------- E1 & T1 ------------------------------ */
+
+#define CCR3_PRE1       0x80
+#define CCR3_PRE0       0x40
+#define CCR3_EPT        0x20
+#define CCR3_RADD       0x10
+#define CCR3_RCRC       0x04
+#define CCR3_XCRC       0x02
+
+
+/* RTR1-4 (Receive Timeslot Register 1-4)
+   ---------------- E1 & T1 ------------------------------ */
+
+#define RTR1_TS0        0x80
+#define RTR1_TS1        0x40
+#define RTR1_TS2        0x20
+#define RTR1_TS3        0x10
+#define RTR1_TS4        0x08
+#define RTR1_TS5        0x04
+#define RTR1_TS6        0x02
+#define RTR1_TS7        0x01
+
+#define RTR2_TS8        0x80
+#define RTR2_TS9        0x40
+#define RTR2_TS10       0x20
+#define RTR2_TS11       0x10
+#define RTR2_TS12       0x08
+#define RTR2_TS13       0x04
+#define RTR2_TS14       0x02
+#define RTR2_TS15       0x01
+
+#define RTR3_TS16       0x80
+#define RTR3_TS17       0x40
+#define RTR3_TS18       0x20
+#define RTR3_TS19       0x10
+#define RTR3_TS20       0x08
+#define RTR3_TS21       0x04
+#define RTR3_TS22       0x02
+#define RTR3_TS23       0x01
+
+#define RTR4_TS24       0x80
+#define RTR4_TS25       0x40
+#define RTR4_TS26       0x20
+#define RTR4_TS27       0x10
+#define RTR4_TS28       0x08
+#define RTR4_TS29       0x04
+#define RTR4_TS30       0x02
+#define RTR4_TS31       0x01
+
+
+/* TTR1-4 (Transmit Timeslot Register 1-4)
+   ---------------- E1 & T1 ------------------------------ */
+
+#define TTR1_TS0        0x80
+#define TTR1_TS1        0x40
+#define TTR1_TS2        0x20
+#define TTR1_TS3        0x10
+#define TTR1_TS4        0x08
+#define TTR1_TS5        0x04
+#define TTR1_TS6        0x02
+#define TTR1_TS7        0x01
+
+#define TTR2_TS8        0x80
+#define TTR2_TS9        0x40
+#define TTR2_TS10       0x20
+#define TTR2_TS11       0x10
+#define TTR2_TS12       0x08
+#define TTR2_TS13       0x04
+#define TTR2_TS14       0x02
+#define TTR2_TS15       0x01
+
+#define TTR3_TS16       0x80
+#define TTR3_TS17       0x40
+#define TTR3_TS18       0x20
+#define TTR3_TS19       0x10
+#define TTR3_TS20       0x08
+#define TTR3_TS21       0x04
+#define TTR3_TS22       0x02
+#define TTR3_TS23       0x01
+
+#define TTR4_TS24       0x80
+#define TTR4_TS25       0x40
+#define TTR4_TS26       0x20
+#define TTR4_TS27       0x10
+#define TTR4_TS28       0x08
+#define TTR4_TS29       0x04
+#define TTR4_TS30       0x02
+#define TTR4_TS31       0x01
+
+
+
+/* IMR0-4 (Interrupt Mask Register 0-4)
+
+   ----------------- E1 & T1 ----------------------------- */
+
+#define IMR0_RME        0x80
+#define IMR0_RFS        0x40
+#define IMR0_T8MS       0x20
+#define IMR0_ISF        0x20
+#define IMR0_RMB        0x10
+#define IMR0_CASC       0x08
+#define IMR0_RSC        0x08
+#define IMR0_CRC6       0x04
+#define IMR0_CRC4       0x04
+#define IMR0_PDEN	0x02
+#define IMR0_RPF        0x01
+
+#define IMR1_CASE       0x80
+#define IMR1_RDO        0x40
+#define IMR1_ALLS       0x20
+#define IMR1_XDU        0x10
+#define IMR1_XMB        0x08
+#define IMR1_XLSC       0x02
+#define IMR1_XPR        0x01
+#define IMR1_LLBSC	0x80
+
+#define IMR2_FAR        0x80
+#define IMR2_LFA        0x40
+#define IMR2_MFAR       0x20
+#define IMR2_T400MS     0x10
+#define IMR2_LMFA       0x10
+#define IMR2_AIS        0x08
+#define IMR2_LOS        0x04
+#define IMR2_RAR        0x02
+#define IMR2_RA         0x01
+
+#define IMR3_ES         0x80
+#define IMR3_SEC        0x40
+#define IMR3_LMFA16     0x20
+#define IMR3_AIS16      0x10
+#define IMR3_RA16       0x08
+#define IMR3_API        0x04
+#define IMR3_XSLP       0x20
+#define IMR3_XSLN       0x10
+#define IMR3_LLBSC      0x08
+#define IMR3_XRS        0x04
+#define IMR3_SLN        0x02
+#define IMR3_SLP        0x01
+
+#define IMR4_LFA        0x80
+#define IMR4_FER        0x40
+#define IMR4_CER        0x20
+#define IMR4_AIS        0x10
+#define IMR4_LOS        0x08
+#define IMR4_CVE        0x04
+#define IMR4_SLIP       0x02
+#define IMR4_EBE        0x01
+
+/* FMR0-5 for E1 and T1  (Framer Mode Register ) */
+
+#define FMR0_XC1        0x80
+#define FMR0_XC0        0x40
+#define FMR0_RC1        0x20
+#define FMR0_RC0        0x10
+#define FMR0_EXTD       0x08
+#define FMR0_ALM        0x04
+#define E1_FMR0_FRS     0x02
+#define T1_FMR0_FRS     0x08
+#define FMR0_SRAF       0x04
+#define FMR0_EXLS       0x02
+#define FMR0_SIM        0x01
+
+#define FMR1_MFCS       0x80
+#define FMR1_AFR        0x40
+#define FMR1_ENSA       0x20
+#define FMR1_CTM        0x80
+#define FMR1_SIGM       0x40
+#define FMR1_EDL        0x20
+#define FMR1_PMOD       0x10
+#define FMR1_XFS        0x08
+#define FMR1_CRC        0x08
+#define FMR1_ECM        0x04
+#define FMR1_IMOD       0x02
+#define FMR1_XAIS       0x01
+
+#define FMR2_RFS1       0x80
+#define FMR2_RFS0       0x40
+#define FMR2_MCSP	0x40
+#define FMR2_RTM        0x20
+#define FMR2_SSP        0x20
+#define FMR2_DAIS       0x10
+#define FMR2_SAIS       0x08
+#define FMR2_PLB        0x04
+#define FMR2_AXRA       0x02
+#define FMR2_ALMF       0x01
+#define FMR2_EXZE       0x01
+
+#define LOOP_RTM	0x40
+#define LOOP_SFM	0x40
+#define LOOP_ECLB	0x20
+#define LOOP_CLA	0x1f
+
+/*--------------------- E1 ----------------------------*/
+#define FMR3_XLD	0x20
+#define FMR3_XLU	0x10
+
+/*--------------------- T1 ----------------------------*/
+#define FMR4_AIS3       0x80
+#define FMR4_TM         0x40
+#define FMR4_XRA        0x20
+#define FMR4_SSC1       0x10
+#define FMR4_SSC0       0x08
+#define FMR4_AUTO       0x04
+#define FMR4_FM1        0x02
+#define FMR4_FM0        0x01
+
+#define FMR5_SRS        0x80
+#define FMR5_EIBR       0x40
+#define FMR5_XLD        0x20
+#define FMR5_XLU        0x10
+
+
+/* LOOP (Channel Loop Back)
+
+   ------------------ E1 & T1 ---------------------------- */
+
+#define LOOP_SFM        0x40
+#define LOOP_ECLB       0x20
+#define LOOP_CLA4       0x10
+#define LOOP_CLA3       0x08
+#define LOOP_CLA2       0x04
+#define LOOP_CLA1       0x02
+#define LOOP_CLA0       0x01
+
+
+
+/* XSW (Transmit Service Word Pulseframe)
+
+   ------------------- E1 --------------------------- */
+
+#define XSW_XSIS        0x80
+#define XSW_XRA         0x20
+#define XSW_XY0         0x10
+#define XSW_XY1         0x08
+#define XSW_XY2         0x04
+#define XSW_XY3         0x02
+#define XSW_XY4         0x01
+
+
+/* XSP (Transmit Spare Bits)
+
+   ------------------- E1 --------------------------- */
+
+#define XSP_XAP         0x80
+#define XSP_CASEN       0x40
+#define XSP_TT0         0x20
+#define XSP_EBP         0x10
+#define XSP_AXS         0x08
+#define XSP_XSIF        0x04
+#define XSP_XS13        0x02
+#define XSP_XS15        0x01
+
+
+/* XC0/1 (Transmit Control 0/1)
+   ------------------ E1 & T1 ---------------------------- */
+
+#define XC0_SA8E        0x80
+#define XC0_SA7E        0x40
+#define XC0_SA6E        0x20
+#define XC0_SA5E        0x10
+#define XC0_SA4E        0x08
+#define XC0_BRM         0x80
+#define XC0_MFBS        0x40
+#define XC0_SFRZ        0x10
+#define XC0_XCO2        0x04
+#define XC0_XCO1        0x02
+#define XC0_XCO0        0x01
+
+#define XC1_XTO5        0x20
+#define XC1_XTO4        0x10
+#define XC1_XTO3        0x08
+#define XC1_XTO2        0x04
+#define XC1_XTO1        0x02
+#define XC1_XTO0        0x01
+
+
+/* RC0/1 (Receive Control 0/1)
+   ------------------ E1 & T1 ---------------------------- */
+
+#define RC0_SICS        0x40
+#define RC0_CRCI        0x20
+#define RC0_XCRCI       0x10
+#define RC0_RDIS        0x08
+#define RC0_RCO2        0x04
+#define RC0_RCO1        0x02
+#define RC0_RCO0        0x01
+
+#define RC1_SWD         0x80
+#define RC1_ASY4        0x40
+#define RC1_RRAM        0x40
+#define RC1_RTO5        0x20
+#define RC1_RTO4        0x10
+#define RC1_RTO3        0x08
+#define RC1_RTO2        0x04
+#define RC1_RTO1        0x02
+#define RC1_RTO0        0x01
+
+
+
+/* XPM0-2 (Transmit Pulse Mask 0-2)
+   --------------------- E1 & T1 ------------------------- */
+
+#define XPM0_XP12       0x80
+#define XPM0_XP11       0x40
+#define XPM0_XP10       0x20
+#define XPM0_XP04       0x10
+#define XPM0_XP03       0x08
+#define XPM0_XP02       0x04
+#define XPM0_XP01       0x02
+#define XPM0_XP00       0x01
+
+#define XPM1_XP30       0x80
+#define XPM1_XP24       0x40
+#define XPM1_XP23       0x20
+#define XPM1_XP22       0x10
+#define XPM1_XP21       0x08
+#define XPM1_XP20       0x04
+#define XPM1_XP14       0x02
+#define XPM1_XP13       0x01
+
+#define XPM2_XLHP       0x80
+#define XPM2_XLT        0x40
+#define XPM2_DAXLT      0x20
+#define XPM2_XP34       0x08
+#define XPM2_XP33       0x04
+#define XPM2_XP32       0x02
+#define XPM2_XP31       0x01
+
+
+/* TSWM (Transparent Service Word Mask)
+   ------------------ E1 ---------------------------- */
+
+#define TSWM_TSIS       0x80
+#define TSWM_TSIF       0x40
+#define TSWM_TRA        0x20
+#define TSWM_TSA4       0x10
+#define TSWM_TSA5       0x08
+#define TSWM_TSA6       0x04
+#define TSWM_TSA7       0x02
+#define TSWM_TSA8       0x01
+
+/* IDLE <Idle Channel Code Register>
+
+   ------------------ E1 & T1 ----------------------- */
+
+#define IDLE_IDL7       0x80
+#define IDLE_IDL6       0x40
+#define IDLE_IDL5       0x20
+#define IDLE_IDL4       0x10
+#define IDLE_IDL3       0x08
+#define IDLE_IDL2       0x04
+#define IDLE_IDL1       0x02
+#define IDLE_IDL0       0x01
+
+
+/* XSA4-8 <Transmit SA4-8 Register(Read/Write) >
+   -------------------E1 ----------------------------- */
+
+#define XSA4_XS47       0x80
+#define XSA4_XS46       0x40
+#define XSA4_XS45       0x20
+#define XSA4_XS44       0x10
+#define XSA4_XS43       0x08
+#define XSA4_XS42       0x04
+#define XSA4_XS41       0x02
+#define XSA4_XS40       0x01
+
+#define XSA5_XS57       0x80
+#define XSA5_XS56       0x40
+#define XSA5_XS55       0x20
+#define XSA5_XS54       0x10
+#define XSA5_XS53       0x08
+#define XSA5_XS52       0x04
+#define XSA5_XS51       0x02
+#define XSA5_XS50       0x01
+
+#define XSA6_XS67       0x80
+#define XSA6_XS66       0x40
+#define XSA6_XS65       0x20
+#define XSA6_XS64       0x10
+#define XSA6_XS63       0x08
+#define XSA6_XS62       0x04
+#define XSA6_XS61       0x02
+#define XSA6_XS60       0x01
+
+#define XSA7_XS77       0x80
+#define XSA7_XS76       0x40
+#define XSA7_XS75       0x20
+#define XSA7_XS74       0x10
+#define XSA7_XS73       0x08
+#define XSA7_XS72       0x04
+#define XSA7_XS71       0x02
+#define XSA7_XS70       0x01
+
+#define XSA8_XS87       0x80
+#define XSA8_XS86       0x40
+#define XSA8_XS85       0x20
+#define XSA8_XS84       0x10
+#define XSA8_XS83       0x08
+#define XSA8_XS82       0x04
+#define XSA8_XS81       0x02
+#define XSA8_XS80       0x01
+
+
+/* XDL1-3 (Transmit DL-Bit Register1-3 (read/write))
+   ----------------------- T1 --------------------- */
+
+#define XDL1_XDL17      0x80
+#define XDL1_XDL16      0x40
+#define XDL1_XDL15      0x20
+#define XDL1_XDL14      0x10
+#define XDL1_XDL13      0x08
+#define XDL1_XDL12      0x04
+#define XDL1_XDL11      0x02
+#define XDL1_XDL10      0x01
+
+#define XDL2_XDL27      0x80
+#define XDL2_XDL26      0x40
+#define XDL2_XDL25      0x20
+#define XDL2_XDL24      0x10
+#define XDL2_XDL23      0x08
+#define XDL2_XDL22      0x04
+#define XDL2_XDL21      0x02
+#define XDL2_XDL20      0x01
+
+#define XDL3_XDL37      0x80
+#define XDL3_XDL36      0x40
+#define XDL3_XDL35      0x20
+#define XDL3_XDL34      0x10
+#define XDL3_XDL33      0x08
+#define XDL3_XDL32      0x04
+#define XDL3_XDL31      0x02
+#define XDL3_XDL30      0x01
+
+
+/* ICB1-4 (Idle Channel Register 1-4)
+   ------------------ E1 ---------------------------- */
+
+#define E1_ICB1_IC0	0x80
+#define E1_ICB1_IC1	0x40
+#define E1_ICB1_IC2	0x20
+#define E1_ICB1_IC3	0x10
+#define E1_ICB1_IC4	0x08
+#define E1_ICB1_IC5	0x04
+#define E1_ICB1_IC6	0x02
+#define E1_ICB1_IC7	0x01
+
+#define E1_ICB2_IC8	0x80
+#define E1_ICB2_IC9	0x40
+#define E1_ICB2_IC10	0x20
+#define E1_ICB2_IC11	0x10
+#define E1_ICB2_IC12	0x08
+#define E1_ICB2_IC13	0x04
+#define E1_ICB2_IC14	0x02
+#define E1_ICB2_IC15	0x01
+
+#define E1_ICB3_IC16	0x80
+#define E1_ICB3_IC17	0x40
+#define E1_ICB3_IC18	0x20
+#define E1_ICB3_IC19	0x10
+#define E1_ICB3_IC20	0x08
+#define E1_ICB3_IC21	0x04
+#define E1_ICB3_IC22	0x02
+#define E1_ICB3_IC23	0x01
+
+#define E1_ICB4_IC24	0x80
+#define E1_ICB4_IC25	0x40
+#define E1_ICB4_IC26	0x20
+#define E1_ICB4_IC27	0x10
+#define E1_ICB4_IC28	0x08
+#define E1_ICB4_IC29	0x04
+#define E1_ICB4_IC30	0x02
+#define E1_ICB4_IC31	0x01
+
+/* ICB1-4 (Idle Channel Register 1-4)
+   ------------------ T1 ---------------------------- */
+
+#define T1_ICB1_IC1	0x80
+#define T1_ICB1_IC2	0x40
+#define T1_ICB1_IC3	0x20
+#define T1_ICB1_IC4	0x10
+#define T1_ICB1_IC5	0x08
+#define T1_ICB1_IC6	0x04
+#define T1_ICB1_IC7	0x02
+#define T1_ICB1_IC8	0x01
+
+#define T1_ICB2_IC9	0x80
+#define T1_ICB2_IC10	0x40
+#define T1_ICB2_IC11	0x20
+#define T1_ICB2_IC12	0x10
+#define T1_ICB2_IC13	0x08
+#define T1_ICB2_IC14	0x04
+#define T1_ICB2_IC15	0x02
+#define T1_ICB2_IC16	0x01
+
+#define T1_ICB3_IC17	0x80
+#define T1_ICB3_IC18	0x40
+#define T1_ICB3_IC19	0x20
+#define T1_ICB3_IC20	0x10
+#define T1_ICB3_IC21	0x08
+#define T1_ICB3_IC22	0x04
+#define T1_ICB3_IC23	0x02
+#define T1_ICB3_IC24	0x01
+
+/* FMR3 (Framer Mode Register 3)
+   --------------------E1------------------------ */
+
+#define FMR3_CMI        0x08
+#define FMR3_SYNSA      0x04
+#define FMR3_CFRZ       0x02
+#define FMR3_EXTIW      0x01
+
+
+
+/* CCB1-3 (Clear Channel Register)
+   ------------------- T1 ----------------------- */
+
+#define CCB1_CH1        0x80
+#define CCB1_CH2        0x40
+#define CCB1_CH3        0x20
+#define CCB1_CH4        0x10
+#define CCB1_CH5        0x08
+#define CCB1_CH6        0x04
+#define CCB1_CH7        0x02
+#define CCB1_CH8        0x01
+
+#define CCB2_CH9        0x80
+#define CCB2_CH10       0x40
+#define CCB2_CH11       0x20
+#define CCB2_CH12       0x10
+#define CCB2_CH13       0x08
+#define CCB2_CH14       0x04
+#define CCB2_CH15       0x02
+#define CCB2_CH16       0x01
+
+#define CCB3_CH17       0x80
+#define CCB3_CH18       0x40
+#define CCB3_CH19       0x20
+#define CCB3_CH20       0x10
+#define CCB3_CH21       0x08
+#define CCB3_CH22       0x04
+#define CCB3_CH23       0x02
+#define CCB3_CH24       0x01
+
+
+/* LIM0/1 (Line Interface Mode 0/1)
+   ------------------- E1 & T1 --------------------------- */
+
+#define LIM0_XFB        0x80
+#define LIM0_XDOS       0x40
+#define LIM0_SCL1       0x20
+#define LIM0_SCL0       0x10
+#define LIM0_EQON       0x08
+#define LIM0_ELOS       0x04
+#define LIM0_LL         0x02
+#define LIM0_MAS        0x01
+
+#define LIM1_EFSC       0x80
+#define LIM1_RIL2       0x40
+#define LIM1_RIL1       0x20
+#define LIM1_RIL0       0x10
+#define LIM1_DCOC       0x08
+#define LIM1_JATT       0x04
+#define LIM1_RL         0x02
+#define LIM1_DRS        0x01
+
+
+/* PCDR (Pulse Count Detection Register(Read/Write))
+   ------------------ E1 & T1 ------------------------- */
+
+#define PCDR_PCD7	0x80
+#define PCDR_PCD6	0x40
+#define PCDR_PCD5	0x20
+#define PCDR_PCD4	0x10
+#define PCDR_PCD3	0x08
+#define PCDR_PCD2	0x04
+#define PCDR_PCD1	0x02
+#define PCDR_PCD0	0x01
+
+#define PCRR_PCR7	0x80
+#define PCRR_PCR6	0x40
+#define PCRR_PCR5	0x20
+#define PCRR_PCR4	0x10
+#define PCRR_PCR3	0x08
+#define PCRR_PCR2	0x04
+#define PCRR_PCR1	0x02
+#define PCRR_PCR0	0x01
+
+
+/* LIM2 (Line Interface Mode 2)
+
+   ------------------ E1 & T1 ---------------------------- */
+
+#define LIM2_DJA2	0x20
+#define LIM2_DJA1	0x10
+#define LIM2_LOS2	0x02
+#define LIM2_LOS1	0x01
+
+/* LCR1 (Loop Code Register 1) */
+
+#define LCR1_EPRM	0x80
+#define	LCR1_XPRBS	0x40
+
+/* SIC1 (System Interface Control 1) */
+#define SIC1_SRSC	0x80
+#define SIC1_RBS1	0x20
+#define SIC1_RBS0	0x10
+#define SIC1_SXSC	0x08
+#define SIC1_XBS1	0x02
+#define SIC1_XBS0	0x01
+
+/* DEC (Disable Error Counter)
+   ------------------ E1 & T1 ---------------------------- */
+
+#define DEC_DCEC3       0x20
+#define DEC_DBEC        0x10
+#define DEC_DCEC1       0x08
+#define DEC_DCEC        0x08
+#define DEC_DEBC        0x04
+#define DEC_DCVC        0x02
+#define DEC_DFEC        0x01
+
+
+/* FALC Register Bits (Receive Mode)
+   ---------------------------------------------------------------------------- */
+
+
+/* FRS0/1 (Framer Receive Status Register 0/1)
+   ----------------- E1 & T1 ---------------------------------- */
+
+#define FRS0_LOS        0x80
+#define FRS0_AIS        0x40
+#define FRS0_LFA        0x20
+#define FRS0_RRA        0x10
+#define FRS0_API        0x08
+#define FRS0_NMF        0x04
+#define FRS0_LMFA       0x02
+#define FRS0_FSRF       0x01
+
+#define FRS1_TS16RA     0x40
+#define FRS1_TS16LOS    0x20
+#define FRS1_TS16AIS    0x10
+#define FRS1_TS16LFA    0x08
+#define FRS1_EXZD       0x80
+#define FRS1_LLBDD      0x10
+#define FRS1_LLBAD      0x08
+#define FRS1_XLS        0x02
+#define FRS1_XLO        0x01
+#define FRS1_PDEN	0x40
+
+/* FRS2/3 (Framer Receive Status Register 2/3)
+   ----------------- T1 ---------------------------------- */
+
+#define FRS2_ESC2       0x80
+#define FRS2_ESC1       0x40
+#define FRS2_ESC0       0x20
+
+#define FRS3_FEH5       0x20
+#define FRS3_FEH4       0x10
+#define FRS3_FEH3       0x08
+#define FRS3_FEH2       0x04
+#define FRS3_FEH1       0x02
+#define FRS3_FEH0       0x01
+
+
+/* RSW (Receive Service Word Pulseframe)
+   ----------------- E1 ------------------------------ */
+
+#define RSW_RSI         0x80
+#define RSW_RRA         0x20
+#define RSW_RYO         0x10
+#define RSW_RY1         0x08
+#define RSW_RY2         0x04
+#define RSW_RY3         0x02
+#define RSW_RY4         0x01
+
+
+/* RSP (Receive Spare Bits / Additional Status)
+   ---------------- E1 ------------------------------- */
+
+#define RSP_SI1         0x80
+#define RSP_SI2         0x40
+#define RSP_LLBDD	0x10
+#define RSP_LLBAD	0x08
+#define RSP_RSIF        0x04
+#define RSP_RS13        0x02
+#define RSP_RS15        0x01
+
+
+/* FECL (Framing Error Counter)
+   ---------------- E1 & T1 -------------------------- */
+
+#define FECL_FE7        0x80
+#define FECL_FE6        0x40
+#define FECL_FE5        0x20
+#define FECL_FE4        0x10
+#define FECL_FE3        0x08
+#define FECL_FE2        0x04
+#define FECL_FE1        0x02
+#define FECL_FE0        0x01
+
+#define FECH_FE15       0x80
+#define FECH_FE14       0x40
+#define FECH_FE13       0x20
+#define FECH_FE12       0x10
+#define FECH_FE11       0x08
+#define FECH_FE10       0x04
+#define FECH_FE9        0x02
+#define FECH_FE8        0x01
+
+
+/* CVCl (Code Violation Counter)
+   ----------------- E1 ------------------------- */
+
+#define CVCL_CV7        0x80
+#define CVCL_CV6        0x40
+#define CVCL_CV5        0x20
+#define CVCL_CV4        0x10
+#define CVCL_CV3        0x08
+#define CVCL_CV2        0x04
+#define CVCL_CV1        0x02
+#define CVCL_CV0        0x01
+
+#define CVCH_CV15       0x80
+#define CVCH_CV14       0x40
+#define CVCH_CV13       0x20
+#define CVCH_CV12       0x10
+#define CVCH_CV11       0x08
+#define CVCH_CV10       0x04
+#define CVCH_CV9        0x02
+#define CVCH_CV8        0x01
+
+
+/* CEC1-3L (CRC Error Counter)
+   ------------------ E1 ----------------------------- */
+
+#define CEC1L_CR7       0x80
+#define CEC1L_CR6       0x40
+#define CEC1L_CR5       0x20
+#define CEC1L_CR4       0x10
+#define CEC1L_CR3       0x08
+#define CEC1L_CR2       0x04
+#define CEC1L_CR1       0x02
+#define CEC1L_CR0       0x01
+
+#define CEC1H_CR15      0x80
+#define CEC1H_CR14      0x40
+#define CEC1H_CR13      0x20
+#define CEC1H_CR12      0x10
+#define CEC1H_CR11      0x08
+#define CEC1H_CR10      0x04
+#define CEC1H_CR9       0x02
+#define CEC1H_CR8       0x01
+
+#define CEC2L_CR7       0x80
+#define CEC2L_CR6       0x40
+#define CEC2L_CR5       0x20
+#define CEC2L_CR4       0x10
+#define CEC2L_CR3       0x08
+#define CEC2L_CR2       0x04
+#define CEC2L_CR1       0x02
+#define CEC2L_CR0       0x01
+
+#define CEC2H_CR15      0x80
+#define CEC2H_CR14      0x40
+#define CEC2H_CR13      0x20
+#define CEC2H_CR12      0x10
+#define CEC2H_CR11      0x08
+#define CEC2H_CR10      0x04
+#define CEC2H_CR9       0x02
+#define CEC2H_CR8       0x01
+
+#define CEC3L_CR7       0x80
+#define CEC3L_CR6       0x40
+#define CEC3L_CR5       0x20
+#define CEC3L_CR4       0x10
+#define CEC3L_CR3       0x08
+#define CEC3L_CR2       0x04
+#define CEC3L_CR1       0x02
+#define CEC3L_CR0       0x01
+
+#define CEC3H_CR15      0x80
+#define CEC3H_CR14      0x40
+#define CEC3H_CR13      0x20
+#define CEC3H_CR12      0x10
+#define CEC3H_CR11      0x08
+#define CEC3H_CR10      0x04
+#define CEC3H_CR9       0x02
+#define CEC3H_CR8       0x01
+
+
+/* CECL (CRC Error Counter)
+
+   ------------------ T1 ----------------------------- */
+
+#define CECL_CR7        0x80
+#define CECL_CR6        0x40
+#define CECL_CR5        0x20
+#define CECL_CR4        0x10
+#define CECL_CR3        0x08
+#define CECL_CR2        0x04
+#define CECL_CR1        0x02
+#define CECL_CR0        0x01
+
+#define CECH_CR15       0x80
+#define CECH_CR14       0x40
+#define CECH_CR13       0x20
+#define CECH_CR12       0x10
+#define CECH_CR11       0x08
+#define CECH_CR10       0x04
+#define CECH_CR9        0x02
+#define CECH_CR8        0x01
+
+/* EBCL (E Bit Error Counter)
+   ------------------- E1 & T1 ------------------------- */
+
+#define EBCL_EB7        0x80
+#define EBCL_EB6        0x40
+#define EBCL_EB5        0x20
+#define EBCL_EB4        0x10
+#define EBCL_EB3        0x08
+#define EBCL_EB2        0x04
+#define EBCL_EB1        0x02
+#define EBCL_EB0        0x01
+
+#define EBCH_EB15       0x80
+#define EBCH_EB14       0x40
+#define EBCH_EB13       0x20
+#define EBCH_EB12       0x10
+#define EBCH_EB11       0x08
+#define EBCH_EB10       0x04
+#define EBCH_EB9        0x02
+#define EBCH_EB8        0x01
+
+
+/* RSA4-8 (Receive Sa4-8-Bit Register)
+   -------------------- E1 --------------------------- */
+
+#define RSA4_RS47       0x80
+#define RSA4_RS46       0x40
+#define RSA4_RS45       0x20
+#define RSA4_RS44       0x10
+#define RSA4_RS43       0x08
+#define RSA4_RS42       0x04
+#define RSA4_RS41       0x02
+#define RSA4_RS40       0x01
+
+#define RSA5_RS57       0x80
+#define RSA5_RS56       0x40
+#define RSA5_RS55       0x20
+#define RSA5_RS54       0x10
+#define RSA5_RS53       0x08
+#define RSA5_RS52       0x04
+#define RSA5_RS51       0x02
+#define RSA5_RS50       0x01
+
+#define RSA6_RS67       0x80
+#define RSA6_RS66       0x40
+#define RSA6_RS65       0x20
+#define RSA6_RS64       0x10
+#define RSA6_RS63       0x08
+#define RSA6_RS62       0x04
+#define RSA6_RS61       0x02
+#define RSA6_RS60       0x01
+
+#define RSA7_RS77       0x80
+#define RSA7_RS76       0x40
+#define RSA7_RS75       0x20
+#define RSA7_RS74       0x10
+#define RSA7_RS73       0x08
+#define RSA7_RS72       0x04
+#define RSA7_RS71       0x02
+#define RSA7_RS70       0x01
+
+#define RSA8_RS87       0x80
+#define RSA8_RS86       0x40
+#define RSA8_RS85       0x20
+#define RSA8_RS84       0x10
+#define RSA8_RS83       0x08
+#define RSA8_RS82       0x04
+#define RSA8_RS81       0x02
+#define RSA8_RS80       0x01
+
+/* RSA6S (Receive Sa6 Bit Status Register)
+   ------------------------ T1 ------------------------- */
+
+#define RSA6S_SX        0x20
+#define RSA6S_SF        0x10
+#define RSA6S_SE        0x08
+#define RSA6S_SC        0x04
+#define RSA6S_SA        0x02
+#define RSA6S_S8        0x01
+
+
+/* RDL1-3 Receive DL-Bit Register1-3)
+   ------------------------ T1 ------------------------- */
+
+#define RDL1_RDL17      0x80
+#define RDL1_RDL16      0x40
+#define RDL1_RDL15      0x20
+#define RDL1_RDL14      0x10
+#define RDL1_RDL13      0x08
+#define RDL1_RDL12      0x04
+#define RDL1_RDL11      0x02
+#define RDL1_RDL10      0x01
+
+#define RDL2_RDL27      0x80
+#define RDL2_RDL26      0x40
+#define RDL2_RDL25      0x20
+#define RDL2_RDL24      0x10
+#define RDL2_RDL23      0x08
+#define RDL2_RDL22      0x04
+#define RDL2_RDL21      0x02
+#define RDL2_RDL20      0x01
+
+#define RDL3_RDL37      0x80
+#define RDL3_RDL36      0x40
+#define RDL3_RDL35      0x20
+#define RDL3_RDL34      0x10
+#define RDL3_RDL33      0x08
+#define RDL3_RDL32      0x04
+#define RDL3_RDL31      0x02
+#define RDL3_RDL30      0x01
+
+
+/* SIS (Signaling Status Register)
+
+   -------------------- E1 & T1 -------------------------- */
+
+#define SIS_XDOV        0x80
+#define SIS_XFW         0x40
+#define SIS_XREP        0x20
+#define SIS_RLI         0x08
+#define SIS_CEC         0x04
+#define SIS_BOM         0x01
+
+
+/* RSIS (Receive Signaling Status Register)
+
+   -------------------- E1 & T1 --------------------------- */
+
+#define RSIS_VFR        0x80
+#define RSIS_RDO        0x40
+#define RSIS_CRC16      0x20
+#define RSIS_RAB        0x10
+#define RSIS_HA1        0x08
+#define RSIS_HA0        0x04
+#define RSIS_HFR        0x02
+#define RSIS_LA         0x01
+
+
+/* RBCL/H (Receive Byte Count Low/High)
+
+   ------------------- E1 & T1 ----------------------- */
+
+#define RBCL_RBC7       0x80
+#define RBCL_RBC6       0x40
+#define RBCL_RBC5       0x20
+#define RBCL_RBC4       0x10
+#define RBCL_RBC3       0x08
+#define RBCL_RBC2       0x04
+#define RBCL_RBC1       0x02
+#define RBCL_RBC0       0x01
+
+#define RBCH_OV         0x10
+#define RBCH_RBC11      0x08
+#define RBCH_RBC10      0x04
+#define RBCH_RBC9       0x02
+#define RBCH_RBC8       0x01
+
+
+/* ISR1-3  (Interrupt Status Register 1-3)
+
+   ------------------ E1 & T1 ------------------------------ */
+
+#define  FISR0_RME	0x80
+#define  FISR0_RFS	0x40
+#define  FISR0_T8MS	0x20
+#define  FISR0_ISF	0x20
+#define  FISR0_RMB	0x10
+#define  FISR0_CASC	0x08
+#define  FISR0_RSC	0x08
+#define  FISR0_CRC6	0x04
+#define  FISR0_CRC4	0x04
+#define  FISR0_PDEN	0x02
+#define  FISR0_RPF	0x01
+
+#define  FISR1_CASE	0x80
+#define  FISR1_LLBSC	0x80
+#define  FISR1_RDO	0x40
+#define  FISR1_ALLS	0x20
+#define  FISR1_XDU	0x10
+#define  FISR1_XMB	0x08
+#define  FISR1_XLSC	0x02
+#define  FISR1_XPR	0x01
+
+#define  FISR2_FAR	0x80
+#define  FISR2_LFA	0x40
+#define  FISR2_MFAR	0x20
+#define  FISR2_T400MS	0x10
+#define  FISR2_LMFA	0x10
+#define  FISR2_AIS	0x08
+#define  FISR2_LOS	0x04
+#define  FISR2_RAR	0x02
+#define  FISR2_RA	0x01
+
+#define  FISR3_ES	0x80
+#define  FISR3_SEC	0x40
+#define  FISR3_LMFA16	0x20
+#define  FISR3_AIS16	0x10
+#define  FISR3_RA16	0x08
+#define  FISR3_API	0x04
+#define  FISR3_XSLP	0x20
+#define  FISR3_XSLN	0x10
+#define  FISR3_LLBSC	0x08
+#define  FISR3_XRS	0x04
+#define  FISR3_SLN	0x02
+#define  FISR3_SLP	0x01
+
+
+/* GIS  (Global Interrupt Status Register)
+
+   --------------------- E1 & T1 --------------------- */
+
+#define  GIS_ISR3	0x08
+#define  GIS_ISR2	0x04
+#define  GIS_ISR1	0x02
+#define  GIS_ISR0	0x01
+
+
+/* VSTR  (Version Status Register)
+
+   --------------------- E1 & T1 --------------------- */
+
+#define  VSTR_VN3	0x08
+#define  VSTR_VN2	0x04
+#define  VSTR_VN1	0x02
+#define  VSTR_VN0	0x01
+
+
+/*>>>>>>>>>>>>>>>>>>>>>  Local Control Structures  <<<<<<<<<<<<<<<<<<<<<<<<< */
+
+/* Write-only Registers (E1/T1 control mode write registers) */
+#define XFIFOH	0x00		/* Tx FIFO High Byte */
+#define XFIFOL	0x01		/* Tx FIFO Low Byte */
+#define CMDR	0x02		/* Command Reg */
+#define DEC	0x60		/* Disable Error Counter */
+#define TEST2	0x62		/* Manuf. Test Reg 2 */
+#define XS(nbr)	(0x70 + (nbr))	/* Tx CAS Reg (0 to 15) */
+
+/* Read-write Registers (E1/T1 status mode read registers) */
+#define MODE	0x03	/* Mode Reg */
+#define RAH1	0x04	/* Receive Address High 1 */
+#define RAH2	0x05	/* Receive Address High 2 */
+#define RAL1	0x06	/* Receive Address Low 1 */
+#define RAL2	0x07	/* Receive Address Low 2 */
+#define IPC	0x08	/* Interrupt Port Configuration */
+#define CCR1	0x09	/* Common Configuration Reg 1 */
+#define CCR3	0x0A	/* Common Configuration Reg 3 */
+#define PRE	0x0B	/* Preamble Reg */
+#define RTR1	0x0C	/* Receive Timeslot Reg 1 */
+#define RTR2	0x0D	/* Receive Timeslot Reg 2 */
+#define RTR3	0x0E	/* Receive Timeslot Reg 3 */
+#define RTR4	0x0F	/* Receive Timeslot Reg 4 */
+#define TTR1	0x10	/* Transmit Timeslot Reg 1 */
+#define TTR2	0x11	/* Transmit Timeslot Reg 2 */
+#define TTR3	0x12	/* Transmit Timeslot Reg 3 */
+#define TTR4	0x13	/* Transmit Timeslot Reg 4 */
+#define IMR0	0x14	/* Interrupt Mask Reg 0 */
+#define IMR1	0x15	/* Interrupt Mask Reg 1 */
+#define IMR2	0x16	/* Interrupt Mask Reg 2 */
+#define IMR3	0x17	/* Interrupt Mask Reg 3 */
+#define IMR4	0x18	/* Interrupt Mask Reg 4 */
+#define IMR5	0x19	/* Interrupt Mask Reg 5 */
+#define FMR0	0x1A	/* Framer Mode Reigster 0 */
+#define FMR1	0x1B	/* Framer Mode Reigster 1 */
+#define FMR2	0x1C	/* Framer Mode Reigster 2 */
+#define LOOP	0x1D	/* Channel Loop Back */
+#define XSW	0x1E	/* Transmit Service Word */
+#define FMR4	0x1E	/* Framer Mode Reg 4 */
+#define XSP	0x1F	/* Transmit Spare Bits */
+#define FMR5	0x1F	/* Framer Mode Reg 5 */
+#define XC0	0x20	/* Transmit Control 0 */
+#define XC1	0x21	/* Transmit Control 1 */
+#define RC0	0x22	/* Receive Control 0 */
+#define RC1	0x23	/* Receive Control 1 */
+#define XPM0	0x24	/* Transmit Pulse Mask 0 */
+#define XPM1	0x25	/* Transmit Pulse Mask 1 */
+#define XPM2	0x26	/* Transmit Pulse Mask 2 */
+#define TSWM	0x27	/* Transparent Service Word Mask */
+#define TEST1	0x28	/* Manuf. Test Reg 1 */
+#define IDLE	0x29	/* Idle Channel Code */
+#define XSA4    0x2A	/* Transmit SA4 Bit Reg */
+#define XDL1	0x2A	/* Transmit DL-Bit Reg 2 */
+#define XSA5    0x2B	/* Transmit SA4 Bit Reg */
+#define XDL2	0x2B	/* Transmit DL-Bit Reg 2 */
+#define XSA6    0x2C	/* Transmit SA4 Bit Reg */
+#define XDL3	0x2C	/* Transmit DL-Bit Reg 2 */
+#define XSA7    0x2D	/* Transmit SA4 Bit Reg */
+#define CCB1	0x2D	/* Clear Channel Reg 1 */
+#define XSA8    0x2E	/* Transmit SA4 Bit Reg */
+#define CCB2	0x2E	/* Clear Channel Reg 2 */
+#define FMR3	0x2F	/* Framer Mode Reg. 3 */
+#define CCB3	0x2F	/* Clear Channel Reg 3 */
+#define ICB1	0x30	/* Idle Channel Reg 1 */
+#define ICB2	0x31	/* Idle Channel Reg 2 */
+#define ICB3	0x32	/* Idle Channel Reg 3 */
+#define ICB4	0x33	/* Idle Channel Reg 4 */
+#define LIM0	0x34	/* Line Interface Mode 0 */
+#define LIM1	0x35	/* Line Interface Mode 1 */
+#define PCDR	0x36	/* Pulse Count Detection */
+#define PCRR	0x37	/* Pulse Count Recovery */
+#define LIM2	0x38	/* Line Interface Mode Reg 2 */
+#define LCR1	0x39	/* Loop Code Reg 1 */
+#define LCR2	0x3A	/* Loop Code Reg 2 */
+#define LCR3	0x3B	/* Loop Code Reg 3 */
+#define SIC1	0x3C	/* System Interface Control 1 */
+
+/* Read-only Registers (E1/T1 control mode read registers) */
+#define RFIFOH	0x00		/* Receive FIFO */
+#define RFIFOL	0x01		/* Receive FIFO */
+#define FRS0	0x4C		/* Framer Receive Status 0 */
+#define FRS1	0x4D		/* Framer Receive Status 1 */
+#define RSW	0x4E		/* Receive Service Word */
+#define FRS2	0x4E		/* Framer Receive Status 2 */
+#define RSP	0x4F		/* Receive Spare Bits */
+#define FRS3	0x4F		/* Framer Receive Status 3 */
+#define FECL	0x50		/* Framing Error Counter */
+#define FECH	0x51		/* Framing Error Counter */
+#define CVCL	0x52		/* Code Violation Counter */
+#define CVCH	0x53		/* Code Violation Counter */
+#define CECL	0x54		/* CRC Error Counter 1 */
+#define CECH	0x55		/* CRC Error Counter 1 */
+#define EBCL	0x56		/* E-Bit Error Counter */
+#define EBCH	0x57		/* E-Bit Error Counter */
+#define BECL	0x58		/* Bit Error Counter Low */
+#define BECH	0x59		/* Bit Error Counter Low */
+#define CEC3	0x5A		/* CRC Error Counter 3 (16-bit) */
+#define RSA4	0x5C		/* Receive SA4 Bit Reg */
+#define RDL1	0x5C		/* Receive DL-Bit Reg 1 */
+#define RSA5	0x5D		/* Receive SA5 Bit Reg */
+#define RDL2	0x5D		/* Receive DL-Bit Reg 2 */
+#define RSA6	0x5E		/* Receive SA6 Bit Reg */
+#define RDL3	0x5E		/* Receive DL-Bit Reg 3 */
+#define RSA7	0x5F		/* Receive SA7 Bit Reg */
+#define RSA8	0x60		/* Receive SA8 Bit Reg */
+#define RSA6S	0x61		/* Receive SA6 Bit Status Reg */
+#define TSR0	0x62		/* Manuf. Test Reg 0 */
+#define TSR1	0x63		/* Manuf. Test Reg 1 */
+#define SIS	0x64		/* Signaling Status Reg */
+#define RSIS	0x65		/* Receive Signaling Status Reg */
+#define RBCL	0x66		/* Receive Byte Control */
+#define RBCH	0x67		/* Receive Byte Control */
+#define FISR0	0x68		/* Interrupt Status Reg 0 */
+#define FISR1	0x69		/* Interrupt Status Reg 1 */
+#define FISR2	0x6A		/* Interrupt Status Reg 2 */
+#define FISR3	0x6B		/* Interrupt Status Reg 3 */
+#define GIS	0x6E		/* Global Interrupt Status */
+#define VSTR	0x6F		/* Version Status */
+#define RS(nbr)	(0x70 + (nbr))	/* Rx CAS Reg (0 to 15) */
+
+#endif	/* _FALC_LH_H */
+
diff -urN linux-2.2.17-pre1/include/linux/hd64572.h linux/include/linux/hd64572.h
--- linux-2.2.17-pre1/include/linux/hd64572.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/hd64572.h	Mon Dec  3 22:05:28 2001
@@ -0,0 +1,437 @@
+/*
+ * hd64572.h	Description of the Hitachi HD64572 (SCA-II), valid for 
+ * 		CPU modes 0 & 2.
+ *
+ * Author:	Ivan Passos <ivan@cyclades.com>
+ *
+ * Copyright:   (c) 2000 Cyclades Corp.
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ * $Log: hd64572.h,v $
+ * Revision 1.0 2000/01/25 ivan
+ * Initial version.
+ *
+ */
+
+#ifndef _HD64572_H
+#define _HD64572_H
+
+/* Illegal Access Register */
+#define	ILAR	0x00
+
+/* Wait Controller Registers */
+#define PABR0L	0x20	/* Physical Addr Boundary Register 0 L */
+#define PABR0H	0x21	/* Physical Addr Boundary Register 0 H */
+#define PABR1L	0x22	/* Physical Addr Boundary Register 1 L */
+#define PABR1H	0x23	/* Physical Addr Boundary Register 1 H */
+#define WCRL	0x24	/* Wait Control Register L */
+#define WCRM	0x25	/* Wait Control Register M */
+#define WCRH	0x26	/* Wait Control Register H */
+
+/* Interrupt Registers */
+#define IVR	0x60	/* Interrupt Vector Register */
+#define IMVR	0x64	/* Interrupt Modified Vector Register */
+#define ITCR	0x68	/* Interrupt Control Register */
+#define ISR0	0x6c	/* Interrupt Status Register 0 */
+#define ISR1	0x70	/* Interrupt Status Register 1 */
+#define IER0	0x74	/* Interrupt Enable Register 0 */
+#define IER1	0x78	/* Interrupt Enable Register 1 */
+
+/* Register Access Macros (chan is 0 or 1 in _any_ case) */
+#define	M_REG(reg, chan)	(reg + 0x80*chan)		/* MSCI */
+#define	DRX_REG(reg, chan)	(reg + 0x40*chan)		/* DMA Rx */
+#define	DTX_REG(reg, chan)	(reg + 0x20*(2*chan + 1))	/* DMA Tx */
+#define	TRX_REG(reg, chan)	(reg + 0x20*chan)		/* Timer Rx */
+#define	TTX_REG(reg, chan)	(reg + 0x10*(2*chan + 1))	/* Timer Tx */
+#define	ST_REG(reg, chan)	(reg + 0x80*chan)		/* Status Cnt */
+#define IR0_DRX(val, chan)	((val)<<(8*(chan)))		/* Int DMA Rx */
+#define IR0_DTX(val, chan)	((val)<<(4*(2*chan + 1)))	/* Int DMA Tx */
+#define IR0_M(val, chan)	((val)<<(8*(chan)))		/* Int MSCI */
+
+/* MSCI Channel Registers */
+#define MD0	0x138	/* Mode reg 0 */
+#define MD1	0x139	/* Mode reg 1 */
+#define MD2	0x13a	/* Mode reg 2 */
+#define MD3	0x13b	/* Mode reg 3 */
+#define CTL	0x130	/* Control reg */
+#define RXS	0x13c	/* RX clock source */
+#define TXS	0x13d	/* TX clock source */
+#define EXS	0x13e	/* External clock input selection */
+#define TMCT	0x144	/* Time constant (Tx) */
+#define TMCR	0x145	/* Time constant (Rx) */
+#define CMD	0x128	/* Command reg */
+#define ST0	0x118	/* Status reg 0 */
+#define ST1	0x119	/* Status reg 1 */
+#define ST2	0x11a	/* Status reg 2 */
+#define ST3	0x11b	/* Status reg 3 */
+#define ST4	0x11c	/* Status reg 4 */
+#define FST	0x11d	/* frame Status reg  */
+#define IE0	0x120	/* Interrupt enable reg 0 */
+#define IE1	0x121	/* Interrupt enable reg 1 */
+#define IE2	0x122	/* Interrupt enable reg 2 */
+#define IE4	0x124	/* Interrupt enable reg 4 */
+#define FIE	0x125	/* Frame Interrupt enable reg  */
+#define SA0	0x140	/* Syn Address reg 0 */
+#define SA1	0x141	/* Syn Address reg 1 */
+#define IDL	0x142	/* Idle register */
+#define TRBL	0x100	/* TX/RX buffer reg L */ 
+#define TRBK	0x101	/* TX/RX buffer reg K */ 
+#define TRBJ	0x102	/* TX/RX buffer reg J */ 
+#define TRBH	0x103	/* TX/RX buffer reg H */ 
+#define TRC0	0x148	/* TX Ready control reg 0 */ 
+#define TRC1	0x149	/* TX Ready control reg 1 */ 
+#define RRC	0x14a	/* RX Ready control reg */ 
+#define CST0	0x108	/* Current Status Register 0 */ 
+#define CST1	0x109	/* Current Status Register 1 */ 
+#define CST2	0x10a	/* Current Status Register 2 */ 
+#define CST3	0x10b	/* Current Status Register 3 */ 
+#define GPO	0x131	/* General Purpose Output Pin Ctl Reg */
+#define TFS	0x14b	/* Tx Start Threshold Ctl Reg */
+#define TFN	0x143	/* Inter-transmit-frame Time Fill Ctl Reg */
+#define TBN	0x110	/* Tx Buffer Number Reg */
+#define RBN	0x111	/* Rx Buffer Number Reg */
+#define TNR0	0x150	/* Tx DMA Request Ctl Reg 0 */
+#define TNR1	0x151	/* Tx DMA Request Ctl Reg 1 */
+#define TCR	0x152	/* Tx DMA Critical Request Reg */
+#define RNR	0x154	/* Rx DMA Request Ctl Reg */
+#define RCR	0x156	/* Rx DMA Critical Request Reg */
+
+/* Timer Registers */
+#define TCNTL	0x200	/* Timer Upcounter L */
+#define TCNTH	0x201	/* Timer Upcounter H */
+#define TCONRL	0x204	/* Timer Constant Register L */
+#define TCONRH	0x205	/* Timer Constant Register H */
+#define TCSR	0x206	/* Timer Control/Status Register */
+#define TEPR	0x207	/* Timer Expand Prescale Register */
+
+/* DMA registers */
+#define PCR		0x40		/* DMA priority control reg */
+#define DRR		0x44		/* DMA reset reg */
+#define DMER		0x07		/* DMA Master Enable reg */
+#define BTCR		0x08		/* Burst Tx Ctl Reg */
+#define BOLR		0x0c		/* Back-off Length Reg */
+#define DSR_RX(chan)	(0x48 + 2*chan)	/* DMA Status Reg (Rx) */
+#define DSR_TX(chan)	(0x49 + 2*chan)	/* DMA Status Reg (Tx) */
+#define DIR_RX(chan)	(0x4c + 2*chan)	/* DMA Interrupt Enable Reg (Rx) */
+#define DIR_TX(chan)	(0x4d + 2*chan)	/* DMA Interrupt Enable Reg (Tx) */
+#define FCT_RX(chan)	(0x50 + 2*chan)	/* Frame End Interrupt Counter (Rx) */
+#define FCT_TX(chan)	(0x51 + 2*chan)	/* Frame End Interrupt Counter (Tx) */
+#define DMR_RX(chan)	(0x54 + 2*chan)	/* DMA Mode Reg (Rx) */
+#define DMR_TX(chan)	(0x55 + 2*chan)	/* DMA Mode Reg (Tx) */
+#define DCR_RX(chan)	(0x58 + 2*chan)	/* DMA Command Reg (Rx) */
+#define DCR_TX(chan)	(0x59 + 2*chan)	/* DMA Command Reg (Tx) */
+
+/* DMA Channel Registers */
+#define DARL	0x80	/* Dest Addr Register L (single-block, RX only) */
+#define DARH	0x81	/* Dest Addr Register H (single-block, RX only) */
+#define DARB	0x82	/* Dest Addr Register B (single-block, RX only) */
+#define DARBH	0x83	/* Dest Addr Register BH (single-block, RX only) */
+#define SARL	0x80	/* Source Addr Register L (single-block, TX only) */
+#define SARH	0x81	/* Source Addr Register H (single-block, TX only) */
+#define SARB	0x82	/* Source Addr Register B (single-block, TX only) */
+#define DARBH	0x83	/* Source Addr Register BH (single-block, TX only) */
+#define BARL	0x80	/* Buffer Addr Register L (chained-block) */
+#define BARH	0x81	/* Buffer Addr Register H (chained-block) */
+#define BARB	0x82	/* Buffer Addr Register B (chained-block) */
+#define BARBH	0x83	/* Buffer Addr Register BH (chained-block) */
+#define CDAL	0x84	/* Current Descriptor Addr Register L */
+#define CDAH	0x85	/* Current Descriptor Addr Register H */
+#define CDAB	0x86	/* Current Descriptor Addr Register B */
+#define CDABH	0x87	/* Current Descriptor Addr Register BH */
+#define EDAL	0x88	/* Error Descriptor Addr Register L */
+#define EDAH	0x89	/* Error Descriptor Addr Register H */
+#define EDAB	0x8a	/* Error Descriptor Addr Register B */
+#define EDABH	0x8b	/* Error Descriptor Addr Register BH */
+#define BFLL	0x90	/* RX Buffer Length L (only RX) */
+#define BFLH	0x91	/* RX Buffer Length H (only RX) */
+#define BCRL	0x8c	/* Byte Count Register L */
+#define BCRH	0x8d	/* Byte Count Register H */
+
+/* Block Descriptor Structure */
+typedef struct {
+	unsigned long	next;		/* pointer to next block descriptor */
+	unsigned long	ptbuf;		/* buffer pointer */
+	unsigned short	len;		/* data length */
+	unsigned char	status;		/* status */
+	unsigned char	filler[5];	/* alignment filler (16 bytes) */ 
+} pcsca_bd_t;
+
+/* 
+	Descriptor Status definitions:
+
+	Bit	Transmission	Reception
+
+	7	EOM		EOM
+	6	-		Short Frame
+	5	-		Abort
+	4	-		Residual bit
+	3	Underrun	Overrun	
+	2	-		CRC
+	1	Ownership	Ownership
+	0	EOT		-
+*/
+#define DST_EOT		0x01	/* End of transmit command */
+#define DST_OSB		0x02	/* Ownership bit */
+#define DST_CRC		0x04	/* CRC Error */
+#define DST_OVR		0x08	/* Overrun */
+#define DST_UDR		0x08	/* Underrun */
+#define DST_RBIT	0x10	/* Residual bit */
+#define DST_ABT		0x20	/* Abort */
+#define DST_SHRT	0x40	/* Short Frame  */
+#define DST_EOM		0x80	/* End of Message  */
+
+/* Status Counter Registers */
+#define CMCR	0x158	/* Counter Master Ctl Reg */
+#define TECNTL	0x160	/* Tx EOM Counter L */
+#define TECNTM	0x161	/* Tx EOM Counter M */
+#define TECNTH	0x162	/* Tx EOM Counter H */
+#define TECCR	0x163	/* Tx EOM Counter Ctl Reg */
+#define URCNTL	0x164	/* Underrun Counter L */
+#define URCNTH	0x165	/* Underrun Counter H */
+#define URCCR	0x167	/* Underrun Counter Ctl Reg */
+#define RECNTL	0x168	/* Rx EOM Counter L */
+#define RECNTM	0x169	/* Rx EOM Counter M */
+#define RECNTH	0x16a	/* Rx EOM Counter H */
+#define RECCR	0x16b	/* Rx EOM Counter Ctl Reg */
+#define ORCNTL	0x16c	/* Overrun Counter L */
+#define ORCNTH	0x16d	/* Overrun Counter H */
+#define ORCCR	0x16f	/* Overrun Counter Ctl Reg */
+#define CECNTL	0x170	/* CRC Counter L */
+#define CECNTH	0x171	/* CRC Counter H */
+#define CECCR	0x173	/* CRC Counter Ctl Reg */
+#define ABCNTL	0x174	/* Abort frame Counter L */
+#define ABCNTH	0x175	/* Abort frame Counter H */
+#define ABCCR	0x177	/* Abort frame Counter Ctl Reg */
+#define SHCNTL	0x178	/* Short frame Counter L */
+#define SHCNTH	0x179	/* Short frame Counter H */
+#define SHCCR	0x17b	/* Short frame Counter Ctl Reg */
+#define RSCNTL	0x17c	/* Residual bit Counter L */
+#define RSCNTH	0x17d	/* Residual bit Counter H */
+#define RSCCR	0x17f	/* Residual bit Counter Ctl Reg */
+
+/* Register Programming Constants */
+
+#define IR0_DMIC	0x00000001
+#define IR0_DMIB	0x00000002
+#define IR0_DMIA	0x00000004
+#define IR0_EFT		0x00000008
+#define IR0_DMAREQ	0x00010000
+#define IR0_TXINT	0x00020000
+#define IR0_RXINTB	0x00040000
+#define IR0_RXINTA	0x00080000
+#define IR0_TXRDY	0x00100000
+#define IR0_RXRDY	0x00200000
+
+#define MD0_CRC16_0	0x00
+#define MD0_CRC16_1	0x01
+#define MD0_CRC32	0x02
+#define MD0_CRC_CCITT	0x03
+#define MD0_CRCC0	0x04
+#define MD0_CRCC1	0x08
+#define MD0_AUTO_ENA	0x10
+#define MD0_ASYNC	0x00
+#define MD0_BY_MSYNC	0x20
+#define MD0_BY_BISYNC	0x40
+#define MD0_BY_EXT	0x60
+#define MD0_BIT_SYNC	0x80
+#define MD0_TRANSP	0xc0
+
+#define MD1_NOADDR	0x00
+#define MD1_SADDR1	0x40
+#define MD1_SADDR2	0x80
+#define MD1_DADDR	0xc0
+
+#define MD2_F_DUPLEX	0x00
+#define MD2_AUTO_ECHO	0x01
+#define MD2_LOOP_HI_Z	0x02
+#define MD2_LOOP_MIR	0x03
+#define MD2_ADPLL_X8	0x00
+#define MD2_ADPLL_X16	0x08
+#define MD2_ADPLL_X32	0x10
+#define MD2_NRZ		0x00
+#define MD2_NRZI	0x20
+#define MD2_NRZ_IEEE	0x40
+#define MD2_MANCH	0x00
+#define MD2_FM1		0x20
+#define MD2_FM0		0x40
+#define MD2_FM		0x80
+
+#define CTL_RTS		0x01
+#define CTL_DTR		0x02
+#define CTL_SYN		0x04
+#define CTL_IDLC	0x10
+#define CTL_UDRNC	0x20
+#define CTL_URSKP	0x40
+#define CTL_URCT	0x80
+
+#define	RXS_BR0		0x01
+#define	RXS_BR1		0x02
+#define	RXS_BR2		0x04
+#define	RXS_BR3		0x08
+#define	RXS_ECLK	0x00
+#define	RXS_ECLK_NS	0x20
+#define	RXS_IBRG	0x40
+#define	RXS_PLL1	0x50
+#define	RXS_PLL2	0x60
+#define	RXS_PLL3	0x70
+#define	RXS_DRTXC	0x80
+
+#define	TXS_BR0		0x01
+#define	TXS_BR1		0x02
+#define	TXS_BR2		0x04
+#define	TXS_BR3		0x08
+#define	TXS_ECLK	0x00
+#define	TXS_IBRG	0x40
+#define	TXS_RCLK	0x60
+#define	TXS_DTRXC	0x80
+
+#define	EXS_RES0	0x01
+#define	EXS_RES1	0x02
+#define	EXS_RES2	0x04
+#define	EXS_TES0	0x10
+#define	EXS_TES1	0x20
+#define	EXS_TES2	0x40
+
+#define CMD_RX_RST	0x11
+#define CMD_RX_ENA	0x12
+#define CMD_RX_DIS	0x13
+#define CMD_RX_CRC_INIT	0x14
+#define CMD_RX_MSG_REJ	0x15
+#define CMD_RX_MP_SRCH	0x16
+#define CMD_RX_CRC_EXC	0x17
+#define CMD_RX_CRC_FRC	0x18
+#define CMD_TX_RST	0x01
+#define CMD_TX_ENA	0x02
+#define CMD_TX_DISA	0x03
+#define CMD_TX_CRC_INIT	0x04
+#define CMD_TX_CRC_EXC	0x05
+#define CMD_TX_EOM	0x06
+#define CMD_TX_ABORT	0x07
+#define CMD_TX_MP_ON	0x08
+#define CMD_TX_BUF_CLR	0x09
+#define CMD_TX_DISB	0x0b
+#define CMD_CH_RST	0x21
+#define CMD_SRCH_MODE	0x31
+#define CMD_NOP		0x00
+
+#define ST0_RXRDY	0x01
+#define ST0_TXRDY	0x02
+#define ST0_RXINTB	0x20
+#define ST0_RXINTA	0x40
+#define ST0_TXINT	0x80
+
+#define ST1_IDLE	0x01
+#define ST1_ABORT	0x02
+#define ST1_CDCD	0x04
+#define ST1_CCTS	0x08
+#define ST1_SYN_FLAG	0x10
+#define ST1_CLMD	0x20
+#define ST1_TXIDLE	0x40
+#define ST1_UDRN	0x80
+
+#define ST2_CRCE	0x04
+#define ST2_ONRN	0x08
+#define ST2_RBIT	0x10
+#define ST2_ABORT	0x20
+#define ST2_SHORT	0x40
+#define ST2_EOM		0x80
+
+#define ST3_RX_ENA	0x01
+#define ST3_TX_ENA	0x02
+#define ST3_DCD		0x04
+#define ST3_CTS		0x08
+#define ST3_SRCH_MODE	0x10
+#define ST3_SLOOP	0x20
+#define ST3_GPI		0x80
+
+#define ST4_RDNR	0x01
+#define ST4_RDCR	0x02
+#define ST4_TDNR	0x04
+#define ST4_TDCR	0x08
+#define ST4_OCLM	0x20
+#define ST4_CFT		0x40
+#define ST4_CGPI	0x80
+
+#define FST_CRCEF	0x04
+#define FST_OVRNF	0x08
+#define FST_RBIF	0x10
+#define FST_ABTF	0x20
+#define FST_SHRTF	0x40
+#define FST_EOMF	0x80
+
+#define IE0_RXRDY	0x01
+#define IE0_TXRDY	0x02
+#define IE0_RXINTB	0x20
+#define IE0_RXINTA	0x40
+#define IE0_TXINT	0x80
+
+#define IE1_IDLD	0x01
+#define IE1_ABTD	0x02
+#define IE1_CDCD	0x04
+#define IE1_CCTS	0x08
+#define IE1_SYNCD	0x10
+#define IE1_CLMD	0x20
+#define IE1_IDL		0x40
+#define IE1_UDRN	0x80
+
+#define IE2_CRCE	0x04
+#define IE2_OVRN	0x08
+#define IE2_RBIT	0x10
+#define IE2_ABT		0x20
+#define IE2_SHRT	0x40
+#define IE2_EOM		0x80
+
+#define IE4_RDNR	0x01
+#define IE4_RDCR	0x02
+#define IE4_TDNR	0x04
+#define IE4_TDCR	0x08
+#define IE4_OCLM	0x20
+#define IE4_CFT		0x40
+#define IE4_CGPI	0x80
+
+#define FIE_CRCEF	0x04
+#define FIE_OVRNF	0x08
+#define FIE_RBIF	0x10
+#define FIE_ABTF	0x20
+#define FIE_SHRTF	0x40
+#define FIE_EOMF	0x80
+
+#define DSR_DWE		0x01
+#define DSR_DE		0x02
+#define DSR_REF		0x04
+#define DSR_UDRF	0x04
+#define DSR_COA		0x08
+#define DSR_COF		0x10
+#define DSR_BOF		0x20
+#define DSR_EOM		0x40
+#define DSR_EOT		0x80
+
+#define DIR_REF		0x04
+#define DIR_UDRF	0x04
+#define DIR_COA		0x08
+#define DIR_COF		0x10
+#define DIR_BOF		0x20
+#define DIR_EOM		0x40
+#define DIR_EOT		0x80
+
+#define DMR_CNTE	0x02
+#define DMR_NF		0x04
+#define DMR_SEOME	0x08
+#define DMR_TMOD	0x10
+
+#define DCR_SW_ABT	0x01
+#define DCR_FCT_CLR	0x02
+
+#define PCR_PR0		0x01
+#define PCR_PR1		0x02
+#define PCR_PR2		0x04
+#define PCR_CCC		0x08
+#define PCR_BRC		0x10
+#define PCR_OSB		0x40
+#define PCR_BURST	0x80
+
+#endif /* (_HD64572_H) */
diff -urN linux-2.2.17-pre1/include/linux/hdlc.h linux/include/linux/hdlc.h
--- linux-2.2.17-pre1/include/linux/hdlc.h	Wed Jun  7 14:26:44 2000
+++ linux/include/linux/hdlc.h	Mon Dec  3 22:05:28 2001
@@ -38,6 +38,8 @@
 #define LINE_X21	3
 #define LINE_LOOPBACK	4	/* On-card loopback */
 #define LINE_NOLOOPBACK	5
+#define LINE_T1		6
+#define LINE_E1		7
 #define LINE_MIN_CLOCK 75	/* This & higher values are real clock rates */
 
 
diff -urN linux-2.2.17-pre1/include/linux/ixjuser.h linux/include/linux/ixjuser.h
--- linux-2.2.17-pre1/include/linux/ixjuser.h	Tue Jan  4 10:12:25 2000
+++ linux/include/linux/ixjuser.h	Mon Dec  3 22:05:28 2001
@@ -1,7 +1,8 @@
-/*
+/******************************************************************************
+ *
  *    ixjuser.h
  *
- *    User-space include file for the Internet PhoneJACK and
+ *    Device Driver for the Internet PhoneJACK and
  *    Internet LineJACK Telephony Cards.
  *
  *    (c) Copyright 1999 Quicknet Technologies, Inc.
@@ -22,31 +23,48 @@
  * at our website:    http://www.quicknet.net
  *
  * Fixes:
- */
+ *
+ * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET
+ * TECHNOLOGIES, INC.HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION 
+ * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ *****************************************************************************/
 
-static char ixjuser_h_rcsid[] = "$Id: ixjuser.h,v 3.4 1999/12/16 22:18:36 root Exp root $";
+static char ixjuser_h_rcsid[] = "$Id: ixjuser.h,v 3.11 2000/03/30 22:06:48 eokerson Exp $";
 
-#include <linux/telephony.h>
+#include "telephony.h"
 
-/***************************************************************************
 
-  If you use the IXJCTL_TESTRAM command, the card must be power
-  cycled to reset the SRAM values before futher use.
+/******************************************************************************
+*
+* IOCTL's used for the Quicknet Cards
+*
+* If you use the IXJCTL_TESTRAM command, the card must be power cycled to
+* reset the SRAM values before futher use.
+*
+******************************************************************************/
 
-***************************************************************************/
 #define IXJCTL_DSP_RESET 		_IO  ('q', 0xC0)
 
-#define IXJCTL_RING         PHONE_RING
-#define IXJCTL_HOOKSTATE    PHONE_HOOKSTATE
+#define IXJCTL_RING                     PHONE_RING
+#define IXJCTL_HOOKSTATE                PHONE_HOOKSTATE
 #define IXJCTL_MAXRINGS			PHONE_MAXRINGS
-#define IXJCTL_RING_CADENCE	PHONE_RING_CADENCE
+#define IXJCTL_RING_CADENCE		PHONE_RING_CADENCE
 #define IXJCTL_RING_START		PHONE_RING_START
 #define IXJCTL_RING_STOP		PHONE_RING_STOP
 
 #define IXJCTL_CARDTYPE			_IOR ('q', 0xC1, int)
-#define IXJCTL_SERIAL			  _IOR ('q', 0xC2, int)
-#define IXJCTL_DSP_TYPE     _IOR ('q', 0xC3, int)
-#define IXJCTL_DSP_VERSION  _IOR ('q', 0xC4, int)
+#define IXJCTL_SERIAL			_IOR ('q', 0xC2, int)
+#define IXJCTL_DSP_TYPE                 _IOR ('q', 0xC3, int)
+#define IXJCTL_DSP_VERSION              _IOR ('q', 0xC4, int)
+#define IXJCTL_VERSION              	_IOR ('q', 0xDA, char *)
 #define IXJCTL_DSP_IDLE			_IO  ('q', 0xC5)
 #define IXJCTL_TESTRAM			_IO  ('q', 0xC6)
 
@@ -104,8 +122,22 @@
 	char enable;
 } IXJ_FILTER;
 
+typedef struct {
+	char enable;
+	char en_filter;
+	unsigned int filter;
+	unsigned int on1;
+	unsigned int off1;
+	unsigned int on2;
+	unsigned int off2;
+	unsigned int on3;
+	unsigned int off3;
+} IXJ_FILTER_CADENCE;
+
 #define IXJCTL_SET_FILTER		_IOW ('q', 0xC7, IXJ_FILTER *)
 #define IXJCTL_GET_FILTER_HIST		_IOW ('q', 0xC8, int)
+#define IXJCTL_FILTER_CADENCE		_IOW ('q', 0xD6, IXJ_FILTER_CADENCE *)
+#define IXJCTL_PLAY_CID			_IO  ('q', 0xD7)
 /******************************************************************************
 *
 * This IOCTL allows you to reassign values in the tone index table.  The
@@ -222,7 +254,9 @@
 	hz1800 = 0x1405,
 	hz1860 = 0xe0b,
 	hz2100 = 0xf5f6,
-	hz2450 = 0xd3b3
+	hz2130 = 0xf2f5,
+	hz2450 = 0xd3b3,
+	hz2750 = 0xb8e4
 } IXJ_FREQ;
 
 typedef enum {
@@ -344,6 +378,7 @@
 #define AEC_LOW   1
 #define AEC_MED   2
 #define AEC_HIGH  3
+#define AEC_AUTO  4
 /******************************************************************************
 *
 * Call Progress Tones, DTMF, etc.
@@ -533,16 +568,16 @@
 
 /******************************************************************************
 * 
-* The DAA Analog GAIN sets 2 parameters at one time, the receive gain (AGRR), 
+* The DAA Analog GAIN sets 2 parameters at one time, the recieve gain (AGRR), 
 * and the transmit gain (AGX).  OR together the components and pass them
 * as the parameter to IXJCTL_DAA_AGAIN.  The default setting is both at 0dB.
 * 
 ******************************************************************************/
 #define IXJCTL_DAA_AGAIN		_IOW ('q', 0xD2, int)
 
-#define AGRR00DB	0x00	// Analog gain in receive direction 0dB
-#define AGRR3_5DB	0x10	// Analog gain in receive direction 3.5dB
-#define AGRR06DB	0x30	// Analog gain in receive direction 6dB
+#define AGRR00DB	0x00	// Analog gain in recieve direction 0dB
+#define AGRR3_5DB	0x10	// Analog gain in recieve direction 3.5dB
+#define AGRR06DB	0x30	// Analog gain in recieve direction 6dB
 
 #define AGX00DB		0x00	// Analog gain in transmit direction 0dB
 #define AGX_6DB		0x04	// Analog gain in transmit direction -6dB
@@ -551,18 +586,9 @@
 
 #define IXJCTL_PSTN_LINETEST		_IO  ('q', 0xD3)
 
-typedef struct {
-	char month[3];
-	char day[3];
-	char hour[3];
-	char min[3];
-	int numlen;
-	char number[11];
-	int namelen;
-	char name[80];
-} IXJ_CID;
-
-#define IXJCTL_CID			_IOR ('q', 0xD4, IXJ_CID *)
+#define IXJCTL_CID			_IOR ('q', 0xD4, PHONE_CID *)
+#define IXJCTL_VMWI			_IOR ('q', 0xD8, int)
+#define IXJCTL_CIDCW			_IOW ('q', 0xD9, PHONE_CID *)
 /******************************************************************************
 * 
 * The wink duration is tunable with this ioctl.  The default wink duration  
diff -urN linux-2.2.17-pre1/include/linux/pc300.h linux/include/linux/pc300.h
--- linux-2.2.17-pre1/include/linux/pc300.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/pc300.h	Mon Dec  3 22:05:28 2001
@@ -0,0 +1,374 @@
+/*
+ * pc300.h	Cyclades-PC300(tm) Kernel API Definitions.
+ *
+ * Author:	Ivan Passos <ivan@cyclades.com>
+ *
+ * Copyright:	(c) 1999-2000 Cyclades Corp.
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ * $Log: pc300.h,v $
+ * Revision 2.0 2000/03/27 ivan
+ * Added support for the PC300/TE cards.
+ *
+ * Revision 1.1 2000/01/31 ivan
+ * Replaced 'pc300[drv|sca].h' former PC300 driver include files.
+ *
+ * Revision 1.0 1999/12/16 ivan
+ * First official release.
+ * Inclusion of 'nchan' field on structure 'pc300hw', to allow variable 
+ * number of ports per card.
+ * Inclusion of 'if_ptr' field on structure 'pc300dev'.
+ *
+ * Revision 0.6 1999/11/17 ivan
+ * Changed X.25-specific function names to comply with adopted convention.
+ *
+ * Revision 0.5 1999/11/16 Daniela Squassoni
+ * X.25 support.
+ *
+ * Revision 0.4 1999/11/15 ivan
+ * Inclusion of 'clock' field on structure 'pc300hw'.
+ *
+ * Revision 0.3 1999/11/10 ivan
+ * IOCTL name changing.
+ * Inclusion of driver function prototypes.
+ *
+ * Revision 0.2 1999/11/03 ivan
+ * Inclusion of 'tx_skb' and union 'ifu' on structure 'pc300dev'.
+ *
+ * Revision 0.1 1999/01/15 ivan
+ * Initial version.
+ *
+ */
+
+#ifndef	_PC300_H
+#define	_PC300_H
+
+#ifndef __HDLC_H
+#include <linux/hdlc.h>
+#endif
+#ifndef _HD64572_H
+#include <linux/hd64572.h>
+#endif
+#ifndef _FALC_LH_H
+#include <linux/falc-lh.h>
+#endif
+
+#ifndef CY_TYPES
+#define CY_TYPES
+#if defined(__alpha__)
+typedef	unsigned long	ucdouble;	/* 64 bits, unsigned */
+typedef	unsigned int	uclong;		/* 32 bits, unsigned */
+#else
+typedef	unsigned long	uclong;		/* 32 bits, unsigned */
+#endif
+typedef	unsigned short	ucshort;	/* 16 bits, unsigned */
+typedef	unsigned char	ucchar;		/* 8 bits, unsigned */
+#endif /* CY_TYPES */
+
+#define	PC300_DEVNAME	"hdlc"	/* Dev. name base (for hdlc0, hdlc1, etc.) */
+#define	PC300_MAXINDEX	100	/* Max dev. name index (the '0' in hdlc0) */
+
+#define	PC300_MAXCARDS	4	/* Max number of cards per system */
+#define	PC300_MAXCHAN	2	/* Number of channels per card */
+
+#define	PC300_PLX_WIN	0x80    /* PLX control window size (128b) */
+#define	PC300_RAMSIZE	0x80000 /* RAM window size (512Kb) */
+#define	PC300_SCASIZE	0x400   /* SCA window size (1Kb) */
+#define	PC300_FALCSIZE	0x400	/* FALC window size (1Kb) */
+
+#define PC300_OSC_CLOCK	24576000
+#define PC300_PCI_CLOCK	33000000
+
+#define BD_DEF_LEN	0x0800	/* DMA buffer length (2KB) */
+#define DMA_TX_MEMSZ	0x8000	/* Total DMA Tx memory size (32KB/ch) */
+#define DMA_RX_MEMSZ	0x10000	/* Total DMA Rx memory size (64KB/ch) */
+
+#define N_DMA_TX_BUF	(DMA_TX_MEMSZ / BD_DEF_LEN)	/* DMA Tx buffers */
+#define N_DMA_RX_BUF	(DMA_RX_MEMSZ / BD_DEF_LEN)	/* DMA Rx buffers */
+
+/* DMA Buffer Offsets */
+#define DMA_TX_BASE	((N_DMA_TX_BUF + N_DMA_RX_BUF) *	\
+			 PC300_MAXCHAN * sizeof(pcsca_bd_t))
+#define DMA_RX_BASE	(DMA_TX_BASE + PC300_MAXCHAN*DMA_TX_MEMSZ)
+
+/* DMA Descriptor Offsets */
+#define DMA_TX_BD_BASE	0x0000
+#define DMA_RX_BD_BASE	(DMA_TX_BD_BASE + ((PC300_MAXCHAN*DMA_TX_MEMSZ / \
+				BD_DEF_LEN) * sizeof(pcsca_bd_t)))
+
+/* DMA Descriptor Macros */
+#define TX_BD_ADDR(chan, n)	(DMA_TX_BD_BASE + \
+				 ((N_DMA_TX_BUF*chan) + n) * sizeof(pcsca_bd_t))
+#define RX_BD_ADDR(chan, n)	(DMA_RX_BD_BASE + \
+				 ((N_DMA_RX_BUF*chan) + n) * sizeof(pcsca_bd_t))
+
+/* Macro to access the FALC registers (TE only) */
+#define F_REG(reg, chan)	(0x200*(chan) + ((reg)<<2))
+
+/***************************************
+ * Memory access functions/macros      *
+ * (required to support Alpha systems) *
+ ***************************************/
+#ifdef __KERNEL__
+#define cpc_writeb(port,val)	{writeb((ucchar)(val),(ulong)(port)); mb();}
+#define cpc_writew(port,val)	{writew((ushort)(val),(ulong)(port)); mb();}
+#define cpc_writel(port,val)	{writel((uclong)(val),(ulong)(port)); mb();}
+
+#define cpc_readb(port)		readb(port)
+#define cpc_readw(port)		readw(port)
+#define cpc_readl(port)		readl(port)
+
+#else /* __KERNEL__ */
+#define cpc_writeb(port,val)	(*(volatile ucchar *)(port) = (ucchar)(val))
+#define cpc_writew(port,val)	(*(volatile ucshort *)(port) = (ucshort)(val))
+#define cpc_writel(port,val)	(*(volatile uclong *)(port) = (uclong)(val))
+
+#define cpc_readb(port)		(*(volatile ucchar *)(port))
+#define cpc_readw(port)		(*(volatile ucshort *)(port))
+#define cpc_readl(port)		(*(volatile uclong *)(port))
+
+#endif /* __KERNEL__ */
+
+/****** Data Structures *****************************************************/
+
+/*
+ *      RUNTIME_9050 - PLX PCI9050-1 local configuration and shared runtime
+ *      registers. This structure can be used to access the 9050 registers
+ *      (memory mapped).
+ */
+struct RUNTIME_9050 {
+	uclong	loc_addr_range[4];	/* 00-0Ch : Local Address Ranges */
+	uclong	loc_rom_range;		/* 10h : Local ROM Range */
+	uclong	loc_addr_base[4];	/* 14-20h : Local Address Base Addrs */
+	uclong	loc_rom_base;		/* 24h : Local ROM Base */
+	uclong	loc_bus_descr[4];	/* 28-34h : Local Bus Descriptors */
+	uclong	rom_bus_descr;		/* 38h : ROM Bus Descriptor */
+	uclong	cs_base[4];		/* 3C-48h : Chip Select Base Addrs */
+	uclong	intr_ctrl_stat;		/* 4Ch : Interrupt Control/Status */
+	uclong	init_ctrl;		/* 50h : EEPROM ctrl, Init Ctrl, etc */
+};
+
+#define PLX_9050_LINT1_ENABLE	0x01
+#define PLX_9050_LINT1_POL	0x02
+#define PLX_9050_LINT1_STATUS	0x04
+#define PLX_9050_LINT2_ENABLE	0x08
+#define PLX_9050_LINT2_POL	0x10
+#define PLX_9050_LINT2_STATUS	0x20
+#define PLX_9050_INTR_ENABLE	0x40
+#define PLX_9050_SW_INTR	0x80
+
+/* Masks to access the init_ctrl PLX register */
+#define	PC300_CLKSEL_MASK		(0x00000004UL)
+#define	PC300_CHMEDIA_MASK(chan)	(0x00000020UL<<(chan*3))
+#define	PC300_CTYPE_MASK		(0x00000800UL)
+
+/* CPLD Registers (base addr = falcbase, TE only) */
+#define CPLD_REG1	0x140	/* Chip resets, DCD/CTS status */
+#define CPLD_REG2	0x144	/* Clock enable , LED control */
+
+/* CPLD Register bit description: for the FALC bits, they should always be 
+   set based on the channel (use (bit<<(2*ch)) to access the correct bit for 
+   that channel) */
+#define CPLD_REG1_FALC_RESET	0x01
+#define CPLD_REG1_SCA_RESET	0x02
+#define CPLD_REG1_GLOBAL_CLK	0x08
+#define CPLD_REG1_FALC_DCD	0x10
+#define CPLD_REG1_FALC_CTS	0x20
+
+#define CPLD_REG2_FALC_TX_CLK	0x01
+#define CPLD_REG2_FALC_RX_CLK	0x02
+#define CPLD_REG2_FALC_LED1	0x10
+#define CPLD_REG2_FALC_LED2	0x20
+
+/* Structure with FALC-related fields (TE only) */
+#define PC300_FALC_MAXLOOP	0x0000ffff	/* for falc_issue_cmd() */
+
+typedef struct falc {
+	ucchar sync;		/* If true FALC is synchronized */
+	ucchar active;		/* if TRUE then already active */
+	ucchar loop_active;	/* if TRUE a line loopback UP was received */
+	ucchar loop_gen;	/* if TRUE a line loopback UP was issued */
+
+	ucchar num_channels;
+	ucchar offset;		/* 1 for T1, 0 for E1 */
+	ucchar full_bandwidth;
+
+	ucchar xmb_cause;
+	ucchar multiframe_mode;
+
+	/* Statistics */
+	ucshort pden;	/* Pulse Density violation count */
+	ucshort los;	/* Loss of Signal count */
+	ucshort losr;	/* Loss of Signal recovery count */
+	ucshort lfa;	/* Loss of frame alignment count */
+	ucshort farec;	/* Frame Alignment Recovery count */
+	ucshort lmfa;	/* Loss of multiframe alignment count */
+	ucshort ais;	/* Remote Alarm indication Signal count */
+	ucshort sec;	/* One-second timer */
+	ucshort es;	/* Errored second */
+	ucshort rai;	/* remote alarm received */
+	ucshort bec;
+	ucshort fec;
+	ucshort cvc;
+	ucshort cec;
+	ucshort ebc;
+
+	/* Status */
+	ucchar red_alarm;
+	ucchar blue_alarm;
+	ucchar loss_fa;
+	ucchar yellow_alarm;
+	ucchar loss_mfa;
+	ucchar prbs;
+} falc_t;
+
+typedef struct pc300dev {
+	void *if_ptr;	/* General purpose pointer */
+	struct pc300ch *chan;
+#ifdef __KERNEL__
+	char name[16];
+	void *private;
+	hdlc_device *hdlc;
+	struct net_device_stats stats;
+	struct sk_buff *tx_skb;
+#endif /* __KERNEL__ */
+}pc300dev_t;
+
+typedef struct pc300hw {
+	int type;		/* RSV, X21, etc. */
+	int nchan;		/* number of channels */
+	int irq;		/* interrupt request level */
+	uclong clock;		/* Board clock */
+	uclong plxphys;		/* PLX registers MMIO base (physical) */
+	uclong plxbase;		/* PLX registers MMIO base (virtual) */
+	uclong plxsize;		/* PLX registers MMIO size */
+	uclong scaphys;		/* SCA registers MMIO base (physical) */
+	uclong scabase;		/* SCA registers MMIO base (virtual) */
+	uclong scasize;		/* SCA registers MMIO size */
+	uclong ramphys;		/* On-board RAM MMIO base (physical) */
+	uclong rambase;		/* On-board RAM MMIO base (virtual) */
+	uclong ramsize;		/* On-board RAM MMIO size */
+	uclong falcphys;	/* FALC registers MMIO base (physical) */
+	uclong falcbase;	/* FALC registers MMIO base (virtual) */
+	uclong falcsize;	/* FALC registers MMIO size */
+} pc300hw_t;
+
+typedef struct pc300chconf {
+	ucchar media;		/* HW media (RS232, V.35, etc.) */
+	uclong proto;		/* Protocol (PPP, X.25, etc.) */
+	uclong clkrate;		/* Clock rate (in bps, 0 = ext. clock) */
+
+	/* TE-specific parameters */
+	ucchar lcode;		/* Line Code (AMI, B8ZS, etc.) */
+	ucchar fr_mode;		/* Frame Mode (ESF, D4, etc.) */
+	ucchar lbo;		/* Line Build Out */
+	ucchar rx_sens;		/* Rx Sensitivity (long- or short-haul) */
+	uclong tslot_bitmap;	/* bit[i]=1  =>  timeslot _i_ is active */
+} pc300chconf_t;
+
+typedef struct pc300ch {
+	struct pc300 *card;
+	int channel;
+	pc300dev_t d;
+	pc300chconf_t conf;
+	ucchar tx_first_bd;	/* First TX DMA block descr. w/ data */
+	ucchar tx_next_bd;	/* Next free TX DMA block descriptor */
+	ucchar rx_first_bd;	/* First free RX DMA block descriptor */
+	ucchar rx_last_bd;	/* Last free RX DMA block descriptor */
+	falc_t falc;		/* FALC structure (TE only) */
+} pc300ch_t;
+
+typedef struct pc300 {
+	pc300hw_t hw;			/* hardware config. */
+	pc300ch_t chan[PC300_MAXCHAN];
+#ifdef __KERNEL__
+	spinlock_t card_lock;
+#endif /* __KERNEL__ */
+} pc300_t;
+
+/* DEV ioctl() commands */
+#define	N_SPPP_IOCTLS	2
+
+enum pc300_ioctl_cmds {
+	SIOCCPCRESERVED = (SIOCDEVPRIVATE + N_SPPP_IOCTLS),
+	SIOCGPC300CONF,
+	SIOCSPC300CONF,
+	SIOCGPC300STATUS,
+	SIOCGPC300FALCSTATUS,
+};
+
+/* Control Constant Definitions */
+#define	PC300_RSV	0x01
+#define	PC300_X21	0x02
+#define	PC300_TE	0x03
+
+#define PC300_LC_AMI	0x01
+#define PC300_LC_B8ZS	0x02
+#define PC300_LC_NRZ	0x03
+#define PC300_LC_HDB3	0x04
+
+/* Framing (T1) */
+#define PC300_FR_ESF		0x01
+#define PC300_FR_D4		0x02
+#define PC300_FR_ESF_JAPAN	0x03
+
+/* Framing (E1) */
+#define PC300_FR_MF_CRC4	0x04
+#define PC300_FR_MF_NON_CRC4	0x05
+
+#define PC300_LBO_0_DB		0x00
+#define PC300_LBO_7_5_DB	0x01
+#define PC300_LBO_15_DB		0x02
+#define PC300_LBO_22_5_DB	0x03
+
+#define PC300_RX_SENS_SH	0x01
+#define PC300_RX_SENS_LH	0x02
+
+#define PC300_TX_TIMEOUT	(2*HZ)
+#define PC300_TX_QUEUE_LEN	10
+#define	PC300_DEF_MTU		1500
+
+#ifdef __KERNEL__
+/* Function Prototypes */
+static void tx_dma_buf_pt_init(pc300_t *, int);
+static void tx_dma_buf_init(pc300_t *, int);
+static void rx_dma_buf_pt_init(pc300_t *, int);
+static void rx_dma_buf_init(pc300_t *, int);
+static void tx_dma_buf_check(pc300_t *, int);
+static void rx_dma_buf_check(pc300_t *, int);
+int dma_buf_write(pc300_t *, int, ucchar *, int);
+int dma_buf_read(pc300_t *, int, struct sk_buff *);
+void tx_dma_start(pc300_t *, int);
+void rx_dma_start(pc300_t *, int);
+void tx_dma_stop(pc300_t *, int);
+void rx_dma_stop(pc300_t *, int);
+int cpc_queue_xmit(struct sk_buff *, struct device *);
+void cpc_net_rx(hdlc_device *);
+#ifdef CONFIG_PC300_X25
+int cpc_x25_packetlayer_xmit(struct sk_buff *, struct device *);
+void cpc_lapb_connected(void *, int);
+void cpc_lapb_disconnected(void *, int);
+void cpc_lapb_data_indication(void *, struct sk_buff *);
+void cpc_lapb_data_transmit(void *, struct sk_buff *);
+#endif /* CONFIG_PC300_X25 */
+static void cpc_intr(int, void *, struct pt_regs *);
+void cpc_sca_status(pc300_t *, int);
+int cpc_ioctl(hdlc_device *, struct ifreq *, int);
+static int clock_rate_calc(uclong, uclong, int *);
+int ch_config(pc300dev_t *);
+int rx_config(pc300dev_t *);
+int tx_config(pc300dev_t *);
+int cpc_opench(pc300dev_t *);
+void cpc_closech(pc300dev_t *);
+int cpc_open(hdlc_device *);
+void cpc_close(hdlc_device *);
+static uclong detect_ram(pc300_t *);
+static void plx_init(pc300_t *);
+static int cpc_detect(void);
+#endif /* __KERNEL__ */
+
+#endif	/* _PC300_H */
diff -urN linux-2.2.17-pre1/include/linux/pci.h linux/include/linux/pci.h
--- linux-2.2.17-pre1/include/linux/pci.h	Wed Jun  7 14:26:44 2000
+++ linux/include/linux/pci.h	Mon Dec  3 22:05:28 2001
@@ -951,6 +951,10 @@
 #define PCI_DEVICE_ID_CYCLOM_8Y_Hi	0x0105
 #define PCI_DEVICE_ID_CYCLOM_Z_Lo	0x0200
 #define PCI_DEVICE_ID_CYCLOM_Z_Hi	0x0201
+#define PCI_DEVICE_ID_PC300_RX_2	0x0300
+#define PCI_DEVICE_ID_PC300_RX_1	0x0301
+#define PCI_DEVICE_ID_PC300_TE_2	0x0310
+#define PCI_DEVICE_ID_PC300_TE_1	0x0311
 
 #define PCI_VENDOR_ID_ESSENTIAL		0x120f
 #define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER	0x0001
diff -urN linux-2.2.17-pre1/include/linux/telephony.h linux/include/linux/telephony.h
--- linux-2.2.17-pre1/include/linux/telephony.h	Wed May  3 17:16:52 2000
+++ linux/include/linux/telephony.h	Mon Dec  3 22:05:28 2001
@@ -1,32 +1,33 @@
-/*
- *              telephony.h
+/******************************************************************************
+ *
+ *		telephony.h
  *
- *              Basic Linux Telephony Interface
+ *		Basic Linux Telephony Interface
  *
- *              (c) Copyright 1999 Quicknet Technologies, Inc.
+ *		(c) Copyright 1999 Quicknet Technologies, Inc.
  *
- *              This program is free software; you can redistribute it and/or
- *              modify it under the terms of the GNU General Public License
- *              as published by the Free Software Foundation; either version
- *              2 of the License, or (at your option) any later version.
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
  *
- * Authors:       Ed Okerson, <eokerson@quicknet.net>
- *                Greg Herlein, <gherlein@quicknet.net>
+ *    Authors:       Ed Okerson, <eokerson@quicknet.net>
+ *                   Greg Herlein, <gherlein@quicknet.net>
  *
- * Contributors:  Alan Cox, <acox@redhat.com>
- *                David Erhart, <derhart@quicknet.net>
+ *    Contributors:  Alan Cox, <acox@redhat.com>
+ *                   David W. Erhart, <derhart@quicknet.net>
  *
  * Version:       0.1.0 - December 19, 1999
  *
  * Fixes:
- */
+ * 
+ *****************************************************************************/
 
 #ifndef TELEPHONY_H
 #define TELEPHONY_H
 
-/* vendor identification numbers */
 #define PHONE_VENDOR_IXJ          1
-#define PHONE_VENDOR_QUICKNET     PHONE_IXJ
+#define PHONE_VENDOR_QUICKNET	  PHONE_VENDOR_IXJ
 #define PHONE_VENDOR_VOICETRONIX  2
 #define PHONE_VENDOR_ACULAB       3
 #define PHONE_VENDOR_DIGI         4
@@ -43,7 +44,6 @@
  *
  *****************************************************************************/
 
- 
 /******************************************************************************
 *
 * The capabilities ioctls can inform you of the capabilities of each phone
@@ -81,11 +81,23 @@
 #define PHONE_CAPABILITIES_LIST         _IOR ('q', 0x81, struct phone_capability *)
 #define PHONE_CAPABILITIES_CHECK        _IOW ('q', 0x82, struct phone_capability *)
 
+typedef struct {
+        char month[3];
+        char day[3];
+        char hour[3];
+        char min[3];
+        int numlen;
+        char number[11];
+        int namelen;
+        char name[80];
+} PHONE_CID;
+
 #define PHONE_RING			_IO  ('q', 0x83)
 #define PHONE_HOOKSTATE			_IO  ('q', 0x84)
 #define PHONE_MAXRINGS			_IOW ('q', 0x85, char)
 #define PHONE_RING_CADENCE		_IOW ('q', 0x86, short)
-#define PHONE_RING_START		_IO  ('q', 0x87)
+#define OLD_PHONE_RING_START		_IO  ('q', 0x87)
+#define PHONE_RING_START		_IOW ('q', 0x87, PHONE_CID *)
 #define PHONE_RING_STOP			_IO  ('q', 0x88)
 
 #define USA_RING_CADENCE	 0xC0C0
@@ -167,6 +179,23 @@
 #define PHONE_QUERY_CODEC		_IOWR ('q', 0xA7, struct phone_codec_data *)
 #define PHONE_PSTN_LINETEST		_IO ('q', 0xA8)
 
+/******************************************************************************
+* 
+* This controls the VAD/CNG functionality of G.723.1.  The driver will
+* always pass full size frames, any unused bytes will be padded with zeros,
+* and frames passed to the driver should also be padded with zeros.  The
+* frame type is encoded in the least significant two bits of the first
+* WORD of the frame as follows:
+*
+* bits 1-0	Frame Type	Data Rate		Significant Words
+* 00		0		G.723.1 6.3		12
+* 01		1		G.723.1 5.3		10
+* 10		2		VAD/CNG			 2
+* 11		3		Repeat last CNG		 2 bits
+* 
+******************************************************************************/
+#define PHONE_VAD			_IOW ('q', 0xA9, int)
+
 
 /******************************************************************************
 *
@@ -198,7 +227,12 @@
 	unsigned int f1:1;
 	unsigned int f2:1;
 	unsigned int f3:1;
-	unsigned int reserved:23;
+	unsigned int flash:1;
+	unsigned int fc0:1;
+	unsigned int fc1:1;
+	unsigned int fc2:1;
+	unsigned int fc3:1;
+	unsigned int reserved:18;
 };
 
 union telephony_exception {
diff -urN linux-2.2.17-pre1/mm/page_alloc.c linux/mm/page_alloc.c
--- linux-2.2.17-pre1/mm/page_alloc.c	Wed Jun  7 14:26:44 2000
+++ linux/mm/page_alloc.c	Mon Dec  3 22:05:28 2001
@@ -227,7 +227,7 @@
 		}
 
 		/* Do we have to help kswapd or can we proceed? */
-		if (nr_free_pages < (freepages.low + freepages.low) / 2) {
+		if (nr_free_pages < (freepages.min + freepages.low) / 2) {
 			wake_up_interruptible(&kswapd_wait);
 
 			/* Help kswapd a bit... */
diff -urN linux-2.2.17-pre1/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- linux-2.2.17-pre1/net/appletalk/ddp.c	Wed Jun  7 14:26:44 2000
+++ linux/net/appletalk/ddp.c	Mon Dec  3 22:05:28 2001
@@ -1583,8 +1583,12 @@
 		 * Note. ddp-> becomes invalid at the realloc.
 		 */
 		if(skb_headroom(skb) < 22)
+		{
 			/* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */
-			skb = skb_realloc_headroom(skb, 32);
+			struct sk_buff *nskb = skb_realloc_headroom(skb, 32);
+			kfree(skb);
+			skb=nskb;
+		}
 		else
 			skb = skb_unshare(skb, GFP_ATOMIC);
 		
diff -urN linux-2.2.17-pre1/net/core/dev.c linux/net/core/dev.c
--- linux-2.2.17-pre1/net/core/dev.c	Wed Jun  7 14:26:44 2000
+++ linux/net/core/dev.c	Mon Dec  3 22:05:28 2001
@@ -98,6 +98,7 @@
 extern void n2_init(void);
 extern void c101_init(void);
 extern int wanxl_init(void);
+extern int cpc_init(void);
 extern void sync_ppp_init(void);
 
 NET_PROFILE_DEFINE(dev_queue_xmit)
@@ -2039,6 +2040,9 @@
 #endif
 #ifdef CONFIG_WANXL
 	wanxl_init();
+#endif
+#ifdef CONFIG_PC300
+	cpc_init();
 #endif
 #ifdef CONFIG_HDLC
 	sync_ppp_init();
